forked from OSchip/llvm-project
[Sparc] Emit large negative adjustments to SP/FP with sethi+xor instead of sethi+or. This generates correct code for both sparc32 and sparc64.
llvm-svn: 195576
This commit is contained in:
parent
9c338504e5
commit
1116868a0d
|
@ -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
|
||||
|
|
|
@ -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<const SparcInstrInfo*>(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<SparcMachineFunctionInfo>();
|
||||
|
||||
|
@ -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<const SparcInstrInfo*>(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 {
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -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*)
|
||||
|
|
Loading…
Reference in New Issue