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/GISelValueTracking.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
33using namespace llvm;
34
35namespace {
36
37#define GET_GICOMBINER_TYPES
38#include "RISCVGenPreLegalizeGICombiner.inc"
39#undef GET_GICOMBINER_TYPES
40
41class RISCVPreLegalizerCombinerImpl : public Combiner {
42protected:
43 const CombinerHelper Helper;
44 const RISCVPreLegalizerCombinerImplRuleConfig &RuleConfig;
45 const RISCVSubtarget &STI;
46
47public:
48 RISCVPreLegalizerCombinerImpl(
49 MachineFunction &MF, CombinerInfo &CInfo, const TargetPassConfig *TPC,
50 GISelValueTracking &VT, 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
59private:
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
69RISCVPreLegalizerCombinerImpl::RISCVPreLegalizerCombinerImpl(
70 MachineFunction &MF, CombinerInfo &CInfo, const TargetPassConfig *TPC,
71 GISelValueTracking &VT, GISelCSEInfo *CSEInfo,
72 const RISCVPreLegalizerCombinerImplRuleConfig &RuleConfig,
73 const RISCVSubtarget &STI, MachineDominatorTree *MDT,
74 const LegalizerInfo *LI)
75 : Combiner(MF, CInfo, TPC, &VT, CSEInfo),
76 Helper(Observer, B, /*IsPreLegalize*/ true, &VT, 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
87class RISCVPreLegalizerCombiner : public MachineFunctionPass {
88public:
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
99private:
100 RISCVPreLegalizerCombinerImplRuleConfig RuleConfig;
101};
102} // end anonymous namespace
103
104void RISCVPreLegalizerCombiner::getAnalysisUsage(AnalysisUsage &AU) const {
105 AU.addRequired<TargetPassConfig>();
106 AU.setPreservesCFG();
107 getSelectionDAGFallbackAnalysisUsage(AU);
108 AU.addRequired<GISelValueTrackingAnalysisLegacy>();
109 AU.addPreserved<GISelValueTrackingAnalysisLegacy>();
110 AU.addRequired<MachineDominatorTreeWrapperPass>();
111 AU.addPreserved<MachineDominatorTreeWrapperPass>();
112 AU.addRequired<GISelCSEAnalysisWrapperPass>();
113 AU.addPreserved<GISelCSEAnalysisWrapperPass>();
114 MachineFunctionPass::getAnalysisUsage(AU);
115}
116
117RISCVPreLegalizerCombiner::RISCVPreLegalizerCombiner()
118 : MachineFunctionPass(ID) {
119 if (!RuleConfig.parseCommandLineOption())
120 report_fatal_error(reason: "Invalid rule identifier");
121}
122
123bool RISCVPreLegalizerCombiner::runOnMachineFunction(MachineFunction &MF) {
124 if (MF.getProperties().hasFailedISel())
125 return false;
126 auto &TPC = getAnalysis<TargetPassConfig>();
127
128 // Enable CSE.
129 GISelCSEAnalysisWrapper &Wrapper =
130 getAnalysis<GISelCSEAnalysisWrapperPass>().getCSEWrapper();
131 auto *CSEInfo = &Wrapper.get(CSEOpt: TPC.getCSEConfig());
132
133 const RISCVSubtarget &ST = MF.getSubtarget<RISCVSubtarget>();
134 const auto *LI = ST.getLegalizerInfo();
135
136 const Function &F = MF.getFunction();
137 bool EnableOpt =
138 MF.getTarget().getOptLevel() != CodeGenOptLevel::None && !skipFunction(F);
139 GISelValueTracking *VT =
140 &getAnalysis<GISelValueTrackingAnalysisLegacy>().get(MF);
141 MachineDominatorTree *MDT =
142 &getAnalysis<MachineDominatorTreeWrapperPass>().getDomTree();
143 CombinerInfo CInfo(/*AllowIllegalOps*/ true, /*ShouldLegalizeIllegal*/ false,
144 /*LegalizerInfo*/ nullptr, EnableOpt, F.hasOptSize(),
145 F.hasMinSize());
146 // Disable fixed-point iteration to reduce compile-time
147 CInfo.MaxIterations = 1;
148 CInfo.ObserverLvl = CombinerInfo::ObserverLevel::SinglePass;
149 // This is the first Combiner, so the input IR might contain dead
150 // instructions.
151 CInfo.EnableFullDCE = true;
152 RISCVPreLegalizerCombinerImpl Impl(MF, CInfo, &TPC, *VT, CSEInfo, RuleConfig,
153 ST, MDT, LI);
154 return Impl.combineMachineInstrs();
155}
156
157char RISCVPreLegalizerCombiner::ID = 0;
158INITIALIZE_PASS_BEGIN(RISCVPreLegalizerCombiner, DEBUG_TYPE,
159 "Combine RISC-V machine instrs before legalization", false,
160 false)
161INITIALIZE_PASS_DEPENDENCY(TargetPassConfig)
162INITIALIZE_PASS_DEPENDENCY(GISelValueTrackingAnalysisLegacy)
163INITIALIZE_PASS_DEPENDENCY(GISelCSEAnalysisWrapperPass)
164INITIALIZE_PASS_END(RISCVPreLegalizerCombiner, DEBUG_TYPE,
165 "Combine RISC-V machine instrs before legalization", false,
166 false)
167
168FunctionPass *llvm::createRISCVPreLegalizerCombiner() {
169 return new RISCVPreLegalizerCombiner();
170}
171