1 //===-- SPIRVPostLegalizer.cpp - ammend info after legalization -*- C++ -*-===//
3 // which may appear after the legalizer pass
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
9 //===----------------------------------------------------------------------===//
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.
15 //===----------------------------------------------------------------------===//
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"
28 #define DEBUG_TYPE "spirv-postlegalizer"
33 class SPIRVPostLegalizer
: public MachineFunctionPass
{
36 SPIRVPostLegalizer() : MachineFunctionPass(ID
) {
37 initializeSPIRVPostLegalizerPass(*PassRegistry::getPassRegistry());
39 bool runOnMachineFunction(MachineFunction
&MF
) override
;
43 // Defined in SPIRVLegalizerInfo.cpp.
44 extern bool isTypeFoldingSupported(unsigned Opcode
);
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
);
56 static bool isMetaInstrGET(unsigned Opcode
) {
57 return Opcode
== SPIRV::GET_ID
|| Opcode
== SPIRV::GET_fID
||
58 Opcode
== SPIRV::GET_pID32
|| Opcode
== SPIRV::GET_pID64
||
59 Opcode
== SPIRV::GET_vID
|| Opcode
== SPIRV::GET_vfID
||
60 Opcode
== SPIRV::GET_vpID32
|| Opcode
== SPIRV::GET_vpID64
;
63 static bool mayBeInserted(unsigned Opcode
) {
65 case TargetOpcode::G_SMAX
:
66 case TargetOpcode::G_UMAX
:
67 case TargetOpcode::G_SMIN
:
68 case TargetOpcode::G_UMIN
:
69 case TargetOpcode::G_FMINNUM
:
70 case TargetOpcode::G_FMINIMUM
:
71 case TargetOpcode::G_FMAXNUM
:
72 case TargetOpcode::G_FMAXIMUM
:
75 return isTypeFoldingSupported(Opcode
);
79 static void processNewInstrs(MachineFunction
&MF
, SPIRVGlobalRegistry
*GR
,
80 MachineIRBuilder MIB
) {
81 MachineRegisterInfo
&MRI
= MF
.getRegInfo();
83 for (MachineBasicBlock
&MBB
: MF
) {
84 for (MachineInstr
&I
: MBB
) {
85 const unsigned Opcode
= I
.getOpcode();
86 if (Opcode
== TargetOpcode::G_UNMERGE_VALUES
) {
87 unsigned ArgI
= I
.getNumOperands() - 1;
88 Register SrcReg
= I
.getOperand(ArgI
).isReg()
89 ? I
.getOperand(ArgI
).getReg()
92 SrcReg
.isValid() ? GR
->getSPIRVTypeForVReg(SrcReg
) : nullptr;
93 if (!DefType
|| DefType
->getOpcode() != SPIRV::OpTypeVector
)
95 "cannot select G_UNMERGE_VALUES with a non-vector argument");
96 SPIRVType
*ScalarType
=
97 GR
->getSPIRVTypeForVReg(DefType
->getOperand(1).getReg());
98 for (unsigned i
= 0; i
< I
.getNumDefs(); ++i
) {
99 Register ResVReg
= I
.getOperand(i
).getReg();
100 SPIRVType
*ResType
= GR
->getSPIRVTypeForVReg(ResVReg
);
102 // There was no "assign type" actions, let's fix this now
103 ResType
= ScalarType
;
104 MRI
.setRegClass(ResVReg
, &SPIRV::IDRegClass
);
106 LLT::scalar(GR
->getScalarOrVectorBitWidth(ResType
)));
107 GR
->assignSPIRVTypeToVReg(ResType
, ResVReg
, *GR
->CurMF
);
110 } else if (mayBeInserted(Opcode
) && I
.getNumDefs() == 1 &&
111 I
.getNumOperands() > 1 && I
.getOperand(1).isReg()) {
112 // Legalizer may have added a new instructions and introduced new
113 // registers, we must decorate them as if they were introduced in a
115 Register ResVReg
= I
.getOperand(0).getReg();
116 SPIRVType
*ResVType
= GR
->getSPIRVTypeForVReg(ResVReg
);
117 // Check if the register defined by the instruction is newly generated
118 // or already processed
120 // Set type of the defined register
121 ResVType
= GR
->getSPIRVTypeForVReg(I
.getOperand(1).getReg());
122 // Check if we have type defined for operands of the new instruction
126 MRI
.setRegClass(ResVReg
, &SPIRV::IDRegClass
);
128 LLT::scalar(GR
->getScalarOrVectorBitWidth(ResVType
)));
129 GR
->assignSPIRVTypeToVReg(ResVType
, ResVReg
, *GR
->CurMF
);
131 // If this is a simple operation that is to be reduced by TableGen
132 // definition we must apply some of pre-legalizer rules here
133 if (isTypeFoldingSupported(Opcode
)) {
134 // Check if the instruction newly generated or already processed
135 MachineInstr
*NextMI
= I
.getNextNode();
136 if (NextMI
&& isMetaInstrGET(NextMI
->getOpcode()))
138 // Restore usual instructions pattern for the newly inserted
140 MRI
.setRegClass(ResVReg
, MRI
.getType(ResVReg
).isVector()
142 : &SPIRV::ANYIDRegClass
);
143 MRI
.setType(ResVReg
, LLT::scalar(32));
144 insertAssignInstr(ResVReg
, nullptr, ResVType
, GR
, MIB
, MRI
);
145 processInstr(I
, MIB
, MRI
, GR
);
152 bool SPIRVPostLegalizer::runOnMachineFunction(MachineFunction
&MF
) {
153 // Initialize the type registry.
154 const SPIRVSubtarget
&ST
= MF
.getSubtarget
<SPIRVSubtarget
>();
155 SPIRVGlobalRegistry
*GR
= ST
.getSPIRVGlobalRegistry();
156 GR
->setCurrentFunc(MF
);
157 MachineIRBuilder
MIB(MF
);
159 processNewInstrs(MF
, GR
, MIB
);
164 INITIALIZE_PASS(SPIRVPostLegalizer
, DEBUG_TYPE
, "SPIRV post legalizer", false,
167 char SPIRVPostLegalizer::ID
= 0;
169 FunctionPass
*llvm::createSPIRVPostLegalizerPass() {
170 return new SPIRVPostLegalizer();