blob: 535bb3e5b443085f1db062486c6a7b5fdfc6205a [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 Neto22f144c2017-06-12 14:26:21 -040020#include <clspv/Passes.h>
21
22#include <llvm/ADT/StringSwitch.h>
23#include <llvm/ADT/UniqueVector.h>
24#include <llvm/Analysis/LoopInfo.h>
25#include <llvm/IR/Constants.h>
26#include <llvm/IR/Dominators.h>
27#include <llvm/IR/Instructions.h>
28#include <llvm/IR/Metadata.h>
29#include <llvm/IR/Module.h>
30#include <llvm/Pass.h>
David Netocd8ca5f2017-10-02 23:34:11 -040031#include <llvm/Support/CommandLine.h>
David Neto22f144c2017-06-12 14:26:21 -040032#include <llvm/Support/raw_ostream.h>
33#include <llvm/Transforms/Utils/Cloning.h>
34
35#include <spirv/1.0/spirv.hpp>
36#include <clspv/AddressSpace.h>
37#include <clspv/spirv_c_strings.hpp>
38#include <clspv/spirv_glsl.hpp>
39
David Neto4feb7a42017-10-06 17:29:42 -040040#include "ArgKind.h"
David Neto48f56a42017-10-06 16:44:25 -040041
David Neto22f144c2017-06-12 14:26:21 -040042#include <list>
David Neto0676e6f2017-07-11 18:47:44 -040043#include <iomanip>
44#include <sstream>
David Neto44795152017-07-13 15:45:28 -040045#include <utility>
David Neto22f144c2017-06-12 14:26:21 -040046
47#if defined(_MSC_VER)
48#pragma warning(pop)
49#endif
50
51using namespace llvm;
52using namespace clspv;
David Neto156783e2017-07-05 15:39:41 -040053using namespace mdconst;
David Neto22f144c2017-06-12 14:26:21 -040054
55namespace {
David Netocd8ca5f2017-10-02 23:34:11 -040056
David Neto3fbb4072017-10-16 11:28:14 -040057// The value of 1/pi. This value is from MSDN
58// https://msdn.microsoft.com/en-us/library/4hwaceh6.aspx
59const double kOneOverPi = 0.318309886183790671538;
60const glsl::ExtInst kGlslExtInstBad = static_cast<glsl::ExtInst>(0);
61
David Netocd8ca5f2017-10-02 23:34:11 -040062// By default, reuse the same descriptor set number for all arguments.
63// To turn that off, use -distinct-kernel-descriptor-sets
64llvm::cl::opt<bool> distinct_kernel_descriptor_sets(
65 "distinct-kernel-descriptor-sets", llvm::cl::init(false),
66 llvm::cl::desc(
67 "Each kernel uses its own descriptor set for its arguments"));
68
David Netoc66b3352017-10-20 14:28:46 -040069// Some drivers don't like to see constant composite values constructed
70// from scalar Undef values. Replace numeric scalar and vector Undef with
71// corresponding OpConstantNull. We need to keep Undef for image values,
72// for example. In the LLVM domain, image values are passed as pointer to
73// struct.
74// See https://github.com/google/clspv/issues/95
David Neto75d54be2017-10-18 15:37:17 -040075llvm::cl::opt<bool> hack_undef(
76 "hack-undef", llvm::cl::init(false),
David Netoc66b3352017-10-20 14:28:46 -040077 llvm::cl::desc("Use OpConstantNull instead of OpUndef for floating point, "
78 "integer, or vectors of them"));
David Neto75d54be2017-10-18 15:37:17 -040079
David Neto22f144c2017-06-12 14:26:21 -040080enum SPIRVOperandType {
81 NUMBERID,
82 LITERAL_INTEGER,
83 LITERAL_STRING,
84 LITERAL_FLOAT
85};
86
87struct SPIRVOperand {
88 explicit SPIRVOperand(SPIRVOperandType Ty, uint32_t Num)
89 : Type(Ty), LiteralNum(1, Num) {}
90 explicit SPIRVOperand(SPIRVOperandType Ty, const char *Str)
91 : Type(Ty), LiteralStr(Str) {}
92 explicit SPIRVOperand(SPIRVOperandType Ty, StringRef Str)
93 : Type(Ty), LiteralStr(Str) {}
94 explicit SPIRVOperand(SPIRVOperandType Ty, ArrayRef<uint32_t> NumVec)
95 : Type(Ty), LiteralNum(NumVec.begin(), NumVec.end()) {}
96
97 SPIRVOperandType getType() { return Type; };
98 uint32_t getNumID() { return LiteralNum[0]; };
99 std::string getLiteralStr() { return LiteralStr; };
100 ArrayRef<uint32_t> getLiteralNum() { return LiteralNum; };
101
102private:
103 SPIRVOperandType Type;
104 std::string LiteralStr;
105 SmallVector<uint32_t, 4> LiteralNum;
106};
107
108struct SPIRVInstruction {
109 explicit SPIRVInstruction(uint16_t WCount, spv::Op Opc, uint32_t ResID,
110 ArrayRef<SPIRVOperand *> Ops)
111 : WordCount(WCount), Opcode(static_cast<uint16_t>(Opc)), ResultID(ResID),
112 Operands(Ops.begin(), Ops.end()) {}
113
114 uint16_t getWordCount() const { return WordCount; }
115 uint16_t getOpcode() const { return Opcode; }
116 uint32_t getResultID() const { return ResultID; }
117 ArrayRef<SPIRVOperand *> getOperands() const { return Operands; }
118
119private:
120 uint16_t WordCount;
121 uint16_t Opcode;
122 uint32_t ResultID;
123 SmallVector<SPIRVOperand *, 4> Operands;
124};
125
126struct SPIRVProducerPass final : public ModulePass {
127 typedef std::vector<SPIRVOperand *> SPIRVOperandList;
128 typedef DenseMap<Type *, uint32_t> TypeMapType;
129 typedef UniqueVector<Type *> TypeList;
130 typedef DenseMap<Value *, uint32_t> ValueMapType;
David Netofb9a7972017-08-25 17:08:24 -0400131 typedef UniqueVector<Value *> ValueList;
David Neto22f144c2017-06-12 14:26:21 -0400132 typedef std::vector<std::pair<Value *, uint32_t>> EntryPointVecType;
133 typedef std::list<SPIRVInstruction *> SPIRVInstructionList;
134 typedef std::vector<
135 std::tuple<Value *, SPIRVInstructionList::iterator, uint32_t>>
136 DeferredInstVecType;
137 typedef DenseMap<FunctionType *, std::pair<FunctionType *, uint32_t>>
138 GlobalConstFuncMapType;
139
David Neto44795152017-07-13 15:45:28 -0400140 explicit SPIRVProducerPass(
141 raw_pwrite_stream &out, raw_ostream &descriptor_map_out,
142 ArrayRef<std::pair<unsigned, std::string>> samplerMap, bool outputAsm,
143 bool outputCInitList)
David Netoc2c368d2017-06-30 16:50:17 -0400144 : ModulePass(ID), samplerMap(samplerMap), out(out),
David Neto0676e6f2017-07-11 18:47:44 -0400145 binaryTempOut(binaryTempUnderlyingVector), binaryOut(&out),
David Netoc2c368d2017-06-30 16:50:17 -0400146 descriptorMapOut(descriptor_map_out), outputAsm(outputAsm),
David Neto0676e6f2017-07-11 18:47:44 -0400147 outputCInitList(outputCInitList), patchBoundOffset(0), nextID(1),
David Netoa60b00b2017-09-15 16:34:09 -0400148 OpExtInstImportID(0), HasVariablePointers(false), SamplerTy(nullptr),
149 WorkgroupSizeValueID(0), WorkgroupSizeVarID(0) {}
David Neto22f144c2017-06-12 14:26:21 -0400150
151 void getAnalysisUsage(AnalysisUsage &AU) const override {
152 AU.addRequired<DominatorTreeWrapperPass>();
153 AU.addRequired<LoopInfoWrapperPass>();
154 }
155
156 virtual bool runOnModule(Module &module) override;
157
158 // output the SPIR-V header block
159 void outputHeader();
160
161 // patch the SPIR-V header block
162 void patchHeader();
163
164 uint32_t lookupType(Type *Ty) {
165 if (Ty->isPointerTy() &&
166 (Ty->getPointerAddressSpace() != AddressSpace::UniformConstant)) {
167 auto PointeeTy = Ty->getPointerElementType();
168 if (PointeeTy->isStructTy() &&
169 dyn_cast<StructType>(PointeeTy)->isOpaque()) {
170 Ty = PointeeTy;
171 }
172 }
173
174 if (0 == TypeMap.count(Ty)) {
175 Ty->print(errs());
176 llvm_unreachable("Unhandled type!");
177 }
178
179 return TypeMap[Ty];
180 }
181 TypeMapType &getImageTypeMap() { return ImageTypeMap; }
182 TypeList &getTypeList() { return Types; };
183 ValueList &getConstantList() { return Constants; };
184 ValueMapType &getValueMap() { return ValueMap; }
185 ValueMapType &getAllocatedValueMap() { return AllocatedValueMap; }
186 SPIRVInstructionList &getSPIRVInstList() { return SPIRVInsts; };
187 ValueToValueMapTy &getArgumentGVMap() { return ArgumentGVMap; };
188 ValueMapType &getArgumentGVIDMap() { return ArgumentGVIDMap; };
189 EntryPointVecType &getEntryPointVec() { return EntryPointVec; };
190 DeferredInstVecType &getDeferredInstVec() { return DeferredInstVec; };
191 ValueList &getEntryPointInterfacesVec() { return EntryPointInterfacesVec; };
192 uint32_t &getOpExtInstImportID() { return OpExtInstImportID; };
193 std::vector<uint32_t> &getBuiltinDimVec() { return BuiltinDimensionVec; };
194 bool hasVariablePointers() { return true; /* We use StorageBuffer everywhere */ };
195 void setVariablePointers(bool Val) { HasVariablePointers = Val; };
David Neto44795152017-07-13 15:45:28 -0400196 ArrayRef<std::pair<unsigned, std::string>> &getSamplerMap() { return samplerMap; }
David Neto22f144c2017-06-12 14:26:21 -0400197 GlobalConstFuncMapType &getGlobalConstFuncTypeMap() {
198 return GlobalConstFuncTypeMap;
199 }
200 SmallPtrSet<Value *, 16> &getGlobalConstArgSet() {
201 return GlobalConstArgumentSet;
202 }
David Neto1a1a0582017-07-07 12:01:44 -0400203 TypeList &getPointerTypesNeedingArrayStride() {
204 return PointerTypesNeedingArrayStride;
205 }
David Neto22f144c2017-06-12 14:26:21 -0400206
207 void GenerateLLVMIRInfo(Module &M);
208 bool FindExtInst(Module &M);
209 void FindTypePerGlobalVar(GlobalVariable &GV);
210 void FindTypePerFunc(Function &F);
David Neto19a1bad2017-08-25 15:01:41 -0400211 // Inserts |Ty| and relevant sub-types into the |Types| member, indicating that
212 // |Ty| and its subtypes will need a corresponding SPIR-V type.
David Neto22f144c2017-06-12 14:26:21 -0400213 void FindType(Type *Ty);
214 void FindConstantPerGlobalVar(GlobalVariable &GV);
215 void FindConstantPerFunc(Function &F);
216 void FindConstant(Value *V);
217 void GenerateExtInstImport();
David Neto19a1bad2017-08-25 15:01:41 -0400218 // Generates instructions for SPIR-V types corresponding to the LLVM types
219 // saved in the |Types| member. A type follows its subtypes. IDs are
220 // allocated sequentially starting with the current value of nextID, and
221 // with a type following its subtypes. Also updates nextID to just beyond
222 // the last generated ID.
David Neto22f144c2017-06-12 14:26:21 -0400223 void GenerateSPIRVTypes(const DataLayout &DL);
224 void GenerateSPIRVConstants();
225 void GenerateModuleInfo();
226 void GenerateGlobalVar(GlobalVariable &GV);
227 void GenerateSamplers(Module &M);
228 void GenerateFuncPrologue(Function &F);
229 void GenerateFuncBody(Function &F);
230 void GenerateInstForArg(Function &F);
231 spv::Op GetSPIRVCmpOpcode(CmpInst *CmpI);
232 spv::Op GetSPIRVCastOpcode(Instruction &I);
233 spv::Op GetSPIRVBinaryOpcode(Instruction &I);
234 void GenerateInstruction(Instruction &I);
235 void GenerateFuncEpilogue();
236 void HandleDeferredInstruction();
David Neto1a1a0582017-07-07 12:01:44 -0400237 void HandleDeferredDecorations(const DataLayout& DL);
David Neto22f144c2017-06-12 14:26:21 -0400238 bool is4xi8vec(Type *Ty) const;
239 spv::StorageClass GetStorageClass(unsigned AddrSpace) const;
240 spv::BuiltIn GetBuiltin(StringRef globalVarName) const;
David Neto3fbb4072017-10-16 11:28:14 -0400241 // Returns the GLSL extended instruction enum that the given function
242 // call maps to. If none, then returns the 0 value, i.e. GLSLstd4580Bad.
David Neto22f144c2017-06-12 14:26:21 -0400243 glsl::ExtInst getExtInstEnum(StringRef Name);
David Neto3fbb4072017-10-16 11:28:14 -0400244 // Returns the GLSL extended instruction enum indirectly used by the given
245 // function. That is, to implement the given function, we use an extended
246 // instruction plus one more instruction. If none, then returns the 0 value,
247 // i.e. GLSLstd4580Bad.
248 glsl::ExtInst getIndirectExtInstEnum(StringRef Name);
249 // Returns the single GLSL extended instruction used directly or
250 // indirectly by the given function call.
251 glsl::ExtInst getDirectOrIndirectExtInstEnum(StringRef Name);
David Neto22f144c2017-06-12 14:26:21 -0400252 void PrintResID(SPIRVInstruction *Inst);
253 void PrintOpcode(SPIRVInstruction *Inst);
254 void PrintOperand(SPIRVOperand *Op);
255 void PrintCapability(SPIRVOperand *Op);
256 void PrintExtInst(SPIRVOperand *Op);
257 void PrintAddrModel(SPIRVOperand *Op);
258 void PrintMemModel(SPIRVOperand *Op);
259 void PrintExecModel(SPIRVOperand *Op);
260 void PrintExecMode(SPIRVOperand *Op);
261 void PrintSourceLanguage(SPIRVOperand *Op);
262 void PrintFuncCtrl(SPIRVOperand *Op);
263 void PrintStorageClass(SPIRVOperand *Op);
264 void PrintDecoration(SPIRVOperand *Op);
265 void PrintBuiltIn(SPIRVOperand *Op);
266 void PrintSelectionControl(SPIRVOperand *Op);
267 void PrintLoopControl(SPIRVOperand *Op);
268 void PrintDimensionality(SPIRVOperand *Op);
269 void PrintImageFormat(SPIRVOperand *Op);
270 void PrintMemoryAccess(SPIRVOperand *Op);
271 void PrintImageOperandsType(SPIRVOperand *Op);
272 void WriteSPIRVAssembly();
273 void WriteOneWord(uint32_t Word);
274 void WriteResultID(SPIRVInstruction *Inst);
275 void WriteWordCountAndOpcode(SPIRVInstruction *Inst);
276 void WriteOperand(SPIRVOperand *Op);
277 void WriteSPIRVBinary();
278
279private:
280 static char ID;
David Neto44795152017-07-13 15:45:28 -0400281 ArrayRef<std::pair<unsigned, std::string>> samplerMap;
David Neto22f144c2017-06-12 14:26:21 -0400282 raw_pwrite_stream &out;
David Neto0676e6f2017-07-11 18:47:44 -0400283
284 // TODO(dneto): Wouldn't it be better to always just emit a binary, and then
285 // convert to other formats on demand?
286
287 // When emitting a C initialization list, the WriteSPIRVBinary method
288 // will actually write its words to this vector via binaryTempOut.
289 SmallVector<char, 100> binaryTempUnderlyingVector;
290 raw_svector_ostream binaryTempOut;
291
292 // Binary output writes to this stream, which might be |out| or
293 // |binaryTempOut|. It's the latter when we really want to write a C
294 // initializer list.
295 raw_pwrite_stream* binaryOut;
David Netoc2c368d2017-06-30 16:50:17 -0400296 raw_ostream &descriptorMapOut;
David Neto22f144c2017-06-12 14:26:21 -0400297 const bool outputAsm;
David Neto0676e6f2017-07-11 18:47:44 -0400298 const bool outputCInitList; // If true, output look like {0x7023, ... , 5}
David Neto22f144c2017-06-12 14:26:21 -0400299 uint64_t patchBoundOffset;
300 uint32_t nextID;
301
David Neto19a1bad2017-08-25 15:01:41 -0400302 // Maps an LLVM Value pointer to the corresponding SPIR-V Id.
David Neto22f144c2017-06-12 14:26:21 -0400303 TypeMapType TypeMap;
David Neto19a1bad2017-08-25 15:01:41 -0400304 // Maps an LLVM image type to its SPIR-V ID.
David Neto22f144c2017-06-12 14:26:21 -0400305 TypeMapType ImageTypeMap;
David Neto19a1bad2017-08-25 15:01:41 -0400306 // A unique-vector of LLVM types that map to a SPIR-V type.
David Neto22f144c2017-06-12 14:26:21 -0400307 TypeList Types;
308 ValueList Constants;
David Neto19a1bad2017-08-25 15:01:41 -0400309 // Maps an LLVM Value pointer to the corresponding SPIR-V Id.
David Neto22f144c2017-06-12 14:26:21 -0400310 ValueMapType ValueMap;
311 ValueMapType AllocatedValueMap;
312 SPIRVInstructionList SPIRVInsts;
313 ValueToValueMapTy ArgumentGVMap;
314 ValueMapType ArgumentGVIDMap;
315 EntryPointVecType EntryPointVec;
316 DeferredInstVecType DeferredInstVec;
317 ValueList EntryPointInterfacesVec;
318 uint32_t OpExtInstImportID;
319 std::vector<uint32_t> BuiltinDimensionVec;
320 bool HasVariablePointers;
321 Type *SamplerTy;
322 GlobalConstFuncMapType GlobalConstFuncTypeMap;
323 SmallPtrSet<Value *, 16> GlobalConstArgumentSet;
David Neto1a1a0582017-07-07 12:01:44 -0400324 // An ordered set of pointer types of Base arguments to OpPtrAccessChain,
325 // and which point into transparent memory (StorageBuffer storage class).
326 // These will require an ArrayStride decoration.
327 // See SPV_KHR_variable_pointers rev 13.
328 TypeList PointerTypesNeedingArrayStride;
David Netoa60b00b2017-09-15 16:34:09 -0400329
330 // This is truly ugly, but works around what look like driver bugs.
331 // For get_local_size, an earlier part of the flow has created a module-scope
332 // variable in Private address space to hold the value for the workgroup
333 // size. Its intializer is a uint3 value marked as builtin WorkgroupSize.
334 // When this is present, save the IDs of the initializer value and variable
335 // in these two variables. We only ever do a vector load from it, and
336 // when we see one of those, substitute just the value of the intializer.
337 // This mimics what Glslang does, and that's what drivers are used to.
338 uint32_t WorkgroupSizeValueID;
339 uint32_t WorkgroupSizeVarID;
David Neto22f144c2017-06-12 14:26:21 -0400340};
341
342char SPIRVProducerPass::ID;
343}
344
345namespace clspv {
David Neto44795152017-07-13 15:45:28 -0400346ModulePass *
347createSPIRVProducerPass(raw_pwrite_stream &out, raw_ostream &descriptor_map_out,
348 ArrayRef<std::pair<unsigned, std::string>> samplerMap,
349 bool outputAsm, bool outputCInitList) {
350 return new SPIRVProducerPass(out, descriptor_map_out, samplerMap, outputAsm,
351 outputCInitList);
David Neto22f144c2017-06-12 14:26:21 -0400352}
David Netoc2c368d2017-06-30 16:50:17 -0400353} // namespace clspv
David Neto22f144c2017-06-12 14:26:21 -0400354
355bool SPIRVProducerPass::runOnModule(Module &module) {
David Neto0676e6f2017-07-11 18:47:44 -0400356 binaryOut = outputCInitList ? &binaryTempOut : &out;
357
David Neto22f144c2017-06-12 14:26:21 -0400358 // SPIR-V always begins with its header information
359 outputHeader();
360
361 // Gather information from the LLVM IR that we require.
362 GenerateLLVMIRInfo(module);
363
364 // If we are using a sampler map, find the type of the sampler.
365 if (0 < getSamplerMap().size()) {
366 auto SamplerStructTy = module.getTypeByName("opencl.sampler_t");
367 if (!SamplerStructTy) {
368 SamplerStructTy =
369 StructType::create(module.getContext(), "opencl.sampler_t");
370 }
371
372 SamplerTy = SamplerStructTy->getPointerTo(AddressSpace::UniformConstant);
373
374 FindType(SamplerTy);
375 }
376
377 // Collect information on global variables too.
378 for (GlobalVariable &GV : module.globals()) {
379 // If the GV is one of our special __spirv_* variables, remove the
380 // initializer as it was only placed there to force LLVM to not throw the
381 // value away.
382 if (GV.getName().startswith("__spirv_")) {
383 GV.setInitializer(nullptr);
384 }
385
386 // Collect types' information from global variable.
387 FindTypePerGlobalVar(GV);
388
389 // Collect constant information from global variable.
390 FindConstantPerGlobalVar(GV);
391
392 // If the variable is an input, entry points need to know about it.
393 if (AddressSpace::Input == GV.getType()->getPointerAddressSpace()) {
David Netofb9a7972017-08-25 17:08:24 -0400394 getEntryPointInterfacesVec().insert(&GV);
David Neto22f144c2017-06-12 14:26:21 -0400395 }
396 }
397
398 // If there are extended instructions, generate OpExtInstImport.
399 if (FindExtInst(module)) {
400 GenerateExtInstImport();
401 }
402
403 // Generate SPIRV instructions for types.
404 const DataLayout &DL = module.getDataLayout();
405 GenerateSPIRVTypes(DL);
406
407 // Generate SPIRV constants.
408 GenerateSPIRVConstants();
409
410 // If we have a sampler map, we might have literal samplers to generate.
411 if (0 < getSamplerMap().size()) {
412 GenerateSamplers(module);
413 }
414
415 // Generate SPIRV variables.
416 for (GlobalVariable &GV : module.globals()) {
417 GenerateGlobalVar(GV);
418 }
419
420 // Generate SPIRV instructions for each function.
421 for (Function &F : module) {
422 if (F.isDeclaration()) {
423 continue;
424 }
425
426 // Generate Function Prologue.
427 GenerateFuncPrologue(F);
428
429 // Generate SPIRV instructions for function body.
430 GenerateFuncBody(F);
431
432 // Generate Function Epilogue.
433 GenerateFuncEpilogue();
434 }
435
436 HandleDeferredInstruction();
David Neto1a1a0582017-07-07 12:01:44 -0400437 HandleDeferredDecorations(DL);
David Neto22f144c2017-06-12 14:26:21 -0400438
439 // Generate SPIRV module information.
440 GenerateModuleInfo();
441
442 if (outputAsm) {
443 WriteSPIRVAssembly();
444 } else {
445 WriteSPIRVBinary();
446 }
447
448 // We need to patch the SPIR-V header to set bound correctly.
449 patchHeader();
David Neto0676e6f2017-07-11 18:47:44 -0400450
451 if (outputCInitList) {
452 bool first = true;
David Neto0676e6f2017-07-11 18:47:44 -0400453 std::ostringstream os;
454
David Neto57fb0b92017-08-04 15:35:09 -0400455 auto emit_word = [&os, &first](uint32_t word) {
David Neto0676e6f2017-07-11 18:47:44 -0400456 if (!first)
David Neto57fb0b92017-08-04 15:35:09 -0400457 os << ",\n";
458 os << word;
David Neto0676e6f2017-07-11 18:47:44 -0400459 first = false;
460 };
461
462 os << "{";
David Neto57fb0b92017-08-04 15:35:09 -0400463 const std::string str(binaryTempOut.str());
464 for (unsigned i = 0; i < str.size(); i += 4) {
465 const uint32_t a = static_cast<unsigned char>(str[i]);
466 const uint32_t b = static_cast<unsigned char>(str[i + 1]);
467 const uint32_t c = static_cast<unsigned char>(str[i + 2]);
468 const uint32_t d = static_cast<unsigned char>(str[i + 3]);
469 emit_word(a | (b << 8) | (c << 16) | (d << 24));
David Neto0676e6f2017-07-11 18:47:44 -0400470 }
471 os << "}\n";
472 out << os.str();
473 }
474
David Neto22f144c2017-06-12 14:26:21 -0400475 return false;
476}
477
478void SPIRVProducerPass::outputHeader() {
479 if (outputAsm) {
480 // for ASM output the header goes into 5 comments at the beginning of the
481 // file
482 out << "; SPIR-V\n";
483
484 // the major version number is in the 2nd highest byte
485 const uint32_t major = (spv::Version >> 16) & 0xFF;
486
487 // the minor version number is in the 2nd lowest byte
488 const uint32_t minor = (spv::Version >> 8) & 0xFF;
489 out << "; Version: " << major << "." << minor << "\n";
490
491 // use Codeplay's vendor ID
492 out << "; Generator: Codeplay; 0\n";
493
494 out << "; Bound: ";
495
496 // we record where we need to come back to and patch in the bound value
497 patchBoundOffset = out.tell();
498
499 // output one space per digit for the max size of a 32 bit unsigned integer
500 // (which is the maximum ID we could possibly be using)
501 for (uint32_t i = std::numeric_limits<uint32_t>::max(); 0 != i; i /= 10) {
502 out << " ";
503 }
504
505 out << "\n";
506
507 out << "; Schema: 0\n";
508 } else {
David Neto0676e6f2017-07-11 18:47:44 -0400509 binaryOut->write(reinterpret_cast<const char *>(&spv::MagicNumber),
David Neto22f144c2017-06-12 14:26:21 -0400510 sizeof(spv::MagicNumber));
David Neto0676e6f2017-07-11 18:47:44 -0400511 binaryOut->write(reinterpret_cast<const char *>(&spv::Version),
David Neto22f144c2017-06-12 14:26:21 -0400512 sizeof(spv::Version));
513
514 // use Codeplay's vendor ID
515 const uint32_t vendor = 3 << 16;
David Neto0676e6f2017-07-11 18:47:44 -0400516 binaryOut->write(reinterpret_cast<const char *>(&vendor), sizeof(vendor));
David Neto22f144c2017-06-12 14:26:21 -0400517
518 // we record where we need to come back to and patch in the bound value
David Neto0676e6f2017-07-11 18:47:44 -0400519 patchBoundOffset = binaryOut->tell();
David Neto22f144c2017-06-12 14:26:21 -0400520
521 // output a bad bound for now
David Neto0676e6f2017-07-11 18:47:44 -0400522 binaryOut->write(reinterpret_cast<const char *>(&nextID), sizeof(nextID));
David Neto22f144c2017-06-12 14:26:21 -0400523
524 // output the schema (reserved for use and must be 0)
525 const uint32_t schema = 0;
David Neto0676e6f2017-07-11 18:47:44 -0400526 binaryOut->write(reinterpret_cast<const char *>(&schema), sizeof(schema));
David Neto22f144c2017-06-12 14:26:21 -0400527 }
528}
529
530void SPIRVProducerPass::patchHeader() {
531 if (outputAsm) {
532 // get the string representation of the max bound used (nextID will be the
533 // max ID used)
534 auto asString = std::to_string(nextID);
535 out.pwrite(asString.c_str(), asString.size(), patchBoundOffset);
536 } else {
537 // for a binary we just write the value of nextID over bound
David Neto0676e6f2017-07-11 18:47:44 -0400538 binaryOut->pwrite(reinterpret_cast<char *>(&nextID), sizeof(nextID),
539 patchBoundOffset);
David Neto22f144c2017-06-12 14:26:21 -0400540 }
541}
542
543void SPIRVProducerPass::GenerateLLVMIRInfo(Module &M) {
544 // This function generates LLVM IR for function such as global variable for
545 // argument, constant and pointer type for argument access. These information
546 // is artificial one because we need Vulkan SPIR-V output. This function is
547 // executed ahead of FindType and FindConstant.
548 ValueToValueMapTy &ArgGVMap = getArgumentGVMap();
549 LLVMContext &Context = M.getContext();
550
551 // Map for avoiding to generate struct type with same fields.
552 DenseMap<Type *, Type *> ArgTyMap;
553
554 // Collect global constant variables.
555 SmallVector<GlobalVariable *, 8> GVList;
556 for (GlobalVariable &GV : M.globals()) {
557 if (GV.getType()->getAddressSpace() == AddressSpace::Constant) {
558 GVList.push_back(&GV);
559 }
560 }
561
562 // Change global constant variable's address space to ModuleScopePrivate.
563 auto &GlobalConstFuncTyMap = getGlobalConstFuncTypeMap();
564 for (auto GV : GVList) {
565 // If there is no user of gv, delete gv.
566 if (GV->use_empty()) {
567 GV->eraseFromParent();
568 continue;
569 }
570
571 // Create new gv with ModuleScopePrivate address space.
572 Type *NewGVTy = GV->getType()->getPointerElementType();
573 GlobalVariable *NewGV = new GlobalVariable(
574 M, NewGVTy, false, GV->getLinkage(), GV->getInitializer(), "", nullptr,
575 GV->getThreadLocalMode(), AddressSpace::ModuleScopePrivate);
576 NewGV->takeName(GV);
577
578 const SmallVector<User *, 8> GVUsers(GV->user_begin(), GV->user_end());
579 SmallVector<User*, 8> CandidateUsers;
580
581 for (User *GVU : GVUsers) {
582 if (CallInst *Call = dyn_cast<CallInst>(GVU)) {
583 // Find argument index.
584 unsigned GVCstArgIdx = 0;
585 for (unsigned i = 0; i < Call->getNumArgOperands(); i++) {
586 if (GV == Call->getOperand(i)) {
587 GVCstArgIdx = i;
588 }
589 }
590
591 // Record function with global constant.
592 GlobalConstFuncTyMap[Call->getFunctionType()] =
593 std::make_pair(Call->getFunctionType(), GVCstArgIdx);
594 } else if (GetElementPtrInst *GEP = dyn_cast<GetElementPtrInst>(GVU)) {
595 // Check GEP users.
596 for (User *GEPU : GEP->users()) {
597 if (CallInst *GEPCall = dyn_cast<CallInst>(GEPU)) {
598 // Find argument index.
599 unsigned GVCstArgIdx = 0;
600 for (unsigned i = 0; i < GEPCall->getNumArgOperands(); i++) {
601 if (GEP == GEPCall->getOperand(i)) {
602 GVCstArgIdx = i;
603 }
604 }
605
606 // Record function with global constant.
607 GlobalConstFuncTyMap[GEPCall->getFunctionType()] =
608 std::make_pair(GEPCall->getFunctionType(), GVCstArgIdx);
609 }
610 }
611 }
612
613 CandidateUsers.push_back(GVU);
614 }
615
616 for (User *U : CandidateUsers) {
617 // Update users of gv with new gv.
618 U->replaceUsesOfWith(GV, NewGV);
619 }
620
621 // Delete original gv.
622 GV->eraseFromParent();
623 }
624
625 bool HasWorkGroupBuiltin = false;
626 for (GlobalVariable &GV : M.globals()) {
627 const spv::BuiltIn BuiltinType = GetBuiltin(GV.getName());
628 if (spv::BuiltInWorkgroupSize == BuiltinType) {
629 HasWorkGroupBuiltin = true;
630 }
631 }
632
633
634 for (Function &F : M) {
635 // Handle kernel function first.
636 if (F.isDeclaration() || F.getCallingConv() != CallingConv::SPIR_KERNEL) {
637 continue;
638 }
639
640 for (BasicBlock &BB : F) {
641 for (Instruction &I : BB) {
642 if (I.getOpcode() == Instruction::ZExt ||
643 I.getOpcode() == Instruction::SExt ||
644 I.getOpcode() == Instruction::UIToFP) {
645 // If there is zext with i1 type, it will be changed to OpSelect. The
646 // OpSelect needs constant 0 and 1 so the constants are added here.
647
648 auto OpTy = I.getOperand(0)->getType();
649
650 if (OpTy->isIntegerTy(1) ||
651 (OpTy->isVectorTy() &&
652 OpTy->getVectorElementType()->isIntegerTy(1))) {
653 if (I.getOpcode() == Instruction::ZExt) {
654 APInt One(32, 1);
655 FindConstant(Constant::getNullValue(I.getType()));
656 FindConstant(Constant::getIntegerValue(I.getType(), One));
657 } else if (I.getOpcode() == Instruction::SExt) {
658 APInt MinusOne(32, UINT64_MAX, true);
659 FindConstant(Constant::getNullValue(I.getType()));
660 FindConstant(Constant::getIntegerValue(I.getType(), MinusOne));
661 } else {
662 FindConstant(ConstantFP::get(Context, APFloat(0.0f)));
663 FindConstant(ConstantFP::get(Context, APFloat(1.0f)));
664 }
665 }
666 } else if (CallInst *Call = dyn_cast<CallInst>(&I)) {
667 Function *Callee = Call->getCalledFunction();
668
669 // Handle image type specially.
670 if (Callee->getName().equals(
671 "_Z11read_imagef14ocl_image2d_ro11ocl_samplerDv2_f") ||
672 Callee->getName().equals(
673 "_Z11read_imagef14ocl_image3d_ro11ocl_samplerDv4_f")) {
674 TypeMapType &OpImageTypeMap = getImageTypeMap();
675 Type *ImageTy =
676 Call->getArgOperand(0)->getType()->getPointerElementType();
677 OpImageTypeMap[ImageTy] = 0;
678
679 FindConstant(ConstantFP::get(Context, APFloat(0.0f)));
680 }
681 }
682 }
683 }
684
685 if (M.getTypeByName("opencl.image2d_ro_t") ||
686 M.getTypeByName("opencl.image2d_wo_t") ||
687 M.getTypeByName("opencl.image3d_ro_t") ||
688 M.getTypeByName("opencl.image3d_wo_t")) {
689 // Assume Image type's sampled type is float type.
690 FindType(Type::getFloatTy(Context));
691 }
692
693 if (const MDNode *MD =
694 dyn_cast<Function>(&F)->getMetadata("reqd_work_group_size")) {
695 // We generate constants if the WorkgroupSize builtin is being used.
696 if (HasWorkGroupBuiltin) {
697 // Collect constant information for work group size.
698 FindConstant(mdconst::extract<ConstantInt>(MD->getOperand(0)));
699 FindConstant(mdconst::extract<ConstantInt>(MD->getOperand(1)));
700 FindConstant(mdconst::extract<ConstantInt>(MD->getOperand(2)));
701 }
702 }
703
704 // Wrap up all argument types with struct type and create global variables
705 // with them.
706 bool HasArgUser = false;
707 unsigned Idx = 0;
708
709 for (const Argument &Arg : F.args()) {
710 Type *ArgTy = Arg.getType();
711 Type *GVTy = nullptr;
712
713 // Check argument type whether it is pointer type or not. If it is
714 // pointer type, add its address space to new global variable for
715 // argument.
716 unsigned AddrSpace = AddressSpace::Global;
717 if (PointerType *ArgPTy = dyn_cast<PointerType>(ArgTy)) {
718 AddrSpace = ArgPTy->getAddressSpace();
719 }
720
721 Type *TmpArgTy = ArgTy;
722
723 // sampler_t and image types have pointer type of struct type with
724 // opaque
725 // type as field. Extract the struct type. It will be used by global
726 // variable for argument.
727 bool IsSamplerType = false;
728 bool IsImageType = false;
729 if (PointerType *TmpArgPTy = dyn_cast<PointerType>(TmpArgTy)) {
730 if (StructType *STy =
731 dyn_cast<StructType>(TmpArgPTy->getElementType())) {
732 if (STy->isOpaque()) {
733 if (STy->getName().equals("opencl.sampler_t")) {
734 AddrSpace = AddressSpace::UniformConstant;
735 IsSamplerType = true;
736 TmpArgTy = STy;
737 } else if (STy->getName().equals("opencl.image2d_ro_t") ||
738 STy->getName().equals("opencl.image2d_wo_t") ||
739 STy->getName().equals("opencl.image3d_ro_t") ||
740 STy->getName().equals("opencl.image3d_wo_t")) {
741 AddrSpace = AddressSpace::UniformConstant;
742 IsImageType = true;
743 TmpArgTy = STy;
744 } else {
745 llvm_unreachable("Argument has opaque type unsupported???");
746 }
747 }
748 }
749 }
750
751 // LLVM's pointer type is distinguished by address space but we need to
752 // regard constant and global address space as same here. If pointer
753 // type has constant address space, generate new pointer type
754 // temporarily to check previous struct type for argument.
755 if (PointerType *TmpArgPTy = dyn_cast<PointerType>(TmpArgTy)) {
756 AddrSpace = TmpArgPTy->getAddressSpace();
757 if (AddrSpace == AddressSpace::Constant) {
758 TmpArgTy = PointerType::get(TmpArgPTy->getElementType(),
759 AddressSpace::Global);
760 }
761 }
762
763 if (IsSamplerType || IsImageType) {
764 GVTy = TmpArgTy;
765 } else if (ArgTyMap.count(TmpArgTy)) {
766 // If there are arguments handled previously, use its type.
767 GVTy = ArgTyMap[TmpArgTy];
768 } else {
769 // Wrap up argument type with struct type.
David Neto83add0a2017-10-23 15:30:59 -0400770 // Reuse struct types where possible.
David Neto7b2abea2017-10-23 20:02:02 -0400771 SmallVector<Type*,1> members{ArgTy};
David Neto83add0a2017-10-23 15:30:59 -0400772 StructType *STy = StructType::get(Context, members);
David Neto22f144c2017-06-12 14:26:21 -0400773
774 GVTy = STy;
775 ArgTyMap[TmpArgTy] = STy;
776 }
777
778 // In order to build type map between llvm type and spirv id, LLVM
779 // global variable is needed. It has llvm type and other instructions
780 // can access it with its type.
781 GlobalVariable *NewGV = new GlobalVariable(
782 M, GVTy, false, GlobalValue::ExternalLinkage, UndefValue::get(GVTy),
783 F.getName() + ".arg." + std::to_string(Idx++), nullptr,
784 GlobalValue::ThreadLocalMode::NotThreadLocal, AddrSpace);
785
786 // Generate type info for argument global variable.
787 FindType(NewGV->getType());
788
789 ArgGVMap[&Arg] = NewGV;
790
791 // Generate pointer type of argument type for OpAccessChain of argument.
792 if (!Arg.use_empty()) {
793 if (!isa<PointerType>(ArgTy)) {
794 FindType(PointerType::get(ArgTy, AddrSpace));
795 }
796 HasArgUser = true;
797 }
798 }
799
800 if (HasArgUser) {
801 // Generate constant 0 for OpAccessChain of argument.
802 Type *IdxTy = Type::getInt32Ty(Context);
803 FindConstant(ConstantInt::get(IdxTy, 0));
804 FindType(IdxTy);
805 }
806
807 // Collect types' information from function.
808 FindTypePerFunc(F);
809
810 // Collect constant information from function.
811 FindConstantPerFunc(F);
812 }
813
814 for (Function &F : M) {
815 // Handle non-kernel functions.
816 if (F.isDeclaration() || F.getCallingConv() == CallingConv::SPIR_KERNEL) {
817 continue;
818 }
819
820 for (BasicBlock &BB : F) {
821 for (Instruction &I : BB) {
822 if (I.getOpcode() == Instruction::ZExt ||
823 I.getOpcode() == Instruction::SExt ||
824 I.getOpcode() == Instruction::UIToFP) {
825 // If there is zext with i1 type, it will be changed to OpSelect. The
826 // OpSelect needs constant 0 and 1 so the constants are added here.
827
828 auto OpTy = I.getOperand(0)->getType();
829
830 if (OpTy->isIntegerTy(1) ||
831 (OpTy->isVectorTy() &&
832 OpTy->getVectorElementType()->isIntegerTy(1))) {
833 if (I.getOpcode() == Instruction::ZExt) {
834 APInt One(32, 1);
835 FindConstant(Constant::getNullValue(I.getType()));
836 FindConstant(Constant::getIntegerValue(I.getType(), One));
837 } else if (I.getOpcode() == Instruction::SExt) {
838 APInt MinusOne(32, UINT64_MAX, true);
839 FindConstant(Constant::getNullValue(I.getType()));
840 FindConstant(Constant::getIntegerValue(I.getType(), MinusOne));
841 } else {
842 FindConstant(ConstantFP::get(Context, APFloat(0.0f)));
843 FindConstant(ConstantFP::get(Context, APFloat(1.0f)));
844 }
845 }
846 } else if (CallInst *Call = dyn_cast<CallInst>(&I)) {
847 Function *Callee = Call->getCalledFunction();
848
849 // Handle image type specially.
850 if (Callee->getName().equals(
851 "_Z11read_imagef14ocl_image2d_ro11ocl_samplerDv2_f") ||
852 Callee->getName().equals(
853 "_Z11read_imagef14ocl_image3d_ro11ocl_samplerDv4_f")) {
854 TypeMapType &OpImageTypeMap = getImageTypeMap();
855 Type *ImageTy =
856 Call->getArgOperand(0)->getType()->getPointerElementType();
857 OpImageTypeMap[ImageTy] = 0;
858
859 FindConstant(ConstantFP::get(Context, APFloat(0.0f)));
860 }
861 }
862 }
863 }
864
865 if (M.getTypeByName("opencl.image2d_ro_t") ||
866 M.getTypeByName("opencl.image2d_wo_t") ||
867 M.getTypeByName("opencl.image3d_ro_t") ||
868 M.getTypeByName("opencl.image3d_wo_t")) {
869 // Assume Image type's sampled type is float type.
870 FindType(Type::getFloatTy(Context));
871 }
872
873 // Collect types' information from function.
874 FindTypePerFunc(F);
875
876 // Collect constant information from function.
877 FindConstantPerFunc(F);
878 }
879}
880
881bool SPIRVProducerPass::FindExtInst(Module &M) {
882 LLVMContext &Context = M.getContext();
883 bool HasExtInst = false;
884
885 for (Function &F : M) {
886 for (BasicBlock &BB : F) {
887 for (Instruction &I : BB) {
888 if (CallInst *Call = dyn_cast<CallInst>(&I)) {
889 Function *Callee = Call->getCalledFunction();
890 // Check whether this call is for extend instructions.
David Neto3fbb4072017-10-16 11:28:14 -0400891 auto callee_name = Callee->getName();
892 const glsl::ExtInst EInst = getExtInstEnum(callee_name);
893 const glsl::ExtInst IndirectEInst =
894 getIndirectExtInstEnum(callee_name);
David Neto22f144c2017-06-12 14:26:21 -0400895
David Neto3fbb4072017-10-16 11:28:14 -0400896 HasExtInst |=
897 (EInst != kGlslExtInstBad) || (IndirectEInst != kGlslExtInstBad);
898
899 if (IndirectEInst) {
900 // Register extra constants if needed.
901
902 // Registers a type and constant for computing the result of the
903 // given instruction. If the result of the instruction is a vector,
904 // then make a splat vector constant with the same number of
905 // elements.
906 auto register_constant = [this, &I](Constant *constant) {
907 FindType(constant->getType());
908 FindConstant(constant);
909 if (auto *vectorTy = dyn_cast<VectorType>(I.getType())) {
910 // Register the splat vector of the value with the same
911 // width as the result of the instruction.
912 auto *vec_constant = ConstantVector::getSplat(
913 static_cast<unsigned>(vectorTy->getNumElements()),
914 constant);
915 FindConstant(vec_constant);
916 FindType(vec_constant->getType());
917 }
918 };
919 switch (IndirectEInst) {
920 case glsl::ExtInstFindUMsb:
921 // clz needs OpExtInst and OpISub with constant 31, or splat
922 // vector of 31. Add it to the constant list here.
923 register_constant(
924 ConstantInt::get(Type::getInt32Ty(Context), 31));
925 break;
926 case glsl::ExtInstAcos:
927 case glsl::ExtInstAsin:
928 case glsl::ExtInstAtan2:
929 // We need 1/pi for acospi, asinpi, atan2pi.
930 register_constant(
931 ConstantFP::get(Type::getFloatTy(Context), kOneOverPi));
932 break;
933 default:
934 assert(false && "internally inconsistent");
935 }
David Neto22f144c2017-06-12 14:26:21 -0400936 }
937 }
938 }
939 }
940 }
941
942 return HasExtInst;
943}
944
945void SPIRVProducerPass::FindTypePerGlobalVar(GlobalVariable &GV) {
946 // Investigate global variable's type.
947 FindType(GV.getType());
948}
949
950void SPIRVProducerPass::FindTypePerFunc(Function &F) {
951 // Investigate function's type.
952 FunctionType *FTy = F.getFunctionType();
953
954 if (F.getCallingConv() != CallingConv::SPIR_KERNEL) {
955 auto &GlobalConstFuncTyMap = getGlobalConstFuncTypeMap();
956 // Handle function with global constant parameters.
957 if (GlobalConstFuncTyMap.count(FTy)) {
958 uint32_t GVCstArgIdx = GlobalConstFuncTypeMap[FTy].second;
959 SmallVector<Type *, 4> NewFuncParamTys;
960 for (unsigned i = 0; i < FTy->getNumParams(); i++) {
961 Type *ParamTy = FTy->getParamType(i);
962 if (i == GVCstArgIdx) {
963 Type *EleTy = ParamTy->getPointerElementType();
964 ParamTy = PointerType::get(EleTy, AddressSpace::ModuleScopePrivate);
965 }
966
967 NewFuncParamTys.push_back(ParamTy);
968 }
969
970 FunctionType *NewFTy =
971 FunctionType::get(FTy->getReturnType(), NewFuncParamTys, false);
972 GlobalConstFuncTyMap[FTy] = std::make_pair(NewFTy, GVCstArgIdx);
973 FTy = NewFTy;
974 }
975
976 FindType(FTy);
977 } else {
978 // As kernel functions do not have parameters, create new function type and
979 // add it to type map.
980 SmallVector<Type *, 4> NewFuncParamTys;
981 FunctionType *NewFTy =
982 FunctionType::get(FTy->getReturnType(), NewFuncParamTys, false);
983 FindType(NewFTy);
984 }
985
986 // Investigate instructions' type in function body.
987 for (BasicBlock &BB : F) {
988 for (Instruction &I : BB) {
989 if (isa<ShuffleVectorInst>(I)) {
990 for (unsigned i = 0; i < I.getNumOperands(); i++) {
991 // Ignore type for mask of shuffle vector instruction.
992 if (i == 2) {
993 continue;
994 }
995
996 Value *Op = I.getOperand(i);
997 if (!isa<MetadataAsValue>(Op)) {
998 FindType(Op->getType());
999 }
1000 }
1001
1002 FindType(I.getType());
1003 continue;
1004 }
1005
1006 // Work through the operands of the instruction.
1007 for (unsigned i = 0; i < I.getNumOperands(); i++) {
1008 Value *const Op = I.getOperand(i);
1009 // If any of the operands is a constant, find the type!
1010 if (isa<Constant>(Op) && !isa<GlobalValue>(Op)) {
1011 FindType(Op->getType());
1012 }
1013 }
1014
1015 for (Use &Op : I.operands()) {
1016 if (CallInst *Call = dyn_cast<CallInst>(&I)) {
1017 // Avoid to check call instruction's type.
1018 break;
1019 }
1020 if (!isa<MetadataAsValue>(&Op)) {
1021 FindType(Op->getType());
1022 continue;
1023 }
1024 }
1025
1026 CallInst *Call = dyn_cast<CallInst>(&I);
1027
1028 // We don't want to track the type of this call as we are going to replace
1029 // it.
1030 if (Call && ("__translate_sampler_initializer" ==
1031 Call->getCalledFunction()->getName())) {
1032 continue;
1033 }
1034
1035 if (GetElementPtrInst *GEP = dyn_cast<GetElementPtrInst>(&I)) {
1036 // If gep's base operand has ModuleScopePrivate address space, make gep
1037 // return ModuleScopePrivate address space.
1038 if (GEP->getPointerAddressSpace() == AddressSpace::ModuleScopePrivate) {
1039 // Add pointer type with private address space for global constant to
1040 // type list.
1041 Type *EleTy = I.getType()->getPointerElementType();
1042 Type *NewPTy =
1043 PointerType::get(EleTy, AddressSpace::ModuleScopePrivate);
1044
1045 FindType(NewPTy);
1046 continue;
1047 }
1048 }
1049
1050 FindType(I.getType());
1051 }
1052 }
1053}
1054
1055void SPIRVProducerPass::FindType(Type *Ty) {
1056 TypeList &TyList = getTypeList();
1057
1058 if (0 != TyList.idFor(Ty)) {
1059 return;
1060 }
1061
1062 if (Ty->isPointerTy()) {
1063 auto AddrSpace = Ty->getPointerAddressSpace();
1064 if ((AddressSpace::Constant == AddrSpace) ||
1065 (AddressSpace::Global == AddrSpace)) {
1066 auto PointeeTy = Ty->getPointerElementType();
1067
1068 if (PointeeTy->isStructTy() &&
1069 dyn_cast<StructType>(PointeeTy)->isOpaque()) {
1070 FindType(PointeeTy);
1071 auto ActualPointerTy =
1072 PointeeTy->getPointerTo(AddressSpace::UniformConstant);
1073 FindType(ActualPointerTy);
1074 return;
1075 }
1076 }
1077 }
1078
1079 // OpTypeArray has constant and we need to support type of the constant.
1080 if (isa<ArrayType>(Ty)) {
1081 LLVMContext &Context = Ty->getContext();
1082 FindType(Type::getInt32Ty(Context));
1083 }
1084
1085 for (Type *SubTy : Ty->subtypes()) {
1086 FindType(SubTy);
1087 }
1088
1089 TyList.insert(Ty);
1090}
1091
1092void SPIRVProducerPass::FindConstantPerGlobalVar(GlobalVariable &GV) {
1093 // If the global variable has a (non undef) initializer.
1094 if (GV.hasInitializer() && !isa<UndefValue>(GV.getInitializer())) {
1095 FindConstant(GV.getInitializer());
1096 }
1097}
1098
1099void SPIRVProducerPass::FindConstantPerFunc(Function &F) {
1100 // Investigate constants in function body.
1101 for (BasicBlock &BB : F) {
1102 for (Instruction &I : BB) {
1103 CallInst *Call = dyn_cast<CallInst>(&I);
1104
1105 if (Call && ("__translate_sampler_initializer" ==
1106 Call->getCalledFunction()->getName())) {
1107 // We've handled these constants elsewhere, so skip it.
1108 continue;
1109 }
1110
1111 if (isa<AllocaInst>(I)) {
1112 // Alloca instruction has constant for the number of element. Ignore it.
1113 continue;
1114 } else if (isa<ShuffleVectorInst>(I)) {
1115 for (unsigned i = 0; i < I.getNumOperands(); i++) {
1116 // Ignore constant for mask of shuffle vector instruction.
1117 if (i == 2) {
1118 continue;
1119 }
1120
1121 if (isa<Constant>(I.getOperand(i)) &&
1122 !isa<GlobalValue>(I.getOperand(i))) {
1123 FindConstant(I.getOperand(i));
1124 }
1125 }
1126
1127 continue;
1128 } else if (isa<InsertElementInst>(I)) {
1129 // Handle InsertElement with <4 x i8> specially.
1130 Type *CompositeTy = I.getOperand(0)->getType();
1131 if (is4xi8vec(CompositeTy)) {
1132 LLVMContext &Context = CompositeTy->getContext();
1133 if (isa<Constant>(I.getOperand(0))) {
1134 FindConstant(I.getOperand(0));
1135 }
1136
1137 if (isa<Constant>(I.getOperand(1))) {
1138 FindConstant(I.getOperand(1));
1139 }
1140
1141 // Add mask constant 0xFF.
1142 Constant *CstFF = ConstantInt::get(Type::getInt32Ty(Context), 0xFF);
1143 FindConstant(CstFF);
1144
1145 // Add shift amount constant.
1146 if (ConstantInt *CI = dyn_cast<ConstantInt>(I.getOperand(2))) {
1147 uint64_t Idx = CI->getZExtValue();
1148 Constant *CstShiftAmount =
1149 ConstantInt::get(Type::getInt32Ty(Context), Idx * 8);
1150 FindConstant(CstShiftAmount);
1151 }
1152
1153 continue;
1154 }
1155
1156 for (unsigned i = 0; i < I.getNumOperands(); i++) {
1157 // Ignore constant for index of InsertElement instruction.
1158 if (i == 2) {
1159 continue;
1160 }
1161
1162 if (isa<Constant>(I.getOperand(i)) &&
1163 !isa<GlobalValue>(I.getOperand(i))) {
1164 FindConstant(I.getOperand(i));
1165 }
1166 }
1167
1168 continue;
1169 } else if (isa<ExtractElementInst>(I)) {
1170 // Handle ExtractElement with <4 x i8> specially.
1171 Type *CompositeTy = I.getOperand(0)->getType();
1172 if (is4xi8vec(CompositeTy)) {
1173 LLVMContext &Context = CompositeTy->getContext();
1174 if (isa<Constant>(I.getOperand(0))) {
1175 FindConstant(I.getOperand(0));
1176 }
1177
1178 // Add mask constant 0xFF.
1179 Constant *CstFF = ConstantInt::get(Type::getInt32Ty(Context), 0xFF);
1180 FindConstant(CstFF);
1181
1182 // Add shift amount constant.
1183 if (ConstantInt *CI = dyn_cast<ConstantInt>(I.getOperand(1))) {
1184 uint64_t Idx = CI->getZExtValue();
1185 Constant *CstShiftAmount =
1186 ConstantInt::get(Type::getInt32Ty(Context), Idx * 8);
1187 FindConstant(CstShiftAmount);
1188 } else {
1189 ConstantInt *Cst8 = ConstantInt::get(Type::getInt32Ty(Context), 8);
1190 FindConstant(Cst8);
1191 }
1192
1193 continue;
1194 }
1195
1196 for (unsigned i = 0; i < I.getNumOperands(); i++) {
1197 // Ignore constant for index of ExtractElement instruction.
1198 if (i == 1) {
1199 continue;
1200 }
1201
1202 if (isa<Constant>(I.getOperand(i)) &&
1203 !isa<GlobalValue>(I.getOperand(i))) {
1204 FindConstant(I.getOperand(i));
1205 }
1206 }
1207
1208 continue;
1209 } else if ((Instruction::Xor == I.getOpcode()) && I.getType()->isIntegerTy(1)) {
1210 // 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
1211 bool foundConstantTrue = false;
1212 for (Use &Op : I.operands()) {
1213 if (isa<Constant>(Op) && !isa<GlobalValue>(Op)) {
1214 auto CI = cast<ConstantInt>(Op);
1215
1216 if (CI->isZero() || foundConstantTrue) {
1217 // 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.
1218 FindConstant(Op);
1219 } else {
1220 foundConstantTrue = true;
1221 }
1222 }
1223 }
1224
1225 continue;
David Netod2de94a2017-08-28 17:27:47 -04001226 } else if (isa<TruncInst>(I)) {
1227 // For truncation to i8 we mask against 255.
1228 Type *ToTy = I.getType();
1229 if (8u == ToTy->getPrimitiveSizeInBits()) {
1230 LLVMContext &Context = ToTy->getContext();
1231 Constant *Cst255 = ConstantInt::get(Type::getInt32Ty(Context), 0xff);
1232 FindConstant(Cst255);
1233 }
1234 // Fall through.
Neil Henning39672102017-09-29 14:33:13 +01001235 } else if (isa<AtomicRMWInst>(I)) {
1236 LLVMContext &Context = I.getContext();
1237
1238 FindConstant(
1239 ConstantInt::get(Type::getInt32Ty(Context), spv::ScopeDevice));
1240 FindConstant(ConstantInt::get(
1241 Type::getInt32Ty(Context),
1242 spv::MemorySemanticsUniformMemoryMask |
1243 spv::MemorySemanticsSequentiallyConsistentMask));
David Neto22f144c2017-06-12 14:26:21 -04001244 }
1245
1246 for (Use &Op : I.operands()) {
1247 if (isa<Constant>(Op) && !isa<GlobalValue>(Op)) {
1248 FindConstant(Op);
1249 }
1250 }
1251 }
1252 }
1253}
1254
1255void SPIRVProducerPass::FindConstant(Value *V) {
David Neto22f144c2017-06-12 14:26:21 -04001256 ValueList &CstList = getConstantList();
1257
David Netofb9a7972017-08-25 17:08:24 -04001258 // If V is already tracked, ignore it.
1259 if (0 != CstList.idFor(V)) {
David Neto22f144c2017-06-12 14:26:21 -04001260 return;
1261 }
1262
1263 Constant *Cst = cast<Constant>(V);
1264
1265 // Handle constant with <4 x i8> type specially.
1266 Type *CstTy = Cst->getType();
1267 if (is4xi8vec(CstTy)) {
1268 if (!isa<GlobalValue>(V)) {
David Netofb9a7972017-08-25 17:08:24 -04001269 CstList.insert(V);
David Neto22f144c2017-06-12 14:26:21 -04001270 }
1271 }
1272
1273 if (Cst->getNumOperands()) {
1274 for (User::const_op_iterator I = Cst->op_begin(), E = Cst->op_end(); I != E;
1275 ++I) {
1276 FindConstant(*I);
1277 }
1278
David Netofb9a7972017-08-25 17:08:24 -04001279 CstList.insert(Cst);
David Neto22f144c2017-06-12 14:26:21 -04001280 return;
1281 } else if (const ConstantDataSequential *CDS =
1282 dyn_cast<ConstantDataSequential>(Cst)) {
1283 // Add constants for each element to constant list.
1284 for (unsigned i = 0; i < CDS->getNumElements(); i++) {
1285 Constant *EleCst = CDS->getElementAsConstant(i);
1286 FindConstant(EleCst);
1287 }
1288 }
1289
1290 if (!isa<GlobalValue>(V)) {
David Netofb9a7972017-08-25 17:08:24 -04001291 CstList.insert(V);
David Neto22f144c2017-06-12 14:26:21 -04001292 }
1293}
1294
1295spv::StorageClass SPIRVProducerPass::GetStorageClass(unsigned AddrSpace) const {
1296 switch (AddrSpace) {
1297 default:
1298 llvm_unreachable("Unsupported OpenCL address space");
1299 case AddressSpace::Private:
1300 return spv::StorageClassFunction;
1301 case AddressSpace::Global:
1302 case AddressSpace::Constant:
1303 return spv::StorageClassStorageBuffer;
1304 case AddressSpace::Input:
1305 return spv::StorageClassInput;
1306 case AddressSpace::Local:
1307 return spv::StorageClassWorkgroup;
1308 case AddressSpace::UniformConstant:
1309 return spv::StorageClassUniformConstant;
1310 case AddressSpace::ModuleScopePrivate:
1311 return spv::StorageClassPrivate;
1312 }
1313}
1314
1315spv::BuiltIn SPIRVProducerPass::GetBuiltin(StringRef Name) const {
1316 return StringSwitch<spv::BuiltIn>(Name)
1317 .Case("__spirv_GlobalInvocationId", spv::BuiltInGlobalInvocationId)
1318 .Case("__spirv_LocalInvocationId", spv::BuiltInLocalInvocationId)
1319 .Case("__spirv_WorkgroupSize", spv::BuiltInWorkgroupSize)
1320 .Case("__spirv_NumWorkgroups", spv::BuiltInNumWorkgroups)
1321 .Case("__spirv_WorkgroupId", spv::BuiltInWorkgroupId)
1322 .Default(spv::BuiltInMax);
1323}
1324
1325void SPIRVProducerPass::GenerateExtInstImport() {
1326 SPIRVInstructionList &SPIRVInstList = getSPIRVInstList();
1327 uint32_t &ExtInstImportID = getOpExtInstImportID();
1328
1329 //
1330 // Generate OpExtInstImport.
1331 //
1332 // Ops[0] ... Ops[n] = Name (Literal String)
1333 SPIRVOperandList Ops;
1334
1335 SPIRVOperand *Name =
1336 new SPIRVOperand(SPIRVOperandType::LITERAL_STRING, "GLSL.std.450");
1337 Ops.push_back(Name);
1338
1339 size_t NameWordSize = (Name->getLiteralStr().size() + 1) / 4;
1340 assert(NameWordSize < (UINT16_MAX - 2));
1341 if ((Name->getLiteralStr().size() + 1) % 4) {
1342 NameWordSize += 1;
1343 }
1344
1345 uint16_t WordCount = static_cast<uint16_t>(2 + NameWordSize);
1346 ExtInstImportID = nextID;
1347
1348 SPIRVInstruction *Inst =
1349 new SPIRVInstruction(WordCount, spv::OpExtInstImport, nextID++, Ops);
1350 SPIRVInstList.push_back(Inst);
1351}
1352
1353void SPIRVProducerPass::GenerateSPIRVTypes(const DataLayout &DL) {
1354 SPIRVInstructionList &SPIRVInstList = getSPIRVInstList();
1355 ValueMapType &VMap = getValueMap();
1356 ValueMapType &AllocatedVMap = getAllocatedValueMap();
1357 ValueToValueMapTy &ArgGVMap = getArgumentGVMap();
1358
1359 // Map for OpTypeRuntimeArray. If argument has pointer type, 2 spirv type
1360 // instructions are generated. They are OpTypePointer and OpTypeRuntimeArray.
1361 DenseMap<Type *, uint32_t> OpRuntimeTyMap;
1362
1363 for (Type *Ty : getTypeList()) {
1364 // Update TypeMap with nextID for reference later.
1365 TypeMap[Ty] = nextID;
1366
1367 switch (Ty->getTypeID()) {
1368 default: {
1369 Ty->print(errs());
1370 llvm_unreachable("Unsupported type???");
1371 break;
1372 }
1373 case Type::MetadataTyID:
1374 case Type::LabelTyID: {
1375 // Ignore these types.
1376 break;
1377 }
1378 case Type::PointerTyID: {
1379 PointerType *PTy = cast<PointerType>(Ty);
1380 unsigned AddrSpace = PTy->getAddressSpace();
1381
1382 // For the purposes of our Vulkan SPIR-V type system, constant and global
1383 // are conflated.
1384 bool UseExistingOpTypePointer = false;
1385 if (AddressSpace::Constant == AddrSpace) {
1386 AddrSpace = AddressSpace::Global;
1387
1388 // Check to see if we already created this type (for instance, if we had
1389 // a constant <type>* and a global <type>*, the type would be created by
1390 // one of these types, and shared by both).
1391 auto GlobalTy = PTy->getPointerElementType()->getPointerTo(AddrSpace);
1392 if (0 < TypeMap.count(GlobalTy)) {
1393 TypeMap[PTy] = TypeMap[GlobalTy];
1394 break;
1395 }
1396 } else if (AddressSpace::Global == AddrSpace) {
1397 AddrSpace = AddressSpace::Constant;
1398
1399 // Check to see if we already created this type (for instance, if we had
1400 // a constant <type>* and a global <type>*, the type would be created by
1401 // one of these types, and shared by both).
1402 auto ConstantTy = PTy->getPointerElementType()->getPointerTo(AddrSpace);
1403 if (0 < TypeMap.count(ConstantTy)) {
1404 TypeMap[PTy] = TypeMap[ConstantTy];
1405 UseExistingOpTypePointer = true;
1406 }
1407 }
1408
1409 bool IsOpTypeRuntimeArray = false;
1410 bool HasArgUser = false;
1411
1412 for (auto ArgGV : ArgGVMap) {
1413 auto Arg = ArgGV.first;
1414
1415 Type *ArgTy = Arg->getType();
1416 if (ArgTy == PTy) {
1417 if (AddrSpace != AddressSpace::UniformConstant) {
1418 IsOpTypeRuntimeArray = true;
1419 }
1420
1421 for (auto U : Arg->users()) {
1422 if (!isa<GetElementPtrInst>(U) || (U->getType() == PTy)) {
1423 HasArgUser = true;
1424 break;
1425 }
1426 }
1427 }
1428 }
1429
1430 if ((!IsOpTypeRuntimeArray || HasArgUser) && !UseExistingOpTypePointer) {
1431 //
1432 // Generate OpTypePointer.
1433 //
1434
1435 // OpTypePointer
1436 // Ops[0] = Storage Class
1437 // Ops[1] = Element Type ID
1438 SPIRVOperandList Ops;
1439
1440 spv::StorageClass StorageClass = GetStorageClass(AddrSpace);
1441
1442 SPIRVOperand *StorageClassOp =
1443 new SPIRVOperand(SPIRVOperandType::NUMBERID, StorageClass);
1444 Ops.push_back(StorageClassOp);
1445
1446 uint32_t EleTyID = lookupType(PTy->getElementType());
1447 SPIRVOperand *EleTyOp =
1448 new SPIRVOperand(SPIRVOperandType::NUMBERID, EleTyID);
1449 Ops.push_back(EleTyOp);
1450
1451 spv::Op Opcode = spv::OpTypePointer;
1452 uint16_t WordCount = 4;
1453
1454 SPIRVInstruction *Inst =
1455 new SPIRVInstruction(WordCount, Opcode, nextID++, Ops);
1456 SPIRVInstList.push_back(Inst);
1457 }
1458
1459 if (IsOpTypeRuntimeArray) {
1460 //
1461 // Generate OpTypeRuntimeArray.
1462 //
1463
1464 // OpTypeRuntimeArray
1465 // Ops[0] = Element Type ID
1466 SPIRVOperandList Ops;
1467
1468 uint32_t EleTyID = lookupType(PTy->getElementType());
1469 SPIRVOperand *EleTyOp =
1470 new SPIRVOperand(SPIRVOperandType::NUMBERID, EleTyID);
1471 Ops.push_back(EleTyOp);
1472
1473 spv::Op Opcode = spv::OpTypeRuntimeArray;
1474 uint16_t WordCount = 3;
1475
1476 uint32_t OpTypeRuntimeArrayID = nextID;
1477 assert(0 == OpRuntimeTyMap.count(Ty));
1478 OpRuntimeTyMap[Ty] = nextID;
1479
1480 SPIRVInstruction *Inst =
1481 new SPIRVInstruction(WordCount, Opcode, nextID++, Ops);
1482 SPIRVInstList.push_back(Inst);
1483
1484 // Generate OpDecorate.
1485 auto DecoInsertPoint =
1486 std::find_if(SPIRVInstList.begin(), SPIRVInstList.end(),
1487 [](SPIRVInstruction *Inst) -> bool {
1488 return Inst->getOpcode() != spv::OpDecorate &&
1489 Inst->getOpcode() != spv::OpMemberDecorate &&
1490 Inst->getOpcode() != spv::OpExtInstImport;
1491 });
1492
1493 // Ops[0] = Target ID
1494 // Ops[1] = Decoration (ArrayStride)
1495 // Ops[2] = Stride Number(Literal Number)
1496 Ops.clear();
1497
1498 SPIRVOperand *PTyIDOp =
1499 new SPIRVOperand(SPIRVOperandType::NUMBERID, OpTypeRuntimeArrayID);
1500 Ops.push_back(PTyIDOp);
1501
1502 SPIRVOperand *DecoOp = new SPIRVOperand(SPIRVOperandType::NUMBERID,
1503 spv::DecorationArrayStride);
1504 Ops.push_back(DecoOp);
1505
1506 std::vector<uint32_t> LiteralNum;
1507 Type *EleTy = PTy->getElementType();
Neil Henning39672102017-09-29 14:33:13 +01001508 LiteralNum.push_back(static_cast<uint32_t>(DL.getTypeAllocSize(EleTy)));
David Neto22f144c2017-06-12 14:26:21 -04001509 SPIRVOperand *ArrayStrideOp =
1510 new SPIRVOperand(SPIRVOperandType::LITERAL_INTEGER, LiteralNum);
1511 Ops.push_back(ArrayStrideOp);
1512
1513 SPIRVInstruction *DecoInst =
1514 new SPIRVInstruction(4, spv::OpDecorate, 0 /* No id */, Ops);
1515 SPIRVInstList.insert(DecoInsertPoint, DecoInst);
1516 }
1517 break;
1518 }
1519 case Type::StructTyID: {
1520 LLVMContext &Context = Ty->getContext();
1521
1522 StructType *STy = cast<StructType>(Ty);
1523
1524 // Handle sampler type.
1525 if (STy->isOpaque()) {
1526 if (STy->getName().equals("opencl.sampler_t")) {
1527 //
1528 // Generate OpTypeSampler
1529 //
1530 // Empty Ops.
1531 SPIRVOperandList Ops;
1532
1533 SPIRVInstruction *Inst =
1534 new SPIRVInstruction(2, spv::OpTypeSampler, nextID++, Ops);
1535 SPIRVInstList.push_back(Inst);
1536 break;
1537 } else if (STy->getName().equals("opencl.image2d_ro_t") ||
1538 STy->getName().equals("opencl.image2d_wo_t") ||
1539 STy->getName().equals("opencl.image3d_ro_t") ||
1540 STy->getName().equals("opencl.image3d_wo_t")) {
1541 //
1542 // Generate OpTypeImage
1543 //
1544 // Ops[0] = Sampled Type ID
1545 // Ops[1] = Dim ID
1546 // Ops[2] = Depth (Literal Number)
1547 // Ops[3] = Arrayed (Literal Number)
1548 // Ops[4] = MS (Literal Number)
1549 // Ops[5] = Sampled (Literal Number)
1550 // Ops[6] = Image Format ID
1551 //
1552 SPIRVOperandList Ops;
1553
1554 // TODO: Changed Sampled Type according to situations.
1555 uint32_t SampledTyID = lookupType(Type::getFloatTy(Context));
1556 SPIRVOperand *SampledTyIDOp =
1557 new SPIRVOperand(SPIRVOperandType::NUMBERID, SampledTyID);
1558 Ops.push_back(SampledTyIDOp);
1559
1560 spv::Dim DimID = spv::Dim2D;
1561 if (STy->getName().equals("opencl.image3d_ro_t") ||
1562 STy->getName().equals("opencl.image3d_wo_t")) {
1563 DimID = spv::Dim3D;
1564 }
1565 SPIRVOperand *DimIDOp =
1566 new SPIRVOperand(SPIRVOperandType::NUMBERID, DimID);
1567 Ops.push_back(DimIDOp);
1568
1569 // TODO: Set up Depth.
1570 std::vector<uint32_t> LiteralNum;
1571 LiteralNum.push_back(0);
1572 SPIRVOperand *DepthOp =
1573 new SPIRVOperand(SPIRVOperandType::LITERAL_INTEGER, LiteralNum);
1574 Ops.push_back(DepthOp);
1575
1576 // TODO: Set up Arrayed.
1577 LiteralNum.clear();
1578 LiteralNum.push_back(0);
1579 SPIRVOperand *ArrayedOp =
1580 new SPIRVOperand(SPIRVOperandType::LITERAL_INTEGER, LiteralNum);
1581 Ops.push_back(ArrayedOp);
1582
1583 // TODO: Set up MS.
1584 LiteralNum.clear();
1585 LiteralNum.push_back(0);
1586 SPIRVOperand *MSOp =
1587 new SPIRVOperand(SPIRVOperandType::LITERAL_INTEGER, LiteralNum);
1588 Ops.push_back(MSOp);
1589
1590 // TODO: Set up Sampled.
1591 //
1592 // From Spec
1593 //
1594 // 0 indicates this is only known at run time, not at compile time
1595 // 1 indicates will be used with sampler
1596 // 2 indicates will be used without a sampler (a storage image)
1597 uint32_t Sampled = 1;
1598 if (STy->getName().equals("opencl.image2d_wo_t") ||
1599 STy->getName().equals("opencl.image3d_wo_t")) {
1600 Sampled = 2;
1601 }
1602 LiteralNum.clear();
1603 LiteralNum.push_back(Sampled);
1604 SPIRVOperand *SampledOp =
1605 new SPIRVOperand(SPIRVOperandType::LITERAL_INTEGER, LiteralNum);
1606 Ops.push_back(SampledOp);
1607
1608 // TODO: Set up Image Format.
1609 SPIRVOperand *ImageFormatOp = new SPIRVOperand(
1610 SPIRVOperandType::NUMBERID, spv::ImageFormatUnknown);
1611 Ops.push_back(ImageFormatOp);
1612
1613 SPIRVInstruction *Inst =
1614 new SPIRVInstruction(9, spv::OpTypeImage, nextID++, Ops);
1615 SPIRVInstList.push_back(Inst);
1616 break;
1617 }
1618 }
1619
1620 //
1621 // Generate OpTypeStruct
1622 //
1623 // Ops[0] ... Ops[n] = Member IDs
1624 SPIRVOperandList Ops;
1625
1626 for (auto *EleTy : STy->elements()) {
1627 uint32_t EleTyID = lookupType(EleTy);
1628
1629 // Check OpTypeRuntimeArray.
1630 if (isa<PointerType>(EleTy)) {
1631 for (auto ArgGV : ArgGVMap) {
1632 Type *ArgTy = ArgGV.first->getType();
1633 if (ArgTy == EleTy) {
1634 assert(0 != OpRuntimeTyMap.count(EleTy));
1635 EleTyID = OpRuntimeTyMap[EleTy];
1636 }
1637 }
1638 }
1639
1640 SPIRVOperand *EleTyOp =
1641 new SPIRVOperand(SPIRVOperandType::NUMBERID, EleTyID);
1642 Ops.push_back(EleTyOp);
1643 }
1644
1645 uint16_t WordCount = static_cast<uint16_t>(2 + Ops.size());
1646 uint32_t STyID = nextID;
1647
1648 SPIRVInstruction *Inst =
1649 new SPIRVInstruction(WordCount, spv::OpTypeStruct, nextID++, Ops);
1650 SPIRVInstList.push_back(Inst);
1651
1652 // Generate OpMemberDecorate.
1653 auto DecoInsertPoint =
1654 std::find_if(SPIRVInstList.begin(), SPIRVInstList.end(),
1655 [](SPIRVInstruction *Inst) -> bool {
1656 return Inst->getOpcode() != spv::OpDecorate &&
1657 Inst->getOpcode() != spv::OpMemberDecorate &&
1658 Inst->getOpcode() != spv::OpExtInstImport;
1659 });
1660
David Netoc463b372017-08-10 15:32:21 -04001661 const auto StructLayout = DL.getStructLayout(STy);
1662
David Neto22f144c2017-06-12 14:26:21 -04001663 for (unsigned MemberIdx = 0; MemberIdx < STy->getNumElements();
1664 MemberIdx++) {
1665 // Ops[0] = Structure Type ID
1666 // Ops[1] = Member Index(Literal Number)
1667 // Ops[2] = Decoration (Offset)
1668 // Ops[3] = Byte Offset (Literal Number)
1669 Ops.clear();
1670
1671 SPIRVOperand *STyIDOp =
1672 new SPIRVOperand(SPIRVOperandType::NUMBERID, STyID);
1673 Ops.push_back(STyIDOp);
1674
1675 std::vector<uint32_t> LiteralNum;
1676 LiteralNum.push_back(MemberIdx);
1677 SPIRVOperand *MemberIdxOp =
1678 new SPIRVOperand(SPIRVOperandType::LITERAL_INTEGER, LiteralNum);
1679 Ops.push_back(MemberIdxOp);
1680
1681 SPIRVOperand *DecoOp =
1682 new SPIRVOperand(SPIRVOperandType::NUMBERID, spv::DecorationOffset);
1683 Ops.push_back(DecoOp);
1684
1685 LiteralNum.clear();
David Netoc463b372017-08-10 15:32:21 -04001686 const auto ByteOffset =
1687 uint32_t(StructLayout->getElementOffset(MemberIdx));
David Neto22f144c2017-06-12 14:26:21 -04001688 LiteralNum.push_back(ByteOffset);
1689 SPIRVOperand *ByteOffsetOp =
1690 new SPIRVOperand(SPIRVOperandType::LITERAL_INTEGER, LiteralNum);
1691 Ops.push_back(ByteOffsetOp);
1692
1693 SPIRVInstruction *DecoInst =
1694 new SPIRVInstruction(5, spv::OpMemberDecorate, 0 /* No id */, Ops);
1695 SPIRVInstList.insert(DecoInsertPoint, DecoInst);
David Neto22f144c2017-06-12 14:26:21 -04001696 }
1697
1698 // Generate OpDecorate.
1699 for (auto ArgGV : ArgGVMap) {
1700 Type *ArgGVTy = ArgGV.second->getType();
1701 PointerType *PTy = cast<PointerType>(ArgGVTy);
1702 Type *ArgTy = PTy->getElementType();
1703
1704 // Struct type from argument is already distinguished with the other
1705 // struct types on llvm types. As a result, if current processing struct
1706 // type is same with argument type, we can generate OpDecorate with
1707 // Block or BufferBlock.
1708 if (ArgTy == STy) {
1709 // Ops[0] = Target ID
1710 // Ops[1] = Decoration (Block or BufferBlock)
1711 Ops.clear();
1712
1713 SPIRVOperand *STyIDOp =
1714 new SPIRVOperand(SPIRVOperandType::NUMBERID, STyID);
1715 Ops.push_back(STyIDOp);
1716
David Neto6e392822017-08-04 14:06:10 -04001717 // Use Block decorations with StorageBuffer storage class.
1718 const spv::Decoration Deco = spv::DecorationBlock;
David Neto22f144c2017-06-12 14:26:21 -04001719
1720 SPIRVOperand *DecoOp =
1721 new SPIRVOperand(SPIRVOperandType::NUMBERID, Deco);
1722 Ops.push_back(DecoOp);
1723
1724 SPIRVInstruction *DecoInst =
1725 new SPIRVInstruction(3, spv::OpDecorate, 0 /* No id */, Ops);
1726 SPIRVInstList.insert(DecoInsertPoint, DecoInst);
1727 break;
1728 }
1729 }
1730 break;
1731 }
1732 case Type::IntegerTyID: {
1733 unsigned BitWidth = Ty->getPrimitiveSizeInBits();
1734
1735 if (BitWidth == 1) {
1736 SPIRVInstruction *Inst =
1737 new SPIRVInstruction(2, spv::OpTypeBool, nextID++, {});
1738 SPIRVInstList.push_back(Inst);
1739 } else {
1740 // i8 is added to TypeMap as i32.
David Neto391aeb12017-08-26 15:51:58 -04001741 // No matter what LLVM type is requested first, always alias the
1742 // second one's SPIR-V type to be the same as the one we generated
1743 // first.
Neil Henning39672102017-09-29 14:33:13 +01001744 unsigned aliasToWidth = 0;
David Neto22f144c2017-06-12 14:26:21 -04001745 if (BitWidth == 8) {
David Neto391aeb12017-08-26 15:51:58 -04001746 aliasToWidth = 32;
David Neto22f144c2017-06-12 14:26:21 -04001747 BitWidth = 32;
David Neto391aeb12017-08-26 15:51:58 -04001748 } else if (BitWidth == 32) {
1749 aliasToWidth = 8;
1750 }
1751 if (aliasToWidth) {
1752 Type* otherType = Type::getIntNTy(Ty->getContext(), aliasToWidth);
1753 auto where = TypeMap.find(otherType);
1754 if (where == TypeMap.end()) {
1755 // Go ahead and make it, but also map the other type to it.
1756 TypeMap[otherType] = nextID;
1757 } else {
1758 // Alias this SPIR-V type the existing type.
1759 TypeMap[Ty] = where->second;
1760 break;
1761 }
David Neto22f144c2017-06-12 14:26:21 -04001762 }
1763
1764 SPIRVOperand *Ops[2] = {
1765 new SPIRVOperand(SPIRVOperandType::LITERAL_INTEGER, BitWidth),
1766 new SPIRVOperand(SPIRVOperandType::LITERAL_INTEGER, 0u)};
1767
1768 SPIRVInstList.push_back(
1769 new SPIRVInstruction(4, spv::OpTypeInt, nextID++, Ops));
1770 }
1771 break;
1772 }
1773 case Type::HalfTyID:
1774 case Type::FloatTyID:
1775 case Type::DoubleTyID: {
1776 SPIRVOperand *WidthOp = new SPIRVOperand(
1777 SPIRVOperandType::LITERAL_INTEGER, Ty->getPrimitiveSizeInBits());
1778
1779 SPIRVInstList.push_back(
1780 new SPIRVInstruction(3, spv::OpTypeFloat, nextID++, WidthOp));
1781 break;
1782 }
1783 case Type::ArrayTyID: {
1784 LLVMContext &Context = Ty->getContext();
1785 ArrayType *ArrTy = cast<ArrayType>(Ty);
1786 //
1787 // Generate OpConstant and OpTypeArray.
1788 //
1789
1790 //
1791 // Generate OpConstant for array length.
1792 //
1793 // Ops[0] = Result Type ID
1794 // Ops[1] .. Ops[n] = Values LiteralNumber
1795 SPIRVOperandList Ops;
1796
1797 Type *LengthTy = Type::getInt32Ty(Context);
1798 uint32_t ResTyID = lookupType(LengthTy);
1799 SPIRVOperand *ResTyOp =
1800 new SPIRVOperand(SPIRVOperandType::NUMBERID, ResTyID);
1801 Ops.push_back(ResTyOp);
1802
1803 uint64_t Length = ArrTy->getArrayNumElements();
1804 assert(Length < UINT32_MAX);
1805 std::vector<uint32_t> LiteralNum;
1806 LiteralNum.push_back(static_cast<uint32_t>(Length));
1807 SPIRVOperand *ValOp =
1808 new SPIRVOperand(SPIRVOperandType::LITERAL_INTEGER, LiteralNum);
1809 Ops.push_back(ValOp);
1810
1811 // Add constant for length to constant list.
1812 Constant *CstLength = ConstantInt::get(LengthTy, Length);
1813 AllocatedVMap[CstLength] = nextID;
1814 VMap[CstLength] = nextID;
1815 uint32_t LengthID = nextID;
1816
1817 SPIRVInstruction *CstInst =
1818 new SPIRVInstruction(4, spv::OpConstant, nextID++, Ops);
1819 SPIRVInstList.push_back(CstInst);
1820
1821 //
1822 // Generate OpTypeArray.
1823 //
1824 // Ops[0] = Element Type ID
1825 // Ops[1] = Array Length Constant ID
1826 Ops.clear();
1827
1828 uint32_t EleTyID = lookupType(ArrTy->getElementType());
1829 SPIRVOperand *EleTyOp =
1830 new SPIRVOperand(SPIRVOperandType::NUMBERID, EleTyID);
1831 Ops.push_back(EleTyOp);
1832
1833 SPIRVOperand *LengthOp =
1834 new SPIRVOperand(SPIRVOperandType::NUMBERID, LengthID);
1835 Ops.push_back(LengthOp);
1836
1837 // Update TypeMap with nextID.
1838 TypeMap[Ty] = nextID;
1839
1840 SPIRVInstruction *ArrayInst =
1841 new SPIRVInstruction(4, spv::OpTypeArray, nextID++, Ops);
1842 SPIRVInstList.push_back(ArrayInst);
1843 break;
1844 }
1845 case Type::VectorTyID: {
1846 // <4 x i8> is changed to i32.
1847 LLVMContext &Context = Ty->getContext();
1848 if (Ty->getVectorElementType() == Type::getInt8Ty(Context)) {
1849 if (Ty->getVectorNumElements() == 4) {
1850 TypeMap[Ty] = lookupType(Ty->getVectorElementType());
1851 break;
1852 } else {
1853 Ty->print(errs());
1854 llvm_unreachable("Support above i8 vector type");
1855 }
1856 }
1857
1858 // Ops[0] = Component Type ID
1859 // Ops[1] = Component Count (Literal Number)
1860 SPIRVOperand *Ops[2] = {
1861 new SPIRVOperand(SPIRVOperandType::NUMBERID,
1862 lookupType(Ty->getVectorElementType())),
1863 new SPIRVOperand(SPIRVOperandType::LITERAL_INTEGER,
1864 Ty->getVectorNumElements())};
1865
1866 SPIRVInstList.push_back(
1867 new SPIRVInstruction(4, spv::OpTypeVector, nextID++, Ops));
1868 break;
1869 }
1870 case Type::VoidTyID: {
1871 SPIRVInstruction *Inst =
1872 new SPIRVInstruction(2, spv::OpTypeVoid, nextID++, {});
1873 SPIRVInstList.push_back(Inst);
1874 break;
1875 }
1876 case Type::FunctionTyID: {
1877 // Generate SPIRV instruction for function type.
1878 FunctionType *FTy = cast<FunctionType>(Ty);
1879
1880 // Ops[0] = Return Type ID
1881 // Ops[1] ... Ops[n] = Parameter Type IDs
1882 SPIRVOperandList Ops;
1883
1884 // Find SPIRV instruction for return type
1885 uint32_t RetTyID = lookupType(FTy->getReturnType());
1886
1887 SPIRVOperand *RetTyOp =
1888 new SPIRVOperand(SPIRVOperandType::NUMBERID, RetTyID);
1889 Ops.push_back(RetTyOp);
1890
1891 // Find SPIRV instructions for parameter types
1892 for (unsigned k = 0; k < FTy->getNumParams(); k++) {
1893 // Find SPIRV instruction for parameter type.
1894 auto ParamTy = FTy->getParamType(k);
1895 if (ParamTy->isPointerTy()) {
1896 auto PointeeTy = ParamTy->getPointerElementType();
1897 if (PointeeTy->isStructTy() &&
1898 dyn_cast<StructType>(PointeeTy)->isOpaque()) {
1899 ParamTy = PointeeTy;
1900 }
1901 }
1902
1903 uint32_t ParamTyID = lookupType(ParamTy);
1904 SPIRVOperand *ParamTyOp =
1905 new SPIRVOperand(SPIRVOperandType::NUMBERID, ParamTyID);
1906 Ops.push_back(ParamTyOp);
1907 }
1908
1909 // Return type id is included in operand list.
1910 uint16_t WordCount = static_cast<uint16_t>(2 + Ops.size());
1911
1912 SPIRVInstruction *Inst =
1913 new SPIRVInstruction(WordCount, spv::OpTypeFunction, nextID++, Ops);
1914 SPIRVInstList.push_back(Inst);
1915 break;
1916 }
1917 }
1918 }
1919
1920 // Generate OpTypeSampledImage.
1921 TypeMapType &OpImageTypeMap = getImageTypeMap();
1922 for (auto &ImageType : OpImageTypeMap) {
1923 //
1924 // Generate OpTypeSampledImage.
1925 //
1926 // Ops[0] = Image Type ID
1927 //
1928 SPIRVOperandList Ops;
1929
1930 Type *ImgTy = ImageType.first;
1931 uint32_t ImgTyID = TypeMap[ImgTy];
1932 SPIRVOperand *ImgTyOp =
1933 new SPIRVOperand(SPIRVOperandType::NUMBERID, ImgTyID);
1934 Ops.push_back(ImgTyOp);
1935
1936 // Update OpImageTypeMap.
1937 ImageType.second = nextID;
1938
1939 SPIRVInstruction *Inst =
1940 new SPIRVInstruction(3, spv::OpTypeSampledImage, nextID++, Ops);
1941 SPIRVInstList.push_back(Inst);
1942 }
1943}
1944
1945void SPIRVProducerPass::GenerateSPIRVConstants() {
1946 SPIRVInstructionList &SPIRVInstList = getSPIRVInstList();
1947 ValueMapType &VMap = getValueMap();
1948 ValueMapType &AllocatedVMap = getAllocatedValueMap();
1949 ValueList &CstList = getConstantList();
1950
1951 for (uint32_t i = 0; i < CstList.size(); i++) {
David Netofb9a7972017-08-25 17:08:24 -04001952 // UniqueVector ids are 1-based.
1953 Constant *Cst = cast<Constant>(CstList[i+1]);
David Neto22f144c2017-06-12 14:26:21 -04001954
1955 // OpTypeArray's constant was already generated.
David Netofb9a7972017-08-25 17:08:24 -04001956 if (AllocatedVMap.find_as(Cst) != AllocatedVMap.end()) {
David Neto22f144c2017-06-12 14:26:21 -04001957 continue;
1958 }
1959
David Netofb9a7972017-08-25 17:08:24 -04001960 // Set ValueMap with nextID for reference later.
David Neto22f144c2017-06-12 14:26:21 -04001961 VMap[Cst] = nextID;
1962
1963 //
1964 // Generate OpConstant.
1965 //
1966
1967 // Ops[0] = Result Type ID
1968 // Ops[1] .. Ops[n] = Values LiteralNumber
1969 SPIRVOperandList Ops;
1970
1971 uint32_t ResTyID = lookupType(Cst->getType());
1972 SPIRVOperand *ResTyIDOp =
1973 new SPIRVOperand(SPIRVOperandType::NUMBERID, ResTyID);
1974 Ops.push_back(ResTyIDOp);
1975
1976 std::vector<uint32_t> LiteralNum;
1977 uint16_t WordCount = 0;
1978 spv::Op Opcode = spv::OpNop;
1979
1980 if (isa<UndefValue>(Cst)) {
1981 // Ops[0] = Result Type ID
David Netoc66b3352017-10-20 14:28:46 -04001982 Opcode = spv::OpUndef;
1983 if (hack_undef) {
1984 Type *type = Cst->getType();
1985 if (type->isFPOrFPVectorTy() || type->isIntOrIntVectorTy()) {
1986 Opcode = spv::OpConstantNull;
1987 }
1988 }
David Neto22f144c2017-06-12 14:26:21 -04001989 WordCount = 3;
1990 } else if (const ConstantInt *CI = dyn_cast<ConstantInt>(Cst)) {
1991 unsigned BitWidth = CI->getBitWidth();
1992 if (BitWidth == 1) {
1993 // If the bitwidth of constant is 1, generate OpConstantTrue or
1994 // OpConstantFalse.
1995 if (CI->getZExtValue()) {
1996 // Ops[0] = Result Type ID
1997 Opcode = spv::OpConstantTrue;
1998 } else {
1999 // Ops[0] = Result Type ID
2000 Opcode = spv::OpConstantFalse;
2001 }
2002 WordCount = 3;
2003 } else {
2004 auto V = CI->getZExtValue();
2005 LiteralNum.push_back(V & 0xFFFFFFFF);
2006
2007 if (BitWidth > 32) {
2008 LiteralNum.push_back(V >> 32);
2009 }
2010
2011 Opcode = spv::OpConstant;
2012 WordCount = static_cast<uint16_t>(3 + LiteralNum.size());
2013
2014 SPIRVOperand *CstValue =
2015 new SPIRVOperand(SPIRVOperandType::LITERAL_INTEGER, LiteralNum);
2016 Ops.push_back(CstValue);
2017 }
2018 } else if (const ConstantFP *CFP = dyn_cast<ConstantFP>(Cst)) {
2019 uint64_t FPVal = CFP->getValueAPF().bitcastToAPInt().getZExtValue();
2020 Type *CFPTy = CFP->getType();
2021 if (CFPTy->isFloatTy()) {
2022 LiteralNum.push_back(FPVal & 0xFFFFFFFF);
2023 } else {
2024 CFPTy->print(errs());
2025 llvm_unreachable("Implement this ConstantFP Type");
2026 }
2027
2028 Opcode = spv::OpConstant;
2029 WordCount = static_cast<uint16_t>(3 + LiteralNum.size());
2030
2031 SPIRVOperand *CstValue =
2032 new SPIRVOperand(SPIRVOperandType::LITERAL_FLOAT, LiteralNum);
2033 Ops.push_back(CstValue);
2034 } else if (isa<ConstantDataSequential>(Cst) &&
2035 cast<ConstantDataSequential>(Cst)->isString()) {
2036 Cst->print(errs());
2037 llvm_unreachable("Implement this Constant");
2038
2039 } else if (const ConstantDataSequential *CDS =
2040 dyn_cast<ConstantDataSequential>(Cst)) {
David Neto49351ac2017-08-26 17:32:20 -04002041 // Let's convert <4 x i8> constant to int constant specially.
2042 // This case occurs when all the values are specified as constant
2043 // ints.
2044 Type *CstTy = Cst->getType();
2045 if (is4xi8vec(CstTy)) {
2046 LLVMContext &Context = CstTy->getContext();
2047
2048 //
2049 // Generate OpConstant with OpTypeInt 32 0.
2050 //
Neil Henning39672102017-09-29 14:33:13 +01002051 uint32_t IntValue = 0;
2052 for (unsigned k = 0; k < 4; k++) {
2053 const uint64_t Val = CDS->getElementAsInteger(k);
David Neto49351ac2017-08-26 17:32:20 -04002054 IntValue = (IntValue << 8) | (Val & 0xffu);
2055 }
2056
2057 Type *i32 = Type::getInt32Ty(Context);
2058 Constant *CstInt = ConstantInt::get(i32, IntValue);
2059 // If this constant is already registered on VMap, use it.
2060 if (VMap.count(CstInt)) {
2061 uint32_t CstID = VMap[CstInt];
2062 VMap[Cst] = CstID;
2063 continue;
2064 }
2065
2066 LiteralNum.push_back(IntValue);
2067 SPIRVOperand *CstValue =
2068 new SPIRVOperand(SPIRVOperandType::LITERAL_INTEGER, LiteralNum);
2069 Ops.push_back(CstValue);
2070
2071 SPIRVInstruction *CstInst =
2072 new SPIRVInstruction(4, spv::OpConstant, nextID++, Ops);
2073 SPIRVInstList.push_back(CstInst);
2074
2075 continue;
2076 }
2077
2078 // A normal constant-data-sequential case.
David Neto22f144c2017-06-12 14:26:21 -04002079 for (unsigned k = 0; k < CDS->getNumElements(); k++) {
2080 Constant *EleCst = CDS->getElementAsConstant(k);
2081 uint32_t EleCstID = VMap[EleCst];
2082 SPIRVOperand *EleCstIDOp =
2083 new SPIRVOperand(SPIRVOperandType::NUMBERID, EleCstID);
2084 Ops.push_back(EleCstIDOp);
2085 }
2086
2087 Opcode = spv::OpConstantComposite;
2088 WordCount = static_cast<uint16_t>(3 + CDS->getNumElements());
2089 } else if (const ConstantAggregate *CA = dyn_cast<ConstantAggregate>(Cst)) {
2090 // Let's convert <4 x i8> constant to int constant specially.
David Neto49351ac2017-08-26 17:32:20 -04002091 // This case occurs when at least one of the values is an undef.
David Neto22f144c2017-06-12 14:26:21 -04002092 Type *CstTy = Cst->getType();
2093 if (is4xi8vec(CstTy)) {
2094 LLVMContext &Context = CstTy->getContext();
2095
2096 //
2097 // Generate OpConstant with OpTypeInt 32 0.
2098 //
Neil Henning39672102017-09-29 14:33:13 +01002099 uint32_t IntValue = 0;
David Neto22f144c2017-06-12 14:26:21 -04002100 for (User::const_op_iterator I = Cst->op_begin(), E = Cst->op_end();
2101 I != E; ++I) {
2102 uint64_t Val = 0;
David Neto49351ac2017-08-26 17:32:20 -04002103 const Value* CV = *I;
Neil Henning39672102017-09-29 14:33:13 +01002104 if (auto *CI2 = dyn_cast<ConstantInt>(CV)) {
2105 Val = CI2->getZExtValue();
David Neto22f144c2017-06-12 14:26:21 -04002106 }
David Neto49351ac2017-08-26 17:32:20 -04002107 IntValue = (IntValue << 8) | (Val & 0xffu);
David Neto22f144c2017-06-12 14:26:21 -04002108 }
2109
David Neto49351ac2017-08-26 17:32:20 -04002110 Type *i32 = Type::getInt32Ty(Context);
2111 Constant *CstInt = ConstantInt::get(i32, IntValue);
David Neto22f144c2017-06-12 14:26:21 -04002112 // If this constant is already registered on VMap, use it.
2113 if (VMap.count(CstInt)) {
2114 uint32_t CstID = VMap[CstInt];
2115 VMap[Cst] = CstID;
David Neto19a1bad2017-08-25 15:01:41 -04002116 continue;
David Neto22f144c2017-06-12 14:26:21 -04002117 }
2118
David Neto49351ac2017-08-26 17:32:20 -04002119 LiteralNum.push_back(IntValue);
David Neto22f144c2017-06-12 14:26:21 -04002120 SPIRVOperand *CstValue =
2121 new SPIRVOperand(SPIRVOperandType::LITERAL_INTEGER, LiteralNum);
2122 Ops.push_back(CstValue);
2123
2124 SPIRVInstruction *CstInst =
2125 new SPIRVInstruction(4, spv::OpConstant, nextID++, Ops);
2126 SPIRVInstList.push_back(CstInst);
2127
David Neto19a1bad2017-08-25 15:01:41 -04002128 continue;
David Neto22f144c2017-06-12 14:26:21 -04002129 }
2130
2131 // We use a constant composite in SPIR-V for our constant aggregate in
2132 // LLVM.
2133 Opcode = spv::OpConstantComposite;
2134 WordCount = static_cast<uint16_t>(3 + CA->getNumOperands());
2135
2136 for (unsigned k = 0; k < CA->getNumOperands(); k++) {
2137 // Look up the ID of the element of this aggregate (which we will
2138 // previously have created a constant for).
2139 uint32_t ElementConstantID = VMap[CA->getAggregateElement(k)];
2140
2141 // And add an operand to the composite we are constructing
2142 Ops.push_back(
2143 new SPIRVOperand(SPIRVOperandType::NUMBERID, ElementConstantID));
2144 }
2145 } else if (Cst->isNullValue()) {
2146 Opcode = spv::OpConstantNull;
2147 WordCount = 3;
2148 } else {
2149 Cst->print(errs());
2150 llvm_unreachable("Unsupported Constant???");
2151 }
2152
2153 SPIRVInstruction *CstInst =
2154 new SPIRVInstruction(WordCount, Opcode, nextID++, Ops);
2155 SPIRVInstList.push_back(CstInst);
2156 }
2157}
2158
2159void SPIRVProducerPass::GenerateSamplers(Module &M) {
2160 SPIRVInstructionList &SPIRVInstList = getSPIRVInstList();
2161 ValueMapType &VMap = getValueMap();
2162
2163 DenseMap<unsigned, unsigned> SamplerLiteralToIDMap;
2164
2165 unsigned BindingIdx = 0;
2166
2167 // Generate the sampler map.
2168 for (auto SamplerLiteral : getSamplerMap()) {
2169 // Generate OpVariable.
2170 //
2171 // GIDOps[0] : Result Type ID
2172 // GIDOps[1] : Storage Class
2173 SPIRVOperandList Ops;
2174
2175 Ops.push_back(
2176 new SPIRVOperand(SPIRVOperandType::NUMBERID, lookupType(SamplerTy)));
2177
2178 spv::StorageClass StorageClass = spv::StorageClassUniformConstant;
2179 Ops.push_back(new SPIRVOperand(SPIRVOperandType::NUMBERID, StorageClass));
2180
2181 SPIRVInstruction *Inst = new SPIRVInstruction(
2182 static_cast<uint16_t>(2 + Ops.size()), spv::OpVariable, nextID, Ops);
2183 SPIRVInstList.push_back(Inst);
2184
David Neto44795152017-07-13 15:45:28 -04002185 SamplerLiteralToIDMap[SamplerLiteral.first] = nextID++;
David Neto22f144c2017-06-12 14:26:21 -04002186
2187 // Find Insert Point for OpDecorate.
2188 auto DecoInsertPoint =
2189 std::find_if(SPIRVInstList.begin(), SPIRVInstList.end(),
2190 [](SPIRVInstruction *Inst) -> bool {
2191 return Inst->getOpcode() != spv::OpDecorate &&
2192 Inst->getOpcode() != spv::OpMemberDecorate &&
2193 Inst->getOpcode() != spv::OpExtInstImport;
2194 });
2195
2196 // Ops[0] = Target ID
2197 // Ops[1] = Decoration (DescriptorSet)
2198 // Ops[2] = LiteralNumber according to Decoration
2199 Ops.clear();
2200
David Neto44795152017-07-13 15:45:28 -04002201 SPIRVOperand *ArgIDOp =
2202 new SPIRVOperand(SPIRVOperandType::NUMBERID,
2203 SamplerLiteralToIDMap[SamplerLiteral.first]);
David Neto22f144c2017-06-12 14:26:21 -04002204 Ops.push_back(ArgIDOp);
2205
2206 spv::Decoration Deco = spv::DecorationDescriptorSet;
2207 SPIRVOperand *DecoOp = new SPIRVOperand(SPIRVOperandType::NUMBERID, Deco);
2208 Ops.push_back(DecoOp);
2209
David Neto44795152017-07-13 15:45:28 -04002210 descriptorMapOut << "sampler," << SamplerLiteral.first << ",samplerExpr,\""
2211 << SamplerLiteral.second << "\",descriptorSet,0,binding,"
David Netoc2c368d2017-06-30 16:50:17 -04002212 << BindingIdx << "\n";
2213
David Neto22f144c2017-06-12 14:26:21 -04002214 std::vector<uint32_t> LiteralNum;
2215 LiteralNum.push_back(0);
2216 SPIRVOperand *DescSet =
2217 new SPIRVOperand(SPIRVOperandType::LITERAL_INTEGER, LiteralNum);
2218 Ops.push_back(DescSet);
2219
2220 SPIRVInstruction *DescDecoInst =
2221 new SPIRVInstruction(4, spv::OpDecorate, 0 /* No id */, Ops);
2222 SPIRVInstList.insert(DecoInsertPoint, DescDecoInst);
2223
2224 // Ops[0] = Target ID
2225 // Ops[1] = Decoration (Binding)
2226 // Ops[2] = LiteralNumber according to Decoration
2227 Ops.clear();
2228
2229 Ops.push_back(ArgIDOp);
2230
2231 Deco = spv::DecorationBinding;
2232 DecoOp = new SPIRVOperand(SPIRVOperandType::NUMBERID, Deco);
2233 Ops.push_back(DecoOp);
2234
2235 LiteralNum.clear();
2236 LiteralNum.push_back(BindingIdx++);
2237 SPIRVOperand *Binding =
2238 new SPIRVOperand(SPIRVOperandType::LITERAL_INTEGER, LiteralNum);
2239 Ops.push_back(Binding);
2240
2241 SPIRVInstruction *BindDecoInst =
2242 new SPIRVInstruction(4, spv::OpDecorate, 0 /* No id */, Ops);
2243 SPIRVInstList.insert(DecoInsertPoint, BindDecoInst);
2244 }
2245
2246 const char *TranslateSamplerFunctionName = "__translate_sampler_initializer";
2247
2248 auto SamplerFunction = M.getFunction(TranslateSamplerFunctionName);
2249
2250 // If there are no uses of the sampler function, no work to do!
2251 if (!SamplerFunction) {
2252 return;
2253 }
2254
2255 // Iterate through the users of the sampler function.
2256 for (auto User : SamplerFunction->users()) {
2257 if (auto CI = dyn_cast<CallInst>(User)) {
2258 // Get the literal used to initialize the sampler.
2259 auto Constant = dyn_cast<ConstantInt>(CI->getArgOperand(0));
2260
2261 if (!Constant) {
2262 CI->getArgOperand(0)->print(errs());
2263 llvm_unreachable("Argument of sampler initializer was non-constant!");
2264 }
2265
2266 auto SamplerLiteral = static_cast<unsigned>(Constant->getZExtValue());
2267
2268 if (0 == SamplerLiteralToIDMap.count(SamplerLiteral)) {
2269 Constant->print(errs());
2270 llvm_unreachable("Sampler literal was not found in sampler map!");
2271 }
2272
2273 // Calls to the sampler literal function to initialize a sampler are
2274 // re-routed to the global variables declared for the sampler.
2275 VMap[CI] = SamplerLiteralToIDMap[SamplerLiteral];
2276 }
2277 }
2278}
2279
2280void SPIRVProducerPass::GenerateGlobalVar(GlobalVariable &GV) {
2281 SPIRVInstructionList &SPIRVInstList = getSPIRVInstList();
2282 ValueMapType &VMap = getValueMap();
2283 std::vector<uint32_t> &BuiltinDimVec = getBuiltinDimVec();
2284
2285 const spv::BuiltIn BuiltinType = GetBuiltin(GV.getName());
2286 Type *Ty = GV.getType();
2287 PointerType *PTy = cast<PointerType>(Ty);
2288
2289 uint32_t InitializerID = 0;
2290
2291 // Workgroup size is handled differently (it goes into a constant)
2292 if (spv::BuiltInWorkgroupSize == BuiltinType) {
2293 std::vector<bool> HasMDVec;
2294 uint32_t PrevXDimCst = 0xFFFFFFFF;
2295 uint32_t PrevYDimCst = 0xFFFFFFFF;
2296 uint32_t PrevZDimCst = 0xFFFFFFFF;
2297 for (Function &Func : *GV.getParent()) {
2298 if (Func.isDeclaration()) {
2299 continue;
2300 }
2301
2302 // We only need to check kernels.
2303 if (Func.getCallingConv() != CallingConv::SPIR_KERNEL) {
2304 continue;
2305 }
2306
2307 if (const MDNode *MD =
2308 dyn_cast<Function>(&Func)->getMetadata("reqd_work_group_size")) {
2309 uint32_t CurXDimCst = static_cast<uint32_t>(
2310 mdconst::extract<ConstantInt>(MD->getOperand(0))->getZExtValue());
2311 uint32_t CurYDimCst = static_cast<uint32_t>(
2312 mdconst::extract<ConstantInt>(MD->getOperand(1))->getZExtValue());
2313 uint32_t CurZDimCst = static_cast<uint32_t>(
2314 mdconst::extract<ConstantInt>(MD->getOperand(2))->getZExtValue());
2315
2316 if (PrevXDimCst == 0xFFFFFFFF && PrevYDimCst == 0xFFFFFFFF &&
2317 PrevZDimCst == 0xFFFFFFFF) {
2318 PrevXDimCst = CurXDimCst;
2319 PrevYDimCst = CurYDimCst;
2320 PrevZDimCst = CurZDimCst;
2321 } else if (CurXDimCst != PrevXDimCst || CurYDimCst != PrevYDimCst ||
2322 CurZDimCst != PrevZDimCst) {
2323 llvm_unreachable(
2324 "reqd_work_group_size must be the same across all kernels");
2325 } else {
2326 continue;
2327 }
2328
2329 //
2330 // Generate OpConstantComposite.
2331 //
2332 // Ops[0] : Result Type ID
2333 // Ops[1] : Constant size for x dimension.
2334 // Ops[2] : Constant size for y dimension.
2335 // Ops[3] : Constant size for z dimension.
2336 SPIRVOperandList Ops;
2337
2338 uint32_t XDimCstID =
2339 VMap[mdconst::extract<ConstantInt>(MD->getOperand(0))];
2340 uint32_t YDimCstID =
2341 VMap[mdconst::extract<ConstantInt>(MD->getOperand(1))];
2342 uint32_t ZDimCstID =
2343 VMap[mdconst::extract<ConstantInt>(MD->getOperand(2))];
2344
2345 InitializerID = nextID;
2346
2347 Ops.push_back(
2348 new SPIRVOperand(SPIRVOperandType::NUMBERID,
2349 lookupType(Ty->getPointerElementType())));
2350
2351 Ops.push_back(new SPIRVOperand(SPIRVOperandType::NUMBERID, XDimCstID));
2352 Ops.push_back(new SPIRVOperand(SPIRVOperandType::NUMBERID, YDimCstID));
2353 Ops.push_back(new SPIRVOperand(SPIRVOperandType::NUMBERID, ZDimCstID));
2354
2355 SPIRVInstruction *Inst =
2356 new SPIRVInstruction(6, spv::OpConstantComposite, nextID++, Ops);
2357 SPIRVInstList.push_back(Inst);
2358
2359 HasMDVec.push_back(true);
2360 } else {
2361 HasMDVec.push_back(false);
2362 }
2363 }
2364
2365 // Check all kernels have same definitions for work_group_size.
2366 bool HasMD = false;
2367 if (!HasMDVec.empty()) {
2368 HasMD = HasMDVec[0];
2369 for (uint32_t i = 1; i < HasMDVec.size(); i++) {
2370 if (HasMD != HasMDVec[i]) {
2371 llvm_unreachable(
2372 "Kernels should have consistent work group size definition");
2373 }
2374 }
2375 }
2376
2377 // If all kernels do not have metadata for reqd_work_group_size, generate
2378 // OpSpecConstants for x/y/z dimension.
2379 if (!HasMD) {
2380 //
2381 // Generate OpSpecConstants for x/y/z dimension.
2382 //
2383 // Ops[0] : Result Type ID
2384 // Ops[1] : Constant size for x/y/z dimension (Literal Number).
2385 uint32_t XDimCstID = 0;
2386 uint32_t YDimCstID = 0;
2387 uint32_t ZDimCstID = 0;
2388
2389 // X Dimension
2390 SPIRVOperandList Ops;
2391
2392 Ops.push_back(new SPIRVOperand(
2393 SPIRVOperandType::NUMBERID,
2394 lookupType(Ty->getPointerElementType()->getSequentialElementType())));
2395
2396 std::vector<uint32_t> LiteralNum;
2397 LiteralNum.push_back(1);
2398 SPIRVOperand *XDim =
2399 new SPIRVOperand(SPIRVOperandType::LITERAL_INTEGER, LiteralNum);
2400 Ops.push_back(XDim);
2401
2402 XDimCstID = nextID;
2403 BuiltinDimVec.push_back(XDimCstID);
2404
2405 SPIRVInstruction *XDimCstInst =
2406 new SPIRVInstruction(4, spv::OpSpecConstant, nextID++, Ops);
2407 SPIRVInstList.push_back(XDimCstInst);
2408
2409 // Y Dimension
2410 Ops.clear();
2411
2412 Ops.push_back(new SPIRVOperand(
2413 SPIRVOperandType::NUMBERID,
2414 lookupType(Ty->getPointerElementType()->getSequentialElementType())));
2415
2416 LiteralNum.clear();
2417 LiteralNum.push_back(1);
2418 SPIRVOperand *YDim =
2419 new SPIRVOperand(SPIRVOperandType::LITERAL_INTEGER, LiteralNum);
2420 Ops.push_back(YDim);
2421
2422 YDimCstID = nextID;
2423 BuiltinDimVec.push_back(YDimCstID);
2424
2425 SPIRVInstruction *YDimCstInst =
2426 new SPIRVInstruction(4, spv::OpSpecConstant, nextID++, Ops);
2427 SPIRVInstList.push_back(YDimCstInst);
2428
2429 // Z Dimension
2430 Ops.clear();
2431
2432 Ops.push_back(new SPIRVOperand(
2433 SPIRVOperandType::NUMBERID,
2434 lookupType(Ty->getPointerElementType()->getSequentialElementType())));
2435
2436 LiteralNum.clear();
2437 LiteralNum.push_back(1);
2438 SPIRVOperand *ZDim =
2439 new SPIRVOperand(SPIRVOperandType::LITERAL_INTEGER, LiteralNum);
2440 Ops.push_back(ZDim);
2441
2442 ZDimCstID = nextID;
2443 BuiltinDimVec.push_back(ZDimCstID);
2444
2445 SPIRVInstruction *ZDimCstInst =
2446 new SPIRVInstruction(4, spv::OpSpecConstant, nextID++, Ops);
2447 SPIRVInstList.push_back(ZDimCstInst);
2448
2449 //
2450 // Generate OpSpecConstantComposite.
2451 //
2452 // Ops[0] : Result Type ID
2453 // Ops[1] : Constant size for x dimension.
2454 // Ops[2] : Constant size for y dimension.
2455 // Ops[3] : Constant size for z dimension.
2456 InitializerID = nextID;
2457
2458 Ops.clear();
2459
2460 Ops.push_back(new SPIRVOperand(SPIRVOperandType::NUMBERID,
2461 lookupType(Ty->getPointerElementType())));
2462
2463 Ops.push_back(new SPIRVOperand(SPIRVOperandType::NUMBERID, XDimCstID));
2464 Ops.push_back(new SPIRVOperand(SPIRVOperandType::NUMBERID, YDimCstID));
2465 Ops.push_back(new SPIRVOperand(SPIRVOperandType::NUMBERID, ZDimCstID));
2466
2467 SPIRVInstruction *Inst =
2468 new SPIRVInstruction(6, spv::OpSpecConstantComposite, nextID++, Ops);
2469 SPIRVInstList.push_back(Inst);
2470 }
2471 }
2472
2473 if (GV.hasInitializer()) {
2474 InitializerID = VMap[GV.getInitializer()];
2475 }
2476
2477 VMap[&GV] = nextID;
2478
2479 //
2480 // Generate OpVariable.
2481 //
2482 // GIDOps[0] : Result Type ID
2483 // GIDOps[1] : Storage Class
2484 SPIRVOperandList Ops;
2485
2486 Ops.push_back(new SPIRVOperand(SPIRVOperandType::NUMBERID, lookupType(Ty)));
2487
2488 spv::StorageClass StorageClass = GetStorageClass(PTy->getAddressSpace());
2489 Ops.push_back(new SPIRVOperand(SPIRVOperandType::NUMBERID, StorageClass));
2490
2491 if (0 != InitializerID) {
2492 Ops.push_back(new SPIRVOperand(SPIRVOperandType::NUMBERID, InitializerID));
2493 }
2494
2495 SPIRVInstruction *Inst = new SPIRVInstruction(
2496 static_cast<uint16_t>(2 + Ops.size()), spv::OpVariable, nextID++, Ops);
2497 SPIRVInstList.push_back(Inst);
2498
2499 // If we have a builtin.
2500 if (spv::BuiltInMax != BuiltinType) {
2501 // Find Insert Point for OpDecorate.
2502 auto DecoInsertPoint =
2503 std::find_if(SPIRVInstList.begin(), SPIRVInstList.end(),
2504 [](SPIRVInstruction *Inst) -> bool {
2505 return Inst->getOpcode() != spv::OpDecorate &&
2506 Inst->getOpcode() != spv::OpMemberDecorate &&
2507 Inst->getOpcode() != spv::OpExtInstImport;
2508 });
2509 //
2510 // Generate OpDecorate.
2511 //
2512 // DOps[0] = Target ID
2513 // DOps[1] = Decoration (Builtin)
2514 // DOps[2] = BuiltIn ID
2515 uint32_t ResultID;
2516
2517 // WorkgroupSize is different, we decorate the constant composite that has
2518 // its value, rather than the variable that we use to access the value.
2519 if (spv::BuiltInWorkgroupSize == BuiltinType) {
2520 ResultID = InitializerID;
David Netoa60b00b2017-09-15 16:34:09 -04002521 // Save both the value and variable IDs for later.
2522 WorkgroupSizeValueID = InitializerID;
2523 WorkgroupSizeVarID = VMap[&GV];
David Neto22f144c2017-06-12 14:26:21 -04002524 } else {
2525 ResultID = VMap[&GV];
2526 }
2527
2528 SPIRVOperandList DOps;
2529 SPIRVOperand *ResultIDOp =
2530 new SPIRVOperand(SPIRVOperandType::NUMBERID, ResultID);
2531 DOps.push_back(ResultIDOp);
2532
2533 spv::Decoration Deco = spv::DecorationBuiltIn;
2534 SPIRVOperand *DecoOp = new SPIRVOperand(SPIRVOperandType::NUMBERID, Deco);
2535 DOps.push_back(DecoOp);
2536
2537 SPIRVOperand *Builtin =
2538 new SPIRVOperand(SPIRVOperandType::NUMBERID, BuiltinType);
2539 DOps.push_back(Builtin);
2540
2541 SPIRVInstruction *DescDecoInst =
2542 new SPIRVInstruction(4, spv::OpDecorate, 0 /* No id */, DOps);
2543 SPIRVInstList.insert(DecoInsertPoint, DescDecoInst);
2544 }
2545}
2546
2547void SPIRVProducerPass::GenerateFuncPrologue(Function &F) {
2548 SPIRVInstructionList &SPIRVInstList = getSPIRVInstList();
2549 ValueMapType &VMap = getValueMap();
2550 EntryPointVecType &EntryPoints = getEntryPointVec();
2551 ValueToValueMapTy &ArgGVMap = getArgumentGVMap();
2552 ValueMapType &ArgGVIDMap = getArgumentGVIDMap();
2553 auto &GlobalConstFuncTyMap = getGlobalConstFuncTypeMap();
2554 auto &GlobalConstArgSet = getGlobalConstArgSet();
2555
2556 FunctionType *FTy = F.getFunctionType();
2557
2558 //
2559 // Generate OpVariable and OpDecorate for kernel function with arguments.
2560 //
2561 if (F.getCallingConv() == CallingConv::SPIR_KERNEL) {
2562
2563 // Find Insert Point for OpDecorate.
2564 auto DecoInsertPoint =
2565 std::find_if(SPIRVInstList.begin(), SPIRVInstList.end(),
2566 [](SPIRVInstruction *Inst) -> bool {
2567 return Inst->getOpcode() != spv::OpDecorate &&
2568 Inst->getOpcode() != spv::OpMemberDecorate &&
2569 Inst->getOpcode() != spv::OpExtInstImport;
2570 });
2571
2572 uint32_t DescriptorSetIdx = (0 < getSamplerMap().size()) ? 1u : 0u;
David Netocd8ca5f2017-10-02 23:34:11 -04002573 if (distinct_kernel_descriptor_sets) {
2574 for (Function &Func : *F.getParent()) {
2575 if (Func.isDeclaration()) {
2576 continue;
David Neto22f144c2017-06-12 14:26:21 -04002577 }
David Netocd8ca5f2017-10-02 23:34:11 -04002578
2579 if (Func.getCallingConv() == CallingConv::SPIR_KERNEL) {
2580 if (&Func == &F) {
2581 break;
2582 }
2583 DescriptorSetIdx++;
2584 }
David Neto22f144c2017-06-12 14:26:21 -04002585 }
2586 }
2587
David Neto156783e2017-07-05 15:39:41 -04002588 const auto *ArgMap = F.getMetadata("kernel_arg_map");
2589 // Emit descriptor map entries, if there was explicit metadata
2590 // attached.
2591 if (ArgMap) {
2592 for (const auto &arg : ArgMap->operands()) {
2593 const MDNode *arg_node = dyn_cast<MDNode>(arg.get());
David Neto48f56a42017-10-06 16:44:25 -04002594 assert(arg_node->getNumOperands() == 5);
David Neto156783e2017-07-05 15:39:41 -04002595 const auto name =
2596 dyn_cast<MDString>(arg_node->getOperand(0))->getString();
2597 const auto old_index =
2598 dyn_extract<ConstantInt>(arg_node->getOperand(1))->getZExtValue();
2599 const auto new_index =
2600 dyn_extract<ConstantInt>(arg_node->getOperand(2))->getZExtValue();
2601 const auto offset =
2602 dyn_extract<ConstantInt>(arg_node->getOperand(3))->getZExtValue();
David Neto4feb7a42017-10-06 17:29:42 -04002603 const auto argKind =
David Neto48f56a42017-10-06 16:44:25 -04002604 dyn_cast<MDString>(arg_node->getOperand(4))->getString();
David Neto156783e2017-07-05 15:39:41 -04002605 descriptorMapOut << "kernel," << F.getName() << ",arg," << name
2606 << ",argOrdinal," << old_index << ",descriptorSet,"
2607 << DescriptorSetIdx << ",binding," << new_index
David Neto4feb7a42017-10-06 17:29:42 -04002608 << ",offset," << offset << ",argKind," << argKind
David Neto48f56a42017-10-06 16:44:25 -04002609 << "\n";
David Neto156783e2017-07-05 15:39:41 -04002610 }
2611 }
2612
David Neto22f144c2017-06-12 14:26:21 -04002613 uint32_t BindingIdx = 0;
2614 for (auto &Arg : F.args()) {
2615 Value *NewGV = ArgGVMap[&Arg];
2616 VMap[&Arg] = VMap[NewGV];
2617 ArgGVIDMap[&Arg] = VMap[&Arg];
2618
David Neto156783e2017-07-05 15:39:41 -04002619 // Emit a descriptor map entry for this arg, in case there was no explicit
2620 // kernel arg mapping metadata.
2621 if (!ArgMap) {
2622 descriptorMapOut << "kernel," << F.getName() << ",arg," << Arg.getName()
2623 << ",argOrdinal," << BindingIdx << ",descriptorSet,"
2624 << DescriptorSetIdx << ",binding," << BindingIdx
David Neto4feb7a42017-10-06 17:29:42 -04002625 << ",offset,0,argKind,"
2626 << clspv::GetArgKindForType(Arg.getType()) << "\n";
David Netoc2c368d2017-06-30 16:50:17 -04002627 }
2628
David Neto22f144c2017-06-12 14:26:21 -04002629 // Ops[0] = Target ID
2630 // Ops[1] = Decoration (DescriptorSet)
2631 // Ops[2] = LiteralNumber according to Decoration
2632 SPIRVOperandList Ops;
2633
2634 SPIRVOperand *ArgIDOp =
2635 new SPIRVOperand(SPIRVOperandType::NUMBERID, VMap[&Arg]);
2636 Ops.push_back(ArgIDOp);
2637
2638 spv::Decoration Deco = spv::DecorationDescriptorSet;
2639 SPIRVOperand *DecoOp = new SPIRVOperand(SPIRVOperandType::NUMBERID, Deco);
2640 Ops.push_back(DecoOp);
2641
2642 std::vector<uint32_t> LiteralNum;
2643 LiteralNum.push_back(DescriptorSetIdx);
2644 SPIRVOperand *DescSet =
2645 new SPIRVOperand(SPIRVOperandType::LITERAL_INTEGER, LiteralNum);
2646 Ops.push_back(DescSet);
2647
2648 SPIRVInstruction *DescDecoInst =
2649 new SPIRVInstruction(4, spv::OpDecorate, 0 /* No id */, Ops);
2650 SPIRVInstList.insert(DecoInsertPoint, DescDecoInst);
2651
2652 // Ops[0] = Target ID
2653 // Ops[1] = Decoration (Binding)
2654 // Ops[2] = LiteralNumber according to Decoration
2655 Ops.clear();
2656
2657 Ops.push_back(ArgIDOp);
2658
2659 Deco = spv::DecorationBinding;
2660 DecoOp = new SPIRVOperand(SPIRVOperandType::NUMBERID, Deco);
2661 Ops.push_back(DecoOp);
2662
2663 LiteralNum.clear();
2664 LiteralNum.push_back(BindingIdx++);
2665 SPIRVOperand *Binding =
2666 new SPIRVOperand(SPIRVOperandType::LITERAL_INTEGER, LiteralNum);
2667 Ops.push_back(Binding);
2668
2669 SPIRVInstruction *BindDecoInst =
2670 new SPIRVInstruction(4, spv::OpDecorate, 0 /* No id */, Ops);
2671 SPIRVInstList.insert(DecoInsertPoint, BindDecoInst);
2672
2673 // Handle image type argument.
2674 bool HasReadOnlyImageType = false;
2675 bool HasWriteOnlyImageType = false;
2676 if (PointerType *ArgPTy = dyn_cast<PointerType>(Arg.getType())) {
2677 if (StructType *STy = dyn_cast<StructType>(ArgPTy->getElementType())) {
2678 if (STy->isOpaque()) {
2679 if (STy->getName().equals("opencl.image2d_ro_t") ||
2680 STy->getName().equals("opencl.image3d_ro_t")) {
2681 HasReadOnlyImageType = true;
2682 } else if (STy->getName().equals("opencl.image2d_wo_t") ||
2683 STy->getName().equals("opencl.image3d_wo_t")) {
2684 HasWriteOnlyImageType = true;
2685 }
2686 }
2687 }
2688 }
2689
2690 if (HasReadOnlyImageType || HasWriteOnlyImageType) {
2691 // Ops[0] = Target ID
2692 // Ops[1] = Decoration (NonReadable or NonWritable)
2693 Ops.clear();
2694
2695 ArgIDOp = new SPIRVOperand(SPIRVOperandType::NUMBERID, VMap[&Arg]);
2696 Ops.push_back(ArgIDOp);
2697
2698 Deco = spv::DecorationNonReadable;
2699 if (HasReadOnlyImageType) {
2700 Deco = spv::DecorationNonWritable;
2701 }
2702 DecoOp = new SPIRVOperand(SPIRVOperandType::NUMBERID, Deco);
2703 Ops.push_back(DecoOp);
2704
2705 DescDecoInst =
2706 new SPIRVInstruction(3, spv::OpDecorate, 0 /* No id */, Ops);
2707 SPIRVInstList.insert(DecoInsertPoint, DescDecoInst);
2708 }
2709
2710 // Handle const address space.
2711 if (NewGV->getType()->getPointerAddressSpace() ==
2712 AddressSpace::Constant) {
2713 // Ops[0] = Target ID
2714 // Ops[1] = Decoration (NonWriteable)
2715 Ops.clear();
2716
2717 Ops.push_back(ArgIDOp);
2718
2719 Deco = spv::DecorationNonWritable;
2720 DecoOp = new SPIRVOperand(SPIRVOperandType::NUMBERID, Deco);
2721 Ops.push_back(DecoOp);
2722
2723 BindDecoInst =
2724 new SPIRVInstruction(3, spv::OpDecorate, 0 /* No id */, Ops);
2725 SPIRVInstList.insert(DecoInsertPoint, BindDecoInst);
2726 }
2727 }
2728 }
2729
2730 //
2731 // Generate OPFunction.
2732 //
2733
2734 // FOps[0] : Result Type ID
2735 // FOps[1] : Function Control
2736 // FOps[2] : Function Type ID
2737 SPIRVOperandList FOps;
2738
2739 // Find SPIRV instruction for return type.
2740 uint32_t RetTyID = lookupType(FTy->getReturnType());
2741 SPIRVOperand *RetTyOp = new SPIRVOperand(SPIRVOperandType::NUMBERID, RetTyID);
2742 FOps.push_back(RetTyOp);
2743
2744 // Check function attributes for SPIRV Function Control.
2745 uint32_t FuncControl = spv::FunctionControlMaskNone;
2746 if (F.hasFnAttribute(Attribute::AlwaysInline)) {
2747 FuncControl |= spv::FunctionControlInlineMask;
2748 }
2749 if (F.hasFnAttribute(Attribute::NoInline)) {
2750 FuncControl |= spv::FunctionControlDontInlineMask;
2751 }
2752 // TODO: Check llvm attribute for Function Control Pure.
2753 if (F.hasFnAttribute(Attribute::ReadOnly)) {
2754 FuncControl |= spv::FunctionControlPureMask;
2755 }
2756 // TODO: Check llvm attribute for Function Control Const.
2757 if (F.hasFnAttribute(Attribute::ReadNone)) {
2758 FuncControl |= spv::FunctionControlConstMask;
2759 }
2760
2761 SPIRVOperand *FunctionControlOp =
2762 new SPIRVOperand(SPIRVOperandType::NUMBERID, FuncControl);
2763 FOps.push_back(FunctionControlOp);
2764
2765 uint32_t FTyID;
2766 if (F.getCallingConv() == CallingConv::SPIR_KERNEL) {
2767 SmallVector<Type *, 4> NewFuncParamTys;
2768 FunctionType *NewFTy =
2769 FunctionType::get(FTy->getReturnType(), NewFuncParamTys, false);
2770 FTyID = lookupType(NewFTy);
2771 } else {
2772 // Handle function with global constant parameters.
2773 if (GlobalConstFuncTyMap.count(FTy)) {
2774 FTyID = lookupType(GlobalConstFuncTyMap[FTy].first);
2775 } else {
2776 FTyID = lookupType(FTy);
2777 }
2778 }
2779
2780 SPIRVOperand *FTyOp = new SPIRVOperand(SPIRVOperandType::NUMBERID, FTyID);
2781 FOps.push_back(FTyOp);
2782
2783 if (F.getCallingConv() == CallingConv::SPIR_KERNEL) {
2784 EntryPoints.push_back(std::make_pair(&F, nextID));
2785 }
2786
2787 VMap[&F] = nextID;
2788
2789 // Generate SPIRV instruction for function.
2790 SPIRVInstruction *FuncInst =
2791 new SPIRVInstruction(5, spv::OpFunction, nextID++, FOps);
2792 SPIRVInstList.push_back(FuncInst);
2793
2794 //
2795 // Generate OpFunctionParameter for Normal function.
2796 //
2797
2798 if (F.getCallingConv() != CallingConv::SPIR_KERNEL) {
2799 // Iterate Argument for name instead of param type from function type.
2800 unsigned ArgIdx = 0;
2801 for (Argument &Arg : F.args()) {
2802 VMap[&Arg] = nextID;
2803
2804 // ParamOps[0] : Result Type ID
2805 SPIRVOperandList ParamOps;
2806
2807 // Find SPIRV instruction for parameter type.
2808 uint32_t ParamTyID = lookupType(Arg.getType());
2809 if (PointerType *PTy = dyn_cast<PointerType>(Arg.getType())) {
2810 if (GlobalConstFuncTyMap.count(FTy)) {
2811 if (ArgIdx == GlobalConstFuncTyMap[FTy].second) {
2812 Type *EleTy = PTy->getPointerElementType();
2813 Type *ArgTy =
2814 PointerType::get(EleTy, AddressSpace::ModuleScopePrivate);
2815 ParamTyID = lookupType(ArgTy);
2816 GlobalConstArgSet.insert(&Arg);
2817 }
2818 }
2819 }
2820 SPIRVOperand *ParamTyOp =
2821 new SPIRVOperand(SPIRVOperandType::NUMBERID, ParamTyID);
2822 ParamOps.push_back(ParamTyOp);
2823
2824 // Generate SPIRV instruction for parameter.
2825 SPIRVInstruction *ParamInst =
2826 new SPIRVInstruction(3, spv::OpFunctionParameter, nextID++, ParamOps);
2827 SPIRVInstList.push_back(ParamInst);
2828
2829 ArgIdx++;
2830 }
2831 }
2832}
2833
2834void SPIRVProducerPass::GenerateModuleInfo() {
2835 SPIRVInstructionList &SPIRVInstList = getSPIRVInstList();
2836 EntryPointVecType &EntryPoints = getEntryPointVec();
2837 ValueMapType &VMap = getValueMap();
2838 ValueList &EntryPointInterfaces = getEntryPointInterfacesVec();
2839 uint32_t &ExtInstImportID = getOpExtInstImportID();
2840 std::vector<uint32_t> &BuiltinDimVec = getBuiltinDimVec();
2841
2842 // Set up insert point.
2843 auto InsertPoint = SPIRVInstList.begin();
2844
2845 //
2846 // Generate OpCapability
2847 //
2848 // TODO: Which llvm information is mapped to SPIRV Capapbility?
2849
2850 // Ops[0] = Capability
2851 SPIRVOperandList Ops;
2852
2853 SPIRVInstruction *CapInst = new SPIRVInstruction(
2854 2, spv::OpCapability, 0 /* No id */,
2855 new SPIRVOperand(SPIRVOperandType::NUMBERID, spv::CapabilityShader));
2856 SPIRVInstList.insert(InsertPoint, CapInst);
2857
2858 for (Type *Ty : getTypeList()) {
2859 // Find the i16 type.
2860 if (Ty->isIntegerTy(16)) {
2861 // Generate OpCapability for i16 type.
2862 SPIRVInstList.insert(
2863 InsertPoint,
2864 new SPIRVInstruction(2, spv::OpCapability, 0 /* No id */,
2865 new SPIRVOperand(SPIRVOperandType::NUMBERID,
2866 spv::CapabilityInt16)));
2867 } else if (Ty->isIntegerTy(64)) {
2868 // Generate OpCapability for i64 type.
2869 SPIRVInstList.insert(
2870 InsertPoint,
2871 new SPIRVInstruction(2, spv::OpCapability, 0 /* No id */,
2872 new SPIRVOperand(SPIRVOperandType::NUMBERID,
2873 spv::CapabilityInt64)));
2874 } else if (Ty->isHalfTy()) {
2875 // Generate OpCapability for half type.
2876 SPIRVInstList.insert(
2877 InsertPoint,
2878 new SPIRVInstruction(2, spv::OpCapability, 0 /* No id */,
2879 new SPIRVOperand(SPIRVOperandType::NUMBERID,
2880 spv::CapabilityFloat16)));
2881 } else if (Ty->isDoubleTy()) {
2882 // Generate OpCapability for double type.
2883 SPIRVInstList.insert(
2884 InsertPoint,
2885 new SPIRVInstruction(2, spv::OpCapability, 0 /* No id */,
2886 new SPIRVOperand(SPIRVOperandType::NUMBERID,
2887 spv::CapabilityFloat64)));
2888 } else if (auto *STy = dyn_cast<StructType>(Ty)) {
2889 if (STy->isOpaque()) {
David Neto565571c2017-08-21 12:00:05 -04002890 if (STy->getName().equals("opencl.image2d_wo_t") ||
2891 STy->getName().equals("opencl.image3d_wo_t")) {
David Neto22f144c2017-06-12 14:26:21 -04002892 // Generate OpCapability for write only image type.
2893 SPIRVInstList.insert(
2894 InsertPoint,
2895 new SPIRVInstruction(
2896 2, spv::OpCapability, 0 /* No id */,
2897 new SPIRVOperand(
2898 SPIRVOperandType::NUMBERID,
2899 spv::CapabilityStorageImageWriteWithoutFormat)));
2900 }
2901 }
2902 }
2903 }
2904
2905 if (hasVariablePointers()) {
2906 //
2907 // Generate OpCapability and OpExtension
2908 //
2909
2910 //
2911 // Generate OpCapability.
2912 //
2913 // Ops[0] = Capability
2914 //
2915 Ops.clear();
2916
2917 Ops.push_back(new SPIRVOperand(SPIRVOperandType::NUMBERID,
2918 spv::CapabilityVariablePointers));
2919
2920 SPIRVInstList.insert(InsertPoint, new SPIRVInstruction(2, spv::OpCapability,
2921 0 /* No id */, Ops));
2922
2923 //
2924 // Generate OpExtension.
2925 //
2926 // Ops[0] = Name (Literal String)
2927 //
David Netoa772fd12017-08-04 14:17:33 -04002928 for (auto extension : {"SPV_KHR_storage_buffer_storage_class",
2929 "SPV_KHR_variable_pointers"}) {
2930 Ops.clear();
David Neto22f144c2017-06-12 14:26:21 -04002931
David Netoa772fd12017-08-04 14:17:33 -04002932 SPIRVOperand *Name =
2933 new SPIRVOperand(SPIRVOperandType::LITERAL_STRING, extension);
2934 Ops.push_back(Name);
David Neto22f144c2017-06-12 14:26:21 -04002935
David Netoa772fd12017-08-04 14:17:33 -04002936 size_t NameWordSize = (Name->getLiteralStr().size() + 1) / 4;
2937 if ((Name->getLiteralStr().size() + 1) % 4) {
2938 NameWordSize += 1;
2939 }
2940
2941 assert((NameWordSize + 1) < UINT16_MAX);
2942 uint16_t WordCount = static_cast<uint16_t>(1 + NameWordSize);
2943
2944 SPIRVInstruction *ExtensionInst =
2945 new SPIRVInstruction(WordCount, spv::OpExtension, 0 /* No id */, Ops);
2946 SPIRVInstList.insert(InsertPoint, ExtensionInst);
David Neto22f144c2017-06-12 14:26:21 -04002947 }
David Neto22f144c2017-06-12 14:26:21 -04002948 }
2949
2950 if (ExtInstImportID) {
2951 ++InsertPoint;
2952 }
2953
2954 //
2955 // Generate OpMemoryModel
2956 //
2957 // Memory model for Vulkan will always be GLSL450.
2958
2959 // Ops[0] = Addressing Model
2960 // Ops[1] = Memory Model
2961 Ops.clear();
2962 SPIRVOperand *AddrModel =
2963 new SPIRVOperand(SPIRVOperandType::NUMBERID, spv::AddressingModelLogical);
2964 Ops.push_back(AddrModel);
2965
2966 SPIRVOperand *MemModel =
2967 new SPIRVOperand(SPIRVOperandType::NUMBERID, spv::MemoryModelGLSL450);
2968 Ops.push_back(MemModel);
2969
2970 SPIRVInstruction *MemModelInst =
2971 new SPIRVInstruction(3, spv::OpMemoryModel, 0 /* No id */, Ops);
2972 SPIRVInstList.insert(InsertPoint, MemModelInst);
2973
2974 //
2975 // Generate OpEntryPoint
2976 //
2977 for (auto EntryPoint : EntryPoints) {
2978 // Ops[0] = Execution Model
2979 // Ops[1] = EntryPoint ID
2980 // Ops[2] = Name (Literal String)
2981 // ...
2982 //
2983 // TODO: Do we need to consider Interface ID for forward references???
2984 Ops.clear();
2985 SPIRVOperand *ExecModel = new SPIRVOperand(SPIRVOperandType::NUMBERID,
2986 spv::ExecutionModelGLCompute);
2987 Ops.push_back(ExecModel);
2988
2989 SPIRVOperand *EntryPointID =
2990 new SPIRVOperand(SPIRVOperandType::NUMBERID, EntryPoint.second);
2991 Ops.push_back(EntryPointID);
2992
2993 SPIRVOperand *Name = new SPIRVOperand(SPIRVOperandType::LITERAL_STRING,
2994 EntryPoint.first->getName());
2995 Ops.push_back(Name);
2996
2997 size_t NameWordSize = (Name->getLiteralStr().size() + 1) / 4;
2998 if ((Name->getLiteralStr().size() + 1) % 4) {
2999 NameWordSize += 1;
3000 }
3001
3002 assert((3 + NameWordSize) < UINT16_MAX);
3003 uint16_t WordCount = static_cast<uint16_t>(3 + NameWordSize);
3004
3005 for (Value *Interface : EntryPointInterfaces) {
3006 SPIRVOperand *GIDOp =
3007 new SPIRVOperand(SPIRVOperandType::NUMBERID, VMap[Interface]);
3008 Ops.push_back(GIDOp);
3009 WordCount++;
3010 }
3011
3012 SPIRVInstruction *EntryPointInst =
3013 new SPIRVInstruction(WordCount, spv::OpEntryPoint, 0 /* No id */, Ops);
3014 SPIRVInstList.insert(InsertPoint, EntryPointInst);
3015 }
3016
3017 for (auto EntryPoint : EntryPoints) {
3018 if (const MDNode *MD = dyn_cast<Function>(EntryPoint.first)
3019 ->getMetadata("reqd_work_group_size")) {
3020
3021 if (!BuiltinDimVec.empty()) {
3022 llvm_unreachable(
3023 "Kernels should have consistent work group size definition");
3024 }
3025
3026 //
3027 // Generate OpExecutionMode
3028 //
3029
3030 // Ops[0] = Entry Point ID
3031 // Ops[1] = Execution Mode
3032 // Ops[2] ... Ops[n] = Optional literals according to Execution Mode
3033 Ops.clear();
3034 SPIRVOperand *EntryPointID =
3035 new SPIRVOperand(SPIRVOperandType::NUMBERID, EntryPoint.second);
3036 Ops.push_back(EntryPointID);
3037
3038 SPIRVOperand *ExecMode = new SPIRVOperand(SPIRVOperandType::NUMBERID,
3039 spv::ExecutionModeLocalSize);
3040 Ops.push_back(ExecMode);
3041
3042 uint32_t XDim = static_cast<uint32_t>(
3043 mdconst::extract<ConstantInt>(MD->getOperand(0))->getZExtValue());
3044 uint32_t YDim = static_cast<uint32_t>(
3045 mdconst::extract<ConstantInt>(MD->getOperand(1))->getZExtValue());
3046 uint32_t ZDim = static_cast<uint32_t>(
3047 mdconst::extract<ConstantInt>(MD->getOperand(2))->getZExtValue());
3048
3049 std::vector<uint32_t> LiteralNum;
3050 LiteralNum.push_back(XDim);
3051 SPIRVOperand *XDimOp =
3052 new SPIRVOperand(SPIRVOperandType::LITERAL_INTEGER, LiteralNum);
3053 Ops.push_back(XDimOp);
3054
3055 LiteralNum.clear();
3056 LiteralNum.push_back(YDim);
3057 SPIRVOperand *YDimOp =
3058 new SPIRVOperand(SPIRVOperandType::LITERAL_INTEGER, LiteralNum);
3059 Ops.push_back(YDimOp);
3060
3061 LiteralNum.clear();
3062 LiteralNum.push_back(ZDim);
3063 SPIRVOperand *ZDimOp =
3064 new SPIRVOperand(SPIRVOperandType::LITERAL_INTEGER, LiteralNum);
3065 Ops.push_back(ZDimOp);
3066
3067 SPIRVInstruction *ExecModeInst =
3068 new SPIRVInstruction(static_cast<uint16_t>(1 + Ops.size()),
3069 spv::OpExecutionMode, 0 /* No id */, Ops);
3070 SPIRVInstList.insert(InsertPoint, ExecModeInst);
3071 }
3072 }
3073
3074 //
3075 // Generate OpSource.
3076 //
3077 // Ops[0] = SourceLanguage ID
3078 // Ops[1] = Version (LiteralNum)
3079 //
3080 Ops.clear();
3081 SPIRVOperand *SourceLanguage =
3082 new SPIRVOperand(SPIRVOperandType::NUMBERID, spv::SourceLanguageOpenCL_C);
3083 Ops.push_back(SourceLanguage);
3084
3085 std::vector<uint32_t> LiteralNum;
3086 LiteralNum.push_back(120);
3087 SPIRVOperand *Version =
3088 new SPIRVOperand(SPIRVOperandType::LITERAL_INTEGER, LiteralNum);
3089 Ops.push_back(Version);
3090
3091 SPIRVInstruction *OpenSourceInst =
3092 new SPIRVInstruction(3, spv::OpSource, 0 /* No id */, Ops);
3093 SPIRVInstList.insert(InsertPoint, OpenSourceInst);
3094
3095 if (!BuiltinDimVec.empty()) {
3096 //
3097 // Generate OpDecorates for x/y/z dimension.
3098 //
3099 // Ops[0] = Target ID
3100 // Ops[1] = Decoration (SpecId)
3101 // Ops[2] = Specialization Cosntant ID (Literal Number)
3102
3103 // X Dimension
3104 Ops.clear();
3105
3106 SPIRVOperand *TargetID =
3107 new SPIRVOperand(SPIRVOperandType::NUMBERID, BuiltinDimVec[0]);
3108 Ops.push_back(TargetID);
3109
3110 SPIRVOperand *DecoOp =
3111 new SPIRVOperand(SPIRVOperandType::NUMBERID, spv::DecorationSpecId);
3112 Ops.push_back(DecoOp);
3113
3114 LiteralNum.clear();
3115 LiteralNum.push_back(0);
3116 SPIRVOperand *XDim =
3117 new SPIRVOperand(SPIRVOperandType::LITERAL_INTEGER, LiteralNum);
3118 Ops.push_back(XDim);
3119
3120 SPIRVInstruction *XDimDecoInst =
3121 new SPIRVInstruction(4, spv::OpDecorate, 0 /* No id */, Ops);
3122 SPIRVInstList.insert(InsertPoint, XDimDecoInst);
3123
3124 // Y Dimension
3125 Ops.clear();
3126
3127 TargetID = new SPIRVOperand(SPIRVOperandType::NUMBERID, BuiltinDimVec[1]);
3128 Ops.push_back(TargetID);
3129
3130 DecoOp =
3131 new SPIRVOperand(SPIRVOperandType::NUMBERID, spv::DecorationSpecId);
3132 Ops.push_back(DecoOp);
3133
3134 LiteralNum.clear();
3135 LiteralNum.push_back(1);
3136 SPIRVOperand *YDim =
3137 new SPIRVOperand(SPIRVOperandType::LITERAL_INTEGER, LiteralNum);
3138 Ops.push_back(YDim);
3139
3140 SPIRVInstruction *YDimDecoInst =
3141 new SPIRVInstruction(4, spv::OpDecorate, 0 /* No id */, Ops);
3142 SPIRVInstList.insert(InsertPoint, YDimDecoInst);
3143
3144 // Z Dimension
3145 Ops.clear();
3146
3147 TargetID = new SPIRVOperand(SPIRVOperandType::NUMBERID, BuiltinDimVec[2]);
3148 Ops.push_back(TargetID);
3149
3150 DecoOp =
3151 new SPIRVOperand(SPIRVOperandType::NUMBERID, spv::DecorationSpecId);
3152 Ops.push_back(DecoOp);
3153
3154 LiteralNum.clear();
3155 LiteralNum.push_back(2);
3156 SPIRVOperand *ZDim =
3157 new SPIRVOperand(SPIRVOperandType::LITERAL_INTEGER, LiteralNum);
3158 Ops.push_back(ZDim);
3159
3160 SPIRVInstruction *ZDimDecoInst =
3161 new SPIRVInstruction(4, spv::OpDecorate, 0 /* No id */, Ops);
3162 SPIRVInstList.insert(InsertPoint, ZDimDecoInst);
3163 }
3164}
3165
3166void SPIRVProducerPass::GenerateInstForArg(Function &F) {
3167 SPIRVInstructionList &SPIRVInstList = getSPIRVInstList();
3168 ValueMapType &VMap = getValueMap();
3169 Module *Module = F.getParent();
3170 LLVMContext &Context = Module->getContext();
3171 ValueToValueMapTy &ArgGVMap = getArgumentGVMap();
3172
3173 for (Argument &Arg : F.args()) {
3174 if (Arg.use_empty()) {
3175 continue;
3176 }
3177
3178 // Check the type of users of arguments.
3179 bool HasOnlyGEPUse = true;
3180 for (auto *U : Arg.users()) {
3181 if (!isa<GetElementPtrInst>(U) && isa<Instruction>(U)) {
3182 HasOnlyGEPUse = false;
3183 break;
3184 }
3185 }
3186
3187 Type *ArgTy = Arg.getType();
3188
3189 if (PointerType *PTy = dyn_cast<PointerType>(ArgTy)) {
3190 if (StructType *STy = dyn_cast<StructType>(PTy->getElementType())) {
3191 if (STy->isOpaque()) {
3192 // Generate OpLoad for sampler and image types.
3193 if (STy->getName().equals("opencl.sampler_t") ||
3194 STy->getName().equals("opencl.image2d_ro_t") ||
3195 STy->getName().equals("opencl.image2d_wo_t") ||
3196 STy->getName().equals("opencl.image3d_ro_t") ||
3197 STy->getName().equals("opencl.image3d_wo_t")) {
3198 //
3199 // Generate OpLoad.
3200 //
3201 // Ops[0] = Result Type ID
3202 // Ops[1] = Pointer ID
3203 // Ops[2] ... Ops[n] = Optional Memory Access
3204 //
3205 // TODO: Do we need to implement Optional Memory Access???
3206 SPIRVOperandList Ops;
3207
3208 // Use type with address space modified.
3209 ArgTy = ArgGVMap[&Arg]->getType()->getPointerElementType();
3210
3211 uint32_t ResTyID = lookupType(ArgTy);
3212 SPIRVOperand *ResTyIDOp =
3213 new SPIRVOperand(SPIRVOperandType::NUMBERID, ResTyID);
3214 Ops.push_back(ResTyIDOp);
3215
3216 uint32_t PointerID = VMap[&Arg];
3217 SPIRVOperand *PointerIDOp =
3218 new SPIRVOperand(SPIRVOperandType::NUMBERID, PointerID);
3219 Ops.push_back(PointerIDOp);
3220
3221 VMap[&Arg] = nextID;
3222 SPIRVInstruction *Inst =
3223 new SPIRVInstruction(4, spv::OpLoad, nextID++, Ops);
3224 SPIRVInstList.push_back(Inst);
3225 continue;
3226 }
3227 }
3228 }
3229
3230 if (!HasOnlyGEPUse) {
3231 //
3232 // Generate OpAccessChain.
3233 //
3234 // Ops[0] = Result Type ID
3235 // Ops[1] = Base ID
3236 // Ops[2] ... Ops[n] = Indexes ID
3237 SPIRVOperandList Ops;
3238
3239 uint32_t ResTyID = lookupType(ArgTy);
3240 if (!isa<PointerType>(ArgTy)) {
3241 ResTyID = lookupType(PointerType::get(ArgTy, AddressSpace::Global));
3242 }
3243 SPIRVOperand *ResTyOp =
3244 new SPIRVOperand(SPIRVOperandType::NUMBERID, ResTyID);
3245 Ops.push_back(ResTyOp);
3246
3247 uint32_t BaseID = VMap[&Arg];
3248 SPIRVOperand *BaseOp =
3249 new SPIRVOperand(SPIRVOperandType::NUMBERID, BaseID);
3250 Ops.push_back(BaseOp);
3251
3252 Type *IdxTy = Type::getInt32Ty(Context);
3253 uint32_t IndexID = VMap[ConstantInt::get(IdxTy, 0)];
3254 SPIRVOperand *IndexIDOp =
3255 new SPIRVOperand(SPIRVOperandType::NUMBERID, IndexID);
3256 Ops.push_back(IndexIDOp);
3257 Ops.push_back(IndexIDOp);
3258
3259 // Generate SPIRV instruction for argument.
3260 VMap[&Arg] = nextID;
3261 SPIRVInstruction *ArgInst =
3262 new SPIRVInstruction(6, spv::OpAccessChain, nextID++, Ops);
3263 SPIRVInstList.push_back(ArgInst);
3264 } else {
3265 // For GEP uses, generate OpAccessChain with folding GEP ahead of GEP.
3266 // Nothing to do here.
3267 }
3268 } else {
3269 //
3270 // Generate OpAccessChain and OpLoad for non-pointer type argument.
3271 //
3272
3273 //
3274 // Generate OpAccessChain.
3275 //
3276 // Ops[0] = Result Type ID
3277 // Ops[1] = Base ID
3278 // Ops[2] ... Ops[n] = Indexes ID
3279 SPIRVOperandList Ops;
3280
3281 uint32_t ResTyID = lookupType(ArgTy);
3282 if (!isa<PointerType>(ArgTy)) {
3283 ResTyID = lookupType(PointerType::get(ArgTy, AddressSpace::Global));
3284 }
3285 SPIRVOperand *ResTyIDOp =
3286 new SPIRVOperand(SPIRVOperandType::NUMBERID, ResTyID);
3287 Ops.push_back(ResTyIDOp);
3288
3289 uint32_t BaseID = VMap[&Arg];
3290 SPIRVOperand *BaseOp =
3291 new SPIRVOperand(SPIRVOperandType::NUMBERID, BaseID);
3292 Ops.push_back(BaseOp);
3293
3294 Type *IdxTy = Type::getInt32Ty(Context);
3295 uint32_t IndexID = VMap[ConstantInt::get(IdxTy, 0)];
3296 SPIRVOperand *IndexIDOp =
3297 new SPIRVOperand(SPIRVOperandType::NUMBERID, IndexID);
3298 Ops.push_back(IndexIDOp);
3299
3300 // Generate SPIRV instruction for argument.
3301 uint32_t PointerID = nextID;
3302 VMap[&Arg] = nextID;
3303 SPIRVInstruction *ArgInst =
3304 new SPIRVInstruction(5, spv::OpAccessChain, nextID++, Ops);
3305 SPIRVInstList.push_back(ArgInst);
3306
3307 //
3308 // Generate OpLoad.
3309 //
3310
3311 // Ops[0] = Result Type ID
3312 // Ops[1] = Pointer ID
3313 // Ops[2] ... Ops[n] = Optional Memory Access
3314 //
3315 // TODO: Do we need to implement Optional Memory Access???
3316 Ops.clear();
3317
3318 ResTyID = lookupType(ArgTy);
3319 ResTyIDOp = new SPIRVOperand(SPIRVOperandType::NUMBERID, ResTyID);
3320 Ops.push_back(ResTyIDOp);
3321
3322 SPIRVOperand *PointerIDOp =
3323 new SPIRVOperand(SPIRVOperandType::NUMBERID, PointerID);
3324 Ops.push_back(PointerIDOp);
3325
3326 VMap[&Arg] = nextID;
3327 SPIRVInstruction *Inst =
3328 new SPIRVInstruction(4, spv::OpLoad, nextID++, Ops);
3329 SPIRVInstList.push_back(Inst);
3330 }
3331 }
3332}
3333
3334void SPIRVProducerPass::GenerateFuncBody(Function &F) {
3335 SPIRVInstructionList &SPIRVInstList = getSPIRVInstList();
3336 ValueMapType &VMap = getValueMap();
3337
3338 bool IsKernel = false;
3339 if (F.getCallingConv() == CallingConv::SPIR_KERNEL) {
3340 IsKernel = true;
3341 }
3342
3343 for (BasicBlock &BB : F) {
3344 // Register BasicBlock to ValueMap.
3345 VMap[&BB] = nextID;
3346
3347 //
3348 // Generate OpLabel for Basic Block.
3349 //
3350 SPIRVOperandList Ops;
3351 SPIRVInstruction *Inst =
3352 new SPIRVInstruction(2, spv::OpLabel, nextID++, Ops);
3353 SPIRVInstList.push_back(Inst);
3354
David Neto6dcd4712017-06-23 11:06:47 -04003355 // OpVariable instructions must come first.
3356 for (Instruction &I : BB) {
3357 if (isa<AllocaInst>(I)) {
3358 GenerateInstruction(I);
3359 }
3360 }
3361
David Neto22f144c2017-06-12 14:26:21 -04003362 if (&BB == &F.getEntryBlock() && IsKernel) {
3363 GenerateInstForArg(F);
3364 }
3365
3366 for (Instruction &I : BB) {
David Neto6dcd4712017-06-23 11:06:47 -04003367 if (!isa<AllocaInst>(I)) {
3368 GenerateInstruction(I);
3369 }
David Neto22f144c2017-06-12 14:26:21 -04003370 }
3371 }
3372}
3373
3374spv::Op SPIRVProducerPass::GetSPIRVCmpOpcode(CmpInst *I) {
3375 const std::map<CmpInst::Predicate, spv::Op> Map = {
3376 {CmpInst::ICMP_EQ, spv::OpIEqual},
3377 {CmpInst::ICMP_NE, spv::OpINotEqual},
3378 {CmpInst::ICMP_UGT, spv::OpUGreaterThan},
3379 {CmpInst::ICMP_UGE, spv::OpUGreaterThanEqual},
3380 {CmpInst::ICMP_ULT, spv::OpULessThan},
3381 {CmpInst::ICMP_ULE, spv::OpULessThanEqual},
3382 {CmpInst::ICMP_SGT, spv::OpSGreaterThan},
3383 {CmpInst::ICMP_SGE, spv::OpSGreaterThanEqual},
3384 {CmpInst::ICMP_SLT, spv::OpSLessThan},
3385 {CmpInst::ICMP_SLE, spv::OpSLessThanEqual},
3386 {CmpInst::FCMP_OEQ, spv::OpFOrdEqual},
3387 {CmpInst::FCMP_OGT, spv::OpFOrdGreaterThan},
3388 {CmpInst::FCMP_OGE, spv::OpFOrdGreaterThanEqual},
3389 {CmpInst::FCMP_OLT, spv::OpFOrdLessThan},
3390 {CmpInst::FCMP_OLE, spv::OpFOrdLessThanEqual},
3391 {CmpInst::FCMP_ONE, spv::OpFOrdNotEqual},
3392 {CmpInst::FCMP_UEQ, spv::OpFUnordEqual},
3393 {CmpInst::FCMP_UGT, spv::OpFUnordGreaterThan},
3394 {CmpInst::FCMP_UGE, spv::OpFUnordGreaterThanEqual},
3395 {CmpInst::FCMP_ULT, spv::OpFUnordLessThan},
3396 {CmpInst::FCMP_ULE, spv::OpFUnordLessThanEqual},
3397 {CmpInst::FCMP_UNE, spv::OpFUnordNotEqual}};
3398
3399 assert(0 != Map.count(I->getPredicate()));
3400
3401 return Map.at(I->getPredicate());
3402}
3403
3404spv::Op SPIRVProducerPass::GetSPIRVCastOpcode(Instruction &I) {
3405 const std::map<unsigned, spv::Op> Map{
3406 {Instruction::Trunc, spv::OpUConvert},
3407 {Instruction::ZExt, spv::OpUConvert},
3408 {Instruction::SExt, spv::OpSConvert},
3409 {Instruction::FPToUI, spv::OpConvertFToU},
3410 {Instruction::FPToSI, spv::OpConvertFToS},
3411 {Instruction::UIToFP, spv::OpConvertUToF},
3412 {Instruction::SIToFP, spv::OpConvertSToF},
3413 {Instruction::FPTrunc, spv::OpFConvert},
3414 {Instruction::FPExt, spv::OpFConvert},
3415 {Instruction::BitCast, spv::OpBitcast}};
3416
3417 assert(0 != Map.count(I.getOpcode()));
3418
3419 return Map.at(I.getOpcode());
3420}
3421
3422spv::Op SPIRVProducerPass::GetSPIRVBinaryOpcode(Instruction &I) {
3423 if (I.getType()->isIntegerTy(1)) {
3424 switch (I.getOpcode()) {
3425 default:
3426 break;
3427 case Instruction::Or:
3428 return spv::OpLogicalOr;
3429 case Instruction::And:
3430 return spv::OpLogicalAnd;
3431 case Instruction::Xor:
3432 return spv::OpLogicalNotEqual;
3433 }
3434 }
3435
3436 const std::map<unsigned, spv::Op> Map {
3437 {Instruction::Add, spv::OpIAdd},
3438 {Instruction::FAdd, spv::OpFAdd},
3439 {Instruction::Sub, spv::OpISub},
3440 {Instruction::FSub, spv::OpFSub},
3441 {Instruction::Mul, spv::OpIMul},
3442 {Instruction::FMul, spv::OpFMul},
3443 {Instruction::UDiv, spv::OpUDiv},
3444 {Instruction::SDiv, spv::OpSDiv},
3445 {Instruction::FDiv, spv::OpFDiv},
3446 {Instruction::URem, spv::OpUMod},
3447 {Instruction::SRem, spv::OpSRem},
3448 {Instruction::FRem, spv::OpFRem},
3449 {Instruction::Or, spv::OpBitwiseOr},
3450 {Instruction::Xor, spv::OpBitwiseXor},
3451 {Instruction::And, spv::OpBitwiseAnd},
3452 {Instruction::Shl, spv::OpShiftLeftLogical},
3453 {Instruction::LShr, spv::OpShiftRightLogical},
3454 {Instruction::AShr, spv::OpShiftRightArithmetic}};
3455
3456 assert(0 != Map.count(I.getOpcode()));
3457
3458 return Map.at(I.getOpcode());
3459}
3460
3461void SPIRVProducerPass::GenerateInstruction(Instruction &I) {
3462 SPIRVInstructionList &SPIRVInstList = getSPIRVInstList();
3463 ValueMapType &VMap = getValueMap();
3464 ValueToValueMapTy &ArgGVMap = getArgumentGVMap();
3465 ValueMapType &ArgGVIDMap = getArgumentGVIDMap();
3466 DeferredInstVecType &DeferredInsts = getDeferredInstVec();
3467 LLVMContext &Context = I.getParent()->getParent()->getParent()->getContext();
3468
3469 // Register Instruction to ValueMap.
3470 if (0 == VMap[&I]) {
3471 VMap[&I] = nextID;
3472 }
3473
3474 switch (I.getOpcode()) {
3475 default: {
3476 if (Instruction::isCast(I.getOpcode())) {
3477 //
3478 // Generate SPIRV instructions for cast operators.
3479 //
3480
David Netod2de94a2017-08-28 17:27:47 -04003481
3482 auto Ty = I.getType();
David Neto22f144c2017-06-12 14:26:21 -04003483 auto OpTy = I.getOperand(0)->getType();
David Netod2de94a2017-08-28 17:27:47 -04003484 auto toI8 = Ty == Type::getInt8Ty(Context);
3485 auto fromI32 = OpTy == Type::getInt32Ty(Context);
David Neto22f144c2017-06-12 14:26:21 -04003486 // Handle zext, sext and uitofp with i1 type specially.
3487 if ((I.getOpcode() == Instruction::ZExt ||
3488 I.getOpcode() == Instruction::SExt ||
3489 I.getOpcode() == Instruction::UIToFP) &&
3490 (OpTy->isIntegerTy(1) ||
3491 (OpTy->isVectorTy() &&
3492 OpTy->getVectorElementType()->isIntegerTy(1)))) {
3493 //
3494 // Generate OpSelect.
3495 //
3496
3497 // Ops[0] = Result Type ID
3498 // Ops[1] = Condition ID
3499 // Ops[2] = True Constant ID
3500 // Ops[3] = False Constant ID
3501 SPIRVOperandList Ops;
3502
3503 uint32_t ResTyID = lookupType(I.getType());
3504 SPIRVOperand *ResTyIDOp =
3505 new SPIRVOperand(SPIRVOperandType::NUMBERID, ResTyID);
3506 Ops.push_back(ResTyIDOp);
3507
3508 // TODO: zext's first operand should be compare instructions???
3509 uint32_t CondID = VMap[I.getOperand(0)];
3510 SPIRVOperand *CondIDOp =
3511 new SPIRVOperand(SPIRVOperandType::NUMBERID, CondID);
3512 Ops.push_back(CondIDOp);
3513
3514 uint32_t TrueID = 0;
3515 if (I.getOpcode() == Instruction::ZExt) {
3516 APInt One(32, 1);
3517 TrueID = VMap[Constant::getIntegerValue(I.getType(), One)];
3518 } else if (I.getOpcode() == Instruction::SExt) {
3519 APInt MinusOne(32, UINT64_MAX, true);
3520 TrueID = VMap[Constant::getIntegerValue(I.getType(), MinusOne)];
3521 } else {
3522 TrueID = VMap[ConstantFP::get(Context, APFloat(1.0f))];
3523 }
3524 SPIRVOperand *TrueIDOp =
3525 new SPIRVOperand(SPIRVOperandType::NUMBERID, TrueID);
3526 Ops.push_back(TrueIDOp);
3527
3528 uint32_t FalseID = 0;
3529 if (I.getOpcode() == Instruction::ZExt) {
3530 FalseID = VMap[Constant::getNullValue(I.getType())];
3531 } else if (I.getOpcode() == Instruction::SExt) {
3532 FalseID = VMap[Constant::getNullValue(I.getType())];
3533 } else {
3534 FalseID = VMap[ConstantFP::get(Context, APFloat(0.0f))];
3535 }
3536 SPIRVOperand *FalseIDOp =
3537 new SPIRVOperand(SPIRVOperandType::NUMBERID, FalseID);
3538 Ops.push_back(FalseIDOp);
3539
3540 SPIRVInstruction *Inst =
3541 new SPIRVInstruction(6, spv::OpSelect, nextID++, Ops);
3542 SPIRVInstList.push_back(Inst);
David Netod2de94a2017-08-28 17:27:47 -04003543 } else if (I.getOpcode() == Instruction::Trunc && fromI32 && toI8) {
3544 // The SPIR-V target type is a 32-bit int. Keep only the bottom
3545 // 8 bits.
3546 // Before:
3547 // %result = trunc i32 %a to i8
3548 // After
3549 // %result = OpBitwiseAnd %uint %a %uint_255
3550
3551 SPIRVOperandList Ops;
3552
3553 uint32_t ResTyID = lookupType(OpTy);
3554 SPIRVOperand *ResTyIDOp =
3555 new SPIRVOperand(SPIRVOperandType::NUMBERID, ResTyID);
3556 Ops.push_back(ResTyIDOp);
3557
3558 uint32_t Op0ID = VMap[I.getOperand(0)];
3559 SPIRVOperand *Op0IDOp =
3560 new SPIRVOperand(SPIRVOperandType::NUMBERID, Op0ID);
3561 Ops.push_back(Op0IDOp);
3562
3563 Type *UintTy = Type::getInt32Ty(Context);
3564 uint32_t MaskID = VMap[ConstantInt::get(UintTy, 255)];
3565 SPIRVOperand *MaskOp =
3566 new SPIRVOperand(SPIRVOperandType::NUMBERID, MaskID);
3567 Ops.push_back(MaskOp);
3568
3569 SPIRVInstruction *Inst =
3570 new SPIRVInstruction(5, spv::OpBitwiseAnd, nextID++, Ops);
3571 SPIRVInstList.push_back(Inst);
David Neto22f144c2017-06-12 14:26:21 -04003572 } else {
3573 // Ops[0] = Result Type ID
3574 // Ops[1] = Source Value ID
3575 SPIRVOperandList Ops;
3576
3577 uint32_t ResTyID = lookupType(I.getType());
3578 SPIRVOperand *ResTyIDOp =
3579 new SPIRVOperand(SPIRVOperandType::NUMBERID, ResTyID);
3580 Ops.push_back(ResTyIDOp);
3581
3582 uint32_t SrcID = VMap[I.getOperand(0)];
3583 SPIRVOperand *SrcIDOp =
3584 new SPIRVOperand(SPIRVOperandType::NUMBERID, SrcID);
3585 Ops.push_back(SrcIDOp);
3586
3587 SPIRVInstruction *Inst =
3588 new SPIRVInstruction(4, GetSPIRVCastOpcode(I), nextID++, Ops);
3589 SPIRVInstList.push_back(Inst);
3590 }
3591 } else if (isa<BinaryOperator>(I)) {
3592 //
3593 // Generate SPIRV instructions for binary operators.
3594 //
3595
3596 // Handle xor with i1 type specially.
3597 if (I.getOpcode() == Instruction::Xor &&
3598 I.getType() == Type::getInt1Ty(Context) &&
3599 (isa<Constant>(I.getOperand(0)) || isa<Constant>(I.getOperand(1)))) {
3600 //
3601 // Generate OpLogicalNot.
3602 //
3603 // Ops[0] = Result Type ID
3604 // Ops[1] = Operand
3605 SPIRVOperandList Ops;
3606
3607 uint32_t ResTyID = lookupType(I.getType());
3608 SPIRVOperand *ResTyIDOp =
3609 new SPIRVOperand(SPIRVOperandType::NUMBERID, ResTyID);
3610 Ops.push_back(ResTyIDOp);
3611
3612 Value *CondV = I.getOperand(0);
3613 if (isa<Constant>(I.getOperand(0))) {
3614 CondV = I.getOperand(1);
3615 }
3616 uint32_t CondID = VMap[CondV];
3617 SPIRVOperand *CondIDOp =
3618 new SPIRVOperand(SPIRVOperandType::NUMBERID, CondID);
3619 Ops.push_back(CondIDOp);
3620
3621 SPIRVInstruction *Inst =
3622 new SPIRVInstruction(4, spv::OpLogicalNot, nextID++, Ops);
3623 SPIRVInstList.push_back(Inst);
3624 } else {
3625 // Ops[0] = Result Type ID
3626 // Ops[1] = Operand 0
3627 // Ops[2] = Operand 1
3628 SPIRVOperandList Ops;
3629
3630 uint32_t ResTyID = lookupType(I.getType());
3631 SPIRVOperand *ResTyIDOp =
3632 new SPIRVOperand(SPIRVOperandType::NUMBERID, ResTyID);
3633 Ops.push_back(ResTyIDOp);
3634
3635 uint32_t Op0ID = VMap[I.getOperand(0)];
3636 SPIRVOperand *Op0IDOp =
3637 new SPIRVOperand(SPIRVOperandType::NUMBERID, Op0ID);
3638 Ops.push_back(Op0IDOp);
3639
3640 uint32_t Op1ID = VMap[I.getOperand(1)];
3641 SPIRVOperand *Op1IDOp =
3642 new SPIRVOperand(SPIRVOperandType::NUMBERID, Op1ID);
3643 Ops.push_back(Op1IDOp);
3644
3645 SPIRVInstruction *Inst =
3646 new SPIRVInstruction(5, GetSPIRVBinaryOpcode(I), nextID++, Ops);
3647 SPIRVInstList.push_back(Inst);
3648 }
3649 } else {
3650 I.print(errs());
3651 llvm_unreachable("Unsupported instruction???");
3652 }
3653 break;
3654 }
3655 case Instruction::GetElementPtr: {
3656 auto &GlobalConstArgSet = getGlobalConstArgSet();
3657
3658 //
3659 // Generate OpAccessChain.
3660 //
3661 GetElementPtrInst *GEP = cast<GetElementPtrInst>(&I);
3662
3663 //
3664 // Generate OpAccessChain.
3665 //
3666
3667 // Ops[0] = Result Type ID
3668 // Ops[1] = Base ID
3669 // Ops[2] ... Ops[n] = Indexes ID
3670 SPIRVOperandList Ops;
3671
David Neto1a1a0582017-07-07 12:01:44 -04003672 PointerType* ResultType = cast<PointerType>(GEP->getType());
David Neto22f144c2017-06-12 14:26:21 -04003673 if (GEP->getPointerAddressSpace() == AddressSpace::ModuleScopePrivate ||
3674 GlobalConstArgSet.count(GEP->getPointerOperand())) {
3675 // Use pointer type with private address space for global constant.
3676 Type *EleTy = I.getType()->getPointerElementType();
David Neto1a1a0582017-07-07 12:01:44 -04003677 ResultType = PointerType::get(EleTy, AddressSpace::ModuleScopePrivate);
David Neto22f144c2017-06-12 14:26:21 -04003678 }
David Neto1a1a0582017-07-07 12:01:44 -04003679 const uint32_t ResTyID = lookupType(ResultType);
David Neto22f144c2017-06-12 14:26:21 -04003680 SPIRVOperand *ResTyIDOp =
3681 new SPIRVOperand(SPIRVOperandType::NUMBERID, ResTyID);
3682 Ops.push_back(ResTyIDOp);
3683
3684 // Check whether GEP's pointer operand is pointer argument.
3685 bool HasArgBasePointer = false;
3686 for (auto ArgGV : ArgGVMap) {
3687 if (ArgGV.first == GEP->getPointerOperand()) {
3688 if (isa<PointerType>(ArgGV.first->getType())) {
3689 HasArgBasePointer = true;
3690 } else {
3691 llvm_unreachable(
3692 "GEP's pointer operand is argument of non-poninter type???");
3693 }
3694 }
3695 }
3696
3697 uint32_t BaseID;
3698 if (HasArgBasePointer) {
3699 // Point to global variable for argument directly.
3700 BaseID = ArgGVIDMap[GEP->getPointerOperand()];
3701 } else {
3702 BaseID = VMap[GEP->getPointerOperand()];
3703 }
3704
3705 SPIRVOperand *BaseIDOp =
3706 new SPIRVOperand(SPIRVOperandType::NUMBERID, BaseID);
3707 Ops.push_back(BaseIDOp);
3708
3709 uint16_t WordCount = 4;
3710
3711 if (HasArgBasePointer) {
3712 // If GEP's pointer operand is argument, add one more index for struct
3713 // type to wrap up argument type.
3714 Type *IdxTy = Type::getInt32Ty(Context);
3715 uint32_t IndexID = VMap[ConstantInt::get(IdxTy, 0)];
3716 SPIRVOperand *IndexIDOp =
3717 new SPIRVOperand(SPIRVOperandType::NUMBERID, IndexID);
3718 Ops.push_back(IndexIDOp);
3719
3720 WordCount++;
3721 }
3722
3723 //
3724 // Follows below rules for gep.
3725 //
3726 // 1. If gep's first index is 0 and gep's base is not kernel function's
3727 // argument, generate OpAccessChain and ignore gep's first index.
3728 // 2. If gep's first index is not 0, generate OpPtrAccessChain and use gep's
3729 // first index.
3730 // 3. If gep's first index is not constant, generate OpPtrAccessChain and
3731 // use gep's first index.
3732 // 4. If it is not above case 1, 2 and 3, generate OpAccessChain and use
3733 // gep's first index.
3734 //
3735 spv::Op Opcode = spv::OpAccessChain;
3736 unsigned offset = 0;
3737 if (ConstantInt *CstInt = dyn_cast<ConstantInt>(GEP->getOperand(1))) {
3738 if (CstInt->getZExtValue() == 0 && !HasArgBasePointer) {
3739 offset = 1;
3740 } else if (CstInt->getZExtValue() != 0 && !HasArgBasePointer) {
3741 Opcode = spv::OpPtrAccessChain;
David Neto22f144c2017-06-12 14:26:21 -04003742 }
3743 } else if (!HasArgBasePointer) {
3744 Opcode = spv::OpPtrAccessChain;
David Neto1a1a0582017-07-07 12:01:44 -04003745 }
3746
3747 if (Opcode == spv::OpPtrAccessChain) {
David Neto22f144c2017-06-12 14:26:21 -04003748 setVariablePointers(true);
David Neto1a1a0582017-07-07 12:01:44 -04003749 // Do we need to generate ArrayStride? Check against the GEP result type
3750 // rather than the pointer type of the base because when indexing into
3751 // an OpenCL program-scope constant, we'll swap out the LLVM base pointer
3752 // for something else in the SPIR-V.
3753 // E.g. see test/PointerAccessChain/pointer_index_is_constant_1.cl
3754 if (GetStorageClass(ResultType->getAddressSpace()) ==
3755 spv::StorageClassStorageBuffer) {
3756 // Save the need to generate an ArrayStride decoration. But defer
3757 // generation until later, so we only make one decoration.
3758 getPointerTypesNeedingArrayStride().insert(ResultType);
3759 }
David Neto22f144c2017-06-12 14:26:21 -04003760 }
3761
3762 for (auto II = GEP->idx_begin() + offset; II != GEP->idx_end(); II++) {
3763 uint32_t IndexID = VMap[*II];
3764 SPIRVOperand *IndexIDOp =
3765 new SPIRVOperand(SPIRVOperandType::NUMBERID, IndexID);
3766 Ops.push_back(IndexIDOp);
3767
3768 WordCount++;
3769 }
3770
3771 SPIRVInstruction *Inst =
3772 new SPIRVInstruction(WordCount, Opcode, nextID++, Ops);
3773 SPIRVInstList.push_back(Inst);
3774 break;
3775 }
3776 case Instruction::ExtractValue: {
3777 ExtractValueInst *EVI = cast<ExtractValueInst>(&I);
3778 // Ops[0] = Result Type ID
3779 // Ops[1] = Composite ID
3780 // Ops[2] ... Ops[n] = Indexes (Literal Number)
3781 SPIRVOperandList Ops;
3782
3783 uint32_t ResTyID = lookupType(I.getType());
3784 SPIRVOperand *ResTyIDOp =
3785 new SPIRVOperand(SPIRVOperandType::NUMBERID, ResTyID);
3786 Ops.push_back(ResTyIDOp);
3787
3788 uint32_t CompositeID = VMap[EVI->getAggregateOperand()];
3789 SPIRVOperand *CompositeIDOp =
3790 new SPIRVOperand(SPIRVOperandType::NUMBERID, CompositeID);
3791 Ops.push_back(CompositeIDOp);
3792
3793 for (auto &Index : EVI->indices()) {
3794 Ops.push_back(new SPIRVOperand(SPIRVOperandType::LITERAL_INTEGER, Index));
3795 }
3796
3797 uint16_t WordCount = static_cast<uint16_t>(2 + Ops.size());
3798 SPIRVInstruction *Inst =
3799 new SPIRVInstruction(WordCount, spv::OpCompositeExtract, nextID++, Ops);
3800 SPIRVInstList.push_back(Inst);
3801 break;
3802 }
3803 case Instruction::InsertValue: {
3804 InsertValueInst *IVI = cast<InsertValueInst>(&I);
3805 // Ops[0] = Result Type ID
3806 // Ops[1] = Object ID
3807 // Ops[2] = Composite ID
3808 // Ops[3] ... Ops[n] = Indexes (Literal Number)
3809 SPIRVOperandList Ops;
3810
3811 uint32_t ResTyID = lookupType(I.getType());
3812 Ops.push_back(new SPIRVOperand(SPIRVOperandType::NUMBERID, ResTyID));
3813
3814 uint32_t ObjectID = VMap[IVI->getInsertedValueOperand()];
3815 Ops.push_back(new SPIRVOperand(SPIRVOperandType::NUMBERID, ObjectID));
3816
3817 uint32_t CompositeID = VMap[IVI->getAggregateOperand()];
3818 Ops.push_back(new SPIRVOperand(SPIRVOperandType::NUMBERID, CompositeID));
3819
3820 for (auto &Index : IVI->indices()) {
3821 Ops.push_back(new SPIRVOperand(SPIRVOperandType::LITERAL_INTEGER, Index));
3822 }
3823
3824 uint16_t WordCount = static_cast<uint16_t>(2 + Ops.size());
3825 SPIRVInstruction *Inst =
3826 new SPIRVInstruction(WordCount, spv::OpCompositeInsert, nextID++, Ops);
3827 SPIRVInstList.push_back(Inst);
3828 break;
3829 }
3830 case Instruction::Select: {
3831 //
3832 // Generate OpSelect.
3833 //
3834
3835 // Ops[0] = Result Type ID
3836 // Ops[1] = Condition ID
3837 // Ops[2] = True Constant ID
3838 // Ops[3] = False Constant ID
3839 SPIRVOperandList Ops;
3840
3841 // Find SPIRV instruction for parameter type.
3842 auto Ty = I.getType();
3843 if (Ty->isPointerTy()) {
3844 auto PointeeTy = Ty->getPointerElementType();
3845 if (PointeeTy->isStructTy() &&
3846 dyn_cast<StructType>(PointeeTy)->isOpaque()) {
3847 Ty = PointeeTy;
3848 }
3849 }
3850
3851 uint32_t ResTyID = lookupType(Ty);
3852 SPIRVOperand *ResTyIDOp =
3853 new SPIRVOperand(SPIRVOperandType::NUMBERID, ResTyID);
3854 Ops.push_back(ResTyIDOp);
3855
3856 uint32_t CondID = VMap[I.getOperand(0)];
3857 SPIRVOperand *CondIDOp =
3858 new SPIRVOperand(SPIRVOperandType::NUMBERID, CondID);
3859 Ops.push_back(CondIDOp);
3860
3861 uint32_t TrueID = VMap[I.getOperand(1)];
3862 SPIRVOperand *TrueIDOp =
3863 new SPIRVOperand(SPIRVOperandType::NUMBERID, TrueID);
3864 Ops.push_back(TrueIDOp);
3865
3866 uint32_t FalseID = VMap[I.getOperand(2)];
3867 SPIRVOperand *FalseIDOp =
3868 new SPIRVOperand(SPIRVOperandType::NUMBERID, FalseID);
3869 Ops.push_back(FalseIDOp);
3870
3871 SPIRVInstruction *Inst =
3872 new SPIRVInstruction(6, spv::OpSelect, nextID++, Ops);
3873 SPIRVInstList.push_back(Inst);
3874 break;
3875 }
3876 case Instruction::ExtractElement: {
3877 // Handle <4 x i8> type manually.
3878 Type *CompositeTy = I.getOperand(0)->getType();
3879 if (is4xi8vec(CompositeTy)) {
3880 //
3881 // Generate OpShiftRightLogical and OpBitwiseAnd for extractelement with
3882 // <4 x i8>.
3883 //
3884
3885 //
3886 // Generate OpShiftRightLogical
3887 //
3888 // Ops[0] = Result Type ID
3889 // Ops[1] = Operand 0
3890 // Ops[2] = Operand 1
3891 //
3892 SPIRVOperandList Ops;
3893
3894 uint32_t ResTyID = lookupType(CompositeTy);
3895 SPIRVOperand *ResTyIDOp =
3896 new SPIRVOperand(SPIRVOperandType::NUMBERID, ResTyID);
3897 Ops.push_back(ResTyIDOp);
3898
3899 uint32_t Op0ID = VMap[I.getOperand(0)];
3900 SPIRVOperand *Op0IDOp =
3901 new SPIRVOperand(SPIRVOperandType::NUMBERID, Op0ID);
3902 Ops.push_back(Op0IDOp);
3903
3904 uint32_t Op1ID = 0;
3905 if (ConstantInt *CI = dyn_cast<ConstantInt>(I.getOperand(1))) {
3906 // Handle constant index.
3907 uint64_t Idx = CI->getZExtValue();
3908 Value *ShiftAmount =
3909 ConstantInt::get(Type::getInt32Ty(Context), Idx * 8);
3910 Op1ID = VMap[ShiftAmount];
3911 } else {
3912 // Handle variable index.
3913 SPIRVOperandList TmpOps;
3914
3915 uint32_t TmpResTyID = lookupType(Type::getInt32Ty(Context));
3916 SPIRVOperand *TmpResTyIDOp =
3917 new SPIRVOperand(SPIRVOperandType::NUMBERID, TmpResTyID);
3918 TmpOps.push_back(TmpResTyIDOp);
3919
3920 uint32_t IdxID = VMap[I.getOperand(1)];
3921 SPIRVOperand *TmpOp0IDOp =
3922 new SPIRVOperand(SPIRVOperandType::NUMBERID, IdxID);
3923 TmpOps.push_back(TmpOp0IDOp);
3924
3925 ConstantInt *Cst8 = ConstantInt::get(Type::getInt32Ty(Context), 8);
3926 uint32_t Cst8ID = VMap[Cst8];
3927 SPIRVOperand *TmpOp1IDOp =
3928 new SPIRVOperand(SPIRVOperandType::NUMBERID, Cst8ID);
3929 TmpOps.push_back(TmpOp1IDOp);
3930
3931 Op1ID = nextID;
3932
3933 SPIRVInstruction *TmpInst =
3934 new SPIRVInstruction(5, spv::OpIMul, nextID++, TmpOps);
3935 SPIRVInstList.push_back(TmpInst);
3936 }
3937 SPIRVOperand *Op1IDOp =
3938 new SPIRVOperand(SPIRVOperandType::NUMBERID, Op1ID);
3939 Ops.push_back(Op1IDOp);
3940
3941 uint32_t ShiftID = nextID;
3942
3943 SPIRVInstruction *Inst =
3944 new SPIRVInstruction(5, spv::OpShiftRightLogical, nextID++, Ops);
3945 SPIRVInstList.push_back(Inst);
3946
3947 //
3948 // Generate OpBitwiseAnd
3949 //
3950 // Ops[0] = Result Type ID
3951 // Ops[1] = Operand 0
3952 // Ops[2] = Operand 1
3953 //
3954 Ops.clear();
3955
3956 ResTyID = lookupType(CompositeTy);
3957 ResTyIDOp = new SPIRVOperand(SPIRVOperandType::NUMBERID, ResTyID);
3958 Ops.push_back(ResTyIDOp);
3959
3960 Op0ID = ShiftID;
3961 Op0IDOp = new SPIRVOperand(SPIRVOperandType::NUMBERID, Op0ID);
3962 Ops.push_back(Op0IDOp);
3963
3964 Constant *CstFF = ConstantInt::get(Type::getInt32Ty(Context), 0xFF);
3965 Op1ID = VMap[CstFF];
3966 Op1IDOp = new SPIRVOperand(SPIRVOperandType::NUMBERID, Op1ID);
3967 Ops.push_back(Op1IDOp);
3968
David Neto9b2d6252017-09-06 15:47:37 -04003969 // Reset mapping for this value to the result of the bitwise and.
3970 VMap[&I] = nextID;
3971
David Neto22f144c2017-06-12 14:26:21 -04003972 Inst = new SPIRVInstruction(5, spv::OpBitwiseAnd, nextID++, Ops);
3973 SPIRVInstList.push_back(Inst);
3974 break;
3975 }
3976
3977 // Ops[0] = Result Type ID
3978 // Ops[1] = Composite ID
3979 // Ops[2] ... Ops[n] = Indexes (Literal Number)
3980 SPIRVOperandList Ops;
3981
3982 uint32_t ResTyID = lookupType(I.getType());
3983 SPIRVOperand *ResTyIDOp =
3984 new SPIRVOperand(SPIRVOperandType::NUMBERID, ResTyID);
3985 Ops.push_back(ResTyIDOp);
3986
3987 uint32_t CompositeID = VMap[I.getOperand(0)];
3988 SPIRVOperand *CompositeIDOp =
3989 new SPIRVOperand(SPIRVOperandType::NUMBERID, CompositeID);
3990 Ops.push_back(CompositeIDOp);
3991
3992 spv::Op Opcode = spv::OpCompositeExtract;
3993 if (const ConstantInt *CI = dyn_cast<ConstantInt>(I.getOperand(1))) {
3994 std::vector<uint32_t> LiteralNum;
3995 assert(CI->getZExtValue() < UINT32_MAX);
3996 LiteralNum.push_back(static_cast<uint32_t>(CI->getZExtValue()));
3997 SPIRVOperand *Indexes =
3998 new SPIRVOperand(SPIRVOperandType::LITERAL_INTEGER, LiteralNum);
3999 Ops.push_back(Indexes);
4000 } else {
4001 uint32_t IndexID = VMap[I.getOperand(1)];
4002 SPIRVOperand *IndexIDOp =
4003 new SPIRVOperand(SPIRVOperandType::NUMBERID, IndexID);
4004 Ops.push_back(IndexIDOp);
4005 Opcode = spv::OpVectorExtractDynamic;
4006 }
4007
4008 uint16_t WordCount = 5;
4009 SPIRVInstruction *Inst =
4010 new SPIRVInstruction(WordCount, Opcode, nextID++, Ops);
4011 SPIRVInstList.push_back(Inst);
4012 break;
4013 }
4014 case Instruction::InsertElement: {
4015 // Handle <4 x i8> type manually.
4016 Type *CompositeTy = I.getOperand(0)->getType();
4017 if (is4xi8vec(CompositeTy)) {
4018 Constant *CstFF = ConstantInt::get(Type::getInt32Ty(Context), 0xFF);
4019 uint32_t CstFFID = VMap[CstFF];
4020
4021 uint32_t ShiftAmountID = 0;
4022 if (ConstantInt *CI = dyn_cast<ConstantInt>(I.getOperand(2))) {
4023 // Handle constant index.
4024 uint64_t Idx = CI->getZExtValue();
4025 Value *ShiftAmount =
4026 ConstantInt::get(Type::getInt32Ty(Context), Idx * 8);
4027 ShiftAmountID = VMap[ShiftAmount];
4028 } else {
4029 // Handle variable index.
4030 SPIRVOperandList TmpOps;
4031
4032 uint32_t TmpResTyID = lookupType(Type::getInt32Ty(Context));
4033 SPIRVOperand *TmpResTyIDOp =
4034 new SPIRVOperand(SPIRVOperandType::NUMBERID, TmpResTyID);
4035 TmpOps.push_back(TmpResTyIDOp);
4036
4037 uint32_t IdxID = VMap[I.getOperand(2)];
4038 SPIRVOperand *TmpOp0IDOp =
4039 new SPIRVOperand(SPIRVOperandType::NUMBERID, IdxID);
4040 TmpOps.push_back(TmpOp0IDOp);
4041
4042 ConstantInt *Cst8 = ConstantInt::get(Type::getInt32Ty(Context), 8);
4043 uint32_t Cst8ID = VMap[Cst8];
4044 SPIRVOperand *TmpOp1IDOp =
4045 new SPIRVOperand(SPIRVOperandType::NUMBERID, Cst8ID);
4046 TmpOps.push_back(TmpOp1IDOp);
4047
4048 ShiftAmountID = nextID;
4049
4050 SPIRVInstruction *TmpInst =
4051 new SPIRVInstruction(5, spv::OpIMul, nextID++, TmpOps);
4052 SPIRVInstList.push_back(TmpInst);
4053 }
4054
4055 //
4056 // Generate mask operations.
4057 //
4058
4059 // ShiftLeft mask according to index of insertelement.
4060 SPIRVOperandList Ops;
4061
4062 uint32_t ResTyID = lookupType(CompositeTy);
4063 SPIRVOperand *ResTyIDOp =
4064 new SPIRVOperand(SPIRVOperandType::NUMBERID, ResTyID);
4065 Ops.push_back(ResTyIDOp);
4066
4067 uint32_t Op0ID = CstFFID;
4068 SPIRVOperand *Op0IDOp =
4069 new SPIRVOperand(SPIRVOperandType::NUMBERID, Op0ID);
4070 Ops.push_back(Op0IDOp);
4071
4072 uint32_t Op1ID = ShiftAmountID;
4073 SPIRVOperand *Op1IDOp =
4074 new SPIRVOperand(SPIRVOperandType::NUMBERID, Op1ID);
4075 Ops.push_back(Op1IDOp);
4076
4077 uint32_t MaskID = nextID;
4078
4079 SPIRVInstruction *Inst =
4080 new SPIRVInstruction(5, spv::OpShiftLeftLogical, nextID++, Ops);
4081 SPIRVInstList.push_back(Inst);
4082
4083 // Inverse mask.
4084 Ops.clear();
4085
4086 Ops.push_back(ResTyIDOp);
4087
4088 Op0ID = MaskID;
4089 Op0IDOp = new SPIRVOperand(SPIRVOperandType::NUMBERID, Op0ID);
4090 Ops.push_back(Op0IDOp);
4091
4092 uint32_t InvMaskID = nextID;
4093
David Netoa394f392017-08-26 20:45:29 -04004094 Inst = new SPIRVInstruction(4, spv::OpNot, nextID++, Ops);
David Neto22f144c2017-06-12 14:26:21 -04004095 SPIRVInstList.push_back(Inst);
4096
4097 // Apply mask.
4098 Ops.clear();
4099
4100 Ops.push_back(ResTyIDOp);
4101
4102 Op0ID = VMap[I.getOperand(0)];
4103 Op0IDOp = new SPIRVOperand(SPIRVOperandType::NUMBERID, Op0ID);
4104 Ops.push_back(Op0IDOp);
4105
4106 Op1ID = InvMaskID;
4107 Op1IDOp = new SPIRVOperand(SPIRVOperandType::NUMBERID, Op1ID);
4108 Ops.push_back(Op1IDOp);
4109
4110 uint32_t OrgValID = nextID;
4111
4112 Inst = new SPIRVInstruction(5, spv::OpBitwiseAnd, nextID++, Ops);
4113 SPIRVInstList.push_back(Inst);
4114
4115 // Create correct value according to index of insertelement.
4116 Ops.clear();
4117
4118 Ops.push_back(ResTyIDOp);
4119
4120 Op0ID = VMap[I.getOperand(1)];
4121 Op0IDOp = new SPIRVOperand(SPIRVOperandType::NUMBERID, Op0ID);
4122 Ops.push_back(Op0IDOp);
4123
4124 Op1ID = ShiftAmountID;
4125 Op1IDOp = new SPIRVOperand(SPIRVOperandType::NUMBERID, Op1ID);
4126 Ops.push_back(Op1IDOp);
4127
4128 uint32_t InsertValID = nextID;
4129
4130 Inst = new SPIRVInstruction(5, spv::OpShiftLeftLogical, nextID++, Ops);
4131 SPIRVInstList.push_back(Inst);
4132
4133 // Insert value to original value.
4134 Ops.clear();
4135
4136 Ops.push_back(ResTyIDOp);
4137
4138 Op0ID = OrgValID;
4139 Op0IDOp = new SPIRVOperand(SPIRVOperandType::NUMBERID, Op0ID);
4140 Ops.push_back(Op0IDOp);
4141
4142 Op1ID = InsertValID;
4143 Op1IDOp = new SPIRVOperand(SPIRVOperandType::NUMBERID, Op1ID);
4144 Ops.push_back(Op1IDOp);
4145
David Netoa394f392017-08-26 20:45:29 -04004146 VMap[&I] = nextID;
4147
David Neto22f144c2017-06-12 14:26:21 -04004148 Inst = new SPIRVInstruction(5, spv::OpBitwiseOr, nextID++, Ops);
4149 SPIRVInstList.push_back(Inst);
4150
4151 break;
4152 }
4153
4154 // Ops[0] = Result Type ID
4155 // Ops[1] = Object ID
4156 // Ops[2] = Composite ID
4157 // Ops[3] ... Ops[n] = Indexes (Literal Number)
4158 SPIRVOperandList Ops;
4159
4160 uint32_t ResTyID = lookupType(I.getType());
4161 SPIRVOperand *ResTyIDOp =
4162 new SPIRVOperand(SPIRVOperandType::NUMBERID, ResTyID);
4163 Ops.push_back(ResTyIDOp);
4164
4165 uint32_t ObjectID = VMap[I.getOperand(1)];
4166 SPIRVOperand *ObjectIDOp =
4167 new SPIRVOperand(SPIRVOperandType::NUMBERID, ObjectID);
4168 Ops.push_back(ObjectIDOp);
4169
4170 uint32_t CompositeID = VMap[I.getOperand(0)];
4171 SPIRVOperand *CompositeIDOp =
4172 new SPIRVOperand(SPIRVOperandType::NUMBERID, CompositeID);
4173 Ops.push_back(CompositeIDOp);
4174
4175 spv::Op Opcode = spv::OpCompositeInsert;
4176 if (const ConstantInt *CI = dyn_cast<ConstantInt>(I.getOperand(2))) {
4177 std::vector<uint32_t> LiteralNum;
4178 assert(CI->getZExtValue() < UINT32_MAX);
4179 LiteralNum.push_back(static_cast<uint32_t>(CI->getZExtValue()));
4180 SPIRVOperand *Indexes =
4181 new SPIRVOperand(SPIRVOperandType::LITERAL_INTEGER, LiteralNum);
4182 Ops.push_back(Indexes);
4183 } else {
4184 uint32_t IndexID = VMap[I.getOperand(1)];
4185 SPIRVOperand *IndexIDOp =
4186 new SPIRVOperand(SPIRVOperandType::NUMBERID, IndexID);
4187 Ops.push_back(IndexIDOp);
4188 Opcode = spv::OpVectorInsertDynamic;
4189 }
4190
4191 uint16_t WordCount = 6;
4192 SPIRVInstruction *Inst =
4193 new SPIRVInstruction(WordCount, Opcode, nextID++, Ops);
4194 SPIRVInstList.push_back(Inst);
4195 break;
4196 }
4197 case Instruction::ShuffleVector: {
4198 // Ops[0] = Result Type ID
4199 // Ops[1] = Vector 1 ID
4200 // Ops[2] = Vector 2 ID
4201 // Ops[3] ... Ops[n] = Components (Literal Number)
4202 SPIRVOperandList Ops;
4203
4204 uint32_t ResTyID = lookupType(I.getType());
4205 SPIRVOperand *ResTyIDOp =
4206 new SPIRVOperand(SPIRVOperandType::NUMBERID, ResTyID);
4207 Ops.push_back(ResTyIDOp);
4208
4209 uint32_t Vec1ID = VMap[I.getOperand(0)];
4210 SPIRVOperand *Vec1IDOp =
4211 new SPIRVOperand(SPIRVOperandType::NUMBERID, Vec1ID);
4212 Ops.push_back(Vec1IDOp);
4213
4214 uint32_t Vec2ID = VMap[I.getOperand(1)];
4215 SPIRVOperand *Vec2IDOp =
4216 new SPIRVOperand(SPIRVOperandType::NUMBERID, Vec2ID);
4217 Ops.push_back(Vec2IDOp);
4218
4219 uint64_t NumElements = 0;
4220 if (Constant *Cst = dyn_cast<Constant>(I.getOperand(2))) {
4221 NumElements = cast<VectorType>(Cst->getType())->getNumElements();
4222
4223 if (Cst->isNullValue()) {
4224 for (unsigned i = 0; i < NumElements; i++) {
4225 std::vector<uint32_t> LiteralNum;
4226 LiteralNum.push_back(0);
4227 SPIRVOperand *Component =
4228 new SPIRVOperand(SPIRVOperandType::LITERAL_INTEGER, LiteralNum);
4229 Ops.push_back(Component);
4230 }
4231 } else if (const ConstantDataSequential *CDS =
4232 dyn_cast<ConstantDataSequential>(Cst)) {
4233 for (unsigned i = 0; i < CDS->getNumElements(); i++) {
4234 std::vector<uint32_t> LiteralNum;
4235 assert(CDS->getElementAsInteger(i) < UINT32_MAX);
4236 LiteralNum.push_back(
4237 static_cast<uint32_t>(CDS->getElementAsInteger(i)));
4238 SPIRVOperand *Component =
4239 new SPIRVOperand(SPIRVOperandType::LITERAL_INTEGER, LiteralNum);
4240 Ops.push_back(Component);
4241 }
4242 } else if (const ConstantVector *CV = dyn_cast<ConstantVector>(Cst)) {
4243 for (unsigned i = 0; i < CV->getNumOperands(); i++) {
4244 auto Op = CV->getOperand(i);
4245
4246 uint32_t literal = 0;
4247
4248 if (auto CI = dyn_cast<ConstantInt>(Op)) {
4249 literal = static_cast<uint32_t>(CI->getZExtValue());
4250 } else if (auto UI = dyn_cast<UndefValue>(Op)) {
4251 literal = 0xFFFFFFFFu;
4252 } else {
4253 Op->print(errs());
4254 llvm_unreachable("Unsupported element in ConstantVector!");
4255 }
4256
4257 std::vector<uint32_t> LiteralNum;
4258 LiteralNum.push_back(literal);
4259 SPIRVOperand *Component =
4260 new SPIRVOperand(SPIRVOperandType::LITERAL_INTEGER, LiteralNum);
4261 Ops.push_back(Component);
4262 }
4263 } else {
4264 Cst->print(errs());
4265 llvm_unreachable("Unsupported constant mask in ShuffleVector!");
4266 }
4267 }
4268
4269 uint16_t WordCount = static_cast<uint16_t>(5 + NumElements);
4270 SPIRVInstruction *Inst =
4271 new SPIRVInstruction(WordCount, spv::OpVectorShuffle, nextID++, Ops);
4272 SPIRVInstList.push_back(Inst);
4273 break;
4274 }
4275 case Instruction::ICmp:
4276 case Instruction::FCmp: {
4277 CmpInst *CmpI = cast<CmpInst>(&I);
4278
4279 // Ops[0] = Result Type ID
4280 // Ops[1] = Operand 1 ID
4281 // Ops[2] = Operand 2 ID
4282 SPIRVOperandList Ops;
4283
4284 uint32_t ResTyID = lookupType(CmpI->getType());
4285 SPIRVOperand *ResTyIDOp =
4286 new SPIRVOperand(SPIRVOperandType::NUMBERID, ResTyID);
4287 Ops.push_back(ResTyIDOp);
4288
David Netod4ca2e62017-07-06 18:47:35 -04004289 // Pointer equality is invalid.
4290 Type* ArgTy = CmpI->getOperand(0)->getType();
4291 if (isa<PointerType>(ArgTy)) {
4292 CmpI->print(errs());
4293 std::string name = I.getParent()->getParent()->getName();
4294 errs()
4295 << "\nPointer equality test is not supported by SPIR-V for Vulkan, "
4296 << "in function " << name << "\n";
4297 llvm_unreachable("Pointer equality check is invalid");
4298 break;
4299 }
4300
David Neto22f144c2017-06-12 14:26:21 -04004301 uint32_t Op1ID = VMap[CmpI->getOperand(0)];
4302 SPIRVOperand *Op1IDOp = new SPIRVOperand(SPIRVOperandType::NUMBERID, Op1ID);
4303 Ops.push_back(Op1IDOp);
4304
4305 uint32_t Op2ID = VMap[CmpI->getOperand(1)];
4306 SPIRVOperand *Op2IDOp = new SPIRVOperand(SPIRVOperandType::NUMBERID, Op2ID);
4307 Ops.push_back(Op2IDOp);
4308
4309 spv::Op Opcode = GetSPIRVCmpOpcode(CmpI);
4310 SPIRVInstruction *Inst = new SPIRVInstruction(5, Opcode, nextID++, Ops);
4311 SPIRVInstList.push_back(Inst);
4312 break;
4313 }
4314 case Instruction::Br: {
4315 // Branch instrucion is deferred because it needs label's ID. Record slot's
4316 // location on SPIRVInstructionList.
4317 DeferredInsts.push_back(
4318 std::make_tuple(&I, --SPIRVInstList.end(), 0 /* No id */));
4319 break;
4320 }
4321 case Instruction::Switch: {
4322 I.print(errs());
4323 llvm_unreachable("Unsupported instruction???");
4324 break;
4325 }
4326 case Instruction::IndirectBr: {
4327 I.print(errs());
4328 llvm_unreachable("Unsupported instruction???");
4329 break;
4330 }
4331 case Instruction::PHI: {
4332 // Branch instrucion is deferred because it needs label's ID. Record slot's
4333 // location on SPIRVInstructionList.
4334 DeferredInsts.push_back(
4335 std::make_tuple(&I, --SPIRVInstList.end(), nextID++));
4336 break;
4337 }
4338 case Instruction::Alloca: {
4339 //
4340 // Generate OpVariable.
4341 //
4342 // Ops[0] : Result Type ID
4343 // Ops[1] : Storage Class
4344 SPIRVOperandList Ops;
4345
4346 Type *ResTy = I.getType();
4347 uint32_t ResTyID = lookupType(ResTy);
4348 SPIRVOperand *ResTyOp =
4349 new SPIRVOperand(SPIRVOperandType::NUMBERID, ResTyID);
4350 Ops.push_back(ResTyOp);
4351
4352 spv::StorageClass StorageClass = spv::StorageClassFunction;
4353 SPIRVOperand *StorageClassOp =
4354 new SPIRVOperand(SPIRVOperandType::NUMBERID, StorageClass);
4355 Ops.push_back(StorageClassOp);
4356
4357 SPIRVInstruction *Inst =
4358 new SPIRVInstruction(4, spv::OpVariable, nextID++, Ops);
4359 SPIRVInstList.push_back(Inst);
4360 break;
4361 }
4362 case Instruction::Load: {
4363 LoadInst *LD = cast<LoadInst>(&I);
4364 //
4365 // Generate OpLoad.
4366 //
4367
David Neto0a2f98d2017-09-15 19:38:40 -04004368 uint32_t ResTyID = lookupType(LD->getType());
David Netoa60b00b2017-09-15 16:34:09 -04004369 uint32_t PointerID = VMap[LD->getPointerOperand()];
4370
4371 // This is a hack to work around what looks like a driver bug.
4372 // When we're loading from the special variable holding the WorkgroupSize
David Neto0a2f98d2017-09-15 19:38:40 -04004373 // builtin value, use an OpBitWiseAnd of the value's ID rather than
4374 // generating a load.
David Netoa60b00b2017-09-15 16:34:09 -04004375 if (PointerID == WorkgroupSizeVarID) {
David Neto0a2f98d2017-09-15 19:38:40 -04004376 // Generate a bitwise-and of the original value with itself.
4377 // We should have been able to get away with just an OpCopyObject,
4378 // but we need something more complex to get past certain driver bugs.
4379 // This is ridiculous, but necessary.
4380 // TODO(dneto): Revisit this once drivers fix their bugs.
4381
4382 SPIRVOperandList Ops;
4383
4384 SPIRVOperand *ResTyIDOp =
4385 new SPIRVOperand(SPIRVOperandType::NUMBERID, ResTyID);
4386 Ops.push_back(ResTyIDOp);
4387
4388 SPIRVOperand *ValueIDOp0 =
4389 new SPIRVOperand(SPIRVOperandType::NUMBERID, WorkgroupSizeValueID);
4390 Ops.push_back(ValueIDOp0);
4391
4392 SPIRVOperand *ValueIDOp1 =
4393 new SPIRVOperand(SPIRVOperandType::NUMBERID, WorkgroupSizeValueID);
4394 Ops.push_back(ValueIDOp1);
4395
4396 SPIRVInstruction *Inst =
4397 new SPIRVInstruction(5, spv::OpBitwiseAnd, nextID++, Ops);
4398 SPIRVInstList.push_back(Inst);
David Netoa60b00b2017-09-15 16:34:09 -04004399 break;
4400 }
4401
4402 // This is the normal path. Generate a load.
4403
David Neto22f144c2017-06-12 14:26:21 -04004404 // Ops[0] = Result Type ID
4405 // Ops[1] = Pointer ID
4406 // Ops[2] ... Ops[n] = Optional Memory Access
4407 //
4408 // TODO: Do we need to implement Optional Memory Access???
David Neto0a2f98d2017-09-15 19:38:40 -04004409
David Neto22f144c2017-06-12 14:26:21 -04004410 SPIRVOperandList Ops;
4411
David Neto22f144c2017-06-12 14:26:21 -04004412 SPIRVOperand *ResTyIDOp =
4413 new SPIRVOperand(SPIRVOperandType::NUMBERID, ResTyID);
4414 Ops.push_back(ResTyIDOp);
4415
David Neto22f144c2017-06-12 14:26:21 -04004416 SPIRVOperand *PointerIDOp =
4417 new SPIRVOperand(SPIRVOperandType::NUMBERID, PointerID);
4418 Ops.push_back(PointerIDOp);
4419
4420 SPIRVInstruction *Inst =
4421 new SPIRVInstruction(4, spv::OpLoad, nextID++, Ops);
4422 SPIRVInstList.push_back(Inst);
4423 break;
4424 }
4425 case Instruction::Store: {
4426 StoreInst *ST = cast<StoreInst>(&I);
4427 //
4428 // Generate OpStore.
4429 //
4430
4431 // Ops[0] = Pointer ID
4432 // Ops[1] = Object ID
4433 // Ops[2] ... Ops[n] = Optional Memory Access (later???)
4434 //
4435 // TODO: Do we need to implement Optional Memory Access???
4436 SPIRVOperand *Ops[2] = {new SPIRVOperand(SPIRVOperandType::NUMBERID,
4437 VMap[ST->getPointerOperand()]),
4438 new SPIRVOperand(SPIRVOperandType::NUMBERID,
4439 VMap[ST->getValueOperand()])};
4440
4441 SPIRVInstruction *Inst =
4442 new SPIRVInstruction(3, spv::OpStore, 0 /* No id */, Ops);
4443 SPIRVInstList.push_back(Inst);
4444 break;
4445 }
4446 case Instruction::AtomicCmpXchg: {
4447 I.print(errs());
4448 llvm_unreachable("Unsupported instruction???");
4449 break;
4450 }
4451 case Instruction::AtomicRMW: {
Neil Henning39672102017-09-29 14:33:13 +01004452 AtomicRMWInst *AtomicRMW = dyn_cast<AtomicRMWInst>(&I);
4453
4454 spv::Op opcode;
4455
4456 switch (AtomicRMW->getOperation()) {
4457 default:
4458 I.print(errs());
4459 llvm_unreachable("Unsupported instruction???");
4460 case llvm::AtomicRMWInst::Add:
4461 opcode = spv::OpAtomicIAdd;
4462 break;
4463 case llvm::AtomicRMWInst::Sub:
4464 opcode = spv::OpAtomicISub;
4465 break;
4466 case llvm::AtomicRMWInst::Xchg:
4467 opcode = spv::OpAtomicExchange;
4468 break;
4469 case llvm::AtomicRMWInst::Min:
4470 opcode = spv::OpAtomicSMin;
4471 break;
4472 case llvm::AtomicRMWInst::Max:
4473 opcode = spv::OpAtomicSMax;
4474 break;
4475 case llvm::AtomicRMWInst::UMin:
4476 opcode = spv::OpAtomicUMin;
4477 break;
4478 case llvm::AtomicRMWInst::UMax:
4479 opcode = spv::OpAtomicUMax;
4480 break;
4481 case llvm::AtomicRMWInst::And:
4482 opcode = spv::OpAtomicAnd;
4483 break;
4484 case llvm::AtomicRMWInst::Or:
4485 opcode = spv::OpAtomicOr;
4486 break;
4487 case llvm::AtomicRMWInst::Xor:
4488 opcode = spv::OpAtomicXor;
4489 break;
4490 }
4491
4492 //
4493 // Generate OpAtomic*.
4494 //
4495 SPIRVOperandList Ops;
4496
4497 uint32_t TyID = lookupType(I.getType());
4498 Ops.push_back(new SPIRVOperand(SPIRVOperandType::NUMBERID, TyID));
4499
4500 Ops.push_back(new SPIRVOperand(SPIRVOperandType::NUMBERID,
4501 VMap[AtomicRMW->getPointerOperand()]));
4502
4503 auto IntTy = Type::getInt32Ty(I.getContext());
4504
4505 const auto ConstantScopeDevice = ConstantInt::get(IntTy, spv::ScopeDevice);
4506
4507 Ops.push_back(new SPIRVOperand(SPIRVOperandType::NUMBERID,
4508 VMap[ConstantScopeDevice]));
4509
4510 const auto ConstantMemorySemantics = ConstantInt::get(
4511 IntTy, spv::MemorySemanticsUniformMemoryMask |
4512 spv::MemorySemanticsSequentiallyConsistentMask);
4513
4514 Ops.push_back(new SPIRVOperand(SPIRVOperandType::NUMBERID,
4515 VMap[ConstantMemorySemantics]));
4516
4517 Ops.push_back(new SPIRVOperand(SPIRVOperandType::NUMBERID,
4518 VMap[AtomicRMW->getValOperand()]));
4519
4520 VMap[&I] = nextID;
4521
4522 SPIRVInstruction *Inst = new SPIRVInstruction(
4523 static_cast<uint16_t>(2 + Ops.size()), opcode, nextID++, Ops);
4524 SPIRVInstList.push_back(Inst);
David Neto22f144c2017-06-12 14:26:21 -04004525 break;
4526 }
4527 case Instruction::Fence: {
4528 I.print(errs());
4529 llvm_unreachable("Unsupported instruction???");
4530 break;
4531 }
4532 case Instruction::Call: {
4533 CallInst *Call = dyn_cast<CallInst>(&I);
4534 Function *Callee = Call->getCalledFunction();
4535
4536 // Sampler initializers become a load of the corresponding sampler.
4537 if (Callee->getName().equals("__translate_sampler_initializer")) {
4538 // Check that the sampler map was definitely used though.
4539 if (0 == getSamplerMap().size()) {
4540 llvm_unreachable("Sampler literal in source without sampler map!");
4541 }
4542
4543 SPIRVOperandList Ops;
4544
4545 uint32_t ResTyID = lookupType(SamplerTy->getPointerElementType());
4546 SPIRVOperand *ResTyIDOp =
4547 new SPIRVOperand(SPIRVOperandType::NUMBERID, ResTyID);
4548 Ops.push_back(ResTyIDOp);
4549
4550 uint32_t PointerID = VMap[Call];
4551 SPIRVOperand *PointerIDOp =
4552 new SPIRVOperand(SPIRVOperandType::NUMBERID, PointerID);
4553 Ops.push_back(PointerIDOp);
4554
4555 VMap[Call] = nextID;
4556 SPIRVInstruction *Inst =
4557 new SPIRVInstruction(4, spv::OpLoad, nextID++, Ops);
4558 SPIRVInstList.push_back(Inst);
4559
4560 break;
4561 }
4562
4563 if (Callee->getName().startswith("spirv.atomic")) {
4564 spv::Op opcode = StringSwitch<spv::Op>(Callee->getName())
4565 .Case("spirv.atomic_add", spv::OpAtomicIAdd)
4566 .Case("spirv.atomic_sub", spv::OpAtomicISub)
4567 .Case("spirv.atomic_exchange", spv::OpAtomicExchange)
4568 .Case("spirv.atomic_inc", spv::OpAtomicIIncrement)
4569 .Case("spirv.atomic_dec", spv::OpAtomicIDecrement)
4570 .Case("spirv.atomic_compare_exchange",
4571 spv::OpAtomicCompareExchange)
4572 .Case("spirv.atomic_umin", spv::OpAtomicUMin)
4573 .Case("spirv.atomic_smin", spv::OpAtomicSMin)
4574 .Case("spirv.atomic_umax", spv::OpAtomicUMax)
4575 .Case("spirv.atomic_smax", spv::OpAtomicSMax)
4576 .Case("spirv.atomic_and", spv::OpAtomicAnd)
4577 .Case("spirv.atomic_or", spv::OpAtomicOr)
4578 .Case("spirv.atomic_xor", spv::OpAtomicXor)
4579 .Default(spv::OpNop);
4580
4581 //
4582 // Generate OpAtomic*.
4583 //
4584 SPIRVOperandList Ops;
4585
4586 uint32_t TyID = lookupType(I.getType());
4587 Ops.push_back(new SPIRVOperand(SPIRVOperandType::NUMBERID, TyID));
4588
4589 for (unsigned i = 0; i < Call->getNumArgOperands(); i++) {
4590 Ops.push_back(new SPIRVOperand(SPIRVOperandType::NUMBERID,
4591 VMap[Call->getArgOperand(i)]));
4592 }
4593
4594 VMap[&I] = nextID;
4595
4596 SPIRVInstruction *Inst = new SPIRVInstruction(
4597 static_cast<uint16_t>(2 + Ops.size()), opcode, nextID++, Ops);
4598 SPIRVInstList.push_back(Inst);
4599 break;
4600 }
4601
4602 if (Callee->getName().startswith("_Z3dot")) {
4603 // If the argument is a vector type, generate OpDot
4604 if (Call->getArgOperand(0)->getType()->isVectorTy()) {
4605 //
4606 // Generate OpDot.
4607 //
4608 SPIRVOperandList Ops;
4609
4610 uint32_t TyID = lookupType(I.getType());
4611 Ops.push_back(new SPIRVOperand(SPIRVOperandType::NUMBERID, TyID));
4612
4613 for (unsigned i = 0; i < Call->getNumArgOperands(); i++) {
4614 Ops.push_back(new SPIRVOperand(SPIRVOperandType::NUMBERID,
4615 VMap[Call->getArgOperand(i)]));
4616 }
4617
4618 VMap[&I] = nextID;
4619
4620 SPIRVInstruction *Inst = new SPIRVInstruction(
4621 static_cast<uint16_t>(2 + Ops.size()), spv::OpDot, nextID++, Ops);
4622 SPIRVInstList.push_back(Inst);
4623 } else {
4624 //
4625 // Generate OpFMul.
4626 //
4627 SPIRVOperandList Ops;
4628
4629 uint32_t TyID = lookupType(I.getType());
4630 Ops.push_back(new SPIRVOperand(SPIRVOperandType::NUMBERID, TyID));
4631
4632 for (unsigned i = 0; i < Call->getNumArgOperands(); i++) {
4633 Ops.push_back(new SPIRVOperand(SPIRVOperandType::NUMBERID,
4634 VMap[Call->getArgOperand(i)]));
4635 }
4636
4637 VMap[&I] = nextID;
4638
4639 SPIRVInstruction *Inst = new SPIRVInstruction(
4640 static_cast<uint16_t>(2 + Ops.size()), spv::OpFMul, nextID++, Ops);
4641 SPIRVInstList.push_back(Inst);
4642 }
4643 break;
4644 }
4645
David Neto8505ebf2017-10-13 18:50:50 -04004646 if (Callee->getName().startswith("_Z4fmod")) {
4647 // OpenCL fmod(x,y) is x - y * trunc(x/y)
4648 // The sign for a non-zero result is taken from x.
4649 // (Try an example.)
4650 // So translate to OpFRem
4651
4652 SPIRVOperandList Ops;
4653
4654 uint32_t TyID = lookupType(I.getType());
4655 Ops.push_back(new SPIRVOperand(SPIRVOperandType::NUMBERID, TyID));
4656
4657 for (unsigned i = 0; i < Call->getNumArgOperands(); i++) {
4658 Ops.push_back(new SPIRVOperand(SPIRVOperandType::NUMBERID,
4659 VMap[Call->getArgOperand(i)]));
4660 }
4661
4662 VMap[&I] = nextID;
4663
4664 SPIRVInstruction *Inst = new SPIRVInstruction(
4665 static_cast<uint16_t>(2 + Ops.size()), spv::OpFRem, nextID++, Ops);
4666 SPIRVInstList.push_back(Inst);
4667 break;
4668 }
4669
David Neto22f144c2017-06-12 14:26:21 -04004670 // spirv.store_null.* intrinsics become OpStore's.
4671 if (Callee->getName().startswith("spirv.store_null")) {
4672 //
4673 // Generate OpStore.
4674 //
4675
4676 // Ops[0] = Pointer ID
4677 // Ops[1] = Object ID
4678 // Ops[2] ... Ops[n]
4679 SPIRVOperandList Ops;
4680
4681 uint32_t PointerID = VMap[Call->getArgOperand(0)];
4682 SPIRVOperand *PointerIDOp =
4683 new SPIRVOperand(SPIRVOperandType::NUMBERID, PointerID);
4684 Ops.push_back(PointerIDOp);
4685
4686 uint32_t ObjectID = VMap[Call->getArgOperand(1)];
4687 SPIRVOperand *ObjectIDOp =
4688 new SPIRVOperand(SPIRVOperandType::NUMBERID, ObjectID);
4689 Ops.push_back(ObjectIDOp);
4690
4691 SPIRVInstruction *Inst =
4692 new SPIRVInstruction(3, spv::OpStore, 0 /* No id */, Ops);
4693 SPIRVInstList.push_back(Inst);
4694
4695 break;
4696 }
4697
4698 // spirv.copy_memory.* intrinsics become OpMemoryMemory's.
4699 if (Callee->getName().startswith("spirv.copy_memory")) {
4700 //
4701 // Generate OpCopyMemory.
4702 //
4703
4704 // Ops[0] = Dst ID
4705 // Ops[1] = Src ID
4706 // Ops[2] = Memory Access
4707 // Ops[3] = Alignment
4708
4709 auto IsVolatile =
4710 dyn_cast<ConstantInt>(Call->getArgOperand(3))->getZExtValue() != 0;
4711
4712 auto VolatileMemoryAccess = (IsVolatile) ? spv::MemoryAccessVolatileMask
4713 : spv::MemoryAccessMaskNone;
4714
4715 auto MemoryAccess = VolatileMemoryAccess | spv::MemoryAccessAlignedMask;
4716
4717 auto Alignment =
4718 dyn_cast<ConstantInt>(Call->getArgOperand(2))->getZExtValue();
4719
4720 SPIRVOperand *Ops[4] = {
4721 new SPIRVOperand(SPIRVOperandType::NUMBERID,
4722 VMap[Call->getArgOperand(0)]),
4723 new SPIRVOperand(SPIRVOperandType::NUMBERID,
4724 VMap[Call->getArgOperand(1)]),
4725 new SPIRVOperand(SPIRVOperandType::LITERAL_INTEGER, MemoryAccess),
4726 new SPIRVOperand(SPIRVOperandType::LITERAL_INTEGER,
4727 static_cast<uint32_t>(Alignment))};
4728
4729 SPIRVInstruction *Inst =
4730 new SPIRVInstruction(5, spv::OpCopyMemory, 0 /* No id */, Ops);
4731
4732 SPIRVInstList.push_back(Inst);
4733
4734 break;
4735 }
4736
4737 // Nothing to do for abs with uint. Map abs's operand ID to VMap for abs
4738 // with unit.
4739 if (Callee->getName().equals("_Z3absj") ||
4740 Callee->getName().equals("_Z3absDv2_j") ||
4741 Callee->getName().equals("_Z3absDv3_j") ||
4742 Callee->getName().equals("_Z3absDv4_j")) {
4743 VMap[&I] = VMap[Call->getOperand(0)];
4744 break;
4745 }
4746
4747 // barrier is converted to OpControlBarrier
4748 if (Callee->getName().equals("__spirv_control_barrier")) {
4749 //
4750 // Generate OpControlBarrier.
4751 //
4752 // Ops[0] = Execution Scope ID
4753 // Ops[1] = Memory Scope ID
4754 // Ops[2] = Memory Semantics ID
4755 //
4756 Value *ExecutionScope = Call->getArgOperand(0);
4757 Value *MemoryScope = Call->getArgOperand(1);
4758 Value *MemorySemantics = Call->getArgOperand(2);
4759
4760 SPIRVOperand *Ops[3] = {
4761 new SPIRVOperand(SPIRVOperandType::NUMBERID, VMap[ExecutionScope]),
4762 new SPIRVOperand(SPIRVOperandType::NUMBERID, VMap[MemoryScope]),
4763 new SPIRVOperand(SPIRVOperandType::NUMBERID, VMap[MemorySemantics])};
4764
4765 SPIRVInstList.push_back(
4766 new SPIRVInstruction(4, spv::OpControlBarrier, 0 /* No id */, Ops));
4767 break;
4768 }
4769
4770 // memory barrier is converted to OpMemoryBarrier
4771 if (Callee->getName().equals("__spirv_memory_barrier")) {
4772 //
4773 // Generate OpMemoryBarrier.
4774 //
4775 // Ops[0] = Memory Scope ID
4776 // Ops[1] = Memory Semantics ID
4777 //
4778 SPIRVOperandList Ops;
4779
4780 Value *MemoryScope = Call->getArgOperand(0);
4781 Value *MemorySemantics = Call->getArgOperand(1);
4782
4783 uint32_t MemoryScopeID = VMap[MemoryScope];
4784 Ops.push_back(
4785 new SPIRVOperand(SPIRVOperandType::NUMBERID, MemoryScopeID));
4786
4787 uint32_t MemorySemanticsID = VMap[MemorySemantics];
4788 Ops.push_back(
4789 new SPIRVOperand(SPIRVOperandType::NUMBERID, MemorySemanticsID));
4790
4791 SPIRVInstruction *Inst =
4792 new SPIRVInstruction(3, spv::OpMemoryBarrier, 0 /* No id */, Ops);
4793 SPIRVInstList.push_back(Inst);
4794 break;
4795 }
4796
4797 // isinf is converted to OpIsInf
4798 if (Callee->getName().equals("__spirv_isinff") ||
4799 Callee->getName().equals("__spirv_isinfDv2_f") ||
4800 Callee->getName().equals("__spirv_isinfDv3_f") ||
4801 Callee->getName().equals("__spirv_isinfDv4_f")) {
4802 //
4803 // Generate OpIsInf.
4804 //
4805 // Ops[0] = Result Type ID
4806 // Ops[1] = X ID
4807 //
4808 SPIRVOperandList Ops;
4809
4810 uint32_t TyID = lookupType(I.getType());
4811 SPIRVOperand *ResTyIDOp =
4812 new SPIRVOperand(SPIRVOperandType::NUMBERID, TyID);
4813 Ops.push_back(ResTyIDOp);
4814
4815 uint32_t XID = VMap[Call->getArgOperand(0)];
4816 Ops.push_back(new SPIRVOperand(SPIRVOperandType::NUMBERID, XID));
4817
4818 VMap[&I] = nextID;
4819
4820 SPIRVInstruction *Inst =
4821 new SPIRVInstruction(4, spv::OpIsInf, nextID++, Ops);
4822 SPIRVInstList.push_back(Inst);
4823 break;
4824 }
4825
4826 // isnan is converted to OpIsNan
4827 if (Callee->getName().equals("__spirv_isnanf") ||
4828 Callee->getName().equals("__spirv_isnanDv2_f") ||
4829 Callee->getName().equals("__spirv_isnanDv3_f") ||
4830 Callee->getName().equals("__spirv_isnanDv4_f")) {
4831 //
4832 // Generate OpIsInf.
4833 //
4834 // Ops[0] = Result Type ID
4835 // Ops[1] = X ID
4836 //
4837 SPIRVOperandList Ops;
4838
4839 uint32_t TyID = lookupType(I.getType());
4840 SPIRVOperand *ResTyIDOp =
4841 new SPIRVOperand(SPIRVOperandType::NUMBERID, TyID);
4842 Ops.push_back(ResTyIDOp);
4843
4844 uint32_t XID = VMap[Call->getArgOperand(0)];
4845 Ops.push_back(new SPIRVOperand(SPIRVOperandType::NUMBERID, XID));
4846
4847 VMap[&I] = nextID;
4848
4849 SPIRVInstruction *Inst =
4850 new SPIRVInstruction(4, spv::OpIsNan, nextID++, Ops);
4851 SPIRVInstList.push_back(Inst);
4852 break;
4853 }
4854
4855 // all is converted to OpAll
4856 if (Callee->getName().equals("__spirv_allDv2_i") ||
4857 Callee->getName().equals("__spirv_allDv3_i") ||
4858 Callee->getName().equals("__spirv_allDv4_i")) {
4859 //
4860 // Generate OpAll.
4861 //
4862 // Ops[0] = Result Type ID
4863 // Ops[1] = Vector ID
4864 //
4865 SPIRVOperandList Ops;
4866
4867 uint32_t TyID = lookupType(I.getType());
4868 SPIRVOperand *ResTyIDOp =
4869 new SPIRVOperand(SPIRVOperandType::NUMBERID, TyID);
4870 Ops.push_back(ResTyIDOp);
4871
4872 uint32_t VectorID = VMap[Call->getArgOperand(0)];
4873 Ops.push_back(new SPIRVOperand(SPIRVOperandType::NUMBERID, VectorID));
4874
4875 VMap[&I] = nextID;
4876
4877 SPIRVInstruction *Inst =
4878 new SPIRVInstruction(4, spv::OpAll, nextID++, Ops);
4879 SPIRVInstList.push_back(Inst);
4880 break;
4881 }
4882
4883 // any is converted to OpAny
4884 if (Callee->getName().equals("__spirv_anyDv2_i") ||
4885 Callee->getName().equals("__spirv_anyDv3_i") ||
4886 Callee->getName().equals("__spirv_anyDv4_i")) {
4887 //
4888 // Generate OpAny.
4889 //
4890 // Ops[0] = Result Type ID
4891 // Ops[1] = Vector ID
4892 //
4893 SPIRVOperandList Ops;
4894
4895 uint32_t TyID = lookupType(I.getType());
4896 SPIRVOperand *ResTyIDOp =
4897 new SPIRVOperand(SPIRVOperandType::NUMBERID, TyID);
4898 Ops.push_back(ResTyIDOp);
4899
4900 uint32_t VectorID = VMap[Call->getArgOperand(0)];
4901 Ops.push_back(new SPIRVOperand(SPIRVOperandType::NUMBERID, VectorID));
4902
4903 VMap[&I] = nextID;
4904
4905 SPIRVInstruction *Inst =
4906 new SPIRVInstruction(4, spv::OpAny, nextID++, Ops);
4907 SPIRVInstList.push_back(Inst);
4908 break;
4909 }
4910
4911 // read_image is converted to OpSampledImage and OpImageSampleExplicitLod.
4912 // Additionally, OpTypeSampledImage is generated.
4913 if (Callee->getName().equals(
4914 "_Z11read_imagef14ocl_image2d_ro11ocl_samplerDv2_f") ||
4915 Callee->getName().equals(
4916 "_Z11read_imagef14ocl_image3d_ro11ocl_samplerDv4_f")) {
4917 //
4918 // Generate OpSampledImage.
4919 //
4920 // Ops[0] = Result Type ID
4921 // Ops[1] = Image ID
4922 // Ops[2] = Sampler ID
4923 //
4924 SPIRVOperandList Ops;
4925
4926 Value *Image = Call->getArgOperand(0);
4927 Value *Sampler = Call->getArgOperand(1);
4928 Value *Coordinate = Call->getArgOperand(2);
4929
4930 TypeMapType &OpImageTypeMap = getImageTypeMap();
4931 Type *ImageTy = Image->getType()->getPointerElementType();
4932 uint32_t ImageTyID = OpImageTypeMap[ImageTy];
4933 SPIRVOperand *ResTyIDOp =
4934 new SPIRVOperand(SPIRVOperandType::NUMBERID, ImageTyID);
4935 Ops.push_back(ResTyIDOp);
4936
4937 uint32_t ImageID = VMap[Image];
4938 SPIRVOperand *ImageIDOp =
4939 new SPIRVOperand(SPIRVOperandType::NUMBERID, ImageID);
4940 Ops.push_back(ImageIDOp);
4941
4942 uint32_t SamplerID = VMap[Sampler];
4943 SPIRVOperand *SamplerIDOp =
4944 new SPIRVOperand(SPIRVOperandType::NUMBERID, SamplerID);
4945 Ops.push_back(SamplerIDOp);
4946
4947 uint32_t SampledImageID = nextID;
4948
4949 SPIRVInstruction *Inst =
4950 new SPIRVInstruction(5, spv::OpSampledImage, nextID++, Ops);
4951 SPIRVInstList.push_back(Inst);
4952
4953 //
4954 // Generate OpImageSampleExplicitLod.
4955 //
4956 // Ops[0] = Result Type ID
4957 // Ops[1] = Sampled Image ID
4958 // Ops[2] = Coordinate ID
4959 // Ops[3] = Image Operands Type ID
4960 // Ops[4] ... Ops[n] = Operands ID
4961 //
4962 Ops.clear();
4963
4964 uint32_t RetTyID = lookupType(Call->getType());
4965 ResTyIDOp = new SPIRVOperand(SPIRVOperandType::NUMBERID, RetTyID);
4966 Ops.push_back(ResTyIDOp);
4967
4968 SPIRVOperand *SampledImageIDOp =
4969 new SPIRVOperand(SPIRVOperandType::NUMBERID, SampledImageID);
4970 Ops.push_back(SampledImageIDOp);
4971
4972 uint32_t CoordinateID = VMap[Coordinate];
4973 SPIRVOperand *CoordinateIDOp =
4974 new SPIRVOperand(SPIRVOperandType::NUMBERID, CoordinateID);
4975 Ops.push_back(CoordinateIDOp);
4976
4977 std::vector<uint32_t> LiteralNum;
4978 LiteralNum.push_back(spv::ImageOperandsLodMask);
4979 SPIRVOperand *ImageOperandTyIDOp =
4980 new SPIRVOperand(SPIRVOperandType::LITERAL_INTEGER, LiteralNum);
4981 Ops.push_back(ImageOperandTyIDOp);
4982
4983 Constant *CstFP0 = ConstantFP::get(Context, APFloat(0.0f));
4984 uint32_t OperandID = VMap[CstFP0];
4985 SPIRVOperand *OperandIDOp =
4986 new SPIRVOperand(SPIRVOperandType::NUMBERID, OperandID);
4987 Ops.push_back(OperandIDOp);
4988
4989 VMap[&I] = nextID;
4990
4991 Inst =
4992 new SPIRVInstruction(7, spv::OpImageSampleExplicitLod, nextID++, Ops);
4993 SPIRVInstList.push_back(Inst);
4994 break;
4995 }
4996
4997 // write_imagef is mapped to OpImageWrite.
4998 if (Callee->getName().equals(
4999 "_Z12write_imagef14ocl_image2d_woDv2_iDv4_f") ||
5000 Callee->getName().equals(
5001 "_Z12write_imagef14ocl_image3d_woDv4_iDv4_f")) {
5002 //
5003 // Generate OpImageWrite.
5004 //
5005 // Ops[0] = Image ID
5006 // Ops[1] = Coordinate ID
5007 // Ops[2] = Texel ID
5008 // Ops[3] = (Optional) Image Operands Type (Literal Number)
5009 // Ops[4] ... Ops[n] = (Optional) Operands ID
5010 //
5011 SPIRVOperandList Ops;
5012
5013 Value *Image = Call->getArgOperand(0);
5014 Value *Coordinate = Call->getArgOperand(1);
5015 Value *Texel = Call->getArgOperand(2);
5016
5017 uint32_t ImageID = VMap[Image];
5018 SPIRVOperand *ImageIDOp =
5019 new SPIRVOperand(SPIRVOperandType::NUMBERID, ImageID);
5020 Ops.push_back(ImageIDOp);
5021
5022 uint32_t CoordinateID = VMap[Coordinate];
5023 SPIRVOperand *CoordinateIDOp =
5024 new SPIRVOperand(SPIRVOperandType::NUMBERID, CoordinateID);
5025 Ops.push_back(CoordinateIDOp);
5026
5027 uint32_t TexelID = VMap[Texel];
5028 SPIRVOperand *TexelIDOp =
5029 new SPIRVOperand(SPIRVOperandType::NUMBERID, TexelID);
5030 Ops.push_back(TexelIDOp);
5031
5032 SPIRVInstruction *Inst =
5033 new SPIRVInstruction(4, spv::OpImageWrite, 0 /* No id */, Ops);
5034 SPIRVInstList.push_back(Inst);
5035 break;
5036 }
5037
5038 // Call instrucion is deferred because it needs function's ID. Record
5039 // slot's location on SPIRVInstructionList.
5040 DeferredInsts.push_back(
5041 std::make_tuple(&I, --SPIRVInstList.end(), nextID++));
5042
David Neto3fbb4072017-10-16 11:28:14 -04005043 // Check whether the implementation of this call uses an extended
5044 // instruction plus one more value-producing instruction. If so, then
5045 // reserve the id for the extra value-producing slot.
5046 glsl::ExtInst EInst = getIndirectExtInstEnum(Callee->getName());
5047 if (EInst != kGlslExtInstBad) {
5048 // Reserve a spot for the extra value.
David Neto4d02a532017-09-17 12:57:44 -04005049 // Increase nextID.
David Neto22f144c2017-06-12 14:26:21 -04005050 VMap[&I] = nextID;
5051 nextID++;
5052 }
5053 break;
5054 }
5055 case Instruction::Ret: {
5056 unsigned NumOps = I.getNumOperands();
5057 if (NumOps == 0) {
5058 //
5059 // Generate OpReturn.
5060 //
5061
5062 // Empty Ops
5063 SPIRVOperandList Ops;
5064 SPIRVInstruction *Inst =
5065 new SPIRVInstruction(1, spv::OpReturn, 0 /* No id */, Ops);
5066 SPIRVInstList.push_back(Inst);
5067 } else {
5068 //
5069 // Generate OpReturnValue.
5070 //
5071
5072 // Ops[0] = Return Value ID
5073 SPIRVOperandList Ops;
5074 uint32_t RetValID = VMap[I.getOperand(0)];
5075 SPIRVOperand *RetValIDOp =
5076 new SPIRVOperand(SPIRVOperandType::NUMBERID, RetValID);
5077 Ops.push_back(RetValIDOp);
5078
5079 SPIRVInstruction *Inst =
5080 new SPIRVInstruction(2, spv::OpReturnValue, 0 /* No id */, Ops);
5081 SPIRVInstList.push_back(Inst);
5082 break;
5083 }
5084 break;
5085 }
5086 }
5087}
5088
5089void SPIRVProducerPass::GenerateFuncEpilogue() {
5090 SPIRVInstructionList &SPIRVInstList = getSPIRVInstList();
5091
5092 //
5093 // Generate OpFunctionEnd
5094 //
5095
5096 // Empty Ops
5097 SPIRVOperandList Ops;
5098 SPIRVInstruction *Inst =
5099 new SPIRVInstruction(1, spv::OpFunctionEnd, 0 /* No id */, Ops);
5100 SPIRVInstList.push_back(Inst);
5101}
5102
5103bool SPIRVProducerPass::is4xi8vec(Type *Ty) const {
5104 LLVMContext &Context = Ty->getContext();
5105 if (Ty->isVectorTy()) {
5106 if (Ty->getVectorElementType() == Type::getInt8Ty(Context) &&
5107 Ty->getVectorNumElements() == 4) {
5108 return true;
5109 }
5110 }
5111
5112 return false;
5113}
5114
5115void SPIRVProducerPass::HandleDeferredInstruction() {
5116 SPIRVInstructionList &SPIRVInstList = getSPIRVInstList();
5117 ValueMapType &VMap = getValueMap();
5118 DeferredInstVecType &DeferredInsts = getDeferredInstVec();
5119
5120 for (auto DeferredInst = DeferredInsts.rbegin();
5121 DeferredInst != DeferredInsts.rend(); ++DeferredInst) {
5122 Value *Inst = std::get<0>(*DeferredInst);
5123 SPIRVInstructionList::iterator InsertPoint = ++std::get<1>(*DeferredInst);
5124 if (InsertPoint != SPIRVInstList.end()) {
5125 while ((*InsertPoint)->getOpcode() == spv::OpPhi) {
5126 ++InsertPoint;
5127 }
5128 }
5129
5130 if (BranchInst *Br = dyn_cast<BranchInst>(Inst)) {
5131 // Check whether basic block, which has this branch instruction, is loop
5132 // header or not. If it is loop header, generate OpLoopMerge and
5133 // OpBranchConditional.
5134 Function *Func = Br->getParent()->getParent();
5135 DominatorTree &DT =
5136 getAnalysis<DominatorTreeWrapperPass>(*Func).getDomTree();
5137 const LoopInfo &LI =
5138 getAnalysis<LoopInfoWrapperPass>(*Func).getLoopInfo();
5139
5140 BasicBlock *BrBB = Br->getParent();
5141 if (LI.isLoopHeader(BrBB)) {
5142 Value *ContinueBB = nullptr;
5143 Value *MergeBB = nullptr;
5144
5145 Loop *L = LI.getLoopFor(BrBB);
5146 MergeBB = L->getExitBlock();
5147 if (!MergeBB) {
5148 // StructurizeCFG pass converts CFG into triangle shape and the cfg
5149 // has regions with single entry/exit. As a result, loop should not
5150 // have multiple exits.
5151 llvm_unreachable("Loop has multiple exits???");
5152 }
5153
5154 if (L->isLoopLatch(BrBB)) {
5155 ContinueBB = BrBB;
5156 } else {
5157 // From SPIR-V spec 2.11, Continue Target must dominate that back-edge
5158 // block.
5159 BasicBlock *Header = L->getHeader();
5160 BasicBlock *Latch = L->getLoopLatch();
5161 for (BasicBlock *BB : L->blocks()) {
5162 if (BB == Header) {
5163 continue;
5164 }
5165
5166 // Check whether block dominates block with back-edge.
5167 if (DT.dominates(BB, Latch)) {
5168 ContinueBB = BB;
5169 }
5170 }
5171
5172 if (!ContinueBB) {
5173 llvm_unreachable("Wrong continue block from loop");
5174 }
5175 }
5176
5177 //
5178 // Generate OpLoopMerge.
5179 //
5180 // Ops[0] = Merge Block ID
5181 // Ops[1] = Continue Target ID
5182 // Ops[2] = Selection Control
5183 SPIRVOperandList Ops;
5184
5185 // StructurizeCFG pass already manipulated CFG. Just use false block of
5186 // branch instruction as merge block.
5187 uint32_t MergeBBID = VMap[MergeBB];
5188 SPIRVOperand *MergeBBIDOp =
5189 new SPIRVOperand(SPIRVOperandType::NUMBERID, MergeBBID);
5190 Ops.push_back(MergeBBIDOp);
5191
5192 uint32_t ContinueBBID = VMap[ContinueBB];
5193 SPIRVOperand *ContinueBBIDOp =
5194 new SPIRVOperand(SPIRVOperandType::NUMBERID, ContinueBBID);
5195 Ops.push_back(ContinueBBIDOp);
5196
5197 SPIRVOperand *SelectionControlOp = new SPIRVOperand(
5198 SPIRVOperandType::NUMBERID, spv::SelectionControlMaskNone);
5199 Ops.push_back(SelectionControlOp);
5200
5201 SPIRVInstruction *MergeInst =
5202 new SPIRVInstruction(4, spv::OpLoopMerge, 0 /* No id */, Ops);
5203 SPIRVInstList.insert(InsertPoint, MergeInst);
5204
5205 } else if (Br->isConditional()) {
5206 bool HasBackEdge = false;
5207
5208 for (unsigned i = 0; i < Br->getNumSuccessors(); i++) {
5209 if (LI.isLoopHeader(Br->getSuccessor(i))) {
5210 HasBackEdge = true;
5211 }
5212 }
5213 if (!HasBackEdge) {
5214 //
5215 // Generate OpSelectionMerge.
5216 //
5217 // Ops[0] = Merge Block ID
5218 // Ops[1] = Selection Control
5219 SPIRVOperandList Ops;
5220
5221 // StructurizeCFG pass already manipulated CFG. Just use false block
5222 // of branch instruction as merge block.
5223 uint32_t MergeBBID = VMap[Br->getSuccessor(1)];
5224 SPIRVOperand *MergeBBIDOp =
5225 new SPIRVOperand(SPIRVOperandType::NUMBERID, MergeBBID);
5226 Ops.push_back(MergeBBIDOp);
5227
5228 SPIRVOperand *SelectionControlOp = new SPIRVOperand(
5229 SPIRVOperandType::NUMBERID, spv::SelectionControlMaskNone);
5230 Ops.push_back(SelectionControlOp);
5231
5232 SPIRVInstruction *MergeInst = new SPIRVInstruction(
5233 3, spv::OpSelectionMerge, 0 /* No id */, Ops);
5234 SPIRVInstList.insert(InsertPoint, MergeInst);
5235 }
5236 }
5237
5238 if (Br->isConditional()) {
5239 //
5240 // Generate OpBranchConditional.
5241 //
5242 // Ops[0] = Condition ID
5243 // Ops[1] = True Label ID
5244 // Ops[2] = False Label ID
5245 // Ops[3] ... Ops[n] = Branch weights (Literal Number)
5246 SPIRVOperandList Ops;
5247
5248 uint32_t CondID = VMap[Br->getCondition()];
5249 SPIRVOperand *CondIDOp =
5250 new SPIRVOperand(SPIRVOperandType::NUMBERID, CondID);
5251 Ops.push_back(CondIDOp);
5252
5253 uint32_t TrueBBID = VMap[Br->getSuccessor(0)];
5254 SPIRVOperand *TrueBBIDOp =
5255 new SPIRVOperand(SPIRVOperandType::NUMBERID, TrueBBID);
5256 Ops.push_back(TrueBBIDOp);
5257
5258 uint32_t FalseBBID = VMap[Br->getSuccessor(1)];
5259 SPIRVOperand *FalseBBIDOp =
5260 new SPIRVOperand(SPIRVOperandType::NUMBERID, FalseBBID);
5261 Ops.push_back(FalseBBIDOp);
5262
5263 SPIRVInstruction *BrInst = new SPIRVInstruction(
5264 4, spv::OpBranchConditional, 0 /* No id */, Ops);
5265 SPIRVInstList.insert(InsertPoint, BrInst);
5266 } else {
5267 //
5268 // Generate OpBranch.
5269 //
5270 // Ops[0] = Target Label ID
5271 SPIRVOperandList Ops;
5272
5273 uint32_t TargetID = VMap[Br->getSuccessor(0)];
5274 SPIRVOperand *TargetIDOp =
5275 new SPIRVOperand(SPIRVOperandType::NUMBERID, TargetID);
5276 Ops.push_back(TargetIDOp);
5277
5278 SPIRVInstList.insert(
5279 InsertPoint,
5280 new SPIRVInstruction(2, spv::OpBranch, 0 /* No id */, Ops));
5281 }
5282 } else if (PHINode *PHI = dyn_cast<PHINode>(Inst)) {
5283 //
5284 // Generate OpPhi.
5285 //
5286 // Ops[0] = Result Type ID
5287 // Ops[1] ... Ops[n] = (Variable ID, Parent ID) pairs
5288 SPIRVOperandList Ops;
5289
5290 uint32_t ResTyID = lookupType(PHI->getType());
5291 SPIRVOperand *ResTyIDOp =
5292 new SPIRVOperand(SPIRVOperandType::NUMBERID, ResTyID);
5293 Ops.push_back(ResTyIDOp);
5294
5295 uint16_t WordCount = 3;
5296 for (unsigned i = 0; i < PHI->getNumIncomingValues(); i++) {
5297 uint32_t VarID = VMap[PHI->getIncomingValue(i)];
5298 SPIRVOperand *VarIDOp =
5299 new SPIRVOperand(SPIRVOperandType::NUMBERID, VarID);
5300 Ops.push_back(VarIDOp);
5301
5302 uint32_t ParentID = VMap[PHI->getIncomingBlock(i)];
5303 SPIRVOperand *ParentIDOp =
5304 new SPIRVOperand(SPIRVOperandType::NUMBERID, ParentID);
5305 Ops.push_back(ParentIDOp);
5306
5307 WordCount += 2;
5308 }
5309
5310 SPIRVInstList.insert(
5311 InsertPoint, new SPIRVInstruction(WordCount, spv::OpPhi,
5312 std::get<2>(*DeferredInst), Ops));
5313 } else if (CallInst *Call = dyn_cast<CallInst>(Inst)) {
5314 Function *Callee = Call->getCalledFunction();
David Neto3fbb4072017-10-16 11:28:14 -04005315 auto callee_name = Callee->getName();
5316 glsl::ExtInst EInst = getDirectOrIndirectExtInstEnum(callee_name);
David Neto22f144c2017-06-12 14:26:21 -04005317
5318 if (EInst) {
5319 uint32_t &ExtInstImportID = getOpExtInstImportID();
5320
5321 //
5322 // Generate OpExtInst.
5323 //
5324
5325 // Ops[0] = Result Type ID
5326 // Ops[1] = Set ID (OpExtInstImport ID)
5327 // Ops[2] = Instruction Number (Literal Number)
5328 // Ops[3] ... Ops[n] = Operand 1, ... , Operand n
5329 SPIRVOperandList Ops;
5330
5331 uint32_t ResTyID = lookupType(Call->getType());
5332 SPIRVOperand *ResTyIDOp =
5333 new SPIRVOperand(SPIRVOperandType::NUMBERID, ResTyID);
5334 Ops.push_back(ResTyIDOp);
5335
5336 SPIRVOperand *SetIDOp =
5337 new SPIRVOperand(SPIRVOperandType::NUMBERID, ExtInstImportID);
5338 Ops.push_back(SetIDOp);
5339
5340 std::vector<uint32_t> LiteralNum;
5341 LiteralNum.push_back(EInst);
5342 SPIRVOperand *InstructionOp =
5343 new SPIRVOperand(SPIRVOperandType::LITERAL_INTEGER, LiteralNum);
5344 Ops.push_back(InstructionOp);
5345
5346 uint16_t WordCount = 5;
5347
5348 FunctionType *CalleeFTy = cast<FunctionType>(Call->getFunctionType());
5349 for (unsigned i = 0; i < CalleeFTy->getNumParams(); i++) {
5350 uint32_t ArgID = VMap[Call->getOperand(i)];
5351 SPIRVOperand *ArgIDOp =
5352 new SPIRVOperand(SPIRVOperandType::NUMBERID, ArgID);
5353 Ops.push_back(ArgIDOp);
5354 WordCount++;
5355 }
5356
5357 SPIRVInstruction *ExtInst = new SPIRVInstruction(
5358 WordCount, spv::OpExtInst, std::get<2>(*DeferredInst), Ops);
5359 SPIRVInstList.insert(InsertPoint, ExtInst);
5360
David Neto3fbb4072017-10-16 11:28:14 -04005361 const auto IndirectExtInst = getIndirectExtInstEnum(callee_name);
5362 if (IndirectExtInst != kGlslExtInstBad) {
5363 // Generate one more instruction that uses the result of the extended
5364 // instruction. Its result id is one more than the id of the
5365 // extended instruction.
David Neto22f144c2017-06-12 14:26:21 -04005366 LLVMContext &Context =
5367 Call->getParent()->getParent()->getParent()->getContext();
David Neto22f144c2017-06-12 14:26:21 -04005368
David Neto3fbb4072017-10-16 11:28:14 -04005369 auto generate_extra_inst = [this, &Context, &Call, &DeferredInst,
5370 &VMap, &SPIRVInstList, &InsertPoint](
5371 spv::Op opcode, Constant *constant) {
5372 //
5373 // Generate instruction like:
5374 // result = opcode constant <extinst-result>
5375 //
5376 // Ops[0] = Result Type ID
5377 // Ops[1] = Operand 0 ;; the constant, suitably splatted
5378 // Ops[2] = Operand 1 ;; the result of the extended instruction
5379 SPIRVOperandList Ops;
David Neto22f144c2017-06-12 14:26:21 -04005380
David Neto3fbb4072017-10-16 11:28:14 -04005381 Type *resultTy = Call->getType();
5382 Ops.push_back(new SPIRVOperand(SPIRVOperandType::NUMBERID,
5383 lookupType(resultTy)));
5384
5385 if (auto *vectorTy = dyn_cast<VectorType>(resultTy)) {
5386 constant = ConstantVector::getSplat(
5387 static_cast<unsigned>(vectorTy->getNumElements()), constant);
5388 }
5389 uint32_t Op0ID = VMap[constant];
5390 SPIRVOperand *Op0IDOp =
5391 new SPIRVOperand(SPIRVOperandType::NUMBERID, Op0ID);
5392 Ops.push_back(Op0IDOp);
5393
5394 SPIRVOperand *Op1IDOp = new SPIRVOperand(
5395 SPIRVOperandType::NUMBERID, std::get<2>(*DeferredInst));
5396 Ops.push_back(Op1IDOp);
5397
5398 SPIRVInstList.insert(
5399 InsertPoint,
5400 new SPIRVInstruction(5, opcode, std::get<2>(*DeferredInst) + 1,
5401 Ops));
5402 };
5403
5404 switch (IndirectExtInst) {
5405 case glsl::ExtInstFindUMsb: // Implementing clz
5406 generate_extra_inst(
5407 spv::OpISub, ConstantInt::get(Type::getInt32Ty(Context), 31));
5408 break;
5409 case glsl::ExtInstAcos: // Implementing acospi
5410 case glsl::ExtInstAsin: // Implementing asinpi
5411 case glsl::ExtInstAtan2: // Implementing atan2pi
5412 generate_extra_inst(
5413 spv::OpFMul,
5414 ConstantFP::get(Type::getFloatTy(Context), kOneOverPi));
5415 break;
5416
5417 default:
5418 assert(false && "internally inconsistent");
David Neto4d02a532017-09-17 12:57:44 -04005419 }
David Neto22f144c2017-06-12 14:26:21 -04005420 }
David Neto3fbb4072017-10-16 11:28:14 -04005421
David Neto22f144c2017-06-12 14:26:21 -04005422 } else if (Callee->getName().equals("_Z8popcounti") ||
5423 Callee->getName().equals("_Z8popcountj") ||
5424 Callee->getName().equals("_Z8popcountDv2_i") ||
5425 Callee->getName().equals("_Z8popcountDv3_i") ||
5426 Callee->getName().equals("_Z8popcountDv4_i") ||
5427 Callee->getName().equals("_Z8popcountDv2_j") ||
5428 Callee->getName().equals("_Z8popcountDv3_j") ||
5429 Callee->getName().equals("_Z8popcountDv4_j")) {
5430 //
5431 // Generate OpBitCount
5432 //
5433 // Ops[0] = Result Type ID
5434 // Ops[1] = Base ID
5435 SPIRVOperand *Ops[2]{new SPIRVOperand(SPIRVOperandType::NUMBERID,
5436 lookupType(Call->getType())),
5437 new SPIRVOperand(SPIRVOperandType::NUMBERID,
5438 VMap[Call->getOperand(0)])};
5439
5440 SPIRVInstList.insert(
5441 InsertPoint, new SPIRVInstruction(4, spv::OpBitCount,
5442 std::get<2>(*DeferredInst), Ops));
5443 } else {
5444 //
5445 // Generate OpFunctionCall.
5446 //
5447
5448 // Ops[0] = Result Type ID
5449 // Ops[1] = Callee Function ID
5450 // Ops[2] ... Ops[n] = Argument 0, ... , Argument n
5451 SPIRVOperandList Ops;
5452
5453 uint32_t ResTyID = lookupType(Call->getType());
5454 SPIRVOperand *ResTyIDOp =
5455 new SPIRVOperand(SPIRVOperandType::NUMBERID, ResTyID);
5456 Ops.push_back(ResTyIDOp);
5457
5458 uint32_t CalleeID = VMap[Callee];
David Neto43568eb2017-10-13 18:25:25 -04005459 if (CalleeID == 0) {
5460 errs() << "Can't translate function call. Missing builtin? "
5461 << Callee->getName() << " in: " << *Call << "\n";
5462 // TODO(dneto): Can we error out? Enabling this llvm_unreachable
5463 // causes an infinite loop. Instead, go ahead and generate
5464 // the bad function call. A validator will catch the 0-Id.
5465 // llvm_unreachable("Can't translate function call");
5466 }
David Neto22f144c2017-06-12 14:26:21 -04005467
5468 SPIRVOperand *CalleeIDOp =
5469 new SPIRVOperand(SPIRVOperandType::NUMBERID, CalleeID);
5470 Ops.push_back(CalleeIDOp);
5471
5472 uint16_t WordCount = 4;
5473
5474 FunctionType *CalleeFTy = cast<FunctionType>(Call->getFunctionType());
5475 for (unsigned i = 0; i < CalleeFTy->getNumParams(); i++) {
5476 uint32_t ArgID = VMap[Call->getOperand(i)];
5477 SPIRVOperand *ArgIDOp =
5478 new SPIRVOperand(SPIRVOperandType::NUMBERID, ArgID);
5479 Ops.push_back(ArgIDOp);
5480 WordCount++;
5481 }
5482
5483 SPIRVInstruction *CallInst = new SPIRVInstruction(
5484 WordCount, spv::OpFunctionCall, std::get<2>(*DeferredInst), Ops);
5485 SPIRVInstList.insert(InsertPoint, CallInst);
5486 }
5487 }
5488 }
5489}
5490
David Neto1a1a0582017-07-07 12:01:44 -04005491void SPIRVProducerPass::HandleDeferredDecorations(const DataLayout &DL) {
5492 // Insert ArrayStride decorations on pointer types, due to OpPtrAccessChain
5493 // instructions we generated earlier.
5494 if (getPointerTypesNeedingArrayStride().empty())
5495 return;
5496
5497 SPIRVInstructionList &SPIRVInstList = getSPIRVInstList();
David Neto1a1a0582017-07-07 12:01:44 -04005498
5499 // Find an iterator pointing just past the last decoration.
5500 bool seen_decorations = false;
5501 auto DecoInsertPoint =
5502 std::find_if(SPIRVInstList.begin(), SPIRVInstList.end(),
5503 [&seen_decorations](SPIRVInstruction *Inst) -> bool {
5504 const bool is_decoration =
5505 Inst->getOpcode() == spv::OpDecorate ||
5506 Inst->getOpcode() == spv::OpMemberDecorate;
5507 if (is_decoration) {
5508 seen_decorations = true;
5509 return false;
5510 } else {
5511 return seen_decorations;
5512 }
5513 });
5514
5515 for (auto *type : getPointerTypesNeedingArrayStride()) {
5516 auto *ptrType = cast<PointerType>(type);
5517
5518 // Ops[0] = Target ID
5519 // Ops[1] = Decoration (ArrayStride)
5520 // Ops[2] = Stride number (Literal Number)
5521 SPIRVOperandList Ops;
5522
5523 Ops.push_back(
5524 new SPIRVOperand(SPIRVOperandType::NUMBERID, lookupType(ptrType)));
5525 Ops.push_back(new SPIRVOperand(SPIRVOperandType::NUMBERID,
5526 spv::DecorationArrayStride));
5527 Type *elemTy = ptrType->getElementType();
5528 // Same as DL.getIndexedOfffsetInType( elemTy, { 1 } );
Neil Henning39672102017-09-29 14:33:13 +01005529 const uint32_t stride = static_cast<uint32_t>(DL.getTypeAllocSize(elemTy));
David Neto1a1a0582017-07-07 12:01:44 -04005530 Ops.push_back(new SPIRVOperand(SPIRVOperandType::LITERAL_INTEGER, stride));
5531
5532 SPIRVInstruction *DecoInst =
5533 new SPIRVInstruction(4, spv::OpDecorate, 0 /* No id */, Ops);
5534 SPIRVInstList.insert(DecoInsertPoint, DecoInst);
5535 }
5536}
5537
David Neto22f144c2017-06-12 14:26:21 -04005538glsl::ExtInst SPIRVProducerPass::getExtInstEnum(StringRef Name) {
5539 return StringSwitch<glsl::ExtInst>(Name)
5540 .Case("_Z3absi", glsl::ExtInst::ExtInstSAbs)
5541 .Case("_Z3absDv2_i", glsl::ExtInst::ExtInstSAbs)
5542 .Case("_Z3absDv3_i", glsl::ExtInst::ExtInstSAbs)
5543 .Case("_Z3absDv4_i", glsl::ExtInst::ExtInstSAbs)
5544 .Case("_Z5clampiii", glsl::ExtInst::ExtInstSClamp)
5545 .Case("_Z5clampDv2_iS_S_", glsl::ExtInst::ExtInstSClamp)
5546 .Case("_Z5clampDv3_iS_S_", glsl::ExtInst::ExtInstSClamp)
5547 .Case("_Z5clampDv4_iS_S_", glsl::ExtInst::ExtInstSClamp)
5548 .Case("_Z5clampjjj", glsl::ExtInst::ExtInstUClamp)
5549 .Case("_Z5clampDv2_jS_S_", glsl::ExtInst::ExtInstUClamp)
5550 .Case("_Z5clampDv3_jS_S_", glsl::ExtInst::ExtInstUClamp)
5551 .Case("_Z5clampDv4_jS_S_", glsl::ExtInst::ExtInstUClamp)
5552 .Case("_Z5clampfff", glsl::ExtInst::ExtInstFClamp)
5553 .Case("_Z5clampDv2_fS_S_", glsl::ExtInst::ExtInstFClamp)
5554 .Case("_Z5clampDv3_fS_S_", glsl::ExtInst::ExtInstFClamp)
5555 .Case("_Z5clampDv4_fS_S_", glsl::ExtInst::ExtInstFClamp)
David Neto22f144c2017-06-12 14:26:21 -04005556 .Case("_Z3maxii", glsl::ExtInst::ExtInstSMax)
5557 .Case("_Z3maxDv2_iS_", glsl::ExtInst::ExtInstSMax)
5558 .Case("_Z3maxDv3_iS_", glsl::ExtInst::ExtInstSMax)
5559 .Case("_Z3maxDv4_iS_", glsl::ExtInst::ExtInstSMax)
5560 .Case("_Z3maxjj", glsl::ExtInst::ExtInstUMax)
5561 .Case("_Z3maxDv2_jS_", glsl::ExtInst::ExtInstUMax)
5562 .Case("_Z3maxDv3_jS_", glsl::ExtInst::ExtInstUMax)
5563 .Case("_Z3maxDv4_jS_", glsl::ExtInst::ExtInstUMax)
5564 .Case("_Z3maxff", glsl::ExtInst::ExtInstFMax)
5565 .Case("_Z3maxDv2_fS_", glsl::ExtInst::ExtInstFMax)
5566 .Case("_Z3maxDv3_fS_", glsl::ExtInst::ExtInstFMax)
5567 .Case("_Z3maxDv4_fS_", glsl::ExtInst::ExtInstFMax)
5568 .StartsWith("_Z4fmax", glsl::ExtInst::ExtInstFMax)
5569 .Case("_Z3minii", glsl::ExtInst::ExtInstSMin)
5570 .Case("_Z3minDv2_iS_", glsl::ExtInst::ExtInstSMin)
5571 .Case("_Z3minDv3_iS_", glsl::ExtInst::ExtInstSMin)
5572 .Case("_Z3minDv4_iS_", glsl::ExtInst::ExtInstSMin)
5573 .Case("_Z3minjj", glsl::ExtInst::ExtInstUMin)
5574 .Case("_Z3minDv2_jS_", glsl::ExtInst::ExtInstUMin)
5575 .Case("_Z3minDv3_jS_", glsl::ExtInst::ExtInstUMin)
5576 .Case("_Z3minDv4_jS_", glsl::ExtInst::ExtInstUMin)
5577 .Case("_Z3minff", glsl::ExtInst::ExtInstFMin)
5578 .Case("_Z3minDv2_fS_", glsl::ExtInst::ExtInstFMin)
5579 .Case("_Z3minDv3_fS_", glsl::ExtInst::ExtInstFMin)
5580 .Case("_Z3minDv4_fS_", glsl::ExtInst::ExtInstFMin)
5581 .StartsWith("_Z4fmin", glsl::ExtInst::ExtInstFMin)
5582 .StartsWith("_Z7degrees", glsl::ExtInst::ExtInstDegrees)
5583 .StartsWith("_Z7radians", glsl::ExtInst::ExtInstRadians)
5584 .StartsWith("_Z3mix", glsl::ExtInst::ExtInstFMix)
5585 .StartsWith("_Z4acos", glsl::ExtInst::ExtInstAcos)
5586 .StartsWith("_Z5acosh", glsl::ExtInst::ExtInstAcosh)
5587 .StartsWith("_Z4asin", glsl::ExtInst::ExtInstAsin)
5588 .StartsWith("_Z5asinh", glsl::ExtInst::ExtInstAsinh)
5589 .StartsWith("_Z4atan", glsl::ExtInst::ExtInstAtan)
5590 .StartsWith("_Z5atan2", glsl::ExtInst::ExtInstAtan2)
5591 .StartsWith("_Z5atanh", glsl::ExtInst::ExtInstAtanh)
5592 .StartsWith("_Z4ceil", glsl::ExtInst::ExtInstCeil)
5593 .StartsWith("_Z3sin", glsl::ExtInst::ExtInstSin)
5594 .StartsWith("_Z4sinh", glsl::ExtInst::ExtInstSinh)
5595 .StartsWith("_Z8half_sin", glsl::ExtInst::ExtInstSin)
5596 .StartsWith("_Z10native_sin", glsl::ExtInst::ExtInstSin)
5597 .StartsWith("_Z3cos", glsl::ExtInst::ExtInstCos)
5598 .StartsWith("_Z4cosh", glsl::ExtInst::ExtInstCosh)
5599 .StartsWith("_Z8half_cos", glsl::ExtInst::ExtInstCos)
5600 .StartsWith("_Z10native_cos", glsl::ExtInst::ExtInstCos)
5601 .StartsWith("_Z3tan", glsl::ExtInst::ExtInstTan)
5602 .StartsWith("_Z4tanh", glsl::ExtInst::ExtInstTanh)
5603 .StartsWith("_Z8half_tan", glsl::ExtInst::ExtInstTan)
5604 .StartsWith("_Z10native_tan", glsl::ExtInst::ExtInstTan)
5605 .StartsWith("_Z3exp", glsl::ExtInst::ExtInstExp)
5606 .StartsWith("_Z8half_exp", glsl::ExtInst::ExtInstExp)
5607 .StartsWith("_Z10native_exp", glsl::ExtInst::ExtInstExp)
5608 .StartsWith("_Z4exp2", glsl::ExtInst::ExtInstExp2)
5609 .StartsWith("_Z9half_exp2", glsl::ExtInst::ExtInstExp2)
5610 .StartsWith("_Z11native_exp2", glsl::ExtInst::ExtInstExp2)
5611 .StartsWith("_Z3log", glsl::ExtInst::ExtInstLog)
5612 .StartsWith("_Z8half_log", glsl::ExtInst::ExtInstLog)
5613 .StartsWith("_Z10native_log", glsl::ExtInst::ExtInstLog)
5614 .StartsWith("_Z4log2", glsl::ExtInst::ExtInstLog2)
5615 .StartsWith("_Z9half_log2", glsl::ExtInst::ExtInstLog2)
5616 .StartsWith("_Z11native_log2", glsl::ExtInst::ExtInstLog2)
5617 .StartsWith("_Z4fabs", glsl::ExtInst::ExtInstFAbs)
5618 .StartsWith("_Z5floor", glsl::ExtInst::ExtInstFloor)
5619 .StartsWith("_Z5ldexp", glsl::ExtInst::ExtInstLdexp)
5620 .StartsWith("_Z3pow", glsl::ExtInst::ExtInstPow)
5621 .StartsWith("_Z4powr", glsl::ExtInst::ExtInstPow)
5622 .StartsWith("_Z9half_powr", glsl::ExtInst::ExtInstPow)
5623 .StartsWith("_Z11native_powr", glsl::ExtInst::ExtInstPow)
5624 .StartsWith("_Z5round", glsl::ExtInst::ExtInstRound)
5625 .StartsWith("_Z4sqrt", glsl::ExtInst::ExtInstSqrt)
5626 .StartsWith("_Z9half_sqrt", glsl::ExtInst::ExtInstSqrt)
5627 .StartsWith("_Z11native_sqrt", glsl::ExtInst::ExtInstSqrt)
5628 .StartsWith("_Z5rsqrt", glsl::ExtInst::ExtInstInverseSqrt)
5629 .StartsWith("_Z10half_rsqrt", glsl::ExtInst::ExtInstInverseSqrt)
5630 .StartsWith("_Z12native_rsqrt", glsl::ExtInst::ExtInstInverseSqrt)
5631 .StartsWith("_Z5trunc", glsl::ExtInst::ExtInstTrunc)
5632 .StartsWith("_Z5frexp", glsl::ExtInst::ExtInstFrexp)
5633 .StartsWith("_Z4sign", glsl::ExtInst::ExtInstFSign)
5634 .StartsWith("_Z6length", glsl::ExtInst::ExtInstLength)
5635 .StartsWith("_Z8distance", glsl::ExtInst::ExtInstDistance)
David Netoe9a03512017-10-16 10:08:27 -04005636 .StartsWith("_Z4step", glsl::ExtInst::ExtInstStep)
David Neto22f144c2017-06-12 14:26:21 -04005637 .Case("_Z5crossDv3_fS_", glsl::ExtInst::ExtInstCross)
5638 .StartsWith("_Z9normalize", glsl::ExtInst::ExtInstNormalize)
5639 .StartsWith("llvm.fmuladd.", glsl::ExtInst::ExtInstFma)
5640 .Case("spirv.unpack.v2f16", glsl::ExtInst::ExtInstUnpackHalf2x16)
5641 .Case("spirv.pack.v2f16", glsl::ExtInst::ExtInstPackHalf2x16)
David Neto62653202017-10-16 19:05:18 -04005642 .Case("clspv.fract.f", glsl::ExtInst::ExtInstFract)
5643 .Case("clspv.fract.v2f", glsl::ExtInst::ExtInstFract)
5644 .Case("clspv.fract.v3f", glsl::ExtInst::ExtInstFract)
5645 .Case("clspv.fract.v4f", glsl::ExtInst::ExtInstFract)
David Neto3fbb4072017-10-16 11:28:14 -04005646 .Default(kGlslExtInstBad);
5647}
5648
5649glsl::ExtInst SPIRVProducerPass::getIndirectExtInstEnum(StringRef Name) {
5650 // Check indirect cases.
5651 return StringSwitch<glsl::ExtInst>(Name)
5652 .StartsWith("_Z3clz", glsl::ExtInst::ExtInstFindUMsb)
5653 // Use exact match on float arg because these need a multiply
5654 // of a constant of the right floating point type.
5655 .Case("_Z6acospif", glsl::ExtInst::ExtInstAcos)
5656 .Case("_Z6acospiDv2_f", glsl::ExtInst::ExtInstAcos)
5657 .Case("_Z6acospiDv3_f", glsl::ExtInst::ExtInstAcos)
5658 .Case("_Z6acospiDv4_f", glsl::ExtInst::ExtInstAcos)
5659 .Case("_Z6asinpif", glsl::ExtInst::ExtInstAsin)
5660 .Case("_Z6asinpiDv2_f", glsl::ExtInst::ExtInstAsin)
5661 .Case("_Z6asinpiDv3_f", glsl::ExtInst::ExtInstAsin)
5662 .Case("_Z6asinpiDv4_f", glsl::ExtInst::ExtInstAsin)
5663 .Case("_Z7atan2piff", glsl::ExtInst::ExtInstAtan2)
5664 .Case("_Z7atan2piDv2_fS_", glsl::ExtInst::ExtInstAtan2)
5665 .Case("_Z7atan2piDv3_fS_", glsl::ExtInst::ExtInstAtan2)
5666 .Case("_Z7atan2piDv4_fS_", glsl::ExtInst::ExtInstAtan2)
5667 .Default(kGlslExtInstBad);
5668}
5669
5670glsl::ExtInst SPIRVProducerPass::getDirectOrIndirectExtInstEnum(StringRef Name) {
5671 auto direct = getExtInstEnum(Name);
5672 if (direct != kGlslExtInstBad)
5673 return direct;
5674 return getIndirectExtInstEnum(Name);
David Neto22f144c2017-06-12 14:26:21 -04005675}
5676
5677void SPIRVProducerPass::PrintResID(SPIRVInstruction *Inst) {
5678 out << "%" << Inst->getResultID();
5679}
5680
5681void SPIRVProducerPass::PrintOpcode(SPIRVInstruction *Inst) {
5682 spv::Op Opcode = static_cast<spv::Op>(Inst->getOpcode());
5683 out << "\t" << spv::getOpName(Opcode);
5684}
5685
5686void SPIRVProducerPass::PrintOperand(SPIRVOperand *Op) {
5687 SPIRVOperandType OpTy = Op->getType();
5688 switch (OpTy) {
5689 default: {
5690 llvm_unreachable("Unsupported SPIRV Operand Type???");
5691 break;
5692 }
5693 case SPIRVOperandType::NUMBERID: {
5694 out << "%" << Op->getNumID();
5695 break;
5696 }
5697 case SPIRVOperandType::LITERAL_STRING: {
5698 out << "\"" << Op->getLiteralStr() << "\"";
5699 break;
5700 }
5701 case SPIRVOperandType::LITERAL_INTEGER: {
5702 // TODO: Handle LiteralNum carefully.
5703 for (auto Word : Op->getLiteralNum()) {
5704 out << Word;
5705 }
5706 break;
5707 }
5708 case SPIRVOperandType::LITERAL_FLOAT: {
5709 // TODO: Handle LiteralNum carefully.
5710 for (auto Word : Op->getLiteralNum()) {
5711 APFloat APF = APFloat(APFloat::IEEEsingle(), APInt(32, Word));
5712 SmallString<8> Str;
5713 APF.toString(Str, 6, 2);
5714 out << Str;
5715 }
5716 break;
5717 }
5718 }
5719}
5720
5721void SPIRVProducerPass::PrintCapability(SPIRVOperand *Op) {
5722 spv::Capability Cap = static_cast<spv::Capability>(Op->getNumID());
5723 out << spv::getCapabilityName(Cap);
5724}
5725
5726void SPIRVProducerPass::PrintExtInst(SPIRVOperand *Op) {
5727 auto LiteralNum = Op->getLiteralNum();
5728 glsl::ExtInst Ext = static_cast<glsl::ExtInst>(LiteralNum[0]);
5729 out << glsl::getExtInstName(Ext);
5730}
5731
5732void SPIRVProducerPass::PrintAddrModel(SPIRVOperand *Op) {
5733 spv::AddressingModel AddrModel =
5734 static_cast<spv::AddressingModel>(Op->getNumID());
5735 out << spv::getAddressingModelName(AddrModel);
5736}
5737
5738void SPIRVProducerPass::PrintMemModel(SPIRVOperand *Op) {
5739 spv::MemoryModel MemModel = static_cast<spv::MemoryModel>(Op->getNumID());
5740 out << spv::getMemoryModelName(MemModel);
5741}
5742
5743void SPIRVProducerPass::PrintExecModel(SPIRVOperand *Op) {
5744 spv::ExecutionModel ExecModel =
5745 static_cast<spv::ExecutionModel>(Op->getNumID());
5746 out << spv::getExecutionModelName(ExecModel);
5747}
5748
5749void SPIRVProducerPass::PrintExecMode(SPIRVOperand *Op) {
5750 spv::ExecutionMode ExecMode = static_cast<spv::ExecutionMode>(Op->getNumID());
5751 out << spv::getExecutionModeName(ExecMode);
5752}
5753
5754void SPIRVProducerPass::PrintSourceLanguage(SPIRVOperand *Op) {
5755 spv::SourceLanguage SourceLang = static_cast<spv::SourceLanguage>(Op->getNumID());
5756 out << spv::getSourceLanguageName(SourceLang);
5757}
5758
5759void SPIRVProducerPass::PrintFuncCtrl(SPIRVOperand *Op) {
5760 spv::FunctionControlMask FuncCtrl =
5761 static_cast<spv::FunctionControlMask>(Op->getNumID());
5762 out << spv::getFunctionControlName(FuncCtrl);
5763}
5764
5765void SPIRVProducerPass::PrintStorageClass(SPIRVOperand *Op) {
5766 spv::StorageClass StClass = static_cast<spv::StorageClass>(Op->getNumID());
5767 out << getStorageClassName(StClass);
5768}
5769
5770void SPIRVProducerPass::PrintDecoration(SPIRVOperand *Op) {
5771 spv::Decoration Deco = static_cast<spv::Decoration>(Op->getNumID());
5772 out << getDecorationName(Deco);
5773}
5774
5775void SPIRVProducerPass::PrintBuiltIn(SPIRVOperand *Op) {
5776 spv::BuiltIn BIn = static_cast<spv::BuiltIn>(Op->getNumID());
5777 out << getBuiltInName(BIn);
5778}
5779
5780void SPIRVProducerPass::PrintSelectionControl(SPIRVOperand *Op) {
5781 spv::SelectionControlMask BIn =
5782 static_cast<spv::SelectionControlMask>(Op->getNumID());
5783 out << getSelectionControlName(BIn);
5784}
5785
5786void SPIRVProducerPass::PrintLoopControl(SPIRVOperand *Op) {
5787 spv::LoopControlMask BIn = static_cast<spv::LoopControlMask>(Op->getNumID());
5788 out << getLoopControlName(BIn);
5789}
5790
5791void SPIRVProducerPass::PrintDimensionality(SPIRVOperand *Op) {
5792 spv::Dim DIM = static_cast<spv::Dim>(Op->getNumID());
5793 out << getDimName(DIM);
5794}
5795
5796void SPIRVProducerPass::PrintImageFormat(SPIRVOperand *Op) {
5797 spv::ImageFormat Format = static_cast<spv::ImageFormat>(Op->getNumID());
5798 out << getImageFormatName(Format);
5799}
5800
5801void SPIRVProducerPass::PrintMemoryAccess(SPIRVOperand *Op) {
5802 out << spv::getMemoryAccessName(
5803 static_cast<spv::MemoryAccessMask>(Op->getNumID()));
5804}
5805
5806void SPIRVProducerPass::PrintImageOperandsType(SPIRVOperand *Op) {
5807 auto LiteralNum = Op->getLiteralNum();
5808 spv::ImageOperandsMask Type =
5809 static_cast<spv::ImageOperandsMask>(LiteralNum[0]);
5810 out << getImageOperandsName(Type);
5811}
5812
5813void SPIRVProducerPass::WriteSPIRVAssembly() {
5814 SPIRVInstructionList &SPIRVInstList = getSPIRVInstList();
5815
5816 for (auto Inst : SPIRVInstList) {
5817 SPIRVOperandList Ops = Inst->getOperands();
5818 spv::Op Opcode = static_cast<spv::Op>(Inst->getOpcode());
5819
5820 switch (Opcode) {
5821 default: {
5822 llvm_unreachable("Unsupported SPIRV instruction");
5823 break;
5824 }
5825 case spv::OpCapability: {
5826 // Ops[0] = Capability
5827 PrintOpcode(Inst);
5828 out << " ";
5829 PrintCapability(Ops[0]);
5830 out << "\n";
5831 break;
5832 }
5833 case spv::OpMemoryModel: {
5834 // Ops[0] = Addressing Model
5835 // Ops[1] = Memory Model
5836 PrintOpcode(Inst);
5837 out << " ";
5838 PrintAddrModel(Ops[0]);
5839 out << " ";
5840 PrintMemModel(Ops[1]);
5841 out << "\n";
5842 break;
5843 }
5844 case spv::OpEntryPoint: {
5845 // Ops[0] = Execution Model
5846 // Ops[1] = EntryPoint ID
5847 // Ops[2] = Name (Literal String)
5848 // Ops[3] ... Ops[n] = Interface ID
5849 PrintOpcode(Inst);
5850 out << " ";
5851 PrintExecModel(Ops[0]);
5852 for (uint32_t i = 1; i < Ops.size(); i++) {
5853 out << " ";
5854 PrintOperand(Ops[i]);
5855 }
5856 out << "\n";
5857 break;
5858 }
5859 case spv::OpExecutionMode: {
5860 // Ops[0] = Entry Point ID
5861 // Ops[1] = Execution Mode
5862 // Ops[2] ... Ops[n] = Optional literals according to Execution Mode
5863 PrintOpcode(Inst);
5864 out << " ";
5865 PrintOperand(Ops[0]);
5866 out << " ";
5867 PrintExecMode(Ops[1]);
5868 for (uint32_t i = 2; i < Ops.size(); i++) {
5869 out << " ";
5870 PrintOperand(Ops[i]);
5871 }
5872 out << "\n";
5873 break;
5874 }
5875 case spv::OpSource: {
5876 // Ops[0] = SourceLanguage ID
5877 // Ops[1] = Version (LiteralNum)
5878 PrintOpcode(Inst);
5879 out << " ";
5880 PrintSourceLanguage(Ops[0]);
5881 out << " ";
5882 PrintOperand(Ops[1]);
5883 out << "\n";
5884 break;
5885 }
5886 case spv::OpDecorate: {
5887 // Ops[0] = Target ID
5888 // Ops[1] = Decoration (Block or BufferBlock)
5889 // Ops[2] ... Ops[n] = Optional literals according to Decoration
5890 PrintOpcode(Inst);
5891 out << " ";
5892 PrintOperand(Ops[0]);
5893 out << " ";
5894 PrintDecoration(Ops[1]);
5895 // Handle BuiltIn OpDecorate specially.
5896 if (Ops[1]->getNumID() == spv::DecorationBuiltIn) {
5897 out << " ";
5898 PrintBuiltIn(Ops[2]);
5899 } else {
5900 for (uint32_t i = 2; i < Ops.size(); i++) {
5901 out << " ";
5902 PrintOperand(Ops[i]);
5903 }
5904 }
5905 out << "\n";
5906 break;
5907 }
5908 case spv::OpMemberDecorate: {
5909 // Ops[0] = Structure Type ID
5910 // Ops[1] = Member Index(Literal Number)
5911 // Ops[2] = Decoration
5912 // Ops[3] ... Ops[n] = Optional literals according to Decoration
5913 PrintOpcode(Inst);
5914 out << " ";
5915 PrintOperand(Ops[0]);
5916 out << " ";
5917 PrintOperand(Ops[1]);
5918 out << " ";
5919 PrintDecoration(Ops[2]);
5920 for (uint32_t i = 3; i < Ops.size(); i++) {
5921 out << " ";
5922 PrintOperand(Ops[i]);
5923 }
5924 out << "\n";
5925 break;
5926 }
5927 case spv::OpTypePointer: {
5928 // Ops[0] = Storage Class
5929 // Ops[1] = Element Type ID
5930 PrintResID(Inst);
5931 out << " = ";
5932 PrintOpcode(Inst);
5933 out << " ";
5934 PrintStorageClass(Ops[0]);
5935 out << " ";
5936 PrintOperand(Ops[1]);
5937 out << "\n";
5938 break;
5939 }
5940 case spv::OpTypeImage: {
5941 // Ops[0] = Sampled Type ID
5942 // Ops[1] = Dim ID
5943 // Ops[2] = Depth (Literal Number)
5944 // Ops[3] = Arrayed (Literal Number)
5945 // Ops[4] = MS (Literal Number)
5946 // Ops[5] = Sampled (Literal Number)
5947 // Ops[6] = Image Format ID
5948 PrintResID(Inst);
5949 out << " = ";
5950 PrintOpcode(Inst);
5951 out << " ";
5952 PrintOperand(Ops[0]);
5953 out << " ";
5954 PrintDimensionality(Ops[1]);
5955 out << " ";
5956 PrintOperand(Ops[2]);
5957 out << " ";
5958 PrintOperand(Ops[3]);
5959 out << " ";
5960 PrintOperand(Ops[4]);
5961 out << " ";
5962 PrintOperand(Ops[5]);
5963 out << " ";
5964 PrintImageFormat(Ops[6]);
5965 out << "\n";
5966 break;
5967 }
5968 case spv::OpFunction: {
5969 // Ops[0] : Result Type ID
5970 // Ops[1] : Function Control
5971 // Ops[2] : Function Type ID
5972 PrintResID(Inst);
5973 out << " = ";
5974 PrintOpcode(Inst);
5975 out << " ";
5976 PrintOperand(Ops[0]);
5977 out << " ";
5978 PrintFuncCtrl(Ops[1]);
5979 out << " ";
5980 PrintOperand(Ops[2]);
5981 out << "\n";
5982 break;
5983 }
5984 case spv::OpSelectionMerge: {
5985 // Ops[0] = Merge Block ID
5986 // Ops[1] = Selection Control
5987 PrintOpcode(Inst);
5988 out << " ";
5989 PrintOperand(Ops[0]);
5990 out << " ";
5991 PrintSelectionControl(Ops[1]);
5992 out << "\n";
5993 break;
5994 }
5995 case spv::OpLoopMerge: {
5996 // Ops[0] = Merge Block ID
5997 // Ops[1] = Continue Target ID
5998 // Ops[2] = Selection Control
5999 PrintOpcode(Inst);
6000 out << " ";
6001 PrintOperand(Ops[0]);
6002 out << " ";
6003 PrintOperand(Ops[1]);
6004 out << " ";
6005 PrintLoopControl(Ops[2]);
6006 out << "\n";
6007 break;
6008 }
6009 case spv::OpImageSampleExplicitLod: {
6010 // Ops[0] = Result Type ID
6011 // Ops[1] = Sampled Image ID
6012 // Ops[2] = Coordinate ID
6013 // Ops[3] = Image Operands Type ID
6014 // Ops[4] ... Ops[n] = Operands ID
6015 PrintResID(Inst);
6016 out << " = ";
6017 PrintOpcode(Inst);
6018 for (uint32_t i = 0; i < 3; i++) {
6019 out << " ";
6020 PrintOperand(Ops[i]);
6021 }
6022 out << " ";
6023 PrintImageOperandsType(Ops[3]);
6024 for (uint32_t i = 4; i < Ops.size(); i++) {
6025 out << " ";
6026 PrintOperand(Ops[i]);
6027 }
6028 out << "\n";
6029 break;
6030 }
6031 case spv::OpVariable: {
6032 // Ops[0] : Result Type ID
6033 // Ops[1] : Storage Class
6034 // Ops[2] ... Ops[n] = Initializer IDs
6035 PrintResID(Inst);
6036 out << " = ";
6037 PrintOpcode(Inst);
6038 out << " ";
6039 PrintOperand(Ops[0]);
6040 out << " ";
6041 PrintStorageClass(Ops[1]);
6042 for (uint32_t i = 2; i < Ops.size(); i++) {
6043 out << " ";
6044 PrintOperand(Ops[i]);
6045 }
6046 out << "\n";
6047 break;
6048 }
6049 case spv::OpExtInst: {
6050 // Ops[0] = Result Type ID
6051 // Ops[1] = Set ID (OpExtInstImport ID)
6052 // Ops[2] = Instruction Number (Literal Number)
6053 // Ops[3] ... Ops[n] = Operand 1, ... , Operand n
6054 PrintResID(Inst);
6055 out << " = ";
6056 PrintOpcode(Inst);
6057 out << " ";
6058 PrintOperand(Ops[0]);
6059 out << " ";
6060 PrintOperand(Ops[1]);
6061 out << " ";
6062 PrintExtInst(Ops[2]);
6063 for (uint32_t i = 3; i < Ops.size(); i++) {
6064 out << " ";
6065 PrintOperand(Ops[i]);
6066 }
6067 out << "\n";
6068 break;
6069 }
6070 case spv::OpCopyMemory: {
6071 // Ops[0] = Addressing Model
6072 // Ops[1] = Memory Model
6073 PrintOpcode(Inst);
6074 out << " ";
6075 PrintOperand(Ops[0]);
6076 out << " ";
6077 PrintOperand(Ops[1]);
6078 out << " ";
6079 PrintMemoryAccess(Ops[2]);
6080 out << " ";
6081 PrintOperand(Ops[3]);
6082 out << "\n";
6083 break;
6084 }
6085 case spv::OpExtension:
6086 case spv::OpControlBarrier:
6087 case spv::OpMemoryBarrier:
6088 case spv::OpBranch:
6089 case spv::OpBranchConditional:
6090 case spv::OpStore:
6091 case spv::OpImageWrite:
6092 case spv::OpReturnValue:
6093 case spv::OpReturn:
6094 case spv::OpFunctionEnd: {
6095 PrintOpcode(Inst);
6096 for (uint32_t i = 0; i < Ops.size(); i++) {
6097 out << " ";
6098 PrintOperand(Ops[i]);
6099 }
6100 out << "\n";
6101 break;
6102 }
6103 case spv::OpExtInstImport:
6104 case spv::OpTypeRuntimeArray:
6105 case spv::OpTypeStruct:
6106 case spv::OpTypeSampler:
6107 case spv::OpTypeSampledImage:
6108 case spv::OpTypeInt:
6109 case spv::OpTypeFloat:
6110 case spv::OpTypeArray:
6111 case spv::OpTypeVector:
6112 case spv::OpTypeBool:
6113 case spv::OpTypeVoid:
6114 case spv::OpTypeFunction:
6115 case spv::OpFunctionParameter:
6116 case spv::OpLabel:
6117 case spv::OpPhi:
6118 case spv::OpLoad:
6119 case spv::OpSelect:
6120 case spv::OpAccessChain:
6121 case spv::OpPtrAccessChain:
6122 case spv::OpInBoundsAccessChain:
6123 case spv::OpUConvert:
6124 case spv::OpSConvert:
6125 case spv::OpConvertFToU:
6126 case spv::OpConvertFToS:
6127 case spv::OpConvertUToF:
6128 case spv::OpConvertSToF:
6129 case spv::OpFConvert:
6130 case spv::OpConvertPtrToU:
6131 case spv::OpConvertUToPtr:
6132 case spv::OpBitcast:
6133 case spv::OpIAdd:
6134 case spv::OpFAdd:
6135 case spv::OpISub:
6136 case spv::OpFSub:
6137 case spv::OpIMul:
6138 case spv::OpFMul:
6139 case spv::OpUDiv:
6140 case spv::OpSDiv:
6141 case spv::OpFDiv:
6142 case spv::OpUMod:
6143 case spv::OpSRem:
6144 case spv::OpFRem:
6145 case spv::OpBitwiseOr:
6146 case spv::OpBitwiseXor:
6147 case spv::OpBitwiseAnd:
David Netoa394f392017-08-26 20:45:29 -04006148 case spv::OpNot:
David Neto22f144c2017-06-12 14:26:21 -04006149 case spv::OpShiftLeftLogical:
6150 case spv::OpShiftRightLogical:
6151 case spv::OpShiftRightArithmetic:
6152 case spv::OpBitCount:
6153 case spv::OpCompositeExtract:
6154 case spv::OpVectorExtractDynamic:
6155 case spv::OpCompositeInsert:
David Neto0a2f98d2017-09-15 19:38:40 -04006156 case spv::OpCopyObject:
David Neto22f144c2017-06-12 14:26:21 -04006157 case spv::OpVectorInsertDynamic:
6158 case spv::OpVectorShuffle:
6159 case spv::OpIEqual:
6160 case spv::OpINotEqual:
6161 case spv::OpUGreaterThan:
6162 case spv::OpUGreaterThanEqual:
6163 case spv::OpULessThan:
6164 case spv::OpULessThanEqual:
6165 case spv::OpSGreaterThan:
6166 case spv::OpSGreaterThanEqual:
6167 case spv::OpSLessThan:
6168 case spv::OpSLessThanEqual:
6169 case spv::OpFOrdEqual:
6170 case spv::OpFOrdGreaterThan:
6171 case spv::OpFOrdGreaterThanEqual:
6172 case spv::OpFOrdLessThan:
6173 case spv::OpFOrdLessThanEqual:
6174 case spv::OpFOrdNotEqual:
6175 case spv::OpFUnordEqual:
6176 case spv::OpFUnordGreaterThan:
6177 case spv::OpFUnordGreaterThanEqual:
6178 case spv::OpFUnordLessThan:
6179 case spv::OpFUnordLessThanEqual:
6180 case spv::OpFUnordNotEqual:
6181 case spv::OpSampledImage:
6182 case spv::OpFunctionCall:
6183 case spv::OpConstantTrue:
6184 case spv::OpConstantFalse:
6185 case spv::OpConstant:
6186 case spv::OpSpecConstant:
6187 case spv::OpConstantComposite:
6188 case spv::OpSpecConstantComposite:
6189 case spv::OpConstantNull:
6190 case spv::OpLogicalOr:
6191 case spv::OpLogicalAnd:
6192 case spv::OpLogicalNot:
6193 case spv::OpLogicalNotEqual:
6194 case spv::OpUndef:
6195 case spv::OpIsInf:
6196 case spv::OpIsNan:
6197 case spv::OpAny:
6198 case spv::OpAll:
6199 case spv::OpAtomicIAdd:
6200 case spv::OpAtomicISub:
6201 case spv::OpAtomicExchange:
6202 case spv::OpAtomicIIncrement:
6203 case spv::OpAtomicIDecrement:
6204 case spv::OpAtomicCompareExchange:
6205 case spv::OpAtomicUMin:
6206 case spv::OpAtomicSMin:
6207 case spv::OpAtomicUMax:
6208 case spv::OpAtomicSMax:
6209 case spv::OpAtomicAnd:
6210 case spv::OpAtomicOr:
6211 case spv::OpAtomicXor:
6212 case spv::OpDot: {
6213 PrintResID(Inst);
6214 out << " = ";
6215 PrintOpcode(Inst);
6216 for (uint32_t i = 0; i < Ops.size(); i++) {
6217 out << " ";
6218 PrintOperand(Ops[i]);
6219 }
6220 out << "\n";
6221 break;
6222 }
6223 }
6224 }
6225}
6226
6227void SPIRVProducerPass::WriteOneWord(uint32_t Word) {
David Neto0676e6f2017-07-11 18:47:44 -04006228 binaryOut->write(reinterpret_cast<const char *>(&Word), sizeof(uint32_t));
David Neto22f144c2017-06-12 14:26:21 -04006229}
6230
6231void SPIRVProducerPass::WriteResultID(SPIRVInstruction *Inst) {
6232 WriteOneWord(Inst->getResultID());
6233}
6234
6235void SPIRVProducerPass::WriteWordCountAndOpcode(SPIRVInstruction *Inst) {
6236 // High 16 bit : Word Count
6237 // Low 16 bit : Opcode
6238 uint32_t Word = Inst->getOpcode();
6239 Word |= Inst->getWordCount() << 16;
6240 WriteOneWord(Word);
6241}
6242
6243void SPIRVProducerPass::WriteOperand(SPIRVOperand *Op) {
6244 SPIRVOperandType OpTy = Op->getType();
6245 switch (OpTy) {
6246 default: {
6247 llvm_unreachable("Unsupported SPIRV Operand Type???");
6248 break;
6249 }
6250 case SPIRVOperandType::NUMBERID: {
6251 WriteOneWord(Op->getNumID());
6252 break;
6253 }
6254 case SPIRVOperandType::LITERAL_STRING: {
6255 std::string Str = Op->getLiteralStr();
6256 const char *Data = Str.c_str();
6257 size_t WordSize = Str.size() / 4;
6258 for (unsigned Idx = 0; Idx < WordSize; Idx++) {
6259 WriteOneWord(*reinterpret_cast<const uint32_t *>(&Data[4 * Idx]));
6260 }
6261
6262 uint32_t Remainder = Str.size() % 4;
6263 uint32_t LastWord = 0;
6264 if (Remainder) {
6265 for (unsigned Idx = 0; Idx < Remainder; Idx++) {
6266 LastWord |= Data[4 * WordSize + Idx] << 8 * Idx;
6267 }
6268 }
6269
6270 WriteOneWord(LastWord);
6271 break;
6272 }
6273 case SPIRVOperandType::LITERAL_INTEGER:
6274 case SPIRVOperandType::LITERAL_FLOAT: {
6275 auto LiteralNum = Op->getLiteralNum();
6276 // TODO: Handle LiteranNum carefully.
6277 for (auto Word : LiteralNum) {
6278 WriteOneWord(Word);
6279 }
6280 break;
6281 }
6282 }
6283}
6284
6285void SPIRVProducerPass::WriteSPIRVBinary() {
6286 SPIRVInstructionList &SPIRVInstList = getSPIRVInstList();
6287
6288 for (auto Inst : SPIRVInstList) {
6289 SPIRVOperandList Ops = Inst->getOperands();
6290 spv::Op Opcode = static_cast<spv::Op>(Inst->getOpcode());
6291
6292 switch (Opcode) {
6293 default: {
6294 llvm_unreachable("Unsupported SPIRV instruction");
6295 break;
6296 }
6297 case spv::OpCapability:
6298 case spv::OpExtension:
6299 case spv::OpMemoryModel:
6300 case spv::OpEntryPoint:
6301 case spv::OpExecutionMode:
6302 case spv::OpSource:
6303 case spv::OpDecorate:
6304 case spv::OpMemberDecorate:
6305 case spv::OpBranch:
6306 case spv::OpBranchConditional:
6307 case spv::OpSelectionMerge:
6308 case spv::OpLoopMerge:
6309 case spv::OpStore:
6310 case spv::OpImageWrite:
6311 case spv::OpReturnValue:
6312 case spv::OpControlBarrier:
6313 case spv::OpMemoryBarrier:
6314 case spv::OpReturn:
6315 case spv::OpFunctionEnd:
6316 case spv::OpCopyMemory: {
6317 WriteWordCountAndOpcode(Inst);
6318 for (uint32_t i = 0; i < Ops.size(); i++) {
6319 WriteOperand(Ops[i]);
6320 }
6321 break;
6322 }
6323 case spv::OpTypeBool:
6324 case spv::OpTypeVoid:
6325 case spv::OpTypeSampler:
6326 case spv::OpLabel:
6327 case spv::OpExtInstImport:
6328 case spv::OpTypePointer:
6329 case spv::OpTypeRuntimeArray:
6330 case spv::OpTypeStruct:
6331 case spv::OpTypeImage:
6332 case spv::OpTypeSampledImage:
6333 case spv::OpTypeInt:
6334 case spv::OpTypeFloat:
6335 case spv::OpTypeArray:
6336 case spv::OpTypeVector:
6337 case spv::OpTypeFunction: {
6338 WriteWordCountAndOpcode(Inst);
6339 WriteResultID(Inst);
6340 for (uint32_t i = 0; i < Ops.size(); i++) {
6341 WriteOperand(Ops[i]);
6342 }
6343 break;
6344 }
6345 case spv::OpFunction:
6346 case spv::OpFunctionParameter:
6347 case spv::OpAccessChain:
6348 case spv::OpPtrAccessChain:
6349 case spv::OpInBoundsAccessChain:
6350 case spv::OpUConvert:
6351 case spv::OpSConvert:
6352 case spv::OpConvertFToU:
6353 case spv::OpConvertFToS:
6354 case spv::OpConvertUToF:
6355 case spv::OpConvertSToF:
6356 case spv::OpFConvert:
6357 case spv::OpConvertPtrToU:
6358 case spv::OpConvertUToPtr:
6359 case spv::OpBitcast:
6360 case spv::OpIAdd:
6361 case spv::OpFAdd:
6362 case spv::OpISub:
6363 case spv::OpFSub:
6364 case spv::OpIMul:
6365 case spv::OpFMul:
6366 case spv::OpUDiv:
6367 case spv::OpSDiv:
6368 case spv::OpFDiv:
6369 case spv::OpUMod:
6370 case spv::OpSRem:
6371 case spv::OpFRem:
6372 case spv::OpBitwiseOr:
6373 case spv::OpBitwiseXor:
6374 case spv::OpBitwiseAnd:
David Netoa394f392017-08-26 20:45:29 -04006375 case spv::OpNot:
David Neto22f144c2017-06-12 14:26:21 -04006376 case spv::OpShiftLeftLogical:
6377 case spv::OpShiftRightLogical:
6378 case spv::OpShiftRightArithmetic:
6379 case spv::OpBitCount:
6380 case spv::OpCompositeExtract:
6381 case spv::OpVectorExtractDynamic:
6382 case spv::OpCompositeInsert:
David Neto0a2f98d2017-09-15 19:38:40 -04006383 case spv::OpCopyObject:
David Neto22f144c2017-06-12 14:26:21 -04006384 case spv::OpVectorInsertDynamic:
6385 case spv::OpVectorShuffle:
6386 case spv::OpIEqual:
6387 case spv::OpINotEqual:
6388 case spv::OpUGreaterThan:
6389 case spv::OpUGreaterThanEqual:
6390 case spv::OpULessThan:
6391 case spv::OpULessThanEqual:
6392 case spv::OpSGreaterThan:
6393 case spv::OpSGreaterThanEqual:
6394 case spv::OpSLessThan:
6395 case spv::OpSLessThanEqual:
6396 case spv::OpFOrdEqual:
6397 case spv::OpFOrdGreaterThan:
6398 case spv::OpFOrdGreaterThanEqual:
6399 case spv::OpFOrdLessThan:
6400 case spv::OpFOrdLessThanEqual:
6401 case spv::OpFOrdNotEqual:
6402 case spv::OpFUnordEqual:
6403 case spv::OpFUnordGreaterThan:
6404 case spv::OpFUnordGreaterThanEqual:
6405 case spv::OpFUnordLessThan:
6406 case spv::OpFUnordLessThanEqual:
6407 case spv::OpFUnordNotEqual:
6408 case spv::OpExtInst:
6409 case spv::OpIsInf:
6410 case spv::OpIsNan:
6411 case spv::OpAny:
6412 case spv::OpAll:
6413 case spv::OpUndef:
6414 case spv::OpConstantNull:
6415 case spv::OpLogicalOr:
6416 case spv::OpLogicalAnd:
6417 case spv::OpLogicalNot:
6418 case spv::OpLogicalNotEqual:
6419 case spv::OpConstantComposite:
6420 case spv::OpSpecConstantComposite:
6421 case spv::OpConstantTrue:
6422 case spv::OpConstantFalse:
6423 case spv::OpConstant:
6424 case spv::OpSpecConstant:
6425 case spv::OpVariable:
6426 case spv::OpFunctionCall:
6427 case spv::OpSampledImage:
6428 case spv::OpImageSampleExplicitLod:
6429 case spv::OpSelect:
6430 case spv::OpPhi:
6431 case spv::OpLoad:
6432 case spv::OpAtomicIAdd:
6433 case spv::OpAtomicISub:
6434 case spv::OpAtomicExchange:
6435 case spv::OpAtomicIIncrement:
6436 case spv::OpAtomicIDecrement:
6437 case spv::OpAtomicCompareExchange:
6438 case spv::OpAtomicUMin:
6439 case spv::OpAtomicSMin:
6440 case spv::OpAtomicUMax:
6441 case spv::OpAtomicSMax:
6442 case spv::OpAtomicAnd:
6443 case spv::OpAtomicOr:
6444 case spv::OpAtomicXor:
6445 case spv::OpDot: {
6446 WriteWordCountAndOpcode(Inst);
6447 WriteOperand(Ops[0]);
6448 WriteResultID(Inst);
6449 for (uint32_t i = 1; i < Ops.size(); i++) {
6450 WriteOperand(Ops[i]);
6451 }
6452 break;
6453 }
6454 }
6455 }
6456}