1 //===-- NVPTXReplaceImageHandles.cpp - Replace image handles for Fermi ----===//
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
7 //===----------------------------------------------------------------------===//
9 // On Fermi, image handles are not supported. To work around this, we traverse
10 // the machine code and replace image handles with concrete symbols. For this
11 // to work reliably, inlining of all function call must be performed.
13 //===----------------------------------------------------------------------===//
16 #include "NVPTXMachineFunctionInfo.h"
17 #include "NVPTXSubtarget.h"
18 #include "NVPTXTargetMachine.h"
19 #include "MCTargetDesc/NVPTXBaseInfo.h"
20 #include "llvm/ADT/DenseSet.h"
21 #include "llvm/CodeGen/MachineFunction.h"
22 #include "llvm/CodeGen/MachineFunctionPass.h"
23 #include "llvm/CodeGen/MachineRegisterInfo.h"
24 #include "llvm/Support/raw_ostream.h"
29 class NVPTXReplaceImageHandles
: public MachineFunctionPass
{
32 DenseSet
<MachineInstr
*> InstrsToRemove
;
35 NVPTXReplaceImageHandles();
37 bool runOnMachineFunction(MachineFunction
&MF
) override
;
39 StringRef
getPassName() const override
{
40 return "NVPTX Replace Image Handles";
43 bool processInstr(MachineInstr
&MI
);
44 void replaceImageHandle(MachineOperand
&Op
, MachineFunction
&MF
);
45 bool findIndexForHandle(MachineOperand
&Op
, MachineFunction
&MF
,
50 char NVPTXReplaceImageHandles::ID
= 0;
52 NVPTXReplaceImageHandles::NVPTXReplaceImageHandles()
53 : MachineFunctionPass(ID
) {}
55 bool NVPTXReplaceImageHandles::runOnMachineFunction(MachineFunction
&MF
) {
57 InstrsToRemove
.clear();
59 for (MachineFunction::iterator BI
= MF
.begin(), BE
= MF
.end(); BI
!= BE
;
61 for (MachineBasicBlock::iterator I
= (*BI
).begin(), E
= (*BI
).end();
63 MachineInstr
&MI
= *I
;
64 Changed
|= processInstr(MI
);
68 // Now clean up any handle-access instructions
69 // This is needed in debug mode when code cleanup passes are not executed,
70 // but we need the handle access to be eliminated because they are not
71 // valid instructions when image handles are disabled.
72 for (DenseSet
<MachineInstr
*>::iterator I
= InstrsToRemove
.begin(),
73 E
= InstrsToRemove
.end(); I
!= E
; ++I
) {
74 (*I
)->eraseFromParent();
79 bool NVPTXReplaceImageHandles::processInstr(MachineInstr
&MI
) {
80 MachineFunction
&MF
= *MI
.getParent()->getParent();
81 const MCInstrDesc
&MCID
= MI
.getDesc();
83 if (MCID
.TSFlags
& NVPTXII::IsTexFlag
) {
84 // This is a texture fetch, so operand 4 is a texref and operand 5 is
86 MachineOperand
&TexHandle
= MI
.getOperand(4);
87 replaceImageHandle(TexHandle
, MF
);
89 if (!(MCID
.TSFlags
& NVPTXII::IsTexModeUnifiedFlag
)) {
90 MachineOperand
&SampHandle
= MI
.getOperand(5);
91 replaceImageHandle(SampHandle
, MF
);
95 } else if (MCID
.TSFlags
& NVPTXII::IsSuldMask
) {
97 1 << (((MCID
.TSFlags
& NVPTXII::IsSuldMask
) >> NVPTXII::IsSuldShift
) - 1);
99 // For a surface load of vector size N, the Nth operand will be the surfref
100 MachineOperand
&SurfHandle
= MI
.getOperand(VecSize
);
102 replaceImageHandle(SurfHandle
, MF
);
105 } else if (MCID
.TSFlags
& NVPTXII::IsSustFlag
) {
106 // This is a surface store, so operand 0 is a surfref
107 MachineOperand
&SurfHandle
= MI
.getOperand(0);
109 replaceImageHandle(SurfHandle
, MF
);
112 } else if (MCID
.TSFlags
& NVPTXII::IsSurfTexQueryFlag
) {
113 // This is a query, so operand 1 is a surfref/texref
114 MachineOperand
&Handle
= MI
.getOperand(1);
116 replaceImageHandle(Handle
, MF
);
124 void NVPTXReplaceImageHandles::
125 replaceImageHandle(MachineOperand
&Op
, MachineFunction
&MF
) {
127 if (findIndexForHandle(Op
, MF
, Idx
)) {
128 Op
.ChangeToImmediate(Idx
);
132 bool NVPTXReplaceImageHandles::
133 findIndexForHandle(MachineOperand
&Op
, MachineFunction
&MF
, unsigned &Idx
) {
134 const MachineRegisterInfo
&MRI
= MF
.getRegInfo();
135 NVPTXMachineFunctionInfo
*MFI
= MF
.getInfo
<NVPTXMachineFunctionInfo
>();
137 assert(Op
.isReg() && "Handle is not in a reg?");
139 // Which instruction defines the handle?
140 MachineInstr
&TexHandleDef
= *MRI
.getVRegDef(Op
.getReg());
142 switch (TexHandleDef
.getOpcode()) {
143 case NVPTX::LD_i64_avar
: {
144 // The handle is a parameter value being loaded, replace with the
146 const NVPTXTargetMachine
&TM
=
147 static_cast<const NVPTXTargetMachine
&>(MF
.getTarget());
148 if (TM
.getDrvInterface() == NVPTX::CUDA
) {
149 // For CUDA, we preserve the param loads coming from function arguments
153 assert(TexHandleDef
.getOperand(6).isSymbol() && "Load is not a symbol!");
154 StringRef Sym
= TexHandleDef
.getOperand(6).getSymbolName();
155 std::string ParamBaseName
= MF
.getName();
156 ParamBaseName
+= "_param_";
157 assert(Sym
.startswith(ParamBaseName
) && "Invalid symbol reference");
158 unsigned Param
= atoi(Sym
.data()+ParamBaseName
.size());
160 raw_string_ostream
NewSymStr(NewSym
);
161 NewSymStr
<< MF
.getName() << "_param_" << Param
;
163 InstrsToRemove
.insert(&TexHandleDef
);
164 Idx
= MFI
->getImageHandleSymbolIndex(NewSymStr
.str().c_str());
167 case NVPTX::texsurf_handles
: {
168 // The handle is a global variable, replace with the global variable name
169 assert(TexHandleDef
.getOperand(1).isGlobal() && "Load is not a global!");
170 const GlobalValue
*GV
= TexHandleDef
.getOperand(1).getGlobal();
171 assert(GV
->hasName() && "Global sampler must be named!");
172 InstrsToRemove
.insert(&TexHandleDef
);
173 Idx
= MFI
->getImageHandleSymbolIndex(GV
->getName().data());
176 case NVPTX::nvvm_move_i64
:
177 case TargetOpcode::COPY
: {
178 bool Res
= findIndexForHandle(TexHandleDef
.getOperand(1), MF
, Idx
);
180 InstrsToRemove
.insert(&TexHandleDef
);
185 llvm_unreachable("Unknown instruction operating on handle");
189 MachineFunctionPass
*llvm::createNVPTXReplaceImageHandlesPass() {
190 return new NVPTXReplaceImageHandles();