diff options
author | Evan Cheng <evan.cheng@apple.com> | 2011-03-23 22:52:04 +0000 |
---|---|---|
committer | Evan Cheng <evan.cheng@apple.com> | 2011-03-23 22:52:04 +0000 |
commit | 425489d3972ca9819d0c72e9d61e46493e26e635 (patch) | |
tree | 9861b3a415293caefd9227ec9763c19ace1fad6f /llvm/lib/Target/ARM/ARMBaseInstrInfo.cpp | |
parent | ca1176aaeefa0e7adf36d10d6d441dfabffe2175 (diff) | |
download | bcm5719-llvm-425489d3972ca9819d0c72e9d61e46493e26e635.tar.gz bcm5719-llvm-425489d3972ca9819d0c72e9d61e46493e26e635.zip |
Cmp peephole optimization isn't always safe for signed arithmetics.
int tries = INT_MAX;
while (tries > 0) {
tries--;
}
The check should be:
subs r4, #1
cmp r4, #0
bgt LBB0_1
The subs can set the overflow V bit when r4 is INT_MAX+1 (which loop
canonicalization apparently does in this case). cmp #0 would have cleared
it while not changing the N and Z bits. Since BGT is dependent on the V
bit, i.e. (N == V) && !Z, it is not safe to eliminate the cmp #0.
rdar://9172742
llvm-svn: 128179
Diffstat (limited to 'llvm/lib/Target/ARM/ARMBaseInstrInfo.cpp')
-rw-r--r-- | llvm/lib/Target/ARM/ARMBaseInstrInfo.cpp | 46 |
1 files changed, 43 insertions, 3 deletions
diff --git a/llvm/lib/Target/ARM/ARMBaseInstrInfo.cpp b/llvm/lib/Target/ARM/ARMBaseInstrInfo.cpp index a56df304eab..b5f20a44021 100644 --- a/llvm/lib/Target/ARM/ARMBaseInstrInfo.cpp +++ b/llvm/lib/Target/ARM/ARMBaseInstrInfo.cpp @@ -1612,11 +1612,51 @@ OptimizeCompareInstr(MachineInstr *CmpInstr, unsigned SrcReg, int CmpMask, switch (MI->getOpcode()) { default: break; case ARM::ADDri: - case ARM::ANDri: - case ARM::t2ANDri: case ARM::SUBri: case ARM::t2ADDri: - case ARM::t2SUBri: + case ARM::t2SUBri: { + // Scan forward for the use of CPSR, 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. + bool isSafe = false; + I = CmpInstr; + E = MI->getParent()->end(); + while (!isSafe && ++I != E) { + const MachineInstr &Instr = *I; + for (unsigned IO = 0, EO = Instr.getNumOperands(); + !isSafe && IO != EO; ++IO) { + const MachineOperand &MO = Instr.getOperand(IO); + if (!MO.isReg() || MO.getReg() != ARM::CPSR) + continue; + if (MO.isDef()) { + isSafe = true; + break; + } + // Condition code is after the operand before CPSR. + ARMCC::CondCodes CC = (ARMCC::CondCodes)Instr.getOperand(IO-1).getImm(); + switch (CC) { + default: + isSafe = true; + break; + case ARMCC::VS: + case ARMCC::VC: + case ARMCC::GE: + case ARMCC::LT: + case ARMCC::GT: + case ARMCC::LE: + return false; + } + } + } + + if (!isSafe) + return false; + + // fallthrough + } + case ARM::ANDri: + case ARM::t2ANDri: // Toggle the optional operand to CPSR. MI->getOperand(5).setReg(ARM::CPSR); MI->getOperand(5).setIsDef(true); |