Index: lib/Target/SystemZ/SystemZElimCompare.cpp =================================================================== --- lib/Target/SystemZ/SystemZElimCompare.cpp +++ lib/Target/SystemZ/SystemZElimCompare.cpp @@ -110,7 +110,8 @@ return false; } -// Return true if any CC result of MI would reflect the value of Reg. +// 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) { if (MI.getNumOperands() > 0 && MI.getOperand(0).isReg() && MI.getOperand(0).isDef() && MI.getOperand(0).getReg() == Reg) @@ -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)) { + // 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,82 @@ +# RUN: llc -mtriple=s390x-linux-gnu -mcpu=z10 -no-integrated-as -start-after=block-placement %s -o - | FileCheck %s +# Test that load-and-test is used + +--- | + ; ModuleID = '/home/ijonpan/tmp/tc_ltebr.ll' + source_filename = "/home/ijonpan/llvm/llvm-dev-2/test/CodeGen/SystemZ/fp-cmp-04.ll" + target datalayout = "E-m:e-i1:8:16-i8:8:16-i64:64-f128:64-a:8:16-n32:64" + target triple = "s390x--linux-gnu" + + define float @f15(float %val, float %dummy, float* %dest) #0 { + 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 + } + + ; Function Attrs: nounwind + declare void @llvm.stackprotector(i8*, i8**) #1 + + attributes #0 = { "target-cpu"="z10" } + attributes #1 = { nounwind } + +... + +# CHECK: ltebr %f2, %f0 + +--- +name: f15 +alignment: 2 +exposesReturnsTwice: false +legalized: false +regBankSelected: false +selected: false +tracksRegLiveness: true +registers: +liveins: + - { reg: '%f0s', virtual-reg: '' } + - { reg: '%r2d', virtual-reg: '' } +frameInfo: + isFrameAddressTaken: false + isReturnAddressTaken: false + hasStackMap: false + hasPatchPoint: false + stackSize: 0 + offsetAdjustment: 0 + maxAlignment: 0 + adjustsStack: false + hasCalls: false + stackProtector: '' + maxCallFrameSize: 0 + hasOpaqueSPAdjustment: false + hasVAStart: false + hasMustTailInVarArgFunc: false + savePoint: '' + restorePoint: '' +fixedStack: +stack: +constants: +body: | + bb.0.entry: + successors: %bb.1.store(0x80000000) + 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 + +...