1//===---------------- X86PreLegalizerCombiner.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/// \file
9/// This pass does combining of machine instructions at the generic MI level,
10/// before the legalizer.
11///
12//===----------------------------------------------------------------------===//
13#include "X86.h"
14#include "X86TargetMachine.h"
15#include "llvm/CodeGen/GlobalISel/CSEInfo.h"
16#include "llvm/CodeGen/GlobalISel/Combiner.h"
17#include "llvm/CodeGen/GlobalISel/CombinerHelper.h"
18#include "llvm/CodeGen/GlobalISel/CombinerInfo.h"
19#include "llvm/CodeGen/GlobalISel/GIMatchTableExecutorImpl.h"
20#include "llvm/CodeGen/GlobalISel/GISelValueTracking.h"
21#include "llvm/CodeGen/GlobalISel/LegalizerInfo.h"
22#include "llvm/CodeGen/GlobalISel/MIPatternMatch.h"
23#include "llvm/CodeGen/GlobalISel/MachineIRBuilder.h"
24#include "llvm/CodeGen/GlobalISel/Utils.h"
25#include "llvm/CodeGen/MachineDominators.h"
26#include "llvm/CodeGen/MachineFunction.h"
27#include "llvm/CodeGen/MachineFunctionPass.h"
28#include "llvm/CodeGen/TargetPassConfig.h"
29#include "llvm/IR/Instructions.h"
30
31#define GET_GICOMBINER_DEPS
32#include "X86GenPreLegalizeGICombiner.inc"
33#undef GET_GICOMBINER_DEPS
34
35#define DEBUG_TYPE "x86-prelegalizer-combiner"
36
37using namespace llvm;
38using namespace MIPatternMatch;
39
40namespace {
41
42CombinerInfo createCombinerInfo(bool EnableOpt, const Function &F) {
43 CombinerInfo CInfo(/*AllowIllegalOps=*/true, /*ShouldLegalizeIllegal=*/false,
44 nullptr, EnableOpt, F.hasOptSize(), F.hasMinSize());
45
46 // This is the first Combiner, so the input IR might contain dead
47 // instructions.
48 CInfo.EnableFullDCE = true;
49 return CInfo;
50}
51
52#define GET_GICOMBINER_TYPES
53#include "X86GenPreLegalizeGICombiner.inc"
54#undef GET_GICOMBINER_TYPES
55
56class X86PreLegalizerCombinerImpl : public Combiner {
57protected:
58 const CombinerHelper Helper;
59 const X86PreLegalizerCombinerImplRuleConfig &RuleConfig;
60 const X86Subtarget &STI;
61
62public:
63 X86PreLegalizerCombinerImpl(
64 MachineFunction &MF, CombinerInfo &CInfo, GISelValueTracking &VT,
65 GISelCSEInfo *CSEInfo,
66 const X86PreLegalizerCombinerImplRuleConfig &RuleConfig,
67 MachineDominatorTree *MDT);
68
69 static const char *getName() { return "X86PreLegalizerCombiner"; }
70
71 bool tryCombineAll(MachineInstr &I) const override;
72
73 bool tryCombineAllImpl(MachineInstr &I) const;
74
75private:
76#define GET_GICOMBINER_CLASS_MEMBERS
77#include "X86GenPreLegalizeGICombiner.inc"
78#undef GET_GICOMBINER_CLASS_MEMBERS
79};
80
81#define GET_GICOMBINER_IMPL
82#include "X86GenPreLegalizeGICombiner.inc"
83#undef GET_GICOMBINER_IMPL
84
85X86PreLegalizerCombinerImpl::X86PreLegalizerCombinerImpl(
86 MachineFunction &MF, CombinerInfo &CInfo, GISelValueTracking &VT,
87 GISelCSEInfo *CSEInfo,
88 const X86PreLegalizerCombinerImplRuleConfig &RuleConfig,
89 MachineDominatorTree *MDT)
90 : Combiner(MF, CInfo, &VT, CSEInfo),
91 Helper(Observer, B, /*IsPreLegalize=*/true, &VT, MDT,
92 MF.getSubtarget<X86Subtarget>().getLegalizerInfo()),
93 RuleConfig(RuleConfig), STI(MF.getSubtarget<X86Subtarget>()),
94#define GET_GICOMBINER_CONSTRUCTOR_INITS
95#include "X86GenPreLegalizeGICombiner.inc"
96#undef GET_GICOMBINER_CONSTRUCTOR_INITS
97{
98}
99
100bool X86PreLegalizerCombinerImpl::tryCombineAll(MachineInstr &MI) const {
101 return tryCombineAllImpl(I&: MI);
102}
103
104class X86PreLegalizerCombinerLegacy : public MachineFunctionPass {
105public:
106 static char ID;
107
108 X86PreLegalizerCombinerLegacy();
109
110 StringRef getPassName() const override {
111 return "X86PreLegalizerCombinerLegacy";
112 }
113
114 bool runOnMachineFunction(MachineFunction &MF) override;
115
116 void getAnalysisUsage(AnalysisUsage &AU) const override;
117
118private:
119 X86PreLegalizerCombinerImplRuleConfig RuleConfig;
120};
121} // end anonymous namespace
122
123void X86PreLegalizerCombinerLegacy::getAnalysisUsage(AnalysisUsage &AU) const {
124 AU.addRequired<TargetPassConfig>();
125 AU.setPreservesCFG();
126 getSelectionDAGFallbackAnalysisUsage(AU);
127 AU.addRequired<GISelValueTrackingAnalysisLegacy>();
128 AU.addPreserved<GISelValueTrackingAnalysisLegacy>();
129 AU.addRequired<MachineDominatorTreeWrapperPass>();
130 AU.addRequired<GISelCSEAnalysisWrapperPass>();
131 AU.addPreserved<GISelCSEAnalysisWrapperPass>();
132 MachineFunctionPass::getAnalysisUsage(AU);
133}
134
135X86PreLegalizerCombinerLegacy::X86PreLegalizerCombinerLegacy()
136 : MachineFunctionPass(ID) {
137 if (!RuleConfig.parseCommandLineOption())
138 report_fatal_error(reason: "Invalid rule identifier");
139}
140
141bool X86PreLegalizerCombinerLegacy::runOnMachineFunction(MachineFunction &MF) {
142 if (MF.getProperties().hasFailedISel())
143 return false;
144 auto &TPC = getAnalysis<TargetPassConfig>();
145
146 // Enable CSE.
147 GISelCSEAnalysisWrapper &Wrapper =
148 getAnalysis<GISelCSEAnalysisWrapperPass>().getCSEWrapper();
149 auto *CSEInfo = &Wrapper.get(CSEOpt: TPC.getCSEConfig());
150 const Function &F = MF.getFunction();
151 bool EnableOpt =
152 MF.getTarget().getOptLevel() != CodeGenOptLevel::None && !skipFunction(F);
153 GISelValueTracking *VT =
154 &getAnalysis<GISelValueTrackingAnalysisLegacy>().get(MF);
155 MachineDominatorTree *MDT =
156 &getAnalysis<MachineDominatorTreeWrapperPass>().getDomTree();
157 CombinerInfo CInfo = createCombinerInfo(EnableOpt, F);
158 X86PreLegalizerCombinerImpl Impl(MF, CInfo, *VT, CSEInfo, RuleConfig, MDT);
159 return Impl.combineMachineInstrs();
160}
161
162char X86PreLegalizerCombinerLegacy::ID = 0;
163INITIALIZE_PASS_BEGIN(X86PreLegalizerCombinerLegacy, DEBUG_TYPE,
164 "Combine X86 machine instrs before legalization", false,
165 false)
166INITIALIZE_PASS_DEPENDENCY(TargetPassConfig)
167INITIALIZE_PASS_DEPENDENCY(GISelValueTrackingAnalysisLegacy)
168INITIALIZE_PASS_DEPENDENCY(GISelCSEAnalysisWrapperPass)
169INITIALIZE_PASS_END(X86PreLegalizerCombinerLegacy, DEBUG_TYPE,
170 "Combine X86 machine instrs before legalization", false,
171 false)
172
173namespace llvm {
174
175PreservedAnalyses
176X86PreLegalizerCombinerPass::run(MachineFunction &MF,
177 MachineFunctionAnalysisManager &MFAM) {
178 if (MF.getProperties().hasFailedISel())
179 return PreservedAnalyses::all();
180
181 X86PreLegalizerCombinerImplRuleConfig RuleConfig;
182 if (!RuleConfig.parseCommandLineOption())
183 report_fatal_error(reason: "Invalid rule identifier");
184
185 auto &CSEInfo = MFAM.getResult<GISelCSEAnalysis>(IR&: MF);
186 const Function &F = MF.getFunction();
187 bool EnableOpt = MF.getTarget().getOptLevel() != CodeGenOptLevel::None;
188 GISelValueTracking &VT = MFAM.getResult<GISelValueTrackingAnalysis>(IR&: MF);
189 MachineDominatorTree &MDT = MFAM.getResult<MachineDominatorTreeAnalysis>(IR&: MF);
190 CombinerInfo CInfo = createCombinerInfo(EnableOpt, F);
191 X86PreLegalizerCombinerImpl Impl(MF, CInfo, VT, CSEInfo.get(), RuleConfig,
192 &MDT);
193 Impl.combineMachineInstrs();
194
195 PreservedAnalyses PA = getMachineFunctionPassPreservedAnalyses();
196 PA.preserveSet<CFGAnalyses>();
197 PA.preserve<GISelCSEAnalysis>();
198 PA.preserve<GISelValueTrackingAnalysis>();
199 return PA;
200}
201
202FunctionPass *createX86PreLegalizerCombinerLegacy() {
203 return new X86PreLegalizerCombinerLegacy();
204}
205} // end namespace llvm
206