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/SPIRVPostLegalizer.cpp
35266 views
1
//===-- SPIRVPostLegalizer.cpp - ammend info after legalization -*- C++ -*-===//
2
//
3
// which may appear after the legalizer pass
4
//
5
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
6
// See https://llvm.org/LICENSE.txt for license information.
7
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
8
//
9
//===----------------------------------------------------------------------===//
10
//
11
// The pass partially apply pre-legalization logic to new instructions inserted
12
// as a result of legalization:
13
// - assigns SPIR-V types to registers for new instructions.
14
//
15
//===----------------------------------------------------------------------===//
16
17
#include "SPIRV.h"
18
#include "SPIRVSubtarget.h"
19
#include "SPIRVUtils.h"
20
#include "llvm/ADT/PostOrderIterator.h"
21
#include "llvm/Analysis/OptimizationRemarkEmitter.h"
22
#include "llvm/IR/Attributes.h"
23
#include "llvm/IR/Constants.h"
24
#include "llvm/IR/DebugInfoMetadata.h"
25
#include "llvm/IR/IntrinsicsSPIRV.h"
26
#include "llvm/Target/TargetIntrinsicInfo.h"
27
28
#define DEBUG_TYPE "spirv-postlegalizer"
29
30
using namespace llvm;
31
32
namespace {
33
class SPIRVPostLegalizer : public MachineFunctionPass {
34
public:
35
static char ID;
36
SPIRVPostLegalizer() : MachineFunctionPass(ID) {
37
initializeSPIRVPostLegalizerPass(*PassRegistry::getPassRegistry());
38
}
39
bool runOnMachineFunction(MachineFunction &MF) override;
40
};
41
} // namespace
42
43
// Defined in SPIRVLegalizerInfo.cpp.
44
extern bool isTypeFoldingSupported(unsigned Opcode);
45
46
namespace llvm {
47
// Defined in SPIRVPreLegalizer.cpp.
48
extern Register insertAssignInstr(Register Reg, Type *Ty, SPIRVType *SpirvTy,
49
SPIRVGlobalRegistry *GR,
50
MachineIRBuilder &MIB,
51
MachineRegisterInfo &MRI);
52
extern void processInstr(MachineInstr &MI, MachineIRBuilder &MIB,
53
MachineRegisterInfo &MRI, SPIRVGlobalRegistry *GR);
54
} // namespace llvm
55
56
static bool isMetaInstrGET(unsigned Opcode) {
57
return Opcode == SPIRV::GET_ID || Opcode == SPIRV::GET_ID64 ||
58
Opcode == SPIRV::GET_fID || Opcode == SPIRV::GET_fID64 ||
59
Opcode == SPIRV::GET_pID32 || Opcode == SPIRV::GET_pID64 ||
60
Opcode == SPIRV::GET_vID || Opcode == SPIRV::GET_vfID ||
61
Opcode == SPIRV::GET_vpID32 || Opcode == SPIRV::GET_vpID64;
62
}
63
64
static bool mayBeInserted(unsigned Opcode) {
65
switch (Opcode) {
66
case TargetOpcode::G_SMAX:
67
case TargetOpcode::G_UMAX:
68
case TargetOpcode::G_SMIN:
69
case TargetOpcode::G_UMIN:
70
case TargetOpcode::G_FMINNUM:
71
case TargetOpcode::G_FMINIMUM:
72
case TargetOpcode::G_FMAXNUM:
73
case TargetOpcode::G_FMAXIMUM:
74
return true;
75
default:
76
return isTypeFoldingSupported(Opcode);
77
}
78
}
79
80
static void processNewInstrs(MachineFunction &MF, SPIRVGlobalRegistry *GR,
81
MachineIRBuilder MIB) {
82
MachineRegisterInfo &MRI = MF.getRegInfo();
83
84
for (MachineBasicBlock &MBB : MF) {
85
for (MachineInstr &I : MBB) {
86
const unsigned Opcode = I.getOpcode();
87
if (Opcode == TargetOpcode::G_UNMERGE_VALUES) {
88
unsigned ArgI = I.getNumOperands() - 1;
89
Register SrcReg = I.getOperand(ArgI).isReg()
90
? I.getOperand(ArgI).getReg()
91
: Register(0);
92
SPIRVType *DefType =
93
SrcReg.isValid() ? GR->getSPIRVTypeForVReg(SrcReg) : nullptr;
94
if (!DefType || DefType->getOpcode() != SPIRV::OpTypeVector)
95
report_fatal_error(
96
"cannot select G_UNMERGE_VALUES with a non-vector argument");
97
SPIRVType *ScalarType =
98
GR->getSPIRVTypeForVReg(DefType->getOperand(1).getReg());
99
for (unsigned i = 0; i < I.getNumDefs(); ++i) {
100
Register ResVReg = I.getOperand(i).getReg();
101
SPIRVType *ResType = GR->getSPIRVTypeForVReg(ResVReg);
102
if (!ResType) {
103
// There was no "assign type" actions, let's fix this now
104
ResType = ScalarType;
105
MRI.setRegClass(ResVReg, &SPIRV::IDRegClass);
106
MRI.setType(ResVReg,
107
LLT::scalar(GR->getScalarOrVectorBitWidth(ResType)));
108
GR->assignSPIRVTypeToVReg(ResType, ResVReg, *GR->CurMF);
109
}
110
}
111
} else if (mayBeInserted(Opcode) && I.getNumDefs() == 1 &&
112
I.getNumOperands() > 1 && I.getOperand(1).isReg()) {
113
// Legalizer may have added a new instructions and introduced new
114
// registers, we must decorate them as if they were introduced in a
115
// non-automatic way
116
Register ResVReg = I.getOperand(0).getReg();
117
SPIRVType *ResVType = GR->getSPIRVTypeForVReg(ResVReg);
118
// Check if the register defined by the instruction is newly generated
119
// or already processed
120
if (!ResVType) {
121
// Set type of the defined register
122
ResVType = GR->getSPIRVTypeForVReg(I.getOperand(1).getReg());
123
// Check if we have type defined for operands of the new instruction
124
if (!ResVType)
125
continue;
126
// Set type & class
127
MRI.setRegClass(ResVReg, &SPIRV::IDRegClass);
128
MRI.setType(ResVReg,
129
LLT::scalar(GR->getScalarOrVectorBitWidth(ResVType)));
130
GR->assignSPIRVTypeToVReg(ResVType, ResVReg, *GR->CurMF);
131
}
132
// If this is a simple operation that is to be reduced by TableGen
133
// definition we must apply some of pre-legalizer rules here
134
if (isTypeFoldingSupported(Opcode)) {
135
// Check if the instruction newly generated or already processed
136
MachineInstr *NextMI = I.getNextNode();
137
if (NextMI && isMetaInstrGET(NextMI->getOpcode()))
138
continue;
139
// Restore usual instructions pattern for the newly inserted
140
// instruction
141
MRI.setRegClass(ResVReg, MRI.getType(ResVReg).isVector()
142
? &SPIRV::IDRegClass
143
: &SPIRV::ANYIDRegClass);
144
MRI.setType(ResVReg, LLT::scalar(32));
145
insertAssignInstr(ResVReg, nullptr, ResVType, GR, MIB, MRI);
146
processInstr(I, MIB, MRI, GR);
147
}
148
}
149
}
150
}
151
}
152
153
bool SPIRVPostLegalizer::runOnMachineFunction(MachineFunction &MF) {
154
// Initialize the type registry.
155
const SPIRVSubtarget &ST = MF.getSubtarget<SPIRVSubtarget>();
156
SPIRVGlobalRegistry *GR = ST.getSPIRVGlobalRegistry();
157
GR->setCurrentFunc(MF);
158
MachineIRBuilder MIB(MF);
159
160
processNewInstrs(MF, GR, MIB);
161
162
return true;
163
}
164
165
INITIALIZE_PASS(SPIRVPostLegalizer, DEBUG_TYPE, "SPIRV post legalizer", false,
166
false)
167
168
char SPIRVPostLegalizer::ID = 0;
169
170
FunctionPass *llvm::createSPIRVPostLegalizerPass() {
171
return new SPIRVPostLegalizer();
172
}
173
174