forked from OSchip/llvm-project
ARM: Fix optimizeCompare to correctly check safe condition.
It is safe if CPSR is killed or re-defined. When we are done with the basic block, check whether CPSR is live-out. Do not optimize away cmp if CPSR is live-out. llvm-svn: 160090
This commit is contained in:
parent
1325384b32
commit
34cb93e192
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue