LLVM 24.0.0git
SparcInstrInfo.cpp
Go to the documentation of this file.
1//===-- SparcInstrInfo.cpp - Sparc Instruction Information ----------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// This file contains the Sparc implementation of the TargetInstrInfo class.
10//
11//===----------------------------------------------------------------------===//
12
13#include "SparcInstrInfo.h"
14#include "Sparc.h"
16#include "SparcSubtarget.h"
24
25using namespace llvm;
26
27#define GET_INSTRINFO_CTOR_DTOR
28#include "SparcGenInstrInfo.inc"
29
30// Pin the vtable to this file.
31void SparcInstrInfo::anchor() {}
32
34 : SparcGenInstrInfo(ST, RI, SP::ADJCALLSTACKDOWN, SP::ADJCALLSTACKUP),
35 RI(ST), Subtarget(ST) {}
36
39 return Subtarget.is64Bit() ? &SP::I64RegsRegClass : &SP::IntRegsRegClass;
40}
41
42/// isLoadFromStackSlot - If the specified machine instruction is a direct
43/// load from a stack slot, return the virtual or physical register number of
44/// the destination along with the FrameIndex of the loaded stack slot. If
45/// not, return 0. This predicate must return 0 if the instruction has
46/// any side effects other than loading from the stack slot.
48 int &FrameIndex,
49 TypeSize &MemBytes) const {
50 switch (MI.getOpcode()) {
51 default:
52 return 0;
53 case SP::LDri:
54 MemBytes = TypeSize::getFixed(4);
55 break;
56 case SP::LDXri:
57 MemBytes = TypeSize::getFixed(8);
58 break;
59 case SP::LDFri:
60 MemBytes = TypeSize::getFixed(4);
61 break;
62 case SP::LDDFri:
63 MemBytes = TypeSize::getFixed(8);
64 break;
65 case SP::LDQFri:
66 MemBytes = TypeSize::getFixed(16);
67 break;
68 }
69 if (MI.getOperand(1).isFI() && MI.getOperand(2).isImm() &&
70 MI.getOperand(2).getImm() == 0) {
71 FrameIndex = MI.getOperand(1).getIndex();
72 return MI.getOperand(0).getReg();
73 }
74 return 0;
75}
76
77/// isStoreToStackSlot - If the specified machine instruction is a direct
78/// store to a stack slot, return the virtual or physical register number of
79/// the source reg along with the FrameIndex of the loaded stack slot. If
80/// not, return 0. This predicate must return 0 if the instruction has
81/// any side effects other than storing to the stack slot.
83 int &FrameIndex,
84 TypeSize &MemBytes) const {
85 switch (MI.getOpcode()) {
86 default:
87 return 0;
88 case SP::STri:
89 MemBytes = TypeSize::getFixed(4);
90 break;
91 case SP::STXri:
92 MemBytes = TypeSize::getFixed(8);
93 break;
94 case SP::STFri:
95 MemBytes = TypeSize::getFixed(4);
96 break;
97 case SP::STDFri:
98 MemBytes = TypeSize::getFixed(8);
99 break;
100 case SP::STQFri:
101 MemBytes = TypeSize::getFixed(16);
102 break;
103 }
104 if (MI.getOperand(0).isFI() && MI.getOperand(1).isImm() &&
105 MI.getOperand(1).getImm() == 0) {
106 FrameIndex = MI.getOperand(0).getIndex();
107 return MI.getOperand(2).getReg();
108 }
109 return 0;
110}
111
113{
114 switch(CC) {
115 case SPCC::ICC_A: return SPCC::ICC_N;
116 case SPCC::ICC_N: return SPCC::ICC_A;
117 case SPCC::ICC_NE: return SPCC::ICC_E;
118 case SPCC::ICC_E: return SPCC::ICC_NE;
119 case SPCC::ICC_G: return SPCC::ICC_LE;
120 case SPCC::ICC_LE: return SPCC::ICC_G;
121 case SPCC::ICC_GE: return SPCC::ICC_L;
122 case SPCC::ICC_L: return SPCC::ICC_GE;
123 case SPCC::ICC_GU: return SPCC::ICC_LEU;
124 case SPCC::ICC_LEU: return SPCC::ICC_GU;
125 case SPCC::ICC_CC: return SPCC::ICC_CS;
126 case SPCC::ICC_CS: return SPCC::ICC_CC;
127 case SPCC::ICC_POS: return SPCC::ICC_NEG;
128 case SPCC::ICC_NEG: return SPCC::ICC_POS;
129 case SPCC::ICC_VC: return SPCC::ICC_VS;
130 case SPCC::ICC_VS: return SPCC::ICC_VC;
131
132 case SPCC::FCC_A: return SPCC::FCC_N;
133 case SPCC::FCC_N: return SPCC::FCC_A;
134 case SPCC::FCC_U: return SPCC::FCC_O;
135 case SPCC::FCC_O: return SPCC::FCC_U;
136 case SPCC::FCC_G: return SPCC::FCC_ULE;
137 case SPCC::FCC_LE: return SPCC::FCC_UG;
138 case SPCC::FCC_UG: return SPCC::FCC_LE;
139 case SPCC::FCC_ULE: return SPCC::FCC_G;
140 case SPCC::FCC_L: return SPCC::FCC_UGE;
141 case SPCC::FCC_GE: return SPCC::FCC_UL;
142 case SPCC::FCC_UL: return SPCC::FCC_GE;
143 case SPCC::FCC_UGE: return SPCC::FCC_L;
144 case SPCC::FCC_LG: return SPCC::FCC_UE;
145 case SPCC::FCC_UE: return SPCC::FCC_LG;
146 case SPCC::FCC_NE: return SPCC::FCC_E;
147 case SPCC::FCC_E: return SPCC::FCC_NE;
148
149 case SPCC::CPCC_A: return SPCC::CPCC_N;
150 case SPCC::CPCC_N: return SPCC::CPCC_A;
151 case SPCC::CPCC_3: [[fallthrough]];
152 case SPCC::CPCC_2: [[fallthrough]];
153 case SPCC::CPCC_23: [[fallthrough]];
154 case SPCC::CPCC_1: [[fallthrough]];
155 case SPCC::CPCC_13: [[fallthrough]];
156 case SPCC::CPCC_12: [[fallthrough]];
157 case SPCC::CPCC_123: [[fallthrough]];
158 case SPCC::CPCC_0: [[fallthrough]];
159 case SPCC::CPCC_03: [[fallthrough]];
160 case SPCC::CPCC_02: [[fallthrough]];
161 case SPCC::CPCC_023: [[fallthrough]];
162 case SPCC::CPCC_01: [[fallthrough]];
163 case SPCC::CPCC_013: [[fallthrough]];
164 case SPCC::CPCC_012:
165 // "Opposite" code is not meaningful, as we don't know
166 // what the CoProc condition means here. The cond-code will
167 // only be used in inline assembler, so this code should
168 // not be reached in a normal compilation pass.
169 llvm_unreachable("Meaningless inversion of co-processor cond code");
170
171 case SPCC::REG_BEGIN:
172 llvm_unreachable("Use of reserved cond code");
173 case SPCC::REG_Z:
174 return SPCC::REG_NZ;
175 case SPCC::REG_LEZ:
176 return SPCC::REG_GZ;
177 case SPCC::REG_LZ:
178 return SPCC::REG_GEZ;
179 case SPCC::REG_NZ:
180 return SPCC::REG_Z;
181 case SPCC::REG_GZ:
182 return SPCC::REG_LEZ;
183 case SPCC::REG_GEZ:
184 return SPCC::REG_LZ;
185 }
186 llvm_unreachable("Invalid cond code");
187}
188
189static bool isUncondBranchOpcode(int Opc) { return Opc == SP::BA; }
190
191static bool isI32CondBranchOpcode(int Opc) {
192 return Opc == SP::BCOND || Opc == SP::BPICC || Opc == SP::BPICCA ||
193 Opc == SP::BPICCNT || Opc == SP::BPICCANT;
194}
195
196static bool isI64CondBranchOpcode(int Opc) {
197 return Opc == SP::BPXCC || Opc == SP::BPXCCA || Opc == SP::BPXCCNT ||
198 Opc == SP::BPXCCANT;
199}
200
201static bool isRegCondBranchOpcode(int Opc) {
202 return Opc == SP::BPR || Opc == SP::BPRA || Opc == SP::BPRNT ||
203 Opc == SP::BPRANT;
204}
205
206static bool isFCondBranchOpcode(int Opc) {
207 return Opc == SP::FBCOND || Opc == SP::FBCONDA || Opc == SP::FBCOND_V9 ||
208 Opc == SP::FBCONDA_V9;
209}
210
215
216static bool isIndirectBranchOpcode(int Opc) {
217 return Opc == SP::BINDrr || Opc == SP::BINDri;
218}
219
222 unsigned Opc = LastInst->getOpcode();
223 int64_t CC = LastInst->getOperand(1).getImm();
224
225 // Push the branch opcode into Cond too so later in insertBranch
226 // it can use the information to emit the correct SPARC branch opcode.
229
230 // Branch on register contents need another argument to indicate
231 // the register it branches on.
233 Cond.push_back(LastInst->getOperand(2));
234
235 Target = LastInst->getOperand(0).getMBB();
236}
237
240 switch (MI.getOpcode()) {
241 default:
242 llvm_unreachable("unexpected opcode!");
243 case SP::BA:
244 case SP::BCOND:
245 case SP::BCONDA:
246 case SP::FBCOND:
247 case SP::FBCONDA:
248 case SP::BPICC:
249 case SP::BPICCA:
250 case SP::BPICCNT:
251 case SP::BPICCANT:
252 case SP::BPXCC:
253 case SP::BPXCCA:
254 case SP::BPXCCNT:
255 case SP::BPXCCANT:
256 case SP::BPFCC:
257 case SP::BPFCCA:
258 case SP::BPFCCNT:
259 case SP::BPFCCANT:
260 case SP::FBCOND_V9:
261 case SP::FBCONDA_V9:
262 case SP::BPR:
263 case SP::BPRA:
264 case SP::BPRNT:
265 case SP::BPRANT:
266 case SP::CALL_LONGJUMP:
267 return MI.getOperand(0).getMBB();
268 }
269}
270
273 MachineBasicBlock *&FBB,
275 bool AllowModify) const {
276 MachineBasicBlock::iterator I = MBB.getLastNonDebugInstr();
277 if (I == MBB.end())
278 return false;
279
280 if (!isUnpredicatedTerminator(*I))
281 return false;
282
283 // Get the last instruction in the block.
284 MachineInstr *LastInst = &*I;
285 unsigned LastOpc = LastInst->getOpcode();
286
287 // If there is only one terminator instruction, process it.
288 if (I == MBB.begin() || !isUnpredicatedTerminator(*--I)) {
289 if (isUncondBranchOpcode(LastOpc)) {
290 TBB = LastInst->getOperand(0).getMBB();
291 return false;
292 }
293 if (isCondBranchOpcode(LastOpc)) {
294 // Block ends with fall-through condbranch.
295 parseCondBranch(LastInst, TBB, Cond);
296 return false;
297 }
298 return true; // Can't handle indirect branch.
299 }
300
301 // Get the instruction before it if it is a terminator.
302 MachineInstr *SecondLastInst = &*I;
303 unsigned SecondLastOpc = SecondLastInst->getOpcode();
304
305 // If AllowModify is true and the block ends with two or more unconditional
306 // branches, delete all but the first unconditional branch.
307 if (AllowModify && isUncondBranchOpcode(LastOpc)) {
308 while (isUncondBranchOpcode(SecondLastOpc)) {
309 LastInst->eraseFromParent();
310 LastInst = SecondLastInst;
311 LastOpc = LastInst->getOpcode();
312 if (I == MBB.begin() || !isUnpredicatedTerminator(*--I)) {
313 // Return now the only terminator is an unconditional branch.
314 TBB = LastInst->getOperand(0).getMBB();
315 return false;
316 } else {
317 SecondLastInst = &*I;
318 SecondLastOpc = SecondLastInst->getOpcode();
319 }
320 }
321 }
322
323 // If there are three terminators, we don't know what sort of block this is.
324 if (SecondLastInst && I != MBB.begin() && isUnpredicatedTerminator(*--I))
325 return true;
326
327 // If the block ends with a B and a Bcc, handle it.
328 if (isCondBranchOpcode(SecondLastOpc) && isUncondBranchOpcode(LastOpc)) {
329 parseCondBranch(SecondLastInst, TBB, Cond);
330 FBB = LastInst->getOperand(0).getMBB();
331 return false;
332 }
333
334 // If the block ends with two unconditional branches, handle it. The second
335 // one is not executed.
336 if (isUncondBranchOpcode(SecondLastOpc) && isUncondBranchOpcode(LastOpc)) {
337 TBB = SecondLastInst->getOperand(0).getMBB();
338 return false;
339 }
340
341 // ...likewise if it ends with an indirect branch followed by an unconditional
342 // branch.
343 if (isIndirectBranchOpcode(SecondLastOpc) && isUncondBranchOpcode(LastOpc)) {
344 I = LastInst;
345 if (AllowModify)
346 I->eraseFromParent();
347 return true;
348 }
349
350 // Otherwise, can't handle this.
351 return true;
352}
353
358 const DebugLoc &DL,
359 int *BytesAdded) const {
360 assert(TBB && "insertBranch must not be told to insert a fallthrough");
361 assert((Cond.size() <= 3) &&
362 "Sparc branch conditions should have at most three components!");
363
364 if (Cond.empty()) {
365 assert(!FBB && "Unconditional branch with multiple successors!");
366 BuildMI(&MBB, DL, get(SP::BA)).addMBB(TBB);
367 if (BytesAdded)
368 *BytesAdded = 8;
369 return 1;
370 }
371
372 // Conditional branch
373 unsigned Opc = Cond[0].getImm();
374 unsigned CC = Cond[1].getImm();
377 } else {
379 }
380
381 if (!FBB) {
382 if (BytesAdded)
383 *BytesAdded = 8;
384 return 1;
385 }
386
387 BuildMI(&MBB, DL, get(SP::BA)).addMBB(FBB);
388 if (BytesAdded)
389 *BytesAdded = 16;
390 return 2;
391}
392
394 MachineBasicBlock &NewDestBB,
395 MachineBasicBlock &RestoreBB,
396 const DebugLoc &DL, int64_t BrOffset,
397 RegScavenger *RS) const {
398 assert(RS && "RegScavenger required for long branching");
399 assert(MBB.empty() &&
400 "new block should be inserted for expanding unconditional branch");
401 assert(MBB.pred_size() == 1 && "should only have a single predecessor");
402 assert(RestoreBB.empty() &&
403 "restore block should be inserted for restoring clobbered registers");
404
405 MachineFunction *MF = MBB.getParent();
407
408 if (!isInt<32>(BrOffset))
410 "Branch offsets outside of the signed 32-bit range not supported");
411 RS->enterBasicBlockEnd(MBB);
412
413 // A SPARC CALL instruction already has signed 32-bit range, so we'll use it
414 // instead of actually emitting an indirect branch.
415 //
416 // Note that using CALLs to do unconditional long-range branch in this manner
417 // should only be done if the target is out of range of a regular BA
418 // instruction, given that CALLS will always clobber %o7 and interfere with
419 // the processor's predictor machinery.
420 bool IsO7Used = RS->isRegUsed(SP::O7);
421 Register ScratchReg = RS->FindUnusedReg(&SP::IntRegsRegClass);
422 int FI = SMFI->getBranchRelaxationSpillFrameIndex();
423 if (IsO7Used) {
424 if (ScratchReg.isValid()) {
425 BuildMI(&MBB, DL, get(SP::ORrr), ScratchReg)
426 .addReg(SP::G0)
427 .addReg(SP::O7, RegState::Kill);
428 RS->setRegUsed(ScratchReg);
429 } else {
430 // In case we run out of usable registers we'll spill it into the stack.
431 if (FI == -1)
432 report_fatal_error("The function size is incorrectly estimated.");
433 const MCRegisterClass &RC =
434 Subtarget.is64Bit() ? SP::I64RegsRegClass : SP::IntRegsRegClass;
435
437 storeRegToStackSlot(MBB, I, SP::O7, true, FI, &RC, Register());
438 TRI.eliminateFrameIndex(std::prev(I), 0, 0, RS);
439 }
440 }
441
442 BuildMI(&MBB, DL, get(SP::CALL_LONGJUMP))
443 .addMBB(IsO7Used ? &RestoreBB : &NewDestBB);
444
445 if (IsO7Used) {
446 if (ScratchReg.isValid()) {
447 BuildMI(&RestoreBB, DL, get(SP::ORrr), SP::O7)
448 .addReg(SP::G0)
449 .addReg(ScratchReg, RegState::Kill);
450 } else {
451 const MCRegisterClass &RC =
452 Subtarget.is64Bit() ? SP::I64RegsRegClass : SP::IntRegsRegClass;
453
454 MachineBasicBlock::iterator I = RestoreBB.begin();
455 loadRegFromStackSlot(RestoreBB, I, SP::O7, FI, &RC, Register());
456 TRI.eliminateFrameIndex(std::prev(I), 0, 1, RS);
457 }
458 }
459}
460
462 int *BytesRemoved) const {
464 unsigned Count = 0;
465 int Removed = 0;
466 while (I != MBB.begin()) {
467 --I;
468
469 if (I->isDebugInstr())
470 continue;
471
472 if (!isCondBranchOpcode(I->getOpcode()) &&
473 !isUncondBranchOpcode(I->getOpcode()))
474 break; // Not a branch
475
476 Removed += getInstSizeInBytes(*I);
477 I->eraseFromParent();
478 I = MBB.end();
479 ++Count;
480 }
481
482 if (BytesRemoved)
483 *BytesRemoved = Removed;
484 return Count;
485}
486
489 assert(Cond.size() <= 3);
490 SPCC::CondCodes CC = static_cast<SPCC::CondCodes>(Cond[1].getImm());
492 return false;
493}
494
496 int64_t Offset) const {
497 assert((Offset & 0b11) == 0 && "Malformed branch offset");
498 switch (BranchOpc) {
499 case SP::CALL_LONGJUMP:
500 return isIntN(30, Offset >> 2);
501
502 case SP::BA:
503 case SP::BCOND:
504 case SP::BCONDA:
505 case SP::FBCOND:
506 case SP::FBCONDA:
507 return isIntN(22, Offset >> 2);
508
509 case SP::BPICC:
510 case SP::BPICCA:
511 case SP::BPICCNT:
512 case SP::BPICCANT:
513 case SP::BPXCC:
514 case SP::BPXCCA:
515 case SP::BPXCCNT:
516 case SP::BPXCCANT:
517 case SP::BPFCC:
518 case SP::BPFCCA:
519 case SP::BPFCCNT:
520 case SP::BPFCCANT:
521 case SP::FBCOND_V9:
522 case SP::FBCONDA_V9:
523 return isIntN(Subtarget.getCLOpts().bpcc_offset_bits, Offset >> 2);
524
525 case SP::BPR:
526 case SP::BPRA:
527 case SP::BPRNT:
528 case SP::BPRANT:
529 return isIntN(Subtarget.getCLOpts().bpr_offset_bits, Offset >> 2);
530 }
531
532 llvm_unreachable("Unknown branch instruction!");
533}
534
537 const DebugLoc &DL, Register DestReg,
538 Register SrcReg, bool KillSrc,
539 bool RenamableDest, bool RenamableSrc) const {
540 unsigned numSubRegs = 0;
541 unsigned movOpc = 0;
542 const unsigned *subRegIdx = nullptr;
543 bool ExtraG0 = false;
544
545 const unsigned DW_SubRegsIdx[] = { SP::sub_even, SP::sub_odd };
546 const unsigned DFP_FP_SubRegsIdx[] = { SP::sub_even, SP::sub_odd };
547 const unsigned QFP_DFP_SubRegsIdx[] = { SP::sub_even64, SP::sub_odd64 };
548 const unsigned QFP_FP_SubRegsIdx[] = { SP::sub_even, SP::sub_odd,
549 SP::sub_odd64_then_sub_even,
550 SP::sub_odd64_then_sub_odd };
551
552 if (SP::IntRegsRegClass.contains(DestReg, SrcReg))
553 BuildMI(MBB, I, DL, get(SP::ORrr), DestReg).addReg(SP::G0)
554 .addReg(SrcReg, getKillRegState(KillSrc));
555 else if (SP::IntPairRegClass.contains(DestReg, SrcReg)) {
556 subRegIdx = DW_SubRegsIdx;
557 numSubRegs = 2;
558 movOpc = SP::ORrr;
559 ExtraG0 = true;
560 } else if (SP::FPRegsRegClass.contains(DestReg, SrcReg))
561 BuildMI(MBB, I, DL, get(SP::FMOVS), DestReg)
562 .addReg(SrcReg, getKillRegState(KillSrc));
563 else if (SP::DFPRegsRegClass.contains(DestReg, SrcReg)) {
564 if (Subtarget.isV9()) {
565 BuildMI(MBB, I, DL, get(SP::FMOVD), DestReg)
566 .addReg(SrcReg, getKillRegState(KillSrc));
567 } else {
568 // Use two FMOVS instructions.
569 subRegIdx = DFP_FP_SubRegsIdx;
570 numSubRegs = 2;
571 movOpc = SP::FMOVS;
572 }
573 } else if (SP::QFPRegsRegClass.contains(DestReg, SrcReg)) {
574 if (Subtarget.isV9()) {
575 if (Subtarget.hasHardQuad()) {
576 BuildMI(MBB, I, DL, get(SP::FMOVQ), DestReg)
577 .addReg(SrcReg, getKillRegState(KillSrc));
578 } else {
579 // Use two FMOVD instructions.
580 subRegIdx = QFP_DFP_SubRegsIdx;
581 numSubRegs = 2;
582 movOpc = SP::FMOVD;
583 }
584 } else {
585 // Use four FMOVS instructions.
586 subRegIdx = QFP_FP_SubRegsIdx;
587 numSubRegs = 4;
588 movOpc = SP::FMOVS;
589 }
590 } else if (SP::ASRRegsRegClass.contains(DestReg) &&
591 SP::IntRegsRegClass.contains(SrcReg)) {
592 BuildMI(MBB, I, DL, get(SP::WRASRrr), DestReg)
593 .addReg(SP::G0)
594 .addReg(SrcReg, getKillRegState(KillSrc));
595 } else if (SP::IntRegsRegClass.contains(DestReg) &&
596 SP::ASRRegsRegClass.contains(SrcReg)) {
597 BuildMI(MBB, I, DL, get(SP::RDASR), DestReg)
598 .addReg(SrcReg, getKillRegState(KillSrc));
599 } else
600 llvm_unreachable("Impossible reg-to-reg copy");
601
602 if (numSubRegs == 0 || subRegIdx == nullptr || movOpc == 0)
603 return;
604
606 MachineInstr *MovMI = nullptr;
607
608 for (unsigned i = 0; i != numSubRegs; ++i) {
609 Register Dst = TRI->getSubReg(DestReg, subRegIdx[i]);
610 Register Src = TRI->getSubReg(SrcReg, subRegIdx[i]);
611 assert(Dst && Src && "Bad sub-register");
612
613 MachineInstrBuilder MIB = BuildMI(MBB, I, DL, get(movOpc), Dst);
614 if (ExtraG0)
615 MIB.addReg(SP::G0);
616 MIB.addReg(Src);
617 MovMI = MIB.getInstr();
618 }
619 // Add implicit super-register defs and kills to the last MovMI.
620 MovMI->addRegisterDefined(DestReg, TRI);
621 if (KillSrc)
622 MovMI->addRegisterKilled(SrcReg, TRI);
623}
624
627 Register SrcReg, bool isKill, int FI,
628 const TargetRegisterClass *RC,
629 Register VReg,
630 MachineInstr::MIFlag Flags) const {
631 DebugLoc DL;
632 if (I != MBB.end()) DL = I->getDebugLoc();
633
634 MachineFunction *MF = MBB.getParent();
635 const MachineFrameInfo &MFI = MF->getFrameInfo();
638 MFI.getObjectSize(FI), MFI.getObjectAlign(FI));
639
640 // On the order of operands here: think "[FrameIdx + 0] = SrcReg".
641 if (RC == &SP::I64RegsRegClass)
642 BuildMI(MBB, I, DL, get(SP::STXri)).addFrameIndex(FI).addImm(0)
643 .addReg(SrcReg, getKillRegState(isKill)).addMemOperand(MMO);
644 else if (RC == &SP::IntRegsRegClass)
645 BuildMI(MBB, I, DL, get(SP::STri)).addFrameIndex(FI).addImm(0)
646 .addReg(SrcReg, getKillRegState(isKill)).addMemOperand(MMO);
647 else if (RC == &SP::IntPairRegClass)
648 BuildMI(MBB, I, DL, get(SP::STDri)).addFrameIndex(FI).addImm(0)
649 .addReg(SrcReg, getKillRegState(isKill)).addMemOperand(MMO);
650 else if (RC == &SP::FPRegsRegClass)
651 BuildMI(MBB, I, DL, get(SP::STFri)).addFrameIndex(FI).addImm(0)
652 .addReg(SrcReg, getKillRegState(isKill)).addMemOperand(MMO);
653 else if (SP::DFPRegsRegClass.hasSubClassEq(RC))
654 BuildMI(MBB, I, DL, get(SP::STDFri)).addFrameIndex(FI).addImm(0)
655 .addReg(SrcReg, getKillRegState(isKill)).addMemOperand(MMO);
656 else if (SP::QFPRegsRegClass.hasSubClassEq(RC))
657 // Use STQFri irrespective of its legality. If STQ is not legal, it will be
658 // lowered into two STDs in eliminateFrameIndex.
659 BuildMI(MBB, I, DL, get(SP::STQFri)).addFrameIndex(FI).addImm(0)
660 .addReg(SrcReg, getKillRegState(isKill)).addMemOperand(MMO);
661 else
662 llvm_unreachable("Can't store this register to stack slot");
663}
664
667 Register DestReg, int FI,
668 const TargetRegisterClass *RC,
669 Register VReg, unsigned SubReg,
670 MachineInstr::MIFlag Flags) const {
671 DebugLoc DL;
672 if (I != MBB.end()) DL = I->getDebugLoc();
673
674 MachineFunction *MF = MBB.getParent();
675 const MachineFrameInfo &MFI = MF->getFrameInfo();
678 MFI.getObjectSize(FI), MFI.getObjectAlign(FI));
679
680 if (RC == &SP::I64RegsRegClass)
681 BuildMI(MBB, I, DL, get(SP::LDXri), DestReg).addFrameIndex(FI).addImm(0)
682 .addMemOperand(MMO);
683 else if (RC == &SP::IntRegsRegClass)
684 BuildMI(MBB, I, DL, get(SP::LDri), DestReg).addFrameIndex(FI).addImm(0)
685 .addMemOperand(MMO);
686 else if (RC == &SP::IntPairRegClass)
687 BuildMI(MBB, I, DL, get(SP::LDDri), DestReg).addFrameIndex(FI).addImm(0)
688 .addMemOperand(MMO);
689 else if (RC == &SP::FPRegsRegClass)
690 BuildMI(MBB, I, DL, get(SP::LDFri), DestReg).addFrameIndex(FI).addImm(0)
691 .addMemOperand(MMO);
692 else if (SP::DFPRegsRegClass.hasSubClassEq(RC))
693 BuildMI(MBB, I, DL, get(SP::LDDFri), DestReg).addFrameIndex(FI).addImm(0)
694 .addMemOperand(MMO);
695 else if (SP::QFPRegsRegClass.hasSubClassEq(RC))
696 // Use LDQFri irrespective of its legality. If LDQ is not legal, it will be
697 // lowered into two LDDs in eliminateFrameIndex.
698 BuildMI(MBB, I, DL, get(SP::LDQFri), DestReg).addFrameIndex(FI).addImm(0)
699 .addMemOperand(MMO);
700 else
701 llvm_unreachable("Can't load this register from stack slot");
702}
703
706 Register GlobalBaseReg = SparcFI->getGlobalBaseReg();
707 if (GlobalBaseReg)
708 return GlobalBaseReg;
709
710 // Insert the set of GlobalBaseReg into the first MBB of the function
711 MachineBasicBlock &FirstMBB = MF->front();
713 MachineRegisterInfo &RegInfo = MF->getRegInfo();
714
715 const TargetRegisterClass *PtrRC =
716 Subtarget.is64Bit() ? &SP::I64RegsRegClass : &SP::IntRegsRegClass;
717 GlobalBaseReg = RegInfo.createVirtualRegister(PtrRC);
718
719 DebugLoc dl;
720
721 BuildMI(FirstMBB, MBBI, dl, get(SP::GETPCX), GlobalBaseReg)
722 .setOperandDead(1); // implicit-def $o7
723 SparcFI->setGlobalBaseReg(GlobalBaseReg);
724 return GlobalBaseReg;
725}
726
728 unsigned &StructSize) const {
729 if (!MI.isCall())
730 return false;
731
732 unsigned StructSizeOpNum = 0;
733 switch (MI.getOpcode()) {
734 default:
735 llvm_unreachable("Unknown call opcode.");
736 case SP::CALL:
737 StructSizeOpNum = 1;
738 break;
739 case SP::CALLrr:
740 case SP::CALLri:
741 StructSizeOpNum = 2;
742 break;
743 case SP::TLS_CALL:
744 return false;
745 case SP::TAIL_CALLri:
746 case SP::TAIL_CALL:
747 return false;
748 }
749
750 const MachineOperand &MO = MI.getOperand(StructSizeOpNum);
751 if (!MO.isImm())
752 return false;
753
754 // A zero-sized return value has nothing for the callee to copy, so GCC emits
755 // no unimp for it and returns to the instruction right after the delay slot.
756 // We replicate this behavior here.
757 StructSize = MO.getImm();
758 return StructSize != 0;
759}
760
762 unsigned Opcode = MI.getOpcode();
763
764 if (MI.isInlineAsm()) {
765 const MachineFunction *MF = MI.getParent()->getParent();
766 const char *AsmStr = MI.getOperand(0).getSymbolName();
767 return getInlineAsmLength(AsmStr, MF->getTarget().getMCAsmInfo());
768 }
769
770 if (Opcode == TargetOpcode::BUNDLE)
771 return getInstBundleSize(MI);
772
773 if (MI.getOpcode() == SP::GETPCX) {
774 const TargetMachine &TM = MI.getParent()->getParent()->getTarget();
775 if (TM.isPositionIndependent())
776 return 16;
777 switch (TM.getCodeModel()) {
778 default:
779 llvm_unreachable("Unsupported absolute code model");
780 case CodeModel::Small:
781 return 8;
783 return 16;
784 case CodeModel::Large:
785 return 24;
786 }
787 }
788
789 // If the instruction has a delay slot, be conservative and also include
790 // it for sizing purposes. This is done so that the BranchRelaxation pass
791 // will not mistakenly mark out-of-range branches as in-range.
792 if (MI.hasDelaySlot()) {
793 unsigned StructSize = 0;
794 return get(Opcode).getSize() * (2 + needsUnimp(MI, StructSize));
795 }
796 return get(Opcode).getSize();
797}
798
800 Register &SrcReg2, int64_t &CmpMask,
801 int64_t &CmpValue) const {
802 Register DstReg;
803 switch (MI.getOpcode()) {
804 default:
805 break;
806 case SP::SUBCCri:
807 DstReg = MI.getOperand(0).getReg();
808 SrcReg = MI.getOperand(1).getReg();
809 SrcReg2 = 0;
810 CmpMask = ~0;
811 CmpValue = MI.getOperand(2).getImm();
812 return DstReg == SP::G0 && CmpValue == 0;
813 case SP::SUBCCrr:
814 DstReg = MI.getOperand(0).getReg();
815 SrcReg = MI.getOperand(1).getReg();
816 SrcReg2 = MI.getOperand(2).getReg();
817 CmpMask = ~0;
818 CmpValue = 0;
819 return DstReg == SP::G0 && SrcReg2 == SP::G0;
820 }
821
822 return false;
823}
824
826 MachineInstr &CmpInstr, Register SrcReg, Register SrcReg2, int64_t CmpMask,
827 int64_t CmpValue, const MachineRegisterInfo *MRI) const {
828
829 // Get the unique definition of SrcReg.
830 MachineInstr *MI = MRI->getUniqueVRegDef(SrcReg);
831 if (!MI)
832 return false;
833
834 // Only optimize if defining and comparing instruction in same block.
835 if (MI->getParent() != CmpInstr.getParent())
836 return false;
837
838 unsigned NewOpcode;
839 switch (MI->getOpcode()) {
840 case SP::ANDNrr:
841 NewOpcode = SP::ANDNCCrr;
842 break;
843 case SP::ANDNri:
844 NewOpcode = SP::ANDNCCri;
845 break;
846 case SP::ANDrr:
847 NewOpcode = SP::ANDCCrr;
848 break;
849 case SP::ANDri:
850 NewOpcode = SP::ANDCCri;
851 break;
852 case SP::ORrr:
853 NewOpcode = SP::ORCCrr;
854 break;
855 case SP::ORri:
856 NewOpcode = SP::ORCCri;
857 break;
858 case SP::ORNCCrr:
859 NewOpcode = SP::ORNCCrr;
860 break;
861 case SP::ORNri:
862 NewOpcode = SP::ORNCCri;
863 break;
864 case SP::XORrr:
865 NewOpcode = SP::XORCCrr;
866 break;
867 case SP::XNORri:
868 NewOpcode = SP::XNORCCri;
869 break;
870 case SP::XNORrr:
871 NewOpcode = SP::XNORCCrr;
872 break;
873 case SP::ADDrr:
874 NewOpcode = SP::ADDCCrr;
875 break;
876 case SP::ADDri:
877 NewOpcode = SP::ADDCCri;
878 break;
879 case SP::SUBrr:
880 NewOpcode = SP::SUBCCrr;
881 break;
882 case SP::SUBri:
883 NewOpcode = SP::SUBCCri;
884 break;
885 default:
886 return false;
887 }
888
889 bool IsICCModified = false;
892 MachineBasicBlock::iterator E = CmpInstr.getParent()->end();
894
895 // If ICC is used or modified between MI and CmpInstr we cannot optimize.
896 while (++I != C) {
897 if (I->modifiesRegister(SP::ICC, TRI) || I->readsRegister(SP::ICC, TRI))
898 return false;
899 }
900
901 while (++I != E) {
902 // Only allow conditionals on equality.
903 if (I->readsRegister(SP::ICC, TRI)) {
904 bool IsICCBranch = I->getOpcode() == SP::BCOND ||
905 I->getOpcode() == SP::BPICC ||
906 I->getOpcode() == SP::BPXCC;
907 bool IsICCMove =
908 I->getOpcode() == SP::MOVICCrr || I->getOpcode() == SP::MOVICCri ||
909 I->getOpcode() == SP::MOVXCCrr || I->getOpcode() == SP::MOVXCCri;
910 bool IsICCConditional = IsICCBranch || IsICCMove;
911 if (!IsICCConditional ||
912 (I->getOperand(IsICCBranch ? 1 : 3).getImm() != SPCC::ICC_E &&
913 I->getOperand(IsICCBranch ? 1 : 3).getImm() != SPCC::ICC_NE))
914 return false;
915 } else if (I->modifiesRegister(SP::ICC, TRI)) {
916 IsICCModified = true;
917 break;
918 }
919 }
920
921 if (!IsICCModified) {
922 MachineBasicBlock *MBB = CmpInstr.getParent();
923 if (any_of(MBB->successors(),
924 [](MachineBasicBlock *Succ) { return Succ->isLiveIn(SP::ICC); }))
925 return false;
926 }
927
928 if (MRI->hasOneNonDBGUse(SrcReg))
929 MI->getOperand(0).setReg(SP::G0);
930
931 MI->setDesc(get(NewOpcode));
932 MI->addRegisterDefined(SP::ICC);
933 CmpInstr.eraseFromParent();
934
935 return true;
936}
937
939 switch (MI.getOpcode()) {
940 case TargetOpcode::LOAD_STACK_GUARD: {
941 assert(Subtarget.getTargetTriple().isOSLinux() &&
942 "Only Linux target is expected to contain LOAD_STACK_GUARD");
943 // offsetof(tcbhead_t, stack_guard) from sysdeps/sparc/nptl/tls.h in glibc.
944 const int64_t Offset = Subtarget.is64Bit() ? 0x28 : 0x14;
945 MI.setDesc(get(Subtarget.is64Bit() ? SP::LDXri : SP::LDri));
946 MachineInstrBuilder(*MI.getParent()->getParent(), MI)
947 .addReg(SP::G7)
948 .addImm(Offset);
949 return true;
950 }
951 case SP::V8BAR: {
952 assert(!Subtarget.isV9() &&
953 "V8BAR should not be emitted on V9 processors!");
954
955 // Emit stbar; ldstub [%sp-1], %g0
956 // The sequence acts as a full barrier on V8 systems.
957 MachineBasicBlock &MBB = *MI.getParent();
958 MachineInstr &InstSTBAR =
959 *BuildMI(MBB, MI, MI.getDebugLoc(), get(SP::STBAR));
960 MachineInstr &InstLDSTUB =
961 *BuildMI(MBB, MI, MI.getDebugLoc(), get(SP::LDSTUBri), SP::G0)
962 .addReg(SP::O6)
963 .addImm(-1);
964 MIBundleBuilder(MBB, InstSTBAR, InstLDSTUB);
965 MBB.erase(MI);
966 return true;
967 }
968 }
969 return false;
970}
static void parseCondBranch(MachineInstr *LastInst, MachineBasicBlock *&Target, SmallVectorImpl< MachineOperand > &Cond)
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
MachineBasicBlock & MBB
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
MachineBasicBlock MachineBasicBlock::iterator MBBI
static GCRegistry::Add< ShadowStackGC > C("shadow-stack", "Very portable GC for uncooperative code generators")
IRTranslator LLVM IR MI
#define I(x, y, z)
Definition MD5.cpp:57
Register const TargetRegisterInfo * TRI
Promote Memory to Register
Definition Mem2Reg.cpp:110
SmallVector< MachineOperand, 4 > Cond
RISCVCC::CondCode CC
MachineRegisterInfo & MRI
const SmallVectorImpl< MachineOperand > MachineBasicBlock * TBB
This file declares the machine register scavenger class.
static bool contains(SmallPtrSetImpl< ConstantExpr * > &Cache, ConstantExpr *Expr, Constant *C)
Definition Value.cpp:479
This file defines the SmallVector class.
static bool isFCondBranchOpcode(int Opc)
static bool isRegCondBranchOpcode(int Opc)
static SPCC::CondCodes GetOppositeBranchCondition(SPCC::CondCodes CC)
static bool isI32CondBranchOpcode(int Opc)
static bool isI64CondBranchOpcode(int Opc)
Represent a constant reference to an array (0 or more elements consecutively in memory),...
Definition ArrayRef.h:40
A debug info location.
Definition DebugLoc.h:126
MCRegisterClass - Base class of TargetRegisterClass.
Helper class for constructing bundles of MachineInstrs.
MachineInstrBundleIterator< MachineInstr > iterator
The MachineFrameInfo class represents an abstract stack frame until prolog/epilog code is inserted.
Align getObjectAlign(int ObjectIdx) const
Return the alignment of the specified stack object.
int64_t getObjectSize(int ObjectIdx) const
Return the size of the specified object.
MachineFrameInfo & getFrameInfo()
getFrameInfo - Return the frame info object for the current function.
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
Ty * getInfo()
getInfo - Keep track of various per-function pieces of information for backends that would like to do...
const MachineBasicBlock & front() const
MachineMemOperand * getMachineMemOperand(MachinePointerInfo PtrInfo, MachineMemOperand::Flags F, LLT MemTy, Align BaseAlignment, const MMOMetadata &Metadata=MMOMetadata(), SyncScope::ID SSID=SyncScope::System, AtomicOrdering Ordering=AtomicOrdering::NotAtomic, AtomicOrdering FailureOrdering=AtomicOrdering::NotAtomic)
getMachineMemOperand - Allocate a new MachineMemOperand.
const TargetMachine & getTarget() const
getTarget - Return the target machine this machine code is compiled with
const MachineInstrBuilder & setOperandDead(unsigned OpIdx) const
const MachineInstrBuilder & addReg(Register RegNo, RegState Flags={}, unsigned SubReg=0) const
Add a new virtual register operand.
const MachineInstrBuilder & addImm(int64_t Val) const
Add a new immediate operand.
const MachineInstrBuilder & add(const MachineOperand &MO) const
const MachineInstrBuilder & addFrameIndex(int Idx) const
const MachineInstrBuilder & addMBB(MachineBasicBlock *MBB, unsigned TargetFlags=0) const
const MachineInstrBuilder & addMemOperand(MachineMemOperand *MMO) const
MachineInstr * getInstr() const
If conversion operators fail, use this method to get the MachineInstr explicitly.
Representation of each machine instruction.
unsigned getOpcode() const
Returns the opcode of this MachineInstr.
const MachineBasicBlock * getParent() const
LLVM_ABI bool addRegisterKilled(Register IncomingReg, const TargetRegisterInfo *RegInfo, bool AddIfNotFound=false)
We have determined MI kills a register.
LLVM_ABI void addRegisterDefined(Register Reg, const TargetRegisterInfo *RegInfo=nullptr)
We have determined MI defines a register.
const MachineOperand & getOperand(unsigned i) const
LLVM_ABI MachineInstrBundleIterator< MachineInstr > eraseFromParent()
Unlink 'this' from the containing basic block and delete it.
A description of a memory reference used in the backend.
@ MOLoad
The memory access reads data.
@ MOStore
The memory access writes data.
MachineOperand class - Representation of each machine instruction operand.
int64_t getImm() const
MachineBasicBlock * getMBB() const
bool isImm() const
isImm - Tests if this is a MO_Immediate operand.
static MachineOperand CreateImm(int64_t Val)
MachineRegisterInfo - Keep track of information for virtual and physical registers,...
Wrapper class representing virtual and physical registers.
Definition Register.h:20
constexpr bool isValid() const
Definition Register.h:112
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
bool needsUnimp(const MachineInstr &MI, unsigned &StructSize) const
Register isLoadFromStackSlot(const MachineInstr &MI, int &FrameIndex, TypeSize &MemBytes) const override
isLoadFromStackSlot - If the specified machine instruction is a direct load from a stack slot,...
void copyPhysReg(MachineBasicBlock &MBB, MachineBasicBlock::iterator I, const DebugLoc &DL, Register DestReg, Register SrcReg, bool KillSrc, bool RenamableDest=false, bool RenamableSrc=false) const override
bool isBranchOffsetInRange(unsigned BranchOpc, int64_t Offset) const override
Determine if the branch target is in range.
void storeRegToStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, Register SrcReg, bool isKill, int FrameIndex, const TargetRegisterClass *RC, Register VReg, MachineInstr::MIFlag Flags=MachineInstr::NoFlags) const override
bool analyzeCompare(const MachineInstr &MI, Register &SrcReg, Register &SrcReg2, int64_t &CmpMask, int64_t &CmpValue) const override
bool optimizeCompareInstr(MachineInstr &CmpInstr, Register SrcReg, Register SrcReg2, int64_t CmpMask, int64_t CmpValue, const MachineRegisterInfo *MRI) const override
void insertIndirectBranch(MachineBasicBlock &MBB, MachineBasicBlock &NewDestBB, MachineBasicBlock &RestoreBB, const DebugLoc &DL, int64_t BrOffset, RegScavenger *RS) const override
bool reverseBranchCondition(SmallVectorImpl< MachineOperand > &Cond) const override
Register getGlobalBaseReg(MachineFunction *MF) const
void loadRegFromStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, Register DestReg, int FrameIndex, const TargetRegisterClass *RC, Register VReg, unsigned SubReg=0, MachineInstr::MIFlag Flags=MachineInstr::NoFlags) const override
unsigned removeBranch(MachineBasicBlock &MBB, int *BytesRemoved=nullptr) const override
MachineBasicBlock * getBranchDestBlock(const MachineInstr &MI) const override
bool analyzeBranch(MachineBasicBlock &MBB, MachineBasicBlock *&TBB, MachineBasicBlock *&FBB, SmallVectorImpl< MachineOperand > &Cond, bool AllowModify=false) const override
Register isStoreToStackSlot(const MachineInstr &MI, int &FrameIndex, TypeSize &MemBytes) const override
isStoreToStackSlot - If the specified machine instruction is a direct store to a stack slot,...
SparcInstrInfo(const SparcSubtarget &ST)
const SparcRegisterInfo & getRegisterInfo() const
getRegisterInfo - TargetInstrInfo is a superset of MRegister info.
const TargetRegisterClass * getInlineAsmMemoryOperandRegClass(InlineAsm::ConstraintCode C) const override
unsigned getInstSizeInBytes(const MachineInstr &MI) const override
GetInstSize - Return the number of bytes of code the specified instruction may be.
unsigned insertBranch(MachineBasicBlock &MBB, MachineBasicBlock *TBB, MachineBasicBlock *FBB, ArrayRef< MachineOperand > Cond, const DebugLoc &DL, int *BytesAdded=nullptr) const override
bool expandPostRAPseudo(MachineInstr &MI) const override
Primary interface to the complete machine description for the target machine.
bool isPositionIndependent() const
const MCAsmInfo & getMCAsmInfo() const
Return target specific asm information.
CodeModel::Model getCodeModel() const
Returns the code model.
TargetRegisterInfo base class - We assume that the target defines a static array of TargetRegisterDes...
Target - Wrapper for Target specific information.
static constexpr TypeSize getFixed(ScalarTy ExactSize)
Definition TypeSize.h:352
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
@ CPCC_03
Definition Sparc.h:138
@ CPCC_013
Definition Sparc.h:142
@ FCC_ULE
Definition Sparc.h:124
@ ICC_POS
Definition Sparc.h:104
@ ICC_N
Definition Sparc.h:93
@ CPCC_123
Definition Sparc.h:136
@ ICC_G
Definition Sparc.h:96
@ REG_LEZ
Definition Sparc.h:147
@ CPCC_23
Definition Sparc.h:132
@ ICC_L
Definition Sparc.h:99
@ REG_BEGIN
Definition Sparc.h:145
@ CPCC_01
Definition Sparc.h:141
@ CPCC_12
Definition Sparc.h:135
@ ICC_LEU
Definition Sparc.h:101
@ CPCC_012
Definition Sparc.h:143
@ ICC_LE
Definition Sparc.h:97
@ CPCC_023
Definition Sparc.h:140
@ CPCC_13
Definition Sparc.h:134
@ ICC_GE
Definition Sparc.h:98
@ CPCC_02
Definition Sparc.h:139
@ ICC_NE
Definition Sparc.h:94
@ ICC_E
Definition Sparc.h:95
@ ICC_A
Definition Sparc.h:92
@ FCC_UGE
Definition Sparc.h:122
@ REG_GEZ
Definition Sparc.h:151
@ ICC_NEG
Definition Sparc.h:105
This is an optimization pass for GlobalISel generic memory operations.
@ Offset
Definition DWP.cpp:577
static bool isCondBranchOpcode(int Opc)
MachineInstrBuilder BuildMI(MachineFunction &MF, const MIMetadata &MIMD, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
constexpr bool isInt(int64_t x)
Checks if an integer fits into the given bit width.
Definition MathExtras.h:166
@ Kill
The last use of a register.
constexpr RegState getKillRegState(bool B)
static bool isIndirectBranchOpcode(int Opc)
bool any_of(R &&range, UnaryPredicate P)
Provide wrappers to std::any_of which take ranges instead of having to pass begin/end explicitly.
Definition STLExtras.h:1762
decltype(auto) get(const PointerIntPair< PointerTy, IntBits, IntType, PtrTraits, Info > &Pair)
LLVM_ABI void report_fatal_error(Error Err, bool gen_crash_diag=true)
Definition Error.cpp:163
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Count
Definition InstrProf.h:145
static bool isUncondBranchOpcode(int Opc)
constexpr bool isIntN(unsigned N, int64_t x)
Checks if an signed integer fits into the given (dynamic) bit width.
Definition MathExtras.h:249
MCRegisterClass TargetRegisterClass
Definition FastISel.h:58
static LLVM_ABI MachinePointerInfo getFixedStack(MachineFunction &MF, int FI, int64_t Offset=0)
Return a MachinePointerInfo record that refers to the specified FrameIndex.