~ubuntu-branches/ubuntu/trusty/llvm-toolchain-snapshot/trusty-201310232150

« back to all changes in this revision

Viewing changes to lib/Target/R600/R600TextureIntrinsicsReplacer.cpp

  • Committer: Package Import Robot
  • Author(s): Sylvestre Ledru
  • Date: 2013-05-27 15:01:57 UTC
  • mfrom: (0.10.1) (0.9.1) (0.8.1) (0.7.1) (0.6.1) (0.5.2)
  • Revision ID: package-import@ubuntu.com-20130527150157-tdkrsjpuvht7v0qx
Tags: 1:3.4~svn182733-1~exp1
* New snapshot release (3.4 release)
* Add a symlink of libLLVM-3.4.so.1 to usr/lib/llvm-3.4/lib/libLLVM-3.4.so
    to fix make the llvm-config-3.4 --libdir work (Closes: #708677)
  * Various packages rename to allow co installations:
    * libclang1 => libclang1-3.4
    * libclang1-dbg => libclang1-3.4-dbg
    * libclang-dev => libclang-3.4-dev
    * libclang-common-dev => libclang-common-3.4-dev

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
//===-- R600TextureIntrinsicsReplacer.cpp ---------------------------------===//
 
2
//
 
3
//                     The LLVM Compiler Infrastructure
 
4
//
 
5
// This file is distributed under the University of Illinois Open Source
 
6
// License. See LICENSE.TXT for details.
 
7
//
 
8
//===----------------------------------------------------------------------===//
 
9
//
 
10
/// \file
 
11
/// This pass translates tgsi-like texture intrinsics into R600 texture
 
12
/// closer to hardware intrinsics.
 
13
//===----------------------------------------------------------------------===//
 
14
 
 
15
#include "AMDGPU.h"
 
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"
 
22
 
 
23
using namespace llvm;
 
24
 
 
25
namespace {
 
26
class R600TextureIntrinsicsReplacer :
 
27
    public FunctionPass, public InstVisitor<R600TextureIntrinsicsReplacer> {
 
28
  static char ID;
 
29
 
 
30
  Module *Mod;
 
31
  Type *FloatType;
 
32
  Type *Int32Type;
 
33
  Type *V4f32Type;
 
34
  Type *V4i32Type;
 
35
  FunctionType *TexSign;
 
36
  FunctionType *TexQSign;
 
37
 
 
38
  void getAdjustementFromTextureTarget(unsigned TextureType, bool hasLOD,
 
39
                                       unsigned SrcSelect[4], unsigned CT[4],
 
40
                                       bool &useShadowVariant) {
 
41
    enum TextureTypes {
 
42
      TEXTURE_1D = 1,
 
43
      TEXTURE_2D,
 
44
      TEXTURE_3D,
 
45
      TEXTURE_CUBE,
 
46
      TEXTURE_RECT,
 
47
      TEXTURE_SHADOW1D,
 
48
      TEXTURE_SHADOW2D,
 
49
      TEXTURE_SHADOWRECT,
 
50
      TEXTURE_1D_ARRAY,
 
51
      TEXTURE_2D_ARRAY,
 
52
      TEXTURE_SHADOW1D_ARRAY,
 
53
      TEXTURE_SHADOW2D_ARRAY,
 
54
      TEXTURE_SHADOWCUBE,
 
55
      TEXTURE_2D_MSAA,
 
56
      TEXTURE_2D_ARRAY_MSAA,
 
57
      TEXTURE_CUBE_ARRAY,
 
58
      TEXTURE_SHADOWCUBE_ARRAY
 
59
    };
 
60
 
 
61
    switch (TextureType) {
 
62
    case 0:
 
63
      return;
 
64
    case TEXTURE_RECT:
 
65
    case TEXTURE_1D:
 
66
    case TEXTURE_2D:
 
67
    case TEXTURE_3D:
 
68
    case TEXTURE_CUBE:
 
69
    case TEXTURE_1D_ARRAY:
 
70
    case TEXTURE_2D_ARRAY:
 
71
    case TEXTURE_CUBE_ARRAY:
 
72
    case TEXTURE_2D_MSAA:
 
73
    case TEXTURE_2D_ARRAY_MSAA:
 
74
      useShadowVariant = false;
 
75
      break;
 
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;
 
84
      break;
 
85
    default:
 
86
      llvm_unreachable("Unknow Texture Type");
 
87
    }
 
88
 
 
89
    if (TextureType == TEXTURE_RECT ||
 
90
        TextureType == TEXTURE_SHADOWRECT) {
 
91
      CT[0] = 0;
 
92
      CT[1] = 0;
 
93
    }
 
94
 
 
95
    if (TextureType == TEXTURE_CUBE_ARRAY ||
 
96
        TextureType == TEXTURE_SHADOWCUBE_ARRAY) {
 
97
      CT[2] = 0;
 
98
    }
 
99
 
 
100
    if (TextureType == TEXTURE_1D_ARRAY ||
 
101
        TextureType == TEXTURE_SHADOW1D_ARRAY) {
 
102
      if (hasLOD && useShadowVariant) {
 
103
        CT[1] = 0;
 
104
      } else {
 
105
        CT[2] = 0;
 
106
        SrcSelect[2] = 1;
 
107
      }
 
108
    } else if (TextureType == TEXTURE_2D_ARRAY ||
 
109
        TextureType == TEXTURE_SHADOW2D_ARRAY) {
 
110
      CT[2] = 0;
 
111
    }
 
112
 
 
113
    if ((TextureType == TEXTURE_SHADOW1D ||
 
114
        TextureType == TEXTURE_SHADOW2D ||
 
115
        TextureType == TEXTURE_SHADOWRECT ||
 
116
        TextureType == TEXTURE_SHADOW1D_ARRAY) &&
 
117
        !(hasLOD && useShadowVariant)) {
 
118
      SrcSelect[3] = 2;
 
119
    }
 
120
  }
 
121
 
 
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);
 
126
    Constant *Mask[] = {
 
127
      ConstantInt::get(Int32Type, SrcSelect[0]),
 
128
      ConstantInt::get(Int32Type, SrcSelect[1]),
 
129
      ConstantInt::get(Int32Type, SrcSelect[2]),
 
130
      ConstantInt::get(Int32Type, SrcSelect[3])
 
131
    };
 
132
    Value *SwizzleMask = ConstantVector::get(Mask);
 
133
    Value *SwizzledCoord =
 
134
        Builder.CreateShuffleVector(Coord, Coord, SwizzleMask);
 
135
 
 
136
    Value *Args[] = {
 
137
      SwizzledCoord,
 
138
      Offset[0],
 
139
      Offset[1],
 
140
      Offset[2],
 
141
      Resource,
 
142
      Sampler,
 
143
      ConstantInt::get(Int32Type, CT[0]),
 
144
      ConstantInt::get(Int32Type, CT[1]),
 
145
      ConstantInt::get(Int32Type, CT[2]),
 
146
      ConstantInt::get(Int32Type, CT[3])
 
147
    };
 
148
 
 
149
    Function *F = Mod->getFunction(Name);
 
150
    if (!F) {
 
151
      F = Function::Create(FT, GlobalValue::ExternalLinkage, Name, Mod);
 
152
      F->addFnAttr(Attribute::ReadNone);
 
153
    }
 
154
    I.replaceAllUsesWith(Builder.CreateCall(F, Args));
 
155
    I.eraseFromParent();
 
156
  }
 
157
 
 
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);
 
