mirror of
				https://github.com/c64scene-ar/llvm-6502.git
				synced 2025-10-31 08:16:47 +00:00 
			
		
		
		
	git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@207503 91177308-0d34-0410-b5e6-96231b3b80d8
		
			
				
	
	
		
			304 lines
		
	
	
		
			8.3 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			304 lines
		
	
	
		
			8.3 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| //===-- R600TextureIntrinsicsReplacer.cpp ---------------------------------===//
 | |
| //
 | |
| //                     The LLVM Compiler Infrastructure
 | |
| //
 | |
| // This file is distributed under the University of Illinois Open Source
 | |
| // License. See LICENSE.TXT for details.
 | |
| //
 | |
| //===----------------------------------------------------------------------===//
 | |
| //
 | |
| /// \file
 | |
| /// This pass translates tgsi-like texture intrinsics into R600 texture
 | |
| /// closer to hardware intrinsics.
 | |
| //===----------------------------------------------------------------------===//
 | |
| 
 | |
| #include "AMDGPU.h"
 | |
| #include "llvm/ADT/Statistic.h"
 | |
| #include "llvm/Analysis/Passes.h"
 | |
| #include "llvm/IR/Function.h"
 | |
| #include "llvm/IR/GlobalValue.h"
 | |
| #include "llvm/IR/IRBuilder.h"
 | |
| #include "llvm/IR/InstVisitor.h"
 | |
| 
 | |
| using namespace llvm;
 | |
| 
 | |
