Path: blob/main/contrib/llvm-project/llvm/lib/Target/M68k/M68kExpandPseudo.cpp
35267 views
//===-- M68kExpandPseudo.cpp - Expand pseudo instructions -------*- C++ -*-===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//7///8/// \file9/// This file contains a pass that expands pseudo instructions into target10/// instructions to allow proper scheduling, if-conversion, other late11/// optimizations, or simply the encoding of the instructions.12///13//===----------------------------------------------------------------------===//1415#include "M68k.h"16#include "M68kFrameLowering.h"17#include "M68kInstrInfo.h"18#include "M68kMachineFunction.h"19#include "M68kSubtarget.h"2021#include "llvm/CodeGen/MachineFunctionPass.h"22#include "llvm/CodeGen/MachineInstrBuilder.h"23#include "llvm/CodeGen/MachineRegisterInfo.h"24#include "llvm/CodeGen/Passes.h" // For IDs of passes that are preserved.25#include "llvm/IR/EHPersonalities.h"26#include "llvm/IR/GlobalValue.h"2728using namespace llvm;2930#define DEBUG_TYPE "m68k-expand-pseudo"31#define PASS_NAME "M68k pseudo instruction expansion pass"3233namespace {34class M68kExpandPseudo : public MachineFunctionPass {35public:36static char ID;37M68kExpandPseudo() : MachineFunctionPass(ID) {}3839void getAnalysisUsage(AnalysisUsage &AU) const override {40AU.setPreservesCFG();41AU.addPreservedID(MachineLoopInfoID);42AU.addPreservedID(MachineDominatorsID);43MachineFunctionPass::getAnalysisUsage(AU);44}4546const M68kSubtarget *STI;47const M68kInstrInfo *TII;48const M68kRegisterInfo *TRI;49const M68kMachineFunctionInfo *MFI;50const M68kFrameLowering *FL;5152bool runOnMachineFunction(MachineFunction &Fn) override;5354MachineFunctionProperties getRequiredProperties() const override {55return MachineFunctionProperties().set(56MachineFunctionProperties::Property::NoVRegs);57}5859private:60bool ExpandMI(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI);61bool ExpandMBB(MachineBasicBlock &MBB);62};63char M68kExpandPseudo::ID = 0;64} // End anonymous namespace.6566INITIALIZE_PASS(M68kExpandPseudo, DEBUG_TYPE, PASS_NAME, false, false)6768/// 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,72MachineBasicBlock::iterator MBBI) {73MachineInstr &MI = *MBBI;74MachineInstrBuilder MIB(*MI.getParent()->getParent(), MI);75unsigned Opcode = MI.getOpcode();76DebugLoc DL = MBBI->getDebugLoc();77/// TODO infer argument size to create less switch cases78switch (Opcode) {79default:80return false;8182case M68k::MOVI8di:83return TII->ExpandMOVI(MIB, MVT::i8);84case M68k::MOVI16ri:85return TII->ExpandMOVI(MIB, MVT::i16);86case M68k::MOVI32ri:87return TII->ExpandMOVI(MIB, MVT::i32);8889case M68k::MOVXd16d8:90return TII->ExpandMOVX_RR(MIB, MVT::i16, MVT::i8);91case M68k::MOVXd32d8:92return TII->ExpandMOVX_RR(MIB, MVT::i32, MVT::i8);93case M68k::MOVXd32d16:94return TII->ExpandMOVX_RR(MIB, MVT::i32, MVT::i16);9596case M68k::MOVSXd16d8:97return TII->ExpandMOVSZX_RR(MIB, true, MVT::i16, MVT::i8);98case M68k::MOVSXd32d8:99return TII->ExpandMOVSZX_RR(MIB, true, MVT::i32, MVT::i8);100case M68k::MOVSXd32d16:101return TII->ExpandMOVSZX_RR(MIB, true, MVT::i32, MVT::i16);102103case M68k::MOVZXd16d8:104return TII->ExpandMOVSZX_RR(MIB, false, MVT::i16, MVT::i8);105case M68k::MOVZXd32d8:106return TII->ExpandMOVSZX_RR(MIB, false, MVT::i32, MVT::i8);107case M68k::MOVZXd32d16:108return TII->ExpandMOVSZX_RR(MIB, false, MVT::i32, MVT::i16);109110case M68k::MOVSXd16j8:111return TII->ExpandMOVSZX_RM(MIB, true, TII->get(M68k::MOV8dj), MVT::i16,112MVT::i8);113case M68k::MOVSXd32j8:114return TII->ExpandMOVSZX_RM(MIB, true, TII->get(M68k::MOV8dj), MVT::i32,115MVT::i8);116case M68k::MOVSXd32j16:117return TII->ExpandMOVSZX_RM(MIB, true, TII->get(M68k::MOV16rj), MVT::i32,118MVT::i16);119120case M68k::MOVZXd16j8:121return TII->ExpandMOVSZX_RM(MIB, false, TII->get(M68k::MOV8dj), MVT::i16,122MVT::i8);123case M68k::MOVZXd32j8:124return TII->ExpandMOVSZX_RM(MIB, false, TII->get(M68k::MOV8dj), MVT::i32,125MVT::i8);126case M68k::MOVZXd32j16:127return TII->ExpandMOVSZX_RM(MIB, false, TII->get(M68k::MOV16rj), MVT::i32,128MVT::i16);129130case M68k::MOVSXd16p8:131return TII->ExpandMOVSZX_RM(MIB, true, TII->get(M68k::MOV8dp), MVT::i16,132MVT::i8);133case M68k::MOVSXd32p8:134return TII->ExpandMOVSZX_RM(MIB, true, TII->get(M68k::MOV8dp), MVT::i32,135MVT::i8);136case M68k::MOVSXd32p16:137return TII->ExpandMOVSZX_RM(MIB, true, TII->get(M68k::MOV16rp), MVT::i32,138MVT::i16);139140case M68k::MOVZXd16p8:141return TII->ExpandMOVSZX_RM(MIB, false, TII->get(M68k::MOV8dp), MVT::i16,142MVT::i8);143case M68k::MOVZXd32p8:144return TII->ExpandMOVSZX_RM(MIB, false, TII->get(M68k::MOV8dp), MVT::i32,145MVT::i8);146case M68k::MOVZXd32p16:147return TII->ExpandMOVSZX_RM(MIB, false, TII->get(M68k::MOV16rp), MVT::i32,148MVT::i16);149150case M68k::MOVSXd16f8:151return TII->ExpandMOVSZX_RM(MIB, true, TII->get(M68k::MOV8df), MVT::i16,152MVT::i8);153case M68k::MOVSXd32f8:154return TII->ExpandMOVSZX_RM(MIB, true, TII->get(M68k::MOV8df), MVT::i32,155MVT::i8);156case M68k::MOVSXd32f16:157return TII->ExpandMOVSZX_RM(MIB, true, TII->get(M68k::MOV16rf), MVT::i32,158MVT::i16);159160case M68k::MOVZXd16f8:161return TII->ExpandMOVSZX_RM(MIB, false, TII->get(M68k::MOV8df), MVT::i16,162MVT::i8);163case M68k::MOVZXd32f8:164return TII->ExpandMOVSZX_RM(MIB, false, TII->get(M68k::MOV8df), MVT::i32,165MVT::i8);166case M68k::MOVZXd32f16:167return TII->ExpandMOVSZX_RM(MIB, false, TII->get(M68k::MOV16rf), MVT::i32,168MVT::i16);169170case M68k::MOVSXd16q8:171return TII->ExpandMOVSZX_RM(MIB, true, TII->get(M68k::MOV8dq), MVT::i16,172MVT::i8);173case M68k::MOVSXd32q8:174return TII->ExpandMOVSZX_RM(MIB, true, TII->get(M68k::MOV8dq), MVT::i32,175MVT::i8);176case M68k::MOVSXd32q16:177return TII->ExpandMOVSZX_RM(MIB, true, TII->get(M68k::MOV16dq), MVT::i32,178MVT::i16);179180case M68k::MOVZXd16q8:181return TII->ExpandMOVSZX_RM(MIB, false, TII->get(M68k::MOV8dq), MVT::i16,182MVT::i8);183case M68k::MOVZXd32q8:184return TII->ExpandMOVSZX_RM(MIB, false, TII->get(M68k::MOV8dq), MVT::i32,185MVT::i8);186case M68k::MOVZXd32q16:187return TII->ExpandMOVSZX_RM(MIB, false, TII->get(M68k::MOV16dq), MVT::i32,188MVT::i16);189190case M68k::MOV8cd:191return TII->ExpandCCR(MIB, /*IsToCCR=*/true);192case M68k::MOV8dc:193return TII->ExpandCCR(MIB, /*IsToCCR=*/false);194195case M68k::MOVM8jm_P:196return TII->ExpandMOVEM(MIB, TII->get(M68k::MOVM32jm), /*IsRM=*/false);197case M68k::MOVM16jm_P:198return TII->ExpandMOVEM(MIB, TII->get(M68k::MOVM32jm), /*IsRM=*/false);199case M68k::MOVM32jm_P:200return TII->ExpandMOVEM(MIB, TII->get(M68k::MOVM32jm), /*IsRM=*/false);201202case M68k::MOVM8pm_P:203return TII->ExpandMOVEM(MIB, TII->get(M68k::MOVM32pm), /*IsRM=*/false);204case M68k::MOVM16pm_P:205return TII->ExpandMOVEM(MIB, TII->get(M68k::MOVM32pm), /*IsRM=*/false);206case M68k::MOVM32pm_P:207return TII->ExpandMOVEM(MIB, TII->get(M68k::MOVM32pm), /*IsRM=*/false);208209case M68k::MOVM8mj_P:210return TII->ExpandMOVEM(MIB, TII->get(M68k::MOVM32mj), /*IsRM=*/true);211case M68k::MOVM16mj_P:212return TII->ExpandMOVEM(MIB, TII->get(M68k::MOVM32mj), /*IsRM=*/true);213case M68k::MOVM32mj_P:214return TII->ExpandMOVEM(MIB, TII->get(M68k::MOVM32mj), /*IsRM=*/true);215216case M68k::MOVM8mp_P:217return TII->ExpandMOVEM(MIB, TII->get(M68k::MOVM32mp), /*IsRM=*/true);218case M68k::MOVM16mp_P:219return TII->ExpandMOVEM(MIB, TII->get(M68k::MOVM32mp), /*IsRM=*/true);220case M68k::MOVM32mp_P:221return TII->ExpandMOVEM(MIB, TII->get(M68k::MOVM32mp), /*IsRM=*/true);222223case M68k::TCRETURNq:224case M68k::TCRETURNj: {225MachineOperand &JumpTarget = MI.getOperand(0);226MachineOperand &StackAdjust = MI.getOperand(1);227assert(StackAdjust.isImm() && "Expecting immediate value.");228229// Adjust stack pointer.230int StackAdj = StackAdjust.getImm();231int MaxTCDelta = MFI->getTCReturnAddrDelta();232int Offset = 0;233assert(MaxTCDelta <= 0 && "MaxTCDelta should never be positive");234235// Incoporate the retaddr area.236Offset = StackAdj - MaxTCDelta;237assert(Offset >= 0 && "Offset should never be negative");238239if (Offset) {240// Check for possible merge with preceding ADD instruction.241Offset += FL->mergeSPUpdates(MBB, MBBI, true);242FL->emitSPUpdate(MBB, MBBI, Offset, /*InEpilogue=*/true);243}244245// Jump to label or value in register.246if (Opcode == M68k::TCRETURNq) {247MachineInstrBuilder MIB =248BuildMI(MBB, MBBI, DL, TII->get(M68k::TAILJMPq));249if (JumpTarget.isGlobal()) {250MIB.addGlobalAddress(JumpTarget.getGlobal(), JumpTarget.getOffset(),251JumpTarget.getTargetFlags());252} else {253assert(JumpTarget.isSymbol());254MIB.addExternalSymbol(JumpTarget.getSymbolName(),255JumpTarget.getTargetFlags());256}257} else {258BuildMI(MBB, MBBI, DL, TII->get(M68k::TAILJMPj))259.addReg(JumpTarget.getReg(), RegState::Kill);260}261262MachineInstr &NewMI = *std::prev(MBBI);263NewMI.copyImplicitOps(*MBBI->getParent()->getParent(), *MBBI);264265// Delete the pseudo instruction TCRETURN.266MBB.erase(MBBI);267268return true;269}270case M68k::RET: {271if (MBB.getParent()->getFunction().getCallingConv() ==272CallingConv::M68k_INTR) {273BuildMI(MBB, MBBI, DL, TII->get(M68k::RTE));274} else if (int64_t StackAdj = MBBI->getOperand(0).getImm(); StackAdj == 0) {275BuildMI(MBB, MBBI, DL, TII->get(M68k::RTS));276} else {277// Copy return address from stack to a free address(A0 or A1) register278// TODO check if pseudo expand uses free address register279BuildMI(MBB, MBBI, DL, TII->get(M68k::MOV32aj), M68k::A1)280.addReg(M68k::SP);281282// Adjust SP283FL->emitSPUpdate(MBB, MBBI, StackAdj, /*InEpilogue=*/true);284285// Put the return address on stack286BuildMI(MBB, MBBI, DL, TII->get(M68k::MOV32ja))287.addReg(M68k::SP)288.addReg(M68k::A1);289290// RTS291BuildMI(MBB, MBBI, DL, TII->get(M68k::RTS));292}293294// FIXME: Can rest of the operands be ignored, if there is any?295MBB.erase(MBBI);296return true;297}298}299llvm_unreachable("Previous switch has a fallthrough?");300}301302/// Expand all pseudo instructions contained in \p MBB.303/// \returns true if any expansion occurred for \p MBB.304bool M68kExpandPseudo::ExpandMBB(MachineBasicBlock &MBB) {305bool Modified = false;306307// MBBI may be invalidated by the expansion.308MachineBasicBlock::iterator MBBI = MBB.begin(), E = MBB.end();309while (MBBI != E) {310MachineBasicBlock::iterator NMBBI = std::next(MBBI);311Modified |= ExpandMI(MBB, MBBI);312MBBI = NMBBI;313}314315return Modified;316}317318bool M68kExpandPseudo::runOnMachineFunction(MachineFunction &MF) {319STI = &MF.getSubtarget<M68kSubtarget>();320TII = STI->getInstrInfo();321TRI = STI->getRegisterInfo();322MFI = MF.getInfo<M68kMachineFunctionInfo>();323FL = STI->getFrameLowering();324325bool Modified = false;326for (MachineBasicBlock &MBB : MF)327Modified |= ExpandMBB(MBB);328return Modified;329}330331/// Returns an instance of the pseudo instruction expansion pass.332FunctionPass *llvm::createM68kExpandPseudoPass() {333return new M68kExpandPseudo();334}335336337