diff options
-rw-r--r-- | lib/Target/ARM/ARMBaseInstrInfo.cpp | 23 | ||||
-rw-r--r-- | test/CodeGen/ARM/sub-cmp-peephole.ll | 19 |
2 files changed, 33 insertions, 9 deletions
diff --git a/lib/Target/ARM/ARMBaseInstrInfo.cpp b/lib/Target/ARM/ARMBaseInstrInfo.cpp index 57c20ae..3393f09 100644 --- a/lib/Target/ARM/ARMBaseInstrInfo.cpp +++ b/lib/Target/ARM/ARMBaseInstrInfo.cpp @@ -1974,10 +1974,10 @@ optimizeCompareInstr(MachineInstr *CmpInstr, unsigned SrcReg, unsigned SrcReg2, case ARM::t2EORri: { // Scan forward for the use of CPSR // When checking against MI: if it's a conditional code requires - // checking of V bit, then this is not safe to do. If we can't find the - // CPSR use (i.e. used in another block), then it's not safe to perform - // the optimization. - // When checking against Sub, we handle the condition codes GE, LT, GT, LE. + // checking of V bit, then this is not safe to do. + // It is safe to remove CmpInstr if CPSR is redefined or killed. + // If we are done with the basic block, we need to check whether CPSR is + // live-out. SmallVector<std::pair<MachineOperand*, ARMCC::CondCodes>, 4> OperandsToUpdate; bool isSafe = false; @@ -2017,7 +2017,7 @@ optimizeCompareInstr(MachineInstr *CmpInstr, unsigned SrcReg, unsigned SrcReg2, else switch (CC) { default: - isSafe = true; + // CPSR can be used mutliple times, we should continue. break; case ARMCC::VS: case ARMCC::VC: @@ -2030,10 +2030,15 @@ optimizeCompareInstr(MachineInstr *CmpInstr, unsigned SrcReg, unsigned SrcReg2, } } - // If the candidate is Sub, we may exit the loop at end of the basic block. - // In that case, it is still safe to remove CmpInstr. - if (!isSafe && !Sub) - return false; + // If CPSR is not killed nor re-defined, we should check whether it is + // live-out. If it is live-out, do not optimize. + if (!isSafe) { + MachineBasicBlock *MBB = CmpInstr->getParent(); + for (MachineBasicBlock::succ_iterator SI = MBB->succ_begin(), + SE = MBB->succ_end(); SI != SE; ++SI) + if ((*SI)->isLiveIn(ARM::CPSR)) + return false; + } // Toggle the optional operand to CPSR. MI->getOperand(5).setReg(ARM::CPSR); diff --git a/test/CodeGen/ARM/sub-cmp-peephole.ll b/test/CodeGen/ARM/sub-cmp-peephole.ll index c46c891..6fcbdee 100644 --- a/test/CodeGen/ARM/sub-cmp-peephole.ll +++ b/test/CodeGen/ARM/sub-cmp-peephole.ll @@ -44,3 +44,22 @@ entry: %sub. = select i1 %cmp, i32 %sub, i32 0 ret i32 %sub. } +; If CPSR is live-out, we can't remove cmp if there exists +; a swapped sub. +define i32 @j(i32 %a, i32 %b) nounwind { +entry: +; CHECK: j: +; CHECK: sub +; CHECK: cmp + %cmp = icmp eq i32 %b, %a + %sub = sub nsw i32 %a, %b + br i1 %cmp, label %if.then, label %if.else + +if.then: + %cmp2 = icmp sgt i32 %b, %a + %sel = select i1 %cmp2, i32 %sub, i32 %a + ret i32 %sel + +if.else: + ret i32 %sub +} |