aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRafael Espindola <rafael.espindola@gmail.com>2006-12-14 13:31:27 +0000
committerRafael Espindola <rafael.espindola@gmail.com>2006-12-14 13:31:27 +0000
commit15f17a7c4746b8533aabf7c78bde82503ad9fc9f (patch)
tree1495b7007f884fa413bcee1e1e3c81c18540f7e6
parent7a0d51c8e3d6cdc6d961f6525f97f8926fb76c83 (diff)
Avoid creating invalid sub/add instructions on the prolog/epilog
patch by Lauro git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@32577 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--lib/Target/ARM/ARMRegisterInfo.cpp96
-rw-r--r--test/CodeGen/ARM/addSubConstant.ll19
2 files changed, 105 insertions, 10 deletions
diff --git a/lib/Target/ARM/ARMRegisterInfo.cpp b/lib/Target/ARM/ARMRegisterInfo.cpp
index 027b193922..47090b2488 100644
--- a/lib/Target/ARM/ARMRegisterInfo.cpp
+++ b/lib/Target/ARM/ARMRegisterInfo.cpp
@@ -35,6 +35,80 @@ static bool hasFP(const MachineFunction &MF) {
return NoFramePointerElim || MFI->hasVarSizedObjects();
}
+#define ROTATE32L(x, n) (((x) << (n)) | ((x) >> (32 - (n))))
+
+#define ROTATE32R(x, n) (((x) >> (n)) | ((x) << (32 - (n))))
+
+// finds the end position of largest sequence of zeros in binary representation
+// of 'immediate'.
+static int findLargestZeroSequence(unsigned immediate){
+ int max_zero_pos;
+ int max_zero_length = 0;
+ int zero_pos;
+ int zero_length;
+ int pos = 0;
+ int end_pos;
+
+ while ((immediate & 0x3) == 0) {
+ immediate = ROTATE32R(immediate, 2);
+ pos+=2;
+ }
+ end_pos = pos+32;
+
+ while (pos<end_pos){
+ while ((immediate & 0x3) != 0) {
+ immediate = ROTATE32R(immediate, 2);
+ pos+=2;
+ }
+ zero_pos = pos;
+ while ((immediate & 0x3) == 0) {
+ immediate = ROTATE32R(immediate, 2);
+ pos+=2;
+ }
+ zero_length = pos - zero_pos;
+ if (zero_length > max_zero_length){
+ max_zero_length = zero_length;
+ max_zero_pos = zero_pos % 32;
+ }
+
+ }
+
+ return (max_zero_pos + max_zero_length) % 32;
+}
+
+static void splitInstructionWithImmediate(MachineBasicBlock &BB,
+ MachineBasicBlock::iterator I,
+ const TargetInstrDescriptor &TID,
+ unsigned DestReg,
+ unsigned OrigReg,
+ unsigned immediate){
+
+ if (immediate == 0){
+ BuildMI(BB, I, TID, DestReg).addReg(OrigReg).addImm(0)
+ .addImm(0).addImm(ARMShift::LSL);
+ return;
+ }
+
+ int start_pos = findLargestZeroSequence(immediate);
+ unsigned immediate_tmp = ROTATE32R(immediate, start_pos);
+
+ int pos = 0;
+ while (pos < 32){
+ while(((immediate_tmp&0x3) == 0)&&(pos<32)){
+ immediate_tmp = ROTATE32R(immediate_tmp,2);
+ pos+=2;
+ }
+ if (pos < 32){
+ BuildMI(BB, I, TID, DestReg).addReg(OrigReg)
+ .addImm(ROTATE32L(immediate_tmp&0xFF, (start_pos + pos) % 32 ))
+ .addImm(0).addImm(ARMShift::LSL);
+ immediate_tmp = ROTATE32R(immediate_tmp,8);
+ pos+=8;
+ }
+ }
+
+}
+
ARMRegisterInfo::ARMRegisterInfo(const TargetInstrInfo &tii)
: ARMGenRegisterInfo(ARM::ADJCALLSTACKDOWN, ARM::ADJCALLSTACKUP),
TII(tii) {
@@ -110,13 +184,13 @@ eliminateCallFramePseudoInstr(MachineFunction &MF, MachineBasicBlock &MBB,
if (Old->getOpcode() == ARM::ADJCALLSTACKDOWN) {
// sub sp, sp, amount
- BuildMI(MBB, I, TII.get(ARM::SUB), ARM::R13).addReg(ARM::R13).addImm(Amount)
- .addImm(0).addImm(ARMShift::LSL);
+ splitInstructionWithImmediate(MBB, I, TII.get(ARM::SUB), ARM::R13,
+ ARM::R13, Amount);
} else {
// add sp, sp, amount
assert(Old->getOpcode() == ARM::ADJCALLSTACKUP);
- BuildMI(MBB, I, TII.get(ARM::ADD), ARM::R13).addReg(ARM::R13).addImm(Amount)
- .addImm(0).addImm(ARMShift::LSL);
+ splitInstructionWithImmediate(MBB, I, TII.get(ARM::ADD), ARM::R13,
+ ARM::R13, Amount);
}
}
}
@@ -156,8 +230,8 @@ ARMRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II) const {
// Insert a set of r12 with the full address
// r12 = r13 + offset
MachineBasicBlock *MBB2 = MI.getParent();
- BuildMI(*MBB2, II, TII.get(ARM::ADD), ARM::R12).addReg(BaseRegister)
- .addImm(Offset).addImm(0).addImm(ARMShift::LSL);
+ splitInstructionWithImmediate(*MBB2, II, TII.get(ARM::ADD), ARM::R12,
+ BaseRegister, Offset);
// Replace the FrameIndex with r12
MI.getOperand(FrameIdx).ChangeToRegister(ARM::R12, false);
@@ -192,8 +266,9 @@ void ARMRegisterInfo::emitPrologue(MachineFunction &MF) const {
MFI->setStackSize(NumBytes);
//sub sp, sp, #NumBytes
- BuildMI(MBB, MBBI, TII.get(ARM::SUB), ARM::R13).addReg(ARM::R13).addImm(NumBytes)
- .addImm(0).addImm(ARMShift::LSL);
+ splitInstructionWithImmediate(MBB, MBBI, TII.get(ARM::SUB), ARM::R13,
+ ARM::R13, NumBytes);
+
if (HasFP) {
BuildMI(MBB, MBBI, TII.get(ARM::STR))
@@ -219,8 +294,9 @@ void ARMRegisterInfo::emitEpilogue(MachineFunction &MF,
}
//add sp, sp, #NumBytes
- BuildMI(MBB, MBBI, TII.get(ARM::ADD), ARM::R13).addReg(ARM::R13).addImm(NumBytes)
- .addImm(0).addImm(ARMShift::LSL);
+ splitInstructionWithImmediate(MBB, MBBI, TII.get(ARM::ADD), ARM::R13,
+ ARM::R13, NumBytes);
+
}
unsigned ARMRegisterInfo::getRARegister() const {
diff --git a/test/CodeGen/ARM/addSubConstant.ll b/test/CodeGen/ARM/addSubConstant.ll
new file mode 100644
index 0000000000..1cb8844c03
--- /dev/null
+++ b/test/CodeGen/ARM/addSubConstant.ll
@@ -0,0 +1,19 @@
+; RUN: llvm-upgrade < %s | llvm-as | llc -march=arm &&
+; RUN: llvm-upgrade < %s | llvm-as | llc -march=arm | not grep "805306384"
+
+
+int %main() {
+entry:
+ %retval = alloca int, align 4 ; <int*> [#uses=2]
+ %tmp = alloca int, align 4 ; <int*> [#uses=2]
+ %a = alloca [805306369 x sbyte], align 16 ; <[805306369 x sbyte]*> [#uses=0]
+ "alloca point" = bitcast int 0 to int ; <int> [#uses=0]
+ store int 0, int* %tmp
+ %tmp = load int* %tmp ; <int> [#uses=1]
+ store int %tmp, int* %retval
+ br label %return
+
+return: ; preds = %entry
+ %retval = load int* %retval ; <int> [#uses=1]
+ ret int %retval
+}