Skip to content

Commit 1116868

Browse files
committed
[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
1 parent 9c33850 commit 1116868

File tree

5 files changed

+129
-40
lines changed

5 files changed

+129
-40
lines changed

llvm/lib/Target/Sparc/Sparc.h

+17
Original file line numberDiff line numberDiff line change
@@ -105,5 +105,22 @@ namespace llvm {
105105
}
106106
llvm_unreachable("Invalid cond code");
107107
}
108+
109+
inline static unsigned HI22(int64_t imm) {
110+
return (unsigned)((imm >> 10) & ((1 << 22)-1));
111+
}
112+
113+
inline static unsigned LO10(int64_t imm) {
114+
return (unsigned)(imm & 0x3FF);
115+
}
116+
117+
inline static unsigned HIX22(int64_t imm) {
118+
return HI22(~imm);
119+
}
120+
121+
inline static unsigned LOX10(int64_t imm) {
122+
return ~LO10(~imm);
123+
}
124+
108125
} // end namespace llvm
109126
#endif

llvm/lib/Target/Sparc/SparcFrameLowering.cpp

+49-33
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,51 @@ DisableLeafProc("disable-sparc-leaf-proc",
3333
cl::Hidden);
3434

3535

36+
void SparcFrameLowering::emitSPAdjustment(MachineFunction &MF,
37+
MachineBasicBlock &MBB,
38+
MachineBasicBlock::iterator MBBI,
39+
int NumBytes,
40+
unsigned ADDrr,
41+
unsigned ADDri) const {
42+
43+
DebugLoc dl = (MBBI != MBB.end()) ? MBBI->getDebugLoc() : DebugLoc();
44+
const SparcInstrInfo &TII =
45+
*static_cast<const SparcInstrInfo*>(MF.getTarget().getInstrInfo());
46+
47+
if (NumBytes >= -4096 && NumBytes < 4096) {
48+
BuildMI(MBB, MBBI, dl, TII.get(ADDri), SP::O6)
49+
.addReg(SP::O6).addImm(NumBytes);
50+
return;
51+
}
52+
53+
// Emit this the hard way. This clobbers G1 which we always know is
54+
// available here.
55+
if (NumBytes >= 0) {
56+
// Emit nonnegative numbers with sethi + or.
57+
// sethi %hi(NumBytes), %g1
58+
// or %g1, %lo(NumBytes), %g1
59+
// add %sp, %g1, %sp
60+
BuildMI(MBB, MBBI, dl, TII.get(SP::SETHIi), SP::G1)
61+
.addImm(HI22(NumBytes));
62+
BuildMI(MBB, MBBI, dl, TII.get(SP::ORri), SP::G1)
63+
.addReg(SP::G1).addImm(LO10(NumBytes));
64+
BuildMI(MBB, MBBI, dl, TII.get(ADDrr), SP::O6)
65+
.addReg(SP::O6).addReg(SP::G1);
66+
return ;
67+
}
68+
69+
// Emit negative numbers with sethi + xor.
70+
// sethi %hix(NumBytes), %g1
71+
// xor %g1, %lox(NumBytes), %g1
72+
// add %sp, %g1, %sp
73+
BuildMI(MBB, MBBI, dl, TII.get(SP::SETHIi), SP::G1)
74+
.addImm(HIX22(NumBytes));
75+
BuildMI(MBB, MBBI, dl, TII.get(SP::XORri), SP::G1)
76+
.addReg(SP::G1).addImm(LOX10(NumBytes));
77+
BuildMI(MBB, MBBI, dl, TII.get(ADDrr), SP::O6)
78+
.addReg(SP::O6).addReg(SP::G1);
79+
}
80+
3681
void SparcFrameLowering::emitPrologue(MachineFunction &MF) const {
3782
SparcMachineFunctionInfo *FuncInfo = MF.getInfo<SparcMachineFunctionInfo>();
3883

@@ -55,21 +100,8 @@ void SparcFrameLowering::emitPrologue(MachineFunction &MF) const {
55100
SAVErr = SP::ADDrr;
56101
}
57102
NumBytes = - SubTarget.getAdjustedFrameSize(NumBytes);
103+
emitSPAdjustment(MF, MBB, MBBI, NumBytes, SAVErr, SAVEri);
58104

59-
if (NumBytes >= -4096) {
60-
BuildMI(MBB, MBBI, dl, TII.get(SAVEri), SP::O6)
61-
.addReg(SP::O6).addImm(NumBytes);
62-
} else {
63-
// Emit this the hard way. This clobbers G1 which we always know is
64-
// available here.
65-
unsigned OffHi = (unsigned)NumBytes >> 10U;
66-
BuildMI(MBB, MBBI, dl, TII.get(SP::SETHIi), SP::G1).addImm(OffHi);
67-
// Emit G1 = G1 + I6
68-
BuildMI(MBB, MBBI, dl, TII.get(SP::ORri), SP::G1)
69-
.addReg(SP::G1).addImm(NumBytes & ((1 << 10)-1));
70-
BuildMI(MBB, MBBI, dl, TII.get(SAVErr), SP::O6)
71-
.addReg(SP::O6).addReg(SP::G1);
72-
}
73105
MachineModuleInfo &MMI = MF.getMMI();
74106
const MCRegisterInfo *MRI = MMI.getContext().getRegisterInfo();
75107
MCSymbol *FrameLabel = MMI.getContext().CreateTempSymbol();
@@ -100,11 +132,9 @@ eliminateCallFramePseudoInstr(MachineFunction &MF, MachineBasicBlock &MBB,
100132
int Size = MI.getOperand(0).getImm();
101133
if (MI.getOpcode() == SP::ADJCALLSTACKDOWN)
102134
Size = -Size;
103-
const SparcInstrInfo &TII =
104-
*static_cast<const SparcInstrInfo*>(MF.getTarget().getInstrInfo());
135+
105136
if (Size)
106-
BuildMI(MBB, I, DL, TII.get(SP::ADDri), SP::O6).addReg(SP::O6)
107-
.addImm(Size);
137+
emitSPAdjustment(MF, MBB, I, Size, SP::ADDrr, SP::ADDri);
108138
}
109139
MBB.erase(I);
110140
}
@@ -131,21 +161,7 @@ void SparcFrameLowering::emitEpilogue(MachineFunction &MF,
131161
return;
132162

133163
NumBytes = SubTarget.getAdjustedFrameSize(NumBytes);
134-
135-
if (NumBytes < 4096) {
136-
BuildMI(MBB, MBBI, dl, TII.get(SP::ADDri), SP::O6)
137-
.addReg(SP::O6).addImm(NumBytes);
138-
} else {
139-
// Emit this the hard way. This clobbers G1 which we always know is
140-
// available here.
141-
unsigned OffHi = (unsigned)NumBytes >> 10U;
142-
BuildMI(MBB, MBBI, dl, TII.get(SP::SETHIi), SP::G1).addImm(OffHi);
143-
// Emit G1 = G1 + I6
144-
BuildMI(MBB, MBBI, dl, TII.get(SP::ORri), SP::G1)
145-
.addReg(SP::G1).addImm(NumBytes & ((1 << 10)-1));
146-
BuildMI(MBB, MBBI, dl, TII.get(SP::ADDrr), SP::O6)
147-
.addReg(SP::O6).addReg(SP::G1);
148-
}
164+
emitSPAdjustment(MF, MBB, MBBI, NumBytes, SP::ADDrr, SP::ADDri);
149165
}
150166

