summaryrefslogtreecommitdiffstats
path: root/llvm/lib
diff options
context:
space:
mode:
authorRichard Sandiford <rsandifo@linux.vnet.ibm.com>2013-08-05 11:03:20 +0000
committerRichard Sandiford <rsandifo@linux.vnet.ibm.com>2013-08-05 11:03:20 +0000
commitb49a3ab2627d1e5d2811dbc1295c8486ecc87713 (patch)
treeb68f412c6277348fa5e75ce4c383d879eb56328f /llvm/lib
parentc62c64a038bbc518b2dca91008914e2096c89038 (diff)
downloadbcm5719-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.cpp32
-rw-r--r--llvm/lib/Target/SystemZ/SystemZInstrInfo.cpp13
-rw-r--r--llvm/lib/Target/SystemZ/SystemZInstrInfo.h4
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.
OpenPOWER on IntegriCloud