LLVM 19.0.0git
M68kInstrInfo.cpp
Go to the documentation of this file.
1//===-- M68kInstrInfo.cpp - M68k Instruction Information --------*- C++ -*-===//
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/// \file
10/// This file contains the M68k declaration of the TargetInstrInfo class.
11///
12//===----------------------------------------------------------------------===//
13
14#include "M68kInstrInfo.h"
15
16#include "M68kInstrBuilder.h"
17#include "M68kMachineFunction.h"
18#include "M68kTargetMachine.h"
20
21#include "llvm/ADT/STLExtras.h"
22#include "llvm/ADT/ScopeExit.h"
29#include "llvm/Support/Regex.h"
30
31#include <functional>
32
33using namespace llvm;
34
35#define DEBUG_TYPE "M68k-instr-info"
36
37#define GET_INSTRINFO_CTOR_DTOR
38#include "M68kGenInstrInfo.inc"
39
40// Pin the vtable to this file.
41void M68kInstrInfo::anchor() {}
42
44 : M68kGenInstrInfo(M68k::ADJCALLSTACKDOWN, M68k::ADJCALLSTACKUP, 0,
45 M68k::RET),
46 Subtarget(STI), RI(STI) {}
47
48static M68k::CondCode getCondFromBranchOpc(unsigned BrOpc) {
49 switch (BrOpc) {
50 default:
51 return M68k::COND_INVALID;
52 case M68k::Beq8:
53 return M68k::COND_EQ;
54 case M68k::Bne8:
55 return M68k::COND_NE;
56 case M68k::Blt8:
57 return M68k::COND_LT;
58 case M68k::Ble8:
59 return M68k::COND_LE;
60 case M68k::Bgt8:
61 return M68k::COND_GT;
62 case M68k::Bge8:
63 return M68k::COND_GE;
64 case M68k::Bcs8:
65 return M68k::COND_CS;
66 case M68k::Bls8:
67 return M68k::COND_LS;
68 case M68k::Bhi8:
69 return M68k::COND_HI;
70 case M68k::Bcc8:
71 return M68k::COND_CC;
72 case M68k::Bmi8:
73 return M68k::COND_MI;
74 case M68k::Bpl8:
75 return M68k::COND_PL;
76 case M68k::Bvs8:
77 return M68k::COND_VS;
78 case M68k::Bvc8:
79 return M68k::COND_VC;
80 }
81}
82
87 bool AllowModify) const {
88
89 auto UncondBranch =
90 std::pair<MachineBasicBlock::reverse_iterator, MachineBasicBlock *>{
91 MBB.rend(), nullptr};
92
93 // Erase any instructions if allowed at the end of the scope.
94 std::vector<std::reference_wrapper<llvm::MachineInstr>> EraseList;
95 auto FinalizeOnReturn = llvm::make_scope_exit([&EraseList] {
96 std::for_each(EraseList.begin(), EraseList.end(),
97 [](auto &ref) { ref.get().eraseFromParent(); });
98 });
99
100 // Start from the bottom of the block and work up, examining the
101 // terminator instructions.
102 for (auto iter = MBB.rbegin(); iter != MBB.rend(); iter = std::next(iter)) {
103
104 unsigned Opcode = iter->getOpcode();
105
106 if (iter->isDebugInstr())
107 continue;
108
109 // Working from the bottom, when we see a non-terminator instruction, we're
110 // done.
111 if (!isUnpredicatedTerminator(*iter))
112 break;
113
114 // A terminator that isn't a branch can't easily be handled by this
115 // analysis.
116 if (!iter->isBranch())
117 return true;
118
119 // Handle unconditional branches.
120 if (Opcode == M68k::BRA8 || Opcode == M68k::BRA16) {
121 if (!iter->getOperand(0).isMBB())
122 return true;
123 UncondBranch = {iter, iter->getOperand(0).getMBB()};
124
125 // TBB is used to indicate the unconditional destination.
126 TBB = UncondBranch.second;
127
128 if (!AllowModify)
129 continue;
130
131 // If the block has any instructions after a JMP, erase them.
132 EraseList.insert(EraseList.begin(), MBB.rbegin(), iter);
133
134 Cond.clear();
135 FBB = nullptr;
136
137 // Erase the JMP if it's equivalent to a fall-through.
138 if (MBB.isLayoutSuccessor(UncondBranch.second)) {
139 TBB = nullptr;
140 EraseList.push_back(*iter);
141 UncondBranch = {MBB.rend(), nullptr};
142 }
143
144 continue;
145 }
146
147 // Handle conditional branches.
148 auto BranchCode = M68k::GetCondFromBranchOpc(Opcode);
149
150 // Can't handle indirect branch.
151 if (BranchCode == M68k::COND_INVALID)
152 return true;
153
154 // In practice we should never have an undef CCR operand, if we do
155 // abort here as we are not prepared to preserve the flag.
156 // ??? Is this required?
157 // if (iter->getOperand(1).isUndef())
158 // return true;
159
160 // Working from the bottom, handle the first conditional branch.
161 if (Cond.empty()) {
162 if (!iter->getOperand(0).isMBB())
163 return true;
164 MachineBasicBlock *CondBranchTarget = iter->getOperand(0).getMBB();
165
166 // If we see something like this:
167 //
168 // bcc l1
169 // bra l2
170 // ...
171 // l1:
172 // ...
173 // l2:
174 if (UncondBranch.first != MBB.rend()) {
175
176 assert(std::next(UncondBranch.first) == iter && "Wrong block layout.");
177
178 // And we are allowed to modify the block and the target block of the
179 // conditional branch is the direct successor of this block:
180 //
181 // bcc l1
182 // bra l2
183 // l1:
184 // ...
185 // l2:
186 //
187 // we change it to this if allowed:
188 //
189 // bncc l2
190 // l1:
191 // ...
192 // l2:
193 //
194 // Which is a bit more efficient.
195 if (AllowModify && MBB.isLayoutSuccessor(CondBranchTarget)) {
196
197 BranchCode = GetOppositeBranchCondition(BranchCode);
198 unsigned BNCC = GetCondBranchFromCond(BranchCode);
199
200 BuildMI(MBB, *UncondBranch.first, MBB.rfindDebugLoc(iter), get(BNCC))
201 .addMBB(UncondBranch.second);
202
203 EraseList.push_back(*iter);
204 EraseList.push_back(*UncondBranch.first);
205
206 TBB = UncondBranch.second;
207 FBB = nullptr;
208 Cond.push_back(MachineOperand::CreateImm(BranchCode));
209
210 // Otherwise preserve TBB, FBB and Cond as requested
211 } else {
212 TBB = CondBranchTarget;
213 FBB = UncondBranch.second;
214 Cond.push_back(MachineOperand::CreateImm(BranchCode));
215 }
216
217 UncondBranch = {MBB.rend(), nullptr};
218 continue;
219 }
220
221 TBB = CondBranchTarget;
222 FBB = nullptr;
223 Cond.push_back(MachineOperand::CreateImm(BranchCode));
224
225 continue;
226 }
227
228 // Handle subsequent conditional branches. Only handle the case where all
229 // conditional branches branch to the same destination and their condition
230 // opcodes fit one of the special multi-branch idioms.
231 assert(Cond.size() == 1);
232 assert(TBB);
233
234 // If the conditions are the same, we can leave them alone.
235 auto OldBranchCode = static_cast<M68k::CondCode>(Cond[0].getImm());
236 if (!iter->getOperand(0).isMBB())
237 return true;
238 auto NewTBB = iter->getOperand(0).getMBB();
239 if (OldBranchCode == BranchCode && TBB == NewTBB)
240 continue;
241
242 // If they differ we cannot do much here.
243 return true;
244 }
245
246 return false;
247}
248
251 MachineBasicBlock *&FBB,
253 bool AllowModify) const {
254 return AnalyzeBranchImpl(MBB, TBB, FBB, Cond, AllowModify);
255}
256
258 int *BytesRemoved) const {
259 assert(!BytesRemoved && "code size not handled");
260
262 unsigned Count = 0;
263
264 while (I != MBB.begin()) {
265 --I;
266 if (I->isDebugValue())
267 continue;
268 if (I->getOpcode() != M68k::BRA8 &&
270 break;
271 // Remove the branch.
272 I->eraseFromParent();
273 I = MBB.end();
274 ++Count;
275 }
276
277 return Count;
278}
279
282 ArrayRef<MachineOperand> Cond, const DebugLoc &DL, int *BytesAdded) const {
283 // Shouldn't be a fall through.
284 assert(TBB && "InsertBranch must not be told to insert a fallthrough");
285 assert((Cond.size() == 1 || Cond.size() == 0) &&
286 "M68k branch conditions have one component!");
287 assert(!BytesAdded && "code size not handled");
288
289 if (Cond.empty()) {
290 // Unconditional branch?
291 assert(!FBB && "Unconditional branch with multiple successors!");
292 BuildMI(&MBB, DL, get(M68k::BRA8)).addMBB(TBB);
293 return 1;
294 }
295
296 // If FBB is null, it is implied to be a fall-through block.
297 bool FallThru = FBB == nullptr;
298
299 // Conditional branch.
300 unsigned Count = 0;
301 M68k::CondCode CC = (M68k::CondCode)Cond[0].getImm();
302 unsigned Opc = GetCondBranchFromCond(CC);
303 BuildMI(&MBB, DL, get(Opc)).addMBB(TBB);
304 ++Count;
305 if (!FallThru) {
306 // Two-way Conditional branch. Insert the second branch.
307 BuildMI(&MBB, DL, get(M68k::BRA8)).addMBB(FBB);
308 ++Count;
309 }
310 return Count;
311}
312
315 unsigned Reg, MVT From, MVT To) const {
316 if (From == MVT::i8) {
317 unsigned R = Reg;
318 // EXT16 requires i16 register
319 if (To == MVT::i32) {
320 R = RI.getSubReg(Reg, M68k::MxSubRegIndex16Lo);
321 assert(R && "No viable SUB register available");
322 }
323 BuildMI(MBB, I, DL, get(M68k::EXT16), R).addReg(R);
324 }
325
326 if (To == MVT::i32)
327 BuildMI(MBB, I, DL, get(M68k::EXT32), Reg).addReg(Reg);
328}
329
332 unsigned Reg, MVT From, MVT To) const {
333
334 unsigned Mask, And;
335 if (From == MVT::i8)
336 Mask = 0xFF;
337 else
338 Mask = 0xFFFF;
339
340 if (To == MVT::i16)
341 And = M68k::AND16di;
342 else // i32
343 And = M68k::AND32di;
344
345 // TODO use xor r,r to decrease size
346 BuildMI(MBB, I, DL, get(And), Reg).addReg(Reg).addImm(Mask);
347}
348
350 MVT MVTSrc) const {
351 unsigned Move = MVTDst == MVT::i16 ? M68k::MOV16rr : M68k::MOV32rr;
352 Register Dst = MIB->getOperand(0).getReg();
353 Register Src = MIB->getOperand(1).getReg();
354
355 assert(Dst != Src && "You cannot use the same Regs with MOVX_RR");
356
357 const auto &TRI = getRegisterInfo();
358
359 const auto *RCDst = TRI.getMaximalPhysRegClass(Dst, MVTDst);
360 const auto *RCSrc = TRI.getMaximalPhysRegClass(Src, MVTSrc);
361
362 assert(RCDst && RCSrc && "Wrong use of MOVX_RR");
363 assert(RCDst != RCSrc && "You cannot use the same Reg Classes with MOVX_RR");
364 (void)RCSrc;
365
366 // We need to find the super source register that matches the size of Dst
367 unsigned SSrc = RI.getMatchingMegaReg(Src, RCDst);
368 assert(SSrc && "No viable MEGA register available");
369
370 DebugLoc DL = MIB->getDebugLoc();
371
372 // If it happens to that super source register is the destination register
373 // we do nothing
374 if (Dst == SSrc) {
375 LLVM_DEBUG(dbgs() << "Remove " << *MIB.getInstr() << '\n');
376 MIB->eraseFromParent();
377 } else { // otherwise we need to MOV
378 LLVM_DEBUG(dbgs() << "Expand " << *MIB.getInstr() << " to MOV\n");
379 MIB->setDesc(get(Move));
380 MIB->getOperand(1).setReg(SSrc);
381 }
382
383 return true;
384}
385
386/// Expand SExt MOVE pseudos into a MOV and a EXT if the operands are two
387/// different registers or just EXT if it is the same register
389 MVT MVTDst, MVT MVTSrc) const {
390 LLVM_DEBUG(dbgs() << "Expand " << *MIB.getInstr() << " to ");
391
392 unsigned Move;
393
394 if (MVTDst == MVT::i16)
395 Move = M68k::MOV16rr;
396 else // i32
397 Move = M68k::MOV32rr;
398
399 Register Dst = MIB->getOperand(0).getReg();
400 Register Src = MIB->getOperand(1).getReg();
401
402 assert(Dst != Src && "You cannot use the same Regs with MOVSX_RR");
403
404 const auto &TRI = getRegisterInfo();
405
406 const auto *RCDst = TRI.getMaximalPhysRegClass(Dst, MVTDst);
407 const auto *RCSrc = TRI.getMaximalPhysRegClass(Src, MVTSrc);
408
409 assert(RCDst && RCSrc && "Wrong use of MOVSX_RR");
410 assert(RCDst != RCSrc && "You cannot use the same Reg Classes with MOVSX_RR");
411 (void)RCSrc;
412
413 // We need to find the super source register that matches the size of Dst
414 unsigned SSrc = RI.getMatchingMegaReg(Src, RCDst);
415 assert(SSrc && "No viable MEGA register available");
416
418 DebugLoc DL = MIB->getDebugLoc();
419
420 if (Dst != SSrc) {
421 LLVM_DEBUG(dbgs() << "Move and " << '\n');
422 BuildMI(MBB, MIB.getInstr(), DL, get(Move), Dst).addReg(SSrc);
423 }
424
425 if (IsSigned) {
426 LLVM_DEBUG(dbgs() << "Sign Extend" << '\n');
427 AddSExt(MBB, MIB.getInstr(), DL, Dst, MVTSrc, MVTDst);
428 } else {
429 LLVM_DEBUG(dbgs() << "Zero Extend" << '\n');
430 AddZExt(MBB, MIB.getInstr(), DL, Dst, MVTSrc, MVTDst);
431 }
432
433 MIB->eraseFromParent();
434
435 return true;
436}
437
439 const MCInstrDesc &Desc, MVT MVTDst,
440 MVT MVTSrc) const {
441 LLVM_DEBUG(dbgs() << "Expand " << *MIB.getInstr() << " to LOAD and ");
442
443 Register Dst = MIB->getOperand(0).getReg();
444
445 // We need the subreg of Dst to make instruction verifier happy because the
446 // real machine instruction consumes and produces values of the same size and
447 // the registers the will be used here fall into different classes and this
448 // makes IV cry. We could use a bigger operation, but this will put some
449 // pressure on cache and memory, so no.
450 unsigned SubDst =
451 RI.getSubReg(Dst, MVTSrc == MVT::i8 ? M68k::MxSubRegIndex8Lo
452 : M68k::MxSubRegIndex16Lo);
453 assert(SubDst && "No viable SUB register available");
454
455 // Make this a plain move
456 MIB->setDesc(Desc);
457 MIB->getOperand(0).setReg(SubDst);
458
460 I++;
462 DebugLoc DL = MIB->getDebugLoc();
463
464 if (IsSigned) {
465 LLVM_DEBUG(dbgs() << "Sign Extend" << '\n');
466 AddSExt(MBB, I, DL, Dst, MVTSrc, MVTDst);
467 } else {
468 LLVM_DEBUG(dbgs() << "Zero Extend" << '\n');
469 AddZExt(MBB, I, DL, Dst, MVTSrc, MVTDst);
470 }
471
472 return true;
473}
474
476 const MCInstrDesc &Desc, bool IsPush) const {
478 I++;
480 MachineOperand MO = MIB->getOperand(0);
481 DebugLoc DL = MIB->getDebugLoc();
482 if (IsPush)
484 else
486
487 MIB->eraseFromParent();
488 return true;
489}
490
491bool M68kInstrInfo::ExpandCCR(MachineInstrBuilder &MIB, bool IsToCCR) const {
492
493 // Replace the pseudo instruction with the real one
494 if (IsToCCR)
495 MIB->setDesc(get(M68k::MOV16cd));
496 else
497 // FIXME M68010 or later is required
498 MIB->setDesc(get(M68k::MOV16dc));
499
500 // Promote used register to the next class
501 auto &Opd = MIB->getOperand(1);
502 Opd.setReg(getRegisterInfo().getMatchingSuperReg(
503 Opd.getReg(), M68k::MxSubRegIndex8Lo, &M68k::DR16RegClass));
504
505 return true;
506}
507
509 const MCInstrDesc &Desc, bool IsRM) const {
510 int Reg = 0, Offset = 0, Base = 0;
511 auto XR32 = RI.getRegClass(M68k::XR32RegClassID);
512 auto DL = MIB->getDebugLoc();
513 auto MI = MIB.getInstr();
514 auto &MBB = *MIB->getParent();
515
516 if (IsRM) {
517 Reg = MIB->getOperand(0).getReg();
518 Offset = MIB->getOperand(1).getImm();
519 Base = MIB->getOperand(2).getReg();
520 } else {
521 Offset = MIB->getOperand(0).getImm();
522 Base = MIB->getOperand(1).getReg();
523 Reg = MIB->getOperand(2).getReg();
524 }
525
526 // If the register is not in XR32 then it is smaller than 32 bit, we
527 // implicitly promote it to 32
528 if (!XR32->contains(Reg)) {
529 Reg = RI.getMatchingMegaReg(Reg, XR32);
530 assert(Reg && "Has not meaningful MEGA register");
531 }
532
533 unsigned Mask = 1 << RI.getSpillRegisterOrder(Reg);
534 if (IsRM) {
535 BuildMI(MBB, MI, DL, Desc)
536 .addImm(Mask)
537 .addImm(Offset)
538 .addReg(Base)
540 .copyImplicitOps(*MIB);
541 } else {
542 BuildMI(MBB, MI, DL, Desc)
543 .addImm(Offset)
544 .addReg(Base)
545 .addImm(Mask)
547 .copyImplicitOps(*MIB);
548 }
549
550 MIB->eraseFromParent();
551
552 return true;
553}
554
555/// Expand a single-def pseudo instruction to a two-addr
556/// instruction with two undef reads of the register being defined.
557/// This is used for mapping:
558/// %d0 = SETCS_C32d
559/// to:
560/// %d0 = SUBX32dd %d0<undef>, %d0<undef>
561///
563 const MCInstrDesc &Desc) {
564 assert(Desc.getNumOperands() == 3 && "Expected two-addr instruction.");
565 Register Reg = MIB->getOperand(0).getReg();
566 MIB->setDesc(Desc);
567
568 // MachineInstr::addOperand() will insert explicit operands before any
569 // implicit operands.
571 // But we don't trust that.
572 assert(MIB->getOperand(1).getReg() == Reg &&
573 MIB->getOperand(2).getReg() == Reg && "Misplaced operand");
574 return true;
575}
576
578 MachineInstrBuilder MIB(*MI.getParent()->getParent(), MI);
579 switch (MI.getOpcode()) {
580 case M68k::PUSH8d:
581 return ExpandPUSH_POP(MIB, get(M68k::MOV8ed), true);
582 case M68k::PUSH16d:
583 return ExpandPUSH_POP(MIB, get(M68k::MOV16er), true);
584 case M68k::PUSH32r:
585 return ExpandPUSH_POP(MIB, get(M68k::MOV32er), true);
586
587 case M68k::POP8d:
588 return ExpandPUSH_POP(MIB, get(M68k::MOV8do), false);
589 case M68k::POP16d:
590 return ExpandPUSH_POP(MIB, get(M68k::MOV16ro), false);
591 case M68k::POP32r:
592 return ExpandPUSH_POP(MIB, get(M68k::MOV32ro), false);
593
594 case M68k::SETCS_C8d:
595 return Expand2AddrUndef(MIB, get(M68k::SUBX8dd));
596 case M68k::SETCS_C16d:
597 return Expand2AddrUndef(MIB, get(M68k::SUBX16dd));
598 case M68k::SETCS_C32d:
599 return Expand2AddrUndef(MIB, get(M68k::SUBX32dd));
600 }
601 return false;
602}
603
605 const MachineOperand &MO) const {
606 assert(MO.isReg());
607
608 // Check whether this MO belongs to an instruction with addressing mode 'k',
609 // Refer to TargetInstrInfo.h for more information about this function.
610
611 const MachineInstr *MI = MO.getParent();
612 const unsigned NameIndices = M68kInstrNameIndices[MI->getOpcode()];
613 StringRef InstrName(&M68kInstrNameData[NameIndices]);
614 const unsigned OperandNo = MO.getOperandNo();
615
616 // If this machine operand is the 2nd operand, then check
617 // whether the instruction has destination addressing mode 'k'.
618 if (OperandNo == 1)
619 return Regex("[A-Z]+(8|16|32)k[a-z](_TC)?$").match(InstrName);
620
621 // If this machine operand is the last one, then check
622 // whether the instruction has source addressing mode 'k'.
623 if (OperandNo == MI->getNumExplicitOperands() - 1)
624 return Regex("[A-Z]+(8|16|32)[a-z]k(_TC)?$").match(InstrName);
625
626 return false;
627}
628
631 const DebugLoc &DL, MCRegister DstReg,
632 MCRegister SrcReg, bool KillSrc) const {
633 unsigned Opc = 0;
634
635 // First deal with the normal symmetric copies.
636 if (M68k::XR32RegClass.contains(DstReg, SrcReg))
637 Opc = M68k::MOV32rr;
638 else if (M68k::XR16RegClass.contains(DstReg, SrcReg))
639 Opc = M68k::MOV16rr;
640 else if (M68k::DR8RegClass.contains(DstReg, SrcReg))
641 Opc = M68k::MOV8dd;
642
643 if (Opc) {
644 BuildMI(MBB, MI, DL, get(Opc), DstReg)
645 .addReg(SrcReg, getKillRegState(KillSrc));
646 return;
647 }
648
649 // Now deal with asymmetrically sized copies. The cases that follow are upcast
650 // moves.
651 //
652 // NOTE
653 // These moves are not aware of type nature of these values and thus
654 // won't do any SExt or ZExt and upper bits will basically contain garbage.
656 if (M68k::DR8RegClass.contains(SrcReg)) {
657 if (M68k::XR16RegClass.contains(DstReg))
658 Opc = M68k::MOVXd16d8;
659 else if (M68k::XR32RegClass.contains(DstReg))
660 Opc = M68k::MOVXd32d8;
661 } else if (M68k::XR16RegClass.contains(SrcReg) &&
662 M68k::XR32RegClass.contains(DstReg))
663 Opc = M68k::MOVXd32d16;
664
665 if (Opc) {
666 BuildMI(MBB, MI, DL, get(Opc), DstReg)
667 .addReg(SrcReg, getKillRegState(KillSrc));
668 return;
669 }
670
671 bool FromCCR = SrcReg == M68k::CCR;
672 bool FromSR = SrcReg == M68k::SR;
673 bool ToCCR = DstReg == M68k::CCR;
674 bool ToSR = DstReg == M68k::SR;
675
676 if (FromCCR) {
677 assert(M68k::DR8RegClass.contains(DstReg) &&
678 "Need DR8 register to copy CCR");
679 Opc = M68k::MOV8dc;
680 } else if (ToCCR) {
681 assert(M68k::DR8RegClass.contains(SrcReg) &&
682 "Need DR8 register to copy CCR");
683 Opc = M68k::MOV8cd;
684 } else if (FromSR || ToSR)
685 llvm_unreachable("Cannot emit SR copy instruction");
686
687 if (Opc) {
688 BuildMI(MBB, MI, DL, get(Opc), DstReg)
689 .addReg(SrcReg, getKillRegState(KillSrc));
690 return;
691 }
692
693 LLVM_DEBUG(dbgs() << "Cannot copy " << RI.getName(SrcReg) << " to "
694 << RI.getName(DstReg) << '\n');
695 llvm_unreachable("Cannot emit physreg copy instruction");
696}
697
698namespace {
699unsigned getLoadStoreRegOpcode(unsigned Reg, const TargetRegisterClass *RC,
700 const TargetRegisterInfo *TRI,
701 const M68kSubtarget &STI, bool load) {
702 switch (TRI->getRegSizeInBits(*RC)) {
703 default:
704 llvm_unreachable("Unknown spill size");
705 case 8:
706 if (M68k::DR8RegClass.hasSubClassEq(RC))
707 return load ? M68k::MOV8dp : M68k::MOV8pd;
708 if (M68k::CCRCRegClass.hasSubClassEq(RC))
709 return load ? M68k::MOV16cp : M68k::MOV16pc;
710
711 llvm_unreachable("Unknown 1-byte regclass");
712 case 16:
713 assert(M68k::XR16RegClass.hasSubClassEq(RC) && "Unknown 2-byte regclass");
714 return load ? M68k::MOVM16mp_P : M68k::MOVM16pm_P;
715 case 32:
716 assert(M68k::XR32RegClass.hasSubClassEq(RC) && "Unknown 4-byte regclass");
717 return load ? M68k::MOVM32mp_P : M68k::MOVM32pm_P;
718 }
719}
720
721unsigned getStoreRegOpcode(unsigned SrcReg, const TargetRegisterClass *RC,
722 const TargetRegisterInfo *TRI,
723 const M68kSubtarget &STI) {
724 return getLoadStoreRegOpcode(SrcReg, RC, TRI, STI, false);
725}
726
727unsigned getLoadRegOpcode(unsigned DstReg, const TargetRegisterClass *RC,
728 const TargetRegisterInfo *TRI,
729 const M68kSubtarget &STI) {
730 return getLoadStoreRegOpcode(DstReg, RC, TRI, STI, true);
731}
732} // end anonymous namespace
733
735 unsigned SubIdx, unsigned &Size,
736 unsigned &Offset,
737 const MachineFunction &MF) const {
738 // The slot size must be the maximum size so we can easily use MOVEM.L
739 Size = 4;
740 Offset = 0;
741 return true;
742}
743
746 bool IsKill, int FrameIndex, const TargetRegisterClass *RC,
747 const TargetRegisterInfo *TRI, Register VReg) const {
748 const MachineFrameInfo &MFI = MBB.getParent()->getFrameInfo();
749 assert(MFI.getObjectSize(FrameIndex) >= TRI->getSpillSize(*RC) &&
750 "Stack slot is too small to store");
751 (void)MFI;
752
753 unsigned Opc = getStoreRegOpcode(SrcReg, RC, TRI, Subtarget);
755 // (0,FrameIndex) <- $reg
756 M68k::addFrameReference(BuildMI(MBB, MI, DL, get(Opc)), FrameIndex)
757 .addReg(SrcReg, getKillRegState(IsKill));
758}
759
762 Register DstReg, int FrameIndex,
763 const TargetRegisterClass *RC,
764 const TargetRegisterInfo *TRI,
765 Register VReg) const {
766 const MachineFrameInfo &MFI = MBB.getParent()->getFrameInfo();
767 assert(MFI.getObjectSize(FrameIndex) >= TRI->getSpillSize(*RC) &&
768 "Stack slot is too small to load");
769 (void)MFI;
770
771 unsigned Opc = getLoadRegOpcode(DstReg, RC, TRI, Subtarget);
773 M68k::addFrameReference(BuildMI(MBB, MI, DL, get(Opc), DstReg), FrameIndex);
774}
775
776/// Return a virtual register initialized with the global base register
777/// value. Output instructions required to initialize the register in the
778/// function entry block, if necessary.
779///
780/// TODO Move this function to M68kMachineFunctionInfo.
783 unsigned GlobalBaseReg = MxFI->getGlobalBaseReg();
784 if (GlobalBaseReg != 0)
785 return GlobalBaseReg;
786
787 // Create the register. The code to initialize it is inserted later,
788 // by the M68kGlobalBaseReg pass (below).
789 //
790 // NOTE
791 // Normally M68k uses A5 register as global base pointer but this will
792 // create unnecessary spill if we use less then 4 registers in code; since A5
793 // is callee-save anyway we could try to allocate caller-save first and if
794 // lucky get one, otherwise it does not really matter which callee-save to
795 // use.
796 MachineRegisterInfo &RegInfo = MF->getRegInfo();
797 GlobalBaseReg = RegInfo.createVirtualRegister(&M68k::AR32_NOSPRegClass);
798 MxFI->setGlobalBaseReg(GlobalBaseReg);
799 return GlobalBaseReg;
800}
801
802std::pair<unsigned, unsigned>
804 return std::make_pair(TF, 0u);
805}
806
809 using namespace M68kII;
810 static const std::pair<unsigned, const char *> TargetFlags[] = {
811 {MO_ABSOLUTE_ADDRESS, "m68k-absolute"},
812 {MO_PC_RELATIVE_ADDRESS, "m68k-pcrel"},
813 {MO_GOT, "m68k-got"},
814 {MO_GOTOFF, "m68k-gotoff"},
815 {MO_GOTPCREL, "m68k-gotpcrel"},
816 {MO_PLT, "m68k-plt"},
817 {MO_TLSGD, "m68k-tlsgd"},
818 {MO_TLSLD, "m68k-tlsld"},
819 {MO_TLSLDM, "m68k-tlsldm"},
820 {MO_TLSIE, "m68k-tlsie"},
821 {MO_TLSLE, "m68k-tlsle"}};
822 return ArrayRef(TargetFlags);
823}
824
825#undef DEBUG_TYPE
826#define DEBUG_TYPE "m68k-create-global-base-reg"
827
828#define PASS_NAME "M68k PIC Global Base Reg Initialization"
829
830namespace {
831/// This initializes the PIC global base register
832struct M68kGlobalBaseReg : public MachineFunctionPass {
833 static char ID;
834 M68kGlobalBaseReg() : MachineFunctionPass(ID) {}
835
836 bool runOnMachineFunction(MachineFunction &MF) override {
837 const M68kSubtarget &STI = MF.getSubtarget<M68kSubtarget>();
839
840 unsigned GlobalBaseReg = MxFI->getGlobalBaseReg();
841
842 // If we didn't need a GlobalBaseReg, don't insert code.
843 if (GlobalBaseReg == 0)
844 return false;
845
846 // Insert the set of GlobalBaseReg into the first MBB of the function
847 MachineBasicBlock &FirstMBB = MF.front();
849 DebugLoc DL = FirstMBB.findDebugLoc(MBBI);
850 const M68kInstrInfo *TII = STI.getInstrInfo();
851
852 // Generate lea (__GLOBAL_OFFSET_TABLE_,%PC), %A5
853 BuildMI(FirstMBB, MBBI, DL, TII->get(M68k::LEA32q), GlobalBaseReg)
854 .addExternalSymbol("_GLOBAL_OFFSET_TABLE_", M68kII::MO_GOTPCREL);
855
856 return true;
857 }
858
859 void getAnalysisUsage(AnalysisUsage &AU) const override {
860 AU.setPreservesCFG();
862 }
863};
864char M68kGlobalBaseReg::ID = 0;
865} // namespace
866
867INITIALIZE_PASS(M68kGlobalBaseReg, DEBUG_TYPE, PASS_NAME, false, false)
868
870 return new M68kGlobalBaseReg();
871}
MachineBasicBlock & MBB
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
MachineBasicBlock MachineBasicBlock::iterator MBBI
AMDGPU Mark last scratch load
BlockVerifier::State From
#define LLVM_DEBUG(X)
Definition: Debug.h:101
uint64_t Size
#define DEBUG_TYPE
const HexagonInstrInfo * TII
IRTranslator LLVM IR MI
This file implements the LivePhysRegs utility for tracking liveness of physical registers.
This file exposes functions that may be used with BuildMI from the MachineInstrBuilder....
static M68k::CondCode getCondFromBranchOpc(unsigned BrOpc)
static bool Expand2AddrUndef(MachineInstrBuilder &MIB, const MCInstrDesc &Desc)
Expand a single-def pseudo instruction to a two-addr instruction with two undef reads of the register...
This file contains the M68k implementation of the TargetInstrInfo class.
This file contains the declarations for the code emitter which are useful outside of the emitter itse...
This file declares the M68k specific subclass of MachineFunctionInfo.
This file declares the M68k specific subclass of TargetMachine.
#define I(x, y, z)
Definition: MD5.cpp:58
unsigned const TargetRegisterInfo * TRI
#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)
Definition: PassSupport.h:38
const SmallVectorImpl< MachineOperand > MachineBasicBlock * TBB
const SmallVectorImpl< MachineOperand > & Cond
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
This file contains some templates that are useful if you are working with the STL at all.
This file defines the make_scope_exit function, which executes user-defined cleanup logic at scope ex...
static SPCC::CondCodes GetOppositeBranchCondition(SPCC::CondCodes CC)
#define PASS_NAME
static bool contains(SmallPtrSetImpl< ConstantExpr * > &Cache, ConstantExpr *Expr, Constant *C)
Definition: Value.cpp:469
static unsigned getStoreRegOpcode(Register SrcReg, const TargetRegisterClass *RC, bool IsStackAligned, const X86Subtarget &STI)
static unsigned getLoadRegOpcode(Register DestReg, const TargetRegisterClass *RC, bool IsStackAligned, const X86Subtarget &STI)
static unsigned getLoadStoreRegOpcode(Register Reg, const TargetRegisterClass *RC, bool IsStackAligned, const X86Subtarget &STI, bool Load)
static unsigned GetCondBranchFromCond(XCore::CondCode CC)
GetCondBranchFromCond - Return the Branch instruction opcode that matches the cc.
Represent the analysis usage information of a pass.
void setPreservesCFG()
This function should be called by the pass, iff they do not:
Definition: Pass.cpp:269
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
Definition: ArrayRef.h:41
A debug info location.
Definition: DebugLoc.h:33
FunctionPass class - This class is used to implement most global optimizations.
Definition: Pass.h:311
unsigned getGlobalBaseReg(MachineFunction *MF) const
Return a virtual register initialized with the global base register value.
const M68kSubtarget & Subtarget
bool ExpandMOVSZX_RR(MachineInstrBuilder &MIB, bool IsSigned, MVT MVTDst, MVT MVTSrc) const
Move from register and extend.
const M68kRegisterInfo & getRegisterInfo() const
TargetInstrInfo is a superset of MRegister info.
const M68kRegisterInfo RI
bool analyzeBranch(MachineBasicBlock &MBB, MachineBasicBlock *&TBB, MachineBasicBlock *&FBB, SmallVectorImpl< MachineOperand > &Cond, bool AllowModify) const override
ArrayRef< std::pair< unsigned, const char * > > getSerializableDirectMachineOperandTargetFlags() const override
bool expandPostRAPseudo(MachineInstr &MI) const override
unsigned insertBranch(MachineBasicBlock &MBB, MachineBasicBlock *TBB, MachineBasicBlock *FBB, ArrayRef< MachineOperand > Cond, const DebugLoc &DL, int *BytesAdded=nullptr) const override
void loadRegFromStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, Register DestReg, int FrameIndex, const TargetRegisterClass *RC, const TargetRegisterInfo *TRI, Register VReg) const override
void storeRegToStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, Register SrcReg, bool IsKill, int FrameIndex, const TargetRegisterClass *RC, const TargetRegisterInfo *TRI, Register VReg) const override
std::pair< unsigned, unsigned > decomposeMachineOperandsTargetFlags(unsigned TF) const override
bool AnalyzeBranchImpl(MachineBasicBlock &MBB, MachineBasicBlock *&TBB, MachineBasicBlock *&FBB, SmallVectorImpl< MachineOperand > &Cond, bool AllowModify) const
bool isPCRelRegisterOperandLegal(const MachineOperand &MO) const override
bool ExpandMOVX_RR(MachineInstrBuilder &MIB, MVT MVTDst, MVT MVTSrc) const
Move across register classes without extension.
bool ExpandMOVEM(MachineInstrBuilder &MIB, const MCInstrDesc &Desc, bool IsRM) const
Expand all MOVEM pseudos into real MOVEMs.
unsigned removeBranch(MachineBasicBlock &MBB, int *BytesRemoved=nullptr) const override
bool ExpandPUSH_POP(MachineInstrBuilder &MIB, const MCInstrDesc &Desc, bool IsPush) const
Push/Pop to/from stack.
M68kInstrInfo(const M68kSubtarget &STI)
void AddZExt(MachineBasicBlock &MBB, MachineBasicBlock::iterator I, DebugLoc DL, unsigned Reg, MVT From, MVT To) const
Add appropriate ZExt nodes.
void copyPhysReg(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, const DebugLoc &DL, MCRegister DestReg, MCRegister SrcReg, bool KillSrc) const override
bool ExpandCCR(MachineInstrBuilder &MIB, bool IsToCCR) const
Moves to/from CCR.
bool ExpandMOVSZX_RM(MachineInstrBuilder &MIB, bool IsSigned, const MCInstrDesc &Desc, MVT MVTDst, MVT MVTSrc) const
Move from memory and extend.
bool getStackSlotRange(const TargetRegisterClass *RC, unsigned SubIdx, unsigned &Size, unsigned &Offset, const MachineFunction &MF) const override
void AddSExt(MachineBasicBlock &MBB, MachineBasicBlock::iterator I, DebugLoc DL, unsigned Reg, MVT From, MVT To) const
Add appropriate SExt nodes.
unsigned getMatchingMegaReg(unsigned Reg, const TargetRegisterClass *RC) const
Return a mega-register of the specified register Reg so its sub-register of index SubIdx is Reg,...
int getSpillRegisterOrder(unsigned Reg) const
Return spill order index of a register, if there is none then trap.
unsigned getStackRegister() const
const M68kInstrInfo * getInstrInfo() const override
Describe properties that are true of each instruction in the target description file.
Definition: MCInstrDesc.h:198
Wrapper class representing physical registers. Should be passed by value.
Definition: MCRegister.h:33
Machine Value Type.
reverse_iterator rend()
instr_iterator insert(instr_iterator I, MachineInstr *M)
Insert MI into the instruction list before I, possibly inside a bundle.
void push_back(MachineInstr *MI)
DebugLoc rfindDebugLoc(reverse_instr_iterator MBBI)
Has exact same behavior as findDebugLoc (it also searches towards the end of this MBB) except that th...
DebugLoc findDebugLoc(instr_iterator MBBI)
Find the next valid DebugLoc starting at MBBI, skipping any debug instructions.
bool isLayoutSuccessor(const MachineBasicBlock *MBB) const
Return true if the specified MBB will be emitted immediately after this block, such that if this bloc...
const MachineFunction * getParent() const
Return the MachineFunction containing this basic block.
reverse_iterator rbegin()
The MachineFrameInfo class represents an abstract stack frame until prolog/epilog code is inserted.
int64_t getObjectSize(int ObjectIdx) const
Return the size of the specified object.
MachineFunctionPass - This class adapts the FunctionPass interface to allow convenient creation of pa...
void getAnalysisUsage(AnalysisUsage &AU) const override
getAnalysisUsage - Subclasses that override getAnalysisUsage must call this.
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
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
const MachineInstrBuilder & addExternalSymbol(const char *FnName, unsigned TargetFlags=0) const
const MachineInstrBuilder & addImm(int64_t Val) const
Add a new immediate operand.
const MachineInstrBuilder & add(const MachineOperand &MO) const
const MachineInstrBuilder & addReg(Register RegNo, unsigned flags=0, unsigned SubReg=0) const
Add a new virtual register operand.
const MachineInstrBuilder & addMBB(MachineBasicBlock *MBB, unsigned TargetFlags=0) const
const MachineInstrBuilder & copyImplicitOps(const MachineInstr &OtherMI) const
Copy all the implicit operands from OtherMI onto this one.
MachineInstr * getInstr() const
If conversion operators fail, use this method to get the MachineInstr explicitly.
Representation of each machine instruction.
Definition: MachineInstr.h:69
const MachineBasicBlock * getParent() const
Definition: MachineInstr.h:341
void setDesc(const MCInstrDesc &TID)
Replace the instruction descriptor (thus opcode) of the current instruction with a new one.
const DebugLoc & getDebugLoc() const
Returns the debug location id of this MachineInstr.
Definition: MachineInstr.h:487
void eraseFromParent()
Unlink 'this' from the containing basic block and delete it.
const MachineOperand & getOperand(unsigned i) const
Definition: MachineInstr.h:568
MachineOperand class - Representation of each machine instruction operand.
unsigned getOperandNo() const
Returns the index of this operand in the instruction that it belongs to.
int64_t getImm() const
bool isReg() const
isReg - Tests if this is a MO_Register operand.
void setReg(Register Reg)
Change the register this operand corresponds to.
MachineInstr * getParent()
getParent - Return the instruction that this operand belongs to.
static MachineOperand CreateImm(int64_t Val)
Register getReg() const
getReg - Returns the register number.
MachineRegisterInfo - Keep track of information for virtual and physical registers,...
Register createVirtualRegister(const TargetRegisterClass *RegClass, StringRef Name="")
createVirtualRegister - Create and return a new virtual register in the function with the specified r...
bool match(StringRef String, SmallVectorImpl< StringRef > *Matches=nullptr, std::string *Error=nullptr) const
matches - Match the regex against a given String.
Definition: Regex.cpp:83
Wrapper class representing virtual and physical registers.
Definition: Register.h:19
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
Definition: SmallVector.h:586
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:50
TargetRegisterInfo base class - We assume that the target defines a static array of TargetRegisterDes...
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
Definition: CallingConv.h:24
@ MO_GOTPCREL
On a symbol operand this indicates that the immediate is offset to the GOT entry for the symbol name ...
Definition: M68kBaseInfo.h:153
static const MachineInstrBuilder & addFrameReference(const MachineInstrBuilder &MIB, int FI, int Offset=0)
addFrameReference - This function is used to add a reference to the base of an abstract object on the...
static M68k::CondCode GetCondFromBranchOpc(unsigned Opcode)
@ Implicit
Not emitted register (e.g. carry, or temporary result).
@ Undef
Value of the register doesn't matter.
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
@ Offset
Definition: DWP.cpp:456
MachineInstrBuilder BuildMI(MachineFunction &MF, const MIMetadata &MIMD, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
detail::scope_exit< std::decay_t< Callable > > make_scope_exit(Callable &&F)
Definition: ScopeExit.h:59
FunctionPass * createM68kGlobalBaseRegPass()
This pass initializes a global base register for PIC on M68k.
decltype(auto) get(const PointerIntPair< PointerTy, IntBits, IntType, PtrTraits, Info > &Pair)
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition: Debug.cpp:163
@ And
Bitwise or logical AND of integers.
unsigned getKillRegState(bool B)
Description of the encoding of one expression Op.