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 getAdjustementFromTextureTarget(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) {
69
case TEXTURE_1D_ARRAY:
70
case TEXTURE_2D_ARRAY:
71
case TEXTURE_CUBE_ARRAY:
73
case TEXTURE_2D_ARRAY_MSAA:
74
useShadowVariant = false;
76
case TEXTURE_SHADOW1D:
77
case TEXTURE_SHADOW2D:
78
case TEXTURE_SHADOWRECT:
79
case TEXTURE_SHADOW1D_ARRAY:
80
case TEXTURE_SHADOW2D_ARRAY:
81
case TEXTURE_SHADOWCUBE:
82
case TEXTURE_SHADOWCUBE_ARRAY:
83
useShadowVariant = true;
86
llvm_unreachable("Unknow Texture Type");
89
if (TextureType == TEXTURE_RECT ||
90
TextureType == TEXTURE_SHADOWRECT) {
95
if (TextureType == TEXTURE_CUBE_ARRAY ||
96
TextureType == TEXTURE_SHADOWCUBE_ARRAY) {
100
if (TextureType == TEXTURE_1D_ARRAY ||
101
TextureType == TEXTURE_SHADOW1D_ARRAY) {
102
if (hasLOD && useShadowVariant) {
108
} else if (TextureType == TEXTURE_2D_ARRAY ||
109
TextureType == TEXTURE_SHADOW2D_ARRAY) {
113
if ((TextureType == TEXTURE_SHADOW1D ||
114
TextureType == TEXTURE_SHADOW2D ||
115
TextureType == TEXTURE_SHADOWRECT ||
116
TextureType == TEXTURE_SHADOW1D_ARRAY) &&
117
!(hasLOD && useShadowVariant)) {
122
void ReplaceCallInst(CallInst &I, FunctionType *FT, const char *Name,
123
unsigned SrcSelect[4], Value *Offset[3], Value *Resource,
124
Value *Sampler, unsigned CT[4], Value *Coord) {
125
IRBuilder<> Builder(&I);
127
ConstantInt::get(Int32Type, SrcSelect[0]),
128
ConstantInt::get(Int32Type, SrcSelect[1]),
129
ConstantInt::get(Int32Type, SrcSelect[2]),
130
ConstantInt::get(Int32Type, SrcSelect[3])
132
Value *SwizzleMask = ConstantVector::get(Mask);
133
Value *SwizzledCoord =
134
Builder.CreateShuffleVector(Coord, Coord, SwizzleMask);
143
ConstantInt::get(Int32Type, CT[0]),
144
ConstantInt::get(Int32Type, CT[1]),
145
ConstantInt::get(Int32Type, CT[2]),
146
ConstantInt::get(Int32Type, CT[3])
149
Function *F = Mod->getFunction(Name);
151
F = Function::Create(FT, GlobalValue::ExternalLinkage, Name, Mod);
152
F->addFnAttr(Attribute::ReadNone);
154
I.replaceAllUsesWith(Builder.CreateCall(F, Args));
158
void ReplaceTexIntrinsic(CallInst &I, bool hasLOD, FunctionType *FT,
159
const char *VanillaInt,
160
const char *ShadowInt) {
161
Value *Coord = I.getArgOperand(0);
162
Value *ResourceId = I.getArgOperand(1);
163
Value *SamplerId = I.getArgOperand(2);
165
unsigned TextureType =
166
dyn_cast<ConstantInt>(I.getArgOperand(3))->getZExtValue();
168
unsigned SrcSelect[4] = { 0, 1, 2, 3 };
169
unsigned CT[4] = {1, 1, 1, 1};
171
ConstantInt::get(Int32Type, 0),
172
ConstantInt::get(Int32Type, 0),
173
ConstantInt::get(Int32Type, 0)
175
bool useShadowVariant;
177
getAdjustementFromTextureTarget(TextureType, hasLOD, SrcSelect, CT,
180
ReplaceCallInst(I, FT, useShadowVariant?ShadowInt:VanillaInt, SrcSelect,
181
Offset, ResourceId, SamplerId, CT, Coord);
184
void ReplaceTXF(CallInst &I) {
185
Value *Coord = I.getArgOperand(0);
186
Value *ResourceId = I.getArgOperand(4);
187
Value *SamplerId = I.getArgOperand(5);
189
unsigned TextureType =
190
dyn_cast<ConstantInt>(I.getArgOperand(6))->getZExtValue();
192
unsigned SrcSelect[4] = { 0, 1, 2, 3 };
193
unsigned CT[4] = {1, 1, 1, 1};
199
bool useShadowVariant;
201
getAdjustementFromTextureTarget(TextureType, false, SrcSelect, CT,
204
ReplaceCallInst(I, TexQSign, "llvm.R600.txf", SrcSelect,
205
Offset, ResourceId, SamplerId, CT, Coord);
209
R600TextureIntrinsicsReplacer():
213
virtual bool doInitialization(Module &M) {
214
LLVMContext &Ctx = M.getContext();
216
FloatType = Type::getFloatTy(Ctx);
217
Int32Type = Type::getInt32Ty(Ctx);
218
V4f32Type = VectorType::get(FloatType, 4);
219
V4i32Type = VectorType::get(Int32Type, 4);
232
TexSign = FunctionType::get(V4f32Type, ArgsType, /*isVarArg=*/false);
233
Type *ArgsQType[] = {
245
TexQSign = FunctionType::get(V4f32Type, ArgsQType, /*isVarArg=*/false);
249
virtual bool runOnFunction(Function &F) {
254
virtual const char *getPassName() const {
255
return "R600 Texture Intrinsics Replacer";
258
void getAnalysisUsage(AnalysisUsage &AU) const {
261
void visitCallInst(CallInst &I) {
262
StringRef Name = I.getCalledFunction()->getName();
263
if (Name == "llvm.AMDGPU.tex") {
264
ReplaceTexIntrinsic(I, false, TexSign, "llvm.R600.tex", "llvm.R600.texc");
267
if (Name == "llvm.AMDGPU.txl") {
268
ReplaceTexIntrinsic(I, true, TexSign, "llvm.R600.txl", "llvm.R600.txlc");
271
if (Name == "llvm.AMDGPU.txb") {
272
ReplaceTexIntrinsic(I, true, TexSign, "llvm.R600.txb", "llvm.R600.txbc");
275
if (Name == "llvm.AMDGPU.txf") {
279
if (Name == "llvm.AMDGPU.txq") {
280
ReplaceTexIntrinsic(I, false, TexQSign, "llvm.R600.txq", "llvm.R600.txq");
283
if (Name == "llvm.AMDGPU.ddx") {
284
ReplaceTexIntrinsic(I, false, TexSign, "llvm.R600.ddx", "llvm.R600.ddx");
287
if (Name == "llvm.AMDGPU.ddy") {
288
ReplaceTexIntrinsic(I, false, TexSign, "llvm.R600.ddy", "llvm.R600.ddy");
295
char R600TextureIntrinsicsReplacer::ID = 0;
299
FunctionPass *llvm::createR600TextureIntrinsicsReplacer() {
300
return new R600TextureIntrinsicsReplacer();