164
 
 
165
    unsigned TextureType =
 
166
        dyn_cast<ConstantInt>(I.getArgOperand(3))->getZExtValue();
 
167
 
 
168
    unsigned SrcSelect[4] = { 0, 1, 2, 3 };
 
169
    unsigned CT[4] = {1, 1, 1, 1};
 
170
    Value *Offset[3] = {
 
171
      ConstantInt::get(Int32Type, 0),
 
172
      ConstantInt::get(Int32Type, 0),
 
173
      ConstantInt::get(Int32Type, 0)
 
174
    };
 
175
    bool useShadowVariant;
 
176
 
 
177
    getAdjustementFromTextureTarget(TextureType, hasLOD, SrcSelect, CT,
 
178
                                    useShadowVariant);
 
179
 
 
180
    ReplaceCallInst(I, FT, useShadowVariant?ShadowInt:VanillaInt, SrcSelect,
 
181
                    Offset, ResourceId, SamplerId, CT, Coord);
 
182
  }
 
183
 
 
184
  void ReplaceTXF(CallInst &I) {
 
185
    Value *Coord = I.getArgOperand(0);
 
186
    Value *ResourceId = I.getArgOperand(4);
 
187
    Value *SamplerId = I.getArgOperand(5);
 
188
 
 
189
    unsigned TextureType =
 
190
        dyn_cast<ConstantInt>(I.getArgOperand(6))->getZExtValue();
 
191
 
 
192
    unsigned SrcSelect[4] = { 0, 1, 2, 3 };
 
193
    unsigned CT[4] = {1, 1, 1, 1};
 
194
    Value *Offset[3] = {
 
195
      I.getArgOperand(1),
 
196
      I.getArgOperand(2),
 
197
      I.getArgOperand(3),
 
198
    };
 
199
    bool useShadowVariant;
 
200
 
 
201
    getAdjustementFromTextureTarget(TextureType, false, SrcSelect, CT,
 
202
                                    useShadowVariant);
 
203
 
 
204
    ReplaceCallInst(I, TexQSign, "llvm.R600.txf", SrcSelect,
 
205
                    Offset, ResourceId, SamplerId, CT, Coord);
 
206
  }
 
