Remove attribution from file headers, per discussion on llvmdev.
[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   : TargetInstrInfo(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).getFrameIndex();
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).getFrameIndex();
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 static unsigned AlphaRevCondCode(unsigned Opcode) {
136   switch (Opcode) {
137   case Alpha::BEQ: return Alpha::BNE;
138   case Alpha::BNE: return Alpha::BEQ;
139   case Alpha::BGE: return Alpha::BLT;
140   case Alpha::BGT: return Alpha::BLE;
141   case Alpha::BLE: return Alpha::BGT;
142   case Alpha::BLT: return Alpha::BGE;
143   case Alpha::BLBC: return Alpha::BLBS;
144   case Alpha::BLBS: return Alpha::BLBC;
145   case Alpha::FBEQ: return Alpha::FBNE;
146   case Alpha::FBNE: return Alpha::FBEQ;
147   case Alpha::FBGE: return Alpha::FBLT;
148   case Alpha::FBGT: return Alpha::FBLE;
149   case Alpha::FBLE: return Alpha::FBGT;
150   case Alpha::FBLT: return Alpha::FBGE;
151   default:
152     assert(0 && "Unknown opcode");
153   }
154 }
155
156 // Branch analysis.
157 bool AlphaInstrInfo::AnalyzeBranch(MachineBasicBlock &MBB,MachineBasicBlock *&TBB,
158                                  MachineBasicBlock *&FBB,
159                                  std::vector<MachineOperand> &Cond) const {
160   // If the block has no terminators, it just falls into the block after it.
161   MachineBasicBlock::iterator I = MBB.end();
162   if (I == MBB.begin() || !isUnpredicatedTerminator(--I))
163     return false;
164
165   // Get the last instruction in the block.
166   MachineInstr *LastInst = I;
167   
168   // If there is only one terminator instruction, process it.
169   if (I == MBB.begin() || !isUnpredicatedTerminator(--I)) {
170     if (LastInst->getOpcode() == Alpha::BR) {
171       TBB = LastInst->getOperand(0).getMachineBasicBlock();
172       return false;
173     } else if (LastInst->getOpcode() == Alpha::COND_BRANCH_I ||
174                LastInst->getOpcode() == Alpha::COND_BRANCH_F) {
175       // Block ends with fall-through condbranch.
176       TBB = LastInst->getOperand(2).getMachineBasicBlock();
177       Cond.push_back(LastInst->getOperand(0));
178       Cond.push_back(LastInst->getOperand(1));
179       return false;
180     }
181     // Otherwise, don't know what this is.
182     return true;
183   }
184   
185   // Get the instruction before it if it's a terminator.
186   MachineInstr *SecondLastInst = I;
187
188   // If there are three terminators, we don't know what sort of block this is.
189   if (SecondLastInst && I != MBB.begin() &&
190       isUnpredicatedTerminator(--I))
191     return true;
192   
193   // If the block ends with Alpha::BR and Alpha::COND_BRANCH_*, handle it.
194   if ((SecondLastInst->getOpcode() == Alpha::COND_BRANCH_I ||
195       SecondLastInst->getOpcode() == Alpha::COND_BRANCH_F) && 
196       LastInst->getOpcode() == Alpha::BR) {
197     TBB =  SecondLastInst->getOperand(2).getMachineBasicBlock();
198     Cond.push_back(SecondLastInst->getOperand(0));
199     Cond.push_back(SecondLastInst->getOperand(1));
200     FBB = LastInst->getOperand(0).getMachineBasicBlock();
201     return false;
202   }
203   
204   // If the block ends with two Alpha::BRs, handle it.  The second one is not
205   // executed, so remove it.
206   if (SecondLastInst->getOpcode() == Alpha::BR && 
207       LastInst->getOpcode() == Alpha::BR) {
208     TBB = SecondLastInst->getOperand(0).getMachineBasicBlock();
209     I = LastInst;
210     I->eraseFromParent();
211     return false;
212   }
213
214   // Otherwise, can't handle this.
215   return true;
216 }
217
218 unsigned AlphaInstrInfo::RemoveBranch(MachineBasicBlock &MBB) const {
219   MachineBasicBlock::iterator I = MBB.end();
220   if (I == MBB.begin()) return 0;
221   --I;
222   if (I->getOpcode() != Alpha::BR && 
223       I->getOpcode() != Alpha::COND_BRANCH_I &&
224       I->getOpcode() != Alpha::COND_BRANCH_F)
225     return 0;
226   
227   // Remove the branch.
228   I->eraseFromParent();
229   
230   I = MBB.end();
231
232   if (I == MBB.begin()) return 1;
233   --I;
234   if (I->getOpcode() != Alpha::COND_BRANCH_I && 
235       I->getOpcode() != Alpha::COND_BRANCH_F)
236     return 1;
237   
238   // Remove the branch.
239   I->eraseFromParent();
240   return 2;
241 }
242
243 void AlphaInstrInfo::insertNoop(MachineBasicBlock &MBB, 
244                                 MachineBasicBlock::iterator MI) const {
245   BuildMI(MBB, MI, get(Alpha::BISr), Alpha::R31).addReg(Alpha::R31)
246     .addReg(Alpha::R31);
247 }
248
249 bool AlphaInstrInfo::BlockHasNoFallThrough(MachineBasicBlock &MBB) const {
250   if (MBB.empty()) return false;
251   
252   switch (MBB.back().getOpcode()) {
253   case Alpha::RETDAG: // Return.
254   case Alpha::RETDAGp:
255   case Alpha::BR:     // Uncond branch.
256   case Alpha::JMP:  // Indirect branch.
257     return true;
258   default: return false;
259   }
260 }
261 bool AlphaInstrInfo::
262 ReverseBranchCondition(std::vector<MachineOperand> &Cond) const {
263   assert(Cond.size() == 2 && "Invalid Alpha branch opcode!");
264   Cond[0].setImm(AlphaRevCondCode(Cond[0].getImm()));
265   return false;
266 }
267