summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/Target/SystemZ/SystemZElimCompare.cpp43
-rw-r--r--test/CodeGen/SystemZ/fp-cmp-07.mir44
2 files changed, 80 insertions, 7 deletions
diff --git a/lib/Target/SystemZ/SystemZElimCompare.cpp b/lib/Target/SystemZ/SystemZElimCompare.cpp
index d70f9e90cd3..5f75b13b3ef 100644
--- a/lib/Target/SystemZ/SystemZElimCompare.cpp
+++ b/lib/Target/SystemZ/SystemZElimCompare.cpp
@@ -110,12 +110,8 @@ static bool isCCLiveOut(MachineBasicBlock &MBB) {
return false;
}
-// Return true if any CC result of MI would reflect the value of Reg.
-static bool resultTests(MachineInstr &MI, unsigned Reg) {
- if (MI.getNumOperands() > 0 && MI.getOperand(0).isReg() &&
- MI.getOperand(0).isDef() && MI.getOperand(0).getReg() == Reg)
- return true;
-
+// Returns true if MI is an instruction whose output equals the value in Reg.
+static bool preservesValueOf(MachineInstr &MI, unsigned Reg) {
switch (MI.getOpcode()) {
case SystemZ::LR:
case SystemZ::LGR:
@@ -136,6 +132,16 @@ static bool resultTests(MachineInstr &MI, unsigned Reg) {
return false;
}
+// Return true if any CC result of MI would (perhaps after conversion)
+// reflect the value of Reg.
+static bool resultTests(MachineInstr &MI, unsigned Reg) {
+ if (MI.getNumOperands() > 0 && MI.getOperand(0).isReg() &&
+ MI.getOperand(0).isDef() && MI.getOperand(0).getReg() == Reg)
+ return true;
+
+ return (preservesValueOf(MI, Reg));
+}
+
// Describe the references to Reg or any of its aliases in MI.
Reference SystemZElimCompare::getRegReferences(MachineInstr &MI, unsigned Reg) {
Reference Ref;
@@ -421,11 +427,34 @@ bool SystemZElimCompare::optimizeCompareZero(
}
SrcRefs |= getRegReferences(MI, SrcReg);
if (SrcRefs.Def)
- return false;
+ break;
CCRefs |= getRegReferences(MI, SystemZ::CC);
if (CCRefs.Use && CCRefs.Def)
+ break;
+ }
+
+ // Also do a forward search to handle cases where an instruction after the
+ // compare can be converted like
+ //
+ // LTEBRCompare %F0S, %F0S, %CC<imp-def> LTEBRCompare %F0S, %F0S, %CC<imp-def>
+ // %F2S<def> = LER %F0S
+ //
+ MBBI = Compare, MBBE = MBB.end();
+ while (++MBBI != MBBE) {
+ MachineInstr &MI = *MBBI;
+ if (preservesValueOf(MI, SrcReg)) {
+ // Try to eliminate Compare by reusing a CC result from MI.
+ if (convertToLoadAndTest(MI)) {
+ EliminatedComparisons += 1;
+ return true;
+ }
+ }
+ if (getRegReferences(MI, SrcReg).Def)
+ return false;
+ if (getRegReferences(MI, SystemZ::CC))
return false;
}
+
return false;
}
diff --git a/test/CodeGen/SystemZ/fp-cmp-07.mir b/test/CodeGen/SystemZ/fp-cmp-07.mir
new file mode 100644
index 00000000000..1d766fe300a
--- /dev/null
+++ b/test/CodeGen/SystemZ/fp-cmp-07.mir
@@ -0,0 +1,44 @@
+# RUN: llc -mtriple=s390x-linux-gnu -mcpu=z10 -no-integrated-as -start-after=block-placement %s -o - | FileCheck %s
+# Test that LTEBR is used without an unnecessary LER
+
+--- |
+ define float @f15(float %val, float %dummy, float* %dest) {
+ entry:
+ call void asm sideeffect "blah $0", "{f2}"(float %val)
+ %cmp = fcmp olt float %val, 0.000000e+00
+ br i1 %cmp, label %exit, label %store
+
+ store: ; preds = %entry
+ store float %val, float* %dest
+ br label %exit
+
+ exit: ; preds = %store, %entry
+ ret float %val
+ }
+
+...
+
+# CHECK: ltebr %f2, %f0
+
+---
+name: f15
+tracksRegLiveness: true
+liveins:
+ - { reg: '%f0s', virtual-reg: '' }
+ - { reg: '%r2d', virtual-reg: '' }
+body: |
+ bb.0.entry:
+ liveins: %f0s, %r2d
+
+ LTEBRCompare %f0s, %f0s, implicit-def %cc
+ %f2s = LER %f0s
+ INLINEASM $"blah $0", 1, 9, %f2s
+ CondReturn 15, 4, implicit %f0s, implicit %cc
+
+ bb.1.store:
+ liveins: %f0s, %r2d
+
+ STE %f0s, killed %r2d, 0, _ :: (store 4 into %ir.dest)
+ Return implicit %f0s
+
+...