207
 
 
208
public:
 
209
  R600TextureIntrinsicsReplacer():
 
210
    FunctionPass(ID) {
 
211
  }
 
212
 
 
213
  virtual bool doInitialization(Module &M) {
 
214
    LLVMContext &Ctx = M.getContext();
 
215
    Mod = &M;
 
216
    FloatType = Type::getFloatTy(Ctx);
 
217
    Int32Type = Type::getInt32Ty(Ctx);
 
218
    V4f32Type = VectorType::get(FloatType, 4);
 
219
    V4i32Type = VectorType::get(Int32Type, 4);
 
220
    Type *ArgsType[] = {
 
221
      V4f32Type,
 
222
      Int32Type,
 
223
      Int32Type,
 
224
      Int32Type,
 
225
      Int32Type,
 
226
      Int32Type,
 
227
      Int32Type,
 
228
      Int32Type,
 
229
      Int32Type,
 
230
      Int32Type,
 
231
    };
 
232
    TexSign = FunctionType::get(V4f32Type, ArgsType, /*isVarArg=*/false);
 
233
    Type *ArgsQType[] = {
 
234
      V4i32Type,
 
235
      Int32Type,
 
236
      Int32Type,
 
237
      Int32Type,
 
238
      Int32Type,
 
239
      Int32Type,
 
240
      Int32Type,
 
241
      Int32Type,
 
242
      Int32Type,
 
243
      Int32Type,
 
244
    };
 
245
    TexQSign = FunctionType::get(V4f32Type, ArgsQType, /*isVarArg=*/false);
 
246
    return false;
 
247
  }
 
248
 
 
249
  virtual bool runOnFunction(Function &F) {
 
250
    visit(F);
 
251
    return false;
 
252
  }
 
253
 
 
254
  virtual const char *getPassName() const {
 
255
    return "R600 Texture Intrinsics Replacer";
 
256
  }
 
257
 
 
258
  void getAnalysisUsage(AnalysisUsage &AU) const {
 
259
  }
 
260
 
 
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");
 
265
      return;
 
266
    }
 
267
    if (Name == "llvm.AMDGPU.txl") {
 
268
      ReplaceTexIntrinsic(I, true, TexSign, "llvm.R600.txl", "llvm.R600.txlc");
 
269
      return;
 
270
    }
 
271
    if (Name == "llvm.AMDGPU.txb") {
 
272
      ReplaceTexIntrinsic(I, true, TexSign, "llvm.R600.txb", "llvm.R600.txbc");
 
273
      return;
 
274
    }
 
275
    if (Name == "llvm.AMDGPU.txf") {
 
276
      ReplaceTXF(I);
 
277
      return;
 
278
    }
 
279
    if (Name == "llvm.AMDGPU.txq") {
 
280
      ReplaceTexIntrinsic(I, false, TexQSign, "llvm.R600.txq", "llvm.R600.txq");
 
281
      return;
 
282
    }
 
283
    if (Name == "llvm.AMDGPU.ddx") {
 
284
      ReplaceTexIntrinsic(I, false, TexSign, "llvm.R600.ddx", "llvm.R600.ddx");
 
285
      return;
 
286
    }
 
287
    if (Name == "llvm.AMDGPU.ddy") {
 
288
      ReplaceTexIntrinsic(I, false, TexSign, "llvm.R600.ddy", "llvm.R600.ddy");
 
289
      return;
 
290
    }
 
291
  }
 
292
 
 
293
};
 
294
 
 
295
char R600TextureIntrinsicsReplacer::ID = 0;
 
296
 
 
297
}
 
298
 
 
299
FunctionPass *llvm::createR600TextureIntrinsicsReplacer() {
 
300
  return new R600TextureIntrinsicsReplacer();
 
301
}