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