151167
bool SparcFrameLowering::hasReservedCallFrame(const MachineFunction &MF) const {

llvm/lib/Target/Sparc/SparcFrameLowering.h

+8
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,14 @@ class SparcFrameLowering : public TargetFrameLowering {
4949

5050
// Returns true if MF is a leaf procedure.
5151
bool isLeafProc(MachineFunction &MF) const;
52+
53+
54+
// Emits code for adjusting SP in function prologue/epilogue.
55+
void emitSPAdjustment(MachineFunction &MF,
56+
MachineBasicBlock &MBB,
57+
MachineBasicBlock::iterator MBBI,
58+
int NumBytes, unsigned ADDrr, unsigned ADDri) const;
59+
5260
};
5361

5462
} // End llvm namespace

llvm/lib/Target/Sparc/SparcRegisterInfo.cpp

+34-7
Original file line numberDiff line numberDiff line change
@@ -105,19 +105,46 @@ static void replaceFI(MachineFunction &MF,
105105
// encode it.
106106
MI.getOperand(FIOperandNum).ChangeToRegister(FramePtr, false);
107107
MI.getOperand(FIOperandNum + 1).ChangeToImmediate(Offset);
108-
} else {
109-
// Otherwise, emit a G1 = SETHI %hi(offset). FIXME: it would be better to
110-
// scavenge a register here instead of reserving G1 all of the time.
111-
const TargetInstrInfo &TII = *MF.getTarget().getInstrInfo();
112-
unsigned OffHi = (unsigned)Offset >> 10U;
113-
BuildMI(*MI.getParent(), II, dl, TII.get(SP::SETHIi), SP::G1).addImm(OffHi);
108+
return;
109+
}
110+
111+
const TargetInstrInfo &TII = *MF.getTarget().getInstrInfo();
112+
113+
// FIXME: it would be better to scavenge a register here instead of
114+
// reserving G1 all of the time.
115+
if (Offset >= 0) {
116+
// Emit nonnegaive immediates with sethi + or.
117+
// sethi %hi(Offset), %g1
118+
// add %g1, %fp, %g1
119+
// Insert G1+%lo(offset) into the user.
120+
BuildMI(*MI.getParent(), II, dl, TII.get(SP::SETHIi), SP::G1)
121+
.addImm(HI22(Offset));
122+
123+
114124
// Emit G1 = G1 + I6
115125
BuildMI(*MI.getParent(), II, dl, TII.get(SP::ADDrr), SP::G1).addReg(SP::G1)
116126
.addReg(FramePtr);
117127
// Insert: G1+%lo(offset) into the user.
118128
MI.getOperand(FIOperandNum).ChangeToRegister(SP::G1, false);
119-
MI.getOperand(FIOperandNum + 1).ChangeToImmediate(Offset & ((1 << 10)-1));
129+
MI.getOperand(FIOperandNum + 1).ChangeToImmediate(LO10(Offset));
130+
return;
120131
}
132+
133+
// Emit Negative numbers with sethi + xor
134+
// sethi %hix(Offset), %g1
135+
// xor %g1, %lox(offset), %g1
136+
// add %g1, %fp, %g1
137+
// Insert: G1 + 0 into the user.
138+
BuildMI(*MI.getParent(), II, dl, TII.get(SP::SETHIi), SP::G1)
139+
.addImm(HIX22(Offset));
140+
BuildMI(*MI.getParent(), II, dl, TII.get(SP::XORri), SP::G1)
141+
.addReg(SP::G1).addImm(LOX10(Offset));
142+
143+
BuildMI(*MI.getParent(), II, dl, TII.get(SP::ADDrr), SP::G1).addReg(SP::G1)
144+
.addReg(FramePtr);
145+
// Insert: G1+%lo(offset) into the user.
146+
MI.getOperand(FIOperandNum).ChangeToRegister(SP::G1, false);
147+
MI.getOperand(FIOperandNum + 1).ChangeToImmediate(0);
121148
}
122149

123150

llvm/test/CodeGen/SPARC/64abi.ll

+21
Original file line numberDiff line numberDiff line change
@@ -390,3 +390,24 @@ entry:
390390
%2 = add nsw i32 %0, %1
391391
ret i32 %2
392392
}
393+
394+
; CHECK-LABEL: test_large_stack
395+
396+
; CHECK: sethi 16, %g1
397+
; CHECK: xor %g1, -176, %g1
398+
; CHECK: save %sp, %g1, %sp
399+
400+
; CHECK: sethi 14, %g1
401+
; CHECK: xor %g1, -1, %g1
402+
; CHECK: add %g1, %fp, %g1
403+
; CHECK: call use_buf
404+
405+
define i32 @test_large_stack() {
406+
entry:
407+
%buffer1 = alloca [16384 x i8], align 8
408+
%buffer1.sub = getelementptr inbounds [16384 x i8]* %buffer1, i32 0, i32 0
409+
%0 = call i32 @use_buf(i32 16384, i8* %buffer1.sub)
410+
ret i32 %0
411+
}
412+
413+
declare i32 @use_buf(i32, i8*)

0 commit comments

Comments
 (0)