- Eliminate MCCodeEmitter's dependency on TargetMachine. It now uses MCInstrInfo
[oota-llvm.git] / lib / Target / SystemZ / SystemZInstrInfo.cpp
1 //===- SystemZInstrInfo.cpp - SystemZ Instruction Information --------------===//
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 SystemZ implementation of the TargetInstrInfo class.
11 //
12 //===----------------------------------------------------------------------===//
13
14 #include "SystemZ.h"
15 #include "SystemZInstrBuilder.h"
16 #include "SystemZInstrInfo.h"
17 #include "SystemZMachineFunctionInfo.h"
18 #include "SystemZTargetMachine.h"
19 #include "llvm/Function.h"
20 #include "llvm/CodeGen/MachineFrameInfo.h"
21 #include "llvm/CodeGen/MachineInstrBuilder.h"
22 #include "llvm/CodeGen/MachineRegisterInfo.h"
23 #include "llvm/CodeGen/PseudoSourceValue.h"
24 #include "llvm/Target/TargetRegistry.h"
25 #include "llvm/Support/ErrorHandling.h"
26
27 #define GET_INSTRINFO_CTOR
28 #define GET_INSTRINFO_MC_DESC
29 #include "SystemZGenInstrInfo.inc"
30
31 using namespace llvm;
32
33 SystemZInstrInfo::SystemZInstrInfo(SystemZTargetMachine &tm)
34   : SystemZGenInstrInfo(SystemZ::ADJCALLSTACKUP, SystemZ::ADJCALLSTACKDOWN),
35     RI(tm, *this), TM(tm) {
36 }
37
38 /// isGVStub - Return true if the GV requires an extra load to get the
39 /// real address.
40 static inline bool isGVStub(GlobalValue *GV, SystemZTargetMachine &TM) {
41   return TM.getSubtarget<SystemZSubtarget>().GVRequiresExtraLoad(GV, TM, false);
42 }
43
44 void SystemZInstrInfo::storeRegToStackSlot(MachineBasicBlock &MBB,
45                                           MachineBasicBlock::iterator MI,
46                                     unsigned SrcReg, bool isKill, int FrameIdx,
47                                            const TargetRegisterClass *RC,
48                                            const TargetRegisterInfo *TRI) const {
49   DebugLoc DL;
50   if (MI != MBB.end()) DL = MI->getDebugLoc();
51
52   unsigned Opc = 0;
53   if (RC == &SystemZ::GR32RegClass ||
54       RC == &SystemZ::ADDR32RegClass)
55     Opc = SystemZ::MOV32mr;
56   else if (RC == &SystemZ::GR64RegClass ||
57            RC == &SystemZ::ADDR64RegClass) {
58     Opc = SystemZ::MOV64mr;
59   } else if (RC == &SystemZ::FP32RegClass) {
60     Opc = SystemZ::FMOV32mr;
61   } else if (RC == &SystemZ::FP64RegClass) {
62     Opc = SystemZ::FMOV64mr;
63   } else if (RC == &SystemZ::GR64PRegClass) {
64     Opc = SystemZ::MOV64Pmr;
65   } else if (RC == &SystemZ::GR128RegClass) {
66     Opc = SystemZ::MOV128mr;
67   } else
68     llvm_unreachable("Unsupported regclass to store");
69
70   addFrameReference(BuildMI(MBB, MI, DL, get(Opc)), FrameIdx)
71     .addReg(SrcReg, getKillRegState(isKill));
72 }
73
74 void SystemZInstrInfo::loadRegFromStackSlot(MachineBasicBlock &MBB,
75                                            MachineBasicBlock::iterator MI,
76                                            unsigned DestReg, int FrameIdx,
77                                             const TargetRegisterClass *RC,
78                                             const TargetRegisterInfo *TRI) const{
79   DebugLoc DL;
80   if (MI != MBB.end()) DL = MI->getDebugLoc();
81
82   unsigned Opc = 0;
83   if (RC == &SystemZ::GR32RegClass ||
84       RC == &SystemZ::ADDR32RegClass)
85     Opc = SystemZ::MOV32rm;
86   else if (RC == &SystemZ::GR64RegClass ||
87            RC == &SystemZ::ADDR64RegClass) {
88     Opc = SystemZ::MOV64rm;
89   } else if (RC == &SystemZ::FP32RegClass) {
90     Opc = SystemZ::FMOV32rm;
91   } else if (RC == &SystemZ::FP64RegClass) {
92     Opc = SystemZ::FMOV64rm;
93   } else if (RC == &SystemZ::GR64PRegClass) {
94     Opc = SystemZ::MOV64Prm;
95   } else if (RC == &SystemZ::GR128RegClass) {
96     Opc = SystemZ::MOV128rm;
97   } else
98     llvm_unreachable("Unsupported regclass to load");
99
100   addFrameReference(BuildMI(MBB, MI, DL, get(Opc), DestReg), FrameIdx);
101 }
102
103 void SystemZInstrInfo::copyPhysReg(MachineBasicBlock &MBB,
104                                    MachineBasicBlock::iterator I, DebugLoc DL,
105                                    unsigned DestReg, unsigned SrcReg,
106                                    bool KillSrc) const {
107   unsigned Opc;
108   if (SystemZ::GR64RegClass.contains(DestReg, SrcReg))
109     Opc = SystemZ::MOV64rr;
110   else if (SystemZ::GR32RegClass.contains(DestReg, SrcReg))
111     Opc = SystemZ::MOV32rr;
112   else if (SystemZ::GR64PRegClass.contains(DestReg, SrcReg))
113     Opc = SystemZ::MOV64rrP;
114   else if (SystemZ::GR128RegClass.contains(DestReg, SrcReg))
115     Opc = SystemZ::MOV128rr;
116   else if (SystemZ::FP32RegClass.contains(DestReg, SrcReg))
117     Opc = SystemZ::FMOV32rr;
118   else if (SystemZ::FP64RegClass.contains(DestReg, SrcReg))
119     Opc = SystemZ::FMOV64rr;
120   else
121     llvm_unreachable("Impossible reg-to-reg copy");
122
123   BuildMI(MBB, I, DL, get(Opc), DestReg)
124     .addReg(SrcReg, getKillRegState(KillSrc));
125 }
126
127 unsigned SystemZInstrInfo::isLoadFromStackSlot(const MachineInstr *MI,
128                                                int &FrameIndex) const {
129   switch (MI->getOpcode()) {
130   default: break;
131   case SystemZ::MOV32rm:
132   case SystemZ::MOV32rmy:
133   case SystemZ::MOV64rm:
134   case SystemZ::MOVSX32rm8:
135   case SystemZ::MOVSX32rm16y:
136   case SystemZ::MOVSX64rm8:
137   case SystemZ::MOVSX64rm16:
138   case SystemZ::MOVSX64rm32:
139   case SystemZ::MOVZX32rm8:
140   case SystemZ::MOVZX32rm16:
141   case SystemZ::MOVZX64rm8:
142   case SystemZ::MOVZX64rm16:
143   case SystemZ::MOVZX64rm32:
144   case SystemZ::FMOV32rm:
145   case SystemZ::FMOV32rmy:
146   case SystemZ::FMOV64rm:
147   case SystemZ::FMOV64rmy:
148   case SystemZ::MOV64Prm:
149   case SystemZ::MOV64Prmy:
150   case SystemZ::MOV128rm:
151     if (MI->getOperand(1).isFI() &&
152         MI->getOperand(2).isImm() && MI->getOperand(3).isReg() &&
153         MI->getOperand(2).getImm() == 0 && MI->getOperand(3).getReg() == 0) {
154       FrameIndex = MI->getOperand(1).getIndex();
155       return MI->getOperand(0).getReg();
156     }
157     break;
158   }
159   return 0;
160 }
161
162 unsigned SystemZInstrInfo::isStoreToStackSlot(const MachineInstr *MI,
163                                               int &FrameIndex) const {
164   switch (MI->getOpcode()) {
165   default: break;
166   case SystemZ::MOV32mr:
167   case SystemZ::MOV32mry:
168   case SystemZ::MOV64mr:
169   case SystemZ::MOV32m8r:
170   case SystemZ::MOV32m8ry:
171   case SystemZ::MOV32m16r:
172   case SystemZ::MOV32m16ry:
173   case SystemZ::MOV64m8r:
174   case SystemZ::MOV64m8ry:
175   case SystemZ::MOV64m16r:
176   case SystemZ::MOV64m16ry:
177   case SystemZ::MOV64m32r:
178   case SystemZ::MOV64m32ry:
179   case SystemZ::FMOV32mr:
180   case SystemZ::FMOV32mry:
181   case SystemZ::FMOV64mr:
182   case SystemZ::FMOV64mry:
183   case SystemZ::MOV64Pmr:
184   case SystemZ::MOV64Pmry:
185   case SystemZ::MOV128mr:
186     if (MI->getOperand(0).isFI() &&
187         MI->getOperand(1).isImm() && MI->getOperand(2).isReg() &&
188         MI->getOperand(1).getImm() == 0 && MI->getOperand(2).getReg() == 0) {
189       FrameIndex = MI->getOperand(0).getIndex();
190       return MI->getOperand(3).getReg();
191     }
192     break;
193   }
194   return 0;
195 }
196
197 bool SystemZInstrInfo::
198 ReverseBranchCondition(SmallVectorImpl<MachineOperand> &Cond) const {
199   assert(Cond.size() == 1 && "Invalid Xbranch condition!");
200
201   SystemZCC::CondCodes CC = static_cast<SystemZCC::CondCodes>(Cond[0].getImm());
202   Cond[0].setImm(getOppositeCondition(CC));
203   return false;
204 }
205
206 bool SystemZInstrInfo::isUnpredicatedTerminator(const MachineInstr *MI) const {
207   const MCInstrDesc &MCID = MI->getDesc();
208   if (!MCID.isTerminator()) return false;
209
210   // Conditional branch is a special case.
211   if (MCID.isBranch() && !MCID.isBarrier())
212     return true;
213   if (!MCID.isPredicable())
214     return true;
215   return !isPredicated(MI);
216 }
217
218 bool SystemZInstrInfo::AnalyzeBranch(MachineBasicBlock &MBB,
219                                      MachineBasicBlock *&TBB,
220                                      MachineBasicBlock *&FBB,
221                                      SmallVectorImpl<MachineOperand> &Cond,
222                                      bool AllowModify) const {
223   // Start from the bottom of the block and work up, examining the
224   // terminator instructions.
225   MachineBasicBlock::iterator I = MBB.end();
226   while (I != MBB.begin()) {
227     --I;
228     if (I->isDebugValue())
229       continue;
230     // Working from the bottom, when we see a non-terminator
231     // instruction, we're done.
232     if (!isUnpredicatedTerminator(I))
233       break;
234
235     // A terminator that isn't a branch can't easily be handled
236     // by this analysis.
237     if (!I->getDesc().isBranch())
238       return true;
239
240     // Handle unconditional branches.
241     if (I->getOpcode() == SystemZ::JMP) {
242       if (!AllowModify) {
243         TBB = I->getOperand(0).getMBB();
244         continue;
245       }
246
247       // If the block has any instructions after a JMP, delete them.
248       while (llvm::next(I) != MBB.end())
249         llvm::next(I)->eraseFromParent();
250       Cond.clear();
251       FBB = 0;
252
253       // Delete the JMP if it's equivalent to a fall-through.
254       if (MBB.isLayoutSuccessor(I->getOperand(0).getMBB())) {
255         TBB = 0;
256         I->eraseFromParent();
257         I = MBB.end();
258         continue;
259       }
260
261       // TBB is used to indicate the unconditinal destination.
262       TBB = I->getOperand(0).getMBB();
263       continue;
264     }
265
266     // Handle conditional branches.
267     SystemZCC::CondCodes BranchCode = getCondFromBranchOpc(I->getOpcode());
268     if (BranchCode == SystemZCC::INVALID)
269       return true;  // Can't handle indirect branch.
270
271     // Working from the bottom, handle the first conditional branch.
272     if (Cond.empty()) {
273       FBB = TBB;
274       TBB = I->getOperand(0).getMBB();
275       Cond.push_back(MachineOperand::CreateImm(BranchCode));
276       continue;
277     }
278
279     // Handle subsequent conditional branches. Only handle the case where all
280     // conditional branches branch to the same destination.
281     assert(Cond.size() == 1);
282     assert(TBB);
283
284     // Only handle the case where all conditional branches branch to
285     // the same destination.
286     if (TBB != I->getOperand(0).getMBB())
287       return true;
288
289     SystemZCC::CondCodes OldBranchCode = (SystemZCC::CondCodes)Cond[0].getImm();
290     // If the conditions are the same, we can leave them alone.
291     if (OldBranchCode == BranchCode)
292       continue;
293
294     return true;
295   }
296
297   return false;
298 }
299
300 unsigned SystemZInstrInfo::RemoveBranch(MachineBasicBlock &MBB) const {
301   MachineBasicBlock::iterator I = MBB.end();
302   unsigned Count = 0;
303
304   while (I != MBB.begin()) {
305     --I;
306     if (I->isDebugValue())
307       continue;
308     if (I->getOpcode() != SystemZ::JMP &&
309         getCondFromBranchOpc(I->getOpcode()) == SystemZCC::INVALID)
310       break;
311     // Remove the branch.
312     I->eraseFromParent();
313     I = MBB.end();
314     ++Count;
315   }
316
317   return Count;
318 }
319
320 unsigned
321 SystemZInstrInfo::InsertBranch(MachineBasicBlock &MBB, MachineBasicBlock *TBB,
322                                MachineBasicBlock *FBB,
323                                const SmallVectorImpl<MachineOperand> &Cond,
324                                DebugLoc DL) const {
325   // Shouldn't be a fall through.
326   assert(TBB && "InsertBranch must not be told to insert a fallthrough");
327   assert((Cond.size() == 1 || Cond.size() == 0) &&
328          "SystemZ branch conditions have one component!");
329
330   if (Cond.empty()) {
331     // Unconditional branch?
332     assert(!FBB && "Unconditional branch with multiple successors!");
333     BuildMI(&MBB, DL, get(SystemZ::JMP)).addMBB(TBB);
334     return 1;
335   }
336
337   // Conditional branch.
338   unsigned Count = 0;
339   SystemZCC::CondCodes CC = (SystemZCC::CondCodes)Cond[0].getImm();
340   BuildMI(&MBB, DL, getBrCond(CC)).addMBB(TBB);
341   ++Count;
342
343   if (FBB) {
344     // Two-way Conditional branch. Insert the second branch.
345     BuildMI(&MBB, DL, get(SystemZ::JMP)).addMBB(FBB);
346     ++Count;
347   }
348   return Count;
349 }
350
351 const MCInstrDesc&
352 SystemZInstrInfo::getBrCond(SystemZCC::CondCodes CC) const {
353   switch (CC) {
354   default:
355    llvm_unreachable("Unknown condition code!");
356   case SystemZCC::O:   return get(SystemZ::JO);
357   case SystemZCC::H:   return get(SystemZ::JH);
358   case SystemZCC::NLE: return get(SystemZ::JNLE);
359   case SystemZCC::L:   return get(SystemZ::JL);
360   case SystemZCC::NHE: return get(SystemZ::JNHE);
361   case SystemZCC::LH:  return get(SystemZ::JLH);
362   case SystemZCC::NE:  return get(SystemZ::JNE);
363   case SystemZCC::E:   return get(SystemZ::JE);
364   case SystemZCC::NLH: return get(SystemZ::JNLH);
365   case SystemZCC::HE:  return get(SystemZ::JHE);
366   case SystemZCC::NL:  return get(SystemZ::JNL);
367   case SystemZCC::LE:  return get(SystemZ::JLE);
368   case SystemZCC::NH:  return get(SystemZ::JNH);
369   case SystemZCC::NO:  return get(SystemZ::JNO);
370   }
371 }
372
373 SystemZCC::CondCodes
374 SystemZInstrInfo::getCondFromBranchOpc(unsigned Opc) const {
375   switch (Opc) {
376   default:            return SystemZCC::INVALID;
377   case SystemZ::JO:   return SystemZCC::O;
378   case SystemZ::JH:   return SystemZCC::H;
379   case SystemZ::JNLE: return SystemZCC::NLE;
380   case SystemZ::JL:   return SystemZCC::L;
381   case SystemZ::JNHE: return SystemZCC::NHE;
382   case SystemZ::JLH:  return SystemZCC::LH;
383   case SystemZ::JNE:  return SystemZCC::NE;
384   case SystemZ::JE:   return SystemZCC::E;
385   case SystemZ::JNLH: return SystemZCC::NLH;
386   case SystemZ::JHE:  return SystemZCC::HE;
387   case SystemZ::JNL:  return SystemZCC::NL;
388   case SystemZ::JLE:  return SystemZCC::LE;
389   case SystemZ::JNH:  return SystemZCC::NH;
390   case SystemZ::JNO:  return SystemZCC::NO;
391   }
392 }
393
394 SystemZCC::CondCodes
395 SystemZInstrInfo::getOppositeCondition(SystemZCC::CondCodes CC) const {
396   switch (CC) {
397   default:
398     llvm_unreachable("Invalid condition!");
399   case SystemZCC::O:   return SystemZCC::NO;
400   case SystemZCC::H:   return SystemZCC::NH;
401   case SystemZCC::NLE: return SystemZCC::LE;
402   case SystemZCC::L:   return SystemZCC::NL;
403   case SystemZCC::NHE: return SystemZCC::HE;
404   case SystemZCC::LH:  return SystemZCC::NLH;
405   case SystemZCC::NE:  return SystemZCC::E;
406   case SystemZCC::E:   return SystemZCC::NE;
407   case SystemZCC::NLH: return SystemZCC::LH;
408   case SystemZCC::HE:  return SystemZCC::NHE;
409   case SystemZCC::NL:  return SystemZCC::L;
410   case SystemZCC::LE:  return SystemZCC::NLE;
411   case SystemZCC::NH:  return SystemZCC::H;
412   case SystemZCC::NO:  return SystemZCC::O;
413   }
414 }
415
416 const MCInstrDesc&
417 SystemZInstrInfo::getLongDispOpc(unsigned Opc) const {
418   switch (Opc) {
419   default:
420     llvm_unreachable("Don't have long disp version of this instruction");
421   case SystemZ::MOV32mr:   return get(SystemZ::MOV32mry);
422   case SystemZ::MOV32rm:   return get(SystemZ::MOV32rmy);
423   case SystemZ::MOVSX32rm16: return get(SystemZ::MOVSX32rm16y);
424   case SystemZ::MOV32m8r:  return get(SystemZ::MOV32m8ry);
425   case SystemZ::MOV32m16r: return get(SystemZ::MOV32m16ry);
426   case SystemZ::MOV64m8r:  return get(SystemZ::MOV64m8ry);
427   case SystemZ::MOV64m16r: return get(SystemZ::MOV64m16ry);
428   case SystemZ::MOV64m32r: return get(SystemZ::MOV64m32ry);
429   case SystemZ::MOV8mi:    return get(SystemZ::MOV8miy);
430   case SystemZ::MUL32rm:   return get(SystemZ::MUL32rmy);
431   case SystemZ::CMP32rm:   return get(SystemZ::CMP32rmy);
432   case SystemZ::UCMP32rm:  return get(SystemZ::UCMP32rmy);
433   case SystemZ::FMOV32mr:  return get(SystemZ::FMOV32mry);
434   case SystemZ::FMOV64mr:  return get(SystemZ::FMOV64mry);
435   case SystemZ::FMOV32rm:  return get(SystemZ::FMOV32rmy);
436   case SystemZ::FMOV64rm:  return get(SystemZ::FMOV64rmy);
437   case SystemZ::MOV64Pmr:  return get(SystemZ::MOV64Pmry);
438   case SystemZ::MOV64Prm:  return get(SystemZ::MOV64Prmy);
439   }
440 }
441
442 MCInstrInfo *createSystemZMCInstrInfo() {
443   MCInstrInfo *X = new MCInstrInfo();
444   InitSystemZMCInstrInfo(X);
445   return X;
446 }
447
448 extern "C" void LLVMInitializeSystemZMCInstrInfo() {
449   TargetRegistry::RegisterMCInstrInfo(TheSystemZTarget,
450                                       createSystemZMCInstrInfo);
451 }