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