1//=== lib/CodeGen/GlobalISel/AArch64O0PreLegalizerCombiner.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 "AArch64.h"
15#include "AArch64GlobalISelUtils.h"
16#include "AArch64TargetMachine.h"
17#include "llvm/CodeGen/GlobalISel/Combiner.h"
18#include "llvm/CodeGen/GlobalISel/CombinerHelper.h"
19#include "llvm/CodeGen/GlobalISel/CombinerInfo.h"
20#include "llvm/CodeGen/GlobalISel/GIMatchTableExecutorImpl.h"
21#include "llvm/CodeGen/GlobalISel/GISelValueTracking.h"
22#include "llvm/CodeGen/GlobalISel/MIPatternMatch.h"
23#include "llvm/CodeGen/GlobalISel/MachineIRBuilder.h"
24#include "llvm/CodeGen/LibcallLoweringInfo.h"
25#include "llvm/CodeGen/MachineDominators.h"
26#include "llvm/CodeGen/MachineFunction.h"
27#include "llvm/CodeGen/MachineFunctionAnalysisManager.h"
28#include "llvm/CodeGen/MachineFunctionPass.h"
29#include "llvm/CodeGen/MachinePassManager.h"
30#include "llvm/CodeGen/TargetPassConfig.h"
31#include "llvm/IR/Instructions.h"
32#include <memory>
33
34#define GET_GICOMBINER_DEPS
35#include "AArch64GenO0PreLegalizeGICombiner.inc"
36#undef GET_GICOMBINER_DEPS
37
38#define DEBUG_TYPE "aarch64-O0-prelegalizer-combiner"
39
40using namespace llvm;
41using namespace MIPatternMatch;
42
43#define GET_GICOMBINER_TYPES
44#include "AArch64GenO0PreLegalizeGICombiner.inc"
45#undef GET_GICOMBINER_TYPES
46
47namespace {
48
49class AArch64O0PreLegalizerCombinerImpl : public Combiner {
50protected:
51 const CombinerHelper Helper;
52 const AArch64O0PreLegalizerCombinerImplRuleConfig &RuleConfig;
53 const AArch64Subtarget &STI;
54 const LibcallLoweringInfo &Libcalls;
55
56public:
57 AArch64O0PreLegalizerCombinerImpl(
58 MachineFunction &MF, CombinerInfo &CInfo, GISelCSEInfo *CSEInfo,
59 const AArch64O0PreLegalizerCombinerImplRuleConfig &RuleConfig,
60 const AArch64Subtarget &STI, const LibcallLoweringInfo &Libcalls);
61
62 static const char *getName() { return "AArch64O0PreLegalizerCombiner"; }
63
64 bool tryCombineAll(MachineInstr &I) const override;
65
66 bool tryCombineAllImpl(MachineInstr &I) const;
67
68private:
69#define GET_GICOMBINER_CLASS_MEMBERS
70#include "AArch64GenO0PreLegalizeGICombiner.inc"
71#undef GET_GICOMBINER_CLASS_MEMBERS
72};
73
74#define GET_GICOMBINER_IMPL
75#include "AArch64GenO0PreLegalizeGICombiner.inc"
76#undef GET_GICOMBINER_IMPL
77
78AArch64O0PreLegalizerCombinerImpl::AArch64O0PreLegalizerCombinerImpl(
79 MachineFunction &MF, CombinerInfo &CInfo, GISelCSEInfo *CSEInfo,
80 const AArch64O0PreLegalizerCombinerImplRuleConfig &RuleConfig,
81 const AArch64Subtarget &STI, const LibcallLoweringInfo &Libcalls)
82 : Combiner(MF, CInfo, /*VT=*/nullptr, CSEInfo),
83 Helper(Observer, B, /*IsPreLegalize*/ true, /*VT=*/nullptr),
84 RuleConfig(RuleConfig), STI(STI), Libcalls(Libcalls),
85#define GET_GICOMBINER_CONSTRUCTOR_INITS
86#include "AArch64GenO0PreLegalizeGICombiner.inc"
87#undef GET_GICOMBINER_CONSTRUCTOR_INITS
88{
89}
90
91bool AArch64O0PreLegalizerCombinerImpl::tryCombineAll(MachineInstr &MI) const {
92 if (tryCombineAllImpl(I&: MI))
93 return true;
94
95 return false;
96}
97
98bool runCombiner(
99 MachineFunction &MF, const LibcallLoweringInfo &Libcalls,
100 const AArch64O0PreLegalizerCombinerImplRuleConfig &RuleConfig) {
101 const Function &F = MF.getFunction();
102 const AArch64Subtarget &ST = MF.getSubtarget<AArch64Subtarget>();
103
104 CombinerInfo CInfo(/*AllowIllegalOps=*/true, /*ShouldLegalizeIllegal=*/false,
105 /*LegalizerInfo=*/nullptr, /*EnableOpt=*/false,
106 F.hasOptSize(), F.hasMinSize());
107 // Disable fixed-point iteration in the Combiner. This improves compile-time
108 // at the cost of possibly missing optimizations. See PR#94291 for details.
109 CInfo.MaxIterations = 1;
110
111 AArch64O0PreLegalizerCombinerImpl Impl(MF, CInfo,
112 /*CSEInfo*/ nullptr, RuleConfig, ST,
113 Libcalls);
114 return Impl.combineMachineInstrs();
115}
116
117// Pass boilerplate
118// ================
119
120class AArch64O0PreLegalizerCombinerLegacy : public MachineFunctionPass {
121public:
122 static char ID;
123
124 AArch64O0PreLegalizerCombinerLegacy();
125
126 StringRef getPassName() const override {
127 return "AArch64O0PreLegalizerCombiner";
128 }
129
130 bool runOnMachineFunction(MachineFunction &MF) override;
131
132 void getAnalysisUsage(AnalysisUsage &AU) const override;
133
134private:
135 AArch64O0PreLegalizerCombinerImplRuleConfig RuleConfig;
136};
137} // end anonymous namespace
138
139void AArch64O0PreLegalizerCombinerLegacy::getAnalysisUsage(
140 AnalysisUsage &AU) const {
141 AU.setPreservesCFG();
142 getSelectionDAGFallbackAnalysisUsage(AU);
143 AU.addRequired<LibcallLoweringInfoWrapper>();
144 MachineFunctionPass::getAnalysisUsage(AU);
145}
146
147AArch64O0PreLegalizerCombinerLegacy::AArch64O0PreLegalizerCombinerLegacy()
148 : MachineFunctionPass(ID) {
149 if (!RuleConfig.parseCommandLineOption())
150 report_fatal_error(reason: "Invalid rule identifier");
151}
152
153bool AArch64O0PreLegalizerCombinerLegacy::runOnMachineFunction(
154 MachineFunction &MF) {
155 if (MF.getProperties().hasFailedISel())
156 return false;
157
158 const Function &F = MF.getFunction();
159
160 const AArch64Subtarget &ST = MF.getSubtarget<AArch64Subtarget>();
161 const LibcallLoweringInfo &Libcalls =
162 getAnalysis<LibcallLoweringInfoWrapper>().getLibcallLowering(
163 M: *F.getParent(), Subtarget: ST);
164
165 return runCombiner(MF, Libcalls, RuleConfig);
166}
167
168char AArch64O0PreLegalizerCombinerLegacy::ID = 0;
169INITIALIZE_PASS_BEGIN(AArch64O0PreLegalizerCombinerLegacy, DEBUG_TYPE,
170 "Combine AArch64 machine instrs before legalization",
171 false, false)
172INITIALIZE_PASS_DEPENDENCY(GISelCSEAnalysisWrapperPass)
173INITIALIZE_PASS_DEPENDENCY(LibcallLoweringInfoWrapper)
174INITIALIZE_PASS_END(AArch64O0PreLegalizerCombinerLegacy, DEBUG_TYPE,
175 "Combine AArch64 machine instrs before legalization", false,
176 false)
177
178AArch64O0PreLegalizerCombinerPass::AArch64O0PreLegalizerCombinerPass()
179 : RuleConfig(
180 std::make_unique<AArch64O0PreLegalizerCombinerImplRuleConfig>()) {
181 if (!RuleConfig->parseCommandLineOption())
182 report_fatal_error(reason: "Invalid rule identifier");
183}
184
185AArch64O0PreLegalizerCombinerPass::AArch64O0PreLegalizerCombinerPass(
186 AArch64O0PreLegalizerCombinerPass &&) = default;
187
188AArch64O0PreLegalizerCombinerPass::~AArch64O0PreLegalizerCombinerPass() =
189 default;
190
191PreservedAnalyses
192AArch64O0PreLegalizerCombinerPass::run(MachineFunction &MF,
193 MachineFunctionAnalysisManager &MFAM) {
194 if (MF.getProperties().hasFailedISel())
195 return PreservedAnalyses::all();
196
197 const AArch64Subtarget &ST = MF.getSubtarget<AArch64Subtarget>();
198 auto &MAMProxy =
199 MFAM.getResult<ModuleAnalysisManagerMachineFunctionProxy>(IR&: MF);
200 const LibcallLoweringModuleAnalysisResult *LibcallResult =
201 MAMProxy.getCachedResult<LibcallLoweringModuleAnalysis>(
202 IR&: *MF.getFunction().getParent());
203 if (!LibcallResult)
204 reportFatalUsageError(reason: "LibcallLoweringModuleAnalysis result not available");
205
206 const LibcallLoweringInfo &Libcalls = LibcallResult->getLibcallLowering(Subtarget: ST);
207
208 if (!runCombiner(MF, Libcalls, RuleConfig: *RuleConfig))
209 return PreservedAnalyses::all();
210
211 PreservedAnalyses PA = getMachineFunctionPassPreservedAnalyses();
212 PA.preserveSet<CFGAnalyses>();
213 return PA;
214}
215
216namespace llvm {
217FunctionPass *createAArch64O0PreLegalizerCombiner() {
218 return new AArch64O0PreLegalizerCombinerLegacy();
219}
220} // end namespace llvm
221