]>
Commit | Line | Data |
---|---|---|
223e47cc LB |
1 | //===-- SparcInstrInfo.cpp - Sparc Instruction Information ----------------===// |
2 | // | |
3 | // The LLVM Compiler Infrastructure | |
4 | // | |
5 | // This file is distributed under the University of Illinois Open Source | |
6 | // License. See LICENSE.TXT for details. | |
7 | // | |
8 | //===----------------------------------------------------------------------===// | |
9 | // | |
10 | // This file contains the Sparc implementation of the TargetInstrInfo class. | |
11 | // | |
12 | //===----------------------------------------------------------------------===// | |
13 | ||
14 | #include "SparcInstrInfo.h" | |
15 | #include "Sparc.h" | |
16 | #include "SparcMachineFunctionInfo.h" | |
17 | #include "SparcSubtarget.h" | |
18 | #include "llvm/CodeGen/MachineInstrBuilder.h" | |
19 | #include "llvm/CodeGen/MachineRegisterInfo.h" | |
20 | #include "llvm/Support/ErrorHandling.h" | |
21 | #include "llvm/Support/TargetRegistry.h" | |
22 | #include "llvm/ADT/STLExtras.h" | |
23 | #include "llvm/ADT/SmallVector.h" | |
24 | ||
25 | #define GET_INSTRINFO_CTOR | |
26 | #include "SparcGenInstrInfo.inc" | |
27 | ||
28 | using namespace llvm; | |
29 | ||
30 | SparcInstrInfo::SparcInstrInfo(SparcSubtarget &ST) | |
31 | : SparcGenInstrInfo(SP::ADJCALLSTACKDOWN, SP::ADJCALLSTACKUP), | |
32 | RI(ST, *this), Subtarget(ST) { | |
33 | } | |
34 | ||
35 | /// isLoadFromStackSlot - If the specified machine instruction is a direct | |
36 | /// load from a stack slot, return the virtual or physical register number of | |
37 | /// the destination along with the FrameIndex of the loaded stack slot. If | |
38 | /// not, return 0. This predicate must return 0 if the instruction has | |
39 | /// any side effects other than loading from the stack slot. | |
40 | unsigned SparcInstrInfo::isLoadFromStackSlot(const MachineInstr *MI, | |
41 | int &FrameIndex) const { | |
42 | if (MI->getOpcode() == SP::LDri || | |
43 | MI->getOpcode() == SP::LDFri || | |
44 | MI->getOpcode() == SP::LDDFri) { | |
45 | if (MI->getOperand(1).isFI() && MI->getOperand(2).isImm() && | |
46 | MI->getOperand(2).getImm() == 0) { | |
47 | FrameIndex = MI->getOperand(1).getIndex(); | |
48 | return MI->getOperand(0).getReg(); | |
49 | } | |
50 | } | |
51 | return 0; | |
52 | } | |
53 | ||
54 | /// isStoreToStackSlot - If the specified machine instruction is a direct | |
55 | /// store to a stack slot, return the virtual or physical register number of | |
56 | /// the source reg along with the FrameIndex of the loaded stack slot. If | |
57 | /// not, return 0. This predicate must return 0 if the instruction has | |
58 | /// any side effects other than storing to the stack slot. | |
59 | unsigned SparcInstrInfo::isStoreToStackSlot(const MachineInstr *MI, | |
60 | int &FrameIndex) const { | |
61 | if (MI->getOpcode() == SP::STri || | |
62 | MI->getOpcode() == SP::STFri || | |
63 | MI->getOpcode() == SP::STDFri) { | |
64 | if (MI->getOperand(0).isFI() && MI->getOperand(1).isImm() && | |
65 | MI->getOperand(1).getImm() == 0) { | |
66 | FrameIndex = MI->getOperand(0).getIndex(); | |
67 | return MI->getOperand(2).getReg(); | |
68 | } | |
69 | } | |
70 | return 0; | |
71 | } | |
72 | ||
73 | static bool IsIntegerCC(unsigned CC) | |
74 | { | |
75 | return (CC <= SPCC::ICC_VC); | |
76 | } | |
77 | ||
78 | ||
79 | static SPCC::CondCodes GetOppositeBranchCondition(SPCC::CondCodes CC) | |
80 | { | |
81 | switch(CC) { | |
82 | case SPCC::ICC_NE: return SPCC::ICC_E; | |
83 | case SPCC::ICC_E: return SPCC::ICC_NE; | |
84 | case SPCC::ICC_G: return SPCC::ICC_LE; | |
85 | case SPCC::ICC_LE: return SPCC::ICC_G; | |
86 | case SPCC::ICC_GE: return SPCC::ICC_L; | |
87 | case SPCC::ICC_L: return SPCC::ICC_GE; | |
88 | case SPCC::ICC_GU: return SPCC::ICC_LEU; | |
89 | case SPCC::ICC_LEU: return SPCC::ICC_GU; | |
90 | case SPCC::ICC_CC: return SPCC::ICC_CS; | |
91 | case SPCC::ICC_CS: return SPCC::ICC_CC; | |
92 | case SPCC::ICC_POS: return SPCC::ICC_NEG; | |
93 | case SPCC::ICC_NEG: return SPCC::ICC_POS; | |
94 | case SPCC::ICC_VC: return SPCC::ICC_VS; | |
95 | case SPCC::ICC_VS: return SPCC::ICC_VC; | |
96 | ||
97 | case SPCC::FCC_U: return SPCC::FCC_O; | |
98 | case SPCC::FCC_O: return SPCC::FCC_U; | |
99 | case SPCC::FCC_G: return SPCC::FCC_LE; | |
100 | case SPCC::FCC_LE: return SPCC::FCC_G; | |
101 | case SPCC::FCC_UG: return SPCC::FCC_ULE; | |
102 | case SPCC::FCC_ULE: return SPCC::FCC_UG; | |
103 | case SPCC::FCC_L: return SPCC::FCC_GE; | |
104 | case SPCC::FCC_GE: return SPCC::FCC_L; | |
105 | case SPCC::FCC_UL: return SPCC::FCC_UGE; | |
106 | case SPCC::FCC_UGE: return SPCC::FCC_UL; | |
107 | case SPCC::FCC_LG: return SPCC::FCC_UE; | |
108 | case SPCC::FCC_UE: return SPCC::FCC_LG; | |
109 | case SPCC::FCC_NE: return SPCC::FCC_E; | |
110 | case SPCC::FCC_E: return SPCC::FCC_NE; | |
111 | } | |
112 | llvm_unreachable("Invalid cond code"); | |
113 | } | |
114 | ||
115 | MachineInstr * | |
116 | SparcInstrInfo::emitFrameIndexDebugValue(MachineFunction &MF, | |
117 | int FrameIx, | |
118 | uint64_t Offset, | |
119 | const MDNode *MDPtr, | |
120 | DebugLoc dl) const { | |
121 | MachineInstrBuilder MIB = BuildMI(MF, dl, get(SP::DBG_VALUE)) | |
122 | .addFrameIndex(FrameIx).addImm(0).addImm(Offset).addMetadata(MDPtr); | |
123 | return &*MIB; | |
124 | } | |
125 | ||
126 | ||
127 | bool SparcInstrInfo::AnalyzeBranch(MachineBasicBlock &MBB, | |
128 | MachineBasicBlock *&TBB, | |
129 | MachineBasicBlock *&FBB, | |
130 | SmallVectorImpl<MachineOperand> &Cond, | |
131 | bool AllowModify) const | |
132 | { | |
133 | ||
134 | MachineBasicBlock::iterator I = MBB.end(); | |
135 | MachineBasicBlock::iterator UnCondBrIter = MBB.end(); | |
136 | while (I != MBB.begin()) { | |
137 | --I; | |
138 | ||
139 | if (I->isDebugValue()) | |
140 | continue; | |
141 | ||
142 | //When we see a non-terminator, we are done | |
143 | if (!isUnpredicatedTerminator(I)) | |
144 | break; | |
145 | ||
146 | //Terminator is not a branch | |
147 | if (!I->isBranch()) | |
148 | return true; | |
149 | ||
150 | //Handle Unconditional branches | |
151 | if (I->getOpcode() == SP::BA) { | |
152 | UnCondBrIter = I; | |
153 | ||
154 | if (!AllowModify) { | |
155 | TBB = I->getOperand(0).getMBB(); | |
156 | continue; | |
157 | } | |
158 | ||
159 | while (llvm::next(I) != MBB.end()) | |
160 | llvm::next(I)->eraseFromParent(); | |
161 | ||
162 | Cond.clear(); | |
163 | FBB = 0; | |
164 | ||
165 | if (MBB.isLayoutSuccessor(I->getOperand(0).getMBB())) { | |
166 | TBB = 0; | |
167 | I->eraseFromParent(); | |
168 | I = MBB.end(); | |
169 | UnCondBrIter = MBB.end(); | |
170 | continue; | |
171 | } | |
172 | ||
173 | TBB = I->getOperand(0).getMBB(); | |
174 | continue; | |
175 | } | |
176 | ||
177 | unsigned Opcode = I->getOpcode(); | |
178 | if (Opcode != SP::BCOND && Opcode != SP::FBCOND) | |
179 | return true; //Unknown Opcode | |
180 | ||
181 | SPCC::CondCodes BranchCode = (SPCC::CondCodes)I->getOperand(1).getImm(); | |
182 | ||
183 | if (Cond.empty()) { | |
184 | MachineBasicBlock *TargetBB = I->getOperand(0).getMBB(); | |
185 | if (AllowModify && UnCondBrIter != MBB.end() && | |
186 | MBB.isLayoutSuccessor(TargetBB)) { | |
187 | ||
188 | //Transform the code | |
189 | // | |
190 | // brCC L1 | |
191 | // ba L2 | |
192 | // L1: | |
193 | // .. | |
194 | // L2: | |
195 | // | |
196 | // into | |
197 | // | |
198 | // brnCC L2 | |
199 | // L1: | |
200 | // ... | |
201 | // L2: | |
202 | // | |
203 | BranchCode = GetOppositeBranchCondition(BranchCode); | |
204 | MachineBasicBlock::iterator OldInst = I; | |
205 | BuildMI(MBB, UnCondBrIter, MBB.findDebugLoc(I), get(Opcode)) | |
206 | .addMBB(UnCondBrIter->getOperand(0).getMBB()).addImm(BranchCode); | |
207 | BuildMI(MBB, UnCondBrIter, MBB.findDebugLoc(I), get(SP::BA)) | |
208 | .addMBB(TargetBB); | |
209 | ||
210 | OldInst->eraseFromParent(); | |
211 | UnCondBrIter->eraseFromParent(); | |
212 | ||
213 | UnCondBrIter = MBB.end(); | |
214 | I = MBB.end(); | |
215 | continue; | |
216 | } | |
217 | FBB = TBB; | |
218 | TBB = I->getOperand(0).getMBB(); | |
219 | Cond.push_back(MachineOperand::CreateImm(BranchCode)); | |
220 | continue; | |
221 | } | |
222 | //FIXME: Handle subsequent conditional branches | |
223 | //For now, we can't handle multiple conditional branches | |
224 | return true; | |
225 | } | |
226 | return false; | |
227 | } | |
228 | ||
229 | unsigned | |
230 | SparcInstrInfo::InsertBranch(MachineBasicBlock &MBB,MachineBasicBlock *TBB, | |
231 | MachineBasicBlock *FBB, | |
232 | const SmallVectorImpl<MachineOperand> &Cond, | |
233 | DebugLoc DL) const { | |
234 | assert(TBB && "InsertBranch must not be told to insert a fallthrough"); | |
235 | assert((Cond.size() == 1 || Cond.size() == 0) && | |
236 | "Sparc branch conditions should have one component!"); | |
237 | ||
238 | if (Cond.empty()) { | |
239 | assert(!FBB && "Unconditional branch with multiple successors!"); | |
240 | BuildMI(&MBB, DL, get(SP::BA)).addMBB(TBB); | |
241 | return 1; | |
242 | } | |
243 | ||
244 | //Conditional branch | |
245 | unsigned CC = Cond[0].getImm(); | |
246 | ||
247 | if (IsIntegerCC(CC)) | |
248 | BuildMI(&MBB, DL, get(SP::BCOND)).addMBB(TBB).addImm(CC); | |
249 | else | |
250 | BuildMI(&MBB, DL, get(SP::FBCOND)).addMBB(TBB).addImm(CC); | |
251 | if (!FBB) | |
252 | return 1; | |
253 | ||
254 | BuildMI(&MBB, DL, get(SP::BA)).addMBB(FBB); | |
255 | return 2; | |
256 | } | |
257 | ||
258 | unsigned SparcInstrInfo::RemoveBranch(MachineBasicBlock &MBB) const | |
259 | { | |
260 | MachineBasicBlock::iterator I = MBB.end(); | |
261 | unsigned Count = 0; | |
262 | while (I != MBB.begin()) { | |
263 | --I; | |
264 | ||
265 | if (I->isDebugValue()) | |
266 | continue; | |
267 | ||
268 | if (I->getOpcode() != SP::BA | |
269 | && I->getOpcode() != SP::BCOND | |
270 | && I->getOpcode() != SP::FBCOND) | |
271 | break; // Not a branch | |
272 | ||
273 | I->eraseFromParent(); | |
274 | I = MBB.end(); | |
275 | ++Count; | |
276 | } | |
277 | return Count; | |
278 | } | |
279 | ||
280 | void SparcInstrInfo::copyPhysReg(MachineBasicBlock &MBB, | |
281 | MachineBasicBlock::iterator I, DebugLoc DL, | |
282 | unsigned DestReg, unsigned SrcReg, | |
283 | bool KillSrc) const { | |
284 | if (SP::IntRegsRegClass.contains(DestReg, SrcReg)) | |
285 | BuildMI(MBB, I, DL, get(SP::ORrr), DestReg).addReg(SP::G0) | |
286 | .addReg(SrcReg, getKillRegState(KillSrc)); | |
287 | else if (SP::FPRegsRegClass.contains(DestReg, SrcReg)) | |
288 | BuildMI(MBB, I, DL, get(SP::FMOVS), DestReg) | |
289 | .addReg(SrcReg, getKillRegState(KillSrc)); | |
290 | else if (SP::DFPRegsRegClass.contains(DestReg, SrcReg)) | |
291 | BuildMI(MBB, I, DL, get(Subtarget.isV9() ? SP::FMOVD : SP::FpMOVD), DestReg) | |
292 | .addReg(SrcReg, getKillRegState(KillSrc)); | |
293 | else | |
294 | llvm_unreachable("Impossible reg-to-reg copy"); | |
295 | } | |
296 | ||
297 | void SparcInstrInfo:: | |
298 | storeRegToStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator I, | |
299 | unsigned SrcReg, bool isKill, int FI, | |
300 | const TargetRegisterClass *RC, | |
301 | const TargetRegisterInfo *TRI) const { | |
302 | DebugLoc DL; | |
303 | if (I != MBB.end()) DL = I->getDebugLoc(); | |
304 | ||
305 | // On the order of operands here: think "[FrameIdx + 0] = SrcReg". | |
306 | if (RC == &SP::IntRegsRegClass) | |
307 | BuildMI(MBB, I, DL, get(SP::STri)).addFrameIndex(FI).addImm(0) | |
308 | .addReg(SrcReg, getKillRegState(isKill)); | |
309 | else if (RC == &SP::FPRegsRegClass) | |
310 | BuildMI(MBB, I, DL, get(SP::STFri)).addFrameIndex(FI).addImm(0) | |
311 | .addReg(SrcReg, getKillRegState(isKill)); | |
312 | else if (RC == &SP::DFPRegsRegClass) | |
313 | BuildMI(MBB, I, DL, get(SP::STDFri)).addFrameIndex(FI).addImm(0) | |
314 | .addReg(SrcReg, getKillRegState(isKill)); | |
315 | else | |
316 | llvm_unreachable("Can't store this register to stack slot"); | |
317 | } | |
318 | ||
319 | void SparcInstrInfo:: | |
320 | loadRegFromStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator I, | |
321 | unsigned DestReg, int FI, | |
322 | const TargetRegisterClass *RC, | |
323 | const TargetRegisterInfo *TRI) const { | |
324 | DebugLoc DL; | |
325 | if (I != MBB.end()) DL = I->getDebugLoc(); | |
326 | ||
327 | if (RC == &SP::IntRegsRegClass) | |
328 | BuildMI(MBB, I, DL, get(SP::LDri), DestReg).addFrameIndex(FI).addImm(0); | |
329 | else if (RC == &SP::FPRegsRegClass) | |
330 | BuildMI(MBB, I, DL, get(SP::LDFri), DestReg).addFrameIndex(FI).addImm(0); | |
331 | else if (RC == &SP::DFPRegsRegClass) | |
332 | BuildMI(MBB, I, DL, get(SP::LDDFri), DestReg).addFrameIndex(FI).addImm(0); | |
333 | else | |
334 | llvm_unreachable("Can't load this register from stack slot"); | |
335 | } | |
336 | ||
337 | unsigned SparcInstrInfo::getGlobalBaseReg(MachineFunction *MF) const | |
338 | { | |
339 | SparcMachineFunctionInfo *SparcFI = MF->getInfo<SparcMachineFunctionInfo>(); | |
340 | unsigned GlobalBaseReg = SparcFI->getGlobalBaseReg(); | |
341 | if (GlobalBaseReg != 0) | |
342 | return GlobalBaseReg; | |
343 | ||
344 | // Insert the set of GlobalBaseReg into the first MBB of the function | |
345 | MachineBasicBlock &FirstMBB = MF->front(); | |
346 | MachineBasicBlock::iterator MBBI = FirstMBB.begin(); | |
347 | MachineRegisterInfo &RegInfo = MF->getRegInfo(); | |
348 | ||
349 | GlobalBaseReg = RegInfo.createVirtualRegister(&SP::IntRegsRegClass); | |
350 | ||
351 | ||
352 | DebugLoc dl; | |
353 | ||
354 | BuildMI(FirstMBB, MBBI, dl, get(SP::GETPCX), GlobalBaseReg); | |
355 | SparcFI->setGlobalBaseReg(GlobalBaseReg); | |
356 | return GlobalBaseReg; | |
357 | } |