diff options
| author | Bill Wendling <isanbard@gmail.com> | 2010-08-06 01:32:48 +0000 |
|---|---|---|
| committer | Bill Wendling <isanbard@gmail.com> | 2010-08-06 01:32:48 +0000 |
| commit | e4ddbdfd3cf031034020671d03626f0373fbd5ca (patch) | |
| tree | 6f2a410521d3378fe204476415e5ba036c7ed9dc /lib/Target/ARM | |
| parent | 5759b9b8be05293e848308f01c6eeff70d2ce15d (diff) | |
Add the Optimize Compares pass (disabled by default).
This pass tries to remove comparison instructions when possible. For instance,
if you have this code:
sub r1, 1
cmp r1, 0
bz L1
and "sub" either sets the same flag as the "cmp" instruction or could be
converted to set the same flag, then we can eliminate the "cmp" instruction all
together. This is a important for ARM where the ALU instructions could set the
CPSR flag, but need a special suffix ('s') to do so.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@110423 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Target/ARM')
| -rw-r--r-- | lib/Target/ARM/ARMBaseInstrInfo.cpp | 56 | ||||
| -rw-r--r-- | lib/Target/ARM/ARMBaseInstrInfo.h | 11 |
2 files changed, 67 insertions, 0 deletions
diff --git a/lib/Target/ARM/ARMBaseInstrInfo.cpp b/lib/Target/ARM/ARMBaseInstrInfo.cpp index b9784eec1b..68e35ed75e 100644 --- a/lib/Target/ARM/ARMBaseInstrInfo.cpp +++ b/lib/Target/ARM/ARMBaseInstrInfo.cpp @@ -1353,3 +1353,59 @@ bool llvm::rewriteARMFrameIndex(MachineInstr &MI, unsigned FrameRegIdx, Offset = (isSub) ? -Offset : Offset; return Offset == 0; } + +bool ARMBaseInstrInfo:: +isCompareInstr(const MachineInstr *MI, unsigned &SrcReg, int &CmpValue) const { + switch (MI->getOpcode()) { + default: break; + case ARM::t2CMPri: + case ARM::t2CMPzri: + SrcReg = MI->getOperand(0).getReg(); + CmpValue = MI->getOperand(1).getImm(); + return true; + } + + return false; +} + +/// convertToSetZeroFlag - Convert the instruction to set the "zero" flag so +/// that we can remove a "comparison with zero". +bool ARMBaseInstrInfo:: +convertToSetZeroFlag(MachineInstr *MI, MachineInstr *CmpInstr) const { + // Conservatively refuse to convert an instruction which isn't in the same BB + // as the comparison. + if (MI->getParent() != CmpInstr->getParent()) + return false; + + // Check that CPSR isn't set between the comparison instruction and the one we + // want to change. + MachineBasicBlock::const_iterator I = CmpInstr, E = MI; + --I; + for (; I != E; --I) { + const MachineInstr &Instr = *I; + + for (unsigned IO = 0, EO = Instr.getNumOperands(); IO != EO; ++IO) { + const MachineOperand &MO = Instr.getOperand(IO); + if (!MO.isDef() || !MO.isReg()) continue; + + // This instruction modifies CPSR before the one we want to change. We + // can't do this transformation. + if (MO.getReg() == ARM::CPSR) + return false; + } + } + + // Set the "zero" bit in CPSR. + switch (MI->getOpcode()) { + default: break; + case ARM::t2SUBri: { + MI->RemoveOperand(5); + MachineInstrBuilder MB(MI); + MB.addReg(ARM::CPSR, RegState::Define | RegState::Implicit); + CmpInstr->eraseFromParent(); + return true; + } + } + + return false; +} diff --git a/lib/Target/ARM/ARMBaseInstrInfo.h b/lib/Target/ARM/ARMBaseInstrInfo.h index 20fae2e54e..4f1c453924 100644 --- a/lib/Target/ARM/ARMBaseInstrInfo.h +++ b/lib/Target/ARM/ARMBaseInstrInfo.h @@ -336,6 +336,17 @@ public: unsigned NumInstrs) const { return NumInstrs && NumInstrs == 1; } + + /// isCompareInstr - If the machine instruction is a comparison instruction, + /// then return true. Also return the source register in SrcReg and the value + /// it compares against in CmpValue. + virtual bool isCompareInstr(const MachineInstr *MI, unsigned &SrcReg, + int &CmpValue) const; + + /// convertToSetZeroFlag - Convert the instruction to set the zero flag so + /// that we can remove a "comparison with zero". + virtual bool convertToSetZeroFlag(MachineInstr *Instr, + MachineInstr *CmpInstr) const; }; static inline |
