1 //===-- R600TextureIntrinsicsReplacer.cpp ---------------------------------===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
11 /// This pass translates tgsi-like texture intrinsics into R600 texture
12 /// closer to hardware intrinsics.
13 //===----------------------------------------------------------------------===//
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"
26 class R600TextureIntrinsicsReplacer :
27 public FunctionPass, public InstVisitor<R600TextureIntrinsicsReplacer> {
35 FunctionType *TexSign;
36 FunctionType *TexQSign;
38 void getAdjustmentFromTextureTarget(unsigned TextureType, bool hasLOD,
39 unsigned SrcSelect[4], unsigned CT[4],
40 bool &useShadowVariant) {
52 TEXTURE_SHADOW1D_ARRAY,
53 TEXTURE_SHADOW2D_ARRAY,
56 TEXTURE_2D_ARRAY_MSAA,
58 TEXTURE_SHADOWCUBE_ARRAY
61 switch (TextureType) {
63 useShadowVariant = false;
70 case TEXTURE_1D_ARRAY:
71 case TEXTURE_2D_ARRAY:
72 case TEXTURE_CUBE_ARRAY:
74 case TEXTURE_2D_ARRAY_MSAA:
75 useShadowVariant = false;
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;
87 llvm_unreachable("Unknow Texture Type");
90 if (TextureType == TEXTURE_RECT ||
91 TextureType == TEXTURE_SHADOWRECT) {
96 if (TextureType == TEXTURE_CUBE_ARRAY ||
97 TextureType == TEXTURE_SHADOWCUBE_ARRAY) {
101 if (TextureType == TEXTURE_1D_ARRAY ||
102 TextureType == TEXTURE_SHADOW1D_ARRAY) {
103 if (hasLOD && useShadowVariant) {
109 } else if (TextureType == TEXTURE_2D_ARRAY ||
110 TextureType == TEXTURE_SHADOW2D_ARRAY) {
114 if ((TextureType == TEXTURE_SHADOW1D ||
115 TextureType == TEXTURE_SHADOW2D ||
116 TextureType == TEXTURE_SHADOWRECT ||
117 TextureType == TEXTURE_SHADOW1D_ARRAY) &&
118 !(hasLOD && useShadowVariant)) {
123 void ReplaceCallInst(CallInst &I, FunctionType *FT, const char *Name,
124 unsigned SrcSelect[4], Value *Offset[3], Value *Resource,
125 Value *Sampler, unsigned CT[4], Value *Coord) {
126 IRBuilder<> Builder(&I);
128 ConstantInt::get(Int32Type, SrcSelect[0]),
129 ConstantInt::get(Int32Type, SrcSelect[1]),
130 ConstantInt::get(Int32Type, SrcSelect[2]),
131 ConstantInt::get(Int32Type, SrcSelect[3])
133 Value *SwizzleMask = ConstantVector::get(Mask);
134 Value *SwizzledCoord =
135 Builder.CreateShuffleVector(Coord, Coord, SwizzleMask);
144 ConstantInt::get(Int32Type, CT[0]),
145 ConstantInt::get(Int32Type, CT[1]),
146 ConstantInt::get(Int32Type, CT[2]),
147 ConstantInt::get(Int32Type, CT[3])
150 Function *F = Mod->getFunction(Name);
152 F = Function::Create(FT, GlobalValue::ExternalLinkage, Name, Mod);
153 F->addFnAttr(Attribute::ReadNone);
155 I.replaceAllUsesWith(Builder.CreateCall(F, Args));
159 void ReplaceTexIntrinsic(CallInst &I, bool hasLOD, FunctionType *FT,
160 const char *VanillaInt,
161 const char *ShadowInt) {
162 Value *Coord = I.getArgOperand(0);
163 Value *ResourceId = I.getArgOperand(1);
164 Value *SamplerId = I.getArgOperand(2);
166 unsigned TextureType =
167 dyn_cast<ConstantInt>(I.getArgOperand(3))->getZExtValue();
169 unsigned SrcSelect[4] = { 0, 1, 2, 3 };
170 unsigned CT[4] = {1, 1, 1, 1};
172 ConstantInt::get(Int32Type, 0),
173 ConstantInt::get(Int32Type, 0),
174 ConstantInt::get(Int32Type, 0)
176 bool useShadowVariant;
178 getAdjustmentFromTextureTarget(TextureType, hasLOD, SrcSelect, CT,
181 ReplaceCallInst(I, FT, useShadowVariant?ShadowInt:VanillaInt, SrcSelect,
182 Offset, ResourceId, SamplerId, CT, Coord);
185 void ReplaceTXF(CallInst &I) {
186 Value *Coord = I.getArgOperand(0);
187 Value *ResourceId = I.getArgOperand(4);
188 Value *SamplerId = I.getArgOperand(5);
190 unsigned TextureType =
191 dyn_cast<ConstantInt>(I.getArgOperand(6))->getZExtValue();
193 unsigned SrcSelect[4] = { 0, 1, 2, 3 };
194 unsigned CT[4] = {1, 1, 1, 1};
200 bool useShadowVariant;
202 getAdjustmentFromTextureTarget(TextureType, false, SrcSelect, CT,
205 ReplaceCallInst(I, TexQSign, "llvm.R600.txf", SrcSelect,
206 Offset, ResourceId, SamplerId, CT, Coord);
210 R600TextureIntrinsicsReplacer():
214 virtual bool doInitialization(Module &M) {
215 LLVMContext &Ctx = M.getContext();
217 FloatType = Type::getFloatTy(Ctx);
218 Int32Type = Type::getInt32Ty(Ctx);
219 V4f32Type = VectorType::get(FloatType, 4);
220 V4i32Type = VectorType::get(Int32Type, 4);
233 TexSign = FunctionType::get(V4f32Type, ArgsType, /*isVarArg=*/false);
234 Type *ArgsQType[] = {
246 TexQSign = FunctionType::get(V4f32Type, ArgsQType, /*isVarArg=*/false);
250 virtual bool runOnFunction(Function &F) {
255 virtual const char *getPassName() const {
256 return "R600 Texture Intrinsics Replacer";
259 void getAnalysisUsage(AnalysisUsage &AU) const {
262 void visitCallInst(CallInst &I) {
263 if (!I.getCalledFunction()) {
266 StringRef Name = I.getCalledFunction()->getName();
267 if (Name == "llvm.AMDGPU.tex") {
268 ReplaceTexIntrinsic(I, false, TexSign, "llvm.R600.tex", "llvm.R600.texc");
271 if (Name == "llvm.AMDGPU.txl") {
272 ReplaceTexIntrinsic(I, true, TexSign, "llvm.R600.txl", "llvm.R600.txlc");
275 if (Name == "llvm.AMDGPU.txb") {
276 ReplaceTexIntrinsic(I, true, TexSign, "llvm.R600.txb", "llvm.R600.txbc");
279 if (Name == "llvm.AMDGPU.txf") {
283 if (Name == "llvm.AMDGPU.txq") {
284 ReplaceTexIntrinsic(I, false, TexQSign, "llvm.R600.txq", "llvm.R600.txq");
287 if (Name == "llvm.AMDGPU.ddx") {
288 ReplaceTexIntrinsic(I, false, TexSign, "llvm.R600.ddx", "llvm.R600.ddx");
291 if (Name == "llvm.AMDGPU.ddy") {
292 ReplaceTexIntrinsic(I, false, TexSign, "llvm.R600.ddy", "llvm.R600.ddy");
299 char R600TextureIntrinsicsReplacer::ID = 0;
303 FunctionPass *llvm::createR600TextureIntrinsicsReplacer() {
304 return new R600TextureIntrinsicsReplacer();