LLVM 24.0.0git
M68kExpandPseudo.cpp
Go to the documentation of this file.
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//===----------------------------------------------------------------------===//
15
16#include "M68k.h"
17#include "M68kFrameLowering.h"
18#include "M68kInstrInfo.h"
19#include "M68kMachineFunction.h"
20#include "M68kSubtarget.h"
21
25#include "llvm/CodeGen/Passes.h" // For IDs of passes that are preserved.
27#include "llvm/IR/GlobalValue.h"
28
29using namespace llvm;
30
31#define DEBUG_TYPE "m68k-expand-pseudo"
32#define PASS_NAME "M68k pseudo instruction expansion pass"
33
34namespace {
35class M68kExpandPseudo : public MachineFunctionPass {
36public:
37 static char ID;
38 M68kExpandPseudo() : MachineFunctionPass(ID) {}
39
40 void getAnalysisUsage(AnalysisUsage &AU) const override {
41 AU.setPreservesCFG();
45 }
46
47 const M68kSubtarget *STI;
48 const M68kInstrInfo *TII;
49 const M68kRegisterInfo *TRI;
50 const M68kMachineFunctionInfo *MFI;
51 const M68kFrameLowering *FL;
52
53 bool runOnMachineFunction(MachineFunction &Fn) override;
54
55 MachineFunctionProperties getRequiredProperties() const override {
56 return MachineFunctionProperties().setNoVRegs();
57 }
58
59private:
61 bool ExpandMBB(MachineBasicBlock &MBB);
62};
63char M68kExpandPseudo::ID = 0;
64} // End anonymous namespace.
65
66INITIALIZE_PASS(M68kExpandPseudo, DEBUG_TYPE, PASS_NAME, false, false)
67
68/// If \p MBBI is a pseudo instruction, this method expands
69/// it to the corresponding (sequence of) actual instruction(s).
70/// \returns true if \p MBBI has been expanded.
71bool M68kExpandPseudo::ExpandMI(MachineBasicBlock &MBB,
74 MachineInstrBuilder MIB(*MI.getParent()->getParent(), MI);
75 unsigned Opcode = MI.getOpcode();
76 DebugLoc DL = MBBI->getDebugLoc();
77 /// TODO infer argument size to create less switch cases
78 switch (Opcode) {
79 default:
80 return false;
81
82 case M68k::MOVI8di:
83 return TII->ExpandMOVI(MIB, MVT::i8);
84 case M68k::MOVI16di:
85 return TII->ExpandMOVI(MIB, MVT::i16);
86 case M68k::MOVI32ri:
87 return TII->ExpandMOVI(MIB, MVT::i32);
88
89 case M68k::MOVXd16d8:
90 return TII->ExpandMOVX_RR(MIB, MVT::i16, MVT::i8);
91 case M68k::MOVXd32d8:
92 return TII->ExpandMOVX_RR(MIB, MVT::i32, MVT::i8);
93 case M68k::MOVXd32d16:
94 return TII->ExpandMOVX_RR(MIB, MVT::i32, MVT::i16);
95
96 case M68k::MOVSXd16d8:
97 return TII->ExpandMOVSZX_RR(MIB, true, MVT::i16, MVT::i8);
98 case M68k::MOVSXd32d8:
99 return TII->ExpandMOVSZX_RR(MIB, true, MVT::i32, MVT::i8);
100 case M68k::MOVSXd32d16:
101 return TII->ExpandMOVSZX_RR(MIB, true, MVT::i32, MVT::i16);
102
103 case M68k::MOVZXd16d8:
104 return TII->ExpandMOVSZX_RR(MIB, false, MVT::i16, MVT::i8);
105 case M68k::MOVZXd32d8:
106 return TII->ExpandMOVSZX_RR(MIB, false, MVT::i32, MVT::i8);
107 case M68k::MOVZXd32d16:
108 return TII->ExpandMOVSZX_RR(MIB, false, MVT::i32, MVT::i16);
109
110 case M68k::MOVSXd16j8:
111 return TII->ExpandMOVSZX_RM(MIB, true, TII->get(M68k::MOV8dj), MVT::i16,
112 MVT::i8);
113 case M68k::MOVSXd32j8:
114 return TII->ExpandMOVSZX_RM(MIB, true, TII->get(M68k::MOV8dj), MVT::i32,
115 MVT::i8);
116 case M68k::MOVSXd32j16:
117 return TII->ExpandMOVSZX_RM(MIB, true, TII->get(M68k::MOV16rj), MVT::i32,
118 MVT::i16);
119
120 case M68k::MOVZXd16j8:
121 return TII->ExpandMOVSZX_RM(MIB, false, TII->get(M68k::MOV8dj), MVT::i16,
122 MVT::i8);
123 case M68k::MOVZXd32j8:
124 return TII->ExpandMOVSZX_RM(MIB, false, TII->get(M68k::MOV8dj), MVT::i32,
125 MVT::i8);
126 case M68k::MOVZXd32j16:
127 return TII->ExpandMOVSZX_RM(MIB, false, TII->get(M68k::MOV16rj), MVT::i32,
128 MVT::i16);
129
130 case M68k::MOVSXd16p8:
131 return TII->ExpandMOVSZX_RM(MIB, true, TII->get(M68k::MOV8dp), MVT::i16,
132 MVT::i8);
133 case M68k::MOVSXd32p8:
134 return TII->ExpandMOVSZX_RM(MIB, true, TII->get(M68k::MOV8dp), MVT::i32,
135 MVT::i8);
136 case M68k::MOVSXd32p16:
137 return TII->ExpandMOVSZX_RM(MIB, true, TII->get(M68k::MOV16rp), MVT::i32,
138 MVT::i16);
139
140 case M68k::MOVZXd16p8:
141 return TII->ExpandMOVSZX_RM(MIB, false, TII->get(M68k::MOV8dp), MVT::i16,
142 MVT::i8);
143 case M68k::MOVZXd32p8:
144 return TII->ExpandMOVSZX_RM(MIB, false, TII->get(M68k::MOV8dp), MVT::i32,
145 MVT::i8);
146 case M68k::MOVZXd32p16:
147 return TII->ExpandMOVSZX_RM(MIB, false, TII->get(M68k::MOV16rp), MVT::i32,
148 MVT::i16);
149
150 case M68k::MOVSXd16f8:
151 return TII->ExpandMOVSZX_RM(MIB, true, TII->get(M68k::MOV8df), MVT::i16,
152 MVT::i8);
153 case M68k::MOVSXd32f8:
154 return TII->ExpandMOVSZX_RM(MIB, true, TII->get(M68k::MOV8df), MVT::i32,
155 MVT::i8);
156 case M68k::MOVSXd32f16:
157 return TII->ExpandMOVSZX_RM(MIB, true, TII->get(M68k::MOV16rf), MVT::i32,
158 MVT::i16);
159
160 case M68k::MOVZXd16f8:
161 return TII->ExpandMOVSZX_RM(MIB, false, TII->get(M68k::MOV8df), MVT::i16,
162 MVT::i8);
163 case M68k::MOVZXd32f8:
164 return TII->ExpandMOVSZX_RM(MIB, false, TII->get(M68k::MOV8df), MVT::i32,
165 MVT::i8);
166 case M68k::MOVZXd32f16:
167 return TII->ExpandMOVSZX_RM(MIB, false, TII->get(M68k::MOV16rf), MVT::i32,
168 MVT::i16);
169
170 case M68k::MOVSXd16q8:
171 return TII->ExpandMOVSZX_RM(MIB, true, TII->get(M68k::MOV8dq), MVT::i16,
172 MVT::i8);
173 case M68k::MOVSXd32q8:
174 return TII->ExpandMOVSZX_RM(MIB, true, TII->get(M68k::MOV8dq), MVT::i32,
175 MVT::i8);
176 case M68k::MOVSXd32q16:
177 return TII->ExpandMOVSZX_RM(MIB, true, TII->get(M68k::MOV16dq), MVT::i32,
178 MVT::i16);
179
180 case M68k::MOVZXd16q8:
181 return TII->ExpandMOVSZX_RM(MIB, false, TII->get(M68k::MOV8dq), MVT::i16,
182 MVT::i8);
183 case M68k::MOVZXd32q8:
184 return TII->ExpandMOVSZX_RM(MIB, false, TII->get(M68k::MOV8dq), MVT::i32,
185 MVT::i8);
186 case M68k::MOVZXd32q16:
187 return TII->ExpandMOVSZX_RM(MIB, false, TII->get(M68k::MOV16dq), MVT::i32,
188 MVT::i16);
189
190 case M68k::MOVM8jm_P:
191 case M68k::MOVM16jm_P:
192 return TII->ExpandMOVEM(MIB, TII->get(M68k::MOVM16jm), /*IsRM=*/false);
193 case M68k::MOVM32jm_P:
194 return TII->ExpandMOVEM(MIB, TII->get(M68k::MOVM32jm), /*IsRM=*/false);
195
196 case M68k::MOVM8pm_P:
197 case M68k::MOVM16pm_P:
198 return TII->ExpandMOVEM(MIB, TII->get(M68k::MOVM16pm), /*IsRM=*/false);
199 case M68k::MOVM32pm_P:
200 return TII->ExpandMOVEM(MIB, TII->get(M68k::MOVM32pm), /*IsRM=*/false);
201
202 case M68k::MOVM8mj_P:
203 case M68k::MOVM16mj_P:
204 return TII->ExpandMOVEM(MIB, TII->get(M68k::MOVM16mj), /*IsRM=*/true);
205 case M68k::MOVM32mj_P:
206 return TII->ExpandMOVEM(MIB, TII->get(M68k::MOVM32mj), /*IsRM=*/true);
207
208 case M68k::MOVM8mp_P:
209 case M68k::MOVM16mp_P:
210 return TII->ExpandMOVEM(MIB, TII->get(M68k::MOVM16mp), /*IsRM=*/true);
211 case M68k::MOVM32mp_P:
212 return TII->ExpandMOVEM(MIB, TII->get(M68k::MOVM32mp), /*IsRM=*/true);
213
214 case M68k::TCRETURNq:
215 case M68k::TCRETURNj: {
216 MachineOperand &JumpTarget = MI.getOperand(0);
217 MachineOperand &StackAdjust = MI.getOperand(1);
218 assert(StackAdjust.isImm() && "Expecting immediate value.");
219
220 // Adjust stack pointer.
221 int StackAdj = StackAdjust.getImm();
222 int MaxTCDelta = MFI->getTCReturnAddrDelta();
223 int Offset = 0;
224 assert(MaxTCDelta <= 0 && "MaxTCDelta should never be positive");
225
226 // Incoporate the retaddr area.
227 Offset = StackAdj - MaxTCDelta;
228 assert(Offset >= 0 && "Offset should never be negative");
229
230 if (Offset) {
231 // Check for possible merge with preceding ADD instruction.
232 Offset += FL->mergeSPUpdates(MBB, MBBI, true);
233 FL->emitSPUpdate(MBB, MBBI, Offset, /*InEpilogue=*/true);
234 }
235
236 // Jump to label or value in register.
237 if (Opcode == M68k::TCRETURNq) {
239 BuildMI(MBB, MBBI, DL, TII->get(M68k::TAILJMPq));
240 if (JumpTarget.isGlobal()) {
241 MIB.addGlobalAddress(JumpTarget.getGlobal(), JumpTarget.getOffset(),
242 JumpTarget.getTargetFlags());
243 } else {
244 assert(JumpTarget.isSymbol());
245 MIB.addExternalSymbol(JumpTarget.getSymbolName(),
246 JumpTarget.getTargetFlags());
247 }
248 } else {
249 BuildMI(MBB, MBBI, DL, TII->get(M68k::TAILJMPj))
250 .addReg(JumpTarget.getReg(), RegState::Kill);
251 }
252
253 MachineInstr &NewMI = *std::prev(MBBI);
254 NewMI.copyImplicitOps(*MBBI->getParent()->getParent(), *MBBI);
255
256 // Delete the pseudo instruction TCRETURN.
257 MBB.erase(MBBI);
258
259 return true;
260 }
261 case M68k::RET: {
262 if (MBB.getParent()->getFunction().getCallingConv() ==
264 BuildMI(MBB, MBBI, DL, TII->get(M68k::RTE));
265 } else if (int64_t StackAdj = MBBI->getOperand(0).getImm(); StackAdj == 0) {
266 BuildMI(MBB, MBBI, DL, TII->get(M68k::RTS));
267 } else {
268 // Copy return address from stack to a free address(A0 or A1) register
269 // TODO check if pseudo expand uses free address register
270 BuildMI(MBB, MBBI, DL, TII->get(M68k::MOV32aj), M68k::A1)
271 .addReg(M68k::SP);
272
273 // Adjust SP
274 FL->emitSPUpdate(MBB, MBBI, StackAdj, /*InEpilogue=*/true);
275
276 // Put the return address on stack
277 BuildMI(MBB, MBBI, DL, TII->get(M68k::MOV32ja))
278 .addReg(M68k::SP)
279 .addReg(M68k::A1);
280
281 // RTS
282 BuildMI(MBB, MBBI, DL, TII->get(M68k::RTS));
283 }
284
285 // FIXME: Can rest of the operands be ignored, if there is any?
286 MBB.erase(MBBI);
287 return true;
288 }
289 }
290 llvm_unreachable("Previous switch has a fallthrough?");
291}
292
293/// Expand all pseudo instructions contained in \p MBB.
294/// \returns true if any expansion occurred for \p MBB.
295bool M68kExpandPseudo::ExpandMBB(MachineBasicBlock &MBB) {
296 bool Modified = false;
297
298 // MBBI may be invalidated by the expansion.
300 while (MBBI != E) {
301 MachineBasicBlock::iterator NMBBI = std::next(MBBI);
302 Modified |= ExpandMI(MBB, MBBI);
303 MBBI = NMBBI;
304 }
305
306 return Modified;
307}
308
309bool M68kExpandPseudo::runOnMachineFunction(MachineFunction &MF) {
310 STI = &MF.getSubtarget<M68kSubtarget>();
311 TII = STI->getInstrInfo();
312 TRI = STI->getRegisterInfo();
313 MFI = MF.getInfo<M68kMachineFunctionInfo>();
314 FL = STI->getFrameLowering();
315
316 bool Modified = false;
317 for (MachineBasicBlock &MBB : MF)
318 Modified |= ExpandMBB(MBB);
319 return Modified;
320}
321
322/// Returns an instance of the pseudo instruction expansion pass.
324 return new M68kExpandPseudo();
325}
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
MachineBasicBlock & MBB
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
MachineBasicBlock MachineBasicBlock::iterator MBBI
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
#define DEBUG_TYPE
const HexagonInstrInfo * TII
IRTranslator LLVM IR MI
This file contains the M68k declaration of TargetFrameLowering class.
This file contains the M68k implementation of the TargetInstrInfo class.
This file declares the M68k specific subclass of MachineFunctionInfo.
This file declares the M68k specific subclass of TargetSubtargetInfo.
This file contains the entry points for global functions defined in the M68k target library,...
Register const TargetRegisterInfo * TRI
#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)
Definition PassSupport.h:56
#define PASS_NAME
Represent the analysis usage information of a pass.
AnalysisUsage & addPreservedID(const void *ID)
LLVM_ABI void setPreservesCFG()
This function should be called by the pass, iff they do not:
Definition Pass.cpp:278
A debug info location.
Definition DebugLoc.h:126
FunctionPass class - This class is used to implement most global optimizations.
Definition Pass.h:314
const M68kInstrInfo * getInstrInfo() const override
const M68kRegisterInfo * getRegisterInfo() const override
const M68kFrameLowering * getFrameLowering() const override
MachineInstrBundleIterator< MachineInstr > iterator
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.
Properties which a MachineFunction may have at a given point in time.
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
Ty * getInfo()
getInfo - Keep track of various per-function pieces of information for backends that would like to do...
const MachineInstrBuilder & addExternalSymbol(const char *FnName, unsigned TargetFlags=0) const
const MachineInstrBuilder & addReg(Register RegNo, RegState Flags={}, unsigned SubReg=0) const
Add a new virtual register operand.
const MachineInstrBuilder & addGlobalAddress(const GlobalValue *GV, int64_t Offset=0, unsigned TargetFlags=0) const
Representation of each machine instruction.
LLVM_ABI void copyImplicitOps(MachineFunction &MF, const MachineInstr &MI)
Copy implicit register operands from specified instruction to this instruction.
MachineOperand class - Representation of each machine instruction operand.
const GlobalValue * getGlobal() const
int64_t getImm() const
bool isImm() const
isImm - Tests if this is a MO_Immediate operand.
bool isSymbol() const
isSymbol - Tests if this is a MO_ExternalSymbol operand.
unsigned getTargetFlags() const
bool isGlobal() const
isGlobal - Tests if this is a MO_GlobalAddress operand.
const char * getSymbolName() const
Register getReg() const
getReg - Returns the register number.
int64_t getOffset() const
Return the offset from the symbol in this operand.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
@ M68k_INTR
Used for M68k interrupt routines.
This is an optimization pass for GlobalISel generic memory operations.
@ Offset
Definition DWP.cpp:577
MachineInstrBuilder BuildMI(MachineFunction &MF, const MIMetadata &MIMD, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
@ Kill
The last use of a register.
LLVM_ABI char & MachineDominatorsID
MachineDominators - This pass is a machine dominators analysis pass.
LLVM_ABI char & MachineLoopInfoID
MachineLoopInfo - This pass is a loop analysis pass.
FunctionPass * createM68kExpandPseudoPass()
Return a Machine IR pass that expands M68k-specific pseudo instructions into a sequence of actual ins...