1 //=== RISCVPreLegalizerCombiner.cpp ---------------------------------------===// 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 pass does combining of machine instructions at the generic MI level, 10 // before the legalizer. 11 // 12 //===----------------------------------------------------------------------===// 13 14 #include "RISCVSubtarget.h" 15 #include "llvm/CodeGen/GlobalISel/CSEInfo.h" 16 #include "llvm/CodeGen/GlobalISel/Combiner.h" 17 #include "llvm/CodeGen/GlobalISel/CombinerHelper.h" 18 #include "llvm/CodeGen/GlobalISel/CombinerInfo.h" 19 #include "llvm/CodeGen/GlobalISel/GIMatchTableExecutorImpl.h" 20 #include "llvm/CodeGen/GlobalISel/GISelKnownBits.h" 21 #include "llvm/CodeGen/GlobalISel/MachineIRBuilder.h" 22 #include "llvm/CodeGen/MachineDominators.h" 23 #include "llvm/CodeGen/MachineFunction.h" 24 #include "llvm/CodeGen/MachineFunctionPass.h" 25 #include "llvm/CodeGen/TargetPassConfig.h" 26 27 #define GET_GICOMBINER_DEPS 28 #include "RISCVGenPreLegalizeGICombiner.inc" 29 #undef GET_GICOMBINER_DEPS 30 31 #define DEBUG_TYPE "riscv-prelegalizer-combiner" 32 33 using namespace llvm; 34 35 namespace { 36 37 #define GET_GICOMBINER_TYPES 38 #include "RISCVGenPreLegalizeGICombiner.inc" 39 #undef GET_GICOMBINER_TYPES 40 41 class RISCVPreLegalizerCombinerImpl : public Combiner { 42 protected: 43 const CombinerHelper Helper; 44 const RISCVPreLegalizerCombinerImplRuleConfig &RuleConfig; 45 const RISCVSubtarget &STI; 46 47 public: 48 RISCVPreLegalizerCombinerImpl( 49 MachineFunction &MF, CombinerInfo &CInfo, const TargetPassConfig *TPC, 50 GISelKnownBits &KB, GISelCSEInfo *CSEInfo, 51 const RISCVPreLegalizerCombinerImplRuleConfig &RuleConfig, 52 const RISCVSubtarget &STI, MachineDominatorTree *MDT, 53 const LegalizerInfo *LI); 54 55 static const char *getName() { return "RISCV00PreLegalizerCombiner"; } 56 57 bool tryCombineAll(MachineInstr &I) const override; 58 59 private: 60 #define GET_GICOMBINER_CLASS_MEMBERS 61 #include "RISCVGenPreLegalizeGICombiner.inc" 62 #undef GET_GICOMBINER_CLASS_MEMBERS 63 }; 64 65 #define GET_GICOMBINER_IMPL 66 #include "RISCVGenPreLegalizeGICombiner.inc" 67 #undef GET_GICOMBINER_IMPL 68 69 RISCVPreLegalizerCombinerImpl::RISCVPreLegalizerCombinerImpl( 70 MachineFunction &MF, CombinerInfo &CInfo, const TargetPassConfig *TPC, 71 GISelKnownBits &KB, GISelCSEInfo *CSEInfo, 72 const RISCVPreLegalizerCombinerImplRuleConfig &RuleConfig, 73 const RISCVSubtarget &STI, MachineDominatorTree *MDT, 74 const LegalizerInfo *LI) 75 : Combiner(MF, CInfo, TPC, &KB, CSEInfo), 76 Helper(Observer, B, /*IsPreLegalize*/ true, &KB, MDT, LI), 77 RuleConfig(RuleConfig), STI(STI), 78 #define GET_GICOMBINER_CONSTRUCTOR_INITS 79 #include "RISCVGenPreLegalizeGICombiner.inc" 80 #undef GET_GICOMBINER_CONSTRUCTOR_INITS 81 { 82 } 83 84 // Pass boilerplate 85 // ================ 86 87 class RISCVPreLegalizerCombiner : public MachineFunctionPass { 88 public: 89 static char ID; 90 91 RISCVPreLegalizerCombiner(); 92 93 StringRef getPassName() const override { return "RISCVPreLegalizerCombiner"; } 94 95 bool runOnMachineFunction(MachineFunction &MF) override; 96 97 void getAnalysisUsage(AnalysisUsage &AU) const override; 98 99 private: 100 RISCVPreLegalizerCombinerImplRuleConfig RuleConfig; 101 }; 102 } // end anonymous namespace 103 104 void RISCVPreLegalizerCombiner::getAnalysisUsage(AnalysisUsage &AU) const { 105 AU.addRequired<TargetPassConfig>(); 106 AU.setPreservesCFG(); 107 getSelectionDAGFallbackAnalysisUsage(AU); 108 AU.addRequired<GISelKnownBitsAnalysis>(); 109 AU.addPreserved<GISelKnownBitsAnalysis>(); 110 AU.addRequired<MachineDominatorTreeWrapperPass>(); 111 AU.addPreserved<MachineDominatorTreeWrapperPass>(); 112 AU.addRequired<GISelCSEAnalysisWrapperPass>(); 113 AU.addPreserved<GISelCSEAnalysisWrapperPass>(); 114 MachineFunctionPass::getAnalysisUsage(AU); 115 } 116 117 RISCVPreLegalizerCombiner::RISCVPreLegalizerCombiner() 118 : MachineFunctionPass(ID) { 119 initializeRISCVPreLegalizerCombinerPass(*PassRegistry::getPassRegistry()); 120 121 if (!RuleConfig.parseCommandLineOption()) 122 report_fatal_error("Invalid rule identifier"); 123 } 124 125 bool RISCVPreLegalizerCombiner::runOnMachineFunction(MachineFunction &MF) { 126 if (MF.getProperties().hasProperty( 127 MachineFunctionProperties::Property::FailedISel)) 128 return false; 129 auto &TPC = getAnalysis<TargetPassConfig>(); 130 131 // Enable CSE. 132 GISelCSEAnalysisWrapper &Wrapper = 133 getAnalysis<GISelCSEAnalysisWrapperPass>().getCSEWrapper(); 134 auto *CSEInfo = &Wrapper.get(TPC.getCSEConfig()); 135 136 const RISCVSubtarget &ST = MF.getSubtarget<RISCVSubtarget>(); 137 const auto *LI = ST.getLegalizerInfo(); 138 139 const Function &F = MF.getFunction(); 140 bool EnableOpt = 141 MF.getTarget().getOptLevel() != CodeGenOptLevel::None && !skipFunction(F); 142 GISelKnownBits *KB = &getAnalysis<GISelKnownBitsAnalysis>().get(MF); 143 MachineDominatorTree *MDT = 144 &getAnalysis<MachineDominatorTreeWrapperPass>().getDomTree(); 145 CombinerInfo CInfo(/*AllowIllegalOps*/ true, /*ShouldLegalizeIllegal*/ false, 146 /*LegalizerInfo*/ nullptr, EnableOpt, F.hasOptSize(), 147 F.hasMinSize()); 148 // Disable fixed-point iteration to reduce compile-time 149 CInfo.MaxIterations = 1; 150 CInfo.ObserverLvl = CombinerInfo::ObserverLevel::SinglePass; 151 // This is the first Combiner, so the input IR might contain dead 152 // instructions. 153 CInfo.EnableFullDCE = true; 154 RISCVPreLegalizerCombinerImpl Impl(MF, CInfo, &TPC, *KB, CSEInfo, RuleConfig, 155 ST, MDT, LI); 156 return Impl.combineMachineInstrs(); 157 } 158 159 char RISCVPreLegalizerCombiner::ID = 0; 160 INITIALIZE_PASS_BEGIN(RISCVPreLegalizerCombiner, DEBUG_TYPE, 161 "Combine RISC-V machine instrs before legalization", false, 162 false) 163 INITIALIZE_PASS_DEPENDENCY(TargetPassConfig) 164 INITIALIZE_PASS_DEPENDENCY(GISelKnownBitsAnalysis) 165 INITIALIZE_PASS_DEPENDENCY(GISelCSEAnalysisWrapperPass) 166 INITIALIZE_PASS_END(RISCVPreLegalizerCombiner, DEBUG_TYPE, 167 "Combine RISC-V machine instrs before legalization", false, 168 false) 169 170 namespace llvm { 171 FunctionPass *createRISCVPreLegalizerCombiner() { 172 return new RISCVPreLegalizerCombiner(); 173 } 174 } // end namespace llvm 175