130 lines · cpp
1//===- RISCVExegesisPostprocessing.cpp - Post processing MI for exegesis---===//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// \file9// This Pass converts some of the virtual register operands in VSETVLI and FRM10// pseudos into physical registers.11//12//===----------------------------------------------------------------------===//13 14#include "RISCV.h"15#include "RISCVExegesisPasses.h"16#include "llvm/CodeGen/MachineFunctionPass.h"17#include "llvm/CodeGen/MachineRegisterInfo.h"18#include "llvm/Support/Debug.h"19 20using namespace llvm;21 22#define DEBUG_TYPE "riscv-exegesis-post-processing"23 24namespace {25struct RISCVExegesisPostprocessing : public MachineFunctionPass {26 static char ID;27 28 RISCVExegesisPostprocessing() : MachineFunctionPass(ID) {}29 30 bool runOnMachineFunction(MachineFunction &MF) override;31 32 void getAnalysisUsage(AnalysisUsage &AU) const override {33 AU.setPreservesCFG();34 MachineFunctionPass::getAnalysisUsage(AU);35 }36 37private:38 // Extremely simple register allocator that picks a register that hasn't39 // been defined or used in this function.40 Register allocateGPRRegister(const MachineFunction &MF,41 const MachineRegisterInfo &MRI);42 43 bool processVSETVL(MachineInstr &MI, MachineRegisterInfo &MRI);44 bool processWriteFRM(MachineInstr &MI, MachineRegisterInfo &MRI);45};46} // anonymous namespace47 48char RISCVExegesisPostprocessing::ID = 0;49 50bool RISCVExegesisPostprocessing::runOnMachineFunction(MachineFunction &MF) {51 bool Changed = false;52 for (auto &MBB : MF)53 for (auto &MI : MBB) {54 unsigned Opcode = MI.getOpcode();55 switch (Opcode) {56 case RISCV::VSETVLI:57 case RISCV::VSETVL:58 case RISCV::PseudoVSETVLI:59 case RISCV::PseudoVSETVLIX0:60 Changed |= processVSETVL(MI, MF.getRegInfo());61 break;62 case RISCV::SwapFRMImm:63 case RISCV::WriteFRM:64 Changed |= processWriteFRM(MI, MF.getRegInfo());65 break;66 default:67 break;68 }69 }70 71 if (Changed)72 MF.getRegInfo().clearVirtRegs();73 74 LLVM_DEBUG(MF.print(dbgs() << "===After RISCVExegesisPostprocessing===\n");75 dbgs() << "\n");76 77 return Changed;78}79 80Register RISCVExegesisPostprocessing::allocateGPRRegister(81 const MachineFunction &MF, const MachineRegisterInfo &MRI) {82 const auto &TRI = *MRI.getTargetRegisterInfo();83 84 // We hope to avoid allocating callee-saved registers. And GPRTC85 // happens to account for nearly all caller-saved registers.86 const TargetRegisterClass *GPRClass = TRI.getRegClass(RISCV::GPRTCRegClassID);87 BitVector Candidates = TRI.getAllocatableSet(MF, GPRClass);88 89 for (unsigned SetIdx : Candidates.set_bits()) {90 if (MRI.reg_empty(Register(SetIdx)))91 return Register(SetIdx);92 }93 94 // All bets are off, assign a fixed one.95 return RISCV::X5;96}97 98bool RISCVExegesisPostprocessing::processVSETVL(MachineInstr &MI,99 MachineRegisterInfo &MRI) {100 bool Changed = false;101 // Replace both AVL and VL (i.e. the result) operands with physical102 // registers.103 for (unsigned Idx = 0U; Idx < 2; ++Idx)104 if (MI.getOperand(Idx).isReg()) {105 Register RegOp = MI.getOperand(Idx).getReg();106 if (RegOp.isVirtual()) {107 MRI.replaceRegWith(RegOp, allocateGPRRegister(*MI.getMF(), MRI));108 Changed = true;109 }110 }111 112 return Changed;113}114 115bool RISCVExegesisPostprocessing::processWriteFRM(MachineInstr &MI,116 MachineRegisterInfo &MRI) {117 // The virtual register will be the first operand in both SwapFRMImm and118 // WriteFRM.119 Register DestReg = MI.getOperand(0).getReg();120 if (DestReg.isVirtual()) {121 MRI.replaceRegWith(DestReg, allocateGPRRegister(*MI.getMF(), MRI));122 return true;123 }124 return false;125}126 127FunctionPass *llvm::exegesis::createRISCVPostprocessingPass() {128 return new RISCVExegesisPostprocessing();129}130