Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/contrib/llvm-project/llvm/lib/Target/SPIRV/SPIRVPreLegalizerCombiner.cpp
213799 views
1
2
//===-- SPIRVPreLegalizerCombiner.cpp - combine legalization ----*- C++ -*-===//
3
//
4
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
5
// See https://llvm.org/LICENSE.txt for license information.
6
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7
//
8
//===----------------------------------------------------------------------===//
9
//
10
// This pass does combining of machine instructions at the generic MI level,
11
// before the legalizer.
12
//
13
//===----------------------------------------------------------------------===//
14
15
#include "SPIRV.h"
16
#include "SPIRVTargetMachine.h"
17
#include "llvm/CodeGen/GlobalISel/CSEInfo.h"
18
#include "llvm/CodeGen/GlobalISel/Combiner.h"
19
#include "llvm/CodeGen/GlobalISel/CombinerHelper.h"
20
#include "llvm/CodeGen/GlobalISel/CombinerInfo.h"
21
#include "llvm/CodeGen/GlobalISel/GIMatchTableExecutorImpl.h"
22
#include "llvm/CodeGen/GlobalISel/GISelChangeObserver.h"
23
#include "llvm/CodeGen/GlobalISel/GISelValueTracking.h"
24
#include "llvm/CodeGen/GlobalISel/GenericMachineInstrs.h"
25
#include "llvm/CodeGen/GlobalISel/MIPatternMatch.h"
26
#include "llvm/CodeGen/GlobalISel/MachineIRBuilder.h"
27
#include "llvm/CodeGen/GlobalISel/Utils.h"
28
#include "llvm/CodeGen/MachineDominators.h"
29
#include "llvm/CodeGen/MachineFunctionPass.h"
30
#include "llvm/CodeGen/MachineRegisterInfo.h"
31
#include "llvm/CodeGen/TargetOpcodes.h"
32
#include "llvm/CodeGen/TargetPassConfig.h"
33
#include "llvm/IR/IntrinsicsSPIRV.h"
34
35
#define GET_GICOMBINER_DEPS
36
#include "SPIRVGenPreLegalizeGICombiner.inc"
37
#undef GET_GICOMBINER_DEPS
38
39
#define DEBUG_TYPE "spirv-prelegalizer-combiner"
40
41
using namespace llvm;
42
using namespace MIPatternMatch;
43
44
namespace {
45
46
#define GET_GICOMBINER_TYPES
47
#include "SPIRVGenPreLegalizeGICombiner.inc"
48
#undef GET_GICOMBINER_TYPES
49
50
/// This match is part of a combine that
51
/// rewrites length(X - Y) to distance(X, Y)
52
/// (f32 (g_intrinsic length
53
/// (g_fsub (vXf32 X) (vXf32 Y))))
54
/// ->
55
/// (f32 (g_intrinsic distance
56
/// (vXf32 X) (vXf32 Y)))
57
///
58
bool matchLengthToDistance(MachineInstr &MI, MachineRegisterInfo &MRI) {
59
if (MI.getOpcode() != TargetOpcode::G_INTRINSIC ||
60
cast<GIntrinsic>(MI).getIntrinsicID() != Intrinsic::spv_length)
61
return false;
62
63
// First operand of MI is `G_INTRINSIC` so start at operand 2.
64
Register SubReg = MI.getOperand(2).getReg();
65
MachineInstr *SubInstr = MRI.getVRegDef(SubReg);
66
if (!SubInstr || SubInstr->getOpcode() != TargetOpcode::G_FSUB)
67
return false;
68
69
return true;
70
}
71
void applySPIRVDistance(MachineInstr &MI, MachineRegisterInfo &MRI,
72
MachineIRBuilder &B) {
73
74
// Extract the operands for X and Y from the match criteria.
75
Register SubDestReg = MI.getOperand(2).getReg();
76
MachineInstr *SubInstr = MRI.getVRegDef(SubDestReg);
77
Register SubOperand1 = SubInstr->getOperand(1).getReg();
78
Register SubOperand2 = SubInstr->getOperand(2).getReg();
79
80
// Remove the original `spv_length` instruction.
81
82
Register ResultReg = MI.getOperand(0).getReg();
83
DebugLoc DL = MI.getDebugLoc();
84
MachineBasicBlock &MBB = *MI.getParent();
85
MachineBasicBlock::iterator InsertPt = MI.getIterator();
86
87
// Build the `spv_distance` intrinsic.
88
MachineInstrBuilder NewInstr =
89
BuildMI(MBB, InsertPt, DL, B.getTII().get(TargetOpcode::G_INTRINSIC));
90
NewInstr
91
.addDef(ResultReg) // Result register
92
.addIntrinsicID(Intrinsic::spv_distance) // Intrinsic ID
93
.addUse(SubOperand1) // Operand X
94
.addUse(SubOperand2); // Operand Y
95
96
SPIRVGlobalRegistry *GR =
97
MI.getMF()->getSubtarget<SPIRVSubtarget>().getSPIRVGlobalRegistry();
98
auto RemoveAllUses = [&](Register Reg) {
99
SmallVector<MachineInstr *, 4> UsesToErase(
100
llvm::make_pointer_range(MRI.use_instructions(Reg)));
101
102
// calling eraseFromParent to early invalidates the iterator.
103
for (auto *MIToErase : UsesToErase) {
104
GR->invalidateMachineInstr(MIToErase);
105
MIToErase->eraseFromParent();
106
}
107
};
108
RemoveAllUses(SubDestReg); // remove all uses of FSUB Result
109
GR->invalidateMachineInstr(SubInstr);
110
SubInstr->eraseFromParent(); // remove FSUB instruction
111
}
112
113
class SPIRVPreLegalizerCombinerImpl : public Combiner {
114
protected:
115
const CombinerHelper Helper;
116
const SPIRVPreLegalizerCombinerImplRuleConfig &RuleConfig;
117
const SPIRVSubtarget &STI;
118
119
public:
120
SPIRVPreLegalizerCombinerImpl(
121
MachineFunction &MF, CombinerInfo &CInfo, const TargetPassConfig *TPC,
122
GISelValueTracking &VT, GISelCSEInfo *CSEInfo,
123
const SPIRVPreLegalizerCombinerImplRuleConfig &RuleConfig,
124
const SPIRVSubtarget &STI, MachineDominatorTree *MDT,
125
const LegalizerInfo *LI);
126
127
static const char *getName() { return "SPIRVPreLegalizerCombiner"; }
128
129
bool tryCombineAll(MachineInstr &I) const override;
130
131
bool tryCombineAllImpl(MachineInstr &I) const;
132
133
private:
134
#define GET_GICOMBINER_CLASS_MEMBERS
135
#include "SPIRVGenPreLegalizeGICombiner.inc"
136
#undef GET_GICOMBINER_CLASS_MEMBERS
137
};
138
139
#define GET_GICOMBINER_IMPL
140
#include "SPIRVGenPreLegalizeGICombiner.inc"
141
#undef GET_GICOMBINER_IMPL
142
143
SPIRVPreLegalizerCombinerImpl::SPIRVPreLegalizerCombinerImpl(
144
MachineFunction &MF, CombinerInfo &CInfo, const TargetPassConfig *TPC,
145
GISelValueTracking &VT, GISelCSEInfo *CSEInfo,
146
const SPIRVPreLegalizerCombinerImplRuleConfig &RuleConfig,
147
const SPIRVSubtarget &STI, MachineDominatorTree *MDT,
148
const LegalizerInfo *LI)
149
: Combiner(MF, CInfo, TPC, &VT, CSEInfo),
150
Helper(Observer, B, /*IsPreLegalize*/ true, &VT, MDT, LI),
151
RuleConfig(RuleConfig), STI(STI),
152
#define GET_GICOMBINER_CONSTRUCTOR_INITS
153
#include "SPIRVGenPreLegalizeGICombiner.inc"
154
#undef GET_GICOMBINER_CONSTRUCTOR_INITS
155
{
156
}
157
158
bool SPIRVPreLegalizerCombinerImpl::tryCombineAll(MachineInstr &MI) const {
159
return tryCombineAllImpl(MI);
160
}
161
162
// Pass boilerplate
163
// ================
164
165
class SPIRVPreLegalizerCombiner : public MachineFunctionPass {
166
public:
167
static char ID;
168
169
SPIRVPreLegalizerCombiner();
170
171
StringRef getPassName() const override { return "SPIRVPreLegalizerCombiner"; }
172
173
bool runOnMachineFunction(MachineFunction &MF) override;
174
175
void getAnalysisUsage(AnalysisUsage &AU) const override;
176
177
private:
178
SPIRVPreLegalizerCombinerImplRuleConfig RuleConfig;
179
};
180
181
} // end anonymous namespace
182
183
void SPIRVPreLegalizerCombiner::getAnalysisUsage(AnalysisUsage &AU) const {
184
AU.addRequired<TargetPassConfig>();
185
AU.setPreservesCFG();
186
getSelectionDAGFallbackAnalysisUsage(AU);
187
AU.addRequired<GISelValueTrackingAnalysisLegacy>();
188
AU.addPreserved<GISelValueTrackingAnalysisLegacy>();
189
AU.addRequired<MachineDominatorTreeWrapperPass>();
190
AU.addPreserved<MachineDominatorTreeWrapperPass>();
191
MachineFunctionPass::getAnalysisUsage(AU);
192
}
193
194
SPIRVPreLegalizerCombiner::SPIRVPreLegalizerCombiner()
195
: MachineFunctionPass(ID) {
196
if (!RuleConfig.parseCommandLineOption())
197
report_fatal_error("Invalid rule identifier");
198
}
199
200
bool SPIRVPreLegalizerCombiner::runOnMachineFunction(MachineFunction &MF) {
201
if (MF.getProperties().hasFailedISel())
202
return false;
203
auto &TPC = getAnalysis<TargetPassConfig>();
204
205
const SPIRVSubtarget &ST = MF.getSubtarget<SPIRVSubtarget>();
206
const auto *LI = ST.getLegalizerInfo();
207
208
const Function &F = MF.getFunction();
209
bool EnableOpt =
210
MF.getTarget().getOptLevel() != CodeGenOptLevel::None && !skipFunction(F);
211
GISelValueTracking *VT =
212
&getAnalysis<GISelValueTrackingAnalysisLegacy>().get(MF);
213
MachineDominatorTree *MDT =
214
&getAnalysis<MachineDominatorTreeWrapperPass>().getDomTree();
215
CombinerInfo CInfo(/*AllowIllegalOps*/ true, /*ShouldLegalizeIllegal*/ false,
216
/*LegalizerInfo*/ nullptr, EnableOpt, F.hasOptSize(),
217
F.hasMinSize());
218
// Disable fixed-point iteration to reduce compile-time
219
CInfo.MaxIterations = 1;
220
CInfo.ObserverLvl = CombinerInfo::ObserverLevel::SinglePass;
221
// This is the first Combiner, so the input IR might contain dead
222
// instructions.
223
CInfo.EnableFullDCE = false;
224
SPIRVPreLegalizerCombinerImpl Impl(MF, CInfo, &TPC, *VT, /*CSEInfo*/ nullptr,
225
RuleConfig, ST, MDT, LI);
226
return Impl.combineMachineInstrs();
227
}
228
229
char SPIRVPreLegalizerCombiner::ID = 0;
230
INITIALIZE_PASS_BEGIN(SPIRVPreLegalizerCombiner, DEBUG_TYPE,
231
"Combine SPIRV machine instrs before legalization", false,
232
false)
233
INITIALIZE_PASS_DEPENDENCY(TargetPassConfig)
234
INITIALIZE_PASS_DEPENDENCY(GISelValueTrackingAnalysisLegacy)
235
INITIALIZE_PASS_END(SPIRVPreLegalizerCombiner, DEBUG_TYPE,
236
"Combine SPIRV machine instrs before legalization", false,
237
false)
238
239
namespace llvm {
240
FunctionPass *createSPIRVPreLegalizerCombiner() {
241
return new SPIRVPreLegalizerCombiner();
242
}
243
} // end namespace llvm
244
245