Index: lib/Target/PowerPC/PPCInstrInfo.cpp =================================================================== --- lib/Target/PowerPC/PPCInstrInfo.cpp +++ lib/Target/PowerPC/PPCInstrInfo.cpp @@ -1594,6 +1594,11 @@ if (MIOpC == PPC::CNTLZW || MIOpC == PPC::CNTLZWo || MIOpC == PPC::SLW || MIOpC == PPC::SLWo || MIOpC == PPC::SRW || MIOpC == PPC::SRWo || + MIOpC == PPC::ANDIo || MIOpC == PPC::ANDISo || + MIOpC == PPC::ROTRWI || MIOpC == PPC::ROTRWIo || + MIOpC == PPC::EXTLWI || MIOpC == PPC::EXTLWIo || + MIOpC == PPC::SLWI || MIOpC == PPC::SLWIo || + MIOpC == PPC::SRWI || MIOpC == PPC::SRWIo || isZeroExtendingRotate) { noSub = true; equalityOnly = true; @@ -1627,9 +1632,10 @@ MachineBasicBlock::iterator I = CmpInstr; // Scan forward to find the first use of the compare. + bool FoundUse = false; for (MachineBasicBlock::iterator EL = CmpInstr.getParent()->end(); I != EL; ++I) { - bool FoundUse = false; + FoundUse = false; for (MachineRegisterInfo::use_instr_iterator J =MRI->use_instr_begin(CRReg), JE = MRI->use_instr_end(); J != JE; ++J) if (&*J == &*I) { @@ -1641,6 +1647,10 @@ break; } + SmallVector, 4> PredsToUpdate; + SmallVector, 4> SubRegsToUpdate; + bool NonZeroImmed = false; + // There are two possible candidates which can be changed to set CR[01]. // One is MI, the other is a SUB instruction. // For CMPrr(r1,r2), we are looking for SUB(r1,r2) or SUB(r2,r1). @@ -1653,8 +1663,31 @@ // (and other explicit clobbers); instead we should really check for these // more explicitly (in at least a few predecessors). else if (MI->getParent() != CmpInstr.getParent() || Value != 0) { + if (FoundUse && !equalityOnly) { + MachineInstr *UseMI = &*I; + if (UseMI->getOpcode() == PPC::BCC) { + PPC::Predicate Pred = (PPC::Predicate)UseMI->getOperand(0).getImm(); + int16_t Immed = (int16_t)Value; + + if (Immed == -1 && Pred == PPC::PRED_GT) { + // "greater than -1" means "greater than or equal to 0" + // since we are assuming signed comparison by !equalityOnly + PredsToUpdate.push_back(std::make_pair(&(UseMI->getOperand(0)), + PPC::PRED_GE)); + NonZeroImmed = true; + } + else if (Immed == 1 && Pred == PPC::PRED_LT) { + // "less than 1" means "less than or equal to 0" + PredsToUpdate.push_back(std::make_pair(&(UseMI->getOperand(0)), + PPC::PRED_LE)); + NonZeroImmed = true; + } + } + } + // PPC does not have a record-form SUBri. - return false; + if (!NonZeroImmed) + return false; } // Search for Sub. @@ -1720,15 +1753,12 @@ if (NewOpC == -1) return false; - SmallVector, 4> PredsToUpdate; - SmallVector, 4> SubRegsToUpdate; - // If we have SUB(r1, r2) and CMP(r2, r1), the condition code based on CMP // needs to be updated to be based on SUB. Push the condition code // operands to OperandsToUpdate. If it is safe to remove CmpInstr, the // condition code of these operands will be modified. bool ShouldSwap = false; - if (Sub) { + if (Sub && !NonZeroImmed) { ShouldSwap = SrcReg2 != 0 && Sub->getOperand(1).getReg() == SrcReg2 && Sub->getOperand(2).getReg() == SrcReg; @@ -1765,6 +1795,8 @@ } else // We need to abort on a user we don't understand. return false; } + assert(!(NonZeroImmed && ShouldSwap) && + "NonZeroImmed and ShouldSwap may conflict in updating predicate"); // Create a new virtual register to hold the value of the CR set by the // record-form instruction. If the instruction was not previously in Index: test/CodeGen/PowerPC/opt-cmp-inst-cr0-live.ll =================================================================== --- test/CodeGen/PowerPC/opt-cmp-inst-cr0-live.ll +++ test/CodeGen/PowerPC/opt-cmp-inst-cr0-live.ll @@ -1,5 +1,6 @@ ; RUN: llc -verify-machineinstrs -print-before=peephole-opt -print-after=peephole-opt -mtriple=powerpc64-unknown-linux-gnu -o /dev/null 2>&1 < %s | FileCheck %s +; CHECK-LABEL: fn1 define signext i32 @fn1(i32 %baz) { %1 = mul nsw i32 %baz, 208 %2 = zext i32 %1 to i64 @@ -21,3 +22,35 @@ bar: ret i32 0 } + +; CHECK-LABEL: fn2 +define signext i32 @fn2(i64 %a, i64 %b) { +; CHECK: OR8o {{[^, ]+}}, {{[^, ]+}}, %CR0; +; CHECK: [[CREG:[^, ]+]] = COPY %CR0 +; CHECK: BCC 12, [[CREG]] + %1 = or i64 %b, %a + %2 = icmp sgt i64 %1, -1 + br i1 %2, label %foo, label %bar + +foo: + ret i32 1 + +bar: + ret i32 0 +} + +; CHECK-LABEL: fn3 +define signext i32 @fn3(i32 %a) { +; CHECK: ANDIo {{[^, ]+}}, 10, %CR0; +; CHECK: [[CREG:[^, ]+]] = COPY %CR0 +; CHECK: BCC 76, [[CREG]] + %1 = and i32 %a, 10 + %2 = icmp ne i32 %1, 0 + br i1 %2, label %foo, label %bar + +foo: + ret i32 1 + +bar: + ret i32 0 +}