LLVM API Documentation
00001 //===-- R600TextureIntrinsicsReplacer.cpp ---------------------------------===// 00002 // 00003 // The LLVM Compiler Infrastructure 00004 // 00005 // This file is distributed under the University of Illinois Open Source 00006 // License. See LICENSE.TXT for details. 00007 // 00008 //===----------------------------------------------------------------------===// 00009 // 00010 /// \file 00011 /// This pass translates tgsi-like texture intrinsics into R600 texture 00012 /// closer to hardware intrinsics. 00013 //===----------------------------------------------------------------------===// 00014 00015 #include "AMDGPU.h" 00016 #include "llvm/ADT/Statistic.h" 00017 #include "llvm/Analysis/Passes.h" 00018 #include "llvm/IR/Function.h" 00019 #include "llvm/IR/GlobalValue.h" 00020 #include "llvm/IR/IRBuilder.h" 00021 #include "llvm/IR/InstVisitor.h" 00022 00023 using namespace llvm; 00024 00025 namespace { 00026 class R600TextureIntrinsicsReplacer : 00027 public FunctionPass, public InstVisitor<R600TextureIntrinsicsReplacer> { 00028 static char ID; 00029 00030 Module *Mod; 00031 Type *FloatType; 00032 Type *Int32Type; 00033 Type *V4f32Type; 00034 Type *V4i32Type; 00035 FunctionType *TexSign; 00036 FunctionType *TexQSign; 00037 00038 void getAdjustmentFromTextureTarget(unsigned TextureType, bool hasLOD, 00039 unsigned SrcSelect[4], unsigned CT[4], 00040 bool &useShadowVariant) { 00041 enum TextureTypes { 00042 TEXTURE_1D = 1, 00043 TEXTURE_2D, 00044 TEXTURE_3D, 00045 TEXTURE_CUBE, 00046 TEXTURE_RECT, 00047 TEXTURE_SHADOW1D, 00048 TEXTURE_SHADOW2D, 00049 TEXTURE_SHADOWRECT, 00050 TEXTURE_1D_ARRAY, 00051 TEXTURE_2D_ARRAY, 00052 TEXTURE_SHADOW1D_ARRAY, 00053 TEXTURE_SHADOW2D_ARRAY, 00054 TEXTURE_SHADOWCUBE, 00055 TEXTURE_2D_MSAA, 00056 TEXTURE_2D_ARRAY_MSAA, 00057 TEXTURE_CUBE_ARRAY, 00058 TEXTURE_SHADOWCUBE_ARRAY 00059 }; 00060 00061 switch (TextureType) { 00062 case 0: 00063 useShadowVariant = false; 00064 return; 00065 case TEXTURE_RECT: 00066 case TEXTURE_1D: 00067 case TEXTURE_2D: 00068 case TEXTURE_3D: 00069 case TEXTURE_CUBE: 00070 case TEXTURE_1D_ARRAY: 00071 case TEXTURE_2D_ARRAY: 00072 case TEXTURE_CUBE_ARRAY: 00073 case TEXTURE_2D_MSAA: 00074 case TEXTURE_2D_ARRAY_MSAA: 00075 useShadowVariant = false; 00076 break; 00077 case TEXTURE_SHADOW1D: 00078 case TEXTURE_SHADOW2D: 00079 case TEXTURE_SHADOWRECT: 00080 case TEXTURE_SHADOW1D_ARRAY: 00081 case TEXTURE_SHADOW2D_ARRAY: 00082 case TEXTURE_SHADOWCUBE: 00083 case TEXTURE_SHADOWCUBE_ARRAY: 00084 useShadowVariant = true; 00085 break; 00086 default: 00087 llvm_unreachable("Unknow Texture Type"); 00088 } 00089 00090 if (TextureType == TEXTURE_RECT || 00091 TextureType == TEXTURE_SHADOWRECT) { 00092 CT[0] = 0; 00093 CT[1] = 0; 00094 } 00095 00096 if (TextureType == TEXTURE_CUBE_ARRAY || 00097 TextureType == TEXTURE_SHADOWCUBE_ARRAY) 00098 CT[2] = 0; 00099 00100 if (TextureType == TEXTURE_1D_ARRAY || 00101 TextureType == TEXTURE_SHADOW1D_ARRAY) { 00102 if (hasLOD && useShadowVariant) { 00103 CT[1] = 0; 00104 } else { 00105 CT[2] = 0; 00106 SrcSelect[2] = 1; 00107 } 00108 } else if (TextureType == TEXTURE_2D_ARRAY || 00109 TextureType == TEXTURE_SHADOW2D_ARRAY) { 00110 CT[2] = 0; 00111 } 00112 00113 if ((TextureType == TEXTURE_SHADOW1D || 00114 TextureType == TEXTURE_SHADOW2D || 00115 TextureType == TEXTURE_SHADOWRECT || 00116 TextureType == TEXTURE_SHADOW1D_ARRAY) && 00117 !(hasLOD && useShadowVariant)) 00118 SrcSelect[3] = 2; 00119 } 00120 00121 void ReplaceCallInst(CallInst &I, FunctionType *FT, const char *Name, 00122 unsigned SrcSelect[4], Value *Offset[3], Value *Resource, 00123 Value *Sampler, unsigned CT[4], Value *Coord) { 00124 IRBuilder<> Builder(&I); 00125 Constant *Mask[] = { 00126 ConstantInt::get(Int32Type, SrcSelect[0]), 00127 ConstantInt::get(Int32Type, SrcSelect[1]), 00128 ConstantInt::get(Int32Type, SrcSelect[2]), 00129 ConstantInt::get(Int32Type, SrcSelect[3]) 00130 }; 00131 Value *SwizzleMask = ConstantVector::get(Mask); 00132 Value *SwizzledCoord = 00133 Builder.CreateShuffleVector(Coord, Coord, SwizzleMask); 00134 00135 Value *Args[] = { 00136 SwizzledCoord, 00137 Offset[0], 00138 Offset[1], 00139 Offset[2], 00140 Resource, 00141 Sampler, 00142 ConstantInt::get(Int32Type, CT[0]), 00143 ConstantInt::get(Int32Type, CT[1]), 00144 ConstantInt::get(Int32Type, CT[2]), 00145 ConstantInt::get(Int32Type, CT[3]) 00146 }; 00147 00148 Function *F = Mod->getFunction(Name); 00149 if (!F) { 00150 F = Function::Create(FT, GlobalValue::ExternalLinkage, Name, Mod); 00151 F->addFnAttr(Attribute::ReadNone); 00152 } 00153 I.replaceAllUsesWith(Builder.CreateCall(F, Args)); 00154 I.eraseFromParent(); 00155 } 00156 00157 void ReplaceTexIntrinsic(CallInst &I, bool hasLOD, FunctionType *FT, 00158 const char *VanillaInt, 00159 const char *ShadowInt) { 00160 Value *Coord = I.getArgOperand(0); 00161 Value *ResourceId = I.getArgOperand(1); 00162 Value *SamplerId = I.getArgOperand(2); 00163 00164 unsigned TextureType = 00165 dyn_cast<ConstantInt>(I.getArgOperand(3))->getZExtValue(); 00166 00167 unsigned SrcSelect[4] = { 0, 1, 2, 3 }; 00168 unsigned CT[4] = {1, 1, 1, 1}; 00169 Value *Offset[3] = { 00170 ConstantInt::get(Int32Type, 0), 00171 ConstantInt::get(Int32Type, 0), 00172 ConstantInt::get(Int32Type, 0) 00173 }; 00174 bool useShadowVariant; 00175 00176 getAdjustmentFromTextureTarget(TextureType, hasLOD, SrcSelect, CT, 00177 useShadowVariant); 00178 00179 ReplaceCallInst(I, FT, useShadowVariant?ShadowInt:VanillaInt, SrcSelect, 00180 Offset, ResourceId, SamplerId, CT, Coord); 00181 } 00182 00183 void ReplaceTXF(CallInst &I) { 00184 Value *Coord = I.getArgOperand(0); 00185 Value *ResourceId = I.getArgOperand(4); 00186 Value *SamplerId = I.getArgOperand(5); 00187 00188 unsigned TextureType = 00189 dyn_cast<ConstantInt>(I.getArgOperand(6))->getZExtValue(); 00190 00191 unsigned SrcSelect[4] = { 0, 1, 2, 3 }; 00192 unsigned CT[4] = {1, 1, 1, 1}; 00193 Value *Offset[3] = { 00194 I.getArgOperand(1), 00195 I.getArgOperand(2), 00196 I.getArgOperand(3), 00197 }; 00198 bool useShadowVariant; 00199 00200 getAdjustmentFromTextureTarget(TextureType, false, SrcSelect, CT, 00201 useShadowVariant); 00202 00203 ReplaceCallInst(I, TexQSign, "llvm.R600.txf", SrcSelect, 00204 Offset, ResourceId, SamplerId, CT, Coord); 00205 } 00206 00207 public: 00208 R600TextureIntrinsicsReplacer(): 00209 FunctionPass(ID) { 00210 } 00211 00212 bool doInitialization(Module &M) override { 00213 LLVMContext &Ctx = M.getContext(); 00214 Mod = &M; 00215 FloatType = Type::getFloatTy(Ctx); 00216 Int32Type = Type::getInt32Ty(Ctx); 00217 V4f32Type = VectorType::get(FloatType, 4); 00218 V4i32Type = VectorType::get(Int32Type, 4); 00219 Type *ArgsType[] = { 00220 V4f32Type, 00221 Int32Type, 00222 Int32Type, 00223 Int32Type, 00224 Int32Type, 00225 Int32Type, 00226 Int32Type, 00227 Int32Type, 00228 Int32Type, 00229 Int32Type, 00230 }; 00231 TexSign = FunctionType::get(V4f32Type, ArgsType, /*isVarArg=*/false); 00232 Type *ArgsQType[] = { 00233 V4i32Type, 00234 Int32Type, 00235 Int32Type, 00236 Int32Type, 00237 Int32Type, 00238 Int32Type, 00239 Int32Type, 00240 Int32Type, 00241 Int32Type, 00242 Int32Type, 00243 }; 00244 TexQSign = FunctionType::get(V4f32Type, ArgsQType, /*isVarArg=*/false); 00245 return false; 00246 } 00247 00248 bool runOnFunction(Function &F) override { 00249 visit(F); 00250 return false; 00251 } 00252 00253 const char *getPassName() const override { 00254 return "R600 Texture Intrinsics Replacer"; 00255 } 00256 00257 void getAnalysisUsage(AnalysisUsage &AU) const override { 00258 } 00259 00260 void visitCallInst(CallInst &I) { 00261 if (!I.getCalledFunction()) 00262 return; 00263 00264 StringRef Name = I.getCalledFunction()->getName(); 00265 if (Name == "llvm.AMDGPU.tex") { 00266 ReplaceTexIntrinsic(I, false, TexSign, "llvm.R600.tex", "llvm.R600.texc"); 00267 return; 00268 } 00269 if (Name == "llvm.AMDGPU.txl") { 00270 ReplaceTexIntrinsic(I, true, TexSign, "llvm.R600.txl", "llvm.R600.txlc"); 00271 return; 00272 } 00273 if (Name == "llvm.AMDGPU.txb") { 00274 ReplaceTexIntrinsic(I, true, TexSign, "llvm.R600.txb", "llvm.R600.txbc"); 00275 return; 00276 } 00277 if (Name == "llvm.AMDGPU.txf") { 00278 ReplaceTXF(I); 00279 return; 00280 } 00281 if (Name == "llvm.AMDGPU.txq") { 00282 ReplaceTexIntrinsic(I, false, TexQSign, "llvm.R600.txq", "llvm.R600.txq"); 00283 return; 00284 } 00285 if (Name == "llvm.AMDGPU.ddx") { 00286 ReplaceTexIntrinsic(I, false, TexSign, "llvm.R600.ddx", "llvm.R600.ddx"); 00287 return; 00288 } 00289 if (Name == "llvm.AMDGPU.ddy") { 00290 ReplaceTexIntrinsic(I, false, TexSign, "llvm.R600.ddy", "llvm.R600.ddy"); 00291 return; 00292 } 00293 } 00294 00295 }; 00296 00297 char R600TextureIntrinsicsReplacer::ID = 0; 00298 00299 } 00300 00301 FunctionPass *llvm::createR600TextureIntrinsicsReplacer() { 00302 return new R600TextureIntrinsicsReplacer(); 00303 }