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