blob: ae3952b6af440210626e4fccc504ff324a53b41c [file] [log] [blame]
David Neto22f144c2017-06-12 14:26:21 -04001// Copyright 2017 The Clspv Authors. All rights reserved.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15#ifdef _MSC_VER
16#pragma warning(push, 0)
17#endif
18
David Neto156783e2017-07-05 15:39:41 -040019#include <cassert>
David Neto257c3892018-04-11 13:19:45 -040020#include <cstring>
21
David Neto5c22a252018-03-15 16:07:41 -040022#include <unordered_set>
David Neto482550a2018-03-24 05:21:07 -070023#include <clspv/Option.h>
David Neto22f144c2017-06-12 14:26:21 -040024#include <clspv/Passes.h>
25
26#include <llvm/ADT/StringSwitch.h>
27#include <llvm/ADT/UniqueVector.h>
28#include <llvm/Analysis/LoopInfo.h>
29#include <llvm/IR/Constants.h>
30#include <llvm/IR/Dominators.h>
31#include <llvm/IR/Instructions.h>
32#include <llvm/IR/Metadata.h>
33#include <llvm/IR/Module.h>
34#include <llvm/Pass.h>
David Netocd8ca5f2017-10-02 23:34:11 -040035#include <llvm/Support/CommandLine.h>
David Neto22f144c2017-06-12 14:26:21 -040036#include <llvm/Support/raw_ostream.h>
37#include <llvm/Transforms/Utils/Cloning.h>
38
David Neto85082642018-03-24 06:55:20 -070039#include "spirv/1.0/spirv.hpp"
40#include "clspv/AddressSpace.h"
41#include "clspv/spirv_c_strings.hpp"
42#include "clspv/spirv_glsl.hpp"
David Neto22f144c2017-06-12 14:26:21 -040043
David Neto4feb7a42017-10-06 17:29:42 -040044#include "ArgKind.h"
David Neto85082642018-03-24 06:55:20 -070045#include "ConstantEmitter.h"
David Neto48f56a42017-10-06 16:44:25 -040046
David Neto22f144c2017-06-12 14:26:21 -040047#include <list>
David Neto0676e6f2017-07-11 18:47:44 -040048#include <iomanip>
David Neto26aaf622017-10-23 18:11:53 -040049#include <set>
David Neto0676e6f2017-07-11 18:47:44 -040050#include <sstream>
David Neto257c3892018-04-11 13:19:45 -040051#include <string>
David Neto26aaf622017-10-23 18:11:53 -040052#include <tuple>
David Neto44795152017-07-13 15:45:28 -040053#include <utility>
David Neto22f144c2017-06-12 14:26:21 -040054
55#if defined(_MSC_VER)
56#pragma warning(pop)
57#endif
58
59using namespace llvm;
60using namespace clspv;
David Neto156783e2017-07-05 15:39:41 -040061using namespace mdconst;
David Neto22f144c2017-06-12 14:26:21 -040062
63namespace {
David Netocd8ca5f2017-10-02 23:34:11 -040064
David Neto3fbb4072017-10-16 11:28:14 -040065// The value of 1/pi. This value is from MSDN
66// https://msdn.microsoft.com/en-us/library/4hwaceh6.aspx
67const double kOneOverPi = 0.318309886183790671538;
68const glsl::ExtInst kGlslExtInstBad = static_cast<glsl::ExtInst>(0);
69
David Netoab03f432017-11-03 17:00:44 -040070const char* kCompositeConstructFunctionPrefix = "clspv.composite_construct.";
71
David Neto22f144c2017-06-12 14:26:21 -040072enum SPIRVOperandType {
73 NUMBERID,
74 LITERAL_INTEGER,
75 LITERAL_STRING,
76 LITERAL_FLOAT
77};
78
79struct SPIRVOperand {
80 explicit SPIRVOperand(SPIRVOperandType Ty, uint32_t Num)
81 : Type(Ty), LiteralNum(1, Num) {}
82 explicit SPIRVOperand(SPIRVOperandType Ty, const char *Str)
83 : Type(Ty), LiteralStr(Str) {}
84 explicit SPIRVOperand(SPIRVOperandType Ty, StringRef Str)
85 : Type(Ty), LiteralStr(Str) {}
86 explicit SPIRVOperand(SPIRVOperandType Ty, ArrayRef<uint32_t> NumVec)
87 : Type(Ty), LiteralNum(NumVec.begin(), NumVec.end()) {}
88
89 SPIRVOperandType getType() { return Type; };
90 uint32_t getNumID() { return LiteralNum[0]; };
91 std::string getLiteralStr() { return LiteralStr; };
92 ArrayRef<uint32_t> getLiteralNum() { return LiteralNum; };
93
David Neto87846742018-04-11 17:36:22 -040094 uint32_t GetNumWords() const {
95 switch (Type) {
96 case NUMBERID:
97 return 1;
98 case LITERAL_INTEGER:
99 case LITERAL_FLOAT:
100 return LiteralNum.size();
101 case LITERAL_STRING:
102 // Account for the terminating null character.
103 return (LiteralStr.size() + 4) / 4;
104 }
105 llvm_unreachable("Unhandled case in SPIRVOperand::GetNumWords()");
106 }
107
David Neto22f144c2017-06-12 14:26:21 -0400108private:
109 SPIRVOperandType Type;
110 std::string LiteralStr;
111 SmallVector<uint32_t, 4> LiteralNum;
112};
113
David Netoc6f3ab22018-04-06 18:02:31 -0400114class SPIRVOperandList {
115public:
116 SPIRVOperandList() {}
117 SPIRVOperandList(const SPIRVOperandList& other) = delete;
118 SPIRVOperandList(SPIRVOperandList&& other) {
119 contents_ = std::move(other.contents_);
120 other.contents_.clear();
121 }
122 SPIRVOperandList(ArrayRef<SPIRVOperand *> init)
123 : contents_(init.begin(), init.end()) {}
124 operator ArrayRef<SPIRVOperand *>() { return contents_; }
125 void push_back(SPIRVOperand *op) { contents_.push_back(op); }
126 void clear() { contents_.clear();}
127 size_t size() const { return contents_.size(); }
128 SPIRVOperand *&operator[](size_t i) { return contents_[i]; }
129
David Neto87846742018-04-11 17:36:22 -0400130 const SmallVector<SPIRVOperand *, 8> &getOperands() const {
131 return contents_;
132 }
133
David Netoc6f3ab22018-04-06 18:02:31 -0400134private:
135 SmallVector<SPIRVOperand *,8> contents_;
136};
137
138SPIRVOperandList &operator<<(SPIRVOperandList &list, SPIRVOperand *elem) {
139 list.push_back(elem);
140 return list;
141}
142
143SPIRVOperand* MkNum(uint32_t num) {
144 return new SPIRVOperand(LITERAL_INTEGER, num);
145}
David Neto257c3892018-04-11 13:19:45 -0400146SPIRVOperand* MkInteger(ArrayRef<uint32_t> num_vec) {
147 return new SPIRVOperand(LITERAL_INTEGER, num_vec);
148}
149SPIRVOperand* MkFloat(ArrayRef<uint32_t> num_vec) {
150 return new SPIRVOperand(LITERAL_FLOAT, num_vec);
151}
David Netoc6f3ab22018-04-06 18:02:31 -0400152SPIRVOperand* MkId(uint32_t id) {
153 return new SPIRVOperand(NUMBERID, id);
154}
David Neto257c3892018-04-11 13:19:45 -0400155SPIRVOperand* MkString(StringRef str) {
156 return new SPIRVOperand(LITERAL_STRING, str);
157}
David Netoc6f3ab22018-04-06 18:02:31 -0400158
David Neto22f144c2017-06-12 14:26:21 -0400159struct SPIRVInstruction {
David Neto87846742018-04-11 17:36:22 -0400160 // Create an instruction with an opcode and no result ID, and with the given
161 // operands. This computes its own word count.
162 explicit SPIRVInstruction(spv::Op Opc, ArrayRef<SPIRVOperand *> Ops)
163 : WordCount(1), Opcode(static_cast<uint16_t>(Opc)), ResultID(0),
164 Operands(Ops.begin(), Ops.end()) {
165 for (auto *operand : Ops) {
166 WordCount += operand->GetNumWords();
167 }
168 }
169 // Create an instruction with an opcode and a no-zero result ID, and
170 // with the given operands. This computes its own word count.
171 explicit SPIRVInstruction(spv::Op Opc, uint32_t ResID,
David Neto22f144c2017-06-12 14:26:21 -0400172 ArrayRef<SPIRVOperand *> Ops)
David Neto87846742018-04-11 17:36:22 -0400173 : WordCount(2), Opcode(static_cast<uint16_t>(Opc)), ResultID(ResID),
174 Operands(Ops.begin(), Ops.end()) {
175 if (ResID == 0) {
176 llvm_unreachable("Result ID of 0 was provided");
177 }
178 for (auto *operand : Ops) {
179 WordCount += operand->GetNumWords();
180 }
181 }
David Neto22f144c2017-06-12 14:26:21 -0400182
183 uint16_t getWordCount() const { return WordCount; }
184 uint16_t getOpcode() const { return Opcode; }
185 uint32_t getResultID() const { return ResultID; }
186 ArrayRef<SPIRVOperand *> getOperands() const { return Operands; }
187
188private:
189 uint16_t WordCount;
190 uint16_t Opcode;
191 uint32_t ResultID;
192 SmallVector<SPIRVOperand *, 4> Operands;
193};
194
195struct SPIRVProducerPass final : public ModulePass {
David Neto22f144c2017-06-12 14:26:21 -0400196 typedef DenseMap<Type *, uint32_t> TypeMapType;
197 typedef UniqueVector<Type *> TypeList;
198 typedef DenseMap<Value *, uint32_t> ValueMapType;
David Netofb9a7972017-08-25 17:08:24 -0400199 typedef UniqueVector<Value *> ValueList;
David Neto22f144c2017-06-12 14:26:21 -0400200 typedef std::vector<std::pair<Value *, uint32_t>> EntryPointVecType;
201 typedef std::list<SPIRVInstruction *> SPIRVInstructionList;
David Neto87846742018-04-11 17:36:22 -0400202 // A vector of tuples, each of which is:
203 // - the LLVM instruction that we will later generate SPIR-V code for
204 // - where the SPIR-V instruction should be inserted
205 // - the result ID of the SPIR-V instruction
David Neto22f144c2017-06-12 14:26:21 -0400206 typedef std::vector<
207 std::tuple<Value *, SPIRVInstructionList::iterator, uint32_t>>
208 DeferredInstVecType;
209 typedef DenseMap<FunctionType *, std::pair<FunctionType *, uint32_t>>
210 GlobalConstFuncMapType;
211
David Neto44795152017-07-13 15:45:28 -0400212 explicit SPIRVProducerPass(
213 raw_pwrite_stream &out, raw_ostream &descriptor_map_out,
214 ArrayRef<std::pair<unsigned, std::string>> samplerMap, bool outputAsm,
215 bool outputCInitList)
David Netoc2c368d2017-06-30 16:50:17 -0400216 : ModulePass(ID), samplerMap(samplerMap), out(out),
David Neto0676e6f2017-07-11 18:47:44 -0400217 binaryTempOut(binaryTempUnderlyingVector), binaryOut(&out),
David Netoc2c368d2017-06-30 16:50:17 -0400218 descriptorMapOut(descriptor_map_out), outputAsm(outputAsm),
David Neto0676e6f2017-07-11 18:47:44 -0400219 outputCInitList(outputCInitList), patchBoundOffset(0), nextID(1),
David Netoa60b00b2017-09-15 16:34:09 -0400220 OpExtInstImportID(0), HasVariablePointers(false), SamplerTy(nullptr),
David Neto85082642018-03-24 06:55:20 -0700221 WorkgroupSizeValueID(0), WorkgroupSizeVarID(0),
David Neto257c3892018-04-11 13:19:45 -0400222 NextDescriptorSetIndex(0), constant_i32_zero_id_(0) {}
David Neto22f144c2017-06-12 14:26:21 -0400223
224 void getAnalysisUsage(AnalysisUsage &AU) const override {
225 AU.addRequired<DominatorTreeWrapperPass>();
226 AU.addRequired<LoopInfoWrapperPass>();
227 }
228
229 virtual bool runOnModule(Module &module) override;
230
231 // output the SPIR-V header block
232 void outputHeader();
233
234 // patch the SPIR-V header block
235 void patchHeader();
236
237 uint32_t lookupType(Type *Ty) {
238 if (Ty->isPointerTy() &&
239 (Ty->getPointerAddressSpace() != AddressSpace::UniformConstant)) {
240 auto PointeeTy = Ty->getPointerElementType();
241 if (PointeeTy->isStructTy() &&
242 dyn_cast<StructType>(PointeeTy)->isOpaque()) {
243 Ty = PointeeTy;
244 }
245 }
246
247 if (0 == TypeMap.count(Ty)) {
248 Ty->print(errs());
David Netoe439d702018-03-23 13:14:08 -0700249 llvm_unreachable("\nUnhandled type!");
David Neto22f144c2017-06-12 14:26:21 -0400250 }
251
252 return TypeMap[Ty];
253 }
254 TypeMapType &getImageTypeMap() { return ImageTypeMap; }
255 TypeList &getTypeList() { return Types; };
256 ValueList &getConstantList() { return Constants; };
257 ValueMapType &getValueMap() { return ValueMap; }
258 ValueMapType &getAllocatedValueMap() { return AllocatedValueMap; }
259 SPIRVInstructionList &getSPIRVInstList() { return SPIRVInsts; };
260 ValueToValueMapTy &getArgumentGVMap() { return ArgumentGVMap; };
261 ValueMapType &getArgumentGVIDMap() { return ArgumentGVIDMap; };
262 EntryPointVecType &getEntryPointVec() { return EntryPointVec; };
263 DeferredInstVecType &getDeferredInstVec() { return DeferredInstVec; };
264 ValueList &getEntryPointInterfacesVec() { return EntryPointInterfacesVec; };
265 uint32_t &getOpExtInstImportID() { return OpExtInstImportID; };
266 std::vector<uint32_t> &getBuiltinDimVec() { return BuiltinDimensionVec; };
267 bool hasVariablePointers() { return true; /* We use StorageBuffer everywhere */ };
268 void setVariablePointers(bool Val) { HasVariablePointers = Val; };
David Neto44795152017-07-13 15:45:28 -0400269 ArrayRef<std::pair<unsigned, std::string>> &getSamplerMap() { return samplerMap; }
David Neto22f144c2017-06-12 14:26:21 -0400270 GlobalConstFuncMapType &getGlobalConstFuncTypeMap() {
271 return GlobalConstFuncTypeMap;
272 }
273 SmallPtrSet<Value *, 16> &getGlobalConstArgSet() {
274 return GlobalConstArgumentSet;
275 }
David Neto85082642018-03-24 06:55:20 -0700276 TypeList &getTypesNeedingArrayStride() {
277 return TypesNeedingArrayStride;
David Neto1a1a0582017-07-07 12:01:44 -0400278 }
David Neto22f144c2017-06-12 14:26:21 -0400279
David Netoc6f3ab22018-04-06 18:02:31 -0400280 void GenerateLLVMIRInfo(Module &M, const DataLayout &DL);
David Neto22f144c2017-06-12 14:26:21 -0400281 bool FindExtInst(Module &M);
282 void FindTypePerGlobalVar(GlobalVariable &GV);
283 void FindTypePerFunc(Function &F);
David Neto19a1bad2017-08-25 15:01:41 -0400284 // Inserts |Ty| and relevant sub-types into the |Types| member, indicating that
285 // |Ty| and its subtypes will need a corresponding SPIR-V type.
David Neto22f144c2017-06-12 14:26:21 -0400286 void FindType(Type *Ty);
287 void FindConstantPerGlobalVar(GlobalVariable &GV);
288 void FindConstantPerFunc(Function &F);
289 void FindConstant(Value *V);
290 void GenerateExtInstImport();
David Neto19a1bad2017-08-25 15:01:41 -0400291 // Generates instructions for SPIR-V types corresponding to the LLVM types
292 // saved in the |Types| member. A type follows its subtypes. IDs are
293 // allocated sequentially starting with the current value of nextID, and
294 // with a type following its subtypes. Also updates nextID to just beyond
295 // the last generated ID.
David Netoc6f3ab22018-04-06 18:02:31 -0400296 void GenerateSPIRVTypes(LLVMContext& context, const DataLayout &DL);
David Neto22f144c2017-06-12 14:26:21 -0400297 void GenerateSPIRVConstants();
David Neto5c22a252018-03-15 16:07:41 -0400298 void GenerateModuleInfo(Module &M);
David Neto22f144c2017-06-12 14:26:21 -0400299 void GenerateGlobalVar(GlobalVariable &GV);
David Netoc6f3ab22018-04-06 18:02:31 -0400300 void GenerateWorkgroupVars();
David Neto22f144c2017-06-12 14:26:21 -0400301 void GenerateSamplers(Module &M);
302 void GenerateFuncPrologue(Function &F);
303 void GenerateFuncBody(Function &F);
304 void GenerateInstForArg(Function &F);
305 spv::Op GetSPIRVCmpOpcode(CmpInst *CmpI);
306 spv::Op GetSPIRVCastOpcode(Instruction &I);
307 spv::Op GetSPIRVBinaryOpcode(Instruction &I);
308 void GenerateInstruction(Instruction &I);
309 void GenerateFuncEpilogue();
310 void HandleDeferredInstruction();
David Neto1a1a0582017-07-07 12:01:44 -0400311 void HandleDeferredDecorations(const DataLayout& DL);
David Neto22f144c2017-06-12 14:26:21 -0400312 bool is4xi8vec(Type *Ty) const;
David Neto257c3892018-04-11 13:19:45 -0400313 // Return the SPIR-V Id for 32-bit constant zero. The constant must already
314 // have been created.
315 uint32_t GetI32Zero();
David Neto22f144c2017-06-12 14:26:21 -0400316 spv::StorageClass GetStorageClass(unsigned AddrSpace) const;
317 spv::BuiltIn GetBuiltin(StringRef globalVarName) const;
David Neto3fbb4072017-10-16 11:28:14 -0400318 // Returns the GLSL extended instruction enum that the given function
319 // call maps to. If none, then returns the 0 value, i.e. GLSLstd4580Bad.
David Neto22f144c2017-06-12 14:26:21 -0400320 glsl::ExtInst getExtInstEnum(StringRef Name);
David Neto3fbb4072017-10-16 11:28:14 -0400321 // Returns the GLSL extended instruction enum indirectly used by the given
322 // function. That is, to implement the given function, we use an extended
323 // instruction plus one more instruction. If none, then returns the 0 value,
324 // i.e. GLSLstd4580Bad.
325 glsl::ExtInst getIndirectExtInstEnum(StringRef Name);
326 // Returns the single GLSL extended instruction used directly or
327 // indirectly by the given function call.
328 glsl::ExtInst getDirectOrIndirectExtInstEnum(StringRef Name);
David Neto22f144c2017-06-12 14:26:21 -0400329 void PrintResID(SPIRVInstruction *Inst);
330 void PrintOpcode(SPIRVInstruction *Inst);
331 void PrintOperand(SPIRVOperand *Op);
332 void PrintCapability(SPIRVOperand *Op);
333 void PrintExtInst(SPIRVOperand *Op);
334 void PrintAddrModel(SPIRVOperand *Op);
335 void PrintMemModel(SPIRVOperand *Op);
336 void PrintExecModel(SPIRVOperand *Op);
337 void PrintExecMode(SPIRVOperand *Op);
338 void PrintSourceLanguage(SPIRVOperand *Op);
339 void PrintFuncCtrl(SPIRVOperand *Op);
340 void PrintStorageClass(SPIRVOperand *Op);
341 void PrintDecoration(SPIRVOperand *Op);
342 void PrintBuiltIn(SPIRVOperand *Op);
343 void PrintSelectionControl(SPIRVOperand *Op);
344 void PrintLoopControl(SPIRVOperand *Op);
345 void PrintDimensionality(SPIRVOperand *Op);
346 void PrintImageFormat(SPIRVOperand *Op);
347 void PrintMemoryAccess(SPIRVOperand *Op);
348 void PrintImageOperandsType(SPIRVOperand *Op);
349 void WriteSPIRVAssembly();
350 void WriteOneWord(uint32_t Word);
351 void WriteResultID(SPIRVInstruction *Inst);
352 void WriteWordCountAndOpcode(SPIRVInstruction *Inst);
353 void WriteOperand(SPIRVOperand *Op);
354 void WriteSPIRVBinary();
355
356private:
357 static char ID;
David Neto44795152017-07-13 15:45:28 -0400358 ArrayRef<std::pair<unsigned, std::string>> samplerMap;
David Neto22f144c2017-06-12 14:26:21 -0400359 raw_pwrite_stream &out;
David Neto0676e6f2017-07-11 18:47:44 -0400360
361 // TODO(dneto): Wouldn't it be better to always just emit a binary, and then
362 // convert to other formats on demand?
363
364 // When emitting a C initialization list, the WriteSPIRVBinary method
365 // will actually write its words to this vector via binaryTempOut.
366 SmallVector<char, 100> binaryTempUnderlyingVector;
367 raw_svector_ostream binaryTempOut;
368
369 // Binary output writes to this stream, which might be |out| or
370 // |binaryTempOut|. It's the latter when we really want to write a C
371 // initializer list.
372 raw_pwrite_stream* binaryOut;
David Netoc2c368d2017-06-30 16:50:17 -0400373 raw_ostream &descriptorMapOut;
David Neto22f144c2017-06-12 14:26:21 -0400374 const bool outputAsm;
David Neto0676e6f2017-07-11 18:47:44 -0400375 const bool outputCInitList; // If true, output look like {0x7023, ... , 5}
David Neto22f144c2017-06-12 14:26:21 -0400376 uint64_t patchBoundOffset;
377 uint32_t nextID;
378
David Neto19a1bad2017-08-25 15:01:41 -0400379 // Maps an LLVM Value pointer to the corresponding SPIR-V Id.
David Neto22f144c2017-06-12 14:26:21 -0400380 TypeMapType TypeMap;
David Neto19a1bad2017-08-25 15:01:41 -0400381 // Maps an LLVM image type to its SPIR-V ID.
David Neto22f144c2017-06-12 14:26:21 -0400382 TypeMapType ImageTypeMap;
David Neto19a1bad2017-08-25 15:01:41 -0400383 // A unique-vector of LLVM types that map to a SPIR-V type.
David Neto22f144c2017-06-12 14:26:21 -0400384 TypeList Types;
385 ValueList Constants;
David Neto19a1bad2017-08-25 15:01:41 -0400386 // Maps an LLVM Value pointer to the corresponding SPIR-V Id.
David Neto22f144c2017-06-12 14:26:21 -0400387 ValueMapType ValueMap;
388 ValueMapType AllocatedValueMap;
389 SPIRVInstructionList SPIRVInsts;
David Netoe439d702018-03-23 13:14:08 -0700390 // Maps a kernel argument value to a global value. OpenCL kernel arguments
391 // have to map to resources: buffers, samplers, images, or sampled images.
David Neto22f144c2017-06-12 14:26:21 -0400392 ValueToValueMapTy ArgumentGVMap;
393 ValueMapType ArgumentGVIDMap;
394 EntryPointVecType EntryPointVec;
395 DeferredInstVecType DeferredInstVec;
396 ValueList EntryPointInterfacesVec;
397 uint32_t OpExtInstImportID;
398 std::vector<uint32_t> BuiltinDimensionVec;
399 bool HasVariablePointers;
400 Type *SamplerTy;
David Netoc77d9e22018-03-24 06:30:28 -0700401
402 // If a function F has a pointer-to-__constant parameter, then this variable
David Neto9ed8e2f2018-03-24 06:47:24 -0700403 // will map F's type to (G, index of the parameter), where in a first phase
404 // G is F's type. During FindTypePerFunc, G will be changed to F's type
405 // but replacing the pointer-to-constant parameter with
406 // pointer-to-ModuleScopePrivate.
David Netoc77d9e22018-03-24 06:30:28 -0700407 // TODO(dneto): This doesn't seem general enough? A function might have
408 // more than one such parameter.
David Neto22f144c2017-06-12 14:26:21 -0400409 GlobalConstFuncMapType GlobalConstFuncTypeMap;
410 SmallPtrSet<Value *, 16> GlobalConstArgumentSet;
David Neto1a1a0582017-07-07 12:01:44 -0400411 // An ordered set of pointer types of Base arguments to OpPtrAccessChain,
David Neto85082642018-03-24 06:55:20 -0700412 // or array types, and which point into transparent memory (StorageBuffer
413 // storage class). These will require an ArrayStride decoration.
David Neto1a1a0582017-07-07 12:01:44 -0400414 // See SPV_KHR_variable_pointers rev 13.
David Neto85082642018-03-24 06:55:20 -0700415 TypeList TypesNeedingArrayStride;
David Netoa60b00b2017-09-15 16:34:09 -0400416
417 // This is truly ugly, but works around what look like driver bugs.
418 // For get_local_size, an earlier part of the flow has created a module-scope
419 // variable in Private address space to hold the value for the workgroup
420 // size. Its intializer is a uint3 value marked as builtin WorkgroupSize.
421 // When this is present, save the IDs of the initializer value and variable
422 // in these two variables. We only ever do a vector load from it, and
423 // when we see one of those, substitute just the value of the intializer.
424 // This mimics what Glslang does, and that's what drivers are used to.
David Neto66cfe642018-03-24 06:13:56 -0700425 // TODO(dneto): Remove this once drivers are fixed.
David Netoa60b00b2017-09-15 16:34:09 -0400426 uint32_t WorkgroupSizeValueID;
427 uint32_t WorkgroupSizeVarID;
David Neto26aaf622017-10-23 18:11:53 -0400428
429 // What module-scope variables already have had their binding information
430 // emitted?
431 DenseSet<Value*> GVarWithEmittedBindingInfo;
David Neto85082642018-03-24 06:55:20 -0700432
David Netoc6f3ab22018-04-06 18:02:31 -0400433 // An ordered list of the kernel arguments of type pointer-to-local.
434 using LocalArgList = SmallVector<const Argument*, 8>;
435 LocalArgList LocalArgs;
436 // Information about a pointer-to-local argument.
437 struct LocalArgInfo {
438 // The SPIR-V ID of the array variable.
439 uint32_t variable_id;
440 // The element type of the
441 Type* elem_type;
442 // The ID of the array type.
443 uint32_t array_size_id;
444 // The ID of the array type.
445 uint32_t array_type_id;
446 // The ID of the pointer to the array type.
447 uint32_t ptr_array_type_id;
448 // The ID of the pointer to the first element of the array.
449 uint32_t first_elem_ptr_id;
450 // The specialization constant ID of the array size.
451 int spec_id;
452 };
453 // A mapping from a pointer-to-local argument value to a LocalArgInfo value.
454 DenseMap<const Argument*, LocalArgInfo> LocalArgMap;
455
David Neto85082642018-03-24 06:55:20 -0700456 // The next descriptor set index to use.
457 uint32_t NextDescriptorSetIndex;
David Netoc6f3ab22018-04-06 18:02:31 -0400458
459 // A mapping from pointer-to-local argument to a specialization constant ID
460 // for that argument's array size. This is generated from AllocatArgSpecIds.
461 ArgIdMapType ArgSpecIdMap;
David Neto257c3892018-04-11 13:19:45 -0400462
463 // The ID of 32-bit integer zero constant. This is only valid after
464 // GenerateSPIRVConstants has run.
465 uint32_t constant_i32_zero_id_;
David Neto22f144c2017-06-12 14:26:21 -0400466};
467
468char SPIRVProducerPass::ID;
David Netoc6f3ab22018-04-06 18:02:31 -0400469
David Neto22f144c2017-06-12 14:26:21 -0400470}
471
472namespace clspv {
David Neto44795152017-07-13 15:45:28 -0400473ModulePass *
474createSPIRVProducerPass(raw_pwrite_stream &out, raw_ostream &descriptor_map_out,
475 ArrayRef<std::pair<unsigned, std::string>> samplerMap,
476 bool outputAsm, bool outputCInitList) {
477 return new SPIRVProducerPass(out, descriptor_map_out, samplerMap, outputAsm,
478 outputCInitList);
David Neto22f144c2017-06-12 14:26:21 -0400479}
David Netoc2c368d2017-06-30 16:50:17 -0400480} // namespace clspv
David Neto22f144c2017-06-12 14:26:21 -0400481
482bool SPIRVProducerPass::runOnModule(Module &module) {
David Neto0676e6f2017-07-11 18:47:44 -0400483 binaryOut = outputCInitList ? &binaryTempOut : &out;
484
David Neto257c3892018-04-11 13:19:45 -0400485 constant_i32_zero_id_ = 0; // Reset, for the benefit of validity checks.
486
David Netoc6f3ab22018-04-06 18:02:31 -0400487 ArgSpecIdMap = AllocateArgSpecIds(module);
488
David Neto22f144c2017-06-12 14:26:21 -0400489 // SPIR-V always begins with its header information
490 outputHeader();
491
David Netoc6f3ab22018-04-06 18:02:31 -0400492 const DataLayout &DL = module.getDataLayout();
493
David Neto22f144c2017-06-12 14:26:21 -0400494 // Gather information from the LLVM IR that we require.
David Netoc6f3ab22018-04-06 18:02:31 -0400495 GenerateLLVMIRInfo(module, DL);
David Neto22f144c2017-06-12 14:26:21 -0400496
497 // If we are using a sampler map, find the type of the sampler.
498 if (0 < getSamplerMap().size()) {
499 auto SamplerStructTy = module.getTypeByName("opencl.sampler_t");
500 if (!SamplerStructTy) {
501 SamplerStructTy =
502 StructType::create(module.getContext(), "opencl.sampler_t");
503 }
504
505 SamplerTy = SamplerStructTy->getPointerTo(AddressSpace::UniformConstant);
506
507 FindType(SamplerTy);
508 }
509
510 // Collect information on global variables too.
511 for (GlobalVariable &GV : module.globals()) {
512 // If the GV is one of our special __spirv_* variables, remove the
513 // initializer as it was only placed there to force LLVM to not throw the
514 // value away.
515 if (GV.getName().startswith("__spirv_")) {
516 GV.setInitializer(nullptr);
517 }
518
519 // Collect types' information from global variable.
520 FindTypePerGlobalVar(GV);
521
522 // Collect constant information from global variable.
523 FindConstantPerGlobalVar(GV);
524
525 // If the variable is an input, entry points need to know about it.
526 if (AddressSpace::Input == GV.getType()->getPointerAddressSpace()) {
David Netofb9a7972017-08-25 17:08:24 -0400527 getEntryPointInterfacesVec().insert(&GV);
David Neto22f144c2017-06-12 14:26:21 -0400528 }
529 }
530
David Netoc6f3ab22018-04-06 18:02:31 -0400531 // Find types related to pointer-to-local arguments.
532 for (auto& arg_spec_id_pair : ArgSpecIdMap) {
533 const Argument* arg = arg_spec_id_pair.first;
534 FindType(arg->getType());
535 FindType(arg->getType()->getPointerElementType());
536 }
537
David Neto22f144c2017-06-12 14:26:21 -0400538 // If there are extended instructions, generate OpExtInstImport.
539 if (FindExtInst(module)) {
540 GenerateExtInstImport();
541 }
542
543 // Generate SPIRV instructions for types.
David Netoc6f3ab22018-04-06 18:02:31 -0400544 GenerateSPIRVTypes(module.getContext(), DL);
David Neto22f144c2017-06-12 14:26:21 -0400545
546 // Generate SPIRV constants.
547 GenerateSPIRVConstants();
548
549 // If we have a sampler map, we might have literal samplers to generate.
550 if (0 < getSamplerMap().size()) {
551 GenerateSamplers(module);
552 }
553
554 // Generate SPIRV variables.
555 for (GlobalVariable &GV : module.globals()) {
556 GenerateGlobalVar(GV);
557 }
David Netoc6f3ab22018-04-06 18:02:31 -0400558 GenerateWorkgroupVars();
David Neto22f144c2017-06-12 14:26:21 -0400559
560 // Generate SPIRV instructions for each function.
561 for (Function &F : module) {
562 if (F.isDeclaration()) {
563 continue;
564 }
565
566 // Generate Function Prologue.
567 GenerateFuncPrologue(F);
568
569 // Generate SPIRV instructions for function body.
570 GenerateFuncBody(F);
571
572 // Generate Function Epilogue.
573 GenerateFuncEpilogue();
574 }
575
576 HandleDeferredInstruction();
David Neto1a1a0582017-07-07 12:01:44 -0400577 HandleDeferredDecorations(DL);
David Neto22f144c2017-06-12 14:26:21 -0400578
579 // Generate SPIRV module information.
David Neto5c22a252018-03-15 16:07:41 -0400580 GenerateModuleInfo(module);
David Neto22f144c2017-06-12 14:26:21 -0400581
582 if (outputAsm) {
583 WriteSPIRVAssembly();
584 } else {
585 WriteSPIRVBinary();
586 }
587
588 // We need to patch the SPIR-V header to set bound correctly.
589 patchHeader();
David Neto0676e6f2017-07-11 18:47:44 -0400590
591 if (outputCInitList) {
592 bool first = true;
David Neto0676e6f2017-07-11 18:47:44 -0400593 std::ostringstream os;
594
David Neto57fb0b92017-08-04 15:35:09 -0400595 auto emit_word = [&os, &first](uint32_t word) {
David Neto0676e6f2017-07-11 18:47:44 -0400596 if (!first)
David Neto57fb0b92017-08-04 15:35:09 -0400597 os << ",\n";
598 os << word;
David Neto0676e6f2017-07-11 18:47:44 -0400599 first = false;
600 };
601
602 os << "{";
David Neto57fb0b92017-08-04 15:35:09 -0400603 const std::string str(binaryTempOut.str());
604 for (unsigned i = 0; i < str.size(); i += 4) {
605 const uint32_t a = static_cast<unsigned char>(str[i]);
606 const uint32_t b = static_cast<unsigned char>(str[i + 1]);
607 const uint32_t c = static_cast<unsigned char>(str[i + 2]);
608 const uint32_t d = static_cast<unsigned char>(str[i + 3]);
609 emit_word(a | (b << 8) | (c << 16) | (d << 24));
David Neto0676e6f2017-07-11 18:47:44 -0400610 }
611 os << "}\n";
612 out << os.str();
613 }
614
David Neto22f144c2017-06-12 14:26:21 -0400615 return false;
616}
617
618void SPIRVProducerPass::outputHeader() {
619 if (outputAsm) {
620 // for ASM output the header goes into 5 comments at the beginning of the
621 // file
622 out << "; SPIR-V\n";
623
624 // the major version number is in the 2nd highest byte
625 const uint32_t major = (spv::Version >> 16) & 0xFF;
626
627 // the minor version number is in the 2nd lowest byte
628 const uint32_t minor = (spv::Version >> 8) & 0xFF;
629 out << "; Version: " << major << "." << minor << "\n";
630
631 // use Codeplay's vendor ID
632 out << "; Generator: Codeplay; 0\n";
633
634 out << "; Bound: ";
635
636 // we record where we need to come back to and patch in the bound value
637 patchBoundOffset = out.tell();
638
639 // output one space per digit for the max size of a 32 bit unsigned integer
640 // (which is the maximum ID we could possibly be using)
641 for (uint32_t i = std::numeric_limits<uint32_t>::max(); 0 != i; i /= 10) {
642 out << " ";
643 }
644
645 out << "\n";
646
647 out << "; Schema: 0\n";
648 } else {
David Neto0676e6f2017-07-11 18:47:44 -0400649 binaryOut->write(reinterpret_cast<const char *>(&spv::MagicNumber),
David Neto22f144c2017-06-12 14:26:21 -0400650 sizeof(spv::MagicNumber));
David Neto0676e6f2017-07-11 18:47:44 -0400651 binaryOut->write(reinterpret_cast<const char *>(&spv::Version),
David Neto22f144c2017-06-12 14:26:21 -0400652 sizeof(spv::Version));
653
654 // use Codeplay's vendor ID
655 const uint32_t vendor = 3 << 16;
David Neto0676e6f2017-07-11 18:47:44 -0400656 binaryOut->write(reinterpret_cast<const char *>(&vendor), sizeof(vendor));
David Neto22f144c2017-06-12 14:26:21 -0400657
658 // we record where we need to come back to and patch in the bound value
David Neto0676e6f2017-07-11 18:47:44 -0400659 patchBoundOffset = binaryOut->tell();
David Neto22f144c2017-06-12 14:26:21 -0400660
661 // output a bad bound for now
David Neto0676e6f2017-07-11 18:47:44 -0400662 binaryOut->write(reinterpret_cast<const char *>(&nextID), sizeof(nextID));
David Neto22f144c2017-06-12 14:26:21 -0400663
664 // output the schema (reserved for use and must be 0)
665 const uint32_t schema = 0;
David Neto0676e6f2017-07-11 18:47:44 -0400666 binaryOut->write(reinterpret_cast<const char *>(&schema), sizeof(schema));
David Neto22f144c2017-06-12 14:26:21 -0400667 }
668}
669
670void SPIRVProducerPass::patchHeader() {
671 if (outputAsm) {
672 // get the string representation of the max bound used (nextID will be the
673 // max ID used)
674 auto asString = std::to_string(nextID);
675 out.pwrite(asString.c_str(), asString.size(), patchBoundOffset);
676 } else {
677 // for a binary we just write the value of nextID over bound
David Neto0676e6f2017-07-11 18:47:44 -0400678 binaryOut->pwrite(reinterpret_cast<char *>(&nextID), sizeof(nextID),
679 patchBoundOffset);
David Neto22f144c2017-06-12 14:26:21 -0400680 }
681}
682
David Netoc6f3ab22018-04-06 18:02:31 -0400683void SPIRVProducerPass::GenerateLLVMIRInfo(Module &M, const DataLayout &DL) {
David Neto22f144c2017-06-12 14:26:21 -0400684 // This function generates LLVM IR for function such as global variable for
685 // argument, constant and pointer type for argument access. These information
686 // is artificial one because we need Vulkan SPIR-V output. This function is
687 // executed ahead of FindType and FindConstant.
688 ValueToValueMapTy &ArgGVMap = getArgumentGVMap();
689 LLVMContext &Context = M.getContext();
690
691 // Map for avoiding to generate struct type with same fields.
692 DenseMap<Type *, Type *> ArgTyMap;
693
David Neto5c22a252018-03-15 16:07:41 -0400694 // These function calls need a <2 x i32> as an intermediate result but not
695 // the final result.
696 std::unordered_set<std::string> NeedsIVec2{
697 "_Z15get_image_width14ocl_image2d_ro",
698 "_Z15get_image_width14ocl_image2d_wo",
699 "_Z16get_image_height14ocl_image2d_ro",
700 "_Z16get_image_height14ocl_image2d_wo",
701 };
702
David Neto22f144c2017-06-12 14:26:21 -0400703 // Collect global constant variables.
David Netoc6f3ab22018-04-06 18:02:31 -0400704 {
705 SmallVector<GlobalVariable *, 8> GVList;
706 SmallVector<GlobalVariable *, 8> DeadGVList;
707 for (GlobalVariable &GV : M.globals()) {
708 if (GV.getType()->getAddressSpace() == AddressSpace::Constant) {
709 if (GV.use_empty()) {
710 DeadGVList.push_back(&GV);
711 } else {
712 GVList.push_back(&GV);
713 }
David Netofba9d262018-03-24 06:14:18 -0700714 }
David Neto22f144c2017-06-12 14:26:21 -0400715 }
David Neto22f144c2017-06-12 14:26:21 -0400716
David Netoc6f3ab22018-04-06 18:02:31 -0400717 // Remove dead global __constant variables.
718 for (auto GV : DeadGVList) {
719 GV->eraseFromParent();
David Neto85082642018-03-24 06:55:20 -0700720 }
David Netoc6f3ab22018-04-06 18:02:31 -0400721 DeadGVList.clear();
David Neto22f144c2017-06-12 14:26:21 -0400722
David Netoc6f3ab22018-04-06 18:02:31 -0400723 if (clspv::Option::ModuleConstantsInStorageBuffer()) {
724 // For now, we only support a single storage buffer.
725 if (GVList.size() > 0) {
726 assert(GVList.size() == 1);
727 const auto *GV = GVList[0];
728 const size_t constants_byte_size =
729 (DL.getTypeSizeInBits(GV->getInitializer()->getType())) / 8;
730 const size_t kConstantMaxSize = 65536;
731 if (constants_byte_size > kConstantMaxSize) {
732 outs() << "Max __constant capacity of " << kConstantMaxSize
733 << " bytes exceeded: " << constants_byte_size
734 << " bytes used\n";
735 llvm_unreachable("Max __constant capacity exceeded");
736 }
737 }
738 } else {
739 // Change global constant variable's address space to ModuleScopePrivate.
740 auto &GlobalConstFuncTyMap = getGlobalConstFuncTypeMap();
741 for (auto GV : GVList) {
742 // Create new gv with ModuleScopePrivate address space.
743 Type *NewGVTy = GV->getType()->getPointerElementType();
744 GlobalVariable *NewGV = new GlobalVariable(
745 M, NewGVTy, false, GV->getLinkage(), GV->getInitializer(), "",
746 nullptr, GV->getThreadLocalMode(),
747 AddressSpace::ModuleScopePrivate);
748 NewGV->takeName(GV);
David Neto22f144c2017-06-12 14:26:21 -0400749
David Netoc6f3ab22018-04-06 18:02:31 -0400750 const SmallVector<User *, 8> GVUsers(GV->user_begin(), GV->user_end());
751 SmallVector<User *, 8> CandidateUsers;
752
753 auto record_called_function_type_as_user =
754 [&GlobalConstFuncTyMap](Value *gv, CallInst *call) {
755 // Find argument index.
756 unsigned index = 0;
757 for (unsigned i = 0; i < call->getNumArgOperands(); i++) {
758 if (gv == call->getOperand(i)) {
759 // TODO(dneto): Should we break here?
760 index = i;
761 }
762 }
763
764 // Record function type with global constant.
765 GlobalConstFuncTyMap[call->getFunctionType()] =
766 std::make_pair(call->getFunctionType(), index);
767 };
768
769 for (User *GVU : GVUsers) {
770 if (CallInst *Call = dyn_cast<CallInst>(GVU)) {
771 record_called_function_type_as_user(GV, Call);
772 } else if (GetElementPtrInst *GEP =
773 dyn_cast<GetElementPtrInst>(GVU)) {
774 // Check GEP users.
775 for (User *GEPU : GEP->users()) {
776 if (CallInst *GEPCall = dyn_cast<CallInst>(GEPU)) {
777 record_called_function_type_as_user(GEP, GEPCall);
David Neto85082642018-03-24 06:55:20 -0700778 }
779 }
David Netoc77d9e22018-03-24 06:30:28 -0700780 }
David Netoc6f3ab22018-04-06 18:02:31 -0400781
782 CandidateUsers.push_back(GVU);
David Neto22f144c2017-06-12 14:26:21 -0400783 }
David Neto85082642018-03-24 06:55:20 -0700784
David Netoc6f3ab22018-04-06 18:02:31 -0400785 for (User *U : CandidateUsers) {
786 // Update users of gv with new gv.
787 U->replaceUsesOfWith(GV, NewGV);
788 }
David Neto22f144c2017-06-12 14:26:21 -0400789
David Netoc6f3ab22018-04-06 18:02:31 -0400790 // Delete original gv.
791 GV->eraseFromParent();
David Neto85082642018-03-24 06:55:20 -0700792 }
David Neto22f144c2017-06-12 14:26:21 -0400793 }
David Neto22f144c2017-06-12 14:26:21 -0400794 }
795
796 bool HasWorkGroupBuiltin = false;
797 for (GlobalVariable &GV : M.globals()) {
798 const spv::BuiltIn BuiltinType = GetBuiltin(GV.getName());
799 if (spv::BuiltInWorkgroupSize == BuiltinType) {
800 HasWorkGroupBuiltin = true;
801 }
802 }
803
804
David Neto26aaf622017-10-23 18:11:53 -0400805 // Map kernel functions to their ordinal number in the compilation unit.
806 UniqueVector<Function*> KernelOrdinal;
807
808 // Map the global variables created for kernel args to their creation
809 // order.
810 UniqueVector<GlobalVariable*> KernelArgVarOrdinal;
811
David Netoc6f3ab22018-04-06 18:02:31 -0400812 // For each kernel argument type, record the kernel arg global resource variables
David Neto26aaf622017-10-23 18:11:53 -0400813 // generated for that type, the function in which that variable was most
814 // recently used, and the binding number it took. For reproducibility,
815 // we track things by ordinal number (rather than pointer), and we use a
816 // std::set rather than DenseSet since std::set maintains an ordering.
817 // Each tuple is the ordinals of the kernel function, the binding number,
818 // and the ordinal of the kernal-arg-var.
819 //
820 // This table lets us reuse module-scope StorageBuffer variables between
821 // different kernels.
822 DenseMap<Type *, std::set<std::tuple<unsigned, unsigned, unsigned>>>
823 GVarsForType;
824
David Neto22f144c2017-06-12 14:26:21 -0400825 for (Function &F : M) {
826 // Handle kernel function first.
827 if (F.isDeclaration() || F.getCallingConv() != CallingConv::SPIR_KERNEL) {
828 continue;
829 }
David Neto26aaf622017-10-23 18:11:53 -0400830 KernelOrdinal.insert(&F);
David Neto22f144c2017-06-12 14:26:21 -0400831
832 for (BasicBlock &BB : F) {
833 for (Instruction &I : BB) {
834 if (I.getOpcode() == Instruction::ZExt ||
835 I.getOpcode() == Instruction::SExt ||
836 I.getOpcode() == Instruction::UIToFP) {
837 // If there is zext with i1 type, it will be changed to OpSelect. The
838 // OpSelect needs constant 0 and 1 so the constants are added here.
839
840 auto OpTy = I.getOperand(0)->getType();
841
842 if (OpTy->isIntegerTy(1) ||
843 (OpTy->isVectorTy() &&
844 OpTy->getVectorElementType()->isIntegerTy(1))) {
845 if (I.getOpcode() == Instruction::ZExt) {
846 APInt One(32, 1);
847 FindConstant(Constant::getNullValue(I.getType()));
848 FindConstant(Constant::getIntegerValue(I.getType(), One));
849 } else if (I.getOpcode() == Instruction::SExt) {
850 APInt MinusOne(32, UINT64_MAX, true);
851 FindConstant(Constant::getNullValue(I.getType()));
852 FindConstant(Constant::getIntegerValue(I.getType(), MinusOne));
853 } else {
854 FindConstant(ConstantFP::get(Context, APFloat(0.0f)));
855 FindConstant(ConstantFP::get(Context, APFloat(1.0f)));
856 }
857 }
858 } else if (CallInst *Call = dyn_cast<CallInst>(&I)) {
859 Function *Callee = Call->getCalledFunction();
860
861 // Handle image type specially.
862 if (Callee->getName().equals(
863 "_Z11read_imagef14ocl_image2d_ro11ocl_samplerDv2_f") ||
864 Callee->getName().equals(
865 "_Z11read_imagef14ocl_image3d_ro11ocl_samplerDv4_f")) {
866 TypeMapType &OpImageTypeMap = getImageTypeMap();
867 Type *ImageTy =
868 Call->getArgOperand(0)->getType()->getPointerElementType();
869 OpImageTypeMap[ImageTy] = 0;
870
871 FindConstant(ConstantFP::get(Context, APFloat(0.0f)));
872 }
David Neto5c22a252018-03-15 16:07:41 -0400873
874 if (NeedsIVec2.find(Callee->getName()) != NeedsIVec2.end()) {
875 FindType(VectorType::get(Type::getInt32Ty(Context), 2));
876 }
David Neto22f144c2017-06-12 14:26:21 -0400877 }
878 }
879 }
880
881 if (M.getTypeByName("opencl.image2d_ro_t") ||
882 M.getTypeByName("opencl.image2d_wo_t") ||
883 M.getTypeByName("opencl.image3d_ro_t") ||
884 M.getTypeByName("opencl.image3d_wo_t")) {
885 // Assume Image type's sampled type is float type.
886 FindType(Type::getFloatTy(Context));
887 }
888
889 if (const MDNode *MD =
890 dyn_cast<Function>(&F)->getMetadata("reqd_work_group_size")) {
891 // We generate constants if the WorkgroupSize builtin is being used.
892 if (HasWorkGroupBuiltin) {
893 // Collect constant information for work group size.
894 FindConstant(mdconst::extract<ConstantInt>(MD->getOperand(0)));
895 FindConstant(mdconst::extract<ConstantInt>(MD->getOperand(1)));
896 FindConstant(mdconst::extract<ConstantInt>(MD->getOperand(2)));
897 }
898 }
899
900 // Wrap up all argument types with struct type and create global variables
901 // with them.
902 bool HasArgUser = false;
903 unsigned Idx = 0;
904
905 for (const Argument &Arg : F.args()) {
906 Type *ArgTy = Arg.getType();
David Neto22f144c2017-06-12 14:26:21 -0400907
David Netoe439d702018-03-23 13:14:08 -0700908 // The pointee type of the module scope variable we will make.
909 Type *GVTy = nullptr;
David Neto22f144c2017-06-12 14:26:21 -0400910
911 Type *TmpArgTy = ArgTy;
912
913 // sampler_t and image types have pointer type of struct type with
David Netoe439d702018-03-23 13:14:08 -0700914 // opaque type as field. Extract the struct type. It will be used by
915 // global variable for argument.
David Neto22f144c2017-06-12 14:26:21 -0400916 bool IsSamplerType = false;
917 bool IsImageType = false;
918 if (PointerType *TmpArgPTy = dyn_cast<PointerType>(TmpArgTy)) {
919 if (StructType *STy =
920 dyn_cast<StructType>(TmpArgPTy->getElementType())) {
921 if (STy->isOpaque()) {
922 if (STy->getName().equals("opencl.sampler_t")) {
David Neto22f144c2017-06-12 14:26:21 -0400923 IsSamplerType = true;
924 TmpArgTy = STy;
925 } else if (STy->getName().equals("opencl.image2d_ro_t") ||
926 STy->getName().equals("opencl.image2d_wo_t") ||
927 STy->getName().equals("opencl.image3d_ro_t") ||
928 STy->getName().equals("opencl.image3d_wo_t")) {
David Neto22f144c2017-06-12 14:26:21 -0400929 IsImageType = true;
930 TmpArgTy = STy;
931 } else {
932 llvm_unreachable("Argument has opaque type unsupported???");
933 }
934 }
935 }
936 }
David Netoc6f3ab22018-04-06 18:02:31 -0400937 const bool IsPointerToLocal = IsLocalPtr(ArgTy);
938 // Can't both be pointer-to-local and (sampler or image).
939 assert(!((IsSamplerType || IsImageType) && IsPointerToLocal));
David Neto22f144c2017-06-12 14:26:21 -0400940
David Netoe439d702018-03-23 13:14:08 -0700941 // Determine the address space for the module-scope variable.
942 unsigned AddrSpace = AddressSpace::Global;
943 if (IsSamplerType || IsImageType) {
944 AddrSpace = AddressSpace::UniformConstant;
945 } else if (PointerType *ArgPTy = dyn_cast<PointerType>(ArgTy)) {
946 AddrSpace = ArgPTy->getAddressSpace();
David Neto482550a2018-03-24 05:21:07 -0700947 } else if (clspv::Option::PodArgsInUniformBuffer()) {
David Netoe439d702018-03-23 13:14:08 -0700948 // Use a uniform buffer for POD arguments.
949 AddrSpace = AddressSpace::Uniform;
950 }
951
David Neto22f144c2017-06-12 14:26:21 -0400952 // LLVM's pointer type is distinguished by address space but we need to
953 // regard constant and global address space as same here. If pointer
954 // type has constant address space, generate new pointer type
955 // temporarily to check previous struct type for argument.
956 if (PointerType *TmpArgPTy = dyn_cast<PointerType>(TmpArgTy)) {
David Netoe439d702018-03-23 13:14:08 -0700957 if (TmpArgPTy->getAddressSpace() == AddressSpace::Constant) {
David Neto22f144c2017-06-12 14:26:21 -0400958 TmpArgTy = PointerType::get(TmpArgPTy->getElementType(),
959 AddressSpace::Global);
960 }
961 }
962
963 if (IsSamplerType || IsImageType) {
964 GVTy = TmpArgTy;
David Netoc6f3ab22018-04-06 18:02:31 -0400965 } else if (IsPointerToLocal) {
966 assert(ArgTy == TmpArgTy);
967 auto spec_id = ArgSpecIdMap[&Arg];
968 assert(spec_id > 0);
969 LocalArgMap[&Arg] =
970 LocalArgInfo{nextID, ArgTy->getPointerElementType(),
971 nextID + 1, nextID + 2,
972 nextID + 3, nextID + 4,
973 spec_id};
974 LocalArgs.push_back(&Arg);
975 nextID += 5;
David Neto22f144c2017-06-12 14:26:21 -0400976 } else if (ArgTyMap.count(TmpArgTy)) {
977 // If there are arguments handled previously, use its type.
978 GVTy = ArgTyMap[TmpArgTy];
979 } else {
980 // Wrap up argument type with struct type.
David Neto83add0a2017-10-23 15:30:59 -0400981 // Reuse struct types where possible.
David Neto7b2abea2017-10-23 20:02:02 -0400982 SmallVector<Type*,1> members{ArgTy};
David Neto83add0a2017-10-23 15:30:59 -0400983 StructType *STy = StructType::get(Context, members);
David Neto22f144c2017-06-12 14:26:21 -0400984
985 GVTy = STy;
986 ArgTyMap[TmpArgTy] = STy;
987 }
988
David Netoc6f3ab22018-04-06 18:02:31 -0400989 if (!IsPointerToLocal) {
990 // In order to build type map between llvm type and spirv id, LLVM
991 // global variable is needed. It has llvm type and other instructions
992 // can access it with its type.
993 //
994 // Reuse a global variable if it was created for a different entry
995 // point.
David Neto26aaf622017-10-23 18:11:53 -0400996
David Netoc6f3ab22018-04-06 18:02:31 -0400997 // Returns a new global variable for this kernel argument, and remembers
998 // it in KernelArgVarOrdinal.
999 auto make_gvar = [&]() {
1000 auto result = new GlobalVariable(
1001 M, GVTy, false, GlobalValue::ExternalLinkage,
1002 UndefValue::get(GVTy),
1003 F.getName() + ".arg." + std::to_string(Idx), nullptr,
1004 GlobalValue::ThreadLocalMode::NotThreadLocal, AddrSpace);
1005 KernelArgVarOrdinal.insert(result);
1006 return result;
1007 };
David Neto26aaf622017-10-23 18:11:53 -04001008
David Netoc6f3ab22018-04-06 18:02:31 -04001009 // Make a new variable if there was none for this type, or if we can
1010 // reuse one created for a different function but not yet reused for
1011 // the current function, *and* the binding is the same.
1012 // Always make a new variable if we're forcing distinct descriptor sets.
1013 GlobalVariable *GV = nullptr;
1014 auto which_set = GVarsForType.find(GVTy);
1015 if (IsSamplerType || IsImageType || which_set == GVarsForType.end() ||
1016 clspv::Option::DistinctKernelDescriptorSets()) {
1017 GV = make_gvar();
1018 } else {
1019 auto &set = which_set->second;
1020 // Reuse a variable if it was associated with a different function.
1021 for (auto iter = set.begin(), end = set.end(); iter != end; ++iter) {
1022 const unsigned fn_ordinal = std::get<0>(*iter);
1023 const unsigned binding = std::get<1>(*iter);
1024 if (fn_ordinal != KernelOrdinal.idFor(&F) && binding == Idx) {
1025 GV = KernelArgVarOrdinal[std::get<2>(*iter)];
1026 // Remove it from the set. We'll add it back later.
1027 set.erase(iter);
1028 break;
1029 }
1030 }
1031 if (!GV) {
1032 GV = make_gvar();
David Neto26aaf622017-10-23 18:11:53 -04001033 }
1034 }
David Netoc6f3ab22018-04-06 18:02:31 -04001035 assert(GV);
1036 GVarsForType[GVTy].insert(std::make_tuple(
1037 KernelOrdinal.idFor(&F), Idx, KernelArgVarOrdinal.idFor(GV)));
1038
1039 // Generate type info for argument global variable.
1040 FindType(GV->getType());
1041
1042 ArgGVMap[&Arg] = GV;
1043
1044 Idx++;
David Neto26aaf622017-10-23 18:11:53 -04001045 }
David Neto22f144c2017-06-12 14:26:21 -04001046
1047 // Generate pointer type of argument type for OpAccessChain of argument.
1048 if (!Arg.use_empty()) {
1049 if (!isa<PointerType>(ArgTy)) {
David Netoe439d702018-03-23 13:14:08 -07001050 auto ty = PointerType::get(ArgTy, AddrSpace);
1051 FindType(ty);
David Neto22f144c2017-06-12 14:26:21 -04001052 }
1053 HasArgUser = true;
1054 }
1055 }
1056
1057 if (HasArgUser) {
1058 // Generate constant 0 for OpAccessChain of argument.
1059 Type *IdxTy = Type::getInt32Ty(Context);
1060 FindConstant(ConstantInt::get(IdxTy, 0));
1061 FindType(IdxTy);
1062 }
1063
1064 // Collect types' information from function.
1065 FindTypePerFunc(F);
1066
1067 // Collect constant information from function.
1068 FindConstantPerFunc(F);
1069 }
1070
1071 for (Function &F : M) {
1072 // Handle non-kernel functions.
1073 if (F.isDeclaration() || F.getCallingConv() == CallingConv::SPIR_KERNEL) {
1074 continue;
1075 }
1076
1077 for (BasicBlock &BB : F) {
1078 for (Instruction &I : BB) {
1079 if (I.getOpcode() == Instruction::ZExt ||
1080 I.getOpcode() == Instruction::SExt ||
1081 I.getOpcode() == Instruction::UIToFP) {
1082 // If there is zext with i1 type, it will be changed to OpSelect. The
1083 // OpSelect needs constant 0 and 1 so the constants are added here.
1084
1085 auto OpTy = I.getOperand(0)->getType();
1086
1087 if (OpTy->isIntegerTy(1) ||
1088 (OpTy->isVectorTy() &&
1089 OpTy->getVectorElementType()->isIntegerTy(1))) {
1090 if (I.getOpcode() == Instruction::ZExt) {
1091 APInt One(32, 1);
1092 FindConstant(Constant::getNullValue(I.getType()));
1093 FindConstant(Constant::getIntegerValue(I.getType(), One));
1094 } else if (I.getOpcode() == Instruction::SExt) {
1095 APInt MinusOne(32, UINT64_MAX, true);
1096 FindConstant(Constant::getNullValue(I.getType()));
1097 FindConstant(Constant::getIntegerValue(I.getType(), MinusOne));
1098 } else {
1099 FindConstant(ConstantFP::get(Context, APFloat(0.0f)));
1100 FindConstant(ConstantFP::get(Context, APFloat(1.0f)));
1101 }
1102 }
1103 } else if (CallInst *Call = dyn_cast<CallInst>(&I)) {
1104 Function *Callee = Call->getCalledFunction();
1105
1106 // Handle image type specially.
1107 if (Callee->getName().equals(
1108 "_Z11read_imagef14ocl_image2d_ro11ocl_samplerDv2_f") ||
1109 Callee->getName().equals(
1110 "_Z11read_imagef14ocl_image3d_ro11ocl_samplerDv4_f")) {
1111 TypeMapType &OpImageTypeMap = getImageTypeMap();
1112 Type *ImageTy =
1113 Call->getArgOperand(0)->getType()->getPointerElementType();
1114 OpImageTypeMap[ImageTy] = 0;
1115
1116 FindConstant(ConstantFP::get(Context, APFloat(0.0f)));
1117 }
1118 }
1119 }
1120 }
1121
1122 if (M.getTypeByName("opencl.image2d_ro_t") ||
1123 M.getTypeByName("opencl.image2d_wo_t") ||
1124 M.getTypeByName("opencl.image3d_ro_t") ||
1125 M.getTypeByName("opencl.image3d_wo_t")) {
1126 // Assume Image type's sampled type is float type.
1127 FindType(Type::getFloatTy(Context));
1128 }
1129
1130 // Collect types' information from function.
1131 FindTypePerFunc(F);
1132
1133 // Collect constant information from function.
1134 FindConstantPerFunc(F);
1135 }
1136}
1137
1138bool SPIRVProducerPass::FindExtInst(Module &M) {
1139 LLVMContext &Context = M.getContext();
1140 bool HasExtInst = false;
1141
1142 for (Function &F : M) {
1143 for (BasicBlock &BB : F) {
1144 for (Instruction &I : BB) {
1145 if (CallInst *Call = dyn_cast<CallInst>(&I)) {
1146 Function *Callee = Call->getCalledFunction();
1147 // Check whether this call is for extend instructions.
David Neto3fbb4072017-10-16 11:28:14 -04001148 auto callee_name = Callee->getName();
1149 const glsl::ExtInst EInst = getExtInstEnum(callee_name);
1150 const glsl::ExtInst IndirectEInst =
1151 getIndirectExtInstEnum(callee_name);
David Neto22f144c2017-06-12 14:26:21 -04001152
David Neto3fbb4072017-10-16 11:28:14 -04001153 HasExtInst |=
1154 (EInst != kGlslExtInstBad) || (IndirectEInst != kGlslExtInstBad);
1155
1156 if (IndirectEInst) {
1157 // Register extra constants if needed.
1158
1159 // Registers a type and constant for computing the result of the
1160 // given instruction. If the result of the instruction is a vector,
1161 // then make a splat vector constant with the same number of
1162 // elements.
1163 auto register_constant = [this, &I](Constant *constant) {
1164 FindType(constant->getType());
1165 FindConstant(constant);
1166 if (auto *vectorTy = dyn_cast<VectorType>(I.getType())) {
1167 // Register the splat vector of the value with the same
1168 // width as the result of the instruction.
1169 auto *vec_constant = ConstantVector::getSplat(
1170 static_cast<unsigned>(vectorTy->getNumElements()),
1171 constant);
1172 FindConstant(vec_constant);
1173 FindType(vec_constant->getType());
1174 }
1175 };
1176 switch (IndirectEInst) {
1177 case glsl::ExtInstFindUMsb:
1178 // clz needs OpExtInst and OpISub with constant 31, or splat
1179 // vector of 31. Add it to the constant list here.
1180 register_constant(
1181 ConstantInt::get(Type::getInt32Ty(Context), 31));
1182 break;
1183 case glsl::ExtInstAcos:
1184 case glsl::ExtInstAsin:
1185 case glsl::ExtInstAtan2:
1186 // We need 1/pi for acospi, asinpi, atan2pi.
1187 register_constant(
1188 ConstantFP::get(Type::getFloatTy(Context), kOneOverPi));
1189 break;
1190 default:
1191 assert(false && "internally inconsistent");
1192 }
David Neto22f144c2017-06-12 14:26:21 -04001193 }
1194 }
1195 }
1196 }
1197 }
1198
1199 return HasExtInst;
1200}
1201
1202void SPIRVProducerPass::FindTypePerGlobalVar(GlobalVariable &GV) {
1203 // Investigate global variable's type.
1204 FindType(GV.getType());
1205}
1206
1207void SPIRVProducerPass::FindTypePerFunc(Function &F) {
1208 // Investigate function's type.
1209 FunctionType *FTy = F.getFunctionType();
1210
1211 if (F.getCallingConv() != CallingConv::SPIR_KERNEL) {
1212 auto &GlobalConstFuncTyMap = getGlobalConstFuncTypeMap();
David Neto9ed8e2f2018-03-24 06:47:24 -07001213 // Handle a regular function with global constant parameters.
David Neto22f144c2017-06-12 14:26:21 -04001214 if (GlobalConstFuncTyMap.count(FTy)) {
1215 uint32_t GVCstArgIdx = GlobalConstFuncTypeMap[FTy].second;
1216 SmallVector<Type *, 4> NewFuncParamTys;
1217 for (unsigned i = 0; i < FTy->getNumParams(); i++) {
1218 Type *ParamTy = FTy->getParamType(i);
1219 if (i == GVCstArgIdx) {
1220 Type *EleTy = ParamTy->getPointerElementType();
1221 ParamTy = PointerType::get(EleTy, AddressSpace::ModuleScopePrivate);
1222 }
1223
1224 NewFuncParamTys.push_back(ParamTy);
1225 }
1226
1227 FunctionType *NewFTy =
1228 FunctionType::get(FTy->getReturnType(), NewFuncParamTys, false);
1229 GlobalConstFuncTyMap[FTy] = std::make_pair(NewFTy, GVCstArgIdx);
1230 FTy = NewFTy;
1231 }
1232
1233 FindType(FTy);
1234 } else {
1235 // As kernel functions do not have parameters, create new function type and
1236 // add it to type map.
1237 SmallVector<Type *, 4> NewFuncParamTys;
1238 FunctionType *NewFTy =
1239 FunctionType::get(FTy->getReturnType(), NewFuncParamTys, false);
1240 FindType(NewFTy);
1241 }
1242
1243 // Investigate instructions' type in function body.
1244 for (BasicBlock &BB : F) {
1245 for (Instruction &I : BB) {
1246 if (isa<ShuffleVectorInst>(I)) {
1247 for (unsigned i = 0; i < I.getNumOperands(); i++) {
1248 // Ignore type for mask of shuffle vector instruction.
1249 if (i == 2) {
1250 continue;
1251 }
1252
1253 Value *Op = I.getOperand(i);
1254 if (!isa<MetadataAsValue>(Op)) {
1255 FindType(Op->getType());
1256 }
1257 }
1258
1259 FindType(I.getType());
1260 continue;
1261 }
1262
1263 // Work through the operands of the instruction.
1264 for (unsigned i = 0; i < I.getNumOperands(); i++) {
1265 Value *const Op = I.getOperand(i);
1266 // If any of the operands is a constant, find the type!
1267 if (isa<Constant>(Op) && !isa<GlobalValue>(Op)) {
1268 FindType(Op->getType());
1269 }
1270 }
1271
1272 for (Use &Op : I.operands()) {
1273 if (CallInst *Call = dyn_cast<CallInst>(&I)) {
1274 // Avoid to check call instruction's type.
1275 break;
1276 }
1277 if (!isa<MetadataAsValue>(&Op)) {
1278 FindType(Op->getType());
1279 continue;
1280 }
1281 }
1282
1283 CallInst *Call = dyn_cast<CallInst>(&I);
1284
1285 // We don't want to track the type of this call as we are going to replace
1286 // it.
1287 if (Call && ("__translate_sampler_initializer" ==
1288 Call->getCalledFunction()->getName())) {
1289 continue;
1290 }
1291
1292 if (GetElementPtrInst *GEP = dyn_cast<GetElementPtrInst>(&I)) {
1293 // If gep's base operand has ModuleScopePrivate address space, make gep
1294 // return ModuleScopePrivate address space.
1295 if (GEP->getPointerAddressSpace() == AddressSpace::ModuleScopePrivate) {
1296 // Add pointer type with private address space for global constant to
1297 // type list.
1298 Type *EleTy = I.getType()->getPointerElementType();
1299 Type *NewPTy =
1300 PointerType::get(EleTy, AddressSpace::ModuleScopePrivate);
1301
1302 FindType(NewPTy);
1303 continue;
1304 }
1305 }
1306
1307 FindType(I.getType());
1308 }
1309 }
1310}
1311
1312void SPIRVProducerPass::FindType(Type *Ty) {
1313 TypeList &TyList = getTypeList();
1314
1315 if (0 != TyList.idFor(Ty)) {
1316 return;
1317 }
1318
1319 if (Ty->isPointerTy()) {
1320 auto AddrSpace = Ty->getPointerAddressSpace();
1321 if ((AddressSpace::Constant == AddrSpace) ||
1322 (AddressSpace::Global == AddrSpace)) {
1323 auto PointeeTy = Ty->getPointerElementType();
1324
1325 if (PointeeTy->isStructTy() &&
1326 dyn_cast<StructType>(PointeeTy)->isOpaque()) {
1327 FindType(PointeeTy);
1328 auto ActualPointerTy =
1329 PointeeTy->getPointerTo(AddressSpace::UniformConstant);
1330 FindType(ActualPointerTy);
1331 return;
1332 }
1333 }
1334 }
1335
1336 // OpTypeArray has constant and we need to support type of the constant.
1337 if (isa<ArrayType>(Ty)) {
1338 LLVMContext &Context = Ty->getContext();
1339 FindType(Type::getInt32Ty(Context));
1340 }
1341
1342 for (Type *SubTy : Ty->subtypes()) {
1343 FindType(SubTy);
1344 }
1345
1346 TyList.insert(Ty);
1347}
1348
1349void SPIRVProducerPass::FindConstantPerGlobalVar(GlobalVariable &GV) {
1350 // If the global variable has a (non undef) initializer.
1351 if (GV.hasInitializer() && !isa<UndefValue>(GV.getInitializer())) {
1352 FindConstant(GV.getInitializer());
1353 }
1354}
1355
1356void SPIRVProducerPass::FindConstantPerFunc(Function &F) {
1357 // Investigate constants in function body.
1358 for (BasicBlock &BB : F) {
1359 for (Instruction &I : BB) {
1360 CallInst *Call = dyn_cast<CallInst>(&I);
1361
1362 if (Call && ("__translate_sampler_initializer" ==
1363 Call->getCalledFunction()->getName())) {
1364 // We've handled these constants elsewhere, so skip it.
1365 continue;
1366 }
1367
1368 if (isa<AllocaInst>(I)) {
1369 // Alloca instruction has constant for the number of element. Ignore it.
1370 continue;
1371 } else if (isa<ShuffleVectorInst>(I)) {
1372 for (unsigned i = 0; i < I.getNumOperands(); i++) {
1373 // Ignore constant for mask of shuffle vector instruction.
1374 if (i == 2) {
1375 continue;
1376 }
1377
1378 if (isa<Constant>(I.getOperand(i)) &&
1379 !isa<GlobalValue>(I.getOperand(i))) {
1380 FindConstant(I.getOperand(i));
1381 }
1382 }
1383
1384 continue;
1385 } else if (isa<InsertElementInst>(I)) {
1386 // Handle InsertElement with <4 x i8> specially.
1387 Type *CompositeTy = I.getOperand(0)->getType();
1388 if (is4xi8vec(CompositeTy)) {
1389 LLVMContext &Context = CompositeTy->getContext();
1390 if (isa<Constant>(I.getOperand(0))) {
1391 FindConstant(I.getOperand(0));
1392 }
1393
1394 if (isa<Constant>(I.getOperand(1))) {
1395 FindConstant(I.getOperand(1));
1396 }
1397
1398 // Add mask constant 0xFF.
1399 Constant *CstFF = ConstantInt::get(Type::getInt32Ty(Context), 0xFF);
1400 FindConstant(CstFF);
1401
1402 // Add shift amount constant.
1403 if (ConstantInt *CI = dyn_cast<ConstantInt>(I.getOperand(2))) {
1404 uint64_t Idx = CI->getZExtValue();
1405 Constant *CstShiftAmount =
1406 ConstantInt::get(Type::getInt32Ty(Context), Idx * 8);
1407 FindConstant(CstShiftAmount);
1408 }
1409
1410 continue;
1411 }
1412
1413 for (unsigned i = 0; i < I.getNumOperands(); i++) {
1414 // Ignore constant for index of InsertElement instruction.
1415 if (i == 2) {
1416 continue;
1417 }
1418
1419 if (isa<Constant>(I.getOperand(i)) &&
1420 !isa<GlobalValue>(I.getOperand(i))) {
1421 FindConstant(I.getOperand(i));
1422 }
1423 }
1424
1425 continue;
1426 } else if (isa<ExtractElementInst>(I)) {
1427 // Handle ExtractElement with <4 x i8> specially.
1428 Type *CompositeTy = I.getOperand(0)->getType();
1429 if (is4xi8vec(CompositeTy)) {
1430 LLVMContext &Context = CompositeTy->getContext();
1431 if (isa<Constant>(I.getOperand(0))) {
1432 FindConstant(I.getOperand(0));
1433 }
1434
1435 // Add mask constant 0xFF.
1436 Constant *CstFF = ConstantInt::get(Type::getInt32Ty(Context), 0xFF);
1437 FindConstant(CstFF);
1438
1439 // Add shift amount constant.
1440 if (ConstantInt *CI = dyn_cast<ConstantInt>(I.getOperand(1))) {
1441 uint64_t Idx = CI->getZExtValue();
1442 Constant *CstShiftAmount =
1443 ConstantInt::get(Type::getInt32Ty(Context), Idx * 8);
1444 FindConstant(CstShiftAmount);
1445 } else {
1446 ConstantInt *Cst8 = ConstantInt::get(Type::getInt32Ty(Context), 8);
1447 FindConstant(Cst8);
1448 }
1449
1450 continue;
1451 }
1452
1453 for (unsigned i = 0; i < I.getNumOperands(); i++) {
1454 // Ignore constant for index of ExtractElement instruction.
1455 if (i == 1) {
1456 continue;
1457 }
1458
1459 if (isa<Constant>(I.getOperand(i)) &&
1460 !isa<GlobalValue>(I.getOperand(i))) {
1461 FindConstant(I.getOperand(i));
1462 }
1463 }
1464
1465 continue;
1466 } else if ((Instruction::Xor == I.getOpcode()) && I.getType()->isIntegerTy(1)) {
1467 // We special case for Xor where the type is i1 and one of the arguments is a constant 1 (true), this is an OpLogicalNot in SPIR-V, and we don't need the constant
1468 bool foundConstantTrue = false;
1469 for (Use &Op : I.operands()) {
1470 if (isa<Constant>(Op) && !isa<GlobalValue>(Op)) {
1471 auto CI = cast<ConstantInt>(Op);
1472
1473 if (CI->isZero() || foundConstantTrue) {
1474 // If we already found the true constant, we might (probably only on -O0) have an OpLogicalNot which is taking a constant argument, so discover it anyway.
1475 FindConstant(Op);
1476 } else {
1477 foundConstantTrue = true;
1478 }
1479 }
1480 }
1481
1482 continue;
David Netod2de94a2017-08-28 17:27:47 -04001483 } else if (isa<TruncInst>(I)) {
1484 // For truncation to i8 we mask against 255.
1485 Type *ToTy = I.getType();
1486 if (8u == ToTy->getPrimitiveSizeInBits()) {
1487 LLVMContext &Context = ToTy->getContext();
1488 Constant *Cst255 = ConstantInt::get(Type::getInt32Ty(Context), 0xff);
1489 FindConstant(Cst255);
1490 }
1491 // Fall through.
Neil Henning39672102017-09-29 14:33:13 +01001492 } else if (isa<AtomicRMWInst>(I)) {
1493 LLVMContext &Context = I.getContext();
1494
1495 FindConstant(
1496 ConstantInt::get(Type::getInt32Ty(Context), spv::ScopeDevice));
1497 FindConstant(ConstantInt::get(
1498 Type::getInt32Ty(Context),
1499 spv::MemorySemanticsUniformMemoryMask |
1500 spv::MemorySemanticsSequentiallyConsistentMask));
David Neto22f144c2017-06-12 14:26:21 -04001501 }
1502
1503 for (Use &Op : I.operands()) {
1504 if (isa<Constant>(Op) && !isa<GlobalValue>(Op)) {
1505 FindConstant(Op);
1506 }
1507 }
1508 }
1509 }
1510}
1511
1512void SPIRVProducerPass::FindConstant(Value *V) {
David Neto22f144c2017-06-12 14:26:21 -04001513 ValueList &CstList = getConstantList();
1514
David Netofb9a7972017-08-25 17:08:24 -04001515 // If V is already tracked, ignore it.
1516 if (0 != CstList.idFor(V)) {
David Neto22f144c2017-06-12 14:26:21 -04001517 return;
1518 }
1519
1520 Constant *Cst = cast<Constant>(V);
1521
1522 // Handle constant with <4 x i8> type specially.
1523 Type *CstTy = Cst->getType();
1524 if (is4xi8vec(CstTy)) {
1525 if (!isa<GlobalValue>(V)) {
David Netofb9a7972017-08-25 17:08:24 -04001526 CstList.insert(V);
David Neto22f144c2017-06-12 14:26:21 -04001527 }
1528 }
1529
1530 if (Cst->getNumOperands()) {
1531 for (User::const_op_iterator I = Cst->op_begin(), E = Cst->op_end(); I != E;
1532 ++I) {
1533 FindConstant(*I);
1534 }
1535
David Netofb9a7972017-08-25 17:08:24 -04001536 CstList.insert(Cst);
David Neto22f144c2017-06-12 14:26:21 -04001537 return;
1538 } else if (const ConstantDataSequential *CDS =
1539 dyn_cast<ConstantDataSequential>(Cst)) {
1540 // Add constants for each element to constant list.
1541 for (unsigned i = 0; i < CDS->getNumElements(); i++) {
1542 Constant *EleCst = CDS->getElementAsConstant(i);
1543 FindConstant(EleCst);
1544 }
1545 }
1546
1547 if (!isa<GlobalValue>(V)) {
David Netofb9a7972017-08-25 17:08:24 -04001548 CstList.insert(V);
David Neto22f144c2017-06-12 14:26:21 -04001549 }
1550}
1551
1552spv::StorageClass SPIRVProducerPass::GetStorageClass(unsigned AddrSpace) const {
1553 switch (AddrSpace) {
1554 default:
1555 llvm_unreachable("Unsupported OpenCL address space");
1556 case AddressSpace::Private:
1557 return spv::StorageClassFunction;
1558 case AddressSpace::Global:
1559 case AddressSpace::Constant:
1560 return spv::StorageClassStorageBuffer;
1561 case AddressSpace::Input:
1562 return spv::StorageClassInput;
1563 case AddressSpace::Local:
1564 return spv::StorageClassWorkgroup;
1565 case AddressSpace::UniformConstant:
1566 return spv::StorageClassUniformConstant;
David Neto9ed8e2f2018-03-24 06:47:24 -07001567 case AddressSpace::Uniform:
David Netoe439d702018-03-23 13:14:08 -07001568 return spv::StorageClassUniform;
David Neto22f144c2017-06-12 14:26:21 -04001569 case AddressSpace::ModuleScopePrivate:
1570 return spv::StorageClassPrivate;
1571 }
1572}
1573
1574spv::BuiltIn SPIRVProducerPass::GetBuiltin(StringRef Name) const {
1575 return StringSwitch<spv::BuiltIn>(Name)
1576 .Case("__spirv_GlobalInvocationId", spv::BuiltInGlobalInvocationId)
1577 .Case("__spirv_LocalInvocationId", spv::BuiltInLocalInvocationId)
1578 .Case("__spirv_WorkgroupSize", spv::BuiltInWorkgroupSize)
1579 .Case("__spirv_NumWorkgroups", spv::BuiltInNumWorkgroups)
1580 .Case("__spirv_WorkgroupId", spv::BuiltInWorkgroupId)
1581 .Default(spv::BuiltInMax);
1582}
1583
1584void SPIRVProducerPass::GenerateExtInstImport() {
1585 SPIRVInstructionList &SPIRVInstList = getSPIRVInstList();
1586 uint32_t &ExtInstImportID = getOpExtInstImportID();
1587
1588 //
1589 // Generate OpExtInstImport.
1590 //
1591 // Ops[0] ... Ops[n] = Name (Literal String)
David Neto22f144c2017-06-12 14:26:21 -04001592 ExtInstImportID = nextID;
David Neto87846742018-04-11 17:36:22 -04001593 SPIRVInstList.push_back(new SPIRVInstruction(spv::OpExtInstImport, nextID++,
1594 MkString("GLSL.std.450")));
David Neto22f144c2017-06-12 14:26:21 -04001595}
1596
David Netoc6f3ab22018-04-06 18:02:31 -04001597void SPIRVProducerPass::GenerateSPIRVTypes(LLVMContext& Context, const DataLayout &DL) {
David Neto22f144c2017-06-12 14:26:21 -04001598 SPIRVInstructionList &SPIRVInstList = getSPIRVInstList();
1599 ValueMapType &VMap = getValueMap();
1600 ValueMapType &AllocatedVMap = getAllocatedValueMap();
1601 ValueToValueMapTy &ArgGVMap = getArgumentGVMap();
1602
1603 // Map for OpTypeRuntimeArray. If argument has pointer type, 2 spirv type
1604 // instructions are generated. They are OpTypePointer and OpTypeRuntimeArray.
1605 DenseMap<Type *, uint32_t> OpRuntimeTyMap;
1606
1607 for (Type *Ty : getTypeList()) {
1608 // Update TypeMap with nextID for reference later.
1609 TypeMap[Ty] = nextID;
1610
1611 switch (Ty->getTypeID()) {
1612 default: {
1613 Ty->print(errs());
1614 llvm_unreachable("Unsupported type???");
1615 break;
1616 }
1617 case Type::MetadataTyID:
1618 case Type::LabelTyID: {
1619 // Ignore these types.
1620 break;
1621 }
1622 case Type::PointerTyID: {
1623 PointerType *PTy = cast<PointerType>(Ty);
1624 unsigned AddrSpace = PTy->getAddressSpace();
1625
1626 // For the purposes of our Vulkan SPIR-V type system, constant and global
1627 // are conflated.
1628 bool UseExistingOpTypePointer = false;
1629 if (AddressSpace::Constant == AddrSpace) {
1630 AddrSpace = AddressSpace::Global;
1631
1632 // Check to see if we already created this type (for instance, if we had
1633 // a constant <type>* and a global <type>*, the type would be created by
1634 // one of these types, and shared by both).
1635 auto GlobalTy = PTy->getPointerElementType()->getPointerTo(AddrSpace);
1636 if (0 < TypeMap.count(GlobalTy)) {
1637 TypeMap[PTy] = TypeMap[GlobalTy];
David Netoe439d702018-03-23 13:14:08 -07001638 UseExistingOpTypePointer = true;
David Neto22f144c2017-06-12 14:26:21 -04001639 break;
1640 }
1641 } else if (AddressSpace::Global == AddrSpace) {
1642 AddrSpace = AddressSpace::Constant;
1643
1644 // Check to see if we already created this type (for instance, if we had
1645 // a constant <type>* and a global <type>*, the type would be created by
1646 // one of these types, and shared by both).
1647 auto ConstantTy = PTy->getPointerElementType()->getPointerTo(AddrSpace);
1648 if (0 < TypeMap.count(ConstantTy)) {
1649 TypeMap[PTy] = TypeMap[ConstantTy];
1650 UseExistingOpTypePointer = true;
1651 }
1652 }
1653
1654 bool IsOpTypeRuntimeArray = false;
1655 bool HasArgUser = false;
1656
1657 for (auto ArgGV : ArgGVMap) {
1658 auto Arg = ArgGV.first;
1659
1660 Type *ArgTy = Arg->getType();
1661 if (ArgTy == PTy) {
1662 if (AddrSpace != AddressSpace::UniformConstant) {
1663 IsOpTypeRuntimeArray = true;
1664 }
1665
1666 for (auto U : Arg->users()) {
1667 if (!isa<GetElementPtrInst>(U) || (U->getType() == PTy)) {
1668 HasArgUser = true;
1669 break;
1670 }
1671 }
1672 }
1673 }
1674
1675 if ((!IsOpTypeRuntimeArray || HasArgUser) && !UseExistingOpTypePointer) {
1676 //
1677 // Generate OpTypePointer.
1678 //
1679
1680 // OpTypePointer
1681 // Ops[0] = Storage Class
1682 // Ops[1] = Element Type ID
1683 SPIRVOperandList Ops;
1684
David Neto257c3892018-04-11 13:19:45 -04001685 Ops << MkNum(GetStorageClass(AddrSpace))
1686 << MkId(lookupType(PTy->getElementType()));
David Neto22f144c2017-06-12 14:26:21 -04001687
David Neto87846742018-04-11 17:36:22 -04001688 auto *Inst = new SPIRVInstruction(spv::OpTypePointer, nextID++, Ops);
David Neto22f144c2017-06-12 14:26:21 -04001689 SPIRVInstList.push_back(Inst);
1690 }
1691
1692 if (IsOpTypeRuntimeArray) {
1693 //
1694 // Generate OpTypeRuntimeArray.
1695 //
1696
1697 // OpTypeRuntimeArray
1698 // Ops[0] = Element Type ID
1699 SPIRVOperandList Ops;
1700
David Neto257c3892018-04-11 13:19:45 -04001701 Type *EleTy = PTy->getElementType();
1702 Ops << MkId(lookupType(EleTy));
David Neto22f144c2017-06-12 14:26:21 -04001703
David Neto22f144c2017-06-12 14:26:21 -04001704 uint32_t OpTypeRuntimeArrayID = nextID;
1705 assert(0 == OpRuntimeTyMap.count(Ty));
1706 OpRuntimeTyMap[Ty] = nextID;
1707
David Neto87846742018-04-11 17:36:22 -04001708 auto *Inst =
1709 new SPIRVInstruction(spv::OpTypeRuntimeArray, nextID++, Ops);
David Neto22f144c2017-06-12 14:26:21 -04001710 SPIRVInstList.push_back(Inst);
1711
1712 // Generate OpDecorate.
1713 auto DecoInsertPoint =
1714 std::find_if(SPIRVInstList.begin(), SPIRVInstList.end(),
1715 [](SPIRVInstruction *Inst) -> bool {
1716 return Inst->getOpcode() != spv::OpDecorate &&
1717 Inst->getOpcode() != spv::OpMemberDecorate &&
1718 Inst->getOpcode() != spv::OpExtInstImport;
1719 });
1720
1721 // Ops[0] = Target ID
1722 // Ops[1] = Decoration (ArrayStride)
1723 // Ops[2] = Stride Number(Literal Number)
1724 Ops.clear();
1725
David Neto257c3892018-04-11 13:19:45 -04001726 Ops << MkId(OpTypeRuntimeArrayID) << MkNum(spv::DecorationArrayStride)
1727 << MkNum(static_cast<uint32_t>(DL.getTypeAllocSize(EleTy)));
David Neto22f144c2017-06-12 14:26:21 -04001728
David Neto87846742018-04-11 17:36:22 -04001729 auto *DecoInst = new SPIRVInstruction(spv::OpDecorate, Ops);
David Neto22f144c2017-06-12 14:26:21 -04001730 SPIRVInstList.insert(DecoInsertPoint, DecoInst);
1731 }
1732 break;
1733 }
1734 case Type::StructTyID: {
1735 LLVMContext &Context = Ty->getContext();
1736
1737 StructType *STy = cast<StructType>(Ty);
1738
1739 // Handle sampler type.
1740 if (STy->isOpaque()) {
1741 if (STy->getName().equals("opencl.sampler_t")) {
1742 //
1743 // Generate OpTypeSampler
1744 //
1745 // Empty Ops.
1746 SPIRVOperandList Ops;
1747
David Neto87846742018-04-11 17:36:22 -04001748 auto *Inst = new SPIRVInstruction(spv::OpTypeSampler, nextID++, Ops);
David Neto22f144c2017-06-12 14:26:21 -04001749 SPIRVInstList.push_back(Inst);
1750 break;
1751 } else if (STy->getName().equals("opencl.image2d_ro_t") ||
1752 STy->getName().equals("opencl.image2d_wo_t") ||
1753 STy->getName().equals("opencl.image3d_ro_t") ||
1754 STy->getName().equals("opencl.image3d_wo_t")) {
1755 //
1756 // Generate OpTypeImage
1757 //
1758 // Ops[0] = Sampled Type ID
1759 // Ops[1] = Dim ID
1760 // Ops[2] = Depth (Literal Number)
1761 // Ops[3] = Arrayed (Literal Number)
1762 // Ops[4] = MS (Literal Number)
1763 // Ops[5] = Sampled (Literal Number)
1764 // Ops[6] = Image Format ID
1765 //
1766 SPIRVOperandList Ops;
1767
1768 // TODO: Changed Sampled Type according to situations.
1769 uint32_t SampledTyID = lookupType(Type::getFloatTy(Context));
David Neto257c3892018-04-11 13:19:45 -04001770 Ops << MkId(SampledTyID);
David Neto22f144c2017-06-12 14:26:21 -04001771
1772 spv::Dim DimID = spv::Dim2D;
1773 if (STy->getName().equals("opencl.image3d_ro_t") ||
1774 STy->getName().equals("opencl.image3d_wo_t")) {
1775 DimID = spv::Dim3D;
1776 }
David Neto257c3892018-04-11 13:19:45 -04001777 Ops << MkNum(DimID);
David Neto22f144c2017-06-12 14:26:21 -04001778
1779 // TODO: Set up Depth.
David Neto257c3892018-04-11 13:19:45 -04001780 Ops << MkNum(0);
David Neto22f144c2017-06-12 14:26:21 -04001781
1782 // TODO: Set up Arrayed.
David Neto257c3892018-04-11 13:19:45 -04001783 Ops << MkNum(0);
David Neto22f144c2017-06-12 14:26:21 -04001784
1785 // TODO: Set up MS.
David Neto257c3892018-04-11 13:19:45 -04001786 Ops << MkNum(0);
David Neto22f144c2017-06-12 14:26:21 -04001787
1788 // TODO: Set up Sampled.
1789 //
1790 // From Spec
1791 //
1792 // 0 indicates this is only known at run time, not at compile time
1793 // 1 indicates will be used with sampler
1794 // 2 indicates will be used without a sampler (a storage image)
1795 uint32_t Sampled = 1;
1796 if (STy->getName().equals("opencl.image2d_wo_t") ||
1797 STy->getName().equals("opencl.image3d_wo_t")) {
1798 Sampled = 2;
1799 }
David Neto257c3892018-04-11 13:19:45 -04001800 Ops << MkNum(Sampled);
David Neto22f144c2017-06-12 14:26:21 -04001801
1802 // TODO: Set up Image Format.
David Neto257c3892018-04-11 13:19:45 -04001803 Ops << MkNum(spv::ImageFormatUnknown);
David Neto22f144c2017-06-12 14:26:21 -04001804
David Neto87846742018-04-11 17:36:22 -04001805 auto *Inst = new SPIRVInstruction(spv::OpTypeImage, nextID++, Ops);
David Neto22f144c2017-06-12 14:26:21 -04001806 SPIRVInstList.push_back(Inst);
1807 break;
1808 }
1809 }
1810
1811 //
1812 // Generate OpTypeStruct
1813 //
1814 // Ops[0] ... Ops[n] = Member IDs
1815 SPIRVOperandList Ops;
1816
1817 for (auto *EleTy : STy->elements()) {
1818 uint32_t EleTyID = lookupType(EleTy);
1819
1820 // Check OpTypeRuntimeArray.
1821 if (isa<PointerType>(EleTy)) {
David Netoc6f3ab22018-04-06 18:02:31 -04001822 // TODO(dneto): Isn't this a straight lookup instead of a loop?
David Neto22f144c2017-06-12 14:26:21 -04001823 for (auto ArgGV : ArgGVMap) {
1824 Type *ArgTy = ArgGV.first->getType();
1825 if (ArgTy == EleTy) {
1826 assert(0 != OpRuntimeTyMap.count(EleTy));
1827 EleTyID = OpRuntimeTyMap[EleTy];
1828 }
1829 }
1830 }
1831
David Neto257c3892018-04-11 13:19:45 -04001832 Ops << MkId(EleTyID);
David Neto22f144c2017-06-12 14:26:21 -04001833 }
1834
David Neto22f144c2017-06-12 14:26:21 -04001835 uint32_t STyID = nextID;
1836
David Neto87846742018-04-11 17:36:22 -04001837 auto *Inst =
1838 new SPIRVInstruction(spv::OpTypeStruct, nextID++, Ops);
David Neto22f144c2017-06-12 14:26:21 -04001839 SPIRVInstList.push_back(Inst);
1840
1841 // Generate OpMemberDecorate.
1842 auto DecoInsertPoint =
1843 std::find_if(SPIRVInstList.begin(), SPIRVInstList.end(),
1844 [](SPIRVInstruction *Inst) -> bool {
1845 return Inst->getOpcode() != spv::OpDecorate &&
1846 Inst->getOpcode() != spv::OpMemberDecorate &&
1847 Inst->getOpcode() != spv::OpExtInstImport;
1848 });
1849
David Netoc463b372017-08-10 15:32:21 -04001850 const auto StructLayout = DL.getStructLayout(STy);
1851
David Neto22f144c2017-06-12 14:26:21 -04001852 for (unsigned MemberIdx = 0; MemberIdx < STy->getNumElements();
1853 MemberIdx++) {
1854 // Ops[0] = Structure Type ID
1855 // Ops[1] = Member Index(Literal Number)
1856 // Ops[2] = Decoration (Offset)
1857 // Ops[3] = Byte Offset (Literal Number)
1858 Ops.clear();
1859
David Neto257c3892018-04-11 13:19:45 -04001860 Ops << MkId(STyID) << MkNum(MemberIdx) << MkNum(spv::DecorationOffset);
David Neto22f144c2017-06-12 14:26:21 -04001861
David Netoc463b372017-08-10 15:32:21 -04001862 const auto ByteOffset =
1863 uint32_t(StructLayout->getElementOffset(MemberIdx));
David Neto257c3892018-04-11 13:19:45 -04001864 Ops << MkNum(ByteOffset);
David Neto22f144c2017-06-12 14:26:21 -04001865
David Neto87846742018-04-11 17:36:22 -04001866 auto *DecoInst = new SPIRVInstruction(spv::OpMemberDecorate, Ops);
David Neto22f144c2017-06-12 14:26:21 -04001867 SPIRVInstList.insert(DecoInsertPoint, DecoInst);
David Neto22f144c2017-06-12 14:26:21 -04001868 }
1869
1870 // Generate OpDecorate.
1871 for (auto ArgGV : ArgGVMap) {
1872 Type *ArgGVTy = ArgGV.second->getType();
1873 PointerType *PTy = cast<PointerType>(ArgGVTy);
1874 Type *ArgTy = PTy->getElementType();
1875
1876 // Struct type from argument is already distinguished with the other
1877 // struct types on llvm types. As a result, if current processing struct
1878 // type is same with argument type, we can generate OpDecorate with
1879 // Block or BufferBlock.
1880 if (ArgTy == STy) {
1881 // Ops[0] = Target ID
1882 // Ops[1] = Decoration (Block or BufferBlock)
1883 Ops.clear();
1884
David Neto6e392822017-08-04 14:06:10 -04001885 // Use Block decorations with StorageBuffer storage class.
David Neto257c3892018-04-11 13:19:45 -04001886 Ops << MkId(STyID) << MkNum(spv::DecorationBlock);
David Neto22f144c2017-06-12 14:26:21 -04001887
David Neto87846742018-04-11 17:36:22 -04001888 auto *DecoInst = new SPIRVInstruction(spv::OpDecorate, Ops);
David Neto22f144c2017-06-12 14:26:21 -04001889 SPIRVInstList.insert(DecoInsertPoint, DecoInst);
1890 break;
1891 }
1892 }
1893 break;
1894 }
1895 case Type::IntegerTyID: {
1896 unsigned BitWidth = Ty->getPrimitiveSizeInBits();
1897
1898 if (BitWidth == 1) {
David Neto87846742018-04-11 17:36:22 -04001899 auto *Inst = new SPIRVInstruction(spv::OpTypeBool, nextID++, {});
David Neto22f144c2017-06-12 14:26:21 -04001900 SPIRVInstList.push_back(Inst);
1901 } else {
1902 // i8 is added to TypeMap as i32.
David Neto391aeb12017-08-26 15:51:58 -04001903 // No matter what LLVM type is requested first, always alias the
1904 // second one's SPIR-V type to be the same as the one we generated
1905 // first.
Neil Henning39672102017-09-29 14:33:13 +01001906 unsigned aliasToWidth = 0;
David Neto22f144c2017-06-12 14:26:21 -04001907 if (BitWidth == 8) {
David Neto391aeb12017-08-26 15:51:58 -04001908 aliasToWidth = 32;
David Neto22f144c2017-06-12 14:26:21 -04001909 BitWidth = 32;
David Neto391aeb12017-08-26 15:51:58 -04001910 } else if (BitWidth == 32) {
1911 aliasToWidth = 8;
1912 }
1913 if (aliasToWidth) {
1914 Type* otherType = Type::getIntNTy(Ty->getContext(), aliasToWidth);
1915 auto where = TypeMap.find(otherType);
1916 if (where == TypeMap.end()) {
1917 // Go ahead and make it, but also map the other type to it.
1918 TypeMap[otherType] = nextID;
1919 } else {
1920 // Alias this SPIR-V type the existing type.
1921 TypeMap[Ty] = where->second;
1922 break;
1923 }
David Neto22f144c2017-06-12 14:26:21 -04001924 }
1925
David Neto257c3892018-04-11 13:19:45 -04001926 SPIRVOperandList Ops;
1927 Ops << MkNum(BitWidth) << MkNum(0 /* not signed */);
David Neto22f144c2017-06-12 14:26:21 -04001928
1929 SPIRVInstList.push_back(
David Neto87846742018-04-11 17:36:22 -04001930 new SPIRVInstruction(spv::OpTypeInt, nextID++, Ops));
David Neto22f144c2017-06-12 14:26:21 -04001931 }
1932 break;
1933 }
1934 case Type::HalfTyID:
1935 case Type::FloatTyID:
1936 case Type::DoubleTyID: {
1937 SPIRVOperand *WidthOp = new SPIRVOperand(
1938 SPIRVOperandType::LITERAL_INTEGER, Ty->getPrimitiveSizeInBits());
1939
1940 SPIRVInstList.push_back(
David Neto87846742018-04-11 17:36:22 -04001941 new SPIRVInstruction(spv::OpTypeFloat, nextID++, WidthOp));
David Neto22f144c2017-06-12 14:26:21 -04001942 break;
1943 }
1944 case Type::ArrayTyID: {
1945 LLVMContext &Context = Ty->getContext();
1946 ArrayType *ArrTy = cast<ArrayType>(Ty);
1947 //
1948 // Generate OpConstant and OpTypeArray.
1949 //
1950
1951 //
1952 // Generate OpConstant for array length.
1953 //
1954 // Ops[0] = Result Type ID
1955 // Ops[1] .. Ops[n] = Values LiteralNumber
1956 SPIRVOperandList Ops;
1957
1958 Type *LengthTy = Type::getInt32Ty(Context);
1959 uint32_t ResTyID = lookupType(LengthTy);
David Neto257c3892018-04-11 13:19:45 -04001960 Ops << MkId(ResTyID);
David Neto22f144c2017-06-12 14:26:21 -04001961
1962 uint64_t Length = ArrTy->getArrayNumElements();
1963 assert(Length < UINT32_MAX);
David Neto257c3892018-04-11 13:19:45 -04001964 Ops << MkNum(static_cast<uint32_t>(Length));
David Neto22f144c2017-06-12 14:26:21 -04001965
1966 // Add constant for length to constant list.
1967 Constant *CstLength = ConstantInt::get(LengthTy, Length);
1968 AllocatedVMap[CstLength] = nextID;
1969 VMap[CstLength] = nextID;
1970 uint32_t LengthID = nextID;
1971
David Neto87846742018-04-11 17:36:22 -04001972 auto *CstInst = new SPIRVInstruction(spv::OpConstant, nextID++, Ops);
David Neto22f144c2017-06-12 14:26:21 -04001973 SPIRVInstList.push_back(CstInst);
1974
David Neto85082642018-03-24 06:55:20 -07001975 // Remember to generate ArrayStride later
1976 getTypesNeedingArrayStride().insert(Ty);
1977
David Neto22f144c2017-06-12 14:26:21 -04001978 //
1979 // Generate OpTypeArray.
1980 //
1981 // Ops[0] = Element Type ID
1982 // Ops[1] = Array Length Constant ID
1983 Ops.clear();
1984
1985 uint32_t EleTyID = lookupType(ArrTy->getElementType());
David Neto257c3892018-04-11 13:19:45 -04001986 Ops << MkId(EleTyID) << MkId(LengthID);
David Neto22f144c2017-06-12 14:26:21 -04001987
1988 // Update TypeMap with nextID.
1989 TypeMap[Ty] = nextID;
1990
David Neto87846742018-04-11 17:36:22 -04001991 auto *ArrayInst = new SPIRVInstruction(spv::OpTypeArray, nextID++, Ops);
David Neto22f144c2017-06-12 14:26:21 -04001992 SPIRVInstList.push_back(ArrayInst);
1993 break;
1994 }
1995 case Type::VectorTyID: {
1996 // <4 x i8> is changed to i32.
1997 LLVMContext &Context = Ty->getContext();
1998 if (Ty->getVectorElementType() == Type::getInt8Ty(Context)) {
1999 if (Ty->getVectorNumElements() == 4) {
2000 TypeMap[Ty] = lookupType(Ty->getVectorElementType());
2001 break;
2002 } else {
2003 Ty->print(errs());
2004 llvm_unreachable("Support above i8 vector type");
2005 }
2006 }
2007
2008 // Ops[0] = Component Type ID
2009 // Ops[1] = Component Count (Literal Number)
David Neto257c3892018-04-11 13:19:45 -04002010 SPIRVOperandList Ops;
2011 Ops << MkId(lookupType(Ty->getVectorElementType()))
2012 << MkNum(Ty->getVectorNumElements());
David Neto22f144c2017-06-12 14:26:21 -04002013
David Neto87846742018-04-11 17:36:22 -04002014 SPIRVInstruction* inst = new SPIRVInstruction(spv::OpTypeVector, nextID++, Ops);
David Netoc6f3ab22018-04-06 18:02:31 -04002015 SPIRVInstList.push_back(inst);
David Neto22f144c2017-06-12 14:26:21 -04002016 break;
2017 }
2018 case Type::VoidTyID: {
David Neto87846742018-04-11 17:36:22 -04002019 auto *Inst = new SPIRVInstruction(spv::OpTypeVoid, nextID++, {});
David Neto22f144c2017-06-12 14:26:21 -04002020 SPIRVInstList.push_back(Inst);
2021 break;
2022 }
2023 case Type::FunctionTyID: {
2024 // Generate SPIRV instruction for function type.
2025 FunctionType *FTy = cast<FunctionType>(Ty);
2026
2027 // Ops[0] = Return Type ID
2028 // Ops[1] ... Ops[n] = Parameter Type IDs
2029 SPIRVOperandList Ops;
2030
2031 // Find SPIRV instruction for return type
David Netoc6f3ab22018-04-06 18:02:31 -04002032 Ops << MkId(lookupType(FTy->getReturnType()));
David Neto22f144c2017-06-12 14:26:21 -04002033
2034 // Find SPIRV instructions for parameter types
2035 for (unsigned k = 0; k < FTy->getNumParams(); k++) {
2036 // Find SPIRV instruction for parameter type.
2037 auto ParamTy = FTy->getParamType(k);
2038 if (ParamTy->isPointerTy()) {
2039 auto PointeeTy = ParamTy->getPointerElementType();
2040 if (PointeeTy->isStructTy() &&
2041 dyn_cast<StructType>(PointeeTy)->isOpaque()) {
2042 ParamTy = PointeeTy;
2043 }
2044 }
2045
David Netoc6f3ab22018-04-06 18:02:31 -04002046 Ops << MkId(lookupType(ParamTy));
David Neto22f144c2017-06-12 14:26:21 -04002047 }
2048
David Neto87846742018-04-11 17:36:22 -04002049 auto *Inst = new SPIRVInstruction(spv::OpTypeFunction, nextID++, Ops);
David Neto22f144c2017-06-12 14:26:21 -04002050 SPIRVInstList.push_back(Inst);
2051 break;
2052 }
2053 }
2054 }
2055
2056 // Generate OpTypeSampledImage.
2057 TypeMapType &OpImageTypeMap = getImageTypeMap();
2058 for (auto &ImageType : OpImageTypeMap) {
2059 //
2060 // Generate OpTypeSampledImage.
2061 //
2062 // Ops[0] = Image Type ID
2063 //
2064 SPIRVOperandList Ops;
2065
2066 Type *ImgTy = ImageType.first;
David Netoc6f3ab22018-04-06 18:02:31 -04002067 Ops << MkId(TypeMap[ImgTy]);
David Neto22f144c2017-06-12 14:26:21 -04002068
2069 // Update OpImageTypeMap.
2070 ImageType.second = nextID;
2071
David Neto87846742018-04-11 17:36:22 -04002072 auto *Inst = new SPIRVInstruction(spv::OpTypeSampledImage, nextID++, Ops);
David Neto22f144c2017-06-12 14:26:21 -04002073 SPIRVInstList.push_back(Inst);
2074 }
David Netoc6f3ab22018-04-06 18:02:31 -04002075
2076 // Generate types for pointer-to-local arguments.
2077 for (auto* arg : LocalArgs) {
2078
2079 LocalArgInfo& arg_info = LocalArgMap[arg];
2080
2081 // Generate the spec constant.
2082 SPIRVOperandList Ops;
2083 Ops << MkId(lookupType(Type::getInt32Ty(Context))) << MkNum(1);
David Neto87846742018-04-11 17:36:22 -04002084 SPIRVInstList.push_back(
2085 new SPIRVInstruction(spv::OpSpecConstant, arg_info.array_size_id, Ops));
David Netoc6f3ab22018-04-06 18:02:31 -04002086
2087 // Generate the array type.
2088 Ops.clear();
2089 // The element type must have been created.
2090 uint32_t elem_ty_id = lookupType(arg_info.elem_type);
2091 assert(elem_ty_id);
2092 Ops << MkId(elem_ty_id) << MkId(arg_info.array_size_id);
2093
2094 SPIRVInstList.push_back(
David Neto87846742018-04-11 17:36:22 -04002095 new SPIRVInstruction(spv::OpTypeArray, arg_info.array_type_id, Ops));
David Netoc6f3ab22018-04-06 18:02:31 -04002096
2097 Ops.clear();
2098 Ops << MkNum(spv::StorageClassWorkgroup) << MkId(arg_info.array_type_id);
David Neto87846742018-04-11 17:36:22 -04002099 SPIRVInstList.push_back(new SPIRVInstruction(
2100 spv::OpTypePointer, arg_info.ptr_array_type_id, Ops));
David Netoc6f3ab22018-04-06 18:02:31 -04002101 }
David Neto22f144c2017-06-12 14:26:21 -04002102}
2103
2104void SPIRVProducerPass::GenerateSPIRVConstants() {
2105 SPIRVInstructionList &SPIRVInstList = getSPIRVInstList();
2106 ValueMapType &VMap = getValueMap();
2107 ValueMapType &AllocatedVMap = getAllocatedValueMap();
2108 ValueList &CstList = getConstantList();
David Neto482550a2018-03-24 05:21:07 -07002109 const bool hack_undef = clspv::Option::HackUndef();
David Neto22f144c2017-06-12 14:26:21 -04002110
2111 for (uint32_t i = 0; i < CstList.size(); i++) {
David Netofb9a7972017-08-25 17:08:24 -04002112 // UniqueVector ids are 1-based.
2113 Constant *Cst = cast<Constant>(CstList[i+1]);
David Neto22f144c2017-06-12 14:26:21 -04002114
2115 // OpTypeArray's constant was already generated.
David Netofb9a7972017-08-25 17:08:24 -04002116 if (AllocatedVMap.find_as(Cst) != AllocatedVMap.end()) {
David Neto22f144c2017-06-12 14:26:21 -04002117 continue;
2118 }
2119
David Netofb9a7972017-08-25 17:08:24 -04002120 // Set ValueMap with nextID for reference later.
David Neto22f144c2017-06-12 14:26:21 -04002121 VMap[Cst] = nextID;
2122
2123 //
2124 // Generate OpConstant.
2125 //
2126
2127 // Ops[0] = Result Type ID
2128 // Ops[1] .. Ops[n] = Values LiteralNumber
2129 SPIRVOperandList Ops;
2130
David Neto257c3892018-04-11 13:19:45 -04002131 Ops << MkId(lookupType(Cst->getType()));
David Neto22f144c2017-06-12 14:26:21 -04002132
2133 std::vector<uint32_t> LiteralNum;
David Neto22f144c2017-06-12 14:26:21 -04002134 spv::Op Opcode = spv::OpNop;
2135
2136 if (isa<UndefValue>(Cst)) {
2137 // Ops[0] = Result Type ID
David Netoc66b3352017-10-20 14:28:46 -04002138 Opcode = spv::OpUndef;
2139 if (hack_undef) {
2140 Type *type = Cst->getType();
2141 if (type->isFPOrFPVectorTy() || type->isIntOrIntVectorTy()) {
2142 Opcode = spv::OpConstantNull;
2143 }
2144 }
David Neto22f144c2017-06-12 14:26:21 -04002145 } else if (const ConstantInt *CI = dyn_cast<ConstantInt>(Cst)) {
2146 unsigned BitWidth = CI->getBitWidth();
2147 if (BitWidth == 1) {
2148 // If the bitwidth of constant is 1, generate OpConstantTrue or
2149 // OpConstantFalse.
2150 if (CI->getZExtValue()) {
2151 // Ops[0] = Result Type ID
2152 Opcode = spv::OpConstantTrue;
2153 } else {
2154 // Ops[0] = Result Type ID
2155 Opcode = spv::OpConstantFalse;
2156 }
David Neto22f144c2017-06-12 14:26:21 -04002157 } else {
2158 auto V = CI->getZExtValue();
2159 LiteralNum.push_back(V & 0xFFFFFFFF);
2160
2161 if (BitWidth > 32) {
2162 LiteralNum.push_back(V >> 32);
2163 }
2164
2165 Opcode = spv::OpConstant;
David Neto22f144c2017-06-12 14:26:21 -04002166
David Neto257c3892018-04-11 13:19:45 -04002167 Ops << MkInteger(LiteralNum);
2168
2169 if (BitWidth == 32 && V == 0) {
2170 constant_i32_zero_id_ = nextID;
2171 }
David Neto22f144c2017-06-12 14:26:21 -04002172 }
2173 } else if (const ConstantFP *CFP = dyn_cast<ConstantFP>(Cst)) {
2174 uint64_t FPVal = CFP->getValueAPF().bitcastToAPInt().getZExtValue();
2175 Type *CFPTy = CFP->getType();
2176 if (CFPTy->isFloatTy()) {
2177 LiteralNum.push_back(FPVal & 0xFFFFFFFF);
2178 } else {
2179 CFPTy->print(errs());
2180 llvm_unreachable("Implement this ConstantFP Type");
2181 }
2182
2183 Opcode = spv::OpConstant;
David Neto22f144c2017-06-12 14:26:21 -04002184
David Neto257c3892018-04-11 13:19:45 -04002185 Ops << MkFloat(LiteralNum);
David Neto22f144c2017-06-12 14:26:21 -04002186 } else if (isa<ConstantDataSequential>(Cst) &&
2187 cast<ConstantDataSequential>(Cst)->isString()) {
2188 Cst->print(errs());
2189 llvm_unreachable("Implement this Constant");
2190
2191 } else if (const ConstantDataSequential *CDS =
2192 dyn_cast<ConstantDataSequential>(Cst)) {
David Neto49351ac2017-08-26 17:32:20 -04002193 // Let's convert <4 x i8> constant to int constant specially.
2194 // This case occurs when all the values are specified as constant
2195 // ints.
2196 Type *CstTy = Cst->getType();
2197 if (is4xi8vec(CstTy)) {
2198 LLVMContext &Context = CstTy->getContext();
2199
2200 //
2201 // Generate OpConstant with OpTypeInt 32 0.
2202 //
Neil Henning39672102017-09-29 14:33:13 +01002203 uint32_t IntValue = 0;
2204 for (unsigned k = 0; k < 4; k++) {
2205 const uint64_t Val = CDS->getElementAsInteger(k);
David Neto49351ac2017-08-26 17:32:20 -04002206 IntValue = (IntValue << 8) | (Val & 0xffu);
2207 }
2208
2209 Type *i32 = Type::getInt32Ty(Context);
2210 Constant *CstInt = ConstantInt::get(i32, IntValue);
2211 // If this constant is already registered on VMap, use it.
2212 if (VMap.count(CstInt)) {
2213 uint32_t CstID = VMap[CstInt];
2214 VMap[Cst] = CstID;
2215 continue;
2216 }
2217
David Neto257c3892018-04-11 13:19:45 -04002218 Ops << MkNum(IntValue);
David Neto49351ac2017-08-26 17:32:20 -04002219
David Neto87846742018-04-11 17:36:22 -04002220 auto *CstInst = new SPIRVInstruction(spv::OpConstant, nextID++, Ops);
David Neto49351ac2017-08-26 17:32:20 -04002221 SPIRVInstList.push_back(CstInst);
2222
2223 continue;
2224 }
2225
2226 // A normal constant-data-sequential case.
David Neto22f144c2017-06-12 14:26:21 -04002227 for (unsigned k = 0; k < CDS->getNumElements(); k++) {
2228 Constant *EleCst = CDS->getElementAsConstant(k);
2229 uint32_t EleCstID = VMap[EleCst];
David Neto257c3892018-04-11 13:19:45 -04002230 Ops << MkId(EleCstID);
David Neto22f144c2017-06-12 14:26:21 -04002231 }
2232
2233 Opcode = spv::OpConstantComposite;
David Neto22f144c2017-06-12 14:26:21 -04002234 } else if (const ConstantAggregate *CA = dyn_cast<ConstantAggregate>(Cst)) {
2235 // Let's convert <4 x i8> constant to int constant specially.
David Neto49351ac2017-08-26 17:32:20 -04002236 // This case occurs when at least one of the values is an undef.
David Neto22f144c2017-06-12 14:26:21 -04002237 Type *CstTy = Cst->getType();
2238 if (is4xi8vec(CstTy)) {
2239 LLVMContext &Context = CstTy->getContext();
2240
2241 //
2242 // Generate OpConstant with OpTypeInt 32 0.
2243 //
Neil Henning39672102017-09-29 14:33:13 +01002244 uint32_t IntValue = 0;
David Neto22f144c2017-06-12 14:26:21 -04002245 for (User::const_op_iterator I = Cst->op_begin(), E = Cst->op_end();
2246 I != E; ++I) {
2247 uint64_t Val = 0;
David Neto49351ac2017-08-26 17:32:20 -04002248 const Value* CV = *I;
Neil Henning39672102017-09-29 14:33:13 +01002249 if (auto *CI2 = dyn_cast<ConstantInt>(CV)) {
2250 Val = CI2->getZExtValue();
David Neto22f144c2017-06-12 14:26:21 -04002251 }
David Neto49351ac2017-08-26 17:32:20 -04002252 IntValue = (IntValue << 8) | (Val & 0xffu);
David Neto22f144c2017-06-12 14:26:21 -04002253 }
2254
David Neto49351ac2017-08-26 17:32:20 -04002255 Type *i32 = Type::getInt32Ty(Context);
2256 Constant *CstInt = ConstantInt::get(i32, IntValue);
David Neto22f144c2017-06-12 14:26:21 -04002257 // If this constant is already registered on VMap, use it.
2258 if (VMap.count(CstInt)) {
2259 uint32_t CstID = VMap[CstInt];
2260 VMap[Cst] = CstID;
David Neto19a1bad2017-08-25 15:01:41 -04002261 continue;
David Neto22f144c2017-06-12 14:26:21 -04002262 }
2263
David Neto257c3892018-04-11 13:19:45 -04002264 Ops << MkNum(IntValue);
David Neto22f144c2017-06-12 14:26:21 -04002265
David Neto87846742018-04-11 17:36:22 -04002266 auto *CstInst = new SPIRVInstruction(spv::OpConstant, nextID++, Ops);
David Neto22f144c2017-06-12 14:26:21 -04002267 SPIRVInstList.push_back(CstInst);
2268
David Neto19a1bad2017-08-25 15:01:41 -04002269 continue;
David Neto22f144c2017-06-12 14:26:21 -04002270 }
2271
2272 // We use a constant composite in SPIR-V for our constant aggregate in
2273 // LLVM.
2274 Opcode = spv::OpConstantComposite;
David Neto22f144c2017-06-12 14:26:21 -04002275
2276 for (unsigned k = 0; k < CA->getNumOperands(); k++) {
2277 // Look up the ID of the element of this aggregate (which we will
2278 // previously have created a constant for).
2279 uint32_t ElementConstantID = VMap[CA->getAggregateElement(k)];
2280
2281 // And add an operand to the composite we are constructing
David Neto257c3892018-04-11 13:19:45 -04002282 Ops << MkId(ElementConstantID);
David Neto22f144c2017-06-12 14:26:21 -04002283 }
2284 } else if (Cst->isNullValue()) {
2285 Opcode = spv::OpConstantNull;
David Neto22f144c2017-06-12 14:26:21 -04002286 } else {
2287 Cst->print(errs());
2288 llvm_unreachable("Unsupported Constant???");
2289 }
2290
David Neto87846742018-04-11 17:36:22 -04002291 auto *CstInst = new SPIRVInstruction(Opcode, nextID++, Ops);
David Neto22f144c2017-06-12 14:26:21 -04002292 SPIRVInstList.push_back(CstInst);
2293 }
2294}
2295
2296void SPIRVProducerPass::GenerateSamplers(Module &M) {
2297 SPIRVInstructionList &SPIRVInstList = getSPIRVInstList();
2298 ValueMapType &VMap = getValueMap();
2299
2300 DenseMap<unsigned, unsigned> SamplerLiteralToIDMap;
2301
2302 unsigned BindingIdx = 0;
2303
2304 // Generate the sampler map.
2305 for (auto SamplerLiteral : getSamplerMap()) {
2306 // Generate OpVariable.
2307 //
2308 // GIDOps[0] : Result Type ID
2309 // GIDOps[1] : Storage Class
2310 SPIRVOperandList Ops;
2311
David Neto257c3892018-04-11 13:19:45 -04002312 Ops << MkId(lookupType(SamplerTy))
2313 << MkNum(spv::StorageClassUniformConstant);
David Neto22f144c2017-06-12 14:26:21 -04002314
David Neto87846742018-04-11 17:36:22 -04002315 auto *Inst = new SPIRVInstruction(spv::OpVariable, nextID, Ops);
David Neto22f144c2017-06-12 14:26:21 -04002316 SPIRVInstList.push_back(Inst);
2317
David Neto44795152017-07-13 15:45:28 -04002318 SamplerLiteralToIDMap[SamplerLiteral.first] = nextID++;
David Neto22f144c2017-06-12 14:26:21 -04002319
2320 // Find Insert Point for OpDecorate.
2321 auto DecoInsertPoint =
2322 std::find_if(SPIRVInstList.begin(), SPIRVInstList.end(),
2323 [](SPIRVInstruction *Inst) -> bool {
2324 return Inst->getOpcode() != spv::OpDecorate &&
2325 Inst->getOpcode() != spv::OpMemberDecorate &&
2326 Inst->getOpcode() != spv::OpExtInstImport;
2327 });
2328
2329 // Ops[0] = Target ID
2330 // Ops[1] = Decoration (DescriptorSet)
2331 // Ops[2] = LiteralNumber according to Decoration
2332 Ops.clear();
2333
David Neto257c3892018-04-11 13:19:45 -04002334 uint32_t ArgID = SamplerLiteralToIDMap[SamplerLiteral.first];
2335 Ops << MkId(ArgID) << MkNum(spv::DecorationDescriptorSet)
2336 << MkNum(NextDescriptorSetIndex);
David Neto22f144c2017-06-12 14:26:21 -04002337
David Neto44795152017-07-13 15:45:28 -04002338 descriptorMapOut << "sampler," << SamplerLiteral.first << ",samplerExpr,\""
David Neto257c3892018-04-11 13:19:45 -04002339 << SamplerLiteral.second << "\",descriptorSet,"
2340 << NextDescriptorSetIndex << ",binding," << BindingIdx
2341 << "\n";
David Neto22f144c2017-06-12 14:26:21 -04002342
David Neto87846742018-04-11 17:36:22 -04002343 auto *DescDecoInst = new SPIRVInstruction(spv::OpDecorate, Ops);
David Neto22f144c2017-06-12 14:26:21 -04002344 SPIRVInstList.insert(DecoInsertPoint, DescDecoInst);
2345
2346 // Ops[0] = Target ID
2347 // Ops[1] = Decoration (Binding)
2348 // Ops[2] = LiteralNumber according to Decoration
2349 Ops.clear();
David Neto257c3892018-04-11 13:19:45 -04002350 Ops << MkId(ArgID) << MkNum(spv::DecorationBinding) << MkNum(BindingIdx);
2351 BindingIdx++;
David Neto22f144c2017-06-12 14:26:21 -04002352
David Neto87846742018-04-11 17:36:22 -04002353 auto *BindDecoInst = new SPIRVInstruction(spv::OpDecorate, Ops);
David Neto22f144c2017-06-12 14:26:21 -04002354 SPIRVInstList.insert(DecoInsertPoint, BindDecoInst);
2355 }
David Neto85082642018-03-24 06:55:20 -07002356 if (BindingIdx > 0) {
2357 // We generated something.
2358 ++NextDescriptorSetIndex;
2359 }
David Neto22f144c2017-06-12 14:26:21 -04002360
2361 const char *TranslateSamplerFunctionName = "__translate_sampler_initializer";
2362
2363 auto SamplerFunction = M.getFunction(TranslateSamplerFunctionName);
2364
2365 // If there are no uses of the sampler function, no work to do!
2366 if (!SamplerFunction) {
2367 return;
2368 }
2369
2370 // Iterate through the users of the sampler function.
2371 for (auto User : SamplerFunction->users()) {
2372 if (auto CI = dyn_cast<CallInst>(User)) {
2373 // Get the literal used to initialize the sampler.
2374 auto Constant = dyn_cast<ConstantInt>(CI->getArgOperand(0));
2375
2376 if (!Constant) {
2377 CI->getArgOperand(0)->print(errs());
2378 llvm_unreachable("Argument of sampler initializer was non-constant!");
2379 }
2380
2381 auto SamplerLiteral = static_cast<unsigned>(Constant->getZExtValue());
2382
2383 if (0 == SamplerLiteralToIDMap.count(SamplerLiteral)) {
2384 Constant->print(errs());
2385 llvm_unreachable("Sampler literal was not found in sampler map!");
2386 }
2387
2388 // Calls to the sampler literal function to initialize a sampler are
2389 // re-routed to the global variables declared for the sampler.
2390 VMap[CI] = SamplerLiteralToIDMap[SamplerLiteral];
2391 }
2392 }
2393}
2394
2395void SPIRVProducerPass::GenerateGlobalVar(GlobalVariable &GV) {
2396 SPIRVInstructionList &SPIRVInstList = getSPIRVInstList();
2397 ValueMapType &VMap = getValueMap();
2398 std::vector<uint32_t> &BuiltinDimVec = getBuiltinDimVec();
David Neto85082642018-03-24 06:55:20 -07002399 const DataLayout &DL = GV.getParent()->getDataLayout();
David Neto22f144c2017-06-12 14:26:21 -04002400
2401 const spv::BuiltIn BuiltinType = GetBuiltin(GV.getName());
2402 Type *Ty = GV.getType();
2403 PointerType *PTy = cast<PointerType>(Ty);
2404
2405 uint32_t InitializerID = 0;
2406
2407 // Workgroup size is handled differently (it goes into a constant)
2408 if (spv::BuiltInWorkgroupSize == BuiltinType) {
2409 std::vector<bool> HasMDVec;
2410 uint32_t PrevXDimCst = 0xFFFFFFFF;
2411 uint32_t PrevYDimCst = 0xFFFFFFFF;
2412 uint32_t PrevZDimCst = 0xFFFFFFFF;
2413 for (Function &Func : *GV.getParent()) {
2414 if (Func.isDeclaration()) {
2415 continue;
2416 }
2417
2418 // We only need to check kernels.
2419 if (Func.getCallingConv() != CallingConv::SPIR_KERNEL) {
2420 continue;
2421 }
2422
2423 if (const MDNode *MD =
2424 dyn_cast<Function>(&Func)->getMetadata("reqd_work_group_size")) {
2425 uint32_t CurXDimCst = static_cast<uint32_t>(
2426 mdconst::extract<ConstantInt>(MD->getOperand(0))->getZExtValue());
2427 uint32_t CurYDimCst = static_cast<uint32_t>(
2428 mdconst::extract<ConstantInt>(MD->getOperand(1))->getZExtValue());
2429 uint32_t CurZDimCst = static_cast<uint32_t>(
2430 mdconst::extract<ConstantInt>(MD->getOperand(2))->getZExtValue());
2431
2432 if (PrevXDimCst == 0xFFFFFFFF && PrevYDimCst == 0xFFFFFFFF &&
2433 PrevZDimCst == 0xFFFFFFFF) {
2434 PrevXDimCst = CurXDimCst;
2435 PrevYDimCst = CurYDimCst;
2436 PrevZDimCst = CurZDimCst;
2437 } else if (CurXDimCst != PrevXDimCst || CurYDimCst != PrevYDimCst ||
2438 CurZDimCst != PrevZDimCst) {
2439 llvm_unreachable(
2440 "reqd_work_group_size must be the same across all kernels");
2441 } else {
2442 continue;
2443 }
2444
2445 //
2446 // Generate OpConstantComposite.
2447 //
2448 // Ops[0] : Result Type ID
2449 // Ops[1] : Constant size for x dimension.
2450 // Ops[2] : Constant size for y dimension.
2451 // Ops[3] : Constant size for z dimension.
2452 SPIRVOperandList Ops;
2453
2454 uint32_t XDimCstID =
2455 VMap[mdconst::extract<ConstantInt>(MD->getOperand(0))];
2456 uint32_t YDimCstID =
2457 VMap[mdconst::extract<ConstantInt>(MD->getOperand(1))];
2458 uint32_t ZDimCstID =
2459 VMap[mdconst::extract<ConstantInt>(MD->getOperand(2))];
2460
2461 InitializerID = nextID;
2462
David Neto257c3892018-04-11 13:19:45 -04002463 Ops << MkId(lookupType(Ty->getPointerElementType())) << MkId(XDimCstID)
2464 << MkId(YDimCstID) << MkId(ZDimCstID);
David Neto22f144c2017-06-12 14:26:21 -04002465
David Neto87846742018-04-11 17:36:22 -04002466 auto *Inst =
2467 new SPIRVInstruction(spv::OpConstantComposite, nextID++, Ops);
David Neto22f144c2017-06-12 14:26:21 -04002468 SPIRVInstList.push_back(Inst);
2469
2470 HasMDVec.push_back(true);
2471 } else {
2472 HasMDVec.push_back(false);
2473 }
2474 }
2475
2476 // Check all kernels have same definitions for work_group_size.
2477 bool HasMD = false;
2478 if (!HasMDVec.empty()) {
2479 HasMD = HasMDVec[0];
2480 for (uint32_t i = 1; i < HasMDVec.size(); i++) {
2481 if (HasMD != HasMDVec[i]) {
2482 llvm_unreachable(
2483 "Kernels should have consistent work group size definition");
2484 }
2485 }
2486 }
2487
2488 // If all kernels do not have metadata for reqd_work_group_size, generate
2489 // OpSpecConstants for x/y/z dimension.
2490 if (!HasMD) {
2491 //
2492 // Generate OpSpecConstants for x/y/z dimension.
2493 //
2494 // Ops[0] : Result Type ID
2495 // Ops[1] : Constant size for x/y/z dimension (Literal Number).
2496 uint32_t XDimCstID = 0;
2497 uint32_t YDimCstID = 0;
2498 uint32_t ZDimCstID = 0;
2499
David Neto22f144c2017-06-12 14:26:21 -04002500 SPIRVOperandList Ops;
David Neto257c3892018-04-11 13:19:45 -04002501 uint32_t result_type_id =
2502 lookupType(Ty->getPointerElementType()->getSequentialElementType());
David Neto22f144c2017-06-12 14:26:21 -04002503
David Neto257c3892018-04-11 13:19:45 -04002504 // X Dimension
2505 Ops << MkId(result_type_id) << MkNum(1);
2506 XDimCstID = nextID++;
2507 SPIRVInstList.push_back(
David Neto87846742018-04-11 17:36:22 -04002508 new SPIRVInstruction(spv::OpSpecConstant, XDimCstID, Ops));
David Neto22f144c2017-06-12 14:26:21 -04002509
2510 // Y Dimension
2511 Ops.clear();
David Neto257c3892018-04-11 13:19:45 -04002512 Ops << MkId(result_type_id) << MkNum(1);
2513 YDimCstID = nextID++;
2514 SPIRVInstList.push_back(
David Neto87846742018-04-11 17:36:22 -04002515 new SPIRVInstruction(spv::OpSpecConstant, YDimCstID, Ops));
David Neto22f144c2017-06-12 14:26:21 -04002516
2517 // Z Dimension
2518 Ops.clear();
David Neto257c3892018-04-11 13:19:45 -04002519 Ops << MkId(result_type_id) << MkNum(1);
2520 ZDimCstID = nextID++;
2521 SPIRVInstList.push_back(
David Neto87846742018-04-11 17:36:22 -04002522 new SPIRVInstruction(spv::OpSpecConstant, ZDimCstID, Ops));
David Neto22f144c2017-06-12 14:26:21 -04002523
David Neto22f144c2017-06-12 14:26:21 -04002524
David Neto257c3892018-04-11 13:19:45 -04002525 BuiltinDimVec.push_back(XDimCstID);
2526 BuiltinDimVec.push_back(YDimCstID);
David Neto22f144c2017-06-12 14:26:21 -04002527 BuiltinDimVec.push_back(ZDimCstID);
2528
David Neto22f144c2017-06-12 14:26:21 -04002529
2530 //
2531 // Generate OpSpecConstantComposite.
2532 //
2533 // Ops[0] : Result Type ID
2534 // Ops[1] : Constant size for x dimension.
2535 // Ops[2] : Constant size for y dimension.
2536 // Ops[3] : Constant size for z dimension.
2537 InitializerID = nextID;
2538
2539 Ops.clear();
David Neto257c3892018-04-11 13:19:45 -04002540 Ops << MkId(lookupType(Ty->getPointerElementType())) << MkId(XDimCstID)
2541 << MkId(YDimCstID) << MkId(ZDimCstID);
David Neto22f144c2017-06-12 14:26:21 -04002542
David Neto87846742018-04-11 17:36:22 -04002543 auto *Inst =
2544 new SPIRVInstruction(spv::OpSpecConstantComposite, nextID++, Ops);
David Neto22f144c2017-06-12 14:26:21 -04002545 SPIRVInstList.push_back(Inst);
2546 }
2547 }
2548
David Neto22f144c2017-06-12 14:26:21 -04002549 VMap[&GV] = nextID;
2550
2551 //
2552 // Generate OpVariable.
2553 //
2554 // GIDOps[0] : Result Type ID
2555 // GIDOps[1] : Storage Class
2556 SPIRVOperandList Ops;
2557
David Neto85082642018-03-24 06:55:20 -07002558 const auto AS = PTy->getAddressSpace();
David Netoc6f3ab22018-04-06 18:02:31 -04002559 Ops << MkId(lookupType(Ty)) << MkNum(GetStorageClass(AS));
David Neto22f144c2017-06-12 14:26:21 -04002560
David Neto85082642018-03-24 06:55:20 -07002561 if (GV.hasInitializer()) {
2562 InitializerID = VMap[GV.getInitializer()];
David Neto22f144c2017-06-12 14:26:21 -04002563 }
2564
David Neto85082642018-03-24 06:55:20 -07002565 const bool module_scope_constant_external_init =
2566 (0 != InitializerID) && (AS == AddressSpace::Constant) &&
2567 clspv::Option::ModuleConstantsInStorageBuffer();
2568
2569 if (0 != InitializerID) {
2570 if (!module_scope_constant_external_init) {
2571 // Emit the ID of the intiializer as part of the variable definition.
David Netoc6f3ab22018-04-06 18:02:31 -04002572 Ops << MkId(InitializerID);
David Neto85082642018-03-24 06:55:20 -07002573 }
2574 }
2575 const uint32_t var_id = nextID++;
2576
David Neto87846742018-04-11 17:36:22 -04002577 auto *Inst = new SPIRVInstruction(spv::OpVariable, var_id, Ops);
David Neto22f144c2017-06-12 14:26:21 -04002578 SPIRVInstList.push_back(Inst);
2579
2580 // If we have a builtin.
2581 if (spv::BuiltInMax != BuiltinType) {
2582 // Find Insert Point for OpDecorate.
2583 auto DecoInsertPoint =
2584 std::find_if(SPIRVInstList.begin(), SPIRVInstList.end(),
2585 [](SPIRVInstruction *Inst) -> bool {
2586 return Inst->getOpcode() != spv::OpDecorate &&
2587 Inst->getOpcode() != spv::OpMemberDecorate &&
2588 Inst->getOpcode() != spv::OpExtInstImport;
2589 });
2590 //
2591 // Generate OpDecorate.
2592 //
2593 // DOps[0] = Target ID
2594 // DOps[1] = Decoration (Builtin)
2595 // DOps[2] = BuiltIn ID
2596 uint32_t ResultID;
2597
2598 // WorkgroupSize is different, we decorate the constant composite that has
2599 // its value, rather than the variable that we use to access the value.
2600 if (spv::BuiltInWorkgroupSize == BuiltinType) {
2601 ResultID = InitializerID;
David Netoa60b00b2017-09-15 16:34:09 -04002602 // Save both the value and variable IDs for later.
2603 WorkgroupSizeValueID = InitializerID;
2604 WorkgroupSizeVarID = VMap[&GV];
David Neto22f144c2017-06-12 14:26:21 -04002605 } else {
2606 ResultID = VMap[&GV];
2607 }
2608
2609 SPIRVOperandList DOps;
David Neto257c3892018-04-11 13:19:45 -04002610 DOps << MkId(ResultID) << MkNum(spv::DecorationBuiltIn)
2611 << MkNum(BuiltinType);
David Neto22f144c2017-06-12 14:26:21 -04002612
David Neto87846742018-04-11 17:36:22 -04002613 auto *DescDecoInst = new SPIRVInstruction(spv::OpDecorate, DOps);
David Neto22f144c2017-06-12 14:26:21 -04002614 SPIRVInstList.insert(DecoInsertPoint, DescDecoInst);
David Neto85082642018-03-24 06:55:20 -07002615 } else if (module_scope_constant_external_init) {
2616 // This module scope constant is initialized from a storage buffer with data
2617 // provided by the host at binding 0 of the next descriptor set.
2618 const uint32_t descriptor_set = NextDescriptorSetIndex++;
2619
2620 // Emit the intiialier to the descriptor map file.
2621 // Use "kind,buffer" to indicate storage buffer. We might want to expand
2622 // that later to other types, like uniform buffer.
2623 descriptorMapOut << "constant,descriptorSet," << descriptor_set
2624 << ",binding,0,kind,buffer,hexbytes,";
2625 clspv::ConstantEmitter(DL, descriptorMapOut).Emit(GV.getInitializer());
2626 descriptorMapOut << "\n";
2627
2628 // Find Insert Point for OpDecorate.
2629 auto DecoInsertPoint =
2630 std::find_if(SPIRVInstList.begin(), SPIRVInstList.end(),
2631 [](SPIRVInstruction *Inst) -> bool {
2632 return Inst->getOpcode() != spv::OpDecorate &&
2633 Inst->getOpcode() != spv::OpMemberDecorate &&
2634 Inst->getOpcode() != spv::OpExtInstImport;
2635 });
2636
David Neto257c3892018-04-11 13:19:45 -04002637 // OpDecorate %var Binding <binding>
David Neto85082642018-03-24 06:55:20 -07002638 SPIRVOperandList DOps;
David Neto257c3892018-04-11 13:19:45 -04002639 DOps << MkId(var_id) << MkNum(spv::DecorationBinding) << MkNum(0);
2640 DecoInsertPoint = SPIRVInstList.insert(
David Neto87846742018-04-11 17:36:22 -04002641 DecoInsertPoint, new SPIRVInstruction(spv::OpDecorate, DOps));
David Neto85082642018-03-24 06:55:20 -07002642
2643 // OpDecorate %var DescriptorSet <descriptor_set>
2644 DOps.clear();
David Neto257c3892018-04-11 13:19:45 -04002645 DOps << MkId(var_id) << MkNum(spv::DecorationDescriptorSet)
2646 << MkNum(descriptor_set);
David Netoc6f3ab22018-04-06 18:02:31 -04002647 SPIRVInstList.insert(DecoInsertPoint,
David Neto87846742018-04-11 17:36:22 -04002648 new SPIRVInstruction(spv::OpDecorate, DOps));
David Neto22f144c2017-06-12 14:26:21 -04002649 }
2650}
2651
David Netoc6f3ab22018-04-06 18:02:31 -04002652void SPIRVProducerPass::GenerateWorkgroupVars() {
2653 SPIRVInstructionList &SPIRVInstList = getSPIRVInstList();
2654 for (auto* arg : LocalArgs) {
2655 const auto& info = LocalArgMap[arg];
2656
2657 // Generate OpVariable.
2658 //
2659 // GIDOps[0] : Result Type ID
2660 // GIDOps[1] : Storage Class
2661 SPIRVOperandList Ops;
2662 Ops << MkId(info.ptr_array_type_id) << MkNum(spv::StorageClassWorkgroup);
2663
2664 SPIRVInstList.push_back(
David Neto87846742018-04-11 17:36:22 -04002665 new SPIRVInstruction(spv::OpVariable, info.variable_id, Ops));
David Netoc6f3ab22018-04-06 18:02:31 -04002666 }
2667}
2668
David Neto22f144c2017-06-12 14:26:21 -04002669void SPIRVProducerPass::GenerateFuncPrologue(Function &F) {
David Netoc6f3ab22018-04-06 18:02:31 -04002670 const DataLayout &DL = F.getParent()->getDataLayout();
David Neto22f144c2017-06-12 14:26:21 -04002671 SPIRVInstructionList &SPIRVInstList = getSPIRVInstList();
2672 ValueMapType &VMap = getValueMap();
2673 EntryPointVecType &EntryPoints = getEntryPointVec();
2674 ValueToValueMapTy &ArgGVMap = getArgumentGVMap();
2675 ValueMapType &ArgGVIDMap = getArgumentGVIDMap();
2676 auto &GlobalConstFuncTyMap = getGlobalConstFuncTypeMap();
2677 auto &GlobalConstArgSet = getGlobalConstArgSet();
2678
2679 FunctionType *FTy = F.getFunctionType();
2680
2681 //
2682 // Generate OpVariable and OpDecorate for kernel function with arguments.
2683 //
2684 if (F.getCallingConv() == CallingConv::SPIR_KERNEL) {
2685
2686 // Find Insert Point for OpDecorate.
2687 auto DecoInsertPoint =
2688 std::find_if(SPIRVInstList.begin(), SPIRVInstList.end(),
2689 [](SPIRVInstruction *Inst) -> bool {
2690 return Inst->getOpcode() != spv::OpDecorate &&
2691 Inst->getOpcode() != spv::OpMemberDecorate &&
2692 Inst->getOpcode() != spv::OpExtInstImport;
2693 });
2694
David Neto85082642018-03-24 06:55:20 -07002695 const uint32_t DescriptorSetIdx = NextDescriptorSetIndex;
David Neto482550a2018-03-24 05:21:07 -07002696 if (clspv::Option::DistinctKernelDescriptorSets()) {
David Neto85082642018-03-24 06:55:20 -07002697 ++NextDescriptorSetIndex;
David Neto22f144c2017-06-12 14:26:21 -04002698 }
2699
David Netoe439d702018-03-23 13:14:08 -07002700 auto remap_arg_kind = [](StringRef argKind) {
David Neto482550a2018-03-24 05:21:07 -07002701 return clspv::Option::PodArgsInUniformBuffer() && argKind.equals("pod")
2702 ? "pod_ubo"
2703 : argKind;
David Netoe439d702018-03-23 13:14:08 -07002704 };
2705
David Neto156783e2017-07-05 15:39:41 -04002706 const auto *ArgMap = F.getMetadata("kernel_arg_map");
2707 // Emit descriptor map entries, if there was explicit metadata
2708 // attached.
2709 if (ArgMap) {
David Netoc6f3ab22018-04-06 18:02:31 -04002710 // The binding number is the new argument index minus the number
2711 // pointer-to-local arguments. Do this adjustment here rather than
2712 // adding yet another data member to the metadata for each argument.
2713 int num_ptr_local = 0;
2714
David Neto156783e2017-07-05 15:39:41 -04002715 for (const auto &arg : ArgMap->operands()) {
2716 const MDNode *arg_node = dyn_cast<MDNode>(arg.get());
David Netoc6f3ab22018-04-06 18:02:31 -04002717 assert(arg_node->getNumOperands() == 6);
David Neto156783e2017-07-05 15:39:41 -04002718 const auto name =
2719 dyn_cast<MDString>(arg_node->getOperand(0))->getString();
2720 const auto old_index =
2721 dyn_extract<ConstantInt>(arg_node->getOperand(1))->getZExtValue();
2722 const auto new_index =
2723 dyn_extract<ConstantInt>(arg_node->getOperand(2))->getZExtValue();
2724 const auto offset =
2725 dyn_extract<ConstantInt>(arg_node->getOperand(3))->getZExtValue();
David Netoc6f3ab22018-04-06 18:02:31 -04002726 const auto argKind = remap_arg_kind(
2727 dyn_cast<MDString>(arg_node->getOperand(4))->getString());
2728 const auto spec_id =
2729 dyn_extract<ConstantInt>(arg_node->getOperand(5))->getSExtValue();
2730 if (spec_id > 0) {
2731 num_ptr_local++;
2732 FunctionType *fTy =
2733 cast<FunctionType>(F.getType()->getPointerElementType());
2734 descriptorMapOut
2735 << "kernel," << F.getName() << ",arg," << name << ",argOrdinal,"
2736 << old_index << ",argKind," << argKind << ",arrayElemSize,"
2737 << DL.getTypeAllocSize(
2738 fTy->getParamType(new_index)->getPointerElementType())
2739 << ",arrayNumElemSpecId," << spec_id << "\n";
2740 } else {
2741 descriptorMapOut << "kernel," << F.getName() << ",arg," << name
2742 << ",argOrdinal," << old_index << ",descriptorSet,"
2743 << DescriptorSetIdx << ",binding,"
2744 << (new_index - num_ptr_local) << ",offset,"
2745 << offset << ",argKind," << argKind << "\n";
2746 }
David Neto156783e2017-07-05 15:39:41 -04002747 }
2748 }
2749
David Neto22f144c2017-06-12 14:26:21 -04002750 uint32_t BindingIdx = 0;
David Netoc6f3ab22018-04-06 18:02:31 -04002751 uint32_t arg_index = 0;
David Neto22f144c2017-06-12 14:26:21 -04002752 for (auto &Arg : F.args()) {
David Netoc6f3ab22018-04-06 18:02:31 -04002753 // Always use a binding, unless it's pointer-to-local.
2754 const bool uses_binding = !IsLocalPtr(Arg.getType());
David Neto22f144c2017-06-12 14:26:21 -04002755
David Neto156783e2017-07-05 15:39:41 -04002756 // Emit a descriptor map entry for this arg, in case there was no explicit
2757 // kernel arg mapping metadata.
David Netoc6f3ab22018-04-06 18:02:31 -04002758 auto argKind = remap_arg_kind(clspv::GetArgKindForType(Arg.getType()));
David Neto156783e2017-07-05 15:39:41 -04002759 if (!ArgMap) {
David Netoc6f3ab22018-04-06 18:02:31 -04002760 if (uses_binding) {
2761 descriptorMapOut << "kernel," << F.getName() << ",arg,"
2762 << Arg.getName() << ",argOrdinal," << arg_index
2763 << ",descriptorSet," << DescriptorSetIdx
2764 << ",binding," << BindingIdx << ",offset,0,argKind,"
2765 << argKind << "\n";
2766 } else {
2767 descriptorMapOut << "kernel," << F.getName() << ",arg,"
2768 << Arg.getName() << ",argOrdinal," << arg_index
2769 << ",argKind," << argKind << ",arrayElemSize,"
2770 << DL.getTypeAllocSize(
2771 Arg.getType()->getPointerElementType())
2772 << ",arrayNumElemSpecId," << ArgSpecIdMap[&Arg]
2773 << "\n";
2774 }
David Netoc2c368d2017-06-30 16:50:17 -04002775 }
2776
David Netoc6f3ab22018-04-06 18:02:31 -04002777 if (uses_binding) {
2778 Value *NewGV = ArgGVMap[&Arg];
2779 VMap[&Arg] = VMap[NewGV];
2780 ArgGVIDMap[&Arg] = VMap[&Arg];
David Neto26aaf622017-10-23 18:11:53 -04002781
David Netoc6f3ab22018-04-06 18:02:31 -04002782 if (0 == GVarWithEmittedBindingInfo.count(NewGV)) {
2783 // Generate a new global variable for this argument.
2784 GVarWithEmittedBindingInfo.insert(NewGV);
David Neto22f144c2017-06-12 14:26:21 -04002785
David Netoc6f3ab22018-04-06 18:02:31 -04002786 SPIRVOperandList Ops;
2787 SPIRVOperand *ArgIDOp = nullptr;
David Neto257c3892018-04-11 13:19:45 -04002788 uint32_t ArgID = 0;
David Neto22f144c2017-06-12 14:26:21 -04002789
David Netoc6f3ab22018-04-06 18:02:31 -04002790 if (uses_binding) {
2791 // Ops[0] = Target ID
2792 // Ops[1] = Decoration (DescriptorSet)
2793 // Ops[2] = LiteralNumber according to Decoration
David Neto22f144c2017-06-12 14:26:21 -04002794
David Neto257c3892018-04-11 13:19:45 -04002795 ArgID = VMap[&Arg];
2796 Ops << MkId(ArgID) << MkNum(spv::DecorationDescriptorSet)
2797 << MkNum(DescriptorSetIdx);
David Neto22f144c2017-06-12 14:26:21 -04002798
David Neto87846742018-04-11 17:36:22 -04002799 auto *DescDecoInst = new SPIRVInstruction(spv::OpDecorate, Ops);
David Netoc6f3ab22018-04-06 18:02:31 -04002800 SPIRVInstList.insert(DecoInsertPoint, DescDecoInst);
David Neto22f144c2017-06-12 14:26:21 -04002801
David Netoc6f3ab22018-04-06 18:02:31 -04002802 // Ops[0] = Target ID
2803 // Ops[1] = Decoration (Binding)
2804 // Ops[2] = LiteralNumber according to Decoration
2805 Ops.clear();
David Neto257c3892018-04-11 13:19:45 -04002806 Ops << MkId(ArgID) << MkNum(spv::DecorationBinding)
2807 << MkNum(BindingIdx);
David Netoc6f3ab22018-04-06 18:02:31 -04002808
David Neto87846742018-04-11 17:36:22 -04002809 auto *BindDecoInst = new SPIRVInstruction(spv::OpDecorate, Ops);
David Netoc6f3ab22018-04-06 18:02:31 -04002810 SPIRVInstList.insert(DecoInsertPoint, BindDecoInst);
2811 }
2812
2813 // Handle image type argument.
2814 bool HasReadOnlyImageType = false;
2815 bool HasWriteOnlyImageType = false;
2816 if (PointerType *ArgPTy = dyn_cast<PointerType>(Arg.getType())) {
2817 if (StructType *STy =
2818 dyn_cast<StructType>(ArgPTy->getElementType())) {
2819 if (STy->isOpaque()) {
2820 if (STy->getName().equals("opencl.image2d_ro_t") ||
2821 STy->getName().equals("opencl.image3d_ro_t")) {
2822 HasReadOnlyImageType = true;
2823 } else if (STy->getName().equals("opencl.image2d_wo_t") ||
2824 STy->getName().equals("opencl.image3d_wo_t")) {
2825 HasWriteOnlyImageType = true;
2826 }
2827 }
David Neto22f144c2017-06-12 14:26:21 -04002828 }
2829 }
David Netoc6f3ab22018-04-06 18:02:31 -04002830
2831 if (HasReadOnlyImageType || HasWriteOnlyImageType) {
2832 // Ops[0] = Target ID
2833 // Ops[1] = Decoration (NonReadable or NonWritable)
2834 Ops.clear();
2835
David Neto257c3892018-04-11 13:19:45 -04002836 Ops << MkId(VMap[&Arg]);
David Netoc6f3ab22018-04-06 18:02:31 -04002837
David Neto257c3892018-04-11 13:19:45 -04002838 // In OpenCL 1.2 an image is either read-only or write-only, but
2839 // never both.
2840 Ops << MkNum(HasReadOnlyImageType ? spv::DecorationNonWritable
2841 : spv::DecorationNonReadable);
David Netoc6f3ab22018-04-06 18:02:31 -04002842
David Neto87846742018-04-11 17:36:22 -04002843 auto *DescDecoInst = new SPIRVInstruction(spv::OpDecorate, Ops);
David Netoc6f3ab22018-04-06 18:02:31 -04002844 SPIRVInstList.insert(DecoInsertPoint, DescDecoInst);
2845 }
2846
2847 // Handle const address space.
2848 if (uses_binding && NewGV->getType()->getPointerAddressSpace() ==
2849 AddressSpace::Constant) {
2850 // Ops[0] = Target ID
2851 // Ops[1] = Decoration (NonWriteable)
2852 Ops.clear();
David Neto257c3892018-04-11 13:19:45 -04002853 assert(ArgID > 0);
2854 Ops << MkId(ArgID) << MkNum(spv::DecorationNonWritable);
David Netoc6f3ab22018-04-06 18:02:31 -04002855
David Neto87846742018-04-11 17:36:22 -04002856 auto *BindDecoInst = new SPIRVInstruction(spv::OpDecorate, Ops);
David Netoc6f3ab22018-04-06 18:02:31 -04002857 SPIRVInstList.insert(DecoInsertPoint, BindDecoInst);
2858 }
David Neto22f144c2017-06-12 14:26:21 -04002859 }
David Netoc6f3ab22018-04-06 18:02:31 -04002860 BindingIdx++;
David Neto22f144c2017-06-12 14:26:21 -04002861 }
David Netoc6f3ab22018-04-06 18:02:31 -04002862 arg_index++;
David Neto22f144c2017-06-12 14:26:21 -04002863 }
2864 }
2865
2866 //
2867 // Generate OPFunction.
2868 //
2869
2870 // FOps[0] : Result Type ID
2871 // FOps[1] : Function Control
2872 // FOps[2] : Function Type ID
2873 SPIRVOperandList FOps;
2874
2875 // Find SPIRV instruction for return type.
David Neto257c3892018-04-11 13:19:45 -04002876 FOps << MkId(lookupType(FTy->getReturnType()));
David Neto22f144c2017-06-12 14:26:21 -04002877
2878 // Check function attributes for SPIRV Function Control.
2879 uint32_t FuncControl = spv::FunctionControlMaskNone;
2880 if (F.hasFnAttribute(Attribute::AlwaysInline)) {
2881 FuncControl |= spv::FunctionControlInlineMask;
2882 }
2883 if (F.hasFnAttribute(Attribute::NoInline)) {
2884 FuncControl |= spv::FunctionControlDontInlineMask;
2885 }
2886 // TODO: Check llvm attribute for Function Control Pure.
2887 if (F.hasFnAttribute(Attribute::ReadOnly)) {
2888 FuncControl |= spv::FunctionControlPureMask;
2889 }
2890 // TODO: Check llvm attribute for Function Control Const.
2891 if (F.hasFnAttribute(Attribute::ReadNone)) {
2892 FuncControl |= spv::FunctionControlConstMask;
2893 }
2894
David Neto257c3892018-04-11 13:19:45 -04002895 FOps << MkNum(FuncControl);
David Neto22f144c2017-06-12 14:26:21 -04002896
2897 uint32_t FTyID;
2898 if (F.getCallingConv() == CallingConv::SPIR_KERNEL) {
2899 SmallVector<Type *, 4> NewFuncParamTys;
2900 FunctionType *NewFTy =
2901 FunctionType::get(FTy->getReturnType(), NewFuncParamTys, false);
2902 FTyID = lookupType(NewFTy);
2903 } else {
David Neto9ed8e2f2018-03-24 06:47:24 -07002904 // Handle regular function with global constant parameters.
David Neto22f144c2017-06-12 14:26:21 -04002905 if (GlobalConstFuncTyMap.count(FTy)) {
2906 FTyID = lookupType(GlobalConstFuncTyMap[FTy].first);
2907 } else {
2908 FTyID = lookupType(FTy);
2909 }
2910 }
2911
David Neto257c3892018-04-11 13:19:45 -04002912 FOps << MkId(FTyID);
David Neto22f144c2017-06-12 14:26:21 -04002913
2914 if (F.getCallingConv() == CallingConv::SPIR_KERNEL) {
2915 EntryPoints.push_back(std::make_pair(&F, nextID));
2916 }
2917
2918 VMap[&F] = nextID;
2919
David Neto482550a2018-03-24 05:21:07 -07002920 if (clspv::Option::ShowIDs()) {
David Netob05675d2018-02-16 12:37:49 -05002921 errs() << "Function " << F.getName() << " is " << nextID << "\n";
2922 }
David Neto22f144c2017-06-12 14:26:21 -04002923 // Generate SPIRV instruction for function.
David Neto87846742018-04-11 17:36:22 -04002924 auto *FuncInst = new SPIRVInstruction(spv::OpFunction, nextID++, FOps);
David Neto22f144c2017-06-12 14:26:21 -04002925 SPIRVInstList.push_back(FuncInst);
2926
2927 //
2928 // Generate OpFunctionParameter for Normal function.
2929 //
2930
2931 if (F.getCallingConv() != CallingConv::SPIR_KERNEL) {
2932 // Iterate Argument for name instead of param type from function type.
2933 unsigned ArgIdx = 0;
2934 for (Argument &Arg : F.args()) {
2935 VMap[&Arg] = nextID;
2936
2937 // ParamOps[0] : Result Type ID
2938 SPIRVOperandList ParamOps;
2939
2940 // Find SPIRV instruction for parameter type.
2941 uint32_t ParamTyID = lookupType(Arg.getType());
2942 if (PointerType *PTy = dyn_cast<PointerType>(Arg.getType())) {
2943 if (GlobalConstFuncTyMap.count(FTy)) {
2944 if (ArgIdx == GlobalConstFuncTyMap[FTy].second) {
2945 Type *EleTy = PTy->getPointerElementType();
2946 Type *ArgTy =
2947 PointerType::get(EleTy, AddressSpace::ModuleScopePrivate);
2948 ParamTyID = lookupType(ArgTy);
2949 GlobalConstArgSet.insert(&Arg);
2950 }
2951 }
2952 }
David Neto257c3892018-04-11 13:19:45 -04002953 ParamOps << MkId(ParamTyID);
David Neto22f144c2017-06-12 14:26:21 -04002954
2955 // Generate SPIRV instruction for parameter.
David Neto87846742018-04-11 17:36:22 -04002956 auto *ParamInst =
2957 new SPIRVInstruction(spv::OpFunctionParameter, nextID++, ParamOps);
David Neto22f144c2017-06-12 14:26:21 -04002958 SPIRVInstList.push_back(ParamInst);
2959
2960 ArgIdx++;
2961 }
2962 }
2963}
2964
David Neto5c22a252018-03-15 16:07:41 -04002965void SPIRVProducerPass::GenerateModuleInfo(Module& module) {
David Neto22f144c2017-06-12 14:26:21 -04002966 SPIRVInstructionList &SPIRVInstList = getSPIRVInstList();
2967 EntryPointVecType &EntryPoints = getEntryPointVec();
2968 ValueMapType &VMap = getValueMap();
2969 ValueList &EntryPointInterfaces = getEntryPointInterfacesVec();
2970 uint32_t &ExtInstImportID = getOpExtInstImportID();
2971 std::vector<uint32_t> &BuiltinDimVec = getBuiltinDimVec();
2972
2973 // Set up insert point.
2974 auto InsertPoint = SPIRVInstList.begin();
2975
2976 //
2977 // Generate OpCapability
2978 //
2979 // TODO: Which llvm information is mapped to SPIRV Capapbility?
2980
2981 // Ops[0] = Capability
2982 SPIRVOperandList Ops;
2983
David Neto87846742018-04-11 17:36:22 -04002984 auto *CapInst =
2985 new SPIRVInstruction(spv::OpCapability, {MkNum(spv::CapabilityShader)});
David Neto22f144c2017-06-12 14:26:21 -04002986 SPIRVInstList.insert(InsertPoint, CapInst);
2987
2988 for (Type *Ty : getTypeList()) {
2989 // Find the i16 type.
2990 if (Ty->isIntegerTy(16)) {
2991 // Generate OpCapability for i16 type.
David Neto87846742018-04-11 17:36:22 -04002992 SPIRVInstList.insert(InsertPoint,
2993 new SPIRVInstruction(spv::OpCapability,
2994 {MkNum(spv::CapabilityInt16)}));
David Neto22f144c2017-06-12 14:26:21 -04002995 } else if (Ty->isIntegerTy(64)) {
2996 // Generate OpCapability for i64 type.
David Neto87846742018-04-11 17:36:22 -04002997 SPIRVInstList.insert(InsertPoint,
2998 new SPIRVInstruction(spv::OpCapability,
2999 {MkNum(spv::CapabilityInt64)}));
David Neto22f144c2017-06-12 14:26:21 -04003000 } else if (Ty->isHalfTy()) {
3001 // Generate OpCapability for half type.
3002 SPIRVInstList.insert(
David Neto87846742018-04-11 17:36:22 -04003003 InsertPoint, new SPIRVInstruction(spv::OpCapability,
3004 {MkNum(spv::CapabilityFloat16)}));
David Neto22f144c2017-06-12 14:26:21 -04003005 } else if (Ty->isDoubleTy()) {
3006 // Generate OpCapability for double type.
3007 SPIRVInstList.insert(
David Neto87846742018-04-11 17:36:22 -04003008 InsertPoint, new SPIRVInstruction(spv::OpCapability,
3009 {MkNum(spv::CapabilityFloat64)}));
David Neto22f144c2017-06-12 14:26:21 -04003010 } else if (auto *STy = dyn_cast<StructType>(Ty)) {
3011 if (STy->isOpaque()) {
David Neto565571c2017-08-21 12:00:05 -04003012 if (STy->getName().equals("opencl.image2d_wo_t") ||
3013 STy->getName().equals("opencl.image3d_wo_t")) {
David Neto22f144c2017-06-12 14:26:21 -04003014 // Generate OpCapability for write only image type.
3015 SPIRVInstList.insert(
3016 InsertPoint,
3017 new SPIRVInstruction(
David Neto87846742018-04-11 17:36:22 -04003018 spv::OpCapability,
3019 {MkNum(spv::CapabilityStorageImageWriteWithoutFormat)}));
David Neto22f144c2017-06-12 14:26:21 -04003020 }
3021 }
3022 }
3023 }
3024
David Neto5c22a252018-03-15 16:07:41 -04003025 { // OpCapability ImageQuery
3026 bool hasImageQuery = false;
3027 for (const char *imageQuery : {
3028 "_Z15get_image_width14ocl_image2d_ro",
3029 "_Z15get_image_width14ocl_image2d_wo",
3030 "_Z16get_image_height14ocl_image2d_ro",
3031 "_Z16get_image_height14ocl_image2d_wo",
3032 }) {
3033 if (module.getFunction(imageQuery)) {
3034 hasImageQuery = true;
3035 break;
3036 }
3037 }
3038 if (hasImageQuery) {
David Neto87846742018-04-11 17:36:22 -04003039 auto *ImageQueryCapInst = new SPIRVInstruction(
3040 spv::OpCapability, {MkNum(spv::CapabilityImageQuery)});
David Neto5c22a252018-03-15 16:07:41 -04003041 SPIRVInstList.insert(InsertPoint, ImageQueryCapInst);
3042 }
3043 }
3044
David Neto22f144c2017-06-12 14:26:21 -04003045 if (hasVariablePointers()) {
3046 //
3047 // Generate OpCapability and OpExtension
3048 //
3049
3050 //
3051 // Generate OpCapability.
3052 //
3053 // Ops[0] = Capability
3054 //
3055 Ops.clear();
David Neto257c3892018-04-11 13:19:45 -04003056 Ops << MkNum(spv::CapabilityVariablePointers);
David Neto22f144c2017-06-12 14:26:21 -04003057
David Neto87846742018-04-11 17:36:22 -04003058 SPIRVInstList.insert(InsertPoint,
3059 new SPIRVInstruction(spv::OpCapability, Ops));
David Neto22f144c2017-06-12 14:26:21 -04003060
3061 //
3062 // Generate OpExtension.
3063 //
3064 // Ops[0] = Name (Literal String)
3065 //
David Netoa772fd12017-08-04 14:17:33 -04003066 for (auto extension : {"SPV_KHR_storage_buffer_storage_class",
3067 "SPV_KHR_variable_pointers"}) {
David Neto22f144c2017-06-12 14:26:21 -04003068
David Neto87846742018-04-11 17:36:22 -04003069 auto *ExtensionInst =
3070 new SPIRVInstruction(spv::OpExtension, {MkString(extension)});
David Netoa772fd12017-08-04 14:17:33 -04003071 SPIRVInstList.insert(InsertPoint, ExtensionInst);
David Neto22f144c2017-06-12 14:26:21 -04003072 }
David Neto22f144c2017-06-12 14:26:21 -04003073 }
3074
3075 if (ExtInstImportID) {
3076 ++InsertPoint;
3077 }
3078
3079 //
3080 // Generate OpMemoryModel
3081 //
3082 // Memory model for Vulkan will always be GLSL450.
3083
3084 // Ops[0] = Addressing Model
3085 // Ops[1] = Memory Model
3086 Ops.clear();
David Neto257c3892018-04-11 13:19:45 -04003087 Ops << MkNum(spv::AddressingModelLogical) << MkNum(spv::MemoryModelGLSL450);
David Neto22f144c2017-06-12 14:26:21 -04003088
David Neto87846742018-04-11 17:36:22 -04003089 auto *MemModelInst = new SPIRVInstruction(spv::OpMemoryModel, Ops);
David Neto22f144c2017-06-12 14:26:21 -04003090 SPIRVInstList.insert(InsertPoint, MemModelInst);
3091
3092 //
3093 // Generate OpEntryPoint
3094 //
3095 for (auto EntryPoint : EntryPoints) {
3096 // Ops[0] = Execution Model
3097 // Ops[1] = EntryPoint ID
3098 // Ops[2] = Name (Literal String)
3099 // ...
3100 //
3101 // TODO: Do we need to consider Interface ID for forward references???
3102 Ops.clear();
David Neto257c3892018-04-11 13:19:45 -04003103 const StringRef& name = EntryPoint.first->getName();
3104 Ops << MkNum(spv::ExecutionModelGLCompute) << MkId(EntryPoint.second)
3105 << MkString(name);
David Neto22f144c2017-06-12 14:26:21 -04003106
David Neto22f144c2017-06-12 14:26:21 -04003107 for (Value *Interface : EntryPointInterfaces) {
David Neto257c3892018-04-11 13:19:45 -04003108 Ops << MkId(VMap[Interface]);
David Neto22f144c2017-06-12 14:26:21 -04003109 }
3110
David Neto87846742018-04-11 17:36:22 -04003111 auto *EntryPointInst = new SPIRVInstruction(spv::OpEntryPoint, Ops);
David Neto22f144c2017-06-12 14:26:21 -04003112 SPIRVInstList.insert(InsertPoint, EntryPointInst);
3113 }
3114
3115 for (auto EntryPoint : EntryPoints) {
3116 if (const MDNode *MD = dyn_cast<Function>(EntryPoint.first)
3117 ->getMetadata("reqd_work_group_size")) {
3118
3119 if (!BuiltinDimVec.empty()) {
3120 llvm_unreachable(
3121 "Kernels should have consistent work group size definition");
3122 }
3123
3124 //
3125 // Generate OpExecutionMode
3126 //
3127
3128 // Ops[0] = Entry Point ID
3129 // Ops[1] = Execution Mode
3130 // Ops[2] ... Ops[n] = Optional literals according to Execution Mode
3131 Ops.clear();
David Neto257c3892018-04-11 13:19:45 -04003132 Ops << MkId(EntryPoint.second)
3133 << MkNum(spv::ExecutionModeLocalSize);
David Neto22f144c2017-06-12 14:26:21 -04003134
3135 uint32_t XDim = static_cast<uint32_t>(
3136 mdconst::extract<ConstantInt>(MD->getOperand(0))->getZExtValue());
3137 uint32_t YDim = static_cast<uint32_t>(
3138 mdconst::extract<ConstantInt>(MD->getOperand(1))->getZExtValue());
3139 uint32_t ZDim = static_cast<uint32_t>(
3140 mdconst::extract<ConstantInt>(MD->getOperand(2))->getZExtValue());
3141
David Neto257c3892018-04-11 13:19:45 -04003142 Ops << MkNum(XDim) << MkNum(YDim) << MkNum(ZDim);
David Neto22f144c2017-06-12 14:26:21 -04003143
David Neto87846742018-04-11 17:36:22 -04003144 auto *ExecModeInst = new SPIRVInstruction(spv::OpExecutionMode, Ops);
David Neto22f144c2017-06-12 14:26:21 -04003145 SPIRVInstList.insert(InsertPoint, ExecModeInst);
3146 }
3147 }
3148
3149 //
3150 // Generate OpSource.
3151 //
3152 // Ops[0] = SourceLanguage ID
3153 // Ops[1] = Version (LiteralNum)
3154 //
3155 Ops.clear();
David Neto257c3892018-04-11 13:19:45 -04003156 Ops << MkNum(spv::SourceLanguageOpenCL_C) << MkNum(120);
David Neto22f144c2017-06-12 14:26:21 -04003157
David Neto87846742018-04-11 17:36:22 -04003158 auto *OpenSourceInst = new SPIRVInstruction(spv::OpSource, Ops);
David Neto22f144c2017-06-12 14:26:21 -04003159 SPIRVInstList.insert(InsertPoint, OpenSourceInst);
3160
3161 if (!BuiltinDimVec.empty()) {
3162 //
3163 // Generate OpDecorates for x/y/z dimension.
3164 //
3165 // Ops[0] = Target ID
3166 // Ops[1] = Decoration (SpecId)
David Neto257c3892018-04-11 13:19:45 -04003167 // Ops[2] = Specialization Constant ID (Literal Number)
David Neto22f144c2017-06-12 14:26:21 -04003168
3169 // X Dimension
3170 Ops.clear();
David Neto257c3892018-04-11 13:19:45 -04003171 Ops << MkId(BuiltinDimVec[0]) << MkNum(spv::DecorationSpecId) << MkNum(0);
David Neto87846742018-04-11 17:36:22 -04003172 SPIRVInstList.insert(InsertPoint,
3173 new SPIRVInstruction(spv::OpDecorate, Ops));
David Neto22f144c2017-06-12 14:26:21 -04003174
3175 // Y Dimension
3176 Ops.clear();
David Neto257c3892018-04-11 13:19:45 -04003177 Ops << MkId(BuiltinDimVec[1]) << MkNum(spv::DecorationSpecId) << MkNum(1);
David Neto87846742018-04-11 17:36:22 -04003178 SPIRVInstList.insert(InsertPoint,
3179 new SPIRVInstruction(spv::OpDecorate, Ops));
David Neto22f144c2017-06-12 14:26:21 -04003180
3181 // Z Dimension
3182 Ops.clear();
David Neto257c3892018-04-11 13:19:45 -04003183 Ops << MkId(BuiltinDimVec[2]) << MkNum(spv::DecorationSpecId) << MkNum(2);
David Neto87846742018-04-11 17:36:22 -04003184 SPIRVInstList.insert(InsertPoint,
3185 new SPIRVInstruction(spv::OpDecorate, Ops));
David Neto22f144c2017-06-12 14:26:21 -04003186 }
3187}
3188
3189void SPIRVProducerPass::GenerateInstForArg(Function &F) {
3190 SPIRVInstructionList &SPIRVInstList = getSPIRVInstList();
3191 ValueMapType &VMap = getValueMap();
3192 Module *Module = F.getParent();
3193 LLVMContext &Context = Module->getContext();
3194 ValueToValueMapTy &ArgGVMap = getArgumentGVMap();
3195
3196 for (Argument &Arg : F.args()) {
3197 if (Arg.use_empty()) {
3198 continue;
3199 }
3200
David Netoc6f3ab22018-04-06 18:02:31 -04003201 Type *ArgTy = Arg.getType();
3202 if (IsLocalPtr(ArgTy)) {
3203 // Generate OpAccessChain to point to the first element of the array.
3204 const LocalArgInfo &info = LocalArgMap[&Arg];
3205 VMap[&Arg] = info.first_elem_ptr_id;
3206
3207 SPIRVOperandList Ops;
3208 uint32_t zeroId = VMap[ConstantInt::get(Type::getInt32Ty(Context), 0)];
3209 Ops << MkId(lookupType(ArgTy)) << MkId(info.variable_id) << MkId(zeroId);
3210 SPIRVInstList.push_back(new SPIRVInstruction(
David Neto87846742018-04-11 17:36:22 -04003211 spv::OpAccessChain, info.first_elem_ptr_id, Ops));
David Netoc6f3ab22018-04-06 18:02:31 -04003212
3213 continue;
3214 }
3215
David Neto22f144c2017-06-12 14:26:21 -04003216 // Check the type of users of arguments.
3217 bool HasOnlyGEPUse = true;
3218 for (auto *U : Arg.users()) {
3219 if (!isa<GetElementPtrInst>(U) && isa<Instruction>(U)) {
3220 HasOnlyGEPUse = false;
3221 break;
3222 }
3223 }
3224
David Neto22f144c2017-06-12 14:26:21 -04003225 if (PointerType *PTy = dyn_cast<PointerType>(ArgTy)) {
3226 if (StructType *STy = dyn_cast<StructType>(PTy->getElementType())) {
3227 if (STy->isOpaque()) {
3228 // Generate OpLoad for sampler and image types.
3229 if (STy->getName().equals("opencl.sampler_t") ||
3230 STy->getName().equals("opencl.image2d_ro_t") ||
3231 STy->getName().equals("opencl.image2d_wo_t") ||
3232 STy->getName().equals("opencl.image3d_ro_t") ||
3233 STy->getName().equals("opencl.image3d_wo_t")) {
3234 //
3235 // Generate OpLoad.
3236 //
3237 // Ops[0] = Result Type ID
3238 // Ops[1] = Pointer ID
3239 // Ops[2] ... Ops[n] = Optional Memory Access
3240 //
3241 // TODO: Do we need to implement Optional Memory Access???
3242 SPIRVOperandList Ops;
3243
3244 // Use type with address space modified.
3245 ArgTy = ArgGVMap[&Arg]->getType()->getPointerElementType();
3246
David Neto257c3892018-04-11 13:19:45 -04003247 Ops << MkId(lookupType(ArgTy));
David Neto22f144c2017-06-12 14:26:21 -04003248
3249 uint32_t PointerID = VMap[&Arg];
David Neto257c3892018-04-11 13:19:45 -04003250 Ops << MkId(PointerID);
David Neto22f144c2017-06-12 14:26:21 -04003251
3252 VMap[&Arg] = nextID;
David Neto87846742018-04-11 17:36:22 -04003253 auto *Inst = new SPIRVInstruction(spv::OpLoad, nextID++, Ops);
David Neto22f144c2017-06-12 14:26:21 -04003254 SPIRVInstList.push_back(Inst);
3255 continue;
3256 }
3257 }
3258 }
3259
3260 if (!HasOnlyGEPUse) {
3261 //
3262 // Generate OpAccessChain.
3263 //
3264 // Ops[0] = Result Type ID
3265 // Ops[1] = Base ID
3266 // Ops[2] ... Ops[n] = Indexes ID
3267 SPIRVOperandList Ops;
3268
3269 uint32_t ResTyID = lookupType(ArgTy);
3270 if (!isa<PointerType>(ArgTy)) {
3271 ResTyID = lookupType(PointerType::get(ArgTy, AddressSpace::Global));
3272 }
David Neto257c3892018-04-11 13:19:45 -04003273 Ops << MkId(ResTyID);
David Neto22f144c2017-06-12 14:26:21 -04003274
3275 uint32_t BaseID = VMap[&Arg];
David Neto257c3892018-04-11 13:19:45 -04003276 Ops << MkId(BaseID) << MkId(GetI32Zero())
3277 << MkId(GetI32Zero());
David Neto22f144c2017-06-12 14:26:21 -04003278
3279 // Generate SPIRV instruction for argument.
3280 VMap[&Arg] = nextID;
David Neto87846742018-04-11 17:36:22 -04003281 auto *ArgInst = new SPIRVInstruction(spv::OpAccessChain, nextID++, Ops);
David Neto22f144c2017-06-12 14:26:21 -04003282 SPIRVInstList.push_back(ArgInst);
3283 } else {
3284 // For GEP uses, generate OpAccessChain with folding GEP ahead of GEP.
3285 // Nothing to do here.
3286 }
3287 } else {
3288 //
3289 // Generate OpAccessChain and OpLoad for non-pointer type argument.
3290 //
3291
3292 //
3293 // Generate OpAccessChain.
3294 //
3295 // Ops[0] = Result Type ID
3296 // Ops[1] = Base ID
3297 // Ops[2] ... Ops[n] = Indexes ID
3298 SPIRVOperandList Ops;
3299
3300 uint32_t ResTyID = lookupType(ArgTy);
3301 if (!isa<PointerType>(ArgTy)) {
David Neto482550a2018-03-24 05:21:07 -07003302 auto AS = clspv::Option::PodArgsInUniformBuffer()
3303 ? AddressSpace::Uniform
3304 : AddressSpace::Global;
David Netoe439d702018-03-23 13:14:08 -07003305 ResTyID = lookupType(PointerType::get(ArgTy, AS));
David Neto22f144c2017-06-12 14:26:21 -04003306 }
David Neto257c3892018-04-11 13:19:45 -04003307 Ops << MkId(ResTyID);
David Neto22f144c2017-06-12 14:26:21 -04003308
3309 uint32_t BaseID = VMap[&Arg];
David Neto257c3892018-04-11 13:19:45 -04003310 Ops << MkId(BaseID) << MkId(GetI32Zero());
David Neto22f144c2017-06-12 14:26:21 -04003311
3312 // Generate SPIRV instruction for argument.
3313 uint32_t PointerID = nextID;
3314 VMap[&Arg] = nextID;
David Neto87846742018-04-11 17:36:22 -04003315 auto *ArgInst = new SPIRVInstruction(spv::OpAccessChain, nextID++, Ops);
David Neto22f144c2017-06-12 14:26:21 -04003316 SPIRVInstList.push_back(ArgInst);
3317
3318 //
3319 // Generate OpLoad.
3320 //
3321
3322 // Ops[0] = Result Type ID
3323 // Ops[1] = Pointer ID
3324 // Ops[2] ... Ops[n] = Optional Memory Access
3325 //
3326 // TODO: Do we need to implement Optional Memory Access???
3327 Ops.clear();
David Neto257c3892018-04-11 13:19:45 -04003328 Ops << MkId(lookupType(ArgTy)) << MkId(PointerID);
David Neto22f144c2017-06-12 14:26:21 -04003329
3330 VMap[&Arg] = nextID;
David Neto87846742018-04-11 17:36:22 -04003331 auto *Inst = new SPIRVInstruction(spv::OpLoad, nextID++, Ops);
David Neto22f144c2017-06-12 14:26:21 -04003332 SPIRVInstList.push_back(Inst);
3333 }
3334 }
3335}
3336
3337void SPIRVProducerPass::GenerateFuncBody(Function &F) {
3338 SPIRVInstructionList &SPIRVInstList = getSPIRVInstList();
3339 ValueMapType &VMap = getValueMap();
3340
3341 bool IsKernel = false;
3342 if (F.getCallingConv() == CallingConv::SPIR_KERNEL) {
3343 IsKernel = true;
3344 }
3345
3346 for (BasicBlock &BB : F) {
3347 // Register BasicBlock to ValueMap.
3348 VMap[&BB] = nextID;
3349
3350 //
3351 // Generate OpLabel for Basic Block.
3352 //
3353 SPIRVOperandList Ops;
David Neto87846742018-04-11 17:36:22 -04003354 auto *Inst = new SPIRVInstruction(spv::OpLabel, nextID++, Ops);
David Neto22f144c2017-06-12 14:26:21 -04003355 SPIRVInstList.push_back(Inst);
3356
David Neto6dcd4712017-06-23 11:06:47 -04003357 // OpVariable instructions must come first.
3358 for (Instruction &I : BB) {
3359 if (isa<AllocaInst>(I)) {
3360 GenerateInstruction(I);
3361 }
3362 }
3363
David Neto22f144c2017-06-12 14:26:21 -04003364 if (&BB == &F.getEntryBlock() && IsKernel) {
3365 GenerateInstForArg(F);
3366 }
3367
3368 for (Instruction &I : BB) {
David Neto6dcd4712017-06-23 11:06:47 -04003369 if (!isa<AllocaInst>(I)) {
3370 GenerateInstruction(I);
3371 }
David Neto22f144c2017-06-12 14:26:21 -04003372 }
3373 }
3374}
3375
3376spv::Op SPIRVProducerPass::GetSPIRVCmpOpcode(CmpInst *I) {
3377 const std::map<CmpInst::Predicate, spv::Op> Map = {
3378 {CmpInst::ICMP_EQ, spv::OpIEqual},
3379 {CmpInst::ICMP_NE, spv::OpINotEqual},
3380 {CmpInst::ICMP_UGT, spv::OpUGreaterThan},
3381 {CmpInst::ICMP_UGE, spv::OpUGreaterThanEqual},
3382 {CmpInst::ICMP_ULT, spv::OpULessThan},
3383 {CmpInst::ICMP_ULE, spv::OpULessThanEqual},
3384 {CmpInst::ICMP_SGT, spv::OpSGreaterThan},
3385 {CmpInst::ICMP_SGE, spv::OpSGreaterThanEqual},
3386 {CmpInst::ICMP_SLT, spv::OpSLessThan},
3387 {CmpInst::ICMP_SLE, spv::OpSLessThanEqual},
3388 {CmpInst::FCMP_OEQ, spv::OpFOrdEqual},
3389 {CmpInst::FCMP_OGT, spv::OpFOrdGreaterThan},
3390 {CmpInst::FCMP_OGE, spv::OpFOrdGreaterThanEqual},
3391 {CmpInst::FCMP_OLT, spv::OpFOrdLessThan},
3392 {CmpInst::FCMP_OLE, spv::OpFOrdLessThanEqual},
3393 {CmpInst::FCMP_ONE, spv::OpFOrdNotEqual},
3394 {CmpInst::FCMP_UEQ, spv::OpFUnordEqual},
3395 {CmpInst::FCMP_UGT, spv::OpFUnordGreaterThan},
3396 {CmpInst::FCMP_UGE, spv::OpFUnordGreaterThanEqual},
3397 {CmpInst::FCMP_ULT, spv::OpFUnordLessThan},
3398 {CmpInst::FCMP_ULE, spv::OpFUnordLessThanEqual},
3399 {CmpInst::FCMP_UNE, spv::OpFUnordNotEqual}};
3400
3401 assert(0 != Map.count(I->getPredicate()));
3402
3403 return Map.at(I->getPredicate());
3404}
3405
3406spv::Op SPIRVProducerPass::GetSPIRVCastOpcode(Instruction &I) {
3407 const std::map<unsigned, spv::Op> Map{
3408 {Instruction::Trunc, spv::OpUConvert},
3409 {Instruction::ZExt, spv::OpUConvert},
3410 {Instruction::SExt, spv::OpSConvert},
3411 {Instruction::FPToUI, spv::OpConvertFToU},
3412 {Instruction::FPToSI, spv::OpConvertFToS},
3413 {Instruction::UIToFP, spv::OpConvertUToF},
3414 {Instruction::SIToFP, spv::OpConvertSToF},
3415 {Instruction::FPTrunc, spv::OpFConvert},
3416 {Instruction::FPExt, spv::OpFConvert},
3417 {Instruction::BitCast, spv::OpBitcast}};
3418
3419 assert(0 != Map.count(I.getOpcode()));
3420
3421 return Map.at(I.getOpcode());
3422}
3423
3424spv::Op SPIRVProducerPass::GetSPIRVBinaryOpcode(Instruction &I) {
3425 if (I.getType()->isIntegerTy(1)) {
3426 switch (I.getOpcode()) {
3427 default:
3428 break;
3429 case Instruction::Or:
3430 return spv::OpLogicalOr;
3431 case Instruction::And:
3432 return spv::OpLogicalAnd;
3433 case Instruction::Xor:
3434 return spv::OpLogicalNotEqual;
3435 }
3436 }
3437
3438 const std::map<unsigned, spv::Op> Map {
3439 {Instruction::Add, spv::OpIAdd},
3440 {Instruction::FAdd, spv::OpFAdd},
3441 {Instruction::Sub, spv::OpISub},
3442 {Instruction::FSub, spv::OpFSub},
3443 {Instruction::Mul, spv::OpIMul},
3444 {Instruction::FMul, spv::OpFMul},
3445 {Instruction::UDiv, spv::OpUDiv},
3446 {Instruction::SDiv, spv::OpSDiv},
3447 {Instruction::FDiv, spv::OpFDiv},
3448 {Instruction::URem, spv::OpUMod},
3449 {Instruction::SRem, spv::OpSRem},
3450 {Instruction::FRem, spv::OpFRem},
3451 {Instruction::Or, spv::OpBitwiseOr},
3452 {Instruction::Xor, spv::OpBitwiseXor},
3453 {Instruction::And, spv::OpBitwiseAnd},
3454 {Instruction::Shl, spv::OpShiftLeftLogical},
3455 {Instruction::LShr, spv::OpShiftRightLogical},
3456 {Instruction::AShr, spv::OpShiftRightArithmetic}};
3457
3458 assert(0 != Map.count(I.getOpcode()));
3459
3460 return Map.at(I.getOpcode());
3461}
3462
3463void SPIRVProducerPass::GenerateInstruction(Instruction &I) {
3464 SPIRVInstructionList &SPIRVInstList = getSPIRVInstList();
3465 ValueMapType &VMap = getValueMap();
3466 ValueToValueMapTy &ArgGVMap = getArgumentGVMap();
3467 ValueMapType &ArgGVIDMap = getArgumentGVIDMap();
3468 DeferredInstVecType &DeferredInsts = getDeferredInstVec();
3469 LLVMContext &Context = I.getParent()->getParent()->getParent()->getContext();
3470
3471 // Register Instruction to ValueMap.
3472 if (0 == VMap[&I]) {
3473 VMap[&I] = nextID;
3474 }
3475
3476 switch (I.getOpcode()) {
3477 default: {
3478 if (Instruction::isCast(I.getOpcode())) {
3479 //
3480 // Generate SPIRV instructions for cast operators.
3481 //
3482
David Netod2de94a2017-08-28 17:27:47 -04003483
3484 auto Ty = I.getType();
David Neto22f144c2017-06-12 14:26:21 -04003485 auto OpTy = I.getOperand(0)->getType();
David Netod2de94a2017-08-28 17:27:47 -04003486 auto toI8 = Ty == Type::getInt8Ty(Context);
3487 auto fromI32 = OpTy == Type::getInt32Ty(Context);
David Neto22f144c2017-06-12 14:26:21 -04003488 // Handle zext, sext and uitofp with i1 type specially.
3489 if ((I.getOpcode() == Instruction::ZExt ||
3490 I.getOpcode() == Instruction::SExt ||
3491 I.getOpcode() == Instruction::UIToFP) &&
3492 (OpTy->isIntegerTy(1) ||
3493 (OpTy->isVectorTy() &&
3494 OpTy->getVectorElementType()->isIntegerTy(1)))) {
3495 //
3496 // Generate OpSelect.
3497 //
3498
3499 // Ops[0] = Result Type ID
3500 // Ops[1] = Condition ID
3501 // Ops[2] = True Constant ID
3502 // Ops[3] = False Constant ID
3503 SPIRVOperandList Ops;
3504
David Neto257c3892018-04-11 13:19:45 -04003505 Ops << MkId(lookupType(I.getType()));
David Neto22f144c2017-06-12 14:26:21 -04003506
David Neto22f144c2017-06-12 14:26:21 -04003507 uint32_t CondID = VMap[I.getOperand(0)];
David Neto257c3892018-04-11 13:19:45 -04003508 Ops << MkId(CondID);
David Neto22f144c2017-06-12 14:26:21 -04003509
3510 uint32_t TrueID = 0;
3511 if (I.getOpcode() == Instruction::ZExt) {
3512 APInt One(32, 1);
3513 TrueID = VMap[Constant::getIntegerValue(I.getType(), One)];
3514 } else if (I.getOpcode() == Instruction::SExt) {
3515 APInt MinusOne(32, UINT64_MAX, true);
3516 TrueID = VMap[Constant::getIntegerValue(I.getType(), MinusOne)];
3517 } else {
3518 TrueID = VMap[ConstantFP::get(Context, APFloat(1.0f))];
3519 }
David Neto257c3892018-04-11 13:19:45 -04003520 Ops << MkId(TrueID);
David Neto22f144c2017-06-12 14:26:21 -04003521
3522 uint32_t FalseID = 0;
3523 if (I.getOpcode() == Instruction::ZExt) {
3524 FalseID = VMap[Constant::getNullValue(I.getType())];
3525 } else if (I.getOpcode() == Instruction::SExt) {
3526 FalseID = VMap[Constant::getNullValue(I.getType())];
3527 } else {
3528 FalseID = VMap[ConstantFP::get(Context, APFloat(0.0f))];
3529 }
David Neto257c3892018-04-11 13:19:45 -04003530 Ops << MkId(FalseID);
David Neto22f144c2017-06-12 14:26:21 -04003531
David Neto87846742018-04-11 17:36:22 -04003532 auto *Inst = new SPIRVInstruction(spv::OpSelect, nextID++, Ops);
David Neto22f144c2017-06-12 14:26:21 -04003533 SPIRVInstList.push_back(Inst);
David Netod2de94a2017-08-28 17:27:47 -04003534 } else if (I.getOpcode() == Instruction::Trunc && fromI32 && toI8) {
3535 // The SPIR-V target type is a 32-bit int. Keep only the bottom
3536 // 8 bits.
3537 // Before:
3538 // %result = trunc i32 %a to i8
3539 // After
3540 // %result = OpBitwiseAnd %uint %a %uint_255
3541
3542 SPIRVOperandList Ops;
3543
David Neto257c3892018-04-11 13:19:45 -04003544 Ops << MkId(lookupType(OpTy)) << MkId(VMap[I.getOperand(0)]);
David Netod2de94a2017-08-28 17:27:47 -04003545
3546 Type *UintTy = Type::getInt32Ty(Context);
3547 uint32_t MaskID = VMap[ConstantInt::get(UintTy, 255)];
David Neto257c3892018-04-11 13:19:45 -04003548 Ops << MkId(MaskID);
David Netod2de94a2017-08-28 17:27:47 -04003549
David Neto87846742018-04-11 17:36:22 -04003550 auto *Inst = new SPIRVInstruction(spv::OpBitwiseAnd, nextID++, Ops);
David Netod2de94a2017-08-28 17:27:47 -04003551 SPIRVInstList.push_back(Inst);
David Neto22f144c2017-06-12 14:26:21 -04003552 } else {
3553 // Ops[0] = Result Type ID
3554 // Ops[1] = Source Value ID
3555 SPIRVOperandList Ops;
3556
David Neto257c3892018-04-11 13:19:45 -04003557 Ops << MkId(lookupType(I.getType())) << MkId(VMap[I.getOperand(0)]);
David Neto22f144c2017-06-12 14:26:21 -04003558
David Neto87846742018-04-11 17:36:22 -04003559 auto *Inst = new SPIRVInstruction(GetSPIRVCastOpcode(I), nextID++, Ops);
David Neto22f144c2017-06-12 14:26:21 -04003560 SPIRVInstList.push_back(Inst);
3561 }
3562 } else if (isa<BinaryOperator>(I)) {
3563 //
3564 // Generate SPIRV instructions for binary operators.
3565 //
3566
3567 // Handle xor with i1 type specially.
3568 if (I.getOpcode() == Instruction::Xor &&
3569 I.getType() == Type::getInt1Ty(Context) &&
3570 (isa<Constant>(I.getOperand(0)) || isa<Constant>(I.getOperand(1)))) {
3571 //
3572 // Generate OpLogicalNot.
3573 //
3574 // Ops[0] = Result Type ID
3575 // Ops[1] = Operand
3576 SPIRVOperandList Ops;
3577
David Neto257c3892018-04-11 13:19:45 -04003578 Ops << MkId(lookupType(I.getType()));
David Neto22f144c2017-06-12 14:26:21 -04003579
3580 Value *CondV = I.getOperand(0);
3581 if (isa<Constant>(I.getOperand(0))) {
3582 CondV = I.getOperand(1);
3583 }
David Neto257c3892018-04-11 13:19:45 -04003584 Ops << MkId(VMap[CondV]);
David Neto22f144c2017-06-12 14:26:21 -04003585
David Neto87846742018-04-11 17:36:22 -04003586 auto *Inst = new SPIRVInstruction(spv::OpLogicalNot, nextID++, Ops);
David Neto22f144c2017-06-12 14:26:21 -04003587 SPIRVInstList.push_back(Inst);
3588 } else {
3589 // Ops[0] = Result Type ID
3590 // Ops[1] = Operand 0
3591 // Ops[2] = Operand 1
3592 SPIRVOperandList Ops;
3593
David Neto257c3892018-04-11 13:19:45 -04003594 Ops << MkId(lookupType(I.getType())) << MkId(VMap[I.getOperand(0)])
3595 << MkId(VMap[I.getOperand(1)]);
David Neto22f144c2017-06-12 14:26:21 -04003596
David Neto87846742018-04-11 17:36:22 -04003597 auto *Inst =
3598 new SPIRVInstruction(GetSPIRVBinaryOpcode(I), nextID++, Ops);
David Neto22f144c2017-06-12 14:26:21 -04003599 SPIRVInstList.push_back(Inst);
3600 }
3601 } else {
3602 I.print(errs());
3603 llvm_unreachable("Unsupported instruction???");
3604 }
3605 break;
3606 }
3607 case Instruction::GetElementPtr: {
3608 auto &GlobalConstArgSet = getGlobalConstArgSet();
3609
3610 //
3611 // Generate OpAccessChain.
3612 //
3613 GetElementPtrInst *GEP = cast<GetElementPtrInst>(&I);
3614
3615 //
3616 // Generate OpAccessChain.
3617 //
3618
3619 // Ops[0] = Result Type ID
3620 // Ops[1] = Base ID
3621 // Ops[2] ... Ops[n] = Indexes ID
3622 SPIRVOperandList Ops;
3623
David Neto1a1a0582017-07-07 12:01:44 -04003624 PointerType* ResultType = cast<PointerType>(GEP->getType());
David Neto22f144c2017-06-12 14:26:21 -04003625 if (GEP->getPointerAddressSpace() == AddressSpace::ModuleScopePrivate ||
3626 GlobalConstArgSet.count(GEP->getPointerOperand())) {
3627 // Use pointer type with private address space for global constant.
3628 Type *EleTy = I.getType()->getPointerElementType();
David Neto1a1a0582017-07-07 12:01:44 -04003629 ResultType = PointerType::get(EleTy, AddressSpace::ModuleScopePrivate);
David Neto22f144c2017-06-12 14:26:21 -04003630 }
David Neto257c3892018-04-11 13:19:45 -04003631
3632 Ops << MkId(lookupType(ResultType));
David Neto22f144c2017-06-12 14:26:21 -04003633
3634 // Check whether GEP's pointer operand is pointer argument.
3635 bool HasArgBasePointer = false;
3636 for (auto ArgGV : ArgGVMap) {
3637 if (ArgGV.first == GEP->getPointerOperand()) {
3638 if (isa<PointerType>(ArgGV.first->getType())) {
3639 HasArgBasePointer = true;
3640 } else {
3641 llvm_unreachable(
3642 "GEP's pointer operand is argument of non-poninter type???");
3643 }
3644 }
3645 }
3646
3647 uint32_t BaseID;
3648 if (HasArgBasePointer) {
3649 // Point to global variable for argument directly.
3650 BaseID = ArgGVIDMap[GEP->getPointerOperand()];
3651 } else {
3652 BaseID = VMap[GEP->getPointerOperand()];
3653 }
3654
David Neto257c3892018-04-11 13:19:45 -04003655 Ops << MkId(BaseID);
David Neto22f144c2017-06-12 14:26:21 -04003656
David Neto22f144c2017-06-12 14:26:21 -04003657 if (HasArgBasePointer) {
3658 // If GEP's pointer operand is argument, add one more index for struct
3659 // type to wrap up argument type.
3660 Type *IdxTy = Type::getInt32Ty(Context);
David Neto257c3892018-04-11 13:19:45 -04003661 Ops << MkId(VMap[ConstantInt::get(IdxTy, 0)]);
David Neto22f144c2017-06-12 14:26:21 -04003662 }
3663
3664 //
3665 // Follows below rules for gep.
3666 //
3667 // 1. If gep's first index is 0 and gep's base is not kernel function's
3668 // argument, generate OpAccessChain and ignore gep's first index.
3669 // 2. If gep's first index is not 0, generate OpPtrAccessChain and use gep's
3670 // first index.
3671 // 3. If gep's first index is not constant, generate OpPtrAccessChain and
3672 // use gep's first index.
3673 // 4. If it is not above case 1, 2 and 3, generate OpAccessChain and use
3674 // gep's first index.
3675 //
3676 spv::Op Opcode = spv::OpAccessChain;
3677 unsigned offset = 0;
3678 if (ConstantInt *CstInt = dyn_cast<ConstantInt>(GEP->getOperand(1))) {
3679 if (CstInt->getZExtValue() == 0 && !HasArgBasePointer) {
3680 offset = 1;
3681 } else if (CstInt->getZExtValue() != 0 && !HasArgBasePointer) {
3682 Opcode = spv::OpPtrAccessChain;
David Neto22f144c2017-06-12 14:26:21 -04003683 }
3684 } else if (!HasArgBasePointer) {
3685 Opcode = spv::OpPtrAccessChain;
David Neto1a1a0582017-07-07 12:01:44 -04003686 }
3687
3688 if (Opcode == spv::OpPtrAccessChain) {
David Neto22f144c2017-06-12 14:26:21 -04003689 setVariablePointers(true);
David Neto1a1a0582017-07-07 12:01:44 -04003690 // Do we need to generate ArrayStride? Check against the GEP result type
3691 // rather than the pointer type of the base because when indexing into
3692 // an OpenCL program-scope constant, we'll swap out the LLVM base pointer
3693 // for something else in the SPIR-V.
3694 // E.g. see test/PointerAccessChain/pointer_index_is_constant_1.cl
3695 if (GetStorageClass(ResultType->getAddressSpace()) ==
3696 spv::StorageClassStorageBuffer) {
3697 // Save the need to generate an ArrayStride decoration. But defer
3698 // generation until later, so we only make one decoration.
David Neto85082642018-03-24 06:55:20 -07003699 getTypesNeedingArrayStride().insert(ResultType);
David Neto1a1a0582017-07-07 12:01:44 -04003700 }
David Neto22f144c2017-06-12 14:26:21 -04003701 }
3702
3703 for (auto II = GEP->idx_begin() + offset; II != GEP->idx_end(); II++) {
David Neto257c3892018-04-11 13:19:45 -04003704 Ops << MkId(VMap[*II]);
David Neto22f144c2017-06-12 14:26:21 -04003705 }
3706
David Neto87846742018-04-11 17:36:22 -04003707 auto *Inst = new SPIRVInstruction(Opcode, nextID++, Ops);
David Neto22f144c2017-06-12 14:26:21 -04003708 SPIRVInstList.push_back(Inst);
3709 break;
3710 }
3711 case Instruction::ExtractValue: {
3712 ExtractValueInst *EVI = cast<ExtractValueInst>(&I);
3713 // Ops[0] = Result Type ID
3714 // Ops[1] = Composite ID
3715 // Ops[2] ... Ops[n] = Indexes (Literal Number)
3716 SPIRVOperandList Ops;
3717
David Neto257c3892018-04-11 13:19:45 -04003718 Ops << MkId(lookupType(I.getType()));
David Neto22f144c2017-06-12 14:26:21 -04003719
3720 uint32_t CompositeID = VMap[EVI->getAggregateOperand()];
David Neto257c3892018-04-11 13:19:45 -04003721 Ops << MkId(CompositeID);
David Neto22f144c2017-06-12 14:26:21 -04003722
3723 for (auto &Index : EVI->indices()) {
David Neto257c3892018-04-11 13:19:45 -04003724 Ops << MkNum(Index);
David Neto22f144c2017-06-12 14:26:21 -04003725 }
3726
David Neto87846742018-04-11 17:36:22 -04003727 auto *Inst = new SPIRVInstruction(spv::OpCompositeExtract, nextID++, Ops);
David Neto22f144c2017-06-12 14:26:21 -04003728 SPIRVInstList.push_back(Inst);
3729 break;
3730 }
3731 case Instruction::InsertValue: {
3732 InsertValueInst *IVI = cast<InsertValueInst>(&I);
3733 // Ops[0] = Result Type ID
3734 // Ops[1] = Object ID
3735 // Ops[2] = Composite ID
3736 // Ops[3] ... Ops[n] = Indexes (Literal Number)
3737 SPIRVOperandList Ops;
3738
3739 uint32_t ResTyID = lookupType(I.getType());
David Neto257c3892018-04-11 13:19:45 -04003740 Ops << MkId(ResTyID);
David Neto22f144c2017-06-12 14:26:21 -04003741
3742 uint32_t ObjectID = VMap[IVI->getInsertedValueOperand()];
David Neto257c3892018-04-11 13:19:45 -04003743 Ops << MkId(ObjectID);
David Neto22f144c2017-06-12 14:26:21 -04003744
3745 uint32_t CompositeID = VMap[IVI->getAggregateOperand()];
David Neto257c3892018-04-11 13:19:45 -04003746 Ops << MkId(CompositeID);
David Neto22f144c2017-06-12 14:26:21 -04003747
3748 for (auto &Index : IVI->indices()) {
David Neto257c3892018-04-11 13:19:45 -04003749 Ops << MkNum(Index);
David Neto22f144c2017-06-12 14:26:21 -04003750 }
3751
David Neto87846742018-04-11 17:36:22 -04003752 auto *Inst = new SPIRVInstruction(spv::OpCompositeInsert, nextID++, Ops);
David Neto22f144c2017-06-12 14:26:21 -04003753 SPIRVInstList.push_back(Inst);
3754 break;
3755 }
3756 case Instruction::Select: {
3757 //
3758 // Generate OpSelect.
3759 //
3760
3761 // Ops[0] = Result Type ID
3762 // Ops[1] = Condition ID
3763 // Ops[2] = True Constant ID
3764 // Ops[3] = False Constant ID
3765 SPIRVOperandList Ops;
3766
3767 // Find SPIRV instruction for parameter type.
3768 auto Ty = I.getType();
3769 if (Ty->isPointerTy()) {
3770 auto PointeeTy = Ty->getPointerElementType();
3771 if (PointeeTy->isStructTy() &&
3772 dyn_cast<StructType>(PointeeTy)->isOpaque()) {
3773 Ty = PointeeTy;
3774 }
3775 }
3776
David Neto257c3892018-04-11 13:19:45 -04003777 Ops << MkId(lookupType(Ty)) << MkId(VMap[I.getOperand(0)])
3778 << MkId(VMap[I.getOperand(1)]) << MkId(VMap[I.getOperand(2)]);
David Neto22f144c2017-06-12 14:26:21 -04003779
David Neto87846742018-04-11 17:36:22 -04003780 auto *Inst = new SPIRVInstruction(spv::OpSelect, nextID++, Ops);
David Neto22f144c2017-06-12 14:26:21 -04003781 SPIRVInstList.push_back(Inst);
3782 break;
3783 }
3784 case Instruction::ExtractElement: {
3785 // Handle <4 x i8> type manually.
3786 Type *CompositeTy = I.getOperand(0)->getType();
3787 if (is4xi8vec(CompositeTy)) {
3788 //
3789 // Generate OpShiftRightLogical and OpBitwiseAnd for extractelement with
3790 // <4 x i8>.
3791 //
3792
3793 //
3794 // Generate OpShiftRightLogical
3795 //
3796 // Ops[0] = Result Type ID
3797 // Ops[1] = Operand 0
3798 // Ops[2] = Operand 1
3799 //
3800 SPIRVOperandList Ops;
3801
David Neto257c3892018-04-11 13:19:45 -04003802 Ops << MkId(lookupType(CompositeTy));
David Neto22f144c2017-06-12 14:26:21 -04003803
3804 uint32_t Op0ID = VMap[I.getOperand(0)];
David Neto257c3892018-04-11 13:19:45 -04003805 Ops << MkId(Op0ID);
David Neto22f144c2017-06-12 14:26:21 -04003806
3807 uint32_t Op1ID = 0;
3808 if (ConstantInt *CI = dyn_cast<ConstantInt>(I.getOperand(1))) {
3809 // Handle constant index.
3810 uint64_t Idx = CI->getZExtValue();
3811 Value *ShiftAmount =
3812 ConstantInt::get(Type::getInt32Ty(Context), Idx * 8);
3813 Op1ID = VMap[ShiftAmount];
3814 } else {
3815 // Handle variable index.
3816 SPIRVOperandList TmpOps;
3817
David Neto257c3892018-04-11 13:19:45 -04003818 TmpOps << MkId(lookupType(Type::getInt32Ty(Context)))
3819 << MkId(VMap[I.getOperand(1)]);
David Neto22f144c2017-06-12 14:26:21 -04003820
3821 ConstantInt *Cst8 = ConstantInt::get(Type::getInt32Ty(Context), 8);
David Neto257c3892018-04-11 13:19:45 -04003822 TmpOps << MkId(VMap[Cst8]);
David Neto22f144c2017-06-12 14:26:21 -04003823
3824 Op1ID = nextID;
3825
David Neto87846742018-04-11 17:36:22 -04003826 auto *TmpInst = new SPIRVInstruction(spv::OpIMul, nextID++, TmpOps);
David Neto22f144c2017-06-12 14:26:21 -04003827 SPIRVInstList.push_back(TmpInst);
3828 }
David Neto257c3892018-04-11 13:19:45 -04003829 Ops << MkId(Op1ID);
David Neto22f144c2017-06-12 14:26:21 -04003830
3831 uint32_t ShiftID = nextID;
3832
David Neto87846742018-04-11 17:36:22 -04003833 auto *Inst =
3834 new SPIRVInstruction(spv::OpShiftRightLogical, nextID++, Ops);
David Neto22f144c2017-06-12 14:26:21 -04003835 SPIRVInstList.push_back(Inst);
3836
3837 //
3838 // Generate OpBitwiseAnd
3839 //
3840 // Ops[0] = Result Type ID
3841 // Ops[1] = Operand 0
3842 // Ops[2] = Operand 1
3843 //
3844 Ops.clear();
3845
David Neto257c3892018-04-11 13:19:45 -04003846 Ops << MkId(lookupType(CompositeTy)) << MkId(ShiftID);
David Neto22f144c2017-06-12 14:26:21 -04003847
3848 Constant *CstFF = ConstantInt::get(Type::getInt32Ty(Context), 0xFF);
David Neto257c3892018-04-11 13:19:45 -04003849 Ops << MkId(VMap[CstFF]);
David Neto22f144c2017-06-12 14:26:21 -04003850
David Neto9b2d6252017-09-06 15:47:37 -04003851 // Reset mapping for this value to the result of the bitwise and.
3852 VMap[&I] = nextID;
3853
David Neto87846742018-04-11 17:36:22 -04003854 Inst = new SPIRVInstruction(spv::OpBitwiseAnd, nextID++, Ops);
David Neto22f144c2017-06-12 14:26:21 -04003855 SPIRVInstList.push_back(Inst);
3856 break;
3857 }
3858
3859 // Ops[0] = Result Type ID
3860 // Ops[1] = Composite ID
3861 // Ops[2] ... Ops[n] = Indexes (Literal Number)
3862 SPIRVOperandList Ops;
3863
David Neto257c3892018-04-11 13:19:45 -04003864 Ops << MkId(lookupType(I.getType())) << MkId(VMap[I.getOperand(0)]);
David Neto22f144c2017-06-12 14:26:21 -04003865
3866 spv::Op Opcode = spv::OpCompositeExtract;
3867 if (const ConstantInt *CI = dyn_cast<ConstantInt>(I.getOperand(1))) {
David Neto257c3892018-04-11 13:19:45 -04003868 Ops << MkNum(static_cast<uint32_t>(CI->getZExtValue()));
David Neto22f144c2017-06-12 14:26:21 -04003869 } else {
David Neto257c3892018-04-11 13:19:45 -04003870 Ops << MkId(VMap[I.getOperand(1)]);
David Neto22f144c2017-06-12 14:26:21 -04003871 Opcode = spv::OpVectorExtractDynamic;
3872 }
3873
David Neto87846742018-04-11 17:36:22 -04003874 auto *Inst = new SPIRVInstruction(Opcode, nextID++, Ops);
David Neto22f144c2017-06-12 14:26:21 -04003875 SPIRVInstList.push_back(Inst);
3876 break;
3877 }
3878 case Instruction::InsertElement: {
3879 // Handle <4 x i8> type manually.
3880 Type *CompositeTy = I.getOperand(0)->getType();
3881 if (is4xi8vec(CompositeTy)) {
3882 Constant *CstFF = ConstantInt::get(Type::getInt32Ty(Context), 0xFF);
3883 uint32_t CstFFID = VMap[CstFF];
3884
3885 uint32_t ShiftAmountID = 0;
3886 if (ConstantInt *CI = dyn_cast<ConstantInt>(I.getOperand(2))) {
3887 // Handle constant index.
3888 uint64_t Idx = CI->getZExtValue();
3889 Value *ShiftAmount =
3890 ConstantInt::get(Type::getInt32Ty(Context), Idx * 8);
3891 ShiftAmountID = VMap[ShiftAmount];
3892 } else {
3893 // Handle variable index.
3894 SPIRVOperandList TmpOps;
3895
David Neto257c3892018-04-11 13:19:45 -04003896 TmpOps << MkId(lookupType(Type::getInt32Ty(Context)))
3897 << MkId(VMap[I.getOperand(2)]);
David Neto22f144c2017-06-12 14:26:21 -04003898
3899 ConstantInt *Cst8 = ConstantInt::get(Type::getInt32Ty(Context), 8);
David Neto257c3892018-04-11 13:19:45 -04003900 TmpOps << MkId(VMap[Cst8]);
David Neto22f144c2017-06-12 14:26:21 -04003901
3902 ShiftAmountID = nextID;
3903
David Neto87846742018-04-11 17:36:22 -04003904 auto *TmpInst = new SPIRVInstruction(spv::OpIMul, nextID++, TmpOps);
David Neto22f144c2017-06-12 14:26:21 -04003905 SPIRVInstList.push_back(TmpInst);
3906 }
3907
3908 //
3909 // Generate mask operations.
3910 //
3911
3912 // ShiftLeft mask according to index of insertelement.
3913 SPIRVOperandList Ops;
3914
David Neto257c3892018-04-11 13:19:45 -04003915 const uint32_t ResTyID = lookupType(CompositeTy);
3916 Ops << MkId(ResTyID) << MkId(CstFFID) << MkId(ShiftAmountID);
David Neto22f144c2017-06-12 14:26:21 -04003917
3918 uint32_t MaskID = nextID;
3919
David Neto87846742018-04-11 17:36:22 -04003920 auto *Inst = new SPIRVInstruction(spv::OpShiftLeftLogical, nextID++, Ops);
David Neto22f144c2017-06-12 14:26:21 -04003921 SPIRVInstList.push_back(Inst);
3922
3923 // Inverse mask.
3924 Ops.clear();
David Neto257c3892018-04-11 13:19:45 -04003925 Ops << MkId(ResTyID) << MkId(MaskID);
David Neto22f144c2017-06-12 14:26:21 -04003926
3927 uint32_t InvMaskID = nextID;
3928
David Neto87846742018-04-11 17:36:22 -04003929 Inst = new SPIRVInstruction(spv::OpNot, nextID++, Ops);
David Neto22f144c2017-06-12 14:26:21 -04003930 SPIRVInstList.push_back(Inst);
3931
3932 // Apply mask.
3933 Ops.clear();
David Neto257c3892018-04-11 13:19:45 -04003934 Ops << MkId(ResTyID) << MkId(VMap[I.getOperand(0)]) << MkId(InvMaskID);
David Neto22f144c2017-06-12 14:26:21 -04003935
3936 uint32_t OrgValID = nextID;
3937
David Neto87846742018-04-11 17:36:22 -04003938 Inst = new SPIRVInstruction(spv::OpBitwiseAnd, nextID++, Ops);
David Neto22f144c2017-06-12 14:26:21 -04003939 SPIRVInstList.push_back(Inst);
3940
3941 // Create correct value according to index of insertelement.
3942 Ops.clear();
David Neto257c3892018-04-11 13:19:45 -04003943 Ops << MkId(ResTyID) << MkId(VMap[I.getOperand(1)]) << MkId(ShiftAmountID);
David Neto22f144c2017-06-12 14:26:21 -04003944
3945 uint32_t InsertValID = nextID;
3946
David Neto87846742018-04-11 17:36:22 -04003947 Inst = new SPIRVInstruction(spv::OpShiftLeftLogical, nextID++, Ops);
David Neto22f144c2017-06-12 14:26:21 -04003948 SPIRVInstList.push_back(Inst);
3949
3950 // Insert value to original value.
3951 Ops.clear();
David Neto257c3892018-04-11 13:19:45 -04003952 Ops << MkId(ResTyID) << MkId(OrgValID) << MkId(InsertValID);
David Neto22f144c2017-06-12 14:26:21 -04003953
David Netoa394f392017-08-26 20:45:29 -04003954 VMap[&I] = nextID;
3955
David Neto87846742018-04-11 17:36:22 -04003956 Inst = new SPIRVInstruction(spv::OpBitwiseOr, nextID++, Ops);
David Neto22f144c2017-06-12 14:26:21 -04003957 SPIRVInstList.push_back(Inst);
3958
3959 break;
3960 }
3961
3962 // Ops[0] = Result Type ID
3963 // Ops[1] = Object ID
3964 // Ops[2] = Composite ID
3965 // Ops[3] ... Ops[n] = Indexes (Literal Number)
3966 SPIRVOperandList Ops;
3967
David Neto257c3892018-04-11 13:19:45 -04003968 Ops << MkId(lookupType(I.getType())) << MkId(VMap[I.getOperand(1)])
3969 << MkId(VMap[I.getOperand(0)]);
David Neto22f144c2017-06-12 14:26:21 -04003970
3971 spv::Op Opcode = spv::OpCompositeInsert;
3972 if (const ConstantInt *CI = dyn_cast<ConstantInt>(I.getOperand(2))) {
David Neto257c3892018-04-11 13:19:45 -04003973 const auto value = CI->getZExtValue();
3974 assert(value <= UINT32_MAX);
3975 Ops << MkNum(static_cast<uint32_t>(value));
David Neto22f144c2017-06-12 14:26:21 -04003976 } else {
David Neto257c3892018-04-11 13:19:45 -04003977 Ops << MkId(VMap[I.getOperand(1)]);
David Neto22f144c2017-06-12 14:26:21 -04003978 Opcode = spv::OpVectorInsertDynamic;
3979 }
3980
David Neto87846742018-04-11 17:36:22 -04003981 auto *Inst = new SPIRVInstruction(Opcode, nextID++, Ops);
David Neto22f144c2017-06-12 14:26:21 -04003982 SPIRVInstList.push_back(Inst);
3983 break;
3984 }
3985 case Instruction::ShuffleVector: {
3986 // Ops[0] = Result Type ID
3987 // Ops[1] = Vector 1 ID
3988 // Ops[2] = Vector 2 ID
3989 // Ops[3] ... Ops[n] = Components (Literal Number)
3990 SPIRVOperandList Ops;
3991
David Neto257c3892018-04-11 13:19:45 -04003992 Ops << MkId(lookupType(I.getType())) << MkId(VMap[I.getOperand(0)])
3993 << MkId(VMap[I.getOperand(1)]);
David Neto22f144c2017-06-12 14:26:21 -04003994
3995 uint64_t NumElements = 0;
3996 if (Constant *Cst = dyn_cast<Constant>(I.getOperand(2))) {
3997 NumElements = cast<VectorType>(Cst->getType())->getNumElements();
3998
3999 if (Cst->isNullValue()) {
4000 for (unsigned i = 0; i < NumElements; i++) {
David Neto257c3892018-04-11 13:19:45 -04004001 Ops << MkNum(0);
David Neto22f144c2017-06-12 14:26:21 -04004002 }
4003 } else if (const ConstantDataSequential *CDS =
4004 dyn_cast<ConstantDataSequential>(Cst)) {
4005 for (unsigned i = 0; i < CDS->getNumElements(); i++) {
4006 std::vector<uint32_t> LiteralNum;
David Neto257c3892018-04-11 13:19:45 -04004007 const auto value = CDS->getElementAsInteger(i);
4008 assert(value <= UINT32_MAX);
4009 Ops << MkNum(static_cast<uint32_t>(value));
David Neto22f144c2017-06-12 14:26:21 -04004010 }
4011 } else if (const ConstantVector *CV = dyn_cast<ConstantVector>(Cst)) {
4012 for (unsigned i = 0; i < CV->getNumOperands(); i++) {
4013 auto Op = CV->getOperand(i);
4014
4015 uint32_t literal = 0;
4016
4017 if (auto CI = dyn_cast<ConstantInt>(Op)) {
4018 literal = static_cast<uint32_t>(CI->getZExtValue());
4019 } else if (auto UI = dyn_cast<UndefValue>(Op)) {
4020 literal = 0xFFFFFFFFu;
4021 } else {
4022 Op->print(errs());
4023 llvm_unreachable("Unsupported element in ConstantVector!");
4024 }
4025
David Neto257c3892018-04-11 13:19:45 -04004026 Ops << MkNum(literal);
David Neto22f144c2017-06-12 14:26:21 -04004027 }
4028 } else {
4029 Cst->print(errs());
4030 llvm_unreachable("Unsupported constant mask in ShuffleVector!");
4031 }
4032 }
4033
David Neto87846742018-04-11 17:36:22 -04004034 auto *Inst = new SPIRVInstruction(spv::OpVectorShuffle, nextID++, Ops);
David Neto22f144c2017-06-12 14:26:21 -04004035 SPIRVInstList.push_back(Inst);
4036 break;
4037 }
4038 case Instruction::ICmp:
4039 case Instruction::FCmp: {
4040 CmpInst *CmpI = cast<CmpInst>(&I);
4041
David Netod4ca2e62017-07-06 18:47:35 -04004042 // Pointer equality is invalid.
4043 Type* ArgTy = CmpI->getOperand(0)->getType();
4044 if (isa<PointerType>(ArgTy)) {
4045 CmpI->print(errs());
4046 std::string name = I.getParent()->getParent()->getName();
4047 errs()
4048 << "\nPointer equality test is not supported by SPIR-V for Vulkan, "
4049 << "in function " << name << "\n";
4050 llvm_unreachable("Pointer equality check is invalid");
4051 break;
4052 }
4053
David Neto257c3892018-04-11 13:19:45 -04004054 // Ops[0] = Result Type ID
4055 // Ops[1] = Operand 1 ID
4056 // Ops[2] = Operand 2 ID
4057 SPIRVOperandList Ops;
David Neto22f144c2017-06-12 14:26:21 -04004058
David Neto257c3892018-04-11 13:19:45 -04004059 Ops << MkId(lookupType(CmpI->getType())) << MkId(VMap[CmpI->getOperand(0)])
4060 << MkId(VMap[CmpI->getOperand(1)]);
David Neto22f144c2017-06-12 14:26:21 -04004061
4062 spv::Op Opcode = GetSPIRVCmpOpcode(CmpI);
David Neto87846742018-04-11 17:36:22 -04004063 auto *Inst = new SPIRVInstruction(Opcode, nextID++, Ops);
David Neto22f144c2017-06-12 14:26:21 -04004064 SPIRVInstList.push_back(Inst);
4065 break;
4066 }
4067 case Instruction::Br: {
4068 // Branch instrucion is deferred because it needs label's ID. Record slot's
4069 // location on SPIRVInstructionList.
4070 DeferredInsts.push_back(
4071 std::make_tuple(&I, --SPIRVInstList.end(), 0 /* No id */));
4072 break;
4073 }
4074 case Instruction::Switch: {
4075 I.print(errs());
4076 llvm_unreachable("Unsupported instruction???");
4077 break;
4078 }
4079 case Instruction::IndirectBr: {
4080 I.print(errs());
4081 llvm_unreachable("Unsupported instruction???");
4082 break;
4083 }
4084 case Instruction::PHI: {
4085 // Branch instrucion is deferred because it needs label's ID. Record slot's
4086 // location on SPIRVInstructionList.
4087 DeferredInsts.push_back(
4088 std::make_tuple(&I, --SPIRVInstList.end(), nextID++));
4089 break;
4090 }
4091 case Instruction::Alloca: {
4092 //
4093 // Generate OpVariable.
4094 //
4095 // Ops[0] : Result Type ID
4096 // Ops[1] : Storage Class
4097 SPIRVOperandList Ops;
4098
David Neto257c3892018-04-11 13:19:45 -04004099 Ops << MkId(lookupType(I.getType())) << MkNum(spv::StorageClassFunction);
David Neto22f144c2017-06-12 14:26:21 -04004100
David Neto87846742018-04-11 17:36:22 -04004101 auto *Inst = new SPIRVInstruction(spv::OpVariable, nextID++, Ops);
David Neto22f144c2017-06-12 14:26:21 -04004102 SPIRVInstList.push_back(Inst);
4103 break;
4104 }
4105 case Instruction::Load: {
4106 LoadInst *LD = cast<LoadInst>(&I);
4107 //
4108 // Generate OpLoad.
4109 //
4110
David Neto0a2f98d2017-09-15 19:38:40 -04004111 uint32_t ResTyID = lookupType(LD->getType());
David Netoa60b00b2017-09-15 16:34:09 -04004112 uint32_t PointerID = VMap[LD->getPointerOperand()];
4113
4114 // This is a hack to work around what looks like a driver bug.
4115 // When we're loading from the special variable holding the WorkgroupSize
David Neto0a2f98d2017-09-15 19:38:40 -04004116 // builtin value, use an OpBitWiseAnd of the value's ID rather than
4117 // generating a load.
David Neto66cfe642018-03-24 06:13:56 -07004118 // TODO(dneto): Remove this awful hack once drivers are fixed.
David Netoa60b00b2017-09-15 16:34:09 -04004119 if (PointerID == WorkgroupSizeVarID) {
David Neto0a2f98d2017-09-15 19:38:40 -04004120 // Generate a bitwise-and of the original value with itself.
4121 // We should have been able to get away with just an OpCopyObject,
4122 // but we need something more complex to get past certain driver bugs.
4123 // This is ridiculous, but necessary.
4124 // TODO(dneto): Revisit this once drivers fix their bugs.
4125
4126 SPIRVOperandList Ops;
David Neto257c3892018-04-11 13:19:45 -04004127 Ops << MkId(ResTyID) << MkId(WorkgroupSizeValueID)
4128 << MkId(WorkgroupSizeValueID);
David Neto0a2f98d2017-09-15 19:38:40 -04004129
David Neto87846742018-04-11 17:36:22 -04004130 auto *Inst = new SPIRVInstruction(spv::OpBitwiseAnd, nextID++, Ops);
David Neto0a2f98d2017-09-15 19:38:40 -04004131 SPIRVInstList.push_back(Inst);
David Netoa60b00b2017-09-15 16:34:09 -04004132 break;
4133 }
4134
4135 // This is the normal path. Generate a load.
4136
David Neto22f144c2017-06-12 14:26:21 -04004137 // Ops[0] = Result Type ID
4138 // Ops[1] = Pointer ID
4139 // Ops[2] ... Ops[n] = Optional Memory Access
4140 //
4141 // TODO: Do we need to implement Optional Memory Access???
David Neto0a2f98d2017-09-15 19:38:40 -04004142
David Neto22f144c2017-06-12 14:26:21 -04004143 SPIRVOperandList Ops;
David Neto257c3892018-04-11 13:19:45 -04004144 Ops << MkId(ResTyID) << MkId(PointerID);
David Neto22f144c2017-06-12 14:26:21 -04004145
David Neto87846742018-04-11 17:36:22 -04004146 auto *Inst = new SPIRVInstruction(spv::OpLoad, nextID++, Ops);
David Neto22f144c2017-06-12 14:26:21 -04004147 SPIRVInstList.push_back(Inst);
4148 break;
4149 }
4150 case Instruction::Store: {
4151 StoreInst *ST = cast<StoreInst>(&I);
4152 //
4153 // Generate OpStore.
4154 //
4155
4156 // Ops[0] = Pointer ID
4157 // Ops[1] = Object ID
4158 // Ops[2] ... Ops[n] = Optional Memory Access (later???)
4159 //
4160 // TODO: Do we need to implement Optional Memory Access???
David Neto257c3892018-04-11 13:19:45 -04004161 SPIRVOperandList Ops;
4162 Ops << MkId(VMap[ST->getPointerOperand()])
4163 << MkId(VMap[ST->getValueOperand()]);
David Neto22f144c2017-06-12 14:26:21 -04004164
David Neto87846742018-04-11 17:36:22 -04004165 auto *Inst = new SPIRVInstruction(spv::OpStore, Ops);
David Neto22f144c2017-06-12 14:26:21 -04004166 SPIRVInstList.push_back(Inst);
4167 break;
4168 }
4169 case Instruction::AtomicCmpXchg: {
4170 I.print(errs());
4171 llvm_unreachable("Unsupported instruction???");
4172 break;
4173 }
4174 case Instruction::AtomicRMW: {
Neil Henning39672102017-09-29 14:33:13 +01004175 AtomicRMWInst *AtomicRMW = dyn_cast<AtomicRMWInst>(&I);
4176
4177 spv::Op opcode;
4178
4179 switch (AtomicRMW->getOperation()) {
4180 default:
4181 I.print(errs());
4182 llvm_unreachable("Unsupported instruction???");
4183 case llvm::AtomicRMWInst::Add:
4184 opcode = spv::OpAtomicIAdd;
4185 break;
4186 case llvm::AtomicRMWInst::Sub:
4187 opcode = spv::OpAtomicISub;
4188 break;
4189 case llvm::AtomicRMWInst::Xchg:
4190 opcode = spv::OpAtomicExchange;
4191 break;
4192 case llvm::AtomicRMWInst::Min:
4193 opcode = spv::OpAtomicSMin;
4194 break;
4195 case llvm::AtomicRMWInst::Max:
4196 opcode = spv::OpAtomicSMax;
4197 break;
4198 case llvm::AtomicRMWInst::UMin:
4199 opcode = spv::OpAtomicUMin;
4200 break;
4201 case llvm::AtomicRMWInst::UMax:
4202 opcode = spv::OpAtomicUMax;
4203 break;
4204 case llvm::AtomicRMWInst::And:
4205 opcode = spv::OpAtomicAnd;
4206 break;
4207 case llvm::AtomicRMWInst::Or:
4208 opcode = spv::OpAtomicOr;
4209 break;
4210 case llvm::AtomicRMWInst::Xor:
4211 opcode = spv::OpAtomicXor;
4212 break;
4213 }
4214
4215 //
4216 // Generate OpAtomic*.
4217 //
4218 SPIRVOperandList Ops;
4219
David Neto257c3892018-04-11 13:19:45 -04004220 Ops << MkId(lookupType(I.getType()))
4221 << MkId(VMap[AtomicRMW->getPointerOperand()]);
Neil Henning39672102017-09-29 14:33:13 +01004222
4223 auto IntTy = Type::getInt32Ty(I.getContext());
Neil Henning39672102017-09-29 14:33:13 +01004224 const auto ConstantScopeDevice = ConstantInt::get(IntTy, spv::ScopeDevice);
David Neto257c3892018-04-11 13:19:45 -04004225 Ops << MkId(VMap[ConstantScopeDevice]);
Neil Henning39672102017-09-29 14:33:13 +01004226
4227 const auto ConstantMemorySemantics = ConstantInt::get(
4228 IntTy, spv::MemorySemanticsUniformMemoryMask |
4229 spv::MemorySemanticsSequentiallyConsistentMask);
David Neto257c3892018-04-11 13:19:45 -04004230 Ops << MkId(VMap[ConstantMemorySemantics]);
Neil Henning39672102017-09-29 14:33:13 +01004231
David Neto257c3892018-04-11 13:19:45 -04004232 Ops << MkId(VMap[AtomicRMW->getValOperand()]);
Neil Henning39672102017-09-29 14:33:13 +01004233
4234 VMap[&I] = nextID;
4235
David Neto87846742018-04-11 17:36:22 -04004236 auto *Inst = new SPIRVInstruction(opcode, nextID++, Ops);
Neil Henning39672102017-09-29 14:33:13 +01004237 SPIRVInstList.push_back(Inst);
David Neto22f144c2017-06-12 14:26:21 -04004238 break;
4239 }
4240 case Instruction::Fence: {
4241 I.print(errs());
4242 llvm_unreachable("Unsupported instruction???");
4243 break;
4244 }
4245 case Instruction::Call: {
4246 CallInst *Call = dyn_cast<CallInst>(&I);
4247 Function *Callee = Call->getCalledFunction();
4248
4249 // Sampler initializers become a load of the corresponding sampler.
4250 if (Callee->getName().equals("__translate_sampler_initializer")) {
4251 // Check that the sampler map was definitely used though.
4252 if (0 == getSamplerMap().size()) {
4253 llvm_unreachable("Sampler literal in source without sampler map!");
4254 }
4255
4256 SPIRVOperandList Ops;
4257
David Neto257c3892018-04-11 13:19:45 -04004258 Ops << MkId(lookupType(SamplerTy->getPointerElementType()))
4259 << MkId(VMap[Call]);
David Neto22f144c2017-06-12 14:26:21 -04004260
4261 VMap[Call] = nextID;
David Neto87846742018-04-11 17:36:22 -04004262 auto *Inst = new SPIRVInstruction(spv::OpLoad, nextID++, Ops);
David Neto22f144c2017-06-12 14:26:21 -04004263 SPIRVInstList.push_back(Inst);
4264
4265 break;
4266 }
4267
4268 if (Callee->getName().startswith("spirv.atomic")) {
4269 spv::Op opcode = StringSwitch<spv::Op>(Callee->getName())
4270 .Case("spirv.atomic_add", spv::OpAtomicIAdd)
4271 .Case("spirv.atomic_sub", spv::OpAtomicISub)
4272 .Case("spirv.atomic_exchange", spv::OpAtomicExchange)
4273 .Case("spirv.atomic_inc", spv::OpAtomicIIncrement)
4274 .Case("spirv.atomic_dec", spv::OpAtomicIDecrement)
4275 .Case("spirv.atomic_compare_exchange",
4276 spv::OpAtomicCompareExchange)
4277 .Case("spirv.atomic_umin", spv::OpAtomicUMin)
4278 .Case("spirv.atomic_smin", spv::OpAtomicSMin)
4279 .Case("spirv.atomic_umax", spv::OpAtomicUMax)
4280 .Case("spirv.atomic_smax", spv::OpAtomicSMax)
4281 .Case("spirv.atomic_and", spv::OpAtomicAnd)
4282 .Case("spirv.atomic_or", spv::OpAtomicOr)
4283 .Case("spirv.atomic_xor", spv::OpAtomicXor)
4284 .Default(spv::OpNop);
4285
4286 //
4287 // Generate OpAtomic*.
4288 //
4289 SPIRVOperandList Ops;
4290
David Neto257c3892018-04-11 13:19:45 -04004291 Ops << MkId(lookupType(I.getType()));
David Neto22f144c2017-06-12 14:26:21 -04004292
4293 for (unsigned i = 0; i < Call->getNumArgOperands(); i++) {
David Neto257c3892018-04-11 13:19:45 -04004294 Ops << MkId(VMap[Call->getArgOperand(i)]);
David Neto22f144c2017-06-12 14:26:21 -04004295 }
4296
4297 VMap[&I] = nextID;
4298
David Neto87846742018-04-11 17:36:22 -04004299 auto *Inst = new SPIRVInstruction(opcode, nextID++, Ops);
David Neto22f144c2017-06-12 14:26:21 -04004300 SPIRVInstList.push_back(Inst);
4301 break;
4302 }
4303
4304 if (Callee->getName().startswith("_Z3dot")) {
4305 // If the argument is a vector type, generate OpDot
4306 if (Call->getArgOperand(0)->getType()->isVectorTy()) {
4307 //
4308 // Generate OpDot.
4309 //
4310 SPIRVOperandList Ops;
4311
David Neto257c3892018-04-11 13:19:45 -04004312 Ops << MkId(lookupType(I.getType()));
David Neto22f144c2017-06-12 14:26:21 -04004313
4314 for (unsigned i = 0; i < Call->getNumArgOperands(); i++) {
David Neto257c3892018-04-11 13:19:45 -04004315 Ops << MkId(VMap[Call->getArgOperand(i)]);
David Neto22f144c2017-06-12 14:26:21 -04004316 }
4317
4318 VMap[&I] = nextID;
4319
David Neto87846742018-04-11 17:36:22 -04004320 auto *Inst = new SPIRVInstruction(spv::OpDot, nextID++, Ops);
David Neto22f144c2017-06-12 14:26:21 -04004321 SPIRVInstList.push_back(Inst);
4322 } else {
4323 //
4324 // Generate OpFMul.
4325 //
4326 SPIRVOperandList Ops;
4327
David Neto257c3892018-04-11 13:19:45 -04004328 Ops << MkId(lookupType(I.getType()));
David Neto22f144c2017-06-12 14:26:21 -04004329
4330 for (unsigned i = 0; i < Call->getNumArgOperands(); i++) {
David Neto257c3892018-04-11 13:19:45 -04004331 Ops << MkId(VMap[Call->getArgOperand(i)]);
David Neto22f144c2017-06-12 14:26:21 -04004332 }
4333
4334 VMap[&I] = nextID;
4335
David Neto87846742018-04-11 17:36:22 -04004336 auto *Inst = new SPIRVInstruction(spv::OpFMul, nextID++, Ops);
David Neto22f144c2017-06-12 14:26:21 -04004337 SPIRVInstList.push_back(Inst);
4338 }
4339 break;
4340 }
4341
David Neto8505ebf2017-10-13 18:50:50 -04004342 if (Callee->getName().startswith("_Z4fmod")) {
4343 // OpenCL fmod(x,y) is x - y * trunc(x/y)
4344 // The sign for a non-zero result is taken from x.
4345 // (Try an example.)
4346 // So translate to OpFRem
4347
4348 SPIRVOperandList Ops;
4349
David Neto257c3892018-04-11 13:19:45 -04004350 Ops << MkId(lookupType(I.getType()));
David Neto8505ebf2017-10-13 18:50:50 -04004351
4352 for (unsigned i = 0; i < Call->getNumArgOperands(); i++) {
David Neto257c3892018-04-11 13:19:45 -04004353 Ops << MkId(VMap[Call->getArgOperand(i)]);
David Neto8505ebf2017-10-13 18:50:50 -04004354 }
4355
4356 VMap[&I] = nextID;
4357
David Neto87846742018-04-11 17:36:22 -04004358 auto *Inst = new SPIRVInstruction(spv::OpFRem, nextID++, Ops);
David Neto8505ebf2017-10-13 18:50:50 -04004359 SPIRVInstList.push_back(Inst);
4360 break;
4361 }
4362
David Neto22f144c2017-06-12 14:26:21 -04004363 // spirv.store_null.* intrinsics become OpStore's.
4364 if (Callee->getName().startswith("spirv.store_null")) {
4365 //
4366 // Generate OpStore.
4367 //
4368
4369 // Ops[0] = Pointer ID
4370 // Ops[1] = Object ID
4371 // Ops[2] ... Ops[n]
4372 SPIRVOperandList Ops;
4373
4374 uint32_t PointerID = VMap[Call->getArgOperand(0)];
David Neto22f144c2017-06-12 14:26:21 -04004375 uint32_t ObjectID = VMap[Call->getArgOperand(1)];
David Neto257c3892018-04-11 13:19:45 -04004376 Ops << MkId(PointerID) << MkId(ObjectID);
David Neto22f144c2017-06-12 14:26:21 -04004377
David Neto87846742018-04-11 17:36:22 -04004378 SPIRVInstList.push_back(new SPIRVInstruction(spv::OpStore, Ops));
David Neto22f144c2017-06-12 14:26:21 -04004379
4380 break;
4381 }
4382
4383 // spirv.copy_memory.* intrinsics become OpMemoryMemory's.
4384 if (Callee->getName().startswith("spirv.copy_memory")) {
4385 //
4386 // Generate OpCopyMemory.
4387 //
4388
4389 // Ops[0] = Dst ID
4390 // Ops[1] = Src ID
4391 // Ops[2] = Memory Access
4392 // Ops[3] = Alignment
4393
4394 auto IsVolatile =
4395 dyn_cast<ConstantInt>(Call->getArgOperand(3))->getZExtValue() != 0;
4396
4397 auto VolatileMemoryAccess = (IsVolatile) ? spv::MemoryAccessVolatileMask
4398 : spv::MemoryAccessMaskNone;
4399
4400 auto MemoryAccess = VolatileMemoryAccess | spv::MemoryAccessAlignedMask;
4401
4402 auto Alignment =
4403 dyn_cast<ConstantInt>(Call->getArgOperand(2))->getZExtValue();
4404
David Neto257c3892018-04-11 13:19:45 -04004405 SPIRVOperandList Ops;
4406 Ops << MkId(VMap[Call->getArgOperand(0)])
4407 << MkId(VMap[Call->getArgOperand(1)]) << MkNum(MemoryAccess)
4408 << MkNum(static_cast<uint32_t>(Alignment));
David Neto22f144c2017-06-12 14:26:21 -04004409
David Neto87846742018-04-11 17:36:22 -04004410 auto *Inst = new SPIRVInstruction(spv::OpCopyMemory, Ops);
David Neto22f144c2017-06-12 14:26:21 -04004411
4412 SPIRVInstList.push_back(Inst);
4413
4414 break;
4415 }
4416
4417 // Nothing to do for abs with uint. Map abs's operand ID to VMap for abs
4418 // with unit.
4419 if (Callee->getName().equals("_Z3absj") ||
4420 Callee->getName().equals("_Z3absDv2_j") ||
4421 Callee->getName().equals("_Z3absDv3_j") ||
4422 Callee->getName().equals("_Z3absDv4_j")) {
4423 VMap[&I] = VMap[Call->getOperand(0)];
4424 break;
4425 }
4426
4427 // barrier is converted to OpControlBarrier
4428 if (Callee->getName().equals("__spirv_control_barrier")) {
4429 //
4430 // Generate OpControlBarrier.
4431 //
4432 // Ops[0] = Execution Scope ID
4433 // Ops[1] = Memory Scope ID
4434 // Ops[2] = Memory Semantics ID
4435 //
4436 Value *ExecutionScope = Call->getArgOperand(0);
4437 Value *MemoryScope = Call->getArgOperand(1);
4438 Value *MemorySemantics = Call->getArgOperand(2);
4439
David Neto257c3892018-04-11 13:19:45 -04004440 SPIRVOperandList Ops;
4441 Ops << MkId(VMap[ExecutionScope]) << MkId(VMap[MemoryScope])
4442 << MkId(VMap[MemorySemantics]);
David Neto22f144c2017-06-12 14:26:21 -04004443
David Neto87846742018-04-11 17:36:22 -04004444 SPIRVInstList.push_back(new SPIRVInstruction(spv::OpControlBarrier, Ops));
David Neto22f144c2017-06-12 14:26:21 -04004445 break;
4446 }
4447
4448 // memory barrier is converted to OpMemoryBarrier
4449 if (Callee->getName().equals("__spirv_memory_barrier")) {
4450 //
4451 // Generate OpMemoryBarrier.
4452 //
4453 // Ops[0] = Memory Scope ID
4454 // Ops[1] = Memory Semantics ID
4455 //
4456 SPIRVOperandList Ops;
4457
David Neto257c3892018-04-11 13:19:45 -04004458 uint32_t MemoryScopeID = VMap[Call->getArgOperand(0)];
4459 uint32_t MemorySemanticsID = VMap[Call->getArgOperand(1)];
David Neto22f144c2017-06-12 14:26:21 -04004460
David Neto257c3892018-04-11 13:19:45 -04004461 Ops << MkId(MemoryScopeID) << MkId(MemorySemanticsID);
David Neto22f144c2017-06-12 14:26:21 -04004462
David Neto87846742018-04-11 17:36:22 -04004463 auto *Inst = new SPIRVInstruction(spv::OpMemoryBarrier, Ops);
David Neto22f144c2017-06-12 14:26:21 -04004464 SPIRVInstList.push_back(Inst);
4465 break;
4466 }
4467
4468 // isinf is converted to OpIsInf
4469 if (Callee->getName().equals("__spirv_isinff") ||
4470 Callee->getName().equals("__spirv_isinfDv2_f") ||
4471 Callee->getName().equals("__spirv_isinfDv3_f") ||
4472 Callee->getName().equals("__spirv_isinfDv4_f")) {
4473 //
4474 // Generate OpIsInf.
4475 //
4476 // Ops[0] = Result Type ID
4477 // Ops[1] = X ID
4478 //
4479 SPIRVOperandList Ops;
4480
David Neto257c3892018-04-11 13:19:45 -04004481 Ops << MkId(lookupType(I.getType()))
4482 << MkId(VMap[Call->getArgOperand(0)]);
David Neto22f144c2017-06-12 14:26:21 -04004483
4484 VMap[&I] = nextID;
4485
David Neto87846742018-04-11 17:36:22 -04004486 auto *Inst = new SPIRVInstruction(spv::OpIsInf, nextID++, Ops);
David Neto22f144c2017-06-12 14:26:21 -04004487 SPIRVInstList.push_back(Inst);
4488 break;
4489 }
4490
4491 // isnan is converted to OpIsNan
4492 if (Callee->getName().equals("__spirv_isnanf") ||
4493 Callee->getName().equals("__spirv_isnanDv2_f") ||
4494 Callee->getName().equals("__spirv_isnanDv3_f") ||
4495 Callee->getName().equals("__spirv_isnanDv4_f")) {
4496 //
4497 // Generate OpIsInf.
4498 //
4499 // Ops[0] = Result Type ID
4500 // Ops[1] = X ID
4501 //
4502 SPIRVOperandList Ops;
4503
David Neto257c3892018-04-11 13:19:45 -04004504 Ops << MkId(lookupType(I.getType()))
4505 << MkId(VMap[Call->getArgOperand(0)]);
David Neto22f144c2017-06-12 14:26:21 -04004506
4507 VMap[&I] = nextID;
4508
David Neto87846742018-04-11 17:36:22 -04004509 auto *Inst = new SPIRVInstruction(spv::OpIsNan, nextID++, Ops);
David Neto22f144c2017-06-12 14:26:21 -04004510 SPIRVInstList.push_back(Inst);
4511 break;
4512 }
4513
4514 // all is converted to OpAll
4515 if (Callee->getName().equals("__spirv_allDv2_i") ||
4516 Callee->getName().equals("__spirv_allDv3_i") ||
4517 Callee->getName().equals("__spirv_allDv4_i")) {
4518 //
4519 // Generate OpAll.
4520 //
4521 // Ops[0] = Result Type ID
4522 // Ops[1] = Vector ID
4523 //
4524 SPIRVOperandList Ops;
4525
David Neto257c3892018-04-11 13:19:45 -04004526 Ops << MkId(lookupType(I.getType()))
4527 << MkId(VMap[Call->getArgOperand(0)]);
David Neto22f144c2017-06-12 14:26:21 -04004528
4529 VMap[&I] = nextID;
4530
David Neto87846742018-04-11 17:36:22 -04004531 auto *Inst = new SPIRVInstruction(spv::OpAll, nextID++, Ops);
David Neto22f144c2017-06-12 14:26:21 -04004532 SPIRVInstList.push_back(Inst);
4533 break;
4534 }
4535
4536 // any is converted to OpAny
4537 if (Callee->getName().equals("__spirv_anyDv2_i") ||
4538 Callee->getName().equals("__spirv_anyDv3_i") ||
4539 Callee->getName().equals("__spirv_anyDv4_i")) {
4540 //
4541 // Generate OpAny.
4542 //
4543 // Ops[0] = Result Type ID
4544 // Ops[1] = Vector ID
4545 //
4546 SPIRVOperandList Ops;
4547
David Neto257c3892018-04-11 13:19:45 -04004548 Ops << MkId(lookupType(I.getType()))
4549 << MkId(VMap[Call->getArgOperand(0)]);
David Neto22f144c2017-06-12 14:26:21 -04004550
4551 VMap[&I] = nextID;
4552
David Neto87846742018-04-11 17:36:22 -04004553 auto *Inst = new SPIRVInstruction(spv::OpAny, nextID++, Ops);
David Neto22f144c2017-06-12 14:26:21 -04004554 SPIRVInstList.push_back(Inst);
4555 break;
4556 }
4557
4558 // read_image is converted to OpSampledImage and OpImageSampleExplicitLod.
4559 // Additionally, OpTypeSampledImage is generated.
4560 if (Callee->getName().equals(
4561 "_Z11read_imagef14ocl_image2d_ro11ocl_samplerDv2_f") ||
4562 Callee->getName().equals(
4563 "_Z11read_imagef14ocl_image3d_ro11ocl_samplerDv4_f")) {
4564 //
4565 // Generate OpSampledImage.
4566 //
4567 // Ops[0] = Result Type ID
4568 // Ops[1] = Image ID
4569 // Ops[2] = Sampler ID
4570 //
4571 SPIRVOperandList Ops;
4572
4573 Value *Image = Call->getArgOperand(0);
4574 Value *Sampler = Call->getArgOperand(1);
4575 Value *Coordinate = Call->getArgOperand(2);
4576
4577 TypeMapType &OpImageTypeMap = getImageTypeMap();
4578 Type *ImageTy = Image->getType()->getPointerElementType();
4579 uint32_t ImageTyID = OpImageTypeMap[ImageTy];
David Neto22f144c2017-06-12 14:26:21 -04004580 uint32_t ImageID = VMap[Image];
David Neto22f144c2017-06-12 14:26:21 -04004581 uint32_t SamplerID = VMap[Sampler];
David Neto257c3892018-04-11 13:19:45 -04004582
4583 Ops << MkId(ImageTyID) << MkId(ImageID) << MkId(SamplerID);
David Neto22f144c2017-06-12 14:26:21 -04004584
4585 uint32_t SampledImageID = nextID;
4586
David Neto87846742018-04-11 17:36:22 -04004587 auto *Inst = new SPIRVInstruction(spv::OpSampledImage, nextID++, Ops);
David Neto22f144c2017-06-12 14:26:21 -04004588 SPIRVInstList.push_back(Inst);
4589
4590 //
4591 // Generate OpImageSampleExplicitLod.
4592 //
4593 // Ops[0] = Result Type ID
4594 // Ops[1] = Sampled Image ID
4595 // Ops[2] = Coordinate ID
4596 // Ops[3] = Image Operands Type ID
4597 // Ops[4] ... Ops[n] = Operands ID
4598 //
4599 Ops.clear();
4600
David Neto257c3892018-04-11 13:19:45 -04004601 Ops << MkId(lookupType(Call->getType())) << MkId(SampledImageID)
4602 << MkId(VMap[Coordinate]) << MkNum(spv::ImageOperandsLodMask);
David Neto22f144c2017-06-12 14:26:21 -04004603
4604 Constant *CstFP0 = ConstantFP::get(Context, APFloat(0.0f));
David Neto257c3892018-04-11 13:19:45 -04004605 Ops << MkId(VMap[CstFP0]);
David Neto22f144c2017-06-12 14:26:21 -04004606
4607 VMap[&I] = nextID;
4608
David Neto87846742018-04-11 17:36:22 -04004609 Inst = new SPIRVInstruction(spv::OpImageSampleExplicitLod, nextID++, Ops);
David Neto22f144c2017-06-12 14:26:21 -04004610 SPIRVInstList.push_back(Inst);
4611 break;
4612 }
4613
4614 // write_imagef is mapped to OpImageWrite.
4615 if (Callee->getName().equals(
4616 "_Z12write_imagef14ocl_image2d_woDv2_iDv4_f") ||
4617 Callee->getName().equals(
4618 "_Z12write_imagef14ocl_image3d_woDv4_iDv4_f")) {
4619 //
4620 // Generate OpImageWrite.
4621 //
4622 // Ops[0] = Image ID
4623 // Ops[1] = Coordinate ID
4624 // Ops[2] = Texel ID
4625 // Ops[3] = (Optional) Image Operands Type (Literal Number)
4626 // Ops[4] ... Ops[n] = (Optional) Operands ID
4627 //
4628 SPIRVOperandList Ops;
4629
4630 Value *Image = Call->getArgOperand(0);
4631 Value *Coordinate = Call->getArgOperand(1);
4632 Value *Texel = Call->getArgOperand(2);
4633
4634 uint32_t ImageID = VMap[Image];
David Neto22f144c2017-06-12 14:26:21 -04004635 uint32_t CoordinateID = VMap[Coordinate];
David Neto22f144c2017-06-12 14:26:21 -04004636 uint32_t TexelID = VMap[Texel];
David Neto257c3892018-04-11 13:19:45 -04004637 Ops << MkId(ImageID) << MkId(CoordinateID) << MkId(TexelID);
David Neto22f144c2017-06-12 14:26:21 -04004638
David Neto87846742018-04-11 17:36:22 -04004639 auto *Inst = new SPIRVInstruction(spv::OpImageWrite, Ops);
David Neto22f144c2017-06-12 14:26:21 -04004640 SPIRVInstList.push_back(Inst);
4641 break;
4642 }
4643
David Neto5c22a252018-03-15 16:07:41 -04004644 // get_image_width is mapped to OpImageQuerySize
4645 if (Callee->getName().equals("_Z15get_image_width14ocl_image2d_ro") ||
4646 Callee->getName().equals("_Z15get_image_width14ocl_image2d_wo") ||
4647 Callee->getName().equals("_Z16get_image_height14ocl_image2d_ro") ||
4648 Callee->getName().equals("_Z16get_image_height14ocl_image2d_wo")) {
4649 //
4650 // Generate OpImageQuerySize, then pull out the right component.
4651 // Assume 2D image for now.
4652 //
4653 // Ops[0] = Image ID
4654 //
4655 // %sizes = OpImageQuerySizes %uint2 %im
4656 // %result = OpCompositeExtract %uint %sizes 0-or-1
4657 SPIRVOperandList Ops;
4658
4659 // Implement:
4660 // %sizes = OpImageQuerySizes %uint2 %im
4661 uint32_t SizesTypeID =
4662 TypeMap[VectorType::get(Type::getInt32Ty(Context), 2)];
David Neto5c22a252018-03-15 16:07:41 -04004663 Value *Image = Call->getArgOperand(0);
4664 uint32_t ImageID = VMap[Image];
David Neto257c3892018-04-11 13:19:45 -04004665 Ops << MkId(SizesTypeID) << MkId(ImageID);
David Neto5c22a252018-03-15 16:07:41 -04004666
4667 uint32_t SizesID = nextID++;
David Neto87846742018-04-11 17:36:22 -04004668 auto *QueryInst =
4669 new SPIRVInstruction(spv::OpImageQuerySize, SizesID, Ops);
David Neto5c22a252018-03-15 16:07:41 -04004670 SPIRVInstList.push_back(QueryInst);
4671
4672 // Reset value map entry since we generated an intermediate instruction.
4673 VMap[&I] = nextID;
4674
4675 // Implement:
4676 // %result = OpCompositeExtract %uint %sizes 0-or-1
4677 Ops.clear();
David Neto257c3892018-04-11 13:19:45 -04004678 Ops << MkId(TypeMap[I.getType()]) << MkId(SizesID);
David Neto5c22a252018-03-15 16:07:41 -04004679
4680 uint32_t component = Callee->getName().contains("height") ? 1 : 0;
David Neto257c3892018-04-11 13:19:45 -04004681 Ops << MkNum(component);
David Neto5c22a252018-03-15 16:07:41 -04004682
David Neto87846742018-04-11 17:36:22 -04004683 auto *Inst = new SPIRVInstruction(spv::OpCompositeExtract, nextID++, Ops);
David Neto5c22a252018-03-15 16:07:41 -04004684 SPIRVInstList.push_back(Inst);
4685 break;
4686 }
4687
David Neto22f144c2017-06-12 14:26:21 -04004688 // Call instrucion is deferred because it needs function's ID. Record
4689 // slot's location on SPIRVInstructionList.
4690 DeferredInsts.push_back(
4691 std::make_tuple(&I, --SPIRVInstList.end(), nextID++));
4692
David Neto3fbb4072017-10-16 11:28:14 -04004693 // Check whether the implementation of this call uses an extended
4694 // instruction plus one more value-producing instruction. If so, then
4695 // reserve the id for the extra value-producing slot.
4696 glsl::ExtInst EInst = getIndirectExtInstEnum(Callee->getName());
4697 if (EInst != kGlslExtInstBad) {
4698 // Reserve a spot for the extra value.
David Neto4d02a532017-09-17 12:57:44 -04004699 // Increase nextID.
David Neto22f144c2017-06-12 14:26:21 -04004700 VMap[&I] = nextID;
4701 nextID++;
4702 }
4703 break;
4704 }
4705 case Instruction::Ret: {
4706 unsigned NumOps = I.getNumOperands();
4707 if (NumOps == 0) {
4708 //
4709 // Generate OpReturn.
4710 //
David Neto87846742018-04-11 17:36:22 -04004711 SPIRVInstList.push_back(new SPIRVInstruction(spv::OpReturn, {}));
David Neto22f144c2017-06-12 14:26:21 -04004712 } else {
4713 //
4714 // Generate OpReturnValue.
4715 //
4716
4717 // Ops[0] = Return Value ID
4718 SPIRVOperandList Ops;
David Neto257c3892018-04-11 13:19:45 -04004719
4720 Ops << MkId(VMap[I.getOperand(0)]);
David Neto22f144c2017-06-12 14:26:21 -04004721
David Neto87846742018-04-11 17:36:22 -04004722 auto *Inst = new SPIRVInstruction(spv::OpReturnValue, Ops);
David Neto22f144c2017-06-12 14:26:21 -04004723 SPIRVInstList.push_back(Inst);
4724 break;
4725 }
4726 break;
4727 }
4728 }
4729}
4730
4731void SPIRVProducerPass::GenerateFuncEpilogue() {
4732 SPIRVInstructionList &SPIRVInstList = getSPIRVInstList();
4733
4734 //
4735 // Generate OpFunctionEnd
4736 //
4737
David Neto87846742018-04-11 17:36:22 -04004738 auto *Inst = new SPIRVInstruction(spv::OpFunctionEnd, {});
David Neto22f144c2017-06-12 14:26:21 -04004739 SPIRVInstList.push_back(Inst);
4740}
4741
4742bool SPIRVProducerPass::is4xi8vec(Type *Ty) const {
4743 LLVMContext &Context = Ty->getContext();
4744 if (Ty->isVectorTy()) {
4745 if (Ty->getVectorElementType() == Type::getInt8Ty(Context) &&
4746 Ty->getVectorNumElements() == 4) {
4747 return true;
4748 }
4749 }
4750
4751 return false;
4752}
4753
David Neto257c3892018-04-11 13:19:45 -04004754uint32_t SPIRVProducerPass::GetI32Zero() {
4755 if (0 == constant_i32_zero_id_) {
4756 llvm_unreachable("Requesting a 32-bit integer constant but it is not "
4757 "defined in the SPIR-V module");
4758 }
4759 return constant_i32_zero_id_;
4760}
4761
David Neto22f144c2017-06-12 14:26:21 -04004762void SPIRVProducerPass::HandleDeferredInstruction() {
4763 SPIRVInstructionList &SPIRVInstList = getSPIRVInstList();
4764 ValueMapType &VMap = getValueMap();
4765 DeferredInstVecType &DeferredInsts = getDeferredInstVec();
4766
4767 for (auto DeferredInst = DeferredInsts.rbegin();
4768 DeferredInst != DeferredInsts.rend(); ++DeferredInst) {
4769 Value *Inst = std::get<0>(*DeferredInst);
4770 SPIRVInstructionList::iterator InsertPoint = ++std::get<1>(*DeferredInst);
4771 if (InsertPoint != SPIRVInstList.end()) {
4772 while ((*InsertPoint)->getOpcode() == spv::OpPhi) {
4773 ++InsertPoint;
4774 }
4775 }
4776
4777 if (BranchInst *Br = dyn_cast<BranchInst>(Inst)) {
4778 // Check whether basic block, which has this branch instruction, is loop
4779 // header or not. If it is loop header, generate OpLoopMerge and
4780 // OpBranchConditional.
4781 Function *Func = Br->getParent()->getParent();
4782 DominatorTree &DT =
4783 getAnalysis<DominatorTreeWrapperPass>(*Func).getDomTree();
4784 const LoopInfo &LI =
4785 getAnalysis<LoopInfoWrapperPass>(*Func).getLoopInfo();
4786
4787 BasicBlock *BrBB = Br->getParent();
4788 if (LI.isLoopHeader(BrBB)) {
4789 Value *ContinueBB = nullptr;
4790 Value *MergeBB = nullptr;
4791
4792 Loop *L = LI.getLoopFor(BrBB);
4793 MergeBB = L->getExitBlock();
4794 if (!MergeBB) {
4795 // StructurizeCFG pass converts CFG into triangle shape and the cfg
4796 // has regions with single entry/exit. As a result, loop should not
4797 // have multiple exits.
4798 llvm_unreachable("Loop has multiple exits???");
4799 }
4800
4801 if (L->isLoopLatch(BrBB)) {
4802 ContinueBB = BrBB;
4803 } else {
4804 // From SPIR-V spec 2.11, Continue Target must dominate that back-edge
4805 // block.
4806 BasicBlock *Header = L->getHeader();
4807 BasicBlock *Latch = L->getLoopLatch();
4808 for (BasicBlock *BB : L->blocks()) {
4809 if (BB == Header) {
4810 continue;
4811 }
4812
4813 // Check whether block dominates block with back-edge.
4814 if (DT.dominates(BB, Latch)) {
4815 ContinueBB = BB;
4816 }
4817 }
4818
4819 if (!ContinueBB) {
4820 llvm_unreachable("Wrong continue block from loop");
4821 }
4822 }
4823
4824 //
4825 // Generate OpLoopMerge.
4826 //
4827 // Ops[0] = Merge Block ID
4828 // Ops[1] = Continue Target ID
4829 // Ops[2] = Selection Control
4830 SPIRVOperandList Ops;
4831
4832 // StructurizeCFG pass already manipulated CFG. Just use false block of
4833 // branch instruction as merge block.
4834 uint32_t MergeBBID = VMap[MergeBB];
David Neto22f144c2017-06-12 14:26:21 -04004835 uint32_t ContinueBBID = VMap[ContinueBB];
David Neto257c3892018-04-11 13:19:45 -04004836 Ops << MkId(MergeBBID) << MkId(ContinueBBID)
4837 << MkNum(spv::SelectionControlMaskNone);
David Neto22f144c2017-06-12 14:26:21 -04004838
David Neto87846742018-04-11 17:36:22 -04004839 auto *MergeInst = new SPIRVInstruction(spv::OpLoopMerge, Ops);
David Neto22f144c2017-06-12 14:26:21 -04004840 SPIRVInstList.insert(InsertPoint, MergeInst);
4841
4842 } else if (Br->isConditional()) {
4843 bool HasBackEdge = false;
4844
4845 for (unsigned i = 0; i < Br->getNumSuccessors(); i++) {
4846 if (LI.isLoopHeader(Br->getSuccessor(i))) {
4847 HasBackEdge = true;
4848 }
4849 }
4850 if (!HasBackEdge) {
4851 //
4852 // Generate OpSelectionMerge.
4853 //
4854 // Ops[0] = Merge Block ID
4855 // Ops[1] = Selection Control
4856 SPIRVOperandList Ops;
4857
4858 // StructurizeCFG pass already manipulated CFG. Just use false block
4859 // of branch instruction as merge block.
4860 uint32_t MergeBBID = VMap[Br->getSuccessor(1)];
David Neto257c3892018-04-11 13:19:45 -04004861 Ops << MkId(MergeBBID) << MkNum(spv::SelectionControlMaskNone);
David Neto22f144c2017-06-12 14:26:21 -04004862
David Neto87846742018-04-11 17:36:22 -04004863 auto *MergeInst = new SPIRVInstruction(spv::OpSelectionMerge, Ops);
David Neto22f144c2017-06-12 14:26:21 -04004864 SPIRVInstList.insert(InsertPoint, MergeInst);
4865 }
4866 }
4867
4868 if (Br->isConditional()) {
4869 //
4870 // Generate OpBranchConditional.
4871 //
4872 // Ops[0] = Condition ID
4873 // Ops[1] = True Label ID
4874 // Ops[2] = False Label ID
4875 // Ops[3] ... Ops[n] = Branch weights (Literal Number)
4876 SPIRVOperandList Ops;
4877
4878 uint32_t CondID = VMap[Br->getCondition()];
David Neto22f144c2017-06-12 14:26:21 -04004879 uint32_t TrueBBID = VMap[Br->getSuccessor(0)];
David Neto22f144c2017-06-12 14:26:21 -04004880 uint32_t FalseBBID = VMap[Br->getSuccessor(1)];
David Neto257c3892018-04-11 13:19:45 -04004881
4882 Ops << MkId(CondID) << MkId(TrueBBID) << MkId(FalseBBID);
David Neto22f144c2017-06-12 14:26:21 -04004883
David Neto87846742018-04-11 17:36:22 -04004884 auto *BrInst = new SPIRVInstruction(spv::OpBranchConditional, Ops);
David Neto22f144c2017-06-12 14:26:21 -04004885 SPIRVInstList.insert(InsertPoint, BrInst);
4886 } else {
4887 //
4888 // Generate OpBranch.
4889 //
4890 // Ops[0] = Target Label ID
4891 SPIRVOperandList Ops;
4892
4893 uint32_t TargetID = VMap[Br->getSuccessor(0)];
David Neto257c3892018-04-11 13:19:45 -04004894 Ops << MkId(TargetID);
David Neto22f144c2017-06-12 14:26:21 -04004895
David Neto87846742018-04-11 17:36:22 -04004896 SPIRVInstList.insert(InsertPoint,
4897 new SPIRVInstruction(spv::OpBranch, Ops));
David Neto22f144c2017-06-12 14:26:21 -04004898 }
4899 } else if (PHINode *PHI = dyn_cast<PHINode>(Inst)) {
4900 //
4901 // Generate OpPhi.
4902 //
4903 // Ops[0] = Result Type ID
4904 // Ops[1] ... Ops[n] = (Variable ID, Parent ID) pairs
4905 SPIRVOperandList Ops;
4906
David Neto257c3892018-04-11 13:19:45 -04004907 Ops << MkId(lookupType(PHI->getType()));
David Neto22f144c2017-06-12 14:26:21 -04004908
David Neto22f144c2017-06-12 14:26:21 -04004909 for (unsigned i = 0; i < PHI->getNumIncomingValues(); i++) {
4910 uint32_t VarID = VMap[PHI->getIncomingValue(i)];
David Neto22f144c2017-06-12 14:26:21 -04004911 uint32_t ParentID = VMap[PHI->getIncomingBlock(i)];
David Neto257c3892018-04-11 13:19:45 -04004912 Ops << MkId(VarID) << MkId(ParentID);
David Neto22f144c2017-06-12 14:26:21 -04004913 }
4914
4915 SPIRVInstList.insert(
David Neto87846742018-04-11 17:36:22 -04004916 InsertPoint,
4917 new SPIRVInstruction(spv::OpPhi, std::get<2>(*DeferredInst), Ops));
David Neto22f144c2017-06-12 14:26:21 -04004918 } else if (CallInst *Call = dyn_cast<CallInst>(Inst)) {
4919 Function *Callee = Call->getCalledFunction();
David Neto3fbb4072017-10-16 11:28:14 -04004920 auto callee_name = Callee->getName();
4921 glsl::ExtInst EInst = getDirectOrIndirectExtInstEnum(callee_name);
David Neto22f144c2017-06-12 14:26:21 -04004922
4923 if (EInst) {
4924 uint32_t &ExtInstImportID = getOpExtInstImportID();
4925
4926 //
4927 // Generate OpExtInst.
4928 //
4929
4930 // Ops[0] = Result Type ID
4931 // Ops[1] = Set ID (OpExtInstImport ID)
4932 // Ops[2] = Instruction Number (Literal Number)
4933 // Ops[3] ... Ops[n] = Operand 1, ... , Operand n
4934 SPIRVOperandList Ops;
4935
David Neto257c3892018-04-11 13:19:45 -04004936 Ops << MkId(lookupType(Call->getType())) << MkId(ExtInstImportID) << MkNum(EInst);
David Neto22f144c2017-06-12 14:26:21 -04004937
David Neto22f144c2017-06-12 14:26:21 -04004938 FunctionType *CalleeFTy = cast<FunctionType>(Call->getFunctionType());
4939 for (unsigned i = 0; i < CalleeFTy->getNumParams(); i++) {
David Neto257c3892018-04-11 13:19:45 -04004940 Ops << MkId(VMap[Call->getOperand(i)]);
David Neto22f144c2017-06-12 14:26:21 -04004941 }
4942
David Neto87846742018-04-11 17:36:22 -04004943 auto *ExtInst = new SPIRVInstruction(spv::OpExtInst,
4944 std::get<2>(*DeferredInst), Ops);
David Neto22f144c2017-06-12 14:26:21 -04004945 SPIRVInstList.insert(InsertPoint, ExtInst);
4946
David Neto3fbb4072017-10-16 11:28:14 -04004947 const auto IndirectExtInst = getIndirectExtInstEnum(callee_name);
4948 if (IndirectExtInst != kGlslExtInstBad) {
4949 // Generate one more instruction that uses the result of the extended
4950 // instruction. Its result id is one more than the id of the
4951 // extended instruction.
David Neto22f144c2017-06-12 14:26:21 -04004952 LLVMContext &Context =
4953 Call->getParent()->getParent()->getParent()->getContext();
David Neto22f144c2017-06-12 14:26:21 -04004954
David Neto3fbb4072017-10-16 11:28:14 -04004955 auto generate_extra_inst = [this, &Context, &Call, &DeferredInst,
4956 &VMap, &SPIRVInstList, &InsertPoint](
4957 spv::Op opcode, Constant *constant) {
4958 //
4959 // Generate instruction like:
4960 // result = opcode constant <extinst-result>
4961 //
4962 // Ops[0] = Result Type ID
4963 // Ops[1] = Operand 0 ;; the constant, suitably splatted
4964 // Ops[2] = Operand 1 ;; the result of the extended instruction
4965 SPIRVOperandList Ops;
David Neto22f144c2017-06-12 14:26:21 -04004966
David Neto3fbb4072017-10-16 11:28:14 -04004967 Type *resultTy = Call->getType();
David Neto257c3892018-04-11 13:19:45 -04004968 Ops << MkId(lookupType(resultTy));
David Neto3fbb4072017-10-16 11:28:14 -04004969
4970 if (auto *vectorTy = dyn_cast<VectorType>(resultTy)) {
4971 constant = ConstantVector::getSplat(
4972 static_cast<unsigned>(vectorTy->getNumElements()), constant);
4973 }
David Neto257c3892018-04-11 13:19:45 -04004974 Ops << MkId(VMap[constant]) << MkId(std::get<2>(*DeferredInst));
David Neto3fbb4072017-10-16 11:28:14 -04004975
4976 SPIRVInstList.insert(
David Neto87846742018-04-11 17:36:22 -04004977 InsertPoint, new SPIRVInstruction(
4978 opcode, std::get<2>(*DeferredInst) + 1, Ops));
David Neto3fbb4072017-10-16 11:28:14 -04004979 };
4980
4981 switch (IndirectExtInst) {
4982 case glsl::ExtInstFindUMsb: // Implementing clz
4983 generate_extra_inst(
4984 spv::OpISub, ConstantInt::get(Type::getInt32Ty(Context), 31));
4985 break;
4986 case glsl::ExtInstAcos: // Implementing acospi
4987 case glsl::ExtInstAsin: // Implementing asinpi
4988 case glsl::ExtInstAtan2: // Implementing atan2pi
4989 generate_extra_inst(
4990 spv::OpFMul,
4991 ConstantFP::get(Type::getFloatTy(Context), kOneOverPi));
4992 break;
4993
4994 default:
4995 assert(false && "internally inconsistent");
David Neto4d02a532017-09-17 12:57:44 -04004996 }
David Neto22f144c2017-06-12 14:26:21 -04004997 }
David Neto3fbb4072017-10-16 11:28:14 -04004998
David Neto22f144c2017-06-12 14:26:21 -04004999 } else if (Callee->getName().equals("_Z8popcounti") ||
5000 Callee->getName().equals("_Z8popcountj") ||
5001 Callee->getName().equals("_Z8popcountDv2_i") ||
5002 Callee->getName().equals("_Z8popcountDv3_i") ||
5003 Callee->getName().equals("_Z8popcountDv4_i") ||
5004 Callee->getName().equals("_Z8popcountDv2_j") ||
5005 Callee->getName().equals("_Z8popcountDv3_j") ||
5006 Callee->getName().equals("_Z8popcountDv4_j")) {
5007 //
5008 // Generate OpBitCount
5009 //
5010 // Ops[0] = Result Type ID
5011 // Ops[1] = Base ID
David Neto257c3892018-04-11 13:19:45 -04005012 SPIRVOperandList Ops;
5013 Ops << MkId(lookupType(Call->getType()))
5014 << MkId(VMap[Call->getOperand(0)]);
David Neto22f144c2017-06-12 14:26:21 -04005015
5016 SPIRVInstList.insert(
David Neto87846742018-04-11 17:36:22 -04005017 InsertPoint, new SPIRVInstruction(spv::OpBitCount,
David Neto22f144c2017-06-12 14:26:21 -04005018 std::get<2>(*DeferredInst), Ops));
David Netoab03f432017-11-03 17:00:44 -04005019
5020 } else if (Callee->getName().startswith(kCompositeConstructFunctionPrefix)) {
5021
5022 // Generate an OpCompositeConstruct
5023 SPIRVOperandList Ops;
5024
5025 // The result type.
David Neto257c3892018-04-11 13:19:45 -04005026 Ops << MkId(lookupType(Call->getType()));
David Netoab03f432017-11-03 17:00:44 -04005027
5028 for (Use &use : Call->arg_operands()) {
David Neto257c3892018-04-11 13:19:45 -04005029 Value *val = use.get();
5030 Ops << MkId(VMap[use.get()]);
David Netoab03f432017-11-03 17:00:44 -04005031 }
5032
5033 SPIRVInstList.insert(
David Neto87846742018-04-11 17:36:22 -04005034 InsertPoint, new SPIRVInstruction(spv::OpCompositeConstruct,
5035 std::get<2>(*DeferredInst), Ops));
David Netoab03f432017-11-03 17:00:44 -04005036
David Neto22f144c2017-06-12 14:26:21 -04005037 } else {
5038 //
5039 // Generate OpFunctionCall.
5040 //
5041
5042 // Ops[0] = Result Type ID
5043 // Ops[1] = Callee Function ID
5044 // Ops[2] ... Ops[n] = Argument 0, ... , Argument n
5045 SPIRVOperandList Ops;
5046
David Neto257c3892018-04-11 13:19:45 -04005047 Ops << MkId( lookupType(Call->getType()));
David Neto22f144c2017-06-12 14:26:21 -04005048
5049 uint32_t CalleeID = VMap[Callee];
David Neto43568eb2017-10-13 18:25:25 -04005050 if (CalleeID == 0) {
5051 errs() << "Can't translate function call. Missing builtin? "
5052 << Callee->getName() << " in: " << *Call << "\n";
5053 // TODO(dneto): Can we error out? Enabling this llvm_unreachable
5054 // causes an infinite loop. Instead, go ahead and generate
5055 // the bad function call. A validator will catch the 0-Id.
5056 // llvm_unreachable("Can't translate function call");
5057 }
David Neto22f144c2017-06-12 14:26:21 -04005058
David Neto257c3892018-04-11 13:19:45 -04005059 Ops << MkId(CalleeID);
David Neto22f144c2017-06-12 14:26:21 -04005060
David Neto22f144c2017-06-12 14:26:21 -04005061 FunctionType *CalleeFTy = cast<FunctionType>(Call->getFunctionType());
5062 for (unsigned i = 0; i < CalleeFTy->getNumParams(); i++) {
David Neto257c3892018-04-11 13:19:45 -04005063 Ops << MkId(VMap[Call->getOperand(i)]);
David Neto22f144c2017-06-12 14:26:21 -04005064 }
5065
David Neto87846742018-04-11 17:36:22 -04005066 auto *CallInst = new SPIRVInstruction(spv::OpFunctionCall,
5067 std::get<2>(*DeferredInst), Ops);
David Neto22f144c2017-06-12 14:26:21 -04005068 SPIRVInstList.insert(InsertPoint, CallInst);
5069 }
5070 }
5071 }
5072}
5073
David Neto1a1a0582017-07-07 12:01:44 -04005074void SPIRVProducerPass::HandleDeferredDecorations(const DataLayout &DL) {
David Netoc6f3ab22018-04-06 18:02:31 -04005075 if (getTypesNeedingArrayStride().empty() && LocalArgs.empty()) {
David Neto1a1a0582017-07-07 12:01:44 -04005076 return;
David Netoc6f3ab22018-04-06 18:02:31 -04005077 }
David Neto1a1a0582017-07-07 12:01:44 -04005078
5079 SPIRVInstructionList &SPIRVInstList = getSPIRVInstList();
David Neto1a1a0582017-07-07 12:01:44 -04005080
5081 // Find an iterator pointing just past the last decoration.
5082 bool seen_decorations = false;
5083 auto DecoInsertPoint =
5084 std::find_if(SPIRVInstList.begin(), SPIRVInstList.end(),
5085 [&seen_decorations](SPIRVInstruction *Inst) -> bool {
5086 const bool is_decoration =
5087 Inst->getOpcode() == spv::OpDecorate ||
5088 Inst->getOpcode() == spv::OpMemberDecorate;
5089 if (is_decoration) {
5090 seen_decorations = true;
5091 return false;
5092 } else {
5093 return seen_decorations;
5094 }
5095 });
5096
David Netoc6f3ab22018-04-06 18:02:31 -04005097 // Insert ArrayStride decorations on pointer types, due to OpPtrAccessChain
5098 // instructions we generated earlier.
David Neto85082642018-03-24 06:55:20 -07005099 for (auto *type : getTypesNeedingArrayStride()) {
5100 Type *elemTy = nullptr;
5101 if (auto *ptrTy = dyn_cast<PointerType>(type)) {
5102 elemTy = ptrTy->getElementType();
5103 } else if (auto* arrayTy = dyn_cast<ArrayType>(type)) {
5104 elemTy = arrayTy->getArrayElementType();
5105 } else if (auto* seqTy = dyn_cast<SequentialType>(type)) {
5106 elemTy = seqTy->getSequentialElementType();
5107 } else {
5108 errs() << "Unhandled strided type " << *type << "\n";
5109 llvm_unreachable("Unhandled strided type");
5110 }
David Neto1a1a0582017-07-07 12:01:44 -04005111
5112 // Ops[0] = Target ID
5113 // Ops[1] = Decoration (ArrayStride)
5114 // Ops[2] = Stride number (Literal Number)
5115 SPIRVOperandList Ops;
5116
David Neto85082642018-03-24 06:55:20 -07005117 // Same as DL.getIndexedOffsetInType( elemTy, { 1 } );
Neil Henning39672102017-09-29 14:33:13 +01005118 const uint32_t stride = static_cast<uint32_t>(DL.getTypeAllocSize(elemTy));
David Neto257c3892018-04-11 13:19:45 -04005119
5120 Ops << MkId(lookupType(type)) << MkNum(spv::DecorationArrayStride)
5121 << MkNum(stride);
David Neto1a1a0582017-07-07 12:01:44 -04005122
David Neto87846742018-04-11 17:36:22 -04005123 auto *DecoInst = new SPIRVInstruction(spv::OpDecorate, Ops);
David Neto1a1a0582017-07-07 12:01:44 -04005124 SPIRVInstList.insert(DecoInsertPoint, DecoInst);
5125 }
David Netoc6f3ab22018-04-06 18:02:31 -04005126
5127 // Emit SpecId decorations targeting the array size value.
5128 for (const Argument *arg : LocalArgs) {
5129 const LocalArgInfo &arg_info = LocalArgMap[arg];
5130 SPIRVOperandList Ops;
5131 Ops << MkId(arg_info.array_size_id) << MkNum(spv::DecorationSpecId)
5132 << MkNum(arg_info.spec_id);
5133 SPIRVInstList.insert(DecoInsertPoint,
David Neto87846742018-04-11 17:36:22 -04005134 new SPIRVInstruction(spv::OpDecorate, Ops));
David Netoc6f3ab22018-04-06 18:02:31 -04005135 }
David Neto1a1a0582017-07-07 12:01:44 -04005136}
5137
David Neto22f144c2017-06-12 14:26:21 -04005138glsl::ExtInst SPIRVProducerPass::getExtInstEnum(StringRef Name) {
5139 return StringSwitch<glsl::ExtInst>(Name)
5140 .Case("_Z3absi", glsl::ExtInst::ExtInstSAbs)
5141 .Case("_Z3absDv2_i", glsl::ExtInst::ExtInstSAbs)
5142 .Case("_Z3absDv3_i", glsl::ExtInst::ExtInstSAbs)
5143 .Case("_Z3absDv4_i", glsl::ExtInst::ExtInstSAbs)
5144 .Case("_Z5clampiii", glsl::ExtInst::ExtInstSClamp)
5145 .Case("_Z5clampDv2_iS_S_", glsl::ExtInst::ExtInstSClamp)
5146 .Case("_Z5clampDv3_iS_S_", glsl::ExtInst::ExtInstSClamp)
5147 .Case("_Z5clampDv4_iS_S_", glsl::ExtInst::ExtInstSClamp)
5148 .Case("_Z5clampjjj", glsl::ExtInst::ExtInstUClamp)
5149 .Case("_Z5clampDv2_jS_S_", glsl::ExtInst::ExtInstUClamp)
5150 .Case("_Z5clampDv3_jS_S_", glsl::ExtInst::ExtInstUClamp)
5151 .Case("_Z5clampDv4_jS_S_", glsl::ExtInst::ExtInstUClamp)
5152 .Case("_Z5clampfff", glsl::ExtInst::ExtInstFClamp)
5153 .Case("_Z5clampDv2_fS_S_", glsl::ExtInst::ExtInstFClamp)
5154 .Case("_Z5clampDv3_fS_S_", glsl::ExtInst::ExtInstFClamp)
5155 .Case("_Z5clampDv4_fS_S_", glsl::ExtInst::ExtInstFClamp)
David Neto22f144c2017-06-12 14:26:21 -04005156 .Case("_Z3maxii", glsl::ExtInst::ExtInstSMax)
5157 .Case("_Z3maxDv2_iS_", glsl::ExtInst::ExtInstSMax)
5158 .Case("_Z3maxDv3_iS_", glsl::ExtInst::ExtInstSMax)
5159 .Case("_Z3maxDv4_iS_", glsl::ExtInst::ExtInstSMax)
5160 .Case("_Z3maxjj", glsl::ExtInst::ExtInstUMax)
5161 .Case("_Z3maxDv2_jS_", glsl::ExtInst::ExtInstUMax)
5162 .Case("_Z3maxDv3_jS_", glsl::ExtInst::ExtInstUMax)
5163 .Case("_Z3maxDv4_jS_", glsl::ExtInst::ExtInstUMax)
5164 .Case("_Z3maxff", glsl::ExtInst::ExtInstFMax)
5165 .Case("_Z3maxDv2_fS_", glsl::ExtInst::ExtInstFMax)
5166 .Case("_Z3maxDv3_fS_", glsl::ExtInst::ExtInstFMax)
5167 .Case("_Z3maxDv4_fS_", glsl::ExtInst::ExtInstFMax)
5168 .StartsWith("_Z4fmax", glsl::ExtInst::ExtInstFMax)
5169 .Case("_Z3minii", glsl::ExtInst::ExtInstSMin)
5170 .Case("_Z3minDv2_iS_", glsl::ExtInst::ExtInstSMin)
5171 .Case("_Z3minDv3_iS_", glsl::ExtInst::ExtInstSMin)
5172 .Case("_Z3minDv4_iS_", glsl::ExtInst::ExtInstSMin)
5173 .Case("_Z3minjj", glsl::ExtInst::ExtInstUMin)
5174 .Case("_Z3minDv2_jS_", glsl::ExtInst::ExtInstUMin)
5175 .Case("_Z3minDv3_jS_", glsl::ExtInst::ExtInstUMin)
5176 .Case("_Z3minDv4_jS_", glsl::ExtInst::ExtInstUMin)
5177 .Case("_Z3minff", glsl::ExtInst::ExtInstFMin)
5178 .Case("_Z3minDv2_fS_", glsl::ExtInst::ExtInstFMin)
5179 .Case("_Z3minDv3_fS_", glsl::ExtInst::ExtInstFMin)
5180 .Case("_Z3minDv4_fS_", glsl::ExtInst::ExtInstFMin)
5181 .StartsWith("_Z4fmin", glsl::ExtInst::ExtInstFMin)
5182 .StartsWith("_Z7degrees", glsl::ExtInst::ExtInstDegrees)
5183 .StartsWith("_Z7radians", glsl::ExtInst::ExtInstRadians)
5184 .StartsWith("_Z3mix", glsl::ExtInst::ExtInstFMix)
5185 .StartsWith("_Z4acos", glsl::ExtInst::ExtInstAcos)
5186 .StartsWith("_Z5acosh", glsl::ExtInst::ExtInstAcosh)
5187 .StartsWith("_Z4asin", glsl::ExtInst::ExtInstAsin)
5188 .StartsWith("_Z5asinh", glsl::ExtInst::ExtInstAsinh)
5189 .StartsWith("_Z4atan", glsl::ExtInst::ExtInstAtan)
5190 .StartsWith("_Z5atan2", glsl::ExtInst::ExtInstAtan2)
5191 .StartsWith("_Z5atanh", glsl::ExtInst::ExtInstAtanh)
5192 .StartsWith("_Z4ceil", glsl::ExtInst::ExtInstCeil)
5193 .StartsWith("_Z3sin", glsl::ExtInst::ExtInstSin)
5194 .StartsWith("_Z4sinh", glsl::ExtInst::ExtInstSinh)
5195 .StartsWith("_Z8half_sin", glsl::ExtInst::ExtInstSin)
5196 .StartsWith("_Z10native_sin", glsl::ExtInst::ExtInstSin)
5197 .StartsWith("_Z3cos", glsl::ExtInst::ExtInstCos)
5198 .StartsWith("_Z4cosh", glsl::ExtInst::ExtInstCosh)
5199 .StartsWith("_Z8half_cos", glsl::ExtInst::ExtInstCos)
5200 .StartsWith("_Z10native_cos", glsl::ExtInst::ExtInstCos)
5201 .StartsWith("_Z3tan", glsl::ExtInst::ExtInstTan)
5202 .StartsWith("_Z4tanh", glsl::ExtInst::ExtInstTanh)
5203 .StartsWith("_Z8half_tan", glsl::ExtInst::ExtInstTan)
5204 .StartsWith("_Z10native_tan", glsl::ExtInst::ExtInstTan)
5205 .StartsWith("_Z3exp", glsl::ExtInst::ExtInstExp)
5206 .StartsWith("_Z8half_exp", glsl::ExtInst::ExtInstExp)
5207 .StartsWith("_Z10native_exp", glsl::ExtInst::ExtInstExp)
5208 .StartsWith("_Z4exp2", glsl::ExtInst::ExtInstExp2)
5209 .StartsWith("_Z9half_exp2", glsl::ExtInst::ExtInstExp2)
5210 .StartsWith("_Z11native_exp2", glsl::ExtInst::ExtInstExp2)
5211 .StartsWith("_Z3log", glsl::ExtInst::ExtInstLog)
5212 .StartsWith("_Z8half_log", glsl::ExtInst::ExtInstLog)
5213 .StartsWith("_Z10native_log", glsl::ExtInst::ExtInstLog)
5214 .StartsWith("_Z4log2", glsl::ExtInst::ExtInstLog2)
5215 .StartsWith("_Z9half_log2", glsl::ExtInst::ExtInstLog2)
5216 .StartsWith("_Z11native_log2", glsl::ExtInst::ExtInstLog2)
5217 .StartsWith("_Z4fabs", glsl::ExtInst::ExtInstFAbs)
5218 .StartsWith("_Z5floor", glsl::ExtInst::ExtInstFloor)
5219 .StartsWith("_Z5ldexp", glsl::ExtInst::ExtInstLdexp)
5220 .StartsWith("_Z3pow", glsl::ExtInst::ExtInstPow)
5221 .StartsWith("_Z4powr", glsl::ExtInst::ExtInstPow)
5222 .StartsWith("_Z9half_powr", glsl::ExtInst::ExtInstPow)
5223 .StartsWith("_Z11native_powr", glsl::ExtInst::ExtInstPow)
5224 .StartsWith("_Z5round", glsl::ExtInst::ExtInstRound)
5225 .StartsWith("_Z4sqrt", glsl::ExtInst::ExtInstSqrt)
5226 .StartsWith("_Z9half_sqrt", glsl::ExtInst::ExtInstSqrt)
5227 .StartsWith("_Z11native_sqrt", glsl::ExtInst::ExtInstSqrt)
5228 .StartsWith("_Z5rsqrt", glsl::ExtInst::ExtInstInverseSqrt)
5229 .StartsWith("_Z10half_rsqrt", glsl::ExtInst::ExtInstInverseSqrt)
5230 .StartsWith("_Z12native_rsqrt", glsl::ExtInst::ExtInstInverseSqrt)
5231 .StartsWith("_Z5trunc", glsl::ExtInst::ExtInstTrunc)
5232 .StartsWith("_Z5frexp", glsl::ExtInst::ExtInstFrexp)
5233 .StartsWith("_Z4sign", glsl::ExtInst::ExtInstFSign)
5234 .StartsWith("_Z6length", glsl::ExtInst::ExtInstLength)
5235 .StartsWith("_Z8distance", glsl::ExtInst::ExtInstDistance)
David Netoe9a03512017-10-16 10:08:27 -04005236 .StartsWith("_Z4step", glsl::ExtInst::ExtInstStep)
David Neto22f144c2017-06-12 14:26:21 -04005237 .Case("_Z5crossDv3_fS_", glsl::ExtInst::ExtInstCross)
5238 .StartsWith("_Z9normalize", glsl::ExtInst::ExtInstNormalize)
5239 .StartsWith("llvm.fmuladd.", glsl::ExtInst::ExtInstFma)
5240 .Case("spirv.unpack.v2f16", glsl::ExtInst::ExtInstUnpackHalf2x16)
5241 .Case("spirv.pack.v2f16", glsl::ExtInst::ExtInstPackHalf2x16)
David Neto62653202017-10-16 19:05:18 -04005242 .Case("clspv.fract.f", glsl::ExtInst::ExtInstFract)
5243 .Case("clspv.fract.v2f", glsl::ExtInst::ExtInstFract)
5244 .Case("clspv.fract.v3f", glsl::ExtInst::ExtInstFract)
5245 .Case("clspv.fract.v4f", glsl::ExtInst::ExtInstFract)
David Neto3fbb4072017-10-16 11:28:14 -04005246 .Default(kGlslExtInstBad);
5247}
5248
5249glsl::ExtInst SPIRVProducerPass::getIndirectExtInstEnum(StringRef Name) {
5250 // Check indirect cases.
5251 return StringSwitch<glsl::ExtInst>(Name)
5252 .StartsWith("_Z3clz", glsl::ExtInst::ExtInstFindUMsb)
5253 // Use exact match on float arg because these need a multiply
5254 // of a constant of the right floating point type.
5255 .Case("_Z6acospif", glsl::ExtInst::ExtInstAcos)
5256 .Case("_Z6acospiDv2_f", glsl::ExtInst::ExtInstAcos)
5257 .Case("_Z6acospiDv3_f", glsl::ExtInst::ExtInstAcos)
5258 .Case("_Z6acospiDv4_f", glsl::ExtInst::ExtInstAcos)
5259 .Case("_Z6asinpif", glsl::ExtInst::ExtInstAsin)
5260 .Case("_Z6asinpiDv2_f", glsl::ExtInst::ExtInstAsin)
5261 .Case("_Z6asinpiDv3_f", glsl::ExtInst::ExtInstAsin)
5262 .Case("_Z6asinpiDv4_f", glsl::ExtInst::ExtInstAsin)
5263 .Case("_Z7atan2piff", glsl::ExtInst::ExtInstAtan2)
5264 .Case("_Z7atan2piDv2_fS_", glsl::ExtInst::ExtInstAtan2)
5265 .Case("_Z7atan2piDv3_fS_", glsl::ExtInst::ExtInstAtan2)
5266 .Case("_Z7atan2piDv4_fS_", glsl::ExtInst::ExtInstAtan2)
5267 .Default(kGlslExtInstBad);
5268}
5269
5270glsl::ExtInst SPIRVProducerPass::getDirectOrIndirectExtInstEnum(StringRef Name) {
5271 auto direct = getExtInstEnum(Name);
5272 if (direct != kGlslExtInstBad)
5273 return direct;
5274 return getIndirectExtInstEnum(Name);
David Neto22f144c2017-06-12 14:26:21 -04005275}
5276
5277void SPIRVProducerPass::PrintResID(SPIRVInstruction *Inst) {
5278 out << "%" << Inst->getResultID();
5279}
5280
5281void SPIRVProducerPass::PrintOpcode(SPIRVInstruction *Inst) {
5282 spv::Op Opcode = static_cast<spv::Op>(Inst->getOpcode());
5283 out << "\t" << spv::getOpName(Opcode);
5284}
5285
5286void SPIRVProducerPass::PrintOperand(SPIRVOperand *Op) {
5287 SPIRVOperandType OpTy = Op->getType();
5288 switch (OpTy) {
5289 default: {
5290 llvm_unreachable("Unsupported SPIRV Operand Type???");
5291 break;
5292 }
5293 case SPIRVOperandType::NUMBERID: {
5294 out << "%" << Op->getNumID();
5295 break;
5296 }
5297 case SPIRVOperandType::LITERAL_STRING: {
5298 out << "\"" << Op->getLiteralStr() << "\"";
5299 break;
5300 }
5301 case SPIRVOperandType::LITERAL_INTEGER: {
5302 // TODO: Handle LiteralNum carefully.
5303 for (auto Word : Op->getLiteralNum()) {
5304 out << Word;
5305 }
5306 break;
5307 }
5308 case SPIRVOperandType::LITERAL_FLOAT: {
5309 // TODO: Handle LiteralNum carefully.
5310 for (auto Word : Op->getLiteralNum()) {
5311 APFloat APF = APFloat(APFloat::IEEEsingle(), APInt(32, Word));
5312 SmallString<8> Str;
5313 APF.toString(Str, 6, 2);
5314 out << Str;
5315 }
5316 break;
5317 }
5318 }
5319}
5320
5321void SPIRVProducerPass::PrintCapability(SPIRVOperand *Op) {
5322 spv::Capability Cap = static_cast<spv::Capability>(Op->getNumID());
5323 out << spv::getCapabilityName(Cap);
5324}
5325
5326void SPIRVProducerPass::PrintExtInst(SPIRVOperand *Op) {
5327 auto LiteralNum = Op->getLiteralNum();
5328 glsl::ExtInst Ext = static_cast<glsl::ExtInst>(LiteralNum[0]);
5329 out << glsl::getExtInstName(Ext);
5330}
5331
5332void SPIRVProducerPass::PrintAddrModel(SPIRVOperand *Op) {
5333 spv::AddressingModel AddrModel =
5334 static_cast<spv::AddressingModel>(Op->getNumID());
5335 out << spv::getAddressingModelName(AddrModel);
5336}
5337
5338void SPIRVProducerPass::PrintMemModel(SPIRVOperand *Op) {
5339 spv::MemoryModel MemModel = static_cast<spv::MemoryModel>(Op->getNumID());
5340 out << spv::getMemoryModelName(MemModel);
5341}
5342
5343void SPIRVProducerPass::PrintExecModel(SPIRVOperand *Op) {
5344 spv::ExecutionModel ExecModel =
5345 static_cast<spv::ExecutionModel>(Op->getNumID());
5346 out << spv::getExecutionModelName(ExecModel);
5347}
5348
5349void SPIRVProducerPass::PrintExecMode(SPIRVOperand *Op) {
5350 spv::ExecutionMode ExecMode = static_cast<spv::ExecutionMode>(Op->getNumID());
5351 out << spv::getExecutionModeName(ExecMode);
5352}
5353
5354void SPIRVProducerPass::PrintSourceLanguage(SPIRVOperand *Op) {
5355 spv::SourceLanguage SourceLang = static_cast<spv::SourceLanguage>(Op->getNumID());
5356 out << spv::getSourceLanguageName(SourceLang);
5357}
5358
5359void SPIRVProducerPass::PrintFuncCtrl(SPIRVOperand *Op) {
5360 spv::FunctionControlMask FuncCtrl =
5361 static_cast<spv::FunctionControlMask>(Op->getNumID());
5362 out << spv::getFunctionControlName(FuncCtrl);
5363}
5364
5365void SPIRVProducerPass::PrintStorageClass(SPIRVOperand *Op) {
5366 spv::StorageClass StClass = static_cast<spv::StorageClass>(Op->getNumID());
5367 out << getStorageClassName(StClass);
5368}
5369
5370void SPIRVProducerPass::PrintDecoration(SPIRVOperand *Op) {
5371 spv::Decoration Deco = static_cast<spv::Decoration>(Op->getNumID());
5372 out << getDecorationName(Deco);
5373}
5374
5375void SPIRVProducerPass::PrintBuiltIn(SPIRVOperand *Op) {
5376 spv::BuiltIn BIn = static_cast<spv::BuiltIn>(Op->getNumID());
5377 out << getBuiltInName(BIn);
5378}
5379
5380void SPIRVProducerPass::PrintSelectionControl(SPIRVOperand *Op) {
5381 spv::SelectionControlMask BIn =
5382 static_cast<spv::SelectionControlMask>(Op->getNumID());
5383 out << getSelectionControlName(BIn);
5384}
5385
5386void SPIRVProducerPass::PrintLoopControl(SPIRVOperand *Op) {
5387 spv::LoopControlMask BIn = static_cast<spv::LoopControlMask>(Op->getNumID());
5388 out << getLoopControlName(BIn);
5389}
5390
5391void SPIRVProducerPass::PrintDimensionality(SPIRVOperand *Op) {
5392 spv::Dim DIM = static_cast<spv::Dim>(Op->getNumID());
5393 out << getDimName(DIM);
5394}
5395
5396void SPIRVProducerPass::PrintImageFormat(SPIRVOperand *Op) {
5397 spv::ImageFormat Format = static_cast<spv::ImageFormat>(Op->getNumID());
5398 out << getImageFormatName(Format);
5399}
5400
5401void SPIRVProducerPass::PrintMemoryAccess(SPIRVOperand *Op) {
5402 out << spv::getMemoryAccessName(
5403 static_cast<spv::MemoryAccessMask>(Op->getNumID()));
5404}
5405
5406void SPIRVProducerPass::PrintImageOperandsType(SPIRVOperand *Op) {
5407 auto LiteralNum = Op->getLiteralNum();
5408 spv::ImageOperandsMask Type =
5409 static_cast<spv::ImageOperandsMask>(LiteralNum[0]);
5410 out << getImageOperandsName(Type);
5411}
5412
5413void SPIRVProducerPass::WriteSPIRVAssembly() {
5414 SPIRVInstructionList &SPIRVInstList = getSPIRVInstList();
5415
5416 for (auto Inst : SPIRVInstList) {
5417 SPIRVOperandList Ops = Inst->getOperands();
5418 spv::Op Opcode = static_cast<spv::Op>(Inst->getOpcode());
5419
5420 switch (Opcode) {
5421 default: {
5422 llvm_unreachable("Unsupported SPIRV instruction");
5423 break;
5424 }
5425 case spv::OpCapability: {
5426 // Ops[0] = Capability
5427 PrintOpcode(Inst);
5428 out << " ";
5429 PrintCapability(Ops[0]);
5430 out << "\n";
5431 break;
5432 }
5433 case spv::OpMemoryModel: {
5434 // Ops[0] = Addressing Model
5435 // Ops[1] = Memory Model
5436 PrintOpcode(Inst);
5437 out << " ";
5438 PrintAddrModel(Ops[0]);
5439 out << " ";
5440 PrintMemModel(Ops[1]);
5441 out << "\n";
5442 break;
5443 }
5444 case spv::OpEntryPoint: {
5445 // Ops[0] = Execution Model
5446 // Ops[1] = EntryPoint ID
5447 // Ops[2] = Name (Literal String)
5448 // Ops[3] ... Ops[n] = Interface ID
5449 PrintOpcode(Inst);
5450 out << " ";
5451 PrintExecModel(Ops[0]);
5452 for (uint32_t i = 1; i < Ops.size(); i++) {
5453 out << " ";
5454 PrintOperand(Ops[i]);
5455 }
5456 out << "\n";
5457 break;
5458 }
5459 case spv::OpExecutionMode: {
5460 // Ops[0] = Entry Point ID
5461 // Ops[1] = Execution Mode
5462 // Ops[2] ... Ops[n] = Optional literals according to Execution Mode
5463 PrintOpcode(Inst);
5464 out << " ";
5465 PrintOperand(Ops[0]);
5466 out << " ";
5467 PrintExecMode(Ops[1]);
5468 for (uint32_t i = 2; i < Ops.size(); i++) {
5469 out << " ";
5470 PrintOperand(Ops[i]);
5471 }
5472 out << "\n";
5473 break;
5474 }
5475 case spv::OpSource: {
5476 // Ops[0] = SourceLanguage ID
5477 // Ops[1] = Version (LiteralNum)
5478 PrintOpcode(Inst);
5479 out << " ";
5480 PrintSourceLanguage(Ops[0]);
5481 out << " ";
5482 PrintOperand(Ops[1]);
5483 out << "\n";
5484 break;
5485 }
5486 case spv::OpDecorate: {
5487 // Ops[0] = Target ID
5488 // Ops[1] = Decoration (Block or BufferBlock)
5489 // Ops[2] ... Ops[n] = Optional literals according to Decoration
5490 PrintOpcode(Inst);
5491 out << " ";
5492 PrintOperand(Ops[0]);
5493 out << " ";
5494 PrintDecoration(Ops[1]);
5495 // Handle BuiltIn OpDecorate specially.
5496 if (Ops[1]->getNumID() == spv::DecorationBuiltIn) {
5497 out << " ";
5498 PrintBuiltIn(Ops[2]);
5499 } else {
5500 for (uint32_t i = 2; i < Ops.size(); i++) {
5501 out << " ";
5502 PrintOperand(Ops[i]);
5503 }
5504 }
5505 out << "\n";
5506 break;
5507 }
5508 case spv::OpMemberDecorate: {
5509 // Ops[0] = Structure Type ID
5510 // Ops[1] = Member Index(Literal Number)
5511 // Ops[2] = Decoration
5512 // Ops[3] ... Ops[n] = Optional literals according to Decoration
5513 PrintOpcode(Inst);
5514 out << " ";
5515 PrintOperand(Ops[0]);
5516 out << " ";
5517 PrintOperand(Ops[1]);
5518 out << " ";
5519 PrintDecoration(Ops[2]);
5520 for (uint32_t i = 3; i < Ops.size(); i++) {
5521 out << " ";
5522 PrintOperand(Ops[i]);
5523 }
5524 out << "\n";
5525 break;
5526 }
5527 case spv::OpTypePointer: {
5528 // Ops[0] = Storage Class
5529 // Ops[1] = Element Type ID
5530 PrintResID(Inst);
5531 out << " = ";
5532 PrintOpcode(Inst);
5533 out << " ";
5534 PrintStorageClass(Ops[0]);
5535 out << " ";
5536 PrintOperand(Ops[1]);
5537 out << "\n";
5538 break;
5539 }
5540 case spv::OpTypeImage: {
5541 // Ops[0] = Sampled Type ID
5542 // Ops[1] = Dim ID
5543 // Ops[2] = Depth (Literal Number)
5544 // Ops[3] = Arrayed (Literal Number)
5545 // Ops[4] = MS (Literal Number)
5546 // Ops[5] = Sampled (Literal Number)
5547 // Ops[6] = Image Format ID
5548 PrintResID(Inst);
5549 out << " = ";
5550 PrintOpcode(Inst);
5551 out << " ";
5552 PrintOperand(Ops[0]);
5553 out << " ";
5554 PrintDimensionality(Ops[1]);
5555 out << " ";
5556 PrintOperand(Ops[2]);
5557 out << " ";
5558 PrintOperand(Ops[3]);
5559 out << " ";
5560 PrintOperand(Ops[4]);
5561 out << " ";
5562 PrintOperand(Ops[5]);
5563 out << " ";
5564 PrintImageFormat(Ops[6]);
5565 out << "\n";
5566 break;
5567 }
5568 case spv::OpFunction: {
5569 // Ops[0] : Result Type ID
5570 // Ops[1] : Function Control
5571 // Ops[2] : Function Type ID
5572 PrintResID(Inst);
5573 out << " = ";
5574 PrintOpcode(Inst);
5575 out << " ";
5576 PrintOperand(Ops[0]);
5577 out << " ";
5578 PrintFuncCtrl(Ops[1]);
5579 out << " ";
5580 PrintOperand(Ops[2]);
5581 out << "\n";
5582 break;
5583 }
5584 case spv::OpSelectionMerge: {
5585 // Ops[0] = Merge Block ID
5586 // Ops[1] = Selection Control
5587 PrintOpcode(Inst);
5588 out << " ";
5589 PrintOperand(Ops[0]);
5590 out << " ";
5591 PrintSelectionControl(Ops[1]);
5592 out << "\n";
5593 break;
5594 }
5595 case spv::OpLoopMerge: {
5596 // Ops[0] = Merge Block ID
5597 // Ops[1] = Continue Target ID
5598 // Ops[2] = Selection Control
5599 PrintOpcode(Inst);
5600 out << " ";
5601 PrintOperand(Ops[0]);
5602 out << " ";
5603 PrintOperand(Ops[1]);
5604 out << " ";
5605 PrintLoopControl(Ops[2]);
5606 out << "\n";
5607 break;
5608 }
5609 case spv::OpImageSampleExplicitLod: {
5610 // Ops[0] = Result Type ID
5611 // Ops[1] = Sampled Image ID
5612 // Ops[2] = Coordinate ID
5613 // Ops[3] = Image Operands Type ID
5614 // Ops[4] ... Ops[n] = Operands ID
5615 PrintResID(Inst);
5616 out << " = ";
5617 PrintOpcode(Inst);
5618 for (uint32_t i = 0; i < 3; i++) {
5619 out << " ";
5620 PrintOperand(Ops[i]);
5621 }
5622 out << " ";
5623 PrintImageOperandsType(Ops[3]);
5624 for (uint32_t i = 4; i < Ops.size(); i++) {
5625 out << " ";
5626 PrintOperand(Ops[i]);
5627 }
5628 out << "\n";
5629 break;
5630 }
5631 case spv::OpVariable: {
5632 // Ops[0] : Result Type ID
5633 // Ops[1] : Storage Class
5634 // Ops[2] ... Ops[n] = Initializer IDs
5635 PrintResID(Inst);
5636 out << " = ";
5637 PrintOpcode(Inst);
5638 out << " ";
5639 PrintOperand(Ops[0]);
5640 out << " ";
5641 PrintStorageClass(Ops[1]);
5642 for (uint32_t i = 2; i < Ops.size(); i++) {
5643 out << " ";
5644 PrintOperand(Ops[i]);
5645 }
5646 out << "\n";
5647 break;
5648 }
5649 case spv::OpExtInst: {
5650 // Ops[0] = Result Type ID
5651 // Ops[1] = Set ID (OpExtInstImport ID)
5652 // Ops[2] = Instruction Number (Literal Number)
5653 // Ops[3] ... Ops[n] = Operand 1, ... , Operand n
5654 PrintResID(Inst);
5655 out << " = ";
5656 PrintOpcode(Inst);
5657 out << " ";
5658 PrintOperand(Ops[0]);
5659 out << " ";
5660 PrintOperand(Ops[1]);
5661 out << " ";
5662 PrintExtInst(Ops[2]);
5663 for (uint32_t i = 3; i < Ops.size(); i++) {
5664 out << " ";
5665 PrintOperand(Ops[i]);
5666 }
5667 out << "\n";
5668 break;
5669 }
5670 case spv::OpCopyMemory: {
5671 // Ops[0] = Addressing Model
5672 // Ops[1] = Memory Model
5673 PrintOpcode(Inst);
5674 out << " ";
5675 PrintOperand(Ops[0]);
5676 out << " ";
5677 PrintOperand(Ops[1]);
5678 out << " ";
5679 PrintMemoryAccess(Ops[2]);
5680 out << " ";
5681 PrintOperand(Ops[3]);
5682 out << "\n";
5683 break;
5684 }
5685 case spv::OpExtension:
5686 case spv::OpControlBarrier:
5687 case spv::OpMemoryBarrier:
5688 case spv::OpBranch:
5689 case spv::OpBranchConditional:
5690 case spv::OpStore:
5691 case spv::OpImageWrite:
5692 case spv::OpReturnValue:
5693 case spv::OpReturn:
5694 case spv::OpFunctionEnd: {
5695 PrintOpcode(Inst);
5696 for (uint32_t i = 0; i < Ops.size(); i++) {
5697 out << " ";
5698 PrintOperand(Ops[i]);
5699 }
5700 out << "\n";
5701 break;
5702 }
5703 case spv::OpExtInstImport:
5704 case spv::OpTypeRuntimeArray:
5705 case spv::OpTypeStruct:
5706 case spv::OpTypeSampler:
5707 case spv::OpTypeSampledImage:
5708 case spv::OpTypeInt:
5709 case spv::OpTypeFloat:
5710 case spv::OpTypeArray:
5711 case spv::OpTypeVector:
5712 case spv::OpTypeBool:
5713 case spv::OpTypeVoid:
5714 case spv::OpTypeFunction:
5715 case spv::OpFunctionParameter:
5716 case spv::OpLabel:
5717 case spv::OpPhi:
5718 case spv::OpLoad:
5719 case spv::OpSelect:
5720 case spv::OpAccessChain:
5721 case spv::OpPtrAccessChain:
5722 case spv::OpInBoundsAccessChain:
5723 case spv::OpUConvert:
5724 case spv::OpSConvert:
5725 case spv::OpConvertFToU:
5726 case spv::OpConvertFToS:
5727 case spv::OpConvertUToF:
5728 case spv::OpConvertSToF:
5729 case spv::OpFConvert:
5730 case spv::OpConvertPtrToU:
5731 case spv::OpConvertUToPtr:
5732 case spv::OpBitcast:
5733 case spv::OpIAdd:
5734 case spv::OpFAdd:
5735 case spv::OpISub:
5736 case spv::OpFSub:
5737 case spv::OpIMul:
5738 case spv::OpFMul:
5739 case spv::OpUDiv:
5740 case spv::OpSDiv:
5741 case spv::OpFDiv:
5742 case spv::OpUMod:
5743 case spv::OpSRem:
5744 case spv::OpFRem:
5745 case spv::OpBitwiseOr:
5746 case spv::OpBitwiseXor:
5747 case spv::OpBitwiseAnd:
David Netoa394f392017-08-26 20:45:29 -04005748 case spv::OpNot:
David Neto22f144c2017-06-12 14:26:21 -04005749 case spv::OpShiftLeftLogical:
5750 case spv::OpShiftRightLogical:
5751 case spv::OpShiftRightArithmetic:
5752 case spv::OpBitCount:
David Netoab03f432017-11-03 17:00:44 -04005753 case spv::OpCompositeConstruct:
David Neto22f144c2017-06-12 14:26:21 -04005754 case spv::OpCompositeExtract:
5755 case spv::OpVectorExtractDynamic:
5756 case spv::OpCompositeInsert:
David Neto0a2f98d2017-09-15 19:38:40 -04005757 case spv::OpCopyObject:
David Neto22f144c2017-06-12 14:26:21 -04005758 case spv::OpVectorInsertDynamic:
5759 case spv::OpVectorShuffle:
5760 case spv::OpIEqual:
5761 case spv::OpINotEqual:
5762 case spv::OpUGreaterThan:
5763 case spv::OpUGreaterThanEqual:
5764 case spv::OpULessThan:
5765 case spv::OpULessThanEqual:
5766 case spv::OpSGreaterThan:
5767 case spv::OpSGreaterThanEqual:
5768 case spv::OpSLessThan:
5769 case spv::OpSLessThanEqual:
5770 case spv::OpFOrdEqual:
5771 case spv::OpFOrdGreaterThan:
5772 case spv::OpFOrdGreaterThanEqual:
5773 case spv::OpFOrdLessThan:
5774 case spv::OpFOrdLessThanEqual:
5775 case spv::OpFOrdNotEqual:
5776 case spv::OpFUnordEqual:
5777 case spv::OpFUnordGreaterThan:
5778 case spv::OpFUnordGreaterThanEqual:
5779 case spv::OpFUnordLessThan:
5780 case spv::OpFUnordLessThanEqual:
5781 case spv::OpFUnordNotEqual:
5782 case spv::OpSampledImage:
5783 case spv::OpFunctionCall:
5784 case spv::OpConstantTrue:
5785 case spv::OpConstantFalse:
5786 case spv::OpConstant:
5787 case spv::OpSpecConstant:
5788 case spv::OpConstantComposite:
5789 case spv::OpSpecConstantComposite:
5790 case spv::OpConstantNull:
5791 case spv::OpLogicalOr:
5792 case spv::OpLogicalAnd:
5793 case spv::OpLogicalNot:
5794 case spv::OpLogicalNotEqual:
5795 case spv::OpUndef:
5796 case spv::OpIsInf:
5797 case spv::OpIsNan:
5798 case spv::OpAny:
5799 case spv::OpAll:
David Neto5c22a252018-03-15 16:07:41 -04005800 case spv::OpImageQuerySize:
David Neto22f144c2017-06-12 14:26:21 -04005801 case spv::OpAtomicIAdd:
5802 case spv::OpAtomicISub:
5803 case spv::OpAtomicExchange:
5804 case spv::OpAtomicIIncrement:
5805 case spv::OpAtomicIDecrement:
5806 case spv::OpAtomicCompareExchange:
5807 case spv::OpAtomicUMin:
5808 case spv::OpAtomicSMin:
5809 case spv::OpAtomicUMax:
5810 case spv::OpAtomicSMax:
5811 case spv::OpAtomicAnd:
5812 case spv::OpAtomicOr:
5813 case spv::OpAtomicXor:
5814 case spv::OpDot: {
5815 PrintResID(Inst);
5816 out << " = ";
5817 PrintOpcode(Inst);
5818 for (uint32_t i = 0; i < Ops.size(); i++) {
5819 out << " ";
5820 PrintOperand(Ops[i]);
5821 }
5822 out << "\n";
5823 break;
5824 }
5825 }
5826 }
5827}
5828
5829void SPIRVProducerPass::WriteOneWord(uint32_t Word) {
David Neto0676e6f2017-07-11 18:47:44 -04005830 binaryOut->write(reinterpret_cast<const char *>(&Word), sizeof(uint32_t));
David Neto22f144c2017-06-12 14:26:21 -04005831}
5832
5833void SPIRVProducerPass::WriteResultID(SPIRVInstruction *Inst) {
5834 WriteOneWord(Inst->getResultID());
5835}
5836
5837void SPIRVProducerPass::WriteWordCountAndOpcode(SPIRVInstruction *Inst) {
5838 // High 16 bit : Word Count
5839 // Low 16 bit : Opcode
5840 uint32_t Word = Inst->getOpcode();
5841 Word |= Inst->getWordCount() << 16;
5842 WriteOneWord(Word);
5843}
5844
5845void SPIRVProducerPass::WriteOperand(SPIRVOperand *Op) {
5846 SPIRVOperandType OpTy = Op->getType();
5847 switch (OpTy) {
5848 default: {
5849 llvm_unreachable("Unsupported SPIRV Operand Type???");
5850 break;
5851 }
5852 case SPIRVOperandType::NUMBERID: {
5853 WriteOneWord(Op->getNumID());
5854 break;
5855 }
5856 case SPIRVOperandType::LITERAL_STRING: {
5857 std::string Str = Op->getLiteralStr();
5858 const char *Data = Str.c_str();
5859 size_t WordSize = Str.size() / 4;
5860 for (unsigned Idx = 0; Idx < WordSize; Idx++) {
5861 WriteOneWord(*reinterpret_cast<const uint32_t *>(&Data[4 * Idx]));
5862 }
5863
5864 uint32_t Remainder = Str.size() % 4;
5865 uint32_t LastWord = 0;
5866 if (Remainder) {
5867 for (unsigned Idx = 0; Idx < Remainder; Idx++) {
5868 LastWord |= Data[4 * WordSize + Idx] << 8 * Idx;
5869 }
5870 }
5871
5872 WriteOneWord(LastWord);
5873 break;
5874 }
5875 case SPIRVOperandType::LITERAL_INTEGER:
5876 case SPIRVOperandType::LITERAL_FLOAT: {
5877 auto LiteralNum = Op->getLiteralNum();
5878 // TODO: Handle LiteranNum carefully.
5879 for (auto Word : LiteralNum) {
5880 WriteOneWord(Word);
5881 }
5882 break;
5883 }
5884 }
5885}
5886
5887void SPIRVProducerPass::WriteSPIRVBinary() {
5888 SPIRVInstructionList &SPIRVInstList = getSPIRVInstList();
5889
5890 for (auto Inst : SPIRVInstList) {
David Netoc6f3ab22018-04-06 18:02:31 -04005891 SPIRVOperandList Ops{Inst->getOperands()};
David Neto22f144c2017-06-12 14:26:21 -04005892 spv::Op Opcode = static_cast<spv::Op>(Inst->getOpcode());
5893
5894 switch (Opcode) {
5895 default: {
David Neto5c22a252018-03-15 16:07:41 -04005896 errs() << "Unsupported SPIR-V instruction opcode " << int(Opcode) << "\n";
David Neto22f144c2017-06-12 14:26:21 -04005897 llvm_unreachable("Unsupported SPIRV instruction");
5898 break;
5899 }
5900 case spv::OpCapability:
5901 case spv::OpExtension:
5902 case spv::OpMemoryModel:
5903 case spv::OpEntryPoint:
5904 case spv::OpExecutionMode:
5905 case spv::OpSource:
5906 case spv::OpDecorate:
5907 case spv::OpMemberDecorate:
5908 case spv::OpBranch:
5909 case spv::OpBranchConditional:
5910 case spv::OpSelectionMerge:
5911 case spv::OpLoopMerge:
5912 case spv::OpStore:
5913 case spv::OpImageWrite:
5914 case spv::OpReturnValue:
5915 case spv::OpControlBarrier:
5916 case spv::OpMemoryBarrier:
5917 case spv::OpReturn:
5918 case spv::OpFunctionEnd:
5919 case spv::OpCopyMemory: {
5920 WriteWordCountAndOpcode(Inst);
5921 for (uint32_t i = 0; i < Ops.size(); i++) {
5922 WriteOperand(Ops[i]);
5923 }
5924 break;
5925 }
5926 case spv::OpTypeBool:
5927 case spv::OpTypeVoid:
5928 case spv::OpTypeSampler:
5929 case spv::OpLabel:
5930 case spv::OpExtInstImport:
5931 case spv::OpTypePointer:
5932 case spv::OpTypeRuntimeArray:
5933 case spv::OpTypeStruct:
5934 case spv::OpTypeImage:
5935 case spv::OpTypeSampledImage:
5936 case spv::OpTypeInt:
5937 case spv::OpTypeFloat:
5938 case spv::OpTypeArray:
5939 case spv::OpTypeVector:
5940 case spv::OpTypeFunction: {
5941 WriteWordCountAndOpcode(Inst);
5942 WriteResultID(Inst);
5943 for (uint32_t i = 0; i < Ops.size(); i++) {
5944 WriteOperand(Ops[i]);
5945 }
5946 break;
5947 }
5948 case spv::OpFunction:
5949 case spv::OpFunctionParameter:
5950 case spv::OpAccessChain:
5951 case spv::OpPtrAccessChain:
5952 case spv::OpInBoundsAccessChain:
5953 case spv::OpUConvert:
5954 case spv::OpSConvert:
5955 case spv::OpConvertFToU:
5956 case spv::OpConvertFToS:
5957 case spv::OpConvertUToF:
5958 case spv::OpConvertSToF:
5959 case spv::OpFConvert:
5960 case spv::OpConvertPtrToU:
5961 case spv::OpConvertUToPtr:
5962 case spv::OpBitcast:
5963 case spv::OpIAdd:
5964 case spv::OpFAdd:
5965 case spv::OpISub:
5966 case spv::OpFSub:
5967 case spv::OpIMul:
5968 case spv::OpFMul:
5969 case spv::OpUDiv:
5970 case spv::OpSDiv:
5971 case spv::OpFDiv:
5972 case spv::OpUMod:
5973 case spv::OpSRem:
5974 case spv::OpFRem:
5975 case spv::OpBitwiseOr:
5976 case spv::OpBitwiseXor:
5977 case spv::OpBitwiseAnd:
David Netoa394f392017-08-26 20:45:29 -04005978 case spv::OpNot:
David Neto22f144c2017-06-12 14:26:21 -04005979 case spv::OpShiftLeftLogical:
5980 case spv::OpShiftRightLogical:
5981 case spv::OpShiftRightArithmetic:
5982 case spv::OpBitCount:
David Netoab03f432017-11-03 17:00:44 -04005983 case spv::OpCompositeConstruct:
David Neto22f144c2017-06-12 14:26:21 -04005984 case spv::OpCompositeExtract:
5985 case spv::OpVectorExtractDynamic:
5986 case spv::OpCompositeInsert:
David Neto0a2f98d2017-09-15 19:38:40 -04005987 case spv::OpCopyObject:
David Neto22f144c2017-06-12 14:26:21 -04005988 case spv::OpVectorInsertDynamic:
5989 case spv::OpVectorShuffle:
5990 case spv::OpIEqual:
5991 case spv::OpINotEqual:
5992 case spv::OpUGreaterThan:
5993 case spv::OpUGreaterThanEqual:
5994 case spv::OpULessThan:
5995 case spv::OpULessThanEqual:
5996 case spv::OpSGreaterThan:
5997 case spv::OpSGreaterThanEqual:
5998 case spv::OpSLessThan:
5999 case spv::OpSLessThanEqual:
6000 case spv::OpFOrdEqual:
6001 case spv::OpFOrdGreaterThan:
6002 case spv::OpFOrdGreaterThanEqual:
6003 case spv::OpFOrdLessThan:
6004 case spv::OpFOrdLessThanEqual:
6005 case spv::OpFOrdNotEqual:
6006 case spv::OpFUnordEqual:
6007 case spv::OpFUnordGreaterThan:
6008 case spv::OpFUnordGreaterThanEqual:
6009 case spv::OpFUnordLessThan:
6010 case spv::OpFUnordLessThanEqual:
6011 case spv::OpFUnordNotEqual:
6012 case spv::OpExtInst:
6013 case spv::OpIsInf:
6014 case spv::OpIsNan:
6015 case spv::OpAny:
6016 case spv::OpAll:
6017 case spv::OpUndef:
6018 case spv::OpConstantNull:
6019 case spv::OpLogicalOr:
6020 case spv::OpLogicalAnd:
6021 case spv::OpLogicalNot:
6022 case spv::OpLogicalNotEqual:
6023 case spv::OpConstantComposite:
6024 case spv::OpSpecConstantComposite:
6025 case spv::OpConstantTrue:
6026 case spv::OpConstantFalse:
6027 case spv::OpConstant:
6028 case spv::OpSpecConstant:
6029 case spv::OpVariable:
6030 case spv::OpFunctionCall:
6031 case spv::OpSampledImage:
6032 case spv::OpImageSampleExplicitLod:
David Neto5c22a252018-03-15 16:07:41 -04006033 case spv::OpImageQuerySize:
David Neto22f144c2017-06-12 14:26:21 -04006034 case spv::OpSelect:
6035 case spv::OpPhi:
6036 case spv::OpLoad:
6037 case spv::OpAtomicIAdd:
6038 case spv::OpAtomicISub:
6039 case spv::OpAtomicExchange:
6040 case spv::OpAtomicIIncrement:
6041 case spv::OpAtomicIDecrement:
6042 case spv::OpAtomicCompareExchange:
6043 case spv::OpAtomicUMin:
6044 case spv::OpAtomicSMin:
6045 case spv::OpAtomicUMax:
6046 case spv::OpAtomicSMax:
6047 case spv::OpAtomicAnd:
6048 case spv::OpAtomicOr:
6049 case spv::OpAtomicXor:
6050 case spv::OpDot: {
6051 WriteWordCountAndOpcode(Inst);
6052 WriteOperand(Ops[0]);
6053 WriteResultID(Inst);
6054 for (uint32_t i = 1; i < Ops.size(); i++) {
6055 WriteOperand(Ops[i]);
6056 }
6057 break;
6058 }
6059 }
6060 }
6061}