summaryrefslogtreecommitdiffstats
path: root/llvm/lib/Target/SystemZ/SystemZElimCompare.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib/Target/SystemZ/SystemZElimCompare.cpp')
-rw-r--r--llvm/lib/Target/SystemZ/SystemZElimCompare.cpp61
1 files changed, 56 insertions, 5 deletions
diff --git a/llvm/lib/Target/SystemZ/SystemZElimCompare.cpp b/llvm/lib/Target/SystemZ/SystemZElimCompare.cpp
index b292b554779..6e42e283c9f 100644
--- a/llvm/lib/Target/SystemZ/SystemZElimCompare.cpp
+++ b/llvm/lib/Target/SystemZ/SystemZElimCompare.cpp
@@ -28,6 +28,7 @@ using namespace llvm;
#define DEBUG_TYPE "systemz-elim-compare"
STATISTIC(BranchOnCounts, "Number of branch-on-count instructions");
+STATISTIC(LoadAndTraps, "Number of load-and-trap instructions");
STATISTIC(EliminatedComparisons, "Number of eliminated comparisons");
STATISTIC(FusedComparisons, "Number of fused compare-and-branch instructions");
@@ -73,6 +74,8 @@ private:
Reference getRegReferences(MachineInstr &MI, unsigned Reg);
bool convertToBRCT(MachineInstr &MI, MachineInstr &Compare,
SmallVectorImpl<MachineInstr *> &CCUsers);
+ bool convertToLoadAndTrap(MachineInstr &MI, MachineInstr &Compare,
+ SmallVectorImpl<MachineInstr *> &CCUsers);
bool convertToLoadAndTest(MachineInstr &MI);
bool adjustCCMasksForInstr(MachineInstr &MI, MachineInstr &Compare,
SmallVectorImpl<MachineInstr *> &CCUsers);
@@ -225,6 +228,48 @@ bool SystemZElimCompare::convertToBRCT(
return true;
}
+// Compare compares the result of MI against zero. If MI is a suitable load
+// instruction and if CCUsers is a single conditional trap on zero, eliminate
+// the load and convert the branch to a load-and-trap. Return true on success.
+bool SystemZElimCompare::convertToLoadAndTrap(
+ MachineInstr &MI, MachineInstr &Compare,
+ SmallVectorImpl<MachineInstr *> &CCUsers) {
+ unsigned LATOpcode = TII->getLoadAndTrap(MI.getOpcode());
+ if (!LATOpcode)
+ return false;
+
+ // Check whether we have a single CondTrap that traps on zero.
+ if (CCUsers.size() != 1)
+ return false;
+ MachineInstr *Branch = CCUsers[0];
+ if (Branch->getOpcode() != SystemZ::CondTrap ||
+ Branch->getOperand(0).getImm() != SystemZ::CCMASK_ICMP ||
+ Branch->getOperand(1).getImm() != SystemZ::CCMASK_CMP_EQ)
+ return false;
+
+ // We already know that there are no references to the register between
+ // MI and Compare. Make sure that there are also no references between
+ // Compare and Branch.
+ unsigned SrcReg = getCompareSourceReg(Compare);
+ MachineBasicBlock::iterator MBBI = Compare, MBBE = Branch;
+ for (++MBBI; MBBI != MBBE; ++MBBI)
+ if (getRegReferences(*MBBI, SrcReg))
+ return false;
+
+ // The transformation is OK. Rebuild Branch as a load-and-trap.
+ MachineOperand Target(Branch->getOperand(2));
+ while (Branch->getNumOperands())
+ Branch->RemoveOperand(0);
+ Branch->setDesc(TII->get(LATOpcode));
+ MachineInstrBuilder(*Branch->getParent()->getParent(), Branch)
+ .addOperand(MI.getOperand(0))
+ .addOperand(MI.getOperand(1))
+ .addOperand(MI.getOperand(2))
+ .addOperand(MI.getOperand(3));
+ MI.eraseFromParent();
+ return true;
+}
+
// If MI is a load instruction, try to convert it into a LOAD AND TEST.
// Return true on success.
bool SystemZElimCompare::convertToLoadAndTest(MachineInstr &MI) {
@@ -353,11 +398,17 @@ bool SystemZElimCompare::optimizeCompareZero(
MachineInstr &MI = *MBBI;
if (resultTests(MI, SrcReg)) {
// Try to remove both MI and Compare by converting a branch to BRCT(G).
- // We don't care in this case whether CC is modified between MI and
- // Compare.
- if (!CCRefs.Use && !SrcRefs && convertToBRCT(MI, Compare, CCUsers)) {
- BranchOnCounts += 1;
- return true;
+ // or a load-and-trap instruction. We don't care in this case whether
+ // CC is modified between MI and Compare.
+ if (!CCRefs.Use && !SrcRefs) {
+ if (convertToBRCT(MI, Compare, CCUsers)) {
+ BranchOnCounts += 1;
+ return true;
+ }
+ if (convertToLoadAndTrap(MI, Compare, CCUsers)) {
+ LoadAndTraps += 1;
+ return true;
+ }
}
// Try to eliminate Compare by reusing a CC result from MI.
if ((!CCRefs && convertToLoadAndTest(MI)) ||
OpenPOWER on IntegriCloud