1111// ===----------------------------------------------------------------------===//
1212
1313#include " RISCVInstrInfo.h"
14- #include " MCTargetDesc/RISCVBaseInfo.h"
1514#include " MCTargetDesc/RISCVMatInt.h"
1615#include " RISCV.h"
1716#include " RISCVMachineFunctionInfo.h"
@@ -2928,7 +2927,6 @@ bool RISCVInstrInfo::isMBBSafeToOutlineFrom(MachineBasicBlock &MBB,
29282927
29292928// Enum values indicating how an outlined call should be constructed.
29302929enum MachineOutlinerConstructionID {
2931- MachineOutlinerTailCall,
29322930 MachineOutlinerDefault
29332931};
29342932
@@ -2937,118 +2935,46 @@ bool RISCVInstrInfo::shouldOutlineFromFunctionByDefault(
29372935 return MF.getFunction ().hasMinSize ();
29382936}
29392937
2940- static bool isCandidatePatchable (const MachineBasicBlock &MBB) {
2941- const MachineFunction *MF = MBB.getParent ();
2942- const Function &F = MF->getFunction ();
2943- return F.getFnAttribute (" fentry-call" ).getValueAsBool () ||
2944- F.hasFnAttribute (" patchable-function-entry" );
2945- }
2946-
2947- static bool isMIReadsReg (const MachineInstr &MI, const TargetRegisterInfo *TRI,
2948- unsigned RegNo) {
2949- return MI.readsRegister (RegNo, TRI) ||
2950- MI.getDesc ().hasImplicitUseOfPhysReg (RegNo);
2951- }
2952-
2953- static bool isMIModifiesReg (const MachineInstr &MI,
2954- const TargetRegisterInfo *TRI, unsigned RegNo) {
2955- return MI.modifiesRegister (RegNo, TRI) ||
2956- MI.getDesc ().hasImplicitDefOfPhysReg (RegNo);
2957- }
2958-
2959- static bool cannotInsertTailCall (const MachineBasicBlock &MBB) {
2960- if (!MBB.back ().isReturn ())
2961- return true ;
2962- if (isCandidatePatchable (MBB))
2963- return true ;
2964-
2965- // If the candidate reads the pre-set register
2966- // that can be used for expanding PseudoTAIL instruction,
2967- // then we cannot insert tail call.
2968- const TargetSubtargetInfo &STI = MBB.getParent ()->getSubtarget ();
2969- unsigned TailExpandUseRegNo =
2970- RISCVII::getTailExpandUseRegNo (STI.getFeatureBits ());
2971- for (const MachineInstr &MI : MBB) {
2972- if (isMIReadsReg (MI, STI.getRegisterInfo (), TailExpandUseRegNo))
2973- return true ;
2974- if (isMIModifiesReg (MI, STI.getRegisterInfo (), TailExpandUseRegNo))
2975- break ;
2976- }
2977- return false ;
2978- }
2979-
2980- static std::optional<MachineOutlinerConstructionID>
2981- analyzeCandidate (outliner::Candidate &C) {
2982- // If last instruction is return then we can rely on
2983- // the verification already performed in the getOutliningTypeImpl.
2984- if (C.back ().isReturn ()) {
2985- assert (!cannotInsertTailCall (*C.getMBB ()) &&
2986- " The candidate who uses return instruction must be outlined "
2987- " using tail call" );
2988- return MachineOutlinerTailCall;
2989- }
2990-
2991- auto CandidateUsesX5 = [](outliner::Candidate &C) {
2992- const TargetRegisterInfo *TRI = C.getMF ()->getSubtarget ().getRegisterInfo ();
2993- if (std::any_of (C.begin (), C.end (), [TRI](const MachineInstr &MI) {
2994- return isMIModifiesReg (MI, TRI, RISCV::X5);
2995- }))
2996- return true ;
2997- return !C.isAvailableAcrossAndOutOfSeq (RISCV::X5, *TRI);
2998- };
2999-
3000- if (!CandidateUsesX5 (C))
3001- return MachineOutlinerDefault;
3002-
3003- return std::nullopt ;
3004- }
3005-
30062938std::optional<std::unique_ptr<outliner::OutlinedFunction>>
30072939RISCVInstrInfo::getOutliningCandidateInfo (
30082940 const MachineModuleInfo &MMI,
30092941 std::vector<outliner::Candidate> &RepeatedSequenceLocs,
30102942 unsigned MinRepeats) const {
30112943
3012- // Each RepeatedSequenceLoc is identical.
3013- outliner::Candidate &Candidate = RepeatedSequenceLocs[0 ];
3014- auto CandidateInfo = analyzeCandidate (Candidate);
3015- if (!CandidateInfo)
3016- RepeatedSequenceLocs.clear ();
2944+ // First we need to filter out candidates where the X5 register (IE t0) can't
2945+ // be used to setup the function call.
2946+ auto CannotInsertCall = [](outliner::Candidate &C) {
2947+ const TargetRegisterInfo *TRI = C.getMF ()->getSubtarget ().getRegisterInfo ();
2948+ return !C.isAvailableAcrossAndOutOfSeq (RISCV::X5, *TRI);
2949+ };
2950+
2951+ llvm::erase_if (RepeatedSequenceLocs, CannotInsertCall);
30172952
30182953 // If the sequence doesn't have enough candidates left, then we're done.
30192954 if (RepeatedSequenceLocs.size () < MinRepeats)
30202955 return std::nullopt ;
30212956
3022- unsigned InstrSizeCExt =
3023- Candidate.getMF ()->getSubtarget <RISCVSubtarget>().hasStdExtCOrZca () ? 2
3024- : 4 ;
3025- unsigned CallOverhead = 0 , FrameOverhead = 0 ;
3026-
3027- MachineOutlinerConstructionID MOCI = CandidateInfo.value ();
3028- switch (MOCI) {
3029- case MachineOutlinerDefault:
3030- // call t0, function = 8 bytes.
3031- CallOverhead = 8 ;
3032- // jr t0 = 4 bytes, 2 bytes if compressed instructions are enabled.
3033- FrameOverhead = InstrSizeCExt;
3034- break ;
3035- case MachineOutlinerTailCall:
3036- // tail call = auipc + jalr in the worst case without linker relaxation.
3037- CallOverhead = 4 + InstrSizeCExt;
3038- // Using tail call we move ret instruction from caller to callee.
3039- FrameOverhead = 0 ;
3040- break ;
3041- }
2957+ unsigned SequenceSize = 0 ;
2958+
2959+ for (auto &MI : RepeatedSequenceLocs[0 ])
2960+ SequenceSize += getInstSizeInBytes (MI);
30422961
2962+ // call t0, function = 8 bytes.
2963+ unsigned CallOverhead = 8 ;
30432964 for (auto &C : RepeatedSequenceLocs)
3044- C.setCallInfo (MOCI , CallOverhead);
2965+ C.setCallInfo (MachineOutlinerDefault , CallOverhead);
30452966
3046- unsigned SequenceSize = 0 ;
3047- for (auto &MI : Candidate)
3048- SequenceSize += getInstSizeInBytes (MI);
2967+ // jr t0 = 4 bytes, 2 bytes if compressed instructions are enabled.
2968+ unsigned FrameOverhead = 4 ;
2969+ if (RepeatedSequenceLocs[0 ]
2970+ .getMF ()
2971+ ->getSubtarget <RISCVSubtarget>()
2972+ .hasStdExtCOrZca ())
2973+ FrameOverhead = 2 ;
30492974
30502975 return std::make_unique<outliner::OutlinedFunction>(
3051- RepeatedSequenceLocs, SequenceSize, FrameOverhead, MOCI);
2976+ RepeatedSequenceLocs, SequenceSize, FrameOverhead,
2977+ MachineOutlinerDefault);
30522978}
30532979
30542980outliner::InstrType
@@ -3069,8 +2995,15 @@ RISCVInstrInfo::getOutliningTypeImpl(const MachineModuleInfo &MMI,
30692995 return F.needsUnwindTableEntry () ? outliner::InstrType::Illegal
30702996 : outliner::InstrType::Invisible;
30712997
3072- if (cannotInsertTailCall (*MBB) &&
3073- (MI.isReturn () || isMIModifiesReg (MI, TRI, RISCV::X5)))
2998+ // We need support for tail calls to outlined functions before return
2999+ // statements can be allowed.
3000+ if (MI.isReturn ())
3001+ return outliner::InstrType::Illegal;
3002+
3003+ // Don't allow modifying the X5 register which we use for return addresses for
3004+ // these outlined functions.
3005+ if (MI.modifiesRegister (RISCV::X5, TRI) ||
3006+ MI.getDesc ().hasImplicitDefOfPhysReg (RISCV::X5))
30743007 return outliner::InstrType::Illegal;
30753008
30763009 // Make sure the operands don't reference something unsafe.
@@ -3106,9 +3039,6 @@ void RISCVInstrInfo::buildOutlinedFrame(
31063039 }
31073040 }
31083041
3109- if (OF.FrameConstructionID == MachineOutlinerTailCall)
3110- return ;
3111-
31123042 MBB.addLiveIn (RISCV::X5);
31133043
31143044 // Add in a return instruction to the end of the outlined frame.
@@ -3122,13 +3052,6 @@ MachineBasicBlock::iterator RISCVInstrInfo::insertOutlinedCall(
31223052 Module &M, MachineBasicBlock &MBB, MachineBasicBlock::iterator &It,
31233053 MachineFunction &MF, outliner::Candidate &C) const {
31243054
3125- if (C.CallConstructionID == MachineOutlinerTailCall) {
3126- It = MBB.insert (It, BuildMI (MF, DebugLoc (), get (RISCV::PseudoTAIL))
3127- .addGlobalAddress (M.getNamedValue (MF.getName ()),
3128- /* Offset=*/ 0 , RISCVII::MO_CALL));
3129- return It;
3130- }
3131-
31323055 // Add in a call instruction to the outlined function at the given location.
31333056 It = MBB.insert (It,
31343057 BuildMI (MF, DebugLoc (), get (RISCV::PseudoCALLReg), RISCV::X5)
0 commit comments