Bug Summary

File:llvm/lib/Target/M68k/M68kInstrInfo.cpp
Warning:line 405, column 15
Value stored to 'RCSrc' during its initialization is never read

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-pc-linux-gnu -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name M68kInstrInfo.cpp -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=cplusplus -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -analyzer-config-compatibility-mode=true -mrelocation-model pic -pic-level 2 -mframe-pointer=none -fmath-errno -fno-rounding-math -mconstructor-aliases -munwind-tables -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -ffunction-sections -fdata-sections -fcoverage-compilation-dir=/build/llvm-toolchain-snapshot-14~++20210903100615+fd66b44ec19e/build-llvm/lib/Target/M68k -resource-dir /usr/lib/llvm-14/lib/clang/14.0.0 -D _GNU_SOURCE -D __STDC_CONSTANT_MACROS -D __STDC_FORMAT_MACROS -D __STDC_LIMIT_MACROS -I /build/llvm-toolchain-snapshot-14~++20210903100615+fd66b44ec19e/build-llvm/lib/Target/M68k -I /build/llvm-toolchain-snapshot-14~++20210903100615+fd66b44ec19e/llvm/lib/Target/M68k -I /build/llvm-toolchain-snapshot-14~++20210903100615+fd66b44ec19e/build-llvm/include -I /build/llvm-toolchain-snapshot-14~++20210903100615+fd66b44ec19e/llvm/include -D NDEBUG -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/10/../../../../include/c++/10 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/10/../../../../include/x86_64-linux-gnu/c++/10 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/10/../../../../include/c++/10/backward -internal-isystem /usr/lib/llvm-14/lib/clang/14.0.0/include -internal-isystem /usr/local/include -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/10/../../../../x86_64-linux-gnu/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -O2 -Wno-unused-parameter -Wwrite-strings -Wno-missing-field-initializers -Wno-long-long -Wno-maybe-uninitialized -Wno-class-memaccess -Wno-redundant-move -Wno-pessimizing-move -Wno-noexcept-type -Wno-comment -std=c++14 -fdeprecated-macro -fdebug-compilation-dir=/build/llvm-toolchain-snapshot-14~++20210903100615+fd66b44ec19e/build-llvm/lib/Target/M68k -fdebug-prefix-map=/build/llvm-toolchain-snapshot-14~++20210903100615+fd66b44ec19e=. -ferror-limit 19 -fvisibility hidden -fvisibility-inlines-hidden -stack-protector 2 -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -analyzer-output=html -analyzer-config stable-report-filename=true -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /tmp/scan-build-2021-09-04-040900-46481-1 -x c++ /build/llvm-toolchain-snapshot-14~++20210903100615+fd66b44ec19e/llvm/lib/Target/M68k/M68kInstrInfo.cpp
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"
19#include "MCTargetDesc/M68kMCCodeEmitter.h"
20
21#include "llvm/ADT/STLExtras.h"
22#include "llvm/ADT/ScopeExit.h"
23#include "llvm/CodeGen/LivePhysRegs.h"
24#include "llvm/CodeGen/LiveVariables.h"
25#include "llvm/CodeGen/MachineInstrBuilder.h"
26#include "llvm/CodeGen/MachineRegisterInfo.h"
27#include "llvm/Support/ErrorHandling.h"
28#include "llvm/Support/TargetRegistry.h"
29
30#include <functional>
31
32using namespace llvm;
33
34#define DEBUG_TYPE"M68k-instr-info" "M68k-instr-info"
35
36#define GET_INSTRINFO_CTOR_DTOR
37#include "M68kGenInstrInfo.inc"
38
39// Pin the vtable to this file.
40void M68kInstrInfo::anchor() {}
41
42M68kInstrInfo::M68kInstrInfo(const M68kSubtarget &STI)
43 : M68kGenInstrInfo(M68k::ADJCALLSTACKDOWN, M68k::ADJCALLSTACKUP, 0,
44 M68k::RET),
45 Subtarget(STI), RI(STI) {}
46
47static M68k::CondCode getCondFromBranchOpc(unsigned BrOpc) {
48 switch (BrOpc) {
49 default:
50 return M68k::COND_INVALID;
51 case M68k::Beq8:
52 return M68k::COND_EQ;
53 case M68k::Bne8:
54 return M68k::COND_NE;
55 case M68k::Blt8:
56 return M68k::COND_LT;
57 case M68k::Ble8:
58 return M68k::COND_LE;
59 case M68k::Bgt8:
60 return M68k::COND_GT;
61 case M68k::Bge8:
62 return M68k::COND_GE;
63 case M68k::Bcs8:
64 return M68k::COND_CS;
65 case M68k::Bls8:
66 return M68k::COND_LS;
67 case M68k::Bhi8:
68 return M68k::COND_HI;
69 case M68k::Bcc8:
70 return M68k::COND_CC;
71 case M68k::Bmi8:
72 return M68k::COND_MI;
73 case M68k::Bpl8:
74 return M68k::COND_PL;
75 case M68k::Bvs8:
76 return M68k::COND_VS;
77 case M68k::Bvc8:
78 return M68k::COND_VC;
79 }
80}
81
82bool M68kInstrInfo::AnalyzeBranchImpl(MachineBasicBlock &MBB,
83 MachineBasicBlock *&TBB,
84 MachineBasicBlock *&FBB,
85 SmallVectorImpl<MachineOperand> &Cond,
86 bool AllowModify) const {
87
88 auto UncondBranch =
89 std::pair<MachineBasicBlock::reverse_iterator, MachineBasicBlock *>{
90 MBB.rend(), nullptr};
91
92 // Erase any instructions if allowed at the end of the scope.
93 std::vector<std::reference_wrapper<llvm::MachineInstr>> EraseList;
94 auto FinalizeOnReturn = llvm::make_scope_exit([&EraseList] {
95 std::for_each(EraseList.begin(), EraseList.end(),
96 [](auto &ref) { ref.get().eraseFromParent(); });
97 });
98
99 // Start from the bottom of the block and work up, examining the
100 // terminator instructions.
101 for (auto iter = MBB.rbegin(); iter != MBB.rend(); iter = std::next(iter)) {
102
103 unsigned Opcode = iter->getOpcode();
104
105 if (iter->isDebugInstr())
106 continue;
107
108 // Working from the bottom, when we see a non-terminator instruction, we're
109 // done.
110 if (!isUnpredicatedTerminator(*iter))
111 break;
112
113 // A terminator that isn't a branch can't easily be handled by this
114 // analysis.
115 if (!iter->isBranch())
116 return true;
117
118 // Handle unconditional branches.
119 if (Opcode == M68k::BRA8 || Opcode == M68k::BRA16) {
120 if (!iter->getOperand(0).isMBB())
121 return true;
122 UncondBranch = {iter, iter->getOperand(0).getMBB()};
123
124 // TBB is used to indicate the unconditional destination.
125 TBB = UncondBranch.second;
126
127 if (!AllowModify)
128 continue;
129
130 // If the block has any instructions after a JMP, erase them.
131 EraseList.insert(EraseList.begin(), MBB.rbegin(), iter);
132
133 Cond.clear();
134 FBB = nullptr;
135
136 // Erase the JMP if it's equivalent to a fall-through.
137 if (MBB.isLayoutSuccessor(UncondBranch.second)) {
138 TBB = nullptr;
139 EraseList.push_back(*iter);
140 UncondBranch = {MBB.rend(), nullptr};
141 }
142
143 continue;
144 }
145
146 // Handle conditional branches.
147 auto BranchCode = M68k::GetCondFromBranchOpc(Opcode);
148
149 // Can't handle indirect branch.
150 if (BranchCode == M68k::COND_INVALID)
151 return true;
152
153 // In practice we should never have an undef CCR operand, if we do
154 // abort here as we are not prepared to preserve the flag.
155 // ??? Is this required?
156 // if (iter->getOperand(1).isUndef())
157 // return true;
158
159 // Working from the bottom, handle the first conditional branch.
160 if (Cond.empty()) {
161 if (!iter->getOperand(0).isMBB())
162 return true;
163 MachineBasicBlock *CondBranchTarget = iter->getOperand(0).getMBB();
164
165 // If we see something like this:
166 //
167 // bcc l1
168 // bra l2
169 // ...
170 // l1:
171 // ...
172 // l2:
173 if (UncondBranch.first != MBB.rend()) {
174
175 assert(std::next(UncondBranch.first) == iter && "Wrong block layout.")(static_cast<void> (0));
176
177 // And we are allowed to modify the block and the target block of the
178 // conditional branch is the direct successor of this block:
179 //
180 // bcc l1
181 // bra l2
182 // l1:
183 // ...
184 // l2:
185 //
186 // we change it to this if allowed:
187 //
188 // bncc l2
189 // l1:
190 // ...
191 // l2:
192 //
193 // Which is a bit more efficient.
194 if (AllowModify && MBB.isLayoutSuccessor(CondBranchTarget)) {
195
196 BranchCode = GetOppositeBranchCondition(BranchCode);
197 unsigned BNCC = GetCondBranchFromCond(BranchCode);
198
199 BuildMI(MBB, *UncondBranch.first, MBB.rfindDebugLoc(iter), get(BNCC))
200 .addMBB(UncondBranch.second);
201
202 EraseList.push_back(*iter);
203 EraseList.push_back(*UncondBranch.first);
204
205 TBB = UncondBranch.second;
206 FBB = nullptr;
207 Cond.push_back(MachineOperand::CreateImm(BranchCode));
208
209 // Otherwise preserve TBB, FBB and Cond as requested
210 } else {
211 TBB = CondBranchTarget;
212 FBB = UncondBranch.second;
213 Cond.push_back(MachineOperand::CreateImm(BranchCode));
214 }
215
216 UncondBranch = {MBB.rend(), nullptr};
217 continue;
218 }
219
220 TBB = CondBranchTarget;
221 FBB = nullptr;
222 Cond.push_back(MachineOperand::CreateImm(BranchCode));
223
224 continue;
225 }
226
227 // Handle subsequent conditional branches. Only handle the case where all
228 // conditional branches branch to the same destination and their condition
229 // opcodes fit one of the special multi-branch idioms.
230 assert(Cond.size() == 1)(static_cast<void> (0));
231 assert(TBB)(static_cast<void> (0));
232
233 // If the conditions are the same, we can leave them alone.
234 auto OldBranchCode = static_cast<M68k::CondCode>(Cond[0].getImm());
235 if (!iter->getOperand(0).isMBB())
236 return true;
237 auto NewTBB = iter->getOperand(0).getMBB();
238 if (OldBranchCode == BranchCode && TBB == NewTBB)
239 continue;
240
241 // If they differ we cannot do much here.
242 return true;
243 }
244
245 return false;
246}
247
248bool M68kInstrInfo::analyzeBranch(MachineBasicBlock &MBB,
249 MachineBasicBlock *&TBB,
250 MachineBasicBlock *&FBB,
251 SmallVectorImpl<MachineOperand> &Cond,
252 bool AllowModify) const {
253 return AnalyzeBranchImpl(MBB, TBB, FBB, Cond, AllowModify);
254}
255
256unsigned M68kInstrInfo::removeBranch(MachineBasicBlock &MBB,
257 int *BytesRemoved) const {
258 assert(!BytesRemoved && "code size not handled")(static_cast<void> (0));
259
260 MachineBasicBlock::iterator I = MBB.end();
261 unsigned Count = 0;
262
263 while (I != MBB.begin()) {
264 --I;
265 if (I->isDebugValue())
266 continue;
267 if (I->getOpcode() != M68k::BRA8 &&
268 getCondFromBranchOpc(I->getOpcode()) == M68k::COND_INVALID)
269 break;
270 // Remove the branch.
271 I->eraseFromParent();
272 I = MBB.end();
273 ++Count;
274 }
275
276 return Count;
277}
278
279unsigned M68kInstrInfo::insertBranch(
280 MachineBasicBlock &MBB, MachineBasicBlock *TBB, MachineBasicBlock *FBB,
281 ArrayRef<MachineOperand> Cond, const DebugLoc &DL, int *BytesAdded) const {
282 // Shouldn't be a fall through.
283 assert(TBB && "InsertBranch must not be told to insert a fallthrough")(static_cast<void> (0));
284 assert((Cond.size() == 1 || Cond.size() == 0) &&(static_cast<void> (0))
285 "M68k branch conditions have one component!")(static_cast<void> (0));
286 assert(!BytesAdded && "code size not handled")(static_cast<void> (0));
287
288 if (Cond.empty()) {
289 // Unconditional branch?
290 assert(!FBB && "Unconditional branch with multiple successors!")(static_cast<void> (0));
291 BuildMI(&MBB, DL, get(M68k::BRA8)).addMBB(TBB);
292 return 1;
293 }
294
295 // If FBB is null, it is implied to be a fall-through block.
296 bool FallThru = FBB == nullptr;
297
298 // Conditional branch.
299 unsigned Count = 0;
300 M68k::CondCode CC = (M68k::CondCode)Cond[0].getImm();
301 unsigned Opc = GetCondBranchFromCond(CC);
302 BuildMI(&MBB, DL, get(Opc)).addMBB(TBB);
303 ++Count;
304 if (!FallThru) {
305 // Two-way Conditional branch. Insert the second branch.
306 BuildMI(&MBB, DL, get(M68k::BRA8)).addMBB(FBB);
307 ++Count;
308 }
309 return Count;
310}
311
312void M68kInstrInfo::AddSExt(MachineBasicBlock &MBB,
313 MachineBasicBlock::iterator I, DebugLoc DL,
314 unsigned Reg, MVT From, MVT To) const {
315 if (From == MVT::i8) {
316 unsigned R = Reg;
317 // EXT16 requires i16 register
318 if (To == MVT::i32) {
319 R = RI.getSubReg(Reg, M68k::MxSubRegIndex16Lo);
320 assert(R && "No viable SUB register available")(static_cast<void> (0));
321 }
322 BuildMI(MBB, I, DL, get(M68k::EXT16), R).addReg(R);
323 }
324
325 if (To == MVT::i32)
326 BuildMI(MBB, I, DL, get(M68k::EXT32), Reg).addReg(Reg);
327}
328
329void M68kInstrInfo::AddZExt(MachineBasicBlock &MBB,
330 MachineBasicBlock::iterator I, DebugLoc DL,
331 unsigned Reg, MVT From, MVT To) const {
332
333 unsigned Mask, And;
334 if (From == MVT::i8)
335 Mask = 0xFF;
336 else
337 Mask = 0xFFFF;
338
339 if (To == MVT::i16)
340 And = M68k::AND16di;
341 else // i32
342 And = M68k::AND32di;
343
344 // TODO use xor r,r to decrease size
345 BuildMI(MBB, I, DL, get(And), Reg).addReg(Reg).addImm(Mask);
346}
347
348bool M68kInstrInfo::ExpandMOVX_RR(MachineInstrBuilder &MIB, MVT MVTDst,
349 MVT MVTSrc) const {
350 unsigned Move = MVTDst == MVT::i16 ? M68k::MOV16rr : M68k::MOV32rr;
351 unsigned Dst = MIB->getOperand(0).getReg();
352 unsigned Src = MIB->getOperand(1).getReg();
353
354 assert(Dst != Src && "You cannot use the same Regs with MOVX_RR")(static_cast<void> (0));
355
356 const auto &TRI = getRegisterInfo();
357
358 const auto *RCDst = TRI.getMaximalPhysRegClass(Dst, MVTDst);
359 const auto *RCSrc = TRI.getMaximalPhysRegClass(Src, MVTSrc);
360
361 assert(RCDst && RCSrc && "Wrong use of MOVX_RR")(static_cast<void> (0));
362 assert(RCDst != RCSrc && "You cannot use the same Reg Classes with MOVX_RR")(static_cast<void> (0));
363
364 // We need to find the super source register that matches the size of Dst
365 unsigned SSrc = RI.getMatchingMegaReg(Src, RCDst);
366 assert(SSrc && "No viable MEGA register available")(static_cast<void> (0));
367
368 DebugLoc DL = MIB->getDebugLoc();
369
370 // If it happens to that super source register is the destination register
371 // we do nothing
372 if (Dst == SSrc) {
373 LLVM_DEBUG(dbgs() << "Remove " << *MIB.getInstr() << '\n')do { } while (false);
374 MIB->eraseFromParent();
375 } else { // otherwise we need to MOV
376 LLVM_DEBUG(dbgs() << "Expand " << *MIB.getInstr() << " to MOV\n")do { } while (false);
377 MIB->setDesc(get(Move));
378 MIB->getOperand(1).setReg(SSrc);
379 }
380
381 return true;
382}
383
384/// Expand SExt MOVE pseudos into a MOV and a EXT if the operands are two
385/// different registers or just EXT if it is the same register
386bool M68kInstrInfo::ExpandMOVSZX_RR(MachineInstrBuilder &MIB, bool IsSigned,
387 MVT MVTDst, MVT MVTSrc) const {
388 LLVM_DEBUG(dbgs() << "Expand " << *MIB.getInstr() << " to ")do { } while (false);
389
390 unsigned Move;
391
392 if (MVTDst == MVT::i16)
393 Move = M68k::MOV16rr;
394 else // i32
395 Move = M68k::MOV32rr;
396
397 unsigned Dst = MIB->getOperand(0).getReg();
398 unsigned Src = MIB->getOperand(1).getReg();
399
400 assert(Dst != Src && "You cannot use the same Regs with MOVSX_RR")(static_cast<void> (0));
401
402 const auto &TRI = getRegisterInfo();
403
404 const auto *RCDst = TRI.getMaximalPhysRegClass(Dst, MVTDst);
405 const auto *RCSrc = TRI.getMaximalPhysRegClass(Src, MVTSrc);
Value stored to 'RCSrc' during its initialization is never read
406
407 assert(RCDst && RCSrc && "Wrong use of MOVSX_RR")(static_cast<void> (0));
408 assert(RCDst != RCSrc && "You cannot use the same Reg Classes with MOVSX_RR")(static_cast<void> (0));
409
410 // We need to find the super source register that matches the size of Dst
411 unsigned SSrc = RI.getMatchingMegaReg(Src, RCDst);
412 assert(SSrc && "No viable MEGA register available")(static_cast<void> (0));
413
414 MachineBasicBlock &MBB = *MIB->getParent();
415 DebugLoc DL = MIB->getDebugLoc();
416
417 if (Dst != SSrc) {
418 LLVM_DEBUG(dbgs() << "Move and " << '\n')do { } while (false);
419 BuildMI(MBB, MIB.getInstr(), DL, get(Move), Dst).addReg(SSrc);
420 }
421
422 if (IsSigned) {
423 LLVM_DEBUG(dbgs() << "Sign Extend" << '\n')do { } while (false);
424 AddSExt(MBB, MIB.getInstr(), DL, Dst, MVTSrc, MVTDst);
425 } else {
426 LLVM_DEBUG(dbgs() << "Zero Extend" << '\n')do { } while (false);
427 AddZExt(MBB, MIB.getInstr(), DL, Dst, MVTSrc, MVTDst);
428 }
429
430 MIB->eraseFromParent();
431
432 return true;
433}
434
435bool M68kInstrInfo::ExpandMOVSZX_RM(MachineInstrBuilder &MIB, bool IsSigned,
436 const MCInstrDesc &Desc, MVT MVTDst,
437 MVT MVTSrc) const {
438 LLVM_DEBUG(dbgs() << "Expand " << *MIB.getInstr() << " to LOAD and ")do { } while (false);
439
440 unsigned Dst = MIB->getOperand(0).getReg();
441
442 // We need the subreg of Dst to make instruction verifier happy because the
443 // real machine instruction consumes and produces values of the same size and
444 // the registers the will be used here fall into different classes and this
445 // makes IV cry. We could use a bigger operation, but this will put some
446 // pressure on cache and memory, so no.
447 unsigned SubDst =
448 RI.getSubReg(Dst, MVTSrc == MVT::i8 ? M68k::MxSubRegIndex8Lo
449 : M68k::MxSubRegIndex16Lo);
450 assert(SubDst && "No viable SUB register available")(static_cast<void> (0));
451
452 // Make this a plain move
453 MIB->setDesc(Desc);
454 MIB->getOperand(0).setReg(SubDst);
455
456 MachineBasicBlock::iterator I = MIB.getInstr();
457 I++;
458 MachineBasicBlock &MBB = *MIB->getParent();
459 DebugLoc DL = MIB->getDebugLoc();
460
461 if (IsSigned) {
462 LLVM_DEBUG(dbgs() << "Sign Extend" << '\n')do { } while (false);
463 AddSExt(MBB, I, DL, Dst, MVTSrc, MVTDst);
464 } else {
465 LLVM_DEBUG(dbgs() << "Zero Extend" << '\n')do { } while (false);
466 AddZExt(MBB, I, DL, Dst, MVTSrc, MVTDst);
467 }
468
469 return true;
470}
471
472bool M68kInstrInfo::ExpandPUSH_POP(MachineInstrBuilder &MIB,
473 const MCInstrDesc &Desc, bool IsPush) const {
474 MachineBasicBlock::iterator I = MIB.getInstr();
475 I++;
476 MachineBasicBlock &MBB = *MIB->getParent();
477 MachineOperand MO = MIB->getOperand(0);
478 DebugLoc DL = MIB->getDebugLoc();
479 if (IsPush)
480 BuildMI(MBB, I, DL, Desc).addReg(RI.getStackRegister()).add(MO);
481 else
482 BuildMI(MBB, I, DL, Desc, MO.getReg()).addReg(RI.getStackRegister());
483
484 MIB->eraseFromParent();
485 return true;
486}
487
488bool M68kInstrInfo::ExpandCCR(MachineInstrBuilder &MIB, bool IsToCCR) const {
489
490 // Replace the pseudo instruction with the real one
491 if (IsToCCR)
492 MIB->setDesc(get(M68k::MOV16cd));
493 else
494 // FIXME M68010 or later is required
495 MIB->setDesc(get(M68k::MOV16dc));
496
497 // Promote used register to the next class
498 auto &Opd = MIB->getOperand(1);
499 Opd.setReg(getRegisterInfo().getMatchingSuperReg(
500 Opd.getReg(), M68k::MxSubRegIndex8Lo, &M68k::DR16RegClass));
501
502 return true;
503}
504
505bool M68kInstrInfo::ExpandMOVEM(MachineInstrBuilder &MIB,
506 const MCInstrDesc &Desc, bool IsRM) const {
507 int Reg = 0, Offset = 0, Base = 0;
508 auto XR32 = RI.getRegClass(M68k::XR32RegClassID);
509 auto DL = MIB->getDebugLoc();
510 auto MI = MIB.getInstr();
511 auto &MBB = *MIB->getParent();
512
513 if (IsRM) {
514 Reg = MIB->getOperand(0).getReg();
515 Offset = MIB->getOperand(1).getImm();
516 Base = MIB->getOperand(2).getReg();
517 } else {
518 Offset = MIB->getOperand(0).getImm();
519 Base = MIB->getOperand(1).getReg();
520 Reg = MIB->getOperand(2).getReg();
521 }
522
523 // If the register is not in XR32 then it is smaller than 32 bit, we
524 // implicitly promote it to 32
525 if (!XR32->contains(Reg)) {
526 Reg = RI.getMatchingMegaReg(Reg, XR32);
527 assert(Reg && "Has not meaningful MEGA register")(static_cast<void> (0));
528 }
529
530 unsigned Mask = 1 << RI.getSpillRegisterOrder(Reg);
531 if (IsRM) {
532 BuildMI(MBB, MI, DL, Desc)
533 .addImm(Mask)
534 .addImm(Offset)
535 .addReg(Base)
536 .addReg(Reg, RegState::ImplicitDefine)
537 .copyImplicitOps(*MIB);
538 } else {
539 BuildMI(MBB, MI, DL, Desc)
540 .addImm(Offset)
541 .addReg(Base)
542 .addImm(Mask)
543 .addReg(Reg, RegState::Implicit)
544 .copyImplicitOps(*MIB);
545 }
546
547 MIB->eraseFromParent();
548
549 return true;
550}
551
552/// Expand a single-def pseudo instruction to a two-addr
553/// instruction with two undef reads of the register being defined.
554/// This is used for mapping:
555/// %d0 = SETCS_C32d
556/// to:
557/// %d0 = SUBX32dd %d0<undef>, %d0<undef>
558///
559static bool Expand2AddrUndef(MachineInstrBuilder &MIB,
560 const MCInstrDesc &Desc) {
561 assert(Desc.getNumOperands() == 3 && "Expected two-addr instruction.")(static_cast<void> (0));
562 unsigned Reg = MIB->getOperand(0).getReg();
563 MIB->setDesc(Desc);
564
565 // MachineInstr::addOperand() will insert explicit operands before any
566 // implicit operands.
567 MIB.addReg(Reg, RegState::Undef).addReg(Reg, RegState::Undef);
568 // But we don't trust that.
569 assert(MIB->getOperand(1).getReg() == Reg &&(static_cast<void> (0))
570 MIB->getOperand(2).getReg() == Reg && "Misplaced operand")(static_cast<void> (0));
571 return true;
572}
573
574bool M68kInstrInfo::expandPostRAPseudo(MachineInstr &MI) const {
575 MachineInstrBuilder MIB(*MI.getParent()->getParent(), MI);
576 switch (MI.getOpcode()) {
577 case M68k::PUSH8d:
578 return ExpandPUSH_POP(MIB, get(M68k::MOV8ed), true);
579 case M68k::PUSH16d:
580 return ExpandPUSH_POP(MIB, get(M68k::MOV16er), true);
581 case M68k::PUSH32r:
582 return ExpandPUSH_POP(MIB, get(M68k::MOV32er), true);
583
584 case M68k::POP8d:
585 return ExpandPUSH_POP(MIB, get(M68k::MOV8do), false);
586 case M68k::POP16d:
587 return ExpandPUSH_POP(MIB, get(M68k::MOV16ro), false);
588 case M68k::POP32r:
589 return ExpandPUSH_POP(MIB, get(M68k::MOV32ro), false);
590
591 case M68k::SETCS_C8d:
592 return Expand2AddrUndef(MIB, get(M68k::SUBX8dd));
593 case M68k::SETCS_C16d:
594 return Expand2AddrUndef(MIB, get(M68k::SUBX16dd));
595 case M68k::SETCS_C32d:
596 return Expand2AddrUndef(MIB, get(M68k::SUBX32dd));
597 }
598 return false;
599}
600
601bool M68kInstrInfo::isPCRelRegisterOperandLegal(
602 const MachineOperand &MO) const {
603 assert(MO.isReg())(static_cast<void> (0));
604 const auto *MI = MO.getParent();
605 const uint8_t *Beads = M68k::getMCInstrBeads(MI->getOpcode());
606 assert(*Beads)(static_cast<void> (0));
607
608 // Only addressing mode k has (non-pc) register with PCRel
609 // So we're looking for EA Beads equal to
610 // `3Bits<011>_1Bit<1>_2Bits<11>`
611 // FIXME: There is an important caveat and two assumptions
612 // here: The caveat is that EA encoding always sit on the LSB.
613 // Where the assumptions are that if there are more than one
614 // operands, the EA encoding for the source operand always sit
615 // on the LSB. At the same time, k addressing mode can not be used
616 // on destination operand.
617 // The last assumption is kinda dirty so we need to find a way around
618 // it
619 const uint8_t EncEAk[3] = {0b011, 0b1, 0b11};
620 for (const uint8_t Pat : EncEAk) {
621 uint8_t Bead = *(Beads++);
622 if (!Bead)
623 return false;
624
625 switch (Bead & 0xF) {
626 default:
627 return false;
628 case M68kBeads::Bits1:
629 case M68kBeads::Bits2:
630 case M68kBeads::Bits3: {
631 uint8_t Val = (Bead & 0xF0) >> 4;
632 if (Val != Pat)
633 return false;
634 }
635 }
636 }
637 return true;
638}
639
640void M68kInstrInfo::copyPhysReg(MachineBasicBlock &MBB,
641 MachineBasicBlock::iterator MI,
642 const DebugLoc &DL, MCRegister DstReg,
643 MCRegister SrcReg, bool KillSrc) const {
644 unsigned Opc = 0;
645
646 // First deal with the normal symmetric copies.
647 if (M68k::XR32RegClass.contains(DstReg, SrcReg))
648 Opc = M68k::MOV32rr;
649 else if (M68k::XR16RegClass.contains(DstReg, SrcReg))
650 Opc = M68k::MOV16rr;
651 else if (M68k::DR8RegClass.contains(DstReg, SrcReg))
652 Opc = M68k::MOV8dd;
653
654 if (Opc) {
655 BuildMI(MBB, MI, DL, get(Opc), DstReg)
656 .addReg(SrcReg, getKillRegState(KillSrc));
657 return;
658 }
659
660 // Now deal with asymmetrically sized copies. The cases that follow are upcast
661 // moves.
662 //
663 // NOTE
664 // These moves are not aware of type nature of these values and thus
665 // won't do any SExt or ZExt and upper bits will basically contain garbage.
666 MachineInstrBuilder MIB(*MBB.getParent(), MI);
667 if (M68k::DR8RegClass.contains(SrcReg)) {
668 if (M68k::XR16RegClass.contains(DstReg))
669 Opc = M68k::MOVXd16d8;
670 else if (M68k::XR32RegClass.contains(DstReg))
671 Opc = M68k::MOVXd32d8;
672 } else if (M68k::XR16RegClass.contains(SrcReg) &&
673 M68k::XR32RegClass.contains(DstReg))
674 Opc = M68k::MOVXd32d16;
675
676 if (Opc) {
677 BuildMI(MBB, MI, DL, get(Opc), DstReg)
678 .addReg(SrcReg, getKillRegState(KillSrc));
679 return;
680 }
681
682 bool FromCCR = SrcReg == M68k::CCR;
683 bool FromSR = SrcReg == M68k::SR;
684 bool ToCCR = DstReg == M68k::CCR;
685 bool ToSR = DstReg == M68k::SR;
686
687 if (FromCCR) {
688 assert(M68k::DR8RegClass.contains(DstReg) &&(static_cast<void> (0))
689 "Need DR8 register to copy CCR")(static_cast<void> (0));
690 Opc = M68k::MOV8dc;
691 } else if (ToCCR) {
692 assert(M68k::DR8RegClass.contains(SrcReg) &&(static_cast<void> (0))
693 "Need DR8 register to copy CCR")(static_cast<void> (0));
694 Opc = M68k::MOV8cd;
695 } else if (FromSR || ToSR)
696 llvm_unreachable("Cannot emit SR copy instruction")__builtin_unreachable();
697
698 if (Opc) {
699 BuildMI(MBB, MI, DL, get(Opc), DstReg)
700 .addReg(SrcReg, getKillRegState(KillSrc));
701 return;
702 }
703
704 LLVM_DEBUG(dbgs() << "Cannot copy " << RI.getName(SrcReg) << " to "do { } while (false)
705 << RI.getName(DstReg) << '\n')do { } while (false);
706 llvm_unreachable("Cannot emit physreg copy instruction")__builtin_unreachable();
707}
708
709namespace {
710unsigned getLoadStoreRegOpcode(unsigned Reg, const TargetRegisterClass *RC,
711 const TargetRegisterInfo *TRI,
712 const M68kSubtarget &STI, bool load) {
713 switch (TRI->getRegSizeInBits(*RC)) {
714 default:
715 llvm_unreachable("Unknown spill size")__builtin_unreachable();
716 case 8:
717 if (M68k::DR8RegClass.hasSubClassEq(RC))
718 return load ? M68k::MOVM8mp_P : M68k::MOVM8pm_P;
719 if (M68k::CCRCRegClass.hasSubClassEq(RC))
720 return load ? M68k::MOV16cp : M68k::MOV16pc;
721
722 llvm_unreachable("Unknown 1-byte regclass")__builtin_unreachable();
723 case 16:
724 assert(M68k::XR16RegClass.hasSubClassEq(RC) && "Unknown 2-byte regclass")(static_cast<void> (0));
725 return load ? M68k::MOVM16mp_P : M68k::MOVM16pm_P;
726 case 32:
727 assert(M68k::XR32RegClass.hasSubClassEq(RC) && "Unknown 4-byte regclass")(static_cast<void> (0));
728 return load ? M68k::MOVM32mp_P : M68k::MOVM32pm_P;
729 }
730}
731
732unsigned getStoreRegOpcode(unsigned SrcReg, const TargetRegisterClass *RC,
733 const TargetRegisterInfo *TRI,
734 const M68kSubtarget &STI) {
735 return getLoadStoreRegOpcode(SrcReg, RC, TRI, STI, false);
736}
737
738unsigned getLoadRegOpcode(unsigned DstReg, const TargetRegisterClass *RC,
739 const TargetRegisterInfo *TRI,
740 const M68kSubtarget &STI) {
741 return getLoadStoreRegOpcode(DstReg, RC, TRI, STI, true);
742}
743} // end anonymous namespace
744
745bool M68kInstrInfo::getStackSlotRange(const TargetRegisterClass *RC,
746 unsigned SubIdx, unsigned &Size,
747 unsigned &Offset,
748 const MachineFunction &MF) const {
749 // The slot size must be the maximum size so we can easily use MOVEM.L
750 Size = 4;
751 Offset = 0;
752 return true;
753}
754
755void M68kInstrInfo::storeRegToStackSlot(MachineBasicBlock &MBB,
756 MachineBasicBlock::iterator MI,
757 Register SrcReg, bool IsKill,
758 int FrameIndex,
759 const TargetRegisterClass *RC,
760 const TargetRegisterInfo *TRI) const {
761 const MachineFunction &MF = *MBB.getParent();
762 assert(MF.getFrameInfo().getObjectSize(FrameIndex) == 4 &&(static_cast<void> (0))
763 "Stack slot too small for store")(static_cast<void> (0));
764 unsigned Opc = getStoreRegOpcode(SrcReg, RC, TRI, Subtarget);
765 DebugLoc DL = MBB.findDebugLoc(MI);
766 // (0,FrameIndex) <- $reg
767 M68k::addFrameReference(BuildMI(MBB, MI, DL, get(Opc)), FrameIndex)
768 .addReg(SrcReg, getKillRegState(IsKill));
769}
770
771void M68kInstrInfo::loadRegFromStackSlot(MachineBasicBlock &MBB,
772 MachineBasicBlock::iterator MI,
773 Register DstReg, int FrameIndex,
774 const TargetRegisterClass *RC,
775 const TargetRegisterInfo *TRI) const {
776 const MachineFunction &MF = *MBB.getParent();
777 assert(MF.getFrameInfo().getObjectSize(FrameIndex) == 4 &&(static_cast<void> (0))
778 "Stack slot too small for store")(static_cast<void> (0));
779 unsigned Opc = getLoadRegOpcode(DstReg, RC, TRI, Subtarget);
780 DebugLoc DL = MBB.findDebugLoc(MI);
781 M68k::addFrameReference(BuildMI(MBB, MI, DL, get(Opc), DstReg), FrameIndex);
782}
783
784/// Return a virtual register initialized with the the global base register
785/// value. Output instructions required to initialize the register in the
786/// function entry block, if necessary.
787///
788/// TODO Move this function to M68kMachineFunctionInfo.
789unsigned M68kInstrInfo::getGlobalBaseReg(MachineFunction *MF) const {
790 M68kMachineFunctionInfo *MxFI = MF->getInfo<M68kMachineFunctionInfo>();
791 unsigned GlobalBaseReg = MxFI->getGlobalBaseReg();
792 if (GlobalBaseReg != 0)
793 return GlobalBaseReg;
794
795 // Create the register. The code to initialize it is inserted later,
796 // by the CGBR pass (below).
797 //
798 // NOTE
799 // Normally M68k uses A5 register as global base pointer but this will
800 // create unnecessary spill if we use less then 4 registers in code; since A5
801 // is callee-save anyway we could try to allocate caller-save first and if
802 // lucky get one, otherwise it does not really matter which callee-save to
803 // use.
804 MachineRegisterInfo &RegInfo = MF->getRegInfo();
805 GlobalBaseReg = RegInfo.createVirtualRegister(&M68k::AR32_NOSPRegClass);
806 MxFI->setGlobalBaseReg(GlobalBaseReg);
807 return GlobalBaseReg;
808}
809
810std::pair<unsigned, unsigned>
811M68kInstrInfo::decomposeMachineOperandsTargetFlags(unsigned TF) const {
812 return std::make_pair(TF, 0u);
813}
814
815ArrayRef<std::pair<unsigned, const char *>>
816M68kInstrInfo::getSerializableDirectMachineOperandTargetFlags() const {
817 using namespace M68kII;
818 static const std::pair<unsigned, const char *> TargetFlags[] = {
819 {MO_ABSOLUTE_ADDRESS, "m68k-absolute"},
820 {MO_PC_RELATIVE_ADDRESS, "m68k-pcrel"},
821 {MO_GOT, "m68k-got"},
822 {MO_GOTOFF, "m68k-gotoff"},
823 {MO_GOTPCREL, "m68k-gotpcrel"},
824 {MO_PLT, "m68k-plt"}};
825 return makeArrayRef(TargetFlags);
826}
827
828namespace {
829/// Create Global Base Reg pass. This initializes the PIC global base register
830struct CGBR : public MachineFunctionPass {
831 static char ID;
832 CGBR() : MachineFunctionPass(ID) {}
833
834 bool runOnMachineFunction(MachineFunction &MF) override {
835 const M68kSubtarget &STI = MF.getSubtarget<M68kSubtarget>();
836 M68kMachineFunctionInfo *MxFI = MF.getInfo<M68kMachineFunctionInfo>();
837
838 unsigned GlobalBaseReg = MxFI->getGlobalBaseReg();
839
840 // If we didn't need a GlobalBaseReg, don't insert code.
841 if (GlobalBaseReg == 0)
842 return false;
843
844 // Insert the set of GlobalBaseReg into the first MBB of the function
845 MachineBasicBlock &FirstMBB = MF.front();
846 MachineBasicBlock::iterator MBBI = FirstMBB.begin();
847 DebugLoc DL = FirstMBB.findDebugLoc(MBBI);
848 const M68kInstrInfo *TII = STI.getInstrInfo();
849
850 // Generate lea (__GLOBAL_OFFSET_TABLE_,%PC), %A5
851 BuildMI(FirstMBB, MBBI, DL, TII->get(M68k::LEA32q), GlobalBaseReg)
852 .addExternalSymbol("_GLOBAL_OFFSET_TABLE_", M68kII::MO_GOTPCREL);
853
854 return true;
855 }
856
857 StringRef getPassName() const override {
858 return "M68k PIC Global Base Reg Initialization";
859 }
860
861 void getAnalysisUsage(AnalysisUsage &AU) const override {
862 AU.setPreservesCFG();
863 MachineFunctionPass::getAnalysisUsage(AU);
864 }
865};
866} // namespace
867
868char CGBR::ID = 0;
869FunctionPass *llvm::createM68kGlobalBaseRegPass() { return new CGBR(); }