OSDN Git Service

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