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