LLVM 20.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"
31#include "llvm/Support/Regex.h"
32
33#include <functional>
34
35using namespace llvm;
36
37#define DEBUG_TYPE "M68k-instr-info"
38
39#define GET_INSTRINFO_CTOR_DTOR
40#include "M68kGenInstrInfo.inc"
41
42// Pin the vtable to this file.
43void M68kInstrInfo::anchor() {}
44
46 : M68kGenInstrInfo(M68k::ADJCALLSTACKDOWN, M68k::ADJCALLSTACKUP, 0,
47 M68k::RET),
48 Subtarget(STI), RI(STI) {}
49
50static M68k::CondCode getCondFromBranchOpc(unsigned BrOpc) {
51 switch (BrOpc) {
52 default:
53 return M68k::COND_INVALID;
54 case M68k::Beq8:
55 return M68k::COND_EQ;
56 case M68k::Bne8:
57 return M68k::COND_NE;
58 case M68k::Blt8:
59 return M68k::COND_LT;
60 case M68k::Ble8:
61 return M68k::COND_LE;
62 case M68k::Bgt8:
63 return M68k::COND_GT;
64 case M68k::Bge8:
65 return M68k::COND_GE;
66 case M68k::Bcs8:
67 return M68k::COND_CS;
68 case M68k::Bls8:
69 return M68k::COND_LS;
70 case M68k::Bhi8:
71 return M68k::COND_HI;
72 case M68k::Bcc8:
73 return M68k::COND_CC;
74 case M68k::Bmi8:
75 return M68k::COND_MI;
76 case M68k::Bpl8:
77 return M68k::COND_PL;
78 case M68k::Bvs8:
79 return M68k::COND_VS;
80 case M68k::Bvc8:
81 return M68k::COND_VC;
82 }
83}
84
89 bool AllowModify) const {
90
91 auto UncondBranch =
92 std::pair<MachineBasicBlock::reverse_iterator, MachineBasicBlock *>{
93 MBB.rend(), nullptr};
94
95 // Erase any instructions if allowed at the end of the scope.
96 std::vector<std::reference_wrapper<llvm::MachineInstr>> EraseList;
97 auto FinalizeOnReturn = llvm::make_scope_exit([&EraseList] {
98 std::for_each(EraseList.begin(), EraseList.end(),
99 [](auto &ref) { ref.get().eraseFromParent(); });
100 });
101
102 // Start from the bottom of the block and work up, examining the
103 // terminator instructions.
104 for (auto iter = MBB.rbegin(); iter != MBB.rend(); iter = std::next(iter)) {
105
106 unsigned Opcode = iter->getOpcode();
107
108 if (iter->isDebugInstr())
109 continue;
110
111 // Working from the bottom, when we see a non-terminator instruction, we're
112 // done.
113 if (!isUnpredicatedTerminator(*iter))
114 break;
115
116 // A terminator that isn't a branch can't easily be handled by this
117 // analysis.
118 if (!iter->isBranch())
119 return true;
120
121 // Handle unconditional branches.
122 if (Opcode == M68k::BRA8 || Opcode == M68k::BRA16) {
123 if (!iter->getOperand(0).isMBB())
124 return true;
125 UncondBranch = {iter, iter->getOperand(0).getMBB()};
126
127 // TBB is used to indicate the unconditional destination.
128 TBB = UncondBranch.second;
129
130 if (!AllowModify)
131 continue;
132
133 // If the block has any instructions after a JMP, erase them.
134 EraseList.insert(EraseList.begin(), MBB.rbegin(), iter);
135
136 Cond.clear();
137 FBB = nullptr;
138
139 // Erase the JMP if it's equivalent to a fall-through.
140 if (MBB.isLayoutSuccessor(UncondBranch.second)) {
141 TBB = nullptr;
142 EraseList.push_back(*iter);
143 UncondBranch = {MBB.rend(), nullptr};
144 }
145
146 continue;
147 }
148
149 // Handle conditional branches.
150 auto BranchCode = M68k::GetCondFromBranchOpc(Opcode);
151
152 // Can't handle indirect branch.
153 if (BranchCode == M68k::COND_INVALID)
154 return true;
155
156 // In practice we should never have an undef CCR operand, if we do
157 // abort here as we are not prepared to preserve the flag.
158 // ??? Is this required?
159 // if (iter->getOperand(1).isUndef())
160 // return true;
161
162 // Working from the bottom, handle the first conditional branch.
163 if (Cond.empty()) {
164 if (!iter->getOperand(0).isMBB())
165 return true;
166 MachineBasicBlock *CondBranchTarget = iter->getOperand(0).getMBB();
167
168 // If we see something like this:
169 //
170 // bcc l1
171 // bra l2
172 // ...
173 // l1:
174 // ...
175 // l2:
176 if (UncondBranch.first != MBB.rend()) {
177
178 assert(std::next(UncondBranch.first) == iter && "Wrong block layout.");
179
180 // And we are allowed to modify the block and the target block of the
181 // conditional branch is the direct successor of this block:
182 //
183 // bcc l1
184 // bra l2
185 // l1:
186 // ...
187 // l2:
188 //
189 // we change it to this if allowed:
190 //
191 // bncc l2
192 // l1:
193 // ...
194 // l2:
195 //
196 // Which is a bit more efficient.
197 if (AllowModify && MBB.isLayoutSuccessor(CondBranchTarget)) {
198
199 BranchCode = GetOppositeBranchCondition(BranchCode);
200 unsigned BNCC = GetCondBranchFromCond(BranchCode);
201
202 BuildMI(MBB, *UncondBranch.first, MBB.rfindDebugLoc(iter), get(BNCC))
203 .addMBB(UncondBranch.second);
204
205 EraseList.push_back(*iter);
206 EraseList.push_back(*UncondBranch.first);
207
208 TBB = UncondBranch.second;
209 FBB = nullptr;
210 Cond.push_back(MachineOperand::CreateImm(BranchCode));
211
212 // Otherwise preserve TBB, FBB and Cond as requested
213 } else {
214 TBB = CondBranchTarget;
215 FBB = UncondBranch.second;
216 Cond.push_back(MachineOperand::CreateImm(BranchCode));
217 }
218
219 UncondBranch = {MBB.rend(), nullptr};
220 continue;
221 }
222
223 TBB = CondBranchTarget;
224 FBB = nullptr;
225 Cond.push_back(MachineOperand::CreateImm(BranchCode));
226
227 continue;
228 }
229
230 // Handle subsequent conditional branches. Only handle the case where all
231 // conditional branches branch to the same destination and their condition
232 // opcodes fit one of the special multi-branch idioms.
233 assert(Cond.size() == 1);
234 assert(TBB);
235
236 // If the conditions are the same, we can leave them alone.
237 auto OldBranchCode = static_cast<M68k::CondCode>(Cond[0].getImm());
238 if (!iter->getOperand(0).isMBB())
239 return true;
240 auto NewTBB = iter->getOperand(0).getMBB();
241 if (OldBranchCode == BranchCode && TBB == NewTBB)
242 continue;
243
244 // If they differ we cannot do much here.
245 return true;
246 }
247
248 return false;
249}
250
253 MachineBasicBlock *&FBB,
255 bool AllowModify) const {
256 return AnalyzeBranchImpl(MBB, TBB, FBB, Cond, AllowModify);
257}
258
260 int *BytesRemoved) const {
261 assert(!BytesRemoved && "code size not handled");
262
264 unsigned Count = 0;
265
266 while (I != MBB.begin()) {
267 --I;
268 if (I->isDebugValue())
269 continue;
270 if (I->getOpcode() != M68k::BRA8 &&
272 break;
273 // Remove the branch.
274 I->eraseFromParent();
275 I = MBB.end();
276 ++Count;
277 }
278
279 return Count;
280}
281
284 ArrayRef<MachineOperand> Cond, const DebugLoc &DL, int *BytesAdded) const {
285 // Shouldn't be a fall through.
286 assert(TBB && "InsertBranch must not be told to insert a fallthrough");
287 assert((Cond.size() == 1 || Cond.size() == 0) &&
288 "M68k branch conditions have one component!");
289 assert(!BytesAdded && "code size not handled");
290
291 if (Cond.empty()) {
292 // Unconditional branch?
293 assert(!FBB && "Unconditional branch with multiple successors!");
294 BuildMI(&MBB, DL, get(M68k::BRA8)).addMBB(TBB);
295 return 1;
296 }
297
298 // If FBB is null, it is implied to be a fall-through block.
299 bool FallThru = FBB == nullptr;
300
301 // Conditional branch.
302 unsigned Count = 0;
303 M68k::CondCode CC = (M68k::CondCode)Cond[0].getImm();
304 unsigned Opc = GetCondBranchFromCond(CC);
305 BuildMI(&MBB, DL, get(Opc)).addMBB(TBB);
306 ++Count;
307 if (!FallThru) {
308 // Two-way Conditional branch. Insert the second branch.
309 BuildMI(&MBB, DL, get(M68k::BRA8)).addMBB(FBB);
310 ++Count;
311 }
312 return Count;
313}
314
317 unsigned Reg, MVT From, MVT To) const {
318 if (From == MVT::i8) {
319 unsigned R = Reg;
320 // EXT16 requires i16 register
321 if (To == MVT::i32) {
322 R = RI.getSubReg(Reg, M68k::MxSubRegIndex16Lo);
323 assert(R && "No viable SUB register available");
324 }
325 BuildMI(MBB, I, DL, get(M68k::EXT16), R).addReg(R);
326 }
327
328 if (To == MVT::i32)
329 BuildMI(MBB, I, DL, get(M68k::EXT32), Reg).addReg(Reg);
330}
331
334 unsigned Reg, MVT From, MVT To) const {
335
336 unsigned Mask, And;
337 if (From == MVT::i8)
338 Mask = 0xFF;
339 else
340 Mask = 0xFFFF;
341
342 if (To == MVT::i16)
343 And = M68k::AND16di;
344 else // i32
345 And = M68k::AND32di;
346
347 // TODO use xor r,r to decrease size
348 BuildMI(MBB, I, DL, get(And), Reg).addReg(Reg).addImm(Mask);
349}
350
351// Convert MOVI to the appropriate instruction (sequence) for setting
352// the register to an immediate value.
354 Register Reg = MIB->getOperand(0).getReg();
355 int64_t Imm = MIB->getOperand(1).getImm();
356 bool IsAddressReg = false;
357
358 const auto *DR32 = RI.getRegClass(M68k::DR32RegClassID);
359 const auto *AR32 = RI.getRegClass(M68k::AR32RegClassID);
360 const auto *AR16 = RI.getRegClass(M68k::AR16RegClassID);
361
362 if (AR16->contains(Reg) || AR32->contains(Reg))
363 IsAddressReg = true;
364
365 // We need to assign to the full register to make IV happy
366 Register SReg =
367 MVTSize == MVT::i32
368 ? Reg
369 : Register(RI.getMatchingMegaReg(Reg, IsAddressReg ? AR32 : DR32));
370 assert(SReg && "No viable MEGA register available");
371
372 LLVM_DEBUG(dbgs() << "Expand " << *MIB.getInstr() << " to ");
373
374 // Sign extention doesn't matter if we only use the bottom 8 bits
375 if (MVTSize == MVT::i8 || (!IsAddressReg && Imm >= -128 && Imm <= 127)) {
376 LLVM_DEBUG(dbgs() << "MOVEQ\n");
377
378 MIB->setDesc(get(M68k::MOVQ));
379 MIB->getOperand(0).setReg(SReg);
380
381 // Counter the effects of sign-extension with a bitwise not.
382 // This is only faster and smaller for 32 bit values.
383 } else if (DR32->contains(Reg) && isUInt<8>(Imm)) {
384 LLVM_DEBUG(dbgs() << "MOVEQ and NOT\n");
385
387 DebugLoc DL = MIB->getDebugLoc();
388
389 unsigned SubReg = RI.getSubReg(Reg, M68k::MxSubRegIndex8Lo);
390 assert(SubReg && "No viable SUB register available");
391
392 BuildMI(MBB, MIB.getInstr(), DL, get(M68k::MOVQ), SReg).addImm(~Imm & 0xFF);
393 BuildMI(MBB, MIB.getInstr(), DL, get(M68k::NOT8d), SubReg).addReg(SubReg);
394
395 MIB->removeFromParent();
396
397 // Special case for setting address register to NULL (0)
398 } else if (IsAddressReg && Imm == 0) {
399 LLVM_DEBUG(dbgs() << "SUBA\n");
400
402 DebugLoc DL = MIB->getDebugLoc();
403
404 BuildMI(MBB, MIB.getInstr(), DL, get(M68k::SUB32ar), SReg)
405 .addReg(SReg, RegState::Undef)
406 .addReg(SReg, RegState::Undef);
407
408 MIB->removeFromParent();
409
410 // movea.w implicitly sign extends to the full register width,
411 // so exploit that if the immediate fits in the correct range.
412 //
413 // TODO: use lea imm.w, %an for further constants when 16-bit
414 // absolute addressing is implemented.
415 } else if (AR32->contains(Reg) && isUInt<16>(Imm)) {
416 LLVM_DEBUG(dbgs() << "MOVEA w/ implicit extend\n");
417
418 unsigned SubReg = RI.getSubReg(Reg, M68k::MxSubRegIndex16Lo);
419 assert(SubReg && "No viable SUB register available");
420
421 MIB->setDesc(get(M68k::MOV16ai));
422 MIB->getOperand(0).setReg(SubReg);
423
424 // Fall back to a move with immediate
425 } else {
426 LLVM_DEBUG(dbgs() << "MOVE\n");
427 MIB->setDesc(get(MVTSize == MVT::i16 ? M68k::MOV16ri : M68k::MOV32ri));
428 }
429
430 return true;
431}
432
434 MVT MVTSrc) const {
435 unsigned Move = MVTDst == MVT::i16 ? M68k::MOV16rr : M68k::MOV32rr;
436 Register Dst = MIB->getOperand(0).getReg();
437 Register Src = MIB->getOperand(1).getReg();
438
439 assert(Dst != Src && "You cannot use the same Regs with MOVX_RR");
440
441 const auto &TRI = getRegisterInfo();
442
443 const auto *RCDst = TRI.getMaximalPhysRegClass(Dst, MVTDst);
444 const auto *RCSrc = TRI.getMaximalPhysRegClass(Src, MVTSrc);
445
446 assert(RCDst && RCSrc && "Wrong use of MOVX_RR");
447 assert(RCDst != RCSrc && "You cannot use the same Reg Classes with MOVX_RR");
448 (void)RCSrc;
449
450 // We need to find the super source register that matches the size of Dst
451 unsigned SSrc = RI.getMatchingMegaReg(Src, RCDst);
452 assert(SSrc && "No viable MEGA register available");
453
454 DebugLoc DL = MIB->getDebugLoc();
455
456 // If it happens to that super source register is the destination register
457 // we do nothing
458 if (Dst == SSrc) {
459 LLVM_DEBUG(dbgs() << "Remove " << *MIB.getInstr() << '\n');
460 MIB->eraseFromParent();
461 } else { // otherwise we need to MOV
462 LLVM_DEBUG(dbgs() << "Expand " << *MIB.getInstr() << " to MOV\n");
463 MIB->setDesc(get(Move));
464 MIB->getOperand(1).setReg(SSrc);
465 }
466
467 return true;
468}
469
470/// Expand SExt MOVE pseudos into a MOV and a EXT if the operands are two
471/// different registers or just EXT if it is the same register
473 MVT MVTDst, MVT MVTSrc) const {
474 LLVM_DEBUG(dbgs() << "Expand " << *MIB.getInstr() << " to ");
475
476 unsigned Move;
477
478 if (MVTDst == MVT::i16)
479 Move = M68k::MOV16rr;
480 else // i32
481 Move = M68k::MOV32rr;
482
483 Register Dst = MIB->getOperand(0).getReg();
484 Register Src = MIB->getOperand(1).getReg();
485
486 assert(Dst != Src && "You cannot use the same Regs with MOVSX_RR");
487
488 const auto &TRI = getRegisterInfo();
489
490 const auto *RCDst = TRI.getMaximalPhysRegClass(Dst, MVTDst);
491 const auto *RCSrc = TRI.getMaximalPhysRegClass(Src, MVTSrc);
492
493 assert(RCDst && RCSrc && "Wrong use of MOVSX_RR");
494 assert(RCDst != RCSrc && "You cannot use the same Reg Classes with MOVSX_RR");
495 (void)RCSrc;
496
497 // We need to find the super source register that matches the size of Dst
498 unsigned SSrc = RI.getMatchingMegaReg(Src, RCDst);
499 assert(SSrc && "No viable MEGA register available");
500
502 DebugLoc DL = MIB->getDebugLoc();
503
504 if (Dst != SSrc) {
505 LLVM_DEBUG(dbgs() << "Move and " << '\n');
506 BuildMI(MBB, MIB.getInstr(), DL, get(Move), Dst).addReg(SSrc);
507 }
508
509 if (IsSigned) {
510 LLVM_DEBUG(dbgs() << "Sign Extend" << '\n');
511 AddSExt(MBB, MIB.getInstr(), DL, Dst, MVTSrc, MVTDst);
512 } else {
513 LLVM_DEBUG(dbgs() << "Zero Extend" << '\n');
514 AddZExt(MBB, MIB.getInstr(), DL, Dst, MVTSrc, MVTDst);
515 }
516
517 MIB->eraseFromParent();
518
519 return true;
520}
521
523 const MCInstrDesc &Desc, MVT MVTDst,
524 MVT MVTSrc) const {
525 LLVM_DEBUG(dbgs() << "Expand " << *MIB.getInstr() << " to LOAD and ");
526
527 Register Dst = MIB->getOperand(0).getReg();
528
529 // We need the subreg of Dst to make instruction verifier happy because the
530 // real machine instruction consumes and produces values of the same size and
531 // the registers the will be used here fall into different classes and this
532 // makes IV cry. We could use a bigger operation, but this will put some
533 // pressure on cache and memory, so no.
534 unsigned SubDst =
535 RI.getSubReg(Dst, MVTSrc == MVT::i8 ? M68k::MxSubRegIndex8Lo
536 : M68k::MxSubRegIndex16Lo);
537 assert(SubDst && "No viable SUB register available");
538
539 // Make this a plain move
540 MIB->setDesc(Desc);
541 MIB->getOperand(0).setReg(SubDst);
542
544 I++;
546 DebugLoc DL = MIB->getDebugLoc();
547
548 if (IsSigned) {
549 LLVM_DEBUG(dbgs() << "Sign Extend" << '\n');
550 AddSExt(MBB, I, DL, Dst, MVTSrc, MVTDst);
551 } else {
552 LLVM_DEBUG(dbgs() << "Zero Extend" << '\n');
553 AddZExt(MBB, I, DL, Dst, MVTSrc, MVTDst);
554 }
555
556 return true;
557}
558
560 const MCInstrDesc &Desc, bool IsPush) const {
562 I++;
564 MachineOperand MO = MIB->getOperand(0);
565 DebugLoc DL = MIB->getDebugLoc();
566 if (IsPush)
568 else
570
571 MIB->eraseFromParent();
572 return true;
573}
574
575bool M68kInstrInfo::ExpandCCR(MachineInstrBuilder &MIB, bool IsToCCR) const {
576 if (MIB->getOpcode() == M68k::MOV8cd) {
577 // Promote used register to the next class
578 MachineOperand &Opd = MIB->getOperand(1);
579 Opd.setReg(getRegisterInfo().getMatchingSuperReg(
580 Opd.getReg(), M68k::MxSubRegIndex8Lo, &M68k::DR16RegClass));
581 }
582
583 // Replace the pseudo instruction with the real one
584 if (IsToCCR)
585 MIB->setDesc(get(M68k::MOV16cd));
586 else
587 // FIXME M68010 or later is required
588 MIB->setDesc(get(M68k::MOV16dc));
589
590 return true;
591}
592
594 const MCInstrDesc &Desc, bool IsRM) const {
595 int Reg = 0, Offset = 0, Base = 0;
596 auto XR32 = RI.getRegClass(M68k::XR32RegClassID);
597 auto DL = MIB->getDebugLoc();
598 auto MI = MIB.getInstr();
599 auto &MBB = *MIB->getParent();
600
601 if (IsRM) {
602 Reg = MIB->getOperand(0).getReg();
603 Offset = MIB->getOperand(1).getImm();
604 Base = MIB->getOperand(2).getReg();
605 } else {
606 Offset = MIB->getOperand(0).getImm();
607 Base = MIB->getOperand(1).getReg();
608 Reg = MIB->getOperand(2).getReg();
609 }
610
611 // If the register is not in XR32 then it is smaller than 32 bit, we
612 // implicitly promote it to 32
613 if (!XR32->contains(Reg)) {
614 Reg = RI.getMatchingMegaReg(Reg, XR32);
615 assert(Reg && "Has not meaningful MEGA register");
616 }
617
618 unsigned Mask = 1 << RI.getSpillRegisterOrder(Reg);
619 if (IsRM) {
620 BuildMI(MBB, MI, DL, Desc)
621 .addImm(Mask)
622 .addImm(Offset)
623 .addReg(Base)
625 .copyImplicitOps(*MIB);
626 } else {
627 BuildMI(MBB, MI, DL, Desc)
628 .addImm(Offset)
629 .addReg(Base)
630 .addImm(Mask)
632 .copyImplicitOps(*MIB);
633 }
634
635 MIB->eraseFromParent();
636
637 return true;
638}
639
640/// Expand a single-def pseudo instruction to a two-addr
641/// instruction with two undef reads of the register being defined.
642/// This is used for mapping:
643/// %d0 = SETCS_C32d
644/// to:
645/// %d0 = SUBX32dd %d0<undef>, %d0<undef>
646///
648 const MCInstrDesc &Desc) {
649 assert(Desc.getNumOperands() == 3 && "Expected two-addr instruction.");
650 Register Reg = MIB->getOperand(0).getReg();
651 MIB->setDesc(Desc);
652
653 // MachineInstr::addOperand() will insert explicit operands before any
654 // implicit operands.
656 // But we don't trust that.
657 assert(MIB->getOperand(1).getReg() == Reg &&
658 MIB->getOperand(2).getReg() == Reg && "Misplaced operand");
659 return true;
660}
661
663 MachineInstrBuilder MIB(*MI.getParent()->getParent(), MI);
664 switch (MI.getOpcode()) {
665 case M68k::PUSH8d:
666 return ExpandPUSH_POP(MIB, get(M68k::MOV8ed), true);
667 case M68k::PUSH16d:
668 return ExpandPUSH_POP(MIB, get(M68k::MOV16er), true);
669 case M68k::PUSH32r:
670 return ExpandPUSH_POP(MIB, get(M68k::MOV32er), true);
671
672 case M68k::POP8d:
673 return ExpandPUSH_POP(MIB, get(M68k::MOV8do), false);
674 case M68k::POP16d:
675 return ExpandPUSH_POP(MIB, get(M68k::MOV16ro), false);
676 case M68k::POP32r:
677 return ExpandPUSH_POP(MIB, get(M68k::MOV32ro), false);
678
679 case M68k::SETCS_C8d:
680 return Expand2AddrUndef(MIB, get(M68k::SUBX8dd));
681 case M68k::SETCS_C16d:
682 return Expand2AddrUndef(MIB, get(M68k::SUBX16dd));
683 case M68k::SETCS_C32d:
684 return Expand2AddrUndef(MIB, get(M68k::SUBX32dd));
685 }
686 return false;
687}
688
690 const MachineOperand &MO) const {
691 assert(MO.isReg());
692
693 // Check whether this MO belongs to an instruction with addressing mode 'k',
694 // Refer to TargetInstrInfo.h for more information about this function.
695
696 const MachineInstr *MI = MO.getParent();
697 const unsigned NameIndices = M68kInstrNameIndices[MI->getOpcode()];
698 StringRef InstrName(&M68kInstrNameData[NameIndices]);
699 const unsigned OperandNo = MO.getOperandNo();
700
701 // If this machine operand is the 2nd operand, then check
702 // whether the instruction has destination addressing mode 'k'.
703 if (OperandNo == 1)
704 return Regex("[A-Z]+(8|16|32)k[a-z](_TC)?$").match(InstrName);
705
706 // If this machine operand is the last one, then check
707 // whether the instruction has source addressing mode 'k'.
708 if (OperandNo == MI->getNumExplicitOperands() - 1)
709 return Regex("[A-Z]+(8|16|32)[a-z]k(_TC)?$").match(InstrName);
710
711 return false;
712}
713
716 const DebugLoc &DL, MCRegister DstReg,
717 MCRegister SrcReg, bool KillSrc,
718 bool RenamableDest, bool RenamableSrc) const {
719 unsigned Opc = 0;
720
721 // First deal with the normal symmetric copies.
722 if (M68k::XR32RegClass.contains(DstReg, SrcReg))
723 Opc = M68k::MOV32rr;
724 else if (M68k::XR16RegClass.contains(DstReg, SrcReg))
725 Opc = M68k::MOV16rr;
726 else if (M68k::DR8RegClass.contains(DstReg, SrcReg))
727 Opc = M68k::MOV8dd;
728
729 if (Opc) {
730 BuildMI(MBB, MI, DL, get(Opc), DstReg)
731 .addReg(SrcReg, getKillRegState(KillSrc));
732 return;
733 }
734
735 // Now deal with asymmetrically sized copies. The cases that follow are upcast
736 // moves.
737 //
738 // NOTE
739 // These moves are not aware of type nature of these values and thus
740 // won't do any SExt or ZExt and upper bits will basically contain garbage.
742 if (M68k::DR8RegClass.contains(SrcReg)) {
743 if (M68k::XR16RegClass.contains(DstReg))
744 Opc = M68k::MOVXd16d8;
745 else if (M68k::XR32RegClass.contains(DstReg))
746 Opc = M68k::MOVXd32d8;
747 } else if (M68k::XR16RegClass.contains(SrcReg) &&
748 M68k::XR32RegClass.contains(DstReg))
749 Opc = M68k::MOVXd32d16;
750
751 if (Opc) {
752 BuildMI(MBB, MI, DL, get(Opc), DstReg)
753 .addReg(SrcReg, getKillRegState(KillSrc));
754 return;
755 }
756
757 bool FromCCR = SrcReg == M68k::CCR;
758 bool FromSR = SrcReg == M68k::SR;
759 bool ToCCR = DstReg == M68k::CCR;
760 bool ToSR = DstReg == M68k::SR;
761
762 if (FromCCR) {
763 if (M68k::DR8RegClass.contains(DstReg)) {
764 Opc = M68k::MOV8dc;
765 } else if (M68k::DR16RegClass.contains(DstReg)) {
766 Opc = M68k::MOV16dc;
767 } else if (M68k::DR32RegClass.contains(DstReg)) {
768 Opc = M68k::MOV16dc;
769 } else {
770 LLVM_DEBUG(dbgs() << "Cannot copy CCR to " << RI.getName(DstReg) << '\n');
771 llvm_unreachable("Invalid register for MOVE from CCR");
772 }
773 } else if (ToCCR) {
774 if (M68k::DR8RegClass.contains(SrcReg)) {
775 Opc = M68k::MOV8cd;
776 } else if (M68k::DR16RegClass.contains(SrcReg)) {
777 Opc = M68k::MOV16cd;
778 } else if (M68k::DR32RegClass.contains(SrcReg)) {
779 Opc = M68k::MOV16cd;
780 } else {
781 LLVM_DEBUG(dbgs() << "Cannot copy " << RI.getName(SrcReg) << " to CCR\n");
782 llvm_unreachable("Invalid register for MOVE to CCR");
783 }
784 } else if (FromSR || ToSR)
785 llvm_unreachable("Cannot emit SR copy instruction");
786
787 if (Opc) {
788 BuildMI(MBB, MI, DL, get(Opc), DstReg)
789 .addReg(SrcReg, getKillRegState(KillSrc));
790 return;
791 }
792
793 LLVM_DEBUG(dbgs() << "Cannot copy " << RI.getName(SrcReg) << " to "
794 << RI.getName(DstReg) << '\n');
795 llvm_unreachable("Cannot emit physreg copy instruction");
796}
797
798namespace {
799unsigned getLoadStoreRegOpcode(unsigned Reg, const TargetRegisterClass *RC,
800 const TargetRegisterInfo *TRI,
801 const M68kSubtarget &STI, bool load) {
802 switch (TRI->getRegSizeInBits(*RC)) {
803 default:
804 llvm_unreachable("Unknown spill size");
805 case 8:
806 if (M68k::DR8RegClass.hasSubClassEq(RC))
807 return load ? M68k::MOV8dp : M68k::MOV8pd;
808 if (M68k::CCRCRegClass.hasSubClassEq(RC))
809 return load ? M68k::MOV16cp : M68k::MOV16pc;
810
811 llvm_unreachable("Unknown 1-byte regclass");
812 case 16:
813 assert(M68k::XR16RegClass.hasSubClassEq(RC) && "Unknown 2-byte regclass");
814 return load ? M68k::MOVM16mp_P : M68k::MOVM16pm_P;
815 case 32:
816 assert(M68k::XR32RegClass.hasSubClassEq(RC) && "Unknown 4-byte regclass");
817 return load ? M68k::MOVM32mp_P : M68k::MOVM32pm_P;
818 }
819}
820
821unsigned getStoreRegOpcode(unsigned SrcReg, const TargetRegisterClass *RC,
822 const TargetRegisterInfo *TRI,
823 const M68kSubtarget &STI) {
824 return getLoadStoreRegOpcode(SrcReg, RC, TRI, STI, false);
825}
826
827unsigned getLoadRegOpcode(unsigned DstReg, const TargetRegisterClass *RC,
828 const TargetRegisterInfo *TRI,
829 const M68kSubtarget &STI) {
830 return getLoadStoreRegOpcode(DstReg, RC, TRI, STI, true);
831}
832} // end anonymous namespace
833
835 unsigned SubIdx, unsigned &Size,
836 unsigned &Offset,
837 const MachineFunction &MF) const {
838 // The slot size must be the maximum size so we can easily use MOVEM.L
839 Size = 4;
840 Offset = 0;
841 return true;
842}
843
846 bool IsKill, int FrameIndex, const TargetRegisterClass *RC,
847 const TargetRegisterInfo *TRI, Register VReg) const {
848 const MachineFrameInfo &MFI = MBB.getParent()->getFrameInfo();
849 assert(MFI.getObjectSize(FrameIndex) >= TRI->getSpillSize(*RC) &&
850 "Stack slot is too small to store");
851 (void)MFI;
852
853 unsigned Opc = getStoreRegOpcode(SrcReg, RC, TRI, Subtarget);
855 // (0,FrameIndex) <- $reg
856 M68k::addFrameReference(BuildMI(MBB, MI, DL, get(Opc)), FrameIndex)
857 .addReg(SrcReg, getKillRegState(IsKill));
858}
859
862 Register DstReg, int FrameIndex,
863 const TargetRegisterClass *RC,
864 const TargetRegisterInfo *TRI,
865 Register VReg) const {
866 const MachineFrameInfo &MFI = MBB.getParent()->getFrameInfo();
867 assert(MFI.getObjectSize(FrameIndex) >= TRI->getSpillSize(*RC) &&
868 "Stack slot is too small to load");
869 (void)MFI;
870
871 unsigned Opc = getLoadRegOpcode(DstReg, RC, TRI, Subtarget);
873 M68k::addFrameReference(BuildMI(MBB, MI, DL, get(Opc), DstReg), FrameIndex);
874}
875
876/// Return a virtual register initialized with the global base register
877/// value. Output instructions required to initialize the register in the
878/// function entry block, if necessary.
879///
880/// TODO Move this function to M68kMachineFunctionInfo.
883 unsigned GlobalBaseReg = MxFI->getGlobalBaseReg();
884 if (GlobalBaseReg != 0)
885 return GlobalBaseReg;
886
887 // Create the register. The code to initialize it is inserted later,
888 // by the M68kGlobalBaseReg pass (below).
889 //
890 // NOTE
891 // Normally M68k uses A5 register as global base pointer but this will
892 // create unnecessary spill if we use less then 4 registers in code; since A5
893 // is callee-save anyway we could try to allocate caller-save first and if
894 // lucky get one, otherwise it does not really matter which callee-save to
895 // use.
896 MachineRegisterInfo &RegInfo = MF->getRegInfo();
897 GlobalBaseReg = RegInfo.createVirtualRegister(&M68k::AR32_NOSPRegClass);
898 MxFI->setGlobalBaseReg(GlobalBaseReg);
899 return GlobalBaseReg;
900}
901
902std::pair<unsigned, unsigned>
904 return std::make_pair(TF, 0u);
905}
906
909 using namespace M68kII;
910 static const std::pair<unsigned, const char *> TargetFlags[] = {
911 {MO_ABSOLUTE_ADDRESS, "m68k-absolute"},
912 {MO_PC_RELATIVE_ADDRESS, "m68k-pcrel"},
913 {MO_GOT, "m68k-got"},
914 {MO_GOTOFF, "m68k-gotoff"},
915 {MO_GOTPCREL, "m68k-gotpcrel"},
916 {MO_PLT, "m68k-plt"},
917 {MO_TLSGD, "m68k-tlsgd"},
918 {MO_TLSLD, "m68k-tlsld"},
919 {MO_TLSLDM, "m68k-tlsldm"},
920 {MO_TLSIE, "m68k-tlsie"},
921 {MO_TLSLE, "m68k-tlsle"}};
922 return ArrayRef(TargetFlags);
923}
924
925#undef DEBUG_TYPE
926#define DEBUG_TYPE "m68k-create-global-base-reg"
927
928#define PASS_NAME "M68k PIC Global Base Reg Initialization"
929
930namespace {
931/// This initializes the PIC global base register
932struct M68kGlobalBaseReg : public MachineFunctionPass {
933 static char ID;
934 M68kGlobalBaseReg() : MachineFunctionPass(ID) {}
935
936 bool runOnMachineFunction(MachineFunction &MF) override {
937 const M68kSubtarget &STI = MF.getSubtarget<M68kSubtarget>();
939
940 unsigned GlobalBaseReg = MxFI->getGlobalBaseReg();
941
942 // If we didn't need a GlobalBaseReg, don't insert code.
943 if (GlobalBaseReg == 0)
944 return false;
945
946 // Insert the set of GlobalBaseReg into the first MBB of the function
947 MachineBasicBlock &FirstMBB = MF.front();
949 DebugLoc DL = FirstMBB.findDebugLoc(MBBI);
950 const M68kInstrInfo *TII = STI.getInstrInfo();
951
952 // Generate lea (__GLOBAL_OFFSET_TABLE_,%PC), %A5
953 BuildMI(FirstMBB, MBBI, DL, TII->get(M68k::LEA32q), GlobalBaseReg)
954 .addExternalSymbol("_GLOBAL_OFFSET_TABLE_", M68kII::MO_GOTPCREL);
955
956 return true;
957 }
958
959 void getAnalysisUsage(AnalysisUsage &AU) const override {
960 AU.setPreservesCFG();
962 }
963};
964char M68kGlobalBaseReg::ID = 0;
965} // namespace
966
967INITIALIZE_PASS(M68kGlobalBaseReg, DEBUG_TYPE, PASS_NAME, false, false)
968
970 return new M68kGlobalBaseReg();
971}
unsigned SubReg
AMDGPU Mark last scratch load
MachineBasicBlock & MBB
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
MachineBasicBlock MachineBasicBlock::iterator MBBI
BlockVerifier::State From
#define LLVM_DEBUG(...)
Definition: Debug.h:106
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.
static bool contains(SmallPtrSetImpl< ConstantExpr * > &Cache, ConstantExpr *Expr, Constant *C)
Definition: Value.cpp:469
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 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:256
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:310
unsigned getGlobalBaseReg(MachineFunction *MF) const
Return a virtual register initialized with the global base register value.
const M68kSubtarget & Subtarget
bool ExpandMOVI(MachineInstrBuilder &MIB, MVT MVTSize) const
Move immediate to register.
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.
void copyPhysReg(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, const DebugLoc &DL, MCRegister DestReg, MCRegister SrcReg, bool KillSrc, bool RenamableDest=false, bool RenamableSrc=false) const override
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.
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
unsigned getOpcode() const
Returns the opcode of this MachineInstr.
Definition: MachineInstr.h:575
MachineInstr * removeFromParent()
Unlink 'this' from the containing basic block, and return it without deleting it.
const MachineBasicBlock * getParent() const
Definition: MachineInstr.h:347
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:499
void eraseFromParent()
Unlink 'this' from the containing basic block and delete it.
const MachineOperand & getOperand(unsigned i) const
Definition: MachineInstr.h:585
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:573
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:51
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:480
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.