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