327 lines · cpp
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-exception6//7//===----------------------------------------------------------------------===//8///9/// \file10/// This file contains a pass that expands pseudo instructions into target11/// instructions to allow proper scheduling, if-conversion, other late12/// 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 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();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().setNoVRegs();57 }58 59private:60 bool ExpandMI(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI);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 expands69/// it to the corresponding (sequence of) actual instruction(s).70/// \returns true if \p MBBI has been expanded.71bool M68kExpandPseudo::ExpandMI(MachineBasicBlock &MBB,72 MachineBasicBlock::iterator MBBI) {73 MachineInstr &MI = *MBBI;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 cases78 switch (Opcode) {79 default:80 return false;81 82 case M68k::MOVI8di:83 return TII->ExpandMOVI(MIB, MVT::i8);84 case M68k::MOVI16ri: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::MOV8cd:191 return TII->ExpandCCR(MIB, /*IsToCCR=*/true);192 case M68k::MOV8dc:193 return TII->ExpandCCR(MIB, /*IsToCCR=*/false);194 195 case M68k::MOVM16jm_P:196 return TII->ExpandMOVEM(MIB, TII->get(M68k::MOVM16jm), /*IsRM=*/false);197 case M68k::MOVM32jm_P:198 return TII->ExpandMOVEM(MIB, TII->get(M68k::MOVM32jm), /*IsRM=*/false);199 200 case M68k::MOVM16pm_P:201 return TII->ExpandMOVEM(MIB, TII->get(M68k::MOVM16pm), /*IsRM=*/false);202 case M68k::MOVM32pm_P:203 return TII->ExpandMOVEM(MIB, TII->get(M68k::MOVM32pm), /*IsRM=*/false);204 205 case M68k::MOVM16mj_P:206 return TII->ExpandMOVEM(MIB, TII->get(M68k::MOVM16mj), /*IsRM=*/true);207 case M68k::MOVM32mj_P:208 return TII->ExpandMOVEM(MIB, TII->get(M68k::MOVM32mj), /*IsRM=*/true);209 210 case M68k::MOVM16mp_P:211 return TII->ExpandMOVEM(MIB, TII->get(M68k::MOVM16mp), /*IsRM=*/true);212 case M68k::MOVM32mp_P:213 return TII->ExpandMOVEM(MIB, TII->get(M68k::MOVM32mp), /*IsRM=*/true);214 215 case M68k::TCRETURNq:216 case M68k::TCRETURNj: {217 MachineOperand &JumpTarget = MI.getOperand(0);218 MachineOperand &StackAdjust = MI.getOperand(1);219 assert(StackAdjust.isImm() && "Expecting immediate value.");220 221 // Adjust stack pointer.222 int StackAdj = StackAdjust.getImm();223 int MaxTCDelta = MFI->getTCReturnAddrDelta();224 int Offset = 0;225 assert(MaxTCDelta <= 0 && "MaxTCDelta should never be positive");226 227 // Incoporate the retaddr area.228 Offset = StackAdj - MaxTCDelta;229 assert(Offset >= 0 && "Offset should never be negative");230 231 if (Offset) {232 // Check for possible merge with preceding ADD instruction.233 Offset += FL->mergeSPUpdates(MBB, MBBI, true);234 FL->emitSPUpdate(MBB, MBBI, Offset, /*InEpilogue=*/true);235 }236 237 // Jump to label or value in register.238 if (Opcode == M68k::TCRETURNq) {239 MachineInstrBuilder MIB =240 BuildMI(MBB, MBBI, DL, TII->get(M68k::TAILJMPq));241 if (JumpTarget.isGlobal()) {242 MIB.addGlobalAddress(JumpTarget.getGlobal(), JumpTarget.getOffset(),243 JumpTarget.getTargetFlags());244 } else {245 assert(JumpTarget.isSymbol());246 MIB.addExternalSymbol(JumpTarget.getSymbolName(),247 JumpTarget.getTargetFlags());248 }249 } else {250 BuildMI(MBB, MBBI, DL, TII->get(M68k::TAILJMPj))251 .addReg(JumpTarget.getReg(), RegState::Kill);252 }253 254 MachineInstr &NewMI = *std::prev(MBBI);255 NewMI.copyImplicitOps(*MBBI->getParent()->getParent(), *MBBI);256 257 // Delete the pseudo instruction TCRETURN.258 MBB.erase(MBBI);259 260 return true;261 }262 case M68k::RET: {263 if (MBB.getParent()->getFunction().getCallingConv() ==264 CallingConv::M68k_INTR) {265 BuildMI(MBB, MBBI, DL, TII->get(M68k::RTE));266 } else if (int64_t StackAdj = MBBI->getOperand(0).getImm(); StackAdj == 0) {267 BuildMI(MBB, MBBI, DL, TII->get(M68k::RTS));268 } else {269 // Copy return address from stack to a free address(A0 or A1) register270 // TODO check if pseudo expand uses free address register271 BuildMI(MBB, MBBI, DL, TII->get(M68k::MOV32aj), M68k::A1)272 .addReg(M68k::SP);273 274 // Adjust SP275 FL->emitSPUpdate(MBB, MBBI, StackAdj, /*InEpilogue=*/true);276 277 // Put the return address on stack278 BuildMI(MBB, MBBI, DL, TII->get(M68k::MOV32ja))279 .addReg(M68k::SP)280 .addReg(M68k::A1);281 282 // RTS283 BuildMI(MBB, MBBI, DL, TII->get(M68k::RTS));284 }285 286 // FIXME: Can rest of the operands be ignored, if there is any?287 MBB.erase(MBBI);288 return true;289 }290 }291 llvm_unreachable("Previous switch has a fallthrough?");292}293 294/// Expand all pseudo instructions contained in \p MBB.295/// \returns true if any expansion occurred for \p MBB.296bool M68kExpandPseudo::ExpandMBB(MachineBasicBlock &MBB) {297 bool Modified = false;298 299 // MBBI may be invalidated by the expansion.300 MachineBasicBlock::iterator MBBI = MBB.begin(), E = MBB.end();301 while (MBBI != E) {302 MachineBasicBlock::iterator NMBBI = std::next(MBBI);303 Modified |= ExpandMI(MBB, MBBI);304 MBBI = NMBBI;305 }306 307 return Modified;308}309 310bool M68kExpandPseudo::runOnMachineFunction(MachineFunction &MF) {311 STI = &MF.getSubtarget<M68kSubtarget>();312 TII = STI->getInstrInfo();313 TRI = STI->getRegisterInfo();314 MFI = MF.getInfo<M68kMachineFunctionInfo>();315 FL = STI->getFrameLowering();316 317 bool Modified = false;318 for (MachineBasicBlock &MBB : MF)319 Modified |= ExpandMBB(MBB);320 return Modified;321}322 323/// Returns an instance of the pseudo instruction expansion pass.324FunctionPass *llvm::createM68kExpandPseudoPass() {325 return new M68kExpandPseudo();326}327