| namespace {
 | |
| class R600TextureIntrinsicsReplacer :
 | |
|     public FunctionPass, public InstVisitor<R600TextureIntrinsicsReplacer> {
 | |
|   static char ID;
 | |
| 
 | |
|   Module *Mod;
 | |
|   Type *FloatType;
 | |
|   Type *Int32Type;
 | |
|   Type *V4f32Type;
 | |
|   Type *V4i32Type;
 | |
|   FunctionType *TexSign;
 | |
|   FunctionType *TexQSign;
 | |
| 
 | |
|   void getAdjustmentFromTextureTarget(unsigned TextureType, bool hasLOD,
 | |
|                                       unsigned SrcSelect[4], unsigned CT[4],
 | |
|                                       bool &useShadowVariant) {
 | |
|     enum TextureTypes {
 | |
|       TEXTURE_1D = 1,
 | |
|       TEXTURE_2D,
 | |
|       TEXTURE_3D,
 | |
|       TEXTURE_CUBE,
 | |
|       TEXTURE_RECT,
 | |
|       TEXTURE_SHADOW1D,
 | |
|       TEXTURE_SHADOW2D,
 | |
|       TEXTURE_SHADOWRECT,
 | |
|       TEXTURE_1D_ARRAY,
 | |
|       TEXTURE_2D_ARRAY,
 | |
|       TEXTURE_SHADOW1D_ARRAY,
 | |
|       TEXTURE_SHADOW2D_ARRAY,
 | |
|       TEXTURE_SHADOWCUBE,
 | |
|       TEXTURE_2D_MSAA,
 | |
|       TEXTURE_2D_ARRAY_MSAA,
 | |
|       TEXTURE_CUBE_ARRAY,
 | |
|       TEXTURE_SHADOWCUBE_ARRAY
 | |
|     };
 | |
| 
 | |
|     switch (TextureType) {
 | |
|     case 0:
 | |
|       useShadowVariant = false;
 | |
|       return;
 | |
|     case TEXTURE_RECT:
 | |
|     case TEXTURE_1D:
 | |
|     case TEXTURE_2D:
 | |
|     case TEXTURE_3D:
 | |
|     case TEXTURE_CUBE:
 | |
|     case TEXTURE_1D_ARRAY:
 | |
|     case TEXTURE_2D_ARRAY:
 | |
|     case TEXTURE_CUBE_ARRAY:
 | |
|     case TEXTURE_2D_MSAA:
 | |
|     case TEXTURE_2D_ARRAY_MSAA:
 | |
|       useShadowVariant = false;
 | |
|       break;
 | |
|     case TEXTURE_SHADOW1D:
 | |
|     case TEXTURE_SHADOW2D:
 | |
|     case TEXTURE_SHADOWRECT:
 | |
|     case TEXTURE_SHADOW1D_ARRAY:
 | |
|     case TEXTURE_SHADOW2D_ARRAY:
 | |
|     case TEXTURE_SHADOWCUBE:
 | |
|     case TEXTURE_SHADOWCUBE_ARRAY:
 | |
|       useShadowVariant = true;
 | |
|       break;
 | |
|     default:
 | |
|       llvm_unreachable("Unknow Texture Type");
 | |
|     }
 | |
| 
 | |
|     if (TextureType == TEXTURE_RECT ||
 | |
|         TextureType == TEXTURE_SHADOWRECT) {
 | |
|       CT[0] = 0;
 | |
|       CT[1] = 0;
 | |
|     }
 | |
| 
 | |
|     if (TextureType == TEXTURE_CUBE_ARRAY ||
 | |
|         TextureType == TEXTURE_SHADOWCUBE_ARRAY)
 | |
|       CT[2] = 0;
 | |
| 
 | |
|     if (TextureType == TEXTURE_1D_ARRAY ||
 | |
|         TextureType == TEXTURE_SHADOW1D_ARRAY) {
 | |
|       if (hasLOD && useShadowVariant) {
 | |
|         CT[1] = 0;
 | |
|       } else {
 | |
|         CT[2] = 0;
 | |
|         SrcSelect[2] = 1;
 | |
|       }
 | |
|     } else if (TextureType == TEXTURE_2D_ARRAY ||
 | |
|         TextureType == TEXTURE_SHADOW2D_ARRAY) {
 | |
|       CT[2] = 0;
 | |
|     }
 | |
| 
 | |
|     if ((TextureType == TEXTURE_SHADOW1D ||
 | |
|         TextureType == TEXTURE_SHADOW2D ||
 | |
|         TextureType == TEXTURE_SHADOWRECT ||
 | |
|         TextureType == TEXTURE_SHADOW1D_ARRAY) &&
 | |
|         !(hasLOD && useShadowVariant))
 | |
|       SrcSelect[3] = 2;
 | |
|   }
 | |
| 
 | |
|   void ReplaceCallInst(CallInst &I, FunctionType *FT, const char *Name,
 | |
|                        unsigned SrcSelect[4], Value *Offset[3], Value *Resource,
 | |
|                        Value *Sampler, unsigned CT[4], Value *Coord) {
 | |
|     IRBuilder<> Builder(&I);
 | |
|     Constant *Mask[] = {
 | |
|       ConstantInt::get(Int32Type, SrcSelect[0]),
 | |
|       ConstantInt::get(Int32Type, SrcSelect[1]),
 | |
|       ConstantInt::get(Int32Type, SrcSelect[2]),
 | |
|       ConstantInt::get(Int32Type, SrcSelect[3])
 | |
|     };
 | |
|     Value *SwizzleMask = ConstantVector::get(Mask);
 | |
|     Value *SwizzledCoord =
 | |
|         Builder.CreateShuffleVector(Coord, Coord, SwizzleMask);
 | |
| 
 | |
|     Value *Args[] = {
 | |
|       SwizzledCoord,
 | |
|       Offset[0],
 | |
|       Offset[1],
 | |
|       Offset[2],
 | |
|       Resource,
 | |
|       Sampler,
 | |
|       ConstantInt::get(Int32Type, CT[0]),
 | |
|       ConstantInt::get(Int32Type, CT[1]),
 | |
|       ConstantInt::get(Int32Type, CT[2]),
 | |
|       ConstantInt::get(Int32Type, CT[3])
 | |
|     };
 | |
| 
 | |
|     Function *F = Mod->getFunction(Name);
 | |
|     if (!F) {
 | |
|       F = Function::Create(FT, GlobalValue::ExternalLinkage, Name, Mod);
 | |
|       F->addFnAttr(Attribute::ReadNone);
 | |
|     }
 | |
|     I.replaceAllUsesWith(Builder.CreateCall(F, Args));
 | |
|     I.eraseFromParent();
 | |
|   }
 | |
| 
 | |
|   void ReplaceTexIntrinsic(CallInst &I, bool hasLOD, FunctionType *FT,
 | |
|                            const char *VanillaInt,
 | |
|                            const char *ShadowInt) {
 | |
|     Value *Coord = I.getArgOperand(0);
 | |
|     Value *ResourceId = I.getArgOperand(1);
 | |
|     Value *SamplerId = I.getArgOperand(2);
 | |
| 
 | |
|     unsigned TextureType =
 | |
|         dyn_cast<ConstantInt>(I.getArgOperand(3))->getZExtValue();
 | |
| 
 | |
|     unsigned SrcSelect[4] = { 0, 1, 2, 3 };
 | |
|     unsigned CT[4] = {1, 1, 1, 1};
 | |
|     Value *Offset[3] = {
 | |
|       ConstantInt::get(Int32Type, 0),
 | |
|       ConstantInt::get(Int32Type, 0),
 | |
|       ConstantInt::get(Int32Type, 0)
 | |
|     };
 | |
|     bool useShadowVariant;
 | |
| 
 | |
|     getAdjustmentFromTextureTarget(TextureType, hasLOD, SrcSelect, CT,
 | |
|                                    useShadowVariant);
 | |
| 
 | |
|     ReplaceCallInst(I, FT, useShadowVariant?ShadowInt:VanillaInt, SrcSelect,
 | |
|                     Offset, ResourceId, SamplerId, CT, Coord);
 | |
|   }
 | |
| 
 | |
|   void ReplaceTXF(CallInst &I) {
 | |
|     Value *Coord = I.getArgOperand(0);
 | |
|     Value *ResourceId = I.getArgOperand(4);
 | |
|     Value *SamplerId = I.getArgOperand(5);
 | |
| 
 | |
|     unsigned TextureType =
 | |
|         dyn_cast<ConstantInt>(I.getArgOperand(6))->getZExtValue();
 | |
| 
 | |
|     unsigned SrcSelect[4] = { 0, 1, 2, 3 };
 | |
|     unsigned CT[4] = {1, 1, 1, 1};
 | |
|     Value *Offset[3] = {
 | |
|       I.getArgOperand(1),
 | |
|       I.getArgOperand(2),
 | |
|       I.getArgOperand(3),
 | |
|     };
 | |
|     bool useShadowVariant;
 | |
| 
 | |
|     getAdjustmentFromTextureTarget(TextureType, false, SrcSelect, CT,
 | |
|                                    useShadowVariant);
 | |
| 
 | |
|     ReplaceCallInst(I, TexQSign, "llvm.R600.txf", SrcSelect,
 | |
|                     Offset, ResourceId, SamplerId, CT, Coord);
 | |
|   }
 | |
| 
 | |
| public:
 | |
|   R600TextureIntrinsicsReplacer():
 | |
|     FunctionPass(ID) {
 | |
|   }
 | |
| 
 | |
|   bool doInitialization(Module &M) override {
 | |
|     LLVMContext &Ctx = M.getContext();
 | |
|     Mod = &M;
 | |
|     FloatType = Type::getFloatTy(Ctx);
 | |
|     Int32Type = Type::getInt32Ty(Ctx);
 | |
|     V4f32Type = VectorType::get(FloatType, 4);
 | |
|     V4i32Type = VectorType::get(Int32Type, 4);
 | |
|     Type *ArgsType[] = {
 | |
|       V4f32Type,
 | |
|       Int32Type,
 | |
|       Int32Type,
 | |
|       Int32Type,
 | |
|       Int32Type,
 | |
|       Int32Type,
 | |
|       Int32Type,
 | |
|       Int32Type,
 | |
|       Int32Type,
 | |
|       Int32Type,
 | |
|     };
 | |
|     TexSign = FunctionType::get(V4f32Type, ArgsType, /*isVarArg=*/false);
 | |
|     Type *ArgsQType[] = {
 | |
|       V4i32Type,
 | |
|       Int32Type,
 | |
|       Int32Type,
 | |
|       Int32Type,
 | |
|       Int32Type,
 | |
|       Int32Type,
 | |
|       Int32Type,
 | |
|       Int32Type,
 | |
|       Int32Type,
 | |
|       Int32Type,
 | |
|     };
 | |
|     TexQSign = FunctionType::get(V4f32Type, ArgsQType, /*isVarArg=*/false);
 | |
|     return false;
 | |
|   }
 | |
| 
 | |
|   bool runOnFunction(Function &F) override {
 | |
|     visit(F);
 | |
|     return false;
 | |
|   }
 | |
| 
 | |
|   const char *getPassName() const override {
 | |
|     return "R600 Texture Intrinsics Replacer";
 | |
|   }
 | |
| 
 | |
|   void getAnalysisUsage(AnalysisUsage &AU) const override {
 | |
|   }
 | |
| 
 | |
|   void visitCallInst(CallInst &I) {
 | |
|     if (!I.getCalledFunction())
 | |
|       return;
 | |
| 
 | |
|     StringRef Name = I.getCalledFunction()->getName();
 | |
|     if (Name == "llvm.AMDGPU.tex") {
 | |
|       ReplaceTexIntrinsic(I, false, TexSign, "llvm.R600.tex", "llvm.R600.texc");
 | |
|       return;
 | |
|     }
 | |
|     if (Name == "llvm.AMDGPU.txl") {
 | |
|       ReplaceTexIntrinsic(I, true, TexSign, "llvm.R600.txl", "llvm.R600.txlc");
 | |
|       return;
 | |
|     }
 | |
|     if (Name == "llvm.AMDGPU.txb") {
 | |
|       ReplaceTexIntrinsic(I, true, TexSign, "llvm.R600.txb", "llvm.R600.txbc");
 | |
|       return;
 | |
|     }
 | |
|     if (Name == "llvm.AMDGPU.txf") {
 | |
|       ReplaceTXF(I);
 | |
|       return;
 | |
|     }
 | |
|     if (Name == "llvm.AMDGPU.txq") {
 | |
|       ReplaceTexIntrinsic(I, false, TexQSign, "llvm.R600.txq", "llvm.R600.txq");
 | |
|       return;
 | |
|     }
 | |
|     if (Name == "llvm.AMDGPU.ddx") {
 | |
|       ReplaceTexIntrinsic(I, false, TexSign, "llvm.R600.ddx", "llvm.R600.ddx");
 | |
|       return;
 | |
|     }
 | |
|     if (Name == "llvm.AMDGPU.ddy") {
 | |
|       ReplaceTexIntrinsic(I, false, TexSign, "llvm.R600.ddy", "llvm.R600.ddy");
 | |
|       return;
 | |
|     }
 | |
|   }
 | |
| 
 | |
| };
 | |
| 
 | |
| char R600TextureIntrinsicsReplacer::ID = 0;
 | |
| 
 | |
| }
 | |
| 
 | |
| FunctionPass *llvm::createR600TextureIntrinsicsReplacer() {
 | |
|   return new R600TextureIntrinsicsReplacer();
 | |
| }
 |