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
RISCVPostRAExpandPseudo()34*0fca6ea1SDimitry Andric RISCVPostRAExpandPseudo() : MachineFunctionPass(ID) {}
355f757f3fSDimitry Andric
365f757f3fSDimitry Andric bool runOnMachineFunction(MachineFunction &MF) override;
375f757f3fSDimitry Andric
getPassName() const385f757f3fSDimitry 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
runOnMachineFunction(MachineFunction & MF)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
expandMBB(MachineBasicBlock & MBB)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
expandMI(MachineBasicBlock & MBB,MachineBasicBlock::iterator MBBI,MachineBasicBlock::iterator & NextMBBI)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
expandMovImm(MachineBasicBlock & MBB,MachineBasicBlock::iterator MBBI)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
expandMovAddr(MachineBasicBlock & MBB,MachineBasicBlock::iterator MBBI)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
createRISCVPostRAExpandPseudoPass()1295f757f3fSDimitry Andric FunctionPass *createRISCVPostRAExpandPseudoPass() {
1305f757f3fSDimitry Andric return new RISCVPostRAExpandPseudo();
1315f757f3fSDimitry Andric }
1325f757f3fSDimitry Andric
1335f757f3fSDimitry Andric } // end of namespace llvm
134