1//===--------------- X86PostLegalizerCombiner.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/// Lowering combines (e.g. pseudo matching) should be handled by
15/// X86PostLegalizerLowering.
16///
17/// Combines which don't rely on instruction legality should go in the
18/// X86PreLegalizerCombiner.
19///
20//===----------------------------------------------------------------------===//
21#include "X86.h"
22#include "X86TargetMachine.h"
23#include "llvm/ADT/STLExtras.h"
24#include "llvm/CodeGen/GlobalISel/CSEInfo.h"
25#include "llvm/CodeGen/GlobalISel/CSEMIRBuilder.h"
26#include "llvm/CodeGen/GlobalISel/Combiner.h"
27#include "llvm/CodeGen/GlobalISel/CombinerHelper.h"
28#include "llvm/CodeGen/GlobalISel/CombinerInfo.h"
29#include "llvm/CodeGen/GlobalISel/GIMatchTableExecutorImpl.h"
30#include "llvm/CodeGen/GlobalISel/GISelChangeObserver.h"
31#include "llvm/CodeGen/GlobalISel/GISelValueTracking.h"
32#include "llvm/CodeGen/GlobalISel/GenericMachineInstrs.h"
33#include "llvm/CodeGen/GlobalISel/MIPatternMatch.h"
34#include "llvm/CodeGen/GlobalISel/MachineIRBuilder.h"
35#include "llvm/CodeGen/GlobalISel/Utils.h"
36#include "llvm/CodeGen/MachineDominators.h"
37#include "llvm/CodeGen/MachineFunctionPass.h"
38#include "llvm/CodeGen/MachineRegisterInfo.h"
39#include "llvm/CodeGen/TargetOpcodes.h"
40#include "llvm/CodeGen/TargetPassConfig.h"
41#include "llvm/Support/Debug.h"
42
43#define GET_GICOMBINER_DEPS
44#include "X86GenPostLegalizeGICombiner.inc"
45#undef GET_GICOMBINER_DEPS
46
47#define DEBUG_TYPE "X86-postlegalizer-combiner"
48
49using namespace llvm;
50using namespace MIPatternMatch;
51
52namespace {
53
54CombinerInfo createCombinerInfo(bool OptEnabled, const Function &F) {
55 CombinerInfo CInfo(/*AllowIllegalOps=*/true,
56 /*ShouldLegalizeIllegal=*/false,
57 /*LInfo=*/nullptr, /*OptEnabled=*/OptEnabled,
58 /*OptSize=*/F.hasOptSize(), /*MinSize=*/F.hasMinSize());
59 // Disable fixed-point iteration to reduce compile-time
60 CInfo.MaxIterations = 1;
61 CInfo.ObserverLvl = CombinerInfo::ObserverLevel::SinglePass;
62 // Legalizer performs DCE, so a full DCE pass is unnecessary.
63 CInfo.EnableFullDCE = false;
64 return CInfo;
65}
66
67#define GET_GICOMBINER_TYPES
68#include "X86GenPostLegalizeGICombiner.inc"
69#undef GET_GICOMBINER_TYPES
70
71class X86PostLegalizerCombinerImpl : public Combiner {
72protected:
73 const CombinerHelper Helper;
74 const X86PostLegalizerCombinerImplRuleConfig &RuleConfig;
75 const X86Subtarget &STI;
76
77public:
78 X86PostLegalizerCombinerImpl(
79 MachineFunction &MF, CombinerInfo &CInfo, GISelValueTracking &VT,
80 GISelCSEInfo *CSEInfo,
81 const X86PostLegalizerCombinerImplRuleConfig &RuleConfig,
82 MachineDominatorTree *MDT);
83
84 static const char *getName() { return "X86PostLegalizerCombiner"; }
85
86 bool tryCombineAll(MachineInstr &I) const override;
87 bool tryCombineAllImpl(MachineInstr &I) const;
88
89private:
90#define GET_GICOMBINER_CLASS_MEMBERS
91#include "X86GenPostLegalizeGICombiner.inc"
92#undef GET_GICOMBINER_CLASS_MEMBERS
93};
94
95#define GET_GICOMBINER_IMPL
96#include "X86GenPostLegalizeGICombiner.inc"
97#undef GET_GICOMBINER_IMPL
98
99X86PostLegalizerCombinerImpl::X86PostLegalizerCombinerImpl(
100 MachineFunction &MF, CombinerInfo &CInfo, GISelValueTracking &VT,
101 GISelCSEInfo *CSEInfo,
102 const X86PostLegalizerCombinerImplRuleConfig &RuleConfig,
103 MachineDominatorTree *MDT)
104 : Combiner(MF, CInfo, &VT, CSEInfo),
105 Helper(Observer, B, /*IsPreLegalize=*/false, &VT, MDT,
106 MF.getSubtarget<X86Subtarget>().getLegalizerInfo()),
107 RuleConfig(RuleConfig), STI(MF.getSubtarget<X86Subtarget>()),
108#define GET_GICOMBINER_CONSTRUCTOR_INITS
109#include "X86GenPostLegalizeGICombiner.inc"
110#undef GET_GICOMBINER_CONSTRUCTOR_INITS
111{
112}
113
114bool X86PostLegalizerCombinerImpl::tryCombineAll(MachineInstr &MI) const {
115 return tryCombineAllImpl(I&: MI);
116}
117
118class X86PostLegalizerCombinerLegacy : public MachineFunctionPass {
119public:
120 static char ID;
121
122 X86PostLegalizerCombinerLegacy();
123
124 StringRef getPassName() const override {
125 return "X86PostLegalizerCombinerLegacy";
126 }
127
128 bool runOnMachineFunction(MachineFunction &MF) override;
129 void getAnalysisUsage(AnalysisUsage &AU) const override;
130
131private:
132 X86PostLegalizerCombinerImplRuleConfig RuleConfig;
133};
134} // end anonymous namespace
135
136void X86PostLegalizerCombinerLegacy::getAnalysisUsage(AnalysisUsage &AU) const {
137 AU.addRequired<TargetPassConfig>();
138 AU.setPreservesCFG();
139 getSelectionDAGFallbackAnalysisUsage(AU);
140 AU.addRequired<GISelValueTrackingAnalysisLegacy>();
141 AU.addPreserved<GISelValueTrackingAnalysisLegacy>();
142 // This is only added when processing level is not OptNone.
143 AU.addRequired<MachineDominatorTreeWrapperPass>();
144 AU.addRequired<GISelCSEAnalysisWrapperPass>();
145 AU.addPreserved<GISelCSEAnalysisWrapperPass>();
146
147 MachineFunctionPass::getAnalysisUsage(AU);
148}
149
150X86PostLegalizerCombinerLegacy::X86PostLegalizerCombinerLegacy()
151 : MachineFunctionPass(ID) {
152 if (!RuleConfig.parseCommandLineOption())
153 reportFatalInternalError(reason: "Invalid rule identifier");
154}
155
156bool X86PostLegalizerCombinerLegacy::runOnMachineFunction(MachineFunction &MF) {
157 if (MF.getProperties().hasFailedISel())
158 return false;
159 assert(MF.getProperties().hasLegalized() && "Expected a legalized function?");
160 auto *TPC = &getAnalysis<TargetPassConfig>();
161 const Function &F = MF.getFunction();
162
163 GISelValueTracking *VT =
164 &getAnalysis<GISelValueTrackingAnalysisLegacy>().get(MF);
165 MachineDominatorTree *MDT =
166 &getAnalysis<MachineDominatorTreeWrapperPass>().getDomTree();
167 GISelCSEAnalysisWrapper &Wrapper =
168 getAnalysis<GISelCSEAnalysisWrapperPass>().getCSEWrapper();
169 auto *CSEInfo = &Wrapper.get(CSEOpt: TPC->getCSEConfig());
170
171 CombinerInfo CInfo = createCombinerInfo(OptEnabled: !skipFunction(F), F);
172
173 X86PostLegalizerCombinerImpl Impl(MF, CInfo, *VT, CSEInfo, RuleConfig, MDT);
174 return Impl.combineMachineInstrs();
175}
176
177char X86PostLegalizerCombinerLegacy::ID = 0;
178INITIALIZE_PASS_BEGIN(X86PostLegalizerCombinerLegacy, DEBUG_TYPE,
179 "Combine X86 MachineInstrs after legalization", false,
180 false)
181INITIALIZE_PASS_DEPENDENCY(TargetPassConfig)
182INITIALIZE_PASS_DEPENDENCY(GISelValueTrackingAnalysisLegacy)
183INITIALIZE_PASS_END(X86PostLegalizerCombinerLegacy, DEBUG_TYPE,
184 "Combine X86 MachineInstrs after legalization", false,
185 false)
186
187namespace llvm {
188
189PreservedAnalyses
190X86PostLegalizerCombinerPass::run(MachineFunction &MF,
191 MachineFunctionAnalysisManager &MFAM) {
192 if (MF.getProperties().hasFailedISel())
193 return PreservedAnalyses::all();
194 assert(MF.getProperties().hasLegalized() && "Expected a legalized function.");
195 const Function &F = MF.getFunction();
196
197 GISelValueTracking VT = MFAM.getResult<GISelValueTrackingAnalysis>(IR&: MF);
198 MachineDominatorTree &MDT = MFAM.getResult<MachineDominatorTreeAnalysis>(IR&: MF);
199 auto &CSEInfo = MFAM.getResult<GISelCSEAnalysis>(IR&: MF);
200
201 CombinerInfo CInfo = createCombinerInfo(OptEnabled: true, F);
202
203 X86PostLegalizerCombinerImplRuleConfig RuleConfig;
204 if (!RuleConfig.parseCommandLineOption())
205 reportFatalInternalError(reason: "Invalid rule identifier");
206
207 X86PostLegalizerCombinerImpl Impl(MF, CInfo, VT, CSEInfo.get(), RuleConfig,
208 &MDT);
209 if (!Impl.combineMachineInstrs())
210 return PreservedAnalyses::all();
211
212 PreservedAnalyses PA = getMachineFunctionPassPreservedAnalyses();
213 PA.preserveSet<CFGAnalyses>();
214 PA.preserve<GISelCSEAnalysis>();
215 PA.preserve<GISelValueTrackingAnalysis>();
216 return PA;
217}
218
219FunctionPass *createX86PostLegalizerCombinerLegacy() {
220 return new X86PostLegalizerCombinerLegacy();
221}
222} // end namespace llvm
223