LLVM 17.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-pseudos"
32
33namespace {
34class M68kExpandPseudo : public MachineFunctionPass {
35public:
36 static char ID;
37 M68kExpandPseudo() : MachineFunctionPass(ID) {}
38
39 void getAnalysisUsage(AnalysisUsage &AU) const override {
40 AU.setPreservesCFG();
44 }
45
46 const M68kSubtarget *STI;
47 const M68kInstrInfo *TII;
48 const M68kRegisterInfo *TRI;
49 const M68kMachineFunctionInfo *MFI;
50 const M68kFrameLowering *FL;
51
52 bool runOnMachineFunction(MachineFunction &Fn) override;
53
56 MachineFunctionProperties::Property::NoVRegs);
57 }
58
59 StringRef getPassName() const override {
60 return "M68k pseudo instruction expansion pass";
61 }
62
63private:
65 bool ExpandMBB(MachineBasicBlock &MBB);
66};
67char M68kExpandPseudo::ID = 0;
68} // End anonymous namespace.
69
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.
73bool M68kExpandPseudo::ExpandMI(MachineBasicBlock &MBB,
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;
83
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);
90
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);
97
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);
104
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);
114
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);
124
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);
134
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);
144
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);
154
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);
164
165 case M68k::MOV8cd:
166 return TII->ExpandCCR(MIB, /*IsToCCR=*/true);
167 case M68k::MOV8dc:
168 return TII->ExpandCCR(MIB, /*IsToCCR=*/false);
169
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);
176
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);
183
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);
190
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);
197
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.");
203
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");
209
210 // Incoporate the retaddr area.
211 Offset = StackAdj - MaxTCDelta;
212 assert(Offset >= 0 && "Offset should never be negative");
213
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);
218 }
219
220 // Jump to label or value in register.
221 if (Opcode == M68k::TCRETURNq) {
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());
231 }
232 } else {
233 BuildMI(MBB, MBBI, DL, TII->get(M68k::TAILJMPj))
234 .addReg(JumpTarget.getReg(), RegState::Kill);
235 }
236
237 MachineInstr &NewMI = *std::prev(MBBI);
238 NewMI.copyImplicitOps(*MBBI->getParent()->getParent(), *MBBI);
239
240 // Delete the pseudo instruction TCRETURN.
241 MBB.erase(MBBI);
242
243 return true;
244 }
245 case M68k::RET: {
246 // Adjust stack to erase error code
247 int64_t StackAdj = MBBI->getOperand(0).getImm();
249
250 if (StackAdj == 0) {
251 MIB = BuildMI(MBB, MBBI, DL, TII->get(M68k::RTS));
252 } else if (isUInt<16>(StackAdj)) {
253
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);
261
262 // Adjust SP
263 FL->emitSPUpdate(MBB, MBBI, StackAdj, /*InEpilogue=*/true);
264
265 // Put the return address on stack
266 BuildMI(MBB, MBBI, DL, TII->get(M68k::MOV32ja))
267 .addReg(M68k::SP)
268 .addReg(M68k::A1);
269
270 // RTS
271 BuildMI(MBB, MBBI, DL, TII->get(M68k::RTS));
272 }
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");
278 }
279
280 // FIXME: Can rest of the operands be ignored, if there is any?
281 MBB.erase(MBBI);
282 return true;
283 }
284 }
285 llvm_unreachable("Previous switch has a fallthrough?");
286}
287
288/// Expand all pseudo instructions contained in \p MBB.
289/// \returns true if any expansion occurred for \p MBB.
290bool M68kExpandPseudo::ExpandMBB(MachineBasicBlock &MBB) {
291 bool Modified = false;
292
293 // MBBI may be invalidated by the expansion.
295 while (MBBI != E) {
296 MachineBasicBlock::iterator NMBBI = std::next(MBBI);
297 Modified |= ExpandMI(MBB, MBBI);
298 MBBI = NMBBI;
299 }
300
301 return Modified;
302}
303
304bool M68kExpandPseudo::runOnMachineFunction(MachineFunction &MF) {
305 STI = &MF.getSubtarget<M68kSubtarget>();
306 TII = STI->getInstrInfo();
307 TRI = STI->getRegisterInfo();
309 FL = STI->getFrameLowering();
310
311 bool Modified = false;
312 for (MachineBasicBlock &MBB : MF)
313 Modified |= ExpandMBB(MBB);
314 return Modified;
315}
316
317/// Returns an instance of the pseudo instruction expansion pass.
319 return new M68kExpandPseudo();
320}
MachineBasicBlock & MBB
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
MachineBasicBlock MachineBasicBlock::iterator MBBI
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
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,...
unsigned const TargetRegisterInfo * TRI
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
Represent the analysis usage information of a pass.
AnalysisUsage & addPreservedID(const void *ID)
void setPreservesCFG()
This function should be called by the pass, iff they do not:
Definition: Pass.cpp:265
A debug info location.
Definition: DebugLoc.h:33
FunctionPass class - This class is used to implement most global optimizations.
Definition: Pass.h:308
const MachineFunction * getParent() const
Return the MachineFunction containing this basic block.
instr_iterator erase(instr_iterator I)
Remove an instruction from the instruction list and delete it.
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.
virtual bool runOnMachineFunction(MachineFunction &MF)=0
runOnMachineFunction - This method must be overloaded to perform the desired machine code transformat...
virtual MachineFunctionProperties getRequiredProperties() const
Properties which a MachineFunction may have at a given point in time.
MachineFunctionProperties & set(Property P)
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 & addGlobalAddress(const GlobalValue *GV, int64_t Offset=0, unsigned TargetFlags=0) const
const MachineInstrBuilder & addReg(Register RegNo, unsigned flags=0, unsigned SubReg=0) const
Add a new virtual register operand.
Representation of each machine instruction.
Definition: MachineInstr.h:68
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.
virtual StringRef getPassName() const
getPassName - Return a nice clean name for a pass.
Definition: Pass.cpp:81
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:50
#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
@ Kill
The last use of a register.
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
@ Offset
Definition: DWP.cpp:406
MachineInstrBuilder BuildMI(MachineFunction &MF, const MIMetadata &MIMD, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
char & MachineDominatorsID
MachineDominators - This pass is a machine dominators analysis pass.
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...