1//=== WebAssemblyPostLegalizerCombiner.cpp ----------------------*- C++ -*-===//
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/// \file
10/// Post-legalization combines on generic MachineInstrs.
11///
12/// The combines here must preserve instruction legality.
13///
14/// Combines which don't rely on instruction legality should go in the
15/// WebAssemblyPreLegalizerCombiner.
16///
17//===----------------------------------------------------------------------===//
18
19#include "WebAssembly.h"
20#include "llvm/CodeGen/GlobalISel/CSEInfo.h"
21#include "llvm/CodeGen/GlobalISel/Combiner.h"
22#include "llvm/CodeGen/GlobalISel/CombinerHelper.h"
23#include "llvm/CodeGen/GlobalISel/CombinerInfo.h"
24#include "llvm/CodeGen/GlobalISel/GIMatchTableExecutorImpl.h"
25#include "llvm/CodeGen/GlobalISel/GISelValueTracking.h"
26#include "llvm/CodeGen/GlobalISel/MachineIRBuilder.h"
27#include "llvm/CodeGen/MachineDominators.h"
28#include "llvm/CodeGen/MachineFunctionAnalysisManager.h"
29#include "llvm/CodeGen/MachineFunctionPass.h"
30#include "llvm/CodeGen/MachinePassManager.h"
31#include "llvm/CodeGen/TargetPassConfig.h"
32#include "llvm/IR/Analysis.h"
33
34#define GET_GICOMBINER_DEPS
35#include "WebAssemblyGenPostLegalizeGICombiner.inc"
36#undef GET_GICOMBINER_DEPS
37
38#define DEBUG_TYPE "wasm-postlegalizer-combiner"
39
40using namespace llvm;
41
42namespace {
43
44#define GET_GICOMBINER_TYPES
45#include "WebAssemblyGenPostLegalizeGICombiner.inc"
46#undef GET_GICOMBINER_TYPES
47
48class WebAssemblyPostLegalizerCombinerImpl : public Combiner {
49protected:
50 const CombinerHelper Helper;
51 const WebAssemblyPostLegalizerCombinerImplRuleConfig &RuleConfig;
52 const WebAssemblySubtarget &STI;
53
54public:
55 WebAssemblyPostLegalizerCombinerImpl(
56 MachineFunction &MF, CombinerInfo &CInfo, GISelValueTracking &VT,
57 GISelCSEInfo *CSEInfo,
58 const WebAssemblyPostLegalizerCombinerImplRuleConfig &RuleConfig,
59 const WebAssemblySubtarget &STI, MachineDominatorTree *MDT,
60 const LegalizerInfo *LI);
61
62 static const char *getName() { return "WebAssemblyPostLegalizerCombiner"; }
63
64 bool tryCombineAll(MachineInstr &I) const override;
65
66private:
67#define GET_GICOMBINER_CLASS_MEMBERS
68#include "WebAssemblyGenPostLegalizeGICombiner.inc"
69#undef GET_GICOMBINER_CLASS_MEMBERS
70};
71
72#define GET_GICOMBINER_IMPL
73#include "WebAssemblyGenPostLegalizeGICombiner.inc"
74#undef GET_GICOMBINER_IMPL
75
76WebAssemblyPostLegalizerCombinerImpl::WebAssemblyPostLegalizerCombinerImpl(
77 MachineFunction &MF, CombinerInfo &CInfo, GISelValueTracking &VT,
78 GISelCSEInfo *CSEInfo,
79 const WebAssemblyPostLegalizerCombinerImplRuleConfig &RuleConfig,
80 const WebAssemblySubtarget &STI, MachineDominatorTree *MDT,
81 const LegalizerInfo *LI)
82 : Combiner(MF, CInfo, &VT, CSEInfo),
83 Helper(Observer, B, /*IsPreLegalize*/ false, &VT, MDT, LI),
84 RuleConfig(RuleConfig), STI(STI),
85#define GET_GICOMBINER_CONSTRUCTOR_INITS
86#include "WebAssemblyGenPostLegalizeGICombiner.inc"
87#undef GET_GICOMBINER_CONSTRUCTOR_INITS
88{
89}
90
91class WebAssemblyPostLegalizerCombinerLegacy : public MachineFunctionPass {
92public:
93 static char ID;
94
95 WebAssemblyPostLegalizerCombinerLegacy();
96
97 StringRef getPassName() const override {
98 return "WebAssemblyPostLegalizerCombiner";
99 }
100
101 bool runOnMachineFunction(MachineFunction &MF) override;
102 void getAnalysisUsage(AnalysisUsage &AU) const override;
103};
104} // end anonymous namespace
105
106void WebAssemblyPostLegalizerCombinerLegacy::getAnalysisUsage(
107 AnalysisUsage &AU) const {
108 AU.addRequired<TargetPassConfig>();
109 AU.setPreservesCFG();
110 getSelectionDAGFallbackAnalysisUsage(AU);
111 AU.addRequired<GISelValueTrackingAnalysisLegacy>();
112 AU.addPreserved<GISelValueTrackingAnalysisLegacy>();
113 AU.addRequired<MachineDominatorTreeWrapperPass>();
114 AU.addRequired<GISelCSEAnalysisWrapperPass>();
115 AU.addPreserved<GISelCSEAnalysisWrapperPass>();
116 MachineFunctionPass::getAnalysisUsage(AU);
117}
118
119WebAssemblyPostLegalizerCombinerLegacy::WebAssemblyPostLegalizerCombinerLegacy()
120 : MachineFunctionPass(ID) {}
121
122static bool
123runCombinerOnMachineFunction(MachineFunction &MF,
124 function_ref<bool()> ShouldSkip,
125 function_ref<GISelValueTracking *()> GetVT,
126 function_ref<MachineDominatorTree *()> GetMDT,
127 function_ref<GISelCSEInfo *()> GetCSEInfo) {
128 if (MF.getProperties().hasFailedISel())
129 return false;
130 assert(MF.getProperties().hasLegalized() && "Expected a legalized function?");
131 const Function &F = MF.getFunction();
132 bool EnableOpt =
133 MF.getTarget().getOptLevel() != CodeGenOptLevel::None && !ShouldSkip;
134
135 WebAssemblyPostLegalizerCombinerImplRuleConfig RuleConfig;
136 if (!RuleConfig.parseCommandLineOption())
137 reportFatalUsageError(reason: "Invalid rule identifier");
138
139 const WebAssemblySubtarget &ST = MF.getSubtarget<WebAssemblySubtarget>();
140 const auto *LI = ST.getLegalizerInfo();
141
142 GISelValueTracking *VT = GetVT();
143 MachineDominatorTree *MDT = GetMDT();
144 GISelCSEInfo *CSEInfo = GetCSEInfo();
145
146 CombinerInfo CInfo(/*AllowIllegalOps*/ true, /*ShouldLegalizeIllegal*/ false,
147 /*LegalizerInfo*/ nullptr, EnableOpt, F.hasOptSize(),
148 F.hasMinSize());
149 // Disable fixed-point iteration to reduce compile-time
150 CInfo.MaxIterations = 1;
151 CInfo.ObserverLvl = CombinerInfo::ObserverLevel::SinglePass;
152 // Legalizer performs DCE, so a full DCE pass is unnecessary.
153 CInfo.EnableFullDCE = false;
154 WebAssemblyPostLegalizerCombinerImpl Impl(MF, CInfo, *VT, CSEInfo, RuleConfig,
155 ST, MDT, LI);
156 return Impl.combineMachineInstrs();
157}
158
159char WebAssemblyPostLegalizerCombinerLegacy::ID = 0;
160INITIALIZE_PASS_BEGIN(WebAssemblyPostLegalizerCombinerLegacy, DEBUG_TYPE,
161 "Combine WebAssembly MachineInstrs after legalization",
162 false, false)
163INITIALIZE_PASS_DEPENDENCY(TargetPassConfig)
164INITIALIZE_PASS_DEPENDENCY(GISelValueTrackingAnalysisLegacy)
165INITIALIZE_PASS_END(WebAssemblyPostLegalizerCombinerLegacy, DEBUG_TYPE,
166 "Combine WebAssembly MachineInstrs after legalization",
167 false, false)
168
169FunctionPass *llvm::createWebAssemblyPostLegalizerCombinerLegacyPass() {
170 return new WebAssemblyPostLegalizerCombinerLegacy();
171}
172
173bool WebAssemblyPostLegalizerCombinerLegacy::runOnMachineFunction(
174 MachineFunction &MF) {
175 return runCombinerOnMachineFunction(
176 MF, ShouldSkip: [&]() { return skipFunction(F: MF.getFunction()); },
177 GetVT: [&]() {
178 return &getAnalysis<GISelValueTrackingAnalysisLegacy>().get(MF);
179 },
180 GetMDT: [&]() {
181 return &getAnalysis<MachineDominatorTreeWrapperPass>().getDomTree();
182 },
183 GetCSEInfo: [&]() {
184 TargetPassConfig *TPC = &getAnalysis<TargetPassConfig>();
185 GISelCSEAnalysisWrapper &Wrapper =
186 getAnalysis<GISelCSEAnalysisWrapperPass>().getCSEWrapper();
187 return &Wrapper.get(CSEOpt: TPC->getCSEConfig());
188 });
189}
190
191PreservedAnalyses WebAssemblyPostLegalizerCombinerPass::run(
192 MachineFunction &MF, MachineFunctionAnalysisManager &MFAM) {
193 bool Changed = runCombinerOnMachineFunction(
194 MF, ShouldSkip: [&]() { return MF.getFunction().hasOptNone(); },
195 GetVT: [&]() { return &MFAM.getResult<GISelValueTrackingAnalysis>(IR&: MF); },
196 GetMDT: [&]() { return &MFAM.getResult<MachineDominatorTreeAnalysis>(IR&: MF); },
197 GetCSEInfo: [&]() { return MFAM.getResult<GISelCSEAnalysis>(IR&: MF).get(); });
198 return Changed ? getMachineFunctionPassPreservedAnalyses()
199 .preserveSet<CFGAnalyses>()
200 : PreservedAnalyses::all();
201}
202