Index: lib/Target/SystemZ/SystemZElimCompare.cpp =================================================================== --- lib/Target/SystemZ/SystemZElimCompare.cpp +++ lib/Target/SystemZ/SystemZElimCompare.cpp @@ -110,9 +110,10 @@ 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() && +// Return true if any CC result of MI would reflect the value of Reg, or if +// it can be converted to do so. +static bool resultTests(MachineInstr &MI, unsigned Reg, bool BeforeCompare = true) { + if (BeforeCompare && MI.getNumOperands() > 0 && MI.getOperand(0).isReg() && MI.getOperand(0).isDef() && MI.getOperand(0).getReg() == Reg) return true; @@ -421,11 +422,34 @@ } 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 LTEBRCompare %F0S, %F0S, %CC + // %F2S = LER %F0S + // + MBBI = Compare, MBBE = MBB.end(); + while (++MBBI != MBBE) { + MachineInstr &MI = *MBBI; + if (resultTests(MI, SrcReg, false/*BeforeCompare*/)) { + // 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; } Index: test/CodeGen/SystemZ/fp-cmp-07.mir =================================================================== --- /dev/null +++ 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 + +...