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