blob: 5339bf14ac7ea653a7acdda1f509e48146f661ab [file] [log] [blame]
Ulrich Weigand5f613df2013-05-06 16:15:19 +00001//===-- 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 "SystemZInstrInfo.h"
15#include "SystemZInstrBuilder.h"
Richard Sandiford312425f2013-05-20 14:23:08 +000016#include "llvm/Target/TargetMachine.h"
Ulrich Weigand5f613df2013-05-06 16:15:19 +000017
18#define GET_INSTRINFO_CTOR
19#define GET_INSTRMAP_INFO
20#include "SystemZGenInstrInfo.inc"
21
22using namespace llvm;
23
24SystemZInstrInfo::SystemZInstrInfo(SystemZTargetMachine &tm)
25 : SystemZGenInstrInfo(SystemZ::ADJCALLSTACKDOWN, SystemZ::ADJCALLSTACKUP),
26 RI(tm, *this) {
27}
28
29// MI is a 128-bit load or store. Split it into two 64-bit loads or stores,
30// each having the opcode given by NewOpcode.
31void SystemZInstrInfo::splitMove(MachineBasicBlock::iterator MI,
32 unsigned NewOpcode) const {
33 MachineBasicBlock *MBB = MI->getParent();
34 MachineFunction &MF = *MBB->getParent();
35
36 // Get two load or store instructions. Use the original instruction for one
37 // of them (arbitarily the second here) and create a clone for the other.
38 MachineInstr *EarlierMI = MF.CloneMachineInstr(MI);
39 MBB->insert(MI, EarlierMI);
40
41 // Set up the two 64-bit registers.
42 MachineOperand &HighRegOp = EarlierMI->getOperand(0);
43 MachineOperand &LowRegOp = MI->getOperand(0);
44 HighRegOp.setReg(RI.getSubReg(HighRegOp.getReg(), SystemZ::subreg_high));
45 LowRegOp.setReg(RI.getSubReg(LowRegOp.getReg(), SystemZ::subreg_low));
46
47 // The address in the first (high) instruction is already correct.
48 // Adjust the offset in the second (low) instruction.
49 MachineOperand &HighOffsetOp = EarlierMI->getOperand(2);
50 MachineOperand &LowOffsetOp = MI->getOperand(2);
51 LowOffsetOp.setImm(LowOffsetOp.getImm() + 8);
52
53 // Set the opcodes.
54 unsigned HighOpcode = getOpcodeForOffset(NewOpcode, HighOffsetOp.getImm());
55 unsigned LowOpcode = getOpcodeForOffset(NewOpcode, LowOffsetOp.getImm());
56 assert(HighOpcode && LowOpcode && "Both offsets should be in range");
57
58 EarlierMI->setDesc(get(HighOpcode));
59 MI->setDesc(get(LowOpcode));
60}
61
62// Split ADJDYNALLOC instruction MI.
63void SystemZInstrInfo::splitAdjDynAlloc(MachineBasicBlock::iterator MI) const {
64 MachineBasicBlock *MBB = MI->getParent();
65 MachineFunction &MF = *MBB->getParent();
66 MachineFrameInfo *MFFrame = MF.getFrameInfo();
67 MachineOperand &OffsetMO = MI->getOperand(2);
68
69 uint64_t Offset = (MFFrame->getMaxCallFrameSize() +
70 SystemZMC::CallFrameSize +
71 OffsetMO.getImm());
72 unsigned NewOpcode = getOpcodeForOffset(SystemZ::LA, Offset);
73 assert(NewOpcode && "No support for huge argument lists yet");
74 MI->setDesc(get(NewOpcode));
75 OffsetMO.setImm(Offset);
76}
77
78// If MI is a simple load or store for a frame object, return the register
79// it loads or stores and set FrameIndex to the index of the frame object.
80// Return 0 otherwise.
81//
82// Flag is SimpleBDXLoad for loads and SimpleBDXStore for stores.
83static int isSimpleMove(const MachineInstr *MI, int &FrameIndex, int Flag) {
84 const MCInstrDesc &MCID = MI->getDesc();
85 if ((MCID.TSFlags & Flag) &&
86 MI->getOperand(1).isFI() &&
87 MI->getOperand(2).getImm() == 0 &&
88 MI->getOperand(3).getReg() == 0) {
89 FrameIndex = MI->getOperand(1).getIndex();
90 return MI->getOperand(0).getReg();
91 }
92 return 0;
93}
94
95unsigned SystemZInstrInfo::isLoadFromStackSlot(const MachineInstr *MI,
96 int &FrameIndex) const {
97 return isSimpleMove(MI, FrameIndex, SystemZII::SimpleBDXLoad);
98}
99
100unsigned SystemZInstrInfo::isStoreToStackSlot(const MachineInstr *MI,
101 int &FrameIndex) const {
102 return isSimpleMove(MI, FrameIndex, SystemZII::SimpleBDXStore);
103}
104
105bool SystemZInstrInfo::AnalyzeBranch(MachineBasicBlock &MBB,
106 MachineBasicBlock *&TBB,
107 MachineBasicBlock *&FBB,
108 SmallVectorImpl<MachineOperand> &Cond,
109 bool AllowModify) const {
110 // Most of the code and comments here are boilerplate.
111
112 // Start from the bottom of the block and work up, examining the
113 // terminator instructions.
114 MachineBasicBlock::iterator I = MBB.end();
115 while (I != MBB.begin()) {
116 --I;
117 if (I->isDebugValue())
118 continue;
119
120 // Working from the bottom, when we see a non-terminator instruction, we're
121 // done.
122 if (!isUnpredicatedTerminator(I))
123 break;
124
125 // A terminator that isn't a branch can't easily be handled by this
126 // analysis.
Richard Sandiford53c9efd2013-05-28 10:13:54 +0000127 if (!I->isBranch())
Ulrich Weigand5f613df2013-05-06 16:15:19 +0000128 return true;
129
130 // Can't handle indirect branches.
Richard Sandiford53c9efd2013-05-28 10:13:54 +0000131 SystemZII::Branch Branch(getBranchInfo(I));
132 if (!Branch.Target->isMBB())
Ulrich Weigand5f613df2013-05-06 16:15:19 +0000133 return true;
134
Richard Sandiford0fb90ab2013-05-28 10:41:11 +0000135 // Punt on compound branches.
136 if (Branch.Type != SystemZII::BranchNormal)
137 return true;
138
Richard Sandiford53c9efd2013-05-28 10:13:54 +0000139 if (Branch.CCMask == SystemZ::CCMASK_ANY) {
Ulrich Weigand5f613df2013-05-06 16:15:19 +0000140 // Handle unconditional branches.
141 if (!AllowModify) {
Richard Sandiford53c9efd2013-05-28 10:13:54 +0000142 TBB = Branch.Target->getMBB();
Ulrich Weigand5f613df2013-05-06 16:15:19 +0000143 continue;
144 }
145
146 // If the block has any instructions after a JMP, delete them.
147 while (llvm::next(I) != MBB.end())
148 llvm::next(I)->eraseFromParent();
149
150 Cond.clear();
151 FBB = 0;
152
153 // Delete the JMP if it's equivalent to a fall-through.
Richard Sandiford53c9efd2013-05-28 10:13:54 +0000154 if (MBB.isLayoutSuccessor(Branch.Target->getMBB())) {
Ulrich Weigand5f613df2013-05-06 16:15:19 +0000155 TBB = 0;
156 I->eraseFromParent();
157 I = MBB.end();
158 continue;
159 }
160
161 // TBB is used to indicate the unconditinal destination.
Richard Sandiford53c9efd2013-05-28 10:13:54 +0000162 TBB = Branch.Target->getMBB();
Ulrich Weigand5f613df2013-05-06 16:15:19 +0000163 continue;
164 }
165
166 // Working from the bottom, handle the first conditional branch.
167 if (Cond.empty()) {
168 // FIXME: add X86-style branch swap
169 FBB = TBB;
Richard Sandiford53c9efd2013-05-28 10:13:54 +0000170 TBB = Branch.Target->getMBB();
171 Cond.push_back(MachineOperand::CreateImm(Branch.CCMask));
Ulrich Weigand5f613df2013-05-06 16:15:19 +0000172 continue;
173 }
174
175 // Handle subsequent conditional branches.
176 assert(Cond.size() == 1);
177 assert(TBB);
178
179 // Only handle the case where all conditional branches branch to the same
180 // destination.
Richard Sandiford53c9efd2013-05-28 10:13:54 +0000181 if (TBB != Branch.Target->getMBB())
Ulrich Weigand5f613df2013-05-06 16:15:19 +0000182 return true;
183
184 // If the conditions are the same, we can leave them alone.
185 unsigned OldCond = Cond[0].getImm();
Richard Sandiford53c9efd2013-05-28 10:13:54 +0000186 if (OldCond == Branch.CCMask)
Ulrich Weigand5f613df2013-05-06 16:15:19 +0000187 continue;
188
189 // FIXME: Try combining conditions like X86 does. Should be easy on Z!
190 }
191
192 return false;
193}
194
195unsigned SystemZInstrInfo::RemoveBranch(MachineBasicBlock &MBB) const {
196 // Most of the code and comments here are boilerplate.
197 MachineBasicBlock::iterator I = MBB.end();
198 unsigned Count = 0;
199
200 while (I != MBB.begin()) {
201 --I;
202 if (I->isDebugValue())
203 continue;
Richard Sandiford53c9efd2013-05-28 10:13:54 +0000204 if (!I->isBranch())
Ulrich Weigand5f613df2013-05-06 16:15:19 +0000205 break;
Richard Sandiford53c9efd2013-05-28 10:13:54 +0000206 if (!getBranchInfo(I).Target->isMBB())
Ulrich Weigand5f613df2013-05-06 16:15:19 +0000207 break;
208 // Remove the branch.
209 I->eraseFromParent();
210 I = MBB.end();
211 ++Count;
212 }
213
214 return Count;
215}
216
217unsigned
218SystemZInstrInfo::InsertBranch(MachineBasicBlock &MBB, MachineBasicBlock *TBB,
219 MachineBasicBlock *FBB,
220 const SmallVectorImpl<MachineOperand> &Cond,
221 DebugLoc DL) const {
222 // In this function we output 32-bit branches, which should always
223 // have enough range. They can be shortened and relaxed by later code
224 // in the pipeline, if desired.
225
226 // Shouldn't be a fall through.
227 assert(TBB && "InsertBranch must not be told to insert a fallthrough");
228 assert((Cond.size() == 1 || Cond.size() == 0) &&
229 "SystemZ branch conditions have one component!");
230
231 if (Cond.empty()) {
232 // Unconditional branch?
233 assert(!FBB && "Unconditional branch with multiple successors!");
Richard Sandiford312425f2013-05-20 14:23:08 +0000234 BuildMI(&MBB, DL, get(SystemZ::J)).addMBB(TBB);
Ulrich Weigand5f613df2013-05-06 16:15:19 +0000235 return 1;
236 }
237
238 // Conditional branch.
239 unsigned Count = 0;
240 unsigned CC = Cond[0].getImm();
Richard Sandiford312425f2013-05-20 14:23:08 +0000241 BuildMI(&MBB, DL, get(SystemZ::BRC)).addImm(CC).addMBB(TBB);
Ulrich Weigand5f613df2013-05-06 16:15:19 +0000242 ++Count;
243
244 if (FBB) {
245 // Two-way Conditional branch. Insert the second branch.
Richard Sandiford312425f2013-05-20 14:23:08 +0000246 BuildMI(&MBB, DL, get(SystemZ::J)).addMBB(FBB);
Ulrich Weigand5f613df2013-05-06 16:15:19 +0000247 ++Count;
248 }
249 return Count;
250}
251
252void
253SystemZInstrInfo::copyPhysReg(MachineBasicBlock &MBB,
254 MachineBasicBlock::iterator MBBI, DebugLoc DL,
255 unsigned DestReg, unsigned SrcReg,
256 bool KillSrc) const {
257 // Split 128-bit GPR moves into two 64-bit moves. This handles ADDR128 too.
258 if (SystemZ::GR128BitRegClass.contains(DestReg, SrcReg)) {
259 copyPhysReg(MBB, MBBI, DL, RI.getSubReg(DestReg, SystemZ::subreg_high),
260 RI.getSubReg(SrcReg, SystemZ::subreg_high), KillSrc);
261 copyPhysReg(MBB, MBBI, DL, RI.getSubReg(DestReg, SystemZ::subreg_low),
262 RI.getSubReg(SrcReg, SystemZ::subreg_low), KillSrc);
263 return;
264 }
265
266 // Everything else needs only one instruction.
267 unsigned Opcode;
268 if (SystemZ::GR32BitRegClass.contains(DestReg, SrcReg))
269 Opcode = SystemZ::LR;
270 else if (SystemZ::GR64BitRegClass.contains(DestReg, SrcReg))
271 Opcode = SystemZ::LGR;
272 else if (SystemZ::FP32BitRegClass.contains(DestReg, SrcReg))
273 Opcode = SystemZ::LER;
274 else if (SystemZ::FP64BitRegClass.contains(DestReg, SrcReg))
275 Opcode = SystemZ::LDR;
276 else if (SystemZ::FP128BitRegClass.contains(DestReg, SrcReg))
277 Opcode = SystemZ::LXR;
278 else
279 llvm_unreachable("Impossible reg-to-reg copy");
280
281 BuildMI(MBB, MBBI, DL, get(Opcode), DestReg)
282 .addReg(SrcReg, getKillRegState(KillSrc));
283}
284
285void
286SystemZInstrInfo::storeRegToStackSlot(MachineBasicBlock &MBB,
287 MachineBasicBlock::iterator MBBI,
288 unsigned SrcReg, bool isKill,
289 int FrameIdx,
290 const TargetRegisterClass *RC,
291 const TargetRegisterInfo *TRI) const {
292 DebugLoc DL = MBBI != MBB.end() ? MBBI->getDebugLoc() : DebugLoc();
293
294 // Callers may expect a single instruction, so keep 128-bit moves
295 // together for now and lower them after register allocation.
296 unsigned LoadOpcode, StoreOpcode;
297 getLoadStoreOpcodes(RC, LoadOpcode, StoreOpcode);
298 addFrameReference(BuildMI(MBB, MBBI, DL, get(StoreOpcode))
299 .addReg(SrcReg, getKillRegState(isKill)), FrameIdx);
300}
301
302void
303SystemZInstrInfo::loadRegFromStackSlot(MachineBasicBlock &MBB,
304 MachineBasicBlock::iterator MBBI,
305 unsigned DestReg, int FrameIdx,
306 const TargetRegisterClass *RC,
307 const TargetRegisterInfo *TRI) const {
308 DebugLoc DL = MBBI != MBB.end() ? MBBI->getDebugLoc() : DebugLoc();
309
310 // Callers may expect a single instruction, so keep 128-bit moves
311 // together for now and lower them after register allocation.
312 unsigned LoadOpcode, StoreOpcode;
313 getLoadStoreOpcodes(RC, LoadOpcode, StoreOpcode);
314 addFrameReference(BuildMI(MBB, MBBI, DL, get(LoadOpcode), DestReg),
315 FrameIdx);
316}
317
318bool
319SystemZInstrInfo::expandPostRAPseudo(MachineBasicBlock::iterator MI) const {
320 switch (MI->getOpcode()) {
321 case SystemZ::L128:
322 splitMove(MI, SystemZ::LG);
323 return true;
324
325 case SystemZ::ST128:
326 splitMove(MI, SystemZ::STG);
327 return true;
328
329 case SystemZ::LX:
330 splitMove(MI, SystemZ::LD);
331 return true;
332
333 case SystemZ::STX:
334 splitMove(MI, SystemZ::STD);
335 return true;
336
337 case SystemZ::ADJDYNALLOC:
338 splitAdjDynAlloc(MI);
339 return true;
340
341 default:
342 return false;
343 }
344}
345
346bool SystemZInstrInfo::
347ReverseBranchCondition(SmallVectorImpl<MachineOperand> &Cond) const {
348 assert(Cond.size() == 1 && "Invalid branch condition!");
349 Cond[0].setImm(Cond[0].getImm() ^ SystemZ::CCMASK_ANY);
350 return false;
351}
352
Richard Sandiford312425f2013-05-20 14:23:08 +0000353uint64_t SystemZInstrInfo::getInstSizeInBytes(const MachineInstr *MI) const {
354 if (MI->getOpcode() == TargetOpcode::INLINEASM) {
355 const MachineFunction *MF = MI->getParent()->getParent();
356 const char *AsmStr = MI->getOperand(0).getSymbolName();
357 return getInlineAsmLength(AsmStr, *MF->getTarget().getMCAsmInfo());
358 }
359 return MI->getDesc().getSize();
360}
361
Richard Sandiford53c9efd2013-05-28 10:13:54 +0000362SystemZII::Branch
363SystemZInstrInfo::getBranchInfo(const MachineInstr *MI) const {
Ulrich Weigand5f613df2013-05-06 16:15:19 +0000364 switch (MI->getOpcode()) {
365 case SystemZ::BR:
366 case SystemZ::J:
367 case SystemZ::JG:
Richard Sandiford0fb90ab2013-05-28 10:41:11 +0000368 return SystemZII::Branch(SystemZII::BranchNormal, SystemZ::CCMASK_ANY,
369 &MI->getOperand(0));
Ulrich Weigand5f613df2013-05-06 16:15:19 +0000370
371 case SystemZ::BRC:
372 case SystemZ::BRCL:
Richard Sandiford0fb90ab2013-05-28 10:41:11 +0000373 return SystemZII::Branch(SystemZII::BranchNormal,
374 MI->getOperand(0).getImm(), &MI->getOperand(1));
375
Richard Sandiforde1d9f002013-05-29 11:58:52 +0000376 case SystemZ::CIJ:
Richard Sandiford0fb90ab2013-05-28 10:41:11 +0000377 case SystemZ::CRJ:
378 return SystemZII::Branch(SystemZII::BranchC, MI->getOperand(2).getImm(),
379 &MI->getOperand(3));
380
Richard Sandiforde1d9f002013-05-29 11:58:52 +0000381 case SystemZ::CGIJ:
Richard Sandiford0fb90ab2013-05-28 10:41:11 +0000382 case SystemZ::CGRJ:
383 return SystemZII::Branch(SystemZII::BranchCG, MI->getOperand(2).getImm(),
384 &MI->getOperand(3));
Ulrich Weigand5f613df2013-05-06 16:15:19 +0000385
386 default:
Richard Sandiford53c9efd2013-05-28 10:13:54 +0000387 llvm_unreachable("Unrecognized branch opcode");
Ulrich Weigand5f613df2013-05-06 16:15:19 +0000388 }
389}
390
391void SystemZInstrInfo::getLoadStoreOpcodes(const TargetRegisterClass *RC,
392 unsigned &LoadOpcode,
393 unsigned &StoreOpcode) const {
394 if (RC == &SystemZ::GR32BitRegClass || RC == &SystemZ::ADDR32BitRegClass) {
395 LoadOpcode = SystemZ::L;
396 StoreOpcode = SystemZ::ST32;
397 } else if (RC == &SystemZ::GR64BitRegClass ||
398 RC == &SystemZ::ADDR64BitRegClass) {
399 LoadOpcode = SystemZ::LG;
400 StoreOpcode = SystemZ::STG;
401 } else if (RC == &SystemZ::GR128BitRegClass ||
402 RC == &SystemZ::ADDR128BitRegClass) {
403 LoadOpcode = SystemZ::L128;
404 StoreOpcode = SystemZ::ST128;
405 } else if (RC == &SystemZ::FP32BitRegClass) {
406 LoadOpcode = SystemZ::LE;
407 StoreOpcode = SystemZ::STE;
408 } else if (RC == &SystemZ::FP64BitRegClass) {
409 LoadOpcode = SystemZ::LD;
410 StoreOpcode = SystemZ::STD;
411 } else if (RC == &SystemZ::FP128BitRegClass) {
412 LoadOpcode = SystemZ::LX;
413 StoreOpcode = SystemZ::STX;
414 } else
415 llvm_unreachable("Unsupported regclass to load or store");
416}
417
418unsigned SystemZInstrInfo::getOpcodeForOffset(unsigned Opcode,
419 int64_t Offset) const {
420 const MCInstrDesc &MCID = get(Opcode);
421 int64_t Offset2 = (MCID.TSFlags & SystemZII::Is128Bit ? Offset + 8 : Offset);
422 if (isUInt<12>(Offset) && isUInt<12>(Offset2)) {
423 // Get the instruction to use for unsigned 12-bit displacements.
424 int Disp12Opcode = SystemZ::getDisp12Opcode(Opcode);
425 if (Disp12Opcode >= 0)
426 return Disp12Opcode;
427
428 // All address-related instructions can use unsigned 12-bit
429 // displacements.
430 return Opcode;
431 }
432 if (isInt<20>(Offset) && isInt<20>(Offset2)) {
433 // Get the instruction to use for signed 20-bit displacements.
434 int Disp20Opcode = SystemZ::getDisp20Opcode(Opcode);
435 if (Disp20Opcode >= 0)
436 return Disp20Opcode;
437
438 // Check whether Opcode allows signed 20-bit displacements.
439 if (MCID.TSFlags & SystemZII::Has20BitOffset)
440 return Opcode;
441 }
442 return 0;
443}
444
Richard Sandiforde1d9f002013-05-29 11:58:52 +0000445unsigned SystemZInstrInfo::getCompareAndBranch(unsigned Opcode,
446 const MachineInstr *MI) const {
Richard Sandiford0fb90ab2013-05-28 10:41:11 +0000447 switch (Opcode) {
448 case SystemZ::CR:
449 return SystemZ::CRJ;
450 case SystemZ::CGR:
451 return SystemZ::CGRJ;
Richard Sandiforde1d9f002013-05-29 11:58:52 +0000452 case SystemZ::CHI:
453 return MI && isInt<8>(MI->getOperand(1).getImm()) ? SystemZ::CIJ : 0;
454 case SystemZ::CGHI:
455 return MI && isInt<8>(MI->getOperand(1).getImm()) ? SystemZ::CGIJ : 0;
Richard Sandiford0fb90ab2013-05-28 10:41:11 +0000456 default:
457 return 0;
458 }
459}
460
Ulrich Weigand5f613df2013-05-06 16:15:19 +0000461void SystemZInstrInfo::loadImmediate(MachineBasicBlock &MBB,
462 MachineBasicBlock::iterator MBBI,
463 unsigned Reg, uint64_t Value) const {
464 DebugLoc DL = MBBI != MBB.end() ? MBBI->getDebugLoc() : DebugLoc();
465 unsigned Opcode;
466 if (isInt<16>(Value))
467 Opcode = SystemZ::LGHI;
468 else if (SystemZ::isImmLL(Value))
469 Opcode = SystemZ::LLILL;
470 else if (SystemZ::isImmLH(Value)) {
471 Opcode = SystemZ::LLILH;
472 Value >>= 16;
473 } else {
474 assert(isInt<32>(Value) && "Huge values not handled yet");
475 Opcode = SystemZ::LGFI;
476 }
477 BuildMI(MBB, MBBI, DL, get(Opcode), Reg).addImm(Value);
478}