]> CyberLeo.Net >> Repos - FreeBSD/stable/9.git/blob - contrib/llvm/lib/Target/Alpha/AlphaInstrInfo.cpp
Copy head to stable/9 as part of 9.0-RELEASE release cycle.
[FreeBSD/stable/9.git] / contrib / llvm / lib / Target / Alpha / AlphaInstrInfo.cpp
1 //===- AlphaInstrInfo.cpp - Alpha Instruction Information -------*- C++ -*-===//
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 Alpha implementation of the TargetInstrInfo class.
11 //
12 //===----------------------------------------------------------------------===//
13
14 #include "Alpha.h"
15 #include "AlphaInstrInfo.h"
16 #include "AlphaMachineFunctionInfo.h"
17 #include "llvm/CodeGen/MachineInstrBuilder.h"
18 #include "llvm/CodeGen/MachineRegisterInfo.h"
19 #include "llvm/Target/TargetRegistry.h"
20 #include "llvm/ADT/STLExtras.h"
21 #include "llvm/ADT/SmallVector.h"
22 #include "llvm/Support/ErrorHandling.h"
23
24 #define GET_INSTRINFO_CTOR
25 #include "AlphaGenInstrInfo.inc"
26 using namespace llvm;
27
28 AlphaInstrInfo::AlphaInstrInfo()
29   : AlphaGenInstrInfo(Alpha::ADJUSTSTACKDOWN, Alpha::ADJUSTSTACKUP),
30     RI(*this) {
31 }
32
33
34 unsigned 
35 AlphaInstrInfo::isLoadFromStackSlot(const MachineInstr *MI,
36                                     int &FrameIndex) const {
37   switch (MI->getOpcode()) {
38   case Alpha::LDL:
39   case Alpha::LDQ:
40   case Alpha::LDBU:
41   case Alpha::LDWU:
42   case Alpha::LDS:
43   case Alpha::LDT:
44     if (MI->getOperand(1).isFI()) {
45       FrameIndex = MI->getOperand(1).getIndex();
46       return MI->getOperand(0).getReg();
47     }
48     break;
49   }
50   return 0;
51 }
52
53 unsigned 
54 AlphaInstrInfo::isStoreToStackSlot(const MachineInstr *MI,
55                                    int &FrameIndex) const {
56   switch (MI->getOpcode()) {
57   case Alpha::STL:
58   case Alpha::STQ:
59   case Alpha::STB:
60   case Alpha::STW:
61   case Alpha::STS:
62   case Alpha::STT:
63     if (MI->getOperand(1).isFI()) {
64       FrameIndex = MI->getOperand(1).getIndex();
65       return MI->getOperand(0).getReg();
66     }
67     break;
68   }
69   return 0;
70 }
71
72 static bool isAlphaIntCondCode(unsigned Opcode) {
73   switch (Opcode) {
74   case Alpha::BEQ: 
75   case Alpha::BNE: 
76   case Alpha::BGE: 
77   case Alpha::BGT: 
78   case Alpha::BLE: 
79   case Alpha::BLT: 
80   case Alpha::BLBC: 
81   case Alpha::BLBS:
82     return true;
83   default:
84     return false;
85   }
86 }
87
88 unsigned AlphaInstrInfo::InsertBranch(MachineBasicBlock &MBB,
89                                       MachineBasicBlock *TBB,
90                                       MachineBasicBlock *FBB,
91                                       const SmallVectorImpl<MachineOperand> &Cond,
92                                       DebugLoc DL) const {
93   assert(TBB && "InsertBranch must not be told to insert a fallthrough");
94   assert((Cond.size() == 2 || Cond.size() == 0) && 
95          "Alpha branch conditions have two components!");
96
97   // One-way branch.
98   if (FBB == 0) {
99     if (Cond.empty())   // Unconditional branch
100       BuildMI(&MBB, DL, get(Alpha::BR)).addMBB(TBB);
101     else                // Conditional branch
102       if (isAlphaIntCondCode(Cond[0].getImm()))
103         BuildMI(&MBB, DL, get(Alpha::COND_BRANCH_I))
104           .addImm(Cond[0].getImm()).addReg(Cond[1].getReg()).addMBB(TBB);
105       else
106         BuildMI(&MBB, DL, get(Alpha::COND_BRANCH_F))
107           .addImm(Cond[0].getImm()).addReg(Cond[1].getReg()).addMBB(TBB);
108     return 1;
109   }
110   
111   // Two-way Conditional Branch.
112   if (isAlphaIntCondCode(Cond[0].getImm()))
113     BuildMI(&MBB, DL, get(Alpha::COND_BRANCH_I))
114       .addImm(Cond[0].getImm()).addReg(Cond[1].getReg()).addMBB(TBB);
115   else
116     BuildMI(&MBB, DL, get(Alpha::COND_BRANCH_F))
117       .addImm(Cond[0].getImm()).addReg(Cond[1].getReg()).addMBB(TBB);
118   BuildMI(&MBB, DL, get(Alpha::BR)).addMBB(FBB);
119   return 2;
120 }
121
122 void AlphaInstrInfo::copyPhysReg(MachineBasicBlock &MBB,
123                                  MachineBasicBlock::iterator MI, DebugLoc DL,
124                                  unsigned DestReg, unsigned SrcReg,
125                                  bool KillSrc) const {
126   if (Alpha::GPRCRegClass.contains(DestReg, SrcReg)) {
127     BuildMI(MBB, MI, DL, get(Alpha::BISr), DestReg)
128       .addReg(SrcReg)
129       .addReg(SrcReg, getKillRegState(KillSrc));
130   } else if (Alpha::F4RCRegClass.contains(DestReg, SrcReg)) {
131     BuildMI(MBB, MI, DL, get(Alpha::CPYSS), DestReg)
132       .addReg(SrcReg)
133       .addReg(SrcReg, getKillRegState(KillSrc));
134   } else if (Alpha::F8RCRegClass.contains(DestReg, SrcReg)) {
135     BuildMI(MBB, MI, DL, get(Alpha::CPYST), DestReg)
136       .addReg(SrcReg)
137       .addReg(SrcReg, getKillRegState(KillSrc));
138   } else {
139     llvm_unreachable("Attempt to copy register that is not GPR or FPR");
140   }
141 }
142
143 void
144 AlphaInstrInfo::storeRegToStackSlot(MachineBasicBlock &MBB,
145                                     MachineBasicBlock::iterator MI,
146                                     unsigned SrcReg, bool isKill, int FrameIdx,
147                                     const TargetRegisterClass *RC,
148                                     const TargetRegisterInfo *TRI) const {
149   //cerr << "Trying to store " << getPrettyName(SrcReg) << " to "
150   //     << FrameIdx << "\n";
151   //BuildMI(MBB, MI, Alpha::WTF, 0).addReg(SrcReg);
152
153   DebugLoc DL;
154   if (MI != MBB.end()) DL = MI->getDebugLoc();
155
156   if (RC == Alpha::F4RCRegisterClass)
157     BuildMI(MBB, MI, DL, get(Alpha::STS))
158       .addReg(SrcReg, getKillRegState(isKill))
159       .addFrameIndex(FrameIdx).addReg(Alpha::F31);
160   else if (RC == Alpha::F8RCRegisterClass)
161     BuildMI(MBB, MI, DL, get(Alpha::STT))
162       .addReg(SrcReg, getKillRegState(isKill))
163       .addFrameIndex(FrameIdx).addReg(Alpha::F31);
164   else if (RC == Alpha::GPRCRegisterClass)
165     BuildMI(MBB, MI, DL, get(Alpha::STQ))
166       .addReg(SrcReg, getKillRegState(isKill))
167       .addFrameIndex(FrameIdx).addReg(Alpha::F31);
168   else
169     llvm_unreachable("Unhandled register class");
170 }
171
172 void
173 AlphaInstrInfo::loadRegFromStackSlot(MachineBasicBlock &MBB,
174                                         MachineBasicBlock::iterator MI,
175                                         unsigned DestReg, int FrameIdx,
176                                      const TargetRegisterClass *RC,
177                                      const TargetRegisterInfo *TRI) const {
178   //cerr << "Trying to load " << getPrettyName(DestReg) << " to "
179   //     << FrameIdx << "\n";
180   DebugLoc DL;
181   if (MI != MBB.end()) DL = MI->getDebugLoc();
182
183   if (RC == Alpha::F4RCRegisterClass)
184     BuildMI(MBB, MI, DL, get(Alpha::LDS), DestReg)
185       .addFrameIndex(FrameIdx).addReg(Alpha::F31);
186   else if (RC == Alpha::F8RCRegisterClass)
187     BuildMI(MBB, MI, DL, get(Alpha::LDT), DestReg)
188       .addFrameIndex(FrameIdx).addReg(Alpha::F31);
189   else if (RC == Alpha::GPRCRegisterClass)
190     BuildMI(MBB, MI, DL, get(Alpha::LDQ), DestReg)
191       .addFrameIndex(FrameIdx).addReg(Alpha::F31);
192   else
193     llvm_unreachable("Unhandled register class");
194 }
195
196 static unsigned AlphaRevCondCode(unsigned Opcode) {
197   switch (Opcode) {
198   case Alpha::BEQ: return Alpha::BNE;
199   case Alpha::BNE: return Alpha::BEQ;
200   case Alpha::BGE: return Alpha::BLT;
201   case Alpha::BGT: return Alpha::BLE;
202   case Alpha::BLE: return Alpha::BGT;
203   case Alpha::BLT: return Alpha::BGE;
204   case Alpha::BLBC: return Alpha::BLBS;
205   case Alpha::BLBS: return Alpha::BLBC;
206   case Alpha::FBEQ: return Alpha::FBNE;
207   case Alpha::FBNE: return Alpha::FBEQ;
208   case Alpha::FBGE: return Alpha::FBLT;
209   case Alpha::FBGT: return Alpha::FBLE;
210   case Alpha::FBLE: return Alpha::FBGT;
211   case Alpha::FBLT: return Alpha::FBGE;
212   default:
213     llvm_unreachable("Unknown opcode");
214   }
215   return 0; // Not reached
216 }
217
218 // Branch analysis.
219 bool AlphaInstrInfo::AnalyzeBranch(MachineBasicBlock &MBB,MachineBasicBlock *&TBB,
220                                    MachineBasicBlock *&FBB,
221                                    SmallVectorImpl<MachineOperand> &Cond,
222                                    bool AllowModify) const {
223   // If the block has no terminators, it just falls into the block after it.
224   MachineBasicBlock::iterator I = MBB.end();
225   if (I == MBB.begin())
226     return false;
227   --I;
228   while (I->isDebugValue()) {
229     if (I == MBB.begin())
230       return false;
231     --I;
232   }
233   if (!isUnpredicatedTerminator(I))
234     return false;
235
236   // Get the last instruction in the block.
237   MachineInstr *LastInst = I;
238   
239   // If there is only one terminator instruction, process it.
240   if (I == MBB.begin() || !isUnpredicatedTerminator(--I)) {
241     if (LastInst->getOpcode() == Alpha::BR) {
242       TBB = LastInst->getOperand(0).getMBB();
243       return false;
244     } else if (LastInst->getOpcode() == Alpha::COND_BRANCH_I ||
245                LastInst->getOpcode() == Alpha::COND_BRANCH_F) {
246       // Block ends with fall-through condbranch.
247       TBB = LastInst->getOperand(2).getMBB();
248       Cond.push_back(LastInst->getOperand(0));
249       Cond.push_back(LastInst->getOperand(1));
250       return false;
251     }
252     // Otherwise, don't know what this is.
253     return true;
254   }
255   
256   // Get the instruction before it if it's a terminator.
257   MachineInstr *SecondLastInst = I;
258
259   // If there are three terminators, we don't know what sort of block this is.
260   if (SecondLastInst && I != MBB.begin() &&
261       isUnpredicatedTerminator(--I))
262     return true;
263   
264   // If the block ends with Alpha::BR and Alpha::COND_BRANCH_*, handle it.
265   if ((SecondLastInst->getOpcode() == Alpha::COND_BRANCH_I ||
266       SecondLastInst->getOpcode() == Alpha::COND_BRANCH_F) && 
267       LastInst->getOpcode() == Alpha::BR) {
268     TBB =  SecondLastInst->getOperand(2).getMBB();
269     Cond.push_back(SecondLastInst->getOperand(0));
270     Cond.push_back(SecondLastInst->getOperand(1));
271     FBB = LastInst->getOperand(0).getMBB();
272     return false;
273   }
274   
275   // If the block ends with two Alpha::BRs, handle it.  The second one is not
276   // executed, so remove it.
277   if (SecondLastInst->getOpcode() == Alpha::BR && 
278       LastInst->getOpcode() == Alpha::BR) {
279     TBB = SecondLastInst->getOperand(0).getMBB();
280     I = LastInst;
281     if (AllowModify)
282       I->eraseFromParent();
283     return false;
284   }
285
286   // Otherwise, can't handle this.
287   return true;
288 }
289
290 unsigned AlphaInstrInfo::RemoveBranch(MachineBasicBlock &MBB) const {
291   MachineBasicBlock::iterator I = MBB.end();
292   if (I == MBB.begin()) return 0;
293   --I;
294   while (I->isDebugValue()) {
295     if (I == MBB.begin())
296       return 0;
297     --I;
298   }
299   if (I->getOpcode() != Alpha::BR && 
300       I->getOpcode() != Alpha::COND_BRANCH_I &&
301       I->getOpcode() != Alpha::COND_BRANCH_F)
302     return 0;
303   
304   // Remove the branch.
305   I->eraseFromParent();
306   
307   I = MBB.end();
308
309   if (I == MBB.begin()) return 1;
310   --I;
311   if (I->getOpcode() != Alpha::COND_BRANCH_I && 
312       I->getOpcode() != Alpha::COND_BRANCH_F)
313     return 1;
314   
315   // Remove the branch.
316   I->eraseFromParent();
317   return 2;
318 }
319
320 void AlphaInstrInfo::insertNoop(MachineBasicBlock &MBB, 
321                                 MachineBasicBlock::iterator MI) const {
322   DebugLoc DL;
323   BuildMI(MBB, MI, DL, get(Alpha::BISr), Alpha::R31)
324     .addReg(Alpha::R31)
325     .addReg(Alpha::R31);
326 }
327
328 bool AlphaInstrInfo::
329 ReverseBranchCondition(SmallVectorImpl<MachineOperand> &Cond) const {
330   assert(Cond.size() == 2 && "Invalid Alpha branch opcode!");
331   Cond[0].setImm(AlphaRevCondCode(Cond[0].getImm()));
332   return false;
333 }
334
335 /// getGlobalBaseReg - Return a virtual register initialized with the
336 /// the global base register value. Output instructions required to
337 /// initialize the register in the function entry block, if necessary.
338 ///
339 unsigned AlphaInstrInfo::getGlobalBaseReg(MachineFunction *MF) const {
340   AlphaMachineFunctionInfo *AlphaFI = MF->getInfo<AlphaMachineFunctionInfo>();
341   unsigned GlobalBaseReg = AlphaFI->getGlobalBaseReg();
342   if (GlobalBaseReg != 0)
343     return GlobalBaseReg;
344
345   // Insert the set of GlobalBaseReg into the first MBB of the function
346   MachineBasicBlock &FirstMBB = MF->front();
347   MachineBasicBlock::iterator MBBI = FirstMBB.begin();
348   MachineRegisterInfo &RegInfo = MF->getRegInfo();
349   const TargetInstrInfo *TII = MF->getTarget().getInstrInfo();
350
351   GlobalBaseReg = RegInfo.createVirtualRegister(&Alpha::GPRCRegClass);
352   BuildMI(FirstMBB, MBBI, DebugLoc(), TII->get(TargetOpcode::COPY),
353           GlobalBaseReg).addReg(Alpha::R29);
354   RegInfo.addLiveIn(Alpha::R29);
355
356   AlphaFI->setGlobalBaseReg(GlobalBaseReg);
357   return GlobalBaseReg;
358 }
359
360 /// getGlobalRetAddr - Return a virtual register initialized with the
361 /// the global base register value. Output instructions required to
362 /// initialize the register in the function entry block, if necessary.
363 ///
364 unsigned AlphaInstrInfo::getGlobalRetAddr(MachineFunction *MF) const {
365   AlphaMachineFunctionInfo *AlphaFI = MF->getInfo<AlphaMachineFunctionInfo>();
366   unsigned GlobalRetAddr = AlphaFI->getGlobalRetAddr();
367   if (GlobalRetAddr != 0)
368     return GlobalRetAddr;
369
370   // Insert the set of GlobalRetAddr into the first MBB of the function
371   MachineBasicBlock &FirstMBB = MF->front();
372   MachineBasicBlock::iterator MBBI = FirstMBB.begin();
373   MachineRegisterInfo &RegInfo = MF->getRegInfo();
374   const TargetInstrInfo *TII = MF->getTarget().getInstrInfo();
375
376   GlobalRetAddr = RegInfo.createVirtualRegister(&Alpha::GPRCRegClass);
377   BuildMI(FirstMBB, MBBI, DebugLoc(), TII->get(TargetOpcode::COPY),
378           GlobalRetAddr).addReg(Alpha::R26);
379   RegInfo.addLiveIn(Alpha::R26);
380
381   AlphaFI->setGlobalRetAddr(GlobalRetAddr);
382   return GlobalRetAddr;
383 }