LLVM API Documentation

 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
R600TextureIntrinsicsReplacer.cpp
Go to the documentation of this file.
1 //===-- R600TextureIntrinsicsReplacer.cpp ---------------------------------===//
2 //
3 // The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 /// \file
11 /// This pass translates tgsi-like texture intrinsics into R600 texture
12 /// closer to hardware intrinsics.
13 //===----------------------------------------------------------------------===//
14 
15 #include "AMDGPU.h"
16 #include "llvm/ADT/Statistic.h"
17 #include "llvm/Analysis/Passes.h"
18 #include "llvm/IR/Function.h"
19 #include "llvm/IR/GlobalValue.h"
20 #include "llvm/IR/IRBuilder.h"
21 #include "llvm/InstVisitor.h"
22 
23 using namespace llvm;
24 
25 namespace {
26 class R600TextureIntrinsicsReplacer :
27  public FunctionPass, public InstVisitor<R600TextureIntrinsicsReplacer> {
28  static char ID;
29 
30  Module *Mod;
31  Type *FloatType;
32  Type *Int32Type;
33  Type *V4f32Type;
34  Type *V4i32Type;
35  FunctionType *TexSign;
36  FunctionType *TexQSign;
37 
38  void getAdjustmentFromTextureTarget(unsigned TextureType, bool hasLOD,
39  unsigned SrcSelect[4], unsigned CT[4],
40  bool &useShadowVariant) {
41  enum TextureTypes {
42  TEXTURE_1D = 1,
43  TEXTURE_2D,
44  TEXTURE_3D,
45  TEXTURE_CUBE,
46  TEXTURE_RECT,
47  TEXTURE_SHADOW1D,
48  TEXTURE_SHADOW2D,
49  TEXTURE_SHADOWRECT,
50  TEXTURE_1D_ARRAY,
51  TEXTURE_2D_ARRAY,
52  TEXTURE_SHADOW1D_ARRAY,
53  TEXTURE_SHADOW2D_ARRAY,
54  TEXTURE_SHADOWCUBE,
55  TEXTURE_2D_MSAA,
56  TEXTURE_2D_ARRAY_MSAA,
57  TEXTURE_CUBE_ARRAY,
58  TEXTURE_SHADOWCUBE_ARRAY
59  };
60 
61  switch (TextureType) {
62  case 0:
63  useShadowVariant = false;
64  return;
65  case TEXTURE_RECT:
66  case TEXTURE_1D:
67  case TEXTURE_2D:
68  case TEXTURE_3D:
69  case TEXTURE_CUBE:
70  case TEXTURE_1D_ARRAY:
71  case TEXTURE_2D_ARRAY:
72  case TEXTURE_CUBE_ARRAY:
73  case TEXTURE_2D_MSAA:
74  case TEXTURE_2D_ARRAY_MSAA:
75  useShadowVariant = false;
76  break;
77  case TEXTURE_SHADOW1D:
78  case TEXTURE_SHADOW2D:
79  case TEXTURE_SHADOWRECT:
80  case TEXTURE_SHADOW1D_ARRAY:
81  case TEXTURE_SHADOW2D_ARRAY:
82  case TEXTURE_SHADOWCUBE:
83  case TEXTURE_SHADOWCUBE_ARRAY:
84  useShadowVariant = true;
85  break;
86  default:
87  llvm_unreachable("Unknow Texture Type");
88  }
89 
90  if (TextureType == TEXTURE_RECT ||
91  TextureType == TEXTURE_SHADOWRECT) {
92  CT[0] = 0;
93  CT[1] = 0;
94  }
95 
96  if (TextureType == TEXTURE_CUBE_ARRAY ||
97  TextureType == TEXTURE_SHADOWCUBE_ARRAY)
98  CT[2] = 0;
99 
100  if (TextureType == TEXTURE_1D_ARRAY ||
101  TextureType == TEXTURE_SHADOW1D_ARRAY) {
102  if (hasLOD && useShadowVariant) {
103  CT[1] = 0;
104  } else {
105  CT[2] = 0;
106  SrcSelect[2] = 1;
107  }
108  } else if (TextureType == TEXTURE_2D_ARRAY ||
109  TextureType == TEXTURE_SHADOW2D_ARRAY) {
110  CT[2] = 0;
111  }
112 
113  if ((TextureType == TEXTURE_SHADOW1D ||
114  TextureType == TEXTURE_SHADOW2D ||
115  TextureType == TEXTURE_SHADOWRECT ||
116  TextureType == TEXTURE_SHADOW1D_ARRAY) &&
117  !(hasLOD && useShadowVariant))
118  SrcSelect[3] = 2;
119  }
120 
121  void ReplaceCallInst(CallInst &I, FunctionType *FT, const char *Name,
122  unsigned SrcSelect[4], Value *Offset[3], Value *Resource,
123  Value *Sampler, unsigned CT[4], Value *Coord) {
124  IRBuilder<> Builder(&I);
125  Constant *Mask[] = {
126  ConstantInt::get(Int32Type, SrcSelect[0]),
127  ConstantInt::get(Int32Type, SrcSelect[1]),
128  ConstantInt::get(Int32Type, SrcSelect[2]),
129  ConstantInt::get(Int32Type, SrcSelect[3])
130  };
131  Value *SwizzleMask = ConstantVector::get(Mask);
132  Value *SwizzledCoord =
133  Builder.CreateShuffleVector(Coord, Coord, SwizzleMask);
134 
135  Value *Args[] = {
136  SwizzledCoord,
137  Offset[0],
138  Offset[1],
139  Offset[2],
140  Resource,
141  Sampler,
142  ConstantInt::get(Int32Type, CT[0]),
143  ConstantInt::get(Int32Type, CT[1]),
144  ConstantInt::get(Int32Type, CT[2]),
145  ConstantInt::get(Int32Type, CT[3])
146  };
147 
148  Function *F = Mod->getFunction(Name);
149  if (!F) {
152  }
153  I.replaceAllUsesWith(Builder.CreateCall(F, Args));
154  I.eraseFromParent();
155  }
156 
157  void ReplaceTexIntrinsic(CallInst &I, bool hasLOD, FunctionType *FT,
158  const char *VanillaInt,
159  const char *ShadowInt) {
160  Value *Coord = I.getArgOperand(0);
161  Value *ResourceId = I.getArgOperand(1);
162  Value *SamplerId = I.getArgOperand(2);
163 
164  unsigned TextureType =
165  dyn_cast<ConstantInt>(I.getArgOperand(3))->getZExtValue();
166 
167  unsigned SrcSelect[4] = { 0, 1, 2, 3 };
168  unsigned CT[4] = {1, 1, 1, 1};
169  Value *Offset[3] = {
170  ConstantInt::get(Int32Type, 0),
171  ConstantInt::get(Int32Type, 0),
172  ConstantInt::get(Int32Type, 0)
173  };
174  bool useShadowVariant;
175 
176  getAdjustmentFromTextureTarget(TextureType, hasLOD, SrcSelect, CT,
177  useShadowVariant);
178 
179  ReplaceCallInst(I, FT, useShadowVariant?ShadowInt:VanillaInt, SrcSelect,
180  Offset, ResourceId, SamplerId, CT, Coord);
181  }
182 
183  void ReplaceTXF(CallInst &I) {
184  Value *Coord = I.getArgOperand(0);
185  Value *ResourceId = I.getArgOperand(4);
186  Value *SamplerId = I.getArgOperand(5);
187 
188  unsigned TextureType =
189  dyn_cast<ConstantInt>(I.getArgOperand(6))->getZExtValue();
190 
191  unsigned SrcSelect[4] = { 0, 1, 2, 3 };
192  unsigned CT[4] = {1, 1, 1, 1};
193  Value *Offset[3] = {
194  I.getArgOperand(1),
195  I.getArgOperand(2),
196  I.getArgOperand(3),
197  };
198  bool useShadowVariant;
199 
200  getAdjustmentFromTextureTarget(TextureType, false, SrcSelect, CT,
201  useShadowVariant);
202 
203  ReplaceCallInst(I, TexQSign, "llvm.R600.txf", SrcSelect,
204  Offset, ResourceId, SamplerId, CT, Coord);
205  }
206 
207 public:
208  R600TextureIntrinsicsReplacer():
209  FunctionPass(ID) {
210  }
211 
212  virtual bool doInitialization(Module &M) {
213  LLVMContext &Ctx = M.getContext();
214  Mod = &M;
215  FloatType = Type::getFloatTy(Ctx);
216  Int32Type = Type::getInt32Ty(Ctx);
217  V4f32Type = VectorType::get(FloatType, 4);
218  V4i32Type = VectorType::get(Int32Type, 4);
219  Type *ArgsType[] = {
220  V4f32Type,
221  Int32Type,
222  Int32Type,
223  Int32Type,
224  Int32Type,
225  Int32Type,
226  Int32Type,
227  Int32Type,
228  Int32Type,
229  Int32Type,
230  };
231  TexSign = FunctionType::get(V4f32Type, ArgsType, /*isVarArg=*/false);
232  Type *ArgsQType[] = {
233  V4i32Type,
234  Int32Type,
235  Int32Type,
236  Int32Type,
237  Int32Type,
238  Int32Type,
239  Int32Type,
240  Int32Type,
241  Int32Type,
242  Int32Type,
243  };
244  TexQSign = FunctionType::get(V4f32Type, ArgsQType, /*isVarArg=*/false);
245  return false;
246  }
247 
248  virtual bool runOnFunction(Function &F) {
249  visit(F);
250  return false;
251  }
252 
253  virtual const char *getPassName() const {
254  return "R600 Texture Intrinsics Replacer";
255  }
256 
257  void getAnalysisUsage(AnalysisUsage &AU) const {
258  }
259 
260  void visitCallInst(CallInst &I) {
261  if (!I.getCalledFunction())
262  return;
263 
264  StringRef Name = I.getCalledFunction()->getName();
265  if (Name == "llvm.AMDGPU.tex") {
266  ReplaceTexIntrinsic(I, false, TexSign, "llvm.R600.tex", "llvm.R600.texc");
267  return;
268  }
269  if (Name == "llvm.AMDGPU.txl") {
270  ReplaceTexIntrinsic(I, true, TexSign, "llvm.R600.txl", "llvm.R600.txlc");
271  return;
272  }
273  if (Name == "llvm.AMDGPU.txb") {
274  ReplaceTexIntrinsic(I, true, TexSign, "llvm.R600.txb", "llvm.R600.txbc");
275  return;
276  }
277  if (Name == "llvm.AMDGPU.txf") {
278  ReplaceTXF(I);
279  return;
280  }
281  if (Name == "llvm.AMDGPU.txq") {
282  ReplaceTexIntrinsic(I, false, TexQSign, "llvm.R600.txq", "llvm.R600.txq");
283  return;
284  }
285  if (Name == "llvm.AMDGPU.ddx") {
286  ReplaceTexIntrinsic(I, false, TexSign, "llvm.R600.ddx", "llvm.R600.ddx");
287  return;
288  }
289  if (Name == "llvm.AMDGPU.ddy") {
290  ReplaceTexIntrinsic(I, false, TexSign, "llvm.R600.ddy", "llvm.R600.ddy");
291  return;
292  }
293  }
294 
295 };
296 
298 
299 }
300 
302  return new R600TextureIntrinsicsReplacer();
303 }
Base class for instruction visitors.
Definition: InstVisitor.h:81
The main container class for the LLVM Intermediate Representation.
Definition: Module.h:112
enable_if_c<!is_simple_type< Y >::value, typename cast_retty< X, const Y >::ret_type >::type dyn_cast(const Y &Val)
Definition: Casting.h:266
Externally visible function.
Definition: GlobalValue.h:34
F(f)
StringRef getName() const
Definition: Value.cpp:167
FunctionPass * createR600TextureIntrinsicsReplacer()
static Type * getFloatTy(LLVMContext &C)
Definition: Type.cpp:230
#define llvm_unreachable(msg)
static Constant * get(ArrayRef< Constant * > V)
Definition: Constants.cpp:923
This provides a uniform API for creating instructions and inserting them into a basic block: either a...
Definition: IRBuilder.h:421
ID
LLVM Calling Convention Representation.
Definition: CallingConv.h:26
Function does not access memory.
Definition: Attributes.h:93
void addFnAttr(Attribute::AttrKind N)
Add function attributes to this function.
Definition: Function.h:176
static FunctionType * get(Type *Result, ArrayRef< Type * > Params, bool isVarArg)
Definition: Type.cpp:361
void replaceAllUsesWith(Value *V)
Definition: Value.cpp:303
LLVM Constant Representation.
Definition: Constant.h:41
Class for constant integers.
Definition: Constants.h:51
static Constant * get(Type *Ty, uint64_t V, bool isSigned=false)
Definition: Constants.cpp:492
Function * getCalledFunction() const
Value * getArgOperand(unsigned i) const
static IntegerType * getInt32Ty(LLVMContext &C)
Definition: Type.cpp:241
#define I(x, y, z)
Definition: MD5.cpp:54
LLVM Value Representation.
Definition: Value.h:66
static VectorType * get(Type *ElementType, unsigned NumElements)
Definition: Type.cpp:706
LLVMContext & getContext() const
Definition: Module.h:249
static Function * Create(FunctionType *Ty, LinkageTypes Linkage, const Twine &N="", Module *M=0)
Definition: Function.h:128