[llvm-commits] [llvm] r76883 - in /llvm/trunk/lib/Target/ARM: ARMBaseInstrInfo.h ARMBaseRegisterInfo.cpp ARMBaseRegisterInfo.h ARMInstrInfo.cpp ARMInstrInfo.h ARMInstrThumb2.td Thumb1InstrInfo.cpp Thumb1InstrInfo.h Thumb2InstrInfo.cpp Thumb2InstrInfo.h
David Goodwin
david_goodwin at apple.com
Thu Jul 23 10:06:47 PDT 2009
Author: david_goodwin
Date: Thu Jul 23 12:06:46 2009
New Revision: 76883
URL: http://llvm.org/viewvc/llvm-project?rev=76883&view=rev
Log:
Fix frame index elimination to correctly handle thumb-2 addressing modes that don't allow negative offsets. During frame elimination convert *i12 opcode to a *i8 when necessary due to a negative offset.
Modified:
llvm/trunk/lib/Target/ARM/ARMBaseInstrInfo.h
llvm/trunk/lib/Target/ARM/ARMBaseRegisterInfo.cpp
llvm/trunk/lib/Target/ARM/ARMBaseRegisterInfo.h
llvm/trunk/lib/Target/ARM/ARMInstrInfo.cpp
llvm/trunk/lib/Target/ARM/ARMInstrInfo.h
llvm/trunk/lib/Target/ARM/ARMInstrThumb2.td
llvm/trunk/lib/Target/ARM/Thumb1InstrInfo.cpp
llvm/trunk/lib/Target/ARM/Thumb1InstrInfo.h
llvm/trunk/lib/Target/ARM/Thumb2InstrInfo.cpp
llvm/trunk/lib/Target/ARM/Thumb2InstrInfo.h
Modified: llvm/trunk/lib/Target/ARM/ARMBaseInstrInfo.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/ARMBaseInstrInfo.h?rev=76883&r1=76882&r2=76883&view=diff
==============================================================================
--- llvm/trunk/lib/Target/ARM/ARMBaseInstrInfo.h (original)
+++ llvm/trunk/lib/Target/ARM/ARMBaseInstrInfo.h Thu Jul 23 12:06:46 2009
@@ -215,6 +215,13 @@
// Return the opcode that implements 'Op', or 0 if no opcode
virtual unsigned getOpcode(ARMII::Op Op) const =0;
+ // If 'opcode' is an instruction with an unsigned offset that also
+ // has a version with a signed offset, return the opcode for the
+ // version with the signed offset. In 'NumBits' return the number of
+ // bits for the signed offset.
+ virtual unsigned unsignedOffsetOpcodeToSigned(unsigned opcode,
+ unsigned *NumBits) const = 0;
+
// Return true if the block does not fall through.
virtual bool BlockHasNoFallThrough(const MachineBasicBlock &MBB) const =0;
Modified: llvm/trunk/lib/Target/ARM/ARMBaseRegisterInfo.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/ARMBaseRegisterInfo.cpp?rev=76883&r1=76882&r2=76883&view=diff
==============================================================================
--- llvm/trunk/lib/Target/ARM/ARMBaseRegisterInfo.cpp (original)
+++ llvm/trunk/lib/Target/ARM/ARMBaseRegisterInfo.cpp Thu Jul 23 12:06:46 2009
@@ -142,6 +142,11 @@
return TII.getOpcode((ARMII::Op)Op);
}
+unsigned ARMBaseRegisterInfo::
+unsignedOffsetOpcodeToSigned(unsigned opcode, unsigned *NumBits) const {
+ return TII.unsignedOffsetOpcodeToSigned(opcode, NumBits);
+}
+
const unsigned*
ARMBaseRegisterInfo::getCalleeSavedRegs(const MachineFunction *MF) const {
static const unsigned CalleeSavedRegs[] = {
@@ -1109,6 +1114,8 @@
int InstrOffs = 0;
unsigned NumBits = 0;
unsigned Scale = 1;
+ bool encodedOffset = true;
+ bool HandlesNeg = true;
switch (AddrMode) {
case ARMII::AddrMode2: {
ImmIdx = i+2;
@@ -1139,17 +1146,21 @@
ImmIdx = i+1;
InstrOffs = MI.getOperand(ImmIdx).getImm();
NumBits = 12;
+ encodedOffset = false;
+ HandlesNeg = false;
break;
}
case ARMII::AddrModeT2_i8: {
ImmIdx = i+1;
InstrOffs = MI.getOperand(ImmIdx).getImm();
NumBits = 8;
+ encodedOffset = false;
break;
}
case ARMII::AddrModeT2_so: {
ImmIdx = i+2;
InstrOffs = MI.getOperand(ImmIdx).getImm();
+ encodedOffset = false;
break;
}
default:
@@ -1160,29 +1171,55 @@
Offset += InstrOffs * Scale;
assert((Offset & (Scale-1)) == 0 && "Can't encode this offset!");
if (Offset < 0) {
+ // For addrmodes that cannot handle negative offsets, convert to
+ // an opcode that can, or set NumBits == 0 to avoid folding
+ // address computation
+ if (!HandlesNeg) {
+ unsigned usop = unsignedOffsetOpcodeToSigned(Opcode, &NumBits);
+ if (usop != 0) {
+ MI.setDesc(TII.get(usop));
+ HandlesNeg = true;
+ Opcode = usop;
+ }
+ else {
+ NumBits = 0;
+ }
+ }
+
Offset = -Offset;
isSub = true;
}
- // Common case: small offset, fits into instruction.
- MachineOperand &ImmOp = MI.getOperand(ImmIdx);
- int ImmedOffset = Offset / Scale;
- unsigned Mask = (1 << NumBits) - 1;
- if ((unsigned)Offset <= Mask * Scale) {
- // Replace the FrameIndex with sp
- MI.getOperand(i).ChangeToRegister(FrameReg, false);
- if (isSub)
- ImmedOffset |= 1 << NumBits;
+ // Attempt to fold address comp. if opcode has offset bits
+ if (NumBits > 0) {
+ // Common case: small offset, fits into instruction.
+ MachineOperand &ImmOp = MI.getOperand(ImmIdx);
+ int ImmedOffset = Offset / Scale;
+ unsigned Mask = (1 << NumBits) - 1;
+ if ((unsigned)Offset <= Mask * Scale) {
+ // Replace the FrameIndex with sp
+ MI.getOperand(i).ChangeToRegister(FrameReg, false);
+ if (isSub) {
+ if (encodedOffset)
+ ImmedOffset |= 1 << NumBits;
+ else
+ ImmedOffset = -ImmedOffset;
+ }
+ ImmOp.ChangeToImmediate(ImmedOffset);
+ return;
+ }
+
+ // Otherwise, it didn't fit. Pull in what we can to simplify the immed.
+ ImmedOffset = ImmedOffset & Mask;
+ if (isSub) {
+ if (encodedOffset)
+ ImmedOffset |= 1 << NumBits;
+ else
+ ImmedOffset = -ImmedOffset;
+ }
ImmOp.ChangeToImmediate(ImmedOffset);
- return;
+ Offset &= ~(Mask*Scale);
}
-
- // Otherwise, it didn't fit. Pull in what we can to simplify the immed.
- ImmedOffset = ImmedOffset & Mask;
- if (isSub)
- ImmedOffset |= 1 << NumBits;
- ImmOp.ChangeToImmediate(ImmedOffset);
- Offset &= ~(Mask*Scale);
}
// If we get here, the immediate doesn't fit into the instruction. We folded
Modified: llvm/trunk/lib/Target/ARM/ARMBaseRegisterInfo.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/ARMBaseRegisterInfo.h?rev=76883&r1=76882&r2=76883&view=diff
==============================================================================
--- llvm/trunk/lib/Target/ARM/ARMBaseRegisterInfo.h (original)
+++ llvm/trunk/lib/Target/ARM/ARMBaseRegisterInfo.h Thu Jul 23 12:06:46 2009
@@ -59,6 +59,13 @@
// Return the opcode that implements 'Op', or 0 if no opcode
unsigned getOpcode(int Op) const;
+ // If 'opcode' is an instruction with an unsigned offset that also
+ // has a version with a signed offset, return the opcode for the
+ // version with the signed offset. In 'NumBits' return the number of
+ // bits for the signed offset.
+ unsigned unsignedOffsetOpcodeToSigned(unsigned opcode,
+ unsigned *NumBits) const;
+
public:
/// getRegisterNumbering - Given the enum value for some register, e.g.
/// ARM::LR, return the number that it corresponds to (e.g. 14). It
Modified: llvm/trunk/lib/Target/ARM/ARMInstrInfo.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/ARMInstrInfo.cpp?rev=76883&r1=76882&r2=76883&view=diff
==============================================================================
--- llvm/trunk/lib/Target/ARM/ARMInstrInfo.cpp (original)
+++ llvm/trunk/lib/Target/ARM/ARMInstrInfo.cpp Thu Jul 23 12:06:46 2009
@@ -30,6 +30,11 @@
}
unsigned ARMInstrInfo::
+unsignedOffsetOpcodeToSigned(unsigned opcode, unsigned *NumBits) const {
+ return 0;
+}
+
+unsigned ARMInstrInfo::
getUnindexedOpcode(unsigned Opc) const {
switch (Opc) {
default: break;
Modified: llvm/trunk/lib/Target/ARM/ARMInstrInfo.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/ARMInstrInfo.h?rev=76883&r1=76882&r2=76883&view=diff
==============================================================================
--- llvm/trunk/lib/Target/ARM/ARMInstrInfo.h (original)
+++ llvm/trunk/lib/Target/ARM/ARMInstrInfo.h Thu Jul 23 12:06:46 2009
@@ -35,6 +35,13 @@
// Return the opcode that implements 'Op', or 0 if no opcode
unsigned getOpcode(ARMII::Op Op) const;
+ // If 'opcode' is an instruction with an unsigned offset that also
+ // has a version with a signed offset, return the opcode for the
+ // version with the signed offset. In 'NumBits' return the number of
+ // bits for the signed offset.
+ unsigned unsignedOffsetOpcodeToSigned(unsigned opcode,
+ unsigned *NumBits) const;
+
// Return true if the block does not fall through.
bool BlockHasNoFallThrough(const MachineBasicBlock &MBB) const;
Modified: llvm/trunk/lib/Target/ARM/ARMInstrThumb2.td
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/ARMInstrThumb2.td?rev=76883&r1=76882&r2=76883&view=diff
==============================================================================
--- llvm/trunk/lib/Target/ARM/ARMInstrThumb2.td (original)
+++ llvm/trunk/lib/Target/ARM/ARMInstrThumb2.td Thu Jul 23 12:06:46 2009
@@ -109,7 +109,7 @@
let MIOperandInfo = (ops GPR:$base, i32imm:$offsimm);
}
-// t2addrmode_imm8 := reg - imm8
+// t2addrmode_imm8 := reg +/- imm8
def t2addrmode_imm8 : Operand<i32>,
ComplexPattern<i32, 2, "SelectT2AddrModeImm8", []> {
let PrintMethod = "printT2AddrModeImm8Operand";
Modified: llvm/trunk/lib/Target/ARM/Thumb1InstrInfo.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/Thumb1InstrInfo.cpp?rev=76883&r1=76882&r2=76883&view=diff
==============================================================================
--- llvm/trunk/lib/Target/ARM/Thumb1InstrInfo.cpp (original)
+++ llvm/trunk/lib/Target/ARM/Thumb1InstrInfo.cpp Thu Jul 23 12:06:46 2009
@@ -30,6 +30,12 @@
return 0;
}
+unsigned
+Thumb1InstrInfo::unsignedOffsetOpcodeToSigned(unsigned opcode,
+ unsigned *NumBits) const {
+ return 0;
+}
+
unsigned Thumb1InstrInfo::getOpcode(ARMII::Op Op) const {
switch (Op) {
case ARMII::ADDri: return ARM::tADDi8;
Modified: llvm/trunk/lib/Target/ARM/Thumb1InstrInfo.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/Thumb1InstrInfo.h?rev=76883&r1=76882&r2=76883&view=diff
==============================================================================
--- llvm/trunk/lib/Target/ARM/Thumb1InstrInfo.h (original)
+++ llvm/trunk/lib/Target/ARM/Thumb1InstrInfo.h Thu Jul 23 12:06:46 2009
@@ -34,6 +34,13 @@
// Return the opcode that implements 'Op', or 0 if no opcode
unsigned getOpcode(ARMII::Op Op) const;
+ // If 'opcode' is an instruction with an unsigned offset that also
+ // has a version with a signed offset, return the opcode for the
+ // version with the signed offset. In 'NumBits' return the number of
+ // bits for the signed offset.
+ unsigned unsignedOffsetOpcodeToSigned(unsigned opcode,
+ unsigned *NumBits) const;
+
// Return true if the block does not fall through.
bool BlockHasNoFallThrough(const MachineBasicBlock &MBB) const;
Modified: llvm/trunk/lib/Target/ARM/Thumb2InstrInfo.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/Thumb2InstrInfo.cpp?rev=76883&r1=76882&r2=76883&view=diff
==============================================================================
--- llvm/trunk/lib/Target/ARM/Thumb2InstrInfo.cpp (original)
+++ llvm/trunk/lib/Target/ARM/Thumb2InstrInfo.cpp Thu Jul 23 12:06:46 2009
@@ -88,6 +88,29 @@
return false;
}
+unsigned
+Thumb2InstrInfo::unsignedOffsetOpcodeToSigned(unsigned opcode,
+ unsigned *NumBits) const
+{
+ if (NumBits != NULL)
+ *NumBits = 8;
+
+ switch (opcode) {
+ case ARM::t2LDRi12: return ARM::t2LDRi8;
+ case ARM::t2LDRHi12: return ARM::t2LDRHi8;
+ case ARM::t2LDRBi12: return ARM::t2LDRBi8;
+ case ARM::t2LDRSHi12: return ARM::t2LDRSHi8;
+ case ARM::t2LDRSBi12: return ARM::t2LDRSBi8;
+ case ARM::t2STRi12: return ARM::t2STRi8;
+ case ARM::t2STRBi12: return ARM::t2STRBi8;
+ case ARM::t2STRHi12: return ARM::t2STRHi8;
+ default:
+ break;
+ }
+
+ return 0;
+}
+
bool
Thumb2InstrInfo::copyRegToReg(MachineBasicBlock &MBB,
MachineBasicBlock::iterator I,
Modified: llvm/trunk/lib/Target/ARM/Thumb2InstrInfo.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/Thumb2InstrInfo.h?rev=76883&r1=76882&r2=76883&view=diff
==============================================================================
--- llvm/trunk/lib/Target/ARM/Thumb2InstrInfo.h (original)
+++ llvm/trunk/lib/Target/ARM/Thumb2InstrInfo.h Thu Jul 23 12:06:46 2009
@@ -34,6 +34,13 @@
// Return the opcode that implements 'Op', or 0 if no opcode
unsigned getOpcode(ARMII::Op Op) const;
+ // If 'opcode' is an instruction with an unsigned offset that also
+ // has a version with a signed offset, return the opcode for the
+ // version with the signed offset. In 'NumBits' return the number of
+ // bits for the signed offset.
+ unsigned unsignedOffsetOpcodeToSigned(unsigned opcode,
+ unsigned *NumBits) const;
+
// Return true if the block does not fall through.
bool BlockHasNoFallThrough(const MachineBasicBlock &MBB) const;
More information about the llvm-commits
mailing list