xref: /openbsd-src/gnu/llvm/llvm/lib/Target/RISCV/RISCVExpandPseudoInsts.cpp (revision d415bd752c734aee168c4ee86ff32e8cc249eb16)
109467b48Spatrick //===-- RISCVExpandPseudoInsts.cpp - Expand pseudo instructions -----------===//
209467b48Spatrick //
309467b48Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
409467b48Spatrick // See https://llvm.org/LICENSE.txt for license information.
509467b48Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
609467b48Spatrick //
709467b48Spatrick //===----------------------------------------------------------------------===//
809467b48Spatrick //
909467b48Spatrick // This file contains a pass that expands pseudo instructions into target
1009467b48Spatrick // instructions. This pass should be run after register allocation but before
1109467b48Spatrick // the post-regalloc scheduling pass.
1209467b48Spatrick //
1309467b48Spatrick //===----------------------------------------------------------------------===//
1409467b48Spatrick 
1509467b48Spatrick #include "RISCV.h"
1609467b48Spatrick #include "RISCVInstrInfo.h"
1709467b48Spatrick #include "RISCVTargetMachine.h"
1809467b48Spatrick 
1909467b48Spatrick #include "llvm/CodeGen/LivePhysRegs.h"
2009467b48Spatrick #include "llvm/CodeGen/MachineFunctionPass.h"
2109467b48Spatrick #include "llvm/CodeGen/MachineInstrBuilder.h"
22*d415bd75Srobert #include "llvm/MC/MCContext.h"
2309467b48Spatrick 
2409467b48Spatrick using namespace llvm;
2509467b48Spatrick 
2609467b48Spatrick #define RISCV_EXPAND_PSEUDO_NAME "RISCV pseudo instruction expansion pass"
27*d415bd75Srobert #define RISCV_PRERA_EXPAND_PSEUDO_NAME "RISCV Pre-RA pseudo instruction expansion pass"
2809467b48Spatrick 
2909467b48Spatrick namespace {
3009467b48Spatrick 
3109467b48Spatrick class RISCVExpandPseudo : public MachineFunctionPass {
3209467b48Spatrick public:
3309467b48Spatrick   const RISCVInstrInfo *TII;
3409467b48Spatrick   static char ID;
3509467b48Spatrick 
RISCVExpandPseudo()3609467b48Spatrick   RISCVExpandPseudo() : MachineFunctionPass(ID) {
3709467b48Spatrick     initializeRISCVExpandPseudoPass(*PassRegistry::getPassRegistry());
3809467b48Spatrick   }
3909467b48Spatrick 
4009467b48Spatrick   bool runOnMachineFunction(MachineFunction &MF) override;
4109467b48Spatrick 
getPassName() const4209467b48Spatrick   StringRef getPassName() const override { return RISCV_EXPAND_PSEUDO_NAME; }
4309467b48Spatrick 
4409467b48Spatrick private:
4509467b48Spatrick   bool expandMBB(MachineBasicBlock &MBB);
4609467b48Spatrick   bool expandMI(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,
4709467b48Spatrick                 MachineBasicBlock::iterator &NextMBBI);
48*d415bd75Srobert   bool expandCCOp(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,
4909467b48Spatrick                   MachineBasicBlock::iterator &NextMBBI);
5073471bf0Spatrick   bool expandVSetVL(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI);
5173471bf0Spatrick   bool expandVMSET_VMCLR(MachineBasicBlock &MBB,
5273471bf0Spatrick                          MachineBasicBlock::iterator MBBI, unsigned Opcode);
5309467b48Spatrick };
5409467b48Spatrick 
5509467b48Spatrick char RISCVExpandPseudo::ID = 0;
5609467b48Spatrick 
runOnMachineFunction(MachineFunction & MF)5709467b48Spatrick bool RISCVExpandPseudo::runOnMachineFunction(MachineFunction &MF) {
5809467b48Spatrick   TII = static_cast<const RISCVInstrInfo *>(MF.getSubtarget().getInstrInfo());
5909467b48Spatrick   bool Modified = false;
6009467b48Spatrick   for (auto &MBB : MF)
6109467b48Spatrick     Modified |= expandMBB(MBB);
6209467b48Spatrick   return Modified;
6309467b48Spatrick }
6409467b48Spatrick 
expandMBB(MachineBasicBlock & MBB)6509467b48Spatrick bool RISCVExpandPseudo::expandMBB(MachineBasicBlock &MBB) {
6609467b48Spatrick   bool Modified = false;
6709467b48Spatrick 
6809467b48Spatrick   MachineBasicBlock::iterator MBBI = MBB.begin(), E = MBB.end();
6909467b48Spatrick   while (MBBI != E) {
7009467b48Spatrick     MachineBasicBlock::iterator NMBBI = std::next(MBBI);
7109467b48Spatrick     Modified |= expandMI(MBB, MBBI, NMBBI);
7209467b48Spatrick     MBBI = NMBBI;
7309467b48Spatrick   }
7409467b48Spatrick 
7509467b48Spatrick   return Modified;
7609467b48Spatrick }
7709467b48Spatrick 
expandMI(MachineBasicBlock & MBB,MachineBasicBlock::iterator MBBI,MachineBasicBlock::iterator & NextMBBI)7809467b48Spatrick bool RISCVExpandPseudo::expandMI(MachineBasicBlock &MBB,
7909467b48Spatrick                                  MachineBasicBlock::iterator MBBI,
8009467b48Spatrick                                  MachineBasicBlock::iterator &NextMBBI) {
81*d415bd75Srobert   // RISCVInstrInfo::getInstSizeInBytes expects that the total size of the
82*d415bd75Srobert   // expanded instructions for each pseudo is correct in the Size field of the
83*d415bd75Srobert   // tablegen definition for the pseudo.
8409467b48Spatrick   switch (MBBI->getOpcode()) {
85*d415bd75Srobert   case RISCV::PseudoCCMOVGPR:
86*d415bd75Srobert   case RISCV::PseudoCCADD:
87*d415bd75Srobert   case RISCV::PseudoCCSUB:
88*d415bd75Srobert   case RISCV::PseudoCCAND:
89*d415bd75Srobert   case RISCV::PseudoCCOR:
90*d415bd75Srobert   case RISCV::PseudoCCXOR:
91*d415bd75Srobert   case RISCV::PseudoCCADDW:
92*d415bd75Srobert   case RISCV::PseudoCCSUBW:
93*d415bd75Srobert     return expandCCOp(MBB, MBBI, NextMBBI);
9473471bf0Spatrick   case RISCV::PseudoVSETVLI:
95*d415bd75Srobert   case RISCV::PseudoVSETVLIX0:
9673471bf0Spatrick   case RISCV::PseudoVSETIVLI:
9773471bf0Spatrick     return expandVSetVL(MBB, MBBI);
9873471bf0Spatrick   case RISCV::PseudoVMCLR_M_B1:
9973471bf0Spatrick   case RISCV::PseudoVMCLR_M_B2:
10073471bf0Spatrick   case RISCV::PseudoVMCLR_M_B4:
10173471bf0Spatrick   case RISCV::PseudoVMCLR_M_B8:
10273471bf0Spatrick   case RISCV::PseudoVMCLR_M_B16:
10373471bf0Spatrick   case RISCV::PseudoVMCLR_M_B32:
10473471bf0Spatrick   case RISCV::PseudoVMCLR_M_B64:
10573471bf0Spatrick     // vmclr.m vd => vmxor.mm vd, vd, vd
10673471bf0Spatrick     return expandVMSET_VMCLR(MBB, MBBI, RISCV::VMXOR_MM);
10773471bf0Spatrick   case RISCV::PseudoVMSET_M_B1:
10873471bf0Spatrick   case RISCV::PseudoVMSET_M_B2:
10973471bf0Spatrick   case RISCV::PseudoVMSET_M_B4:
11073471bf0Spatrick   case RISCV::PseudoVMSET_M_B8:
11173471bf0Spatrick   case RISCV::PseudoVMSET_M_B16:
11273471bf0Spatrick   case RISCV::PseudoVMSET_M_B32:
11373471bf0Spatrick   case RISCV::PseudoVMSET_M_B64:
11473471bf0Spatrick     // vmset.m vd => vmxnor.mm vd, vd, vd
11573471bf0Spatrick     return expandVMSET_VMCLR(MBB, MBBI, RISCV::VMXNOR_MM);
11609467b48Spatrick   }
11709467b48Spatrick 
11809467b48Spatrick   return false;
11909467b48Spatrick }
12009467b48Spatrick 
expandCCOp(MachineBasicBlock & MBB,MachineBasicBlock::iterator MBBI,MachineBasicBlock::iterator & NextMBBI)121*d415bd75Srobert bool RISCVExpandPseudo::expandCCOp(MachineBasicBlock &MBB,
122*d415bd75Srobert                                    MachineBasicBlock::iterator MBBI,
123*d415bd75Srobert                                    MachineBasicBlock::iterator &NextMBBI) {
124*d415bd75Srobert 
12509467b48Spatrick   MachineFunction *MF = MBB.getParent();
12609467b48Spatrick   MachineInstr &MI = *MBBI;
12709467b48Spatrick   DebugLoc DL = MI.getDebugLoc();
12809467b48Spatrick 
129*d415bd75Srobert   MachineBasicBlock *TrueBB = MF->CreateMachineBasicBlock(MBB.getBasicBlock());
130*d415bd75Srobert   MachineBasicBlock *MergeBB = MF->CreateMachineBasicBlock(MBB.getBasicBlock());
131*d415bd75Srobert 
132*d415bd75Srobert   MF->insert(++MBB.getIterator(), TrueBB);
133*d415bd75Srobert   MF->insert(++TrueBB->getIterator(), MergeBB);
134*d415bd75Srobert 
135*d415bd75Srobert   // We want to copy the "true" value when the condition is true which means
136*d415bd75Srobert   // we need to invert the branch condition to jump over TrueBB when the
137*d415bd75Srobert   // condition is false.
138*d415bd75Srobert   auto CC = static_cast<RISCVCC::CondCode>(MI.getOperand(3).getImm());
139*d415bd75Srobert   CC = RISCVCC::getOppositeBranchCondition(CC);
140*d415bd75Srobert 
141*d415bd75Srobert   // Insert branch instruction.
142*d415bd75Srobert   BuildMI(MBB, MBBI, DL, TII->getBrCond(CC))
143*d415bd75Srobert       .addReg(MI.getOperand(1).getReg())
144*d415bd75Srobert       .addReg(MI.getOperand(2).getReg())
145*d415bd75Srobert       .addMBB(MergeBB);
146*d415bd75Srobert 
14709467b48Spatrick   Register DestReg = MI.getOperand(0).getReg();
148*d415bd75Srobert   assert(MI.getOperand(4).getReg() == DestReg);
14909467b48Spatrick 
150*d415bd75Srobert   if (MI.getOpcode() == RISCV::PseudoCCMOVGPR) {
151*d415bd75Srobert     // Add MV.
152*d415bd75Srobert     BuildMI(TrueBB, DL, TII->get(RISCV::ADDI), DestReg)
153*d415bd75Srobert         .add(MI.getOperand(5))
154*d415bd75Srobert         .addImm(0);
155*d415bd75Srobert   } else {
156*d415bd75Srobert     unsigned NewOpc;
157*d415bd75Srobert     switch (MI.getOpcode()) {
158*d415bd75Srobert     default:
159*d415bd75Srobert       llvm_unreachable("Unexpected opcode!");
160*d415bd75Srobert     case RISCV::PseudoCCADD:   NewOpc = RISCV::ADD;   break;
161*d415bd75Srobert     case RISCV::PseudoCCSUB:   NewOpc = RISCV::SUB;   break;
162*d415bd75Srobert     case RISCV::PseudoCCAND:   NewOpc = RISCV::AND;   break;
163*d415bd75Srobert     case RISCV::PseudoCCOR:    NewOpc = RISCV::OR;    break;
164*d415bd75Srobert     case RISCV::PseudoCCXOR:   NewOpc = RISCV::XOR;   break;
165*d415bd75Srobert     case RISCV::PseudoCCADDW:  NewOpc = RISCV::ADDW;  break;
166*d415bd75Srobert     case RISCV::PseudoCCSUBW:  NewOpc = RISCV::SUBW;  break;
167*d415bd75Srobert     }
168*d415bd75Srobert     BuildMI(TrueBB, DL, TII->get(NewOpc), DestReg)
169*d415bd75Srobert         .add(MI.getOperand(5))
170*d415bd75Srobert         .add(MI.getOperand(6));
171*d415bd75Srobert   }
17209467b48Spatrick 
173*d415bd75Srobert   TrueBB->addSuccessor(MergeBB);
17409467b48Spatrick 
175*d415bd75Srobert   MergeBB->splice(MergeBB->end(), &MBB, MI, MBB.end());
176*d415bd75Srobert   MergeBB->transferSuccessors(&MBB);
17709467b48Spatrick 
178*d415bd75Srobert   MBB.addSuccessor(TrueBB);
179*d415bd75Srobert   MBB.addSuccessor(MergeBB);
18009467b48Spatrick 
18109467b48Spatrick   NextMBBI = MBB.end();
18209467b48Spatrick   MI.eraseFromParent();
183*d415bd75Srobert 
184*d415bd75Srobert   // Make sure live-ins are correctly attached to this new basic block.
185*d415bd75Srobert   LivePhysRegs LiveRegs;
186*d415bd75Srobert   computeAndAddLiveIns(LiveRegs, *TrueBB);
187*d415bd75Srobert   computeAndAddLiveIns(LiveRegs, *MergeBB);
188*d415bd75Srobert 
18909467b48Spatrick   return true;
19009467b48Spatrick }
19109467b48Spatrick 
expandVSetVL(MachineBasicBlock & MBB,MachineBasicBlock::iterator MBBI)19273471bf0Spatrick bool RISCVExpandPseudo::expandVSetVL(MachineBasicBlock &MBB,
19373471bf0Spatrick                                      MachineBasicBlock::iterator MBBI) {
19473471bf0Spatrick   assert(MBBI->getNumExplicitOperands() == 3 && MBBI->getNumOperands() >= 5 &&
19573471bf0Spatrick          "Unexpected instruction format");
19673471bf0Spatrick 
19773471bf0Spatrick   DebugLoc DL = MBBI->getDebugLoc();
19873471bf0Spatrick 
19973471bf0Spatrick   assert((MBBI->getOpcode() == RISCV::PseudoVSETVLI ||
200*d415bd75Srobert           MBBI->getOpcode() == RISCV::PseudoVSETVLIX0 ||
20173471bf0Spatrick           MBBI->getOpcode() == RISCV::PseudoVSETIVLI) &&
20273471bf0Spatrick          "Unexpected pseudo instruction");
20373471bf0Spatrick   unsigned Opcode;
204*d415bd75Srobert   if (MBBI->getOpcode() == RISCV::PseudoVSETIVLI)
20573471bf0Spatrick     Opcode = RISCV::VSETIVLI;
206*d415bd75Srobert   else
207*d415bd75Srobert     Opcode = RISCV::VSETVLI;
20873471bf0Spatrick   const MCInstrDesc &Desc = TII->get(Opcode);
20973471bf0Spatrick   assert(Desc.getNumOperands() == 3 && "Unexpected instruction format");
21073471bf0Spatrick 
21173471bf0Spatrick   Register DstReg = MBBI->getOperand(0).getReg();
21273471bf0Spatrick   bool DstIsDead = MBBI->getOperand(0).isDead();
21373471bf0Spatrick   BuildMI(MBB, MBBI, DL, Desc)
21473471bf0Spatrick       .addReg(DstReg, RegState::Define | getDeadRegState(DstIsDead))
21573471bf0Spatrick       .add(MBBI->getOperand(1))  // VL
21673471bf0Spatrick       .add(MBBI->getOperand(2)); // VType
21773471bf0Spatrick 
21873471bf0Spatrick   MBBI->eraseFromParent(); // The pseudo instruction is gone now.
21973471bf0Spatrick   return true;
22073471bf0Spatrick }
22173471bf0Spatrick 
expandVMSET_VMCLR(MachineBasicBlock & MBB,MachineBasicBlock::iterator MBBI,unsigned Opcode)22273471bf0Spatrick bool RISCVExpandPseudo::expandVMSET_VMCLR(MachineBasicBlock &MBB,
22373471bf0Spatrick                                           MachineBasicBlock::iterator MBBI,
22473471bf0Spatrick                                           unsigned Opcode) {
22573471bf0Spatrick   DebugLoc DL = MBBI->getDebugLoc();
22673471bf0Spatrick   Register DstReg = MBBI->getOperand(0).getReg();
22773471bf0Spatrick   const MCInstrDesc &Desc = TII->get(Opcode);
22873471bf0Spatrick   BuildMI(MBB, MBBI, DL, Desc, DstReg)
22973471bf0Spatrick       .addReg(DstReg, RegState::Undef)
23073471bf0Spatrick       .addReg(DstReg, RegState::Undef);
23173471bf0Spatrick   MBBI->eraseFromParent(); // The pseudo instruction is gone now.
23273471bf0Spatrick   return true;
23373471bf0Spatrick }
23473471bf0Spatrick 
235*d415bd75Srobert class RISCVPreRAExpandPseudo : public MachineFunctionPass {
236*d415bd75Srobert public:
237*d415bd75Srobert   const RISCVInstrInfo *TII;
238*d415bd75Srobert   static char ID;
23973471bf0Spatrick 
RISCVPreRAExpandPseudo()240*d415bd75Srobert   RISCVPreRAExpandPseudo() : MachineFunctionPass(ID) {
241*d415bd75Srobert     initializeRISCVPreRAExpandPseudoPass(*PassRegistry::getPassRegistry());
24273471bf0Spatrick   }
243*d415bd75Srobert 
244*d415bd75Srobert   bool runOnMachineFunction(MachineFunction &MF) override;
245*d415bd75Srobert 
getAnalysisUsage(AnalysisUsage & AU) const246*d415bd75Srobert   void getAnalysisUsage(AnalysisUsage &AU) const override {
247*d415bd75Srobert     AU.setPreservesCFG();
248*d415bd75Srobert     MachineFunctionPass::getAnalysisUsage(AU);
249*d415bd75Srobert   }
getPassName() const250*d415bd75Srobert   StringRef getPassName() const override {
251*d415bd75Srobert     return RISCV_PRERA_EXPAND_PSEUDO_NAME;
252*d415bd75Srobert   }
253*d415bd75Srobert 
254*d415bd75Srobert private:
255*d415bd75Srobert   bool expandMBB(MachineBasicBlock &MBB);
256*d415bd75Srobert   bool expandMI(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,
257*d415bd75Srobert                 MachineBasicBlock::iterator &NextMBBI);
258*d415bd75Srobert   bool expandAuipcInstPair(MachineBasicBlock &MBB,
259*d415bd75Srobert                            MachineBasicBlock::iterator MBBI,
260*d415bd75Srobert                            MachineBasicBlock::iterator &NextMBBI,
261*d415bd75Srobert                            unsigned FlagsHi, unsigned SecondOpcode);
262*d415bd75Srobert   bool expandLoadLocalAddress(MachineBasicBlock &MBB,
263*d415bd75Srobert                               MachineBasicBlock::iterator MBBI,
264*d415bd75Srobert                               MachineBasicBlock::iterator &NextMBBI);
265*d415bd75Srobert   bool expandLoadAddress(MachineBasicBlock &MBB,
266*d415bd75Srobert                          MachineBasicBlock::iterator MBBI,
267*d415bd75Srobert                          MachineBasicBlock::iterator &NextMBBI);
268*d415bd75Srobert   bool expandLoadTLSIEAddress(MachineBasicBlock &MBB,
269*d415bd75Srobert                               MachineBasicBlock::iterator MBBI,
270*d415bd75Srobert                               MachineBasicBlock::iterator &NextMBBI);
271*d415bd75Srobert   bool expandLoadTLSGDAddress(MachineBasicBlock &MBB,
272*d415bd75Srobert                               MachineBasicBlock::iterator MBBI,
273*d415bd75Srobert                               MachineBasicBlock::iterator &NextMBBI);
274*d415bd75Srobert };
275*d415bd75Srobert 
276*d415bd75Srobert char RISCVPreRAExpandPseudo::ID = 0;
277*d415bd75Srobert 
runOnMachineFunction(MachineFunction & MF)278*d415bd75Srobert bool RISCVPreRAExpandPseudo::runOnMachineFunction(MachineFunction &MF) {
279*d415bd75Srobert   TII = static_cast<const RISCVInstrInfo *>(MF.getSubtarget().getInstrInfo());
280*d415bd75Srobert   bool Modified = false;
281*d415bd75Srobert   for (auto &MBB : MF)
282*d415bd75Srobert     Modified |= expandMBB(MBB);
283*d415bd75Srobert   return Modified;
284*d415bd75Srobert }
285*d415bd75Srobert 
expandMBB(MachineBasicBlock & MBB)286*d415bd75Srobert bool RISCVPreRAExpandPseudo::expandMBB(MachineBasicBlock &MBB) {
287*d415bd75Srobert   bool Modified = false;
288*d415bd75Srobert 
289*d415bd75Srobert   MachineBasicBlock::iterator MBBI = MBB.begin(), E = MBB.end();
290*d415bd75Srobert   while (MBBI != E) {
291*d415bd75Srobert     MachineBasicBlock::iterator NMBBI = std::next(MBBI);
292*d415bd75Srobert     Modified |= expandMI(MBB, MBBI, NMBBI);
293*d415bd75Srobert     MBBI = NMBBI;
294*d415bd75Srobert   }
295*d415bd75Srobert 
296*d415bd75Srobert   return Modified;
297*d415bd75Srobert }
298*d415bd75Srobert 
expandMI(MachineBasicBlock & MBB,MachineBasicBlock::iterator MBBI,MachineBasicBlock::iterator & NextMBBI)299*d415bd75Srobert bool RISCVPreRAExpandPseudo::expandMI(MachineBasicBlock &MBB,
300*d415bd75Srobert                                       MachineBasicBlock::iterator MBBI,
301*d415bd75Srobert                                       MachineBasicBlock::iterator &NextMBBI) {
302*d415bd75Srobert 
303*d415bd75Srobert   switch (MBBI->getOpcode()) {
304*d415bd75Srobert   case RISCV::PseudoLLA:
305*d415bd75Srobert     return expandLoadLocalAddress(MBB, MBBI, NextMBBI);
306*d415bd75Srobert   case RISCV::PseudoLA:
307*d415bd75Srobert     return expandLoadAddress(MBB, MBBI, NextMBBI);
308*d415bd75Srobert   case RISCV::PseudoLA_TLS_IE:
309*d415bd75Srobert     return expandLoadTLSIEAddress(MBB, MBBI, NextMBBI);
310*d415bd75Srobert   case RISCV::PseudoLA_TLS_GD:
311*d415bd75Srobert     return expandLoadTLSGDAddress(MBB, MBBI, NextMBBI);
312*d415bd75Srobert   }
313*d415bd75Srobert   return false;
314*d415bd75Srobert }
315*d415bd75Srobert 
expandAuipcInstPair(MachineBasicBlock & MBB,MachineBasicBlock::iterator MBBI,MachineBasicBlock::iterator & NextMBBI,unsigned FlagsHi,unsigned SecondOpcode)316*d415bd75Srobert bool RISCVPreRAExpandPseudo::expandAuipcInstPair(
317*d415bd75Srobert     MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,
318*d415bd75Srobert     MachineBasicBlock::iterator &NextMBBI, unsigned FlagsHi,
319*d415bd75Srobert     unsigned SecondOpcode) {
320*d415bd75Srobert   MachineFunction *MF = MBB.getParent();
321*d415bd75Srobert   MachineInstr &MI = *MBBI;
322*d415bd75Srobert   DebugLoc DL = MI.getDebugLoc();
323*d415bd75Srobert 
324*d415bd75Srobert   Register DestReg = MI.getOperand(0).getReg();
325*d415bd75Srobert   Register ScratchReg =
326*d415bd75Srobert       MF->getRegInfo().createVirtualRegister(&RISCV::GPRRegClass);
327*d415bd75Srobert 
328*d415bd75Srobert   MachineOperand &Symbol = MI.getOperand(1);
329*d415bd75Srobert   Symbol.setTargetFlags(FlagsHi);
330*d415bd75Srobert   MCSymbol *AUIPCSymbol = MF->getContext().createNamedTempSymbol("pcrel_hi");
331*d415bd75Srobert 
332*d415bd75Srobert   MachineInstr *MIAUIPC =
333*d415bd75Srobert       BuildMI(MBB, MBBI, DL, TII->get(RISCV::AUIPC), ScratchReg).add(Symbol);
334*d415bd75Srobert   MIAUIPC->setPreInstrSymbol(*MF, AUIPCSymbol);
335*d415bd75Srobert 
336*d415bd75Srobert   MachineInstr *SecondMI =
337*d415bd75Srobert       BuildMI(MBB, MBBI, DL, TII->get(SecondOpcode), DestReg)
338*d415bd75Srobert           .addReg(ScratchReg)
339*d415bd75Srobert           .addSym(AUIPCSymbol, RISCVII::MO_PCREL_LO);
340*d415bd75Srobert 
341*d415bd75Srobert   if (MI.hasOneMemOperand())
342*d415bd75Srobert     SecondMI->addMemOperand(*MF, *MI.memoperands_begin());
343*d415bd75Srobert 
344*d415bd75Srobert   MI.eraseFromParent();
34573471bf0Spatrick   return true;
34673471bf0Spatrick }
34773471bf0Spatrick 
expandLoadLocalAddress(MachineBasicBlock & MBB,MachineBasicBlock::iterator MBBI,MachineBasicBlock::iterator & NextMBBI)348*d415bd75Srobert bool RISCVPreRAExpandPseudo::expandLoadLocalAddress(
349*d415bd75Srobert     MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,
350*d415bd75Srobert     MachineBasicBlock::iterator &NextMBBI) {
351*d415bd75Srobert   return expandAuipcInstPair(MBB, MBBI, NextMBBI, RISCVII::MO_PCREL_HI,
352*d415bd75Srobert                              RISCV::ADDI);
35373471bf0Spatrick }
354*d415bd75Srobert 
expandLoadAddress(MachineBasicBlock & MBB,MachineBasicBlock::iterator MBBI,MachineBasicBlock::iterator & NextMBBI)355*d415bd75Srobert bool RISCVPreRAExpandPseudo::expandLoadAddress(
356*d415bd75Srobert     MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,
357*d415bd75Srobert     MachineBasicBlock::iterator &NextMBBI) {
358*d415bd75Srobert   MachineFunction *MF = MBB.getParent();
359*d415bd75Srobert 
360*d415bd75Srobert   const auto &STI = MF->getSubtarget<RISCVSubtarget>();
361*d415bd75Srobert   // When HWASAN is used and tagging of global variables is enabled
362*d415bd75Srobert   // they should be accessed via the GOT, since the tagged address of a global
363*d415bd75Srobert   // is incompatible with existing code models. This also applies to non-pic
364*d415bd75Srobert   // mode.
365*d415bd75Srobert   assert(MF->getTarget().isPositionIndependent() || STI.allowTaggedGlobals());
366*d415bd75Srobert   unsigned SecondOpcode = STI.is64Bit() ? RISCV::LD : RISCV::LW;
367*d415bd75Srobert   return expandAuipcInstPair(MBB, MBBI, NextMBBI, RISCVII::MO_GOT_HI,
368*d415bd75Srobert                              SecondOpcode);
369*d415bd75Srobert }
370*d415bd75Srobert 
expandLoadTLSIEAddress(MachineBasicBlock & MBB,MachineBasicBlock::iterator MBBI,MachineBasicBlock::iterator & NextMBBI)371*d415bd75Srobert bool RISCVPreRAExpandPseudo::expandLoadTLSIEAddress(
372*d415bd75Srobert     MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,
373*d415bd75Srobert     MachineBasicBlock::iterator &NextMBBI) {
374*d415bd75Srobert   MachineFunction *MF = MBB.getParent();
375*d415bd75Srobert 
376*d415bd75Srobert   const auto &STI = MF->getSubtarget<RISCVSubtarget>();
377*d415bd75Srobert   unsigned SecondOpcode = STI.is64Bit() ? RISCV::LD : RISCV::LW;
378*d415bd75Srobert   return expandAuipcInstPair(MBB, MBBI, NextMBBI, RISCVII::MO_TLS_GOT_HI,
379*d415bd75Srobert                              SecondOpcode);
380*d415bd75Srobert }
381*d415bd75Srobert 
expandLoadTLSGDAddress(MachineBasicBlock & MBB,MachineBasicBlock::iterator MBBI,MachineBasicBlock::iterator & NextMBBI)382*d415bd75Srobert bool RISCVPreRAExpandPseudo::expandLoadTLSGDAddress(
383*d415bd75Srobert     MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,
384*d415bd75Srobert     MachineBasicBlock::iterator &NextMBBI) {
385*d415bd75Srobert   return expandAuipcInstPair(MBB, MBBI, NextMBBI, RISCVII::MO_TLS_GD_HI,
386*d415bd75Srobert                              RISCV::ADDI);
38773471bf0Spatrick }
38873471bf0Spatrick 
38909467b48Spatrick } // end of anonymous namespace
39009467b48Spatrick 
39109467b48Spatrick INITIALIZE_PASS(RISCVExpandPseudo, "riscv-expand-pseudo",
39209467b48Spatrick                 RISCV_EXPAND_PSEUDO_NAME, false, false)
393*d415bd75Srobert 
394*d415bd75Srobert INITIALIZE_PASS(RISCVPreRAExpandPseudo, "riscv-prera-expand-pseudo",
395*d415bd75Srobert                 RISCV_PRERA_EXPAND_PSEUDO_NAME, false, false)
396*d415bd75Srobert 
39709467b48Spatrick namespace llvm {
39809467b48Spatrick 
createRISCVExpandPseudoPass()39909467b48Spatrick FunctionPass *createRISCVExpandPseudoPass() { return new RISCVExpandPseudo(); }
createRISCVPreRAExpandPseudoPass()400*d415bd75Srobert FunctionPass *createRISCVPreRAExpandPseudoPass() { return new RISCVPreRAExpandPseudo(); }
40109467b48Spatrick 
40209467b48Spatrick } // end of namespace llvm
403