LLVM  14.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 
26 #include "llvm/CodeGen/Passes.h" // For IDs of passes that are preserved.
27 #include "llvm/IR/GlobalValue.h"
28 
29 using namespace llvm;
30 
31 #define DEBUG_TYPE "M68k-expand-pseudos"
32 
33 namespace {
34 class M68kExpandPseudo : public MachineFunctionPass {
35 public:
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 
54  MachineFunctionProperties getRequiredProperties() const override {
57  }
58 
59  StringRef getPassName() const override {
60  return "M68k pseudo instruction expansion pass";
61  }
62 
63 private:
65  bool ExpandMBB(MachineBasicBlock &MBB);
66 };
67 char 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.
73 bool M68kExpandPseudo::ExpandMI(MachineBasicBlock &MBB,
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;
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) {
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());
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.
290 bool 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 
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();
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 }
MI
IRTranslator LLVM IR MI
Definition: IRTranslator.cpp:105
llvm
This is an optimization pass for GlobalISel generic memory operations.
Definition: AllocatorList.h:23
llvm::MachineOperand::getGlobal
const GlobalValue * getGlobal() const
Definition: MachineOperand.h:563
llvm::MachineFunctionPass
MachineFunctionPass - This class adapts the FunctionPass interface to allow convenient creation of pa...
Definition: MachineFunctionPass.h:30
llvm::M68kRegisterInfo
Definition: M68kRegisterInfo.h:30
llvm::MachineOperand::isSymbol
bool isSymbol() const
isSymbol - Tests if this is a MO_ExternalSymbol operand.
Definition: MachineOperand.h:341
EHPersonalities.h
llvm::MachineFunctionProperties
Properties which a MachineFunction may have at a given point in time.
Definition: MachineFunction.h:111
Offset
uint64_t Offset
Definition: ELFObjHandler.cpp:80
llvm::RegState::Kill
@ Kill
The last use of a register.
Definition: MachineInstrBuilder.h:48
llvm::MachineOperand::getOffset
int64_t getOffset() const
Return the offset from the symbol in this operand.
Definition: MachineOperand.h:600
TRI
unsigned const TargetRegisterInfo * TRI
Definition: MachineSink.cpp:1564
llvm::MachineFunctionPass::getAnalysisUsage
void getAnalysisUsage(AnalysisUsage &AU) const override
getAnalysisUsage - Subclasses that override getAnalysisUsage must call this.
Definition: MachineFunctionPass.cpp:102
MachineRegisterInfo.h
llvm::MachineBasicBlock::erase
instr_iterator erase(instr_iterator I)
Remove an instruction from the instruction list and delete it.
Definition: MachineBasicBlock.cpp:1298
M68k.h
M68kInstrInfo.h
GlobalValue.h
llvm::MachineInstr::copyImplicitOps
void copyImplicitOps(MachineFunction &MF, const MachineInstr &MI)
Copy implicit register operands from specified instruction to this instruction.
Definition: MachineInstr.cpp:1471
E
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
llvm::MachineOperand::getImm
int64_t getImm() const
Definition: MachineOperand.h:537
llvm::MachineFunction::getInfo
Ty * getInfo()
getInfo - Keep track of various per-function pieces of information for backends that would like to do...
Definition: MachineFunction.h:739
llvm::AnalysisUsage
Represent the analysis usage information of a pass.
Definition: PassAnalysisSupport.h:47
TII
const HexagonInstrInfo * TII
Definition: HexagonCopyToCombine.cpp:127
llvm::MachineOperand
MachineOperand class - Representation of each machine instruction operand.
Definition: MachineOperand.h:49
llvm::MachineFunctionProperties::set
MachineFunctionProperties & set(Property P)
Definition: MachineFunction.h:180
LoopDeletionResult::Modified
@ Modified
llvm::MachineInstrBuilder::addExternalSymbol
const MachineInstrBuilder & addExternalSymbol(const char *FnName, unsigned TargetFlags=0) const
Definition: MachineInstrBuilder.h:184
M68kFrameLowering.h
llvm::MachineBasicBlock
Definition: MachineBasicBlock.h:95
llvm::M68kSubtarget
Definition: M68kSubtarget.h:45
llvm::MachineFunctionProperties::Property::NoVRegs
@ NoVRegs
Passes.h
llvm::MachineFunction::getSubtarget
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
Definition: MachineFunction.h:641
llvm::MachineLoopInfoID
char & MachineLoopInfoID
MachineLoopInfo - This pass is a loop analysis pass.
Definition: MachineLoopInfo.cpp:44
llvm::isUInt< 16 >
constexpr bool isUInt< 16 >(uint64_t x)
Definition: MathExtras.h:408
llvm::MachineOperand::getTargetFlags
unsigned getTargetFlags() const
Definition: MachineOperand.h:221
llvm::MachineInstr
Representation of each machine instruction.
Definition: MachineInstr.h:64
llvm::MachineInstrBuilder
Definition: MachineInstrBuilder.h:69
MachineFunctionPass.h
llvm::MVT::i8
@ i8
Definition: MachineValueType.h:44
assert
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
llvm::MachineBasicBlock::getParent
const MachineFunction * getParent() const
Return the MachineFunction containing this basic block.
Definition: MachineBasicBlock.h:229
llvm::MachineInstrBuilder::addReg
const MachineInstrBuilder & addReg(Register RegNo, unsigned flags=0, unsigned SubReg=0) const
Add a new virtual register operand.
Definition: MachineInstrBuilder.h:97
llvm::MachineOperand::getReg
Register getReg() const
getReg - Returns the register number.
Definition: MachineOperand.h:360
llvm::MachineFunction
Definition: MachineFunction.h:241
llvm::StringRef
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:57
llvm::AnalysisUsage::setPreservesCFG
void setPreservesCFG()
This function should be called by the pass, iff they do not:
Definition: Pass.cpp:253
llvm::AnalysisUsage::addPreservedID
AnalysisUsage & addPreservedID(const void *ID)
Definition: PassAnalysisSupport.h:88
MBBI
MachineBasicBlock MachineBasicBlock::iterator MBBI
Definition: AArch64SLSHardening.cpp:75
llvm_unreachable
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
Definition: ErrorHandling.h:134
llvm::M68kMachineFunctionInfo
Definition: M68kMachineFunction.h:23
DL
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
Definition: AArch64SLSHardening.cpp:76
llvm::M68kFrameLowering
Definition: M68kFrameLowering.h:28
llvm::M68kInstrInfo
Definition: M68kInstrInfo.h:237
MBB
MachineBasicBlock & MBB
Definition: AArch64SLSHardening.cpp:74
llvm::ARCISD::RET
@ RET
Definition: ARCISelLowering.h:52
M68kMachineFunction.h
llvm::MVT::i32
@ i32
Definition: MachineValueType.h:46
llvm::MachineOperand::isImm
bool isImm() const
isImm - Tests if this is a MO_Immediate operand.
Definition: MachineOperand.h:323
llvm::MachineInstrBuilder::addGlobalAddress
const MachineInstrBuilder & addGlobalAddress(const GlobalValue *GV, int64_t Offset=0, unsigned TargetFlags=0) const
Definition: MachineInstrBuilder.h:177
llvm::createM68kExpandPseudoPass
FunctionPass * createM68kExpandPseudoPass()
Return a Machine IR pass that expands M68k-specific pseudo instructions into a sequence of actual ins...
Definition: M68kExpandPseudo.cpp:318
llvm::MachineBasicBlock::begin
iterator begin()
Definition: MachineBasicBlock.h:272
MachineInstrBuilder.h
llvm::MachineOperand::getSymbolName
const char * getSymbolName() const
Definition: MachineOperand.h:608
llvm::BuildMI
MachineInstrBuilder BuildMI(MachineFunction &MF, const DebugLoc &DL, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
Definition: MachineInstrBuilder.h:328
llvm::MachineDominatorsID
char & MachineDominatorsID
MachineDominators - This pass is a machine dominators analysis pass.
M68kSubtarget.h
llvm::MVT::i16
@ i16
Definition: MachineValueType.h:45
llvm::FunctionPass
FunctionPass class - This class is used to implement most global optimizations.
Definition: Pass.h:298
llvm::DebugLoc
A debug info location.
Definition: DebugLoc.h:33
llvm::MachineInstrBundleIterator< MachineInstr >
llvm::MachineBasicBlock::end
iterator end()
Definition: MachineBasicBlock.h:274
llvm::MachineOperand::isGlobal
bool isGlobal() const
isGlobal - Tests if this is a MO_GlobalAddress operand.
Definition: MachineOperand.h:339
llvm::Intrinsic::ID
unsigned ID
Definition: TargetTransformInfo.h:38