Fix a problem where lib/Target/TargetInstrInfo.h would include and use
[oota-llvm.git] / 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 "AlphaGenInstrInfo.inc"
17 #include "llvm/ADT/STLExtras.h"
18 #include "llvm/CodeGen/MachineInstrBuilder.h"
19 using namespace llvm;
20
21 AlphaInstrInfo::AlphaInstrInfo()
22   : TargetInstrInfoImpl(AlphaInsts, array_lengthof(AlphaInsts)),
23     RI(*this) { }
24
25
26 bool AlphaInstrInfo::isMoveInstr(const MachineInstr& MI,
27                                  unsigned& sourceReg,
28                                  unsigned& destReg) const {
29   MachineOpCode oc = MI.getOpcode();
30   if (oc == Alpha::BISr   || 
31       oc == Alpha::CPYSS  || 
32       oc == Alpha::CPYST  ||
33       oc == Alpha::CPYSSt || 
34       oc == Alpha::CPYSTs) {
35     // or r1, r2, r2 
36     // cpys(s|t) r1 r2 r2
37     assert(MI.getNumOperands() >= 3 &&
38            MI.getOperand(0).isRegister() &&
39            MI.getOperand(1).isRegister() &&
40            MI.getOperand(2).isRegister() &&
41            "invalid Alpha BIS instruction!");
42     if (MI.getOperand(1).getReg() == MI.getOperand(2).getReg()) {
43       sourceReg = MI.getOperand(1).getReg();
44       destReg = MI.getOperand(0).getReg();
45       return true;
46     }
47   }
48   return false;
49 }
50
51 unsigned 
52 AlphaInstrInfo::isLoadFromStackSlot(MachineInstr *MI, int &FrameIndex) const {
53   switch (MI->getOpcode()) {
54   case Alpha::LDL:
55   case Alpha::LDQ:
56   case Alpha::LDBU:
57   case Alpha::LDWU:
58   case Alpha::LDS:
59   case Alpha::LDT:
60     if (MI->getOperand(1).isFrameIndex()) {
61       FrameIndex = MI->getOperand(1).getIndex();
62       return MI->getOperand(0).getReg();
63     }
64     break;
65   }
66   return 0;
67 }
68
69 unsigned 
70 AlphaInstrInfo::isStoreToStackSlot(MachineInstr *MI, int &FrameIndex) const {
71   switch (MI->getOpcode()) {
72   case Alpha::STL:
73   case Alpha::STQ:
74   case Alpha::STB:
75   case Alpha::STW:
76   case Alpha::STS:
77   case Alpha::STT:
78     if (MI->getOperand(1).isFrameIndex()) {
79       FrameIndex = MI->getOperand(1).getIndex();
80       return MI->getOperand(0).getReg();
81     }
82     break;
83   }
84   return 0;
85 }
86
87 static bool isAlphaIntCondCode(unsigned Opcode) {
88   switch (Opcode) {
89   case Alpha::BEQ: 
90   case Alpha::BNE: 
91   case Alpha::BGE: 
92   case Alpha::BGT: 
93   case Alpha::BLE: 
94   case Alpha::BLT: 
95   case Alpha::BLBC: 
96   case Alpha::BLBS:
97     return true;
98   default:
99     return false;
100   }
101 }
102
103 unsigned AlphaInstrInfo::InsertBranch(MachineBasicBlock &MBB,MachineBasicBlock *TBB,
104                                   MachineBasicBlock *FBB,
105                                   const std::vector<MachineOperand> &Cond)const{
106   assert(TBB && "InsertBranch must not be told to insert a fallthrough");
107   assert((Cond.size() == 2 || Cond.size() == 0) && 
108          "Alpha branch conditions have two components!");
109
110   // One-way branch.
111   if (FBB == 0) {
112     if (Cond.empty())   // Unconditional branch
113       BuildMI(&MBB, get(Alpha::BR)).addMBB(TBB);
114     else                // Conditional branch
115       if (isAlphaIntCondCode(Cond[0].getImm()))
116         BuildMI(&MBB, get(Alpha::COND_BRANCH_I))
117           .addImm(Cond[0].getImm()).addReg(Cond[1].getReg()).addMBB(TBB);
118       else
119         BuildMI(&MBB, get(Alpha::COND_BRANCH_F))
120           .addImm(Cond[0].getImm()).addReg(Cond[1].getReg()).addMBB(TBB);
121     return 1;
122   }
123   
124   // Two-way Conditional Branch.
125   if (isAlphaIntCondCode(Cond[0].getImm()))
126     BuildMI(&MBB, get(Alpha::COND_BRANCH_I))
127       .addImm(Cond[0].getImm()).addReg(Cond[1].getReg()).addMBB(TBB);
128   else
129     BuildMI(&MBB, get(Alpha::COND_BRANCH_F))
130       .addImm(Cond[0].getImm()).addReg(Cond[1].getReg()).addMBB(TBB);
131   BuildMI(&MBB, get(Alpha::BR)).addMBB(FBB);
132   return 2;
133 }
134
135 void AlphaInstrInfo::copyRegToReg(MachineBasicBlock &MBB,
136                                      MachineBasicBlock::iterator MI,
137                                      unsigned DestReg, unsigned SrcReg,
138                                      const TargetRegisterClass *DestRC,
139                                      const TargetRegisterClass *SrcRC) const {
140   //cerr << "copyRegToReg " << DestReg << " <- " << SrcReg << "\n";
141   if (DestRC != SrcRC) {
142     cerr << "Not yet supported!";
143     abort();
144   }
145
146   if (DestRC == Alpha::GPRCRegisterClass) {
147     BuildMI(MBB, MI, get(Alpha::BISr), DestReg).addReg(SrcReg).addReg(SrcReg);
148   } else if (DestRC == Alpha::F4RCRegisterClass) {
149     BuildMI(MBB, MI, get(Alpha::CPYSS), DestReg).addReg(SrcReg).addReg(SrcReg);
150   } else if (DestRC == Alpha::F8RCRegisterClass) {
151     BuildMI(MBB, MI, get(Alpha::CPYST), DestReg).addReg(SrcReg).addReg(SrcReg);
152   } else {
153     cerr << "Attempt to copy register that is not GPR or FPR";
154     abort();
155   }
156 }
157
158 static unsigned AlphaRevCondCode(unsigned Opcode) {
159   switch (Opcode) {
160   case Alpha::BEQ: return Alpha::BNE;
161   case Alpha::BNE: return Alpha::BEQ;
162   case Alpha::BGE: return Alpha::BLT;
163   case Alpha::BGT: return Alpha::BLE;
164   case Alpha::BLE: return Alpha::BGT;
165   case Alpha::BLT: return Alpha::BGE;
166   case Alpha::BLBC: return Alpha::BLBS;
167   case Alpha::BLBS: return Alpha::BLBC;
168   case Alpha::FBEQ: return Alpha::FBNE;
169   case Alpha::FBNE: return Alpha::FBEQ;
170   case Alpha::FBGE: return Alpha::FBLT;
171   case Alpha::FBGT: return Alpha::FBLE;
172   case Alpha::FBLE: return Alpha::FBGT;
173   case Alpha::FBLT: return Alpha::FBGE;
174   default:
175     assert(0 && "Unknown opcode");
176   }
177 }
178
179 // Branch analysis.
180 bool AlphaInstrInfo::AnalyzeBranch(MachineBasicBlock &MBB,MachineBasicBlock *&TBB,
181                                  MachineBasicBlock *&FBB,
182                                  std::vector<MachineOperand> &Cond) const {
183   // If the block has no terminators, it just falls into the block after it.
184   MachineBasicBlock::iterator I = MBB.end();
185   if (I == MBB.begin() || !isUnpredicatedTerminator(--I))
186     return false;
187
188   // Get the last instruction in the block.
189   MachineInstr *LastInst = I;
190   
191   // If there is only one terminator instruction, process it.
192   if (I == MBB.begin() || !isUnpredicatedTerminator(--I)) {
193     if (LastInst->getOpcode() == Alpha::BR) {
194       TBB = LastInst->getOperand(0).getMBB();
195       return false;
196     } else if (LastInst->getOpcode() == Alpha::COND_BRANCH_I ||
197                LastInst->getOpcode() == Alpha::COND_BRANCH_F) {
198       // Block ends with fall-through condbranch.
199       TBB = LastInst->getOperand(2).getMBB();
200       Cond.push_back(LastInst->getOperand(0));
201       Cond.push_back(LastInst->getOperand(1));
202       return false;
203     }
204     // Otherwise, don't know what this is.
205     return true;
206   }
207   
208   // Get the instruction before it if it's a terminator.
209   MachineInstr *SecondLastInst = I;
210
211   // If there are three terminators, we don't know what sort of block this is.
212   if (SecondLastInst && I != MBB.begin() &&
213       isUnpredicatedTerminator(--I))
214     return true;
215   
216   // If the block ends with Alpha::BR and Alpha::COND_BRANCH_*, handle it.
217   if ((SecondLastInst->getOpcode() == Alpha::COND_BRANCH_I ||
218       SecondLastInst->getOpcode() == Alpha::COND_BRANCH_F) && 
219       LastInst->getOpcode() == Alpha::BR) {
220     TBB =  SecondLastInst->getOperand(2).getMBB();
221     Cond.push_back(SecondLastInst->getOperand(0));
222     Cond.push_back(SecondLastInst->getOperand(1));
223     FBB = LastInst->getOperand(0).getMBB();
224     return false;
225   }
226   
227   // If the block ends with two Alpha::BRs, handle it.  The second one is not
228   // executed, so remove it.
229   if (SecondLastInst->getOpcode() == Alpha::BR && 
230       LastInst->getOpcode() == Alpha::BR) {
231     TBB = SecondLastInst->getOperand(0).getMBB();
232     I = LastInst;
233     I->eraseFromParent();
234     return false;
235   }
236
237   // Otherwise, can't handle this.
238   return true;
239 }
240
241 unsigned AlphaInstrInfo::RemoveBranch(MachineBasicBlock &MBB) const {
242   MachineBasicBlock::iterator I = MBB.end();
243   if (I == MBB.begin()) return 0;
244   --I;
245   if (I->getOpcode() != Alpha::BR && 
246       I->getOpcode() != Alpha::COND_BRANCH_I &&
247       I->getOpcode() != Alpha::COND_BRANCH_F)
248     return 0;
249   
250   // Remove the branch.
251   I->eraseFromParent();
252   
253   I = MBB.end();
254
255   if (I == MBB.begin()) return 1;
256   --I;
257   if (I->getOpcode() != Alpha::COND_BRANCH_I && 
258       I->getOpcode() != Alpha::COND_BRANCH_F)
259     return 1;
260   
261   // Remove the branch.
262   I->eraseFromParent();
263   return 2;
264 }
265
266 void AlphaInstrInfo::insertNoop(MachineBasicBlock &MBB, 
267                                 MachineBasicBlock::iterator MI) const {
268   BuildMI(MBB, MI, get(Alpha::BISr), Alpha::R31).addReg(Alpha::R31)
269     .addReg(Alpha::R31);
270 }
271
272 bool AlphaInstrInfo::BlockHasNoFallThrough(MachineBasicBlock &MBB) const {
273   if (MBB.empty()) return false;
274   
275   switch (MBB.back().getOpcode()) {
276   case Alpha::RETDAG: // Return.
277   case Alpha::RETDAGp:
278   case Alpha::BR:     // Uncond branch.
279   case Alpha::JMP:  // Indirect branch.
280     return true;
281   default: return false;
282   }
283 }
284 bool AlphaInstrInfo::
285 ReverseBranchCondition(std::vector<MachineOperand> &Cond) const {
286   assert(Cond.size() == 2 && "Invalid Alpha branch opcode!");
287   Cond[0].setImm(AlphaRevCondCode(Cond[0].getImm()));
288   return false;
289 }
290