1//===-- SPIRVPreLegalizerCombiner.cpp - combine legalization ----*- 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// This pass does combining of machine instructions at the generic MI level,
10// before the legalizer.
11//
12//===----------------------------------------------------------------------===//
13
14#include "SPIRV.h"
15#include "SPIRVCombinerHelper.h"
16#include "llvm/CodeGen/GlobalISel/CSEInfo.h"
17#include "llvm/CodeGen/GlobalISel/Combiner.h"
18#include "llvm/CodeGen/GlobalISel/CombinerInfo.h"
19#include "llvm/CodeGen/GlobalISel/GIMatchTableExecutorImpl.h"
20#include "llvm/CodeGen/GlobalISel/GISelChangeObserver.h"
21#include "llvm/CodeGen/GlobalISel/GISelValueTracking.h"
22#include "llvm/CodeGen/GlobalISel/MIPatternMatch.h"
23#include "llvm/CodeGen/MachineDominators.h"
24#include "llvm/CodeGen/MachineFunctionPass.h"
25#include "llvm/CodeGen/TargetPassConfig.h"
26
27#define GET_GICOMBINER_DEPS
28#include "SPIRVGenPreLegalizeGICombiner.inc"
29#undef GET_GICOMBINER_DEPS
30
31#define DEBUG_TYPE "spirv-prelegalizer-combiner"
32
33using namespace llvm;
34using namespace MIPatternMatch;
35
36namespace {
37
38#define GET_GICOMBINER_TYPES
39#include "SPIRVGenPreLegalizeGICombiner.inc"
40#undef GET_GICOMBINER_TYPES
41
42class SPIRVPreLegalizerCombinerImpl : public Combiner {
43protected:
44 const SPIRVCombinerHelper Helper;
45 const SPIRVPreLegalizerCombinerImplRuleConfig &RuleConfig;
46 const SPIRVSubtarget &STI;
47
48public:
49 SPIRVPreLegalizerCombinerImpl(
50 MachineFunction &MF, CombinerInfo &CInfo, GISelValueTracking &VT,
51 GISelCSEInfo *CSEInfo,
52 const SPIRVPreLegalizerCombinerImplRuleConfig &RuleConfig,
53 const SPIRVSubtarget &STI, MachineDominatorTree *MDT,
54 const LegalizerInfo *LI);
55
56 static const char *getName() { return "SPIRVPreLegalizerCombiner"; }
57
58 bool tryCombineAll(MachineInstr &I) const override;
59
60 bool tryCombineAllImpl(MachineInstr &I) const;
61
62private:
63#define GET_GICOMBINER_CLASS_MEMBERS
64#include "SPIRVGenPreLegalizeGICombiner.inc"
65#undef GET_GICOMBINER_CLASS_MEMBERS
66};
67
68#define GET_GICOMBINER_IMPL
69#include "SPIRVGenPreLegalizeGICombiner.inc"
70#undef GET_GICOMBINER_IMPL
71
72SPIRVPreLegalizerCombinerImpl::SPIRVPreLegalizerCombinerImpl(
73 MachineFunction &MF, CombinerInfo &CInfo, GISelValueTracking &VT,
74 GISelCSEInfo *CSEInfo,
75 const SPIRVPreLegalizerCombinerImplRuleConfig &RuleConfig,
76 const SPIRVSubtarget &STI, MachineDominatorTree *MDT,
77 const LegalizerInfo *LI)
78 : Combiner(MF, CInfo, &VT, CSEInfo),
79 Helper(Observer, B, /*IsPreLegalize*/ true, &VT, MDT, LI, STI),
80 RuleConfig(RuleConfig), STI(STI),
81#define GET_GICOMBINER_CONSTRUCTOR_INITS
82#include "SPIRVGenPreLegalizeGICombiner.inc"
83#undef GET_GICOMBINER_CONSTRUCTOR_INITS
84{
85}
86
87bool SPIRVPreLegalizerCombinerImpl::tryCombineAll(MachineInstr &MI) const {
88 return tryCombineAllImpl(I&: MI);
89}
90
91// Pass boilerplate
92// ================
93
94class SPIRVPreLegalizerCombiner : public MachineFunctionPass {
95public:
96 static char ID;
97
98 SPIRVPreLegalizerCombiner();
99
100 StringRef getPassName() const override { return "SPIRVPreLegalizerCombiner"; }
101
102 bool runOnMachineFunction(MachineFunction &MF) override;
103
104 void getAnalysisUsage(AnalysisUsage &AU) const override;
105
106private:
107 SPIRVPreLegalizerCombinerImplRuleConfig RuleConfig;
108};
109
110} // end anonymous namespace
111
112void SPIRVPreLegalizerCombiner::getAnalysisUsage(AnalysisUsage &AU) const {
113 AU.setPreservesCFG();
114 getSelectionDAGFallbackAnalysisUsage(AU);
115 AU.addRequired<GISelValueTrackingAnalysisLegacy>();
116 AU.addPreserved<GISelValueTrackingAnalysisLegacy>();
117 AU.addRequired<MachineDominatorTreeWrapperPass>();
118 AU.addPreserved<MachineDominatorTreeWrapperPass>();
119 MachineFunctionPass::getAnalysisUsage(AU);
120}
121
122SPIRVPreLegalizerCombiner::SPIRVPreLegalizerCombiner()
123 : MachineFunctionPass(ID) {
124 if (!RuleConfig.parseCommandLineOption())
125 report_fatal_error(reason: "Invalid rule identifier");
126}
127
128bool SPIRVPreLegalizerCombiner::runOnMachineFunction(MachineFunction &MF) {
129 if (MF.getProperties().hasFailedISel())
130 return false;
131
132 const SPIRVSubtarget &ST = MF.getSubtarget<SPIRVSubtarget>();
133 const auto *LI = ST.getLegalizerInfo();
134
135 const Function &F = MF.getFunction();
136 bool EnableOpt =
137 MF.getTarget().getOptLevel() != CodeGenOptLevel::None && !skipFunction(F);
138 GISelValueTracking *VT =
139 &getAnalysis<GISelValueTrackingAnalysisLegacy>().get(MF);
140 MachineDominatorTree *MDT =
141 &getAnalysis<MachineDominatorTreeWrapperPass>().getDomTree();
142 CombinerInfo CInfo(/*AllowIllegalOps*/ true, /*ShouldLegalizeIllegal*/ false,
143 /*LegalizerInfo*/ nullptr, EnableOpt, F.hasOptSize(),
144 F.hasMinSize());
145 // Disable fixed-point iteration to reduce compile-time
146 CInfo.MaxIterations = 1;
147 CInfo.ObserverLvl = CombinerInfo::ObserverLevel::SinglePass;
148 // This is the first Combiner, so the input IR might contain dead
149 // instructions.
150 CInfo.EnableFullDCE = false;
151 SPIRVPreLegalizerCombinerImpl Impl(MF, CInfo, *VT, /*CSEInfo*/ nullptr,
152 RuleConfig, ST, MDT, LI);
153 return Impl.combineMachineInstrs();
154}
155
156char SPIRVPreLegalizerCombiner::ID = 0;
157INITIALIZE_PASS_BEGIN(SPIRVPreLegalizerCombiner, DEBUG_TYPE,
158 "Combine SPIRV machine instrs before legalization", false,
159 false)
160INITIALIZE_PASS_DEPENDENCY(GISelValueTrackingAnalysisLegacy)
161INITIALIZE_PASS_END(SPIRVPreLegalizerCombiner, DEBUG_TYPE,
162 "Combine SPIRV machine instrs before legalization", false,
163 false)
164
165namespace llvm {
166FunctionPass *createSPIRVPreLegalizerCombiner() {
167 return new SPIRVPreLegalizerCombiner();
168}
169} // end namespace llvm
170