blob: 75146c072ed94d1598080b0fcd1387b4d575ee77 [file] [log] [blame]
Chris Lattner5074bb52002-04-09 05:18:31 +00001//===-- PrologEpilogCodeInserter.cpp - Insert Prolog & Epilog code for fn -===//
2//
3// Insert SAVE/RESTORE instructions for the function
4//
5// Insert prolog code at the unique function entry point.
6// Insert epilog code at each function exit point.
7// InsertPrologEpilog invokes these only if the function is not compiled
8// with the leaf function optimization.
9//
10//===----------------------------------------------------------------------===//
11
12#include "SparcInternals.h"
13#include "SparcRegClassInfo.h"
14#include "llvm/CodeGen/MachineCodeForMethod.h"
Vikram S. Adve1ce40962002-07-08 23:31:24 +000015#include "llvm/CodeGen/MachineCodeForBasicBlock.h"
Chris Lattner5074bb52002-04-09 05:18:31 +000016#include "llvm/CodeGen/MachineCodeForInstruction.h"
17#include "llvm/CodeGen/MachineInstr.h"
Vikram S. Advee997a112002-07-10 21:42:13 +000018#include "llvm/CodeGen/InstrSelectionSupport.h"
Chris Lattner5074bb52002-04-09 05:18:31 +000019#include "llvm/Pass.h"
20#include "llvm/Function.h"
Chris Lattner5074bb52002-04-09 05:18:31 +000021
22namespace {
Chris Lattner7076ff22002-06-25 16:13:21 +000023 class InsertPrologEpilogCode : public FunctionPass {
24 TargetMachine &Target;
25 public:
26 InsertPrologEpilogCode(TargetMachine &T) : Target(T) {}
27
28 const char *getPassName() const { return "Sparc Prolog/Epilog Inserter"; }
29
30 bool runOnFunction(Function &F) {
31 MachineCodeForMethod &mcodeInfo = MachineCodeForMethod::get(&F);
32 if (!mcodeInfo.isCompiledAsLeafMethod()) {
33 InsertPrologCode(F);
34 InsertEpilogCode(F);
35 }
36 return false;
Chris Lattner5074bb52002-04-09 05:18:31 +000037 }
Chris Lattner7076ff22002-06-25 16:13:21 +000038
39 void InsertPrologCode(Function &F);
40 void InsertEpilogCode(Function &F);
41 };
Chris Lattner5074bb52002-04-09 05:18:31 +000042
43} // End anonymous namespace
44
45//------------------------------------------------------------------------
46// External Function: GetInstructionsForProlog
47// External Function: GetInstructionsForEpilog
48//
49// Purpose:
50// Create prolog and epilog code for procedure entry and exit
51//------------------------------------------------------------------------
52
Chris Lattner7076ff22002-06-25 16:13:21 +000053void InsertPrologEpilogCode::InsertPrologCode(Function &F)
Chris Lattner5074bb52002-04-09 05:18:31 +000054{
Anand Shukla458496c2002-06-25 20:55:50 +000055 std::vector<MachineInstr*> mvec;
Chris Lattner5074bb52002-04-09 05:18:31 +000056 MachineInstr* M;
57 const MachineFrameInfo& frameInfo = Target.getFrameInfo();
58
59 // The second operand is the stack size. If it does not fit in the
60 // immediate field, we have to use a free register to hold the size.
Vikram S. Adve78044fb2002-10-13 00:24:06 +000061 // See the comments below for the choice of this register.
Chris Lattner5074bb52002-04-09 05:18:31 +000062 //
Chris Lattner7076ff22002-06-25 16:13:21 +000063 MachineCodeForMethod& mcInfo = MachineCodeForMethod::get(&F);
Chris Lattner5074bb52002-04-09 05:18:31 +000064 unsigned int staticStackSize = mcInfo.getStaticStackSize();
65
66 if (staticStackSize < (unsigned) frameInfo.getMinStackFrameSize())
67 staticStackSize = (unsigned) frameInfo.getMinStackFrameSize();
Vikram S. Adve78044fb2002-10-13 00:24:06 +000068
Chris Lattner5074bb52002-04-09 05:18:31 +000069 if (unsigned padsz = (staticStackSize %
70 (unsigned) frameInfo.getStackFrameSizeAlignment()))
71 staticStackSize += frameInfo.getStackFrameSizeAlignment() - padsz;
72
73 if (Target.getInstrInfo().constantFitsInImmedField(SAVE, staticStackSize))
74 {
75 M = new MachineInstr(SAVE);
76 M->SetMachineOperandReg(0, Target.getRegInfo().getStackPointer());
77 M->SetMachineOperandConst(1, MachineOperand::MO_SignExtendedImmed,
78 - (int) staticStackSize);
79 M->SetMachineOperandReg(2, Target.getRegInfo().getStackPointer());
80 mvec.push_back(M);
81 }
82 else
83 {
Vikram S. Advee997a112002-07-10 21:42:13 +000084 // We have to put the stack size value into a register before SAVE.
Vikram S. Adve78044fb2002-10-13 00:24:06 +000085 // Use register %g1 since it is volatile across calls. Note that the
86 // local (%l) and in (%i) registers cannot be used before the SAVE!
Vikram S. Advee997a112002-07-10 21:42:13 +000087 // Do this by creating a code sequence equivalent to:
Vikram S. Adve78044fb2002-10-13 00:24:06 +000088 // SETSW -(stackSize), %g1
Vikram S. Advee997a112002-07-10 21:42:13 +000089 int32_t C = - (int) staticStackSize;
90 int uregNum = Target.getRegInfo().getUnifiedRegNum(
Chris Lattner5074bb52002-04-09 05:18:31 +000091 Target.getRegInfo().getRegClassIDOfType(Type::IntTy),
Vikram S. Adve78044fb2002-10-13 00:24:06 +000092 SparcIntRegClass::g1);
Vikram S. Advee997a112002-07-10 21:42:13 +000093
94 M = new MachineInstr(SETHI);
95 M->SetMachineOperandConst(0, MachineOperand::MO_SignExtendedImmed, C);
96 M->SetMachineOperandReg(1, uregNum);
97 M->setOperandHi32(0);
Chris Lattner5074bb52002-04-09 05:18:31 +000098 mvec.push_back(M);
99
Vikram S. Advee997a112002-07-10 21:42:13 +0000100 M = new MachineInstr(OR);
101 M->SetMachineOperandReg(0, uregNum);
102 M->SetMachineOperandConst(1, MachineOperand::MO_SignExtendedImmed, C);
103 M->SetMachineOperandReg(2, uregNum);
104 M->setOperandLo32(1);
105 mvec.push_back(M);
106
107 M = new MachineInstr(SRA);
108 M->SetMachineOperandReg(0, uregNum);
109 M->SetMachineOperandConst(1, MachineOperand::MO_UnextendedImmed, 0);
110 M->SetMachineOperandReg(2, uregNum);
111 mvec.push_back(M);
112
Vikram S. Adve78044fb2002-10-13 00:24:06 +0000113 // Now generate the SAVE using the value in register %g1
Chris Lattner5074bb52002-04-09 05:18:31 +0000114 M = new MachineInstr(SAVE);
115 M->SetMachineOperandReg(0, Target.getRegInfo().getStackPointer());
Vikram S. Adve6d6deba2002-08-01 14:26:11 +0000116 M->SetMachineOperandReg(1, uregNum);
Chris Lattner5074bb52002-04-09 05:18:31 +0000117 M->SetMachineOperandReg(2, Target.getRegInfo().getStackPointer());
118 mvec.push_back(M);
119 }
120
Vikram S. Adve1ce40962002-07-08 23:31:24 +0000121 MachineCodeForBasicBlock& bbMvec = MachineCodeForBasicBlock::get(&F.getEntryNode());
Chris Lattner7076ff22002-06-25 16:13:21 +0000122 bbMvec.insert(bbMvec.begin(), mvec.begin(), mvec.end());
Chris Lattner5074bb52002-04-09 05:18:31 +0000123}
124
Chris Lattner7076ff22002-06-25 16:13:21 +0000125void InsertPrologEpilogCode::InsertEpilogCode(Function &F)
Chris Lattner5074bb52002-04-09 05:18:31 +0000126{
Chris Lattner7076ff22002-06-25 16:13:21 +0000127 for (Function::iterator I = F.begin(), E = F.end(); I != E; ++I) {
128 Instruction *TermInst = (Instruction*)I->getTerminator();
Chris Lattner5074bb52002-04-09 05:18:31 +0000129 if (TermInst->getOpcode() == Instruction::Ret)
130 {
Chris Lattner5074bb52002-04-09 05:18:31 +0000131 MachineInstr *Restore = new MachineInstr(RESTORE);
132 Restore->SetMachineOperandReg(0, Target.getRegInfo().getZeroRegNum());
133 Restore->SetMachineOperandConst(1, MachineOperand::MO_SignExtendedImmed,
134 (int64_t)0);
135 Restore->SetMachineOperandReg(2, Target.getRegInfo().getZeroRegNum());
136
Vikram S. Adve1ce40962002-07-08 23:31:24 +0000137 MachineCodeForBasicBlock& bbMvec = MachineCodeForBasicBlock::get(I);
Chris Lattner5074bb52002-04-09 05:18:31 +0000138 MachineCodeForInstruction &termMvec =
139 MachineCodeForInstruction::get(TermInst);
140
141 // Remove the NOPs in the delay slots of the return instruction
142 const MachineInstrInfo &mii = Target.getInstrInfo();
143 unsigned numNOPs = 0;
144 while (termMvec.back()->getOpCode() == NOP)
145 {
146 assert( termMvec.back() == bbMvec.back());
Chris Lattner6b17c832002-04-09 18:02:02 +0000147 delete bbMvec.pop_back();
Chris Lattner5074bb52002-04-09 05:18:31 +0000148 termMvec.pop_back();
Chris Lattner5074bb52002-04-09 05:18:31 +0000149 ++numNOPs;
150 }
151 assert(termMvec.back() == bbMvec.back());
152
153 // Check that we found the right number of NOPs and have the right
154 // number of instructions to replace them.
155 unsigned ndelays = mii.getNumDelaySlots(termMvec.back()->getOpCode());
156 assert(numNOPs == ndelays && "Missing NOPs in delay slots?");
157 assert(ndelays == 1 && "Cannot use epilog code for delay slots?");
158
159 // Append the epilog code to the end of the basic block.
160 bbMvec.push_back(Restore);
161 }
162 }
163}
164
Vikram S. Adve36d3e032002-09-16 15:39:26 +0000165Pass* UltraSparc::getPrologEpilogInsertionPass() {
166 return new InsertPrologEpilogCode(*this);
Chris Lattner5074bb52002-04-09 05:18:31 +0000167}