blob: c57d1c0d8359a0e309e295b134dba6b87ad8c536 [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 Neto78383442018-06-15 20:31:56 -040046#include "DescriptorCounter.h"
David Neto48f56a42017-10-06 16:44:25 -040047
David Neto22f144c2017-06-12 14:26:21 -040048#include <list>
David Neto0676e6f2017-07-11 18:47:44 -040049#include <iomanip>
David Neto26aaf622017-10-23 18:11:53 -040050#include <set>
David Neto0676e6f2017-07-11 18:47:44 -040051#include <sstream>
David Neto257c3892018-04-11 13:19:45 -040052#include <string>
David Neto26aaf622017-10-23 18:11:53 -040053#include <tuple>
David Neto44795152017-07-13 15:45:28 -040054#include <utility>
David Neto22f144c2017-06-12 14:26:21 -040055
56#if defined(_MSC_VER)
57#pragma warning(pop)
58#endif
59
60using namespace llvm;
61using namespace clspv;
David Neto156783e2017-07-05 15:39:41 -040062using namespace mdconst;
David Neto22f144c2017-06-12 14:26:21 -040063
64namespace {
David Netocd8ca5f2017-10-02 23:34:11 -040065
David Neto3fbb4072017-10-16 11:28:14 -040066// The value of 1/pi. This value is from MSDN
67// https://msdn.microsoft.com/en-us/library/4hwaceh6.aspx
68const double kOneOverPi = 0.318309886183790671538;
69const glsl::ExtInst kGlslExtInstBad = static_cast<glsl::ExtInst>(0);
70
David Netoab03f432017-11-03 17:00:44 -040071const char* kCompositeConstructFunctionPrefix = "clspv.composite_construct.";
72
David Neto22f144c2017-06-12 14:26:21 -040073enum SPIRVOperandType {
74 NUMBERID,
75 LITERAL_INTEGER,
76 LITERAL_STRING,
77 LITERAL_FLOAT
78};
79
80struct SPIRVOperand {
81 explicit SPIRVOperand(SPIRVOperandType Ty, uint32_t Num)
82 : Type(Ty), LiteralNum(1, Num) {}
83 explicit SPIRVOperand(SPIRVOperandType Ty, const char *Str)
84 : Type(Ty), LiteralStr(Str) {}
85 explicit SPIRVOperand(SPIRVOperandType Ty, StringRef Str)
86 : Type(Ty), LiteralStr(Str) {}
87 explicit SPIRVOperand(SPIRVOperandType Ty, ArrayRef<uint32_t> NumVec)
88 : Type(Ty), LiteralNum(NumVec.begin(), NumVec.end()) {}
89
90 SPIRVOperandType getType() { return Type; };
91 uint32_t getNumID() { return LiteralNum[0]; };
92 std::string getLiteralStr() { return LiteralStr; };
93 ArrayRef<uint32_t> getLiteralNum() { return LiteralNum; };
94
David Neto87846742018-04-11 17:36:22 -040095 uint32_t GetNumWords() const {
96 switch (Type) {
97 case NUMBERID:
98 return 1;
99 case LITERAL_INTEGER:
100 case LITERAL_FLOAT:
David Netoee2660d2018-06-28 16:31:29 -0400101 return uint32_t(LiteralNum.size());
David Neto87846742018-04-11 17:36:22 -0400102 case LITERAL_STRING:
103 // Account for the terminating null character.
David Netoee2660d2018-06-28 16:31:29 -0400104 return uint32_t((LiteralStr.size() + 4) / 4);
David Neto87846742018-04-11 17:36:22 -0400105 }
106 llvm_unreachable("Unhandled case in SPIRVOperand::GetNumWords()");
107 }
108
David Neto22f144c2017-06-12 14:26:21 -0400109private:
110 SPIRVOperandType Type;
111 std::string LiteralStr;
112 SmallVector<uint32_t, 4> LiteralNum;
113};
114
David Netoc6f3ab22018-04-06 18:02:31 -0400115class SPIRVOperandList {
116public:
117 SPIRVOperandList() {}
118 SPIRVOperandList(const SPIRVOperandList& other) = delete;
119 SPIRVOperandList(SPIRVOperandList&& other) {
120 contents_ = std::move(other.contents_);
121 other.contents_.clear();
122 }
123 SPIRVOperandList(ArrayRef<SPIRVOperand *> init)
124 : contents_(init.begin(), init.end()) {}
125 operator ArrayRef<SPIRVOperand *>() { return contents_; }
126 void push_back(SPIRVOperand *op) { contents_.push_back(op); }
127 void clear() { contents_.clear();}
128 size_t size() const { return contents_.size(); }
129 SPIRVOperand *&operator[](size_t i) { return contents_[i]; }
130
David Neto87846742018-04-11 17:36:22 -0400131 const SmallVector<SPIRVOperand *, 8> &getOperands() const {
132 return contents_;
133 }
134
David Netoc6f3ab22018-04-06 18:02:31 -0400135private:
136 SmallVector<SPIRVOperand *,8> contents_;
137};
138
139SPIRVOperandList &operator<<(SPIRVOperandList &list, SPIRVOperand *elem) {
140 list.push_back(elem);
141 return list;
142}
143
144SPIRVOperand* MkNum(uint32_t num) {
145 return new SPIRVOperand(LITERAL_INTEGER, num);
146}
David Neto257c3892018-04-11 13:19:45 -0400147SPIRVOperand* MkInteger(ArrayRef<uint32_t> num_vec) {
148 return new SPIRVOperand(LITERAL_INTEGER, num_vec);
149}
150SPIRVOperand* MkFloat(ArrayRef<uint32_t> num_vec) {
151 return new SPIRVOperand(LITERAL_FLOAT, num_vec);
152}
David Netoc6f3ab22018-04-06 18:02:31 -0400153SPIRVOperand* MkId(uint32_t id) {
154 return new SPIRVOperand(NUMBERID, id);
155}
David Neto257c3892018-04-11 13:19:45 -0400156SPIRVOperand* MkString(StringRef str) {
157 return new SPIRVOperand(LITERAL_STRING, str);
158}
David Netoc6f3ab22018-04-06 18:02:31 -0400159
David Neto22f144c2017-06-12 14:26:21 -0400160struct SPIRVInstruction {
David Neto87846742018-04-11 17:36:22 -0400161 // Create an instruction with an opcode and no result ID, and with the given
162 // operands. This computes its own word count.
163 explicit SPIRVInstruction(spv::Op Opc, ArrayRef<SPIRVOperand *> Ops)
164 : WordCount(1), Opcode(static_cast<uint16_t>(Opc)), ResultID(0),
165 Operands(Ops.begin(), Ops.end()) {
166 for (auto *operand : Ops) {
David Netoee2660d2018-06-28 16:31:29 -0400167 WordCount += uint16_t(operand->GetNumWords());
David Neto87846742018-04-11 17:36:22 -0400168 }
169 }
170 // Create an instruction with an opcode and a no-zero result ID, and
171 // with the given operands. This computes its own word count.
172 explicit SPIRVInstruction(spv::Op Opc, uint32_t ResID,
David Neto22f144c2017-06-12 14:26:21 -0400173 ArrayRef<SPIRVOperand *> Ops)
David Neto87846742018-04-11 17:36:22 -0400174 : WordCount(2), Opcode(static_cast<uint16_t>(Opc)), ResultID(ResID),
175 Operands(Ops.begin(), Ops.end()) {
176 if (ResID == 0) {
177 llvm_unreachable("Result ID of 0 was provided");
178 }
179 for (auto *operand : Ops) {
180 WordCount += operand->GetNumWords();
181 }
182 }
David Neto22f144c2017-06-12 14:26:21 -0400183
David Netoee2660d2018-06-28 16:31:29 -0400184 uint32_t getWordCount() const { return WordCount; }
David Neto22f144c2017-06-12 14:26:21 -0400185 uint16_t getOpcode() const { return Opcode; }
186 uint32_t getResultID() const { return ResultID; }
187 ArrayRef<SPIRVOperand *> getOperands() const { return Operands; }
188
189private:
David Netoee2660d2018-06-28 16:31:29 -0400190 uint32_t WordCount; // Check the 16-bit bound at code generation time.
David Neto22f144c2017-06-12 14:26:21 -0400191 uint16_t Opcode;
192 uint32_t ResultID;
193 SmallVector<SPIRVOperand *, 4> Operands;
194};
195
196struct SPIRVProducerPass final : public ModulePass {
David Neto22f144c2017-06-12 14:26:21 -0400197 typedef DenseMap<Type *, uint32_t> TypeMapType;
198 typedef UniqueVector<Type *> TypeList;
199 typedef DenseMap<Value *, uint32_t> ValueMapType;
David Netofb9a7972017-08-25 17:08:24 -0400200 typedef UniqueVector<Value *> ValueList;
David Neto22f144c2017-06-12 14:26:21 -0400201 typedef std::vector<std::pair<Value *, uint32_t>> EntryPointVecType;
202 typedef std::list<SPIRVInstruction *> SPIRVInstructionList;
David Neto87846742018-04-11 17:36:22 -0400203 // A vector of tuples, each of which is:
204 // - the LLVM instruction that we will later generate SPIR-V code for
205 // - where the SPIR-V instruction should be inserted
206 // - the result ID of the SPIR-V instruction
David Neto22f144c2017-06-12 14:26:21 -0400207 typedef std::vector<
208 std::tuple<Value *, SPIRVInstructionList::iterator, uint32_t>>
209 DeferredInstVecType;
210 typedef DenseMap<FunctionType *, std::pair<FunctionType *, uint32_t>>
211 GlobalConstFuncMapType;
212
David Neto44795152017-07-13 15:45:28 -0400213 explicit SPIRVProducerPass(
214 raw_pwrite_stream &out, raw_ostream &descriptor_map_out,
215 ArrayRef<std::pair<unsigned, std::string>> samplerMap, bool outputAsm,
216 bool outputCInitList)
David Netoc2c368d2017-06-30 16:50:17 -0400217 : ModulePass(ID), samplerMap(samplerMap), out(out),
David Neto0676e6f2017-07-11 18:47:44 -0400218 binaryTempOut(binaryTempUnderlyingVector), binaryOut(&out),
David Netoc2c368d2017-06-30 16:50:17 -0400219 descriptorMapOut(descriptor_map_out), outputAsm(outputAsm),
David Neto0676e6f2017-07-11 18:47:44 -0400220 outputCInitList(outputCInitList), patchBoundOffset(0), nextID(1),
David Netoa60b00b2017-09-15 16:34:09 -0400221 OpExtInstImportID(0), HasVariablePointers(false), SamplerTy(nullptr),
David Neto85082642018-03-24 06:55:20 -0700222 WorkgroupSizeValueID(0), WorkgroupSizeVarID(0),
David Neto78383442018-06-15 20:31:56 -0400223 constant_i32_zero_id_(0) {}
David Neto22f144c2017-06-12 14:26:21 -0400224
225 void getAnalysisUsage(AnalysisUsage &AU) const override {
226 AU.addRequired<DominatorTreeWrapperPass>();
227 AU.addRequired<LoopInfoWrapperPass>();
228 }
229
230 virtual bool runOnModule(Module &module) override;
231
232 // output the SPIR-V header block
233 void outputHeader();
234
235 // patch the SPIR-V header block
236 void patchHeader();
237
238 uint32_t lookupType(Type *Ty) {
239 if (Ty->isPointerTy() &&
240 (Ty->getPointerAddressSpace() != AddressSpace::UniformConstant)) {
241 auto PointeeTy = Ty->getPointerElementType();
242 if (PointeeTy->isStructTy() &&
243 dyn_cast<StructType>(PointeeTy)->isOpaque()) {
244 Ty = PointeeTy;
245 }
246 }
247
248 if (0 == TypeMap.count(Ty)) {
249 Ty->print(errs());
David Netoe439d702018-03-23 13:14:08 -0700250 llvm_unreachable("\nUnhandled type!");
David Neto22f144c2017-06-12 14:26:21 -0400251 }
252
253 return TypeMap[Ty];
254 }
255 TypeMapType &getImageTypeMap() { return ImageTypeMap; }
256 TypeList &getTypeList() { return Types; };
257 ValueList &getConstantList() { return Constants; };
258 ValueMapType &getValueMap() { return ValueMap; }
259 ValueMapType &getAllocatedValueMap() { return AllocatedValueMap; }
260 SPIRVInstructionList &getSPIRVInstList() { return SPIRVInsts; };
261 ValueToValueMapTy &getArgumentGVMap() { return ArgumentGVMap; };
262 ValueMapType &getArgumentGVIDMap() { return ArgumentGVIDMap; };
263 EntryPointVecType &getEntryPointVec() { return EntryPointVec; };
264 DeferredInstVecType &getDeferredInstVec() { return DeferredInstVec; };
265 ValueList &getEntryPointInterfacesVec() { return EntryPointInterfacesVec; };
266 uint32_t &getOpExtInstImportID() { return OpExtInstImportID; };
267 std::vector<uint32_t> &getBuiltinDimVec() { return BuiltinDimensionVec; };
268 bool hasVariablePointers() { return true; /* We use StorageBuffer everywhere */ };
269 void setVariablePointers(bool Val) { HasVariablePointers = Val; };
David Neto44795152017-07-13 15:45:28 -0400270 ArrayRef<std::pair<unsigned, std::string>> &getSamplerMap() { return samplerMap; }
David Neto22f144c2017-06-12 14:26:21 -0400271 GlobalConstFuncMapType &getGlobalConstFuncTypeMap() {
272 return GlobalConstFuncTypeMap;
273 }
274 SmallPtrSet<Value *, 16> &getGlobalConstArgSet() {
275 return GlobalConstArgumentSet;
276 }
David Neto85082642018-03-24 06:55:20 -0700277 TypeList &getTypesNeedingArrayStride() {
278 return TypesNeedingArrayStride;
David Neto1a1a0582017-07-07 12:01:44 -0400279 }
David Neto22f144c2017-06-12 14:26:21 -0400280
David Netoc6f3ab22018-04-06 18:02:31 -0400281 void GenerateLLVMIRInfo(Module &M, const DataLayout &DL);
David Neto22f144c2017-06-12 14:26:21 -0400282 bool FindExtInst(Module &M);
283 void FindTypePerGlobalVar(GlobalVariable &GV);
284 void FindTypePerFunc(Function &F);
David Neto19a1bad2017-08-25 15:01:41 -0400285 // Inserts |Ty| and relevant sub-types into the |Types| member, indicating that
286 // |Ty| and its subtypes will need a corresponding SPIR-V type.
David Neto22f144c2017-06-12 14:26:21 -0400287 void FindType(Type *Ty);
288 void FindConstantPerGlobalVar(GlobalVariable &GV);
289 void FindConstantPerFunc(Function &F);
290 void FindConstant(Value *V);
291 void GenerateExtInstImport();
David Neto19a1bad2017-08-25 15:01:41 -0400292 // Generates instructions for SPIR-V types corresponding to the LLVM types
293 // saved in the |Types| member. A type follows its subtypes. IDs are
294 // allocated sequentially starting with the current value of nextID, and
295 // with a type following its subtypes. Also updates nextID to just beyond
296 // the last generated ID.
David Netoc6f3ab22018-04-06 18:02:31 -0400297 void GenerateSPIRVTypes(LLVMContext& context, const DataLayout &DL);
David Neto22f144c2017-06-12 14:26:21 -0400298 void GenerateSPIRVConstants();
David Neto5c22a252018-03-15 16:07:41 -0400299 void GenerateModuleInfo(Module &M);
David Neto22f144c2017-06-12 14:26:21 -0400300 void GenerateGlobalVar(GlobalVariable &GV);
David Netoc6f3ab22018-04-06 18:02:31 -0400301 void GenerateWorkgroupVars();
David Neto22f144c2017-06-12 14:26:21 -0400302 void GenerateSamplers(Module &M);
303 void GenerateFuncPrologue(Function &F);
304 void GenerateFuncBody(Function &F);
305 void GenerateInstForArg(Function &F);
David Netob6e2e062018-04-25 10:32:06 -0400306 void GenerateEntryPointInitialStores();
David Neto22f144c2017-06-12 14:26:21 -0400307 spv::Op GetSPIRVCmpOpcode(CmpInst *CmpI);
308 spv::Op GetSPIRVCastOpcode(Instruction &I);
309 spv::Op GetSPIRVBinaryOpcode(Instruction &I);
310 void GenerateInstruction(Instruction &I);
311 void GenerateFuncEpilogue();
312 void HandleDeferredInstruction();
David Neto1a1a0582017-07-07 12:01:44 -0400313 void HandleDeferredDecorations(const DataLayout& DL);
David Neto22f144c2017-06-12 14:26:21 -0400314 bool is4xi8vec(Type *Ty) const;
David Neto257c3892018-04-11 13:19:45 -0400315 // Return the SPIR-V Id for 32-bit constant zero. The constant must already
316 // have been created.
317 uint32_t GetI32Zero();
David Neto22f144c2017-06-12 14:26:21 -0400318 spv::StorageClass GetStorageClass(unsigned AddrSpace) const;
319 spv::BuiltIn GetBuiltin(StringRef globalVarName) const;
David Neto3fbb4072017-10-16 11:28:14 -0400320 // Returns the GLSL extended instruction enum that the given function
321 // call maps to. If none, then returns the 0 value, i.e. GLSLstd4580Bad.
David Neto22f144c2017-06-12 14:26:21 -0400322 glsl::ExtInst getExtInstEnum(StringRef Name);
David Neto3fbb4072017-10-16 11:28:14 -0400323 // Returns the GLSL extended instruction enum indirectly used by the given
324 // function. That is, to implement the given function, we use an extended
325 // instruction plus one more instruction. If none, then returns the 0 value,
326 // i.e. GLSLstd4580Bad.
327 glsl::ExtInst getIndirectExtInstEnum(StringRef Name);
328 // Returns the single GLSL extended instruction used directly or
329 // indirectly by the given function call.
330 glsl::ExtInst getDirectOrIndirectExtInstEnum(StringRef Name);
David Neto22f144c2017-06-12 14:26:21 -0400331 void PrintResID(SPIRVInstruction *Inst);
332 void PrintOpcode(SPIRVInstruction *Inst);
333 void PrintOperand(SPIRVOperand *Op);
334 void PrintCapability(SPIRVOperand *Op);
335 void PrintExtInst(SPIRVOperand *Op);
336 void PrintAddrModel(SPIRVOperand *Op);
337 void PrintMemModel(SPIRVOperand *Op);
338 void PrintExecModel(SPIRVOperand *Op);
339 void PrintExecMode(SPIRVOperand *Op);
340 void PrintSourceLanguage(SPIRVOperand *Op);
341 void PrintFuncCtrl(SPIRVOperand *Op);
342 void PrintStorageClass(SPIRVOperand *Op);
343 void PrintDecoration(SPIRVOperand *Op);
344 void PrintBuiltIn(SPIRVOperand *Op);
345 void PrintSelectionControl(SPIRVOperand *Op);
346 void PrintLoopControl(SPIRVOperand *Op);
347 void PrintDimensionality(SPIRVOperand *Op);
348 void PrintImageFormat(SPIRVOperand *Op);
349 void PrintMemoryAccess(SPIRVOperand *Op);
350 void PrintImageOperandsType(SPIRVOperand *Op);
351 void WriteSPIRVAssembly();
352 void WriteOneWord(uint32_t Word);
353 void WriteResultID(SPIRVInstruction *Inst);
354 void WriteWordCountAndOpcode(SPIRVInstruction *Inst);
355 void WriteOperand(SPIRVOperand *Op);
356 void WriteSPIRVBinary();
357
358private:
359 static char ID;
David Neto44795152017-07-13 15:45:28 -0400360 ArrayRef<std::pair<unsigned, std::string>> samplerMap;
David Neto22f144c2017-06-12 14:26:21 -0400361 raw_pwrite_stream &out;
David Neto0676e6f2017-07-11 18:47:44 -0400362
363 // TODO(dneto): Wouldn't it be better to always just emit a binary, and then
364 // convert to other formats on demand?
365
366 // When emitting a C initialization list, the WriteSPIRVBinary method
367 // will actually write its words to this vector via binaryTempOut.
368 SmallVector<char, 100> binaryTempUnderlyingVector;
369 raw_svector_ostream binaryTempOut;
370
371 // Binary output writes to this stream, which might be |out| or
372 // |binaryTempOut|. It's the latter when we really want to write a C
373 // initializer list.
374 raw_pwrite_stream* binaryOut;
David Netoc2c368d2017-06-30 16:50:17 -0400375 raw_ostream &descriptorMapOut;
David Neto22f144c2017-06-12 14:26:21 -0400376 const bool outputAsm;
David Neto0676e6f2017-07-11 18:47:44 -0400377 const bool outputCInitList; // If true, output look like {0x7023, ... , 5}
David Neto22f144c2017-06-12 14:26:21 -0400378 uint64_t patchBoundOffset;
379 uint32_t nextID;
380
David Neto19a1bad2017-08-25 15:01:41 -0400381 // Maps an LLVM Value pointer to the corresponding SPIR-V Id.
David Neto22f144c2017-06-12 14:26:21 -0400382 TypeMapType TypeMap;
David Neto19a1bad2017-08-25 15:01:41 -0400383 // Maps an LLVM image type to its SPIR-V ID.
David Neto22f144c2017-06-12 14:26:21 -0400384 TypeMapType ImageTypeMap;
David Neto19a1bad2017-08-25 15:01:41 -0400385 // A unique-vector of LLVM types that map to a SPIR-V type.
David Neto22f144c2017-06-12 14:26:21 -0400386 TypeList Types;
387 ValueList Constants;
David Neto19a1bad2017-08-25 15:01:41 -0400388 // Maps an LLVM Value pointer to the corresponding SPIR-V Id.
David Neto22f144c2017-06-12 14:26:21 -0400389 ValueMapType ValueMap;
390 ValueMapType AllocatedValueMap;
391 SPIRVInstructionList SPIRVInsts;
David Netoe439d702018-03-23 13:14:08 -0700392 // Maps a kernel argument value to a global value. OpenCL kernel arguments
393 // have to map to resources: buffers, samplers, images, or sampled images.
David Neto22f144c2017-06-12 14:26:21 -0400394 ValueToValueMapTy ArgumentGVMap;
395 ValueMapType ArgumentGVIDMap;
396 EntryPointVecType EntryPointVec;
397 DeferredInstVecType DeferredInstVec;
398 ValueList EntryPointInterfacesVec;
399 uint32_t OpExtInstImportID;
400 std::vector<uint32_t> BuiltinDimensionVec;
401 bool HasVariablePointers;
402 Type *SamplerTy;
David Netoc77d9e22018-03-24 06:30:28 -0700403
404 // If a function F has a pointer-to-__constant parameter, then this variable
David Neto9ed8e2f2018-03-24 06:47:24 -0700405 // will map F's type to (G, index of the parameter), where in a first phase
406 // G is F's type. During FindTypePerFunc, G will be changed to F's type
407 // but replacing the pointer-to-constant parameter with
408 // pointer-to-ModuleScopePrivate.
David Netoc77d9e22018-03-24 06:30:28 -0700409 // TODO(dneto): This doesn't seem general enough? A function might have
410 // more than one such parameter.
David Neto22f144c2017-06-12 14:26:21 -0400411 GlobalConstFuncMapType GlobalConstFuncTypeMap;
412 SmallPtrSet<Value *, 16> GlobalConstArgumentSet;
David Neto1a1a0582017-07-07 12:01:44 -0400413 // An ordered set of pointer types of Base arguments to OpPtrAccessChain,
David Neto85082642018-03-24 06:55:20 -0700414 // or array types, and which point into transparent memory (StorageBuffer
415 // storage class). These will require an ArrayStride decoration.
David Neto1a1a0582017-07-07 12:01:44 -0400416 // See SPV_KHR_variable_pointers rev 13.
David Neto85082642018-03-24 06:55:20 -0700417 TypeList TypesNeedingArrayStride;
David Netoa60b00b2017-09-15 16:34:09 -0400418
419 // This is truly ugly, but works around what look like driver bugs.
420 // For get_local_size, an earlier part of the flow has created a module-scope
421 // variable in Private address space to hold the value for the workgroup
422 // size. Its intializer is a uint3 value marked as builtin WorkgroupSize.
423 // When this is present, save the IDs of the initializer value and variable
424 // in these two variables. We only ever do a vector load from it, and
425 // when we see one of those, substitute just the value of the intializer.
426 // This mimics what Glslang does, and that's what drivers are used to.
David Neto66cfe642018-03-24 06:13:56 -0700427 // TODO(dneto): Remove this once drivers are fixed.
David Netoa60b00b2017-09-15 16:34:09 -0400428 uint32_t WorkgroupSizeValueID;
429 uint32_t WorkgroupSizeVarID;
David Neto26aaf622017-10-23 18:11:53 -0400430
431 // What module-scope variables already have had their binding information
432 // emitted?
433 DenseSet<Value*> GVarWithEmittedBindingInfo;
David Neto85082642018-03-24 06:55:20 -0700434
David Netoc6f3ab22018-04-06 18:02:31 -0400435 // An ordered list of the kernel arguments of type pointer-to-local.
436 using LocalArgList = SmallVector<const Argument*, 8>;
437 LocalArgList LocalArgs;
438 // Information about a pointer-to-local argument.
439 struct LocalArgInfo {
440 // The SPIR-V ID of the array variable.
441 uint32_t variable_id;
442 // The element type of the
443 Type* elem_type;
444 // The ID of the array type.
445 uint32_t array_size_id;
446 // The ID of the array type.
447 uint32_t array_type_id;
448 // The ID of the pointer to the array type.
449 uint32_t ptr_array_type_id;
450 // The ID of the pointer to the first element of the array.
451 uint32_t first_elem_ptr_id;
452 // The specialization constant ID of the array size.
453 int spec_id;
454 };
455 // A mapping from a pointer-to-local argument value to a LocalArgInfo value.
456 DenseMap<const Argument*, LocalArgInfo> LocalArgMap;
457
David Netoc6f3ab22018-04-06 18:02:31 -0400458 // A mapping from pointer-to-local argument to a specialization constant ID
459 // for that argument's array size. This is generated from AllocatArgSpecIds.
460 ArgIdMapType ArgSpecIdMap;
David Neto257c3892018-04-11 13:19:45 -0400461
462 // The ID of 32-bit integer zero constant. This is only valid after
463 // GenerateSPIRVConstants has run.
464 uint32_t constant_i32_zero_id_;
David Neto22f144c2017-06-12 14:26:21 -0400465};
466
467char SPIRVProducerPass::ID;
David Netoc6f3ab22018-04-06 18:02:31 -0400468
David Neto22f144c2017-06-12 14:26:21 -0400469}
470
471namespace clspv {
David Neto44795152017-07-13 15:45:28 -0400472ModulePass *
473createSPIRVProducerPass(raw_pwrite_stream &out, raw_ostream &descriptor_map_out,
474 ArrayRef<std::pair<unsigned, std::string>> samplerMap,
475 bool outputAsm, bool outputCInitList) {
476 return new SPIRVProducerPass(out, descriptor_map_out, samplerMap, outputAsm,
477 outputCInitList);
David Neto22f144c2017-06-12 14:26:21 -0400478}
David Netoc2c368d2017-06-30 16:50:17 -0400479} // namespace clspv
David Neto22f144c2017-06-12 14:26:21 -0400480
481bool SPIRVProducerPass::runOnModule(Module &module) {
David Neto0676e6f2017-07-11 18:47:44 -0400482 binaryOut = outputCInitList ? &binaryTempOut : &out;
483
David Neto257c3892018-04-11 13:19:45 -0400484 constant_i32_zero_id_ = 0; // Reset, for the benefit of validity checks.
485
David Netoc6f3ab22018-04-06 18:02:31 -0400486 ArgSpecIdMap = AllocateArgSpecIds(module);
487
David Neto22f144c2017-06-12 14:26:21 -0400488 // SPIR-V always begins with its header information
489 outputHeader();
490
David Netoc6f3ab22018-04-06 18:02:31 -0400491 const DataLayout &DL = module.getDataLayout();
492
David Neto22f144c2017-06-12 14:26:21 -0400493 // Gather information from the LLVM IR that we require.
David Netoc6f3ab22018-04-06 18:02:31 -0400494 GenerateLLVMIRInfo(module, DL);
David Neto22f144c2017-06-12 14:26:21 -0400495
496 // If we are using a sampler map, find the type of the sampler.
497 if (0 < getSamplerMap().size()) {
498 auto SamplerStructTy = module.getTypeByName("opencl.sampler_t");
499 if (!SamplerStructTy) {
500 SamplerStructTy =
501 StructType::create(module.getContext(), "opencl.sampler_t");
502 }
503
504 SamplerTy = SamplerStructTy->getPointerTo(AddressSpace::UniformConstant);
505
506 FindType(SamplerTy);
507 }
508
509 // Collect information on global variables too.
510 for (GlobalVariable &GV : module.globals()) {
511 // If the GV is one of our special __spirv_* variables, remove the
512 // initializer as it was only placed there to force LLVM to not throw the
513 // value away.
514 if (GV.getName().startswith("__spirv_")) {
515 GV.setInitializer(nullptr);
516 }
517
518 // Collect types' information from global variable.
519 FindTypePerGlobalVar(GV);
520
521 // Collect constant information from global variable.
522 FindConstantPerGlobalVar(GV);
523
524 // If the variable is an input, entry points need to know about it.
525 if (AddressSpace::Input == GV.getType()->getPointerAddressSpace()) {
David Netofb9a7972017-08-25 17:08:24 -0400526 getEntryPointInterfacesVec().insert(&GV);
David Neto22f144c2017-06-12 14:26:21 -0400527 }
528 }
529
David Netoc6f3ab22018-04-06 18:02:31 -0400530 // Find types related to pointer-to-local arguments.
531 for (auto& arg_spec_id_pair : ArgSpecIdMap) {
532 const Argument* arg = arg_spec_id_pair.first;
533 FindType(arg->getType());
534 FindType(arg->getType()->getPointerElementType());
535 }
536
David Neto22f144c2017-06-12 14:26:21 -0400537 // If there are extended instructions, generate OpExtInstImport.
538 if (FindExtInst(module)) {
539 GenerateExtInstImport();
540 }
541
542 // Generate SPIRV instructions for types.
David Netoc6f3ab22018-04-06 18:02:31 -0400543 GenerateSPIRVTypes(module.getContext(), DL);
David Neto22f144c2017-06-12 14:26:21 -0400544
545 // Generate SPIRV constants.
546 GenerateSPIRVConstants();
547
548 // If we have a sampler map, we might have literal samplers to generate.
549 if (0 < getSamplerMap().size()) {
550 GenerateSamplers(module);
551 }
552
553 // Generate SPIRV variables.
554 for (GlobalVariable &GV : module.globals()) {
555 GenerateGlobalVar(GV);
556 }
David Netoc6f3ab22018-04-06 18:02:31 -0400557 GenerateWorkgroupVars();
David Neto22f144c2017-06-12 14:26:21 -0400558
559 // Generate SPIRV instructions for each function.
560 for (Function &F : module) {
561 if (F.isDeclaration()) {
562 continue;
563 }
564
565 // Generate Function Prologue.
566 GenerateFuncPrologue(F);
567
568 // Generate SPIRV instructions for function body.
569 GenerateFuncBody(F);
570
571 // Generate Function Epilogue.
572 GenerateFuncEpilogue();
573 }
574
575 HandleDeferredInstruction();
David Neto1a1a0582017-07-07 12:01:44 -0400576 HandleDeferredDecorations(DL);
David Neto22f144c2017-06-12 14:26:21 -0400577
578 // Generate SPIRV module information.
David Neto5c22a252018-03-15 16:07:41 -0400579 GenerateModuleInfo(module);
David Neto22f144c2017-06-12 14:26:21 -0400580
581 if (outputAsm) {
582 WriteSPIRVAssembly();
583 } else {
584 WriteSPIRVBinary();
585 }
586
587 // We need to patch the SPIR-V header to set bound correctly.
588 patchHeader();
David Neto0676e6f2017-07-11 18:47:44 -0400589
590 if (outputCInitList) {
591 bool first = true;
David Neto0676e6f2017-07-11 18:47:44 -0400592 std::ostringstream os;
593
David Neto57fb0b92017-08-04 15:35:09 -0400594 auto emit_word = [&os, &first](uint32_t word) {
David Neto0676e6f2017-07-11 18:47:44 -0400595 if (!first)
David Neto57fb0b92017-08-04 15:35:09 -0400596 os << ",\n";
597 os << word;
David Neto0676e6f2017-07-11 18:47:44 -0400598 first = false;
599 };
600
601 os << "{";
David Neto57fb0b92017-08-04 15:35:09 -0400602 const std::string str(binaryTempOut.str());
603 for (unsigned i = 0; i < str.size(); i += 4) {
604 const uint32_t a = static_cast<unsigned char>(str[i]);
605 const uint32_t b = static_cast<unsigned char>(str[i + 1]);
606 const uint32_t c = static_cast<unsigned char>(str[i + 2]);
607 const uint32_t d = static_cast<unsigned char>(str[i + 3]);
608 emit_word(a | (b << 8) | (c << 16) | (d << 24));
David Neto0676e6f2017-07-11 18:47:44 -0400609 }
610 os << "}\n";
611 out << os.str();
612 }
613
David Neto22f144c2017-06-12 14:26:21 -0400614 return false;
615}
616
617void SPIRVProducerPass::outputHeader() {
618 if (outputAsm) {
619 // for ASM output the header goes into 5 comments at the beginning of the
620 // file
621 out << "; SPIR-V\n";
622
623 // the major version number is in the 2nd highest byte
624 const uint32_t major = (spv::Version >> 16) & 0xFF;
625
626 // the minor version number is in the 2nd lowest byte
627 const uint32_t minor = (spv::Version >> 8) & 0xFF;
628 out << "; Version: " << major << "." << minor << "\n";
629
630 // use Codeplay's vendor ID
631 out << "; Generator: Codeplay; 0\n";
632
633 out << "; Bound: ";
634
635 // we record where we need to come back to and patch in the bound value
636 patchBoundOffset = out.tell();
637
638 // output one space per digit for the max size of a 32 bit unsigned integer
639 // (which is the maximum ID we could possibly be using)
640 for (uint32_t i = std::numeric_limits<uint32_t>::max(); 0 != i; i /= 10) {
641 out << " ";
642 }
643
644 out << "\n";
645
646 out << "; Schema: 0\n";
647 } else {
David Neto0676e6f2017-07-11 18:47:44 -0400648 binaryOut->write(reinterpret_cast<const char *>(&spv::MagicNumber),
David Neto22f144c2017-06-12 14:26:21 -0400649 sizeof(spv::MagicNumber));
David Neto0676e6f2017-07-11 18:47:44 -0400650 binaryOut->write(reinterpret_cast<const char *>(&spv::Version),
David Neto22f144c2017-06-12 14:26:21 -0400651 sizeof(spv::Version));
652
653 // use Codeplay's vendor ID
654 const uint32_t vendor = 3 << 16;
David Neto0676e6f2017-07-11 18:47:44 -0400655 binaryOut->write(reinterpret_cast<const char *>(&vendor), sizeof(vendor));
David Neto22f144c2017-06-12 14:26:21 -0400656
657 // we record where we need to come back to and patch in the bound value
David Neto0676e6f2017-07-11 18:47:44 -0400658 patchBoundOffset = binaryOut->tell();
David Neto22f144c2017-06-12 14:26:21 -0400659
660 // output a bad bound for now
David Neto0676e6f2017-07-11 18:47:44 -0400661 binaryOut->write(reinterpret_cast<const char *>(&nextID), sizeof(nextID));
David Neto22f144c2017-06-12 14:26:21 -0400662
663 // output the schema (reserved for use and must be 0)
664 const uint32_t schema = 0;
David Neto0676e6f2017-07-11 18:47:44 -0400665 binaryOut->write(reinterpret_cast<const char *>(&schema), sizeof(schema));
David Neto22f144c2017-06-12 14:26:21 -0400666 }
667}
668
669void SPIRVProducerPass::patchHeader() {
670 if (outputAsm) {
671 // get the string representation of the max bound used (nextID will be the
672 // max ID used)
673 auto asString = std::to_string(nextID);
674 out.pwrite(asString.c_str(), asString.size(), patchBoundOffset);
675 } else {
676 // for a binary we just write the value of nextID over bound
David Neto0676e6f2017-07-11 18:47:44 -0400677 binaryOut->pwrite(reinterpret_cast<char *>(&nextID), sizeof(nextID),
678 patchBoundOffset);
David Neto22f144c2017-06-12 14:26:21 -0400679 }
680}
681
David Netoc6f3ab22018-04-06 18:02:31 -0400682void SPIRVProducerPass::GenerateLLVMIRInfo(Module &M, const DataLayout &DL) {
David Neto22f144c2017-06-12 14:26:21 -0400683 // This function generates LLVM IR for function such as global variable for
684 // argument, constant and pointer type for argument access. These information
685 // is artificial one because we need Vulkan SPIR-V output. This function is
686 // executed ahead of FindType and FindConstant.
687 ValueToValueMapTy &ArgGVMap = getArgumentGVMap();
688 LLVMContext &Context = M.getContext();
689
690 // Map for avoiding to generate struct type with same fields.
691 DenseMap<Type *, Type *> ArgTyMap;
692
David Neto5c22a252018-03-15 16:07:41 -0400693 // These function calls need a <2 x i32> as an intermediate result but not
694 // the final result.
695 std::unordered_set<std::string> NeedsIVec2{
696 "_Z15get_image_width14ocl_image2d_ro",
697 "_Z15get_image_width14ocl_image2d_wo",
698 "_Z16get_image_height14ocl_image2d_ro",
699 "_Z16get_image_height14ocl_image2d_wo",
700 };
701
David Neto22f144c2017-06-12 14:26:21 -0400702 // Collect global constant variables.
David Netoc6f3ab22018-04-06 18:02:31 -0400703 {
704 SmallVector<GlobalVariable *, 8> GVList;
705 SmallVector<GlobalVariable *, 8> DeadGVList;
706 for (GlobalVariable &GV : M.globals()) {
707 if (GV.getType()->getAddressSpace() == AddressSpace::Constant) {
708 if (GV.use_empty()) {
709 DeadGVList.push_back(&GV);
710 } else {
711 GVList.push_back(&GV);
712 }
David Netofba9d262018-03-24 06:14:18 -0700713 }
David Neto22f144c2017-06-12 14:26:21 -0400714 }
David Neto22f144c2017-06-12 14:26:21 -0400715
David Netoc6f3ab22018-04-06 18:02:31 -0400716 // Remove dead global __constant variables.
717 for (auto GV : DeadGVList) {
718 GV->eraseFromParent();
David Neto85082642018-03-24 06:55:20 -0700719 }
David Netoc6f3ab22018-04-06 18:02:31 -0400720 DeadGVList.clear();
David Neto22f144c2017-06-12 14:26:21 -0400721
David Netoc6f3ab22018-04-06 18:02:31 -0400722 if (clspv::Option::ModuleConstantsInStorageBuffer()) {
723 // For now, we only support a single storage buffer.
724 if (GVList.size() > 0) {
725 assert(GVList.size() == 1);
726 const auto *GV = GVList[0];
David Netoee2660d2018-06-28 16:31:29 -0400727 const auto constants_byte_size =
David Netoc6f3ab22018-04-06 18:02:31 -0400728 (DL.getTypeSizeInBits(GV->getInitializer()->getType())) / 8;
729 const size_t kConstantMaxSize = 65536;
730 if (constants_byte_size > kConstantMaxSize) {
731 outs() << "Max __constant capacity of " << kConstantMaxSize
732 << " bytes exceeded: " << constants_byte_size
733 << " bytes used\n";
734 llvm_unreachable("Max __constant capacity exceeded");
735 }
736 }
737 } else {
738 // Change global constant variable's address space to ModuleScopePrivate.
739 auto &GlobalConstFuncTyMap = getGlobalConstFuncTypeMap();
740 for (auto GV : GVList) {
741 // Create new gv with ModuleScopePrivate address space.
742 Type *NewGVTy = GV->getType()->getPointerElementType();
743 GlobalVariable *NewGV = new GlobalVariable(
744 M, NewGVTy, false, GV->getLinkage(), GV->getInitializer(), "",
745 nullptr, GV->getThreadLocalMode(),
746 AddressSpace::ModuleScopePrivate);
747 NewGV->takeName(GV);
David Neto22f144c2017-06-12 14:26:21 -0400748
David Netoc6f3ab22018-04-06 18:02:31 -0400749 const SmallVector<User *, 8> GVUsers(GV->user_begin(), GV->user_end());
750 SmallVector<User *, 8> CandidateUsers;
751
752 auto record_called_function_type_as_user =
753 [&GlobalConstFuncTyMap](Value *gv, CallInst *call) {
754 // Find argument index.
755 unsigned index = 0;
756 for (unsigned i = 0; i < call->getNumArgOperands(); i++) {
757 if (gv == call->getOperand(i)) {
758 // TODO(dneto): Should we break here?
759 index = i;
760 }
761 }
762
763 // Record function type with global constant.
764 GlobalConstFuncTyMap[call->getFunctionType()] =
765 std::make_pair(call->getFunctionType(), index);
766 };
767
768 for (User *GVU : GVUsers) {
769 if (CallInst *Call = dyn_cast<CallInst>(GVU)) {
770 record_called_function_type_as_user(GV, Call);
771 } else if (GetElementPtrInst *GEP =
772 dyn_cast<GetElementPtrInst>(GVU)) {
773 // Check GEP users.
774 for (User *GEPU : GEP->users()) {
775 if (CallInst *GEPCall = dyn_cast<CallInst>(GEPU)) {
776 record_called_function_type_as_user(GEP, GEPCall);
David Neto85082642018-03-24 06:55:20 -0700777 }
778 }
David Netoc77d9e22018-03-24 06:30:28 -0700779 }
David Netoc6f3ab22018-04-06 18:02:31 -0400780
781 CandidateUsers.push_back(GVU);
David Neto22f144c2017-06-12 14:26:21 -0400782 }
David Neto85082642018-03-24 06:55:20 -0700783
David Netoc6f3ab22018-04-06 18:02:31 -0400784 for (User *U : CandidateUsers) {
785 // Update users of gv with new gv.
786 U->replaceUsesOfWith(GV, NewGV);
787 }
David Neto22f144c2017-06-12 14:26:21 -0400788
David Netoc6f3ab22018-04-06 18:02:31 -0400789 // Delete original gv.
790 GV->eraseFromParent();
David Neto85082642018-03-24 06:55:20 -0700791 }
David Neto22f144c2017-06-12 14:26:21 -0400792 }
David Neto22f144c2017-06-12 14:26:21 -0400793 }
794
795 bool HasWorkGroupBuiltin = false;
796 for (GlobalVariable &GV : M.globals()) {
797 const spv::BuiltIn BuiltinType = GetBuiltin(GV.getName());
798 if (spv::BuiltInWorkgroupSize == BuiltinType) {
799 HasWorkGroupBuiltin = true;
800 }
801 }
802
803
David Neto26aaf622017-10-23 18:11:53 -0400804 // Map kernel functions to their ordinal number in the compilation unit.
805 UniqueVector<Function*> KernelOrdinal;
806
807 // Map the global variables created for kernel args to their creation
808 // order.
809 UniqueVector<GlobalVariable*> KernelArgVarOrdinal;
810
David Netoc6f3ab22018-04-06 18:02:31 -0400811 // For each kernel argument type, record the kernel arg global resource variables
David Neto26aaf622017-10-23 18:11:53 -0400812 // generated for that type, the function in which that variable was most
813 // recently used, and the binding number it took. For reproducibility,
814 // we track things by ordinal number (rather than pointer), and we use a
815 // std::set rather than DenseSet since std::set maintains an ordering.
816 // Each tuple is the ordinals of the kernel function, the binding number,
817 // and the ordinal of the kernal-arg-var.
818 //
819 // This table lets us reuse module-scope StorageBuffer variables between
820 // different kernels.
821 DenseMap<Type *, std::set<std::tuple<unsigned, unsigned, unsigned>>>
822 GVarsForType;
823
David Neto22f144c2017-06-12 14:26:21 -0400824 for (Function &F : M) {
825 // Handle kernel function first.
826 if (F.isDeclaration() || F.getCallingConv() != CallingConv::SPIR_KERNEL) {
827 continue;
828 }
David Neto26aaf622017-10-23 18:11:53 -0400829 KernelOrdinal.insert(&F);
David Neto22f144c2017-06-12 14:26:21 -0400830
831 for (BasicBlock &BB : F) {
832 for (Instruction &I : BB) {
833 if (I.getOpcode() == Instruction::ZExt ||
834 I.getOpcode() == Instruction::SExt ||
835 I.getOpcode() == Instruction::UIToFP) {
836 // If there is zext with i1 type, it will be changed to OpSelect. The
837 // OpSelect needs constant 0 and 1 so the constants are added here.
838
839 auto OpTy = I.getOperand(0)->getType();
840
841 if (OpTy->isIntegerTy(1) ||
842 (OpTy->isVectorTy() &&
843 OpTy->getVectorElementType()->isIntegerTy(1))) {
844 if (I.getOpcode() == Instruction::ZExt) {
845 APInt One(32, 1);
846 FindConstant(Constant::getNullValue(I.getType()));
847 FindConstant(Constant::getIntegerValue(I.getType(), One));
848 } else if (I.getOpcode() == Instruction::SExt) {
849 APInt MinusOne(32, UINT64_MAX, true);
850 FindConstant(Constant::getNullValue(I.getType()));
851 FindConstant(Constant::getIntegerValue(I.getType(), MinusOne));
852 } else {
853 FindConstant(ConstantFP::get(Context, APFloat(0.0f)));
854 FindConstant(ConstantFP::get(Context, APFloat(1.0f)));
855 }
856 }
857 } else if (CallInst *Call = dyn_cast<CallInst>(&I)) {
858 Function *Callee = Call->getCalledFunction();
859
860 // Handle image type specially.
861 if (Callee->getName().equals(
862 "_Z11read_imagef14ocl_image2d_ro11ocl_samplerDv2_f") ||
863 Callee->getName().equals(
864 "_Z11read_imagef14ocl_image3d_ro11ocl_samplerDv4_f")) {
865 TypeMapType &OpImageTypeMap = getImageTypeMap();
866 Type *ImageTy =
867 Call->getArgOperand(0)->getType()->getPointerElementType();
868 OpImageTypeMap[ImageTy] = 0;
869
870 FindConstant(ConstantFP::get(Context, APFloat(0.0f)));
871 }
David Neto5c22a252018-03-15 16:07:41 -0400872
873 if (NeedsIVec2.find(Callee->getName()) != NeedsIVec2.end()) {
874 FindType(VectorType::get(Type::getInt32Ty(Context), 2));
875 }
David Neto22f144c2017-06-12 14:26:21 -0400876 }
877 }
878 }
879
880 if (M.getTypeByName("opencl.image2d_ro_t") ||
881 M.getTypeByName("opencl.image2d_wo_t") ||
882 M.getTypeByName("opencl.image3d_ro_t") ||
883 M.getTypeByName("opencl.image3d_wo_t")) {
884 // Assume Image type's sampled type is float type.
885 FindType(Type::getFloatTy(Context));
886 }
887
888 if (const MDNode *MD =
889 dyn_cast<Function>(&F)->getMetadata("reqd_work_group_size")) {
890 // We generate constants if the WorkgroupSize builtin is being used.
891 if (HasWorkGroupBuiltin) {
892 // Collect constant information for work group size.
893 FindConstant(mdconst::extract<ConstantInt>(MD->getOperand(0)));
894 FindConstant(mdconst::extract<ConstantInt>(MD->getOperand(1)));
895 FindConstant(mdconst::extract<ConstantInt>(MD->getOperand(2)));
896 }
897 }
898
899 // Wrap up all argument types with struct type and create global variables
900 // with them.
901 bool HasArgUser = false;
902 unsigned Idx = 0;
903
904 for (const Argument &Arg : F.args()) {
905 Type *ArgTy = Arg.getType();
David Neto22f144c2017-06-12 14:26:21 -0400906
David Netoe439d702018-03-23 13:14:08 -0700907 // The pointee type of the module scope variable we will make.
908 Type *GVTy = nullptr;
David Neto22f144c2017-06-12 14:26:21 -0400909
910 Type *TmpArgTy = ArgTy;
911
912 // sampler_t and image types have pointer type of struct type with
David Netoe439d702018-03-23 13:14:08 -0700913 // opaque type as field. Extract the struct type. It will be used by
914 // global variable for argument.
David Neto22f144c2017-06-12 14:26:21 -0400915 bool IsSamplerType = false;
916 bool IsImageType = false;
917 if (PointerType *TmpArgPTy = dyn_cast<PointerType>(TmpArgTy)) {
918 if (StructType *STy =
919 dyn_cast<StructType>(TmpArgPTy->getElementType())) {
920 if (STy->isOpaque()) {
921 if (STy->getName().equals("opencl.sampler_t")) {
David Neto22f144c2017-06-12 14:26:21 -0400922 IsSamplerType = true;
923 TmpArgTy = STy;
924 } else if (STy->getName().equals("opencl.image2d_ro_t") ||
925 STy->getName().equals("opencl.image2d_wo_t") ||
926 STy->getName().equals("opencl.image3d_ro_t") ||
927 STy->getName().equals("opencl.image3d_wo_t")) {
David Neto22f144c2017-06-12 14:26:21 -0400928 IsImageType = true;
929 TmpArgTy = STy;
930 } else {
931 llvm_unreachable("Argument has opaque type unsupported???");
932 }
933 }
934 }
935 }
David Netoc6f3ab22018-04-06 18:02:31 -0400936 const bool IsPointerToLocal = IsLocalPtr(ArgTy);
937 // Can't both be pointer-to-local and (sampler or image).
938 assert(!((IsSamplerType || IsImageType) && IsPointerToLocal));
David Neto22f144c2017-06-12 14:26:21 -0400939
David Netoe439d702018-03-23 13:14:08 -0700940 // Determine the address space for the module-scope variable.
941 unsigned AddrSpace = AddressSpace::Global;
942 if (IsSamplerType || IsImageType) {
943 AddrSpace = AddressSpace::UniformConstant;
944 } else if (PointerType *ArgPTy = dyn_cast<PointerType>(ArgTy)) {
945 AddrSpace = ArgPTy->getAddressSpace();
David Neto482550a2018-03-24 05:21:07 -0700946 } else if (clspv::Option::PodArgsInUniformBuffer()) {
David Netoe439d702018-03-23 13:14:08 -0700947 // Use a uniform buffer for POD arguments.
948 AddrSpace = AddressSpace::Uniform;
949 }
950
David Neto22f144c2017-06-12 14:26:21 -0400951 // LLVM's pointer type is distinguished by address space but we need to
952 // regard constant and global address space as same here. If pointer
953 // type has constant address space, generate new pointer type
954 // temporarily to check previous struct type for argument.
955 if (PointerType *TmpArgPTy = dyn_cast<PointerType>(TmpArgTy)) {
David Netoe439d702018-03-23 13:14:08 -0700956 if (TmpArgPTy->getAddressSpace() == AddressSpace::Constant) {
David Neto22f144c2017-06-12 14:26:21 -0400957 TmpArgTy = PointerType::get(TmpArgPTy->getElementType(),
958 AddressSpace::Global);
959 }
960 }
961
962 if (IsSamplerType || IsImageType) {
963 GVTy = TmpArgTy;
David Netoc6f3ab22018-04-06 18:02:31 -0400964 } else if (IsPointerToLocal) {
965 assert(ArgTy == TmpArgTy);
966 auto spec_id = ArgSpecIdMap[&Arg];
967 assert(spec_id > 0);
968 LocalArgMap[&Arg] =
969 LocalArgInfo{nextID, ArgTy->getPointerElementType(),
970 nextID + 1, nextID + 2,
971 nextID + 3, nextID + 4,
972 spec_id};
973 LocalArgs.push_back(&Arg);
974 nextID += 5;
David Neto22f144c2017-06-12 14:26:21 -0400975 } else if (ArgTyMap.count(TmpArgTy)) {
976 // If there are arguments handled previously, use its type.
977 GVTy = ArgTyMap[TmpArgTy];
978 } else {
979 // Wrap up argument type with struct type.
David Neto83add0a2017-10-23 15:30:59 -0400980 // Reuse struct types where possible.
David Neto7b2abea2017-10-23 20:02:02 -0400981 SmallVector<Type*,1> members{ArgTy};
David Neto83add0a2017-10-23 15:30:59 -0400982 StructType *STy = StructType::get(Context, members);
David Neto22f144c2017-06-12 14:26:21 -0400983
984 GVTy = STy;
985 ArgTyMap[TmpArgTy] = STy;
986 }
987
David Netoc6f3ab22018-04-06 18:02:31 -0400988 if (!IsPointerToLocal) {
989 // In order to build type map between llvm type and spirv id, LLVM
990 // global variable is needed. It has llvm type and other instructions
991 // can access it with its type.
992 //
993 // Reuse a global variable if it was created for a different entry
994 // point.
David Neto26aaf622017-10-23 18:11:53 -0400995
David Netoc6f3ab22018-04-06 18:02:31 -0400996 // Returns a new global variable for this kernel argument, and remembers
997 // it in KernelArgVarOrdinal.
998 auto make_gvar = [&]() {
999 auto result = new GlobalVariable(
1000 M, GVTy, false, GlobalValue::ExternalLinkage,
1001 UndefValue::get(GVTy),
1002 F.getName() + ".arg." + std::to_string(Idx), nullptr,
1003 GlobalValue::ThreadLocalMode::NotThreadLocal, AddrSpace);
1004 KernelArgVarOrdinal.insert(result);
1005 return result;
1006 };
David Neto26aaf622017-10-23 18:11:53 -04001007
David Netoc6f3ab22018-04-06 18:02:31 -04001008 // Make a new variable if there was none for this type, or if we can
1009 // reuse one created for a different function but not yet reused for
1010 // the current function, *and* the binding is the same.
1011 // Always make a new variable if we're forcing distinct descriptor sets.
1012 GlobalVariable *GV = nullptr;
1013 auto which_set = GVarsForType.find(GVTy);
1014 if (IsSamplerType || IsImageType || which_set == GVarsForType.end() ||
1015 clspv::Option::DistinctKernelDescriptorSets()) {
1016 GV = make_gvar();
1017 } else {
1018 auto &set = which_set->second;
1019 // Reuse a variable if it was associated with a different function.
1020 for (auto iter = set.begin(), end = set.end(); iter != end; ++iter) {
1021 const unsigned fn_ordinal = std::get<0>(*iter);
1022 const unsigned binding = std::get<1>(*iter);
1023 if (fn_ordinal != KernelOrdinal.idFor(&F) && binding == Idx) {
1024 GV = KernelArgVarOrdinal[std::get<2>(*iter)];
1025 // Remove it from the set. We'll add it back later.
1026 set.erase(iter);
1027 break;
1028 }
1029 }
1030 if (!GV) {
1031 GV = make_gvar();
David Neto26aaf622017-10-23 18:11:53 -04001032 }
1033 }
David Netoc6f3ab22018-04-06 18:02:31 -04001034 assert(GV);
1035 GVarsForType[GVTy].insert(std::make_tuple(
1036 KernelOrdinal.idFor(&F), Idx, KernelArgVarOrdinal.idFor(GV)));
1037
1038 // Generate type info for argument global variable.
1039 FindType(GV->getType());
1040
1041 ArgGVMap[&Arg] = GV;
1042
1043 Idx++;
David Neto26aaf622017-10-23 18:11:53 -04001044 }
David Neto22f144c2017-06-12 14:26:21 -04001045
1046 // Generate pointer type of argument type for OpAccessChain of argument.
1047 if (!Arg.use_empty()) {
1048 if (!isa<PointerType>(ArgTy)) {
David Netoe439d702018-03-23 13:14:08 -07001049 auto ty = PointerType::get(ArgTy, AddrSpace);
1050 FindType(ty);
David Neto22f144c2017-06-12 14:26:21 -04001051 }
1052 HasArgUser = true;
1053 }
1054 }
1055
1056 if (HasArgUser) {
1057 // Generate constant 0 for OpAccessChain of argument.
1058 Type *IdxTy = Type::getInt32Ty(Context);
1059 FindConstant(ConstantInt::get(IdxTy, 0));
1060 FindType(IdxTy);
1061 }
1062
1063 // Collect types' information from function.
1064 FindTypePerFunc(F);
1065
1066 // Collect constant information from function.
1067 FindConstantPerFunc(F);
1068 }
1069
1070 for (Function &F : M) {
1071 // Handle non-kernel functions.
1072 if (F.isDeclaration() || F.getCallingConv() == CallingConv::SPIR_KERNEL) {
1073 continue;
1074 }
1075
1076 for (BasicBlock &BB : F) {
1077 for (Instruction &I : BB) {
1078 if (I.getOpcode() == Instruction::ZExt ||
1079 I.getOpcode() == Instruction::SExt ||
1080 I.getOpcode() == Instruction::UIToFP) {
1081 // If there is zext with i1 type, it will be changed to OpSelect. The
1082 // OpSelect needs constant 0 and 1 so the constants are added here.
1083
1084 auto OpTy = I.getOperand(0)->getType();
1085
1086 if (OpTy->isIntegerTy(1) ||
1087 (OpTy->isVectorTy() &&
1088 OpTy->getVectorElementType()->isIntegerTy(1))) {
1089 if (I.getOpcode() == Instruction::ZExt) {
1090 APInt One(32, 1);
1091 FindConstant(Constant::getNullValue(I.getType()));
1092 FindConstant(Constant::getIntegerValue(I.getType(), One));
1093 } else if (I.getOpcode() == Instruction::SExt) {
1094 APInt MinusOne(32, UINT64_MAX, true);
1095 FindConstant(Constant::getNullValue(I.getType()));
1096 FindConstant(Constant::getIntegerValue(I.getType(), MinusOne));
1097 } else {
1098 FindConstant(ConstantFP::get(Context, APFloat(0.0f)));
1099 FindConstant(ConstantFP::get(Context, APFloat(1.0f)));
1100 }
1101 }
1102 } else if (CallInst *Call = dyn_cast<CallInst>(&I)) {
1103 Function *Callee = Call->getCalledFunction();
1104
1105 // Handle image type specially.
1106 if (Callee->getName().equals(
1107 "_Z11read_imagef14ocl_image2d_ro11ocl_samplerDv2_f") ||
1108 Callee->getName().equals(
1109 "_Z11read_imagef14ocl_image3d_ro11ocl_samplerDv4_f")) {
1110 TypeMapType &OpImageTypeMap = getImageTypeMap();
1111 Type *ImageTy =
1112 Call->getArgOperand(0)->getType()->getPointerElementType();
1113 OpImageTypeMap[ImageTy] = 0;
1114
1115 FindConstant(ConstantFP::get(Context, APFloat(0.0f)));
1116 }
1117 }
1118 }
1119 }
1120
1121 if (M.getTypeByName("opencl.image2d_ro_t") ||
1122 M.getTypeByName("opencl.image2d_wo_t") ||
1123 M.getTypeByName("opencl.image3d_ro_t") ||
1124 M.getTypeByName("opencl.image3d_wo_t")) {
1125 // Assume Image type's sampled type is float type.
1126 FindType(Type::getFloatTy(Context));
1127 }
1128
1129 // Collect types' information from function.
1130 FindTypePerFunc(F);
1131
1132 // Collect constant information from function.
1133 FindConstantPerFunc(F);
1134 }
1135}
1136
1137bool SPIRVProducerPass::FindExtInst(Module &M) {
1138 LLVMContext &Context = M.getContext();
1139 bool HasExtInst = false;
1140
1141 for (Function &F : M) {
1142 for (BasicBlock &BB : F) {
1143 for (Instruction &I : BB) {
1144 if (CallInst *Call = dyn_cast<CallInst>(&I)) {
1145 Function *Callee = Call->getCalledFunction();
1146 // Check whether this call is for extend instructions.
David Neto3fbb4072017-10-16 11:28:14 -04001147 auto callee_name = Callee->getName();
1148 const glsl::ExtInst EInst = getExtInstEnum(callee_name);
1149 const glsl::ExtInst IndirectEInst =
1150 getIndirectExtInstEnum(callee_name);
David Neto22f144c2017-06-12 14:26:21 -04001151
David Neto3fbb4072017-10-16 11:28:14 -04001152 HasExtInst |=
1153 (EInst != kGlslExtInstBad) || (IndirectEInst != kGlslExtInstBad);
1154
1155 if (IndirectEInst) {
1156 // Register extra constants if needed.
1157
1158 // Registers a type and constant for computing the result of the
1159 // given instruction. If the result of the instruction is a vector,
1160 // then make a splat vector constant with the same number of
1161 // elements.
1162 auto register_constant = [this, &I](Constant *constant) {
1163 FindType(constant->getType());
1164 FindConstant(constant);
1165 if (auto *vectorTy = dyn_cast<VectorType>(I.getType())) {
1166 // Register the splat vector of the value with the same
1167 // width as the result of the instruction.
1168 auto *vec_constant = ConstantVector::getSplat(
1169 static_cast<unsigned>(vectorTy->getNumElements()),
1170 constant);
1171 FindConstant(vec_constant);
1172 FindType(vec_constant->getType());
1173 }
1174 };
1175 switch (IndirectEInst) {
1176 case glsl::ExtInstFindUMsb:
1177 // clz needs OpExtInst and OpISub with constant 31, or splat
1178 // vector of 31. Add it to the constant list here.
1179 register_constant(
1180 ConstantInt::get(Type::getInt32Ty(Context), 31));
1181 break;
1182 case glsl::ExtInstAcos:
1183 case glsl::ExtInstAsin:
1184 case glsl::ExtInstAtan2:
1185 // We need 1/pi for acospi, asinpi, atan2pi.
1186 register_constant(
1187 ConstantFP::get(Type::getFloatTy(Context), kOneOverPi));
1188 break;
1189 default:
1190 assert(false && "internally inconsistent");
1191 }
David Neto22f144c2017-06-12 14:26:21 -04001192 }
1193 }
1194 }
1195 }
1196 }
1197
1198 return HasExtInst;
1199}
1200
1201void SPIRVProducerPass::FindTypePerGlobalVar(GlobalVariable &GV) {
1202 // Investigate global variable's type.
1203 FindType(GV.getType());
1204}
1205
1206void SPIRVProducerPass::FindTypePerFunc(Function &F) {
1207 // Investigate function's type.
1208 FunctionType *FTy = F.getFunctionType();
1209
1210 if (F.getCallingConv() != CallingConv::SPIR_KERNEL) {
1211 auto &GlobalConstFuncTyMap = getGlobalConstFuncTypeMap();
David Neto9ed8e2f2018-03-24 06:47:24 -07001212 // Handle a regular function with global constant parameters.
David Neto22f144c2017-06-12 14:26:21 -04001213 if (GlobalConstFuncTyMap.count(FTy)) {
1214 uint32_t GVCstArgIdx = GlobalConstFuncTypeMap[FTy].second;
1215 SmallVector<Type *, 4> NewFuncParamTys;
1216 for (unsigned i = 0; i < FTy->getNumParams(); i++) {
1217 Type *ParamTy = FTy->getParamType(i);
1218 if (i == GVCstArgIdx) {
1219 Type *EleTy = ParamTy->getPointerElementType();
1220 ParamTy = PointerType::get(EleTy, AddressSpace::ModuleScopePrivate);
1221 }
1222
1223 NewFuncParamTys.push_back(ParamTy);
1224 }
1225
1226 FunctionType *NewFTy =
1227 FunctionType::get(FTy->getReturnType(), NewFuncParamTys, false);
1228 GlobalConstFuncTyMap[FTy] = std::make_pair(NewFTy, GVCstArgIdx);
1229 FTy = NewFTy;
1230 }
1231
1232 FindType(FTy);
1233 } else {
1234 // As kernel functions do not have parameters, create new function type and
1235 // add it to type map.
1236 SmallVector<Type *, 4> NewFuncParamTys;
1237 FunctionType *NewFTy =
1238 FunctionType::get(FTy->getReturnType(), NewFuncParamTys, false);
1239 FindType(NewFTy);
1240 }
1241
1242 // Investigate instructions' type in function body.
1243 for (BasicBlock &BB : F) {
1244 for (Instruction &I : BB) {
1245 if (isa<ShuffleVectorInst>(I)) {
1246 for (unsigned i = 0; i < I.getNumOperands(); i++) {
1247 // Ignore type for mask of shuffle vector instruction.
1248 if (i == 2) {
1249 continue;
1250 }
1251
1252 Value *Op = I.getOperand(i);
1253 if (!isa<MetadataAsValue>(Op)) {
1254 FindType(Op->getType());
1255 }
1256 }
1257
1258 FindType(I.getType());
1259 continue;
1260 }
1261
1262 // Work through the operands of the instruction.
1263 for (unsigned i = 0; i < I.getNumOperands(); i++) {
1264 Value *const Op = I.getOperand(i);
1265 // If any of the operands is a constant, find the type!
1266 if (isa<Constant>(Op) && !isa<GlobalValue>(Op)) {
1267 FindType(Op->getType());
1268 }
1269 }
1270
1271 for (Use &Op : I.operands()) {
1272 if (CallInst *Call = dyn_cast<CallInst>(&I)) {
1273 // Avoid to check call instruction's type.
1274 break;
1275 }
1276 if (!isa<MetadataAsValue>(&Op)) {
1277 FindType(Op->getType());
1278 continue;
1279 }
1280 }
1281
1282 CallInst *Call = dyn_cast<CallInst>(&I);
1283
1284 // We don't want to track the type of this call as we are going to replace
1285 // it.
1286 if (Call && ("__translate_sampler_initializer" ==
1287 Call->getCalledFunction()->getName())) {
1288 continue;
1289 }
1290
1291 if (GetElementPtrInst *GEP = dyn_cast<GetElementPtrInst>(&I)) {
1292 // If gep's base operand has ModuleScopePrivate address space, make gep
1293 // return ModuleScopePrivate address space.
1294 if (GEP->getPointerAddressSpace() == AddressSpace::ModuleScopePrivate) {
1295 // Add pointer type with private address space for global constant to
1296 // type list.
1297 Type *EleTy = I.getType()->getPointerElementType();
1298 Type *NewPTy =
1299 PointerType::get(EleTy, AddressSpace::ModuleScopePrivate);
1300
1301 FindType(NewPTy);
1302 continue;
1303 }
1304 }
1305
1306 FindType(I.getType());
1307 }
1308 }
1309}
1310
1311void SPIRVProducerPass::FindType(Type *Ty) {
1312 TypeList &TyList = getTypeList();
1313
1314 if (0 != TyList.idFor(Ty)) {
1315 return;
1316 }
1317
1318 if (Ty->isPointerTy()) {
1319 auto AddrSpace = Ty->getPointerAddressSpace();
1320 if ((AddressSpace::Constant == AddrSpace) ||
1321 (AddressSpace::Global == AddrSpace)) {
1322 auto PointeeTy = Ty->getPointerElementType();
1323
1324 if (PointeeTy->isStructTy() &&
1325 dyn_cast<StructType>(PointeeTy)->isOpaque()) {
1326 FindType(PointeeTy);
1327 auto ActualPointerTy =
1328 PointeeTy->getPointerTo(AddressSpace::UniformConstant);
1329 FindType(ActualPointerTy);
1330 return;
1331 }
1332 }
1333 }
1334
1335 // OpTypeArray has constant and we need to support type of the constant.
1336 if (isa<ArrayType>(Ty)) {
1337 LLVMContext &Context = Ty->getContext();
1338 FindType(Type::getInt32Ty(Context));
1339 }
1340
1341 for (Type *SubTy : Ty->subtypes()) {
1342 FindType(SubTy);
1343 }
1344
1345 TyList.insert(Ty);
1346}
1347
1348void SPIRVProducerPass::FindConstantPerGlobalVar(GlobalVariable &GV) {
1349 // If the global variable has a (non undef) initializer.
1350 if (GV.hasInitializer() && !isa<UndefValue>(GV.getInitializer())) {
1351 FindConstant(GV.getInitializer());
1352 }
1353}
1354
1355void SPIRVProducerPass::FindConstantPerFunc(Function &F) {
1356 // Investigate constants in function body.
1357 for (BasicBlock &BB : F) {
1358 for (Instruction &I : BB) {
1359 CallInst *Call = dyn_cast<CallInst>(&I);
1360
1361 if (Call && ("__translate_sampler_initializer" ==
1362 Call->getCalledFunction()->getName())) {
1363 // We've handled these constants elsewhere, so skip it.
1364 continue;
1365 }
1366
1367 if (isa<AllocaInst>(I)) {
1368 // Alloca instruction has constant for the number of element. Ignore it.
1369 continue;
1370 } else if (isa<ShuffleVectorInst>(I)) {
1371 for (unsigned i = 0; i < I.getNumOperands(); i++) {
1372 // Ignore constant for mask of shuffle vector instruction.
1373 if (i == 2) {
1374 continue;
1375 }
1376
1377 if (isa<Constant>(I.getOperand(i)) &&
1378 !isa<GlobalValue>(I.getOperand(i))) {
1379 FindConstant(I.getOperand(i));
1380 }
1381 }
1382
1383 continue;
1384 } else if (isa<InsertElementInst>(I)) {
1385 // Handle InsertElement with <4 x i8> specially.
1386 Type *CompositeTy = I.getOperand(0)->getType();
1387 if (is4xi8vec(CompositeTy)) {
1388 LLVMContext &Context = CompositeTy->getContext();
1389 if (isa<Constant>(I.getOperand(0))) {
1390 FindConstant(I.getOperand(0));
1391 }
1392
1393 if (isa<Constant>(I.getOperand(1))) {
1394 FindConstant(I.getOperand(1));
1395 }
1396
1397 // Add mask constant 0xFF.
1398 Constant *CstFF = ConstantInt::get(Type::getInt32Ty(Context), 0xFF);
1399 FindConstant(CstFF);
1400
1401 // Add shift amount constant.
1402 if (ConstantInt *CI = dyn_cast<ConstantInt>(I.getOperand(2))) {
1403 uint64_t Idx = CI->getZExtValue();
1404 Constant *CstShiftAmount =
1405 ConstantInt::get(Type::getInt32Ty(Context), Idx * 8);
1406 FindConstant(CstShiftAmount);
1407 }
1408
1409 continue;
1410 }
1411
1412 for (unsigned i = 0; i < I.getNumOperands(); i++) {
1413 // Ignore constant for index of InsertElement instruction.
1414 if (i == 2) {
1415 continue;
1416 }
1417
1418 if (isa<Constant>(I.getOperand(i)) &&
1419 !isa<GlobalValue>(I.getOperand(i))) {
1420 FindConstant(I.getOperand(i));
1421 }
1422 }
1423
1424 continue;
1425 } else if (isa<ExtractElementInst>(I)) {
1426 // Handle ExtractElement with <4 x i8> specially.
1427 Type *CompositeTy = I.getOperand(0)->getType();
1428 if (is4xi8vec(CompositeTy)) {
1429 LLVMContext &Context = CompositeTy->getContext();
1430 if (isa<Constant>(I.getOperand(0))) {
1431 FindConstant(I.getOperand(0));
1432 }
1433
1434 // Add mask constant 0xFF.
1435 Constant *CstFF = ConstantInt::get(Type::getInt32Ty(Context), 0xFF);
1436 FindConstant(CstFF);
1437
1438 // Add shift amount constant.
1439 if (ConstantInt *CI = dyn_cast<ConstantInt>(I.getOperand(1))) {
1440 uint64_t Idx = CI->getZExtValue();
1441 Constant *CstShiftAmount =
1442 ConstantInt::get(Type::getInt32Ty(Context), Idx * 8);
1443 FindConstant(CstShiftAmount);
1444 } else {
1445 ConstantInt *Cst8 = ConstantInt::get(Type::getInt32Ty(Context), 8);
1446 FindConstant(Cst8);
1447 }
1448
1449 continue;
1450 }
1451
1452 for (unsigned i = 0; i < I.getNumOperands(); i++) {
1453 // Ignore constant for index of ExtractElement instruction.
1454 if (i == 1) {
1455 continue;
1456 }
1457
1458 if (isa<Constant>(I.getOperand(i)) &&
1459 !isa<GlobalValue>(I.getOperand(i))) {
1460 FindConstant(I.getOperand(i));
1461 }
1462 }
1463
1464 continue;
1465 } else if ((Instruction::Xor == I.getOpcode()) && I.getType()->isIntegerTy(1)) {
1466 // 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
1467 bool foundConstantTrue = false;
1468 for (Use &Op : I.operands()) {
1469 if (isa<Constant>(Op) && !isa<GlobalValue>(Op)) {
1470 auto CI = cast<ConstantInt>(Op);
1471
1472 if (CI->isZero() || foundConstantTrue) {
1473 // 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.
1474 FindConstant(Op);
1475 } else {
1476 foundConstantTrue = true;
1477 }
1478 }
1479 }
1480
1481 continue;
David Netod2de94a2017-08-28 17:27:47 -04001482 } else if (isa<TruncInst>(I)) {
1483 // For truncation to i8 we mask against 255.
1484 Type *ToTy = I.getType();
1485 if (8u == ToTy->getPrimitiveSizeInBits()) {
1486 LLVMContext &Context = ToTy->getContext();
1487 Constant *Cst255 = ConstantInt::get(Type::getInt32Ty(Context), 0xff);
1488 FindConstant(Cst255);
1489 }
1490 // Fall through.
Neil Henning39672102017-09-29 14:33:13 +01001491 } else if (isa<AtomicRMWInst>(I)) {
1492 LLVMContext &Context = I.getContext();
1493
1494 FindConstant(
1495 ConstantInt::get(Type::getInt32Ty(Context), spv::ScopeDevice));
1496 FindConstant(ConstantInt::get(
1497 Type::getInt32Ty(Context),
1498 spv::MemorySemanticsUniformMemoryMask |
1499 spv::MemorySemanticsSequentiallyConsistentMask));
David Neto22f144c2017-06-12 14:26:21 -04001500 }
1501
1502 for (Use &Op : I.operands()) {
1503 if (isa<Constant>(Op) && !isa<GlobalValue>(Op)) {
1504 FindConstant(Op);
1505 }
1506 }
1507 }
1508 }
1509}
1510
1511void SPIRVProducerPass::FindConstant(Value *V) {
David Neto22f144c2017-06-12 14:26:21 -04001512 ValueList &CstList = getConstantList();
1513
David Netofb9a7972017-08-25 17:08:24 -04001514 // If V is already tracked, ignore it.
1515 if (0 != CstList.idFor(V)) {
David Neto22f144c2017-06-12 14:26:21 -04001516 return;
1517 }
1518
1519 Constant *Cst = cast<Constant>(V);
1520
1521 // Handle constant with <4 x i8> type specially.
1522 Type *CstTy = Cst->getType();
1523 if (is4xi8vec(CstTy)) {
1524 if (!isa<GlobalValue>(V)) {
David Netofb9a7972017-08-25 17:08:24 -04001525 CstList.insert(V);
David Neto22f144c2017-06-12 14:26:21 -04001526 }
1527 }
1528
1529 if (Cst->getNumOperands()) {
1530 for (User::const_op_iterator I = Cst->op_begin(), E = Cst->op_end(); I != E;
1531 ++I) {
1532 FindConstant(*I);
1533 }
1534
David Netofb9a7972017-08-25 17:08:24 -04001535 CstList.insert(Cst);
David Neto22f144c2017-06-12 14:26:21 -04001536 return;
1537 } else if (const ConstantDataSequential *CDS =
1538 dyn_cast<ConstantDataSequential>(Cst)) {
1539 // Add constants for each element to constant list.
1540 for (unsigned i = 0; i < CDS->getNumElements(); i++) {
1541 Constant *EleCst = CDS->getElementAsConstant(i);
1542 FindConstant(EleCst);
1543 }
1544 }
1545
1546 if (!isa<GlobalValue>(V)) {
David Netofb9a7972017-08-25 17:08:24 -04001547 CstList.insert(V);
David Neto22f144c2017-06-12 14:26:21 -04001548 }
1549}
1550
1551spv::StorageClass SPIRVProducerPass::GetStorageClass(unsigned AddrSpace) const {
1552 switch (AddrSpace) {
1553 default:
1554 llvm_unreachable("Unsupported OpenCL address space");
1555 case AddressSpace::Private:
1556 return spv::StorageClassFunction;
1557 case AddressSpace::Global:
1558 case AddressSpace::Constant:
1559 return spv::StorageClassStorageBuffer;
1560 case AddressSpace::Input:
1561 return spv::StorageClassInput;
1562 case AddressSpace::Local:
1563 return spv::StorageClassWorkgroup;
1564 case AddressSpace::UniformConstant:
1565 return spv::StorageClassUniformConstant;
David Neto9ed8e2f2018-03-24 06:47:24 -07001566 case AddressSpace::Uniform:
David Netoe439d702018-03-23 13:14:08 -07001567 return spv::StorageClassUniform;
David Neto22f144c2017-06-12 14:26:21 -04001568 case AddressSpace::ModuleScopePrivate:
1569 return spv::StorageClassPrivate;
1570 }
1571}
1572
1573spv::BuiltIn SPIRVProducerPass::GetBuiltin(StringRef Name) const {
1574 return StringSwitch<spv::BuiltIn>(Name)
1575 .Case("__spirv_GlobalInvocationId", spv::BuiltInGlobalInvocationId)
1576 .Case("__spirv_LocalInvocationId", spv::BuiltInLocalInvocationId)
1577 .Case("__spirv_WorkgroupSize", spv::BuiltInWorkgroupSize)
1578 .Case("__spirv_NumWorkgroups", spv::BuiltInNumWorkgroups)
1579 .Case("__spirv_WorkgroupId", spv::BuiltInWorkgroupId)
1580 .Default(spv::BuiltInMax);
1581}
1582
1583void SPIRVProducerPass::GenerateExtInstImport() {
1584 SPIRVInstructionList &SPIRVInstList = getSPIRVInstList();
1585 uint32_t &ExtInstImportID = getOpExtInstImportID();
1586
1587 //
1588 // Generate OpExtInstImport.
1589 //
1590 // Ops[0] ... Ops[n] = Name (Literal String)
David Neto22f144c2017-06-12 14:26:21 -04001591 ExtInstImportID = nextID;
David Neto87846742018-04-11 17:36:22 -04001592 SPIRVInstList.push_back(new SPIRVInstruction(spv::OpExtInstImport, nextID++,
1593 MkString("GLSL.std.450")));
David Neto22f144c2017-06-12 14:26:21 -04001594}
1595
David Netoc6f3ab22018-04-06 18:02:31 -04001596void SPIRVProducerPass::GenerateSPIRVTypes(LLVMContext& Context, const DataLayout &DL) {
David Neto22f144c2017-06-12 14:26:21 -04001597 SPIRVInstructionList &SPIRVInstList = getSPIRVInstList();
1598 ValueMapType &VMap = getValueMap();
1599 ValueMapType &AllocatedVMap = getAllocatedValueMap();
1600 ValueToValueMapTy &ArgGVMap = getArgumentGVMap();
1601
1602 // Map for OpTypeRuntimeArray. If argument has pointer type, 2 spirv type
1603 // instructions are generated. They are OpTypePointer and OpTypeRuntimeArray.
1604 DenseMap<Type *, uint32_t> OpRuntimeTyMap;
1605
1606 for (Type *Ty : getTypeList()) {
1607 // Update TypeMap with nextID for reference later.
1608 TypeMap[Ty] = nextID;
1609
1610 switch (Ty->getTypeID()) {
1611 default: {
1612 Ty->print(errs());
1613 llvm_unreachable("Unsupported type???");
1614 break;
1615 }
1616 case Type::MetadataTyID:
1617 case Type::LabelTyID: {
1618 // Ignore these types.
1619 break;
1620 }
1621 case Type::PointerTyID: {
1622 PointerType *PTy = cast<PointerType>(Ty);
1623 unsigned AddrSpace = PTy->getAddressSpace();
1624
1625 // For the purposes of our Vulkan SPIR-V type system, constant and global
1626 // are conflated.
1627 bool UseExistingOpTypePointer = false;
1628 if (AddressSpace::Constant == AddrSpace) {
1629 AddrSpace = AddressSpace::Global;
1630
1631 // Check to see if we already created this type (for instance, if we had
1632 // a constant <type>* and a global <type>*, the type would be created by
1633 // one of these types, and shared by both).
1634 auto GlobalTy = PTy->getPointerElementType()->getPointerTo(AddrSpace);
1635 if (0 < TypeMap.count(GlobalTy)) {
1636 TypeMap[PTy] = TypeMap[GlobalTy];
David Netoe439d702018-03-23 13:14:08 -07001637 UseExistingOpTypePointer = true;
David Neto22f144c2017-06-12 14:26:21 -04001638 break;
1639 }
1640 } else if (AddressSpace::Global == AddrSpace) {
1641 AddrSpace = AddressSpace::Constant;
1642
1643 // Check to see if we already created this type (for instance, if we had
1644 // a constant <type>* and a global <type>*, the type would be created by
1645 // one of these types, and shared by both).
1646 auto ConstantTy = PTy->getPointerElementType()->getPointerTo(AddrSpace);
1647 if (0 < TypeMap.count(ConstantTy)) {
1648 TypeMap[PTy] = TypeMap[ConstantTy];
1649 UseExistingOpTypePointer = true;
1650 }
1651 }
1652
1653 bool IsOpTypeRuntimeArray = false;
1654 bool HasArgUser = false;
1655
1656 for (auto ArgGV : ArgGVMap) {
1657 auto Arg = ArgGV.first;
1658
1659 Type *ArgTy = Arg->getType();
1660 if (ArgTy == PTy) {
1661 if (AddrSpace != AddressSpace::UniformConstant) {
1662 IsOpTypeRuntimeArray = true;
1663 }
1664
1665 for (auto U : Arg->users()) {
1666 if (!isa<GetElementPtrInst>(U) || (U->getType() == PTy)) {
1667 HasArgUser = true;
1668 break;
1669 }
1670 }
1671 }
1672 }
1673
1674 if ((!IsOpTypeRuntimeArray || HasArgUser) && !UseExistingOpTypePointer) {
1675 //
1676 // Generate OpTypePointer.
1677 //
1678
1679 // OpTypePointer
1680 // Ops[0] = Storage Class
1681 // Ops[1] = Element Type ID
1682 SPIRVOperandList Ops;
1683
David Neto257c3892018-04-11 13:19:45 -04001684 Ops << MkNum(GetStorageClass(AddrSpace))
1685 << MkId(lookupType(PTy->getElementType()));
David Neto22f144c2017-06-12 14:26:21 -04001686
David Neto87846742018-04-11 17:36:22 -04001687 auto *Inst = new SPIRVInstruction(spv::OpTypePointer, nextID++, Ops);
David Neto22f144c2017-06-12 14:26:21 -04001688 SPIRVInstList.push_back(Inst);
1689 }
1690
1691 if (IsOpTypeRuntimeArray) {
1692 //
1693 // Generate OpTypeRuntimeArray.
1694 //
1695
1696 // OpTypeRuntimeArray
1697 // Ops[0] = Element Type ID
1698 SPIRVOperandList Ops;
1699
David Neto257c3892018-04-11 13:19:45 -04001700 Type *EleTy = PTy->getElementType();
1701 Ops << MkId(lookupType(EleTy));
David Neto22f144c2017-06-12 14:26:21 -04001702
David Neto22f144c2017-06-12 14:26:21 -04001703 uint32_t OpTypeRuntimeArrayID = nextID;
1704 assert(0 == OpRuntimeTyMap.count(Ty));
1705 OpRuntimeTyMap[Ty] = nextID;
1706
David Neto87846742018-04-11 17:36:22 -04001707 auto *Inst =
1708 new SPIRVInstruction(spv::OpTypeRuntimeArray, nextID++, Ops);
David Neto22f144c2017-06-12 14:26:21 -04001709 SPIRVInstList.push_back(Inst);
1710
1711 // Generate OpDecorate.
1712 auto DecoInsertPoint =
1713 std::find_if(SPIRVInstList.begin(), SPIRVInstList.end(),
1714 [](SPIRVInstruction *Inst) -> bool {
1715 return Inst->getOpcode() != spv::OpDecorate &&
1716 Inst->getOpcode() != spv::OpMemberDecorate &&
1717 Inst->getOpcode() != spv::OpExtInstImport;
1718 });
1719
1720 // Ops[0] = Target ID
1721 // Ops[1] = Decoration (ArrayStride)
1722 // Ops[2] = Stride Number(Literal Number)
1723 Ops.clear();
1724
David Neto257c3892018-04-11 13:19:45 -04001725 Ops << MkId(OpTypeRuntimeArrayID) << MkNum(spv::DecorationArrayStride)
1726 << MkNum(static_cast<uint32_t>(DL.getTypeAllocSize(EleTy)));
David Neto22f144c2017-06-12 14:26:21 -04001727
David Neto87846742018-04-11 17:36:22 -04001728 auto *DecoInst = new SPIRVInstruction(spv::OpDecorate, Ops);
David Neto22f144c2017-06-12 14:26:21 -04001729 SPIRVInstList.insert(DecoInsertPoint, DecoInst);
1730 }
1731 break;
1732 }
1733 case Type::StructTyID: {
David Neto22f144c2017-06-12 14:26:21 -04001734 StructType *STy = cast<StructType>(Ty);
1735
1736 // Handle sampler type.
1737 if (STy->isOpaque()) {
1738 if (STy->getName().equals("opencl.sampler_t")) {
1739 //
1740 // Generate OpTypeSampler
1741 //
1742 // Empty Ops.
1743 SPIRVOperandList Ops;
1744
David Neto87846742018-04-11 17:36:22 -04001745 auto *Inst = new SPIRVInstruction(spv::OpTypeSampler, nextID++, Ops);
David Neto22f144c2017-06-12 14:26:21 -04001746 SPIRVInstList.push_back(Inst);
1747 break;
1748 } else if (STy->getName().equals("opencl.image2d_ro_t") ||
1749 STy->getName().equals("opencl.image2d_wo_t") ||
1750 STy->getName().equals("opencl.image3d_ro_t") ||
1751 STy->getName().equals("opencl.image3d_wo_t")) {
1752 //
1753 // Generate OpTypeImage
1754 //
1755 // Ops[0] = Sampled Type ID
1756 // Ops[1] = Dim ID
1757 // Ops[2] = Depth (Literal Number)
1758 // Ops[3] = Arrayed (Literal Number)
1759 // Ops[4] = MS (Literal Number)
1760 // Ops[5] = Sampled (Literal Number)
1761 // Ops[6] = Image Format ID
1762 //
1763 SPIRVOperandList Ops;
1764
1765 // TODO: Changed Sampled Type according to situations.
1766 uint32_t SampledTyID = lookupType(Type::getFloatTy(Context));
David Neto257c3892018-04-11 13:19:45 -04001767 Ops << MkId(SampledTyID);
David Neto22f144c2017-06-12 14:26:21 -04001768
1769 spv::Dim DimID = spv::Dim2D;
1770 if (STy->getName().equals("opencl.image3d_ro_t") ||
1771 STy->getName().equals("opencl.image3d_wo_t")) {
1772 DimID = spv::Dim3D;
1773 }
David Neto257c3892018-04-11 13:19:45 -04001774 Ops << MkNum(DimID);
David Neto22f144c2017-06-12 14:26:21 -04001775
1776 // TODO: Set up Depth.
David Neto257c3892018-04-11 13:19:45 -04001777 Ops << MkNum(0);
David Neto22f144c2017-06-12 14:26:21 -04001778
1779 // TODO: Set up Arrayed.
David Neto257c3892018-04-11 13:19:45 -04001780 Ops << MkNum(0);
David Neto22f144c2017-06-12 14:26:21 -04001781
1782 // TODO: Set up MS.
David Neto257c3892018-04-11 13:19:45 -04001783 Ops << MkNum(0);
David Neto22f144c2017-06-12 14:26:21 -04001784
1785 // TODO: Set up Sampled.
1786 //
1787 // From Spec
1788 //
1789 // 0 indicates this is only known at run time, not at compile time
1790 // 1 indicates will be used with sampler
1791 // 2 indicates will be used without a sampler (a storage image)
1792 uint32_t Sampled = 1;
1793 if (STy->getName().equals("opencl.image2d_wo_t") ||
1794 STy->getName().equals("opencl.image3d_wo_t")) {
1795 Sampled = 2;
1796 }
David Neto257c3892018-04-11 13:19:45 -04001797 Ops << MkNum(Sampled);
David Neto22f144c2017-06-12 14:26:21 -04001798
1799 // TODO: Set up Image Format.
David Neto257c3892018-04-11 13:19:45 -04001800 Ops << MkNum(spv::ImageFormatUnknown);
David Neto22f144c2017-06-12 14:26:21 -04001801
David Neto87846742018-04-11 17:36:22 -04001802 auto *Inst = new SPIRVInstruction(spv::OpTypeImage, nextID++, Ops);
David Neto22f144c2017-06-12 14:26:21 -04001803 SPIRVInstList.push_back(Inst);
1804 break;
1805 }
1806 }
1807
1808 //
1809 // Generate OpTypeStruct
1810 //
1811 // Ops[0] ... Ops[n] = Member IDs
1812 SPIRVOperandList Ops;
1813
1814 for (auto *EleTy : STy->elements()) {
1815 uint32_t EleTyID = lookupType(EleTy);
1816
1817 // Check OpTypeRuntimeArray.
1818 if (isa<PointerType>(EleTy)) {
David Netoc6f3ab22018-04-06 18:02:31 -04001819 // TODO(dneto): Isn't this a straight lookup instead of a loop?
David Neto22f144c2017-06-12 14:26:21 -04001820 for (auto ArgGV : ArgGVMap) {
1821 Type *ArgTy = ArgGV.first->getType();
1822 if (ArgTy == EleTy) {
1823 assert(0 != OpRuntimeTyMap.count(EleTy));
1824 EleTyID = OpRuntimeTyMap[EleTy];
1825 }
1826 }
1827 }
1828
David Neto257c3892018-04-11 13:19:45 -04001829 Ops << MkId(EleTyID);
David Neto22f144c2017-06-12 14:26:21 -04001830 }
1831
David Neto22f144c2017-06-12 14:26:21 -04001832 uint32_t STyID = nextID;
1833
David Neto87846742018-04-11 17:36:22 -04001834 auto *Inst =
1835 new SPIRVInstruction(spv::OpTypeStruct, nextID++, Ops);
David Neto22f144c2017-06-12 14:26:21 -04001836 SPIRVInstList.push_back(Inst);
1837
1838 // Generate OpMemberDecorate.
1839 auto DecoInsertPoint =
1840 std::find_if(SPIRVInstList.begin(), SPIRVInstList.end(),
1841 [](SPIRVInstruction *Inst) -> bool {
1842 return Inst->getOpcode() != spv::OpDecorate &&
1843 Inst->getOpcode() != spv::OpMemberDecorate &&
1844 Inst->getOpcode() != spv::OpExtInstImport;
1845 });
1846
David Netoc463b372017-08-10 15:32:21 -04001847 const auto StructLayout = DL.getStructLayout(STy);
1848
David Neto22f144c2017-06-12 14:26:21 -04001849 for (unsigned MemberIdx = 0; MemberIdx < STy->getNumElements();
1850 MemberIdx++) {
1851 // Ops[0] = Structure Type ID
1852 // Ops[1] = Member Index(Literal Number)
1853 // Ops[2] = Decoration (Offset)
1854 // Ops[3] = Byte Offset (Literal Number)
1855 Ops.clear();
1856
David Neto257c3892018-04-11 13:19:45 -04001857 Ops << MkId(STyID) << MkNum(MemberIdx) << MkNum(spv::DecorationOffset);
David Neto22f144c2017-06-12 14:26:21 -04001858
David Netoc463b372017-08-10 15:32:21 -04001859 const auto ByteOffset =
1860 uint32_t(StructLayout->getElementOffset(MemberIdx));
David Neto257c3892018-04-11 13:19:45 -04001861 Ops << MkNum(ByteOffset);
David Neto22f144c2017-06-12 14:26:21 -04001862
David Neto87846742018-04-11 17:36:22 -04001863 auto *DecoInst = new SPIRVInstruction(spv::OpMemberDecorate, Ops);
David Neto22f144c2017-06-12 14:26:21 -04001864 SPIRVInstList.insert(DecoInsertPoint, DecoInst);
David Neto22f144c2017-06-12 14:26:21 -04001865 }
1866
1867 // Generate OpDecorate.
1868 for (auto ArgGV : ArgGVMap) {
1869 Type *ArgGVTy = ArgGV.second->getType();
1870 PointerType *PTy = cast<PointerType>(ArgGVTy);
1871 Type *ArgTy = PTy->getElementType();
1872
1873 // Struct type from argument is already distinguished with the other
1874 // struct types on llvm types. As a result, if current processing struct
1875 // type is same with argument type, we can generate OpDecorate with
1876 // Block or BufferBlock.
1877 if (ArgTy == STy) {
1878 // Ops[0] = Target ID
1879 // Ops[1] = Decoration (Block or BufferBlock)
1880 Ops.clear();
1881
David Neto6e392822017-08-04 14:06:10 -04001882 // Use Block decorations with StorageBuffer storage class.
David Neto257c3892018-04-11 13:19:45 -04001883 Ops << MkId(STyID) << MkNum(spv::DecorationBlock);
David Neto22f144c2017-06-12 14:26:21 -04001884
David Neto87846742018-04-11 17:36:22 -04001885 auto *DecoInst = new SPIRVInstruction(spv::OpDecorate, Ops);
David Neto22f144c2017-06-12 14:26:21 -04001886 SPIRVInstList.insert(DecoInsertPoint, DecoInst);
1887 break;
1888 }
1889 }
1890 break;
1891 }
1892 case Type::IntegerTyID: {
1893 unsigned BitWidth = Ty->getPrimitiveSizeInBits();
1894
1895 if (BitWidth == 1) {
David Neto87846742018-04-11 17:36:22 -04001896 auto *Inst = new SPIRVInstruction(spv::OpTypeBool, nextID++, {});
David Neto22f144c2017-06-12 14:26:21 -04001897 SPIRVInstList.push_back(Inst);
1898 } else {
1899 // i8 is added to TypeMap as i32.
David Neto391aeb12017-08-26 15:51:58 -04001900 // No matter what LLVM type is requested first, always alias the
1901 // second one's SPIR-V type to be the same as the one we generated
1902 // first.
Neil Henning39672102017-09-29 14:33:13 +01001903 unsigned aliasToWidth = 0;
David Neto22f144c2017-06-12 14:26:21 -04001904 if (BitWidth == 8) {
David Neto391aeb12017-08-26 15:51:58 -04001905 aliasToWidth = 32;
David Neto22f144c2017-06-12 14:26:21 -04001906 BitWidth = 32;
David Neto391aeb12017-08-26 15:51:58 -04001907 } else if (BitWidth == 32) {
1908 aliasToWidth = 8;
1909 }
1910 if (aliasToWidth) {
1911 Type* otherType = Type::getIntNTy(Ty->getContext(), aliasToWidth);
1912 auto where = TypeMap.find(otherType);
1913 if (where == TypeMap.end()) {
1914 // Go ahead and make it, but also map the other type to it.
1915 TypeMap[otherType] = nextID;
1916 } else {
1917 // Alias this SPIR-V type the existing type.
1918 TypeMap[Ty] = where->second;
1919 break;
1920 }
David Neto22f144c2017-06-12 14:26:21 -04001921 }
1922
David Neto257c3892018-04-11 13:19:45 -04001923 SPIRVOperandList Ops;
1924 Ops << MkNum(BitWidth) << MkNum(0 /* not signed */);
David Neto22f144c2017-06-12 14:26:21 -04001925
1926 SPIRVInstList.push_back(
David Neto87846742018-04-11 17:36:22 -04001927 new SPIRVInstruction(spv::OpTypeInt, nextID++, Ops));
David Neto22f144c2017-06-12 14:26:21 -04001928 }
1929 break;
1930 }
1931 case Type::HalfTyID:
1932 case Type::FloatTyID:
1933 case Type::DoubleTyID: {
1934 SPIRVOperand *WidthOp = new SPIRVOperand(
1935 SPIRVOperandType::LITERAL_INTEGER, Ty->getPrimitiveSizeInBits());
1936
1937 SPIRVInstList.push_back(
David Neto87846742018-04-11 17:36:22 -04001938 new SPIRVInstruction(spv::OpTypeFloat, nextID++, WidthOp));
David Neto22f144c2017-06-12 14:26:21 -04001939 break;
1940 }
1941 case Type::ArrayTyID: {
David Neto22f144c2017-06-12 14:26:21 -04001942 ArrayType *ArrTy = cast<ArrayType>(Ty);
1943 //
1944 // Generate OpConstant and OpTypeArray.
1945 //
1946
1947 //
1948 // Generate OpConstant for array length.
1949 //
1950 // Ops[0] = Result Type ID
1951 // Ops[1] .. Ops[n] = Values LiteralNumber
1952 SPIRVOperandList Ops;
1953
1954 Type *LengthTy = Type::getInt32Ty(Context);
1955 uint32_t ResTyID = lookupType(LengthTy);
David Neto257c3892018-04-11 13:19:45 -04001956 Ops << MkId(ResTyID);
David Neto22f144c2017-06-12 14:26:21 -04001957
1958 uint64_t Length = ArrTy->getArrayNumElements();
1959 assert(Length < UINT32_MAX);
David Neto257c3892018-04-11 13:19:45 -04001960 Ops << MkNum(static_cast<uint32_t>(Length));
David Neto22f144c2017-06-12 14:26:21 -04001961
1962 // Add constant for length to constant list.
1963 Constant *CstLength = ConstantInt::get(LengthTy, Length);
1964 AllocatedVMap[CstLength] = nextID;
1965 VMap[CstLength] = nextID;
1966 uint32_t LengthID = nextID;
1967
David Neto87846742018-04-11 17:36:22 -04001968 auto *CstInst = new SPIRVInstruction(spv::OpConstant, nextID++, Ops);
David Neto22f144c2017-06-12 14:26:21 -04001969 SPIRVInstList.push_back(CstInst);
1970
David Neto85082642018-03-24 06:55:20 -07001971 // Remember to generate ArrayStride later
1972 getTypesNeedingArrayStride().insert(Ty);
1973
David Neto22f144c2017-06-12 14:26:21 -04001974 //
1975 // Generate OpTypeArray.
1976 //
1977 // Ops[0] = Element Type ID
1978 // Ops[1] = Array Length Constant ID
1979 Ops.clear();
1980
1981 uint32_t EleTyID = lookupType(ArrTy->getElementType());
David Neto257c3892018-04-11 13:19:45 -04001982 Ops << MkId(EleTyID) << MkId(LengthID);
David Neto22f144c2017-06-12 14:26:21 -04001983
1984 // Update TypeMap with nextID.
1985 TypeMap[Ty] = nextID;
1986
David Neto87846742018-04-11 17:36:22 -04001987 auto *ArrayInst = new SPIRVInstruction(spv::OpTypeArray, nextID++, Ops);
David Neto22f144c2017-06-12 14:26:21 -04001988 SPIRVInstList.push_back(ArrayInst);
1989 break;
1990 }
1991 case Type::VectorTyID: {
1992 // <4 x i8> is changed to i32.
David Neto22f144c2017-06-12 14:26:21 -04001993 if (Ty->getVectorElementType() == Type::getInt8Ty(Context)) {
1994 if (Ty->getVectorNumElements() == 4) {
1995 TypeMap[Ty] = lookupType(Ty->getVectorElementType());
1996 break;
1997 } else {
1998 Ty->print(errs());
1999 llvm_unreachable("Support above i8 vector type");
2000 }
2001 }
2002
2003 // Ops[0] = Component Type ID
2004 // Ops[1] = Component Count (Literal Number)
David Neto257c3892018-04-11 13:19:45 -04002005 SPIRVOperandList Ops;
2006 Ops << MkId(lookupType(Ty->getVectorElementType()))
2007 << MkNum(Ty->getVectorNumElements());
David Neto22f144c2017-06-12 14:26:21 -04002008
David Neto87846742018-04-11 17:36:22 -04002009 SPIRVInstruction* inst = new SPIRVInstruction(spv::OpTypeVector, nextID++, Ops);
David Netoc6f3ab22018-04-06 18:02:31 -04002010 SPIRVInstList.push_back(inst);
David Neto22f144c2017-06-12 14:26:21 -04002011 break;
2012 }
2013 case Type::VoidTyID: {
David Neto87846742018-04-11 17:36:22 -04002014 auto *Inst = new SPIRVInstruction(spv::OpTypeVoid, nextID++, {});
David Neto22f144c2017-06-12 14:26:21 -04002015 SPIRVInstList.push_back(Inst);
2016 break;
2017 }
2018 case Type::FunctionTyID: {
2019 // Generate SPIRV instruction for function type.
2020 FunctionType *FTy = cast<FunctionType>(Ty);
2021
2022 // Ops[0] = Return Type ID
2023 // Ops[1] ... Ops[n] = Parameter Type IDs
2024 SPIRVOperandList Ops;
2025
2026 // Find SPIRV instruction for return type
David Netoc6f3ab22018-04-06 18:02:31 -04002027 Ops << MkId(lookupType(FTy->getReturnType()));
David Neto22f144c2017-06-12 14:26:21 -04002028
2029 // Find SPIRV instructions for parameter types
2030 for (unsigned k = 0; k < FTy->getNumParams(); k++) {
2031 // Find SPIRV instruction for parameter type.
2032 auto ParamTy = FTy->getParamType(k);
2033 if (ParamTy->isPointerTy()) {
2034 auto PointeeTy = ParamTy->getPointerElementType();
2035 if (PointeeTy->isStructTy() &&
2036 dyn_cast<StructType>(PointeeTy)->isOpaque()) {
2037 ParamTy = PointeeTy;
2038 }
2039 }
2040
David Netoc6f3ab22018-04-06 18:02:31 -04002041 Ops << MkId(lookupType(ParamTy));
David Neto22f144c2017-06-12 14:26:21 -04002042 }
2043
David Neto87846742018-04-11 17:36:22 -04002044 auto *Inst = new SPIRVInstruction(spv::OpTypeFunction, nextID++, Ops);
David Neto22f144c2017-06-12 14:26:21 -04002045 SPIRVInstList.push_back(Inst);
2046 break;
2047 }
2048 }
2049 }
2050
2051 // Generate OpTypeSampledImage.
2052 TypeMapType &OpImageTypeMap = getImageTypeMap();
2053 for (auto &ImageType : OpImageTypeMap) {
2054 //
2055 // Generate OpTypeSampledImage.
2056 //
2057 // Ops[0] = Image Type ID
2058 //
2059 SPIRVOperandList Ops;
2060
2061 Type *ImgTy = ImageType.first;
David Netoc6f3ab22018-04-06 18:02:31 -04002062 Ops << MkId(TypeMap[ImgTy]);
David Neto22f144c2017-06-12 14:26:21 -04002063
2064 // Update OpImageTypeMap.
2065 ImageType.second = nextID;
2066
David Neto87846742018-04-11 17:36:22 -04002067 auto *Inst = new SPIRVInstruction(spv::OpTypeSampledImage, nextID++, Ops);
David Neto22f144c2017-06-12 14:26:21 -04002068 SPIRVInstList.push_back(Inst);
2069 }
David Netoc6f3ab22018-04-06 18:02:31 -04002070
2071 // Generate types for pointer-to-local arguments.
2072 for (auto* arg : LocalArgs) {
2073
2074 LocalArgInfo& arg_info = LocalArgMap[arg];
2075
2076 // Generate the spec constant.
2077 SPIRVOperandList Ops;
2078 Ops << MkId(lookupType(Type::getInt32Ty(Context))) << MkNum(1);
David Neto87846742018-04-11 17:36:22 -04002079 SPIRVInstList.push_back(
2080 new SPIRVInstruction(spv::OpSpecConstant, arg_info.array_size_id, Ops));
David Netoc6f3ab22018-04-06 18:02:31 -04002081
2082 // Generate the array type.
2083 Ops.clear();
2084 // The element type must have been created.
2085 uint32_t elem_ty_id = lookupType(arg_info.elem_type);
2086 assert(elem_ty_id);
2087 Ops << MkId(elem_ty_id) << MkId(arg_info.array_size_id);
2088
2089 SPIRVInstList.push_back(
David Neto87846742018-04-11 17:36:22 -04002090 new SPIRVInstruction(spv::OpTypeArray, arg_info.array_type_id, Ops));
David Netoc6f3ab22018-04-06 18:02:31 -04002091
2092 Ops.clear();
2093 Ops << MkNum(spv::StorageClassWorkgroup) << MkId(arg_info.array_type_id);
David Neto87846742018-04-11 17:36:22 -04002094 SPIRVInstList.push_back(new SPIRVInstruction(
2095 spv::OpTypePointer, arg_info.ptr_array_type_id, Ops));
David Netoc6f3ab22018-04-06 18:02:31 -04002096 }
David Neto22f144c2017-06-12 14:26:21 -04002097}
2098
2099void SPIRVProducerPass::GenerateSPIRVConstants() {
2100 SPIRVInstructionList &SPIRVInstList = getSPIRVInstList();
2101 ValueMapType &VMap = getValueMap();
2102 ValueMapType &AllocatedVMap = getAllocatedValueMap();
2103 ValueList &CstList = getConstantList();
David Neto482550a2018-03-24 05:21:07 -07002104 const bool hack_undef = clspv::Option::HackUndef();
David Neto22f144c2017-06-12 14:26:21 -04002105
2106 for (uint32_t i = 0; i < CstList.size(); i++) {
David Netofb9a7972017-08-25 17:08:24 -04002107 // UniqueVector ids are 1-based.
2108 Constant *Cst = cast<Constant>(CstList[i+1]);
David Neto22f144c2017-06-12 14:26:21 -04002109
2110 // OpTypeArray's constant was already generated.
David Netofb9a7972017-08-25 17:08:24 -04002111 if (AllocatedVMap.find_as(Cst) != AllocatedVMap.end()) {
David Neto22f144c2017-06-12 14:26:21 -04002112 continue;
2113 }
2114
David Netofb9a7972017-08-25 17:08:24 -04002115 // Set ValueMap with nextID for reference later.
David Neto22f144c2017-06-12 14:26:21 -04002116 VMap[Cst] = nextID;
2117
2118 //
2119 // Generate OpConstant.
2120 //
2121
2122 // Ops[0] = Result Type ID
2123 // Ops[1] .. Ops[n] = Values LiteralNumber
2124 SPIRVOperandList Ops;
2125
David Neto257c3892018-04-11 13:19:45 -04002126 Ops << MkId(lookupType(Cst->getType()));
David Neto22f144c2017-06-12 14:26:21 -04002127
2128 std::vector<uint32_t> LiteralNum;
David Neto22f144c2017-06-12 14:26:21 -04002129 spv::Op Opcode = spv::OpNop;
2130
2131 if (isa<UndefValue>(Cst)) {
2132 // Ops[0] = Result Type ID
David Netoc66b3352017-10-20 14:28:46 -04002133 Opcode = spv::OpUndef;
2134 if (hack_undef) {
2135 Type *type = Cst->getType();
2136 if (type->isFPOrFPVectorTy() || type->isIntOrIntVectorTy()) {
2137 Opcode = spv::OpConstantNull;
2138 }
2139 }
David Neto22f144c2017-06-12 14:26:21 -04002140 } else if (const ConstantInt *CI = dyn_cast<ConstantInt>(Cst)) {
2141 unsigned BitWidth = CI->getBitWidth();
2142 if (BitWidth == 1) {
2143 // If the bitwidth of constant is 1, generate OpConstantTrue or
2144 // OpConstantFalse.
2145 if (CI->getZExtValue()) {
2146 // Ops[0] = Result Type ID
2147 Opcode = spv::OpConstantTrue;
2148 } else {
2149 // Ops[0] = Result Type ID
2150 Opcode = spv::OpConstantFalse;
2151 }
David Neto22f144c2017-06-12 14:26:21 -04002152 } else {
2153 auto V = CI->getZExtValue();
2154 LiteralNum.push_back(V & 0xFFFFFFFF);
2155
2156 if (BitWidth > 32) {
2157 LiteralNum.push_back(V >> 32);
2158 }
2159
2160 Opcode = spv::OpConstant;
David Neto22f144c2017-06-12 14:26:21 -04002161
David Neto257c3892018-04-11 13:19:45 -04002162 Ops << MkInteger(LiteralNum);
2163
2164 if (BitWidth == 32 && V == 0) {
2165 constant_i32_zero_id_ = nextID;
2166 }
David Neto22f144c2017-06-12 14:26:21 -04002167 }
2168 } else if (const ConstantFP *CFP = dyn_cast<ConstantFP>(Cst)) {
2169 uint64_t FPVal = CFP->getValueAPF().bitcastToAPInt().getZExtValue();
2170 Type *CFPTy = CFP->getType();
2171 if (CFPTy->isFloatTy()) {
2172 LiteralNum.push_back(FPVal & 0xFFFFFFFF);
2173 } else {
2174 CFPTy->print(errs());
2175 llvm_unreachable("Implement this ConstantFP Type");
2176 }
2177
2178 Opcode = spv::OpConstant;
David Neto22f144c2017-06-12 14:26:21 -04002179
David Neto257c3892018-04-11 13:19:45 -04002180 Ops << MkFloat(LiteralNum);
David Neto22f144c2017-06-12 14:26:21 -04002181 } else if (isa<ConstantDataSequential>(Cst) &&
2182 cast<ConstantDataSequential>(Cst)->isString()) {
2183 Cst->print(errs());
2184 llvm_unreachable("Implement this Constant");
2185
2186 } else if (const ConstantDataSequential *CDS =
2187 dyn_cast<ConstantDataSequential>(Cst)) {
David Neto49351ac2017-08-26 17:32:20 -04002188 // Let's convert <4 x i8> constant to int constant specially.
2189 // This case occurs when all the values are specified as constant
2190 // ints.
2191 Type *CstTy = Cst->getType();
2192 if (is4xi8vec(CstTy)) {
2193 LLVMContext &Context = CstTy->getContext();
2194
2195 //
2196 // Generate OpConstant with OpTypeInt 32 0.
2197 //
Neil Henning39672102017-09-29 14:33:13 +01002198 uint32_t IntValue = 0;
2199 for (unsigned k = 0; k < 4; k++) {
2200 const uint64_t Val = CDS->getElementAsInteger(k);
David Neto49351ac2017-08-26 17:32:20 -04002201 IntValue = (IntValue << 8) | (Val & 0xffu);
2202 }
2203
2204 Type *i32 = Type::getInt32Ty(Context);
2205 Constant *CstInt = ConstantInt::get(i32, IntValue);
2206 // If this constant is already registered on VMap, use it.
2207 if (VMap.count(CstInt)) {
2208 uint32_t CstID = VMap[CstInt];
2209 VMap[Cst] = CstID;
2210 continue;
2211 }
2212
David Neto257c3892018-04-11 13:19:45 -04002213 Ops << MkNum(IntValue);
David Neto49351ac2017-08-26 17:32:20 -04002214
David Neto87846742018-04-11 17:36:22 -04002215 auto *CstInst = new SPIRVInstruction(spv::OpConstant, nextID++, Ops);
David Neto49351ac2017-08-26 17:32:20 -04002216 SPIRVInstList.push_back(CstInst);
2217
2218 continue;
2219 }
2220
2221 // A normal constant-data-sequential case.
David Neto22f144c2017-06-12 14:26:21 -04002222 for (unsigned k = 0; k < CDS->getNumElements(); k++) {
2223 Constant *EleCst = CDS->getElementAsConstant(k);
2224 uint32_t EleCstID = VMap[EleCst];
David Neto257c3892018-04-11 13:19:45 -04002225 Ops << MkId(EleCstID);
David Neto22f144c2017-06-12 14:26:21 -04002226 }
2227
2228 Opcode = spv::OpConstantComposite;
David Neto22f144c2017-06-12 14:26:21 -04002229 } else if (const ConstantAggregate *CA = dyn_cast<ConstantAggregate>(Cst)) {
2230 // Let's convert <4 x i8> constant to int constant specially.
David Neto49351ac2017-08-26 17:32:20 -04002231 // This case occurs when at least one of the values is an undef.
David Neto22f144c2017-06-12 14:26:21 -04002232 Type *CstTy = Cst->getType();
2233 if (is4xi8vec(CstTy)) {
2234 LLVMContext &Context = CstTy->getContext();
2235
2236 //
2237 // Generate OpConstant with OpTypeInt 32 0.
2238 //
Neil Henning39672102017-09-29 14:33:13 +01002239 uint32_t IntValue = 0;
David Neto22f144c2017-06-12 14:26:21 -04002240 for (User::const_op_iterator I = Cst->op_begin(), E = Cst->op_end();
2241 I != E; ++I) {
2242 uint64_t Val = 0;
David Neto49351ac2017-08-26 17:32:20 -04002243 const Value* CV = *I;
Neil Henning39672102017-09-29 14:33:13 +01002244 if (auto *CI2 = dyn_cast<ConstantInt>(CV)) {
2245 Val = CI2->getZExtValue();
David Neto22f144c2017-06-12 14:26:21 -04002246 }
David Neto49351ac2017-08-26 17:32:20 -04002247 IntValue = (IntValue << 8) | (Val & 0xffu);
David Neto22f144c2017-06-12 14:26:21 -04002248 }
2249
David Neto49351ac2017-08-26 17:32:20 -04002250 Type *i32 = Type::getInt32Ty(Context);
2251 Constant *CstInt = ConstantInt::get(i32, IntValue);
David Neto22f144c2017-06-12 14:26:21 -04002252 // If this constant is already registered on VMap, use it.
2253 if (VMap.count(CstInt)) {
2254 uint32_t CstID = VMap[CstInt];
2255 VMap[Cst] = CstID;
David Neto19a1bad2017-08-25 15:01:41 -04002256 continue;
David Neto22f144c2017-06-12 14:26:21 -04002257 }
2258
David Neto257c3892018-04-11 13:19:45 -04002259 Ops << MkNum(IntValue);
David Neto22f144c2017-06-12 14:26:21 -04002260
David Neto87846742018-04-11 17:36:22 -04002261 auto *CstInst = new SPIRVInstruction(spv::OpConstant, nextID++, Ops);
David Neto22f144c2017-06-12 14:26:21 -04002262 SPIRVInstList.push_back(CstInst);
2263
David Neto19a1bad2017-08-25 15:01:41 -04002264 continue;
David Neto22f144c2017-06-12 14:26:21 -04002265 }
2266
2267 // We use a constant composite in SPIR-V for our constant aggregate in
2268 // LLVM.
2269 Opcode = spv::OpConstantComposite;
David Neto22f144c2017-06-12 14:26:21 -04002270
2271 for (unsigned k = 0; k < CA->getNumOperands(); k++) {
2272 // Look up the ID of the element of this aggregate (which we will
2273 // previously have created a constant for).
2274 uint32_t ElementConstantID = VMap[CA->getAggregateElement(k)];
2275
2276 // And add an operand to the composite we are constructing
David Neto257c3892018-04-11 13:19:45 -04002277 Ops << MkId(ElementConstantID);
David Neto22f144c2017-06-12 14:26:21 -04002278 }
2279 } else if (Cst->isNullValue()) {
2280 Opcode = spv::OpConstantNull;
David Neto22f144c2017-06-12 14:26:21 -04002281 } else {
2282 Cst->print(errs());
2283 llvm_unreachable("Unsupported Constant???");
2284 }
2285
David Neto87846742018-04-11 17:36:22 -04002286 auto *CstInst = new SPIRVInstruction(Opcode, nextID++, Ops);
David Neto22f144c2017-06-12 14:26:21 -04002287 SPIRVInstList.push_back(CstInst);
2288 }
2289}
2290
2291void SPIRVProducerPass::GenerateSamplers(Module &M) {
2292 SPIRVInstructionList &SPIRVInstList = getSPIRVInstList();
2293 ValueMapType &VMap = getValueMap();
2294
2295 DenseMap<unsigned, unsigned> SamplerLiteralToIDMap;
2296
2297 unsigned BindingIdx = 0;
2298
2299 // Generate the sampler map.
2300 for (auto SamplerLiteral : getSamplerMap()) {
2301 // Generate OpVariable.
2302 //
2303 // GIDOps[0] : Result Type ID
2304 // GIDOps[1] : Storage Class
2305 SPIRVOperandList Ops;
2306
David Neto257c3892018-04-11 13:19:45 -04002307 Ops << MkId(lookupType(SamplerTy))
2308 << MkNum(spv::StorageClassUniformConstant);
David Neto22f144c2017-06-12 14:26:21 -04002309
David Neto87846742018-04-11 17:36:22 -04002310 auto *Inst = new SPIRVInstruction(spv::OpVariable, nextID, Ops);
David Neto22f144c2017-06-12 14:26:21 -04002311 SPIRVInstList.push_back(Inst);
2312
David Neto44795152017-07-13 15:45:28 -04002313 SamplerLiteralToIDMap[SamplerLiteral.first] = nextID++;
David Neto22f144c2017-06-12 14:26:21 -04002314
2315 // Find Insert Point for OpDecorate.
2316 auto DecoInsertPoint =
2317 std::find_if(SPIRVInstList.begin(), SPIRVInstList.end(),
2318 [](SPIRVInstruction *Inst) -> bool {
2319 return Inst->getOpcode() != spv::OpDecorate &&
2320 Inst->getOpcode() != spv::OpMemberDecorate &&
2321 Inst->getOpcode() != spv::OpExtInstImport;
2322 });
2323
2324 // Ops[0] = Target ID
2325 // Ops[1] = Decoration (DescriptorSet)
2326 // Ops[2] = LiteralNumber according to Decoration
2327 Ops.clear();
2328
David Neto257c3892018-04-11 13:19:45 -04002329 uint32_t ArgID = SamplerLiteralToIDMap[SamplerLiteral.first];
2330 Ops << MkId(ArgID) << MkNum(spv::DecorationDescriptorSet)
David Neto78383442018-06-15 20:31:56 -04002331 << MkNum(clspv::GetCurrentDescriptorIndex(&M));
David Neto22f144c2017-06-12 14:26:21 -04002332
David Neto44795152017-07-13 15:45:28 -04002333 descriptorMapOut << "sampler," << SamplerLiteral.first << ",samplerExpr,\""
David Neto257c3892018-04-11 13:19:45 -04002334 << SamplerLiteral.second << "\",descriptorSet,"
David Neto78383442018-06-15 20:31:56 -04002335 << clspv::GetCurrentDescriptorIndex(&M) << ",binding," << BindingIdx
David Neto257c3892018-04-11 13:19:45 -04002336 << "\n";
David Neto22f144c2017-06-12 14:26:21 -04002337
David Neto87846742018-04-11 17:36:22 -04002338 auto *DescDecoInst = new SPIRVInstruction(spv::OpDecorate, Ops);
David Neto22f144c2017-06-12 14:26:21 -04002339 SPIRVInstList.insert(DecoInsertPoint, DescDecoInst);
2340
2341 // Ops[0] = Target ID
2342 // Ops[1] = Decoration (Binding)
2343 // Ops[2] = LiteralNumber according to Decoration
2344 Ops.clear();
David Neto257c3892018-04-11 13:19:45 -04002345 Ops << MkId(ArgID) << MkNum(spv::DecorationBinding) << MkNum(BindingIdx);
2346 BindingIdx++;
David Neto22f144c2017-06-12 14:26:21 -04002347
David Neto87846742018-04-11 17:36:22 -04002348 auto *BindDecoInst = new SPIRVInstruction(spv::OpDecorate, Ops);
David Neto22f144c2017-06-12 14:26:21 -04002349 SPIRVInstList.insert(DecoInsertPoint, BindDecoInst);
2350 }
David Neto85082642018-03-24 06:55:20 -07002351 if (BindingIdx > 0) {
2352 // We generated something.
David Neto78383442018-06-15 20:31:56 -04002353 clspv::TakeDescriptorIndex(&M);
David Neto85082642018-03-24 06:55:20 -07002354 }
David Neto22f144c2017-06-12 14:26:21 -04002355
2356 const char *TranslateSamplerFunctionName = "__translate_sampler_initializer";
2357
2358 auto SamplerFunction = M.getFunction(TranslateSamplerFunctionName);
2359
2360 // If there are no uses of the sampler function, no work to do!
2361 if (!SamplerFunction) {
2362 return;
2363 }
2364
2365 // Iterate through the users of the sampler function.
2366 for (auto User : SamplerFunction->users()) {
2367 if (auto CI = dyn_cast<CallInst>(User)) {
2368 // Get the literal used to initialize the sampler.
2369 auto Constant = dyn_cast<ConstantInt>(CI->getArgOperand(0));
2370
2371 if (!Constant) {
2372 CI->getArgOperand(0)->print(errs());
2373 llvm_unreachable("Argument of sampler initializer was non-constant!");
2374 }
2375
2376 auto SamplerLiteral = static_cast<unsigned>(Constant->getZExtValue());
2377
2378 if (0 == SamplerLiteralToIDMap.count(SamplerLiteral)) {
2379 Constant->print(errs());
2380 llvm_unreachable("Sampler literal was not found in sampler map!");
2381 }
2382
2383 // Calls to the sampler literal function to initialize a sampler are
2384 // re-routed to the global variables declared for the sampler.
2385 VMap[CI] = SamplerLiteralToIDMap[SamplerLiteral];
2386 }
2387 }
2388}
2389
2390void SPIRVProducerPass::GenerateGlobalVar(GlobalVariable &GV) {
David Neto78383442018-06-15 20:31:56 -04002391 Module& M = *GV.getParent();
David Neto22f144c2017-06-12 14:26:21 -04002392 SPIRVInstructionList &SPIRVInstList = getSPIRVInstList();
2393 ValueMapType &VMap = getValueMap();
2394 std::vector<uint32_t> &BuiltinDimVec = getBuiltinDimVec();
David Neto85082642018-03-24 06:55:20 -07002395 const DataLayout &DL = GV.getParent()->getDataLayout();
David Neto22f144c2017-06-12 14:26:21 -04002396
2397 const spv::BuiltIn BuiltinType = GetBuiltin(GV.getName());
2398 Type *Ty = GV.getType();
2399 PointerType *PTy = cast<PointerType>(Ty);
2400
2401 uint32_t InitializerID = 0;
2402
2403 // Workgroup size is handled differently (it goes into a constant)
2404 if (spv::BuiltInWorkgroupSize == BuiltinType) {
2405 std::vector<bool> HasMDVec;
2406 uint32_t PrevXDimCst = 0xFFFFFFFF;
2407 uint32_t PrevYDimCst = 0xFFFFFFFF;
2408 uint32_t PrevZDimCst = 0xFFFFFFFF;
2409 for (Function &Func : *GV.getParent()) {
2410 if (Func.isDeclaration()) {
2411 continue;
2412 }
2413
2414 // We only need to check kernels.
2415 if (Func.getCallingConv() != CallingConv::SPIR_KERNEL) {
2416 continue;
2417 }
2418
2419 if (const MDNode *MD =
2420 dyn_cast<Function>(&Func)->getMetadata("reqd_work_group_size")) {
2421 uint32_t CurXDimCst = static_cast<uint32_t>(
2422 mdconst::extract<ConstantInt>(MD->getOperand(0))->getZExtValue());
2423 uint32_t CurYDimCst = static_cast<uint32_t>(
2424 mdconst::extract<ConstantInt>(MD->getOperand(1))->getZExtValue());
2425 uint32_t CurZDimCst = static_cast<uint32_t>(
2426 mdconst::extract<ConstantInt>(MD->getOperand(2))->getZExtValue());
2427
2428 if (PrevXDimCst == 0xFFFFFFFF && PrevYDimCst == 0xFFFFFFFF &&
2429 PrevZDimCst == 0xFFFFFFFF) {
2430 PrevXDimCst = CurXDimCst;
2431 PrevYDimCst = CurYDimCst;
2432 PrevZDimCst = CurZDimCst;
2433 } else if (CurXDimCst != PrevXDimCst || CurYDimCst != PrevYDimCst ||
2434 CurZDimCst != PrevZDimCst) {
2435 llvm_unreachable(
2436 "reqd_work_group_size must be the same across all kernels");
2437 } else {
2438 continue;
2439 }
2440
2441 //
2442 // Generate OpConstantComposite.
2443 //
2444 // Ops[0] : Result Type ID
2445 // Ops[1] : Constant size for x dimension.
2446 // Ops[2] : Constant size for y dimension.
2447 // Ops[3] : Constant size for z dimension.
2448 SPIRVOperandList Ops;
2449
2450 uint32_t XDimCstID =
2451 VMap[mdconst::extract<ConstantInt>(MD->getOperand(0))];
2452 uint32_t YDimCstID =
2453 VMap[mdconst::extract<ConstantInt>(MD->getOperand(1))];
2454 uint32_t ZDimCstID =
2455 VMap[mdconst::extract<ConstantInt>(MD->getOperand(2))];
2456
2457 InitializerID = nextID;
2458
David Neto257c3892018-04-11 13:19:45 -04002459 Ops << MkId(lookupType(Ty->getPointerElementType())) << MkId(XDimCstID)
2460 << MkId(YDimCstID) << MkId(ZDimCstID);
David Neto22f144c2017-06-12 14:26:21 -04002461
David Neto87846742018-04-11 17:36:22 -04002462 auto *Inst =
2463 new SPIRVInstruction(spv::OpConstantComposite, nextID++, Ops);
David Neto22f144c2017-06-12 14:26:21 -04002464 SPIRVInstList.push_back(Inst);
2465
2466 HasMDVec.push_back(true);
2467 } else {
2468 HasMDVec.push_back(false);
2469 }
2470 }
2471
2472 // Check all kernels have same definitions for work_group_size.
2473 bool HasMD = false;
2474 if (!HasMDVec.empty()) {
2475 HasMD = HasMDVec[0];
2476 for (uint32_t i = 1; i < HasMDVec.size(); i++) {
2477 if (HasMD != HasMDVec[i]) {
2478 llvm_unreachable(
2479 "Kernels should have consistent work group size definition");
2480 }
2481 }
2482 }
2483
2484 // If all kernels do not have metadata for reqd_work_group_size, generate
2485 // OpSpecConstants for x/y/z dimension.
2486 if (!HasMD) {
2487 //
2488 // Generate OpSpecConstants for x/y/z dimension.
2489 //
2490 // Ops[0] : Result Type ID
2491 // Ops[1] : Constant size for x/y/z dimension (Literal Number).
2492 uint32_t XDimCstID = 0;
2493 uint32_t YDimCstID = 0;
2494 uint32_t ZDimCstID = 0;
2495
David Neto22f144c2017-06-12 14:26:21 -04002496 SPIRVOperandList Ops;
David Neto257c3892018-04-11 13:19:45 -04002497 uint32_t result_type_id =
2498 lookupType(Ty->getPointerElementType()->getSequentialElementType());
David Neto22f144c2017-06-12 14:26:21 -04002499
David Neto257c3892018-04-11 13:19:45 -04002500 // X Dimension
2501 Ops << MkId(result_type_id) << MkNum(1);
2502 XDimCstID = nextID++;
2503 SPIRVInstList.push_back(
David Neto87846742018-04-11 17:36:22 -04002504 new SPIRVInstruction(spv::OpSpecConstant, XDimCstID, Ops));
David Neto22f144c2017-06-12 14:26:21 -04002505
2506 // Y Dimension
2507 Ops.clear();
David Neto257c3892018-04-11 13:19:45 -04002508 Ops << MkId(result_type_id) << MkNum(1);
2509 YDimCstID = nextID++;
2510 SPIRVInstList.push_back(
David Neto87846742018-04-11 17:36:22 -04002511 new SPIRVInstruction(spv::OpSpecConstant, YDimCstID, Ops));
David Neto22f144c2017-06-12 14:26:21 -04002512
2513 // Z Dimension
2514 Ops.clear();
David Neto257c3892018-04-11 13:19:45 -04002515 Ops << MkId(result_type_id) << MkNum(1);
2516 ZDimCstID = nextID++;
2517 SPIRVInstList.push_back(
David Neto87846742018-04-11 17:36:22 -04002518 new SPIRVInstruction(spv::OpSpecConstant, ZDimCstID, Ops));
David Neto22f144c2017-06-12 14:26:21 -04002519
David Neto22f144c2017-06-12 14:26:21 -04002520
David Neto257c3892018-04-11 13:19:45 -04002521 BuiltinDimVec.push_back(XDimCstID);
2522 BuiltinDimVec.push_back(YDimCstID);
David Neto22f144c2017-06-12 14:26:21 -04002523 BuiltinDimVec.push_back(ZDimCstID);
2524
David Neto22f144c2017-06-12 14:26:21 -04002525
2526 //
2527 // Generate OpSpecConstantComposite.
2528 //
2529 // Ops[0] : Result Type ID
2530 // Ops[1] : Constant size for x dimension.
2531 // Ops[2] : Constant size for y dimension.
2532 // Ops[3] : Constant size for z dimension.
2533 InitializerID = nextID;
2534
2535 Ops.clear();
David Neto257c3892018-04-11 13:19:45 -04002536 Ops << MkId(lookupType(Ty->getPointerElementType())) << MkId(XDimCstID)
2537 << MkId(YDimCstID) << MkId(ZDimCstID);
David Neto22f144c2017-06-12 14:26:21 -04002538
David Neto87846742018-04-11 17:36:22 -04002539 auto *Inst =
2540 new SPIRVInstruction(spv::OpSpecConstantComposite, nextID++, Ops);
David Neto22f144c2017-06-12 14:26:21 -04002541 SPIRVInstList.push_back(Inst);
2542 }
2543 }
2544
David Neto22f144c2017-06-12 14:26:21 -04002545 VMap[&GV] = nextID;
2546
2547 //
2548 // Generate OpVariable.
2549 //
2550 // GIDOps[0] : Result Type ID
2551 // GIDOps[1] : Storage Class
2552 SPIRVOperandList Ops;
2553
David Neto85082642018-03-24 06:55:20 -07002554 const auto AS = PTy->getAddressSpace();
David Netoc6f3ab22018-04-06 18:02:31 -04002555 Ops << MkId(lookupType(Ty)) << MkNum(GetStorageClass(AS));
David Neto22f144c2017-06-12 14:26:21 -04002556
David Neto85082642018-03-24 06:55:20 -07002557 if (GV.hasInitializer()) {
2558 InitializerID = VMap[GV.getInitializer()];
David Neto22f144c2017-06-12 14:26:21 -04002559 }
2560
David Neto85082642018-03-24 06:55:20 -07002561 const bool module_scope_constant_external_init =
2562 (0 != InitializerID) && (AS == AddressSpace::Constant) &&
2563 clspv::Option::ModuleConstantsInStorageBuffer();
2564
2565 if (0 != InitializerID) {
2566 if (!module_scope_constant_external_init) {
2567 // Emit the ID of the intiializer as part of the variable definition.
David Netoc6f3ab22018-04-06 18:02:31 -04002568 Ops << MkId(InitializerID);
David Neto85082642018-03-24 06:55:20 -07002569 }
2570 }
2571 const uint32_t var_id = nextID++;
2572
David Neto87846742018-04-11 17:36:22 -04002573 auto *Inst = new SPIRVInstruction(spv::OpVariable, var_id, Ops);
David Neto22f144c2017-06-12 14:26:21 -04002574 SPIRVInstList.push_back(Inst);
2575
2576 // If we have a builtin.
2577 if (spv::BuiltInMax != BuiltinType) {
2578 // Find Insert Point for OpDecorate.
2579 auto DecoInsertPoint =
2580 std::find_if(SPIRVInstList.begin(), SPIRVInstList.end(),
2581 [](SPIRVInstruction *Inst) -> bool {
2582 return Inst->getOpcode() != spv::OpDecorate &&
2583 Inst->getOpcode() != spv::OpMemberDecorate &&
2584 Inst->getOpcode() != spv::OpExtInstImport;
2585 });
2586 //
2587 // Generate OpDecorate.
2588 //
2589 // DOps[0] = Target ID
2590 // DOps[1] = Decoration (Builtin)
2591 // DOps[2] = BuiltIn ID
2592 uint32_t ResultID;
2593
2594 // WorkgroupSize is different, we decorate the constant composite that has
2595 // its value, rather than the variable that we use to access the value.
2596 if (spv::BuiltInWorkgroupSize == BuiltinType) {
2597 ResultID = InitializerID;
David Netoa60b00b2017-09-15 16:34:09 -04002598 // Save both the value and variable IDs for later.
2599 WorkgroupSizeValueID = InitializerID;
2600 WorkgroupSizeVarID = VMap[&GV];
David Neto22f144c2017-06-12 14:26:21 -04002601 } else {
2602 ResultID = VMap[&GV];
2603 }
2604
2605 SPIRVOperandList DOps;
David Neto257c3892018-04-11 13:19:45 -04002606 DOps << MkId(ResultID) << MkNum(spv::DecorationBuiltIn)
2607 << MkNum(BuiltinType);
David Neto22f144c2017-06-12 14:26:21 -04002608
David Neto87846742018-04-11 17:36:22 -04002609 auto *DescDecoInst = new SPIRVInstruction(spv::OpDecorate, DOps);
David Neto22f144c2017-06-12 14:26:21 -04002610 SPIRVInstList.insert(DecoInsertPoint, DescDecoInst);
David Neto85082642018-03-24 06:55:20 -07002611 } else if (module_scope_constant_external_init) {
2612 // This module scope constant is initialized from a storage buffer with data
2613 // provided by the host at binding 0 of the next descriptor set.
David Neto78383442018-06-15 20:31:56 -04002614 const uint32_t descriptor_set = TakeDescriptorIndex(&M);
David Neto85082642018-03-24 06:55:20 -07002615
2616 // Emit the intiialier to the descriptor map file.
2617 // Use "kind,buffer" to indicate storage buffer. We might want to expand
2618 // that later to other types, like uniform buffer.
2619 descriptorMapOut << "constant,descriptorSet," << descriptor_set
2620 << ",binding,0,kind,buffer,hexbytes,";
2621 clspv::ConstantEmitter(DL, descriptorMapOut).Emit(GV.getInitializer());
2622 descriptorMapOut << "\n";
2623
2624 // Find Insert Point for OpDecorate.
2625 auto DecoInsertPoint =
2626 std::find_if(SPIRVInstList.begin(), SPIRVInstList.end(),
2627 [](SPIRVInstruction *Inst) -> bool {
2628 return Inst->getOpcode() != spv::OpDecorate &&
2629 Inst->getOpcode() != spv::OpMemberDecorate &&
2630 Inst->getOpcode() != spv::OpExtInstImport;
2631 });
2632
David Neto257c3892018-04-11 13:19:45 -04002633 // OpDecorate %var Binding <binding>
David Neto85082642018-03-24 06:55:20 -07002634 SPIRVOperandList DOps;
David Neto257c3892018-04-11 13:19:45 -04002635 DOps << MkId(var_id) << MkNum(spv::DecorationBinding) << MkNum(0);
2636 DecoInsertPoint = SPIRVInstList.insert(
David Neto87846742018-04-11 17:36:22 -04002637 DecoInsertPoint, new SPIRVInstruction(spv::OpDecorate, DOps));
David Neto85082642018-03-24 06:55:20 -07002638
2639 // OpDecorate %var DescriptorSet <descriptor_set>
2640 DOps.clear();
David Neto257c3892018-04-11 13:19:45 -04002641 DOps << MkId(var_id) << MkNum(spv::DecorationDescriptorSet)
2642 << MkNum(descriptor_set);
David Netoc6f3ab22018-04-06 18:02:31 -04002643 SPIRVInstList.insert(DecoInsertPoint,
David Neto87846742018-04-11 17:36:22 -04002644 new SPIRVInstruction(spv::OpDecorate, DOps));
David Neto22f144c2017-06-12 14:26:21 -04002645 }
2646}
2647
David Netoc6f3ab22018-04-06 18:02:31 -04002648void SPIRVProducerPass::GenerateWorkgroupVars() {
2649 SPIRVInstructionList &SPIRVInstList = getSPIRVInstList();
2650 for (auto* arg : LocalArgs) {
2651 const auto& info = LocalArgMap[arg];
2652
2653 // Generate OpVariable.
2654 //
2655 // GIDOps[0] : Result Type ID
2656 // GIDOps[1] : Storage Class
2657 SPIRVOperandList Ops;
2658 Ops << MkId(info.ptr_array_type_id) << MkNum(spv::StorageClassWorkgroup);
2659
2660 SPIRVInstList.push_back(
David Neto87846742018-04-11 17:36:22 -04002661 new SPIRVInstruction(spv::OpVariable, info.variable_id, Ops));
David Netoc6f3ab22018-04-06 18:02:31 -04002662 }
2663}
2664
David Neto22f144c2017-06-12 14:26:21 -04002665void SPIRVProducerPass::GenerateFuncPrologue(Function &F) {
David Neto78383442018-06-15 20:31:56 -04002666 Module& M = *F.getParent();
2667 const DataLayout &DL = M.getDataLayout();
David Neto22f144c2017-06-12 14:26:21 -04002668 SPIRVInstructionList &SPIRVInstList = getSPIRVInstList();
2669 ValueMapType &VMap = getValueMap();
2670 EntryPointVecType &EntryPoints = getEntryPointVec();
2671 ValueToValueMapTy &ArgGVMap = getArgumentGVMap();
2672 ValueMapType &ArgGVIDMap = getArgumentGVIDMap();
2673 auto &GlobalConstFuncTyMap = getGlobalConstFuncTypeMap();
2674 auto &GlobalConstArgSet = getGlobalConstArgSet();
2675
2676 FunctionType *FTy = F.getFunctionType();
2677
2678 //
2679 // Generate OpVariable and OpDecorate for kernel function with arguments.
2680 //
2681 if (F.getCallingConv() == CallingConv::SPIR_KERNEL) {
2682
2683 // Find Insert Point for OpDecorate.
2684 auto DecoInsertPoint =
2685 std::find_if(SPIRVInstList.begin(), SPIRVInstList.end(),
2686 [](SPIRVInstruction *Inst) -> bool {
2687 return Inst->getOpcode() != spv::OpDecorate &&
2688 Inst->getOpcode() != spv::OpMemberDecorate &&
2689 Inst->getOpcode() != spv::OpExtInstImport;
2690 });
2691
David Neto78383442018-06-15 20:31:56 -04002692 const uint32_t DescriptorSetIdx = clspv::GetCurrentDescriptorIndex(&M);
David Neto482550a2018-03-24 05:21:07 -07002693 if (clspv::Option::DistinctKernelDescriptorSets()) {
David Neto78383442018-06-15 20:31:56 -04002694 clspv::TakeDescriptorIndex(&M);
David Neto22f144c2017-06-12 14:26:21 -04002695 }
2696
David Netoe439d702018-03-23 13:14:08 -07002697 auto remap_arg_kind = [](StringRef argKind) {
David Neto482550a2018-03-24 05:21:07 -07002698 return clspv::Option::PodArgsInUniformBuffer() && argKind.equals("pod")
2699 ? "pod_ubo"
2700 : argKind;
David Netoe439d702018-03-23 13:14:08 -07002701 };
2702
David Neto156783e2017-07-05 15:39:41 -04002703 const auto *ArgMap = F.getMetadata("kernel_arg_map");
2704 // Emit descriptor map entries, if there was explicit metadata
2705 // attached.
2706 if (ArgMap) {
David Netoc6f3ab22018-04-06 18:02:31 -04002707 // The binding number is the new argument index minus the number
2708 // pointer-to-local arguments. Do this adjustment here rather than
2709 // adding yet another data member to the metadata for each argument.
2710 int num_ptr_local = 0;
2711
David Neto156783e2017-07-05 15:39:41 -04002712 for (const auto &arg : ArgMap->operands()) {
2713 const MDNode *arg_node = dyn_cast<MDNode>(arg.get());
David Netoc6f3ab22018-04-06 18:02:31 -04002714 assert(arg_node->getNumOperands() == 6);
David Neto156783e2017-07-05 15:39:41 -04002715 const auto name =
2716 dyn_cast<MDString>(arg_node->getOperand(0))->getString();
2717 const auto old_index =
2718 dyn_extract<ConstantInt>(arg_node->getOperand(1))->getZExtValue();
2719 const auto new_index =
2720 dyn_extract<ConstantInt>(arg_node->getOperand(2))->getZExtValue();
2721 const auto offset =
2722 dyn_extract<ConstantInt>(arg_node->getOperand(3))->getZExtValue();
David Netoc6f3ab22018-04-06 18:02:31 -04002723 const auto argKind = remap_arg_kind(
2724 dyn_cast<MDString>(arg_node->getOperand(4))->getString());
2725 const auto spec_id =
2726 dyn_extract<ConstantInt>(arg_node->getOperand(5))->getSExtValue();
2727 if (spec_id > 0) {
2728 num_ptr_local++;
2729 FunctionType *fTy =
2730 cast<FunctionType>(F.getType()->getPointerElementType());
David Netoee2660d2018-06-28 16:31:29 -04002731 descriptorMapOut << "kernel," << F.getName() << ",arg," << name
2732 << ",argOrdinal," << old_index << ",argKind,"
2733 << argKind << ",arrayElemSize,"
2734 << DL.getTypeAllocSize(
2735 fTy->getParamType(unsigned(new_index))
2736 ->getPointerElementType())
2737 << ",arrayNumElemSpecId," << spec_id << "\n";
David Netoc6f3ab22018-04-06 18:02:31 -04002738 } else {
2739 descriptorMapOut << "kernel," << F.getName() << ",arg," << name
2740 << ",argOrdinal," << old_index << ",descriptorSet,"
2741 << DescriptorSetIdx << ",binding,"
2742 << (new_index - num_ptr_local) << ",offset,"
2743 << offset << ",argKind," << argKind << "\n";
2744 }
David Neto156783e2017-07-05 15:39:41 -04002745 }
2746 }
2747
David Neto22f144c2017-06-12 14:26:21 -04002748 uint32_t BindingIdx = 0;
David Netoc6f3ab22018-04-06 18:02:31 -04002749 uint32_t arg_index = 0;
David Neto22f144c2017-06-12 14:26:21 -04002750 for (auto &Arg : F.args()) {
David Netoc6f3ab22018-04-06 18:02:31 -04002751 // Always use a binding, unless it's pointer-to-local.
2752 const bool uses_binding = !IsLocalPtr(Arg.getType());
David Neto22f144c2017-06-12 14:26:21 -04002753
David Neto156783e2017-07-05 15:39:41 -04002754 // Emit a descriptor map entry for this arg, in case there was no explicit
2755 // kernel arg mapping metadata.
David Netoc6f3ab22018-04-06 18:02:31 -04002756 auto argKind = remap_arg_kind(clspv::GetArgKindForType(Arg.getType()));
David Neto156783e2017-07-05 15:39:41 -04002757 if (!ArgMap) {
David Netoc6f3ab22018-04-06 18:02:31 -04002758 if (uses_binding) {
2759 descriptorMapOut << "kernel," << F.getName() << ",arg,"
2760 << Arg.getName() << ",argOrdinal," << arg_index
2761 << ",descriptorSet," << DescriptorSetIdx
2762 << ",binding," << BindingIdx << ",offset,0,argKind,"
2763 << argKind << "\n";
2764 } else {
2765 descriptorMapOut << "kernel," << F.getName() << ",arg,"
2766 << Arg.getName() << ",argOrdinal," << arg_index
2767 << ",argKind," << argKind << ",arrayElemSize,"
2768 << DL.getTypeAllocSize(
2769 Arg.getType()->getPointerElementType())
2770 << ",arrayNumElemSpecId," << ArgSpecIdMap[&Arg]
2771 << "\n";
2772 }
David Netoc2c368d2017-06-30 16:50:17 -04002773 }
2774
David Netoc6f3ab22018-04-06 18:02:31 -04002775 if (uses_binding) {
2776 Value *NewGV = ArgGVMap[&Arg];
2777 VMap[&Arg] = VMap[NewGV];
2778 ArgGVIDMap[&Arg] = VMap[&Arg];
David Neto26aaf622017-10-23 18:11:53 -04002779
David Netoc6f3ab22018-04-06 18:02:31 -04002780 if (0 == GVarWithEmittedBindingInfo.count(NewGV)) {
2781 // Generate a new global variable for this argument.
2782 GVarWithEmittedBindingInfo.insert(NewGV);
David Neto22f144c2017-06-12 14:26:21 -04002783
David Netoc6f3ab22018-04-06 18:02:31 -04002784 SPIRVOperandList Ops;
David Neto257c3892018-04-11 13:19:45 -04002785 uint32_t ArgID = 0;
David Neto22f144c2017-06-12 14:26:21 -04002786
David Netoc6f3ab22018-04-06 18:02:31 -04002787 if (uses_binding) {
2788 // Ops[0] = Target ID
2789 // Ops[1] = Decoration (DescriptorSet)
2790 // Ops[2] = LiteralNumber according to Decoration
David Neto22f144c2017-06-12 14:26:21 -04002791
David Neto257c3892018-04-11 13:19:45 -04002792 ArgID = VMap[&Arg];
2793 Ops << MkId(ArgID) << MkNum(spv::DecorationDescriptorSet)
2794 << MkNum(DescriptorSetIdx);
David Neto22f144c2017-06-12 14:26:21 -04002795
David Neto87846742018-04-11 17:36:22 -04002796 auto *DescDecoInst = new SPIRVInstruction(spv::OpDecorate, Ops);
David Netoc6f3ab22018-04-06 18:02:31 -04002797 SPIRVInstList.insert(DecoInsertPoint, DescDecoInst);
David Neto22f144c2017-06-12 14:26:21 -04002798
David Netoc6f3ab22018-04-06 18:02:31 -04002799 // Ops[0] = Target ID
2800 // Ops[1] = Decoration (Binding)
2801 // Ops[2] = LiteralNumber according to Decoration
2802 Ops.clear();
David Neto257c3892018-04-11 13:19:45 -04002803 Ops << MkId(ArgID) << MkNum(spv::DecorationBinding)
2804 << MkNum(BindingIdx);
David Netoc6f3ab22018-04-06 18:02:31 -04002805
David Neto87846742018-04-11 17:36:22 -04002806 auto *BindDecoInst = new SPIRVInstruction(spv::OpDecorate, Ops);
David Netoc6f3ab22018-04-06 18:02:31 -04002807 SPIRVInstList.insert(DecoInsertPoint, BindDecoInst);
2808 }
2809
2810 // Handle image type argument.
2811 bool HasReadOnlyImageType = false;
2812 bool HasWriteOnlyImageType = false;
2813 if (PointerType *ArgPTy = dyn_cast<PointerType>(Arg.getType())) {
2814 if (StructType *STy =
2815 dyn_cast<StructType>(ArgPTy->getElementType())) {
2816 if (STy->isOpaque()) {
2817 if (STy->getName().equals("opencl.image2d_ro_t") ||
2818 STy->getName().equals("opencl.image3d_ro_t")) {
2819 HasReadOnlyImageType = true;
2820 } else if (STy->getName().equals("opencl.image2d_wo_t") ||
2821 STy->getName().equals("opencl.image3d_wo_t")) {
2822 HasWriteOnlyImageType = true;
2823 }
2824 }
David Neto22f144c2017-06-12 14:26:21 -04002825 }
2826 }
David Netoc6f3ab22018-04-06 18:02:31 -04002827
2828 if (HasReadOnlyImageType || HasWriteOnlyImageType) {
2829 // Ops[0] = Target ID
2830 // Ops[1] = Decoration (NonReadable or NonWritable)
2831 Ops.clear();
2832
David Neto257c3892018-04-11 13:19:45 -04002833 Ops << MkId(VMap[&Arg]);
David Netoc6f3ab22018-04-06 18:02:31 -04002834
David Neto257c3892018-04-11 13:19:45 -04002835 // In OpenCL 1.2 an image is either read-only or write-only, but
2836 // never both.
2837 Ops << MkNum(HasReadOnlyImageType ? spv::DecorationNonWritable
2838 : spv::DecorationNonReadable);
David Netoc6f3ab22018-04-06 18:02:31 -04002839
David Neto87846742018-04-11 17:36:22 -04002840 auto *DescDecoInst = new SPIRVInstruction(spv::OpDecorate, Ops);
David Netoc6f3ab22018-04-06 18:02:31 -04002841 SPIRVInstList.insert(DecoInsertPoint, DescDecoInst);
2842 }
2843
2844 // Handle const address space.
2845 if (uses_binding && NewGV->getType()->getPointerAddressSpace() ==
2846 AddressSpace::Constant) {
2847 // Ops[0] = Target ID
2848 // Ops[1] = Decoration (NonWriteable)
2849 Ops.clear();
David Neto257c3892018-04-11 13:19:45 -04002850 assert(ArgID > 0);
2851 Ops << MkId(ArgID) << MkNum(spv::DecorationNonWritable);
David Netoc6f3ab22018-04-06 18:02:31 -04002852
David Neto87846742018-04-11 17:36:22 -04002853 auto *BindDecoInst = new SPIRVInstruction(spv::OpDecorate, Ops);
David Netoc6f3ab22018-04-06 18:02:31 -04002854 SPIRVInstList.insert(DecoInsertPoint, BindDecoInst);
2855 }
David Neto22f144c2017-06-12 14:26:21 -04002856 }
David Netoc6f3ab22018-04-06 18:02:31 -04002857 BindingIdx++;
David Neto22f144c2017-06-12 14:26:21 -04002858 }
David Netoc6f3ab22018-04-06 18:02:31 -04002859 arg_index++;
David Neto22f144c2017-06-12 14:26:21 -04002860 }
2861 }
2862
2863 //
2864 // Generate OPFunction.
2865 //
2866
2867 // FOps[0] : Result Type ID
2868 // FOps[1] : Function Control
2869 // FOps[2] : Function Type ID
2870 SPIRVOperandList FOps;
2871
2872 // Find SPIRV instruction for return type.
David Neto257c3892018-04-11 13:19:45 -04002873 FOps << MkId(lookupType(FTy->getReturnType()));
David Neto22f144c2017-06-12 14:26:21 -04002874
2875 // Check function attributes for SPIRV Function Control.
2876 uint32_t FuncControl = spv::FunctionControlMaskNone;
2877 if (F.hasFnAttribute(Attribute::AlwaysInline)) {
2878 FuncControl |= spv::FunctionControlInlineMask;
2879 }
2880 if (F.hasFnAttribute(Attribute::NoInline)) {
2881 FuncControl |= spv::FunctionControlDontInlineMask;
2882 }
2883 // TODO: Check llvm attribute for Function Control Pure.
2884 if (F.hasFnAttribute(Attribute::ReadOnly)) {
2885 FuncControl |= spv::FunctionControlPureMask;
2886 }
2887 // TODO: Check llvm attribute for Function Control Const.
2888 if (F.hasFnAttribute(Attribute::ReadNone)) {
2889 FuncControl |= spv::FunctionControlConstMask;
2890 }
2891
David Neto257c3892018-04-11 13:19:45 -04002892 FOps << MkNum(FuncControl);
David Neto22f144c2017-06-12 14:26:21 -04002893
2894 uint32_t FTyID;
2895 if (F.getCallingConv() == CallingConv::SPIR_KERNEL) {
2896 SmallVector<Type *, 4> NewFuncParamTys;
2897 FunctionType *NewFTy =
2898 FunctionType::get(FTy->getReturnType(), NewFuncParamTys, false);
2899 FTyID = lookupType(NewFTy);
2900 } else {
David Neto9ed8e2f2018-03-24 06:47:24 -07002901 // Handle regular function with global constant parameters.
David Neto22f144c2017-06-12 14:26:21 -04002902 if (GlobalConstFuncTyMap.count(FTy)) {
2903 FTyID = lookupType(GlobalConstFuncTyMap[FTy].first);
2904 } else {
2905 FTyID = lookupType(FTy);
2906 }
2907 }
2908
David Neto257c3892018-04-11 13:19:45 -04002909 FOps << MkId(FTyID);
David Neto22f144c2017-06-12 14:26:21 -04002910
2911 if (F.getCallingConv() == CallingConv::SPIR_KERNEL) {
2912 EntryPoints.push_back(std::make_pair(&F, nextID));
2913 }
2914
2915 VMap[&F] = nextID;
2916
David Neto482550a2018-03-24 05:21:07 -07002917 if (clspv::Option::ShowIDs()) {
David Netob05675d2018-02-16 12:37:49 -05002918 errs() << "Function " << F.getName() << " is " << nextID << "\n";
2919 }
David Neto22f144c2017-06-12 14:26:21 -04002920 // Generate SPIRV instruction for function.
David Neto87846742018-04-11 17:36:22 -04002921 auto *FuncInst = new SPIRVInstruction(spv::OpFunction, nextID++, FOps);
David Neto22f144c2017-06-12 14:26:21 -04002922 SPIRVInstList.push_back(FuncInst);
2923
2924 //
2925 // Generate OpFunctionParameter for Normal function.
2926 //
2927
2928 if (F.getCallingConv() != CallingConv::SPIR_KERNEL) {
2929 // Iterate Argument for name instead of param type from function type.
2930 unsigned ArgIdx = 0;
2931 for (Argument &Arg : F.args()) {
2932 VMap[&Arg] = nextID;
2933
2934 // ParamOps[0] : Result Type ID
2935 SPIRVOperandList ParamOps;
2936
2937 // Find SPIRV instruction for parameter type.
2938 uint32_t ParamTyID = lookupType(Arg.getType());
2939 if (PointerType *PTy = dyn_cast<PointerType>(Arg.getType())) {
2940 if (GlobalConstFuncTyMap.count(FTy)) {
2941 if (ArgIdx == GlobalConstFuncTyMap[FTy].second) {
2942 Type *EleTy = PTy->getPointerElementType();
2943 Type *ArgTy =
2944 PointerType::get(EleTy, AddressSpace::ModuleScopePrivate);
2945 ParamTyID = lookupType(ArgTy);
2946 GlobalConstArgSet.insert(&Arg);
2947 }
2948 }
2949 }
David Neto257c3892018-04-11 13:19:45 -04002950 ParamOps << MkId(ParamTyID);
David Neto22f144c2017-06-12 14:26:21 -04002951
2952 // Generate SPIRV instruction for parameter.
David Neto87846742018-04-11 17:36:22 -04002953 auto *ParamInst =
2954 new SPIRVInstruction(spv::OpFunctionParameter, nextID++, ParamOps);
David Neto22f144c2017-06-12 14:26:21 -04002955 SPIRVInstList.push_back(ParamInst);
2956
2957 ArgIdx++;
2958 }
2959 }
2960}
2961
David Neto5c22a252018-03-15 16:07:41 -04002962void SPIRVProducerPass::GenerateModuleInfo(Module& module) {
David Neto22f144c2017-06-12 14:26:21 -04002963 SPIRVInstructionList &SPIRVInstList = getSPIRVInstList();
2964 EntryPointVecType &EntryPoints = getEntryPointVec();
2965 ValueMapType &VMap = getValueMap();
2966 ValueList &EntryPointInterfaces = getEntryPointInterfacesVec();
2967 uint32_t &ExtInstImportID = getOpExtInstImportID();
2968 std::vector<uint32_t> &BuiltinDimVec = getBuiltinDimVec();
2969
2970 // Set up insert point.
2971 auto InsertPoint = SPIRVInstList.begin();
2972
2973 //
2974 // Generate OpCapability
2975 //
2976 // TODO: Which llvm information is mapped to SPIRV Capapbility?
2977
2978 // Ops[0] = Capability
2979 SPIRVOperandList Ops;
2980
David Neto87846742018-04-11 17:36:22 -04002981 auto *CapInst =
2982 new SPIRVInstruction(spv::OpCapability, {MkNum(spv::CapabilityShader)});
David Neto22f144c2017-06-12 14:26:21 -04002983 SPIRVInstList.insert(InsertPoint, CapInst);
2984
2985 for (Type *Ty : getTypeList()) {
2986 // Find the i16 type.
2987 if (Ty->isIntegerTy(16)) {
2988 // Generate OpCapability for i16 type.
David Neto87846742018-04-11 17:36:22 -04002989 SPIRVInstList.insert(InsertPoint,
2990 new SPIRVInstruction(spv::OpCapability,
2991 {MkNum(spv::CapabilityInt16)}));
David Neto22f144c2017-06-12 14:26:21 -04002992 } else if (Ty->isIntegerTy(64)) {
2993 // Generate OpCapability for i64 type.
David Neto87846742018-04-11 17:36:22 -04002994 SPIRVInstList.insert(InsertPoint,
2995 new SPIRVInstruction(spv::OpCapability,
2996 {MkNum(spv::CapabilityInt64)}));
David Neto22f144c2017-06-12 14:26:21 -04002997 } else if (Ty->isHalfTy()) {
2998 // Generate OpCapability for half type.
2999 SPIRVInstList.insert(
David Neto87846742018-04-11 17:36:22 -04003000 InsertPoint, new SPIRVInstruction(spv::OpCapability,
3001 {MkNum(spv::CapabilityFloat16)}));
David Neto22f144c2017-06-12 14:26:21 -04003002 } else if (Ty->isDoubleTy()) {
3003 // Generate OpCapability for double type.
3004 SPIRVInstList.insert(
David Neto87846742018-04-11 17:36:22 -04003005 InsertPoint, new SPIRVInstruction(spv::OpCapability,
3006 {MkNum(spv::CapabilityFloat64)}));
David Neto22f144c2017-06-12 14:26:21 -04003007 } else if (auto *STy = dyn_cast<StructType>(Ty)) {
3008 if (STy->isOpaque()) {
David Neto565571c2017-08-21 12:00:05 -04003009 if (STy->getName().equals("opencl.image2d_wo_t") ||
3010 STy->getName().equals("opencl.image3d_wo_t")) {
David Neto22f144c2017-06-12 14:26:21 -04003011 // Generate OpCapability for write only image type.
3012 SPIRVInstList.insert(
3013 InsertPoint,
3014 new SPIRVInstruction(
David Neto87846742018-04-11 17:36:22 -04003015 spv::OpCapability,
3016 {MkNum(spv::CapabilityStorageImageWriteWithoutFormat)}));
David Neto22f144c2017-06-12 14:26:21 -04003017 }
3018 }
3019 }
3020 }
3021
David Neto5c22a252018-03-15 16:07:41 -04003022 { // OpCapability ImageQuery
3023 bool hasImageQuery = false;
3024 for (const char *imageQuery : {
3025 "_Z15get_image_width14ocl_image2d_ro",
3026 "_Z15get_image_width14ocl_image2d_wo",
3027 "_Z16get_image_height14ocl_image2d_ro",
3028 "_Z16get_image_height14ocl_image2d_wo",
3029 }) {
3030 if (module.getFunction(imageQuery)) {
3031 hasImageQuery = true;
3032 break;
3033 }
3034 }
3035 if (hasImageQuery) {
David Neto87846742018-04-11 17:36:22 -04003036 auto *ImageQueryCapInst = new SPIRVInstruction(
3037 spv::OpCapability, {MkNum(spv::CapabilityImageQuery)});
David Neto5c22a252018-03-15 16:07:41 -04003038 SPIRVInstList.insert(InsertPoint, ImageQueryCapInst);
3039 }
3040 }
3041
David Neto22f144c2017-06-12 14:26:21 -04003042 if (hasVariablePointers()) {
3043 //
3044 // Generate OpCapability and OpExtension
3045 //
3046
3047 //
3048 // Generate OpCapability.
3049 //
3050 // Ops[0] = Capability
3051 //
3052 Ops.clear();
David Neto257c3892018-04-11 13:19:45 -04003053 Ops << MkNum(spv::CapabilityVariablePointers);
David Neto22f144c2017-06-12 14:26:21 -04003054
David Neto87846742018-04-11 17:36:22 -04003055 SPIRVInstList.insert(InsertPoint,
3056 new SPIRVInstruction(spv::OpCapability, Ops));
David Neto22f144c2017-06-12 14:26:21 -04003057
3058 //
3059 // Generate OpExtension.
3060 //
3061 // Ops[0] = Name (Literal String)
3062 //
David Netoa772fd12017-08-04 14:17:33 -04003063 for (auto extension : {"SPV_KHR_storage_buffer_storage_class",
3064 "SPV_KHR_variable_pointers"}) {
David Neto22f144c2017-06-12 14:26:21 -04003065
David Neto87846742018-04-11 17:36:22 -04003066 auto *ExtensionInst =
3067 new SPIRVInstruction(spv::OpExtension, {MkString(extension)});
David Netoa772fd12017-08-04 14:17:33 -04003068 SPIRVInstList.insert(InsertPoint, ExtensionInst);
David Neto22f144c2017-06-12 14:26:21 -04003069 }
David Neto22f144c2017-06-12 14:26:21 -04003070 }
3071
3072 if (ExtInstImportID) {
3073 ++InsertPoint;
3074 }
3075
3076 //
3077 // Generate OpMemoryModel
3078 //
3079 // Memory model for Vulkan will always be GLSL450.
3080
3081 // Ops[0] = Addressing Model
3082 // Ops[1] = Memory Model
3083 Ops.clear();
David Neto257c3892018-04-11 13:19:45 -04003084 Ops << MkNum(spv::AddressingModelLogical) << MkNum(spv::MemoryModelGLSL450);
David Neto22f144c2017-06-12 14:26:21 -04003085
David Neto87846742018-04-11 17:36:22 -04003086 auto *MemModelInst = new SPIRVInstruction(spv::OpMemoryModel, Ops);
David Neto22f144c2017-06-12 14:26:21 -04003087 SPIRVInstList.insert(InsertPoint, MemModelInst);
3088
3089 //
3090 // Generate OpEntryPoint
3091 //
3092 for (auto EntryPoint : EntryPoints) {
3093 // Ops[0] = Execution Model
3094 // Ops[1] = EntryPoint ID
3095 // Ops[2] = Name (Literal String)
3096 // ...
3097 //
3098 // TODO: Do we need to consider Interface ID for forward references???
3099 Ops.clear();
David Neto257c3892018-04-11 13:19:45 -04003100 const StringRef& name = EntryPoint.first->getName();
3101 Ops << MkNum(spv::ExecutionModelGLCompute) << MkId(EntryPoint.second)
3102 << MkString(name);
David Neto22f144c2017-06-12 14:26:21 -04003103
David Neto22f144c2017-06-12 14:26:21 -04003104 for (Value *Interface : EntryPointInterfaces) {
David Neto257c3892018-04-11 13:19:45 -04003105 Ops << MkId(VMap[Interface]);
David Neto22f144c2017-06-12 14:26:21 -04003106 }
3107
David Neto87846742018-04-11 17:36:22 -04003108 auto *EntryPointInst = new SPIRVInstruction(spv::OpEntryPoint, Ops);
David Neto22f144c2017-06-12 14:26:21 -04003109 SPIRVInstList.insert(InsertPoint, EntryPointInst);
3110 }
3111
3112 for (auto EntryPoint : EntryPoints) {
3113 if (const MDNode *MD = dyn_cast<Function>(EntryPoint.first)
3114 ->getMetadata("reqd_work_group_size")) {
3115
3116 if (!BuiltinDimVec.empty()) {
3117 llvm_unreachable(
3118 "Kernels should have consistent work group size definition");
3119 }
3120
3121 //
3122 // Generate OpExecutionMode
3123 //
3124
3125 // Ops[0] = Entry Point ID
3126 // Ops[1] = Execution Mode
3127 // Ops[2] ... Ops[n] = Optional literals according to Execution Mode
3128 Ops.clear();
David Neto257c3892018-04-11 13:19:45 -04003129 Ops << MkId(EntryPoint.second)
3130 << MkNum(spv::ExecutionModeLocalSize);
David Neto22f144c2017-06-12 14:26:21 -04003131
3132 uint32_t XDim = static_cast<uint32_t>(
3133 mdconst::extract<ConstantInt>(MD->getOperand(0))->getZExtValue());
3134 uint32_t YDim = static_cast<uint32_t>(
3135 mdconst::extract<ConstantInt>(MD->getOperand(1))->getZExtValue());
3136 uint32_t ZDim = static_cast<uint32_t>(
3137 mdconst::extract<ConstantInt>(MD->getOperand(2))->getZExtValue());
3138
David Neto257c3892018-04-11 13:19:45 -04003139 Ops << MkNum(XDim) << MkNum(YDim) << MkNum(ZDim);
David Neto22f144c2017-06-12 14:26:21 -04003140
David Neto87846742018-04-11 17:36:22 -04003141 auto *ExecModeInst = new SPIRVInstruction(spv::OpExecutionMode, Ops);
David Neto22f144c2017-06-12 14:26:21 -04003142 SPIRVInstList.insert(InsertPoint, ExecModeInst);
3143 }
3144 }
3145
3146 //
3147 // Generate OpSource.
3148 //
3149 // Ops[0] = SourceLanguage ID
3150 // Ops[1] = Version (LiteralNum)
3151 //
3152 Ops.clear();
David Neto257c3892018-04-11 13:19:45 -04003153 Ops << MkNum(spv::SourceLanguageOpenCL_C) << MkNum(120);
David Neto22f144c2017-06-12 14:26:21 -04003154
David Neto87846742018-04-11 17:36:22 -04003155 auto *OpenSourceInst = new SPIRVInstruction(spv::OpSource, Ops);
David Neto22f144c2017-06-12 14:26:21 -04003156 SPIRVInstList.insert(InsertPoint, OpenSourceInst);
3157
3158 if (!BuiltinDimVec.empty()) {
3159 //
3160 // Generate OpDecorates for x/y/z dimension.
3161 //
3162 // Ops[0] = Target ID
3163 // Ops[1] = Decoration (SpecId)
David Neto257c3892018-04-11 13:19:45 -04003164 // Ops[2] = Specialization Constant ID (Literal Number)
David Neto22f144c2017-06-12 14:26:21 -04003165
3166 // X Dimension
3167 Ops.clear();
David Neto257c3892018-04-11 13:19:45 -04003168 Ops << MkId(BuiltinDimVec[0]) << MkNum(spv::DecorationSpecId) << MkNum(0);
David Neto87846742018-04-11 17:36:22 -04003169 SPIRVInstList.insert(InsertPoint,
3170 new SPIRVInstruction(spv::OpDecorate, Ops));
David Neto22f144c2017-06-12 14:26:21 -04003171
3172 // Y Dimension
3173 Ops.clear();
David Neto257c3892018-04-11 13:19:45 -04003174 Ops << MkId(BuiltinDimVec[1]) << MkNum(spv::DecorationSpecId) << MkNum(1);
David Neto87846742018-04-11 17:36:22 -04003175 SPIRVInstList.insert(InsertPoint,
3176 new SPIRVInstruction(spv::OpDecorate, Ops));
David Neto22f144c2017-06-12 14:26:21 -04003177
3178 // Z Dimension
3179 Ops.clear();
David Neto257c3892018-04-11 13:19:45 -04003180 Ops << MkId(BuiltinDimVec[2]) << MkNum(spv::DecorationSpecId) << MkNum(2);
David Neto87846742018-04-11 17:36:22 -04003181 SPIRVInstList.insert(InsertPoint,
3182 new SPIRVInstruction(spv::OpDecorate, Ops));
David Neto22f144c2017-06-12 14:26:21 -04003183 }
3184}
3185
3186void SPIRVProducerPass::GenerateInstForArg(Function &F) {
3187 SPIRVInstructionList &SPIRVInstList = getSPIRVInstList();
3188 ValueMapType &VMap = getValueMap();
3189 Module *Module = F.getParent();
3190 LLVMContext &Context = Module->getContext();
3191 ValueToValueMapTy &ArgGVMap = getArgumentGVMap();
3192
3193 for (Argument &Arg : F.args()) {
3194 if (Arg.use_empty()) {
3195 continue;
3196 }
3197
David Netoc6f3ab22018-04-06 18:02:31 -04003198 Type *ArgTy = Arg.getType();
3199 if (IsLocalPtr(ArgTy)) {
3200 // Generate OpAccessChain to point to the first element of the array.
3201 const LocalArgInfo &info = LocalArgMap[&Arg];
3202 VMap[&Arg] = info.first_elem_ptr_id;
3203
3204 SPIRVOperandList Ops;
3205 uint32_t zeroId = VMap[ConstantInt::get(Type::getInt32Ty(Context), 0)];
3206 Ops << MkId(lookupType(ArgTy)) << MkId(info.variable_id) << MkId(zeroId);
3207 SPIRVInstList.push_back(new SPIRVInstruction(
David Neto87846742018-04-11 17:36:22 -04003208 spv::OpAccessChain, info.first_elem_ptr_id, Ops));
David Netoc6f3ab22018-04-06 18:02:31 -04003209
3210 continue;
3211 }
3212
David Neto22f144c2017-06-12 14:26:21 -04003213 // Check the type of users of arguments.
3214 bool HasOnlyGEPUse = true;
3215 for (auto *U : Arg.users()) {
3216 if (!isa<GetElementPtrInst>(U) && isa<Instruction>(U)) {
3217 HasOnlyGEPUse = false;
3218 break;
3219 }
3220 }
3221
David Neto22f144c2017-06-12 14:26:21 -04003222 if (PointerType *PTy = dyn_cast<PointerType>(ArgTy)) {
3223 if (StructType *STy = dyn_cast<StructType>(PTy->getElementType())) {
3224 if (STy->isOpaque()) {
3225 // Generate OpLoad for sampler and image types.
3226 if (STy->getName().equals("opencl.sampler_t") ||
3227 STy->getName().equals("opencl.image2d_ro_t") ||
3228 STy->getName().equals("opencl.image2d_wo_t") ||
3229 STy->getName().equals("opencl.image3d_ro_t") ||
3230 STy->getName().equals("opencl.image3d_wo_t")) {
3231 //
3232 // Generate OpLoad.
3233 //
3234 // Ops[0] = Result Type ID
3235 // Ops[1] = Pointer ID
3236 // Ops[2] ... Ops[n] = Optional Memory Access
3237 //
3238 // TODO: Do we need to implement Optional Memory Access???
3239 SPIRVOperandList Ops;
3240
3241 // Use type with address space modified.
3242 ArgTy = ArgGVMap[&Arg]->getType()->getPointerElementType();
3243
David Neto257c3892018-04-11 13:19:45 -04003244 Ops << MkId(lookupType(ArgTy));
David Neto22f144c2017-06-12 14:26:21 -04003245
3246 uint32_t PointerID = VMap[&Arg];
David Neto257c3892018-04-11 13:19:45 -04003247 Ops << MkId(PointerID);
David Neto22f144c2017-06-12 14:26:21 -04003248
3249 VMap[&Arg] = nextID;
David Neto87846742018-04-11 17:36:22 -04003250 auto *Inst = new SPIRVInstruction(spv::OpLoad, nextID++, Ops);
David Neto22f144c2017-06-12 14:26:21 -04003251 SPIRVInstList.push_back(Inst);
3252 continue;
3253 }
3254 }
3255 }
3256
3257 if (!HasOnlyGEPUse) {
3258 //
3259 // Generate OpAccessChain.
3260 //
3261 // Ops[0] = Result Type ID
3262 // Ops[1] = Base ID
3263 // Ops[2] ... Ops[n] = Indexes ID
3264 SPIRVOperandList Ops;
3265
3266 uint32_t ResTyID = lookupType(ArgTy);
3267 if (!isa<PointerType>(ArgTy)) {
3268 ResTyID = lookupType(PointerType::get(ArgTy, AddressSpace::Global));
3269 }
David Neto257c3892018-04-11 13:19:45 -04003270 Ops << MkId(ResTyID);
David Neto22f144c2017-06-12 14:26:21 -04003271
3272 uint32_t BaseID = VMap[&Arg];
David Neto257c3892018-04-11 13:19:45 -04003273 Ops << MkId(BaseID) << MkId(GetI32Zero())
3274 << MkId(GetI32Zero());
David Neto22f144c2017-06-12 14:26:21 -04003275
3276 // Generate SPIRV instruction for argument.
3277 VMap[&Arg] = nextID;
David Neto87846742018-04-11 17:36:22 -04003278 auto *ArgInst = new SPIRVInstruction(spv::OpAccessChain, nextID++, Ops);
David Neto22f144c2017-06-12 14:26:21 -04003279 SPIRVInstList.push_back(ArgInst);
3280 } else {
3281 // For GEP uses, generate OpAccessChain with folding GEP ahead of GEP.
3282 // Nothing to do here.
3283 }
3284 } else {
3285 //
3286 // Generate OpAccessChain and OpLoad for non-pointer type argument.
3287 //
3288
3289 //
3290 // Generate OpAccessChain.
3291 //
3292 // Ops[0] = Result Type ID
3293 // Ops[1] = Base ID
3294 // Ops[2] ... Ops[n] = Indexes ID
3295 SPIRVOperandList Ops;
3296
3297 uint32_t ResTyID = lookupType(ArgTy);
3298 if (!isa<PointerType>(ArgTy)) {
David Neto482550a2018-03-24 05:21:07 -07003299 auto AS = clspv::Option::PodArgsInUniformBuffer()
3300 ? AddressSpace::Uniform
3301 : AddressSpace::Global;
David Netoe439d702018-03-23 13:14:08 -07003302 ResTyID = lookupType(PointerType::get(ArgTy, AS));
David Neto22f144c2017-06-12 14:26:21 -04003303 }
David Neto257c3892018-04-11 13:19:45 -04003304 Ops << MkId(ResTyID);
David Neto22f144c2017-06-12 14:26:21 -04003305
3306 uint32_t BaseID = VMap[&Arg];
David Neto257c3892018-04-11 13:19:45 -04003307 Ops << MkId(BaseID) << MkId(GetI32Zero());
David Neto22f144c2017-06-12 14:26:21 -04003308
3309 // Generate SPIRV instruction for argument.
3310 uint32_t PointerID = nextID;
3311 VMap[&Arg] = nextID;
David Neto87846742018-04-11 17:36:22 -04003312 auto *ArgInst = new SPIRVInstruction(spv::OpAccessChain, nextID++, Ops);
David Neto22f144c2017-06-12 14:26:21 -04003313 SPIRVInstList.push_back(ArgInst);
3314
3315 //
3316 // Generate OpLoad.
3317 //
3318
3319 // Ops[0] = Result Type ID
3320 // Ops[1] = Pointer ID
3321 // Ops[2] ... Ops[n] = Optional Memory Access
3322 //
3323 // TODO: Do we need to implement Optional Memory Access???
3324 Ops.clear();
David Neto257c3892018-04-11 13:19:45 -04003325 Ops << MkId(lookupType(ArgTy)) << MkId(PointerID);
David Neto22f144c2017-06-12 14:26:21 -04003326
3327 VMap[&Arg] = nextID;
David Neto87846742018-04-11 17:36:22 -04003328 auto *Inst = new SPIRVInstruction(spv::OpLoad, nextID++, Ops);
David Neto22f144c2017-06-12 14:26:21 -04003329 SPIRVInstList.push_back(Inst);
3330 }
3331 }
3332}
3333
David Netob6e2e062018-04-25 10:32:06 -04003334void SPIRVProducerPass::GenerateEntryPointInitialStores() {
3335 // Work around a driver bug. Initializers on Private variables might not
3336 // work. So the start of the kernel should store the initializer value to the
3337 // variables. Yes, *every* entry point pays this cost if *any* entry point
3338 // uses this builtin. At this point I judge this to be an acceptable tradeoff
3339 // of complexity vs. runtime, for a broken driver.
3340 // TODO(dneto): Remove this at some point once fixed drivers are widely available.
3341 if (WorkgroupSizeVarID) {
3342 assert(WorkgroupSizeValueID);
3343
3344 SPIRVOperandList Ops;
3345 Ops << MkId(WorkgroupSizeVarID) << MkId(WorkgroupSizeValueID);
3346
3347 auto *Inst = new SPIRVInstruction(spv::OpStore, Ops);
3348 getSPIRVInstList().push_back(Inst);
3349 }
3350}
3351
David Neto22f144c2017-06-12 14:26:21 -04003352void SPIRVProducerPass::GenerateFuncBody(Function &F) {
3353 SPIRVInstructionList &SPIRVInstList = getSPIRVInstList();
3354 ValueMapType &VMap = getValueMap();
3355
David Netob6e2e062018-04-25 10:32:06 -04003356 const bool IsKernel = F.getCallingConv() == CallingConv::SPIR_KERNEL;
David Neto22f144c2017-06-12 14:26:21 -04003357
3358 for (BasicBlock &BB : F) {
3359 // Register BasicBlock to ValueMap.
3360 VMap[&BB] = nextID;
3361
3362 //
3363 // Generate OpLabel for Basic Block.
3364 //
3365 SPIRVOperandList Ops;
David Neto87846742018-04-11 17:36:22 -04003366 auto *Inst = new SPIRVInstruction(spv::OpLabel, nextID++, Ops);
David Neto22f144c2017-06-12 14:26:21 -04003367 SPIRVInstList.push_back(Inst);
3368
David Neto6dcd4712017-06-23 11:06:47 -04003369 // OpVariable instructions must come first.
3370 for (Instruction &I : BB) {
3371 if (isa<AllocaInst>(I)) {
3372 GenerateInstruction(I);
3373 }
3374 }
3375
David Neto22f144c2017-06-12 14:26:21 -04003376 if (&BB == &F.getEntryBlock() && IsKernel) {
David Netob6e2e062018-04-25 10:32:06 -04003377 if (clspv::Option::HackInitializers()) {
3378 GenerateEntryPointInitialStores();
3379 }
David Neto22f144c2017-06-12 14:26:21 -04003380 GenerateInstForArg(F);
3381 }
3382
3383 for (Instruction &I : BB) {
David Neto6dcd4712017-06-23 11:06:47 -04003384 if (!isa<AllocaInst>(I)) {
3385 GenerateInstruction(I);
3386 }
David Neto22f144c2017-06-12 14:26:21 -04003387 }
3388 }
3389}
3390
3391spv::Op SPIRVProducerPass::GetSPIRVCmpOpcode(CmpInst *I) {
3392 const std::map<CmpInst::Predicate, spv::Op> Map = {
3393 {CmpInst::ICMP_EQ, spv::OpIEqual},
3394 {CmpInst::ICMP_NE, spv::OpINotEqual},
3395 {CmpInst::ICMP_UGT, spv::OpUGreaterThan},
3396 {CmpInst::ICMP_UGE, spv::OpUGreaterThanEqual},
3397 {CmpInst::ICMP_ULT, spv::OpULessThan},
3398 {CmpInst::ICMP_ULE, spv::OpULessThanEqual},
3399 {CmpInst::ICMP_SGT, spv::OpSGreaterThan},
3400 {CmpInst::ICMP_SGE, spv::OpSGreaterThanEqual},
3401 {CmpInst::ICMP_SLT, spv::OpSLessThan},
3402 {CmpInst::ICMP_SLE, spv::OpSLessThanEqual},
3403 {CmpInst::FCMP_OEQ, spv::OpFOrdEqual},
3404 {CmpInst::FCMP_OGT, spv::OpFOrdGreaterThan},
3405 {CmpInst::FCMP_OGE, spv::OpFOrdGreaterThanEqual},
3406 {CmpInst::FCMP_OLT, spv::OpFOrdLessThan},
3407 {CmpInst::FCMP_OLE, spv::OpFOrdLessThanEqual},
3408 {CmpInst::FCMP_ONE, spv::OpFOrdNotEqual},
3409 {CmpInst::FCMP_UEQ, spv::OpFUnordEqual},
3410 {CmpInst::FCMP_UGT, spv::OpFUnordGreaterThan},
3411 {CmpInst::FCMP_UGE, spv::OpFUnordGreaterThanEqual},
3412 {CmpInst::FCMP_ULT, spv::OpFUnordLessThan},
3413 {CmpInst::FCMP_ULE, spv::OpFUnordLessThanEqual},
3414 {CmpInst::FCMP_UNE, spv::OpFUnordNotEqual}};
3415
3416 assert(0 != Map.count(I->getPredicate()));
3417
3418 return Map.at(I->getPredicate());
3419}
3420
3421spv::Op SPIRVProducerPass::GetSPIRVCastOpcode(Instruction &I) {
3422 const std::map<unsigned, spv::Op> Map{
3423 {Instruction::Trunc, spv::OpUConvert},
3424 {Instruction::ZExt, spv::OpUConvert},
3425 {Instruction::SExt, spv::OpSConvert},
3426 {Instruction::FPToUI, spv::OpConvertFToU},
3427 {Instruction::FPToSI, spv::OpConvertFToS},
3428 {Instruction::UIToFP, spv::OpConvertUToF},
3429 {Instruction::SIToFP, spv::OpConvertSToF},
3430 {Instruction::FPTrunc, spv::OpFConvert},
3431 {Instruction::FPExt, spv::OpFConvert},
3432 {Instruction::BitCast, spv::OpBitcast}};
3433
3434 assert(0 != Map.count(I.getOpcode()));
3435
3436 return Map.at(I.getOpcode());
3437}
3438
3439spv::Op SPIRVProducerPass::GetSPIRVBinaryOpcode(Instruction &I) {
3440 if (I.getType()->isIntegerTy(1)) {
3441 switch (I.getOpcode()) {
3442 default:
3443 break;
3444 case Instruction::Or:
3445 return spv::OpLogicalOr;
3446 case Instruction::And:
3447 return spv::OpLogicalAnd;
3448 case Instruction::Xor:
3449 return spv::OpLogicalNotEqual;
3450 }
3451 }
3452
3453 const std::map<unsigned, spv::Op> Map {
3454 {Instruction::Add, spv::OpIAdd},
3455 {Instruction::FAdd, spv::OpFAdd},
3456 {Instruction::Sub, spv::OpISub},
3457 {Instruction::FSub, spv::OpFSub},
3458 {Instruction::Mul, spv::OpIMul},
3459 {Instruction::FMul, spv::OpFMul},
3460 {Instruction::UDiv, spv::OpUDiv},
3461 {Instruction::SDiv, spv::OpSDiv},
3462 {Instruction::FDiv, spv::OpFDiv},
3463 {Instruction::URem, spv::OpUMod},
3464 {Instruction::SRem, spv::OpSRem},
3465 {Instruction::FRem, spv::OpFRem},
3466 {Instruction::Or, spv::OpBitwiseOr},
3467 {Instruction::Xor, spv::OpBitwiseXor},
3468 {Instruction::And, spv::OpBitwiseAnd},
3469 {Instruction::Shl, spv::OpShiftLeftLogical},
3470 {Instruction::LShr, spv::OpShiftRightLogical},
3471 {Instruction::AShr, spv::OpShiftRightArithmetic}};
3472
3473 assert(0 != Map.count(I.getOpcode()));
3474
3475 return Map.at(I.getOpcode());
3476}
3477
3478void SPIRVProducerPass::GenerateInstruction(Instruction &I) {
3479 SPIRVInstructionList &SPIRVInstList = getSPIRVInstList();
3480 ValueMapType &VMap = getValueMap();
3481 ValueToValueMapTy &ArgGVMap = getArgumentGVMap();
3482 ValueMapType &ArgGVIDMap = getArgumentGVIDMap();
3483 DeferredInstVecType &DeferredInsts = getDeferredInstVec();
3484 LLVMContext &Context = I.getParent()->getParent()->getParent()->getContext();
3485
3486 // Register Instruction to ValueMap.
3487 if (0 == VMap[&I]) {
3488 VMap[&I] = nextID;
3489 }
3490
3491 switch (I.getOpcode()) {
3492 default: {
3493 if (Instruction::isCast(I.getOpcode())) {
3494 //
3495 // Generate SPIRV instructions for cast operators.
3496 //
3497
David Netod2de94a2017-08-28 17:27:47 -04003498
3499 auto Ty = I.getType();
David Neto22f144c2017-06-12 14:26:21 -04003500 auto OpTy = I.getOperand(0)->getType();
David Netod2de94a2017-08-28 17:27:47 -04003501 auto toI8 = Ty == Type::getInt8Ty(Context);
3502 auto fromI32 = OpTy == Type::getInt32Ty(Context);
David Neto22f144c2017-06-12 14:26:21 -04003503 // Handle zext, sext and uitofp with i1 type specially.
3504 if ((I.getOpcode() == Instruction::ZExt ||
3505 I.getOpcode() == Instruction::SExt ||
3506 I.getOpcode() == Instruction::UIToFP) &&
3507 (OpTy->isIntegerTy(1) ||
3508 (OpTy->isVectorTy() &&
3509 OpTy->getVectorElementType()->isIntegerTy(1)))) {
3510 //
3511 // Generate OpSelect.
3512 //
3513
3514 // Ops[0] = Result Type ID
3515 // Ops[1] = Condition ID
3516 // Ops[2] = True Constant ID
3517 // Ops[3] = False Constant ID
3518 SPIRVOperandList Ops;
3519
David Neto257c3892018-04-11 13:19:45 -04003520 Ops << MkId(lookupType(I.getType()));
David Neto22f144c2017-06-12 14:26:21 -04003521
David Neto22f144c2017-06-12 14:26:21 -04003522 uint32_t CondID = VMap[I.getOperand(0)];
David Neto257c3892018-04-11 13:19:45 -04003523 Ops << MkId(CondID);
David Neto22f144c2017-06-12 14:26:21 -04003524
3525 uint32_t TrueID = 0;
3526 if (I.getOpcode() == Instruction::ZExt) {
3527 APInt One(32, 1);
3528 TrueID = VMap[Constant::getIntegerValue(I.getType(), One)];
3529 } else if (I.getOpcode() == Instruction::SExt) {
3530 APInt MinusOne(32, UINT64_MAX, true);
3531 TrueID = VMap[Constant::getIntegerValue(I.getType(), MinusOne)];
3532 } else {
3533 TrueID = VMap[ConstantFP::get(Context, APFloat(1.0f))];
3534 }
David Neto257c3892018-04-11 13:19:45 -04003535 Ops << MkId(TrueID);
David Neto22f144c2017-06-12 14:26:21 -04003536
3537 uint32_t FalseID = 0;
3538 if (I.getOpcode() == Instruction::ZExt) {
3539 FalseID = VMap[Constant::getNullValue(I.getType())];
3540 } else if (I.getOpcode() == Instruction::SExt) {
3541 FalseID = VMap[Constant::getNullValue(I.getType())];
3542 } else {
3543 FalseID = VMap[ConstantFP::get(Context, APFloat(0.0f))];
3544 }
David Neto257c3892018-04-11 13:19:45 -04003545 Ops << MkId(FalseID);
David Neto22f144c2017-06-12 14:26:21 -04003546
David Neto87846742018-04-11 17:36:22 -04003547 auto *Inst = new SPIRVInstruction(spv::OpSelect, nextID++, Ops);
David Neto22f144c2017-06-12 14:26:21 -04003548 SPIRVInstList.push_back(Inst);
David Netod2de94a2017-08-28 17:27:47 -04003549 } else if (I.getOpcode() == Instruction::Trunc && fromI32 && toI8) {
3550 // The SPIR-V target type is a 32-bit int. Keep only the bottom
3551 // 8 bits.
3552 // Before:
3553 // %result = trunc i32 %a to i8
3554 // After
3555 // %result = OpBitwiseAnd %uint %a %uint_255
3556
3557 SPIRVOperandList Ops;
3558
David Neto257c3892018-04-11 13:19:45 -04003559 Ops << MkId(lookupType(OpTy)) << MkId(VMap[I.getOperand(0)]);
David Netod2de94a2017-08-28 17:27:47 -04003560
3561 Type *UintTy = Type::getInt32Ty(Context);
3562 uint32_t MaskID = VMap[ConstantInt::get(UintTy, 255)];
David Neto257c3892018-04-11 13:19:45 -04003563 Ops << MkId(MaskID);
David Netod2de94a2017-08-28 17:27:47 -04003564
David Neto87846742018-04-11 17:36:22 -04003565 auto *Inst = new SPIRVInstruction(spv::OpBitwiseAnd, nextID++, Ops);
David Netod2de94a2017-08-28 17:27:47 -04003566 SPIRVInstList.push_back(Inst);
David Neto22f144c2017-06-12 14:26:21 -04003567 } else {
3568 // Ops[0] = Result Type ID
3569 // Ops[1] = Source Value ID
3570 SPIRVOperandList Ops;
3571
David Neto257c3892018-04-11 13:19:45 -04003572 Ops << MkId(lookupType(I.getType())) << MkId(VMap[I.getOperand(0)]);
David Neto22f144c2017-06-12 14:26:21 -04003573
David Neto87846742018-04-11 17:36:22 -04003574 auto *Inst = new SPIRVInstruction(GetSPIRVCastOpcode(I), nextID++, Ops);
David Neto22f144c2017-06-12 14:26:21 -04003575 SPIRVInstList.push_back(Inst);
3576 }
3577 } else if (isa<BinaryOperator>(I)) {
3578 //
3579 // Generate SPIRV instructions for binary operators.
3580 //
3581
3582 // Handle xor with i1 type specially.
3583 if (I.getOpcode() == Instruction::Xor &&
3584 I.getType() == Type::getInt1Ty(Context) &&
3585 (isa<Constant>(I.getOperand(0)) || isa<Constant>(I.getOperand(1)))) {
3586 //
3587 // Generate OpLogicalNot.
3588 //
3589 // Ops[0] = Result Type ID
3590 // Ops[1] = Operand
3591 SPIRVOperandList Ops;
3592
David Neto257c3892018-04-11 13:19:45 -04003593 Ops << MkId(lookupType(I.getType()));
David Neto22f144c2017-06-12 14:26:21 -04003594
3595 Value *CondV = I.getOperand(0);
3596 if (isa<Constant>(I.getOperand(0))) {
3597 CondV = I.getOperand(1);
3598 }
David Neto257c3892018-04-11 13:19:45 -04003599 Ops << MkId(VMap[CondV]);
David Neto22f144c2017-06-12 14:26:21 -04003600
David Neto87846742018-04-11 17:36:22 -04003601 auto *Inst = new SPIRVInstruction(spv::OpLogicalNot, nextID++, Ops);
David Neto22f144c2017-06-12 14:26:21 -04003602 SPIRVInstList.push_back(Inst);
3603 } else {
3604 // Ops[0] = Result Type ID
3605 // Ops[1] = Operand 0
3606 // Ops[2] = Operand 1
3607 SPIRVOperandList Ops;
3608
David Neto257c3892018-04-11 13:19:45 -04003609 Ops << MkId(lookupType(I.getType())) << MkId(VMap[I.getOperand(0)])
3610 << MkId(VMap[I.getOperand(1)]);
David Neto22f144c2017-06-12 14:26:21 -04003611
David Neto87846742018-04-11 17:36:22 -04003612 auto *Inst =
3613 new SPIRVInstruction(GetSPIRVBinaryOpcode(I), nextID++, Ops);
David Neto22f144c2017-06-12 14:26:21 -04003614 SPIRVInstList.push_back(Inst);
3615 }
3616 } else {
3617 I.print(errs());
3618 llvm_unreachable("Unsupported instruction???");
3619 }
3620 break;
3621 }
3622 case Instruction::GetElementPtr: {
3623 auto &GlobalConstArgSet = getGlobalConstArgSet();
3624
3625 //
3626 // Generate OpAccessChain.
3627 //
3628 GetElementPtrInst *GEP = cast<GetElementPtrInst>(&I);
3629
3630 //
3631 // Generate OpAccessChain.
3632 //
3633
3634 // Ops[0] = Result Type ID
3635 // Ops[1] = Base ID
3636 // Ops[2] ... Ops[n] = Indexes ID
3637 SPIRVOperandList Ops;
3638
David Neto1a1a0582017-07-07 12:01:44 -04003639 PointerType* ResultType = cast<PointerType>(GEP->getType());
David Neto22f144c2017-06-12 14:26:21 -04003640 if (GEP->getPointerAddressSpace() == AddressSpace::ModuleScopePrivate ||
3641 GlobalConstArgSet.count(GEP->getPointerOperand())) {
3642 // Use pointer type with private address space for global constant.
3643 Type *EleTy = I.getType()->getPointerElementType();
David Neto1a1a0582017-07-07 12:01:44 -04003644 ResultType = PointerType::get(EleTy, AddressSpace::ModuleScopePrivate);
David Neto22f144c2017-06-12 14:26:21 -04003645 }
David Neto257c3892018-04-11 13:19:45 -04003646
3647 Ops << MkId(lookupType(ResultType));
David Neto22f144c2017-06-12 14:26:21 -04003648
3649 // Check whether GEP's pointer operand is pointer argument.
3650 bool HasArgBasePointer = false;
3651 for (auto ArgGV : ArgGVMap) {
3652 if (ArgGV.first == GEP->getPointerOperand()) {
3653 if (isa<PointerType>(ArgGV.first->getType())) {
3654 HasArgBasePointer = true;
3655 } else {
3656 llvm_unreachable(
3657 "GEP's pointer operand is argument of non-poninter type???");
3658 }
3659 }
3660 }
3661
3662 uint32_t BaseID;
3663 if (HasArgBasePointer) {
3664 // Point to global variable for argument directly.
3665 BaseID = ArgGVIDMap[GEP->getPointerOperand()];
3666 } else {
3667 BaseID = VMap[GEP->getPointerOperand()];
3668 }
3669
David Neto257c3892018-04-11 13:19:45 -04003670 Ops << MkId(BaseID);
David Neto22f144c2017-06-12 14:26:21 -04003671
David Neto22f144c2017-06-12 14:26:21 -04003672 if (HasArgBasePointer) {
3673 // If GEP's pointer operand is argument, add one more index for struct
3674 // type to wrap up argument type.
3675 Type *IdxTy = Type::getInt32Ty(Context);
David Neto257c3892018-04-11 13:19:45 -04003676 Ops << MkId(VMap[ConstantInt::get(IdxTy, 0)]);
David Neto22f144c2017-06-12 14:26:21 -04003677 }
3678
3679 //
3680 // Follows below rules for gep.
3681 //
3682 // 1. If gep's first index is 0 and gep's base is not kernel function's
3683 // argument, generate OpAccessChain and ignore gep's first index.
3684 // 2. If gep's first index is not 0, generate OpPtrAccessChain and use gep's
3685 // first index.
3686 // 3. If gep's first index is not constant, generate OpPtrAccessChain and
3687 // use gep's first index.
3688 // 4. If it is not above case 1, 2 and 3, generate OpAccessChain and use
3689 // gep's first index.
3690 //
3691 spv::Op Opcode = spv::OpAccessChain;
3692 unsigned offset = 0;
3693 if (ConstantInt *CstInt = dyn_cast<ConstantInt>(GEP->getOperand(1))) {
3694 if (CstInt->getZExtValue() == 0 && !HasArgBasePointer) {
3695 offset = 1;
3696 } else if (CstInt->getZExtValue() != 0 && !HasArgBasePointer) {
3697 Opcode = spv::OpPtrAccessChain;
David Neto22f144c2017-06-12 14:26:21 -04003698 }
3699 } else if (!HasArgBasePointer) {
3700 Opcode = spv::OpPtrAccessChain;
David Neto1a1a0582017-07-07 12:01:44 -04003701 }
3702
3703 if (Opcode == spv::OpPtrAccessChain) {
David Neto22f144c2017-06-12 14:26:21 -04003704 setVariablePointers(true);
David Neto1a1a0582017-07-07 12:01:44 -04003705 // Do we need to generate ArrayStride? Check against the GEP result type
3706 // rather than the pointer type of the base because when indexing into
3707 // an OpenCL program-scope constant, we'll swap out the LLVM base pointer
3708 // for something else in the SPIR-V.
3709 // E.g. see test/PointerAccessChain/pointer_index_is_constant_1.cl
3710 if (GetStorageClass(ResultType->getAddressSpace()) ==
3711 spv::StorageClassStorageBuffer) {
3712 // Save the need to generate an ArrayStride decoration. But defer
3713 // generation until later, so we only make one decoration.
David Neto85082642018-03-24 06:55:20 -07003714 getTypesNeedingArrayStride().insert(ResultType);
David Neto1a1a0582017-07-07 12:01:44 -04003715 }
David Neto22f144c2017-06-12 14:26:21 -04003716 }
3717
3718 for (auto II = GEP->idx_begin() + offset; II != GEP->idx_end(); II++) {
David Neto257c3892018-04-11 13:19:45 -04003719 Ops << MkId(VMap[*II]);
David Neto22f144c2017-06-12 14:26:21 -04003720 }
3721
David Neto87846742018-04-11 17:36:22 -04003722 auto *Inst = new SPIRVInstruction(Opcode, nextID++, Ops);
David Neto22f144c2017-06-12 14:26:21 -04003723 SPIRVInstList.push_back(Inst);
3724 break;
3725 }
3726 case Instruction::ExtractValue: {
3727 ExtractValueInst *EVI = cast<ExtractValueInst>(&I);
3728 // Ops[0] = Result Type ID
3729 // Ops[1] = Composite ID
3730 // Ops[2] ... Ops[n] = Indexes (Literal Number)
3731 SPIRVOperandList Ops;
3732
David Neto257c3892018-04-11 13:19:45 -04003733 Ops << MkId(lookupType(I.getType()));
David Neto22f144c2017-06-12 14:26:21 -04003734
3735 uint32_t CompositeID = VMap[EVI->getAggregateOperand()];
David Neto257c3892018-04-11 13:19:45 -04003736 Ops << MkId(CompositeID);
David Neto22f144c2017-06-12 14:26:21 -04003737
3738 for (auto &Index : EVI->indices()) {
David Neto257c3892018-04-11 13:19:45 -04003739 Ops << MkNum(Index);
David Neto22f144c2017-06-12 14:26:21 -04003740 }
3741
David Neto87846742018-04-11 17:36:22 -04003742 auto *Inst = new SPIRVInstruction(spv::OpCompositeExtract, nextID++, Ops);
David Neto22f144c2017-06-12 14:26:21 -04003743 SPIRVInstList.push_back(Inst);
3744 break;
3745 }
3746 case Instruction::InsertValue: {
3747 InsertValueInst *IVI = cast<InsertValueInst>(&I);
3748 // Ops[0] = Result Type ID
3749 // Ops[1] = Object ID
3750 // Ops[2] = Composite ID
3751 // Ops[3] ... Ops[n] = Indexes (Literal Number)
3752 SPIRVOperandList Ops;
3753
3754 uint32_t ResTyID = lookupType(I.getType());
David Neto257c3892018-04-11 13:19:45 -04003755 Ops << MkId(ResTyID);
David Neto22f144c2017-06-12 14:26:21 -04003756
3757 uint32_t ObjectID = VMap[IVI->getInsertedValueOperand()];
David Neto257c3892018-04-11 13:19:45 -04003758 Ops << MkId(ObjectID);
David Neto22f144c2017-06-12 14:26:21 -04003759
3760 uint32_t CompositeID = VMap[IVI->getAggregateOperand()];
David Neto257c3892018-04-11 13:19:45 -04003761 Ops << MkId(CompositeID);
David Neto22f144c2017-06-12 14:26:21 -04003762
3763 for (auto &Index : IVI->indices()) {
David Neto257c3892018-04-11 13:19:45 -04003764 Ops << MkNum(Index);
David Neto22f144c2017-06-12 14:26:21 -04003765 }
3766
David Neto87846742018-04-11 17:36:22 -04003767 auto *Inst = new SPIRVInstruction(spv::OpCompositeInsert, nextID++, Ops);
David Neto22f144c2017-06-12 14:26:21 -04003768 SPIRVInstList.push_back(Inst);
3769 break;
3770 }
3771 case Instruction::Select: {
3772 //
3773 // Generate OpSelect.
3774 //
3775
3776 // Ops[0] = Result Type ID
3777 // Ops[1] = Condition ID
3778 // Ops[2] = True Constant ID
3779 // Ops[3] = False Constant ID
3780 SPIRVOperandList Ops;
3781
3782 // Find SPIRV instruction for parameter type.
3783 auto Ty = I.getType();
3784 if (Ty->isPointerTy()) {
3785 auto PointeeTy = Ty->getPointerElementType();
3786 if (PointeeTy->isStructTy() &&
3787 dyn_cast<StructType>(PointeeTy)->isOpaque()) {
3788 Ty = PointeeTy;
3789 }
3790 }
3791
David Neto257c3892018-04-11 13:19:45 -04003792 Ops << MkId(lookupType(Ty)) << MkId(VMap[I.getOperand(0)])
3793 << MkId(VMap[I.getOperand(1)]) << MkId(VMap[I.getOperand(2)]);
David Neto22f144c2017-06-12 14:26:21 -04003794
David Neto87846742018-04-11 17:36:22 -04003795 auto *Inst = new SPIRVInstruction(spv::OpSelect, nextID++, Ops);
David Neto22f144c2017-06-12 14:26:21 -04003796 SPIRVInstList.push_back(Inst);
3797 break;
3798 }
3799 case Instruction::ExtractElement: {
3800 // Handle <4 x i8> type manually.
3801 Type *CompositeTy = I.getOperand(0)->getType();
3802 if (is4xi8vec(CompositeTy)) {
3803 //
3804 // Generate OpShiftRightLogical and OpBitwiseAnd for extractelement with
3805 // <4 x i8>.
3806 //
3807
3808 //
3809 // Generate OpShiftRightLogical
3810 //
3811 // Ops[0] = Result Type ID
3812 // Ops[1] = Operand 0
3813 // Ops[2] = Operand 1
3814 //
3815 SPIRVOperandList Ops;
3816
David Neto257c3892018-04-11 13:19:45 -04003817 Ops << MkId(lookupType(CompositeTy));
David Neto22f144c2017-06-12 14:26:21 -04003818
3819 uint32_t Op0ID = VMap[I.getOperand(0)];
David Neto257c3892018-04-11 13:19:45 -04003820 Ops << MkId(Op0ID);
David Neto22f144c2017-06-12 14:26:21 -04003821
3822 uint32_t Op1ID = 0;
3823 if (ConstantInt *CI = dyn_cast<ConstantInt>(I.getOperand(1))) {
3824 // Handle constant index.
3825 uint64_t Idx = CI->getZExtValue();
3826 Value *ShiftAmount =
3827 ConstantInt::get(Type::getInt32Ty(Context), Idx * 8);
3828 Op1ID = VMap[ShiftAmount];
3829 } else {
3830 // Handle variable index.
3831 SPIRVOperandList TmpOps;
3832
David Neto257c3892018-04-11 13:19:45 -04003833 TmpOps << MkId(lookupType(Type::getInt32Ty(Context)))
3834 << MkId(VMap[I.getOperand(1)]);
David Neto22f144c2017-06-12 14:26:21 -04003835
3836 ConstantInt *Cst8 = ConstantInt::get(Type::getInt32Ty(Context), 8);
David Neto257c3892018-04-11 13:19:45 -04003837 TmpOps << MkId(VMap[Cst8]);
David Neto22f144c2017-06-12 14:26:21 -04003838
3839 Op1ID = nextID;
3840
David Neto87846742018-04-11 17:36:22 -04003841 auto *TmpInst = new SPIRVInstruction(spv::OpIMul, nextID++, TmpOps);
David Neto22f144c2017-06-12 14:26:21 -04003842 SPIRVInstList.push_back(TmpInst);
3843 }
David Neto257c3892018-04-11 13:19:45 -04003844 Ops << MkId(Op1ID);
David Neto22f144c2017-06-12 14:26:21 -04003845
3846 uint32_t ShiftID = nextID;
3847
David Neto87846742018-04-11 17:36:22 -04003848 auto *Inst =
3849 new SPIRVInstruction(spv::OpShiftRightLogical, nextID++, Ops);
David Neto22f144c2017-06-12 14:26:21 -04003850 SPIRVInstList.push_back(Inst);
3851
3852 //
3853 // Generate OpBitwiseAnd
3854 //
3855 // Ops[0] = Result Type ID
3856 // Ops[1] = Operand 0
3857 // Ops[2] = Operand 1
3858 //
3859 Ops.clear();
3860
David Neto257c3892018-04-11 13:19:45 -04003861 Ops << MkId(lookupType(CompositeTy)) << MkId(ShiftID);
David Neto22f144c2017-06-12 14:26:21 -04003862
3863 Constant *CstFF = ConstantInt::get(Type::getInt32Ty(Context), 0xFF);
David Neto257c3892018-04-11 13:19:45 -04003864 Ops << MkId(VMap[CstFF]);
David Neto22f144c2017-06-12 14:26:21 -04003865
David Neto9b2d6252017-09-06 15:47:37 -04003866 // Reset mapping for this value to the result of the bitwise and.
3867 VMap[&I] = nextID;
3868
David Neto87846742018-04-11 17:36:22 -04003869 Inst = new SPIRVInstruction(spv::OpBitwiseAnd, nextID++, Ops);
David Neto22f144c2017-06-12 14:26:21 -04003870 SPIRVInstList.push_back(Inst);
3871 break;
3872 }
3873
3874 // Ops[0] = Result Type ID
3875 // Ops[1] = Composite ID
3876 // Ops[2] ... Ops[n] = Indexes (Literal Number)
3877 SPIRVOperandList Ops;
3878
David Neto257c3892018-04-11 13:19:45 -04003879 Ops << MkId(lookupType(I.getType())) << MkId(VMap[I.getOperand(0)]);
David Neto22f144c2017-06-12 14:26:21 -04003880
3881 spv::Op Opcode = spv::OpCompositeExtract;
3882 if (const ConstantInt *CI = dyn_cast<ConstantInt>(I.getOperand(1))) {
David Neto257c3892018-04-11 13:19:45 -04003883 Ops << MkNum(static_cast<uint32_t>(CI->getZExtValue()));
David Neto22f144c2017-06-12 14:26:21 -04003884 } else {
David Neto257c3892018-04-11 13:19:45 -04003885 Ops << MkId(VMap[I.getOperand(1)]);
David Neto22f144c2017-06-12 14:26:21 -04003886 Opcode = spv::OpVectorExtractDynamic;
3887 }
3888
David Neto87846742018-04-11 17:36:22 -04003889 auto *Inst = new SPIRVInstruction(Opcode, nextID++, Ops);
David Neto22f144c2017-06-12 14:26:21 -04003890 SPIRVInstList.push_back(Inst);
3891 break;
3892 }
3893 case Instruction::InsertElement: {
3894 // Handle <4 x i8> type manually.
3895 Type *CompositeTy = I.getOperand(0)->getType();
3896 if (is4xi8vec(CompositeTy)) {
3897 Constant *CstFF = ConstantInt::get(Type::getInt32Ty(Context), 0xFF);
3898 uint32_t CstFFID = VMap[CstFF];
3899
3900 uint32_t ShiftAmountID = 0;
3901 if (ConstantInt *CI = dyn_cast<ConstantInt>(I.getOperand(2))) {
3902 // Handle constant index.
3903 uint64_t Idx = CI->getZExtValue();
3904 Value *ShiftAmount =
3905 ConstantInt::get(Type::getInt32Ty(Context), Idx * 8);
3906 ShiftAmountID = VMap[ShiftAmount];
3907 } else {
3908 // Handle variable index.
3909 SPIRVOperandList TmpOps;
3910
David Neto257c3892018-04-11 13:19:45 -04003911 TmpOps << MkId(lookupType(Type::getInt32Ty(Context)))
3912 << MkId(VMap[I.getOperand(2)]);
David Neto22f144c2017-06-12 14:26:21 -04003913
3914 ConstantInt *Cst8 = ConstantInt::get(Type::getInt32Ty(Context), 8);
David Neto257c3892018-04-11 13:19:45 -04003915 TmpOps << MkId(VMap[Cst8]);
David Neto22f144c2017-06-12 14:26:21 -04003916
3917 ShiftAmountID = nextID;
3918
David Neto87846742018-04-11 17:36:22 -04003919 auto *TmpInst = new SPIRVInstruction(spv::OpIMul, nextID++, TmpOps);
David Neto22f144c2017-06-12 14:26:21 -04003920 SPIRVInstList.push_back(TmpInst);
3921 }
3922
3923 //
3924 // Generate mask operations.
3925 //
3926
3927 // ShiftLeft mask according to index of insertelement.
3928 SPIRVOperandList Ops;
3929
David Neto257c3892018-04-11 13:19:45 -04003930 const uint32_t ResTyID = lookupType(CompositeTy);
3931 Ops << MkId(ResTyID) << MkId(CstFFID) << MkId(ShiftAmountID);
David Neto22f144c2017-06-12 14:26:21 -04003932
3933 uint32_t MaskID = nextID;
3934
David Neto87846742018-04-11 17:36:22 -04003935 auto *Inst = new SPIRVInstruction(spv::OpShiftLeftLogical, nextID++, Ops);
David Neto22f144c2017-06-12 14:26:21 -04003936 SPIRVInstList.push_back(Inst);
3937
3938 // Inverse mask.
3939 Ops.clear();
David Neto257c3892018-04-11 13:19:45 -04003940 Ops << MkId(ResTyID) << MkId(MaskID);
David Neto22f144c2017-06-12 14:26:21 -04003941
3942 uint32_t InvMaskID = nextID;
3943
David Neto87846742018-04-11 17:36:22 -04003944 Inst = new SPIRVInstruction(spv::OpNot, nextID++, Ops);
David Neto22f144c2017-06-12 14:26:21 -04003945 SPIRVInstList.push_back(Inst);
3946
3947 // Apply mask.
3948 Ops.clear();
David Neto257c3892018-04-11 13:19:45 -04003949 Ops << MkId(ResTyID) << MkId(VMap[I.getOperand(0)]) << MkId(InvMaskID);
David Neto22f144c2017-06-12 14:26:21 -04003950
3951 uint32_t OrgValID = nextID;
3952
David Neto87846742018-04-11 17:36:22 -04003953 Inst = new SPIRVInstruction(spv::OpBitwiseAnd, nextID++, Ops);
David Neto22f144c2017-06-12 14:26:21 -04003954 SPIRVInstList.push_back(Inst);
3955
3956 // Create correct value according to index of insertelement.
3957 Ops.clear();
David Neto257c3892018-04-11 13:19:45 -04003958 Ops << MkId(ResTyID) << MkId(VMap[I.getOperand(1)]) << MkId(ShiftAmountID);
David Neto22f144c2017-06-12 14:26:21 -04003959
3960 uint32_t InsertValID = nextID;
3961
David Neto87846742018-04-11 17:36:22 -04003962 Inst = new SPIRVInstruction(spv::OpShiftLeftLogical, nextID++, Ops);
David Neto22f144c2017-06-12 14:26:21 -04003963 SPIRVInstList.push_back(Inst);
3964
3965 // Insert value to original value.
3966 Ops.clear();
David Neto257c3892018-04-11 13:19:45 -04003967 Ops << MkId(ResTyID) << MkId(OrgValID) << MkId(InsertValID);
David Neto22f144c2017-06-12 14:26:21 -04003968
David Netoa394f392017-08-26 20:45:29 -04003969 VMap[&I] = nextID;
3970
David Neto87846742018-04-11 17:36:22 -04003971 Inst = new SPIRVInstruction(spv::OpBitwiseOr, nextID++, Ops);
David Neto22f144c2017-06-12 14:26:21 -04003972 SPIRVInstList.push_back(Inst);
3973
3974 break;
3975 }
3976
David Neto22f144c2017-06-12 14:26:21 -04003977 SPIRVOperandList Ops;
3978
James Priced26efea2018-06-09 23:28:32 +01003979 // Ops[0] = Result Type ID
3980 Ops << MkId(lookupType(I.getType()));
David Neto22f144c2017-06-12 14:26:21 -04003981
3982 spv::Op Opcode = spv::OpCompositeInsert;
3983 if (const ConstantInt *CI = dyn_cast<ConstantInt>(I.getOperand(2))) {
David Neto257c3892018-04-11 13:19:45 -04003984 const auto value = CI->getZExtValue();
3985 assert(value <= UINT32_MAX);
James Priced26efea2018-06-09 23:28:32 +01003986 // Ops[1] = Object ID
3987 // Ops[2] = Composite ID
3988 // Ops[3] ... Ops[n] = Indexes (Literal Number)
3989 Ops << MkId(VMap[I.getOperand(1)])
3990 << MkId(VMap[I.getOperand(0)])
3991 << MkNum(static_cast<uint32_t>(value));
David Neto22f144c2017-06-12 14:26:21 -04003992 } else {
James Priced26efea2018-06-09 23:28:32 +01003993 // Ops[1] = Composite ID
3994 // Ops[2] = Object ID
3995 // Ops[3] ... Ops[n] = Indexes (Literal Number)
3996 Ops << MkId(VMap[I.getOperand(0)])
3997 << MkId(VMap[I.getOperand(1)])
3998 << MkId(VMap[I.getOperand(2)]);
David Neto22f144c2017-06-12 14:26:21 -04003999 Opcode = spv::OpVectorInsertDynamic;
4000 }
4001
David Neto87846742018-04-11 17:36:22 -04004002 auto *Inst = new SPIRVInstruction(Opcode, nextID++, Ops);
David Neto22f144c2017-06-12 14:26:21 -04004003 SPIRVInstList.push_back(Inst);
4004 break;
4005 }
4006 case Instruction::ShuffleVector: {
4007 // Ops[0] = Result Type ID
4008 // Ops[1] = Vector 1 ID
4009 // Ops[2] = Vector 2 ID
4010 // Ops[3] ... Ops[n] = Components (Literal Number)
4011 SPIRVOperandList Ops;
4012
David Neto257c3892018-04-11 13:19:45 -04004013 Ops << MkId(lookupType(I.getType())) << MkId(VMap[I.getOperand(0)])
4014 << MkId(VMap[I.getOperand(1)]);
David Neto22f144c2017-06-12 14:26:21 -04004015
4016 uint64_t NumElements = 0;
4017 if (Constant *Cst = dyn_cast<Constant>(I.getOperand(2))) {
4018 NumElements = cast<VectorType>(Cst->getType())->getNumElements();
4019
4020 if (Cst->isNullValue()) {
4021 for (unsigned i = 0; i < NumElements; i++) {
David Neto257c3892018-04-11 13:19:45 -04004022 Ops << MkNum(0);
David Neto22f144c2017-06-12 14:26:21 -04004023 }
4024 } else if (const ConstantDataSequential *CDS =
4025 dyn_cast<ConstantDataSequential>(Cst)) {
4026 for (unsigned i = 0; i < CDS->getNumElements(); i++) {
4027 std::vector<uint32_t> LiteralNum;
David Neto257c3892018-04-11 13:19:45 -04004028 const auto value = CDS->getElementAsInteger(i);
4029 assert(value <= UINT32_MAX);
4030 Ops << MkNum(static_cast<uint32_t>(value));
David Neto22f144c2017-06-12 14:26:21 -04004031 }
4032 } else if (const ConstantVector *CV = dyn_cast<ConstantVector>(Cst)) {
4033 for (unsigned i = 0; i < CV->getNumOperands(); i++) {
4034 auto Op = CV->getOperand(i);
4035
4036 uint32_t literal = 0;
4037
4038 if (auto CI = dyn_cast<ConstantInt>(Op)) {
4039 literal = static_cast<uint32_t>(CI->getZExtValue());
4040 } else if (auto UI = dyn_cast<UndefValue>(Op)) {
4041 literal = 0xFFFFFFFFu;
4042 } else {
4043 Op->print(errs());
4044 llvm_unreachable("Unsupported element in ConstantVector!");
4045 }
4046
David Neto257c3892018-04-11 13:19:45 -04004047 Ops << MkNum(literal);
David Neto22f144c2017-06-12 14:26:21 -04004048 }
4049 } else {
4050 Cst->print(errs());
4051 llvm_unreachable("Unsupported constant mask in ShuffleVector!");
4052 }
4053 }
4054
David Neto87846742018-04-11 17:36:22 -04004055 auto *Inst = new SPIRVInstruction(spv::OpVectorShuffle, nextID++, Ops);
David Neto22f144c2017-06-12 14:26:21 -04004056 SPIRVInstList.push_back(Inst);
4057 break;
4058 }
4059 case Instruction::ICmp:
4060 case Instruction::FCmp: {
4061 CmpInst *CmpI = cast<CmpInst>(&I);
4062
David Netod4ca2e62017-07-06 18:47:35 -04004063 // Pointer equality is invalid.
4064 Type* ArgTy = CmpI->getOperand(0)->getType();
4065 if (isa<PointerType>(ArgTy)) {
4066 CmpI->print(errs());
4067 std::string name = I.getParent()->getParent()->getName();
4068 errs()
4069 << "\nPointer equality test is not supported by SPIR-V for Vulkan, "
4070 << "in function " << name << "\n";
4071 llvm_unreachable("Pointer equality check is invalid");
4072 break;
4073 }
4074
David Neto257c3892018-04-11 13:19:45 -04004075 // Ops[0] = Result Type ID
4076 // Ops[1] = Operand 1 ID
4077 // Ops[2] = Operand 2 ID
4078 SPIRVOperandList Ops;
David Neto22f144c2017-06-12 14:26:21 -04004079
David Neto257c3892018-04-11 13:19:45 -04004080 Ops << MkId(lookupType(CmpI->getType())) << MkId(VMap[CmpI->getOperand(0)])
4081 << MkId(VMap[CmpI->getOperand(1)]);
David Neto22f144c2017-06-12 14:26:21 -04004082
4083 spv::Op Opcode = GetSPIRVCmpOpcode(CmpI);
David Neto87846742018-04-11 17:36:22 -04004084 auto *Inst = new SPIRVInstruction(Opcode, nextID++, Ops);
David Neto22f144c2017-06-12 14:26:21 -04004085 SPIRVInstList.push_back(Inst);
4086 break;
4087 }
4088 case Instruction::Br: {
4089 // Branch instrucion is deferred because it needs label's ID. Record slot's
4090 // location on SPIRVInstructionList.
4091 DeferredInsts.push_back(
4092 std::make_tuple(&I, --SPIRVInstList.end(), 0 /* No id */));
4093 break;
4094 }
4095 case Instruction::Switch: {
4096 I.print(errs());
4097 llvm_unreachable("Unsupported instruction???");
4098 break;
4099 }
4100 case Instruction::IndirectBr: {
4101 I.print(errs());
4102 llvm_unreachable("Unsupported instruction???");
4103 break;
4104 }
4105 case Instruction::PHI: {
4106 // Branch instrucion is deferred because it needs label's ID. Record slot's
4107 // location on SPIRVInstructionList.
4108 DeferredInsts.push_back(
4109 std::make_tuple(&I, --SPIRVInstList.end(), nextID++));
4110 break;
4111 }
4112 case Instruction::Alloca: {
4113 //
4114 // Generate OpVariable.
4115 //
4116 // Ops[0] : Result Type ID
4117 // Ops[1] : Storage Class
4118 SPIRVOperandList Ops;
4119
David Neto257c3892018-04-11 13:19:45 -04004120 Ops << MkId(lookupType(I.getType())) << MkNum(spv::StorageClassFunction);
David Neto22f144c2017-06-12 14:26:21 -04004121
David Neto87846742018-04-11 17:36:22 -04004122 auto *Inst = new SPIRVInstruction(spv::OpVariable, nextID++, Ops);
David Neto22f144c2017-06-12 14:26:21 -04004123 SPIRVInstList.push_back(Inst);
4124 break;
4125 }
4126 case Instruction::Load: {
4127 LoadInst *LD = cast<LoadInst>(&I);
4128 //
4129 // Generate OpLoad.
4130 //
4131
David Neto0a2f98d2017-09-15 19:38:40 -04004132 uint32_t ResTyID = lookupType(LD->getType());
David Netoa60b00b2017-09-15 16:34:09 -04004133 uint32_t PointerID = VMap[LD->getPointerOperand()];
4134
4135 // This is a hack to work around what looks like a driver bug.
4136 // When we're loading from the special variable holding the WorkgroupSize
David Neto0a2f98d2017-09-15 19:38:40 -04004137 // builtin value, use an OpBitWiseAnd of the value's ID rather than
4138 // generating a load.
David Neto66cfe642018-03-24 06:13:56 -07004139 // TODO(dneto): Remove this awful hack once drivers are fixed.
David Netoa60b00b2017-09-15 16:34:09 -04004140 if (PointerID == WorkgroupSizeVarID) {
David Neto0a2f98d2017-09-15 19:38:40 -04004141 // Generate a bitwise-and of the original value with itself.
4142 // We should have been able to get away with just an OpCopyObject,
4143 // but we need something more complex to get past certain driver bugs.
4144 // This is ridiculous, but necessary.
4145 // TODO(dneto): Revisit this once drivers fix their bugs.
4146
4147 SPIRVOperandList Ops;
David Neto257c3892018-04-11 13:19:45 -04004148 Ops << MkId(ResTyID) << MkId(WorkgroupSizeValueID)
4149 << MkId(WorkgroupSizeValueID);
David Neto0a2f98d2017-09-15 19:38:40 -04004150
David Neto87846742018-04-11 17:36:22 -04004151 auto *Inst = new SPIRVInstruction(spv::OpBitwiseAnd, nextID++, Ops);
David Neto0a2f98d2017-09-15 19:38:40 -04004152 SPIRVInstList.push_back(Inst);
David Netoa60b00b2017-09-15 16:34:09 -04004153 break;
4154 }
4155
4156 // This is the normal path. Generate a load.
4157
David Neto22f144c2017-06-12 14:26:21 -04004158 // Ops[0] = Result Type ID
4159 // Ops[1] = Pointer ID
4160 // Ops[2] ... Ops[n] = Optional Memory Access
4161 //
4162 // TODO: Do we need to implement Optional Memory Access???
David Neto0a2f98d2017-09-15 19:38:40 -04004163
David Neto22f144c2017-06-12 14:26:21 -04004164 SPIRVOperandList Ops;
David Neto257c3892018-04-11 13:19:45 -04004165 Ops << MkId(ResTyID) << MkId(PointerID);
David Neto22f144c2017-06-12 14:26:21 -04004166
David Neto87846742018-04-11 17:36:22 -04004167 auto *Inst = new SPIRVInstruction(spv::OpLoad, nextID++, Ops);
David Neto22f144c2017-06-12 14:26:21 -04004168 SPIRVInstList.push_back(Inst);
4169 break;
4170 }
4171 case Instruction::Store: {
4172 StoreInst *ST = cast<StoreInst>(&I);
4173 //
4174 // Generate OpStore.
4175 //
4176
4177 // Ops[0] = Pointer ID
4178 // Ops[1] = Object ID
4179 // Ops[2] ... Ops[n] = Optional Memory Access (later???)
4180 //
4181 // TODO: Do we need to implement Optional Memory Access???
David Neto257c3892018-04-11 13:19:45 -04004182 SPIRVOperandList Ops;
4183 Ops << MkId(VMap[ST->getPointerOperand()])
4184 << MkId(VMap[ST->getValueOperand()]);
David Neto22f144c2017-06-12 14:26:21 -04004185
David Neto87846742018-04-11 17:36:22 -04004186 auto *Inst = new SPIRVInstruction(spv::OpStore, Ops);
David Neto22f144c2017-06-12 14:26:21 -04004187 SPIRVInstList.push_back(Inst);
4188 break;
4189 }
4190 case Instruction::AtomicCmpXchg: {
4191 I.print(errs());
4192 llvm_unreachable("Unsupported instruction???");
4193 break;
4194 }
4195 case Instruction::AtomicRMW: {
Neil Henning39672102017-09-29 14:33:13 +01004196 AtomicRMWInst *AtomicRMW = dyn_cast<AtomicRMWInst>(&I);
4197
4198 spv::Op opcode;
4199
4200 switch (AtomicRMW->getOperation()) {
4201 default:
4202 I.print(errs());
4203 llvm_unreachable("Unsupported instruction???");
4204 case llvm::AtomicRMWInst::Add:
4205 opcode = spv::OpAtomicIAdd;
4206 break;
4207 case llvm::AtomicRMWInst::Sub:
4208 opcode = spv::OpAtomicISub;
4209 break;
4210 case llvm::AtomicRMWInst::Xchg:
4211 opcode = spv::OpAtomicExchange;
4212 break;
4213 case llvm::AtomicRMWInst::Min:
4214 opcode = spv::OpAtomicSMin;
4215 break;
4216 case llvm::AtomicRMWInst::Max:
4217 opcode = spv::OpAtomicSMax;
4218 break;
4219 case llvm::AtomicRMWInst::UMin:
4220 opcode = spv::OpAtomicUMin;
4221 break;
4222 case llvm::AtomicRMWInst::UMax:
4223 opcode = spv::OpAtomicUMax;
4224 break;
4225 case llvm::AtomicRMWInst::And:
4226 opcode = spv::OpAtomicAnd;
4227 break;
4228 case llvm::AtomicRMWInst::Or:
4229 opcode = spv::OpAtomicOr;
4230 break;
4231 case llvm::AtomicRMWInst::Xor:
4232 opcode = spv::OpAtomicXor;
4233 break;
4234 }
4235
4236 //
4237 // Generate OpAtomic*.
4238 //
4239 SPIRVOperandList Ops;
4240
David Neto257c3892018-04-11 13:19:45 -04004241 Ops << MkId(lookupType(I.getType()))
4242 << MkId(VMap[AtomicRMW->getPointerOperand()]);
Neil Henning39672102017-09-29 14:33:13 +01004243
4244 auto IntTy = Type::getInt32Ty(I.getContext());
Neil Henning39672102017-09-29 14:33:13 +01004245 const auto ConstantScopeDevice = ConstantInt::get(IntTy, spv::ScopeDevice);
David Neto257c3892018-04-11 13:19:45 -04004246 Ops << MkId(VMap[ConstantScopeDevice]);
Neil Henning39672102017-09-29 14:33:13 +01004247
4248 const auto ConstantMemorySemantics = ConstantInt::get(
4249 IntTy, spv::MemorySemanticsUniformMemoryMask |
4250 spv::MemorySemanticsSequentiallyConsistentMask);
David Neto257c3892018-04-11 13:19:45 -04004251 Ops << MkId(VMap[ConstantMemorySemantics]);
Neil Henning39672102017-09-29 14:33:13 +01004252
David Neto257c3892018-04-11 13:19:45 -04004253 Ops << MkId(VMap[AtomicRMW->getValOperand()]);
Neil Henning39672102017-09-29 14:33:13 +01004254
4255 VMap[&I] = nextID;
4256
David Neto87846742018-04-11 17:36:22 -04004257 auto *Inst = new SPIRVInstruction(opcode, nextID++, Ops);
Neil Henning39672102017-09-29 14:33:13 +01004258 SPIRVInstList.push_back(Inst);
David Neto22f144c2017-06-12 14:26:21 -04004259 break;
4260 }
4261 case Instruction::Fence: {
4262 I.print(errs());
4263 llvm_unreachable("Unsupported instruction???");
4264 break;
4265 }
4266 case Instruction::Call: {
4267 CallInst *Call = dyn_cast<CallInst>(&I);
4268 Function *Callee = Call->getCalledFunction();
4269
4270 // Sampler initializers become a load of the corresponding sampler.
4271 if (Callee->getName().equals("__translate_sampler_initializer")) {
4272 // Check that the sampler map was definitely used though.
4273 if (0 == getSamplerMap().size()) {
David Netob050df02018-06-04 15:27:23 -07004274 errs() << "error: kernel uses a literal sampler but option -samplermap "
4275 "has not been specified\n";
David Neto22f144c2017-06-12 14:26:21 -04004276 llvm_unreachable("Sampler literal in source without sampler map!");
4277 }
4278
4279 SPIRVOperandList Ops;
4280
David Neto257c3892018-04-11 13:19:45 -04004281 Ops << MkId(lookupType(SamplerTy->getPointerElementType()))
4282 << MkId(VMap[Call]);
David Neto22f144c2017-06-12 14:26:21 -04004283
4284 VMap[Call] = nextID;
David Neto87846742018-04-11 17:36:22 -04004285 auto *Inst = new SPIRVInstruction(spv::OpLoad, nextID++, Ops);
David Neto22f144c2017-06-12 14:26:21 -04004286 SPIRVInstList.push_back(Inst);
4287
4288 break;
4289 }
4290
4291 if (Callee->getName().startswith("spirv.atomic")) {
4292 spv::Op opcode = StringSwitch<spv::Op>(Callee->getName())
4293 .Case("spirv.atomic_add", spv::OpAtomicIAdd)
4294 .Case("spirv.atomic_sub", spv::OpAtomicISub)
4295 .Case("spirv.atomic_exchange", spv::OpAtomicExchange)
4296 .Case("spirv.atomic_inc", spv::OpAtomicIIncrement)
4297 .Case("spirv.atomic_dec", spv::OpAtomicIDecrement)
4298 .Case("spirv.atomic_compare_exchange",
4299 spv::OpAtomicCompareExchange)
4300 .Case("spirv.atomic_umin", spv::OpAtomicUMin)
4301 .Case("spirv.atomic_smin", spv::OpAtomicSMin)
4302 .Case("spirv.atomic_umax", spv::OpAtomicUMax)
4303 .Case("spirv.atomic_smax", spv::OpAtomicSMax)
4304 .Case("spirv.atomic_and", spv::OpAtomicAnd)
4305 .Case("spirv.atomic_or", spv::OpAtomicOr)
4306 .Case("spirv.atomic_xor", spv::OpAtomicXor)
4307 .Default(spv::OpNop);
4308
4309 //
4310 // Generate OpAtomic*.
4311 //
4312 SPIRVOperandList Ops;
4313
David Neto257c3892018-04-11 13:19:45 -04004314 Ops << MkId(lookupType(I.getType()));
David Neto22f144c2017-06-12 14:26:21 -04004315
4316 for (unsigned i = 0; i < Call->getNumArgOperands(); i++) {
David Neto257c3892018-04-11 13:19:45 -04004317 Ops << MkId(VMap[Call->getArgOperand(i)]);
David Neto22f144c2017-06-12 14:26:21 -04004318 }
4319
4320 VMap[&I] = nextID;
4321
David Neto87846742018-04-11 17:36:22 -04004322 auto *Inst = new SPIRVInstruction(opcode, nextID++, Ops);
David Neto22f144c2017-06-12 14:26:21 -04004323 SPIRVInstList.push_back(Inst);
4324 break;
4325 }
4326
4327 if (Callee->getName().startswith("_Z3dot")) {
4328 // If the argument is a vector type, generate OpDot
4329 if (Call->getArgOperand(0)->getType()->isVectorTy()) {
4330 //
4331 // Generate OpDot.
4332 //
4333 SPIRVOperandList Ops;
4334
David Neto257c3892018-04-11 13:19:45 -04004335 Ops << MkId(lookupType(I.getType()));
David Neto22f144c2017-06-12 14:26:21 -04004336
4337 for (unsigned i = 0; i < Call->getNumArgOperands(); i++) {
David Neto257c3892018-04-11 13:19:45 -04004338 Ops << MkId(VMap[Call->getArgOperand(i)]);
David Neto22f144c2017-06-12 14:26:21 -04004339 }
4340
4341 VMap[&I] = nextID;
4342
David Neto87846742018-04-11 17:36:22 -04004343 auto *Inst = new SPIRVInstruction(spv::OpDot, nextID++, Ops);
David Neto22f144c2017-06-12 14:26:21 -04004344 SPIRVInstList.push_back(Inst);
4345 } else {
4346 //
4347 // Generate OpFMul.
4348 //
4349 SPIRVOperandList Ops;
4350
David Neto257c3892018-04-11 13:19:45 -04004351 Ops << MkId(lookupType(I.getType()));
David Neto22f144c2017-06-12 14:26:21 -04004352
4353 for (unsigned i = 0; i < Call->getNumArgOperands(); i++) {
David Neto257c3892018-04-11 13:19:45 -04004354 Ops << MkId(VMap[Call->getArgOperand(i)]);
David Neto22f144c2017-06-12 14:26:21 -04004355 }
4356
4357 VMap[&I] = nextID;
4358
David Neto87846742018-04-11 17:36:22 -04004359 auto *Inst = new SPIRVInstruction(spv::OpFMul, nextID++, Ops);
David Neto22f144c2017-06-12 14:26:21 -04004360 SPIRVInstList.push_back(Inst);
4361 }
4362 break;
4363 }
4364
David Neto8505ebf2017-10-13 18:50:50 -04004365 if (Callee->getName().startswith("_Z4fmod")) {
4366 // OpenCL fmod(x,y) is x - y * trunc(x/y)
4367 // The sign for a non-zero result is taken from x.
4368 // (Try an example.)
4369 // So translate to OpFRem
4370
4371 SPIRVOperandList Ops;
4372
David Neto257c3892018-04-11 13:19:45 -04004373 Ops << MkId(lookupType(I.getType()));
David Neto8505ebf2017-10-13 18:50:50 -04004374
4375 for (unsigned i = 0; i < Call->getNumArgOperands(); i++) {
David Neto257c3892018-04-11 13:19:45 -04004376 Ops << MkId(VMap[Call->getArgOperand(i)]);
David Neto8505ebf2017-10-13 18:50:50 -04004377 }
4378
4379 VMap[&I] = nextID;
4380
David Neto87846742018-04-11 17:36:22 -04004381 auto *Inst = new SPIRVInstruction(spv::OpFRem, nextID++, Ops);
David Neto8505ebf2017-10-13 18:50:50 -04004382 SPIRVInstList.push_back(Inst);
4383 break;
4384 }
4385
David Neto22f144c2017-06-12 14:26:21 -04004386 // spirv.store_null.* intrinsics become OpStore's.
4387 if (Callee->getName().startswith("spirv.store_null")) {
4388 //
4389 // Generate OpStore.
4390 //
4391
4392 // Ops[0] = Pointer ID
4393 // Ops[1] = Object ID
4394 // Ops[2] ... Ops[n]
4395 SPIRVOperandList Ops;
4396
4397 uint32_t PointerID = VMap[Call->getArgOperand(0)];
David Neto22f144c2017-06-12 14:26:21 -04004398 uint32_t ObjectID = VMap[Call->getArgOperand(1)];
David Neto257c3892018-04-11 13:19:45 -04004399 Ops << MkId(PointerID) << MkId(ObjectID);
David Neto22f144c2017-06-12 14:26:21 -04004400
David Neto87846742018-04-11 17:36:22 -04004401 SPIRVInstList.push_back(new SPIRVInstruction(spv::OpStore, Ops));
David Neto22f144c2017-06-12 14:26:21 -04004402
4403 break;
4404 }
4405
4406 // spirv.copy_memory.* intrinsics become OpMemoryMemory's.
4407 if (Callee->getName().startswith("spirv.copy_memory")) {
4408 //
4409 // Generate OpCopyMemory.
4410 //
4411
4412 // Ops[0] = Dst ID
4413 // Ops[1] = Src ID
4414 // Ops[2] = Memory Access
4415 // Ops[3] = Alignment
4416
4417 auto IsVolatile =
4418 dyn_cast<ConstantInt>(Call->getArgOperand(3))->getZExtValue() != 0;
4419
4420 auto VolatileMemoryAccess = (IsVolatile) ? spv::MemoryAccessVolatileMask
4421 : spv::MemoryAccessMaskNone;
4422
4423 auto MemoryAccess = VolatileMemoryAccess | spv::MemoryAccessAlignedMask;
4424
4425 auto Alignment =
4426 dyn_cast<ConstantInt>(Call->getArgOperand(2))->getZExtValue();
4427
David Neto257c3892018-04-11 13:19:45 -04004428 SPIRVOperandList Ops;
4429 Ops << MkId(VMap[Call->getArgOperand(0)])
4430 << MkId(VMap[Call->getArgOperand(1)]) << MkNum(MemoryAccess)
4431 << MkNum(static_cast<uint32_t>(Alignment));
David Neto22f144c2017-06-12 14:26:21 -04004432
David Neto87846742018-04-11 17:36:22 -04004433 auto *Inst = new SPIRVInstruction(spv::OpCopyMemory, Ops);
David Neto22f144c2017-06-12 14:26:21 -04004434
4435 SPIRVInstList.push_back(Inst);
4436
4437 break;
4438 }
4439
4440 // Nothing to do for abs with uint. Map abs's operand ID to VMap for abs
4441 // with unit.
4442 if (Callee->getName().equals("_Z3absj") ||
4443 Callee->getName().equals("_Z3absDv2_j") ||
4444 Callee->getName().equals("_Z3absDv3_j") ||
4445 Callee->getName().equals("_Z3absDv4_j")) {
4446 VMap[&I] = VMap[Call->getOperand(0)];
4447 break;
4448 }
4449
4450 // barrier is converted to OpControlBarrier
4451 if (Callee->getName().equals("__spirv_control_barrier")) {
4452 //
4453 // Generate OpControlBarrier.
4454 //
4455 // Ops[0] = Execution Scope ID
4456 // Ops[1] = Memory Scope ID
4457 // Ops[2] = Memory Semantics ID
4458 //
4459 Value *ExecutionScope = Call->getArgOperand(0);
4460 Value *MemoryScope = Call->getArgOperand(1);
4461 Value *MemorySemantics = Call->getArgOperand(2);
4462
David Neto257c3892018-04-11 13:19:45 -04004463 SPIRVOperandList Ops;
4464 Ops << MkId(VMap[ExecutionScope]) << MkId(VMap[MemoryScope])
4465 << MkId(VMap[MemorySemantics]);
David Neto22f144c2017-06-12 14:26:21 -04004466
David Neto87846742018-04-11 17:36:22 -04004467 SPIRVInstList.push_back(new SPIRVInstruction(spv::OpControlBarrier, Ops));
David Neto22f144c2017-06-12 14:26:21 -04004468 break;
4469 }
4470
4471 // memory barrier is converted to OpMemoryBarrier
4472 if (Callee->getName().equals("__spirv_memory_barrier")) {
4473 //
4474 // Generate OpMemoryBarrier.
4475 //
4476 // Ops[0] = Memory Scope ID
4477 // Ops[1] = Memory Semantics ID
4478 //
4479 SPIRVOperandList Ops;
4480
David Neto257c3892018-04-11 13:19:45 -04004481 uint32_t MemoryScopeID = VMap[Call->getArgOperand(0)];
4482 uint32_t MemorySemanticsID = VMap[Call->getArgOperand(1)];
David Neto22f144c2017-06-12 14:26:21 -04004483
David Neto257c3892018-04-11 13:19:45 -04004484 Ops << MkId(MemoryScopeID) << MkId(MemorySemanticsID);
David Neto22f144c2017-06-12 14:26:21 -04004485
David Neto87846742018-04-11 17:36:22 -04004486 auto *Inst = new SPIRVInstruction(spv::OpMemoryBarrier, Ops);
David Neto22f144c2017-06-12 14:26:21 -04004487 SPIRVInstList.push_back(Inst);
4488 break;
4489 }
4490
4491 // isinf is converted to OpIsInf
4492 if (Callee->getName().equals("__spirv_isinff") ||
4493 Callee->getName().equals("__spirv_isinfDv2_f") ||
4494 Callee->getName().equals("__spirv_isinfDv3_f") ||
4495 Callee->getName().equals("__spirv_isinfDv4_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::OpIsInf, nextID++, Ops);
David Neto22f144c2017-06-12 14:26:21 -04004510 SPIRVInstList.push_back(Inst);
4511 break;
4512 }
4513
4514 // isnan is converted to OpIsNan
4515 if (Callee->getName().equals("__spirv_isnanf") ||
4516 Callee->getName().equals("__spirv_isnanDv2_f") ||
4517 Callee->getName().equals("__spirv_isnanDv3_f") ||
4518 Callee->getName().equals("__spirv_isnanDv4_f")) {
4519 //
4520 // Generate OpIsInf.
4521 //
4522 // Ops[0] = Result Type ID
4523 // Ops[1] = X ID
4524 //
4525 SPIRVOperandList Ops;
4526
David Neto257c3892018-04-11 13:19:45 -04004527 Ops << MkId(lookupType(I.getType()))
4528 << MkId(VMap[Call->getArgOperand(0)]);
David Neto22f144c2017-06-12 14:26:21 -04004529
4530 VMap[&I] = nextID;
4531
David Neto87846742018-04-11 17:36:22 -04004532 auto *Inst = new SPIRVInstruction(spv::OpIsNan, nextID++, Ops);
David Neto22f144c2017-06-12 14:26:21 -04004533 SPIRVInstList.push_back(Inst);
4534 break;
4535 }
4536
4537 // all is converted to OpAll
4538 if (Callee->getName().equals("__spirv_allDv2_i") ||
4539 Callee->getName().equals("__spirv_allDv3_i") ||
4540 Callee->getName().equals("__spirv_allDv4_i")) {
4541 //
4542 // Generate OpAll.
4543 //
4544 // Ops[0] = Result Type ID
4545 // Ops[1] = Vector ID
4546 //
4547 SPIRVOperandList Ops;
4548
David Neto257c3892018-04-11 13:19:45 -04004549 Ops << MkId(lookupType(I.getType()))
4550 << MkId(VMap[Call->getArgOperand(0)]);
David Neto22f144c2017-06-12 14:26:21 -04004551
4552 VMap[&I] = nextID;
4553
David Neto87846742018-04-11 17:36:22 -04004554 auto *Inst = new SPIRVInstruction(spv::OpAll, nextID++, Ops);
David Neto22f144c2017-06-12 14:26:21 -04004555 SPIRVInstList.push_back(Inst);
4556 break;
4557 }
4558
4559 // any is converted to OpAny
4560 if (Callee->getName().equals("__spirv_anyDv2_i") ||
4561 Callee->getName().equals("__spirv_anyDv3_i") ||
4562 Callee->getName().equals("__spirv_anyDv4_i")) {
4563 //
4564 // Generate OpAny.
4565 //
4566 // Ops[0] = Result Type ID
4567 // Ops[1] = Vector ID
4568 //
4569 SPIRVOperandList Ops;
4570
David Neto257c3892018-04-11 13:19:45 -04004571 Ops << MkId(lookupType(I.getType()))
4572 << MkId(VMap[Call->getArgOperand(0)]);
David Neto22f144c2017-06-12 14:26:21 -04004573
4574 VMap[&I] = nextID;
4575
David Neto87846742018-04-11 17:36:22 -04004576 auto *Inst = new SPIRVInstruction(spv::OpAny, nextID++, Ops);
David Neto22f144c2017-06-12 14:26:21 -04004577 SPIRVInstList.push_back(Inst);
4578 break;
4579 }
4580
4581 // read_image is converted to OpSampledImage and OpImageSampleExplicitLod.
4582 // Additionally, OpTypeSampledImage is generated.
4583 if (Callee->getName().equals(
4584 "_Z11read_imagef14ocl_image2d_ro11ocl_samplerDv2_f") ||
4585 Callee->getName().equals(
4586 "_Z11read_imagef14ocl_image3d_ro11ocl_samplerDv4_f")) {
4587 //
4588 // Generate OpSampledImage.
4589 //
4590 // Ops[0] = Result Type ID
4591 // Ops[1] = Image ID
4592 // Ops[2] = Sampler ID
4593 //
4594 SPIRVOperandList Ops;
4595
4596 Value *Image = Call->getArgOperand(0);
4597 Value *Sampler = Call->getArgOperand(1);
4598 Value *Coordinate = Call->getArgOperand(2);
4599
4600 TypeMapType &OpImageTypeMap = getImageTypeMap();
4601 Type *ImageTy = Image->getType()->getPointerElementType();
4602 uint32_t ImageTyID = OpImageTypeMap[ImageTy];
David Neto22f144c2017-06-12 14:26:21 -04004603 uint32_t ImageID = VMap[Image];
David Neto22f144c2017-06-12 14:26:21 -04004604 uint32_t SamplerID = VMap[Sampler];
David Neto257c3892018-04-11 13:19:45 -04004605
4606 Ops << MkId(ImageTyID) << MkId(ImageID) << MkId(SamplerID);
David Neto22f144c2017-06-12 14:26:21 -04004607
4608 uint32_t SampledImageID = nextID;
4609
David Neto87846742018-04-11 17:36:22 -04004610 auto *Inst = new SPIRVInstruction(spv::OpSampledImage, nextID++, Ops);
David Neto22f144c2017-06-12 14:26:21 -04004611 SPIRVInstList.push_back(Inst);
4612
4613 //
4614 // Generate OpImageSampleExplicitLod.
4615 //
4616 // Ops[0] = Result Type ID
4617 // Ops[1] = Sampled Image ID
4618 // Ops[2] = Coordinate ID
4619 // Ops[3] = Image Operands Type ID
4620 // Ops[4] ... Ops[n] = Operands ID
4621 //
4622 Ops.clear();
4623
David Neto257c3892018-04-11 13:19:45 -04004624 Ops << MkId(lookupType(Call->getType())) << MkId(SampledImageID)
4625 << MkId(VMap[Coordinate]) << MkNum(spv::ImageOperandsLodMask);
David Neto22f144c2017-06-12 14:26:21 -04004626
4627 Constant *CstFP0 = ConstantFP::get(Context, APFloat(0.0f));
David Neto257c3892018-04-11 13:19:45 -04004628 Ops << MkId(VMap[CstFP0]);
David Neto22f144c2017-06-12 14:26:21 -04004629
4630 VMap[&I] = nextID;
4631
David Neto87846742018-04-11 17:36:22 -04004632 Inst = new SPIRVInstruction(spv::OpImageSampleExplicitLod, nextID++, Ops);
David Neto22f144c2017-06-12 14:26:21 -04004633 SPIRVInstList.push_back(Inst);
4634 break;
4635 }
4636
4637 // write_imagef is mapped to OpImageWrite.
4638 if (Callee->getName().equals(
4639 "_Z12write_imagef14ocl_image2d_woDv2_iDv4_f") ||
4640 Callee->getName().equals(
4641 "_Z12write_imagef14ocl_image3d_woDv4_iDv4_f")) {
4642 //
4643 // Generate OpImageWrite.
4644 //
4645 // Ops[0] = Image ID
4646 // Ops[1] = Coordinate ID
4647 // Ops[2] = Texel ID
4648 // Ops[3] = (Optional) Image Operands Type (Literal Number)
4649 // Ops[4] ... Ops[n] = (Optional) Operands ID
4650 //
4651 SPIRVOperandList Ops;
4652
4653 Value *Image = Call->getArgOperand(0);
4654 Value *Coordinate = Call->getArgOperand(1);
4655 Value *Texel = Call->getArgOperand(2);
4656
4657 uint32_t ImageID = VMap[Image];
David Neto22f144c2017-06-12 14:26:21 -04004658 uint32_t CoordinateID = VMap[Coordinate];
David Neto22f144c2017-06-12 14:26:21 -04004659 uint32_t TexelID = VMap[Texel];
David Neto257c3892018-04-11 13:19:45 -04004660 Ops << MkId(ImageID) << MkId(CoordinateID) << MkId(TexelID);
David Neto22f144c2017-06-12 14:26:21 -04004661
David Neto87846742018-04-11 17:36:22 -04004662 auto *Inst = new SPIRVInstruction(spv::OpImageWrite, Ops);
David Neto22f144c2017-06-12 14:26:21 -04004663 SPIRVInstList.push_back(Inst);
4664 break;
4665 }
4666
David Neto5c22a252018-03-15 16:07:41 -04004667 // get_image_width is mapped to OpImageQuerySize
4668 if (Callee->getName().equals("_Z15get_image_width14ocl_image2d_ro") ||
4669 Callee->getName().equals("_Z15get_image_width14ocl_image2d_wo") ||
4670 Callee->getName().equals("_Z16get_image_height14ocl_image2d_ro") ||
4671 Callee->getName().equals("_Z16get_image_height14ocl_image2d_wo")) {
4672 //
4673 // Generate OpImageQuerySize, then pull out the right component.
4674 // Assume 2D image for now.
4675 //
4676 // Ops[0] = Image ID
4677 //
4678 // %sizes = OpImageQuerySizes %uint2 %im
4679 // %result = OpCompositeExtract %uint %sizes 0-or-1
4680 SPIRVOperandList Ops;
4681
4682 // Implement:
4683 // %sizes = OpImageQuerySizes %uint2 %im
4684 uint32_t SizesTypeID =
4685 TypeMap[VectorType::get(Type::getInt32Ty(Context), 2)];
David Neto5c22a252018-03-15 16:07:41 -04004686 Value *Image = Call->getArgOperand(0);
4687 uint32_t ImageID = VMap[Image];
David Neto257c3892018-04-11 13:19:45 -04004688 Ops << MkId(SizesTypeID) << MkId(ImageID);
David Neto5c22a252018-03-15 16:07:41 -04004689
4690 uint32_t SizesID = nextID++;
David Neto87846742018-04-11 17:36:22 -04004691 auto *QueryInst =
4692 new SPIRVInstruction(spv::OpImageQuerySize, SizesID, Ops);
David Neto5c22a252018-03-15 16:07:41 -04004693 SPIRVInstList.push_back(QueryInst);
4694
4695 // Reset value map entry since we generated an intermediate instruction.
4696 VMap[&I] = nextID;
4697
4698 // Implement:
4699 // %result = OpCompositeExtract %uint %sizes 0-or-1
4700 Ops.clear();
David Neto257c3892018-04-11 13:19:45 -04004701 Ops << MkId(TypeMap[I.getType()]) << MkId(SizesID);
David Neto5c22a252018-03-15 16:07:41 -04004702
4703 uint32_t component = Callee->getName().contains("height") ? 1 : 0;
David Neto257c3892018-04-11 13:19:45 -04004704 Ops << MkNum(component);
David Neto5c22a252018-03-15 16:07:41 -04004705
David Neto87846742018-04-11 17:36:22 -04004706 auto *Inst = new SPIRVInstruction(spv::OpCompositeExtract, nextID++, Ops);
David Neto5c22a252018-03-15 16:07:41 -04004707 SPIRVInstList.push_back(Inst);
4708 break;
4709 }
4710
David Neto22f144c2017-06-12 14:26:21 -04004711 // Call instrucion is deferred because it needs function's ID. Record
4712 // slot's location on SPIRVInstructionList.
4713 DeferredInsts.push_back(
4714 std::make_tuple(&I, --SPIRVInstList.end(), nextID++));
4715
David Neto3fbb4072017-10-16 11:28:14 -04004716 // Check whether the implementation of this call uses an extended
4717 // instruction plus one more value-producing instruction. If so, then
4718 // reserve the id for the extra value-producing slot.
4719 glsl::ExtInst EInst = getIndirectExtInstEnum(Callee->getName());
4720 if (EInst != kGlslExtInstBad) {
4721 // Reserve a spot for the extra value.
David Neto4d02a532017-09-17 12:57:44 -04004722 // Increase nextID.
David Neto22f144c2017-06-12 14:26:21 -04004723 VMap[&I] = nextID;
4724 nextID++;
4725 }
4726 break;
4727 }
4728 case Instruction::Ret: {
4729 unsigned NumOps = I.getNumOperands();
4730 if (NumOps == 0) {
4731 //
4732 // Generate OpReturn.
4733 //
David Neto87846742018-04-11 17:36:22 -04004734 SPIRVInstList.push_back(new SPIRVInstruction(spv::OpReturn, {}));
David Neto22f144c2017-06-12 14:26:21 -04004735 } else {
4736 //
4737 // Generate OpReturnValue.
4738 //
4739
4740 // Ops[0] = Return Value ID
4741 SPIRVOperandList Ops;
David Neto257c3892018-04-11 13:19:45 -04004742
4743 Ops << MkId(VMap[I.getOperand(0)]);
David Neto22f144c2017-06-12 14:26:21 -04004744
David Neto87846742018-04-11 17:36:22 -04004745 auto *Inst = new SPIRVInstruction(spv::OpReturnValue, Ops);
David Neto22f144c2017-06-12 14:26:21 -04004746 SPIRVInstList.push_back(Inst);
4747 break;
4748 }
4749 break;
4750 }
4751 }
4752}
4753
4754void SPIRVProducerPass::GenerateFuncEpilogue() {
4755 SPIRVInstructionList &SPIRVInstList = getSPIRVInstList();
4756
4757 //
4758 // Generate OpFunctionEnd
4759 //
4760
David Neto87846742018-04-11 17:36:22 -04004761 auto *Inst = new SPIRVInstruction(spv::OpFunctionEnd, {});
David Neto22f144c2017-06-12 14:26:21 -04004762 SPIRVInstList.push_back(Inst);
4763}
4764
4765bool SPIRVProducerPass::is4xi8vec(Type *Ty) const {
4766 LLVMContext &Context = Ty->getContext();
4767 if (Ty->isVectorTy()) {
4768 if (Ty->getVectorElementType() == Type::getInt8Ty(Context) &&
4769 Ty->getVectorNumElements() == 4) {
4770 return true;
4771 }
4772 }
4773
4774 return false;
4775}
4776
David Neto257c3892018-04-11 13:19:45 -04004777uint32_t SPIRVProducerPass::GetI32Zero() {
4778 if (0 == constant_i32_zero_id_) {
4779 llvm_unreachable("Requesting a 32-bit integer constant but it is not "
4780 "defined in the SPIR-V module");
4781 }
4782 return constant_i32_zero_id_;
4783}
4784
David Neto22f144c2017-06-12 14:26:21 -04004785void SPIRVProducerPass::HandleDeferredInstruction() {
4786 SPIRVInstructionList &SPIRVInstList = getSPIRVInstList();
4787 ValueMapType &VMap = getValueMap();
4788 DeferredInstVecType &DeferredInsts = getDeferredInstVec();
4789
4790 for (auto DeferredInst = DeferredInsts.rbegin();
4791 DeferredInst != DeferredInsts.rend(); ++DeferredInst) {
4792 Value *Inst = std::get<0>(*DeferredInst);
4793 SPIRVInstructionList::iterator InsertPoint = ++std::get<1>(*DeferredInst);
4794 if (InsertPoint != SPIRVInstList.end()) {
4795 while ((*InsertPoint)->getOpcode() == spv::OpPhi) {
4796 ++InsertPoint;
4797 }
4798 }
4799
4800 if (BranchInst *Br = dyn_cast<BranchInst>(Inst)) {
4801 // Check whether basic block, which has this branch instruction, is loop
4802 // header or not. If it is loop header, generate OpLoopMerge and
4803 // OpBranchConditional.
4804 Function *Func = Br->getParent()->getParent();
4805 DominatorTree &DT =
4806 getAnalysis<DominatorTreeWrapperPass>(*Func).getDomTree();
4807 const LoopInfo &LI =
4808 getAnalysis<LoopInfoWrapperPass>(*Func).getLoopInfo();
4809
4810 BasicBlock *BrBB = Br->getParent();
4811 if (LI.isLoopHeader(BrBB)) {
4812 Value *ContinueBB = nullptr;
4813 Value *MergeBB = nullptr;
4814
4815 Loop *L = LI.getLoopFor(BrBB);
4816 MergeBB = L->getExitBlock();
4817 if (!MergeBB) {
4818 // StructurizeCFG pass converts CFG into triangle shape and the cfg
4819 // has regions with single entry/exit. As a result, loop should not
4820 // have multiple exits.
4821 llvm_unreachable("Loop has multiple exits???");
4822 }
4823
4824 if (L->isLoopLatch(BrBB)) {
4825 ContinueBB = BrBB;
4826 } else {
4827 // From SPIR-V spec 2.11, Continue Target must dominate that back-edge
4828 // block.
4829 BasicBlock *Header = L->getHeader();
4830 BasicBlock *Latch = L->getLoopLatch();
4831 for (BasicBlock *BB : L->blocks()) {
4832 if (BB == Header) {
4833 continue;
4834 }
4835
4836 // Check whether block dominates block with back-edge.
4837 if (DT.dominates(BB, Latch)) {
4838 ContinueBB = BB;
4839 }
4840 }
4841
4842 if (!ContinueBB) {
4843 llvm_unreachable("Wrong continue block from loop");
4844 }
4845 }
4846
4847 //
4848 // Generate OpLoopMerge.
4849 //
4850 // Ops[0] = Merge Block ID
4851 // Ops[1] = Continue Target ID
4852 // Ops[2] = Selection Control
4853 SPIRVOperandList Ops;
4854
4855 // StructurizeCFG pass already manipulated CFG. Just use false block of
4856 // branch instruction as merge block.
4857 uint32_t MergeBBID = VMap[MergeBB];
David Neto22f144c2017-06-12 14:26:21 -04004858 uint32_t ContinueBBID = VMap[ContinueBB];
David Neto257c3892018-04-11 13:19:45 -04004859 Ops << MkId(MergeBBID) << MkId(ContinueBBID)
4860 << MkNum(spv::SelectionControlMaskNone);
David Neto22f144c2017-06-12 14:26:21 -04004861
David Neto87846742018-04-11 17:36:22 -04004862 auto *MergeInst = new SPIRVInstruction(spv::OpLoopMerge, Ops);
David Neto22f144c2017-06-12 14:26:21 -04004863 SPIRVInstList.insert(InsertPoint, MergeInst);
4864
4865 } else if (Br->isConditional()) {
4866 bool HasBackEdge = false;
4867
4868 for (unsigned i = 0; i < Br->getNumSuccessors(); i++) {
4869 if (LI.isLoopHeader(Br->getSuccessor(i))) {
4870 HasBackEdge = true;
4871 }
4872 }
4873 if (!HasBackEdge) {
4874 //
4875 // Generate OpSelectionMerge.
4876 //
4877 // Ops[0] = Merge Block ID
4878 // Ops[1] = Selection Control
4879 SPIRVOperandList Ops;
4880
4881 // StructurizeCFG pass already manipulated CFG. Just use false block
4882 // of branch instruction as merge block.
4883 uint32_t MergeBBID = VMap[Br->getSuccessor(1)];
David Neto257c3892018-04-11 13:19:45 -04004884 Ops << MkId(MergeBBID) << MkNum(spv::SelectionControlMaskNone);
David Neto22f144c2017-06-12 14:26:21 -04004885
David Neto87846742018-04-11 17:36:22 -04004886 auto *MergeInst = new SPIRVInstruction(spv::OpSelectionMerge, Ops);
David Neto22f144c2017-06-12 14:26:21 -04004887 SPIRVInstList.insert(InsertPoint, MergeInst);
4888 }
4889 }
4890
4891 if (Br->isConditional()) {
4892 //
4893 // Generate OpBranchConditional.
4894 //
4895 // Ops[0] = Condition ID
4896 // Ops[1] = True Label ID
4897 // Ops[2] = False Label ID
4898 // Ops[3] ... Ops[n] = Branch weights (Literal Number)
4899 SPIRVOperandList Ops;
4900
4901 uint32_t CondID = VMap[Br->getCondition()];
David Neto22f144c2017-06-12 14:26:21 -04004902 uint32_t TrueBBID = VMap[Br->getSuccessor(0)];
David Neto22f144c2017-06-12 14:26:21 -04004903 uint32_t FalseBBID = VMap[Br->getSuccessor(1)];
David Neto257c3892018-04-11 13:19:45 -04004904
4905 Ops << MkId(CondID) << MkId(TrueBBID) << MkId(FalseBBID);
David Neto22f144c2017-06-12 14:26:21 -04004906
David Neto87846742018-04-11 17:36:22 -04004907 auto *BrInst = new SPIRVInstruction(spv::OpBranchConditional, Ops);
David Neto22f144c2017-06-12 14:26:21 -04004908 SPIRVInstList.insert(InsertPoint, BrInst);
4909 } else {
4910 //
4911 // Generate OpBranch.
4912 //
4913 // Ops[0] = Target Label ID
4914 SPIRVOperandList Ops;
4915
4916 uint32_t TargetID = VMap[Br->getSuccessor(0)];
David Neto257c3892018-04-11 13:19:45 -04004917 Ops << MkId(TargetID);
David Neto22f144c2017-06-12 14:26:21 -04004918
David Neto87846742018-04-11 17:36:22 -04004919 SPIRVInstList.insert(InsertPoint,
4920 new SPIRVInstruction(spv::OpBranch, Ops));
David Neto22f144c2017-06-12 14:26:21 -04004921 }
4922 } else if (PHINode *PHI = dyn_cast<PHINode>(Inst)) {
4923 //
4924 // Generate OpPhi.
4925 //
4926 // Ops[0] = Result Type ID
4927 // Ops[1] ... Ops[n] = (Variable ID, Parent ID) pairs
4928 SPIRVOperandList Ops;
4929
David Neto257c3892018-04-11 13:19:45 -04004930 Ops << MkId(lookupType(PHI->getType()));
David Neto22f144c2017-06-12 14:26:21 -04004931
David Neto22f144c2017-06-12 14:26:21 -04004932 for (unsigned i = 0; i < PHI->getNumIncomingValues(); i++) {
4933 uint32_t VarID = VMap[PHI->getIncomingValue(i)];
David Neto22f144c2017-06-12 14:26:21 -04004934 uint32_t ParentID = VMap[PHI->getIncomingBlock(i)];
David Neto257c3892018-04-11 13:19:45 -04004935 Ops << MkId(VarID) << MkId(ParentID);
David Neto22f144c2017-06-12 14:26:21 -04004936 }
4937
4938 SPIRVInstList.insert(
David Neto87846742018-04-11 17:36:22 -04004939 InsertPoint,
4940 new SPIRVInstruction(spv::OpPhi, std::get<2>(*DeferredInst), Ops));
David Neto22f144c2017-06-12 14:26:21 -04004941 } else if (CallInst *Call = dyn_cast<CallInst>(Inst)) {
4942 Function *Callee = Call->getCalledFunction();
David Neto3fbb4072017-10-16 11:28:14 -04004943 auto callee_name = Callee->getName();
4944 glsl::ExtInst EInst = getDirectOrIndirectExtInstEnum(callee_name);
David Neto22f144c2017-06-12 14:26:21 -04004945
4946 if (EInst) {
4947 uint32_t &ExtInstImportID = getOpExtInstImportID();
4948
4949 //
4950 // Generate OpExtInst.
4951 //
4952
4953 // Ops[0] = Result Type ID
4954 // Ops[1] = Set ID (OpExtInstImport ID)
4955 // Ops[2] = Instruction Number (Literal Number)
4956 // Ops[3] ... Ops[n] = Operand 1, ... , Operand n
4957 SPIRVOperandList Ops;
4958
David Neto257c3892018-04-11 13:19:45 -04004959 Ops << MkId(lookupType(Call->getType())) << MkId(ExtInstImportID) << MkNum(EInst);
David Neto22f144c2017-06-12 14:26:21 -04004960
David Neto22f144c2017-06-12 14:26:21 -04004961 FunctionType *CalleeFTy = cast<FunctionType>(Call->getFunctionType());
4962 for (unsigned i = 0; i < CalleeFTy->getNumParams(); i++) {
David Neto257c3892018-04-11 13:19:45 -04004963 Ops << MkId(VMap[Call->getOperand(i)]);
David Neto22f144c2017-06-12 14:26:21 -04004964 }
4965
David Neto87846742018-04-11 17:36:22 -04004966 auto *ExtInst = new SPIRVInstruction(spv::OpExtInst,
4967 std::get<2>(*DeferredInst), Ops);
David Neto22f144c2017-06-12 14:26:21 -04004968 SPIRVInstList.insert(InsertPoint, ExtInst);
4969
David Neto3fbb4072017-10-16 11:28:14 -04004970 const auto IndirectExtInst = getIndirectExtInstEnum(callee_name);
4971 if (IndirectExtInst != kGlslExtInstBad) {
4972 // Generate one more instruction that uses the result of the extended
4973 // instruction. Its result id is one more than the id of the
4974 // extended instruction.
David Neto22f144c2017-06-12 14:26:21 -04004975 LLVMContext &Context =
4976 Call->getParent()->getParent()->getParent()->getContext();
David Neto22f144c2017-06-12 14:26:21 -04004977
David Neto3fbb4072017-10-16 11:28:14 -04004978 auto generate_extra_inst = [this, &Context, &Call, &DeferredInst,
4979 &VMap, &SPIRVInstList, &InsertPoint](
4980 spv::Op opcode, Constant *constant) {
4981 //
4982 // Generate instruction like:
4983 // result = opcode constant <extinst-result>
4984 //
4985 // Ops[0] = Result Type ID
4986 // Ops[1] = Operand 0 ;; the constant, suitably splatted
4987 // Ops[2] = Operand 1 ;; the result of the extended instruction
4988 SPIRVOperandList Ops;
David Neto22f144c2017-06-12 14:26:21 -04004989
David Neto3fbb4072017-10-16 11:28:14 -04004990 Type *resultTy = Call->getType();
David Neto257c3892018-04-11 13:19:45 -04004991 Ops << MkId(lookupType(resultTy));
David Neto3fbb4072017-10-16 11:28:14 -04004992
4993 if (auto *vectorTy = dyn_cast<VectorType>(resultTy)) {
4994 constant = ConstantVector::getSplat(
4995 static_cast<unsigned>(vectorTy->getNumElements()), constant);
4996 }
David Neto257c3892018-04-11 13:19:45 -04004997 Ops << MkId(VMap[constant]) << MkId(std::get<2>(*DeferredInst));
David Neto3fbb4072017-10-16 11:28:14 -04004998
4999 SPIRVInstList.insert(
David Neto87846742018-04-11 17:36:22 -04005000 InsertPoint, new SPIRVInstruction(
5001 opcode, std::get<2>(*DeferredInst) + 1, Ops));
David Neto3fbb4072017-10-16 11:28:14 -04005002 };
5003
5004 switch (IndirectExtInst) {
5005 case glsl::ExtInstFindUMsb: // Implementing clz
5006 generate_extra_inst(
5007 spv::OpISub, ConstantInt::get(Type::getInt32Ty(Context), 31));
5008 break;
5009 case glsl::ExtInstAcos: // Implementing acospi
5010 case glsl::ExtInstAsin: // Implementing asinpi
5011 case glsl::ExtInstAtan2: // Implementing atan2pi
5012 generate_extra_inst(
5013 spv::OpFMul,
5014 ConstantFP::get(Type::getFloatTy(Context), kOneOverPi));
5015 break;
5016
5017 default:
5018 assert(false && "internally inconsistent");
David Neto4d02a532017-09-17 12:57:44 -04005019 }
David Neto22f144c2017-06-12 14:26:21 -04005020 }
David Neto3fbb4072017-10-16 11:28:14 -04005021
David Neto22f144c2017-06-12 14:26:21 -04005022 } else if (Callee->getName().equals("_Z8popcounti") ||
5023 Callee->getName().equals("_Z8popcountj") ||
5024 Callee->getName().equals("_Z8popcountDv2_i") ||
5025 Callee->getName().equals("_Z8popcountDv3_i") ||
5026 Callee->getName().equals("_Z8popcountDv4_i") ||
5027 Callee->getName().equals("_Z8popcountDv2_j") ||
5028 Callee->getName().equals("_Z8popcountDv3_j") ||
5029 Callee->getName().equals("_Z8popcountDv4_j")) {
5030 //
5031 // Generate OpBitCount
5032 //
5033 // Ops[0] = Result Type ID
5034 // Ops[1] = Base ID
David Neto257c3892018-04-11 13:19:45 -04005035 SPIRVOperandList Ops;
5036 Ops << MkId(lookupType(Call->getType()))
5037 << MkId(VMap[Call->getOperand(0)]);
David Neto22f144c2017-06-12 14:26:21 -04005038
5039 SPIRVInstList.insert(
David Neto87846742018-04-11 17:36:22 -04005040 InsertPoint, new SPIRVInstruction(spv::OpBitCount,
David Neto22f144c2017-06-12 14:26:21 -04005041 std::get<2>(*DeferredInst), Ops));
David Netoab03f432017-11-03 17:00:44 -04005042
5043 } else if (Callee->getName().startswith(kCompositeConstructFunctionPrefix)) {
5044
5045 // Generate an OpCompositeConstruct
5046 SPIRVOperandList Ops;
5047
5048 // The result type.
David Neto257c3892018-04-11 13:19:45 -04005049 Ops << MkId(lookupType(Call->getType()));
David Netoab03f432017-11-03 17:00:44 -04005050
5051 for (Use &use : Call->arg_operands()) {
David Neto257c3892018-04-11 13:19:45 -04005052 Ops << MkId(VMap[use.get()]);
David Netoab03f432017-11-03 17:00:44 -04005053 }
5054
5055 SPIRVInstList.insert(
David Neto87846742018-04-11 17:36:22 -04005056 InsertPoint, new SPIRVInstruction(spv::OpCompositeConstruct,
5057 std::get<2>(*DeferredInst), Ops));
David Netoab03f432017-11-03 17:00:44 -04005058
David Neto22f144c2017-06-12 14:26:21 -04005059 } else {
5060 //
5061 // Generate OpFunctionCall.
5062 //
5063
5064 // Ops[0] = Result Type ID
5065 // Ops[1] = Callee Function ID
5066 // Ops[2] ... Ops[n] = Argument 0, ... , Argument n
5067 SPIRVOperandList Ops;
5068
David Neto257c3892018-04-11 13:19:45 -04005069 Ops << MkId( lookupType(Call->getType()));
David Neto22f144c2017-06-12 14:26:21 -04005070
5071 uint32_t CalleeID = VMap[Callee];
David Neto43568eb2017-10-13 18:25:25 -04005072 if (CalleeID == 0) {
5073 errs() << "Can't translate function call. Missing builtin? "
5074 << Callee->getName() << " in: " << *Call << "\n";
5075 // TODO(dneto): Can we error out? Enabling this llvm_unreachable
5076 // causes an infinite loop. Instead, go ahead and generate
5077 // the bad function call. A validator will catch the 0-Id.
5078 // llvm_unreachable("Can't translate function call");
5079 }
David Neto22f144c2017-06-12 14:26:21 -04005080
David Neto257c3892018-04-11 13:19:45 -04005081 Ops << MkId(CalleeID);
David Neto22f144c2017-06-12 14:26:21 -04005082
David Neto22f144c2017-06-12 14:26:21 -04005083 FunctionType *CalleeFTy = cast<FunctionType>(Call->getFunctionType());
5084 for (unsigned i = 0; i < CalleeFTy->getNumParams(); i++) {
David Neto257c3892018-04-11 13:19:45 -04005085 Ops << MkId(VMap[Call->getOperand(i)]);
David Neto22f144c2017-06-12 14:26:21 -04005086 }
5087
David Neto87846742018-04-11 17:36:22 -04005088 auto *CallInst = new SPIRVInstruction(spv::OpFunctionCall,
5089 std::get<2>(*DeferredInst), Ops);
David Neto22f144c2017-06-12 14:26:21 -04005090 SPIRVInstList.insert(InsertPoint, CallInst);
5091 }
5092 }
5093 }
5094}
5095
David Neto1a1a0582017-07-07 12:01:44 -04005096void SPIRVProducerPass::HandleDeferredDecorations(const DataLayout &DL) {
David Netoc6f3ab22018-04-06 18:02:31 -04005097 if (getTypesNeedingArrayStride().empty() && LocalArgs.empty()) {
David Neto1a1a0582017-07-07 12:01:44 -04005098 return;
David Netoc6f3ab22018-04-06 18:02:31 -04005099 }
David Neto1a1a0582017-07-07 12:01:44 -04005100
5101 SPIRVInstructionList &SPIRVInstList = getSPIRVInstList();
David Neto1a1a0582017-07-07 12:01:44 -04005102
5103 // Find an iterator pointing just past the last decoration.
5104 bool seen_decorations = false;
5105 auto DecoInsertPoint =
5106 std::find_if(SPIRVInstList.begin(), SPIRVInstList.end(),
5107 [&seen_decorations](SPIRVInstruction *Inst) -> bool {
5108 const bool is_decoration =
5109 Inst->getOpcode() == spv::OpDecorate ||
5110 Inst->getOpcode() == spv::OpMemberDecorate;
5111 if (is_decoration) {
5112 seen_decorations = true;
5113 return false;
5114 } else {
5115 return seen_decorations;
5116 }
5117 });
5118
David Netoc6f3ab22018-04-06 18:02:31 -04005119 // Insert ArrayStride decorations on pointer types, due to OpPtrAccessChain
5120 // instructions we generated earlier.
David Neto85082642018-03-24 06:55:20 -07005121 for (auto *type : getTypesNeedingArrayStride()) {
5122 Type *elemTy = nullptr;
5123 if (auto *ptrTy = dyn_cast<PointerType>(type)) {
5124 elemTy = ptrTy->getElementType();
5125 } else if (auto* arrayTy = dyn_cast<ArrayType>(type)) {
5126 elemTy = arrayTy->getArrayElementType();
5127 } else if (auto* seqTy = dyn_cast<SequentialType>(type)) {
5128 elemTy = seqTy->getSequentialElementType();
5129 } else {
5130 errs() << "Unhandled strided type " << *type << "\n";
5131 llvm_unreachable("Unhandled strided type");
5132 }
David Neto1a1a0582017-07-07 12:01:44 -04005133
5134 // Ops[0] = Target ID
5135 // Ops[1] = Decoration (ArrayStride)
5136 // Ops[2] = Stride number (Literal Number)
5137 SPIRVOperandList Ops;
5138
David Neto85082642018-03-24 06:55:20 -07005139 // Same as DL.getIndexedOffsetInType( elemTy, { 1 } );
Neil Henning39672102017-09-29 14:33:13 +01005140 const uint32_t stride = static_cast<uint32_t>(DL.getTypeAllocSize(elemTy));
David Neto257c3892018-04-11 13:19:45 -04005141
5142 Ops << MkId(lookupType(type)) << MkNum(spv::DecorationArrayStride)
5143 << MkNum(stride);
David Neto1a1a0582017-07-07 12:01:44 -04005144
David Neto87846742018-04-11 17:36:22 -04005145 auto *DecoInst = new SPIRVInstruction(spv::OpDecorate, Ops);
David Neto1a1a0582017-07-07 12:01:44 -04005146 SPIRVInstList.insert(DecoInsertPoint, DecoInst);
5147 }
David Netoc6f3ab22018-04-06 18:02:31 -04005148
5149 // Emit SpecId decorations targeting the array size value.
5150 for (const Argument *arg : LocalArgs) {
5151 const LocalArgInfo &arg_info = LocalArgMap[arg];
5152 SPIRVOperandList Ops;
5153 Ops << MkId(arg_info.array_size_id) << MkNum(spv::DecorationSpecId)
5154 << MkNum(arg_info.spec_id);
5155 SPIRVInstList.insert(DecoInsertPoint,
David Neto87846742018-04-11 17:36:22 -04005156 new SPIRVInstruction(spv::OpDecorate, Ops));
David Netoc6f3ab22018-04-06 18:02:31 -04005157 }
David Neto1a1a0582017-07-07 12:01:44 -04005158}
5159
David Neto22f144c2017-06-12 14:26:21 -04005160glsl::ExtInst SPIRVProducerPass::getExtInstEnum(StringRef Name) {
5161 return StringSwitch<glsl::ExtInst>(Name)
5162 .Case("_Z3absi", glsl::ExtInst::ExtInstSAbs)
5163 .Case("_Z3absDv2_i", glsl::ExtInst::ExtInstSAbs)
5164 .Case("_Z3absDv3_i", glsl::ExtInst::ExtInstSAbs)
5165 .Case("_Z3absDv4_i", glsl::ExtInst::ExtInstSAbs)
5166 .Case("_Z5clampiii", glsl::ExtInst::ExtInstSClamp)
5167 .Case("_Z5clampDv2_iS_S_", glsl::ExtInst::ExtInstSClamp)
5168 .Case("_Z5clampDv3_iS_S_", glsl::ExtInst::ExtInstSClamp)
5169 .Case("_Z5clampDv4_iS_S_", glsl::ExtInst::ExtInstSClamp)
5170 .Case("_Z5clampjjj", glsl::ExtInst::ExtInstUClamp)
5171 .Case("_Z5clampDv2_jS_S_", glsl::ExtInst::ExtInstUClamp)
5172 .Case("_Z5clampDv3_jS_S_", glsl::ExtInst::ExtInstUClamp)
5173 .Case("_Z5clampDv4_jS_S_", glsl::ExtInst::ExtInstUClamp)
5174 .Case("_Z5clampfff", glsl::ExtInst::ExtInstFClamp)
5175 .Case("_Z5clampDv2_fS_S_", glsl::ExtInst::ExtInstFClamp)
5176 .Case("_Z5clampDv3_fS_S_", glsl::ExtInst::ExtInstFClamp)
5177 .Case("_Z5clampDv4_fS_S_", glsl::ExtInst::ExtInstFClamp)
David Neto22f144c2017-06-12 14:26:21 -04005178 .Case("_Z3maxii", glsl::ExtInst::ExtInstSMax)
5179 .Case("_Z3maxDv2_iS_", glsl::ExtInst::ExtInstSMax)
5180 .Case("_Z3maxDv3_iS_", glsl::ExtInst::ExtInstSMax)
5181 .Case("_Z3maxDv4_iS_", glsl::ExtInst::ExtInstSMax)
5182 .Case("_Z3maxjj", glsl::ExtInst::ExtInstUMax)
5183 .Case("_Z3maxDv2_jS_", glsl::ExtInst::ExtInstUMax)
5184 .Case("_Z3maxDv3_jS_", glsl::ExtInst::ExtInstUMax)
5185 .Case("_Z3maxDv4_jS_", glsl::ExtInst::ExtInstUMax)
5186 .Case("_Z3maxff", glsl::ExtInst::ExtInstFMax)
5187 .Case("_Z3maxDv2_fS_", glsl::ExtInst::ExtInstFMax)
5188 .Case("_Z3maxDv3_fS_", glsl::ExtInst::ExtInstFMax)
5189 .Case("_Z3maxDv4_fS_", glsl::ExtInst::ExtInstFMax)
5190 .StartsWith("_Z4fmax", glsl::ExtInst::ExtInstFMax)
5191 .Case("_Z3minii", glsl::ExtInst::ExtInstSMin)
5192 .Case("_Z3minDv2_iS_", glsl::ExtInst::ExtInstSMin)
5193 .Case("_Z3minDv3_iS_", glsl::ExtInst::ExtInstSMin)
5194 .Case("_Z3minDv4_iS_", glsl::ExtInst::ExtInstSMin)
5195 .Case("_Z3minjj", glsl::ExtInst::ExtInstUMin)
5196 .Case("_Z3minDv2_jS_", glsl::ExtInst::ExtInstUMin)
5197 .Case("_Z3minDv3_jS_", glsl::ExtInst::ExtInstUMin)
5198 .Case("_Z3minDv4_jS_", glsl::ExtInst::ExtInstUMin)
5199 .Case("_Z3minff", glsl::ExtInst::ExtInstFMin)
5200 .Case("_Z3minDv2_fS_", glsl::ExtInst::ExtInstFMin)
5201 .Case("_Z3minDv3_fS_", glsl::ExtInst::ExtInstFMin)
5202 .Case("_Z3minDv4_fS_", glsl::ExtInst::ExtInstFMin)
5203 .StartsWith("_Z4fmin", glsl::ExtInst::ExtInstFMin)
5204 .StartsWith("_Z7degrees", glsl::ExtInst::ExtInstDegrees)
5205 .StartsWith("_Z7radians", glsl::ExtInst::ExtInstRadians)
5206 .StartsWith("_Z3mix", glsl::ExtInst::ExtInstFMix)
5207 .StartsWith("_Z4acos", glsl::ExtInst::ExtInstAcos)
5208 .StartsWith("_Z5acosh", glsl::ExtInst::ExtInstAcosh)
5209 .StartsWith("_Z4asin", glsl::ExtInst::ExtInstAsin)
5210 .StartsWith("_Z5asinh", glsl::ExtInst::ExtInstAsinh)
5211 .StartsWith("_Z4atan", glsl::ExtInst::ExtInstAtan)
5212 .StartsWith("_Z5atan2", glsl::ExtInst::ExtInstAtan2)
5213 .StartsWith("_Z5atanh", glsl::ExtInst::ExtInstAtanh)
5214 .StartsWith("_Z4ceil", glsl::ExtInst::ExtInstCeil)
5215 .StartsWith("_Z3sin", glsl::ExtInst::ExtInstSin)
5216 .StartsWith("_Z4sinh", glsl::ExtInst::ExtInstSinh)
5217 .StartsWith("_Z8half_sin", glsl::ExtInst::ExtInstSin)
5218 .StartsWith("_Z10native_sin", glsl::ExtInst::ExtInstSin)
5219 .StartsWith("_Z3cos", glsl::ExtInst::ExtInstCos)
5220 .StartsWith("_Z4cosh", glsl::ExtInst::ExtInstCosh)
5221 .StartsWith("_Z8half_cos", glsl::ExtInst::ExtInstCos)
5222 .StartsWith("_Z10native_cos", glsl::ExtInst::ExtInstCos)
5223 .StartsWith("_Z3tan", glsl::ExtInst::ExtInstTan)
5224 .StartsWith("_Z4tanh", glsl::ExtInst::ExtInstTanh)
5225 .StartsWith("_Z8half_tan", glsl::ExtInst::ExtInstTan)
5226 .StartsWith("_Z10native_tan", glsl::ExtInst::ExtInstTan)
5227 .StartsWith("_Z3exp", glsl::ExtInst::ExtInstExp)
5228 .StartsWith("_Z8half_exp", glsl::ExtInst::ExtInstExp)
5229 .StartsWith("_Z10native_exp", glsl::ExtInst::ExtInstExp)
5230 .StartsWith("_Z4exp2", glsl::ExtInst::ExtInstExp2)
5231 .StartsWith("_Z9half_exp2", glsl::ExtInst::ExtInstExp2)
5232 .StartsWith("_Z11native_exp2", glsl::ExtInst::ExtInstExp2)
5233 .StartsWith("_Z3log", glsl::ExtInst::ExtInstLog)
5234 .StartsWith("_Z8half_log", glsl::ExtInst::ExtInstLog)
5235 .StartsWith("_Z10native_log", glsl::ExtInst::ExtInstLog)
5236 .StartsWith("_Z4log2", glsl::ExtInst::ExtInstLog2)
5237 .StartsWith("_Z9half_log2", glsl::ExtInst::ExtInstLog2)
5238 .StartsWith("_Z11native_log2", glsl::ExtInst::ExtInstLog2)
5239 .StartsWith("_Z4fabs", glsl::ExtInst::ExtInstFAbs)
5240 .StartsWith("_Z5floor", glsl::ExtInst::ExtInstFloor)
5241 .StartsWith("_Z5ldexp", glsl::ExtInst::ExtInstLdexp)
5242 .StartsWith("_Z3pow", glsl::ExtInst::ExtInstPow)
5243 .StartsWith("_Z4powr", glsl::ExtInst::ExtInstPow)
5244 .StartsWith("_Z9half_powr", glsl::ExtInst::ExtInstPow)
5245 .StartsWith("_Z11native_powr", glsl::ExtInst::ExtInstPow)
5246 .StartsWith("_Z5round", glsl::ExtInst::ExtInstRound)
5247 .StartsWith("_Z4sqrt", glsl::ExtInst::ExtInstSqrt)
5248 .StartsWith("_Z9half_sqrt", glsl::ExtInst::ExtInstSqrt)
5249 .StartsWith("_Z11native_sqrt", glsl::ExtInst::ExtInstSqrt)
5250 .StartsWith("_Z5rsqrt", glsl::ExtInst::ExtInstInverseSqrt)
5251 .StartsWith("_Z10half_rsqrt", glsl::ExtInst::ExtInstInverseSqrt)
5252 .StartsWith("_Z12native_rsqrt", glsl::ExtInst::ExtInstInverseSqrt)
5253 .StartsWith("_Z5trunc", glsl::ExtInst::ExtInstTrunc)
5254 .StartsWith("_Z5frexp", glsl::ExtInst::ExtInstFrexp)
5255 .StartsWith("_Z4sign", glsl::ExtInst::ExtInstFSign)
5256 .StartsWith("_Z6length", glsl::ExtInst::ExtInstLength)
5257 .StartsWith("_Z8distance", glsl::ExtInst::ExtInstDistance)
David Netoe9a03512017-10-16 10:08:27 -04005258 .StartsWith("_Z4step", glsl::ExtInst::ExtInstStep)
David Neto22f144c2017-06-12 14:26:21 -04005259 .Case("_Z5crossDv3_fS_", glsl::ExtInst::ExtInstCross)
5260 .StartsWith("_Z9normalize", glsl::ExtInst::ExtInstNormalize)
5261 .StartsWith("llvm.fmuladd.", glsl::ExtInst::ExtInstFma)
5262 .Case("spirv.unpack.v2f16", glsl::ExtInst::ExtInstUnpackHalf2x16)
5263 .Case("spirv.pack.v2f16", glsl::ExtInst::ExtInstPackHalf2x16)
David Neto62653202017-10-16 19:05:18 -04005264 .Case("clspv.fract.f", glsl::ExtInst::ExtInstFract)
5265 .Case("clspv.fract.v2f", glsl::ExtInst::ExtInstFract)
5266 .Case("clspv.fract.v3f", glsl::ExtInst::ExtInstFract)
5267 .Case("clspv.fract.v4f", glsl::ExtInst::ExtInstFract)
David Neto3fbb4072017-10-16 11:28:14 -04005268 .Default(kGlslExtInstBad);
5269}
5270
5271glsl::ExtInst SPIRVProducerPass::getIndirectExtInstEnum(StringRef Name) {
5272 // Check indirect cases.
5273 return StringSwitch<glsl::ExtInst>(Name)
5274 .StartsWith("_Z3clz", glsl::ExtInst::ExtInstFindUMsb)
5275 // Use exact match on float arg because these need a multiply
5276 // of a constant of the right floating point type.
5277 .Case("_Z6acospif", glsl::ExtInst::ExtInstAcos)
5278 .Case("_Z6acospiDv2_f", glsl::ExtInst::ExtInstAcos)
5279 .Case("_Z6acospiDv3_f", glsl::ExtInst::ExtInstAcos)
5280 .Case("_Z6acospiDv4_f", glsl::ExtInst::ExtInstAcos)
5281 .Case("_Z6asinpif", glsl::ExtInst::ExtInstAsin)
5282 .Case("_Z6asinpiDv2_f", glsl::ExtInst::ExtInstAsin)
5283 .Case("_Z6asinpiDv3_f", glsl::ExtInst::ExtInstAsin)
5284 .Case("_Z6asinpiDv4_f", glsl::ExtInst::ExtInstAsin)
5285 .Case("_Z7atan2piff", glsl::ExtInst::ExtInstAtan2)
5286 .Case("_Z7atan2piDv2_fS_", glsl::ExtInst::ExtInstAtan2)
5287 .Case("_Z7atan2piDv3_fS_", glsl::ExtInst::ExtInstAtan2)
5288 .Case("_Z7atan2piDv4_fS_", glsl::ExtInst::ExtInstAtan2)
5289 .Default(kGlslExtInstBad);
5290}
5291
5292glsl::ExtInst SPIRVProducerPass::getDirectOrIndirectExtInstEnum(StringRef Name) {
5293 auto direct = getExtInstEnum(Name);
5294 if (direct != kGlslExtInstBad)
5295 return direct;
5296 return getIndirectExtInstEnum(Name);
David Neto22f144c2017-06-12 14:26:21 -04005297}
5298
5299void SPIRVProducerPass::PrintResID(SPIRVInstruction *Inst) {
5300 out << "%" << Inst->getResultID();
5301}
5302
5303void SPIRVProducerPass::PrintOpcode(SPIRVInstruction *Inst) {
5304 spv::Op Opcode = static_cast<spv::Op>(Inst->getOpcode());
5305 out << "\t" << spv::getOpName(Opcode);
5306}
5307
5308void SPIRVProducerPass::PrintOperand(SPIRVOperand *Op) {
5309 SPIRVOperandType OpTy = Op->getType();
5310 switch (OpTy) {
5311 default: {
5312 llvm_unreachable("Unsupported SPIRV Operand Type???");
5313 break;
5314 }
5315 case SPIRVOperandType::NUMBERID: {
5316 out << "%" << Op->getNumID();
5317 break;
5318 }
5319 case SPIRVOperandType::LITERAL_STRING: {
5320 out << "\"" << Op->getLiteralStr() << "\"";
5321 break;
5322 }
5323 case SPIRVOperandType::LITERAL_INTEGER: {
5324 // TODO: Handle LiteralNum carefully.
5325 for (auto Word : Op->getLiteralNum()) {
5326 out << Word;
5327 }
5328 break;
5329 }
5330 case SPIRVOperandType::LITERAL_FLOAT: {
5331 // TODO: Handle LiteralNum carefully.
5332 for (auto Word : Op->getLiteralNum()) {
5333 APFloat APF = APFloat(APFloat::IEEEsingle(), APInt(32, Word));
5334 SmallString<8> Str;
5335 APF.toString(Str, 6, 2);
5336 out << Str;
5337 }
5338 break;
5339 }
5340 }
5341}
5342
5343void SPIRVProducerPass::PrintCapability(SPIRVOperand *Op) {
5344 spv::Capability Cap = static_cast<spv::Capability>(Op->getNumID());
5345 out << spv::getCapabilityName(Cap);
5346}
5347
5348void SPIRVProducerPass::PrintExtInst(SPIRVOperand *Op) {
5349 auto LiteralNum = Op->getLiteralNum();
5350 glsl::ExtInst Ext = static_cast<glsl::ExtInst>(LiteralNum[0]);
5351 out << glsl::getExtInstName(Ext);
5352}
5353
5354void SPIRVProducerPass::PrintAddrModel(SPIRVOperand *Op) {
5355 spv::AddressingModel AddrModel =
5356 static_cast<spv::AddressingModel>(Op->getNumID());
5357 out << spv::getAddressingModelName(AddrModel);
5358}
5359
5360void SPIRVProducerPass::PrintMemModel(SPIRVOperand *Op) {
5361 spv::MemoryModel MemModel = static_cast<spv::MemoryModel>(Op->getNumID());
5362 out << spv::getMemoryModelName(MemModel);
5363}
5364
5365void SPIRVProducerPass::PrintExecModel(SPIRVOperand *Op) {
5366 spv::ExecutionModel ExecModel =
5367 static_cast<spv::ExecutionModel>(Op->getNumID());
5368 out << spv::getExecutionModelName(ExecModel);
5369}
5370
5371void SPIRVProducerPass::PrintExecMode(SPIRVOperand *Op) {
5372 spv::ExecutionMode ExecMode = static_cast<spv::ExecutionMode>(Op->getNumID());
5373 out << spv::getExecutionModeName(ExecMode);
5374}
5375
5376void SPIRVProducerPass::PrintSourceLanguage(SPIRVOperand *Op) {
5377 spv::SourceLanguage SourceLang = static_cast<spv::SourceLanguage>(Op->getNumID());
5378 out << spv::getSourceLanguageName(SourceLang);
5379}
5380
5381void SPIRVProducerPass::PrintFuncCtrl(SPIRVOperand *Op) {
5382 spv::FunctionControlMask FuncCtrl =
5383 static_cast<spv::FunctionControlMask>(Op->getNumID());
5384 out << spv::getFunctionControlName(FuncCtrl);
5385}
5386
5387void SPIRVProducerPass::PrintStorageClass(SPIRVOperand *Op) {
5388 spv::StorageClass StClass = static_cast<spv::StorageClass>(Op->getNumID());
5389 out << getStorageClassName(StClass);
5390}
5391
5392void SPIRVProducerPass::PrintDecoration(SPIRVOperand *Op) {
5393 spv::Decoration Deco = static_cast<spv::Decoration>(Op->getNumID());
5394 out << getDecorationName(Deco);
5395}
5396
5397void SPIRVProducerPass::PrintBuiltIn(SPIRVOperand *Op) {
5398 spv::BuiltIn BIn = static_cast<spv::BuiltIn>(Op->getNumID());
5399 out << getBuiltInName(BIn);
5400}
5401
5402void SPIRVProducerPass::PrintSelectionControl(SPIRVOperand *Op) {
5403 spv::SelectionControlMask BIn =
5404 static_cast<spv::SelectionControlMask>(Op->getNumID());
5405 out << getSelectionControlName(BIn);
5406}
5407
5408void SPIRVProducerPass::PrintLoopControl(SPIRVOperand *Op) {
5409 spv::LoopControlMask BIn = static_cast<spv::LoopControlMask>(Op->getNumID());
5410 out << getLoopControlName(BIn);
5411}
5412
5413void SPIRVProducerPass::PrintDimensionality(SPIRVOperand *Op) {
5414 spv::Dim DIM = static_cast<spv::Dim>(Op->getNumID());
5415 out << getDimName(DIM);
5416}
5417
5418void SPIRVProducerPass::PrintImageFormat(SPIRVOperand *Op) {
5419 spv::ImageFormat Format = static_cast<spv::ImageFormat>(Op->getNumID());
5420 out << getImageFormatName(Format);
5421}
5422
5423void SPIRVProducerPass::PrintMemoryAccess(SPIRVOperand *Op) {
5424 out << spv::getMemoryAccessName(
5425 static_cast<spv::MemoryAccessMask>(Op->getNumID()));
5426}
5427
5428void SPIRVProducerPass::PrintImageOperandsType(SPIRVOperand *Op) {
5429 auto LiteralNum = Op->getLiteralNum();
5430 spv::ImageOperandsMask Type =
5431 static_cast<spv::ImageOperandsMask>(LiteralNum[0]);
5432 out << getImageOperandsName(Type);
5433}
5434
5435void SPIRVProducerPass::WriteSPIRVAssembly() {
5436 SPIRVInstructionList &SPIRVInstList = getSPIRVInstList();
5437
5438 for (auto Inst : SPIRVInstList) {
5439 SPIRVOperandList Ops = Inst->getOperands();
5440 spv::Op Opcode = static_cast<spv::Op>(Inst->getOpcode());
5441
5442 switch (Opcode) {
5443 default: {
5444 llvm_unreachable("Unsupported SPIRV instruction");
5445 break;
5446 }
5447 case spv::OpCapability: {
5448 // Ops[0] = Capability
5449 PrintOpcode(Inst);
5450 out << " ";
5451 PrintCapability(Ops[0]);
5452 out << "\n";
5453 break;
5454 }
5455 case spv::OpMemoryModel: {
5456 // Ops[0] = Addressing Model
5457 // Ops[1] = Memory Model
5458 PrintOpcode(Inst);
5459 out << " ";
5460 PrintAddrModel(Ops[0]);
5461 out << " ";
5462 PrintMemModel(Ops[1]);
5463 out << "\n";
5464 break;
5465 }
5466 case spv::OpEntryPoint: {
5467 // Ops[0] = Execution Model
5468 // Ops[1] = EntryPoint ID
5469 // Ops[2] = Name (Literal String)
5470 // Ops[3] ... Ops[n] = Interface ID
5471 PrintOpcode(Inst);
5472 out << " ";
5473 PrintExecModel(Ops[0]);
5474 for (uint32_t i = 1; i < Ops.size(); i++) {
5475 out << " ";
5476 PrintOperand(Ops[i]);
5477 }
5478 out << "\n";
5479 break;
5480 }
5481 case spv::OpExecutionMode: {
5482 // Ops[0] = Entry Point ID
5483 // Ops[1] = Execution Mode
5484 // Ops[2] ... Ops[n] = Optional literals according to Execution Mode
5485 PrintOpcode(Inst);
5486 out << " ";
5487 PrintOperand(Ops[0]);
5488 out << " ";
5489 PrintExecMode(Ops[1]);
5490 for (uint32_t i = 2; i < Ops.size(); i++) {
5491 out << " ";
5492 PrintOperand(Ops[i]);
5493 }
5494 out << "\n";
5495 break;
5496 }
5497 case spv::OpSource: {
5498 // Ops[0] = SourceLanguage ID
5499 // Ops[1] = Version (LiteralNum)
5500 PrintOpcode(Inst);
5501 out << " ";
5502 PrintSourceLanguage(Ops[0]);
5503 out << " ";
5504 PrintOperand(Ops[1]);
5505 out << "\n";
5506 break;
5507 }
5508 case spv::OpDecorate: {
5509 // Ops[0] = Target ID
5510 // Ops[1] = Decoration (Block or BufferBlock)
5511 // Ops[2] ... Ops[n] = Optional literals according to Decoration
5512 PrintOpcode(Inst);
5513 out << " ";
5514 PrintOperand(Ops[0]);
5515 out << " ";
5516 PrintDecoration(Ops[1]);
5517 // Handle BuiltIn OpDecorate specially.
5518 if (Ops[1]->getNumID() == spv::DecorationBuiltIn) {
5519 out << " ";
5520 PrintBuiltIn(Ops[2]);
5521 } else {
5522 for (uint32_t i = 2; i < Ops.size(); i++) {
5523 out << " ";
5524 PrintOperand(Ops[i]);
5525 }
5526 }
5527 out << "\n";
5528 break;
5529 }
5530 case spv::OpMemberDecorate: {
5531 // Ops[0] = Structure Type ID
5532 // Ops[1] = Member Index(Literal Number)
5533 // Ops[2] = Decoration
5534 // Ops[3] ... Ops[n] = Optional literals according to Decoration
5535 PrintOpcode(Inst);
5536 out << " ";
5537 PrintOperand(Ops[0]);
5538 out << " ";
5539 PrintOperand(Ops[1]);
5540 out << " ";
5541 PrintDecoration(Ops[2]);
5542 for (uint32_t i = 3; i < Ops.size(); i++) {
5543 out << " ";
5544 PrintOperand(Ops[i]);
5545 }
5546 out << "\n";
5547 break;
5548 }
5549 case spv::OpTypePointer: {
5550 // Ops[0] = Storage Class
5551 // Ops[1] = Element Type ID
5552 PrintResID(Inst);
5553 out << " = ";
5554 PrintOpcode(Inst);
5555 out << " ";
5556 PrintStorageClass(Ops[0]);
5557 out << " ";
5558 PrintOperand(Ops[1]);
5559 out << "\n";
5560 break;
5561 }
5562 case spv::OpTypeImage: {
5563 // Ops[0] = Sampled Type ID
5564 // Ops[1] = Dim ID
5565 // Ops[2] = Depth (Literal Number)
5566 // Ops[3] = Arrayed (Literal Number)
5567 // Ops[4] = MS (Literal Number)
5568 // Ops[5] = Sampled (Literal Number)
5569 // Ops[6] = Image Format ID
5570 PrintResID(Inst);
5571 out << " = ";
5572 PrintOpcode(Inst);
5573 out << " ";
5574 PrintOperand(Ops[0]);
5575 out << " ";
5576 PrintDimensionality(Ops[1]);
5577 out << " ";
5578 PrintOperand(Ops[2]);
5579 out << " ";
5580 PrintOperand(Ops[3]);
5581 out << " ";
5582 PrintOperand(Ops[4]);
5583 out << " ";
5584 PrintOperand(Ops[5]);
5585 out << " ";
5586 PrintImageFormat(Ops[6]);
5587 out << "\n";
5588 break;
5589 }
5590 case spv::OpFunction: {
5591 // Ops[0] : Result Type ID
5592 // Ops[1] : Function Control
5593 // Ops[2] : Function Type ID
5594 PrintResID(Inst);
5595 out << " = ";
5596 PrintOpcode(Inst);
5597 out << " ";
5598 PrintOperand(Ops[0]);
5599 out << " ";
5600 PrintFuncCtrl(Ops[1]);
5601 out << " ";
5602 PrintOperand(Ops[2]);
5603 out << "\n";
5604 break;
5605 }
5606 case spv::OpSelectionMerge: {
5607 // Ops[0] = Merge Block ID
5608 // Ops[1] = Selection Control
5609 PrintOpcode(Inst);
5610 out << " ";
5611 PrintOperand(Ops[0]);
5612 out << " ";
5613 PrintSelectionControl(Ops[1]);
5614 out << "\n";
5615 break;
5616 }
5617 case spv::OpLoopMerge: {
5618 // Ops[0] = Merge Block ID
5619 // Ops[1] = Continue Target ID
5620 // Ops[2] = Selection Control
5621 PrintOpcode(Inst);
5622 out << " ";
5623 PrintOperand(Ops[0]);
5624 out << " ";
5625 PrintOperand(Ops[1]);
5626 out << " ";
5627 PrintLoopControl(Ops[2]);
5628 out << "\n";
5629 break;
5630 }
5631 case spv::OpImageSampleExplicitLod: {
5632 // Ops[0] = Result Type ID
5633 // Ops[1] = Sampled Image ID
5634 // Ops[2] = Coordinate ID
5635 // Ops[3] = Image Operands Type ID
5636 // Ops[4] ... Ops[n] = Operands ID
5637 PrintResID(Inst);
5638 out << " = ";
5639 PrintOpcode(Inst);
5640 for (uint32_t i = 0; i < 3; i++) {
5641 out << " ";
5642 PrintOperand(Ops[i]);
5643 }
5644 out << " ";
5645 PrintImageOperandsType(Ops[3]);
5646 for (uint32_t i = 4; i < Ops.size(); i++) {
5647 out << " ";
5648 PrintOperand(Ops[i]);
5649 }
5650 out << "\n";
5651 break;
5652 }
5653 case spv::OpVariable: {
5654 // Ops[0] : Result Type ID
5655 // Ops[1] : Storage Class
5656 // Ops[2] ... Ops[n] = Initializer IDs
5657 PrintResID(Inst);
5658 out << " = ";
5659 PrintOpcode(Inst);
5660 out << " ";
5661 PrintOperand(Ops[0]);
5662 out << " ";
5663 PrintStorageClass(Ops[1]);
5664 for (uint32_t i = 2; i < Ops.size(); i++) {
5665 out << " ";
5666 PrintOperand(Ops[i]);
5667 }
5668 out << "\n";
5669 break;
5670 }
5671 case spv::OpExtInst: {
5672 // Ops[0] = Result Type ID
5673 // Ops[1] = Set ID (OpExtInstImport ID)
5674 // Ops[2] = Instruction Number (Literal Number)
5675 // Ops[3] ... Ops[n] = Operand 1, ... , Operand n
5676 PrintResID(Inst);
5677 out << " = ";
5678 PrintOpcode(Inst);
5679 out << " ";
5680 PrintOperand(Ops[0]);
5681 out << " ";
5682 PrintOperand(Ops[1]);
5683 out << " ";
5684 PrintExtInst(Ops[2]);
5685 for (uint32_t i = 3; i < Ops.size(); i++) {
5686 out << " ";
5687 PrintOperand(Ops[i]);
5688 }
5689 out << "\n";
5690 break;
5691 }
5692 case spv::OpCopyMemory: {
5693 // Ops[0] = Addressing Model
5694 // Ops[1] = Memory Model
5695 PrintOpcode(Inst);
5696 out << " ";
5697 PrintOperand(Ops[0]);
5698 out << " ";
5699 PrintOperand(Ops[1]);
5700 out << " ";
5701 PrintMemoryAccess(Ops[2]);
5702 out << " ";
5703 PrintOperand(Ops[3]);
5704 out << "\n";
5705 break;
5706 }
5707 case spv::OpExtension:
5708 case spv::OpControlBarrier:
5709 case spv::OpMemoryBarrier:
5710 case spv::OpBranch:
5711 case spv::OpBranchConditional:
5712 case spv::OpStore:
5713 case spv::OpImageWrite:
5714 case spv::OpReturnValue:
5715 case spv::OpReturn:
5716 case spv::OpFunctionEnd: {
5717 PrintOpcode(Inst);
5718 for (uint32_t i = 0; i < Ops.size(); i++) {
5719 out << " ";
5720 PrintOperand(Ops[i]);
5721 }
5722 out << "\n";
5723 break;
5724 }
5725 case spv::OpExtInstImport:
5726 case spv::OpTypeRuntimeArray:
5727 case spv::OpTypeStruct:
5728 case spv::OpTypeSampler:
5729 case spv::OpTypeSampledImage:
5730 case spv::OpTypeInt:
5731 case spv::OpTypeFloat:
5732 case spv::OpTypeArray:
5733 case spv::OpTypeVector:
5734 case spv::OpTypeBool:
5735 case spv::OpTypeVoid:
5736 case spv::OpTypeFunction:
5737 case spv::OpFunctionParameter:
5738 case spv::OpLabel:
5739 case spv::OpPhi:
5740 case spv::OpLoad:
5741 case spv::OpSelect:
5742 case spv::OpAccessChain:
5743 case spv::OpPtrAccessChain:
5744 case spv::OpInBoundsAccessChain:
5745 case spv::OpUConvert:
5746 case spv::OpSConvert:
5747 case spv::OpConvertFToU:
5748 case spv::OpConvertFToS:
5749 case spv::OpConvertUToF:
5750 case spv::OpConvertSToF:
5751 case spv::OpFConvert:
5752 case spv::OpConvertPtrToU:
5753 case spv::OpConvertUToPtr:
5754 case spv::OpBitcast:
5755 case spv::OpIAdd:
5756 case spv::OpFAdd:
5757 case spv::OpISub:
5758 case spv::OpFSub:
5759 case spv::OpIMul:
5760 case spv::OpFMul:
5761 case spv::OpUDiv:
5762 case spv::OpSDiv:
5763 case spv::OpFDiv:
5764 case spv::OpUMod:
5765 case spv::OpSRem:
5766 case spv::OpFRem:
5767 case spv::OpBitwiseOr:
5768 case spv::OpBitwiseXor:
5769 case spv::OpBitwiseAnd:
David Netoa394f392017-08-26 20:45:29 -04005770 case spv::OpNot:
David Neto22f144c2017-06-12 14:26:21 -04005771 case spv::OpShiftLeftLogical:
5772 case spv::OpShiftRightLogical:
5773 case spv::OpShiftRightArithmetic:
5774 case spv::OpBitCount:
David Netoab03f432017-11-03 17:00:44 -04005775 case spv::OpCompositeConstruct:
David Neto22f144c2017-06-12 14:26:21 -04005776 case spv::OpCompositeExtract:
5777 case spv::OpVectorExtractDynamic:
5778 case spv::OpCompositeInsert:
David Neto0a2f98d2017-09-15 19:38:40 -04005779 case spv::OpCopyObject:
David Neto22f144c2017-06-12 14:26:21 -04005780 case spv::OpVectorInsertDynamic:
5781 case spv::OpVectorShuffle:
5782 case spv::OpIEqual:
5783 case spv::OpINotEqual:
5784 case spv::OpUGreaterThan:
5785 case spv::OpUGreaterThanEqual:
5786 case spv::OpULessThan:
5787 case spv::OpULessThanEqual:
5788 case spv::OpSGreaterThan:
5789 case spv::OpSGreaterThanEqual:
5790 case spv::OpSLessThan:
5791 case spv::OpSLessThanEqual:
5792 case spv::OpFOrdEqual:
5793 case spv::OpFOrdGreaterThan:
5794 case spv::OpFOrdGreaterThanEqual:
5795 case spv::OpFOrdLessThan:
5796 case spv::OpFOrdLessThanEqual:
5797 case spv::OpFOrdNotEqual:
5798 case spv::OpFUnordEqual:
5799 case spv::OpFUnordGreaterThan:
5800 case spv::OpFUnordGreaterThanEqual:
5801 case spv::OpFUnordLessThan:
5802 case spv::OpFUnordLessThanEqual:
5803 case spv::OpFUnordNotEqual:
5804 case spv::OpSampledImage:
5805 case spv::OpFunctionCall:
5806 case spv::OpConstantTrue:
5807 case spv::OpConstantFalse:
5808 case spv::OpConstant:
5809 case spv::OpSpecConstant:
5810 case spv::OpConstantComposite:
5811 case spv::OpSpecConstantComposite:
5812 case spv::OpConstantNull:
5813 case spv::OpLogicalOr:
5814 case spv::OpLogicalAnd:
5815 case spv::OpLogicalNot:
5816 case spv::OpLogicalNotEqual:
5817 case spv::OpUndef:
5818 case spv::OpIsInf:
5819 case spv::OpIsNan:
5820 case spv::OpAny:
5821 case spv::OpAll:
David Neto5c22a252018-03-15 16:07:41 -04005822 case spv::OpImageQuerySize:
David Neto22f144c2017-06-12 14:26:21 -04005823 case spv::OpAtomicIAdd:
5824 case spv::OpAtomicISub:
5825 case spv::OpAtomicExchange:
5826 case spv::OpAtomicIIncrement:
5827 case spv::OpAtomicIDecrement:
5828 case spv::OpAtomicCompareExchange:
5829 case spv::OpAtomicUMin:
5830 case spv::OpAtomicSMin:
5831 case spv::OpAtomicUMax:
5832 case spv::OpAtomicSMax:
5833 case spv::OpAtomicAnd:
5834 case spv::OpAtomicOr:
5835 case spv::OpAtomicXor:
5836 case spv::OpDot: {
5837 PrintResID(Inst);
5838 out << " = ";
5839 PrintOpcode(Inst);
5840 for (uint32_t i = 0; i < Ops.size(); i++) {
5841 out << " ";
5842 PrintOperand(Ops[i]);
5843 }
5844 out << "\n";
5845 break;
5846 }
5847 }
5848 }
5849}
5850
5851void SPIRVProducerPass::WriteOneWord(uint32_t Word) {
David Neto0676e6f2017-07-11 18:47:44 -04005852 binaryOut->write(reinterpret_cast<const char *>(&Word), sizeof(uint32_t));
David Neto22f144c2017-06-12 14:26:21 -04005853}
5854
5855void SPIRVProducerPass::WriteResultID(SPIRVInstruction *Inst) {
5856 WriteOneWord(Inst->getResultID());
5857}
5858
5859void SPIRVProducerPass::WriteWordCountAndOpcode(SPIRVInstruction *Inst) {
5860 // High 16 bit : Word Count
5861 // Low 16 bit : Opcode
5862 uint32_t Word = Inst->getOpcode();
David Netoee2660d2018-06-28 16:31:29 -04005863 const uint32_t count = Inst->getWordCount();
5864 if (count > 65535) {
5865 errs() << "Word count limit of 65535 exceeded: " << count << "\n";
5866 llvm_unreachable("Word count too high");
5867 }
David Neto22f144c2017-06-12 14:26:21 -04005868 Word |= Inst->getWordCount() << 16;
5869 WriteOneWord(Word);
5870}
5871
5872void SPIRVProducerPass::WriteOperand(SPIRVOperand *Op) {
5873 SPIRVOperandType OpTy = Op->getType();
5874 switch (OpTy) {
5875 default: {
5876 llvm_unreachable("Unsupported SPIRV Operand Type???");
5877 break;
5878 }
5879 case SPIRVOperandType::NUMBERID: {
5880 WriteOneWord(Op->getNumID());
5881 break;
5882 }
5883 case SPIRVOperandType::LITERAL_STRING: {
5884 std::string Str = Op->getLiteralStr();
5885 const char *Data = Str.c_str();
5886 size_t WordSize = Str.size() / 4;
5887 for (unsigned Idx = 0; Idx < WordSize; Idx++) {
5888 WriteOneWord(*reinterpret_cast<const uint32_t *>(&Data[4 * Idx]));
5889 }
5890
5891 uint32_t Remainder = Str.size() % 4;
5892 uint32_t LastWord = 0;
5893 if (Remainder) {
5894 for (unsigned Idx = 0; Idx < Remainder; Idx++) {
5895 LastWord |= Data[4 * WordSize + Idx] << 8 * Idx;
5896 }
5897 }
5898
5899 WriteOneWord(LastWord);
5900 break;
5901 }
5902 case SPIRVOperandType::LITERAL_INTEGER:
5903 case SPIRVOperandType::LITERAL_FLOAT: {
5904 auto LiteralNum = Op->getLiteralNum();
5905 // TODO: Handle LiteranNum carefully.
5906 for (auto Word : LiteralNum) {
5907 WriteOneWord(Word);
5908 }
5909 break;
5910 }
5911 }
5912}
5913
5914void SPIRVProducerPass::WriteSPIRVBinary() {
5915 SPIRVInstructionList &SPIRVInstList = getSPIRVInstList();
5916
5917 for (auto Inst : SPIRVInstList) {
David Netoc6f3ab22018-04-06 18:02:31 -04005918 SPIRVOperandList Ops{Inst->getOperands()};
David Neto22f144c2017-06-12 14:26:21 -04005919 spv::Op Opcode = static_cast<spv::Op>(Inst->getOpcode());
5920
5921 switch (Opcode) {
5922 default: {
David Neto5c22a252018-03-15 16:07:41 -04005923 errs() << "Unsupported SPIR-V instruction opcode " << int(Opcode) << "\n";
David Neto22f144c2017-06-12 14:26:21 -04005924 llvm_unreachable("Unsupported SPIRV instruction");
5925 break;
5926 }
5927 case spv::OpCapability:
5928 case spv::OpExtension:
5929 case spv::OpMemoryModel:
5930 case spv::OpEntryPoint:
5931 case spv::OpExecutionMode:
5932 case spv::OpSource:
5933 case spv::OpDecorate:
5934 case spv::OpMemberDecorate:
5935 case spv::OpBranch:
5936 case spv::OpBranchConditional:
5937 case spv::OpSelectionMerge:
5938 case spv::OpLoopMerge:
5939 case spv::OpStore:
5940 case spv::OpImageWrite:
5941 case spv::OpReturnValue:
5942 case spv::OpControlBarrier:
5943 case spv::OpMemoryBarrier:
5944 case spv::OpReturn:
5945 case spv::OpFunctionEnd:
5946 case spv::OpCopyMemory: {
5947 WriteWordCountAndOpcode(Inst);
5948 for (uint32_t i = 0; i < Ops.size(); i++) {
5949 WriteOperand(Ops[i]);
5950 }
5951 break;
5952 }
5953 case spv::OpTypeBool:
5954 case spv::OpTypeVoid:
5955 case spv::OpTypeSampler:
5956 case spv::OpLabel:
5957 case spv::OpExtInstImport:
5958 case spv::OpTypePointer:
5959 case spv::OpTypeRuntimeArray:
5960 case spv::OpTypeStruct:
5961 case spv::OpTypeImage:
5962 case spv::OpTypeSampledImage:
5963 case spv::OpTypeInt:
5964 case spv::OpTypeFloat:
5965 case spv::OpTypeArray:
5966 case spv::OpTypeVector:
5967 case spv::OpTypeFunction: {
5968 WriteWordCountAndOpcode(Inst);
5969 WriteResultID(Inst);
5970 for (uint32_t i = 0; i < Ops.size(); i++) {
5971 WriteOperand(Ops[i]);
5972 }
5973 break;
5974 }
5975 case spv::OpFunction:
5976 case spv::OpFunctionParameter:
5977 case spv::OpAccessChain:
5978 case spv::OpPtrAccessChain:
5979 case spv::OpInBoundsAccessChain:
5980 case spv::OpUConvert:
5981 case spv::OpSConvert:
5982 case spv::OpConvertFToU:
5983 case spv::OpConvertFToS:
5984 case spv::OpConvertUToF:
5985 case spv::OpConvertSToF:
5986 case spv::OpFConvert:
5987 case spv::OpConvertPtrToU:
5988 case spv::OpConvertUToPtr:
5989 case spv::OpBitcast:
5990 case spv::OpIAdd:
5991 case spv::OpFAdd:
5992 case spv::OpISub:
5993 case spv::OpFSub:
5994 case spv::OpIMul:
5995 case spv::OpFMul:
5996 case spv::OpUDiv:
5997 case spv::OpSDiv:
5998 case spv::OpFDiv:
5999 case spv::OpUMod:
6000 case spv::OpSRem:
6001 case spv::OpFRem:
6002 case spv::OpBitwiseOr:
6003 case spv::OpBitwiseXor:
6004 case spv::OpBitwiseAnd:
David Netoa394f392017-08-26 20:45:29 -04006005 case spv::OpNot:
David Neto22f144c2017-06-12 14:26:21 -04006006 case spv::OpShiftLeftLogical:
6007 case spv::OpShiftRightLogical:
6008 case spv::OpShiftRightArithmetic:
6009 case spv::OpBitCount:
David Netoab03f432017-11-03 17:00:44 -04006010 case spv::OpCompositeConstruct:
David Neto22f144c2017-06-12 14:26:21 -04006011 case spv::OpCompositeExtract:
6012 case spv::OpVectorExtractDynamic:
6013 case spv::OpCompositeInsert:
David Neto0a2f98d2017-09-15 19:38:40 -04006014 case spv::OpCopyObject:
David Neto22f144c2017-06-12 14:26:21 -04006015 case spv::OpVectorInsertDynamic:
6016 case spv::OpVectorShuffle:
6017 case spv::OpIEqual:
6018 case spv::OpINotEqual:
6019 case spv::OpUGreaterThan:
6020 case spv::OpUGreaterThanEqual:
6021 case spv::OpULessThan:
6022 case spv::OpULessThanEqual:
6023 case spv::OpSGreaterThan:
6024 case spv::OpSGreaterThanEqual:
6025 case spv::OpSLessThan:
6026 case spv::OpSLessThanEqual:
6027 case spv::OpFOrdEqual:
6028 case spv::OpFOrdGreaterThan:
6029 case spv::OpFOrdGreaterThanEqual:
6030 case spv::OpFOrdLessThan:
6031 case spv::OpFOrdLessThanEqual:
6032 case spv::OpFOrdNotEqual:
6033 case spv::OpFUnordEqual:
6034 case spv::OpFUnordGreaterThan:
6035 case spv::OpFUnordGreaterThanEqual:
6036 case spv::OpFUnordLessThan:
6037 case spv::OpFUnordLessThanEqual:
6038 case spv::OpFUnordNotEqual:
6039 case spv::OpExtInst:
6040 case spv::OpIsInf:
6041 case spv::OpIsNan:
6042 case spv::OpAny:
6043 case spv::OpAll:
6044 case spv::OpUndef:
6045 case spv::OpConstantNull:
6046 case spv::OpLogicalOr:
6047 case spv::OpLogicalAnd:
6048 case spv::OpLogicalNot:
6049 case spv::OpLogicalNotEqual:
6050 case spv::OpConstantComposite:
6051 case spv::OpSpecConstantComposite:
6052 case spv::OpConstantTrue:
6053 case spv::OpConstantFalse:
6054 case spv::OpConstant:
6055 case spv::OpSpecConstant:
6056 case spv::OpVariable:
6057 case spv::OpFunctionCall:
6058 case spv::OpSampledImage:
6059 case spv::OpImageSampleExplicitLod:
David Neto5c22a252018-03-15 16:07:41 -04006060 case spv::OpImageQuerySize:
David Neto22f144c2017-06-12 14:26:21 -04006061 case spv::OpSelect:
6062 case spv::OpPhi:
6063 case spv::OpLoad:
6064 case spv::OpAtomicIAdd:
6065 case spv::OpAtomicISub:
6066 case spv::OpAtomicExchange:
6067 case spv::OpAtomicIIncrement:
6068 case spv::OpAtomicIDecrement:
6069 case spv::OpAtomicCompareExchange:
6070 case spv::OpAtomicUMin:
6071 case spv::OpAtomicSMin:
6072 case spv::OpAtomicUMax:
6073 case spv::OpAtomicSMax:
6074 case spv::OpAtomicAnd:
6075 case spv::OpAtomicOr:
6076 case spv::OpAtomicXor:
6077 case spv::OpDot: {
6078 WriteWordCountAndOpcode(Inst);
6079 WriteOperand(Ops[0]);
6080 WriteResultID(Inst);
6081 for (uint32_t i = 1; i < Ops.size(); i++) {
6082 WriteOperand(Ops[i]);
6083 }
6084 break;
6085 }
6086 }
6087 }
6088}