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, const TargetPassConfig *TPC,
51 GISelValueTracking &VT, 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, const TargetPassConfig *TPC,
74 GISelValueTracking &VT, GISelCSEInfo *CSEInfo,
75 const SPIRVPreLegalizerCombinerImplRuleConfig &RuleConfig,
76 const SPIRVSubtarget &STI, MachineDominatorTree *MDT,
77 const LegalizerInfo *LI)
78 : Combiner(MF, CInfo, TPC, &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.addRequired<TargetPassConfig>();
114 AU.setPreservesCFG();
115 getSelectionDAGFallbackAnalysisUsage(AU);
116 AU.addRequired<GISelValueTrackingAnalysisLegacy>();
117 AU.addPreserved<GISelValueTrackingAnalysisLegacy>();
118 AU.addRequired<MachineDominatorTreeWrapperPass>();
119 AU.addPreserved<MachineDominatorTreeWrapperPass>();
120 MachineFunctionPass::getAnalysisUsage(AU);
121}
122
123SPIRVPreLegalizerCombiner::SPIRVPreLegalizerCombiner()
124 : MachineFunctionPass(ID) {
125 if (!RuleConfig.parseCommandLineOption())
126 report_fatal_error(reason: "Invalid rule identifier");
127}
128
129bool SPIRVPreLegalizerCombiner::runOnMachineFunction(MachineFunction &MF) {
130 if (MF.getProperties().hasFailedISel())
131 return false;
132 auto &TPC = getAnalysis<TargetPassConfig>();
133
134 const SPIRVSubtarget &ST = MF.getSubtarget<SPIRVSubtarget>();
135 const auto *LI = ST.getLegalizerInfo();
136
137 const Function &F = MF.getFunction();
138 bool EnableOpt =
139 MF.getTarget().getOptLevel() != CodeGenOptLevel::None && !skipFunction(F);
140 GISelValueTracking *VT =
141 &getAnalysis<GISelValueTrackingAnalysisLegacy>().get(MF);
142 MachineDominatorTree *MDT =
143 &getAnalysis<MachineDominatorTreeWrapperPass>().getDomTree();
144 CombinerInfo CInfo(/*AllowIllegalOps*/ true, /*ShouldLegalizeIllegal*/ false,
145 /*LegalizerInfo*/ nullptr, EnableOpt, F.hasOptSize(),
146 F.hasMinSize());
147 // Disable fixed-point iteration to reduce compile-time
148 CInfo.MaxIterations = 1;
149 CInfo.ObserverLvl = CombinerInfo::ObserverLevel::SinglePass;
150 // This is the first Combiner, so the input IR might contain dead
151 // instructions.
152 CInfo.EnableFullDCE = false;
153 SPIRVPreLegalizerCombinerImpl Impl(MF, CInfo, &TPC, *VT, /*CSEInfo*/ nullptr,
154 RuleConfig, ST, MDT, LI);
155 return Impl.combineMachineInstrs();
156}
157
158char SPIRVPreLegalizerCombiner::ID = 0;
159INITIALIZE_PASS_BEGIN(SPIRVPreLegalizerCombiner, DEBUG_TYPE,
160 "Combine SPIRV machine instrs before legalization", false,
161 false)
162INITIALIZE_PASS_DEPENDENCY(TargetPassConfig)
163INITIALIZE_PASS_DEPENDENCY(GISelValueTrackingAnalysisLegacy)
164INITIALIZE_PASS_END(SPIRVPreLegalizerCombiner, DEBUG_TYPE,
165 "Combine SPIRV machine instrs before legalization", false,
166 false)
167
168namespace llvm {
169FunctionPass *createSPIRVPreLegalizerCombiner() {
170 return new SPIRVPreLegalizerCombiner();
171}
172} // end namespace llvm
173