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