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