From 15f17a7c4746b8533aabf7c78bde82503ad9fc9f Mon Sep 17 00:00:00 2001 From: Rafael Espindola Date: Thu, 14 Dec 2006 13:31:27 +0000 Subject: [PATCH] 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 --- lib/Target/ARM/ARMRegisterInfo.cpp | 96 ++++++++++++++++++++++++++---- test/CodeGen/ARM/addSubConstant.ll | 19 ++++++ 2 files changed, 105 insertions(+), 10 deletions(-) create mode 100644 test/CodeGen/ARM/addSubConstant.ll diff --git a/lib/Target/ARM/ARMRegisterInfo.cpp b/lib/Target/ARM/ARMRegisterInfo.cpp index 027b1939223..47090b2488c 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 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 00000000000..1cb8844c035 --- /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 ; [#uses=2] + %tmp = alloca int, align 4 ; [#uses=2] + %a = alloca [805306369 x sbyte], align 16 ; <[805306369 x sbyte]*> [#uses=0] + "alloca point" = bitcast int 0 to int ; [#uses=0] + store int 0, int* %tmp + %tmp = load int* %tmp ; [#uses=1] + store int %tmp, int* %retval + br label %return + +return: ; preds = %entry + %retval = load int* %retval ; [#uses=1] + ret int %retval +}