Index: llvm/lib/Target/RISCV/RISCVInstrInfo.cpp =================================================================== --- llvm/lib/Target/RISCV/RISCVInstrInfo.cpp +++ llvm/lib/Target/RISCV/RISCVInstrInfo.cpp @@ -386,9 +386,6 @@ MachineRegisterInfo &MRI = MF->getRegInfo(); const auto &TM = static_cast(MF->getTarget()); - if (TM.isPositionIndependent()) - report_fatal_error("Unable to insert indirect branch"); - if (!isInt<32>(BrOffset)) report_fatal_error( "Branch offsets outside of the signed 32-bit range not supported"); @@ -398,16 +395,29 @@ // uses the same workaround). Register ScratchReg = MRI.createVirtualRegister(&RISCV::GPRRegClass); auto II = MBB.end(); + unsigned Scav; + + if (TM.isPositionIndependent()) { + MBB.setLabelMustBeEmitted(); + MachineInstr &AuipcMI = *BuildMI(MBB, II, DL, get(RISCV::AUIPC), ScratchReg) + .addMBB(&DestBB, RISCVII::MO_PCREL_HI); + BuildMI(MBB, II, DL, get(RISCV::PseudoBRIND)) + .addReg(ScratchReg, RegState::Kill) + .addMBB(&MBB, RISCVII::MO_PCREL_LO); + RS->enterBasicBlockEnd(MBB); + Scav = RS->scavengeRegisterBackwards(RISCV::GPRRegClass, + AuipcMI.getIterator(), false, 0); + } else { + MachineInstr &LuiMI = *BuildMI(MBB, II, DL, get(RISCV::LUI), ScratchReg) + .addMBB(&DestBB, RISCVII::MO_HI); + BuildMI(MBB, II, DL, get(RISCV::PseudoBRIND)) + .addReg(ScratchReg, RegState::Kill) + .addMBB(&DestBB, RISCVII::MO_LO); + RS->enterBasicBlockEnd(MBB); + Scav = RS->scavengeRegisterBackwards(RISCV::GPRRegClass, + LuiMI.getIterator(), false, 0); + } - MachineInstr &LuiMI = *BuildMI(MBB, II, DL, get(RISCV::LUI), ScratchReg) - .addMBB(&DestBB, RISCVII::MO_HI); - BuildMI(MBB, II, DL, get(RISCV::PseudoBRIND)) - .addReg(ScratchReg, RegState::Kill) - .addMBB(&DestBB, RISCVII::MO_LO); - - RS->enterBasicBlockEnd(MBB); - unsigned Scav = RS->scavengeRegisterBackwards(RISCV::GPRRegClass, - LuiMI.getIterator(), false, 0); MRI.replaceRegWith(ScratchReg, Scav); MRI.clearVirtRegs(); RS->setRegUsed(Scav); Index: llvm/lib/Target/RISCV/RISCVTargetMachine.cpp =================================================================== --- llvm/lib/Target/RISCV/RISCVTargetMachine.cpp +++ llvm/lib/Target/RISCV/RISCVTargetMachine.cpp @@ -32,6 +32,10 @@ #include "llvm/Target/TargetOptions.h" using namespace llvm; +static cl::opt + BranchRelaxation("riscv-enable-branch-relax", cl::Hidden, cl::init(true), + cl::desc("Relax out of range conditional branches")); + extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeRISCVTarget() { RegisterTargetMachine X(getTheRISCV32Target()); RegisterTargetMachine Y(getTheRISCV64Target()); @@ -170,10 +174,17 @@ void RISCVPassConfig::addPreSched2() {} -void RISCVPassConfig::addPreEmitPass() { addPass(&BranchRelaxationPassID); } +void RISCVPassConfig::addPreEmitPass() {} void RISCVPassConfig::addPreEmitPass2() { addPass(createRISCVExpandPseudoPass()); + + // The BranchRelaxation pass must be run after the RISCVExpandPseudo pass + // because it may generate additional instructions, + // resulting in out-of-range branches that are not relaxed. + if (BranchRelaxation) + addPass(&BranchRelaxationPassID); + // Schedule the expansion of AMOs at the last possible moment, avoiding the // possibility for other passes to break the requirements for forward // progress in the LR/SC block.