llvm.org GIT mirror llvm / 5300869
[Sparc] Add support for leaf functions in sparc backend. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@182822 91177308-0d34-0410-b5e6-96231b3b80d8 Venkatraman Govindaraju 6 years ago
7 changed file(s) with 180 addition(s) and 28 deletion(s). Raw diff Collapse all Expand all
134134 bool sawLoad = false;
135135 bool sawStore = false;
136136
137 MachineBasicBlock::iterator I = slot;
137 if (slot == MBB.begin())
138 return MBB.end();
138139
139140 if (slot->getOpcode() == SP::RET)
140141 return MBB.end();
141142
142143 if (slot->getOpcode() == SP::RETL) {
143 --I;
144 if (I->getOpcode() != SP::RESTORErr)
145 return MBB.end();
146 //change retl to ret
147 slot->setDesc(TII->get(SP::RET));
148 return I;
144 MachineBasicBlock::iterator J = slot;
145 --J;
146
147 if (J->getOpcode() == SP::RESTORErr
148 || J->getOpcode() == SP::RESTOREri) {
149 //change retl to ret
150 slot->setDesc(TII->get(SP::RET));
151 return J;
152 }
149153 }
150154
151155 //Call's delay filler can def some of call's uses.
155159 insertDefsUses(slot, RegDefs, RegUses);
156160
157161 bool done = false;
162
163 MachineBasicBlock::iterator I = slot;
158164
159165 while (!done) {
160166 done = (I == MBB.begin());
273279 continue;
274280 if (MO.isDef())
275281 RegDefs.insert(Reg);
276 if (MO.isUse())
282 if (MO.isUse()) {
283 //Implicit register uses of retl are return values and
284 //retl does not use them.
285 if (MO.isImplicit() && MI->getOpcode() == SP::RETL)
286 continue;
277287 RegUses.insert(Reg);
278
288 }
279289 }
280290 }
281291
2525
2626 using namespace llvm;
2727
28 static cl::opt
29 DisableLeafProc("disable-sparc-leaf-proc",
30 cl::init(true),
31 cl::desc("Disable Sparc leaf procedure optimization."),
32 cl::Hidden);
33
34
2835 void SparcFrameLowering::emitPrologue(MachineFunction &MF) const {
36 SparcMachineFunctionInfo *FuncInfo = MF.getInfo();
37 if (FuncInfo->isLeafProc())
38 return;
39
2940 MachineBasicBlock &MBB = MF.front();
3041 MachineFrameInfo *MFI = MF.getFrameInfo();
3142 const SparcInstrInfo &TII =
96107
97108 void SparcFrameLowering::emitEpilogue(MachineFunction &MF,
98109 MachineBasicBlock &MBB) const {
110 SparcMachineFunctionInfo *FuncInfo = MF.getInfo();
111 if (FuncInfo->isLeafProc())
112 return;
99113 MachineBasicBlock::iterator MBBI = MBB.getLastNonDebugInstr();
100114 const SparcInstrInfo &TII =
101115 *static_cast(MF.getTarget().getInstrInfo());
120134 MFI->hasVarSizedObjects() || MFI->isFrameAddressTaken();
121135 }
122136
137
138 static bool verifyLeafProcRegUse(MachineRegisterInfo *MRI)
139 {
140
141 for (unsigned reg = SP::I0; reg <= SP::I7; ++reg)
142 if (MRI->isPhysRegUsed(reg))
143 return false;
144
145 for (unsigned reg = SP::L0; reg <= SP::L7; ++reg)
146 if (MRI->isPhysRegUsed(reg))
147 return false;
148
149 return true;
150 }
151
152 bool SparcFrameLowering::isLeafProc(MachineFunction &MF) const
153 {
154
155 MachineRegisterInfo &MRI = MF.getRegInfo();
156 MachineFrameInfo *MFI = MF.getFrameInfo();
157
158 return !(MFI->hasCalls() // has calls
159 || MRI.isPhysRegUsed(SP::L0) // Too many registers needed
160 || MRI.isPhysRegUsed(SP::O6) // %SP is used
161 || hasFP(MF)); // need %FP
162 }
163
164 void SparcFrameLowering::remapRegsForLeafProc(MachineFunction &MF) const {
165
166 MachineRegisterInfo &MRI = MF.getRegInfo();
167
168 //remap %i[0-7] to %o[0-7]
169 for (unsigned reg = SP::I0; reg <= SP::I7; ++reg) {
170 if (!MRI.isPhysRegUsed(reg))
171 continue;
172 unsigned mapped_reg = (reg - SP::I0 + SP::O0);
173 assert(!MRI.isPhysRegUsed(mapped_reg));
174
175 //Replace I register with O register
176 MRI.replaceRegWith(reg, mapped_reg);
177
178 //mark the reg unused.
179 MRI.setPhysRegUnused(reg);
180 }
181
182 assert(verifyLeafProcRegUse(&MRI));
183 #ifdef XDEBUG
184 MF.verify(0, "After LeafProc Remapping");
185 #endif
186 }
187
188 void SparcFrameLowering::processFunctionBeforeCalleeSavedScan
189 (MachineFunction &MF, RegScavenger *RS) const {
190
191 if (!DisableLeafProc && isLeafProc(MF)) {
192 SparcMachineFunctionInfo *MFI = MF.getInfo();
193 MFI->setLeafProc(true);
194
195 remapRegsForLeafProc(MF);
196 }
197
198 }
3939
4040 bool hasReservedCallFrame(const MachineFunction &MF) const;
4141 bool hasFP(const MachineFunction &MF) const;
42 void processFunctionBeforeCalleeSavedScan(MachineFunction &MF,
43 RegScavenger *RS = NULL) const;
44
45 private:
46 //Remap input registers to output registers for leaf procedure.
47 void remapRegsForLeafProc(MachineFunction &MF) const;
48
49 //Returns true if MF is a leaf procedure.
50 bool isLeafProc(MachineFunction &MF) const;
4251 };
4352
4453 } // End llvm namespace
2727 /// SRetReturnReg - Holds the virtual register into which the sret
2828 /// argument is passed.
2929 unsigned SRetReturnReg;
30
31 /// IsLeafProc - True if the function is a leaf procedure.
32 bool IsLeafProc;
3033 public:
3134 SparcMachineFunctionInfo()
32 : GlobalBaseReg(0), VarArgsFrameOffset(0), SRetReturnReg(0) {}
35 : GlobalBaseReg(0), VarArgsFrameOffset(0), SRetReturnReg(0),
36 IsLeafProc(false) {}
3337 explicit SparcMachineFunctionInfo(MachineFunction &MF)
34 : GlobalBaseReg(0), VarArgsFrameOffset(0), SRetReturnReg(0) {}
38 : GlobalBaseReg(0), VarArgsFrameOffset(0), SRetReturnReg(0),
39 IsLeafProc(false) {}
3540
3641 unsigned getGlobalBaseReg() const { return GlobalBaseReg; }
3742 void setGlobalBaseReg(unsigned Reg) { GlobalBaseReg = Reg; }
4146
4247 unsigned getSRetReturnReg() const { return SRetReturnReg; }
4348 void setSRetReturnReg(unsigned Reg) { SRetReturnReg = Reg; }
49
50 void setLeafProc(bool rhs) { IsLeafProc = rhs; }
51 bool isLeafProc() const { return IsLeafProc; }
4452 };
4553 }
4654
1212
1313 #include "SparcRegisterInfo.h"
1414 #include "Sparc.h"
15 #include "SparcMachineFunctionInfo.h"
1516 #include "SparcSubtarget.h"
1617 #include "llvm/ADT/BitVector.h"
1718 #include "llvm/ADT/STLExtras.h"
8889 int64_t Offset = MF.getFrameInfo()->getObjectOffset(FrameIndex) +
8990 MI.getOperand(FIOperandNum + 1).getImm() +
9091 Subtarget.getStackPointerBias();
91
92 SparcMachineFunctionInfo *FuncInfo = MF.getInfo();
93 unsigned FramePtr = (FuncInfo->isLeafProc()) ? SP::O6 : SP::I6;
9294 // Replace frame index with a frame pointer reference.
9395 if (Offset >= -4096 && Offset <= 4095) {
9496 // If the offset is small enough to fit in the immediate field, directly
9597 // encode it.
96 MI.getOperand(FIOperandNum).ChangeToRegister(SP::I6, false);
98 MI.getOperand(FIOperandNum).ChangeToRegister(FramePtr, false);
9799 MI.getOperand(FIOperandNum + 1).ChangeToImmediate(Offset);
98100 } else {
99101 // Otherwise, emit a G1 = SETHI %hi(offset). FIXME: it would be better to
102104 BuildMI(*MI.getParent(), II, dl, TII.get(SP::SETHIi), SP::G1).addImm(OffHi);
103105 // Emit G1 = G1 + I6
104106 BuildMI(*MI.getParent(), II, dl, TII.get(SP::ADDrr), SP::G1).addReg(SP::G1)
105 .addReg(SP::I6);
107 .addReg(FramePtr);
106108 // Insert: G1+%lo(offset) into the user.
107109 MI.getOperand(FIOperandNum).ChangeToRegister(SP::G1, false);
108110 MI.getOperand(FIOperandNum + 1).ChangeToImmediate(Offset & ((1 << 10)-1));
143143 // register class for that. The i64 type is included here to allow i64 patterns
144144 // using the integer instructions.
145145 def IntRegs : RegisterClass<"SP", [i32, i64], 32,
146 (add I0, I1, I2, I3, I4, I5,
147 G1,
148 G2, G3, G4, // OK for use only in
149 // applications, not libraries.
150 G5, // OK for use in 64 bit mode.
151 L0, L1, L2, L3, L4, L5, L6, L7,
152 O0, O1, O2, O3, O4, O5, O7,
153 // Non-allocatable regs:
154 O6, // stack ptr
155 I6, // frame ptr
156 I7, // return address
157 G0, // constant zero
158 G6, G7 // reserved for kernel
159 )>;
146 (add (sequence "I%u", 0, 7),
147 (sequence "G%u", 0, 7),
148 (sequence "L%u", 0, 7),
149 (sequence "O%u", 0, 7))>;
160150
161151 // Register class for 64-bit mode, with a 64-bit spill slot size.
162152 // These are the same as the 32-bit registers, so TableGen will consider this
0 ; RUN: llc -march=sparc -disable-sparc-leaf-proc=0 < %s | FileCheck %s
1
2 ; CHECK: func_nobody:
3 ; CHECK: jmp %o7+8
4 ; CHECK-NEXT: nop
5 define void @func_nobody() {
6 entry:
7 ret void
8 }
9
10
11 ; CHECK: return_int_const:
12 ; CHECK: jmp %o7+8
13 ; CHECK-NEXT: or %g0, 1729, %o0
14 define i32 @return_int_const() {
15 entry:
16 ret i32 1729
17 }
18
19 ; CHECK: return_double_const:
20 ; CHECK: sethi
21 ; CHECK: jmp %o7+8
22 ; CHECK-NEXT: ldd {{.*}}, %f0
23
24 define double @return_double_const() {
25 entry:
26 ret double 0.000000e+00
27 }
28
29 ; CHECK: leaf_proc_with_args:
30 ; CHECK: add {{%o[0-1]}}, {{%o[0-1]}}, [[R:%[go][0-7]]]
31 ; CHECK: jmp %o7+8
32 ; CHECK-NEXT: add [[R]], %o2, %o0
33
34 define i32 @leaf_proc_with_args(i32 %a, i32 %b, i32 %c) {
35 entry:
36 %0 = add nsw i32 %b, %a
37 %1 = add nsw i32 %0, %c
38 ret i32 %1
39 }
40
41 ; CHECK: leaf_proc_with_args_in_stack:
42 ; CHECK-DAG: ld [%sp+92], {{%[go][0-7]}}
43 ; CHECK-DAG: ld [%sp+96], {{%[go][0-7]}}
44 ; CHECK: jmp %o7+8
45 ; CHECK-NEXT: add {{.*}}, %o0
46 define i32 @leaf_proc_with_args_in_stack(i32 %a, i32 %b, i32 %c, i32 %d, i32 %e, i32 %f, i32 %g, i32 %h) {
47 entry:
48 %0 = add nsw i32 %b, %a
49 %1 = add nsw i32 %0, %c
50 %2 = add nsw i32 %1, %d
51 %3 = add nsw i32 %2, %e
52 %4 = add nsw i32 %3, %f
53 %5 = add nsw i32 %4, %g
54 %6 = add nsw i32 %5, %h
55 ret i32 %6
56 }