File: | llvm/lib/Target/M68k/M68kInstrInfo.cpp |
Warning: | line 359, column 15 Value stored to 'RCSrc' during its initialization is never read |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
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 | |
32 | using 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. |
40 | void M68kInstrInfo::anchor() {} |
41 | |
42 | M68kInstrInfo::M68kInstrInfo(const M68kSubtarget &STI) |
43 | : M68kGenInstrInfo(M68k::ADJCALLSTACKDOWN, M68k::ADJCALLSTACKUP, 0, |
44 | M68k::RET), |
45 | Subtarget(STI), RI(STI) {} |
46 | |
47 | static 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 | |
82 | bool 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 | |
248 | bool 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 | |
256 | unsigned 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 | |
279 | unsigned 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 | |
312 | void 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 | |
329 | void 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 | |
348 | bool 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); |
Value stored to 'RCSrc' during its initialization is never read | |
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 |
386 | bool 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); |
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 | |
435 | bool 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 | |
472 | bool 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 | |
488 | bool 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 | |
505 | bool 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 | /// |
559 | static 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 | |
574 | bool 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 | |
601 | bool 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 | |
640 | void 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 | |
709 | namespace { |
710 | unsigned 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 | |
732 | unsigned getStoreRegOpcode(unsigned SrcReg, const TargetRegisterClass *RC, |
733 | const TargetRegisterInfo *TRI, |
734 | const M68kSubtarget &STI) { |
735 | return getLoadStoreRegOpcode(SrcReg, RC, TRI, STI, false); |
736 | } |
737 | |
738 | unsigned 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 | |
745 | bool 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 | |
755 | void 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 | |
771 | void 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. |
789 | unsigned 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 | |
810 | std::pair<unsigned, unsigned> |
811 | M68kInstrInfo::decomposeMachineOperandsTargetFlags(unsigned TF) const { |
812 | return std::make_pair(TF, 0u); |
813 | } |
814 | |
815 | ArrayRef<std::pair<unsigned, const char *>> |
816 | M68kInstrInfo::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 | |
828 | namespace { |
829 | /// Create Global Base Reg pass. This initializes the PIC global base register |
830 | struct 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 | |
868 | char CGBR::ID = 0; |
869 | FunctionPass *llvm::createM68kGlobalBaseRegPass() { return new CGBR(); } |