xref: /freebsd/contrib/llvm-project/llvm/lib/Target/RISCV/RISCVExpandPseudoInsts.cpp (revision 7877fdebeeb35fad1cbbafce22598b1bdf97c786)
1 //===-- RISCVExpandPseudoInsts.cpp - Expand pseudo instructions -----------===//
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 //
9 // This file contains a pass that expands pseudo instructions into target
10 // instructions. This pass should be run after register allocation but before
11 // the post-regalloc scheduling pass.
12 //
13 //===----------------------------------------------------------------------===//
14 
15 #include "RISCV.h"
16 #include "RISCVInstrInfo.h"
17 #include "RISCVTargetMachine.h"
18 
19 #include "llvm/CodeGen/LivePhysRegs.h"
20 #include "llvm/CodeGen/MachineFunctionPass.h"
21 #include "llvm/CodeGen/MachineInstrBuilder.h"
22 
23 using namespace llvm;
24 
25 #define RISCV_EXPAND_PSEUDO_NAME "RISCV pseudo instruction expansion pass"
26 
27 namespace {
28 
29 class RISCVExpandPseudo : public MachineFunctionPass {
30 public:
31   const RISCVInstrInfo *TII;
32   static char ID;
33 
34   RISCVExpandPseudo() : MachineFunctionPass(ID) {
35     initializeRISCVExpandPseudoPass(*PassRegistry::getPassRegistry());
36   }
37 
38   bool runOnMachineFunction(MachineFunction &MF) override;
39 
40   StringRef getPassName() const override { return RISCV_EXPAND_PSEUDO_NAME; }
41 
42 private:
43   bool expandMBB(MachineBasicBlock &MBB);
44   bool expandMI(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,
45                 MachineBasicBlock::iterator &NextMBBI);
46   bool expandAuipcInstPair(MachineBasicBlock &MBB,
47                            MachineBasicBlock::iterator MBBI,
48                            MachineBasicBlock::iterator &NextMBBI,
49                            unsigned FlagsHi, unsigned SecondOpcode);
50   bool expandLoadLocalAddress(MachineBasicBlock &MBB,
51                               MachineBasicBlock::iterator MBBI,
52                               MachineBasicBlock::iterator &NextMBBI);
53   bool expandLoadAddress(MachineBasicBlock &MBB,
54                          MachineBasicBlock::iterator MBBI,
55                          MachineBasicBlock::iterator &NextMBBI);
56   bool expandLoadTLSIEAddress(MachineBasicBlock &MBB,
57                               MachineBasicBlock::iterator MBBI,
58                               MachineBasicBlock::iterator &NextMBBI);
59   bool expandLoadTLSGDAddress(MachineBasicBlock &MBB,
60                               MachineBasicBlock::iterator MBBI,
61                               MachineBasicBlock::iterator &NextMBBI);
62 };
63 
64 char RISCVExpandPseudo::ID = 0;
65 
66 bool RISCVExpandPseudo::runOnMachineFunction(MachineFunction &MF) {
67   TII = static_cast<const RISCVInstrInfo *>(MF.getSubtarget().getInstrInfo());
68   bool Modified = false;
69   for (auto &MBB : MF)
70     Modified |= expandMBB(MBB);
71   return Modified;
72 }
73 
74 bool RISCVExpandPseudo::expandMBB(MachineBasicBlock &MBB) {
75   bool Modified = false;
76 
77   MachineBasicBlock::iterator MBBI = MBB.begin(), E = MBB.end();
78   while (MBBI != E) {
79     MachineBasicBlock::iterator NMBBI = std::next(MBBI);
80     Modified |= expandMI(MBB, MBBI, NMBBI);
81     MBBI = NMBBI;
82   }
83 
84   return Modified;
85 }
86 
87 bool RISCVExpandPseudo::expandMI(MachineBasicBlock &MBB,
88                                  MachineBasicBlock::iterator MBBI,
89                                  MachineBasicBlock::iterator &NextMBBI) {
90   // RISCVInstrInfo::getInstSizeInBytes hard-codes the number of expanded
91   // instructions for each pseudo, and must be updated when adding new pseudos
92   // or changing existing ones.
93   switch (MBBI->getOpcode()) {
94   case RISCV::PseudoLLA:
95     return expandLoadLocalAddress(MBB, MBBI, NextMBBI);
96   case RISCV::PseudoLA:
97     return expandLoadAddress(MBB, MBBI, NextMBBI);
98   case RISCV::PseudoLA_TLS_IE:
99     return expandLoadTLSIEAddress(MBB, MBBI, NextMBBI);
100   case RISCV::PseudoLA_TLS_GD:
101     return expandLoadTLSGDAddress(MBB, MBBI, NextMBBI);
102   }
103 
104   return false;
105 }
106 
107 bool RISCVExpandPseudo::expandAuipcInstPair(
108     MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,
109     MachineBasicBlock::iterator &NextMBBI, unsigned FlagsHi,
110     unsigned SecondOpcode) {
111   MachineFunction *MF = MBB.getParent();
112   MachineInstr &MI = *MBBI;
113   DebugLoc DL = MI.getDebugLoc();
114 
115   Register DestReg = MI.getOperand(0).getReg();
116   const MachineOperand &Symbol = MI.getOperand(1);
117 
118   MachineBasicBlock *NewMBB = MF->CreateMachineBasicBlock(MBB.getBasicBlock());
119 
120   // Tell AsmPrinter that we unconditionally want the symbol of this label to be
121   // emitted.
122   NewMBB->setLabelMustBeEmitted();
123 
124   MF->insert(++MBB.getIterator(), NewMBB);
125 
126   BuildMI(NewMBB, DL, TII->get(RISCV::AUIPC), DestReg)
127       .addDisp(Symbol, 0, FlagsHi);
128   BuildMI(NewMBB, DL, TII->get(SecondOpcode), DestReg)
129       .addReg(DestReg)
130       .addMBB(NewMBB, RISCVII::MO_PCREL_LO);
131 
132   // Move all the rest of the instructions to NewMBB.
133   NewMBB->splice(NewMBB->end(), &MBB, std::next(MBBI), MBB.end());
134   // Update machine-CFG edges.
135   NewMBB->transferSuccessorsAndUpdatePHIs(&MBB);
136   // Make the original basic block fall-through to the new.
137   MBB.addSuccessor(NewMBB);
138 
139   // Make sure live-ins are correctly attached to this new basic block.
140   LivePhysRegs LiveRegs;
141   computeAndAddLiveIns(LiveRegs, *NewMBB);
142 
143   NextMBBI = MBB.end();
144   MI.eraseFromParent();
145   return true;
146 }
147 
148 bool RISCVExpandPseudo::expandLoadLocalAddress(
149     MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,
150     MachineBasicBlock::iterator &NextMBBI) {
151   return expandAuipcInstPair(MBB, MBBI, NextMBBI, RISCVII::MO_PCREL_HI,
152                              RISCV::ADDI);
153 }
154 
155 bool RISCVExpandPseudo::expandLoadAddress(
156     MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,
157     MachineBasicBlock::iterator &NextMBBI) {
158   MachineFunction *MF = MBB.getParent();
159 
160   unsigned SecondOpcode;
161   unsigned FlagsHi;
162   if (MF->getTarget().isPositionIndependent()) {
163     const auto &STI = MF->getSubtarget<RISCVSubtarget>();
164     SecondOpcode = STI.is64Bit() ? RISCV::LD : RISCV::LW;
165     FlagsHi = RISCVII::MO_GOT_HI;
166   } else {
167     SecondOpcode = RISCV::ADDI;
168     FlagsHi = RISCVII::MO_PCREL_HI;
169   }
170   return expandAuipcInstPair(MBB, MBBI, NextMBBI, FlagsHi, SecondOpcode);
171 }
172 
173 bool RISCVExpandPseudo::expandLoadTLSIEAddress(
174     MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,
175     MachineBasicBlock::iterator &NextMBBI) {
176   MachineFunction *MF = MBB.getParent();
177 
178   const auto &STI = MF->getSubtarget<RISCVSubtarget>();
179   unsigned SecondOpcode = STI.is64Bit() ? RISCV::LD : RISCV::LW;
180   return expandAuipcInstPair(MBB, MBBI, NextMBBI, RISCVII::MO_TLS_GOT_HI,
181                              SecondOpcode);
182 }
183 
184 bool RISCVExpandPseudo::expandLoadTLSGDAddress(
185     MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,
186     MachineBasicBlock::iterator &NextMBBI) {
187   return expandAuipcInstPair(MBB, MBBI, NextMBBI, RISCVII::MO_TLS_GD_HI,
188                              RISCV::ADDI);
189 }
190 
191 } // end of anonymous namespace
192 
193 INITIALIZE_PASS(RISCVExpandPseudo, "riscv-expand-pseudo",
194                 RISCV_EXPAND_PSEUDO_NAME, false, false)
195 namespace llvm {
196 
197 FunctionPass *createRISCVExpandPseudoPass() { return new RISCVExpandPseudo(); }
198 
199 } // end of namespace llvm
200