Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/contrib/llvm-project/llvm/lib/Target/M68k/M68kExpandPseudo.cpp
35267 views
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
22
#include "llvm/CodeGen/MachineFunctionPass.h"
23
#include "llvm/CodeGen/MachineInstrBuilder.h"
24
#include "llvm/CodeGen/MachineRegisterInfo.h"
25
#include "llvm/CodeGen/Passes.h" // For IDs of passes that are preserved.
26
#include "llvm/IR/EHPersonalities.h"
27
#include "llvm/IR/GlobalValue.h"
28
29
using namespace llvm;
30
31
#define DEBUG_TYPE "m68k-expand-pseudo"
32
#define PASS_NAME "M68k pseudo instruction expansion pass"
33
34
namespace {
35
class M68kExpandPseudo : public MachineFunctionPass {
36
public:
37
static char ID;
38
M68kExpandPseudo() : MachineFunctionPass(ID) {}
39
40
void getAnalysisUsage(AnalysisUsage &AU) const override {
41
AU.setPreservesCFG();
42
AU.addPreservedID(MachineLoopInfoID);
43
AU.addPreservedID(MachineDominatorsID);
44
MachineFunctionPass::getAnalysisUsage(AU);
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().set(
57
MachineFunctionProperties::Property::NoVRegs);
58
}
59
60
private:
61
bool ExpandMI(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI);
62
bool ExpandMBB(MachineBasicBlock &MBB);
63
};
64
char M68kExpandPseudo::ID = 0;
65
} // End anonymous namespace.
66
67
INITIALIZE_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.
72
bool M68kExpandPseudo::ExpandMI(MachineBasicBlock &MBB,
73
MachineBasicBlock::iterator MBBI) {
74
MachineInstr &MI = *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::MOVM8jm_P:
197
return TII->ExpandMOVEM(MIB, TII->get(M68k::MOVM32jm), /*IsRM=*/false);
198
case M68k::MOVM16jm_P:
199
return TII->ExpandMOVEM(MIB, TII->get(M68k::MOVM32jm), /*IsRM=*/false);
200
case M68k::MOVM32jm_P:
201
return TII->ExpandMOVEM(MIB, TII->get(M68k::MOVM32jm), /*IsRM=*/false);
202
203
case M68k::MOVM8pm_P:
204
return TII->ExpandMOVEM(MIB, TII->get(M68k::MOVM32pm), /*IsRM=*/false);
205
case M68k::MOVM16pm_P:
206
return TII->ExpandMOVEM(MIB, TII->get(M68k::MOVM32pm), /*IsRM=*/false);
207
case M68k::MOVM32pm_P:
208
return TII->ExpandMOVEM(MIB, TII->get(M68k::MOVM32pm), /*IsRM=*/false);
209
210
case M68k::MOVM8mj_P:
211
return TII->ExpandMOVEM(MIB, TII->get(M68k::MOVM32mj), /*IsRM=*/true);
212
case M68k::MOVM16mj_P:
213
return TII->ExpandMOVEM(MIB, TII->get(M68k::MOVM32mj), /*IsRM=*/true);
214
case M68k::MOVM32mj_P:
215
return TII->ExpandMOVEM(MIB, TII->get(M68k::MOVM32mj), /*IsRM=*/true);
216
217
case M68k::MOVM8mp_P:
218
return TII->ExpandMOVEM(MIB, TII->get(M68k::MOVM32mp), /*IsRM=*/true);
219
case M68k::MOVM16mp_P:
220
return TII->ExpandMOVEM(MIB, TII->get(M68k::MOVM32mp), /*IsRM=*/true);
221
case M68k::MOVM32mp_P:
222
return TII->ExpandMOVEM(MIB, TII->get(M68k::MOVM32mp), /*IsRM=*/true);
223
224
case M68k::TCRETURNq:
225
case M68k::TCRETURNj: {
226
MachineOperand &JumpTarget = MI.getOperand(0);
227
MachineOperand &StackAdjust = MI.getOperand(1);
228
assert(StackAdjust.isImm() && "Expecting immediate value.");
229
230
// Adjust stack pointer.
231
int StackAdj = StackAdjust.getImm();
232
int MaxTCDelta = MFI->getTCReturnAddrDelta();
233
int Offset = 0;
234
assert(MaxTCDelta <= 0 && "MaxTCDelta should never be positive");
235
236
// Incoporate the retaddr area.
237
Offset = StackAdj - MaxTCDelta;
238
assert(Offset >= 0 && "Offset should never be negative");
239
240
if (Offset) {
241
// Check for possible merge with preceding ADD instruction.
242
Offset += FL->mergeSPUpdates(MBB, MBBI, true);
243
FL->emitSPUpdate(MBB, MBBI, Offset, /*InEpilogue=*/true);
244
}
245
246
// Jump to label or value in register.
247
if (Opcode == M68k::TCRETURNq) {
248
MachineInstrBuilder MIB =
249
BuildMI(MBB, MBBI, DL, TII->get(M68k::TAILJMPq));
250
if (JumpTarget.isGlobal()) {
251
MIB.addGlobalAddress(JumpTarget.getGlobal(), JumpTarget.getOffset(),
252
JumpTarget.getTargetFlags());
253
} else {
254
assert(JumpTarget.isSymbol());
255
MIB.addExternalSymbol(JumpTarget.getSymbolName(),
256
JumpTarget.getTargetFlags());
257
}
258
} else {
259
BuildMI(MBB, MBBI, DL, TII->get(M68k::TAILJMPj))
260
.addReg(JumpTarget.getReg(), RegState::Kill);
261
}
262
263
MachineInstr &NewMI = *std::prev(MBBI);
264
NewMI.copyImplicitOps(*MBBI->getParent()->getParent(), *MBBI);
265
266
// Delete the pseudo instruction TCRETURN.
267
MBB.erase(MBBI);
268
269
return true;
270
}
271
case M68k::RET: {
272
if (MBB.getParent()->getFunction().getCallingConv() ==
273
CallingConv::M68k_INTR) {
274
BuildMI(MBB, MBBI, DL, TII->get(M68k::RTE));
275
} else if (int64_t StackAdj = MBBI->getOperand(0).getImm(); StackAdj == 0) {
276
BuildMI(MBB, MBBI, DL, TII->get(M68k::RTS));
277
} else {
278
// Copy return address from stack to a free address(A0 or A1) register
279
// TODO check if pseudo expand uses free address register
280
BuildMI(MBB, MBBI, DL, TII->get(M68k::MOV32aj), M68k::A1)
281
.addReg(M68k::SP);
282
283
// Adjust SP
284
FL->emitSPUpdate(MBB, MBBI, StackAdj, /*InEpilogue=*/true);
285
286
// Put the return address on stack
287
BuildMI(MBB, MBBI, DL, TII->get(M68k::MOV32ja))
288
.addReg(M68k::SP)
289
.addReg(M68k::A1);
290
291
// RTS
292
BuildMI(MBB, MBBI, DL, TII->get(M68k::RTS));
293
}
294
295
// FIXME: Can rest of the operands be ignored, if there is any?
296
MBB.erase(MBBI);
297
return true;
298
}
299
}
300
llvm_unreachable("Previous switch has a fallthrough?");
301
}
302
303
/// Expand all pseudo instructions contained in \p MBB.
304
/// \returns true if any expansion occurred for \p MBB.
305
bool M68kExpandPseudo::ExpandMBB(MachineBasicBlock &MBB) {
306
bool Modified = false;
307
308
// MBBI may be invalidated by the expansion.
309
MachineBasicBlock::iterator MBBI = MBB.begin(), E = MBB.end();
310
while (MBBI != E) {
311
MachineBasicBlock::iterator NMBBI = std::next(MBBI);
312
Modified |= ExpandMI(MBB, MBBI);
313
MBBI = NMBBI;
314
}
315
316
return Modified;
317
}
318
319
bool M68kExpandPseudo::runOnMachineFunction(MachineFunction &MF) {
320
STI = &MF.getSubtarget<M68kSubtarget>();
321
TII = STI->getInstrInfo();
322
TRI = STI->getRegisterInfo();
323
MFI = MF.getInfo<M68kMachineFunctionInfo>();
324
FL = STI->getFrameLowering();
325
326
bool Modified = false;
327
for (MachineBasicBlock &MBB : MF)
328
Modified |= ExpandMBB(MBB);
329
return Modified;
330
}
331
332
/// Returns an instance of the pseudo instruction expansion pass.
333
FunctionPass *llvm::createM68kExpandPseudoPass() {
334
return new M68kExpandPseudo();
335
}
336
337