LLVM API Documentation

R600TextureIntrinsicsReplacer.cpp
Go to the documentation of this file.
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 }