Added Branch Analysis support
[oota-llvm.git] / lib / Target / Mips / MipsInstrInfo.cpp
1 //===- MipsInstrInfo.cpp - Mips Instruction Information ---------*- C++ -*-===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file was developed by Bruno Cardoso Lopes and is distributed under the 
6 // University of Illinois Open Source License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 // This file contains the Mips implementation of the TargetInstrInfo class.
11 //
12 //===----------------------------------------------------------------------===//
13
14 #include "Mips.h"
15 #include "MipsInstrInfo.h"
16 #include "llvm/CodeGen/MachineInstrBuilder.h"
17 #include "MipsGenInstrInfo.inc"
18
19 using namespace llvm;
20
21 // TODO: Add the subtarget support on this constructor
22 MipsInstrInfo::MipsInstrInfo(MipsTargetMachine &tm)
23   : TargetInstrInfo(MipsInsts, sizeof(MipsInsts)/sizeof(MipsInsts[0])),
24     TM(tm), RI(*this) {}
25
26 static bool isZeroImm(const MachineOperand &op) {
27   return op.isImmediate() && op.getImmedValue() == 0;
28 }
29
30 /// Return true if the instruction is a register to register move and
31 /// leave the source and dest operands in the passed parameters.
32 bool MipsInstrInfo::
33 isMoveInstr(const MachineInstr &MI, unsigned &SrcReg, unsigned &DstReg) const 
34 {
35   //  addu  $dst, $src, $zero || addu  $dst, $zero, $src
36   //  or    $dst, $src, $zero || or    $dst, $zero, $src
37   if ((MI.getOpcode() == Mips::ADDu) || (MI.getOpcode() == Mips::OR))
38   {
39     if (MI.getOperand(1).getReg() == Mips::ZERO) {
40       DstReg = MI.getOperand(0).getReg();
41       SrcReg = MI.getOperand(2).getReg();
42       return true;
43     } else if (MI.getOperand(2).getReg() == Mips::ZERO) {
44       DstReg = MI.getOperand(0).getReg();
45       SrcReg = MI.getOperand(1).getReg();
46       return true;
47     }
48   }
49
50   //  addiu $dst, $src, 0
51   if (MI.getOpcode() == Mips::ADDiu) 
52   {
53     if ((MI.getOperand(1).isRegister()) && (isZeroImm(MI.getOperand(2)))) {
54       DstReg = MI.getOperand(0).getReg();
55       SrcReg = MI.getOperand(1).getReg();
56       return true;
57     }
58   }
59   return false;
60 }
61
62 /// isLoadFromStackSlot - If the specified machine instruction is a direct
63 /// load from a stack slot, return the virtual or physical register number of
64 /// the destination along with the FrameIndex of the loaded stack slot.  If
65 /// not, return 0.  This predicate must return 0 if the instruction has
66 /// any side effects other than loading from the stack slot.
67 unsigned MipsInstrInfo::
68 isLoadFromStackSlot(MachineInstr *MI, int &FrameIndex) const 
69 {
70   if (MI->getOpcode() == Mips::LW) 
71   {
72     if ((MI->getOperand(2).isFrameIndex()) && // is a stack slot
73         (MI->getOperand(1).isImmediate()) &&  // the imm is zero
74         (isZeroImm(MI->getOperand(1)))) 
75     {
76       FrameIndex = MI->getOperand(2).getFrameIndex();
77       return MI->getOperand(0).getReg();
78     }
79   }
80
81   return 0;
82 }
83
84 /// isStoreToStackSlot - If the specified machine instruction is a direct
85 /// store to a stack slot, return the virtual or physical register number of
86 /// the source reg along with the FrameIndex of the loaded stack slot.  If
87 /// not, return 0.  This predicate must return 0 if the instruction has
88 /// any side effects other than storing to the stack slot.
89 unsigned MipsInstrInfo::
90 isStoreToStackSlot(MachineInstr *MI, int &FrameIndex) const 
91 {
92   if (MI->getOpcode() == Mips::SW) {
93     if ((MI->getOperand(0).isFrameIndex()) && // is a stack slot
94         (MI->getOperand(1).isImmediate()) &&  // the imm is zero
95         (isZeroImm(MI->getOperand(1)))) 
96     {
97       FrameIndex = MI->getOperand(0).getFrameIndex();
98       return MI->getOperand(2).getReg();
99     }
100   }
101   return 0;
102 }
103
104 /// insertNoop - If data hazard condition is found insert the target nop
105 /// instruction.
106 void MipsInstrInfo::
107 insertNoop(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI) const 
108 {
109   BuildMI(MBB, MI, get(Mips::NOP));
110 }
111
112 //===----------------------------------------------------------------------===//
113 // Branch Analysis
114 //===----------------------------------------------------------------------===//
115
116 /// GetCondFromBranchOpc - Return the Mips CC that matches 
117 /// the correspondent Branch instruction opcode.
118 static Mips::CondCode GetCondFromBranchOpc(unsigned BrOpc) 
119 {
120   switch (BrOpc) {
121   default: return Mips::COND_INVALID;
122   case Mips::BEQ  : return Mips::COND_E;
123   case Mips::BNE  : return Mips::COND_NE;
124   case Mips::BGTZ : return Mips::COND_GZ;
125   case Mips::BGEZ : return Mips::COND_GEZ;
126   case Mips::BLTZ : return Mips::COND_LZ;
127   case Mips::BLEZ : return Mips::COND_LEZ;
128   }
129 }
130
131 /// GetCondBranchFromCond - Return the Branch instruction
132 /// opcode that matches the cc.
133 unsigned Mips::GetCondBranchFromCond(Mips::CondCode CC) 
134 {
135   switch (CC) {
136   default: assert(0 && "Illegal condition code!");
137   case Mips::COND_E   : return Mips::BEQ;
138   case Mips::COND_NE  : return Mips::BNE;
139   case Mips::COND_GZ  : return Mips::BGTZ;
140   case Mips::COND_GEZ : return Mips::BGEZ;
141   case Mips::COND_LZ  : return Mips::BLTZ;
142   case Mips::COND_LEZ : return Mips::BLEZ;
143   }
144 }
145
146 /// GetOppositeBranchCondition - Return the inverse of the specified 
147 /// condition, e.g. turning COND_E to COND_NE.
148 Mips::CondCode Mips::GetOppositeBranchCondition(Mips::CondCode CC) 
149 {
150   switch (CC) {
151   default: assert(0 && "Illegal condition code!");
152   case Mips::COND_E   : return Mips::COND_NE;
153   case Mips::COND_NE  : return Mips::COND_E;
154   case Mips::COND_GZ  : return Mips::COND_LEZ;
155   case Mips::COND_GEZ : return Mips::COND_LZ;
156   case Mips::COND_LZ  : return Mips::COND_GEZ;
157   case Mips::COND_LEZ : return Mips::COND_GZ;
158   }
159 }
160
161 bool MipsInstrInfo::AnalyzeBranch(MachineBasicBlock &MBB, 
162                                   MachineBasicBlock *&TBB,
163                                   MachineBasicBlock *&FBB,
164                                   std::vector<MachineOperand> &Cond) const 
165 {
166   // If the block has no terminators, it just falls into the block after it.
167   MachineBasicBlock::iterator I = MBB.end();
168   if (I == MBB.begin() || !isUnpredicatedTerminator(--I))
169     return false;
170   
171   // Get the last instruction in the block.
172   MachineInstr *LastInst = I;
173   
174   // If there is only one terminator instruction, process it.
175   unsigned LastOpc = LastInst->getOpcode();
176   if (I == MBB.begin() || !isUnpredicatedTerminator(--I)) {
177     if (!isBranch(LastInst->getOpcode()))
178       return true;
179
180     // Unconditional branch
181     if (LastOpc == Mips::J) {
182       TBB = LastInst->getOperand(0).getMachineBasicBlock();
183       return false;
184     }
185
186     Mips::CondCode BranchCode = GetCondFromBranchOpc(LastInst->getOpcode());
187     if (BranchCode == Mips::COND_INVALID)
188       return true;  // Can't handle indirect branch.
189
190     // Conditional branch
191     // Block ends with fall-through condbranch.
192     if (LastOpc != Mips::COND_INVALID) {
193       int LastNumOp = LastInst->getNumOperands();
194
195       TBB = LastInst->getOperand(LastNumOp-1).getMachineBasicBlock();
196       Cond.push_back(MachineOperand::CreateImm(BranchCode));
197
198       for (int i=0; i<LastNumOp-1; i++) {
199         Cond.push_back(LastInst->getOperand(i));
200       }
201
202       return false;
203     }
204   }
205   
206   // Get the instruction before it if it is a terminator.
207   MachineInstr *SecondLastInst = I;
208   
209   // If there are three terminators, we don't know what sort of block this is.
210   if (SecondLastInst && I != MBB.begin() && isUnpredicatedTerminator(--I))
211     return true;
212
213   // If the block ends with Mips::J and a Mips::BNE/Mips::BEQ, handle it.
214   unsigned SecondLastOpc    = SecondLastInst->getOpcode();
215   Mips::CondCode BranchCode = GetCondFromBranchOpc(SecondLastOpc);
216
217   if (SecondLastOpc != Mips::COND_INVALID && LastOpc == Mips::J) {
218     int SecondNumOp = SecondLastInst->getNumOperands();
219
220     TBB = SecondLastInst->getOperand(SecondNumOp-1).getMachineBasicBlock();
221     Cond.push_back(MachineOperand::CreateImm(BranchCode));
222
223     for (int i=0; i<SecondNumOp-1; i++) {
224       Cond.push_back(SecondLastInst->getOperand(i));
225     }
226
227     FBB = LastInst->getOperand(0).getMachineBasicBlock();
228     return false;
229   }
230   
231   // If the block ends with two unconditional branches, handle it. The last 
232   // one is not executed, so remove it.
233   if ((SecondLastOpc == Mips::J) && (LastOpc == Mips::J)) {
234     TBB = SecondLastInst->getOperand(0).getMachineBasicBlock();
235     I = LastInst;
236     I->eraseFromParent();
237     return false;
238   }
239
240   // Otherwise, can't handle this.
241   return true;
242 }
243
244 unsigned MipsInstrInfo::
245 InsertBranch(MachineBasicBlock &MBB, MachineBasicBlock *TBB, 
246              MachineBasicBlock *FBB, const std::vector<MachineOperand> &Cond)
247              const
248 {
249   // Shouldn't be a fall through.
250   assert(TBB && "InsertBranch must not be told to insert a fallthrough");
251   assert((Cond.size() == 3 || Cond.size() == 2 || Cond.size() == 0) &&
252          "Mips branch conditions can have two|three components!");
253
254   if (FBB == 0) { // One way branch.
255     if (Cond.empty()) {
256       // Unconditional branch?
257       BuildMI(&MBB, get(Mips::J)).addMBB(TBB);
258     } else {
259       // Conditional branch.
260       unsigned Opc = GetCondBranchFromCond((Mips::CondCode)Cond[0].getImm());
261       const TargetInstrDescriptor &TID = get(Opc);
262
263       if (TID.numOperands == 3)
264         BuildMI(&MBB, TID).addReg(Cond[1].getReg())
265                           .addReg(Cond[2].getReg())
266                           .addMBB(TBB);
267       else
268         BuildMI(&MBB, TID).addReg(Cond[1].getReg())
269                           .addMBB(TBB);
270
271     }                             
272     return 1;
273   }
274   
275   // Two-way Conditional branch.
276   unsigned Opc = GetCondBranchFromCond((Mips::CondCode)Cond[0].getImm());
277   const TargetInstrDescriptor &TID = get(Opc);
278
279   if (TID.numOperands == 3)
280     BuildMI(&MBB, TID).addReg(Cond[1].getReg())
281                       .addReg(Cond[2].getReg())
282                       .addMBB(TBB);
283   else
284     BuildMI(&MBB, TID).addReg(Cond[1].getReg())
285                       .addMBB(TBB);
286
287   BuildMI(&MBB, get(Mips::J)).addMBB(FBB);
288   return 2;
289 }
290
291 unsigned MipsInstrInfo::
292 RemoveBranch(MachineBasicBlock &MBB) const 
293 {
294   MachineBasicBlock::iterator I = MBB.end();
295   if (I == MBB.begin()) return 0;
296   --I;
297   if (I->getOpcode() != Mips::J && 
298       GetCondFromBranchOpc(I->getOpcode()) == Mips::COND_INVALID)
299     return 0;
300   
301   // Remove the branch.
302   I->eraseFromParent();
303   
304   I = MBB.end();
305   
306   if (I == MBB.begin()) return 1;
307   --I;
308   if (GetCondFromBranchOpc(I->getOpcode()) == Mips::COND_INVALID)
309     return 1;
310   
311   // Remove the branch.
312   I->eraseFromParent();
313   return 2;
314 }
315
316 /// BlockHasNoFallThrough - Analyse if MachineBasicBlock does not
317 /// fall-through into its successor block.
318 bool MipsInstrInfo::
319 BlockHasNoFallThrough(MachineBasicBlock &MBB) const 
320 {
321   if (MBB.empty()) return false;
322   
323   switch (MBB.back().getOpcode()) {
324   case Mips::RET:     // Return.
325   case Mips::JR:      // Indirect branch.
326   case Mips::J:       // Uncond branch.
327     return true;
328   default: return false;
329   }
330 }
331
332 /// ReverseBranchCondition - Return the inverse opcode of the 
333 /// specified Branch instruction.
334 bool MipsInstrInfo::
335 ReverseBranchCondition(std::vector<MachineOperand> &Cond) const 
336 {
337   assert( (Cond.size() == 3 || Cond.size() == 2) && 
338           "Invalid Mips branch condition!");
339   Cond[0].setImm(GetOppositeBranchCondition((Mips::CondCode)Cond[0].getImm()));
340   return false;
341 }
342
343