[ORC] Add std::tuple support to SimplePackedSerialization.
[llvm-project.git] / llvm / lib / Target / M68k / M68kExpandPseudo.cpp
blob6a4aeaab518a94399a5afc849a8b44fa5960768d
1 //===--M68kExpandPseudo.cpp - Expand pseudo instructions ------*- 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 a pass that expands pseudo instructions into target
11 /// instructions to allow proper scheduling, if-conversion, other late
12 /// optimizations, or simply the encoding of the instructions.
13 ///
14 //===----------------------------------------------------------------------===//
16 #include "M68k.h"
17 #include "M68kFrameLowering.h"
18 #include "M68kInstrInfo.h"
19 #include "M68kMachineFunction.h"
20 #include "M68kSubtarget.h"
22 #include "llvm/Analysis/EHPersonalities.h"
23 #include "llvm/CodeGen/MachineFunctionPass.h"
24 #include "llvm/CodeGen/MachineInstrBuilder.h"
25 #include "llvm/CodeGen/MachineRegisterInfo.h"
26 #include "llvm/CodeGen/Passes.h" // For IDs of passes that are preserved.
27 #include "llvm/IR/GlobalValue.h"
29 using namespace llvm;
31 #define DEBUG_TYPE "M68k-expand-pseudos"
33 namespace {
34 class M68kExpandPseudo : public MachineFunctionPass {
35 public:
36 static char ID;
37 M68kExpandPseudo() : MachineFunctionPass(ID) {}
39 void getAnalysisUsage(AnalysisUsage &AU) const override {
40 AU.setPreservesCFG();
41 AU.addPreservedID(MachineLoopInfoID);
42 AU.addPreservedID(MachineDominatorsID);
43 MachineFunctionPass::getAnalysisUsage(AU);
46 const M68kSubtarget *STI;
47 const M68kInstrInfo *TII;
48 const M68kRegisterInfo *TRI;
49 const M68kMachineFunctionInfo *MFI;
50 const M68kFrameLowering *FL;
52 bool runOnMachineFunction(MachineFunction &Fn) override;
54 MachineFunctionProperties getRequiredProperties() const override {
55 return MachineFunctionProperties().set(
56 MachineFunctionProperties::Property::NoVRegs);
59 StringRef getPassName() const override {
60 return "M68k pseudo instruction expansion pass";
63 private:
64 bool ExpandMI(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI);
65 bool ExpandMBB(MachineBasicBlock &MBB);
67 char M68kExpandPseudo::ID = 0;
68 } // End anonymous namespace.
70 /// If \p MBBI is a pseudo instruction, this method expands
71 /// it to the corresponding (sequence of) actual instruction(s).
72 /// \returns true if \p MBBI has been expanded.
73 bool M68kExpandPseudo::ExpandMI(MachineBasicBlock &MBB,
74 MachineBasicBlock::iterator MBBI) {
75 MachineInstr &MI = *MBBI;
76 MachineInstrBuilder MIB(*MI.getParent()->getParent(), MI);
77 unsigned Opcode = MI.getOpcode();
78 DebugLoc DL = MBBI->getDebugLoc();
79 /// TODO infer argument size to create less switch cases
80 switch (Opcode) {
81 default:
82 return false;
84 case M68k::MOVXd16d8:
85 return TII->ExpandMOVX_RR(MIB, MVT::i16, MVT::i8);
86 case M68k::MOVXd32d8:
87 return TII->ExpandMOVX_RR(MIB, MVT::i32, MVT::i8);
88 case M68k::MOVXd32d16:
89 return TII->ExpandMOVX_RR(MIB, MVT::i32, MVT::i16);
91 case M68k::MOVSXd16d8:
92 return TII->ExpandMOVSZX_RR(MIB, true, MVT::i16, MVT::i8);
93 case M68k::MOVSXd32d8:
94 return TII->ExpandMOVSZX_RR(MIB, true, MVT::i32, MVT::i8);
95 case M68k::MOVSXd32d16:
96 return TII->ExpandMOVSZX_RR(MIB, true, MVT::i32, MVT::i16);
98 case M68k::MOVZXd16d8:
99 return TII->ExpandMOVSZX_RR(MIB, false, MVT::i16, MVT::i8);
100 case M68k::MOVZXd32d8:
101 return TII->ExpandMOVSZX_RR(MIB, false, MVT::i32, MVT::i8);
102 case M68k::MOVZXd32d16:
103 return TII->ExpandMOVSZX_RR(MIB, false, MVT::i32, MVT::i16);
105 case M68k::MOVSXd16j8:
106 return TII->ExpandMOVSZX_RM(MIB, true, TII->get(M68k::MOV8dj), MVT::i16,
107 MVT::i8);
108 case M68k::MOVSXd32j8:
109 return TII->ExpandMOVSZX_RM(MIB, true, TII->get(M68k::MOV8dj), MVT::i32,
110 MVT::i8);
111 case M68k::MOVSXd32j16:
112 return TII->ExpandMOVSZX_RM(MIB, true, TII->get(M68k::MOV16rj), MVT::i32,
113 MVT::i16);
115 case M68k::MOVZXd16j8:
116 return TII->ExpandMOVSZX_RM(MIB, false, TII->get(M68k::MOV8dj), MVT::i16,
117 MVT::i8);
118 case M68k::MOVZXd32j8:
119 return TII->ExpandMOVSZX_RM(MIB, false, TII->get(M68k::MOV8dj), MVT::i32,
120 MVT::i8);
121 case M68k::MOVZXd32j16:
122 return TII->ExpandMOVSZX_RM(MIB, false, TII->get(M68k::MOV16rj), MVT::i32,
123 MVT::i16);
125 case M68k::MOVSXd16p8:
126 return TII->ExpandMOVSZX_RM(MIB, true, TII->get(M68k::MOV8dp), MVT::i16,
127 MVT::i8);
128 case M68k::MOVSXd32p8:
129 return TII->ExpandMOVSZX_RM(MIB, true, TII->get(M68k::MOV8dp), MVT::i32,
130 MVT::i8);
131 case M68k::MOVSXd32p16:
132 return TII->ExpandMOVSZX_RM(MIB, true, TII->get(M68k::MOV16rp), MVT::i32,
133 MVT::i16);
135 case M68k::MOVZXd16p8:
136 return TII->ExpandMOVSZX_RM(MIB, false, TII->get(M68k::MOV8dp), MVT::i16,
137 MVT::i8);
138 case M68k::MOVZXd32p8:
139 return TII->ExpandMOVSZX_RM(MIB, false, TII->get(M68k::MOV8dp), MVT::i32,
140 MVT::i8);
141 case M68k::MOVZXd32p16:
142 return TII->ExpandMOVSZX_RM(MIB, false, TII->get(M68k::MOV16rp), MVT::i32,
143 MVT::i16);
145 case M68k::MOVSXd16f8:
146 return TII->ExpandMOVSZX_RM(MIB, true, TII->get(M68k::MOV8df), MVT::i16,
147 MVT::i8);
148 case M68k::MOVSXd32f8:
149 return TII->ExpandMOVSZX_RM(MIB, true, TII->get(M68k::MOV8df), MVT::i32,
150 MVT::i8);
151 case M68k::MOVSXd32f16:
152 return TII->ExpandMOVSZX_RM(MIB, true, TII->get(M68k::MOV16rf), MVT::i32,
153 MVT::i16);
155 case M68k::MOVZXd16f8:
156 return TII->ExpandMOVSZX_RM(MIB, false, TII->get(M68k::MOV8df), MVT::i16,
157 MVT::i8);
158 case M68k::MOVZXd32f8:
159 return TII->ExpandMOVSZX_RM(MIB, false, TII->get(M68k::MOV8df), MVT::i32,
160 MVT::i8);
161 case M68k::MOVZXd32f16:
162 return TII->ExpandMOVSZX_RM(MIB, false, TII->get(M68k::MOV16rf), MVT::i32,
163 MVT::i16);
165 case M68k::MOV8cd:
166 return TII->ExpandCCR(MIB, /*IsToCCR=*/true);
167 case M68k::MOV8dc:
168 return TII->ExpandCCR(MIB, /*IsToCCR=*/false);
170 case M68k::MOVM8jm_P:
171 return TII->ExpandMOVEM(MIB, TII->get(M68k::MOVM32jm), /*IsRM=*/false);
172 case M68k::MOVM16jm_P:
173 return TII->ExpandMOVEM(MIB, TII->get(M68k::MOVM32jm), /*IsRM=*/false);
174 case M68k::MOVM32jm_P:
175 return TII->ExpandMOVEM(MIB, TII->get(M68k::MOVM32jm), /*IsRM=*/false);
177 case M68k::MOVM8pm_P:
178 return TII->ExpandMOVEM(MIB, TII->get(M68k::MOVM32pm), /*IsRM=*/false);
179 case M68k::MOVM16pm_P:
180 return TII->ExpandMOVEM(MIB, TII->get(M68k::MOVM32pm), /*IsRM=*/false);
181 case M68k::MOVM32pm_P:
182 return TII->ExpandMOVEM(MIB, TII->get(M68k::MOVM32pm), /*IsRM=*/false);
184 case M68k::MOVM8mj_P:
185 return TII->ExpandMOVEM(MIB, TII->get(M68k::MOVM32mj), /*IsRM=*/true);
186 case M68k::MOVM16mj_P:
187 return TII->ExpandMOVEM(MIB, TII->get(M68k::MOVM32mj), /*IsRM=*/true);
188 case M68k::MOVM32mj_P:
189 return TII->ExpandMOVEM(MIB, TII->get(M68k::MOVM32mj), /*IsRM=*/true);
191 case M68k::MOVM8mp_P:
192 return TII->ExpandMOVEM(MIB, TII->get(M68k::MOVM32mp), /*IsRM=*/true);
193 case M68k::MOVM16mp_P:
194 return TII->ExpandMOVEM(MIB, TII->get(M68k::MOVM32mp), /*IsRM=*/true);
195 case M68k::MOVM32mp_P:
196 return TII->ExpandMOVEM(MIB, TII->get(M68k::MOVM32mp), /*IsRM=*/true);
198 case M68k::TCRETURNq:
199 case M68k::TCRETURNj: {
200 MachineOperand &JumpTarget = MI.getOperand(0);
201 MachineOperand &StackAdjust = MI.getOperand(1);
202 assert(StackAdjust.isImm() && "Expecting immediate value.");
204 // Adjust stack pointer.
205 int StackAdj = StackAdjust.getImm();
206 int MaxTCDelta = MFI->getTCReturnAddrDelta();
207 int Offset = 0;
208 assert(MaxTCDelta <= 0 && "MaxTCDelta should never be positive");
210 // Incoporate the retaddr area.
211 Offset = StackAdj - MaxTCDelta;
212 assert(Offset >= 0 && "Offset should never be negative");
214 if (Offset) {
215 // Check for possible merge with preceding ADD instruction.
216 Offset += FL->mergeSPUpdates(MBB, MBBI, true);
217 FL->emitSPUpdate(MBB, MBBI, Offset, /*InEpilogue=*/true);
220 // Jump to label or value in register.
221 if (Opcode == M68k::TCRETURNq) {
222 MachineInstrBuilder MIB =
223 BuildMI(MBB, MBBI, DL, TII->get(M68k::TAILJMPq));
224 if (JumpTarget.isGlobal()) {
225 MIB.addGlobalAddress(JumpTarget.getGlobal(), JumpTarget.getOffset(),
226 JumpTarget.getTargetFlags());
227 } else {
228 assert(JumpTarget.isSymbol());
229 MIB.addExternalSymbol(JumpTarget.getSymbolName(),
230 JumpTarget.getTargetFlags());
232 } else {
233 BuildMI(MBB, MBBI, DL, TII->get(M68k::TAILJMPj))
234 .addReg(JumpTarget.getReg(), RegState::Kill);
237 MachineInstr &NewMI = *std::prev(MBBI);
238 NewMI.copyImplicitOps(*MBBI->getParent()->getParent(), *MBBI);
240 // Delete the pseudo instruction TCRETURN.
241 MBB.erase(MBBI);
243 return true;
245 case M68k::RET: {
246 // Adjust stack to erase error code
247 int64_t StackAdj = MBBI->getOperand(0).getImm();
248 MachineInstrBuilder MIB;
250 if (StackAdj == 0) {
251 MIB = BuildMI(MBB, MBBI, DL, TII->get(M68k::RTS));
252 } else if (isUInt<16>(StackAdj)) {
254 if (STI->atLeastM68020()) {
255 llvm_unreachable("RTD is not implemented");
256 } else {
257 // Copy PC from stack to a free address(A0 or A1) register
258 // TODO check if pseudo expand uses free address register
259 BuildMI(MBB, MBBI, DL, TII->get(M68k::MOV32aj), M68k::A1)
260 .addReg(M68k::SP);
262 // Adjust SP
263 FL->emitSPUpdate(MBB, MBBI, StackAdj, /*InEpilogue=*/true);
265 // Put the return address on stack
266 BuildMI(MBB, MBBI, DL, TII->get(M68k::MOV32ja))
267 .addReg(M68k::SP)
268 .addReg(M68k::A1);
270 // RTS
271 BuildMI(MBB, MBBI, DL, TII->get(M68k::RTS));
273 } else {
274 // TODO: RTD can only handle immediates as big as 2**16-1.
275 // If we need to pop off bytes before the return address, we
276 // must do it manually.
277 llvm_unreachable("Stack adjustment size not supported");
280 // FIXME: Can rest of the operands be ignored, if there is any?
281 MBB.erase(MBBI);
282 return true;
285 llvm_unreachable("Previous switch has a fallthrough?");
288 /// Expand all pseudo instructions contained in \p MBB.
289 /// \returns true if any expansion occurred for \p MBB.
290 bool M68kExpandPseudo::ExpandMBB(MachineBasicBlock &MBB) {
291 bool Modified = false;
293 // MBBI may be invalidated by the expansion.
294 MachineBasicBlock::iterator MBBI = MBB.begin(), E = MBB.end();
295 while (MBBI != E) {
296 MachineBasicBlock::iterator NMBBI = std::next(MBBI);
297 Modified |= ExpandMI(MBB, MBBI);
298 MBBI = NMBBI;
301 return Modified;
304 bool M68kExpandPseudo::runOnMachineFunction(MachineFunction &MF) {
305 STI = &static_cast<const M68kSubtarget &>(MF.getSubtarget());
306 TII = STI->getInstrInfo();
307 TRI = STI->getRegisterInfo();
308 MFI = MF.getInfo<M68kMachineFunctionInfo>();
309 FL = STI->getFrameLowering();
311 bool Modified = false;
312 for (MachineBasicBlock &MBB : MF)
313 Modified |= ExpandMBB(MBB);
314 return Modified;
317 /// Returns an instance of the pseudo instruction expansion pass.
318 FunctionPass *llvm::createM68kExpandPseudoPass() {
319 return new M68kExpandPseudo();