diff options
author | Richard Sandiford <rsandifo@linux.vnet.ibm.com> | 2013-08-05 11:03:20 +0000 |
---|---|---|
committer | Richard Sandiford <rsandifo@linux.vnet.ibm.com> | 2013-08-05 11:03:20 +0000 |
commit | b49a3ab2627d1e5d2811dbc1295c8486ecc87713 (patch) | |
tree | b68f412c6277348fa5e75ce4c383d879eb56328f /llvm/lib | |
parent | c62c64a038bbc518b2dca91008914e2096c89038 (diff) | |
download | bcm5719-llvm-b49a3ab2627d1e5d2811dbc1295c8486ecc87713.tar.gz bcm5719-llvm-b49a3ab2627d1e5d2811dbc1295c8486ecc87713.zip |
[SystemZ] Use LOAD AND TEST to eliminate comparisons against zero
llvm-svn: 187720
Diffstat (limited to 'llvm/lib')
-rw-r--r-- | llvm/lib/Target/SystemZ/SystemZElimCompare.cpp | 32 | ||||
-rw-r--r-- | llvm/lib/Target/SystemZ/SystemZInstrInfo.cpp | 13 | ||||
-rw-r--r-- | llvm/lib/Target/SystemZ/SystemZInstrInfo.h | 4 |
3 files changed, 48 insertions, 1 deletions
diff --git a/llvm/lib/Target/SystemZ/SystemZElimCompare.cpp b/llvm/lib/Target/SystemZ/SystemZElimCompare.cpp index 9b0bdd8505e..bcdc5b728f0 100644 --- a/llvm/lib/Target/SystemZ/SystemZElimCompare.cpp +++ b/llvm/lib/Target/SystemZ/SystemZElimCompare.cpp @@ -46,6 +46,7 @@ namespace { bool runOnMachineFunction(MachineFunction &F); private: + bool convertToLoadAndTest(MachineInstr *MI); bool adjustCCMasksForInstr(MachineInstr *MI, MachineInstr *Compare, SmallVectorImpl<MachineInstr *> &CCUsers); bool optimizeCompareZero(MachineInstr *Compare, @@ -83,9 +84,34 @@ static bool resultTests(MachineInstr *MI, unsigned Reg, unsigned SubReg) { MI->getOperand(0).getSubReg() == SubReg) return true; + switch (MI->getOpcode()) { + case SystemZ::LR: + case SystemZ::LGR: + case SystemZ::LGFR: + case SystemZ::LTR: + case SystemZ::LTGR: + case SystemZ::LTGFR: + if (MI->getOperand(1).getReg() == Reg && + MI->getOperand(1).getSubReg() == SubReg) + return true; + } + return false; } +// If MI is a load instruction, try to convert it into a LOAD AND TEST. +// Return true on success. +bool SystemZElimCompare::convertToLoadAndTest(MachineInstr *MI) { + unsigned Opcode = TII->getLoadAndTest(MI->getOpcode()); + if (!Opcode) + return false; + + MI->setDesc(TII->get(Opcode)); + MachineInstrBuilder(*MI->getParent()->getParent(), MI) + .addReg(SystemZ::CC, RegState::ImplicitDefine); + return true; +} + // The CC users in CCUsers are testing the result of a comparison of some // value X against zero and we know that any CC value produced by MI // would also reflect the value of X. Try to adjust CCUsers so that @@ -184,17 +210,21 @@ optimizeCompareZero(MachineInstr *Compare, unsigned SrcSubReg = Compare->getOperand(0).getSubReg(); MachineBasicBlock *MBB = Compare->getParent(); MachineBasicBlock::iterator MBBI = Compare, MBBE = MBB->begin(); + bool SeenUseOfCC = false; while (MBBI != MBBE) { --MBBI; MachineInstr *MI = MBBI; if (resultTests(MI, SrcReg, SrcSubReg) && - adjustCCMasksForInstr(MI, Compare, CCUsers)) { + ((!SeenUseOfCC && convertToLoadAndTest(MI)) || + adjustCCMasksForInstr(MI, Compare, CCUsers))) { EliminatedComparisons += 1; return true; } if (MI->modifiesRegister(SrcReg, TRI) || MI->modifiesRegister(SystemZ::CC, TRI)) return false; + if (MI->readsRegister(SystemZ::CC, TRI)) + SeenUseOfCC = true; } return false; } diff --git a/llvm/lib/Target/SystemZ/SystemZInstrInfo.cpp b/llvm/lib/Target/SystemZ/SystemZInstrInfo.cpp index 9913db7b0e4..5dd8d98d27d 100644 --- a/llvm/lib/Target/SystemZ/SystemZInstrInfo.cpp +++ b/llvm/lib/Target/SystemZ/SystemZInstrInfo.cpp @@ -753,6 +753,19 @@ unsigned SystemZInstrInfo::getOpcodeForOffset(unsigned Opcode, return 0; } +unsigned SystemZInstrInfo::getLoadAndTest(unsigned Opcode) const { + switch (Opcode) { + case SystemZ::L: return SystemZ::LT; + case SystemZ::LY: return SystemZ::LT; + case SystemZ::LG: return SystemZ::LTG; + case SystemZ::LGF: return SystemZ::LTGF; + case SystemZ::LR: return SystemZ::LTR; + case SystemZ::LGFR: return SystemZ::LTGFR; + case SystemZ::LGR: return SystemZ::LTGR; + default: return 0; + } +} + // Return true if Mask matches the regexp 0*1+0*, given that zero masks // have already been filtered out. Store the first set bit in LSB and // the number of set bits in Length if so. diff --git a/llvm/lib/Target/SystemZ/SystemZInstrInfo.h b/llvm/lib/Target/SystemZ/SystemZInstrInfo.h index 763a3956fc1..1392745672f 100644 --- a/llvm/lib/Target/SystemZ/SystemZInstrInfo.h +++ b/llvm/lib/Target/SystemZ/SystemZInstrInfo.h @@ -193,6 +193,10 @@ public: // exists. unsigned getOpcodeForOffset(unsigned Opcode, int64_t Offset) const; + // If Opcode is a load instruction that has a LOAD AND TEST form, + // return the opcode for the testing form, otherwise return 0. + unsigned getLoadAndTest(unsigned Opcode) const; + // Return true if ROTATE AND ... SELECTED BITS can be used to select bits // Mask of the R2 operand, given that only the low BitSize bits of Mask are // significant. Set Start and End to the I3 and I4 operands if so. |