LLVM 21.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
57 MachineFunctionProperties::Property::NoVRegs);
58 }
59
60private:
62 bool ExpandMBB(MachineBasicBlock &MBB);
63};
64char M68kExpandPseudo::ID = 0;
65} // End anonymous namespace.
66
67INITIALIZE_PASS(M68kExpandPseudo, DEBUG_TYPE, PASS_NAME, false, false)
68
69/// If \p MBBI is a pseudo instruction, this method expands
70/// it to the corresponding (sequence of) actual instruction(s).
71/// \returns true if \p MBBI has been expanded.
72bool M68kExpandPseudo::ExpandMI(MachineBasicBlock &MBB,
73 MachineBasicBlock::iterator MBBI) {
75 MachineInstrBuilder MIB(*MI.getParent()->getParent(), MI);
76 unsigned Opcode = MI.getOpcode();
77 DebugLoc DL = MBBI->getDebugLoc();
78 /// TODO infer argument size to create less switch cases
79 switch (Opcode) {
80 default:
81 return false;
82
83 case M68k::MOVI8di:
84 return TII->ExpandMOVI(MIB, MVT::i8);
85 case M68k::MOVI16ri:
86 return TII->ExpandMOVI(MIB, MVT::i16);
87 case M68k::MOVI32ri:
88 return TII->ExpandMOVI(MIB, MVT::i32);
89
90 case M68k::MOVXd16d8:
91 return TII->ExpandMOVX_RR(MIB, MVT::i16, MVT::i8);
92 case M68k::MOVXd32d8:
93 return TII->ExpandMOVX_RR(MIB, MVT::i32, MVT::i8);
94 case M68k::MOVXd32d16:
95 return TII->ExpandMOVX_RR(MIB, MVT::i32, MVT::i16);
96
97 case M68k::MOVSXd16d8:
98 return TII->ExpandMOVSZX_RR(MIB, true, MVT::i16, MVT::i8);
99 case M68k::MOVSXd32d8:
100 return TII->ExpandMOVSZX_RR(MIB, true, MVT::i32, MVT::i8);
101 case M68k::MOVSXd32d16:
102 return TII->ExpandMOVSZX_RR(MIB, true, MVT::i32, MVT::i16);
103
104 case M68k::MOVZXd16d8:
105 return TII->ExpandMOVSZX_RR(MIB, false, MVT::i16, MVT::i8);
106 case M68k::MOVZXd32d8:
107 return TII->ExpandMOVSZX_RR(MIB, false, MVT::i32, MVT::i8);
108 case M68k::MOVZXd32d16:
109 return TII->ExpandMOVSZX_RR(MIB, false, MVT::i32, MVT::i16);
110
111 case M68k::MOVSXd16j8:
112 return TII->ExpandMOVSZX_RM(MIB, true, TII->get(M68k::MOV8dj), MVT::i16,
113 MVT::i8);
114 case M68k::MOVSXd32j8:
115 return TII->ExpandMOVSZX_RM(MIB, true, TII->get(M68k::MOV8dj), MVT::i32,
116 MVT::i8);
117 case M68k::MOVSXd32j16:
118 return TII->ExpandMOVSZX_RM(MIB, true, TII->get(M68k::MOV16rj), MVT::i32,
119 MVT::i16);
120
121 case M68k::MOVZXd16j8:
122 return TII->ExpandMOVSZX_RM(MIB, false, TII->get(M68k::MOV8dj), MVT::i16,
123 MVT::i8);
124 case M68k::MOVZXd32j8:
125 return TII->ExpandMOVSZX_RM(MIB, false, TII->get(M68k::MOV8dj), MVT::i32,
126 MVT::i8);
127 case M68k::MOVZXd32j16:
128 return TII->ExpandMOVSZX_RM(MIB, false, TII->get(M68k::MOV16rj), MVT::i32,
129 MVT::i16);
130
131 case M68k::MOVSXd16p8:
132 return TII->ExpandMOVSZX_RM(MIB, true, TII->get(M68k::MOV8dp), MVT::i16,
133 MVT::i8);
134 case M68k::MOVSXd32p8:
135 return TII->ExpandMOVSZX_RM(MIB, true, TII->get(M68k::MOV8dp), MVT::i32,
136 MVT::i8);
137 case M68k::MOVSXd32p16:
138 return TII->ExpandMOVSZX_RM(MIB, true, TII->get(M68k::MOV16rp), MVT::i32,
139 MVT::i16);
140
141 case M68k::MOVZXd16p8:
142 return TII->ExpandMOVSZX_RM(MIB, false, TII->get(M68k::MOV8dp), MVT::i16,
143 MVT::i8);
144 case M68k::MOVZXd32p8:
145 return TII->ExpandMOVSZX_RM(MIB, false, TII->get(M68k::MOV8dp), MVT::i32,
146 MVT::i8);
147 case M68k::MOVZXd32p16:
148 return TII->ExpandMOVSZX_RM(MIB, false, TII->get(M68k::MOV16rp), MVT::i32,
149 MVT::i16);
150
151 case M68k::MOVSXd16f8:
152 return TII->ExpandMOVSZX_RM(MIB, true, TII->get(M68k::MOV8df), MVT::i16,
153 MVT::i8);
154 case M68k::MOVSXd32f8:
155 return TII->ExpandMOVSZX_RM(MIB, true, TII->get(M68k::MOV8df), MVT::i32,
156 MVT::i8);
157 case M68k::MOVSXd32f16:
158 return TII->ExpandMOVSZX_RM(MIB, true, TII->get(M68k::MOV16rf), MVT::i32,
159 MVT::i16);
160
161 case M68k::MOVZXd16f8:
162 return TII->ExpandMOVSZX_RM(MIB, false, TII->get(M68k::MOV8df), MVT::i16,
163 MVT::i8);
164 case M68k::MOVZXd32f8:
165 return TII->ExpandMOVSZX_RM(MIB, false, TII->get(M68k::MOV8df), MVT::i32,
166 MVT::i8);
167 case M68k::MOVZXd32f16:
168 return TII->ExpandMOVSZX_RM(MIB, false, TII->get(M68k::MOV16rf), MVT::i32,
169 MVT::i16);
170
171 case M68k::MOVSXd16q8:
172 return TII->ExpandMOVSZX_RM(MIB, true, TII->get(M68k::MOV8dq), MVT::i16,
173 MVT::i8);
174 case M68k::MOVSXd32q8:
175 return TII->ExpandMOVSZX_RM(MIB, true, TII->get(M68k::MOV8dq), MVT::i32,
176 MVT::i8);
177 case M68k::MOVSXd32q16:
178 return TII->ExpandMOVSZX_RM(MIB, true, TII->get(M68k::MOV16dq), MVT::i32,
179 MVT::i16);
180
181 case M68k::MOVZXd16q8:
182 return TII->ExpandMOVSZX_RM(MIB, false, TII->get(M68k::MOV8dq), MVT::i16,
183 MVT::i8);
184 case M68k::MOVZXd32q8:
185 return TII->ExpandMOVSZX_RM(MIB, false, TII->get(M68k::MOV8dq), MVT::i32,
186 MVT::i8);
187 case M68k::MOVZXd32q16:
188 return TII->ExpandMOVSZX_RM(MIB, false, TII->get(M68k::MOV16dq), MVT::i32,
189 MVT::i16);
190
191 case M68k::MOV8cd:
192 return TII->ExpandCCR(MIB, /*IsToCCR=*/true);
193 case M68k::MOV8dc:
194 return TII->ExpandCCR(MIB, /*IsToCCR=*/false);
195
196 case M68k::MOVM16jm_P:
197 return TII->ExpandMOVEM(MIB, TII->get(M68k::MOVM16jm), /*IsRM=*/false);
198 case M68k::MOVM32jm_P:
199 return TII->ExpandMOVEM(MIB, TII->get(M68k::MOVM32jm), /*IsRM=*/false);
200
201 case M68k::MOVM16pm_P:
202 return TII->ExpandMOVEM(MIB, TII->get(M68k::MOVM16pm), /*IsRM=*/false);
203 case M68k::MOVM32pm_P:
204 return TII->ExpandMOVEM(MIB, TII->get(M68k::MOVM32pm), /*IsRM=*/false);
205
206 case M68k::MOVM16mj_P:
207 return TII->ExpandMOVEM(MIB, TII->get(M68k::MOVM16mj), /*IsRM=*/true);
208 case M68k::MOVM32mj_P:
209 return TII->ExpandMOVEM(MIB, TII->get(M68k::MOVM32mj), /*IsRM=*/true);
210
211 case M68k::MOVM16mp_P:
212 return TII->ExpandMOVEM(MIB, TII->get(M68k::MOVM16mp), /*IsRM=*/true);
213 case M68k::MOVM32mp_P:
214 return TII->ExpandMOVEM(MIB, TII->get(M68k::MOVM32mp), /*IsRM=*/true);
215
216 case M68k::TCRETURNq:
217 case M68k::TCRETURNj: {
218 MachineOperand &JumpTarget = MI.getOperand(0);
219 MachineOperand &StackAdjust = MI.getOperand(1);
220 assert(StackAdjust.isImm() && "Expecting immediate value.");
221
222 // Adjust stack pointer.
223 int StackAdj = StackAdjust.getImm();
224 int MaxTCDelta = MFI->getTCReturnAddrDelta();
225 int Offset = 0;
226 assert(MaxTCDelta <= 0 && "MaxTCDelta should never be positive");
227
228 // Incoporate the retaddr area.
229 Offset = StackAdj - MaxTCDelta;
230 assert(Offset >= 0 && "Offset should never be negative");
231
232 if (Offset) {
233 // Check for possible merge with preceding ADD instruction.
234 Offset += FL->mergeSPUpdates(MBB, MBBI, true);
235 FL->emitSPUpdate(MBB, MBBI, Offset, /*InEpilogue=*/true);
236 }
237
238 // Jump to label or value in register.
239 if (Opcode == M68k::TCRETURNq) {
241 BuildMI(MBB, MBBI, DL, TII->get(M68k::TAILJMPq));
242 if (JumpTarget.isGlobal()) {
243 MIB.addGlobalAddress(JumpTarget.getGlobal(), JumpTarget.getOffset(),
244 JumpTarget.getTargetFlags());
245 } else {
246 assert(JumpTarget.isSymbol());
247 MIB.addExternalSymbol(JumpTarget.getSymbolName(),
248 JumpTarget.getTargetFlags());
249 }
250 } else {
251 BuildMI(MBB, MBBI, DL, TII->get(M68k::TAILJMPj))
252 .addReg(JumpTarget.getReg(), RegState::Kill);
253 }
254
255 MachineInstr &NewMI = *std::prev(MBBI);
256 NewMI.copyImplicitOps(*MBBI->getParent()->getParent(), *MBBI);
257
258 // Delete the pseudo instruction TCRETURN.
259 MBB.erase(MBBI);
260
261 return true;
262 }
263 case M68k::RET: {
266 BuildMI(MBB, MBBI, DL, TII->get(M68k::RTE));
267 } else if (int64_t StackAdj = MBBI->getOperand(0).getImm(); StackAdj == 0) {
268 BuildMI(MBB, MBBI, DL, TII->get(M68k::RTS));
269 } else {
270 // Copy return address from stack to a free address(A0 or A1) register
271 // TODO check if pseudo expand uses free address register
272 BuildMI(MBB, MBBI, DL, TII->get(M68k::MOV32aj), M68k::A1)
273 .addReg(M68k::SP);
274
275 // Adjust SP
276 FL->emitSPUpdate(MBB, MBBI, StackAdj, /*InEpilogue=*/true);
277
278 // Put the return address on stack
279 BuildMI(MBB, MBBI, DL, TII->get(M68k::MOV32ja))
280 .addReg(M68k::SP)
281 .addReg(M68k::A1);
282
283 // RTS
284 BuildMI(MBB, MBBI, DL, TII->get(M68k::RTS));
285 }
286
287 // FIXME: Can rest of the operands be ignored, if there is any?
288 MBB.erase(MBBI);
289 return true;
290 }
291 }
292 llvm_unreachable("Previous switch has a fallthrough?");
293}
294
295/// Expand all pseudo instructions contained in \p MBB.
296/// \returns true if any expansion occurred for \p MBB.
297bool M68kExpandPseudo::ExpandMBB(MachineBasicBlock &MBB) {
298 bool Modified = false;
299
300 // MBBI may be invalidated by the expansion.
302 while (MBBI != E) {
303 MachineBasicBlock::iterator NMBBI = std::next(MBBI);
304 Modified |= ExpandMI(MBB, MBBI);
305 MBBI = NMBBI;
306 }
307
308 return Modified;
309}
310
311bool M68kExpandPseudo::runOnMachineFunction(MachineFunction &MF) {
312 STI = &MF.getSubtarget<M68kSubtarget>();
313 TII = STI->getInstrInfo();
314 TRI = STI->getRegisterInfo();
316 FL = STI->getFrameLowering();
317
318 bool Modified = false;
319 for (MachineBasicBlock &MBB : MF)
320 Modified |= ExpandMBB(MBB);
321 return Modified;
322}
323
324/// Returns an instance of the pseudo instruction expansion pass.
326 return new M68kExpandPseudo();
327}
MachineBasicBlock & MBB
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
MachineBasicBlock MachineBasicBlock::iterator MBBI
const HexagonInstrInfo * TII
IRTranslator LLVM IR MI
#define PASS_NAME
#define DEBUG_TYPE
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
#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)
Definition: PassSupport.h:38
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:256
A debug info location.
Definition: DebugLoc.h:33
FunctionPass class - This class is used to implement most global optimizations.
Definition: Pass.h:310
CallingConv::ID getCallingConv() const
getCallingConv()/setCallingConv(CC) - These method get and set the calling convention of this functio...
Definition: Function.h:277
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.
Function & getFunction()
Return the LLVM function that this machine code represents.
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:71
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.
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
Definition: CallingConv.h:24
@ M68k_INTR
Used for M68k interrupt routines.
Definition: CallingConv.h:235
@ 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:480
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...