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.addPreserved<MachineDominatorTreeWrapperPass>();
145 AU.addRequired<GISelCSEAnalysisWrapperPass>();
146 AU.addPreserved<GISelCSEAnalysisWrapperPass>();
147
148 MachineFunctionPass::getAnalysisUsage(AU);
149}
150
151X86PostLegalizerCombinerLegacy::X86PostLegalizerCombinerLegacy()
152 : MachineFunctionPass(ID) {
153 if (!RuleConfig.parseCommandLineOption())
154 reportFatalInternalError(reason: "Invalid rule identifier");
155}
156
157bool X86PostLegalizerCombinerLegacy::runOnMachineFunction(MachineFunction &MF) {
158 if (MF.getProperties().hasFailedISel())
159 return false;
160 assert(MF.getProperties().hasLegalized() && "Expected a legalized function?");
161 auto *TPC = &getAnalysis<TargetPassConfig>();
162 const Function &F = MF.getFunction();
163
164 GISelValueTracking *VT =
165 &getAnalysis<GISelValueTrackingAnalysisLegacy>().get(MF);
166 MachineDominatorTree *MDT =
167 &getAnalysis<MachineDominatorTreeWrapperPass>().getDomTree();
168 GISelCSEAnalysisWrapper &Wrapper =
169 getAnalysis<GISelCSEAnalysisWrapperPass>().getCSEWrapper();
170 auto *CSEInfo = &Wrapper.get(CSEOpt: TPC->getCSEConfig());
171
172 CombinerInfo CInfo = createCombinerInfo(OptEnabled: !skipFunction(F), F);
173
174 X86PostLegalizerCombinerImpl Impl(MF, CInfo, *VT, CSEInfo, RuleConfig, MDT);
175 return Impl.combineMachineInstrs();
176}
177
178char X86PostLegalizerCombinerLegacy::ID = 0;
179INITIALIZE_PASS_BEGIN(X86PostLegalizerCombinerLegacy, DEBUG_TYPE,
180 "Combine X86 MachineInstrs after legalization", false,
181 false)
182INITIALIZE_PASS_DEPENDENCY(TargetPassConfig)
183INITIALIZE_PASS_DEPENDENCY(GISelValueTrackingAnalysisLegacy)
184INITIALIZE_PASS_END(X86PostLegalizerCombinerLegacy, DEBUG_TYPE,
185 "Combine X86 MachineInstrs after legalization", false,
186 false)
187
188namespace llvm {
189
190PreservedAnalyses
191X86PostLegalizerCombinerPass::run(MachineFunction &MF,
192 MachineFunctionAnalysisManager &MFAM) {
193 if (MF.getProperties().hasFailedISel())
194 return PreservedAnalyses::all();
195 assert(MF.getProperties().hasLegalized() && "Expected a legalized function.");
196 const Function &F = MF.getFunction();
197
198 GISelValueTracking VT = MFAM.getResult<GISelValueTrackingAnalysis>(IR&: MF);
199 MachineDominatorTree &MDT = MFAM.getResult<MachineDominatorTreeAnalysis>(IR&: MF);
200 auto &CSEInfo = MFAM.getResult<GISelCSEAnalysis>(IR&: MF);
201
202 CombinerInfo CInfo = createCombinerInfo(OptEnabled: true, F);
203
204 X86PostLegalizerCombinerImplRuleConfig RuleConfig;
205 if (!RuleConfig.parseCommandLineOption())
206 reportFatalInternalError(reason: "Invalid rule identifier");
207
208 X86PostLegalizerCombinerImpl Impl(MF, CInfo, VT, CSEInfo.get(), RuleConfig,
209 &MDT);
210 if (!Impl.combineMachineInstrs())
211 return PreservedAnalyses::all();
212
213 PreservedAnalyses PA = getMachineFunctionPassPreservedAnalyses();
214 PA.preserveSet<CFGAnalyses>();
215 PA.preserve<GISelCSEAnalysis>();
216 PA.preserve<GISelValueTrackingAnalysis>();
217 return PA;
218}
219
220FunctionPass *createX86PostLegalizerCombinerLegacy() {
221 return new X86PostLegalizerCombinerLegacy();
222}
223} // end namespace llvm
224