From 2fee935bbaa72bc0f438378156f6f741a9ab9662 Mon Sep 17 00:00:00 2001 From: Venkatraman Govindaraju Date: Sun, 24 Nov 2013 20:23:25 +0000 Subject: [PATCH] [Sparc] Emit large negative adjustments to SP/FP with sethi+xor instead of sethi+or. This generates correct code for both sparc32 and sparc64. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@195576 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Target/Sparc/Sparc.h | 17 +++++ lib/Target/Sparc/SparcFrameLowering.cpp | 82 +++++++++++++++---------- lib/Target/Sparc/SparcFrameLowering.h | 8 +++ lib/Target/Sparc/SparcRegisterInfo.cpp | 41 ++++++++++--- test/CodeGen/SPARC/64abi.ll | 21 +++++++ 5 files changed, 129 insertions(+), 40 deletions(-) diff --git a/lib/Target/Sparc/Sparc.h b/lib/Target/Sparc/Sparc.h index f2d632e54c0..f44b60420d0 100644 --- a/lib/Target/Sparc/Sparc.h +++ b/lib/Target/Sparc/Sparc.h @@ -105,5 +105,22 @@ namespace llvm { } llvm_unreachable("Invalid cond code"); } + + inline static unsigned HI22(int64_t imm) { + return (unsigned)((imm >> 10) & ((1 << 22)-1)); + } + + inline static unsigned LO10(int64_t imm) { + return (unsigned)(imm & 0x3FF); + } + + inline static unsigned HIX22(int64_t imm) { + return HI22(~imm); + } + + inline static unsigned LOX10(int64_t imm) { + return ~LO10(~imm); + } + } // end namespace llvm #endif diff --git a/lib/Target/Sparc/SparcFrameLowering.cpp b/lib/Target/Sparc/SparcFrameLowering.cpp index 1f9cac54b89..77afafbf950 100644 --- a/lib/Target/Sparc/SparcFrameLowering.cpp +++ b/lib/Target/Sparc/SparcFrameLowering.cpp @@ -33,6 +33,51 @@ DisableLeafProc("disable-sparc-leaf-proc", cl::Hidden); +void SparcFrameLowering::emitSPAdjustment(MachineFunction &MF, + MachineBasicBlock &MBB, + MachineBasicBlock::iterator MBBI, + int NumBytes, + unsigned ADDrr, + unsigned ADDri) const { + + DebugLoc dl = (MBBI != MBB.end()) ? MBBI->getDebugLoc() : DebugLoc(); + const SparcInstrInfo &TII = + *static_cast(MF.getTarget().getInstrInfo()); + + if (NumBytes >= -4096 && NumBytes < 4096) { + BuildMI(MBB, MBBI, dl, TII.get(ADDri), SP::O6) + .addReg(SP::O6).addImm(NumBytes); + return; + } + + // Emit this the hard way. This clobbers G1 which we always know is + // available here. + if (NumBytes >= 0) { + // Emit nonnegative numbers with sethi + or. + // sethi %hi(NumBytes), %g1 + // or %g1, %lo(NumBytes), %g1 + // add %sp, %g1, %sp + BuildMI(MBB, MBBI, dl, TII.get(SP::SETHIi), SP::G1) + .addImm(HI22(NumBytes)); + BuildMI(MBB, MBBI, dl, TII.get(SP::ORri), SP::G1) + .addReg(SP::G1).addImm(LO10(NumBytes)); + BuildMI(MBB, MBBI, dl, TII.get(ADDrr), SP::O6) + .addReg(SP::O6).addReg(SP::G1); + return ; + } + + // Emit negative numbers with sethi + xor. + // sethi %hix(NumBytes), %g1 + // xor %g1, %lox(NumBytes), %g1 + // add %sp, %g1, %sp + BuildMI(MBB, MBBI, dl, TII.get(SP::SETHIi), SP::G1) + .addImm(HIX22(NumBytes)); + BuildMI(MBB, MBBI, dl, TII.get(SP::XORri), SP::G1) + .addReg(SP::G1).addImm(LOX10(NumBytes)); + BuildMI(MBB, MBBI, dl, TII.get(ADDrr), SP::O6) + .addReg(SP::O6).addReg(SP::G1); +} + void SparcFrameLowering::emitPrologue(MachineFunction &MF) const { SparcMachineFunctionInfo *FuncInfo = MF.getInfo(); @@ -55,21 +100,8 @@ void SparcFrameLowering::emitPrologue(MachineFunction &MF) const { SAVErr = SP::ADDrr; } NumBytes = - SubTarget.getAdjustedFrameSize(NumBytes); + emitSPAdjustment(MF, MBB, MBBI, NumBytes, SAVErr, SAVEri); - if (NumBytes >= -4096) { - BuildMI(MBB, MBBI, dl, TII.get(SAVEri), SP::O6) - .addReg(SP::O6).addImm(NumBytes); - } else { - // Emit this the hard way. This clobbers G1 which we always know is - // available here. - unsigned OffHi = (unsigned)NumBytes >> 10U; - BuildMI(MBB, MBBI, dl, TII.get(SP::SETHIi), SP::G1).addImm(OffHi); - // Emit G1 = G1 + I6 - BuildMI(MBB, MBBI, dl, TII.get(SP::ORri), SP::G1) - .addReg(SP::G1).addImm(NumBytes & ((1 << 10)-1)); - BuildMI(MBB, MBBI, dl, TII.get(SAVErr), SP::O6) - .addReg(SP::O6).addReg(SP::G1); - } MachineModuleInfo &MMI = MF.getMMI(); const MCRegisterInfo *MRI = MMI.getContext().getRegisterInfo(); MCSymbol *FrameLabel = MMI.getContext().CreateTempSymbol(); @@ -100,11 +132,9 @@ eliminateCallFramePseudoInstr(MachineFunction &MF, MachineBasicBlock &MBB, int Size = MI.getOperand(0).getImm(); if (MI.getOpcode() == SP::ADJCALLSTACKDOWN) Size = -Size; - const SparcInstrInfo &TII = - *static_cast(MF.getTarget().getInstrInfo()); + if (Size) - BuildMI(MBB, I, DL, TII.get(SP::ADDri), SP::O6).addReg(SP::O6) - .addImm(Size); + emitSPAdjustment(MF, MBB, I, Size, SP::ADDrr, SP::ADDri); } MBB.erase(I); } @@ -131,21 +161,7 @@ void SparcFrameLowering::emitEpilogue(MachineFunction &MF, return; NumBytes = SubTarget.getAdjustedFrameSize(NumBytes); - - if (NumBytes < 4096) { - BuildMI(MBB, MBBI, dl, TII.get(SP::ADDri), SP::O6) - .addReg(SP::O6).addImm(NumBytes); - } else { - // Emit this the hard way. This clobbers G1 which we always know is - // available here. - unsigned OffHi = (unsigned)NumBytes >> 10U; - BuildMI(MBB, MBBI, dl, TII.get(SP::SETHIi), SP::G1).addImm(OffHi); - // Emit G1 = G1 + I6 - BuildMI(MBB, MBBI, dl, TII.get(SP::ORri), SP::G1) - .addReg(SP::G1).addImm(NumBytes & ((1 << 10)-1)); - BuildMI(MBB, MBBI, dl, TII.get(SP::ADDrr), SP::O6) - .addReg(SP::O6).addReg(SP::G1); - } + emitSPAdjustment(MF, MBB, MBBI, NumBytes, SP::ADDrr, SP::ADDri); } bool SparcFrameLowering::hasReservedCallFrame(const MachineFunction &MF) const { diff --git a/lib/Target/Sparc/SparcFrameLowering.h b/lib/Target/Sparc/SparcFrameLowering.h index 8eaef599acc..072fde39383 100644 --- a/lib/Target/Sparc/SparcFrameLowering.h +++ b/lib/Target/Sparc/SparcFrameLowering.h @@ -49,6 +49,14 @@ private: // Returns true if MF is a leaf procedure. bool isLeafProc(MachineFunction &MF) const; + + + // Emits code for adjusting SP in function prologue/epilogue. + void emitSPAdjustment(MachineFunction &MF, + MachineBasicBlock &MBB, + MachineBasicBlock::iterator MBBI, + int NumBytes, unsigned ADDrr, unsigned ADDri) const; + }; } // End llvm namespace diff --git a/lib/Target/Sparc/SparcRegisterInfo.cpp b/lib/Target/Sparc/SparcRegisterInfo.cpp index 9442d03c129..c98613aa120 100644 --- a/lib/Target/Sparc/SparcRegisterInfo.cpp +++ b/lib/Target/Sparc/SparcRegisterInfo.cpp @@ -105,19 +105,46 @@ static void replaceFI(MachineFunction &MF, // encode it. MI.getOperand(FIOperandNum).ChangeToRegister(FramePtr, false); MI.getOperand(FIOperandNum + 1).ChangeToImmediate(Offset); - } else { - // Otherwise, emit a G1 = SETHI %hi(offset). FIXME: it would be better to - // scavenge a register here instead of reserving G1 all of the time. - const TargetInstrInfo &TII = *MF.getTarget().getInstrInfo(); - unsigned OffHi = (unsigned)Offset >> 10U; - BuildMI(*MI.getParent(), II, dl, TII.get(SP::SETHIi), SP::G1).addImm(OffHi); + return; + } + + const TargetInstrInfo &TII = *MF.getTarget().getInstrInfo(); + + // FIXME: it would be better to scavenge a register here instead of + // reserving G1 all of the time. + if (Offset >= 0) { + // Emit nonnegaive immediates with sethi + or. + // sethi %hi(Offset), %g1 + // add %g1, %fp, %g1 + // Insert G1+%lo(offset) into the user. + BuildMI(*MI.getParent(), II, dl, TII.get(SP::SETHIi), SP::G1) + .addImm(HI22(Offset)); + + // Emit G1 = G1 + I6 BuildMI(*MI.getParent(), II, dl, TII.get(SP::ADDrr), SP::G1).addReg(SP::G1) .addReg(FramePtr); // Insert: G1+%lo(offset) into the user. MI.getOperand(FIOperandNum).ChangeToRegister(SP::G1, false); - MI.getOperand(FIOperandNum + 1).ChangeToImmediate(Offset & ((1 << 10)-1)); + MI.getOperand(FIOperandNum + 1).ChangeToImmediate(LO10(Offset)); + return; } + + // Emit Negative numbers with sethi + xor + // sethi %hix(Offset), %g1 + // xor %g1, %lox(offset), %g1 + // add %g1, %fp, %g1 + // Insert: G1 + 0 into the user. + BuildMI(*MI.getParent(), II, dl, TII.get(SP::SETHIi), SP::G1) + .addImm(HIX22(Offset)); + BuildMI(*MI.getParent(), II, dl, TII.get(SP::XORri), SP::G1) + .addReg(SP::G1).addImm(LOX10(Offset)); + + BuildMI(*MI.getParent(), II, dl, TII.get(SP::ADDrr), SP::G1).addReg(SP::G1) + .addReg(FramePtr); + // Insert: G1+%lo(offset) into the user. + MI.getOperand(FIOperandNum).ChangeToRegister(SP::G1, false); + MI.getOperand(FIOperandNum + 1).ChangeToImmediate(0); } diff --git a/test/CodeGen/SPARC/64abi.ll b/test/CodeGen/SPARC/64abi.ll index 8a5c996a571..8b752a1a2c3 100644 --- a/test/CodeGen/SPARC/64abi.ll +++ b/test/CodeGen/SPARC/64abi.ll @@ -390,3 +390,24 @@ entry: %2 = add nsw i32 %0, %1 ret i32 %2 } + +; CHECK-LABEL: test_large_stack + +; CHECK: sethi 16, %g1 +; CHECK: xor %g1, -176, %g1 +; CHECK: save %sp, %g1, %sp + +; CHECK: sethi 14, %g1 +; CHECK: xor %g1, -1, %g1 +; CHECK: add %g1, %fp, %g1 +; CHECK: call use_buf + +define i32 @test_large_stack() { +entry: + %buffer1 = alloca [16384 x i8], align 8 + %buffer1.sub = getelementptr inbounds [16384 x i8]* %buffer1, i32 0, i32 0 + %0 = call i32 @use_buf(i32 16384, i8* %buffer1.sub) + ret i32 %0 +} + +declare i32 @use_buf(i32, i8*)