Matches MachineInstr changes.
[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 was developed by the LLVM research group and is distributed under
6 // the University of Illinois Open Source 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/CodeGen/MachineInstrBuilder.h"
18 #include <iostream>
19 using namespace llvm;
20
21 AlphaInstrInfo::AlphaInstrInfo()
22   : TargetInstrInfo(AlphaInsts, sizeof(AlphaInsts)/sizeof(AlphaInsts[0])),
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 void 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, Alpha::BR, 1).addMBB(TBB);
114     else                // Conditional branch
115       if (isAlphaIntCondCode(Cond[0].getImm()))
116         BuildMI(&MBB, Alpha::COND_BRANCH_I, 3)
117           .addImm(Cond[0].getImm()).addReg(Cond[1].getReg()).addMBB(TBB);
118       else
119         BuildMI(&MBB, Alpha::COND_BRANCH_F, 3)
120           .addImm(Cond[0].getImm()).addReg(Cond[1].getReg()).addMBB(TBB);
121     return;
122   }
123   
124   // Two-way Conditional Branch.
125   if (isAlphaIntCondCode(Cond[0].getImm()))
126     BuildMI(&MBB, Alpha::COND_BRANCH_I, 3)
127       .addImm(Cond[0].getImm()).addReg(Cond[1].getReg()).addMBB(TBB);
128   else
129     BuildMI(&MBB, Alpha::COND_BRANCH_F, 3)
130       .addImm(Cond[0].getImm()).addReg(Cond[1].getReg()).addMBB(TBB);
131   BuildMI(&MBB, Alpha::BR, 1).addMBB(FBB);
132 }
133
134 static unsigned AlphaRevCondCode(unsigned Opcode) {
135   switch (Opcode) {
136   case Alpha::BEQ: return Alpha::BNE;
137   case Alpha::BNE: return Alpha::BEQ;
138   case Alpha::BGE: return Alpha::BLT;
139   case Alpha::BGT: return Alpha::BLE;
140   case Alpha::BLE: return Alpha::BGT;
141   case Alpha::BLT: return Alpha::BGE;
142   case Alpha::BLBC: return Alpha::BLBS;
143   case Alpha::BLBS: return Alpha::BLBC;
144   case Alpha::FBEQ: return Alpha::FBNE;
145   case Alpha::FBNE: return Alpha::FBEQ;
146   case Alpha::FBGE: return Alpha::FBLT;
147   case Alpha::FBGT: return Alpha::FBLE;
148   case Alpha::FBLE: return Alpha::FBGT;
149   case Alpha::FBLT: return Alpha::FBGE;
150   default:
151     assert(0 && "Unknown opcode");
152   }
153 }
154
155 // Branch analysis.
156 bool AlphaInstrInfo::AnalyzeBranch(MachineBasicBlock &MBB,MachineBasicBlock *&TBB,
157                                  MachineBasicBlock *&FBB,
158                                  std::vector<MachineOperand> &Cond) const {
159   // If the block has no terminators, it just falls into the block after it.
160   MachineBasicBlock::iterator I = MBB.end();
161   if (I == MBB.begin() || !isTerminatorInstr((--I)->getOpcode()))
162     return false;
163
164   // Get the last instruction in the block.
165   MachineInstr *LastInst = I;
166   
167   // If there is only one terminator instruction, process it.
168   if (I == MBB.begin() || !isTerminatorInstr((--I)->getOpcode())) {
169     if (LastInst->getOpcode() == Alpha::BR) {
170       TBB = LastInst->getOperand(0).getMachineBasicBlock();
171       return false;
172     } else if (LastInst->getOpcode() == Alpha::COND_BRANCH_I ||
173                LastInst->getOpcode() == Alpha::COND_BRANCH_F) {
174       // Block ends with fall-through condbranch.
175       TBB = LastInst->getOperand(2).getMachineBasicBlock();
176       Cond.push_back(LastInst->getOperand(0));
177       Cond.push_back(LastInst->getOperand(1));
178       return false;
179     }
180     // Otherwise, don't know what this is.
181     return true;
182   }
183   
184   // Get the instruction before it if it's a terminator.
185   MachineInstr *SecondLastInst = I;
186
187   // If there are three terminators, we don't know what sort of block this is.
188   if (SecondLastInst && I != MBB.begin() &&
189       isTerminatorInstr((--I)->getOpcode()))
190     return true;
191   
192   // If the block ends with Alpha::BR and Alpha::COND_BRANCH_*, handle it.
193   if ((SecondLastInst->getOpcode() == Alpha::COND_BRANCH_I ||
194       SecondLastInst->getOpcode() == Alpha::COND_BRANCH_F) && 
195       LastInst->getOpcode() == Alpha::BR) {
196     TBB =  SecondLastInst->getOperand(2).getMachineBasicBlock();
197     Cond.push_back(SecondLastInst->getOperand(0));
198     Cond.push_back(SecondLastInst->getOperand(1));
199     FBB = LastInst->getOperand(0).getMachineBasicBlock();
200     return false;
201   }
202   
203   // Otherwise, can't handle this.
204   return true;
205 }
206
207 void AlphaInstrInfo::RemoveBranch(MachineBasicBlock &MBB) const {
208   MachineBasicBlock::iterator I = MBB.end();
209   if (I == MBB.begin()) return;
210   --I;
211   if (I->getOpcode() != Alpha::BR && 
212       I->getOpcode() != Alpha::COND_BRANCH_I &&
213       I->getOpcode() != Alpha::COND_BRANCH_F)
214     return;
215   
216   // Remove the branch.
217   I->eraseFromParent();
218   
219   I = MBB.end();
220
221   if (I == MBB.begin()) return;
222   --I;
223   if (I->getOpcode() != Alpha::COND_BRANCH_I && 
224       I->getOpcode() != Alpha::COND_BRANCH_F)
225     return;
226   
227   // Remove the branch.
228   I->eraseFromParent();
229 }
230
231 void AlphaInstrInfo::insertNoop(MachineBasicBlock &MBB, 
232                                 MachineBasicBlock::iterator MI) const {
233   BuildMI(MBB, MI, Alpha::BISr, 2, Alpha::R31).addReg(Alpha::R31)
234     .addReg(Alpha::R31);
235 }
236
237 bool AlphaInstrInfo::BlockHasNoFallThrough(MachineBasicBlock &MBB) const {
238   if (MBB.empty()) return false;
239   
240   switch (MBB.back().getOpcode()) {
241   case Alpha::BR:     // Uncond branch.
242   case Alpha::JMP:  // Indirect branch.
243     return true;
244   default: return false;
245   }
246 }
247 bool AlphaInstrInfo::
248 ReverseBranchCondition(std::vector<MachineOperand> &Cond) const {
249   assert(Cond.size() == 2 && "Invalid Alpha branch opcode!");
250   Cond[0].setImm(AlphaRevCondCode(Cond[0].getImm()));
251   return false;
252 }
253