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