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-exception
6//
7//===----------------------------------------------------------------------===//
8// \file
9// This Pass converts some of the virtual register operands in VSETVLI and FRM
10// 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't
39 // 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 namespace
47
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, MRI&: MF.getRegInfo());
61 break;
62 case RISCV::SwapFRMImm:
63 case RISCV::WriteFRM:
64 Changed |= processWriteFRM(MI, MRI&: 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 GPRTC
85 // happens to account for nearly all caller-saved registers.
86 const TargetRegisterClass *GPRClass = TRI.getRegClass(i: RISCV::GPRTCRegClassID);
87 BitVector Candidates = TRI.getAllocatableSet(MF, RC: GPRClass);
88
89 for (unsigned SetIdx : Candidates.set_bits()) {
90 if (MRI.reg_empty(RegNo: 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 physical
102 // registers.
103 for (unsigned Idx = 0U; Idx < 2; ++Idx)
104 if (MI.getOperand(i: Idx).isReg()) {
105 Register RegOp = MI.getOperand(i: Idx).getReg();
106 if (RegOp.isVirtual()) {
107 MRI.replaceRegWith(FromReg: RegOp, ToReg: allocateGPRRegister(MF: *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 and
118 // WriteFRM.
119 Register DestReg = MI.getOperand(i: 0).getReg();
120 if (DestReg.isVirtual()) {
121 MRI.replaceRegWith(FromReg: DestReg, ToReg: allocateGPRRegister(MF: *MI.getMF(), MRI));
122 return true;
123 }
124 return false;
125}
126
127FunctionPass *llvm::exegesis::createRISCVPostprocessingPass() {
128 return new RISCVExegesisPostprocessing();
129}
130