15f757f3fSDimitry Andric //===-- RISCVPostRAExpandPseudoInsts.cpp - Expand pseudo instrs ----===// 25f757f3fSDimitry Andric // 35f757f3fSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 45f757f3fSDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 55f757f3fSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 65f757f3fSDimitry Andric // 75f757f3fSDimitry Andric //===----------------------------------------------------------------------===// 85f757f3fSDimitry Andric // 95f757f3fSDimitry Andric // This file contains a pass that expands the pseudo instruction pseudolisimm32 105f757f3fSDimitry Andric // into target instructions. This pass should be run during the post-regalloc 115f757f3fSDimitry Andric // passes, before post RA scheduling. 125f757f3fSDimitry Andric // 135f757f3fSDimitry Andric //===----------------------------------------------------------------------===// 145f757f3fSDimitry Andric 155f757f3fSDimitry Andric #include "MCTargetDesc/RISCVMatInt.h" 165f757f3fSDimitry Andric #include "RISCV.h" 175f757f3fSDimitry Andric #include "RISCVInstrInfo.h" 185f757f3fSDimitry Andric #include "RISCVTargetMachine.h" 195f757f3fSDimitry Andric #include "llvm/CodeGen/MachineFunctionPass.h" 205f757f3fSDimitry Andric #include "llvm/CodeGen/MachineInstrBuilder.h" 215f757f3fSDimitry Andric 225f757f3fSDimitry Andric using namespace llvm; 235f757f3fSDimitry Andric 245f757f3fSDimitry Andric #define RISCV_POST_RA_EXPAND_PSEUDO_NAME \ 255f757f3fSDimitry Andric "RISC-V post-regalloc pseudo instruction expansion pass" 265f757f3fSDimitry Andric 275f757f3fSDimitry Andric namespace { 285f757f3fSDimitry Andric 295f757f3fSDimitry Andric class RISCVPostRAExpandPseudo : public MachineFunctionPass { 305f757f3fSDimitry Andric public: 315f757f3fSDimitry Andric const RISCVInstrInfo *TII; 325f757f3fSDimitry Andric static char ID; 335f757f3fSDimitry Andric 34*0fca6ea1SDimitry Andric RISCVPostRAExpandPseudo() : MachineFunctionPass(ID) {} 355f757f3fSDimitry Andric 365f757f3fSDimitry Andric bool runOnMachineFunction(MachineFunction &MF) override; 375f757f3fSDimitry Andric 385f757f3fSDimitry Andric StringRef getPassName() const override { 395f757f3fSDimitry Andric return RISCV_POST_RA_EXPAND_PSEUDO_NAME; 405f757f3fSDimitry Andric } 415f757f3fSDimitry Andric 425f757f3fSDimitry Andric private: 435f757f3fSDimitry Andric bool expandMBB(MachineBasicBlock &MBB); 445f757f3fSDimitry Andric bool expandMI(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, 455f757f3fSDimitry Andric MachineBasicBlock::iterator &NextMBBI); 465f757f3fSDimitry Andric bool expandMovImm(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI); 47*0fca6ea1SDimitry Andric bool expandMovAddr(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI); 485f757f3fSDimitry Andric }; 495f757f3fSDimitry Andric 505f757f3fSDimitry Andric char RISCVPostRAExpandPseudo::ID = 0; 515f757f3fSDimitry Andric 525f757f3fSDimitry Andric bool RISCVPostRAExpandPseudo::runOnMachineFunction(MachineFunction &MF) { 535f757f3fSDimitry Andric TII = static_cast<const RISCVInstrInfo *>(MF.getSubtarget().getInstrInfo()); 545f757f3fSDimitry Andric bool Modified = false; 555f757f3fSDimitry Andric for (auto &MBB : MF) 565f757f3fSDimitry Andric Modified |= expandMBB(MBB); 575f757f3fSDimitry Andric return Modified; 585f757f3fSDimitry Andric } 595f757f3fSDimitry Andric 605f757f3fSDimitry Andric bool RISCVPostRAExpandPseudo::expandMBB(MachineBasicBlock &MBB) { 615f757f3fSDimitry Andric bool Modified = false; 625f757f3fSDimitry Andric 635f757f3fSDimitry Andric MachineBasicBlock::iterator MBBI = MBB.begin(), E = MBB.end(); 645f757f3fSDimitry Andric while (MBBI != E) { 655f757f3fSDimitry Andric MachineBasicBlock::iterator NMBBI = std::next(MBBI); 665f757f3fSDimitry Andric Modified |= expandMI(MBB, MBBI, NMBBI); 675f757f3fSDimitry Andric MBBI = NMBBI; 685f757f3fSDimitry Andric } 695f757f3fSDimitry Andric 705f757f3fSDimitry Andric return Modified; 715f757f3fSDimitry Andric } 725f757f3fSDimitry Andric 735f757f3fSDimitry Andric bool RISCVPostRAExpandPseudo::expandMI(MachineBasicBlock &MBB, 745f757f3fSDimitry Andric MachineBasicBlock::iterator MBBI, 755f757f3fSDimitry Andric MachineBasicBlock::iterator &NextMBBI) { 765f757f3fSDimitry Andric switch (MBBI->getOpcode()) { 775f757f3fSDimitry Andric case RISCV::PseudoMovImm: 785f757f3fSDimitry Andric return expandMovImm(MBB, MBBI); 79*0fca6ea1SDimitry Andric case RISCV::PseudoMovAddr: 80*0fca6ea1SDimitry Andric return expandMovAddr(MBB, MBBI); 815f757f3fSDimitry Andric default: 825f757f3fSDimitry Andric return false; 835f757f3fSDimitry Andric } 845f757f3fSDimitry Andric } 855f757f3fSDimitry Andric 865f757f3fSDimitry Andric bool RISCVPostRAExpandPseudo::expandMovImm(MachineBasicBlock &MBB, 875f757f3fSDimitry Andric MachineBasicBlock::iterator MBBI) { 885f757f3fSDimitry Andric DebugLoc DL = MBBI->getDebugLoc(); 895f757f3fSDimitry Andric 905f757f3fSDimitry Andric int64_t Val = MBBI->getOperand(1).getImm(); 915f757f3fSDimitry Andric 925f757f3fSDimitry Andric Register DstReg = MBBI->getOperand(0).getReg(); 935f757f3fSDimitry Andric bool DstIsDead = MBBI->getOperand(0).isDead(); 945f757f3fSDimitry Andric bool Renamable = MBBI->getOperand(0).isRenamable(); 955f757f3fSDimitry Andric 965f757f3fSDimitry Andric TII->movImm(MBB, MBBI, DL, DstReg, Val, MachineInstr::NoFlags, Renamable, 975f757f3fSDimitry Andric DstIsDead); 985f757f3fSDimitry Andric 995f757f3fSDimitry Andric MBBI->eraseFromParent(); 1005f757f3fSDimitry Andric return true; 1015f757f3fSDimitry Andric } 1025f757f3fSDimitry Andric 103*0fca6ea1SDimitry Andric bool RISCVPostRAExpandPseudo::expandMovAddr(MachineBasicBlock &MBB, 104*0fca6ea1SDimitry Andric MachineBasicBlock::iterator MBBI) { 105*0fca6ea1SDimitry Andric DebugLoc DL = MBBI->getDebugLoc(); 106*0fca6ea1SDimitry Andric 107*0fca6ea1SDimitry Andric Register DstReg = MBBI->getOperand(0).getReg(); 108*0fca6ea1SDimitry Andric bool DstIsDead = MBBI->getOperand(0).isDead(); 109*0fca6ea1SDimitry Andric bool Renamable = MBBI->getOperand(0).isRenamable(); 110*0fca6ea1SDimitry Andric 111*0fca6ea1SDimitry Andric BuildMI(MBB, MBBI, DL, TII->get(RISCV::LUI)) 112*0fca6ea1SDimitry Andric .addReg(DstReg, RegState::Define | getRenamableRegState(Renamable)) 113*0fca6ea1SDimitry Andric .add(MBBI->getOperand(1)); 114*0fca6ea1SDimitry Andric BuildMI(MBB, MBBI, DL, TII->get(RISCV::ADDI)) 115*0fca6ea1SDimitry Andric .addReg(DstReg, RegState::Define | getDeadRegState(DstIsDead) | 116*0fca6ea1SDimitry Andric getRenamableRegState(Renamable)) 117*0fca6ea1SDimitry Andric .addReg(DstReg, RegState::Kill | getRenamableRegState(Renamable)) 118*0fca6ea1SDimitry Andric .add(MBBI->getOperand(2)); 119*0fca6ea1SDimitry Andric MBBI->eraseFromParent(); 120*0fca6ea1SDimitry Andric return true; 121*0fca6ea1SDimitry Andric } 122*0fca6ea1SDimitry Andric 1235f757f3fSDimitry Andric } // end of anonymous namespace 1245f757f3fSDimitry Andric 1255f757f3fSDimitry Andric INITIALIZE_PASS(RISCVPostRAExpandPseudo, "riscv-expand-pseudolisimm32", 1265f757f3fSDimitry Andric RISCV_POST_RA_EXPAND_PSEUDO_NAME, false, false) 1275f757f3fSDimitry Andric namespace llvm { 1285f757f3fSDimitry Andric 1295f757f3fSDimitry Andric FunctionPass *createRISCVPostRAExpandPseudoPass() { 1305f757f3fSDimitry Andric return new RISCVPostRAExpandPseudo(); 1315f757f3fSDimitry Andric } 1325f757f3fSDimitry Andric 1335f757f3fSDimitry Andric } // end of namespace llvm 134