blob: d194c3e37e17c7dc7acc11e14befbdaa73c2f5a5 [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 Neto257c3892018-04-11 13:19:45 -040020#include <cstring>
David Neto118188e2018-08-24 11:27:54 -040021#include <iomanip>
22#include <list>
David Neto862b7d82018-06-14 18:48:37 -040023#include <memory>
David Neto118188e2018-08-24 11:27:54 -040024#include <set>
25#include <sstream>
26#include <string>
27#include <tuple>
28#include <unordered_set>
29#include <utility>
David Neto862b7d82018-06-14 18:48:37 -040030
David Neto118188e2018-08-24 11:27:54 -040031#include "llvm/ADT/StringSwitch.h"
32#include "llvm/ADT/UniqueVector.h"
33#include "llvm/Analysis/LoopInfo.h"
34#include "llvm/IR/Constants.h"
35#include "llvm/IR/Dominators.h"
36#include "llvm/IR/Instructions.h"
37#include "llvm/IR/Metadata.h"
38#include "llvm/IR/Module.h"
39#include "llvm/Pass.h"
40#include "llvm/Support/CommandLine.h"
41#include "llvm/Support/raw_ostream.h"
42#include "llvm/Transforms/Utils/Cloning.h"
David Neto22f144c2017-06-12 14:26:21 -040043
David Neto85082642018-03-24 06:55:20 -070044#include "spirv/1.0/spirv.hpp"
David Neto118188e2018-08-24 11:27:54 -040045
David Neto85082642018-03-24 06:55:20 -070046#include "clspv/AddressSpace.h"
alan-bakerf5e5f692018-11-27 08:33:24 -050047#include "clspv/DescriptorMap.h"
David Neto118188e2018-08-24 11:27:54 -040048#include "clspv/Option.h"
49#include "clspv/Passes.h"
David Neto85082642018-03-24 06:55:20 -070050#include "clspv/spirv_c_strings.hpp"
51#include "clspv/spirv_glsl.hpp"
David Neto22f144c2017-06-12 14:26:21 -040052
David Neto4feb7a42017-10-06 17:29:42 -040053#include "ArgKind.h"
David Neto85082642018-03-24 06:55:20 -070054#include "ConstantEmitter.h"
Alan Baker202c8c72018-08-13 13:47:44 -040055#include "Constants.h"
David Neto78383442018-06-15 20:31:56 -040056#include "DescriptorCounter.h"
David Neto48f56a42017-10-06 16:44:25 -040057
David Neto22f144c2017-06-12 14:26:21 -040058#if defined(_MSC_VER)
59#pragma warning(pop)
60#endif
61
62using namespace llvm;
63using namespace clspv;
David Neto156783e2017-07-05 15:39:41 -040064using namespace mdconst;
David Neto22f144c2017-06-12 14:26:21 -040065
66namespace {
David Netocd8ca5f2017-10-02 23:34:11 -040067
David Neto862b7d82018-06-14 18:48:37 -040068cl::opt<bool> ShowResourceVars("show-rv", cl::init(false), cl::Hidden,
69 cl::desc("Show resource variable creation"));
70
71// These hacks exist to help transition code generation algorithms
72// without making huge noise in detailed test output.
73const bool Hack_generate_runtime_array_stride_early = true;
74
David Neto3fbb4072017-10-16 11:28:14 -040075// The value of 1/pi. This value is from MSDN
76// https://msdn.microsoft.com/en-us/library/4hwaceh6.aspx
77const double kOneOverPi = 0.318309886183790671538;
78const glsl::ExtInst kGlslExtInstBad = static_cast<glsl::ExtInst>(0);
79
alan-bakerb6b09dc2018-11-08 16:59:28 -050080const char *kCompositeConstructFunctionPrefix = "clspv.composite_construct.";
David Netoab03f432017-11-03 17:00:44 -040081
David Neto22f144c2017-06-12 14:26:21 -040082enum SPIRVOperandType {
83 NUMBERID,
84 LITERAL_INTEGER,
85 LITERAL_STRING,
86 LITERAL_FLOAT
87};
88
89struct SPIRVOperand {
90 explicit SPIRVOperand(SPIRVOperandType Ty, uint32_t Num)
91 : Type(Ty), LiteralNum(1, Num) {}
92 explicit SPIRVOperand(SPIRVOperandType Ty, const char *Str)
93 : Type(Ty), LiteralStr(Str) {}
94 explicit SPIRVOperand(SPIRVOperandType Ty, StringRef Str)
95 : Type(Ty), LiteralStr(Str) {}
96 explicit SPIRVOperand(SPIRVOperandType Ty, ArrayRef<uint32_t> NumVec)
97 : Type(Ty), LiteralNum(NumVec.begin(), NumVec.end()) {}
98
99 SPIRVOperandType getType() { return Type; };
100 uint32_t getNumID() { return LiteralNum[0]; };
101 std::string getLiteralStr() { return LiteralStr; };
102 ArrayRef<uint32_t> getLiteralNum() { return LiteralNum; };
103
David Neto87846742018-04-11 17:36:22 -0400104 uint32_t GetNumWords() const {
105 switch (Type) {
106 case NUMBERID:
107 return 1;
108 case LITERAL_INTEGER:
109 case LITERAL_FLOAT:
David Netoee2660d2018-06-28 16:31:29 -0400110 return uint32_t(LiteralNum.size());
David Neto87846742018-04-11 17:36:22 -0400111 case LITERAL_STRING:
112 // Account for the terminating null character.
David Netoee2660d2018-06-28 16:31:29 -0400113 return uint32_t((LiteralStr.size() + 4) / 4);
David Neto87846742018-04-11 17:36:22 -0400114 }
115 llvm_unreachable("Unhandled case in SPIRVOperand::GetNumWords()");
116 }
117
David Neto22f144c2017-06-12 14:26:21 -0400118private:
119 SPIRVOperandType Type;
120 std::string LiteralStr;
121 SmallVector<uint32_t, 4> LiteralNum;
122};
123
David Netoc6f3ab22018-04-06 18:02:31 -0400124class SPIRVOperandList {
125public:
126 SPIRVOperandList() {}
alan-bakerb6b09dc2018-11-08 16:59:28 -0500127 SPIRVOperandList(const SPIRVOperandList &other) = delete;
128 SPIRVOperandList(SPIRVOperandList &&other) {
David Netoc6f3ab22018-04-06 18:02:31 -0400129 contents_ = std::move(other.contents_);
130 other.contents_.clear();
131 }
132 SPIRVOperandList(ArrayRef<SPIRVOperand *> init)
133 : contents_(init.begin(), init.end()) {}
134 operator ArrayRef<SPIRVOperand *>() { return contents_; }
135 void push_back(SPIRVOperand *op) { contents_.push_back(op); }
alan-bakerb6b09dc2018-11-08 16:59:28 -0500136 void clear() { contents_.clear(); }
David Netoc6f3ab22018-04-06 18:02:31 -0400137 size_t size() const { return contents_.size(); }
138 SPIRVOperand *&operator[](size_t i) { return contents_[i]; }
139
David Neto87846742018-04-11 17:36:22 -0400140 const SmallVector<SPIRVOperand *, 8> &getOperands() const {
141 return contents_;
142 }
143
David Netoc6f3ab22018-04-06 18:02:31 -0400144private:
alan-bakerb6b09dc2018-11-08 16:59:28 -0500145 SmallVector<SPIRVOperand *, 8> contents_;
David Netoc6f3ab22018-04-06 18:02:31 -0400146};
147
148SPIRVOperandList &operator<<(SPIRVOperandList &list, SPIRVOperand *elem) {
149 list.push_back(elem);
150 return list;
151}
152
alan-bakerb6b09dc2018-11-08 16:59:28 -0500153SPIRVOperand *MkNum(uint32_t num) {
David Netoc6f3ab22018-04-06 18:02:31 -0400154 return new SPIRVOperand(LITERAL_INTEGER, num);
155}
alan-bakerb6b09dc2018-11-08 16:59:28 -0500156SPIRVOperand *MkInteger(ArrayRef<uint32_t> num_vec) {
David Neto257c3892018-04-11 13:19:45 -0400157 return new SPIRVOperand(LITERAL_INTEGER, num_vec);
158}
alan-bakerb6b09dc2018-11-08 16:59:28 -0500159SPIRVOperand *MkFloat(ArrayRef<uint32_t> num_vec) {
David Neto257c3892018-04-11 13:19:45 -0400160 return new SPIRVOperand(LITERAL_FLOAT, num_vec);
161}
alan-bakerb6b09dc2018-11-08 16:59:28 -0500162SPIRVOperand *MkId(uint32_t id) { return new SPIRVOperand(NUMBERID, id); }
163SPIRVOperand *MkString(StringRef str) {
David Neto257c3892018-04-11 13:19:45 -0400164 return new SPIRVOperand(LITERAL_STRING, str);
165}
David Netoc6f3ab22018-04-06 18:02:31 -0400166
David Neto22f144c2017-06-12 14:26:21 -0400167struct SPIRVInstruction {
David Neto87846742018-04-11 17:36:22 -0400168 // Create an instruction with an opcode and no result ID, and with the given
169 // operands. This computes its own word count.
170 explicit SPIRVInstruction(spv::Op Opc, ArrayRef<SPIRVOperand *> Ops)
171 : WordCount(1), Opcode(static_cast<uint16_t>(Opc)), ResultID(0),
172 Operands(Ops.begin(), Ops.end()) {
173 for (auto *operand : Ops) {
David Netoee2660d2018-06-28 16:31:29 -0400174 WordCount += uint16_t(operand->GetNumWords());
David Neto87846742018-04-11 17:36:22 -0400175 }
176 }
177 // Create an instruction with an opcode and a no-zero result ID, and
178 // with the given operands. This computes its own word count.
179 explicit SPIRVInstruction(spv::Op Opc, uint32_t ResID,
David Neto22f144c2017-06-12 14:26:21 -0400180 ArrayRef<SPIRVOperand *> Ops)
David Neto87846742018-04-11 17:36:22 -0400181 : WordCount(2), Opcode(static_cast<uint16_t>(Opc)), ResultID(ResID),
182 Operands(Ops.begin(), Ops.end()) {
183 if (ResID == 0) {
184 llvm_unreachable("Result ID of 0 was provided");
185 }
186 for (auto *operand : Ops) {
187 WordCount += operand->GetNumWords();
188 }
189 }
David Neto22f144c2017-06-12 14:26:21 -0400190
David Netoee2660d2018-06-28 16:31:29 -0400191 uint32_t getWordCount() const { return WordCount; }
David Neto22f144c2017-06-12 14:26:21 -0400192 uint16_t getOpcode() const { return Opcode; }
193 uint32_t getResultID() const { return ResultID; }
194 ArrayRef<SPIRVOperand *> getOperands() const { return Operands; }
195
196private:
David Netoee2660d2018-06-28 16:31:29 -0400197 uint32_t WordCount; // Check the 16-bit bound at code generation time.
David Neto22f144c2017-06-12 14:26:21 -0400198 uint16_t Opcode;
199 uint32_t ResultID;
200 SmallVector<SPIRVOperand *, 4> Operands;
201};
202
203struct SPIRVProducerPass final : public ModulePass {
David Neto22f144c2017-06-12 14:26:21 -0400204 typedef DenseMap<Type *, uint32_t> TypeMapType;
205 typedef UniqueVector<Type *> TypeList;
206 typedef DenseMap<Value *, uint32_t> ValueMapType;
David Netofb9a7972017-08-25 17:08:24 -0400207 typedef UniqueVector<Value *> ValueList;
David Neto22f144c2017-06-12 14:26:21 -0400208 typedef std::vector<std::pair<Value *, uint32_t>> EntryPointVecType;
209 typedef std::list<SPIRVInstruction *> SPIRVInstructionList;
David Neto87846742018-04-11 17:36:22 -0400210 // A vector of tuples, each of which is:
211 // - the LLVM instruction that we will later generate SPIR-V code for
212 // - where the SPIR-V instruction should be inserted
213 // - the result ID of the SPIR-V instruction
David Neto22f144c2017-06-12 14:26:21 -0400214 typedef std::vector<
215 std::tuple<Value *, SPIRVInstructionList::iterator, uint32_t>>
216 DeferredInstVecType;
217 typedef DenseMap<FunctionType *, std::pair<FunctionType *, uint32_t>>
218 GlobalConstFuncMapType;
219
David Neto44795152017-07-13 15:45:28 -0400220 explicit SPIRVProducerPass(
alan-bakerf5e5f692018-11-27 08:33:24 -0500221 raw_pwrite_stream &out,
222 std::vector<clspv::version0::DescriptorMapEntry> *descriptor_map_entries,
David Neto44795152017-07-13 15:45:28 -0400223 ArrayRef<std::pair<unsigned, std::string>> samplerMap, bool outputAsm,
224 bool outputCInitList)
David Netoc2c368d2017-06-30 16:50:17 -0400225 : ModulePass(ID), samplerMap(samplerMap), out(out),
David Neto0676e6f2017-07-11 18:47:44 -0400226 binaryTempOut(binaryTempUnderlyingVector), binaryOut(&out),
alan-bakerf5e5f692018-11-27 08:33:24 -0500227 descriptorMapEntries(descriptor_map_entries), outputAsm(outputAsm),
David Neto0676e6f2017-07-11 18:47:44 -0400228 outputCInitList(outputCInitList), patchBoundOffset(0), nextID(1),
alan-baker5b86ed72019-02-15 08:26:50 -0500229 OpExtInstImportID(0), HasVariablePointersStorageBuffer(false),
230 HasVariablePointers(false), SamplerTy(nullptr), WorkgroupSizeValueID(0),
231 WorkgroupSizeVarID(0), max_local_spec_id_(0), constant_i32_zero_id_(0) {
232 }
David Neto22f144c2017-06-12 14:26:21 -0400233
234 void getAnalysisUsage(AnalysisUsage &AU) const override {
235 AU.addRequired<DominatorTreeWrapperPass>();
236 AU.addRequired<LoopInfoWrapperPass>();
237 }
238
239 virtual bool runOnModule(Module &module) override;
240
241 // output the SPIR-V header block
242 void outputHeader();
243
244 // patch the SPIR-V header block
245 void patchHeader();
246
247 uint32_t lookupType(Type *Ty) {
248 if (Ty->isPointerTy() &&
249 (Ty->getPointerAddressSpace() != AddressSpace::UniformConstant)) {
250 auto PointeeTy = Ty->getPointerElementType();
251 if (PointeeTy->isStructTy() &&
252 dyn_cast<StructType>(PointeeTy)->isOpaque()) {
253 Ty = PointeeTy;
254 }
255 }
256
David Neto862b7d82018-06-14 18:48:37 -0400257 auto where = TypeMap.find(Ty);
258 if (where == TypeMap.end()) {
259 if (Ty) {
260 errs() << "Unhandled type " << *Ty << "\n";
261 } else {
262 errs() << "Unhandled type (null)\n";
263 }
David Netoe439d702018-03-23 13:14:08 -0700264 llvm_unreachable("\nUnhandled type!");
David Neto22f144c2017-06-12 14:26:21 -0400265 }
266
David Neto862b7d82018-06-14 18:48:37 -0400267 return where->second;
David Neto22f144c2017-06-12 14:26:21 -0400268 }
269 TypeMapType &getImageTypeMap() { return ImageTypeMap; }
270 TypeList &getTypeList() { return Types; };
271 ValueList &getConstantList() { return Constants; };
272 ValueMapType &getValueMap() { return ValueMap; }
273 ValueMapType &getAllocatedValueMap() { return AllocatedValueMap; }
274 SPIRVInstructionList &getSPIRVInstList() { return SPIRVInsts; };
David Neto22f144c2017-06-12 14:26:21 -0400275 EntryPointVecType &getEntryPointVec() { return EntryPointVec; };
276 DeferredInstVecType &getDeferredInstVec() { return DeferredInstVec; };
277 ValueList &getEntryPointInterfacesVec() { return EntryPointInterfacesVec; };
278 uint32_t &getOpExtInstImportID() { return OpExtInstImportID; };
279 std::vector<uint32_t> &getBuiltinDimVec() { return BuiltinDimensionVec; };
alan-baker5b86ed72019-02-15 08:26:50 -0500280 bool hasVariablePointersStorageBuffer() {
281 return HasVariablePointersStorageBuffer;
282 }
283 void setVariablePointersStorageBuffer(bool Val) {
284 HasVariablePointersStorageBuffer = Val;
285 }
alan-bakerb6b09dc2018-11-08 16:59:28 -0500286 bool hasVariablePointers() {
alan-baker5b86ed72019-02-15 08:26:50 -0500287 return HasVariablePointers;
alan-bakerb6b09dc2018-11-08 16:59:28 -0500288 };
David Neto22f144c2017-06-12 14:26:21 -0400289 void setVariablePointers(bool Val) { HasVariablePointers = Val; };
alan-bakerb6b09dc2018-11-08 16:59:28 -0500290 ArrayRef<std::pair<unsigned, std::string>> &getSamplerMap() {
291 return samplerMap;
292 }
David Neto22f144c2017-06-12 14:26:21 -0400293 GlobalConstFuncMapType &getGlobalConstFuncTypeMap() {
294 return GlobalConstFuncTypeMap;
295 }
296 SmallPtrSet<Value *, 16> &getGlobalConstArgSet() {
297 return GlobalConstArgumentSet;
298 }
alan-bakerb6b09dc2018-11-08 16:59:28 -0500299 TypeList &getTypesNeedingArrayStride() { return TypesNeedingArrayStride; }
David Neto22f144c2017-06-12 14:26:21 -0400300
David Netoc6f3ab22018-04-06 18:02:31 -0400301 void GenerateLLVMIRInfo(Module &M, const DataLayout &DL);
alan-bakerb6b09dc2018-11-08 16:59:28 -0500302 // Populate GlobalConstFuncTypeMap. Also, if module-scope __constant will
303 // *not* be converted to a storage buffer, replace each such global variable
304 // with one in the storage class expecgted by SPIR-V.
David Neto862b7d82018-06-14 18:48:37 -0400305 void FindGlobalConstVars(Module &M, const DataLayout &DL);
306 // Populate ResourceVarInfoList, FunctionToResourceVarsMap, and
307 // ModuleOrderedResourceVars.
308 void FindResourceVars(Module &M, const DataLayout &DL);
Alan Baker202c8c72018-08-13 13:47:44 -0400309 void FindWorkgroupVars(Module &M);
David Neto22f144c2017-06-12 14:26:21 -0400310 bool FindExtInst(Module &M);
311 void FindTypePerGlobalVar(GlobalVariable &GV);
312 void FindTypePerFunc(Function &F);
David Neto862b7d82018-06-14 18:48:37 -0400313 void FindTypesForSamplerMap(Module &M);
314 void FindTypesForResourceVars(Module &M);
alan-bakerb6b09dc2018-11-08 16:59:28 -0500315 // Inserts |Ty| and relevant sub-types into the |Types| member, indicating
316 // that |Ty| and its subtypes will need a corresponding SPIR-V type.
David Neto22f144c2017-06-12 14:26:21 -0400317 void FindType(Type *Ty);
318 void FindConstantPerGlobalVar(GlobalVariable &GV);
319 void FindConstantPerFunc(Function &F);
320 void FindConstant(Value *V);
321 void GenerateExtInstImport();
David Neto19a1bad2017-08-25 15:01:41 -0400322 // Generates instructions for SPIR-V types corresponding to the LLVM types
323 // saved in the |Types| member. A type follows its subtypes. IDs are
324 // allocated sequentially starting with the current value of nextID, and
325 // with a type following its subtypes. Also updates nextID to just beyond
326 // the last generated ID.
alan-bakerb6b09dc2018-11-08 16:59:28 -0500327 void GenerateSPIRVTypes(LLVMContext &context, Module &module);
David Neto22f144c2017-06-12 14:26:21 -0400328 void GenerateSPIRVConstants();
David Neto5c22a252018-03-15 16:07:41 -0400329 void GenerateModuleInfo(Module &M);
David Neto22f144c2017-06-12 14:26:21 -0400330 void GenerateGlobalVar(GlobalVariable &GV);
David Netoc6f3ab22018-04-06 18:02:31 -0400331 void GenerateWorkgroupVars();
David Neto862b7d82018-06-14 18:48:37 -0400332 // Generate descriptor map entries for resource variables associated with
333 // arguments to F.
alan-bakerb6b09dc2018-11-08 16:59:28 -0500334 void GenerateDescriptorMapInfo(const DataLayout &DL, Function &F);
David Neto22f144c2017-06-12 14:26:21 -0400335 void GenerateSamplers(Module &M);
David Neto862b7d82018-06-14 18:48:37 -0400336 // Generate OpVariables for %clspv.resource.var.* calls.
337 void GenerateResourceVars(Module &M);
David Neto22f144c2017-06-12 14:26:21 -0400338 void GenerateFuncPrologue(Function &F);
339 void GenerateFuncBody(Function &F);
David Netob6e2e062018-04-25 10:32:06 -0400340 void GenerateEntryPointInitialStores();
David Neto22f144c2017-06-12 14:26:21 -0400341 spv::Op GetSPIRVCmpOpcode(CmpInst *CmpI);
342 spv::Op GetSPIRVCastOpcode(Instruction &I);
343 spv::Op GetSPIRVBinaryOpcode(Instruction &I);
344 void GenerateInstruction(Instruction &I);
345 void GenerateFuncEpilogue();
346 void HandleDeferredInstruction();
alan-bakerb6b09dc2018-11-08 16:59:28 -0500347 void HandleDeferredDecorations(const DataLayout &DL);
David Neto22f144c2017-06-12 14:26:21 -0400348 bool is4xi8vec(Type *Ty) const;
David Neto257c3892018-04-11 13:19:45 -0400349 // Return the SPIR-V Id for 32-bit constant zero. The constant must already
350 // have been created.
351 uint32_t GetI32Zero();
David Neto22f144c2017-06-12 14:26:21 -0400352 spv::StorageClass GetStorageClass(unsigned AddrSpace) const;
David Neto862b7d82018-06-14 18:48:37 -0400353 spv::StorageClass GetStorageClassForArgKind(clspv::ArgKind arg_kind) const;
David Neto22f144c2017-06-12 14:26:21 -0400354 spv::BuiltIn GetBuiltin(StringRef globalVarName) const;
David Neto3fbb4072017-10-16 11:28:14 -0400355 // Returns the GLSL extended instruction enum that the given function
356 // call maps to. If none, then returns the 0 value, i.e. GLSLstd4580Bad.
David Neto22f144c2017-06-12 14:26:21 -0400357 glsl::ExtInst getExtInstEnum(StringRef Name);
David Neto3fbb4072017-10-16 11:28:14 -0400358 // Returns the GLSL extended instruction enum indirectly used by the given
359 // function. That is, to implement the given function, we use an extended
360 // instruction plus one more instruction. If none, then returns the 0 value,
361 // i.e. GLSLstd4580Bad.
362 glsl::ExtInst getIndirectExtInstEnum(StringRef Name);
363 // Returns the single GLSL extended instruction used directly or
364 // indirectly by the given function call.
365 glsl::ExtInst getDirectOrIndirectExtInstEnum(StringRef Name);
David Neto22f144c2017-06-12 14:26:21 -0400366 void PrintResID(SPIRVInstruction *Inst);
367 void PrintOpcode(SPIRVInstruction *Inst);
368 void PrintOperand(SPIRVOperand *Op);
369 void PrintCapability(SPIRVOperand *Op);
370 void PrintExtInst(SPIRVOperand *Op);
371 void PrintAddrModel(SPIRVOperand *Op);
372 void PrintMemModel(SPIRVOperand *Op);
373 void PrintExecModel(SPIRVOperand *Op);
374 void PrintExecMode(SPIRVOperand *Op);
375 void PrintSourceLanguage(SPIRVOperand *Op);
376 void PrintFuncCtrl(SPIRVOperand *Op);
377 void PrintStorageClass(SPIRVOperand *Op);
378 void PrintDecoration(SPIRVOperand *Op);
379 void PrintBuiltIn(SPIRVOperand *Op);
380 void PrintSelectionControl(SPIRVOperand *Op);
381 void PrintLoopControl(SPIRVOperand *Op);
382 void PrintDimensionality(SPIRVOperand *Op);
383 void PrintImageFormat(SPIRVOperand *Op);
384 void PrintMemoryAccess(SPIRVOperand *Op);
385 void PrintImageOperandsType(SPIRVOperand *Op);
386 void WriteSPIRVAssembly();
387 void WriteOneWord(uint32_t Word);
388 void WriteResultID(SPIRVInstruction *Inst);
389 void WriteWordCountAndOpcode(SPIRVInstruction *Inst);
390 void WriteOperand(SPIRVOperand *Op);
391 void WriteSPIRVBinary();
392
Alan Baker9bf93fb2018-08-28 16:59:26 -0400393 // Returns true if |type| is compatible with OpConstantNull.
alan-bakerb6b09dc2018-11-08 16:59:28 -0500394 bool IsTypeNullable(const Type *type) const;
Alan Baker9bf93fb2018-08-28 16:59:26 -0400395
Alan Bakerfcda9482018-10-02 17:09:59 -0400396 // Populate UBO remapped type maps.
397 void PopulateUBOTypeMaps(Module &module);
398
399 // Wrapped methods of DataLayout accessors. If |type| was remapped for UBOs,
400 // uses the internal map, otherwise it falls back on the data layout.
401 uint64_t GetTypeSizeInBits(Type *type, const DataLayout &DL);
402 uint64_t GetTypeStoreSize(Type *type, const DataLayout &DL);
403 uint64_t GetTypeAllocSize(Type *type, const DataLayout &DL);
404
alan-baker5b86ed72019-02-15 08:26:50 -0500405 // Returns the base pointer of |v|.
406 Value *GetBasePointer(Value *v);
407
408 // Sets |HasVariablePointersStorageBuffer| or |HasVariablePointers| base on
409 // |address_space|.
410 void setVariablePointersCapabilities(unsigned address_space);
411
412 // Returns true if |lhs| and |rhs| represent the same resource or workgroup
413 // variable.
414 bool sameResource(Value *lhs, Value *rhs) const;
415
416 // Returns true if |inst| is phi or select that selects from the same
417 // structure (or null).
418 bool selectFromSameObject(Instruction *inst);
419
alan-bakere9308012019-03-15 10:25:13 -0400420 // Returns true if |Arg| is called with a coherent resource.
421 bool CalledWithCoherentResource(Argument &Arg);
422
David Neto22f144c2017-06-12 14:26:21 -0400423private:
424 static char ID;
David Neto44795152017-07-13 15:45:28 -0400425 ArrayRef<std::pair<unsigned, std::string>> samplerMap;
David Neto22f144c2017-06-12 14:26:21 -0400426 raw_pwrite_stream &out;
David Neto0676e6f2017-07-11 18:47:44 -0400427
428 // TODO(dneto): Wouldn't it be better to always just emit a binary, and then
429 // convert to other formats on demand?
430
431 // When emitting a C initialization list, the WriteSPIRVBinary method
432 // will actually write its words to this vector via binaryTempOut.
433 SmallVector<char, 100> binaryTempUnderlyingVector;
434 raw_svector_ostream binaryTempOut;
435
436 // Binary output writes to this stream, which might be |out| or
437 // |binaryTempOut|. It's the latter when we really want to write a C
438 // initializer list.
alan-bakerf5e5f692018-11-27 08:33:24 -0500439 raw_pwrite_stream* binaryOut;
440 std::vector<version0::DescriptorMapEntry> *descriptorMapEntries;
David Neto22f144c2017-06-12 14:26:21 -0400441 const bool outputAsm;
David Neto0676e6f2017-07-11 18:47:44 -0400442 const bool outputCInitList; // If true, output look like {0x7023, ... , 5}
David Neto22f144c2017-06-12 14:26:21 -0400443 uint64_t patchBoundOffset;
444 uint32_t nextID;
445
David Neto19a1bad2017-08-25 15:01:41 -0400446 // Maps an LLVM Value pointer to the corresponding SPIR-V Id.
David Neto22f144c2017-06-12 14:26:21 -0400447 TypeMapType TypeMap;
David Neto19a1bad2017-08-25 15:01:41 -0400448 // Maps an LLVM image type to its SPIR-V ID.
David Neto22f144c2017-06-12 14:26:21 -0400449 TypeMapType ImageTypeMap;
David Neto19a1bad2017-08-25 15:01:41 -0400450 // A unique-vector of LLVM types that map to a SPIR-V type.
David Neto22f144c2017-06-12 14:26:21 -0400451 TypeList Types;
452 ValueList Constants;
David Neto19a1bad2017-08-25 15:01:41 -0400453 // Maps an LLVM Value pointer to the corresponding SPIR-V Id.
David Neto22f144c2017-06-12 14:26:21 -0400454 ValueMapType ValueMap;
455 ValueMapType AllocatedValueMap;
456 SPIRVInstructionList SPIRVInsts;
David Neto862b7d82018-06-14 18:48:37 -0400457
David Neto22f144c2017-06-12 14:26:21 -0400458 EntryPointVecType EntryPointVec;
459 DeferredInstVecType DeferredInstVec;
460 ValueList EntryPointInterfacesVec;
461 uint32_t OpExtInstImportID;
462 std::vector<uint32_t> BuiltinDimensionVec;
alan-baker5b86ed72019-02-15 08:26:50 -0500463 bool HasVariablePointersStorageBuffer;
David Neto22f144c2017-06-12 14:26:21 -0400464 bool HasVariablePointers;
465 Type *SamplerTy;
alan-bakerb6b09dc2018-11-08 16:59:28 -0500466 DenseMap<unsigned, uint32_t> SamplerMapIndexToIDMap;
David Netoc77d9e22018-03-24 06:30:28 -0700467
468 // If a function F has a pointer-to-__constant parameter, then this variable
David Neto9ed8e2f2018-03-24 06:47:24 -0700469 // will map F's type to (G, index of the parameter), where in a first phase
470 // G is F's type. During FindTypePerFunc, G will be changed to F's type
471 // but replacing the pointer-to-constant parameter with
472 // pointer-to-ModuleScopePrivate.
David Netoc77d9e22018-03-24 06:30:28 -0700473 // TODO(dneto): This doesn't seem general enough? A function might have
474 // more than one such parameter.
David Neto22f144c2017-06-12 14:26:21 -0400475 GlobalConstFuncMapType GlobalConstFuncTypeMap;
476 SmallPtrSet<Value *, 16> GlobalConstArgumentSet;
David Neto1a1a0582017-07-07 12:01:44 -0400477 // An ordered set of pointer types of Base arguments to OpPtrAccessChain,
David Neto85082642018-03-24 06:55:20 -0700478 // or array types, and which point into transparent memory (StorageBuffer
479 // storage class). These will require an ArrayStride decoration.
David Neto1a1a0582017-07-07 12:01:44 -0400480 // See SPV_KHR_variable_pointers rev 13.
David Neto85082642018-03-24 06:55:20 -0700481 TypeList TypesNeedingArrayStride;
David Netoa60b00b2017-09-15 16:34:09 -0400482
483 // This is truly ugly, but works around what look like driver bugs.
484 // For get_local_size, an earlier part of the flow has created a module-scope
485 // variable in Private address space to hold the value for the workgroup
486 // size. Its intializer is a uint3 value marked as builtin WorkgroupSize.
487 // When this is present, save the IDs of the initializer value and variable
488 // in these two variables. We only ever do a vector load from it, and
489 // when we see one of those, substitute just the value of the intializer.
490 // This mimics what Glslang does, and that's what drivers are used to.
David Neto66cfe642018-03-24 06:13:56 -0700491 // TODO(dneto): Remove this once drivers are fixed.
David Netoa60b00b2017-09-15 16:34:09 -0400492 uint32_t WorkgroupSizeValueID;
493 uint32_t WorkgroupSizeVarID;
David Neto26aaf622017-10-23 18:11:53 -0400494
David Neto862b7d82018-06-14 18:48:37 -0400495 // Bookkeeping for mapping kernel arguments to resource variables.
496 struct ResourceVarInfo {
497 ResourceVarInfo(int index_arg, unsigned set_arg, unsigned binding_arg,
alan-bakere9308012019-03-15 10:25:13 -0400498 Function *fn, clspv::ArgKind arg_kind_arg, int coherent_arg)
David Neto862b7d82018-06-14 18:48:37 -0400499 : index(index_arg), descriptor_set(set_arg), binding(binding_arg),
alan-bakere9308012019-03-15 10:25:13 -0400500 var_fn(fn), arg_kind(arg_kind_arg), coherent(coherent_arg),
David Neto862b7d82018-06-14 18:48:37 -0400501 addr_space(fn->getReturnType()->getPointerAddressSpace()) {}
502 const int index; // Index into ResourceVarInfoList
503 const unsigned descriptor_set;
504 const unsigned binding;
505 Function *const var_fn; // The @clspv.resource.var.* function.
506 const clspv::ArgKind arg_kind;
alan-bakere9308012019-03-15 10:25:13 -0400507 const int coherent;
David Neto862b7d82018-06-14 18:48:37 -0400508 const unsigned addr_space; // The LLVM address space
509 // The SPIR-V ID of the OpVariable. Not populated at construction time.
510 uint32_t var_id = 0;
511 };
512 // A list of resource var info. Each one correponds to a module-scope
513 // resource variable we will have to create. Resource var indices are
514 // indices into this vector.
515 SmallVector<std::unique_ptr<ResourceVarInfo>, 8> ResourceVarInfoList;
516 // This is a vector of pointers of all the resource vars, but ordered by
517 // kernel function, and then by argument.
alan-bakerb6b09dc2018-11-08 16:59:28 -0500518 UniqueVector<ResourceVarInfo *> ModuleOrderedResourceVars;
David Neto862b7d82018-06-14 18:48:37 -0400519 // Map a function to the ordered list of resource variables it uses, one for
520 // each argument. If an argument does not use a resource variable, it
521 // will have a null pointer entry.
522 using FunctionToResourceVarsMapType =
523 DenseMap<Function *, SmallVector<ResourceVarInfo *, 8>>;
524 FunctionToResourceVarsMapType FunctionToResourceVarsMap;
525
526 // What LLVM types map to SPIR-V types needing layout? These are the
527 // arrays and structures supporting storage buffers and uniform buffers.
528 TypeList TypesNeedingLayout;
529 // What LLVM struct types map to a SPIR-V struct type with Block decoration?
530 UniqueVector<StructType *> StructTypesNeedingBlock;
531 // For a call that represents a load from an opaque type (samplers, images),
532 // map it to the variable id it should load from.
533 DenseMap<CallInst *, uint32_t> ResourceVarDeferredLoadCalls;
David Neto85082642018-03-24 06:55:20 -0700534
Alan Baker202c8c72018-08-13 13:47:44 -0400535 // One larger than the maximum used SpecId for pointer-to-local arguments.
536 int max_local_spec_id_;
David Netoc6f3ab22018-04-06 18:02:31 -0400537 // An ordered list of the kernel arguments of type pointer-to-local.
alan-bakerb6b09dc2018-11-08 16:59:28 -0500538 using LocalArgList = SmallVector<Argument *, 8>;
David Netoc6f3ab22018-04-06 18:02:31 -0400539 LocalArgList LocalArgs;
540 // Information about a pointer-to-local argument.
541 struct LocalArgInfo {
542 // The SPIR-V ID of the array variable.
543 uint32_t variable_id;
544 // The element type of the
alan-bakerb6b09dc2018-11-08 16:59:28 -0500545 Type *elem_type;
David Netoc6f3ab22018-04-06 18:02:31 -0400546 // The ID of the array type.
547 uint32_t array_size_id;
548 // The ID of the array type.
549 uint32_t array_type_id;
550 // The ID of the pointer to the array type.
551 uint32_t ptr_array_type_id;
David Netoc6f3ab22018-04-06 18:02:31 -0400552 // The specialization constant ID of the array size.
553 int spec_id;
554 };
Alan Baker202c8c72018-08-13 13:47:44 -0400555 // A mapping from Argument to its assigned SpecId.
alan-bakerb6b09dc2018-11-08 16:59:28 -0500556 DenseMap<const Argument *, int> LocalArgSpecIds;
Alan Baker202c8c72018-08-13 13:47:44 -0400557 // A mapping from SpecId to its LocalArgInfo.
558 DenseMap<int, LocalArgInfo> LocalSpecIdInfoMap;
Alan Bakerfcda9482018-10-02 17:09:59 -0400559 // A mapping from a remapped type to its real offsets.
alan-bakerb6b09dc2018-11-08 16:59:28 -0500560 DenseMap<Type *, std::vector<uint32_t>> RemappedUBOTypeOffsets;
Alan Bakerfcda9482018-10-02 17:09:59 -0400561 // A mapping from a remapped type to its real sizes.
alan-bakerb6b09dc2018-11-08 16:59:28 -0500562 DenseMap<Type *, std::tuple<uint64_t, uint64_t, uint64_t>>
563 RemappedUBOTypeSizes;
David Neto257c3892018-04-11 13:19:45 -0400564
565 // The ID of 32-bit integer zero constant. This is only valid after
566 // GenerateSPIRVConstants has run.
567 uint32_t constant_i32_zero_id_;
David Neto22f144c2017-06-12 14:26:21 -0400568};
569
570char SPIRVProducerPass::ID;
David Netoc6f3ab22018-04-06 18:02:31 -0400571
alan-bakerb6b09dc2018-11-08 16:59:28 -0500572} // namespace
David Neto22f144c2017-06-12 14:26:21 -0400573
574namespace clspv {
alan-bakerf5e5f692018-11-27 08:33:24 -0500575ModulePass *createSPIRVProducerPass(
576 raw_pwrite_stream &out,
577 std::vector<version0::DescriptorMapEntry> *descriptor_map_entries,
578 ArrayRef<std::pair<unsigned, std::string>> samplerMap, bool outputAsm,
579 bool outputCInitList) {
580 return new SPIRVProducerPass(out, descriptor_map_entries, samplerMap,
581 outputAsm, outputCInitList);
David Neto22f144c2017-06-12 14:26:21 -0400582}
David Netoc2c368d2017-06-30 16:50:17 -0400583} // namespace clspv
David Neto22f144c2017-06-12 14:26:21 -0400584
585bool SPIRVProducerPass::runOnModule(Module &module) {
David Neto0676e6f2017-07-11 18:47:44 -0400586 binaryOut = outputCInitList ? &binaryTempOut : &out;
587
David Neto257c3892018-04-11 13:19:45 -0400588 constant_i32_zero_id_ = 0; // Reset, for the benefit of validity checks.
589
Alan Bakerfcda9482018-10-02 17:09:59 -0400590 PopulateUBOTypeMaps(module);
591
David Neto22f144c2017-06-12 14:26:21 -0400592 // SPIR-V always begins with its header information
593 outputHeader();
594
David Netoc6f3ab22018-04-06 18:02:31 -0400595 const DataLayout &DL = module.getDataLayout();
596
David Neto22f144c2017-06-12 14:26:21 -0400597 // Gather information from the LLVM IR that we require.
David Netoc6f3ab22018-04-06 18:02:31 -0400598 GenerateLLVMIRInfo(module, DL);
David Neto22f144c2017-06-12 14:26:21 -0400599
David Neto22f144c2017-06-12 14:26:21 -0400600 // Collect information on global variables too.
601 for (GlobalVariable &GV : module.globals()) {
602 // If the GV is one of our special __spirv_* variables, remove the
603 // initializer as it was only placed there to force LLVM to not throw the
604 // value away.
605 if (GV.getName().startswith("__spirv_")) {
606 GV.setInitializer(nullptr);
607 }
608
609 // Collect types' information from global variable.
610 FindTypePerGlobalVar(GV);
611
612 // Collect constant information from global variable.
613 FindConstantPerGlobalVar(GV);
614
615 // If the variable is an input, entry points need to know about it.
616 if (AddressSpace::Input == GV.getType()->getPointerAddressSpace()) {
David Netofb9a7972017-08-25 17:08:24 -0400617 getEntryPointInterfacesVec().insert(&GV);
David Neto22f144c2017-06-12 14:26:21 -0400618 }
619 }
620
621 // If there are extended instructions, generate OpExtInstImport.
622 if (FindExtInst(module)) {
623 GenerateExtInstImport();
624 }
625
626 // Generate SPIRV instructions for types.
Alan Bakerfcda9482018-10-02 17:09:59 -0400627 GenerateSPIRVTypes(module.getContext(), module);
David Neto22f144c2017-06-12 14:26:21 -0400628
629 // Generate SPIRV constants.
630 GenerateSPIRVConstants();
631
632 // If we have a sampler map, we might have literal samplers to generate.
633 if (0 < getSamplerMap().size()) {
634 GenerateSamplers(module);
635 }
636
637 // Generate SPIRV variables.
638 for (GlobalVariable &GV : module.globals()) {
639 GenerateGlobalVar(GV);
640 }
David Neto862b7d82018-06-14 18:48:37 -0400641 GenerateResourceVars(module);
David Netoc6f3ab22018-04-06 18:02:31 -0400642 GenerateWorkgroupVars();
David Neto22f144c2017-06-12 14:26:21 -0400643
644 // Generate SPIRV instructions for each function.
645 for (Function &F : module) {
646 if (F.isDeclaration()) {
647 continue;
648 }
649
David Neto862b7d82018-06-14 18:48:37 -0400650 GenerateDescriptorMapInfo(DL, F);
651
David Neto22f144c2017-06-12 14:26:21 -0400652 // Generate Function Prologue.
653 GenerateFuncPrologue(F);
654
655 // Generate SPIRV instructions for function body.
656 GenerateFuncBody(F);
657
658 // Generate Function Epilogue.
659 GenerateFuncEpilogue();
660 }
661
662 HandleDeferredInstruction();
David Neto1a1a0582017-07-07 12:01:44 -0400663 HandleDeferredDecorations(DL);
David Neto22f144c2017-06-12 14:26:21 -0400664
665 // Generate SPIRV module information.
David Neto5c22a252018-03-15 16:07:41 -0400666 GenerateModuleInfo(module);
David Neto22f144c2017-06-12 14:26:21 -0400667
668 if (outputAsm) {
669 WriteSPIRVAssembly();
670 } else {
671 WriteSPIRVBinary();
672 }
673
674 // We need to patch the SPIR-V header to set bound correctly.
675 patchHeader();
David Neto0676e6f2017-07-11 18:47:44 -0400676
677 if (outputCInitList) {
678 bool first = true;
David Neto0676e6f2017-07-11 18:47:44 -0400679 std::ostringstream os;
680
David Neto57fb0b92017-08-04 15:35:09 -0400681 auto emit_word = [&os, &first](uint32_t word) {
David Neto0676e6f2017-07-11 18:47:44 -0400682 if (!first)
David Neto57fb0b92017-08-04 15:35:09 -0400683 os << ",\n";
684 os << word;
David Neto0676e6f2017-07-11 18:47:44 -0400685 first = false;
686 };
687
688 os << "{";
David Neto57fb0b92017-08-04 15:35:09 -0400689 const std::string str(binaryTempOut.str());
690 for (unsigned i = 0; i < str.size(); i += 4) {
691 const uint32_t a = static_cast<unsigned char>(str[i]);
692 const uint32_t b = static_cast<unsigned char>(str[i + 1]);
693 const uint32_t c = static_cast<unsigned char>(str[i + 2]);
694 const uint32_t d = static_cast<unsigned char>(str[i + 3]);
695 emit_word(a | (b << 8) | (c << 16) | (d << 24));
David Neto0676e6f2017-07-11 18:47:44 -0400696 }
697 os << "}\n";
698 out << os.str();
699 }
700
David Neto22f144c2017-06-12 14:26:21 -0400701 return false;
702}
703
704void SPIRVProducerPass::outputHeader() {
705 if (outputAsm) {
706 // for ASM output the header goes into 5 comments at the beginning of the
707 // file
708 out << "; SPIR-V\n";
709
710 // the major version number is in the 2nd highest byte
711 const uint32_t major = (spv::Version >> 16) & 0xFF;
712
713 // the minor version number is in the 2nd lowest byte
714 const uint32_t minor = (spv::Version >> 8) & 0xFF;
715 out << "; Version: " << major << "." << minor << "\n";
716
717 // use Codeplay's vendor ID
718 out << "; Generator: Codeplay; 0\n";
719
720 out << "; Bound: ";
721
722 // we record where we need to come back to and patch in the bound value
723 patchBoundOffset = out.tell();
724
725 // output one space per digit for the max size of a 32 bit unsigned integer
726 // (which is the maximum ID we could possibly be using)
727 for (uint32_t i = std::numeric_limits<uint32_t>::max(); 0 != i; i /= 10) {
728 out << " ";
729 }
730
731 out << "\n";
732
733 out << "; Schema: 0\n";
734 } else {
David Neto0676e6f2017-07-11 18:47:44 -0400735 binaryOut->write(reinterpret_cast<const char *>(&spv::MagicNumber),
alan-bakerb6b09dc2018-11-08 16:59:28 -0500736 sizeof(spv::MagicNumber));
David Neto0676e6f2017-07-11 18:47:44 -0400737 binaryOut->write(reinterpret_cast<const char *>(&spv::Version),
alan-bakerb6b09dc2018-11-08 16:59:28 -0500738 sizeof(spv::Version));
David Neto22f144c2017-06-12 14:26:21 -0400739
740 // use Codeplay's vendor ID
741 const uint32_t vendor = 3 << 16;
David Neto0676e6f2017-07-11 18:47:44 -0400742 binaryOut->write(reinterpret_cast<const char *>(&vendor), sizeof(vendor));
David Neto22f144c2017-06-12 14:26:21 -0400743
744 // we record where we need to come back to and patch in the bound value
David Neto0676e6f2017-07-11 18:47:44 -0400745 patchBoundOffset = binaryOut->tell();
David Neto22f144c2017-06-12 14:26:21 -0400746
747 // output a bad bound for now
David Neto0676e6f2017-07-11 18:47:44 -0400748 binaryOut->write(reinterpret_cast<const char *>(&nextID), sizeof(nextID));
David Neto22f144c2017-06-12 14:26:21 -0400749
750 // output the schema (reserved for use and must be 0)
751 const uint32_t schema = 0;
David Neto0676e6f2017-07-11 18:47:44 -0400752 binaryOut->write(reinterpret_cast<const char *>(&schema), sizeof(schema));
David Neto22f144c2017-06-12 14:26:21 -0400753 }
754}
755
756void SPIRVProducerPass::patchHeader() {
757 if (outputAsm) {
758 // get the string representation of the max bound used (nextID will be the
759 // max ID used)
760 auto asString = std::to_string(nextID);
761 out.pwrite(asString.c_str(), asString.size(), patchBoundOffset);
762 } else {
763 // for a binary we just write the value of nextID over bound
David Neto0676e6f2017-07-11 18:47:44 -0400764 binaryOut->pwrite(reinterpret_cast<char *>(&nextID), sizeof(nextID),
765 patchBoundOffset);
David Neto22f144c2017-06-12 14:26:21 -0400766 }
767}
768
David Netoc6f3ab22018-04-06 18:02:31 -0400769void SPIRVProducerPass::GenerateLLVMIRInfo(Module &M, const DataLayout &DL) {
David Neto22f144c2017-06-12 14:26:21 -0400770 // This function generates LLVM IR for function such as global variable for
771 // argument, constant and pointer type for argument access. These information
772 // is artificial one because we need Vulkan SPIR-V output. This function is
773 // executed ahead of FindType and FindConstant.
David Neto22f144c2017-06-12 14:26:21 -0400774 LLVMContext &Context = M.getContext();
775
David Neto862b7d82018-06-14 18:48:37 -0400776 FindGlobalConstVars(M, DL);
David Neto5c22a252018-03-15 16:07:41 -0400777
David Neto862b7d82018-06-14 18:48:37 -0400778 FindResourceVars(M, DL);
David Neto22f144c2017-06-12 14:26:21 -0400779
780 bool HasWorkGroupBuiltin = false;
781 for (GlobalVariable &GV : M.globals()) {
782 const spv::BuiltIn BuiltinType = GetBuiltin(GV.getName());
783 if (spv::BuiltInWorkgroupSize == BuiltinType) {
784 HasWorkGroupBuiltin = true;
785 }
786 }
787
David Neto862b7d82018-06-14 18:48:37 -0400788 FindTypesForSamplerMap(M);
789 FindTypesForResourceVars(M);
Alan Baker202c8c72018-08-13 13:47:44 -0400790 FindWorkgroupVars(M);
David Neto22f144c2017-06-12 14:26:21 -0400791
David Neto862b7d82018-06-14 18:48:37 -0400792 // These function calls need a <2 x i32> as an intermediate result but not
793 // the final result.
794 std::unordered_set<std::string> NeedsIVec2{
795 "_Z15get_image_width14ocl_image2d_ro",
796 "_Z15get_image_width14ocl_image2d_wo",
797 "_Z16get_image_height14ocl_image2d_ro",
798 "_Z16get_image_height14ocl_image2d_wo",
799 };
800
David Neto22f144c2017-06-12 14:26:21 -0400801 for (Function &F : M) {
802 // Handle kernel function first.
803 if (F.isDeclaration() || F.getCallingConv() != CallingConv::SPIR_KERNEL) {
804 continue;
805 }
806
807 for (BasicBlock &BB : F) {
808 for (Instruction &I : BB) {
809 if (I.getOpcode() == Instruction::ZExt ||
810 I.getOpcode() == Instruction::SExt ||
811 I.getOpcode() == Instruction::UIToFP) {
812 // If there is zext with i1 type, it will be changed to OpSelect. The
813 // OpSelect needs constant 0 and 1 so the constants are added here.
814
815 auto OpTy = I.getOperand(0)->getType();
816
Kévin Petit24272b62018-10-18 19:16:12 +0000817 if (OpTy->isIntOrIntVectorTy(1)) {
David Neto22f144c2017-06-12 14:26:21 -0400818 if (I.getOpcode() == Instruction::ZExt) {
David Neto22f144c2017-06-12 14:26:21 -0400819 FindConstant(Constant::getNullValue(I.getType()));
Kévin Petit7bfb8992019-02-26 13:45:08 +0000820 FindConstant(ConstantInt::get(I.getType(), 1));
David Neto22f144c2017-06-12 14:26:21 -0400821 } else if (I.getOpcode() == Instruction::SExt) {
David Neto22f144c2017-06-12 14:26:21 -0400822 FindConstant(Constant::getNullValue(I.getType()));
Kévin Petit7bfb8992019-02-26 13:45:08 +0000823 FindConstant(ConstantInt::getSigned(I.getType(), -1));
David Neto22f144c2017-06-12 14:26:21 -0400824 } else {
825 FindConstant(ConstantFP::get(Context, APFloat(0.0f)));
826 FindConstant(ConstantFP::get(Context, APFloat(1.0f)));
827 }
828 }
829 } else if (CallInst *Call = dyn_cast<CallInst>(&I)) {
David Neto862b7d82018-06-14 18:48:37 -0400830 StringRef callee_name = Call->getCalledFunction()->getName();
David Neto22f144c2017-06-12 14:26:21 -0400831
832 // Handle image type specially.
David Neto862b7d82018-06-14 18:48:37 -0400833 if (callee_name.equals(
David Neto22f144c2017-06-12 14:26:21 -0400834 "_Z11read_imagef14ocl_image2d_ro11ocl_samplerDv2_f") ||
David Neto862b7d82018-06-14 18:48:37 -0400835 callee_name.equals(
David Neto22f144c2017-06-12 14:26:21 -0400836 "_Z11read_imagef14ocl_image3d_ro11ocl_samplerDv4_f")) {
837 TypeMapType &OpImageTypeMap = getImageTypeMap();
838 Type *ImageTy =
839 Call->getArgOperand(0)->getType()->getPointerElementType();
840 OpImageTypeMap[ImageTy] = 0;
841
842 FindConstant(ConstantFP::get(Context, APFloat(0.0f)));
843 }
David Neto5c22a252018-03-15 16:07:41 -0400844
David Neto862b7d82018-06-14 18:48:37 -0400845 if (NeedsIVec2.find(callee_name) != NeedsIVec2.end()) {
David Neto5c22a252018-03-15 16:07:41 -0400846 FindType(VectorType::get(Type::getInt32Ty(Context), 2));
847 }
David Neto22f144c2017-06-12 14:26:21 -0400848 }
849 }
850 }
851
David Neto22f144c2017-06-12 14:26:21 -0400852 if (const MDNode *MD =
853 dyn_cast<Function>(&F)->getMetadata("reqd_work_group_size")) {
854 // We generate constants if the WorkgroupSize builtin is being used.
855 if (HasWorkGroupBuiltin) {
856 // Collect constant information for work group size.
857 FindConstant(mdconst::extract<ConstantInt>(MD->getOperand(0)));
858 FindConstant(mdconst::extract<ConstantInt>(MD->getOperand(1)));
859 FindConstant(mdconst::extract<ConstantInt>(MD->getOperand(2)));
860 }
861 }
862
David Neto22f144c2017-06-12 14:26:21 -0400863 // Collect types' information from function.
864 FindTypePerFunc(F);
865
866 // Collect constant information from function.
867 FindConstantPerFunc(F);
868 }
869
870 for (Function &F : M) {
871 // Handle non-kernel functions.
872 if (F.isDeclaration() || F.getCallingConv() == CallingConv::SPIR_KERNEL) {
873 continue;
874 }
875
876 for (BasicBlock &BB : F) {
877 for (Instruction &I : BB) {
878 if (I.getOpcode() == Instruction::ZExt ||
879 I.getOpcode() == Instruction::SExt ||
880 I.getOpcode() == Instruction::UIToFP) {
881 // If there is zext with i1 type, it will be changed to OpSelect. The
882 // OpSelect needs constant 0 and 1 so the constants are added here.
883
884 auto OpTy = I.getOperand(0)->getType();
885
Kévin Petit24272b62018-10-18 19:16:12 +0000886 if (OpTy->isIntOrIntVectorTy(1)) {
David Neto22f144c2017-06-12 14:26:21 -0400887 if (I.getOpcode() == Instruction::ZExt) {
David Neto22f144c2017-06-12 14:26:21 -0400888 FindConstant(Constant::getNullValue(I.getType()));
Kévin Petit7bfb8992019-02-26 13:45:08 +0000889 FindConstant(ConstantInt::get(I.getType(), 1));
David Neto22f144c2017-06-12 14:26:21 -0400890 } else if (I.getOpcode() == Instruction::SExt) {
David Neto22f144c2017-06-12 14:26:21 -0400891 FindConstant(Constant::getNullValue(I.getType()));
Kévin Petit7bfb8992019-02-26 13:45:08 +0000892 FindConstant(ConstantInt::getSigned(I.getType(), -1));
David Neto22f144c2017-06-12 14:26:21 -0400893 } else {
894 FindConstant(ConstantFP::get(Context, APFloat(0.0f)));
895 FindConstant(ConstantFP::get(Context, APFloat(1.0f)));
896 }
897 }
898 } else if (CallInst *Call = dyn_cast<CallInst>(&I)) {
899 Function *Callee = Call->getCalledFunction();
900
901 // Handle image type specially.
902 if (Callee->getName().equals(
903 "_Z11read_imagef14ocl_image2d_ro11ocl_samplerDv2_f") ||
904 Callee->getName().equals(
905 "_Z11read_imagef14ocl_image3d_ro11ocl_samplerDv4_f")) {
906 TypeMapType &OpImageTypeMap = getImageTypeMap();
907 Type *ImageTy =
908 Call->getArgOperand(0)->getType()->getPointerElementType();
909 OpImageTypeMap[ImageTy] = 0;
910
911 FindConstant(ConstantFP::get(Context, APFloat(0.0f)));
912 }
913 }
914 }
915 }
916
917 if (M.getTypeByName("opencl.image2d_ro_t") ||
918 M.getTypeByName("opencl.image2d_wo_t") ||
919 M.getTypeByName("opencl.image3d_ro_t") ||
920 M.getTypeByName("opencl.image3d_wo_t")) {
921 // Assume Image type's sampled type is float type.
922 FindType(Type::getFloatTy(Context));
923 }
924
925 // Collect types' information from function.
926 FindTypePerFunc(F);
927
928 // Collect constant information from function.
929 FindConstantPerFunc(F);
930 }
931}
932
David Neto862b7d82018-06-14 18:48:37 -0400933void SPIRVProducerPass::FindGlobalConstVars(Module &M, const DataLayout &DL) {
934 SmallVector<GlobalVariable *, 8> GVList;
935 SmallVector<GlobalVariable *, 8> DeadGVList;
936 for (GlobalVariable &GV : M.globals()) {
937 if (GV.getType()->getAddressSpace() == AddressSpace::Constant) {
938 if (GV.use_empty()) {
939 DeadGVList.push_back(&GV);
940 } else {
941 GVList.push_back(&GV);
942 }
943 }
944 }
945
946 // Remove dead global __constant variables.
947 for (auto GV : DeadGVList) {
948 GV->eraseFromParent();
949 }
950 DeadGVList.clear();
951
952 if (clspv::Option::ModuleConstantsInStorageBuffer()) {
953 // For now, we only support a single storage buffer.
954 if (GVList.size() > 0) {
955 assert(GVList.size() == 1);
956 const auto *GV = GVList[0];
957 const auto constants_byte_size =
Alan Bakerfcda9482018-10-02 17:09:59 -0400958 (GetTypeSizeInBits(GV->getInitializer()->getType(), DL)) / 8;
David Neto862b7d82018-06-14 18:48:37 -0400959 const size_t kConstantMaxSize = 65536;
960 if (constants_byte_size > kConstantMaxSize) {
961 outs() << "Max __constant capacity of " << kConstantMaxSize
962 << " bytes exceeded: " << constants_byte_size << " bytes used\n";
963 llvm_unreachable("Max __constant capacity exceeded");
964 }
965 }
966 } else {
967 // Change global constant variable's address space to ModuleScopePrivate.
968 auto &GlobalConstFuncTyMap = getGlobalConstFuncTypeMap();
969 for (auto GV : GVList) {
970 // Create new gv with ModuleScopePrivate address space.
971 Type *NewGVTy = GV->getType()->getPointerElementType();
972 GlobalVariable *NewGV = new GlobalVariable(
973 M, NewGVTy, false, GV->getLinkage(), GV->getInitializer(), "",
974 nullptr, GV->getThreadLocalMode(), AddressSpace::ModuleScopePrivate);
975 NewGV->takeName(GV);
976
977 const SmallVector<User *, 8> GVUsers(GV->user_begin(), GV->user_end());
978 SmallVector<User *, 8> CandidateUsers;
979
980 auto record_called_function_type_as_user =
981 [&GlobalConstFuncTyMap](Value *gv, CallInst *call) {
982 // Find argument index.
983 unsigned index = 0;
984 for (unsigned i = 0; i < call->getNumArgOperands(); i++) {
985 if (gv == call->getOperand(i)) {
986 // TODO(dneto): Should we break here?
987 index = i;
988 }
989 }
990
991 // Record function type with global constant.
992 GlobalConstFuncTyMap[call->getFunctionType()] =
993 std::make_pair(call->getFunctionType(), index);
994 };
995
996 for (User *GVU : GVUsers) {
997 if (CallInst *Call = dyn_cast<CallInst>(GVU)) {
998 record_called_function_type_as_user(GV, Call);
999 } else if (GetElementPtrInst *GEP = dyn_cast<GetElementPtrInst>(GVU)) {
1000 // Check GEP users.
1001 for (User *GEPU : GEP->users()) {
1002 if (CallInst *GEPCall = dyn_cast<CallInst>(GEPU)) {
1003 record_called_function_type_as_user(GEP, GEPCall);
1004 }
1005 }
1006 }
1007
1008 CandidateUsers.push_back(GVU);
1009 }
1010
1011 for (User *U : CandidateUsers) {
1012 // Update users of gv with new gv.
alan-bakered80f572019-02-11 17:28:26 -05001013 if (!isa<Constant>(U)) {
1014 // #254: Can't change operands of a constant, but this shouldn't be
1015 // something that sticks around in the module.
1016 U->replaceUsesOfWith(GV, NewGV);
1017 }
David Neto862b7d82018-06-14 18:48:37 -04001018 }
1019
1020 // Delete original gv.
1021 GV->eraseFromParent();
1022 }
1023 }
1024}
1025
Radek Szymanskibe4b0c42018-10-04 22:20:53 +01001026void SPIRVProducerPass::FindResourceVars(Module &M, const DataLayout &) {
David Neto862b7d82018-06-14 18:48:37 -04001027 ResourceVarInfoList.clear();
1028 FunctionToResourceVarsMap.clear();
1029 ModuleOrderedResourceVars.reset();
1030 // Normally, there is one resource variable per clspv.resource.var.*
1031 // function, since that is unique'd by arg type and index. By design,
1032 // we can share these resource variables across kernels because all
1033 // kernels use the same descriptor set.
1034 //
1035 // But if the user requested distinct descriptor sets per kernel, then
1036 // the descriptor allocator has made different (set,binding) pairs for
1037 // the same (type,arg_index) pair. Since we can decorate a resource
1038 // variable with only exactly one DescriptorSet and Binding, we are
1039 // forced in this case to make distinct resource variables whenever
1040 // the same clspv.reource.var.X function is seen with disintct
1041 // (set,binding) values.
1042 const bool always_distinct_sets =
1043 clspv::Option::DistinctKernelDescriptorSets();
1044 for (Function &F : M) {
1045 // Rely on the fact the resource var functions have a stable ordering
1046 // in the module.
Alan Baker202c8c72018-08-13 13:47:44 -04001047 if (F.getName().startswith(clspv::ResourceAccessorFunction())) {
David Neto862b7d82018-06-14 18:48:37 -04001048 // Find all calls to this function with distinct set and binding pairs.
1049 // Save them in ResourceVarInfoList.
1050
1051 // Determine uniqueness of the (set,binding) pairs only withing this
1052 // one resource-var builtin function.
1053 using SetAndBinding = std::pair<unsigned, unsigned>;
1054 // Maps set and binding to the resource var info.
1055 DenseMap<SetAndBinding, ResourceVarInfo *> set_and_binding_map;
1056 bool first_use = true;
1057 for (auto &U : F.uses()) {
1058 if (auto *call = dyn_cast<CallInst>(U.getUser())) {
1059 const auto set = unsigned(
1060 dyn_cast<ConstantInt>(call->getArgOperand(0))->getZExtValue());
1061 const auto binding = unsigned(
1062 dyn_cast<ConstantInt>(call->getArgOperand(1))->getZExtValue());
1063 const auto arg_kind = clspv::ArgKind(
1064 dyn_cast<ConstantInt>(call->getArgOperand(2))->getZExtValue());
1065 const auto arg_index = unsigned(
1066 dyn_cast<ConstantInt>(call->getArgOperand(3))->getZExtValue());
alan-bakere9308012019-03-15 10:25:13 -04001067 const auto coherent = unsigned(
1068 dyn_cast<ConstantInt>(call->getArgOperand(5))->getZExtValue());
David Neto862b7d82018-06-14 18:48:37 -04001069
1070 // Find or make the resource var info for this combination.
1071 ResourceVarInfo *rv = nullptr;
1072 if (always_distinct_sets) {
1073 // Make a new resource var any time we see a different
1074 // (set,binding) pair.
1075 SetAndBinding key{set, binding};
1076 auto where = set_and_binding_map.find(key);
1077 if (where == set_and_binding_map.end()) {
1078 rv = new ResourceVarInfo(int(ResourceVarInfoList.size()), set,
alan-bakere9308012019-03-15 10:25:13 -04001079 binding, &F, arg_kind, coherent);
David Neto862b7d82018-06-14 18:48:37 -04001080 ResourceVarInfoList.emplace_back(rv);
1081 set_and_binding_map[key] = rv;
1082 } else {
1083 rv = where->second;
1084 }
1085 } else {
1086 // The default is to make exactly one resource for each
1087 // clspv.resource.var.* function.
1088 if (first_use) {
1089 first_use = false;
1090 rv = new ResourceVarInfo(int(ResourceVarInfoList.size()), set,
alan-bakere9308012019-03-15 10:25:13 -04001091 binding, &F, arg_kind, coherent);
David Neto862b7d82018-06-14 18:48:37 -04001092 ResourceVarInfoList.emplace_back(rv);
1093 } else {
1094 rv = ResourceVarInfoList.back().get();
1095 }
1096 }
1097
1098 // Now populate FunctionToResourceVarsMap.
1099 auto &mapping =
1100 FunctionToResourceVarsMap[call->getParent()->getParent()];
1101 while (mapping.size() <= arg_index) {
1102 mapping.push_back(nullptr);
1103 }
1104 mapping[arg_index] = rv;
1105 }
1106 }
1107 }
1108 }
1109
1110 // Populate ModuleOrderedResourceVars.
1111 for (Function &F : M) {
1112 auto where = FunctionToResourceVarsMap.find(&F);
1113 if (where != FunctionToResourceVarsMap.end()) {
1114 for (auto &rv : where->second) {
1115 if (rv != nullptr) {
1116 ModuleOrderedResourceVars.insert(rv);
1117 }
1118 }
1119 }
1120 }
1121 if (ShowResourceVars) {
1122 for (auto *info : ModuleOrderedResourceVars) {
1123 outs() << "MORV index " << info->index << " (" << info->descriptor_set
1124 << "," << info->binding << ") " << *(info->var_fn->getReturnType())
1125 << "\n";
1126 }
1127 }
1128}
1129
David Neto22f144c2017-06-12 14:26:21 -04001130bool SPIRVProducerPass::FindExtInst(Module &M) {
1131 LLVMContext &Context = M.getContext();
1132 bool HasExtInst = false;
1133
1134 for (Function &F : M) {
1135 for (BasicBlock &BB : F) {
1136 for (Instruction &I : BB) {
1137 if (CallInst *Call = dyn_cast<CallInst>(&I)) {
1138 Function *Callee = Call->getCalledFunction();
1139 // Check whether this call is for extend instructions.
David Neto3fbb4072017-10-16 11:28:14 -04001140 auto callee_name = Callee->getName();
1141 const glsl::ExtInst EInst = getExtInstEnum(callee_name);
1142 const glsl::ExtInst IndirectEInst =
1143 getIndirectExtInstEnum(callee_name);
David Neto22f144c2017-06-12 14:26:21 -04001144
David Neto3fbb4072017-10-16 11:28:14 -04001145 HasExtInst |=
1146 (EInst != kGlslExtInstBad) || (IndirectEInst != kGlslExtInstBad);
1147
1148 if (IndirectEInst) {
1149 // Register extra constants if needed.
1150
1151 // Registers a type and constant for computing the result of the
1152 // given instruction. If the result of the instruction is a vector,
1153 // then make a splat vector constant with the same number of
1154 // elements.
1155 auto register_constant = [this, &I](Constant *constant) {
1156 FindType(constant->getType());
1157 FindConstant(constant);
1158 if (auto *vectorTy = dyn_cast<VectorType>(I.getType())) {
1159 // Register the splat vector of the value with the same
1160 // width as the result of the instruction.
1161 auto *vec_constant = ConstantVector::getSplat(
1162 static_cast<unsigned>(vectorTy->getNumElements()),
1163 constant);
1164 FindConstant(vec_constant);
1165 FindType(vec_constant->getType());
1166 }
1167 };
1168 switch (IndirectEInst) {
1169 case glsl::ExtInstFindUMsb:
1170 // clz needs OpExtInst and OpISub with constant 31, or splat
1171 // vector of 31. Add it to the constant list here.
1172 register_constant(
1173 ConstantInt::get(Type::getInt32Ty(Context), 31));
1174 break;
1175 case glsl::ExtInstAcos:
1176 case glsl::ExtInstAsin:
Kévin Petiteb9f90a2018-09-29 12:29:34 +01001177 case glsl::ExtInstAtan:
David Neto3fbb4072017-10-16 11:28:14 -04001178 case glsl::ExtInstAtan2:
1179 // We need 1/pi for acospi, asinpi, atan2pi.
1180 register_constant(
1181 ConstantFP::get(Type::getFloatTy(Context), kOneOverPi));
1182 break;
1183 default:
1184 assert(false && "internally inconsistent");
1185 }
David Neto22f144c2017-06-12 14:26:21 -04001186 }
1187 }
1188 }
1189 }
1190 }
1191
1192 return HasExtInst;
1193}
1194
1195void SPIRVProducerPass::FindTypePerGlobalVar(GlobalVariable &GV) {
1196 // Investigate global variable's type.
1197 FindType(GV.getType());
1198}
1199
1200void SPIRVProducerPass::FindTypePerFunc(Function &F) {
1201 // Investigate function's type.
1202 FunctionType *FTy = F.getFunctionType();
1203
1204 if (F.getCallingConv() != CallingConv::SPIR_KERNEL) {
1205 auto &GlobalConstFuncTyMap = getGlobalConstFuncTypeMap();
David Neto9ed8e2f2018-03-24 06:47:24 -07001206 // Handle a regular function with global constant parameters.
David Neto22f144c2017-06-12 14:26:21 -04001207 if (GlobalConstFuncTyMap.count(FTy)) {
1208 uint32_t GVCstArgIdx = GlobalConstFuncTypeMap[FTy].second;
1209 SmallVector<Type *, 4> NewFuncParamTys;
1210 for (unsigned i = 0; i < FTy->getNumParams(); i++) {
1211 Type *ParamTy = FTy->getParamType(i);
1212 if (i == GVCstArgIdx) {
1213 Type *EleTy = ParamTy->getPointerElementType();
1214 ParamTy = PointerType::get(EleTy, AddressSpace::ModuleScopePrivate);
1215 }
1216
1217 NewFuncParamTys.push_back(ParamTy);
1218 }
1219
1220 FunctionType *NewFTy =
1221 FunctionType::get(FTy->getReturnType(), NewFuncParamTys, false);
1222 GlobalConstFuncTyMap[FTy] = std::make_pair(NewFTy, GVCstArgIdx);
1223 FTy = NewFTy;
1224 }
1225
1226 FindType(FTy);
1227 } else {
1228 // As kernel functions do not have parameters, create new function type and
1229 // add it to type map.
1230 SmallVector<Type *, 4> NewFuncParamTys;
1231 FunctionType *NewFTy =
1232 FunctionType::get(FTy->getReturnType(), NewFuncParamTys, false);
1233 FindType(NewFTy);
1234 }
1235
1236 // Investigate instructions' type in function body.
1237 for (BasicBlock &BB : F) {
1238 for (Instruction &I : BB) {
1239 if (isa<ShuffleVectorInst>(I)) {
1240 for (unsigned i = 0; i < I.getNumOperands(); i++) {
1241 // Ignore type for mask of shuffle vector instruction.
1242 if (i == 2) {
1243 continue;
1244 }
1245
1246 Value *Op = I.getOperand(i);
1247 if (!isa<MetadataAsValue>(Op)) {
1248 FindType(Op->getType());
1249 }
1250 }
1251
1252 FindType(I.getType());
1253 continue;
1254 }
1255
David Neto862b7d82018-06-14 18:48:37 -04001256 CallInst *Call = dyn_cast<CallInst>(&I);
1257
1258 if (Call && Call->getCalledFunction()->getName().startswith(
Alan Baker202c8c72018-08-13 13:47:44 -04001259 clspv::ResourceAccessorFunction())) {
David Neto862b7d82018-06-14 18:48:37 -04001260 // This is a fake call representing access to a resource variable.
1261 // We handle that elsewhere.
1262 continue;
1263 }
1264
Alan Baker202c8c72018-08-13 13:47:44 -04001265 if (Call && Call->getCalledFunction()->getName().startswith(
1266 clspv::WorkgroupAccessorFunction())) {
1267 // This is a fake call representing access to a workgroup variable.
1268 // We handle that elsewhere.
1269 continue;
1270 }
1271
David Neto22f144c2017-06-12 14:26:21 -04001272 // Work through the operands of the instruction.
1273 for (unsigned i = 0; i < I.getNumOperands(); i++) {
1274 Value *const Op = I.getOperand(i);
1275 // If any of the operands is a constant, find the type!
1276 if (isa<Constant>(Op) && !isa<GlobalValue>(Op)) {
1277 FindType(Op->getType());
1278 }
1279 }
1280
1281 for (Use &Op : I.operands()) {
Radek Szymanskibe4b0c42018-10-04 22:20:53 +01001282 if (isa<CallInst>(&I)) {
David Neto22f144c2017-06-12 14:26:21 -04001283 // Avoid to check call instruction's type.
1284 break;
1285 }
Alan Baker202c8c72018-08-13 13:47:44 -04001286 if (CallInst *OpCall = dyn_cast<CallInst>(Op)) {
1287 if (OpCall && OpCall->getCalledFunction()->getName().startswith(
1288 clspv::WorkgroupAccessorFunction())) {
1289 // This is a fake call representing access to a workgroup variable.
1290 // We handle that elsewhere.
1291 continue;
1292 }
1293 }
David Neto22f144c2017-06-12 14:26:21 -04001294 if (!isa<MetadataAsValue>(&Op)) {
1295 FindType(Op->getType());
1296 continue;
1297 }
1298 }
1299
David Neto22f144c2017-06-12 14:26:21 -04001300 // We don't want to track the type of this call as we are going to replace
1301 // it.
David Neto862b7d82018-06-14 18:48:37 -04001302 if (Call && ("clspv.sampler.var.literal" ==
David Neto22f144c2017-06-12 14:26:21 -04001303 Call->getCalledFunction()->getName())) {
1304 continue;
1305 }
1306
1307 if (GetElementPtrInst *GEP = dyn_cast<GetElementPtrInst>(&I)) {
1308 // If gep's base operand has ModuleScopePrivate address space, make gep
1309 // return ModuleScopePrivate address space.
1310 if (GEP->getPointerAddressSpace() == AddressSpace::ModuleScopePrivate) {
1311 // Add pointer type with private address space for global constant to
1312 // type list.
1313 Type *EleTy = I.getType()->getPointerElementType();
1314 Type *NewPTy =
1315 PointerType::get(EleTy, AddressSpace::ModuleScopePrivate);
1316
1317 FindType(NewPTy);
1318 continue;
1319 }
1320 }
1321
1322 FindType(I.getType());
1323 }
1324 }
1325}
1326
David Neto862b7d82018-06-14 18:48:37 -04001327void SPIRVProducerPass::FindTypesForSamplerMap(Module &M) {
1328 // If we are using a sampler map, find the type of the sampler.
1329 if (M.getFunction("clspv.sampler.var.literal") ||
1330 0 < getSamplerMap().size()) {
1331 auto SamplerStructTy = M.getTypeByName("opencl.sampler_t");
1332 if (!SamplerStructTy) {
1333 SamplerStructTy = StructType::create(M.getContext(), "opencl.sampler_t");
1334 }
1335
1336 SamplerTy = SamplerStructTy->getPointerTo(AddressSpace::UniformConstant);
1337
1338 FindType(SamplerTy);
1339 }
1340}
1341
1342void SPIRVProducerPass::FindTypesForResourceVars(Module &M) {
1343 // Record types so they are generated.
1344 TypesNeedingLayout.reset();
1345 StructTypesNeedingBlock.reset();
1346
1347 // To match older clspv codegen, generate the float type first if required
1348 // for images.
1349 for (const auto *info : ModuleOrderedResourceVars) {
1350 if (info->arg_kind == clspv::ArgKind::ReadOnlyImage ||
1351 info->arg_kind == clspv::ArgKind::WriteOnlyImage) {
1352 // We need "float" for the sampled component type.
1353 FindType(Type::getFloatTy(M.getContext()));
1354 // We only need to find it once.
1355 break;
1356 }
1357 }
1358
1359 for (const auto *info : ModuleOrderedResourceVars) {
1360 Type *type = info->var_fn->getReturnType();
1361
1362 switch (info->arg_kind) {
1363 case clspv::ArgKind::Buffer:
Alan Bakerfcda9482018-10-02 17:09:59 -04001364 case clspv::ArgKind::BufferUBO:
David Neto862b7d82018-06-14 18:48:37 -04001365 if (auto *sty = dyn_cast<StructType>(type->getPointerElementType())) {
1366 StructTypesNeedingBlock.insert(sty);
1367 } else {
1368 errs() << *type << "\n";
1369 llvm_unreachable("Buffer arguments must map to structures!");
1370 }
1371 break;
1372 case clspv::ArgKind::Pod:
1373 if (auto *sty = dyn_cast<StructType>(type->getPointerElementType())) {
1374 StructTypesNeedingBlock.insert(sty);
1375 } else {
1376 errs() << *type << "\n";
1377 llvm_unreachable("POD arguments must map to structures!");
1378 }
1379 break;
1380 case clspv::ArgKind::ReadOnlyImage:
1381 case clspv::ArgKind::WriteOnlyImage:
1382 case clspv::ArgKind::Sampler:
1383 // Sampler and image types map to the pointee type but
1384 // in the uniform constant address space.
1385 type = PointerType::get(type->getPointerElementType(),
1386 clspv::AddressSpace::UniformConstant);
1387 break;
1388 default:
1389 break;
1390 }
1391
1392 // The converted type is the type of the OpVariable we will generate.
1393 // If the pointee type is an array of size zero, FindType will convert it
1394 // to a runtime array.
1395 FindType(type);
1396 }
1397
1398 // Traverse the arrays and structures underneath each Block, and
1399 // mark them as needing layout.
1400 std::vector<Type *> work_list(StructTypesNeedingBlock.begin(),
1401 StructTypesNeedingBlock.end());
1402 while (!work_list.empty()) {
1403 Type *type = work_list.back();
1404 work_list.pop_back();
1405 TypesNeedingLayout.insert(type);
1406 switch (type->getTypeID()) {
1407 case Type::ArrayTyID:
1408 work_list.push_back(type->getArrayElementType());
1409 if (!Hack_generate_runtime_array_stride_early) {
1410 // Remember this array type for deferred decoration.
1411 TypesNeedingArrayStride.insert(type);
1412 }
1413 break;
1414 case Type::StructTyID:
1415 for (auto *elem_ty : cast<StructType>(type)->elements()) {
1416 work_list.push_back(elem_ty);
1417 }
1418 default:
1419 // This type and its contained types don't get layout.
1420 break;
1421 }
1422 }
1423}
1424
Alan Baker202c8c72018-08-13 13:47:44 -04001425void SPIRVProducerPass::FindWorkgroupVars(Module &M) {
1426 // The SpecId assignment for pointer-to-local arguments is recorded in
1427 // module-level metadata. Translate that information into local argument
1428 // information.
1429 NamedMDNode *nmd = M.getNamedMetadata(clspv::LocalSpecIdMetadataName());
alan-bakerb6b09dc2018-11-08 16:59:28 -05001430 if (!nmd)
1431 return;
Alan Baker202c8c72018-08-13 13:47:44 -04001432 for (auto operand : nmd->operands()) {
1433 MDTuple *tuple = cast<MDTuple>(operand);
1434 ValueAsMetadata *fn_md = cast<ValueAsMetadata>(tuple->getOperand(0));
1435 Function *func = cast<Function>(fn_md->getValue());
alan-bakerb6b09dc2018-11-08 16:59:28 -05001436 ConstantAsMetadata *arg_index_md =
1437 cast<ConstantAsMetadata>(tuple->getOperand(1));
1438 int arg_index = static_cast<int>(
1439 cast<ConstantInt>(arg_index_md->getValue())->getSExtValue());
1440 Argument *arg = &*(func->arg_begin() + arg_index);
Alan Baker202c8c72018-08-13 13:47:44 -04001441
1442 ConstantAsMetadata *spec_id_md =
1443 cast<ConstantAsMetadata>(tuple->getOperand(2));
alan-bakerb6b09dc2018-11-08 16:59:28 -05001444 int spec_id = static_cast<int>(
1445 cast<ConstantInt>(spec_id_md->getValue())->getSExtValue());
Alan Baker202c8c72018-08-13 13:47:44 -04001446
1447 max_local_spec_id_ = std::max(max_local_spec_id_, spec_id + 1);
1448 LocalArgSpecIds[arg] = spec_id;
alan-bakerb6b09dc2018-11-08 16:59:28 -05001449 if (LocalSpecIdInfoMap.count(spec_id))
1450 continue;
Alan Baker202c8c72018-08-13 13:47:44 -04001451
1452 // We haven't seen this SpecId yet, so generate the LocalArgInfo for it.
1453 LocalArgInfo info{nextID, arg->getType()->getPointerElementType(),
1454 nextID + 1, nextID + 2,
1455 nextID + 3, spec_id};
1456 LocalSpecIdInfoMap[spec_id] = info;
1457 nextID += 4;
1458
1459 // Ensure the types necessary for this argument get generated.
1460 Type *IdxTy = Type::getInt32Ty(M.getContext());
1461 FindConstant(ConstantInt::get(IdxTy, 0));
1462 FindType(IdxTy);
1463 FindType(arg->getType());
1464 }
1465}
1466
David Neto22f144c2017-06-12 14:26:21 -04001467void SPIRVProducerPass::FindType(Type *Ty) {
1468 TypeList &TyList = getTypeList();
1469
1470 if (0 != TyList.idFor(Ty)) {
1471 return;
1472 }
1473
1474 if (Ty->isPointerTy()) {
1475 auto AddrSpace = Ty->getPointerAddressSpace();
1476 if ((AddressSpace::Constant == AddrSpace) ||
1477 (AddressSpace::Global == AddrSpace)) {
1478 auto PointeeTy = Ty->getPointerElementType();
1479
1480 if (PointeeTy->isStructTy() &&
1481 dyn_cast<StructType>(PointeeTy)->isOpaque()) {
1482 FindType(PointeeTy);
1483 auto ActualPointerTy =
1484 PointeeTy->getPointerTo(AddressSpace::UniformConstant);
1485 FindType(ActualPointerTy);
1486 return;
1487 }
1488 }
1489 }
1490
David Neto862b7d82018-06-14 18:48:37 -04001491 // By convention, LLVM array type with 0 elements will map to
1492 // OpTypeRuntimeArray. Otherwise, it will map to OpTypeArray, which
1493 // has a constant number of elements. We need to support type of the
1494 // constant.
1495 if (auto *arrayTy = dyn_cast<ArrayType>(Ty)) {
1496 if (arrayTy->getNumElements() > 0) {
1497 LLVMContext &Context = Ty->getContext();
1498 FindType(Type::getInt32Ty(Context));
1499 }
David Neto22f144c2017-06-12 14:26:21 -04001500 }
1501
1502 for (Type *SubTy : Ty->subtypes()) {
1503 FindType(SubTy);
1504 }
1505
1506 TyList.insert(Ty);
1507}
1508
1509void SPIRVProducerPass::FindConstantPerGlobalVar(GlobalVariable &GV) {
1510 // If the global variable has a (non undef) initializer.
1511 if (GV.hasInitializer() && !isa<UndefValue>(GV.getInitializer())) {
David Neto862b7d82018-06-14 18:48:37 -04001512 // Generate the constant if it's not the initializer to a module scope
1513 // constant that we will expect in a storage buffer.
1514 const bool module_scope_constant_external_init =
1515 (GV.getType()->getPointerAddressSpace() == AddressSpace::Constant) &&
1516 clspv::Option::ModuleConstantsInStorageBuffer();
1517 if (!module_scope_constant_external_init) {
1518 FindConstant(GV.getInitializer());
1519 }
David Neto22f144c2017-06-12 14:26:21 -04001520 }
1521}
1522
1523void SPIRVProducerPass::FindConstantPerFunc(Function &F) {
1524 // Investigate constants in function body.
1525 for (BasicBlock &BB : F) {
1526 for (Instruction &I : BB) {
David Neto862b7d82018-06-14 18:48:37 -04001527 if (auto *call = dyn_cast<CallInst>(&I)) {
1528 auto name = call->getCalledFunction()->getName();
1529 if (name == "clspv.sampler.var.literal") {
1530 // We've handled these constants elsewhere, so skip it.
1531 continue;
1532 }
Alan Baker202c8c72018-08-13 13:47:44 -04001533 if (name.startswith(clspv::ResourceAccessorFunction())) {
1534 continue;
1535 }
1536 if (name.startswith(clspv::WorkgroupAccessorFunction())) {
David Neto862b7d82018-06-14 18:48:37 -04001537 continue;
1538 }
David Neto22f144c2017-06-12 14:26:21 -04001539 }
1540
1541 if (isa<AllocaInst>(I)) {
1542 // Alloca instruction has constant for the number of element. Ignore it.
1543 continue;
1544 } else if (isa<ShuffleVectorInst>(I)) {
1545 for (unsigned i = 0; i < I.getNumOperands(); i++) {
1546 // Ignore constant for mask of shuffle vector instruction.
1547 if (i == 2) {
1548 continue;
1549 }
1550
1551 if (isa<Constant>(I.getOperand(i)) &&
1552 !isa<GlobalValue>(I.getOperand(i))) {
1553 FindConstant(I.getOperand(i));
1554 }
1555 }
1556
1557 continue;
1558 } else if (isa<InsertElementInst>(I)) {
1559 // Handle InsertElement with <4 x i8> specially.
1560 Type *CompositeTy = I.getOperand(0)->getType();
1561 if (is4xi8vec(CompositeTy)) {
1562 LLVMContext &Context = CompositeTy->getContext();
1563 if (isa<Constant>(I.getOperand(0))) {
1564 FindConstant(I.getOperand(0));
1565 }
1566
1567 if (isa<Constant>(I.getOperand(1))) {
1568 FindConstant(I.getOperand(1));
1569 }
1570
1571 // Add mask constant 0xFF.
1572 Constant *CstFF = ConstantInt::get(Type::getInt32Ty(Context), 0xFF);
1573 FindConstant(CstFF);
1574
1575 // Add shift amount constant.
1576 if (ConstantInt *CI = dyn_cast<ConstantInt>(I.getOperand(2))) {
1577 uint64_t Idx = CI->getZExtValue();
1578 Constant *CstShiftAmount =
1579 ConstantInt::get(Type::getInt32Ty(Context), Idx * 8);
1580 FindConstant(CstShiftAmount);
1581 }
1582
1583 continue;
1584 }
1585
1586 for (unsigned i = 0; i < I.getNumOperands(); i++) {
1587 // Ignore constant for index of InsertElement instruction.
1588 if (i == 2) {
1589 continue;
1590 }
1591
1592 if (isa<Constant>(I.getOperand(i)) &&
1593 !isa<GlobalValue>(I.getOperand(i))) {
1594 FindConstant(I.getOperand(i));
1595 }
1596 }
1597
1598 continue;
1599 } else if (isa<ExtractElementInst>(I)) {
1600 // Handle ExtractElement with <4 x i8> specially.
1601 Type *CompositeTy = I.getOperand(0)->getType();
1602 if (is4xi8vec(CompositeTy)) {
1603 LLVMContext &Context = CompositeTy->getContext();
1604 if (isa<Constant>(I.getOperand(0))) {
1605 FindConstant(I.getOperand(0));
1606 }
1607
1608 // Add mask constant 0xFF.
1609 Constant *CstFF = ConstantInt::get(Type::getInt32Ty(Context), 0xFF);
1610 FindConstant(CstFF);
1611
1612 // Add shift amount constant.
1613 if (ConstantInt *CI = dyn_cast<ConstantInt>(I.getOperand(1))) {
1614 uint64_t Idx = CI->getZExtValue();
1615 Constant *CstShiftAmount =
1616 ConstantInt::get(Type::getInt32Ty(Context), Idx * 8);
1617 FindConstant(CstShiftAmount);
1618 } else {
1619 ConstantInt *Cst8 = ConstantInt::get(Type::getInt32Ty(Context), 8);
1620 FindConstant(Cst8);
1621 }
1622
1623 continue;
1624 }
1625
1626 for (unsigned i = 0; i < I.getNumOperands(); i++) {
1627 // Ignore constant for index of ExtractElement instruction.
1628 if (i == 1) {
1629 continue;
1630 }
1631
1632 if (isa<Constant>(I.getOperand(i)) &&
1633 !isa<GlobalValue>(I.getOperand(i))) {
1634 FindConstant(I.getOperand(i));
1635 }
1636 }
1637
1638 continue;
alan-bakerb6b09dc2018-11-08 16:59:28 -05001639 } else if ((Instruction::Xor == I.getOpcode()) &&
1640 I.getType()->isIntegerTy(1)) {
1641 // We special case for Xor where the type is i1 and one of the arguments
1642 // is a constant 1 (true), this is an OpLogicalNot in SPIR-V, and we
1643 // don't need the constant
David Neto22f144c2017-06-12 14:26:21 -04001644 bool foundConstantTrue = false;
1645 for (Use &Op : I.operands()) {
1646 if (isa<Constant>(Op) && !isa<GlobalValue>(Op)) {
1647 auto CI = cast<ConstantInt>(Op);
1648
1649 if (CI->isZero() || foundConstantTrue) {
alan-bakerb6b09dc2018-11-08 16:59:28 -05001650 // If we already found the true constant, we might (probably only
1651 // on -O0) have an OpLogicalNot which is taking a constant
1652 // argument, so discover it anyway.
David Neto22f144c2017-06-12 14:26:21 -04001653 FindConstant(Op);
1654 } else {
1655 foundConstantTrue = true;
1656 }
1657 }
1658 }
1659
1660 continue;
David Netod2de94a2017-08-28 17:27:47 -04001661 } else if (isa<TruncInst>(I)) {
alan-bakerb39c8262019-03-08 14:03:37 -05001662 // Special case if i8 is not generally handled.
1663 if (!clspv::Option::Int8Support()) {
1664 // For truncation to i8 we mask against 255.
1665 Type *ToTy = I.getType();
1666 if (8u == ToTy->getPrimitiveSizeInBits()) {
1667 LLVMContext &Context = ToTy->getContext();
1668 Constant *Cst255 =
1669 ConstantInt::get(Type::getInt32Ty(Context), 0xff);
1670 FindConstant(Cst255);
1671 }
David Netod2de94a2017-08-28 17:27:47 -04001672 }
Neil Henning39672102017-09-29 14:33:13 +01001673 } else if (isa<AtomicRMWInst>(I)) {
1674 LLVMContext &Context = I.getContext();
1675
1676 FindConstant(
1677 ConstantInt::get(Type::getInt32Ty(Context), spv::ScopeDevice));
1678 FindConstant(ConstantInt::get(
1679 Type::getInt32Ty(Context),
1680 spv::MemorySemanticsUniformMemoryMask |
1681 spv::MemorySemanticsSequentiallyConsistentMask));
David Neto22f144c2017-06-12 14:26:21 -04001682 }
1683
1684 for (Use &Op : I.operands()) {
1685 if (isa<Constant>(Op) && !isa<GlobalValue>(Op)) {
1686 FindConstant(Op);
1687 }
1688 }
1689 }
1690 }
1691}
1692
1693void SPIRVProducerPass::FindConstant(Value *V) {
David Neto22f144c2017-06-12 14:26:21 -04001694 ValueList &CstList = getConstantList();
1695
David Netofb9a7972017-08-25 17:08:24 -04001696 // If V is already tracked, ignore it.
1697 if (0 != CstList.idFor(V)) {
David Neto22f144c2017-06-12 14:26:21 -04001698 return;
1699 }
1700
David Neto862b7d82018-06-14 18:48:37 -04001701 if (isa<GlobalValue>(V) && clspv::Option::ModuleConstantsInStorageBuffer()) {
1702 return;
1703 }
1704
David Neto22f144c2017-06-12 14:26:21 -04001705 Constant *Cst = cast<Constant>(V);
David Neto862b7d82018-06-14 18:48:37 -04001706 Type *CstTy = Cst->getType();
David Neto22f144c2017-06-12 14:26:21 -04001707
1708 // Handle constant with <4 x i8> type specially.
David Neto22f144c2017-06-12 14:26:21 -04001709 if (is4xi8vec(CstTy)) {
1710 if (!isa<GlobalValue>(V)) {
David Netofb9a7972017-08-25 17:08:24 -04001711 CstList.insert(V);
David Neto22f144c2017-06-12 14:26:21 -04001712 }
1713 }
1714
1715 if (Cst->getNumOperands()) {
1716 for (User::const_op_iterator I = Cst->op_begin(), E = Cst->op_end(); I != E;
1717 ++I) {
1718 FindConstant(*I);
1719 }
1720
David Netofb9a7972017-08-25 17:08:24 -04001721 CstList.insert(Cst);
David Neto22f144c2017-06-12 14:26:21 -04001722 return;
1723 } else if (const ConstantDataSequential *CDS =
1724 dyn_cast<ConstantDataSequential>(Cst)) {
1725 // Add constants for each element to constant list.
1726 for (unsigned i = 0; i < CDS->getNumElements(); i++) {
1727 Constant *EleCst = CDS->getElementAsConstant(i);
1728 FindConstant(EleCst);
1729 }
1730 }
1731
1732 if (!isa<GlobalValue>(V)) {
David Netofb9a7972017-08-25 17:08:24 -04001733 CstList.insert(V);
David Neto22f144c2017-06-12 14:26:21 -04001734 }
1735}
1736
1737spv::StorageClass SPIRVProducerPass::GetStorageClass(unsigned AddrSpace) const {
1738 switch (AddrSpace) {
1739 default:
1740 llvm_unreachable("Unsupported OpenCL address space");
1741 case AddressSpace::Private:
1742 return spv::StorageClassFunction;
1743 case AddressSpace::Global:
David Neto22f144c2017-06-12 14:26:21 -04001744 return spv::StorageClassStorageBuffer;
Alan Bakerfcda9482018-10-02 17:09:59 -04001745 case AddressSpace::Constant:
1746 return clspv::Option::ConstantArgsInUniformBuffer()
1747 ? spv::StorageClassUniform
1748 : spv::StorageClassStorageBuffer;
David Neto22f144c2017-06-12 14:26:21 -04001749 case AddressSpace::Input:
1750 return spv::StorageClassInput;
1751 case AddressSpace::Local:
1752 return spv::StorageClassWorkgroup;
1753 case AddressSpace::UniformConstant:
1754 return spv::StorageClassUniformConstant;
David Neto9ed8e2f2018-03-24 06:47:24 -07001755 case AddressSpace::Uniform:
David Netoe439d702018-03-23 13:14:08 -07001756 return spv::StorageClassUniform;
David Neto22f144c2017-06-12 14:26:21 -04001757 case AddressSpace::ModuleScopePrivate:
1758 return spv::StorageClassPrivate;
1759 }
1760}
1761
David Neto862b7d82018-06-14 18:48:37 -04001762spv::StorageClass
1763SPIRVProducerPass::GetStorageClassForArgKind(clspv::ArgKind arg_kind) const {
1764 switch (arg_kind) {
1765 case clspv::ArgKind::Buffer:
1766 return spv::StorageClassStorageBuffer;
Alan Bakerfcda9482018-10-02 17:09:59 -04001767 case clspv::ArgKind::BufferUBO:
1768 return spv::StorageClassUniform;
David Neto862b7d82018-06-14 18:48:37 -04001769 case clspv::ArgKind::Pod:
1770 return clspv::Option::PodArgsInUniformBuffer()
1771 ? spv::StorageClassUniform
1772 : spv::StorageClassStorageBuffer;
1773 case clspv::ArgKind::Local:
1774 return spv::StorageClassWorkgroup;
1775 case clspv::ArgKind::ReadOnlyImage:
1776 case clspv::ArgKind::WriteOnlyImage:
1777 case clspv::ArgKind::Sampler:
1778 return spv::StorageClassUniformConstant;
Radek Szymanskibe4b0c42018-10-04 22:20:53 +01001779 default:
1780 llvm_unreachable("Unsupported storage class for argument kind");
David Neto862b7d82018-06-14 18:48:37 -04001781 }
1782}
1783
David Neto22f144c2017-06-12 14:26:21 -04001784spv::BuiltIn SPIRVProducerPass::GetBuiltin(StringRef Name) const {
1785 return StringSwitch<spv::BuiltIn>(Name)
1786 .Case("__spirv_GlobalInvocationId", spv::BuiltInGlobalInvocationId)
1787 .Case("__spirv_LocalInvocationId", spv::BuiltInLocalInvocationId)
1788 .Case("__spirv_WorkgroupSize", spv::BuiltInWorkgroupSize)
1789 .Case("__spirv_NumWorkgroups", spv::BuiltInNumWorkgroups)
1790 .Case("__spirv_WorkgroupId", spv::BuiltInWorkgroupId)
1791 .Default(spv::BuiltInMax);
1792}
1793
1794void SPIRVProducerPass::GenerateExtInstImport() {
1795 SPIRVInstructionList &SPIRVInstList = getSPIRVInstList();
1796 uint32_t &ExtInstImportID = getOpExtInstImportID();
1797
1798 //
1799 // Generate OpExtInstImport.
1800 //
1801 // Ops[0] ... Ops[n] = Name (Literal String)
David Neto22f144c2017-06-12 14:26:21 -04001802 ExtInstImportID = nextID;
David Neto87846742018-04-11 17:36:22 -04001803 SPIRVInstList.push_back(new SPIRVInstruction(spv::OpExtInstImport, nextID++,
1804 MkString("GLSL.std.450")));
David Neto22f144c2017-06-12 14:26:21 -04001805}
1806
alan-bakerb6b09dc2018-11-08 16:59:28 -05001807void SPIRVProducerPass::GenerateSPIRVTypes(LLVMContext &Context,
1808 Module &module) {
David Neto22f144c2017-06-12 14:26:21 -04001809 SPIRVInstructionList &SPIRVInstList = getSPIRVInstList();
1810 ValueMapType &VMap = getValueMap();
1811 ValueMapType &AllocatedVMap = getAllocatedValueMap();
Alan Bakerfcda9482018-10-02 17:09:59 -04001812 const auto &DL = module.getDataLayout();
David Neto22f144c2017-06-12 14:26:21 -04001813
1814 // Map for OpTypeRuntimeArray. If argument has pointer type, 2 spirv type
1815 // instructions are generated. They are OpTypePointer and OpTypeRuntimeArray.
1816 DenseMap<Type *, uint32_t> OpRuntimeTyMap;
1817
1818 for (Type *Ty : getTypeList()) {
1819 // Update TypeMap with nextID for reference later.
1820 TypeMap[Ty] = nextID;
1821
1822 switch (Ty->getTypeID()) {
1823 default: {
1824 Ty->print(errs());
1825 llvm_unreachable("Unsupported type???");
1826 break;
1827 }
1828 case Type::MetadataTyID:
1829 case Type::LabelTyID: {
1830 // Ignore these types.
1831 break;
1832 }
1833 case Type::PointerTyID: {
1834 PointerType *PTy = cast<PointerType>(Ty);
1835 unsigned AddrSpace = PTy->getAddressSpace();
1836
1837 // For the purposes of our Vulkan SPIR-V type system, constant and global
1838 // are conflated.
1839 bool UseExistingOpTypePointer = false;
1840 if (AddressSpace::Constant == AddrSpace) {
Alan Bakerfcda9482018-10-02 17:09:59 -04001841 if (!clspv::Option::ConstantArgsInUniformBuffer()) {
1842 AddrSpace = AddressSpace::Global;
alan-bakerb6b09dc2018-11-08 16:59:28 -05001843 // Check to see if we already created this type (for instance, if we
1844 // had a constant <type>* and a global <type>*, the type would be
1845 // created by one of these types, and shared by both).
Alan Bakerfcda9482018-10-02 17:09:59 -04001846 auto GlobalTy = PTy->getPointerElementType()->getPointerTo(AddrSpace);
1847 if (0 < TypeMap.count(GlobalTy)) {
1848 TypeMap[PTy] = TypeMap[GlobalTy];
1849 UseExistingOpTypePointer = true;
1850 break;
1851 }
David Neto22f144c2017-06-12 14:26:21 -04001852 }
1853 } else if (AddressSpace::Global == AddrSpace) {
Alan Bakerfcda9482018-10-02 17:09:59 -04001854 if (!clspv::Option::ConstantArgsInUniformBuffer()) {
1855 AddrSpace = AddressSpace::Constant;
David Neto22f144c2017-06-12 14:26:21 -04001856
alan-bakerb6b09dc2018-11-08 16:59:28 -05001857 // Check to see if we already created this type (for instance, if we
1858 // had a constant <type>* and a global <type>*, the type would be
1859 // created by one of these types, and shared by both).
1860 auto ConstantTy =
1861 PTy->getPointerElementType()->getPointerTo(AddrSpace);
Alan Bakerfcda9482018-10-02 17:09:59 -04001862 if (0 < TypeMap.count(ConstantTy)) {
1863 TypeMap[PTy] = TypeMap[ConstantTy];
1864 UseExistingOpTypePointer = true;
1865 }
David Neto22f144c2017-06-12 14:26:21 -04001866 }
1867 }
1868
David Neto862b7d82018-06-14 18:48:37 -04001869 const bool HasArgUser = true;
David Neto22f144c2017-06-12 14:26:21 -04001870
David Neto862b7d82018-06-14 18:48:37 -04001871 if (HasArgUser && !UseExistingOpTypePointer) {
David Neto22f144c2017-06-12 14:26:21 -04001872 //
1873 // Generate OpTypePointer.
1874 //
1875
1876 // OpTypePointer
1877 // Ops[0] = Storage Class
1878 // Ops[1] = Element Type ID
1879 SPIRVOperandList Ops;
1880
David Neto257c3892018-04-11 13:19:45 -04001881 Ops << MkNum(GetStorageClass(AddrSpace))
1882 << MkId(lookupType(PTy->getElementType()));
David Neto22f144c2017-06-12 14:26:21 -04001883
David Neto87846742018-04-11 17:36:22 -04001884 auto *Inst = new SPIRVInstruction(spv::OpTypePointer, nextID++, Ops);
David Neto22f144c2017-06-12 14:26:21 -04001885 SPIRVInstList.push_back(Inst);
1886 }
David Neto22f144c2017-06-12 14:26:21 -04001887 break;
1888 }
1889 case Type::StructTyID: {
David Neto22f144c2017-06-12 14:26:21 -04001890 StructType *STy = cast<StructType>(Ty);
1891
1892 // Handle sampler type.
1893 if (STy->isOpaque()) {
1894 if (STy->getName().equals("opencl.sampler_t")) {
1895 //
1896 // Generate OpTypeSampler
1897 //
1898 // Empty Ops.
1899 SPIRVOperandList Ops;
1900
David Neto87846742018-04-11 17:36:22 -04001901 auto *Inst = new SPIRVInstruction(spv::OpTypeSampler, nextID++, Ops);
David Neto22f144c2017-06-12 14:26:21 -04001902 SPIRVInstList.push_back(Inst);
1903 break;
1904 } else if (STy->getName().equals("opencl.image2d_ro_t") ||
1905 STy->getName().equals("opencl.image2d_wo_t") ||
1906 STy->getName().equals("opencl.image3d_ro_t") ||
1907 STy->getName().equals("opencl.image3d_wo_t")) {
1908 //
1909 // Generate OpTypeImage
1910 //
1911 // Ops[0] = Sampled Type ID
1912 // Ops[1] = Dim ID
1913 // Ops[2] = Depth (Literal Number)
1914 // Ops[3] = Arrayed (Literal Number)
1915 // Ops[4] = MS (Literal Number)
1916 // Ops[5] = Sampled (Literal Number)
1917 // Ops[6] = Image Format ID
1918 //
1919 SPIRVOperandList Ops;
1920
1921 // TODO: Changed Sampled Type according to situations.
1922 uint32_t SampledTyID = lookupType(Type::getFloatTy(Context));
David Neto257c3892018-04-11 13:19:45 -04001923 Ops << MkId(SampledTyID);
David Neto22f144c2017-06-12 14:26:21 -04001924
1925 spv::Dim DimID = spv::Dim2D;
1926 if (STy->getName().equals("opencl.image3d_ro_t") ||
1927 STy->getName().equals("opencl.image3d_wo_t")) {
1928 DimID = spv::Dim3D;
1929 }
David Neto257c3892018-04-11 13:19:45 -04001930 Ops << MkNum(DimID);
David Neto22f144c2017-06-12 14:26:21 -04001931
1932 // TODO: Set up Depth.
David Neto257c3892018-04-11 13:19:45 -04001933 Ops << MkNum(0);
David Neto22f144c2017-06-12 14:26:21 -04001934
1935 // TODO: Set up Arrayed.
David Neto257c3892018-04-11 13:19:45 -04001936 Ops << MkNum(0);
David Neto22f144c2017-06-12 14:26:21 -04001937
1938 // TODO: Set up MS.
David Neto257c3892018-04-11 13:19:45 -04001939 Ops << MkNum(0);
David Neto22f144c2017-06-12 14:26:21 -04001940
1941 // TODO: Set up Sampled.
1942 //
1943 // From Spec
1944 //
1945 // 0 indicates this is only known at run time, not at compile time
1946 // 1 indicates will be used with sampler
1947 // 2 indicates will be used without a sampler (a storage image)
1948 uint32_t Sampled = 1;
1949 if (STy->getName().equals("opencl.image2d_wo_t") ||
1950 STy->getName().equals("opencl.image3d_wo_t")) {
1951 Sampled = 2;
1952 }
David Neto257c3892018-04-11 13:19:45 -04001953 Ops << MkNum(Sampled);
David Neto22f144c2017-06-12 14:26:21 -04001954
1955 // TODO: Set up Image Format.
David Neto257c3892018-04-11 13:19:45 -04001956 Ops << MkNum(spv::ImageFormatUnknown);
David Neto22f144c2017-06-12 14:26:21 -04001957
David Neto87846742018-04-11 17:36:22 -04001958 auto *Inst = new SPIRVInstruction(spv::OpTypeImage, nextID++, Ops);
David Neto22f144c2017-06-12 14:26:21 -04001959 SPIRVInstList.push_back(Inst);
1960 break;
1961 }
1962 }
1963
1964 //
1965 // Generate OpTypeStruct
1966 //
1967 // Ops[0] ... Ops[n] = Member IDs
1968 SPIRVOperandList Ops;
1969
1970 for (auto *EleTy : STy->elements()) {
David Neto862b7d82018-06-14 18:48:37 -04001971 Ops << MkId(lookupType(EleTy));
David Neto22f144c2017-06-12 14:26:21 -04001972 }
1973
David Neto22f144c2017-06-12 14:26:21 -04001974 uint32_t STyID = nextID;
1975
alan-bakerb6b09dc2018-11-08 16:59:28 -05001976 auto *Inst = new SPIRVInstruction(spv::OpTypeStruct, nextID++, Ops);
David Neto22f144c2017-06-12 14:26:21 -04001977 SPIRVInstList.push_back(Inst);
1978
1979 // Generate OpMemberDecorate.
1980 auto DecoInsertPoint =
1981 std::find_if(SPIRVInstList.begin(), SPIRVInstList.end(),
1982 [](SPIRVInstruction *Inst) -> bool {
1983 return Inst->getOpcode() != spv::OpDecorate &&
1984 Inst->getOpcode() != spv::OpMemberDecorate &&
1985 Inst->getOpcode() != spv::OpExtInstImport;
1986 });
1987
David Netoc463b372017-08-10 15:32:21 -04001988 const auto StructLayout = DL.getStructLayout(STy);
Alan Bakerfcda9482018-10-02 17:09:59 -04001989 // Search for the correct offsets if this type was remapped.
1990 std::vector<uint32_t> *offsets = nullptr;
1991 auto iter = RemappedUBOTypeOffsets.find(STy);
1992 if (iter != RemappedUBOTypeOffsets.end()) {
1993 offsets = &iter->second;
1994 }
David Netoc463b372017-08-10 15:32:21 -04001995
David Neto862b7d82018-06-14 18:48:37 -04001996 // #error TODO(dneto): Only do this if in TypesNeedingLayout.
David Neto22f144c2017-06-12 14:26:21 -04001997 for (unsigned MemberIdx = 0; MemberIdx < STy->getNumElements();
1998 MemberIdx++) {
1999 // Ops[0] = Structure Type ID
2000 // Ops[1] = Member Index(Literal Number)
2001 // Ops[2] = Decoration (Offset)
2002 // Ops[3] = Byte Offset (Literal Number)
2003 Ops.clear();
2004
David Neto257c3892018-04-11 13:19:45 -04002005 Ops << MkId(STyID) << MkNum(MemberIdx) << MkNum(spv::DecorationOffset);
David Neto22f144c2017-06-12 14:26:21 -04002006
alan-bakerb6b09dc2018-11-08 16:59:28 -05002007 auto ByteOffset =
2008 static_cast<uint32_t>(StructLayout->getElementOffset(MemberIdx));
Alan Bakerfcda9482018-10-02 17:09:59 -04002009 if (offsets) {
2010 ByteOffset = (*offsets)[MemberIdx];
2011 }
alan-bakerb6b09dc2018-11-08 16:59:28 -05002012 // const auto ByteOffset =
Alan Bakerfcda9482018-10-02 17:09:59 -04002013 // uint32_t(StructLayout->getElementOffset(MemberIdx));
David Neto257c3892018-04-11 13:19:45 -04002014 Ops << MkNum(ByteOffset);
David Neto22f144c2017-06-12 14:26:21 -04002015
David Neto87846742018-04-11 17:36:22 -04002016 auto *DecoInst = new SPIRVInstruction(spv::OpMemberDecorate, Ops);
David Neto22f144c2017-06-12 14:26:21 -04002017 SPIRVInstList.insert(DecoInsertPoint, DecoInst);
David Neto22f144c2017-06-12 14:26:21 -04002018 }
2019
2020 // Generate OpDecorate.
David Neto862b7d82018-06-14 18:48:37 -04002021 if (StructTypesNeedingBlock.idFor(STy)) {
2022 Ops.clear();
2023 // Use Block decorations with StorageBuffer storage class.
2024 Ops << MkId(STyID) << MkNum(spv::DecorationBlock);
David Neto22f144c2017-06-12 14:26:21 -04002025
David Neto862b7d82018-06-14 18:48:37 -04002026 auto *DecoInst = new SPIRVInstruction(spv::OpDecorate, Ops);
2027 SPIRVInstList.insert(DecoInsertPoint, DecoInst);
David Neto22f144c2017-06-12 14:26:21 -04002028 }
2029 break;
2030 }
2031 case Type::IntegerTyID: {
2032 unsigned BitWidth = Ty->getPrimitiveSizeInBits();
2033
2034 if (BitWidth == 1) {
David Neto87846742018-04-11 17:36:22 -04002035 auto *Inst = new SPIRVInstruction(spv::OpTypeBool, nextID++, {});
David Neto22f144c2017-06-12 14:26:21 -04002036 SPIRVInstList.push_back(Inst);
2037 } else {
alan-bakerb39c8262019-03-08 14:03:37 -05002038 if (!clspv::Option::Int8Support()) {
2039 // i8 is added to TypeMap as i32.
2040 // No matter what LLVM type is requested first, always alias the
2041 // second one's SPIR-V type to be the same as the one we generated
2042 // first.
2043 unsigned aliasToWidth = 0;
2044 if (BitWidth == 8) {
2045 aliasToWidth = 32;
2046 BitWidth = 32;
2047 } else if (BitWidth == 32) {
2048 aliasToWidth = 8;
2049 }
2050 if (aliasToWidth) {
2051 Type *otherType = Type::getIntNTy(Ty->getContext(), aliasToWidth);
2052 auto where = TypeMap.find(otherType);
2053 if (where == TypeMap.end()) {
2054 // Go ahead and make it, but also map the other type to it.
2055 TypeMap[otherType] = nextID;
2056 } else {
2057 // Alias this SPIR-V type the existing type.
2058 TypeMap[Ty] = where->second;
2059 break;
2060 }
David Neto391aeb12017-08-26 15:51:58 -04002061 }
David Neto22f144c2017-06-12 14:26:21 -04002062 }
2063
David Neto257c3892018-04-11 13:19:45 -04002064 SPIRVOperandList Ops;
2065 Ops << MkNum(BitWidth) << MkNum(0 /* not signed */);
David Neto22f144c2017-06-12 14:26:21 -04002066
2067 SPIRVInstList.push_back(
David Neto87846742018-04-11 17:36:22 -04002068 new SPIRVInstruction(spv::OpTypeInt, nextID++, Ops));
David Neto22f144c2017-06-12 14:26:21 -04002069 }
2070 break;
2071 }
2072 case Type::HalfTyID:
2073 case Type::FloatTyID:
2074 case Type::DoubleTyID: {
2075 SPIRVOperand *WidthOp = new SPIRVOperand(
2076 SPIRVOperandType::LITERAL_INTEGER, Ty->getPrimitiveSizeInBits());
2077
2078 SPIRVInstList.push_back(
David Neto87846742018-04-11 17:36:22 -04002079 new SPIRVInstruction(spv::OpTypeFloat, nextID++, WidthOp));
David Neto22f144c2017-06-12 14:26:21 -04002080 break;
2081 }
2082 case Type::ArrayTyID: {
David Neto22f144c2017-06-12 14:26:21 -04002083 ArrayType *ArrTy = cast<ArrayType>(Ty);
David Neto862b7d82018-06-14 18:48:37 -04002084 const uint64_t Length = ArrTy->getArrayNumElements();
2085 if (Length == 0) {
2086 // By convention, map it to a RuntimeArray.
David Neto22f144c2017-06-12 14:26:21 -04002087
David Neto862b7d82018-06-14 18:48:37 -04002088 // Only generate the type once.
2089 // TODO(dneto): Can it ever be generated more than once?
2090 // Doesn't LLVM type uniqueness guarantee we'll only see this
2091 // once?
2092 Type *EleTy = ArrTy->getArrayElementType();
2093 if (OpRuntimeTyMap.count(EleTy) == 0) {
2094 uint32_t OpTypeRuntimeArrayID = nextID;
2095 OpRuntimeTyMap[Ty] = nextID;
David Neto22f144c2017-06-12 14:26:21 -04002096
David Neto862b7d82018-06-14 18:48:37 -04002097 //
2098 // Generate OpTypeRuntimeArray.
2099 //
David Neto22f144c2017-06-12 14:26:21 -04002100
David Neto862b7d82018-06-14 18:48:37 -04002101 // OpTypeRuntimeArray
2102 // Ops[0] = Element Type ID
2103 SPIRVOperandList Ops;
2104 Ops << MkId(lookupType(EleTy));
David Neto22f144c2017-06-12 14:26:21 -04002105
David Neto862b7d82018-06-14 18:48:37 -04002106 SPIRVInstList.push_back(
2107 new SPIRVInstruction(spv::OpTypeRuntimeArray, nextID++, Ops));
David Neto22f144c2017-06-12 14:26:21 -04002108
David Neto862b7d82018-06-14 18:48:37 -04002109 if (Hack_generate_runtime_array_stride_early) {
2110 // Generate OpDecorate.
2111 auto DecoInsertPoint = std::find_if(
2112 SPIRVInstList.begin(), SPIRVInstList.end(),
2113 [](SPIRVInstruction *Inst) -> bool {
2114 return Inst->getOpcode() != spv::OpDecorate &&
2115 Inst->getOpcode() != spv::OpMemberDecorate &&
2116 Inst->getOpcode() != spv::OpExtInstImport;
2117 });
David Neto22f144c2017-06-12 14:26:21 -04002118
David Neto862b7d82018-06-14 18:48:37 -04002119 // Ops[0] = Target ID
2120 // Ops[1] = Decoration (ArrayStride)
2121 // Ops[2] = Stride Number(Literal Number)
2122 Ops.clear();
David Neto85082642018-03-24 06:55:20 -07002123
David Neto862b7d82018-06-14 18:48:37 -04002124 Ops << MkId(OpTypeRuntimeArrayID)
2125 << MkNum(spv::DecorationArrayStride)
Alan Bakerfcda9482018-10-02 17:09:59 -04002126 << MkNum(static_cast<uint32_t>(GetTypeAllocSize(EleTy, DL)));
David Neto22f144c2017-06-12 14:26:21 -04002127
David Neto862b7d82018-06-14 18:48:37 -04002128 auto *DecoInst = new SPIRVInstruction(spv::OpDecorate, Ops);
2129 SPIRVInstList.insert(DecoInsertPoint, DecoInst);
2130 }
2131 }
David Neto22f144c2017-06-12 14:26:21 -04002132
David Neto862b7d82018-06-14 18:48:37 -04002133 } else {
David Neto22f144c2017-06-12 14:26:21 -04002134
David Neto862b7d82018-06-14 18:48:37 -04002135 //
2136 // Generate OpConstant and OpTypeArray.
2137 //
2138
2139 //
2140 // Generate OpConstant for array length.
2141 //
2142 // Ops[0] = Result Type ID
2143 // Ops[1] .. Ops[n] = Values LiteralNumber
2144 SPIRVOperandList Ops;
2145
2146 Type *LengthTy = Type::getInt32Ty(Context);
2147 uint32_t ResTyID = lookupType(LengthTy);
2148 Ops << MkId(ResTyID);
2149
2150 assert(Length < UINT32_MAX);
2151 Ops << MkNum(static_cast<uint32_t>(Length));
2152
2153 // Add constant for length to constant list.
2154 Constant *CstLength = ConstantInt::get(LengthTy, Length);
2155 AllocatedVMap[CstLength] = nextID;
2156 VMap[CstLength] = nextID;
2157 uint32_t LengthID = nextID;
2158
2159 auto *CstInst = new SPIRVInstruction(spv::OpConstant, nextID++, Ops);
2160 SPIRVInstList.push_back(CstInst);
2161
2162 // Remember to generate ArrayStride later
2163 getTypesNeedingArrayStride().insert(Ty);
2164
2165 //
2166 // Generate OpTypeArray.
2167 //
2168 // Ops[0] = Element Type ID
2169 // Ops[1] = Array Length Constant ID
2170 Ops.clear();
2171
2172 uint32_t EleTyID = lookupType(ArrTy->getElementType());
2173 Ops << MkId(EleTyID) << MkId(LengthID);
2174
2175 // Update TypeMap with nextID.
2176 TypeMap[Ty] = nextID;
2177
2178 auto *ArrayInst = new SPIRVInstruction(spv::OpTypeArray, nextID++, Ops);
2179 SPIRVInstList.push_back(ArrayInst);
2180 }
David Neto22f144c2017-06-12 14:26:21 -04002181 break;
2182 }
2183 case Type::VectorTyID: {
alan-bakerb39c8262019-03-08 14:03:37 -05002184 // <4 x i8> is changed to i32 if i8 is not generally supported.
2185 if (!clspv::Option::Int8Support() &&
2186 Ty->getVectorElementType() == Type::getInt8Ty(Context)) {
David Neto22f144c2017-06-12 14:26:21 -04002187 if (Ty->getVectorNumElements() == 4) {
2188 TypeMap[Ty] = lookupType(Ty->getVectorElementType());
2189 break;
2190 } else {
2191 Ty->print(errs());
2192 llvm_unreachable("Support above i8 vector type");
2193 }
2194 }
2195
2196 // Ops[0] = Component Type ID
2197 // Ops[1] = Component Count (Literal Number)
David Neto257c3892018-04-11 13:19:45 -04002198 SPIRVOperandList Ops;
2199 Ops << MkId(lookupType(Ty->getVectorElementType()))
2200 << MkNum(Ty->getVectorNumElements());
David Neto22f144c2017-06-12 14:26:21 -04002201
alan-bakerb6b09dc2018-11-08 16:59:28 -05002202 SPIRVInstruction *inst =
2203 new SPIRVInstruction(spv::OpTypeVector, nextID++, Ops);
David Netoc6f3ab22018-04-06 18:02:31 -04002204 SPIRVInstList.push_back(inst);
David Neto22f144c2017-06-12 14:26:21 -04002205 break;
2206 }
2207 case Type::VoidTyID: {
David Neto87846742018-04-11 17:36:22 -04002208 auto *Inst = new SPIRVInstruction(spv::OpTypeVoid, nextID++, {});
David Neto22f144c2017-06-12 14:26:21 -04002209 SPIRVInstList.push_back(Inst);
2210 break;
2211 }
2212 case Type::FunctionTyID: {
2213 // Generate SPIRV instruction for function type.
2214 FunctionType *FTy = cast<FunctionType>(Ty);
2215
2216 // Ops[0] = Return Type ID
2217 // Ops[1] ... Ops[n] = Parameter Type IDs
2218 SPIRVOperandList Ops;
2219
2220 // Find SPIRV instruction for return type
David Netoc6f3ab22018-04-06 18:02:31 -04002221 Ops << MkId(lookupType(FTy->getReturnType()));
David Neto22f144c2017-06-12 14:26:21 -04002222
2223 // Find SPIRV instructions for parameter types
2224 for (unsigned k = 0; k < FTy->getNumParams(); k++) {
2225 // Find SPIRV instruction for parameter type.
2226 auto ParamTy = FTy->getParamType(k);
2227 if (ParamTy->isPointerTy()) {
2228 auto PointeeTy = ParamTy->getPointerElementType();
2229 if (PointeeTy->isStructTy() &&
2230 dyn_cast<StructType>(PointeeTy)->isOpaque()) {
2231 ParamTy = PointeeTy;
2232 }
2233 }
2234
David Netoc6f3ab22018-04-06 18:02:31 -04002235 Ops << MkId(lookupType(ParamTy));
David Neto22f144c2017-06-12 14:26:21 -04002236 }
2237
David Neto87846742018-04-11 17:36:22 -04002238 auto *Inst = new SPIRVInstruction(spv::OpTypeFunction, nextID++, Ops);
David Neto22f144c2017-06-12 14:26:21 -04002239 SPIRVInstList.push_back(Inst);
2240 break;
2241 }
2242 }
2243 }
2244
2245 // Generate OpTypeSampledImage.
2246 TypeMapType &OpImageTypeMap = getImageTypeMap();
2247 for (auto &ImageType : OpImageTypeMap) {
2248 //
2249 // Generate OpTypeSampledImage.
2250 //
2251 // Ops[0] = Image Type ID
2252 //
2253 SPIRVOperandList Ops;
2254
2255 Type *ImgTy = ImageType.first;
David Netoc6f3ab22018-04-06 18:02:31 -04002256 Ops << MkId(TypeMap[ImgTy]);
David Neto22f144c2017-06-12 14:26:21 -04002257
2258 // Update OpImageTypeMap.
2259 ImageType.second = nextID;
2260
David Neto87846742018-04-11 17:36:22 -04002261 auto *Inst = new SPIRVInstruction(spv::OpTypeSampledImage, nextID++, Ops);
David Neto22f144c2017-06-12 14:26:21 -04002262 SPIRVInstList.push_back(Inst);
2263 }
David Netoc6f3ab22018-04-06 18:02:31 -04002264
2265 // Generate types for pointer-to-local arguments.
Alan Baker202c8c72018-08-13 13:47:44 -04002266 for (auto spec_id = clspv::FirstLocalSpecId(); spec_id < max_local_spec_id_;
2267 ++spec_id) {
alan-bakerb6b09dc2018-11-08 16:59:28 -05002268 LocalArgInfo &arg_info = LocalSpecIdInfoMap[spec_id];
David Netoc6f3ab22018-04-06 18:02:31 -04002269
2270 // Generate the spec constant.
2271 SPIRVOperandList Ops;
2272 Ops << MkId(lookupType(Type::getInt32Ty(Context))) << MkNum(1);
David Neto87846742018-04-11 17:36:22 -04002273 SPIRVInstList.push_back(
2274 new SPIRVInstruction(spv::OpSpecConstant, arg_info.array_size_id, Ops));
David Netoc6f3ab22018-04-06 18:02:31 -04002275
2276 // Generate the array type.
2277 Ops.clear();
2278 // The element type must have been created.
2279 uint32_t elem_ty_id = lookupType(arg_info.elem_type);
2280 assert(elem_ty_id);
2281 Ops << MkId(elem_ty_id) << MkId(arg_info.array_size_id);
2282
2283 SPIRVInstList.push_back(
David Neto87846742018-04-11 17:36:22 -04002284 new SPIRVInstruction(spv::OpTypeArray, arg_info.array_type_id, Ops));
David Netoc6f3ab22018-04-06 18:02:31 -04002285
2286 Ops.clear();
2287 Ops << MkNum(spv::StorageClassWorkgroup) << MkId(arg_info.array_type_id);
David Neto87846742018-04-11 17:36:22 -04002288 SPIRVInstList.push_back(new SPIRVInstruction(
2289 spv::OpTypePointer, arg_info.ptr_array_type_id, Ops));
David Netoc6f3ab22018-04-06 18:02:31 -04002290 }
David Neto22f144c2017-06-12 14:26:21 -04002291}
2292
2293void SPIRVProducerPass::GenerateSPIRVConstants() {
2294 SPIRVInstructionList &SPIRVInstList = getSPIRVInstList();
2295 ValueMapType &VMap = getValueMap();
2296 ValueMapType &AllocatedVMap = getAllocatedValueMap();
2297 ValueList &CstList = getConstantList();
David Neto482550a2018-03-24 05:21:07 -07002298 const bool hack_undef = clspv::Option::HackUndef();
David Neto22f144c2017-06-12 14:26:21 -04002299
2300 for (uint32_t i = 0; i < CstList.size(); i++) {
David Netofb9a7972017-08-25 17:08:24 -04002301 // UniqueVector ids are 1-based.
alan-bakerb6b09dc2018-11-08 16:59:28 -05002302 Constant *Cst = cast<Constant>(CstList[i + 1]);
David Neto22f144c2017-06-12 14:26:21 -04002303
2304 // OpTypeArray's constant was already generated.
David Netofb9a7972017-08-25 17:08:24 -04002305 if (AllocatedVMap.find_as(Cst) != AllocatedVMap.end()) {
David Neto22f144c2017-06-12 14:26:21 -04002306 continue;
2307 }
2308
David Netofb9a7972017-08-25 17:08:24 -04002309 // Set ValueMap with nextID for reference later.
David Neto22f144c2017-06-12 14:26:21 -04002310 VMap[Cst] = nextID;
2311
2312 //
2313 // Generate OpConstant.
2314 //
2315
2316 // Ops[0] = Result Type ID
2317 // Ops[1] .. Ops[n] = Values LiteralNumber
2318 SPIRVOperandList Ops;
2319
David Neto257c3892018-04-11 13:19:45 -04002320 Ops << MkId(lookupType(Cst->getType()));
David Neto22f144c2017-06-12 14:26:21 -04002321
2322 std::vector<uint32_t> LiteralNum;
David Neto22f144c2017-06-12 14:26:21 -04002323 spv::Op Opcode = spv::OpNop;
2324
2325 if (isa<UndefValue>(Cst)) {
2326 // Ops[0] = Result Type ID
David Netoc66b3352017-10-20 14:28:46 -04002327 Opcode = spv::OpUndef;
Alan Baker9bf93fb2018-08-28 16:59:26 -04002328 if (hack_undef && IsTypeNullable(Cst->getType())) {
2329 Opcode = spv::OpConstantNull;
David Netoc66b3352017-10-20 14:28:46 -04002330 }
David Neto22f144c2017-06-12 14:26:21 -04002331 } else if (const ConstantInt *CI = dyn_cast<ConstantInt>(Cst)) {
2332 unsigned BitWidth = CI->getBitWidth();
2333 if (BitWidth == 1) {
2334 // If the bitwidth of constant is 1, generate OpConstantTrue or
2335 // OpConstantFalse.
2336 if (CI->getZExtValue()) {
2337 // Ops[0] = Result Type ID
2338 Opcode = spv::OpConstantTrue;
2339 } else {
2340 // Ops[0] = Result Type ID
2341 Opcode = spv::OpConstantFalse;
2342 }
David Neto22f144c2017-06-12 14:26:21 -04002343 } else {
2344 auto V = CI->getZExtValue();
2345 LiteralNum.push_back(V & 0xFFFFFFFF);
2346
2347 if (BitWidth > 32) {
2348 LiteralNum.push_back(V >> 32);
2349 }
2350
2351 Opcode = spv::OpConstant;
David Neto22f144c2017-06-12 14:26:21 -04002352
David Neto257c3892018-04-11 13:19:45 -04002353 Ops << MkInteger(LiteralNum);
2354
2355 if (BitWidth == 32 && V == 0) {
2356 constant_i32_zero_id_ = nextID;
2357 }
David Neto22f144c2017-06-12 14:26:21 -04002358 }
2359 } else if (const ConstantFP *CFP = dyn_cast<ConstantFP>(Cst)) {
2360 uint64_t FPVal = CFP->getValueAPF().bitcastToAPInt().getZExtValue();
2361 Type *CFPTy = CFP->getType();
2362 if (CFPTy->isFloatTy()) {
2363 LiteralNum.push_back(FPVal & 0xFFFFFFFF);
2364 } else {
2365 CFPTy->print(errs());
2366 llvm_unreachable("Implement this ConstantFP Type");
2367 }
2368
2369 Opcode = spv::OpConstant;
David Neto22f144c2017-06-12 14:26:21 -04002370
David Neto257c3892018-04-11 13:19:45 -04002371 Ops << MkFloat(LiteralNum);
David Neto22f144c2017-06-12 14:26:21 -04002372 } else if (isa<ConstantDataSequential>(Cst) &&
2373 cast<ConstantDataSequential>(Cst)->isString()) {
2374 Cst->print(errs());
2375 llvm_unreachable("Implement this Constant");
2376
2377 } else if (const ConstantDataSequential *CDS =
2378 dyn_cast<ConstantDataSequential>(Cst)) {
David Neto49351ac2017-08-26 17:32:20 -04002379 // Let's convert <4 x i8> constant to int constant specially.
2380 // This case occurs when all the values are specified as constant
2381 // ints.
2382 Type *CstTy = Cst->getType();
2383 if (is4xi8vec(CstTy)) {
2384 LLVMContext &Context = CstTy->getContext();
2385
2386 //
2387 // Generate OpConstant with OpTypeInt 32 0.
2388 //
Neil Henning39672102017-09-29 14:33:13 +01002389 uint32_t IntValue = 0;
2390 for (unsigned k = 0; k < 4; k++) {
2391 const uint64_t Val = CDS->getElementAsInteger(k);
David Neto49351ac2017-08-26 17:32:20 -04002392 IntValue = (IntValue << 8) | (Val & 0xffu);
2393 }
2394
2395 Type *i32 = Type::getInt32Ty(Context);
2396 Constant *CstInt = ConstantInt::get(i32, IntValue);
2397 // If this constant is already registered on VMap, use it.
2398 if (VMap.count(CstInt)) {
2399 uint32_t CstID = VMap[CstInt];
2400 VMap[Cst] = CstID;
2401 continue;
2402 }
2403
David Neto257c3892018-04-11 13:19:45 -04002404 Ops << MkNum(IntValue);
David Neto49351ac2017-08-26 17:32:20 -04002405
David Neto87846742018-04-11 17:36:22 -04002406 auto *CstInst = new SPIRVInstruction(spv::OpConstant, nextID++, Ops);
David Neto49351ac2017-08-26 17:32:20 -04002407 SPIRVInstList.push_back(CstInst);
2408
2409 continue;
2410 }
2411
2412 // A normal constant-data-sequential case.
David Neto22f144c2017-06-12 14:26:21 -04002413 for (unsigned k = 0; k < CDS->getNumElements(); k++) {
2414 Constant *EleCst = CDS->getElementAsConstant(k);
2415 uint32_t EleCstID = VMap[EleCst];
David Neto257c3892018-04-11 13:19:45 -04002416 Ops << MkId(EleCstID);
David Neto22f144c2017-06-12 14:26:21 -04002417 }
2418
2419 Opcode = spv::OpConstantComposite;
David Neto22f144c2017-06-12 14:26:21 -04002420 } else if (const ConstantAggregate *CA = dyn_cast<ConstantAggregate>(Cst)) {
2421 // Let's convert <4 x i8> constant to int constant specially.
David Neto49351ac2017-08-26 17:32:20 -04002422 // This case occurs when at least one of the values is an undef.
David Neto22f144c2017-06-12 14:26:21 -04002423 Type *CstTy = Cst->getType();
2424 if (is4xi8vec(CstTy)) {
2425 LLVMContext &Context = CstTy->getContext();
2426
2427 //
2428 // Generate OpConstant with OpTypeInt 32 0.
2429 //
Neil Henning39672102017-09-29 14:33:13 +01002430 uint32_t IntValue = 0;
David Neto22f144c2017-06-12 14:26:21 -04002431 for (User::const_op_iterator I = Cst->op_begin(), E = Cst->op_end();
2432 I != E; ++I) {
2433 uint64_t Val = 0;
alan-bakerb6b09dc2018-11-08 16:59:28 -05002434 const Value *CV = *I;
Neil Henning39672102017-09-29 14:33:13 +01002435 if (auto *CI2 = dyn_cast<ConstantInt>(CV)) {
2436 Val = CI2->getZExtValue();
David Neto22f144c2017-06-12 14:26:21 -04002437 }
David Neto49351ac2017-08-26 17:32:20 -04002438 IntValue = (IntValue << 8) | (Val & 0xffu);
David Neto22f144c2017-06-12 14:26:21 -04002439 }
2440
David Neto49351ac2017-08-26 17:32:20 -04002441 Type *i32 = Type::getInt32Ty(Context);
2442 Constant *CstInt = ConstantInt::get(i32, IntValue);
David Neto22f144c2017-06-12 14:26:21 -04002443 // If this constant is already registered on VMap, use it.
2444 if (VMap.count(CstInt)) {
2445 uint32_t CstID = VMap[CstInt];
2446 VMap[Cst] = CstID;
David Neto19a1bad2017-08-25 15:01:41 -04002447 continue;
David Neto22f144c2017-06-12 14:26:21 -04002448 }
2449
David Neto257c3892018-04-11 13:19:45 -04002450 Ops << MkNum(IntValue);
David Neto22f144c2017-06-12 14:26:21 -04002451
David Neto87846742018-04-11 17:36:22 -04002452 auto *CstInst = new SPIRVInstruction(spv::OpConstant, nextID++, Ops);
David Neto22f144c2017-06-12 14:26:21 -04002453 SPIRVInstList.push_back(CstInst);
2454
David Neto19a1bad2017-08-25 15:01:41 -04002455 continue;
David Neto22f144c2017-06-12 14:26:21 -04002456 }
2457
2458 // We use a constant composite in SPIR-V for our constant aggregate in
2459 // LLVM.
2460 Opcode = spv::OpConstantComposite;
David Neto22f144c2017-06-12 14:26:21 -04002461
2462 for (unsigned k = 0; k < CA->getNumOperands(); k++) {
2463 // Look up the ID of the element of this aggregate (which we will
2464 // previously have created a constant for).
2465 uint32_t ElementConstantID = VMap[CA->getAggregateElement(k)];
2466
2467 // And add an operand to the composite we are constructing
David Neto257c3892018-04-11 13:19:45 -04002468 Ops << MkId(ElementConstantID);
David Neto22f144c2017-06-12 14:26:21 -04002469 }
2470 } else if (Cst->isNullValue()) {
2471 Opcode = spv::OpConstantNull;
David Neto22f144c2017-06-12 14:26:21 -04002472 } else {
2473 Cst->print(errs());
2474 llvm_unreachable("Unsupported Constant???");
2475 }
2476
alan-baker5b86ed72019-02-15 08:26:50 -05002477 if (Opcode == spv::OpConstantNull && Cst->getType()->isPointerTy()) {
2478 // Null pointer requires variable pointers.
2479 setVariablePointersCapabilities(Cst->getType()->getPointerAddressSpace());
2480 }
2481
David Neto87846742018-04-11 17:36:22 -04002482 auto *CstInst = new SPIRVInstruction(Opcode, nextID++, Ops);
David Neto22f144c2017-06-12 14:26:21 -04002483 SPIRVInstList.push_back(CstInst);
2484 }
2485}
2486
2487void SPIRVProducerPass::GenerateSamplers(Module &M) {
2488 SPIRVInstructionList &SPIRVInstList = getSPIRVInstList();
David Neto22f144c2017-06-12 14:26:21 -04002489
alan-bakerb6b09dc2018-11-08 16:59:28 -05002490 auto &sampler_map = getSamplerMap();
David Neto862b7d82018-06-14 18:48:37 -04002491 SamplerMapIndexToIDMap.clear();
David Neto22f144c2017-06-12 14:26:21 -04002492 DenseMap<unsigned, unsigned> SamplerLiteralToIDMap;
David Neto862b7d82018-06-14 18:48:37 -04002493 DenseMap<unsigned, unsigned> SamplerLiteralToDescriptorSetMap;
2494 DenseMap<unsigned, unsigned> SamplerLiteralToBindingMap;
David Neto22f144c2017-06-12 14:26:21 -04002495
David Neto862b7d82018-06-14 18:48:37 -04002496 // We might have samplers in the sampler map that are not used
2497 // in the translation unit. We need to allocate variables
2498 // for them and bindings too.
2499 DenseSet<unsigned> used_bindings;
David Neto22f144c2017-06-12 14:26:21 -04002500
alan-bakerb6b09dc2018-11-08 16:59:28 -05002501 auto *var_fn = M.getFunction("clspv.sampler.var.literal");
2502 if (!var_fn)
2503 return;
David Neto862b7d82018-06-14 18:48:37 -04002504 for (auto user : var_fn->users()) {
2505 // Populate SamplerLiteralToDescriptorSetMap and
2506 // SamplerLiteralToBindingMap.
2507 //
2508 // Look for calls like
2509 // call %opencl.sampler_t addrspace(2)*
2510 // @clspv.sampler.var.literal(
2511 // i32 descriptor,
2512 // i32 binding,
2513 // i32 index-into-sampler-map)
alan-bakerb6b09dc2018-11-08 16:59:28 -05002514 if (auto *call = dyn_cast<CallInst>(user)) {
2515 const size_t index_into_sampler_map = static_cast<size_t>(
2516 dyn_cast<ConstantInt>(call->getArgOperand(2))->getZExtValue());
David Neto862b7d82018-06-14 18:48:37 -04002517 if (index_into_sampler_map >= sampler_map.size()) {
alan-bakerb6b09dc2018-11-08 16:59:28 -05002518 errs() << "Out of bounds index to sampler map: "
2519 << index_into_sampler_map;
David Neto862b7d82018-06-14 18:48:37 -04002520 llvm_unreachable("bad sampler init: out of bounds");
2521 }
2522
2523 auto sampler_value = sampler_map[index_into_sampler_map].first;
2524 const auto descriptor_set = static_cast<unsigned>(
2525 dyn_cast<ConstantInt>(call->getArgOperand(0))->getZExtValue());
2526 const auto binding = static_cast<unsigned>(
2527 dyn_cast<ConstantInt>(call->getArgOperand(1))->getZExtValue());
2528
2529 SamplerLiteralToDescriptorSetMap[sampler_value] = descriptor_set;
2530 SamplerLiteralToBindingMap[sampler_value] = binding;
2531 used_bindings.insert(binding);
2532 }
2533 }
2534
2535 unsigned index = 0;
2536 for (auto SamplerLiteral : sampler_map) {
David Neto22f144c2017-06-12 14:26:21 -04002537 // Generate OpVariable.
2538 //
2539 // GIDOps[0] : Result Type ID
2540 // GIDOps[1] : Storage Class
2541 SPIRVOperandList Ops;
2542
David Neto257c3892018-04-11 13:19:45 -04002543 Ops << MkId(lookupType(SamplerTy))
2544 << MkNum(spv::StorageClassUniformConstant);
David Neto22f144c2017-06-12 14:26:21 -04002545
David Neto862b7d82018-06-14 18:48:37 -04002546 auto sampler_var_id = nextID++;
2547 auto *Inst = new SPIRVInstruction(spv::OpVariable, sampler_var_id, Ops);
David Neto22f144c2017-06-12 14:26:21 -04002548 SPIRVInstList.push_back(Inst);
2549
David Neto862b7d82018-06-14 18:48:37 -04002550 SamplerMapIndexToIDMap[index] = sampler_var_id;
2551 SamplerLiteralToIDMap[SamplerLiteral.first] = sampler_var_id;
David Neto22f144c2017-06-12 14:26:21 -04002552
2553 // Find Insert Point for OpDecorate.
2554 auto DecoInsertPoint =
2555 std::find_if(SPIRVInstList.begin(), SPIRVInstList.end(),
2556 [](SPIRVInstruction *Inst) -> bool {
2557 return Inst->getOpcode() != spv::OpDecorate &&
2558 Inst->getOpcode() != spv::OpMemberDecorate &&
2559 Inst->getOpcode() != spv::OpExtInstImport;
2560 });
2561
2562 // Ops[0] = Target ID
2563 // Ops[1] = Decoration (DescriptorSet)
2564 // Ops[2] = LiteralNumber according to Decoration
2565 Ops.clear();
2566
David Neto862b7d82018-06-14 18:48:37 -04002567 unsigned descriptor_set;
2568 unsigned binding;
alan-bakerb6b09dc2018-11-08 16:59:28 -05002569 if (SamplerLiteralToBindingMap.find(SamplerLiteral.first) ==
2570 SamplerLiteralToBindingMap.end()) {
David Neto862b7d82018-06-14 18:48:37 -04002571 // This sampler is not actually used. Find the next one.
2572 for (binding = 0; used_bindings.count(binding); binding++)
2573 ;
2574 descriptor_set = 0; // Literal samplers always use descriptor set 0.
2575 used_bindings.insert(binding);
2576 } else {
2577 descriptor_set = SamplerLiteralToDescriptorSetMap[SamplerLiteral.first];
2578 binding = SamplerLiteralToBindingMap[SamplerLiteral.first];
2579 }
2580
2581 Ops << MkId(sampler_var_id) << MkNum(spv::DecorationDescriptorSet)
2582 << MkNum(descriptor_set);
David Neto22f144c2017-06-12 14:26:21 -04002583
alan-bakerf5e5f692018-11-27 08:33:24 -05002584 version0::DescriptorMapEntry::SamplerData sampler_data = {SamplerLiteral.first};
2585 descriptorMapEntries->emplace_back(std::move(sampler_data), descriptor_set, binding);
David Neto22f144c2017-06-12 14:26:21 -04002586
David Neto87846742018-04-11 17:36:22 -04002587 auto *DescDecoInst = new SPIRVInstruction(spv::OpDecorate, Ops);
David Neto22f144c2017-06-12 14:26:21 -04002588 SPIRVInstList.insert(DecoInsertPoint, DescDecoInst);
2589
2590 // Ops[0] = Target ID
2591 // Ops[1] = Decoration (Binding)
2592 // Ops[2] = LiteralNumber according to Decoration
2593 Ops.clear();
David Neto862b7d82018-06-14 18:48:37 -04002594 Ops << MkId(sampler_var_id) << MkNum(spv::DecorationBinding)
2595 << MkNum(binding);
David Neto22f144c2017-06-12 14:26:21 -04002596
David Neto87846742018-04-11 17:36:22 -04002597 auto *BindDecoInst = new SPIRVInstruction(spv::OpDecorate, Ops);
David Neto22f144c2017-06-12 14:26:21 -04002598 SPIRVInstList.insert(DecoInsertPoint, BindDecoInst);
David Neto862b7d82018-06-14 18:48:37 -04002599
2600 index++;
David Neto22f144c2017-06-12 14:26:21 -04002601 }
David Neto862b7d82018-06-14 18:48:37 -04002602}
David Neto22f144c2017-06-12 14:26:21 -04002603
Radek Szymanskibe4b0c42018-10-04 22:20:53 +01002604void SPIRVProducerPass::GenerateResourceVars(Module &) {
David Neto862b7d82018-06-14 18:48:37 -04002605 SPIRVInstructionList &SPIRVInstList = getSPIRVInstList();
2606 ValueMapType &VMap = getValueMap();
David Neto22f144c2017-06-12 14:26:21 -04002607
David Neto862b7d82018-06-14 18:48:37 -04002608 // Generate variables. Make one for each of resource var info object.
2609 for (auto *info : ModuleOrderedResourceVars) {
2610 Type *type = info->var_fn->getReturnType();
2611 // Remap the address space for opaque types.
2612 switch (info->arg_kind) {
2613 case clspv::ArgKind::Sampler:
2614 case clspv::ArgKind::ReadOnlyImage:
2615 case clspv::ArgKind::WriteOnlyImage:
2616 type = PointerType::get(type->getPointerElementType(),
2617 clspv::AddressSpace::UniformConstant);
2618 break;
2619 default:
2620 break;
2621 }
David Neto22f144c2017-06-12 14:26:21 -04002622
David Neto862b7d82018-06-14 18:48:37 -04002623 info->var_id = nextID++;
David Neto22f144c2017-06-12 14:26:21 -04002624
David Neto862b7d82018-06-14 18:48:37 -04002625 const auto type_id = lookupType(type);
2626 const auto sc = GetStorageClassForArgKind(info->arg_kind);
2627 SPIRVOperandList Ops;
2628 Ops << MkId(type_id) << MkNum(sc);
David Neto22f144c2017-06-12 14:26:21 -04002629
David Neto862b7d82018-06-14 18:48:37 -04002630 auto *Inst = new SPIRVInstruction(spv::OpVariable, info->var_id, Ops);
2631 SPIRVInstList.push_back(Inst);
2632
2633 // Map calls to the variable-builtin-function.
2634 for (auto &U : info->var_fn->uses()) {
2635 if (auto *call = dyn_cast<CallInst>(U.getUser())) {
2636 const auto set = unsigned(
2637 dyn_cast<ConstantInt>(call->getOperand(0))->getZExtValue());
2638 const auto binding = unsigned(
2639 dyn_cast<ConstantInt>(call->getOperand(1))->getZExtValue());
2640 if (set == info->descriptor_set && binding == info->binding) {
2641 switch (info->arg_kind) {
2642 case clspv::ArgKind::Buffer:
Alan Bakerfcda9482018-10-02 17:09:59 -04002643 case clspv::ArgKind::BufferUBO:
David Neto862b7d82018-06-14 18:48:37 -04002644 case clspv::ArgKind::Pod:
2645 // The call maps to the variable directly.
2646 VMap[call] = info->var_id;
2647 break;
2648 case clspv::ArgKind::Sampler:
2649 case clspv::ArgKind::ReadOnlyImage:
2650 case clspv::ArgKind::WriteOnlyImage:
2651 // The call maps to a load we generate later.
2652 ResourceVarDeferredLoadCalls[call] = info->var_id;
2653 break;
2654 default:
2655 llvm_unreachable("Unhandled arg kind");
2656 }
2657 }
David Neto22f144c2017-06-12 14:26:21 -04002658 }
David Neto862b7d82018-06-14 18:48:37 -04002659 }
2660 }
David Neto22f144c2017-06-12 14:26:21 -04002661
David Neto862b7d82018-06-14 18:48:37 -04002662 // Generate associated decorations.
David Neto22f144c2017-06-12 14:26:21 -04002663
David Neto862b7d82018-06-14 18:48:37 -04002664 // Find Insert Point for OpDecorate.
2665 auto DecoInsertPoint =
2666 std::find_if(SPIRVInstList.begin(), SPIRVInstList.end(),
2667 [](SPIRVInstruction *Inst) -> bool {
2668 return Inst->getOpcode() != spv::OpDecorate &&
2669 Inst->getOpcode() != spv::OpMemberDecorate &&
2670 Inst->getOpcode() != spv::OpExtInstImport;
2671 });
2672
2673 SPIRVOperandList Ops;
2674 for (auto *info : ModuleOrderedResourceVars) {
2675 // Decorate with DescriptorSet and Binding.
2676 Ops.clear();
2677 Ops << MkId(info->var_id) << MkNum(spv::DecorationDescriptorSet)
2678 << MkNum(info->descriptor_set);
2679 SPIRVInstList.insert(DecoInsertPoint,
2680 new SPIRVInstruction(spv::OpDecorate, Ops));
2681
2682 Ops.clear();
2683 Ops << MkId(info->var_id) << MkNum(spv::DecorationBinding)
2684 << MkNum(info->binding);
2685 SPIRVInstList.insert(DecoInsertPoint,
2686 new SPIRVInstruction(spv::OpDecorate, Ops));
2687
alan-bakere9308012019-03-15 10:25:13 -04002688 if (info->coherent) {
2689 // Decorate with Coherent if required for the variable.
2690 Ops.clear();
2691 Ops << MkId(info->var_id) << MkNum(spv::DecorationCoherent);
2692 SPIRVInstList.insert(DecoInsertPoint,
2693 new SPIRVInstruction(spv::OpDecorate, Ops));
2694 }
2695
David Neto862b7d82018-06-14 18:48:37 -04002696 // Generate NonWritable and NonReadable
2697 switch (info->arg_kind) {
2698 case clspv::ArgKind::Buffer:
Alan Bakerfcda9482018-10-02 17:09:59 -04002699 case clspv::ArgKind::BufferUBO:
David Neto862b7d82018-06-14 18:48:37 -04002700 if (info->var_fn->getReturnType()->getPointerAddressSpace() ==
2701 clspv::AddressSpace::Constant) {
2702 Ops.clear();
2703 Ops << MkId(info->var_id) << MkNum(spv::DecorationNonWritable);
2704 SPIRVInstList.insert(DecoInsertPoint,
2705 new SPIRVInstruction(spv::OpDecorate, Ops));
David Neto22f144c2017-06-12 14:26:21 -04002706 }
David Neto862b7d82018-06-14 18:48:37 -04002707 break;
David Neto862b7d82018-06-14 18:48:37 -04002708 case clspv::ArgKind::WriteOnlyImage:
2709 Ops.clear();
2710 Ops << MkId(info->var_id) << MkNum(spv::DecorationNonReadable);
2711 SPIRVInstList.insert(DecoInsertPoint,
2712 new SPIRVInstruction(spv::OpDecorate, Ops));
2713 break;
2714 default:
2715 break;
David Neto22f144c2017-06-12 14:26:21 -04002716 }
2717 }
2718}
2719
2720void SPIRVProducerPass::GenerateGlobalVar(GlobalVariable &GV) {
alan-bakerb6b09dc2018-11-08 16:59:28 -05002721 Module &M = *GV.getParent();
David Neto22f144c2017-06-12 14:26:21 -04002722 SPIRVInstructionList &SPIRVInstList = getSPIRVInstList();
2723 ValueMapType &VMap = getValueMap();
2724 std::vector<uint32_t> &BuiltinDimVec = getBuiltinDimVec();
David Neto85082642018-03-24 06:55:20 -07002725 const DataLayout &DL = GV.getParent()->getDataLayout();
David Neto22f144c2017-06-12 14:26:21 -04002726
2727 const spv::BuiltIn BuiltinType = GetBuiltin(GV.getName());
2728 Type *Ty = GV.getType();
2729 PointerType *PTy = cast<PointerType>(Ty);
2730
2731 uint32_t InitializerID = 0;
2732
2733 // Workgroup size is handled differently (it goes into a constant)
2734 if (spv::BuiltInWorkgroupSize == BuiltinType) {
2735 std::vector<bool> HasMDVec;
2736 uint32_t PrevXDimCst = 0xFFFFFFFF;
2737 uint32_t PrevYDimCst = 0xFFFFFFFF;
2738 uint32_t PrevZDimCst = 0xFFFFFFFF;
2739 for (Function &Func : *GV.getParent()) {
2740 if (Func.isDeclaration()) {
2741 continue;
2742 }
2743
2744 // We only need to check kernels.
2745 if (Func.getCallingConv() != CallingConv::SPIR_KERNEL) {
2746 continue;
2747 }
2748
2749 if (const MDNode *MD =
2750 dyn_cast<Function>(&Func)->getMetadata("reqd_work_group_size")) {
2751 uint32_t CurXDimCst = static_cast<uint32_t>(
2752 mdconst::extract<ConstantInt>(MD->getOperand(0))->getZExtValue());
2753 uint32_t CurYDimCst = static_cast<uint32_t>(
2754 mdconst::extract<ConstantInt>(MD->getOperand(1))->getZExtValue());
2755 uint32_t CurZDimCst = static_cast<uint32_t>(
2756 mdconst::extract<ConstantInt>(MD->getOperand(2))->getZExtValue());
2757
2758 if (PrevXDimCst == 0xFFFFFFFF && PrevYDimCst == 0xFFFFFFFF &&
2759 PrevZDimCst == 0xFFFFFFFF) {
2760 PrevXDimCst = CurXDimCst;
2761 PrevYDimCst = CurYDimCst;
2762 PrevZDimCst = CurZDimCst;
2763 } else if (CurXDimCst != PrevXDimCst || CurYDimCst != PrevYDimCst ||
2764 CurZDimCst != PrevZDimCst) {
2765 llvm_unreachable(
2766 "reqd_work_group_size must be the same across all kernels");
2767 } else {
2768 continue;
2769 }
2770
2771 //
2772 // Generate OpConstantComposite.
2773 //
2774 // Ops[0] : Result Type ID
2775 // Ops[1] : Constant size for x dimension.
2776 // Ops[2] : Constant size for y dimension.
2777 // Ops[3] : Constant size for z dimension.
2778 SPIRVOperandList Ops;
2779
2780 uint32_t XDimCstID =
2781 VMap[mdconst::extract<ConstantInt>(MD->getOperand(0))];
2782 uint32_t YDimCstID =
2783 VMap[mdconst::extract<ConstantInt>(MD->getOperand(1))];
2784 uint32_t ZDimCstID =
2785 VMap[mdconst::extract<ConstantInt>(MD->getOperand(2))];
2786
2787 InitializerID = nextID;
2788
David Neto257c3892018-04-11 13:19:45 -04002789 Ops << MkId(lookupType(Ty->getPointerElementType())) << MkId(XDimCstID)
2790 << MkId(YDimCstID) << MkId(ZDimCstID);
David Neto22f144c2017-06-12 14:26:21 -04002791
David Neto87846742018-04-11 17:36:22 -04002792 auto *Inst =
2793 new SPIRVInstruction(spv::OpConstantComposite, nextID++, Ops);
David Neto22f144c2017-06-12 14:26:21 -04002794 SPIRVInstList.push_back(Inst);
2795
2796 HasMDVec.push_back(true);
2797 } else {
2798 HasMDVec.push_back(false);
2799 }
2800 }
2801
2802 // Check all kernels have same definitions for work_group_size.
2803 bool HasMD = false;
2804 if (!HasMDVec.empty()) {
2805 HasMD = HasMDVec[0];
2806 for (uint32_t i = 1; i < HasMDVec.size(); i++) {
2807 if (HasMD != HasMDVec[i]) {
2808 llvm_unreachable(
2809 "Kernels should have consistent work group size definition");
2810 }
2811 }
2812 }
2813
2814 // If all kernels do not have metadata for reqd_work_group_size, generate
2815 // OpSpecConstants for x/y/z dimension.
2816 if (!HasMD) {
2817 //
2818 // Generate OpSpecConstants for x/y/z dimension.
2819 //
2820 // Ops[0] : Result Type ID
2821 // Ops[1] : Constant size for x/y/z dimension (Literal Number).
2822 uint32_t XDimCstID = 0;
2823 uint32_t YDimCstID = 0;
2824 uint32_t ZDimCstID = 0;
2825
David Neto22f144c2017-06-12 14:26:21 -04002826 SPIRVOperandList Ops;
David Neto257c3892018-04-11 13:19:45 -04002827 uint32_t result_type_id =
2828 lookupType(Ty->getPointerElementType()->getSequentialElementType());
David Neto22f144c2017-06-12 14:26:21 -04002829
David Neto257c3892018-04-11 13:19:45 -04002830 // X Dimension
2831 Ops << MkId(result_type_id) << MkNum(1);
2832 XDimCstID = nextID++;
2833 SPIRVInstList.push_back(
David Neto87846742018-04-11 17:36:22 -04002834 new SPIRVInstruction(spv::OpSpecConstant, XDimCstID, Ops));
David Neto22f144c2017-06-12 14:26:21 -04002835
2836 // Y Dimension
2837 Ops.clear();
David Neto257c3892018-04-11 13:19:45 -04002838 Ops << MkId(result_type_id) << MkNum(1);
2839 YDimCstID = nextID++;
2840 SPIRVInstList.push_back(
David Neto87846742018-04-11 17:36:22 -04002841 new SPIRVInstruction(spv::OpSpecConstant, YDimCstID, Ops));
David Neto22f144c2017-06-12 14:26:21 -04002842
2843 // Z Dimension
2844 Ops.clear();
David Neto257c3892018-04-11 13:19:45 -04002845 Ops << MkId(result_type_id) << MkNum(1);
2846 ZDimCstID = nextID++;
2847 SPIRVInstList.push_back(
David Neto87846742018-04-11 17:36:22 -04002848 new SPIRVInstruction(spv::OpSpecConstant, ZDimCstID, Ops));
David Neto22f144c2017-06-12 14:26:21 -04002849
David Neto257c3892018-04-11 13:19:45 -04002850 BuiltinDimVec.push_back(XDimCstID);
2851 BuiltinDimVec.push_back(YDimCstID);
David Neto22f144c2017-06-12 14:26:21 -04002852 BuiltinDimVec.push_back(ZDimCstID);
2853
David Neto22f144c2017-06-12 14:26:21 -04002854 //
2855 // Generate OpSpecConstantComposite.
2856 //
2857 // Ops[0] : Result Type ID
2858 // Ops[1] : Constant size for x dimension.
2859 // Ops[2] : Constant size for y dimension.
2860 // Ops[3] : Constant size for z dimension.
2861 InitializerID = nextID;
2862
2863 Ops.clear();
David Neto257c3892018-04-11 13:19:45 -04002864 Ops << MkId(lookupType(Ty->getPointerElementType())) << MkId(XDimCstID)
2865 << MkId(YDimCstID) << MkId(ZDimCstID);
David Neto22f144c2017-06-12 14:26:21 -04002866
David Neto87846742018-04-11 17:36:22 -04002867 auto *Inst =
2868 new SPIRVInstruction(spv::OpSpecConstantComposite, nextID++, Ops);
David Neto22f144c2017-06-12 14:26:21 -04002869 SPIRVInstList.push_back(Inst);
2870 }
2871 }
2872
David Neto22f144c2017-06-12 14:26:21 -04002873 VMap[&GV] = nextID;
2874
2875 //
2876 // Generate OpVariable.
2877 //
2878 // GIDOps[0] : Result Type ID
2879 // GIDOps[1] : Storage Class
2880 SPIRVOperandList Ops;
2881
David Neto85082642018-03-24 06:55:20 -07002882 const auto AS = PTy->getAddressSpace();
David Netoc6f3ab22018-04-06 18:02:31 -04002883 Ops << MkId(lookupType(Ty)) << MkNum(GetStorageClass(AS));
David Neto22f144c2017-06-12 14:26:21 -04002884
David Neto85082642018-03-24 06:55:20 -07002885 if (GV.hasInitializer()) {
2886 InitializerID = VMap[GV.getInitializer()];
David Neto22f144c2017-06-12 14:26:21 -04002887 }
2888
David Neto85082642018-03-24 06:55:20 -07002889 const bool module_scope_constant_external_init =
David Neto862b7d82018-06-14 18:48:37 -04002890 (AS == AddressSpace::Constant) && GV.hasInitializer() &&
David Neto85082642018-03-24 06:55:20 -07002891 clspv::Option::ModuleConstantsInStorageBuffer();
2892
2893 if (0 != InitializerID) {
2894 if (!module_scope_constant_external_init) {
2895 // Emit the ID of the intiializer as part of the variable definition.
David Netoc6f3ab22018-04-06 18:02:31 -04002896 Ops << MkId(InitializerID);
David Neto85082642018-03-24 06:55:20 -07002897 }
2898 }
2899 const uint32_t var_id = nextID++;
2900
David Neto87846742018-04-11 17:36:22 -04002901 auto *Inst = new SPIRVInstruction(spv::OpVariable, var_id, Ops);
David Neto22f144c2017-06-12 14:26:21 -04002902 SPIRVInstList.push_back(Inst);
2903
2904 // If we have a builtin.
2905 if (spv::BuiltInMax != BuiltinType) {
2906 // Find Insert Point for OpDecorate.
2907 auto DecoInsertPoint =
2908 std::find_if(SPIRVInstList.begin(), SPIRVInstList.end(),
2909 [](SPIRVInstruction *Inst) -> bool {
2910 return Inst->getOpcode() != spv::OpDecorate &&
2911 Inst->getOpcode() != spv::OpMemberDecorate &&
2912 Inst->getOpcode() != spv::OpExtInstImport;
2913 });
2914 //
2915 // Generate OpDecorate.
2916 //
2917 // DOps[0] = Target ID
2918 // DOps[1] = Decoration (Builtin)
2919 // DOps[2] = BuiltIn ID
2920 uint32_t ResultID;
2921
2922 // WorkgroupSize is different, we decorate the constant composite that has
2923 // its value, rather than the variable that we use to access the value.
2924 if (spv::BuiltInWorkgroupSize == BuiltinType) {
2925 ResultID = InitializerID;
David Netoa60b00b2017-09-15 16:34:09 -04002926 // Save both the value and variable IDs for later.
2927 WorkgroupSizeValueID = InitializerID;
2928 WorkgroupSizeVarID = VMap[&GV];
David Neto22f144c2017-06-12 14:26:21 -04002929 } else {
2930 ResultID = VMap[&GV];
2931 }
2932
2933 SPIRVOperandList DOps;
David Neto257c3892018-04-11 13:19:45 -04002934 DOps << MkId(ResultID) << MkNum(spv::DecorationBuiltIn)
2935 << MkNum(BuiltinType);
David Neto22f144c2017-06-12 14:26:21 -04002936
David Neto87846742018-04-11 17:36:22 -04002937 auto *DescDecoInst = new SPIRVInstruction(spv::OpDecorate, DOps);
David Neto22f144c2017-06-12 14:26:21 -04002938 SPIRVInstList.insert(DecoInsertPoint, DescDecoInst);
David Neto85082642018-03-24 06:55:20 -07002939 } else if (module_scope_constant_external_init) {
2940 // This module scope constant is initialized from a storage buffer with data
2941 // provided by the host at binding 0 of the next descriptor set.
David Neto78383442018-06-15 20:31:56 -04002942 const uint32_t descriptor_set = TakeDescriptorIndex(&M);
David Neto85082642018-03-24 06:55:20 -07002943
David Neto862b7d82018-06-14 18:48:37 -04002944 // Emit the intializer to the descriptor map file.
David Neto85082642018-03-24 06:55:20 -07002945 // Use "kind,buffer" to indicate storage buffer. We might want to expand
2946 // that later to other types, like uniform buffer.
alan-bakerf5e5f692018-11-27 08:33:24 -05002947 std::string hexbytes;
2948 llvm::raw_string_ostream str(hexbytes);
2949 clspv::ConstantEmitter(DL, str).Emit(GV.getInitializer());
2950 version0::DescriptorMapEntry::ConstantData constant_data = {ArgKind::Buffer, str.str()};
2951 descriptorMapEntries->emplace_back(std::move(constant_data), descriptor_set, 0);
David Neto85082642018-03-24 06:55:20 -07002952
2953 // Find Insert Point for OpDecorate.
2954 auto DecoInsertPoint =
2955 std::find_if(SPIRVInstList.begin(), SPIRVInstList.end(),
2956 [](SPIRVInstruction *Inst) -> bool {
2957 return Inst->getOpcode() != spv::OpDecorate &&
2958 Inst->getOpcode() != spv::OpMemberDecorate &&
2959 Inst->getOpcode() != spv::OpExtInstImport;
2960 });
2961
David Neto257c3892018-04-11 13:19:45 -04002962 // OpDecorate %var Binding <binding>
David Neto85082642018-03-24 06:55:20 -07002963 SPIRVOperandList DOps;
David Neto257c3892018-04-11 13:19:45 -04002964 DOps << MkId(var_id) << MkNum(spv::DecorationBinding) << MkNum(0);
2965 DecoInsertPoint = SPIRVInstList.insert(
David Neto87846742018-04-11 17:36:22 -04002966 DecoInsertPoint, new SPIRVInstruction(spv::OpDecorate, DOps));
David Neto85082642018-03-24 06:55:20 -07002967
2968 // OpDecorate %var DescriptorSet <descriptor_set>
2969 DOps.clear();
David Neto257c3892018-04-11 13:19:45 -04002970 DOps << MkId(var_id) << MkNum(spv::DecorationDescriptorSet)
2971 << MkNum(descriptor_set);
David Netoc6f3ab22018-04-06 18:02:31 -04002972 SPIRVInstList.insert(DecoInsertPoint,
David Neto87846742018-04-11 17:36:22 -04002973 new SPIRVInstruction(spv::OpDecorate, DOps));
David Neto22f144c2017-06-12 14:26:21 -04002974 }
2975}
2976
David Netoc6f3ab22018-04-06 18:02:31 -04002977void SPIRVProducerPass::GenerateWorkgroupVars() {
2978 SPIRVInstructionList &SPIRVInstList = getSPIRVInstList();
Alan Baker202c8c72018-08-13 13:47:44 -04002979 for (auto spec_id = clspv::FirstLocalSpecId(); spec_id < max_local_spec_id_;
2980 ++spec_id) {
alan-bakerb6b09dc2018-11-08 16:59:28 -05002981 LocalArgInfo &info = LocalSpecIdInfoMap[spec_id];
David Netoc6f3ab22018-04-06 18:02:31 -04002982
2983 // Generate OpVariable.
2984 //
2985 // GIDOps[0] : Result Type ID
2986 // GIDOps[1] : Storage Class
2987 SPIRVOperandList Ops;
2988 Ops << MkId(info.ptr_array_type_id) << MkNum(spv::StorageClassWorkgroup);
2989
2990 SPIRVInstList.push_back(
David Neto87846742018-04-11 17:36:22 -04002991 new SPIRVInstruction(spv::OpVariable, info.variable_id, Ops));
David Netoc6f3ab22018-04-06 18:02:31 -04002992 }
2993}
2994
David Neto862b7d82018-06-14 18:48:37 -04002995void SPIRVProducerPass::GenerateDescriptorMapInfo(const DataLayout &DL,
2996 Function &F) {
David Netoc5fb5242018-07-30 13:28:31 -04002997 if (F.getCallingConv() != CallingConv::SPIR_KERNEL) {
2998 return;
2999 }
David Neto862b7d82018-06-14 18:48:37 -04003000 // Gather the list of resources that are used by this function's arguments.
3001 auto &resource_var_at_index = FunctionToResourceVarsMap[&F];
3002
alan-bakerf5e5f692018-11-27 08:33:24 -05003003 // TODO(alan-baker): This should become unnecessary by fixing the rest of the
3004 // flow to generate pod_ubo arguments earlier.
David Neto862b7d82018-06-14 18:48:37 -04003005 auto remap_arg_kind = [](StringRef argKind) {
alan-bakerf5e5f692018-11-27 08:33:24 -05003006 std::string kind =
3007 clspv::Option::PodArgsInUniformBuffer() && argKind.equals("pod")
3008 ? "pod_ubo"
3009 : argKind;
3010 return GetArgKindFromName(kind);
David Neto862b7d82018-06-14 18:48:37 -04003011 };
3012
3013 auto *fty = F.getType()->getPointerElementType();
3014 auto *func_ty = dyn_cast<FunctionType>(fty);
3015
3016 // If we've clustereed POD arguments, then argument details are in metadata.
3017 // If an argument maps to a resource variable, then get descriptor set and
3018 // binding from the resoure variable. Other info comes from the metadata.
3019 const auto *arg_map = F.getMetadata("kernel_arg_map");
3020 if (arg_map) {
3021 for (const auto &arg : arg_map->operands()) {
3022 const MDNode *arg_node = dyn_cast<MDNode>(arg.get());
Kévin PETITa353c832018-03-20 23:21:21 +00003023 assert(arg_node->getNumOperands() == 7);
David Neto862b7d82018-06-14 18:48:37 -04003024 const auto name =
3025 dyn_cast<MDString>(arg_node->getOperand(0))->getString();
3026 const auto old_index =
3027 dyn_extract<ConstantInt>(arg_node->getOperand(1))->getZExtValue();
3028 // Remapped argument index
alan-bakerb6b09dc2018-11-08 16:59:28 -05003029 const size_t new_index = static_cast<size_t>(
3030 dyn_extract<ConstantInt>(arg_node->getOperand(2))->getZExtValue());
David Neto862b7d82018-06-14 18:48:37 -04003031 const auto offset =
3032 dyn_extract<ConstantInt>(arg_node->getOperand(3))->getZExtValue();
Kévin PETITa353c832018-03-20 23:21:21 +00003033 const auto arg_size =
3034 dyn_extract<ConstantInt>(arg_node->getOperand(4))->getZExtValue();
David Neto862b7d82018-06-14 18:48:37 -04003035 const auto argKind = remap_arg_kind(
Kévin PETITa353c832018-03-20 23:21:21 +00003036 dyn_cast<MDString>(arg_node->getOperand(5))->getString());
David Neto862b7d82018-06-14 18:48:37 -04003037 const auto spec_id =
Kévin PETITa353c832018-03-20 23:21:21 +00003038 dyn_extract<ConstantInt>(arg_node->getOperand(6))->getSExtValue();
alan-bakerf5e5f692018-11-27 08:33:24 -05003039
3040 uint32_t descriptor_set = 0;
3041 uint32_t binding = 0;
3042 version0::DescriptorMapEntry::KernelArgData kernel_data = {
3043 F.getName(),
3044 name,
3045 static_cast<uint32_t>(old_index),
3046 argKind,
3047 static_cast<uint32_t>(spec_id),
3048 // This will be set below for pointer-to-local args.
3049 0,
3050 static_cast<uint32_t>(offset),
3051 static_cast<uint32_t>(arg_size)};
David Neto862b7d82018-06-14 18:48:37 -04003052 if (spec_id > 0) {
alan-bakerf5e5f692018-11-27 08:33:24 -05003053 kernel_data.local_element_size = static_cast<uint32_t>(GetTypeAllocSize(
3054 func_ty->getParamType(unsigned(new_index))->getPointerElementType(),
3055 DL));
David Neto862b7d82018-06-14 18:48:37 -04003056 } else {
3057 auto *info = resource_var_at_index[new_index];
3058 assert(info);
alan-bakerf5e5f692018-11-27 08:33:24 -05003059 descriptor_set = info->descriptor_set;
3060 binding = info->binding;
David Neto862b7d82018-06-14 18:48:37 -04003061 }
alan-bakerf5e5f692018-11-27 08:33:24 -05003062 descriptorMapEntries->emplace_back(std::move(kernel_data), descriptor_set, binding);
David Neto862b7d82018-06-14 18:48:37 -04003063 }
3064 } else {
3065 // There is no argument map.
3066 // Take descriptor info from the resource variable calls.
Kévin PETITa353c832018-03-20 23:21:21 +00003067 // Take argument name and size from the arguments list.
David Neto862b7d82018-06-14 18:48:37 -04003068
3069 SmallVector<Argument *, 4> arguments;
3070 for (auto &arg : F.args()) {
3071 arguments.push_back(&arg);
3072 }
3073
3074 unsigned arg_index = 0;
3075 for (auto *info : resource_var_at_index) {
3076 if (info) {
Kévin PETITa353c832018-03-20 23:21:21 +00003077 auto arg = arguments[arg_index];
alan-bakerb6b09dc2018-11-08 16:59:28 -05003078 unsigned arg_size = 0;
Kévin PETITa353c832018-03-20 23:21:21 +00003079 if (info->arg_kind == clspv::ArgKind::Pod) {
alan-bakerb6b09dc2018-11-08 16:59:28 -05003080 arg_size = static_cast<uint32_t>(DL.getTypeStoreSize(arg->getType()));
Kévin PETITa353c832018-03-20 23:21:21 +00003081 }
3082
alan-bakerf5e5f692018-11-27 08:33:24 -05003083 // Local pointer arguments are unused in this case. Offset is always zero.
3084 version0::DescriptorMapEntry::KernelArgData kernel_data = {
3085 F.getName(), arg->getName(),
3086 arg_index, remap_arg_kind(clspv::GetArgKindName(info->arg_kind)),
3087 0, 0,
3088 0, arg_size};
3089 descriptorMapEntries->emplace_back(std::move(kernel_data),
3090 info->descriptor_set, info->binding);
David Neto862b7d82018-06-14 18:48:37 -04003091 }
3092 arg_index++;
3093 }
3094 // Generate mappings for pointer-to-local arguments.
3095 for (arg_index = 0; arg_index < arguments.size(); ++arg_index) {
3096 Argument *arg = arguments[arg_index];
Alan Baker202c8c72018-08-13 13:47:44 -04003097 auto where = LocalArgSpecIds.find(arg);
3098 if (where != LocalArgSpecIds.end()) {
3099 auto &local_arg_info = LocalSpecIdInfoMap[where->second];
alan-bakerf5e5f692018-11-27 08:33:24 -05003100 // Pod arguments members are unused in this case.
3101 version0::DescriptorMapEntry::KernelArgData kernel_data = {
3102 F.getName(),
3103 arg->getName(),
3104 arg_index,
3105 ArgKind::Local,
3106 static_cast<uint32_t>(local_arg_info.spec_id),
3107 static_cast<uint32_t>(GetTypeAllocSize(local_arg_info.elem_type, DL)),
3108 0,
3109 0};
3110 // Pointer-to-local arguments do not utilize descriptor set and binding.
3111 descriptorMapEntries->emplace_back(std::move(kernel_data), 0, 0);
David Neto862b7d82018-06-14 18:48:37 -04003112 }
3113 }
3114 }
3115}
3116
David Neto22f144c2017-06-12 14:26:21 -04003117void SPIRVProducerPass::GenerateFuncPrologue(Function &F) {
3118 SPIRVInstructionList &SPIRVInstList = getSPIRVInstList();
3119 ValueMapType &VMap = getValueMap();
3120 EntryPointVecType &EntryPoints = getEntryPointVec();
David Neto22f144c2017-06-12 14:26:21 -04003121 auto &GlobalConstFuncTyMap = getGlobalConstFuncTypeMap();
3122 auto &GlobalConstArgSet = getGlobalConstArgSet();
3123
3124 FunctionType *FTy = F.getFunctionType();
3125
3126 //
David Neto22f144c2017-06-12 14:26:21 -04003127 // Generate OPFunction.
3128 //
3129
3130 // FOps[0] : Result Type ID
3131 // FOps[1] : Function Control
3132 // FOps[2] : Function Type ID
3133 SPIRVOperandList FOps;
3134
3135 // Find SPIRV instruction for return type.
David Neto257c3892018-04-11 13:19:45 -04003136 FOps << MkId(lookupType(FTy->getReturnType()));
David Neto22f144c2017-06-12 14:26:21 -04003137
3138 // Check function attributes for SPIRV Function Control.
3139 uint32_t FuncControl = spv::FunctionControlMaskNone;
3140 if (F.hasFnAttribute(Attribute::AlwaysInline)) {
3141 FuncControl |= spv::FunctionControlInlineMask;
3142 }
3143 if (F.hasFnAttribute(Attribute::NoInline)) {
3144 FuncControl |= spv::FunctionControlDontInlineMask;
3145 }
3146 // TODO: Check llvm attribute for Function Control Pure.
3147 if (F.hasFnAttribute(Attribute::ReadOnly)) {
3148 FuncControl |= spv::FunctionControlPureMask;
3149 }
3150 // TODO: Check llvm attribute for Function Control Const.
3151 if (F.hasFnAttribute(Attribute::ReadNone)) {
3152 FuncControl |= spv::FunctionControlConstMask;
3153 }
3154
David Neto257c3892018-04-11 13:19:45 -04003155 FOps << MkNum(FuncControl);
David Neto22f144c2017-06-12 14:26:21 -04003156
3157 uint32_t FTyID;
3158 if (F.getCallingConv() == CallingConv::SPIR_KERNEL) {
3159 SmallVector<Type *, 4> NewFuncParamTys;
3160 FunctionType *NewFTy =
3161 FunctionType::get(FTy->getReturnType(), NewFuncParamTys, false);
3162 FTyID = lookupType(NewFTy);
3163 } else {
David Neto9ed8e2f2018-03-24 06:47:24 -07003164 // Handle regular function with global constant parameters.
David Neto22f144c2017-06-12 14:26:21 -04003165 if (GlobalConstFuncTyMap.count(FTy)) {
3166 FTyID = lookupType(GlobalConstFuncTyMap[FTy].first);
3167 } else {
3168 FTyID = lookupType(FTy);
3169 }
3170 }
3171
David Neto257c3892018-04-11 13:19:45 -04003172 FOps << MkId(FTyID);
David Neto22f144c2017-06-12 14:26:21 -04003173
3174 if (F.getCallingConv() == CallingConv::SPIR_KERNEL) {
3175 EntryPoints.push_back(std::make_pair(&F, nextID));
3176 }
3177
3178 VMap[&F] = nextID;
3179
David Neto482550a2018-03-24 05:21:07 -07003180 if (clspv::Option::ShowIDs()) {
David Netob05675d2018-02-16 12:37:49 -05003181 errs() << "Function " << F.getName() << " is " << nextID << "\n";
3182 }
David Neto22f144c2017-06-12 14:26:21 -04003183 // Generate SPIRV instruction for function.
David Neto87846742018-04-11 17:36:22 -04003184 auto *FuncInst = new SPIRVInstruction(spv::OpFunction, nextID++, FOps);
David Neto22f144c2017-06-12 14:26:21 -04003185 SPIRVInstList.push_back(FuncInst);
3186
3187 //
3188 // Generate OpFunctionParameter for Normal function.
3189 //
3190
3191 if (F.getCallingConv() != CallingConv::SPIR_KERNEL) {
alan-bakere9308012019-03-15 10:25:13 -04003192
3193 // Find Insert Point for OpDecorate.
3194 auto DecoInsertPoint =
3195 std::find_if(SPIRVInstList.begin(), SPIRVInstList.end(),
3196 [](SPIRVInstruction *Inst) -> bool {
3197 return Inst->getOpcode() != spv::OpDecorate &&
3198 Inst->getOpcode() != spv::OpMemberDecorate &&
3199 Inst->getOpcode() != spv::OpExtInstImport;
3200 });
3201
David Neto22f144c2017-06-12 14:26:21 -04003202 // Iterate Argument for name instead of param type from function type.
3203 unsigned ArgIdx = 0;
3204 for (Argument &Arg : F.args()) {
alan-bakere9308012019-03-15 10:25:13 -04003205 uint32_t param_id = nextID++;
3206 VMap[&Arg] = param_id;
3207
3208 if (CalledWithCoherentResource(Arg)) {
3209 // If the arg is passed a coherent resource ever, then decorate this
3210 // parameter with Coherent too.
3211 SPIRVOperandList decoration_ops;
3212 decoration_ops << MkId(param_id) << MkNum(spv::DecorationCoherent);
3213 SPIRVInstList.insert(DecoInsertPoint,
3214 new SPIRVInstruction(spv::OpDecorate, decoration_ops));
3215 }
David Neto22f144c2017-06-12 14:26:21 -04003216
3217 // ParamOps[0] : Result Type ID
3218 SPIRVOperandList ParamOps;
3219
3220 // Find SPIRV instruction for parameter type.
3221 uint32_t ParamTyID = lookupType(Arg.getType());
3222 if (PointerType *PTy = dyn_cast<PointerType>(Arg.getType())) {
3223 if (GlobalConstFuncTyMap.count(FTy)) {
3224 if (ArgIdx == GlobalConstFuncTyMap[FTy].second) {
3225 Type *EleTy = PTy->getPointerElementType();
3226 Type *ArgTy =
3227 PointerType::get(EleTy, AddressSpace::ModuleScopePrivate);
3228 ParamTyID = lookupType(ArgTy);
3229 GlobalConstArgSet.insert(&Arg);
3230 }
3231 }
3232 }
David Neto257c3892018-04-11 13:19:45 -04003233 ParamOps << MkId(ParamTyID);
David Neto22f144c2017-06-12 14:26:21 -04003234
3235 // Generate SPIRV instruction for parameter.
David Neto87846742018-04-11 17:36:22 -04003236 auto *ParamInst =
alan-bakere9308012019-03-15 10:25:13 -04003237 new SPIRVInstruction(spv::OpFunctionParameter, param_id, ParamOps);
David Neto22f144c2017-06-12 14:26:21 -04003238 SPIRVInstList.push_back(ParamInst);
3239
3240 ArgIdx++;
3241 }
3242 }
3243}
3244
alan-bakerb6b09dc2018-11-08 16:59:28 -05003245void SPIRVProducerPass::GenerateModuleInfo(Module &module) {
David Neto22f144c2017-06-12 14:26:21 -04003246 SPIRVInstructionList &SPIRVInstList = getSPIRVInstList();
3247 EntryPointVecType &EntryPoints = getEntryPointVec();
3248 ValueMapType &VMap = getValueMap();
3249 ValueList &EntryPointInterfaces = getEntryPointInterfacesVec();
3250 uint32_t &ExtInstImportID = getOpExtInstImportID();
3251 std::vector<uint32_t> &BuiltinDimVec = getBuiltinDimVec();
3252
3253 // Set up insert point.
3254 auto InsertPoint = SPIRVInstList.begin();
3255
3256 //
3257 // Generate OpCapability
3258 //
3259 // TODO: Which llvm information is mapped to SPIRV Capapbility?
3260
3261 // Ops[0] = Capability
3262 SPIRVOperandList Ops;
3263
David Neto87846742018-04-11 17:36:22 -04003264 auto *CapInst =
3265 new SPIRVInstruction(spv::OpCapability, {MkNum(spv::CapabilityShader)});
David Neto22f144c2017-06-12 14:26:21 -04003266 SPIRVInstList.insert(InsertPoint, CapInst);
3267
3268 for (Type *Ty : getTypeList()) {
alan-bakerb39c8262019-03-08 14:03:37 -05003269 if (clspv::Option::Int8Support() && Ty->isIntegerTy(8)) {
3270 // Generate OpCapability for i8 type.
3271 SPIRVInstList.insert(InsertPoint,
3272 new SPIRVInstruction(spv::OpCapability,
3273 {MkNum(spv::CapabilityInt8)}));
3274 } else if (Ty->isIntegerTy(16)) {
David Neto22f144c2017-06-12 14:26:21 -04003275 // Generate OpCapability for i16 type.
David Neto87846742018-04-11 17:36:22 -04003276 SPIRVInstList.insert(InsertPoint,
3277 new SPIRVInstruction(spv::OpCapability,
3278 {MkNum(spv::CapabilityInt16)}));
David Neto22f144c2017-06-12 14:26:21 -04003279 } else if (Ty->isIntegerTy(64)) {
3280 // Generate OpCapability for i64 type.
David Neto87846742018-04-11 17:36:22 -04003281 SPIRVInstList.insert(InsertPoint,
3282 new SPIRVInstruction(spv::OpCapability,
3283 {MkNum(spv::CapabilityInt64)}));
David Neto22f144c2017-06-12 14:26:21 -04003284 } else if (Ty->isHalfTy()) {
3285 // Generate OpCapability for half type.
3286 SPIRVInstList.insert(
David Neto87846742018-04-11 17:36:22 -04003287 InsertPoint, new SPIRVInstruction(spv::OpCapability,
3288 {MkNum(spv::CapabilityFloat16)}));
David Neto22f144c2017-06-12 14:26:21 -04003289 } else if (Ty->isDoubleTy()) {
3290 // Generate OpCapability for double type.
3291 SPIRVInstList.insert(
David Neto87846742018-04-11 17:36:22 -04003292 InsertPoint, new SPIRVInstruction(spv::OpCapability,
3293 {MkNum(spv::CapabilityFloat64)}));
David Neto22f144c2017-06-12 14:26:21 -04003294 } else if (auto *STy = dyn_cast<StructType>(Ty)) {
3295 if (STy->isOpaque()) {
David Neto565571c2017-08-21 12:00:05 -04003296 if (STy->getName().equals("opencl.image2d_wo_t") ||
3297 STy->getName().equals("opencl.image3d_wo_t")) {
David Neto22f144c2017-06-12 14:26:21 -04003298 // Generate OpCapability for write only image type.
3299 SPIRVInstList.insert(
3300 InsertPoint,
3301 new SPIRVInstruction(
David Neto87846742018-04-11 17:36:22 -04003302 spv::OpCapability,
3303 {MkNum(spv::CapabilityStorageImageWriteWithoutFormat)}));
David Neto22f144c2017-06-12 14:26:21 -04003304 }
3305 }
3306 }
3307 }
3308
David Neto5c22a252018-03-15 16:07:41 -04003309 { // OpCapability ImageQuery
3310 bool hasImageQuery = false;
3311 for (const char *imageQuery : {
3312 "_Z15get_image_width14ocl_image2d_ro",
3313 "_Z15get_image_width14ocl_image2d_wo",
3314 "_Z16get_image_height14ocl_image2d_ro",
3315 "_Z16get_image_height14ocl_image2d_wo",
3316 }) {
3317 if (module.getFunction(imageQuery)) {
3318 hasImageQuery = true;
3319 break;
3320 }
3321 }
3322 if (hasImageQuery) {
David Neto87846742018-04-11 17:36:22 -04003323 auto *ImageQueryCapInst = new SPIRVInstruction(
3324 spv::OpCapability, {MkNum(spv::CapabilityImageQuery)});
David Neto5c22a252018-03-15 16:07:41 -04003325 SPIRVInstList.insert(InsertPoint, ImageQueryCapInst);
3326 }
3327 }
3328
David Neto22f144c2017-06-12 14:26:21 -04003329 if (hasVariablePointers()) {
3330 //
David Neto22f144c2017-06-12 14:26:21 -04003331 // Generate OpCapability.
3332 //
3333 // Ops[0] = Capability
3334 //
3335 Ops.clear();
David Neto257c3892018-04-11 13:19:45 -04003336 Ops << MkNum(spv::CapabilityVariablePointers);
David Neto22f144c2017-06-12 14:26:21 -04003337
David Neto87846742018-04-11 17:36:22 -04003338 SPIRVInstList.insert(InsertPoint,
3339 new SPIRVInstruction(spv::OpCapability, Ops));
alan-baker5b86ed72019-02-15 08:26:50 -05003340 } else if (hasVariablePointersStorageBuffer()) {
3341 //
3342 // Generate OpCapability.
3343 //
3344 // Ops[0] = Capability
3345 //
3346 Ops.clear();
3347 Ops << MkNum(spv::CapabilityVariablePointersStorageBuffer);
David Neto22f144c2017-06-12 14:26:21 -04003348
alan-baker5b86ed72019-02-15 08:26:50 -05003349 SPIRVInstList.insert(InsertPoint,
3350 new SPIRVInstruction(spv::OpCapability, Ops));
3351 }
3352
3353 // Always add the storage buffer extension
3354 {
David Neto22f144c2017-06-12 14:26:21 -04003355 //
3356 // Generate OpExtension.
3357 //
3358 // Ops[0] = Name (Literal String)
3359 //
alan-baker5b86ed72019-02-15 08:26:50 -05003360 auto *ExtensionInst = new SPIRVInstruction(
3361 spv::OpExtension, {MkString("SPV_KHR_storage_buffer_storage_class")});
3362 SPIRVInstList.insert(InsertPoint, ExtensionInst);
3363 }
David Neto22f144c2017-06-12 14:26:21 -04003364
alan-baker5b86ed72019-02-15 08:26:50 -05003365 if (hasVariablePointers() || hasVariablePointersStorageBuffer()) {
3366 //
3367 // Generate OpExtension.
3368 //
3369 // Ops[0] = Name (Literal String)
3370 //
3371 auto *ExtensionInst = new SPIRVInstruction(
3372 spv::OpExtension, {MkString("SPV_KHR_variable_pointers")});
3373 SPIRVInstList.insert(InsertPoint, ExtensionInst);
David Neto22f144c2017-06-12 14:26:21 -04003374 }
3375
3376 if (ExtInstImportID) {
3377 ++InsertPoint;
3378 }
3379
3380 //
3381 // Generate OpMemoryModel
3382 //
3383 // Memory model for Vulkan will always be GLSL450.
3384
3385 // Ops[0] = Addressing Model
3386 // Ops[1] = Memory Model
3387 Ops.clear();
David Neto257c3892018-04-11 13:19:45 -04003388 Ops << MkNum(spv::AddressingModelLogical) << MkNum(spv::MemoryModelGLSL450);
David Neto22f144c2017-06-12 14:26:21 -04003389
David Neto87846742018-04-11 17:36:22 -04003390 auto *MemModelInst = new SPIRVInstruction(spv::OpMemoryModel, Ops);
David Neto22f144c2017-06-12 14:26:21 -04003391 SPIRVInstList.insert(InsertPoint, MemModelInst);
3392
3393 //
3394 // Generate OpEntryPoint
3395 //
3396 for (auto EntryPoint : EntryPoints) {
3397 // Ops[0] = Execution Model
3398 // Ops[1] = EntryPoint ID
3399 // Ops[2] = Name (Literal String)
3400 // ...
3401 //
3402 // TODO: Do we need to consider Interface ID for forward references???
3403 Ops.clear();
alan-bakerb6b09dc2018-11-08 16:59:28 -05003404 const StringRef &name = EntryPoint.first->getName();
David Neto257c3892018-04-11 13:19:45 -04003405 Ops << MkNum(spv::ExecutionModelGLCompute) << MkId(EntryPoint.second)
3406 << MkString(name);
David Neto22f144c2017-06-12 14:26:21 -04003407
David Neto22f144c2017-06-12 14:26:21 -04003408 for (Value *Interface : EntryPointInterfaces) {
David Neto257c3892018-04-11 13:19:45 -04003409 Ops << MkId(VMap[Interface]);
David Neto22f144c2017-06-12 14:26:21 -04003410 }
3411
David Neto87846742018-04-11 17:36:22 -04003412 auto *EntryPointInst = new SPIRVInstruction(spv::OpEntryPoint, Ops);
David Neto22f144c2017-06-12 14:26:21 -04003413 SPIRVInstList.insert(InsertPoint, EntryPointInst);
3414 }
3415
3416 for (auto EntryPoint : EntryPoints) {
3417 if (const MDNode *MD = dyn_cast<Function>(EntryPoint.first)
3418 ->getMetadata("reqd_work_group_size")) {
3419
3420 if (!BuiltinDimVec.empty()) {
3421 llvm_unreachable(
3422 "Kernels should have consistent work group size definition");
3423 }
3424
3425 //
3426 // Generate OpExecutionMode
3427 //
3428
3429 // Ops[0] = Entry Point ID
3430 // Ops[1] = Execution Mode
3431 // Ops[2] ... Ops[n] = Optional literals according to Execution Mode
3432 Ops.clear();
alan-bakerb6b09dc2018-11-08 16:59:28 -05003433 Ops << MkId(EntryPoint.second) << MkNum(spv::ExecutionModeLocalSize);
David Neto22f144c2017-06-12 14:26:21 -04003434
3435 uint32_t XDim = static_cast<uint32_t>(
3436 mdconst::extract<ConstantInt>(MD->getOperand(0))->getZExtValue());
3437 uint32_t YDim = static_cast<uint32_t>(
3438 mdconst::extract<ConstantInt>(MD->getOperand(1))->getZExtValue());
3439 uint32_t ZDim = static_cast<uint32_t>(
3440 mdconst::extract<ConstantInt>(MD->getOperand(2))->getZExtValue());
3441
David Neto257c3892018-04-11 13:19:45 -04003442 Ops << MkNum(XDim) << MkNum(YDim) << MkNum(ZDim);
David Neto22f144c2017-06-12 14:26:21 -04003443
David Neto87846742018-04-11 17:36:22 -04003444 auto *ExecModeInst = new SPIRVInstruction(spv::OpExecutionMode, Ops);
David Neto22f144c2017-06-12 14:26:21 -04003445 SPIRVInstList.insert(InsertPoint, ExecModeInst);
3446 }
3447 }
3448
3449 //
3450 // Generate OpSource.
3451 //
3452 // Ops[0] = SourceLanguage ID
3453 // Ops[1] = Version (LiteralNum)
3454 //
3455 Ops.clear();
David Neto257c3892018-04-11 13:19:45 -04003456 Ops << MkNum(spv::SourceLanguageOpenCL_C) << MkNum(120);
David Neto22f144c2017-06-12 14:26:21 -04003457
David Neto87846742018-04-11 17:36:22 -04003458 auto *OpenSourceInst = new SPIRVInstruction(spv::OpSource, Ops);
David Neto22f144c2017-06-12 14:26:21 -04003459 SPIRVInstList.insert(InsertPoint, OpenSourceInst);
3460
3461 if (!BuiltinDimVec.empty()) {
3462 //
3463 // Generate OpDecorates for x/y/z dimension.
3464 //
3465 // Ops[0] = Target ID
3466 // Ops[1] = Decoration (SpecId)
David Neto257c3892018-04-11 13:19:45 -04003467 // Ops[2] = Specialization Constant ID (Literal Number)
David Neto22f144c2017-06-12 14:26:21 -04003468
3469 // X Dimension
3470 Ops.clear();
David Neto257c3892018-04-11 13:19:45 -04003471 Ops << MkId(BuiltinDimVec[0]) << MkNum(spv::DecorationSpecId) << MkNum(0);
David Neto87846742018-04-11 17:36:22 -04003472 SPIRVInstList.insert(InsertPoint,
3473 new SPIRVInstruction(spv::OpDecorate, Ops));
David Neto22f144c2017-06-12 14:26:21 -04003474
3475 // Y Dimension
3476 Ops.clear();
David Neto257c3892018-04-11 13:19:45 -04003477 Ops << MkId(BuiltinDimVec[1]) << MkNum(spv::DecorationSpecId) << MkNum(1);
David Neto87846742018-04-11 17:36:22 -04003478 SPIRVInstList.insert(InsertPoint,
3479 new SPIRVInstruction(spv::OpDecorate, Ops));
David Neto22f144c2017-06-12 14:26:21 -04003480
3481 // Z Dimension
3482 Ops.clear();
David Neto257c3892018-04-11 13:19:45 -04003483 Ops << MkId(BuiltinDimVec[2]) << MkNum(spv::DecorationSpecId) << MkNum(2);
David Neto87846742018-04-11 17:36:22 -04003484 SPIRVInstList.insert(InsertPoint,
3485 new SPIRVInstruction(spv::OpDecorate, Ops));
David Neto22f144c2017-06-12 14:26:21 -04003486 }
3487}
3488
David Netob6e2e062018-04-25 10:32:06 -04003489void SPIRVProducerPass::GenerateEntryPointInitialStores() {
3490 // Work around a driver bug. Initializers on Private variables might not
3491 // work. So the start of the kernel should store the initializer value to the
3492 // variables. Yes, *every* entry point pays this cost if *any* entry point
3493 // uses this builtin. At this point I judge this to be an acceptable tradeoff
3494 // of complexity vs. runtime, for a broken driver.
alan-bakerb6b09dc2018-11-08 16:59:28 -05003495 // TODO(dneto): Remove this at some point once fixed drivers are widely
3496 // available.
David Netob6e2e062018-04-25 10:32:06 -04003497 if (WorkgroupSizeVarID) {
3498 assert(WorkgroupSizeValueID);
3499
3500 SPIRVOperandList Ops;
3501 Ops << MkId(WorkgroupSizeVarID) << MkId(WorkgroupSizeValueID);
3502
3503 auto *Inst = new SPIRVInstruction(spv::OpStore, Ops);
3504 getSPIRVInstList().push_back(Inst);
3505 }
3506}
3507
David Neto22f144c2017-06-12 14:26:21 -04003508void SPIRVProducerPass::GenerateFuncBody(Function &F) {
3509 SPIRVInstructionList &SPIRVInstList = getSPIRVInstList();
3510 ValueMapType &VMap = getValueMap();
3511
David Netob6e2e062018-04-25 10:32:06 -04003512 const bool IsKernel = F.getCallingConv() == CallingConv::SPIR_KERNEL;
David Neto22f144c2017-06-12 14:26:21 -04003513
3514 for (BasicBlock &BB : F) {
3515 // Register BasicBlock to ValueMap.
3516 VMap[&BB] = nextID;
3517
3518 //
3519 // Generate OpLabel for Basic Block.
3520 //
3521 SPIRVOperandList Ops;
David Neto87846742018-04-11 17:36:22 -04003522 auto *Inst = new SPIRVInstruction(spv::OpLabel, nextID++, Ops);
David Neto22f144c2017-06-12 14:26:21 -04003523 SPIRVInstList.push_back(Inst);
3524
David Neto6dcd4712017-06-23 11:06:47 -04003525 // OpVariable instructions must come first.
3526 for (Instruction &I : BB) {
alan-baker5b86ed72019-02-15 08:26:50 -05003527 if (auto *alloca = dyn_cast<AllocaInst>(&I)) {
3528 // Allocating a pointer requires variable pointers.
3529 if (alloca->getAllocatedType()->isPointerTy()) {
3530 setVariablePointersCapabilities(alloca->getAllocatedType()->getPointerAddressSpace());
3531 }
David Neto6dcd4712017-06-23 11:06:47 -04003532 GenerateInstruction(I);
3533 }
3534 }
3535
David Neto22f144c2017-06-12 14:26:21 -04003536 if (&BB == &F.getEntryBlock() && IsKernel) {
David Netob6e2e062018-04-25 10:32:06 -04003537 if (clspv::Option::HackInitializers()) {
3538 GenerateEntryPointInitialStores();
3539 }
David Neto22f144c2017-06-12 14:26:21 -04003540 }
3541
3542 for (Instruction &I : BB) {
David Neto6dcd4712017-06-23 11:06:47 -04003543 if (!isa<AllocaInst>(I)) {
3544 GenerateInstruction(I);
3545 }
David Neto22f144c2017-06-12 14:26:21 -04003546 }
3547 }
3548}
3549
3550spv::Op SPIRVProducerPass::GetSPIRVCmpOpcode(CmpInst *I) {
3551 const std::map<CmpInst::Predicate, spv::Op> Map = {
3552 {CmpInst::ICMP_EQ, spv::OpIEqual},
3553 {CmpInst::ICMP_NE, spv::OpINotEqual},
3554 {CmpInst::ICMP_UGT, spv::OpUGreaterThan},
3555 {CmpInst::ICMP_UGE, spv::OpUGreaterThanEqual},
3556 {CmpInst::ICMP_ULT, spv::OpULessThan},
3557 {CmpInst::ICMP_ULE, spv::OpULessThanEqual},
3558 {CmpInst::ICMP_SGT, spv::OpSGreaterThan},
3559 {CmpInst::ICMP_SGE, spv::OpSGreaterThanEqual},
3560 {CmpInst::ICMP_SLT, spv::OpSLessThan},
3561 {CmpInst::ICMP_SLE, spv::OpSLessThanEqual},
3562 {CmpInst::FCMP_OEQ, spv::OpFOrdEqual},
3563 {CmpInst::FCMP_OGT, spv::OpFOrdGreaterThan},
3564 {CmpInst::FCMP_OGE, spv::OpFOrdGreaterThanEqual},
3565 {CmpInst::FCMP_OLT, spv::OpFOrdLessThan},
3566 {CmpInst::FCMP_OLE, spv::OpFOrdLessThanEqual},
3567 {CmpInst::FCMP_ONE, spv::OpFOrdNotEqual},
3568 {CmpInst::FCMP_UEQ, spv::OpFUnordEqual},
3569 {CmpInst::FCMP_UGT, spv::OpFUnordGreaterThan},
3570 {CmpInst::FCMP_UGE, spv::OpFUnordGreaterThanEqual},
3571 {CmpInst::FCMP_ULT, spv::OpFUnordLessThan},
3572 {CmpInst::FCMP_ULE, spv::OpFUnordLessThanEqual},
3573 {CmpInst::FCMP_UNE, spv::OpFUnordNotEqual}};
3574
3575 assert(0 != Map.count(I->getPredicate()));
3576
3577 return Map.at(I->getPredicate());
3578}
3579
3580spv::Op SPIRVProducerPass::GetSPIRVCastOpcode(Instruction &I) {
3581 const std::map<unsigned, spv::Op> Map{
3582 {Instruction::Trunc, spv::OpUConvert},
3583 {Instruction::ZExt, spv::OpUConvert},
3584 {Instruction::SExt, spv::OpSConvert},
3585 {Instruction::FPToUI, spv::OpConvertFToU},
3586 {Instruction::FPToSI, spv::OpConvertFToS},
3587 {Instruction::UIToFP, spv::OpConvertUToF},
3588 {Instruction::SIToFP, spv::OpConvertSToF},
3589 {Instruction::FPTrunc, spv::OpFConvert},
3590 {Instruction::FPExt, spv::OpFConvert},
3591 {Instruction::BitCast, spv::OpBitcast}};
3592
3593 assert(0 != Map.count(I.getOpcode()));
3594
3595 return Map.at(I.getOpcode());
3596}
3597
3598spv::Op SPIRVProducerPass::GetSPIRVBinaryOpcode(Instruction &I) {
Kévin Petit24272b62018-10-18 19:16:12 +00003599 if (I.getType()->isIntOrIntVectorTy(1)) {
David Neto22f144c2017-06-12 14:26:21 -04003600 switch (I.getOpcode()) {
3601 default:
3602 break;
3603 case Instruction::Or:
3604 return spv::OpLogicalOr;
3605 case Instruction::And:
3606 return spv::OpLogicalAnd;
3607 case Instruction::Xor:
3608 return spv::OpLogicalNotEqual;
3609 }
3610 }
3611
alan-bakerb6b09dc2018-11-08 16:59:28 -05003612 const std::map<unsigned, spv::Op> Map{
David Neto22f144c2017-06-12 14:26:21 -04003613 {Instruction::Add, spv::OpIAdd},
3614 {Instruction::FAdd, spv::OpFAdd},
3615 {Instruction::Sub, spv::OpISub},
3616 {Instruction::FSub, spv::OpFSub},
3617 {Instruction::Mul, spv::OpIMul},
3618 {Instruction::FMul, spv::OpFMul},
3619 {Instruction::UDiv, spv::OpUDiv},
3620 {Instruction::SDiv, spv::OpSDiv},
3621 {Instruction::FDiv, spv::OpFDiv},
3622 {Instruction::URem, spv::OpUMod},
3623 {Instruction::SRem, spv::OpSRem},
3624 {Instruction::FRem, spv::OpFRem},
3625 {Instruction::Or, spv::OpBitwiseOr},
3626 {Instruction::Xor, spv::OpBitwiseXor},
3627 {Instruction::And, spv::OpBitwiseAnd},
3628 {Instruction::Shl, spv::OpShiftLeftLogical},
3629 {Instruction::LShr, spv::OpShiftRightLogical},
3630 {Instruction::AShr, spv::OpShiftRightArithmetic}};
3631
3632 assert(0 != Map.count(I.getOpcode()));
3633
3634 return Map.at(I.getOpcode());
3635}
3636
3637void SPIRVProducerPass::GenerateInstruction(Instruction &I) {
3638 SPIRVInstructionList &SPIRVInstList = getSPIRVInstList();
3639 ValueMapType &VMap = getValueMap();
David Neto22f144c2017-06-12 14:26:21 -04003640 DeferredInstVecType &DeferredInsts = getDeferredInstVec();
3641 LLVMContext &Context = I.getParent()->getParent()->getParent()->getContext();
3642
3643 // Register Instruction to ValueMap.
3644 if (0 == VMap[&I]) {
3645 VMap[&I] = nextID;
3646 }
3647
3648 switch (I.getOpcode()) {
3649 default: {
3650 if (Instruction::isCast(I.getOpcode())) {
3651 //
3652 // Generate SPIRV instructions for cast operators.
3653 //
3654
David Netod2de94a2017-08-28 17:27:47 -04003655 auto Ty = I.getType();
David Neto22f144c2017-06-12 14:26:21 -04003656 auto OpTy = I.getOperand(0)->getType();
David Netod2de94a2017-08-28 17:27:47 -04003657 auto toI8 = Ty == Type::getInt8Ty(Context);
3658 auto fromI32 = OpTy == Type::getInt32Ty(Context);
David Neto22f144c2017-06-12 14:26:21 -04003659 // Handle zext, sext and uitofp with i1 type specially.
3660 if ((I.getOpcode() == Instruction::ZExt ||
3661 I.getOpcode() == Instruction::SExt ||
3662 I.getOpcode() == Instruction::UIToFP) &&
alan-bakerb6b09dc2018-11-08 16:59:28 -05003663 OpTy->isIntOrIntVectorTy(1)) {
David Neto22f144c2017-06-12 14:26:21 -04003664 //
3665 // Generate OpSelect.
3666 //
3667
3668 // Ops[0] = Result Type ID
3669 // Ops[1] = Condition ID
3670 // Ops[2] = True Constant ID
3671 // Ops[3] = False Constant ID
3672 SPIRVOperandList Ops;
3673
David Neto257c3892018-04-11 13:19:45 -04003674 Ops << MkId(lookupType(I.getType()));
David Neto22f144c2017-06-12 14:26:21 -04003675
David Neto22f144c2017-06-12 14:26:21 -04003676 uint32_t CondID = VMap[I.getOperand(0)];
David Neto257c3892018-04-11 13:19:45 -04003677 Ops << MkId(CondID);
David Neto22f144c2017-06-12 14:26:21 -04003678
3679 uint32_t TrueID = 0;
3680 if (I.getOpcode() == Instruction::ZExt) {
Kévin Petit7bfb8992019-02-26 13:45:08 +00003681 TrueID = VMap[ConstantInt::get(I.getType(), 1)];
David Neto22f144c2017-06-12 14:26:21 -04003682 } else if (I.getOpcode() == Instruction::SExt) {
Kévin Petit7bfb8992019-02-26 13:45:08 +00003683 TrueID = VMap[ConstantInt::getSigned(I.getType(), -1)];
David Neto22f144c2017-06-12 14:26:21 -04003684 } else {
3685 TrueID = VMap[ConstantFP::get(Context, APFloat(1.0f))];
3686 }
David Neto257c3892018-04-11 13:19:45 -04003687 Ops << MkId(TrueID);
David Neto22f144c2017-06-12 14:26:21 -04003688
3689 uint32_t FalseID = 0;
3690 if (I.getOpcode() == Instruction::ZExt) {
3691 FalseID = VMap[Constant::getNullValue(I.getType())];
3692 } else if (I.getOpcode() == Instruction::SExt) {
3693 FalseID = VMap[Constant::getNullValue(I.getType())];
3694 } else {
3695 FalseID = VMap[ConstantFP::get(Context, APFloat(0.0f))];
3696 }
David Neto257c3892018-04-11 13:19:45 -04003697 Ops << MkId(FalseID);
David Neto22f144c2017-06-12 14:26:21 -04003698
David Neto87846742018-04-11 17:36:22 -04003699 auto *Inst = new SPIRVInstruction(spv::OpSelect, nextID++, Ops);
David Neto22f144c2017-06-12 14:26:21 -04003700 SPIRVInstList.push_back(Inst);
alan-bakerb39c8262019-03-08 14:03:37 -05003701 } else if (!clspv::Option::Int8Support() &&
3702 I.getOpcode() == Instruction::Trunc && fromI32 && toI8) {
David Netod2de94a2017-08-28 17:27:47 -04003703 // The SPIR-V target type is a 32-bit int. Keep only the bottom
3704 // 8 bits.
3705 // Before:
3706 // %result = trunc i32 %a to i8
3707 // After
3708 // %result = OpBitwiseAnd %uint %a %uint_255
3709
3710 SPIRVOperandList Ops;
3711
David Neto257c3892018-04-11 13:19:45 -04003712 Ops << MkId(lookupType(OpTy)) << MkId(VMap[I.getOperand(0)]);
David Netod2de94a2017-08-28 17:27:47 -04003713
3714 Type *UintTy = Type::getInt32Ty(Context);
3715 uint32_t MaskID = VMap[ConstantInt::get(UintTy, 255)];
David Neto257c3892018-04-11 13:19:45 -04003716 Ops << MkId(MaskID);
David Netod2de94a2017-08-28 17:27:47 -04003717
David Neto87846742018-04-11 17:36:22 -04003718 auto *Inst = new SPIRVInstruction(spv::OpBitwiseAnd, nextID++, Ops);
David Netod2de94a2017-08-28 17:27:47 -04003719 SPIRVInstList.push_back(Inst);
David Neto22f144c2017-06-12 14:26:21 -04003720 } else {
3721 // Ops[0] = Result Type ID
3722 // Ops[1] = Source Value ID
3723 SPIRVOperandList Ops;
3724
David Neto257c3892018-04-11 13:19:45 -04003725 Ops << MkId(lookupType(I.getType())) << MkId(VMap[I.getOperand(0)]);
David Neto22f144c2017-06-12 14:26:21 -04003726
David Neto87846742018-04-11 17:36:22 -04003727 auto *Inst = new SPIRVInstruction(GetSPIRVCastOpcode(I), nextID++, Ops);
David Neto22f144c2017-06-12 14:26:21 -04003728 SPIRVInstList.push_back(Inst);
3729 }
3730 } else if (isa<BinaryOperator>(I)) {
3731 //
3732 // Generate SPIRV instructions for binary operators.
3733 //
3734
3735 // Handle xor with i1 type specially.
3736 if (I.getOpcode() == Instruction::Xor &&
3737 I.getType() == Type::getInt1Ty(Context) &&
Kévin Petit24272b62018-10-18 19:16:12 +00003738 ((isa<ConstantInt>(I.getOperand(0)) &&
3739 !cast<ConstantInt>(I.getOperand(0))->isZero()) ||
3740 (isa<ConstantInt>(I.getOperand(1)) &&
3741 !cast<ConstantInt>(I.getOperand(1))->isZero()))) {
David Neto22f144c2017-06-12 14:26:21 -04003742 //
3743 // Generate OpLogicalNot.
3744 //
3745 // Ops[0] = Result Type ID
3746 // Ops[1] = Operand
3747 SPIRVOperandList Ops;
3748
David Neto257c3892018-04-11 13:19:45 -04003749 Ops << MkId(lookupType(I.getType()));
David Neto22f144c2017-06-12 14:26:21 -04003750
3751 Value *CondV = I.getOperand(0);
3752 if (isa<Constant>(I.getOperand(0))) {
3753 CondV = I.getOperand(1);
3754 }
David Neto257c3892018-04-11 13:19:45 -04003755 Ops << MkId(VMap[CondV]);
David Neto22f144c2017-06-12 14:26:21 -04003756
David Neto87846742018-04-11 17:36:22 -04003757 auto *Inst = new SPIRVInstruction(spv::OpLogicalNot, nextID++, Ops);
David Neto22f144c2017-06-12 14:26:21 -04003758 SPIRVInstList.push_back(Inst);
3759 } else {
3760 // Ops[0] = Result Type ID
3761 // Ops[1] = Operand 0
3762 // Ops[2] = Operand 1
3763 SPIRVOperandList Ops;
3764
David Neto257c3892018-04-11 13:19:45 -04003765 Ops << MkId(lookupType(I.getType())) << MkId(VMap[I.getOperand(0)])
3766 << MkId(VMap[I.getOperand(1)]);
David Neto22f144c2017-06-12 14:26:21 -04003767
David Neto87846742018-04-11 17:36:22 -04003768 auto *Inst =
3769 new SPIRVInstruction(GetSPIRVBinaryOpcode(I), nextID++, Ops);
David Neto22f144c2017-06-12 14:26:21 -04003770 SPIRVInstList.push_back(Inst);
3771 }
3772 } else {
3773 I.print(errs());
3774 llvm_unreachable("Unsupported instruction???");
3775 }
3776 break;
3777 }
3778 case Instruction::GetElementPtr: {
3779 auto &GlobalConstArgSet = getGlobalConstArgSet();
3780
3781 //
3782 // Generate OpAccessChain.
3783 //
3784 GetElementPtrInst *GEP = cast<GetElementPtrInst>(&I);
3785
3786 //
3787 // Generate OpAccessChain.
3788 //
3789
3790 // Ops[0] = Result Type ID
3791 // Ops[1] = Base ID
3792 // Ops[2] ... Ops[n] = Indexes ID
3793 SPIRVOperandList Ops;
3794
alan-bakerb6b09dc2018-11-08 16:59:28 -05003795 PointerType *ResultType = cast<PointerType>(GEP->getType());
David Neto22f144c2017-06-12 14:26:21 -04003796 if (GEP->getPointerAddressSpace() == AddressSpace::ModuleScopePrivate ||
3797 GlobalConstArgSet.count(GEP->getPointerOperand())) {
3798 // Use pointer type with private address space for global constant.
3799 Type *EleTy = I.getType()->getPointerElementType();
David Neto1a1a0582017-07-07 12:01:44 -04003800 ResultType = PointerType::get(EleTy, AddressSpace::ModuleScopePrivate);
David Neto22f144c2017-06-12 14:26:21 -04003801 }
David Neto257c3892018-04-11 13:19:45 -04003802
3803 Ops << MkId(lookupType(ResultType));
David Neto22f144c2017-06-12 14:26:21 -04003804
David Neto862b7d82018-06-14 18:48:37 -04003805 // Generate the base pointer.
3806 Ops << MkId(VMap[GEP->getPointerOperand()]);
David Neto22f144c2017-06-12 14:26:21 -04003807
David Neto862b7d82018-06-14 18:48:37 -04003808 // TODO(dneto): Simplify the following?
David Neto22f144c2017-06-12 14:26:21 -04003809
3810 //
3811 // Follows below rules for gep.
3812 //
David Neto862b7d82018-06-14 18:48:37 -04003813 // 1. If gep's first index is 0 generate OpAccessChain and ignore gep's
3814 // first index.
David Neto22f144c2017-06-12 14:26:21 -04003815 // 2. If gep's first index is not 0, generate OpPtrAccessChain and use gep's
3816 // first index.
3817 // 3. If gep's first index is not constant, generate OpPtrAccessChain and
3818 // use gep's first index.
3819 // 4. If it is not above case 1, 2 and 3, generate OpAccessChain and use
3820 // gep's first index.
3821 //
3822 spv::Op Opcode = spv::OpAccessChain;
3823 unsigned offset = 0;
3824 if (ConstantInt *CstInt = dyn_cast<ConstantInt>(GEP->getOperand(1))) {
David Neto862b7d82018-06-14 18:48:37 -04003825 if (CstInt->getZExtValue() == 0) {
David Neto22f144c2017-06-12 14:26:21 -04003826 offset = 1;
David Neto862b7d82018-06-14 18:48:37 -04003827 } else if (CstInt->getZExtValue() != 0) {
David Neto22f144c2017-06-12 14:26:21 -04003828 Opcode = spv::OpPtrAccessChain;
David Neto22f144c2017-06-12 14:26:21 -04003829 }
David Neto862b7d82018-06-14 18:48:37 -04003830 } else {
David Neto22f144c2017-06-12 14:26:21 -04003831 Opcode = spv::OpPtrAccessChain;
David Neto1a1a0582017-07-07 12:01:44 -04003832 }
3833
3834 if (Opcode == spv::OpPtrAccessChain) {
David Neto1a1a0582017-07-07 12:01:44 -04003835 // Do we need to generate ArrayStride? Check against the GEP result type
3836 // rather than the pointer type of the base because when indexing into
3837 // an OpenCL program-scope constant, we'll swap out the LLVM base pointer
3838 // for something else in the SPIR-V.
3839 // E.g. see test/PointerAccessChain/pointer_index_is_constant_1.cl
alan-baker5b86ed72019-02-15 08:26:50 -05003840 auto address_space = ResultType->getAddressSpace();
3841 setVariablePointersCapabilities(address_space);
3842 switch (GetStorageClass(address_space)) {
Alan Bakerfcda9482018-10-02 17:09:59 -04003843 case spv::StorageClassStorageBuffer:
3844 case spv::StorageClassUniform:
David Neto1a1a0582017-07-07 12:01:44 -04003845 // Save the need to generate an ArrayStride decoration. But defer
3846 // generation until later, so we only make one decoration.
David Neto85082642018-03-24 06:55:20 -07003847 getTypesNeedingArrayStride().insert(ResultType);
Alan Bakerfcda9482018-10-02 17:09:59 -04003848 break;
3849 default:
3850 break;
David Neto1a1a0582017-07-07 12:01:44 -04003851 }
David Neto22f144c2017-06-12 14:26:21 -04003852 }
3853
3854 for (auto II = GEP->idx_begin() + offset; II != GEP->idx_end(); II++) {
David Neto257c3892018-04-11 13:19:45 -04003855 Ops << MkId(VMap[*II]);
David Neto22f144c2017-06-12 14:26:21 -04003856 }
3857
David Neto87846742018-04-11 17:36:22 -04003858 auto *Inst = new SPIRVInstruction(Opcode, nextID++, Ops);
David Neto22f144c2017-06-12 14:26:21 -04003859 SPIRVInstList.push_back(Inst);
3860 break;
3861 }
3862 case Instruction::ExtractValue: {
3863 ExtractValueInst *EVI = cast<ExtractValueInst>(&I);
3864 // Ops[0] = Result Type ID
3865 // Ops[1] = Composite ID
3866 // Ops[2] ... Ops[n] = Indexes (Literal Number)
3867 SPIRVOperandList Ops;
3868
David Neto257c3892018-04-11 13:19:45 -04003869 Ops << MkId(lookupType(I.getType()));
David Neto22f144c2017-06-12 14:26:21 -04003870
3871 uint32_t CompositeID = VMap[EVI->getAggregateOperand()];
David Neto257c3892018-04-11 13:19:45 -04003872 Ops << MkId(CompositeID);
David Neto22f144c2017-06-12 14:26:21 -04003873
3874 for (auto &Index : EVI->indices()) {
David Neto257c3892018-04-11 13:19:45 -04003875 Ops << MkNum(Index);
David Neto22f144c2017-06-12 14:26:21 -04003876 }
3877
David Neto87846742018-04-11 17:36:22 -04003878 auto *Inst = new SPIRVInstruction(spv::OpCompositeExtract, nextID++, Ops);
David Neto22f144c2017-06-12 14:26:21 -04003879 SPIRVInstList.push_back(Inst);
3880 break;
3881 }
3882 case Instruction::InsertValue: {
3883 InsertValueInst *IVI = cast<InsertValueInst>(&I);
3884 // Ops[0] = Result Type ID
3885 // Ops[1] = Object ID
3886 // Ops[2] = Composite ID
3887 // Ops[3] ... Ops[n] = Indexes (Literal Number)
3888 SPIRVOperandList Ops;
3889
3890 uint32_t ResTyID = lookupType(I.getType());
David Neto257c3892018-04-11 13:19:45 -04003891 Ops << MkId(ResTyID);
David Neto22f144c2017-06-12 14:26:21 -04003892
3893 uint32_t ObjectID = VMap[IVI->getInsertedValueOperand()];
David Neto257c3892018-04-11 13:19:45 -04003894 Ops << MkId(ObjectID);
David Neto22f144c2017-06-12 14:26:21 -04003895
3896 uint32_t CompositeID = VMap[IVI->getAggregateOperand()];
David Neto257c3892018-04-11 13:19:45 -04003897 Ops << MkId(CompositeID);
David Neto22f144c2017-06-12 14:26:21 -04003898
3899 for (auto &Index : IVI->indices()) {
David Neto257c3892018-04-11 13:19:45 -04003900 Ops << MkNum(Index);
David Neto22f144c2017-06-12 14:26:21 -04003901 }
3902
David Neto87846742018-04-11 17:36:22 -04003903 auto *Inst = new SPIRVInstruction(spv::OpCompositeInsert, nextID++, Ops);
David Neto22f144c2017-06-12 14:26:21 -04003904 SPIRVInstList.push_back(Inst);
3905 break;
3906 }
3907 case Instruction::Select: {
3908 //
3909 // Generate OpSelect.
3910 //
3911
3912 // Ops[0] = Result Type ID
3913 // Ops[1] = Condition ID
3914 // Ops[2] = True Constant ID
3915 // Ops[3] = False Constant ID
3916 SPIRVOperandList Ops;
3917
3918 // Find SPIRV instruction for parameter type.
3919 auto Ty = I.getType();
3920 if (Ty->isPointerTy()) {
3921 auto PointeeTy = Ty->getPointerElementType();
3922 if (PointeeTy->isStructTy() &&
3923 dyn_cast<StructType>(PointeeTy)->isOpaque()) {
3924 Ty = PointeeTy;
alan-baker5b86ed72019-02-15 08:26:50 -05003925 } else {
3926 // Selecting between pointers requires variable pointers.
3927 setVariablePointersCapabilities(Ty->getPointerAddressSpace());
3928 if (!hasVariablePointers() && !selectFromSameObject(&I)) {
3929 setVariablePointers(true);
3930 }
David Neto22f144c2017-06-12 14:26:21 -04003931 }
3932 }
3933
David Neto257c3892018-04-11 13:19:45 -04003934 Ops << MkId(lookupType(Ty)) << MkId(VMap[I.getOperand(0)])
3935 << MkId(VMap[I.getOperand(1)]) << MkId(VMap[I.getOperand(2)]);
David Neto22f144c2017-06-12 14:26:21 -04003936
David Neto87846742018-04-11 17:36:22 -04003937 auto *Inst = new SPIRVInstruction(spv::OpSelect, nextID++, Ops);
David Neto22f144c2017-06-12 14:26:21 -04003938 SPIRVInstList.push_back(Inst);
3939 break;
3940 }
3941 case Instruction::ExtractElement: {
3942 // Handle <4 x i8> type manually.
3943 Type *CompositeTy = I.getOperand(0)->getType();
3944 if (is4xi8vec(CompositeTy)) {
3945 //
3946 // Generate OpShiftRightLogical and OpBitwiseAnd for extractelement with
3947 // <4 x i8>.
3948 //
3949
3950 //
3951 // Generate OpShiftRightLogical
3952 //
3953 // Ops[0] = Result Type ID
3954 // Ops[1] = Operand 0
3955 // Ops[2] = Operand 1
3956 //
3957 SPIRVOperandList Ops;
3958
David Neto257c3892018-04-11 13:19:45 -04003959 Ops << MkId(lookupType(CompositeTy));
David Neto22f144c2017-06-12 14:26:21 -04003960
3961 uint32_t Op0ID = VMap[I.getOperand(0)];
David Neto257c3892018-04-11 13:19:45 -04003962 Ops << MkId(Op0ID);
David Neto22f144c2017-06-12 14:26:21 -04003963
3964 uint32_t Op1ID = 0;
3965 if (ConstantInt *CI = dyn_cast<ConstantInt>(I.getOperand(1))) {
3966 // Handle constant index.
3967 uint64_t Idx = CI->getZExtValue();
3968 Value *ShiftAmount =
3969 ConstantInt::get(Type::getInt32Ty(Context), Idx * 8);
3970 Op1ID = VMap[ShiftAmount];
3971 } else {
3972 // Handle variable index.
3973 SPIRVOperandList TmpOps;
3974
David Neto257c3892018-04-11 13:19:45 -04003975 TmpOps << MkId(lookupType(Type::getInt32Ty(Context)))
3976 << MkId(VMap[I.getOperand(1)]);
David Neto22f144c2017-06-12 14:26:21 -04003977
3978 ConstantInt *Cst8 = ConstantInt::get(Type::getInt32Ty(Context), 8);
David Neto257c3892018-04-11 13:19:45 -04003979 TmpOps << MkId(VMap[Cst8]);
David Neto22f144c2017-06-12 14:26:21 -04003980
3981 Op1ID = nextID;
3982
David Neto87846742018-04-11 17:36:22 -04003983 auto *TmpInst = new SPIRVInstruction(spv::OpIMul, nextID++, TmpOps);
David Neto22f144c2017-06-12 14:26:21 -04003984 SPIRVInstList.push_back(TmpInst);
3985 }
David Neto257c3892018-04-11 13:19:45 -04003986 Ops << MkId(Op1ID);
David Neto22f144c2017-06-12 14:26:21 -04003987
3988 uint32_t ShiftID = nextID;
3989
David Neto87846742018-04-11 17:36:22 -04003990 auto *Inst =
3991 new SPIRVInstruction(spv::OpShiftRightLogical, nextID++, Ops);
David Neto22f144c2017-06-12 14:26:21 -04003992 SPIRVInstList.push_back(Inst);
3993
3994 //
3995 // Generate OpBitwiseAnd
3996 //
3997 // Ops[0] = Result Type ID
3998 // Ops[1] = Operand 0
3999 // Ops[2] = Operand 1
4000 //
4001 Ops.clear();
4002
David Neto257c3892018-04-11 13:19:45 -04004003 Ops << MkId(lookupType(CompositeTy)) << MkId(ShiftID);
David Neto22f144c2017-06-12 14:26:21 -04004004
4005 Constant *CstFF = ConstantInt::get(Type::getInt32Ty(Context), 0xFF);
David Neto257c3892018-04-11 13:19:45 -04004006 Ops << MkId(VMap[CstFF]);
David Neto22f144c2017-06-12 14:26:21 -04004007
David Neto9b2d6252017-09-06 15:47:37 -04004008 // Reset mapping for this value to the result of the bitwise and.
4009 VMap[&I] = nextID;
4010
David Neto87846742018-04-11 17:36:22 -04004011 Inst = new SPIRVInstruction(spv::OpBitwiseAnd, nextID++, Ops);
David Neto22f144c2017-06-12 14:26:21 -04004012 SPIRVInstList.push_back(Inst);
4013 break;
4014 }
4015
4016 // Ops[0] = Result Type ID
4017 // Ops[1] = Composite ID
4018 // Ops[2] ... Ops[n] = Indexes (Literal Number)
4019 SPIRVOperandList Ops;
4020
David Neto257c3892018-04-11 13:19:45 -04004021 Ops << MkId(lookupType(I.getType())) << MkId(VMap[I.getOperand(0)]);
David Neto22f144c2017-06-12 14:26:21 -04004022
4023 spv::Op Opcode = spv::OpCompositeExtract;
4024 if (const ConstantInt *CI = dyn_cast<ConstantInt>(I.getOperand(1))) {
David Neto257c3892018-04-11 13:19:45 -04004025 Ops << MkNum(static_cast<uint32_t>(CI->getZExtValue()));
David Neto22f144c2017-06-12 14:26:21 -04004026 } else {
David Neto257c3892018-04-11 13:19:45 -04004027 Ops << MkId(VMap[I.getOperand(1)]);
David Neto22f144c2017-06-12 14:26:21 -04004028 Opcode = spv::OpVectorExtractDynamic;
4029 }
4030
David Neto87846742018-04-11 17:36:22 -04004031 auto *Inst = new SPIRVInstruction(Opcode, nextID++, Ops);
David Neto22f144c2017-06-12 14:26:21 -04004032 SPIRVInstList.push_back(Inst);
4033 break;
4034 }
4035 case Instruction::InsertElement: {
4036 // Handle <4 x i8> type manually.
4037 Type *CompositeTy = I.getOperand(0)->getType();
4038 if (is4xi8vec(CompositeTy)) {
4039 Constant *CstFF = ConstantInt::get(Type::getInt32Ty(Context), 0xFF);
4040 uint32_t CstFFID = VMap[CstFF];
4041
4042 uint32_t ShiftAmountID = 0;
4043 if (ConstantInt *CI = dyn_cast<ConstantInt>(I.getOperand(2))) {
4044 // Handle constant index.
4045 uint64_t Idx = CI->getZExtValue();
4046 Value *ShiftAmount =
4047 ConstantInt::get(Type::getInt32Ty(Context), Idx * 8);
4048 ShiftAmountID = VMap[ShiftAmount];
4049 } else {
4050 // Handle variable index.
4051 SPIRVOperandList TmpOps;
4052
David Neto257c3892018-04-11 13:19:45 -04004053 TmpOps << MkId(lookupType(Type::getInt32Ty(Context)))
4054 << MkId(VMap[I.getOperand(2)]);
David Neto22f144c2017-06-12 14:26:21 -04004055
4056 ConstantInt *Cst8 = ConstantInt::get(Type::getInt32Ty(Context), 8);
David Neto257c3892018-04-11 13:19:45 -04004057 TmpOps << MkId(VMap[Cst8]);
David Neto22f144c2017-06-12 14:26:21 -04004058
4059 ShiftAmountID = nextID;
4060
David Neto87846742018-04-11 17:36:22 -04004061 auto *TmpInst = new SPIRVInstruction(spv::OpIMul, nextID++, TmpOps);
David Neto22f144c2017-06-12 14:26:21 -04004062 SPIRVInstList.push_back(TmpInst);
4063 }
4064
4065 //
4066 // Generate mask operations.
4067 //
4068
4069 // ShiftLeft mask according to index of insertelement.
4070 SPIRVOperandList Ops;
4071
David Neto257c3892018-04-11 13:19:45 -04004072 const uint32_t ResTyID = lookupType(CompositeTy);
4073 Ops << MkId(ResTyID) << MkId(CstFFID) << MkId(ShiftAmountID);
David Neto22f144c2017-06-12 14:26:21 -04004074
4075 uint32_t MaskID = nextID;
4076
David Neto87846742018-04-11 17:36:22 -04004077 auto *Inst = new SPIRVInstruction(spv::OpShiftLeftLogical, nextID++, Ops);
David Neto22f144c2017-06-12 14:26:21 -04004078 SPIRVInstList.push_back(Inst);
4079
4080 // Inverse mask.
4081 Ops.clear();
David Neto257c3892018-04-11 13:19:45 -04004082 Ops << MkId(ResTyID) << MkId(MaskID);
David Neto22f144c2017-06-12 14:26:21 -04004083
4084 uint32_t InvMaskID = nextID;
4085
David Neto87846742018-04-11 17:36:22 -04004086 Inst = new SPIRVInstruction(spv::OpNot, nextID++, Ops);
David Neto22f144c2017-06-12 14:26:21 -04004087 SPIRVInstList.push_back(Inst);
4088
4089 // Apply mask.
4090 Ops.clear();
David Neto257c3892018-04-11 13:19:45 -04004091 Ops << MkId(ResTyID) << MkId(VMap[I.getOperand(0)]) << MkId(InvMaskID);
David Neto22f144c2017-06-12 14:26:21 -04004092
4093 uint32_t OrgValID = nextID;
4094
David Neto87846742018-04-11 17:36:22 -04004095 Inst = new SPIRVInstruction(spv::OpBitwiseAnd, nextID++, Ops);
David Neto22f144c2017-06-12 14:26:21 -04004096 SPIRVInstList.push_back(Inst);
4097
4098 // Create correct value according to index of insertelement.
4099 Ops.clear();
alan-bakerb6b09dc2018-11-08 16:59:28 -05004100 Ops << MkId(ResTyID) << MkId(VMap[I.getOperand(1)])
4101 << MkId(ShiftAmountID);
David Neto22f144c2017-06-12 14:26:21 -04004102
4103 uint32_t InsertValID = nextID;
4104
David Neto87846742018-04-11 17:36:22 -04004105 Inst = new SPIRVInstruction(spv::OpShiftLeftLogical, nextID++, Ops);
David Neto22f144c2017-06-12 14:26:21 -04004106 SPIRVInstList.push_back(Inst);
4107
4108 // Insert value to original value.
4109 Ops.clear();
David Neto257c3892018-04-11 13:19:45 -04004110 Ops << MkId(ResTyID) << MkId(OrgValID) << MkId(InsertValID);
David Neto22f144c2017-06-12 14:26:21 -04004111
David Netoa394f392017-08-26 20:45:29 -04004112 VMap[&I] = nextID;
4113
David Neto87846742018-04-11 17:36:22 -04004114 Inst = new SPIRVInstruction(spv::OpBitwiseOr, nextID++, Ops);
David Neto22f144c2017-06-12 14:26:21 -04004115 SPIRVInstList.push_back(Inst);
4116
4117 break;
4118 }
4119
David Neto22f144c2017-06-12 14:26:21 -04004120 SPIRVOperandList Ops;
4121
James Priced26efea2018-06-09 23:28:32 +01004122 // Ops[0] = Result Type ID
4123 Ops << MkId(lookupType(I.getType()));
David Neto22f144c2017-06-12 14:26:21 -04004124
4125 spv::Op Opcode = spv::OpCompositeInsert;
4126 if (const ConstantInt *CI = dyn_cast<ConstantInt>(I.getOperand(2))) {
David Neto257c3892018-04-11 13:19:45 -04004127 const auto value = CI->getZExtValue();
4128 assert(value <= UINT32_MAX);
James Priced26efea2018-06-09 23:28:32 +01004129 // Ops[1] = Object ID
4130 // Ops[2] = Composite ID
4131 // Ops[3] ... Ops[n] = Indexes (Literal Number)
alan-bakerb6b09dc2018-11-08 16:59:28 -05004132 Ops << MkId(VMap[I.getOperand(1)]) << MkId(VMap[I.getOperand(0)])
James Priced26efea2018-06-09 23:28:32 +01004133 << MkNum(static_cast<uint32_t>(value));
David Neto22f144c2017-06-12 14:26:21 -04004134 } else {
James Priced26efea2018-06-09 23:28:32 +01004135 // Ops[1] = Composite ID
4136 // Ops[2] = Object ID
4137 // Ops[3] ... Ops[n] = Indexes (Literal Number)
alan-bakerb6b09dc2018-11-08 16:59:28 -05004138 Ops << MkId(VMap[I.getOperand(0)]) << MkId(VMap[I.getOperand(1)])
James Priced26efea2018-06-09 23:28:32 +01004139 << MkId(VMap[I.getOperand(2)]);
David Neto22f144c2017-06-12 14:26:21 -04004140 Opcode = spv::OpVectorInsertDynamic;
4141 }
4142
David Neto87846742018-04-11 17:36:22 -04004143 auto *Inst = new SPIRVInstruction(Opcode, nextID++, Ops);
David Neto22f144c2017-06-12 14:26:21 -04004144 SPIRVInstList.push_back(Inst);
4145 break;
4146 }
4147 case Instruction::ShuffleVector: {
4148 // Ops[0] = Result Type ID
4149 // Ops[1] = Vector 1 ID
4150 // Ops[2] = Vector 2 ID
4151 // Ops[3] ... Ops[n] = Components (Literal Number)
4152 SPIRVOperandList Ops;
4153
David Neto257c3892018-04-11 13:19:45 -04004154 Ops << MkId(lookupType(I.getType())) << MkId(VMap[I.getOperand(0)])
4155 << MkId(VMap[I.getOperand(1)]);
David Neto22f144c2017-06-12 14:26:21 -04004156
4157 uint64_t NumElements = 0;
4158 if (Constant *Cst = dyn_cast<Constant>(I.getOperand(2))) {
4159 NumElements = cast<VectorType>(Cst->getType())->getNumElements();
4160
4161 if (Cst->isNullValue()) {
4162 for (unsigned i = 0; i < NumElements; i++) {
David Neto257c3892018-04-11 13:19:45 -04004163 Ops << MkNum(0);
David Neto22f144c2017-06-12 14:26:21 -04004164 }
4165 } else if (const ConstantDataSequential *CDS =
4166 dyn_cast<ConstantDataSequential>(Cst)) {
4167 for (unsigned i = 0; i < CDS->getNumElements(); i++) {
4168 std::vector<uint32_t> LiteralNum;
David Neto257c3892018-04-11 13:19:45 -04004169 const auto value = CDS->getElementAsInteger(i);
4170 assert(value <= UINT32_MAX);
4171 Ops << MkNum(static_cast<uint32_t>(value));
David Neto22f144c2017-06-12 14:26:21 -04004172 }
4173 } else if (const ConstantVector *CV = dyn_cast<ConstantVector>(Cst)) {
4174 for (unsigned i = 0; i < CV->getNumOperands(); i++) {
4175 auto Op = CV->getOperand(i);
4176
4177 uint32_t literal = 0;
4178
4179 if (auto CI = dyn_cast<ConstantInt>(Op)) {
4180 literal = static_cast<uint32_t>(CI->getZExtValue());
4181 } else if (auto UI = dyn_cast<UndefValue>(Op)) {
4182 literal = 0xFFFFFFFFu;
4183 } else {
4184 Op->print(errs());
4185 llvm_unreachable("Unsupported element in ConstantVector!");
4186 }
4187
David Neto257c3892018-04-11 13:19:45 -04004188 Ops << MkNum(literal);
David Neto22f144c2017-06-12 14:26:21 -04004189 }
4190 } else {
4191 Cst->print(errs());
4192 llvm_unreachable("Unsupported constant mask in ShuffleVector!");
4193 }
4194 }
4195
David Neto87846742018-04-11 17:36:22 -04004196 auto *Inst = new SPIRVInstruction(spv::OpVectorShuffle, nextID++, Ops);
David Neto22f144c2017-06-12 14:26:21 -04004197 SPIRVInstList.push_back(Inst);
4198 break;
4199 }
4200 case Instruction::ICmp:
4201 case Instruction::FCmp: {
4202 CmpInst *CmpI = cast<CmpInst>(&I);
4203
David Netod4ca2e62017-07-06 18:47:35 -04004204 // Pointer equality is invalid.
alan-bakerb6b09dc2018-11-08 16:59:28 -05004205 Type *ArgTy = CmpI->getOperand(0)->getType();
David Netod4ca2e62017-07-06 18:47:35 -04004206 if (isa<PointerType>(ArgTy)) {
4207 CmpI->print(errs());
4208 std::string name = I.getParent()->getParent()->getName();
4209 errs()
4210 << "\nPointer equality test is not supported by SPIR-V for Vulkan, "
4211 << "in function " << name << "\n";
4212 llvm_unreachable("Pointer equality check is invalid");
4213 break;
4214 }
4215
David Neto257c3892018-04-11 13:19:45 -04004216 // Ops[0] = Result Type ID
4217 // Ops[1] = Operand 1 ID
4218 // Ops[2] = Operand 2 ID
4219 SPIRVOperandList Ops;
David Neto22f144c2017-06-12 14:26:21 -04004220
David Neto257c3892018-04-11 13:19:45 -04004221 Ops << MkId(lookupType(CmpI->getType())) << MkId(VMap[CmpI->getOperand(0)])
4222 << MkId(VMap[CmpI->getOperand(1)]);
David Neto22f144c2017-06-12 14:26:21 -04004223
4224 spv::Op Opcode = GetSPIRVCmpOpcode(CmpI);
David Neto87846742018-04-11 17:36:22 -04004225 auto *Inst = new SPIRVInstruction(Opcode, nextID++, Ops);
David Neto22f144c2017-06-12 14:26:21 -04004226 SPIRVInstList.push_back(Inst);
4227 break;
4228 }
4229 case Instruction::Br: {
4230 // Branch instrucion is deferred because it needs label's ID. Record slot's
4231 // location on SPIRVInstructionList.
4232 DeferredInsts.push_back(
4233 std::make_tuple(&I, --SPIRVInstList.end(), 0 /* No id */));
4234 break;
4235 }
4236 case Instruction::Switch: {
4237 I.print(errs());
4238 llvm_unreachable("Unsupported instruction???");
4239 break;
4240 }
4241 case Instruction::IndirectBr: {
4242 I.print(errs());
4243 llvm_unreachable("Unsupported instruction???");
4244 break;
4245 }
4246 case Instruction::PHI: {
4247 // Branch instrucion is deferred because it needs label's ID. Record slot's
4248 // location on SPIRVInstructionList.
4249 DeferredInsts.push_back(
4250 std::make_tuple(&I, --SPIRVInstList.end(), nextID++));
4251 break;
4252 }
4253 case Instruction::Alloca: {
4254 //
4255 // Generate OpVariable.
4256 //
4257 // Ops[0] : Result Type ID
4258 // Ops[1] : Storage Class
4259 SPIRVOperandList Ops;
4260
David Neto257c3892018-04-11 13:19:45 -04004261 Ops << MkId(lookupType(I.getType())) << MkNum(spv::StorageClassFunction);
David Neto22f144c2017-06-12 14:26:21 -04004262
David Neto87846742018-04-11 17:36:22 -04004263 auto *Inst = new SPIRVInstruction(spv::OpVariable, nextID++, Ops);
David Neto22f144c2017-06-12 14:26:21 -04004264 SPIRVInstList.push_back(Inst);
4265 break;
4266 }
4267 case Instruction::Load: {
4268 LoadInst *LD = cast<LoadInst>(&I);
4269 //
4270 // Generate OpLoad.
4271 //
alan-baker5b86ed72019-02-15 08:26:50 -05004272
4273 if (LD->getType()->isPointerTy()) {
4274 // Loading a pointer requires variable pointers.
4275 setVariablePointersCapabilities(LD->getType()->getPointerAddressSpace());
4276 }
David Neto22f144c2017-06-12 14:26:21 -04004277
David Neto0a2f98d2017-09-15 19:38:40 -04004278 uint32_t ResTyID = lookupType(LD->getType());
David Netoa60b00b2017-09-15 16:34:09 -04004279 uint32_t PointerID = VMap[LD->getPointerOperand()];
4280
4281 // This is a hack to work around what looks like a driver bug.
4282 // When we're loading from the special variable holding the WorkgroupSize
David Neto0a2f98d2017-09-15 19:38:40 -04004283 // builtin value, use an OpBitWiseAnd of the value's ID rather than
4284 // generating a load.
David Neto66cfe642018-03-24 06:13:56 -07004285 // TODO(dneto): Remove this awful hack once drivers are fixed.
David Netoa60b00b2017-09-15 16:34:09 -04004286 if (PointerID == WorkgroupSizeVarID) {
David Neto0a2f98d2017-09-15 19:38:40 -04004287 // Generate a bitwise-and of the original value with itself.
4288 // We should have been able to get away with just an OpCopyObject,
4289 // but we need something more complex to get past certain driver bugs.
4290 // This is ridiculous, but necessary.
4291 // TODO(dneto): Revisit this once drivers fix their bugs.
4292
4293 SPIRVOperandList Ops;
David Neto257c3892018-04-11 13:19:45 -04004294 Ops << MkId(ResTyID) << MkId(WorkgroupSizeValueID)
4295 << MkId(WorkgroupSizeValueID);
David Neto0a2f98d2017-09-15 19:38:40 -04004296
David Neto87846742018-04-11 17:36:22 -04004297 auto *Inst = new SPIRVInstruction(spv::OpBitwiseAnd, nextID++, Ops);
David Neto0a2f98d2017-09-15 19:38:40 -04004298 SPIRVInstList.push_back(Inst);
David Netoa60b00b2017-09-15 16:34:09 -04004299 break;
4300 }
4301
4302 // This is the normal path. Generate a load.
4303
David Neto22f144c2017-06-12 14:26:21 -04004304 // Ops[0] = Result Type ID
4305 // Ops[1] = Pointer ID
4306 // Ops[2] ... Ops[n] = Optional Memory Access
4307 //
4308 // TODO: Do we need to implement Optional Memory Access???
David Neto0a2f98d2017-09-15 19:38:40 -04004309
David Neto22f144c2017-06-12 14:26:21 -04004310 SPIRVOperandList Ops;
David Neto257c3892018-04-11 13:19:45 -04004311 Ops << MkId(ResTyID) << MkId(PointerID);
David Neto22f144c2017-06-12 14:26:21 -04004312
David Neto87846742018-04-11 17:36:22 -04004313 auto *Inst = new SPIRVInstruction(spv::OpLoad, nextID++, Ops);
David Neto22f144c2017-06-12 14:26:21 -04004314 SPIRVInstList.push_back(Inst);
4315 break;
4316 }
4317 case Instruction::Store: {
4318 StoreInst *ST = cast<StoreInst>(&I);
4319 //
4320 // Generate OpStore.
4321 //
4322
alan-baker5b86ed72019-02-15 08:26:50 -05004323 if (ST->getValueOperand()->getType()->isPointerTy()) {
4324 // Storing a pointer requires variable pointers.
4325 setVariablePointersCapabilities(
4326 ST->getValueOperand()->getType()->getPointerAddressSpace());
4327 }
4328
David Neto22f144c2017-06-12 14:26:21 -04004329 // Ops[0] = Pointer ID
4330 // Ops[1] = Object ID
4331 // Ops[2] ... Ops[n] = Optional Memory Access (later???)
4332 //
4333 // TODO: Do we need to implement Optional Memory Access???
David Neto257c3892018-04-11 13:19:45 -04004334 SPIRVOperandList Ops;
4335 Ops << MkId(VMap[ST->getPointerOperand()])
4336 << MkId(VMap[ST->getValueOperand()]);
David Neto22f144c2017-06-12 14:26:21 -04004337
David Neto87846742018-04-11 17:36:22 -04004338 auto *Inst = new SPIRVInstruction(spv::OpStore, Ops);
David Neto22f144c2017-06-12 14:26:21 -04004339 SPIRVInstList.push_back(Inst);
4340 break;
4341 }
4342 case Instruction::AtomicCmpXchg: {
4343 I.print(errs());
4344 llvm_unreachable("Unsupported instruction???");
4345 break;
4346 }
4347 case Instruction::AtomicRMW: {
Neil Henning39672102017-09-29 14:33:13 +01004348 AtomicRMWInst *AtomicRMW = dyn_cast<AtomicRMWInst>(&I);
4349
4350 spv::Op opcode;
4351
4352 switch (AtomicRMW->getOperation()) {
4353 default:
4354 I.print(errs());
4355 llvm_unreachable("Unsupported instruction???");
4356 case llvm::AtomicRMWInst::Add:
4357 opcode = spv::OpAtomicIAdd;
4358 break;
4359 case llvm::AtomicRMWInst::Sub:
4360 opcode = spv::OpAtomicISub;
4361 break;
4362 case llvm::AtomicRMWInst::Xchg:
4363 opcode = spv::OpAtomicExchange;
4364 break;
4365 case llvm::AtomicRMWInst::Min:
4366 opcode = spv::OpAtomicSMin;
4367 break;
4368 case llvm::AtomicRMWInst::Max:
4369 opcode = spv::OpAtomicSMax;
4370 break;
4371 case llvm::AtomicRMWInst::UMin:
4372 opcode = spv::OpAtomicUMin;
4373 break;
4374 case llvm::AtomicRMWInst::UMax:
4375 opcode = spv::OpAtomicUMax;
4376 break;
4377 case llvm::AtomicRMWInst::And:
4378 opcode = spv::OpAtomicAnd;
4379 break;
4380 case llvm::AtomicRMWInst::Or:
4381 opcode = spv::OpAtomicOr;
4382 break;
4383 case llvm::AtomicRMWInst::Xor:
4384 opcode = spv::OpAtomicXor;
4385 break;
4386 }
4387
4388 //
4389 // Generate OpAtomic*.
4390 //
4391 SPIRVOperandList Ops;
4392
David Neto257c3892018-04-11 13:19:45 -04004393 Ops << MkId(lookupType(I.getType()))
4394 << MkId(VMap[AtomicRMW->getPointerOperand()]);
Neil Henning39672102017-09-29 14:33:13 +01004395
4396 auto IntTy = Type::getInt32Ty(I.getContext());
Neil Henning39672102017-09-29 14:33:13 +01004397 const auto ConstantScopeDevice = ConstantInt::get(IntTy, spv::ScopeDevice);
David Neto257c3892018-04-11 13:19:45 -04004398 Ops << MkId(VMap[ConstantScopeDevice]);
Neil Henning39672102017-09-29 14:33:13 +01004399
4400 const auto ConstantMemorySemantics = ConstantInt::get(
4401 IntTy, spv::MemorySemanticsUniformMemoryMask |
4402 spv::MemorySemanticsSequentiallyConsistentMask);
David Neto257c3892018-04-11 13:19:45 -04004403 Ops << MkId(VMap[ConstantMemorySemantics]);
Neil Henning39672102017-09-29 14:33:13 +01004404
David Neto257c3892018-04-11 13:19:45 -04004405 Ops << MkId(VMap[AtomicRMW->getValOperand()]);
Neil Henning39672102017-09-29 14:33:13 +01004406
4407 VMap[&I] = nextID;
4408
David Neto87846742018-04-11 17:36:22 -04004409 auto *Inst = new SPIRVInstruction(opcode, nextID++, Ops);
Neil Henning39672102017-09-29 14:33:13 +01004410 SPIRVInstList.push_back(Inst);
David Neto22f144c2017-06-12 14:26:21 -04004411 break;
4412 }
4413 case Instruction::Fence: {
4414 I.print(errs());
4415 llvm_unreachable("Unsupported instruction???");
4416 break;
4417 }
4418 case Instruction::Call: {
4419 CallInst *Call = dyn_cast<CallInst>(&I);
4420 Function *Callee = Call->getCalledFunction();
4421
Alan Baker202c8c72018-08-13 13:47:44 -04004422 if (Callee->getName().startswith(clspv::ResourceAccessorFunction())) {
David Neto862b7d82018-06-14 18:48:37 -04004423 if (ResourceVarDeferredLoadCalls.count(Call) && Call->hasNUsesOrMore(1)) {
4424 // Generate an OpLoad
4425 SPIRVOperandList Ops;
4426 const auto load_id = nextID++;
David Neto22f144c2017-06-12 14:26:21 -04004427
David Neto862b7d82018-06-14 18:48:37 -04004428 Ops << MkId(lookupType(Call->getType()->getPointerElementType()))
4429 << MkId(ResourceVarDeferredLoadCalls[Call]);
4430
4431 auto *Inst = new SPIRVInstruction(spv::OpLoad, load_id, Ops);
4432 SPIRVInstList.push_back(Inst);
4433 VMap[Call] = load_id;
4434 break;
4435
4436 } else {
4437 // This maps to an OpVariable we've already generated.
4438 // No code is generated for the call.
4439 }
4440 break;
alan-bakerb6b09dc2018-11-08 16:59:28 -05004441 } else if (Callee->getName().startswith(
4442 clspv::WorkgroupAccessorFunction())) {
Alan Baker202c8c72018-08-13 13:47:44 -04004443 // Don't codegen an instruction here, but instead map this call directly
4444 // to the workgroup variable id.
alan-bakerb6b09dc2018-11-08 16:59:28 -05004445 int spec_id = static_cast<int>(
4446 cast<ConstantInt>(Call->getOperand(0))->getSExtValue());
Alan Baker202c8c72018-08-13 13:47:44 -04004447 const auto &info = LocalSpecIdInfoMap[spec_id];
4448 VMap[Call] = info.variable_id;
4449 break;
David Neto862b7d82018-06-14 18:48:37 -04004450 }
4451
4452 // Sampler initializers become a load of the corresponding sampler.
4453
4454 if (Callee->getName().equals("clspv.sampler.var.literal")) {
4455 // Map this to a load from the variable.
4456 const auto index_into_sampler_map =
4457 dyn_cast<ConstantInt>(Call->getArgOperand(2))->getZExtValue();
4458
4459 // Generate an OpLoad
David Neto22f144c2017-06-12 14:26:21 -04004460 SPIRVOperandList Ops;
David Neto862b7d82018-06-14 18:48:37 -04004461 const auto load_id = nextID++;
David Neto22f144c2017-06-12 14:26:21 -04004462
David Neto257c3892018-04-11 13:19:45 -04004463 Ops << MkId(lookupType(SamplerTy->getPointerElementType()))
alan-bakerb6b09dc2018-11-08 16:59:28 -05004464 << MkId(SamplerMapIndexToIDMap[static_cast<unsigned>(
4465 index_into_sampler_map)]);
David Neto22f144c2017-06-12 14:26:21 -04004466
David Neto862b7d82018-06-14 18:48:37 -04004467 auto *Inst = new SPIRVInstruction(spv::OpLoad, load_id, Ops);
David Neto22f144c2017-06-12 14:26:21 -04004468 SPIRVInstList.push_back(Inst);
David Neto862b7d82018-06-14 18:48:37 -04004469 VMap[Call] = load_id;
David Neto22f144c2017-06-12 14:26:21 -04004470 break;
4471 }
4472
4473 if (Callee->getName().startswith("spirv.atomic")) {
4474 spv::Op opcode = StringSwitch<spv::Op>(Callee->getName())
4475 .Case("spirv.atomic_add", spv::OpAtomicIAdd)
4476 .Case("spirv.atomic_sub", spv::OpAtomicISub)
4477 .Case("spirv.atomic_exchange", spv::OpAtomicExchange)
4478 .Case("spirv.atomic_inc", spv::OpAtomicIIncrement)
4479 .Case("spirv.atomic_dec", spv::OpAtomicIDecrement)
4480 .Case("spirv.atomic_compare_exchange",
4481 spv::OpAtomicCompareExchange)
4482 .Case("spirv.atomic_umin", spv::OpAtomicUMin)
4483 .Case("spirv.atomic_smin", spv::OpAtomicSMin)
4484 .Case("spirv.atomic_umax", spv::OpAtomicUMax)
4485 .Case("spirv.atomic_smax", spv::OpAtomicSMax)
4486 .Case("spirv.atomic_and", spv::OpAtomicAnd)
4487 .Case("spirv.atomic_or", spv::OpAtomicOr)
4488 .Case("spirv.atomic_xor", spv::OpAtomicXor)
4489 .Default(spv::OpNop);
4490
4491 //
4492 // Generate OpAtomic*.
4493 //
4494 SPIRVOperandList Ops;
4495
David Neto257c3892018-04-11 13:19:45 -04004496 Ops << MkId(lookupType(I.getType()));
David Neto22f144c2017-06-12 14:26:21 -04004497
4498 for (unsigned i = 0; i < Call->getNumArgOperands(); i++) {
David Neto257c3892018-04-11 13:19:45 -04004499 Ops << MkId(VMap[Call->getArgOperand(i)]);
David Neto22f144c2017-06-12 14:26:21 -04004500 }
4501
4502 VMap[&I] = nextID;
4503
David Neto87846742018-04-11 17:36:22 -04004504 auto *Inst = new SPIRVInstruction(opcode, nextID++, Ops);
David Neto22f144c2017-06-12 14:26:21 -04004505 SPIRVInstList.push_back(Inst);
4506 break;
4507 }
4508
4509 if (Callee->getName().startswith("_Z3dot")) {
4510 // If the argument is a vector type, generate OpDot
4511 if (Call->getArgOperand(0)->getType()->isVectorTy()) {
4512 //
4513 // Generate OpDot.
4514 //
4515 SPIRVOperandList Ops;
4516
David Neto257c3892018-04-11 13:19:45 -04004517 Ops << MkId(lookupType(I.getType()));
David Neto22f144c2017-06-12 14:26:21 -04004518
4519 for (unsigned i = 0; i < Call->getNumArgOperands(); i++) {
David Neto257c3892018-04-11 13:19:45 -04004520 Ops << MkId(VMap[Call->getArgOperand(i)]);
David Neto22f144c2017-06-12 14:26:21 -04004521 }
4522
4523 VMap[&I] = nextID;
4524
David Neto87846742018-04-11 17:36:22 -04004525 auto *Inst = new SPIRVInstruction(spv::OpDot, nextID++, Ops);
David Neto22f144c2017-06-12 14:26:21 -04004526 SPIRVInstList.push_back(Inst);
4527 } else {
4528 //
4529 // Generate OpFMul.
4530 //
4531 SPIRVOperandList Ops;
4532
David Neto257c3892018-04-11 13:19:45 -04004533 Ops << MkId(lookupType(I.getType()));
David Neto22f144c2017-06-12 14:26:21 -04004534
4535 for (unsigned i = 0; i < Call->getNumArgOperands(); i++) {
David Neto257c3892018-04-11 13:19:45 -04004536 Ops << MkId(VMap[Call->getArgOperand(i)]);
David Neto22f144c2017-06-12 14:26:21 -04004537 }
4538
4539 VMap[&I] = nextID;
4540
David Neto87846742018-04-11 17:36:22 -04004541 auto *Inst = new SPIRVInstruction(spv::OpFMul, nextID++, Ops);
David Neto22f144c2017-06-12 14:26:21 -04004542 SPIRVInstList.push_back(Inst);
4543 }
4544 break;
4545 }
4546
David Neto8505ebf2017-10-13 18:50:50 -04004547 if (Callee->getName().startswith("_Z4fmod")) {
4548 // OpenCL fmod(x,y) is x - y * trunc(x/y)
4549 // The sign for a non-zero result is taken from x.
4550 // (Try an example.)
4551 // So translate to OpFRem
4552
4553 SPIRVOperandList Ops;
4554
David Neto257c3892018-04-11 13:19:45 -04004555 Ops << MkId(lookupType(I.getType()));
David Neto8505ebf2017-10-13 18:50:50 -04004556
4557 for (unsigned i = 0; i < Call->getNumArgOperands(); i++) {
David Neto257c3892018-04-11 13:19:45 -04004558 Ops << MkId(VMap[Call->getArgOperand(i)]);
David Neto8505ebf2017-10-13 18:50:50 -04004559 }
4560
4561 VMap[&I] = nextID;
4562
David Neto87846742018-04-11 17:36:22 -04004563 auto *Inst = new SPIRVInstruction(spv::OpFRem, nextID++, Ops);
David Neto8505ebf2017-10-13 18:50:50 -04004564 SPIRVInstList.push_back(Inst);
4565 break;
4566 }
4567
David Neto22f144c2017-06-12 14:26:21 -04004568 // spirv.store_null.* intrinsics become OpStore's.
4569 if (Callee->getName().startswith("spirv.store_null")) {
4570 //
4571 // Generate OpStore.
4572 //
4573
4574 // Ops[0] = Pointer ID
4575 // Ops[1] = Object ID
4576 // Ops[2] ... Ops[n]
4577 SPIRVOperandList Ops;
4578
4579 uint32_t PointerID = VMap[Call->getArgOperand(0)];
David Neto22f144c2017-06-12 14:26:21 -04004580 uint32_t ObjectID = VMap[Call->getArgOperand(1)];
David Neto257c3892018-04-11 13:19:45 -04004581 Ops << MkId(PointerID) << MkId(ObjectID);
David Neto22f144c2017-06-12 14:26:21 -04004582
David Neto87846742018-04-11 17:36:22 -04004583 SPIRVInstList.push_back(new SPIRVInstruction(spv::OpStore, Ops));
David Neto22f144c2017-06-12 14:26:21 -04004584
4585 break;
4586 }
4587
4588 // spirv.copy_memory.* intrinsics become OpMemoryMemory's.
4589 if (Callee->getName().startswith("spirv.copy_memory")) {
4590 //
4591 // Generate OpCopyMemory.
4592 //
4593
4594 // Ops[0] = Dst ID
4595 // Ops[1] = Src ID
4596 // Ops[2] = Memory Access
4597 // Ops[3] = Alignment
4598
4599 auto IsVolatile =
4600 dyn_cast<ConstantInt>(Call->getArgOperand(3))->getZExtValue() != 0;
4601
4602 auto VolatileMemoryAccess = (IsVolatile) ? spv::MemoryAccessVolatileMask
4603 : spv::MemoryAccessMaskNone;
4604
4605 auto MemoryAccess = VolatileMemoryAccess | spv::MemoryAccessAlignedMask;
4606
4607 auto Alignment =
4608 dyn_cast<ConstantInt>(Call->getArgOperand(2))->getZExtValue();
4609
David Neto257c3892018-04-11 13:19:45 -04004610 SPIRVOperandList Ops;
4611 Ops << MkId(VMap[Call->getArgOperand(0)])
4612 << MkId(VMap[Call->getArgOperand(1)]) << MkNum(MemoryAccess)
4613 << MkNum(static_cast<uint32_t>(Alignment));
David Neto22f144c2017-06-12 14:26:21 -04004614
David Neto87846742018-04-11 17:36:22 -04004615 auto *Inst = new SPIRVInstruction(spv::OpCopyMemory, Ops);
David Neto22f144c2017-06-12 14:26:21 -04004616
4617 SPIRVInstList.push_back(Inst);
4618
4619 break;
4620 }
4621
4622 // Nothing to do for abs with uint. Map abs's operand ID to VMap for abs
4623 // with unit.
4624 if (Callee->getName().equals("_Z3absj") ||
4625 Callee->getName().equals("_Z3absDv2_j") ||
4626 Callee->getName().equals("_Z3absDv3_j") ||
alan-bakerb39c8262019-03-08 14:03:37 -05004627 Callee->getName().equals("_Z3absDv4_j") ||
4628 Callee->getName().equals("_Z3absh") ||
4629 Callee->getName().equals("_Z3absDv2_h") ||
4630 Callee->getName().equals("_Z3absDv3_h") ||
4631 Callee->getName().equals("_Z3absDv4_h")) {
David Neto22f144c2017-06-12 14:26:21 -04004632 VMap[&I] = VMap[Call->getOperand(0)];
4633 break;
4634 }
4635
4636 // barrier is converted to OpControlBarrier
4637 if (Callee->getName().equals("__spirv_control_barrier")) {
4638 //
4639 // Generate OpControlBarrier.
4640 //
4641 // Ops[0] = Execution Scope ID
4642 // Ops[1] = Memory Scope ID
4643 // Ops[2] = Memory Semantics ID
4644 //
4645 Value *ExecutionScope = Call->getArgOperand(0);
4646 Value *MemoryScope = Call->getArgOperand(1);
4647 Value *MemorySemantics = Call->getArgOperand(2);
4648
David Neto257c3892018-04-11 13:19:45 -04004649 SPIRVOperandList Ops;
4650 Ops << MkId(VMap[ExecutionScope]) << MkId(VMap[MemoryScope])
4651 << MkId(VMap[MemorySemantics]);
David Neto22f144c2017-06-12 14:26:21 -04004652
David Neto87846742018-04-11 17:36:22 -04004653 SPIRVInstList.push_back(new SPIRVInstruction(spv::OpControlBarrier, Ops));
David Neto22f144c2017-06-12 14:26:21 -04004654 break;
4655 }
4656
4657 // memory barrier is converted to OpMemoryBarrier
4658 if (Callee->getName().equals("__spirv_memory_barrier")) {
4659 //
4660 // Generate OpMemoryBarrier.
4661 //
4662 // Ops[0] = Memory Scope ID
4663 // Ops[1] = Memory Semantics ID
4664 //
4665 SPIRVOperandList Ops;
4666
David Neto257c3892018-04-11 13:19:45 -04004667 uint32_t MemoryScopeID = VMap[Call->getArgOperand(0)];
4668 uint32_t MemorySemanticsID = VMap[Call->getArgOperand(1)];
David Neto22f144c2017-06-12 14:26:21 -04004669
David Neto257c3892018-04-11 13:19:45 -04004670 Ops << MkId(MemoryScopeID) << MkId(MemorySemanticsID);
David Neto22f144c2017-06-12 14:26:21 -04004671
David Neto87846742018-04-11 17:36:22 -04004672 auto *Inst = new SPIRVInstruction(spv::OpMemoryBarrier, Ops);
David Neto22f144c2017-06-12 14:26:21 -04004673 SPIRVInstList.push_back(Inst);
4674 break;
4675 }
4676
4677 // isinf is converted to OpIsInf
4678 if (Callee->getName().equals("__spirv_isinff") ||
4679 Callee->getName().equals("__spirv_isinfDv2_f") ||
4680 Callee->getName().equals("__spirv_isinfDv3_f") ||
4681 Callee->getName().equals("__spirv_isinfDv4_f")) {
4682 //
4683 // Generate OpIsInf.
4684 //
4685 // Ops[0] = Result Type ID
4686 // Ops[1] = X ID
4687 //
4688 SPIRVOperandList Ops;
4689
David Neto257c3892018-04-11 13:19:45 -04004690 Ops << MkId(lookupType(I.getType()))
4691 << MkId(VMap[Call->getArgOperand(0)]);
David Neto22f144c2017-06-12 14:26:21 -04004692
4693 VMap[&I] = nextID;
4694
David Neto87846742018-04-11 17:36:22 -04004695 auto *Inst = new SPIRVInstruction(spv::OpIsInf, nextID++, Ops);
David Neto22f144c2017-06-12 14:26:21 -04004696 SPIRVInstList.push_back(Inst);
4697 break;
4698 }
4699
4700 // isnan is converted to OpIsNan
4701 if (Callee->getName().equals("__spirv_isnanf") ||
4702 Callee->getName().equals("__spirv_isnanDv2_f") ||
4703 Callee->getName().equals("__spirv_isnanDv3_f") ||
4704 Callee->getName().equals("__spirv_isnanDv4_f")) {
4705 //
4706 // Generate OpIsInf.
4707 //
4708 // Ops[0] = Result Type ID
4709 // Ops[1] = X ID
4710 //
4711 SPIRVOperandList Ops;
4712
David Neto257c3892018-04-11 13:19:45 -04004713 Ops << MkId(lookupType(I.getType()))
4714 << MkId(VMap[Call->getArgOperand(0)]);
David Neto22f144c2017-06-12 14:26:21 -04004715
4716 VMap[&I] = nextID;
4717
David Neto87846742018-04-11 17:36:22 -04004718 auto *Inst = new SPIRVInstruction(spv::OpIsNan, nextID++, Ops);
David Neto22f144c2017-06-12 14:26:21 -04004719 SPIRVInstList.push_back(Inst);
4720 break;
4721 }
4722
4723 // all is converted to OpAll
Kévin Petitfd27cca2018-10-31 13:00:17 +00004724 if (Callee->getName().startswith("__spirv_allDv")) {
David Neto22f144c2017-06-12 14:26:21 -04004725 //
4726 // Generate OpAll.
4727 //
4728 // Ops[0] = Result Type ID
4729 // Ops[1] = Vector ID
4730 //
4731 SPIRVOperandList Ops;
4732
David Neto257c3892018-04-11 13:19:45 -04004733 Ops << MkId(lookupType(I.getType()))
4734 << MkId(VMap[Call->getArgOperand(0)]);
David Neto22f144c2017-06-12 14:26:21 -04004735
4736 VMap[&I] = nextID;
4737
David Neto87846742018-04-11 17:36:22 -04004738 auto *Inst = new SPIRVInstruction(spv::OpAll, nextID++, Ops);
David Neto22f144c2017-06-12 14:26:21 -04004739 SPIRVInstList.push_back(Inst);
4740 break;
4741 }
4742
4743 // any is converted to OpAny
Kévin Petitfd27cca2018-10-31 13:00:17 +00004744 if (Callee->getName().startswith("__spirv_anyDv")) {
David Neto22f144c2017-06-12 14:26:21 -04004745 //
4746 // Generate OpAny.
4747 //
4748 // Ops[0] = Result Type ID
4749 // Ops[1] = Vector ID
4750 //
4751 SPIRVOperandList Ops;
4752
David Neto257c3892018-04-11 13:19:45 -04004753 Ops << MkId(lookupType(I.getType()))
4754 << MkId(VMap[Call->getArgOperand(0)]);
David Neto22f144c2017-06-12 14:26:21 -04004755
4756 VMap[&I] = nextID;
4757
David Neto87846742018-04-11 17:36:22 -04004758 auto *Inst = new SPIRVInstruction(spv::OpAny, nextID++, Ops);
David Neto22f144c2017-06-12 14:26:21 -04004759 SPIRVInstList.push_back(Inst);
4760 break;
4761 }
4762
4763 // read_image is converted to OpSampledImage and OpImageSampleExplicitLod.
4764 // Additionally, OpTypeSampledImage is generated.
4765 if (Callee->getName().equals(
4766 "_Z11read_imagef14ocl_image2d_ro11ocl_samplerDv2_f") ||
4767 Callee->getName().equals(
4768 "_Z11read_imagef14ocl_image3d_ro11ocl_samplerDv4_f")) {
4769 //
4770 // Generate OpSampledImage.
4771 //
4772 // Ops[0] = Result Type ID
4773 // Ops[1] = Image ID
4774 // Ops[2] = Sampler ID
4775 //
4776 SPIRVOperandList Ops;
4777
4778 Value *Image = Call->getArgOperand(0);
4779 Value *Sampler = Call->getArgOperand(1);
4780 Value *Coordinate = Call->getArgOperand(2);
4781
4782 TypeMapType &OpImageTypeMap = getImageTypeMap();
4783 Type *ImageTy = Image->getType()->getPointerElementType();
4784 uint32_t ImageTyID = OpImageTypeMap[ImageTy];
David Neto22f144c2017-06-12 14:26:21 -04004785 uint32_t ImageID = VMap[Image];
David Neto22f144c2017-06-12 14:26:21 -04004786 uint32_t SamplerID = VMap[Sampler];
David Neto257c3892018-04-11 13:19:45 -04004787
4788 Ops << MkId(ImageTyID) << MkId(ImageID) << MkId(SamplerID);
David Neto22f144c2017-06-12 14:26:21 -04004789
4790 uint32_t SampledImageID = nextID;
4791
David Neto87846742018-04-11 17:36:22 -04004792 auto *Inst = new SPIRVInstruction(spv::OpSampledImage, nextID++, Ops);
David Neto22f144c2017-06-12 14:26:21 -04004793 SPIRVInstList.push_back(Inst);
4794
4795 //
4796 // Generate OpImageSampleExplicitLod.
4797 //
4798 // Ops[0] = Result Type ID
4799 // Ops[1] = Sampled Image ID
4800 // Ops[2] = Coordinate ID
4801 // Ops[3] = Image Operands Type ID
4802 // Ops[4] ... Ops[n] = Operands ID
4803 //
4804 Ops.clear();
4805
David Neto257c3892018-04-11 13:19:45 -04004806 Ops << MkId(lookupType(Call->getType())) << MkId(SampledImageID)
4807 << MkId(VMap[Coordinate]) << MkNum(spv::ImageOperandsLodMask);
David Neto22f144c2017-06-12 14:26:21 -04004808
4809 Constant *CstFP0 = ConstantFP::get(Context, APFloat(0.0f));
David Neto257c3892018-04-11 13:19:45 -04004810 Ops << MkId(VMap[CstFP0]);
David Neto22f144c2017-06-12 14:26:21 -04004811
4812 VMap[&I] = nextID;
4813
David Neto87846742018-04-11 17:36:22 -04004814 Inst = new SPIRVInstruction(spv::OpImageSampleExplicitLod, nextID++, Ops);
David Neto22f144c2017-06-12 14:26:21 -04004815 SPIRVInstList.push_back(Inst);
4816 break;
4817 }
4818
4819 // write_imagef is mapped to OpImageWrite.
4820 if (Callee->getName().equals(
4821 "_Z12write_imagef14ocl_image2d_woDv2_iDv4_f") ||
4822 Callee->getName().equals(
4823 "_Z12write_imagef14ocl_image3d_woDv4_iDv4_f")) {
4824 //
4825 // Generate OpImageWrite.
4826 //
4827 // Ops[0] = Image ID
4828 // Ops[1] = Coordinate ID
4829 // Ops[2] = Texel ID
4830 // Ops[3] = (Optional) Image Operands Type (Literal Number)
4831 // Ops[4] ... Ops[n] = (Optional) Operands ID
4832 //
4833 SPIRVOperandList Ops;
4834
4835 Value *Image = Call->getArgOperand(0);
4836 Value *Coordinate = Call->getArgOperand(1);
4837 Value *Texel = Call->getArgOperand(2);
4838
4839 uint32_t ImageID = VMap[Image];
David Neto22f144c2017-06-12 14:26:21 -04004840 uint32_t CoordinateID = VMap[Coordinate];
David Neto22f144c2017-06-12 14:26:21 -04004841 uint32_t TexelID = VMap[Texel];
David Neto257c3892018-04-11 13:19:45 -04004842 Ops << MkId(ImageID) << MkId(CoordinateID) << MkId(TexelID);
David Neto22f144c2017-06-12 14:26:21 -04004843
David Neto87846742018-04-11 17:36:22 -04004844 auto *Inst = new SPIRVInstruction(spv::OpImageWrite, Ops);
David Neto22f144c2017-06-12 14:26:21 -04004845 SPIRVInstList.push_back(Inst);
4846 break;
4847 }
4848
David Neto5c22a252018-03-15 16:07:41 -04004849 // get_image_width is mapped to OpImageQuerySize
4850 if (Callee->getName().equals("_Z15get_image_width14ocl_image2d_ro") ||
4851 Callee->getName().equals("_Z15get_image_width14ocl_image2d_wo") ||
4852 Callee->getName().equals("_Z16get_image_height14ocl_image2d_ro") ||
4853 Callee->getName().equals("_Z16get_image_height14ocl_image2d_wo")) {
4854 //
4855 // Generate OpImageQuerySize, then pull out the right component.
4856 // Assume 2D image for now.
4857 //
4858 // Ops[0] = Image ID
4859 //
4860 // %sizes = OpImageQuerySizes %uint2 %im
4861 // %result = OpCompositeExtract %uint %sizes 0-or-1
4862 SPIRVOperandList Ops;
4863
4864 // Implement:
4865 // %sizes = OpImageQuerySizes %uint2 %im
4866 uint32_t SizesTypeID =
4867 TypeMap[VectorType::get(Type::getInt32Ty(Context), 2)];
David Neto5c22a252018-03-15 16:07:41 -04004868 Value *Image = Call->getArgOperand(0);
4869 uint32_t ImageID = VMap[Image];
David Neto257c3892018-04-11 13:19:45 -04004870 Ops << MkId(SizesTypeID) << MkId(ImageID);
David Neto5c22a252018-03-15 16:07:41 -04004871
4872 uint32_t SizesID = nextID++;
David Neto87846742018-04-11 17:36:22 -04004873 auto *QueryInst =
4874 new SPIRVInstruction(spv::OpImageQuerySize, SizesID, Ops);
David Neto5c22a252018-03-15 16:07:41 -04004875 SPIRVInstList.push_back(QueryInst);
4876
4877 // Reset value map entry since we generated an intermediate instruction.
4878 VMap[&I] = nextID;
4879
4880 // Implement:
4881 // %result = OpCompositeExtract %uint %sizes 0-or-1
4882 Ops.clear();
David Neto257c3892018-04-11 13:19:45 -04004883 Ops << MkId(TypeMap[I.getType()]) << MkId(SizesID);
David Neto5c22a252018-03-15 16:07:41 -04004884
4885 uint32_t component = Callee->getName().contains("height") ? 1 : 0;
David Neto257c3892018-04-11 13:19:45 -04004886 Ops << MkNum(component);
David Neto5c22a252018-03-15 16:07:41 -04004887
David Neto87846742018-04-11 17:36:22 -04004888 auto *Inst = new SPIRVInstruction(spv::OpCompositeExtract, nextID++, Ops);
David Neto5c22a252018-03-15 16:07:41 -04004889 SPIRVInstList.push_back(Inst);
4890 break;
4891 }
4892
David Neto22f144c2017-06-12 14:26:21 -04004893 // Call instrucion is deferred because it needs function's ID. Record
4894 // slot's location on SPIRVInstructionList.
4895 DeferredInsts.push_back(
4896 std::make_tuple(&I, --SPIRVInstList.end(), nextID++));
4897
David Neto3fbb4072017-10-16 11:28:14 -04004898 // Check whether the implementation of this call uses an extended
4899 // instruction plus one more value-producing instruction. If so, then
4900 // reserve the id for the extra value-producing slot.
4901 glsl::ExtInst EInst = getIndirectExtInstEnum(Callee->getName());
4902 if (EInst != kGlslExtInstBad) {
4903 // Reserve a spot for the extra value.
David Neto4d02a532017-09-17 12:57:44 -04004904 // Increase nextID.
David Neto22f144c2017-06-12 14:26:21 -04004905 VMap[&I] = nextID;
4906 nextID++;
4907 }
4908 break;
4909 }
4910 case Instruction::Ret: {
4911 unsigned NumOps = I.getNumOperands();
4912 if (NumOps == 0) {
4913 //
4914 // Generate OpReturn.
4915 //
David Neto87846742018-04-11 17:36:22 -04004916 SPIRVInstList.push_back(new SPIRVInstruction(spv::OpReturn, {}));
David Neto22f144c2017-06-12 14:26:21 -04004917 } else {
4918 //
4919 // Generate OpReturnValue.
4920 //
4921
4922 // Ops[0] = Return Value ID
4923 SPIRVOperandList Ops;
David Neto257c3892018-04-11 13:19:45 -04004924
4925 Ops << MkId(VMap[I.getOperand(0)]);
David Neto22f144c2017-06-12 14:26:21 -04004926
David Neto87846742018-04-11 17:36:22 -04004927 auto *Inst = new SPIRVInstruction(spv::OpReturnValue, Ops);
David Neto22f144c2017-06-12 14:26:21 -04004928 SPIRVInstList.push_back(Inst);
4929 break;
4930 }
4931 break;
4932 }
4933 }
4934}
4935
4936void SPIRVProducerPass::GenerateFuncEpilogue() {
4937 SPIRVInstructionList &SPIRVInstList = getSPIRVInstList();
4938
4939 //
4940 // Generate OpFunctionEnd
4941 //
4942
David Neto87846742018-04-11 17:36:22 -04004943 auto *Inst = new SPIRVInstruction(spv::OpFunctionEnd, {});
David Neto22f144c2017-06-12 14:26:21 -04004944 SPIRVInstList.push_back(Inst);
4945}
4946
4947bool SPIRVProducerPass::is4xi8vec(Type *Ty) const {
alan-bakerb39c8262019-03-08 14:03:37 -05004948 // Don't specialize <4 x i8> if i8 is generally supported.
4949 if (clspv::Option::Int8Support())
4950 return false;
4951
David Neto22f144c2017-06-12 14:26:21 -04004952 LLVMContext &Context = Ty->getContext();
4953 if (Ty->isVectorTy()) {
4954 if (Ty->getVectorElementType() == Type::getInt8Ty(Context) &&
4955 Ty->getVectorNumElements() == 4) {
4956 return true;
4957 }
4958 }
4959
4960 return false;
4961}
4962
David Neto257c3892018-04-11 13:19:45 -04004963uint32_t SPIRVProducerPass::GetI32Zero() {
4964 if (0 == constant_i32_zero_id_) {
4965 llvm_unreachable("Requesting a 32-bit integer constant but it is not "
4966 "defined in the SPIR-V module");
4967 }
4968 return constant_i32_zero_id_;
4969}
4970
David Neto22f144c2017-06-12 14:26:21 -04004971void SPIRVProducerPass::HandleDeferredInstruction() {
4972 SPIRVInstructionList &SPIRVInstList = getSPIRVInstList();
4973 ValueMapType &VMap = getValueMap();
4974 DeferredInstVecType &DeferredInsts = getDeferredInstVec();
4975
4976 for (auto DeferredInst = DeferredInsts.rbegin();
4977 DeferredInst != DeferredInsts.rend(); ++DeferredInst) {
4978 Value *Inst = std::get<0>(*DeferredInst);
4979 SPIRVInstructionList::iterator InsertPoint = ++std::get<1>(*DeferredInst);
4980 if (InsertPoint != SPIRVInstList.end()) {
4981 while ((*InsertPoint)->getOpcode() == spv::OpPhi) {
4982 ++InsertPoint;
4983 }
4984 }
4985
4986 if (BranchInst *Br = dyn_cast<BranchInst>(Inst)) {
4987 // Check whether basic block, which has this branch instruction, is loop
4988 // header or not. If it is loop header, generate OpLoopMerge and
4989 // OpBranchConditional.
4990 Function *Func = Br->getParent()->getParent();
4991 DominatorTree &DT =
4992 getAnalysis<DominatorTreeWrapperPass>(*Func).getDomTree();
4993 const LoopInfo &LI =
4994 getAnalysis<LoopInfoWrapperPass>(*Func).getLoopInfo();
4995
4996 BasicBlock *BrBB = Br->getParent();
4997 if (LI.isLoopHeader(BrBB)) {
4998 Value *ContinueBB = nullptr;
4999 Value *MergeBB = nullptr;
5000
5001 Loop *L = LI.getLoopFor(BrBB);
5002 MergeBB = L->getExitBlock();
5003 if (!MergeBB) {
5004 // StructurizeCFG pass converts CFG into triangle shape and the cfg
5005 // has regions with single entry/exit. As a result, loop should not
5006 // have multiple exits.
5007 llvm_unreachable("Loop has multiple exits???");
5008 }
5009
5010 if (L->isLoopLatch(BrBB)) {
5011 ContinueBB = BrBB;
5012 } else {
5013 // From SPIR-V spec 2.11, Continue Target must dominate that back-edge
5014 // block.
5015 BasicBlock *Header = L->getHeader();
5016 BasicBlock *Latch = L->getLoopLatch();
5017 for (BasicBlock *BB : L->blocks()) {
5018 if (BB == Header) {
5019 continue;
5020 }
5021
5022 // Check whether block dominates block with back-edge.
5023 if (DT.dominates(BB, Latch)) {
5024 ContinueBB = BB;
5025 }
5026 }
5027
5028 if (!ContinueBB) {
5029 llvm_unreachable("Wrong continue block from loop");
5030 }
5031 }
5032
5033 //
5034 // Generate OpLoopMerge.
5035 //
5036 // Ops[0] = Merge Block ID
5037 // Ops[1] = Continue Target ID
5038 // Ops[2] = Selection Control
5039 SPIRVOperandList Ops;
5040
5041 // StructurizeCFG pass already manipulated CFG. Just use false block of
5042 // branch instruction as merge block.
5043 uint32_t MergeBBID = VMap[MergeBB];
David Neto22f144c2017-06-12 14:26:21 -04005044 uint32_t ContinueBBID = VMap[ContinueBB];
David Neto257c3892018-04-11 13:19:45 -04005045 Ops << MkId(MergeBBID) << MkId(ContinueBBID)
5046 << MkNum(spv::SelectionControlMaskNone);
David Neto22f144c2017-06-12 14:26:21 -04005047
David Neto87846742018-04-11 17:36:22 -04005048 auto *MergeInst = new SPIRVInstruction(spv::OpLoopMerge, Ops);
David Neto22f144c2017-06-12 14:26:21 -04005049 SPIRVInstList.insert(InsertPoint, MergeInst);
5050
5051 } else if (Br->isConditional()) {
5052 bool HasBackEdge = false;
5053
5054 for (unsigned i = 0; i < Br->getNumSuccessors(); i++) {
5055 if (LI.isLoopHeader(Br->getSuccessor(i))) {
5056 HasBackEdge = true;
5057 }
5058 }
5059 if (!HasBackEdge) {
5060 //
5061 // Generate OpSelectionMerge.
5062 //
5063 // Ops[0] = Merge Block ID
5064 // Ops[1] = Selection Control
5065 SPIRVOperandList Ops;
5066
5067 // StructurizeCFG pass already manipulated CFG. Just use false block
5068 // of branch instruction as merge block.
5069 uint32_t MergeBBID = VMap[Br->getSuccessor(1)];
David Neto257c3892018-04-11 13:19:45 -04005070 Ops << MkId(MergeBBID) << MkNum(spv::SelectionControlMaskNone);
David Neto22f144c2017-06-12 14:26:21 -04005071
David Neto87846742018-04-11 17:36:22 -04005072 auto *MergeInst = new SPIRVInstruction(spv::OpSelectionMerge, Ops);
David Neto22f144c2017-06-12 14:26:21 -04005073 SPIRVInstList.insert(InsertPoint, MergeInst);
5074 }
5075 }
5076
5077 if (Br->isConditional()) {
5078 //
5079 // Generate OpBranchConditional.
5080 //
5081 // Ops[0] = Condition ID
5082 // Ops[1] = True Label ID
5083 // Ops[2] = False Label ID
5084 // Ops[3] ... Ops[n] = Branch weights (Literal Number)
5085 SPIRVOperandList Ops;
5086
5087 uint32_t CondID = VMap[Br->getCondition()];
David Neto22f144c2017-06-12 14:26:21 -04005088 uint32_t TrueBBID = VMap[Br->getSuccessor(0)];
David Neto22f144c2017-06-12 14:26:21 -04005089 uint32_t FalseBBID = VMap[Br->getSuccessor(1)];
David Neto257c3892018-04-11 13:19:45 -04005090
5091 Ops << MkId(CondID) << MkId(TrueBBID) << MkId(FalseBBID);
David Neto22f144c2017-06-12 14:26:21 -04005092
David Neto87846742018-04-11 17:36:22 -04005093 auto *BrInst = new SPIRVInstruction(spv::OpBranchConditional, Ops);
David Neto22f144c2017-06-12 14:26:21 -04005094 SPIRVInstList.insert(InsertPoint, BrInst);
5095 } else {
5096 //
5097 // Generate OpBranch.
5098 //
5099 // Ops[0] = Target Label ID
5100 SPIRVOperandList Ops;
5101
5102 uint32_t TargetID = VMap[Br->getSuccessor(0)];
David Neto257c3892018-04-11 13:19:45 -04005103 Ops << MkId(TargetID);
David Neto22f144c2017-06-12 14:26:21 -04005104
David Neto87846742018-04-11 17:36:22 -04005105 SPIRVInstList.insert(InsertPoint,
5106 new SPIRVInstruction(spv::OpBranch, Ops));
David Neto22f144c2017-06-12 14:26:21 -04005107 }
5108 } else if (PHINode *PHI = dyn_cast<PHINode>(Inst)) {
alan-baker5b86ed72019-02-15 08:26:50 -05005109 if (PHI->getType()->isPointerTy()) {
5110 // OpPhi on pointers requires variable pointers.
5111 setVariablePointersCapabilities(
5112 PHI->getType()->getPointerAddressSpace());
5113 if (!hasVariablePointers() && !selectFromSameObject(PHI)) {
5114 setVariablePointers(true);
5115 }
5116 }
5117
David Neto22f144c2017-06-12 14:26:21 -04005118 //
5119 // Generate OpPhi.
5120 //
5121 // Ops[0] = Result Type ID
5122 // Ops[1] ... Ops[n] = (Variable ID, Parent ID) pairs
5123 SPIRVOperandList Ops;
5124
David Neto257c3892018-04-11 13:19:45 -04005125 Ops << MkId(lookupType(PHI->getType()));
David Neto22f144c2017-06-12 14:26:21 -04005126
David Neto22f144c2017-06-12 14:26:21 -04005127 for (unsigned i = 0; i < PHI->getNumIncomingValues(); i++) {
5128 uint32_t VarID = VMap[PHI->getIncomingValue(i)];
David Neto22f144c2017-06-12 14:26:21 -04005129 uint32_t ParentID = VMap[PHI->getIncomingBlock(i)];
David Neto257c3892018-04-11 13:19:45 -04005130 Ops << MkId(VarID) << MkId(ParentID);
David Neto22f144c2017-06-12 14:26:21 -04005131 }
5132
5133 SPIRVInstList.insert(
David Neto87846742018-04-11 17:36:22 -04005134 InsertPoint,
5135 new SPIRVInstruction(spv::OpPhi, std::get<2>(*DeferredInst), Ops));
David Neto22f144c2017-06-12 14:26:21 -04005136 } else if (CallInst *Call = dyn_cast<CallInst>(Inst)) {
5137 Function *Callee = Call->getCalledFunction();
David Neto3fbb4072017-10-16 11:28:14 -04005138 auto callee_name = Callee->getName();
5139 glsl::ExtInst EInst = getDirectOrIndirectExtInstEnum(callee_name);
David Neto22f144c2017-06-12 14:26:21 -04005140
5141 if (EInst) {
5142 uint32_t &ExtInstImportID = getOpExtInstImportID();
5143
5144 //
5145 // Generate OpExtInst.
5146 //
5147
5148 // Ops[0] = Result Type ID
5149 // Ops[1] = Set ID (OpExtInstImport ID)
5150 // Ops[2] = Instruction Number (Literal Number)
5151 // Ops[3] ... Ops[n] = Operand 1, ... , Operand n
5152 SPIRVOperandList Ops;
5153
David Neto862b7d82018-06-14 18:48:37 -04005154 Ops << MkId(lookupType(Call->getType())) << MkId(ExtInstImportID)
5155 << MkNum(EInst);
David Neto22f144c2017-06-12 14:26:21 -04005156
David Neto22f144c2017-06-12 14:26:21 -04005157 FunctionType *CalleeFTy = cast<FunctionType>(Call->getFunctionType());
5158 for (unsigned i = 0; i < CalleeFTy->getNumParams(); i++) {
David Neto257c3892018-04-11 13:19:45 -04005159 Ops << MkId(VMap[Call->getOperand(i)]);
David Neto22f144c2017-06-12 14:26:21 -04005160 }
5161
David Neto87846742018-04-11 17:36:22 -04005162 auto *ExtInst = new SPIRVInstruction(spv::OpExtInst,
5163 std::get<2>(*DeferredInst), Ops);
David Neto22f144c2017-06-12 14:26:21 -04005164 SPIRVInstList.insert(InsertPoint, ExtInst);
5165
David Neto3fbb4072017-10-16 11:28:14 -04005166 const auto IndirectExtInst = getIndirectExtInstEnum(callee_name);
5167 if (IndirectExtInst != kGlslExtInstBad) {
5168 // Generate one more instruction that uses the result of the extended
5169 // instruction. Its result id is one more than the id of the
5170 // extended instruction.
David Neto22f144c2017-06-12 14:26:21 -04005171 LLVMContext &Context =
5172 Call->getParent()->getParent()->getParent()->getContext();
David Neto22f144c2017-06-12 14:26:21 -04005173
David Neto3fbb4072017-10-16 11:28:14 -04005174 auto generate_extra_inst = [this, &Context, &Call, &DeferredInst,
5175 &VMap, &SPIRVInstList, &InsertPoint](
5176 spv::Op opcode, Constant *constant) {
5177 //
5178 // Generate instruction like:
5179 // result = opcode constant <extinst-result>
5180 //
5181 // Ops[0] = Result Type ID
5182 // Ops[1] = Operand 0 ;; the constant, suitably splatted
5183 // Ops[2] = Operand 1 ;; the result of the extended instruction
5184 SPIRVOperandList Ops;
David Neto22f144c2017-06-12 14:26:21 -04005185
David Neto3fbb4072017-10-16 11:28:14 -04005186 Type *resultTy = Call->getType();
David Neto257c3892018-04-11 13:19:45 -04005187 Ops << MkId(lookupType(resultTy));
David Neto3fbb4072017-10-16 11:28:14 -04005188
5189 if (auto *vectorTy = dyn_cast<VectorType>(resultTy)) {
5190 constant = ConstantVector::getSplat(
5191 static_cast<unsigned>(vectorTy->getNumElements()), constant);
5192 }
David Neto257c3892018-04-11 13:19:45 -04005193 Ops << MkId(VMap[constant]) << MkId(std::get<2>(*DeferredInst));
David Neto3fbb4072017-10-16 11:28:14 -04005194
5195 SPIRVInstList.insert(
David Neto87846742018-04-11 17:36:22 -04005196 InsertPoint, new SPIRVInstruction(
5197 opcode, std::get<2>(*DeferredInst) + 1, Ops));
David Neto3fbb4072017-10-16 11:28:14 -04005198 };
5199
5200 switch (IndirectExtInst) {
5201 case glsl::ExtInstFindUMsb: // Implementing clz
5202 generate_extra_inst(
5203 spv::OpISub, ConstantInt::get(Type::getInt32Ty(Context), 31));
5204 break;
5205 case glsl::ExtInstAcos: // Implementing acospi
5206 case glsl::ExtInstAsin: // Implementing asinpi
Kévin Petiteb9f90a2018-09-29 12:29:34 +01005207 case glsl::ExtInstAtan: // Implementing atanpi
David Neto3fbb4072017-10-16 11:28:14 -04005208 case glsl::ExtInstAtan2: // Implementing atan2pi
5209 generate_extra_inst(
5210 spv::OpFMul,
5211 ConstantFP::get(Type::getFloatTy(Context), kOneOverPi));
5212 break;
5213
5214 default:
5215 assert(false && "internally inconsistent");
David Neto4d02a532017-09-17 12:57:44 -04005216 }
David Neto22f144c2017-06-12 14:26:21 -04005217 }
David Neto3fbb4072017-10-16 11:28:14 -04005218
alan-bakerb39c8262019-03-08 14:03:37 -05005219 } else if (callee_name.startswith("_Z8popcount")) {
David Neto22f144c2017-06-12 14:26:21 -04005220 //
5221 // Generate OpBitCount
5222 //
5223 // Ops[0] = Result Type ID
5224 // Ops[1] = Base ID
David Neto257c3892018-04-11 13:19:45 -04005225 SPIRVOperandList Ops;
5226 Ops << MkId(lookupType(Call->getType()))
5227 << MkId(VMap[Call->getOperand(0)]);
David Neto22f144c2017-06-12 14:26:21 -04005228
5229 SPIRVInstList.insert(
David Neto87846742018-04-11 17:36:22 -04005230 InsertPoint, new SPIRVInstruction(spv::OpBitCount,
David Neto22f144c2017-06-12 14:26:21 -04005231 std::get<2>(*DeferredInst), Ops));
David Netoab03f432017-11-03 17:00:44 -04005232
David Neto862b7d82018-06-14 18:48:37 -04005233 } else if (callee_name.startswith(kCompositeConstructFunctionPrefix)) {
David Netoab03f432017-11-03 17:00:44 -04005234
5235 // Generate an OpCompositeConstruct
5236 SPIRVOperandList Ops;
5237
5238 // The result type.
David Neto257c3892018-04-11 13:19:45 -04005239 Ops << MkId(lookupType(Call->getType()));
David Netoab03f432017-11-03 17:00:44 -04005240
5241 for (Use &use : Call->arg_operands()) {
David Neto257c3892018-04-11 13:19:45 -04005242 Ops << MkId(VMap[use.get()]);
David Netoab03f432017-11-03 17:00:44 -04005243 }
5244
5245 SPIRVInstList.insert(
David Neto87846742018-04-11 17:36:22 -04005246 InsertPoint, new SPIRVInstruction(spv::OpCompositeConstruct,
5247 std::get<2>(*DeferredInst), Ops));
David Netoab03f432017-11-03 17:00:44 -04005248
Alan Baker202c8c72018-08-13 13:47:44 -04005249 } else if (callee_name.startswith(clspv::ResourceAccessorFunction())) {
5250
5251 // We have already mapped the call's result value to an ID.
5252 // Don't generate any code now.
5253
5254 } else if (callee_name.startswith(clspv::WorkgroupAccessorFunction())) {
David Neto862b7d82018-06-14 18:48:37 -04005255
5256 // We have already mapped the call's result value to an ID.
5257 // Don't generate any code now.
5258
David Neto22f144c2017-06-12 14:26:21 -04005259 } else {
alan-baker5b86ed72019-02-15 08:26:50 -05005260 if (Call->getType()->isPointerTy()) {
5261 // Functions returning pointers require variable pointers.
5262 setVariablePointersCapabilities(
5263 Call->getType()->getPointerAddressSpace());
5264 }
5265
David Neto22f144c2017-06-12 14:26:21 -04005266 //
5267 // Generate OpFunctionCall.
5268 //
5269
5270 // Ops[0] = Result Type ID
5271 // Ops[1] = Callee Function ID
5272 // Ops[2] ... Ops[n] = Argument 0, ... , Argument n
5273 SPIRVOperandList Ops;
5274
David Neto862b7d82018-06-14 18:48:37 -04005275 Ops << MkId(lookupType(Call->getType()));
David Neto22f144c2017-06-12 14:26:21 -04005276
5277 uint32_t CalleeID = VMap[Callee];
David Neto43568eb2017-10-13 18:25:25 -04005278 if (CalleeID == 0) {
5279 errs() << "Can't translate function call. Missing builtin? "
David Neto862b7d82018-06-14 18:48:37 -04005280 << callee_name << " in: " << *Call << "\n";
David Neto43568eb2017-10-13 18:25:25 -04005281 // TODO(dneto): Can we error out? Enabling this llvm_unreachable
5282 // causes an infinite loop. Instead, go ahead and generate
5283 // the bad function call. A validator will catch the 0-Id.
5284 // llvm_unreachable("Can't translate function call");
5285 }
David Neto22f144c2017-06-12 14:26:21 -04005286
David Neto257c3892018-04-11 13:19:45 -04005287 Ops << MkId(CalleeID);
David Neto22f144c2017-06-12 14:26:21 -04005288
David Neto22f144c2017-06-12 14:26:21 -04005289 FunctionType *CalleeFTy = cast<FunctionType>(Call->getFunctionType());
5290 for (unsigned i = 0; i < CalleeFTy->getNumParams(); i++) {
alan-baker5b86ed72019-02-15 08:26:50 -05005291 auto *operand = Call->getOperand(i);
5292 if (operand->getType()->isPointerTy()) {
5293 auto sc =
5294 GetStorageClass(operand->getType()->getPointerAddressSpace());
5295 if (sc == spv::StorageClassStorageBuffer) {
5296 // Passing SSBO by reference requires variable pointers storage
5297 // buffer.
5298 setVariablePointersStorageBuffer(true);
5299 } else if (sc == spv::StorageClassWorkgroup) {
5300 // Workgroup references require variable pointers if they are not
5301 // memory object declarations.
5302 if (auto *operand_call = dyn_cast<CallInst>(operand)) {
5303 // Workgroup accessor represents a variable reference.
5304 if (!operand_call->getCalledFunction()->getName().startswith(
5305 clspv::WorkgroupAccessorFunction()))
5306 setVariablePointers(true);
5307 } else {
5308 // Arguments are function parameters.
5309 if (!isa<Argument>(operand))
5310 setVariablePointers(true);
5311 }
5312 }
5313 }
5314 Ops << MkId(VMap[operand]);
David Neto22f144c2017-06-12 14:26:21 -04005315 }
5316
David Neto87846742018-04-11 17:36:22 -04005317 auto *CallInst = new SPIRVInstruction(spv::OpFunctionCall,
5318 std::get<2>(*DeferredInst), Ops);
David Neto22f144c2017-06-12 14:26:21 -04005319 SPIRVInstList.insert(InsertPoint, CallInst);
5320 }
5321 }
5322 }
5323}
5324
David Neto1a1a0582017-07-07 12:01:44 -04005325void SPIRVProducerPass::HandleDeferredDecorations(const DataLayout &DL) {
Alan Baker202c8c72018-08-13 13:47:44 -04005326 if (getTypesNeedingArrayStride().empty() && LocalArgSpecIds.empty()) {
David Neto1a1a0582017-07-07 12:01:44 -04005327 return;
David Netoc6f3ab22018-04-06 18:02:31 -04005328 }
David Neto1a1a0582017-07-07 12:01:44 -04005329
5330 SPIRVInstructionList &SPIRVInstList = getSPIRVInstList();
David Neto1a1a0582017-07-07 12:01:44 -04005331
5332 // Find an iterator pointing just past the last decoration.
5333 bool seen_decorations = false;
5334 auto DecoInsertPoint =
5335 std::find_if(SPIRVInstList.begin(), SPIRVInstList.end(),
5336 [&seen_decorations](SPIRVInstruction *Inst) -> bool {
5337 const bool is_decoration =
5338 Inst->getOpcode() == spv::OpDecorate ||
5339 Inst->getOpcode() == spv::OpMemberDecorate;
5340 if (is_decoration) {
5341 seen_decorations = true;
5342 return false;
5343 } else {
5344 return seen_decorations;
5345 }
5346 });
5347
David Netoc6f3ab22018-04-06 18:02:31 -04005348 // Insert ArrayStride decorations on pointer types, due to OpPtrAccessChain
5349 // instructions we generated earlier.
David Neto85082642018-03-24 06:55:20 -07005350 for (auto *type : getTypesNeedingArrayStride()) {
5351 Type *elemTy = nullptr;
5352 if (auto *ptrTy = dyn_cast<PointerType>(type)) {
5353 elemTy = ptrTy->getElementType();
alan-bakerb6b09dc2018-11-08 16:59:28 -05005354 } else if (auto *arrayTy = dyn_cast<ArrayType>(type)) {
David Neto85082642018-03-24 06:55:20 -07005355 elemTy = arrayTy->getArrayElementType();
alan-bakerb6b09dc2018-11-08 16:59:28 -05005356 } else if (auto *seqTy = dyn_cast<SequentialType>(type)) {
David Neto85082642018-03-24 06:55:20 -07005357 elemTy = seqTy->getSequentialElementType();
5358 } else {
5359 errs() << "Unhandled strided type " << *type << "\n";
5360 llvm_unreachable("Unhandled strided type");
5361 }
David Neto1a1a0582017-07-07 12:01:44 -04005362
5363 // Ops[0] = Target ID
5364 // Ops[1] = Decoration (ArrayStride)
5365 // Ops[2] = Stride number (Literal Number)
5366 SPIRVOperandList Ops;
5367
David Neto85082642018-03-24 06:55:20 -07005368 // Same as DL.getIndexedOffsetInType( elemTy, { 1 } );
Alan Bakerfcda9482018-10-02 17:09:59 -04005369 const uint32_t stride = static_cast<uint32_t>(GetTypeAllocSize(elemTy, DL));
David Neto257c3892018-04-11 13:19:45 -04005370
5371 Ops << MkId(lookupType(type)) << MkNum(spv::DecorationArrayStride)
5372 << MkNum(stride);
David Neto1a1a0582017-07-07 12:01:44 -04005373
David Neto87846742018-04-11 17:36:22 -04005374 auto *DecoInst = new SPIRVInstruction(spv::OpDecorate, Ops);
David Neto1a1a0582017-07-07 12:01:44 -04005375 SPIRVInstList.insert(DecoInsertPoint, DecoInst);
5376 }
David Netoc6f3ab22018-04-06 18:02:31 -04005377
5378 // Emit SpecId decorations targeting the array size value.
Alan Baker202c8c72018-08-13 13:47:44 -04005379 for (auto spec_id = clspv::FirstLocalSpecId(); spec_id < max_local_spec_id_;
5380 ++spec_id) {
alan-bakerb6b09dc2018-11-08 16:59:28 -05005381 LocalArgInfo &arg_info = LocalSpecIdInfoMap[spec_id];
David Netoc6f3ab22018-04-06 18:02:31 -04005382 SPIRVOperandList Ops;
5383 Ops << MkId(arg_info.array_size_id) << MkNum(spv::DecorationSpecId)
5384 << MkNum(arg_info.spec_id);
5385 SPIRVInstList.insert(DecoInsertPoint,
David Neto87846742018-04-11 17:36:22 -04005386 new SPIRVInstruction(spv::OpDecorate, Ops));
David Netoc6f3ab22018-04-06 18:02:31 -04005387 }
David Neto1a1a0582017-07-07 12:01:44 -04005388}
5389
David Neto22f144c2017-06-12 14:26:21 -04005390glsl::ExtInst SPIRVProducerPass::getExtInstEnum(StringRef Name) {
5391 return StringSwitch<glsl::ExtInst>(Name)
alan-bakerb39c8262019-03-08 14:03:37 -05005392 .Case("_Z3absc", glsl::ExtInst::ExtInstSAbs)
5393 .Case("_Z3absDv2_c", glsl::ExtInst::ExtInstSAbs)
5394 .Case("_Z3absDv3_c", glsl::ExtInst::ExtInstSAbs)
5395 .Case("_Z3absDv4_c", glsl::ExtInst::ExtInstSAbs)
Kévin Petit2444e9b2018-11-09 14:14:37 +00005396 .Case("_Z3abss", glsl::ExtInst::ExtInstSAbs)
5397 .Case("_Z3absDv2_s", glsl::ExtInst::ExtInstSAbs)
5398 .Case("_Z3absDv3_s", glsl::ExtInst::ExtInstSAbs)
5399 .Case("_Z3absDv4_s", glsl::ExtInst::ExtInstSAbs)
David Neto22f144c2017-06-12 14:26:21 -04005400 .Case("_Z3absi", glsl::ExtInst::ExtInstSAbs)
5401 .Case("_Z3absDv2_i", glsl::ExtInst::ExtInstSAbs)
5402 .Case("_Z3absDv3_i", glsl::ExtInst::ExtInstSAbs)
5403 .Case("_Z3absDv4_i", glsl::ExtInst::ExtInstSAbs)
Kévin Petit2444e9b2018-11-09 14:14:37 +00005404 .Case("_Z3absl", glsl::ExtInst::ExtInstSAbs)
5405 .Case("_Z3absDv2_l", glsl::ExtInst::ExtInstSAbs)
5406 .Case("_Z3absDv3_l", glsl::ExtInst::ExtInstSAbs)
5407 .Case("_Z3absDv4_l", glsl::ExtInst::ExtInstSAbs)
alan-bakerb39c8262019-03-08 14:03:37 -05005408 .Case("_Z5clampccc", glsl::ExtInst::ExtInstSClamp)
5409 .Case("_Z5clampDv2_cS_S_", glsl::ExtInst::ExtInstSClamp)
5410 .Case("_Z5clampDv3_cS_S_", glsl::ExtInst::ExtInstSClamp)
5411 .Case("_Z5clampDv4_cS_S_", glsl::ExtInst::ExtInstSClamp)
5412 .Case("_Z5clamphhh", glsl::ExtInst::ExtInstUClamp)
5413 .Case("_Z5clampDv2_hS_S_", glsl::ExtInst::ExtInstUClamp)
5414 .Case("_Z5clampDv3_hS_S_", glsl::ExtInst::ExtInstUClamp)
5415 .Case("_Z5clampDv4_hS_S_", glsl::ExtInst::ExtInstUClamp)
Kévin Petit495255d2019-03-06 13:56:48 +00005416 .Case("_Z5clampsss", glsl::ExtInst::ExtInstSClamp)
5417 .Case("_Z5clampDv2_sS_S_", glsl::ExtInst::ExtInstSClamp)
5418 .Case("_Z5clampDv3_sS_S_", glsl::ExtInst::ExtInstSClamp)
5419 .Case("_Z5clampDv4_sS_S_", glsl::ExtInst::ExtInstSClamp)
5420 .Case("_Z5clampttt", glsl::ExtInst::ExtInstUClamp)
5421 .Case("_Z5clampDv2_tS_S_", glsl::ExtInst::ExtInstUClamp)
5422 .Case("_Z5clampDv3_tS_S_", glsl::ExtInst::ExtInstUClamp)
5423 .Case("_Z5clampDv4_tS_S_", glsl::ExtInst::ExtInstUClamp)
David Neto22f144c2017-06-12 14:26:21 -04005424 .Case("_Z5clampiii", glsl::ExtInst::ExtInstSClamp)
5425 .Case("_Z5clampDv2_iS_S_", glsl::ExtInst::ExtInstSClamp)
5426 .Case("_Z5clampDv3_iS_S_", glsl::ExtInst::ExtInstSClamp)
5427 .Case("_Z5clampDv4_iS_S_", glsl::ExtInst::ExtInstSClamp)
5428 .Case("_Z5clampjjj", glsl::ExtInst::ExtInstUClamp)
5429 .Case("_Z5clampDv2_jS_S_", glsl::ExtInst::ExtInstUClamp)
5430 .Case("_Z5clampDv3_jS_S_", glsl::ExtInst::ExtInstUClamp)
5431 .Case("_Z5clampDv4_jS_S_", glsl::ExtInst::ExtInstUClamp)
Kévin Petit495255d2019-03-06 13:56:48 +00005432 .Case("_Z5clamplll", glsl::ExtInst::ExtInstSClamp)
5433 .Case("_Z5clampDv2_lS_S_", glsl::ExtInst::ExtInstSClamp)
5434 .Case("_Z5clampDv3_lS_S_", glsl::ExtInst::ExtInstSClamp)
5435 .Case("_Z5clampDv4_lS_S_", glsl::ExtInst::ExtInstSClamp)
5436 .Case("_Z5clampmmm", glsl::ExtInst::ExtInstUClamp)
5437 .Case("_Z5clampDv2_mS_S_", glsl::ExtInst::ExtInstUClamp)
5438 .Case("_Z5clampDv3_mS_S_", glsl::ExtInst::ExtInstUClamp)
5439 .Case("_Z5clampDv4_mS_S_", glsl::ExtInst::ExtInstUClamp)
David Neto22f144c2017-06-12 14:26:21 -04005440 .Case("_Z5clampfff", glsl::ExtInst::ExtInstFClamp)
5441 .Case("_Z5clampDv2_fS_S_", glsl::ExtInst::ExtInstFClamp)
5442 .Case("_Z5clampDv3_fS_S_", glsl::ExtInst::ExtInstFClamp)
5443 .Case("_Z5clampDv4_fS_S_", glsl::ExtInst::ExtInstFClamp)
alan-bakerb39c8262019-03-08 14:03:37 -05005444 .Case("_Z3maxcc", glsl::ExtInst::ExtInstSMax)
5445 .Case("_Z3maxDv2_cS_", glsl::ExtInst::ExtInstSMax)
5446 .Case("_Z3maxDv3_cS_", glsl::ExtInst::ExtInstSMax)
5447 .Case("_Z3maxDv4_cS_", glsl::ExtInst::ExtInstSMax)
5448 .Case("_Z3maxhh", glsl::ExtInst::ExtInstUMax)
5449 .Case("_Z3maxDv2_hS_", glsl::ExtInst::ExtInstUMax)
5450 .Case("_Z3maxDv3_hS_", glsl::ExtInst::ExtInstUMax)
5451 .Case("_Z3maxDv4_hS_", glsl::ExtInst::ExtInstUMax)
Kévin Petit9e1971c2018-11-09 14:17:18 +00005452 .Case("_Z3maxss", glsl::ExtInst::ExtInstSMax)
5453 .Case("_Z3maxDv2_sS_", glsl::ExtInst::ExtInstSMax)
5454 .Case("_Z3maxDv3_sS_", glsl::ExtInst::ExtInstSMax)
5455 .Case("_Z3maxDv4_sS_", glsl::ExtInst::ExtInstSMax)
5456 .Case("_Z3maxtt", glsl::ExtInst::ExtInstUMax)
5457 .Case("_Z3maxDv2_tS_", glsl::ExtInst::ExtInstUMax)
5458 .Case("_Z3maxDv3_tS_", glsl::ExtInst::ExtInstUMax)
5459 .Case("_Z3maxDv4_tS_", glsl::ExtInst::ExtInstUMax)
David Neto22f144c2017-06-12 14:26:21 -04005460 .Case("_Z3maxii", glsl::ExtInst::ExtInstSMax)
5461 .Case("_Z3maxDv2_iS_", glsl::ExtInst::ExtInstSMax)
5462 .Case("_Z3maxDv3_iS_", glsl::ExtInst::ExtInstSMax)
5463 .Case("_Z3maxDv4_iS_", glsl::ExtInst::ExtInstSMax)
5464 .Case("_Z3maxjj", glsl::ExtInst::ExtInstUMax)
5465 .Case("_Z3maxDv2_jS_", glsl::ExtInst::ExtInstUMax)
5466 .Case("_Z3maxDv3_jS_", glsl::ExtInst::ExtInstUMax)
5467 .Case("_Z3maxDv4_jS_", glsl::ExtInst::ExtInstUMax)
Kévin Petit9e1971c2018-11-09 14:17:18 +00005468 .Case("_Z3maxll", glsl::ExtInst::ExtInstSMax)
5469 .Case("_Z3maxDv2_lS_", glsl::ExtInst::ExtInstSMax)
5470 .Case("_Z3maxDv3_lS_", glsl::ExtInst::ExtInstSMax)
5471 .Case("_Z3maxDv4_lS_", glsl::ExtInst::ExtInstSMax)
5472 .Case("_Z3maxmm", glsl::ExtInst::ExtInstUMax)
5473 .Case("_Z3maxDv2_mS_", glsl::ExtInst::ExtInstUMax)
5474 .Case("_Z3maxDv3_mS_", glsl::ExtInst::ExtInstUMax)
5475 .Case("_Z3maxDv4_mS_", glsl::ExtInst::ExtInstUMax)
David Neto22f144c2017-06-12 14:26:21 -04005476 .Case("_Z3maxff", glsl::ExtInst::ExtInstFMax)
5477 .Case("_Z3maxDv2_fS_", glsl::ExtInst::ExtInstFMax)
5478 .Case("_Z3maxDv3_fS_", glsl::ExtInst::ExtInstFMax)
5479 .Case("_Z3maxDv4_fS_", glsl::ExtInst::ExtInstFMax)
5480 .StartsWith("_Z4fmax", glsl::ExtInst::ExtInstFMax)
alan-bakerb39c8262019-03-08 14:03:37 -05005481 .Case("_Z3mincc", glsl::ExtInst::ExtInstSMin)
5482 .Case("_Z3minDv2_cS_", glsl::ExtInst::ExtInstSMin)
5483 .Case("_Z3minDv3_cS_", glsl::ExtInst::ExtInstSMin)
5484 .Case("_Z3minDv4_cS_", glsl::ExtInst::ExtInstSMin)
5485 .Case("_Z3minhh", glsl::ExtInst::ExtInstUMin)
5486 .Case("_Z3minDv2_hS_", glsl::ExtInst::ExtInstUMin)
5487 .Case("_Z3minDv3_hS_", glsl::ExtInst::ExtInstUMin)
5488 .Case("_Z3minDv4_hS_", glsl::ExtInst::ExtInstUMin)
Kévin Petit9e1971c2018-11-09 14:17:18 +00005489 .Case("_Z3minss", glsl::ExtInst::ExtInstSMin)
5490 .Case("_Z3minDv2_sS_", glsl::ExtInst::ExtInstSMin)
5491 .Case("_Z3minDv3_sS_", glsl::ExtInst::ExtInstSMin)
5492 .Case("_Z3minDv4_sS_", glsl::ExtInst::ExtInstSMin)
5493 .Case("_Z3mintt", glsl::ExtInst::ExtInstUMin)
5494 .Case("_Z3minDv2_tS_", glsl::ExtInst::ExtInstUMin)
5495 .Case("_Z3minDv3_tS_", glsl::ExtInst::ExtInstUMin)
5496 .Case("_Z3minDv4_tS_", glsl::ExtInst::ExtInstUMin)
David Neto22f144c2017-06-12 14:26:21 -04005497 .Case("_Z3minii", glsl::ExtInst::ExtInstSMin)
5498 .Case("_Z3minDv2_iS_", glsl::ExtInst::ExtInstSMin)
5499 .Case("_Z3minDv3_iS_", glsl::ExtInst::ExtInstSMin)
5500 .Case("_Z3minDv4_iS_", glsl::ExtInst::ExtInstSMin)
5501 .Case("_Z3minjj", glsl::ExtInst::ExtInstUMin)
5502 .Case("_Z3minDv2_jS_", glsl::ExtInst::ExtInstUMin)
5503 .Case("_Z3minDv3_jS_", glsl::ExtInst::ExtInstUMin)
5504 .Case("_Z3minDv4_jS_", glsl::ExtInst::ExtInstUMin)
Kévin Petit9e1971c2018-11-09 14:17:18 +00005505 .Case("_Z3minll", glsl::ExtInst::ExtInstSMin)
5506 .Case("_Z3minDv2_lS_", glsl::ExtInst::ExtInstSMin)
5507 .Case("_Z3minDv3_lS_", glsl::ExtInst::ExtInstSMin)
5508 .Case("_Z3minDv4_lS_", glsl::ExtInst::ExtInstSMin)
5509 .Case("_Z3minmm", glsl::ExtInst::ExtInstUMin)
5510 .Case("_Z3minDv2_mS_", glsl::ExtInst::ExtInstUMin)
5511 .Case("_Z3minDv3_mS_", glsl::ExtInst::ExtInstUMin)
5512 .Case("_Z3minDv4_mS_", glsl::ExtInst::ExtInstUMin)
David Neto22f144c2017-06-12 14:26:21 -04005513 .Case("_Z3minff", glsl::ExtInst::ExtInstFMin)
5514 .Case("_Z3minDv2_fS_", glsl::ExtInst::ExtInstFMin)
5515 .Case("_Z3minDv3_fS_", glsl::ExtInst::ExtInstFMin)
5516 .Case("_Z3minDv4_fS_", glsl::ExtInst::ExtInstFMin)
5517 .StartsWith("_Z4fmin", glsl::ExtInst::ExtInstFMin)
5518 .StartsWith("_Z7degrees", glsl::ExtInst::ExtInstDegrees)
5519 .StartsWith("_Z7radians", glsl::ExtInst::ExtInstRadians)
5520 .StartsWith("_Z3mix", glsl::ExtInst::ExtInstFMix)
5521 .StartsWith("_Z4acos", glsl::ExtInst::ExtInstAcos)
5522 .StartsWith("_Z5acosh", glsl::ExtInst::ExtInstAcosh)
5523 .StartsWith("_Z4asin", glsl::ExtInst::ExtInstAsin)
5524 .StartsWith("_Z5asinh", glsl::ExtInst::ExtInstAsinh)
5525 .StartsWith("_Z4atan", glsl::ExtInst::ExtInstAtan)
5526 .StartsWith("_Z5atan2", glsl::ExtInst::ExtInstAtan2)
5527 .StartsWith("_Z5atanh", glsl::ExtInst::ExtInstAtanh)
5528 .StartsWith("_Z4ceil", glsl::ExtInst::ExtInstCeil)
5529 .StartsWith("_Z3sin", glsl::ExtInst::ExtInstSin)
5530 .StartsWith("_Z4sinh", glsl::ExtInst::ExtInstSinh)
5531 .StartsWith("_Z8half_sin", glsl::ExtInst::ExtInstSin)
5532 .StartsWith("_Z10native_sin", glsl::ExtInst::ExtInstSin)
5533 .StartsWith("_Z3cos", glsl::ExtInst::ExtInstCos)
5534 .StartsWith("_Z4cosh", glsl::ExtInst::ExtInstCosh)
5535 .StartsWith("_Z8half_cos", glsl::ExtInst::ExtInstCos)
5536 .StartsWith("_Z10native_cos", glsl::ExtInst::ExtInstCos)
5537 .StartsWith("_Z3tan", glsl::ExtInst::ExtInstTan)
5538 .StartsWith("_Z4tanh", glsl::ExtInst::ExtInstTanh)
5539 .StartsWith("_Z8half_tan", glsl::ExtInst::ExtInstTan)
5540 .StartsWith("_Z10native_tan", glsl::ExtInst::ExtInstTan)
5541 .StartsWith("_Z3exp", glsl::ExtInst::ExtInstExp)
5542 .StartsWith("_Z8half_exp", glsl::ExtInst::ExtInstExp)
5543 .StartsWith("_Z10native_exp", glsl::ExtInst::ExtInstExp)
5544 .StartsWith("_Z4exp2", glsl::ExtInst::ExtInstExp2)
5545 .StartsWith("_Z9half_exp2", glsl::ExtInst::ExtInstExp2)
5546 .StartsWith("_Z11native_exp2", glsl::ExtInst::ExtInstExp2)
5547 .StartsWith("_Z3log", glsl::ExtInst::ExtInstLog)
5548 .StartsWith("_Z8half_log", glsl::ExtInst::ExtInstLog)
5549 .StartsWith("_Z10native_log", glsl::ExtInst::ExtInstLog)
5550 .StartsWith("_Z4log2", glsl::ExtInst::ExtInstLog2)
5551 .StartsWith("_Z9half_log2", glsl::ExtInst::ExtInstLog2)
5552 .StartsWith("_Z11native_log2", glsl::ExtInst::ExtInstLog2)
5553 .StartsWith("_Z4fabs", glsl::ExtInst::ExtInstFAbs)
kpet3458e942018-10-03 14:35:21 +01005554 .StartsWith("_Z3fma", glsl::ExtInst::ExtInstFma)
David Neto22f144c2017-06-12 14:26:21 -04005555 .StartsWith("_Z5floor", glsl::ExtInst::ExtInstFloor)
5556 .StartsWith("_Z5ldexp", glsl::ExtInst::ExtInstLdexp)
5557 .StartsWith("_Z3pow", glsl::ExtInst::ExtInstPow)
5558 .StartsWith("_Z4powr", glsl::ExtInst::ExtInstPow)
5559 .StartsWith("_Z9half_powr", glsl::ExtInst::ExtInstPow)
5560 .StartsWith("_Z11native_powr", glsl::ExtInst::ExtInstPow)
5561 .StartsWith("_Z5round", glsl::ExtInst::ExtInstRound)
5562 .StartsWith("_Z4sqrt", glsl::ExtInst::ExtInstSqrt)
5563 .StartsWith("_Z9half_sqrt", glsl::ExtInst::ExtInstSqrt)
5564 .StartsWith("_Z11native_sqrt", glsl::ExtInst::ExtInstSqrt)
5565 .StartsWith("_Z5rsqrt", glsl::ExtInst::ExtInstInverseSqrt)
5566 .StartsWith("_Z10half_rsqrt", glsl::ExtInst::ExtInstInverseSqrt)
5567 .StartsWith("_Z12native_rsqrt", glsl::ExtInst::ExtInstInverseSqrt)
5568 .StartsWith("_Z5trunc", glsl::ExtInst::ExtInstTrunc)
5569 .StartsWith("_Z5frexp", glsl::ExtInst::ExtInstFrexp)
5570 .StartsWith("_Z4sign", glsl::ExtInst::ExtInstFSign)
5571 .StartsWith("_Z6length", glsl::ExtInst::ExtInstLength)
Kévin Petit7d09cec2018-09-22 15:43:38 +01005572 .StartsWith("_Z11fast_length", glsl::ExtInst::ExtInstLength)
David Neto22f144c2017-06-12 14:26:21 -04005573 .StartsWith("_Z8distance", glsl::ExtInst::ExtInstDistance)
Kévin Petit7d09cec2018-09-22 15:43:38 +01005574 .StartsWith("_Z13fast_distance", glsl::ExtInst::ExtInstDistance)
David Netoe9a03512017-10-16 10:08:27 -04005575 .StartsWith("_Z4step", glsl::ExtInst::ExtInstStep)
kpet6fd2a262018-10-03 14:48:01 +01005576 .StartsWith("_Z10smoothstep", glsl::ExtInst::ExtInstSmoothStep)
David Neto22f144c2017-06-12 14:26:21 -04005577 .Case("_Z5crossDv3_fS_", glsl::ExtInst::ExtInstCross)
5578 .StartsWith("_Z9normalize", glsl::ExtInst::ExtInstNormalize)
Kévin Petit7d09cec2018-09-22 15:43:38 +01005579 .StartsWith("_Z14fast_normalize", glsl::ExtInst::ExtInstNormalize)
David Neto22f144c2017-06-12 14:26:21 -04005580 .StartsWith("llvm.fmuladd.", glsl::ExtInst::ExtInstFma)
5581 .Case("spirv.unpack.v2f16", glsl::ExtInst::ExtInstUnpackHalf2x16)
5582 .Case("spirv.pack.v2f16", glsl::ExtInst::ExtInstPackHalf2x16)
David Neto62653202017-10-16 19:05:18 -04005583 .Case("clspv.fract.f", glsl::ExtInst::ExtInstFract)
5584 .Case("clspv.fract.v2f", glsl::ExtInst::ExtInstFract)
5585 .Case("clspv.fract.v3f", glsl::ExtInst::ExtInstFract)
5586 .Case("clspv.fract.v4f", glsl::ExtInst::ExtInstFract)
David Neto3fbb4072017-10-16 11:28:14 -04005587 .Default(kGlslExtInstBad);
5588}
5589
5590glsl::ExtInst SPIRVProducerPass::getIndirectExtInstEnum(StringRef Name) {
5591 // Check indirect cases.
5592 return StringSwitch<glsl::ExtInst>(Name)
5593 .StartsWith("_Z3clz", glsl::ExtInst::ExtInstFindUMsb)
5594 // Use exact match on float arg because these need a multiply
5595 // of a constant of the right floating point type.
5596 .Case("_Z6acospif", glsl::ExtInst::ExtInstAcos)
5597 .Case("_Z6acospiDv2_f", glsl::ExtInst::ExtInstAcos)
5598 .Case("_Z6acospiDv3_f", glsl::ExtInst::ExtInstAcos)
5599 .Case("_Z6acospiDv4_f", glsl::ExtInst::ExtInstAcos)
5600 .Case("_Z6asinpif", glsl::ExtInst::ExtInstAsin)
5601 .Case("_Z6asinpiDv2_f", glsl::ExtInst::ExtInstAsin)
5602 .Case("_Z6asinpiDv3_f", glsl::ExtInst::ExtInstAsin)
5603 .Case("_Z6asinpiDv4_f", glsl::ExtInst::ExtInstAsin)
Kévin Petiteb9f90a2018-09-29 12:29:34 +01005604 .Case("_Z6atanpif", glsl::ExtInst::ExtInstAtan)
5605 .Case("_Z6atanpiDv2_f", glsl::ExtInst::ExtInstAtan)
5606 .Case("_Z6atanpiDv3_f", glsl::ExtInst::ExtInstAtan)
5607 .Case("_Z6atanpiDv4_f", glsl::ExtInst::ExtInstAtan)
David Neto3fbb4072017-10-16 11:28:14 -04005608 .Case("_Z7atan2piff", glsl::ExtInst::ExtInstAtan2)
5609 .Case("_Z7atan2piDv2_fS_", glsl::ExtInst::ExtInstAtan2)
5610 .Case("_Z7atan2piDv3_fS_", glsl::ExtInst::ExtInstAtan2)
5611 .Case("_Z7atan2piDv4_fS_", glsl::ExtInst::ExtInstAtan2)
5612 .Default(kGlslExtInstBad);
5613}
5614
alan-bakerb6b09dc2018-11-08 16:59:28 -05005615glsl::ExtInst
5616SPIRVProducerPass::getDirectOrIndirectExtInstEnum(StringRef Name) {
David Neto3fbb4072017-10-16 11:28:14 -04005617 auto direct = getExtInstEnum(Name);
5618 if (direct != kGlslExtInstBad)
5619 return direct;
5620 return getIndirectExtInstEnum(Name);
David Neto22f144c2017-06-12 14:26:21 -04005621}
5622
5623void SPIRVProducerPass::PrintResID(SPIRVInstruction *Inst) {
5624 out << "%" << Inst->getResultID();
5625}
5626
5627void SPIRVProducerPass::PrintOpcode(SPIRVInstruction *Inst) {
5628 spv::Op Opcode = static_cast<spv::Op>(Inst->getOpcode());
5629 out << "\t" << spv::getOpName(Opcode);
5630}
5631
5632void SPIRVProducerPass::PrintOperand(SPIRVOperand *Op) {
5633 SPIRVOperandType OpTy = Op->getType();
5634 switch (OpTy) {
5635 default: {
5636 llvm_unreachable("Unsupported SPIRV Operand Type???");
5637 break;
5638 }
5639 case SPIRVOperandType::NUMBERID: {
5640 out << "%" << Op->getNumID();
5641 break;
5642 }
5643 case SPIRVOperandType::LITERAL_STRING: {
5644 out << "\"" << Op->getLiteralStr() << "\"";
5645 break;
5646 }
5647 case SPIRVOperandType::LITERAL_INTEGER: {
5648 // TODO: Handle LiteralNum carefully.
Kévin Petite7d0cce2018-10-31 12:38:56 +00005649 auto Words = Op->getLiteralNum();
5650 auto NumWords = Words.size();
5651
5652 if (NumWords == 1) {
5653 out << Words[0];
5654 } else if (NumWords == 2) {
5655 uint64_t Val = (static_cast<uint64_t>(Words[1]) << 32) | Words[0];
5656 out << Val;
5657 } else {
5658 llvm_unreachable("Handle printing arbitrary precision integer literals.");
David Neto22f144c2017-06-12 14:26:21 -04005659 }
5660 break;
5661 }
5662 case SPIRVOperandType::LITERAL_FLOAT: {
5663 // TODO: Handle LiteralNum carefully.
5664 for (auto Word : Op->getLiteralNum()) {
5665 APFloat APF = APFloat(APFloat::IEEEsingle(), APInt(32, Word));
5666 SmallString<8> Str;
5667 APF.toString(Str, 6, 2);
5668 out << Str;
5669 }
5670 break;
5671 }
5672 }
5673}
5674
5675void SPIRVProducerPass::PrintCapability(SPIRVOperand *Op) {
5676 spv::Capability Cap = static_cast<spv::Capability>(Op->getNumID());
5677 out << spv::getCapabilityName(Cap);
5678}
5679
5680void SPIRVProducerPass::PrintExtInst(SPIRVOperand *Op) {
5681 auto LiteralNum = Op->getLiteralNum();
5682 glsl::ExtInst Ext = static_cast<glsl::ExtInst>(LiteralNum[0]);
5683 out << glsl::getExtInstName(Ext);
5684}
5685
5686void SPIRVProducerPass::PrintAddrModel(SPIRVOperand *Op) {
5687 spv::AddressingModel AddrModel =
5688 static_cast<spv::AddressingModel>(Op->getNumID());
5689 out << spv::getAddressingModelName(AddrModel);
5690}
5691
5692void SPIRVProducerPass::PrintMemModel(SPIRVOperand *Op) {
5693 spv::MemoryModel MemModel = static_cast<spv::MemoryModel>(Op->getNumID());
5694 out << spv::getMemoryModelName(MemModel);
5695}
5696
5697void SPIRVProducerPass::PrintExecModel(SPIRVOperand *Op) {
5698 spv::ExecutionModel ExecModel =
5699 static_cast<spv::ExecutionModel>(Op->getNumID());
5700 out << spv::getExecutionModelName(ExecModel);
5701}
5702
5703void SPIRVProducerPass::PrintExecMode(SPIRVOperand *Op) {
5704 spv::ExecutionMode ExecMode = static_cast<spv::ExecutionMode>(Op->getNumID());
5705 out << spv::getExecutionModeName(ExecMode);
5706}
5707
5708void SPIRVProducerPass::PrintSourceLanguage(SPIRVOperand *Op) {
alan-bakerb6b09dc2018-11-08 16:59:28 -05005709 spv::SourceLanguage SourceLang =
5710 static_cast<spv::SourceLanguage>(Op->getNumID());
David Neto22f144c2017-06-12 14:26:21 -04005711 out << spv::getSourceLanguageName(SourceLang);
5712}
5713
5714void SPIRVProducerPass::PrintFuncCtrl(SPIRVOperand *Op) {
5715 spv::FunctionControlMask FuncCtrl =
5716 static_cast<spv::FunctionControlMask>(Op->getNumID());
5717 out << spv::getFunctionControlName(FuncCtrl);
5718}
5719
5720void SPIRVProducerPass::PrintStorageClass(SPIRVOperand *Op) {
5721 spv::StorageClass StClass = static_cast<spv::StorageClass>(Op->getNumID());
5722 out << getStorageClassName(StClass);
5723}
5724
5725void SPIRVProducerPass::PrintDecoration(SPIRVOperand *Op) {
5726 spv::Decoration Deco = static_cast<spv::Decoration>(Op->getNumID());
5727 out << getDecorationName(Deco);
5728}
5729
5730void SPIRVProducerPass::PrintBuiltIn(SPIRVOperand *Op) {
5731 spv::BuiltIn BIn = static_cast<spv::BuiltIn>(Op->getNumID());
5732 out << getBuiltInName(BIn);
5733}
5734
5735void SPIRVProducerPass::PrintSelectionControl(SPIRVOperand *Op) {
5736 spv::SelectionControlMask BIn =
5737 static_cast<spv::SelectionControlMask>(Op->getNumID());
5738 out << getSelectionControlName(BIn);
5739}
5740
5741void SPIRVProducerPass::PrintLoopControl(SPIRVOperand *Op) {
5742 spv::LoopControlMask BIn = static_cast<spv::LoopControlMask>(Op->getNumID());
5743 out << getLoopControlName(BIn);
5744}
5745
5746void SPIRVProducerPass::PrintDimensionality(SPIRVOperand *Op) {
5747 spv::Dim DIM = static_cast<spv::Dim>(Op->getNumID());
5748 out << getDimName(DIM);
5749}
5750
5751void SPIRVProducerPass::PrintImageFormat(SPIRVOperand *Op) {
5752 spv::ImageFormat Format = static_cast<spv::ImageFormat>(Op->getNumID());
5753 out << getImageFormatName(Format);
5754}
5755
5756void SPIRVProducerPass::PrintMemoryAccess(SPIRVOperand *Op) {
5757 out << spv::getMemoryAccessName(
5758 static_cast<spv::MemoryAccessMask>(Op->getNumID()));
5759}
5760
5761void SPIRVProducerPass::PrintImageOperandsType(SPIRVOperand *Op) {
5762 auto LiteralNum = Op->getLiteralNum();
5763 spv::ImageOperandsMask Type =
5764 static_cast<spv::ImageOperandsMask>(LiteralNum[0]);
5765 out << getImageOperandsName(Type);
5766}
5767
5768void SPIRVProducerPass::WriteSPIRVAssembly() {
5769 SPIRVInstructionList &SPIRVInstList = getSPIRVInstList();
5770
5771 for (auto Inst : SPIRVInstList) {
5772 SPIRVOperandList Ops = Inst->getOperands();
5773 spv::Op Opcode = static_cast<spv::Op>(Inst->getOpcode());
5774
5775 switch (Opcode) {
5776 default: {
5777 llvm_unreachable("Unsupported SPIRV instruction");
5778 break;
5779 }
5780 case spv::OpCapability: {
5781 // Ops[0] = Capability
5782 PrintOpcode(Inst);
5783 out << " ";
5784 PrintCapability(Ops[0]);
5785 out << "\n";
5786 break;
5787 }
5788 case spv::OpMemoryModel: {
5789 // Ops[0] = Addressing Model
5790 // Ops[1] = Memory Model
5791 PrintOpcode(Inst);
5792 out << " ";
5793 PrintAddrModel(Ops[0]);
5794 out << " ";
5795 PrintMemModel(Ops[1]);
5796 out << "\n";
5797 break;
5798 }
5799 case spv::OpEntryPoint: {
5800 // Ops[0] = Execution Model
5801 // Ops[1] = EntryPoint ID
5802 // Ops[2] = Name (Literal String)
5803 // Ops[3] ... Ops[n] = Interface ID
5804 PrintOpcode(Inst);
5805 out << " ";
5806 PrintExecModel(Ops[0]);
5807 for (uint32_t i = 1; i < Ops.size(); i++) {
5808 out << " ";
5809 PrintOperand(Ops[i]);
5810 }
5811 out << "\n";
5812 break;
5813 }
5814 case spv::OpExecutionMode: {
5815 // Ops[0] = Entry Point ID
5816 // Ops[1] = Execution Mode
5817 // Ops[2] ... Ops[n] = Optional literals according to Execution Mode
5818 PrintOpcode(Inst);
5819 out << " ";
5820 PrintOperand(Ops[0]);
5821 out << " ";
5822 PrintExecMode(Ops[1]);
5823 for (uint32_t i = 2; i < Ops.size(); i++) {
5824 out << " ";
5825 PrintOperand(Ops[i]);
5826 }
5827 out << "\n";
5828 break;
5829 }
5830 case spv::OpSource: {
5831 // Ops[0] = SourceLanguage ID
5832 // Ops[1] = Version (LiteralNum)
5833 PrintOpcode(Inst);
5834 out << " ";
5835 PrintSourceLanguage(Ops[0]);
5836 out << " ";
5837 PrintOperand(Ops[1]);
5838 out << "\n";
5839 break;
5840 }
5841 case spv::OpDecorate: {
5842 // Ops[0] = Target ID
5843 // Ops[1] = Decoration (Block or BufferBlock)
5844 // Ops[2] ... Ops[n] = Optional literals according to Decoration
5845 PrintOpcode(Inst);
5846 out << " ";
5847 PrintOperand(Ops[0]);
5848 out << " ";
5849 PrintDecoration(Ops[1]);
5850 // Handle BuiltIn OpDecorate specially.
5851 if (Ops[1]->getNumID() == spv::DecorationBuiltIn) {
5852 out << " ";
5853 PrintBuiltIn(Ops[2]);
5854 } else {
5855 for (uint32_t i = 2; i < Ops.size(); i++) {
5856 out << " ";
5857 PrintOperand(Ops[i]);
5858 }
5859 }
5860 out << "\n";
5861 break;
5862 }
5863 case spv::OpMemberDecorate: {
5864 // Ops[0] = Structure Type ID
5865 // Ops[1] = Member Index(Literal Number)
5866 // Ops[2] = Decoration
5867 // Ops[3] ... Ops[n] = Optional literals according to Decoration
5868 PrintOpcode(Inst);
5869 out << " ";
5870 PrintOperand(Ops[0]);
5871 out << " ";
5872 PrintOperand(Ops[1]);
5873 out << " ";
5874 PrintDecoration(Ops[2]);
5875 for (uint32_t i = 3; i < Ops.size(); i++) {
5876 out << " ";
5877 PrintOperand(Ops[i]);
5878 }
5879 out << "\n";
5880 break;
5881 }
5882 case spv::OpTypePointer: {
5883 // Ops[0] = Storage Class
5884 // Ops[1] = Element Type ID
5885 PrintResID(Inst);
5886 out << " = ";
5887 PrintOpcode(Inst);
5888 out << " ";
5889 PrintStorageClass(Ops[0]);
5890 out << " ";
5891 PrintOperand(Ops[1]);
5892 out << "\n";
5893 break;
5894 }
5895 case spv::OpTypeImage: {
5896 // Ops[0] = Sampled Type ID
5897 // Ops[1] = Dim ID
5898 // Ops[2] = Depth (Literal Number)
5899 // Ops[3] = Arrayed (Literal Number)
5900 // Ops[4] = MS (Literal Number)
5901 // Ops[5] = Sampled (Literal Number)
5902 // Ops[6] = Image Format ID
5903 PrintResID(Inst);
5904 out << " = ";
5905 PrintOpcode(Inst);
5906 out << " ";
5907 PrintOperand(Ops[0]);
5908 out << " ";
5909 PrintDimensionality(Ops[1]);
5910 out << " ";
5911 PrintOperand(Ops[2]);
5912 out << " ";
5913 PrintOperand(Ops[3]);
5914 out << " ";
5915 PrintOperand(Ops[4]);
5916 out << " ";
5917 PrintOperand(Ops[5]);
5918 out << " ";
5919 PrintImageFormat(Ops[6]);
5920 out << "\n";
5921 break;
5922 }
5923 case spv::OpFunction: {
5924 // Ops[0] : Result Type ID
5925 // Ops[1] : Function Control
5926 // Ops[2] : Function Type ID
5927 PrintResID(Inst);
5928 out << " = ";
5929 PrintOpcode(Inst);
5930 out << " ";
5931 PrintOperand(Ops[0]);
5932 out << " ";
5933 PrintFuncCtrl(Ops[1]);
5934 out << " ";
5935 PrintOperand(Ops[2]);
5936 out << "\n";
5937 break;
5938 }
5939 case spv::OpSelectionMerge: {
5940 // Ops[0] = Merge Block ID
5941 // Ops[1] = Selection Control
5942 PrintOpcode(Inst);
5943 out << " ";
5944 PrintOperand(Ops[0]);
5945 out << " ";
5946 PrintSelectionControl(Ops[1]);
5947 out << "\n";
5948 break;
5949 }
5950 case spv::OpLoopMerge: {
5951 // Ops[0] = Merge Block ID
5952 // Ops[1] = Continue Target ID
5953 // Ops[2] = Selection Control
5954 PrintOpcode(Inst);
5955 out << " ";
5956 PrintOperand(Ops[0]);
5957 out << " ";
5958 PrintOperand(Ops[1]);
5959 out << " ";
5960 PrintLoopControl(Ops[2]);
5961 out << "\n";
5962 break;
5963 }
5964 case spv::OpImageSampleExplicitLod: {
5965 // Ops[0] = Result Type ID
5966 // Ops[1] = Sampled Image ID
5967 // Ops[2] = Coordinate ID
5968 // Ops[3] = Image Operands Type ID
5969 // Ops[4] ... Ops[n] = Operands ID
5970 PrintResID(Inst);
5971 out << " = ";
5972 PrintOpcode(Inst);
5973 for (uint32_t i = 0; i < 3; i++) {
5974 out << " ";
5975 PrintOperand(Ops[i]);
5976 }
5977 out << " ";
5978 PrintImageOperandsType(Ops[3]);
5979 for (uint32_t i = 4; i < Ops.size(); i++) {
5980 out << " ";
5981 PrintOperand(Ops[i]);
5982 }
5983 out << "\n";
5984 break;
5985 }
5986 case spv::OpVariable: {
5987 // Ops[0] : Result Type ID
5988 // Ops[1] : Storage Class
5989 // Ops[2] ... Ops[n] = Initializer IDs
5990 PrintResID(Inst);
5991 out << " = ";
5992 PrintOpcode(Inst);
5993 out << " ";
5994 PrintOperand(Ops[0]);
5995 out << " ";
5996 PrintStorageClass(Ops[1]);
5997 for (uint32_t i = 2; i < Ops.size(); i++) {
5998 out << " ";
5999 PrintOperand(Ops[i]);
6000 }
6001 out << "\n";
6002 break;
6003 }
6004 case spv::OpExtInst: {
6005 // Ops[0] = Result Type ID
6006 // Ops[1] = Set ID (OpExtInstImport ID)
6007 // Ops[2] = Instruction Number (Literal Number)
6008 // Ops[3] ... Ops[n] = Operand 1, ... , Operand n
6009 PrintResID(Inst);
6010 out << " = ";
6011 PrintOpcode(Inst);
6012 out << " ";
6013 PrintOperand(Ops[0]);
6014 out << " ";
6015 PrintOperand(Ops[1]);
6016 out << " ";
6017 PrintExtInst(Ops[2]);
6018 for (uint32_t i = 3; i < Ops.size(); i++) {
6019 out << " ";
6020 PrintOperand(Ops[i]);
6021 }
6022 out << "\n";
6023 break;
6024 }
6025 case spv::OpCopyMemory: {
6026 // Ops[0] = Addressing Model
6027 // Ops[1] = Memory Model
6028 PrintOpcode(Inst);
6029 out << " ";
6030 PrintOperand(Ops[0]);
6031 out << " ";
6032 PrintOperand(Ops[1]);
6033 out << " ";
6034 PrintMemoryAccess(Ops[2]);
6035 out << " ";
6036 PrintOperand(Ops[3]);
6037 out << "\n";
6038 break;
6039 }
6040 case spv::OpExtension:
6041 case spv::OpControlBarrier:
6042 case spv::OpMemoryBarrier:
6043 case spv::OpBranch:
6044 case spv::OpBranchConditional:
6045 case spv::OpStore:
6046 case spv::OpImageWrite:
6047 case spv::OpReturnValue:
6048 case spv::OpReturn:
6049 case spv::OpFunctionEnd: {
6050 PrintOpcode(Inst);
6051 for (uint32_t i = 0; i < Ops.size(); i++) {
6052 out << " ";
6053 PrintOperand(Ops[i]);
6054 }
6055 out << "\n";
6056 break;
6057 }
6058 case spv::OpExtInstImport:
6059 case spv::OpTypeRuntimeArray:
6060 case spv::OpTypeStruct:
6061 case spv::OpTypeSampler:
6062 case spv::OpTypeSampledImage:
6063 case spv::OpTypeInt:
6064 case spv::OpTypeFloat:
6065 case spv::OpTypeArray:
6066 case spv::OpTypeVector:
6067 case spv::OpTypeBool:
6068 case spv::OpTypeVoid:
6069 case spv::OpTypeFunction:
6070 case spv::OpFunctionParameter:
6071 case spv::OpLabel:
6072 case spv::OpPhi:
6073 case spv::OpLoad:
6074 case spv::OpSelect:
6075 case spv::OpAccessChain:
6076 case spv::OpPtrAccessChain:
6077 case spv::OpInBoundsAccessChain:
6078 case spv::OpUConvert:
6079 case spv::OpSConvert:
6080 case spv::OpConvertFToU:
6081 case spv::OpConvertFToS:
6082 case spv::OpConvertUToF:
6083 case spv::OpConvertSToF:
6084 case spv::OpFConvert:
6085 case spv::OpConvertPtrToU:
6086 case spv::OpConvertUToPtr:
6087 case spv::OpBitcast:
6088 case spv::OpIAdd:
6089 case spv::OpFAdd:
6090 case spv::OpISub:
6091 case spv::OpFSub:
6092 case spv::OpIMul:
6093 case spv::OpFMul:
6094 case spv::OpUDiv:
6095 case spv::OpSDiv:
6096 case spv::OpFDiv:
6097 case spv::OpUMod:
6098 case spv::OpSRem:
6099 case spv::OpFRem:
6100 case spv::OpBitwiseOr:
6101 case spv::OpBitwiseXor:
6102 case spv::OpBitwiseAnd:
David Netoa394f392017-08-26 20:45:29 -04006103 case spv::OpNot:
David Neto22f144c2017-06-12 14:26:21 -04006104 case spv::OpShiftLeftLogical:
6105 case spv::OpShiftRightLogical:
6106 case spv::OpShiftRightArithmetic:
6107 case spv::OpBitCount:
David Netoab03f432017-11-03 17:00:44 -04006108 case spv::OpCompositeConstruct:
David Neto22f144c2017-06-12 14:26:21 -04006109 case spv::OpCompositeExtract:
6110 case spv::OpVectorExtractDynamic:
6111 case spv::OpCompositeInsert:
David Neto0a2f98d2017-09-15 19:38:40 -04006112 case spv::OpCopyObject:
David Neto22f144c2017-06-12 14:26:21 -04006113 case spv::OpVectorInsertDynamic:
6114 case spv::OpVectorShuffle:
6115 case spv::OpIEqual:
6116 case spv::OpINotEqual:
6117 case spv::OpUGreaterThan:
6118 case spv::OpUGreaterThanEqual:
6119 case spv::OpULessThan:
6120 case spv::OpULessThanEqual:
6121 case spv::OpSGreaterThan:
6122 case spv::OpSGreaterThanEqual:
6123 case spv::OpSLessThan:
6124 case spv::OpSLessThanEqual:
6125 case spv::OpFOrdEqual:
6126 case spv::OpFOrdGreaterThan:
6127 case spv::OpFOrdGreaterThanEqual:
6128 case spv::OpFOrdLessThan:
6129 case spv::OpFOrdLessThanEqual:
6130 case spv::OpFOrdNotEqual:
6131 case spv::OpFUnordEqual:
6132 case spv::OpFUnordGreaterThan:
6133 case spv::OpFUnordGreaterThanEqual:
6134 case spv::OpFUnordLessThan:
6135 case spv::OpFUnordLessThanEqual:
6136 case spv::OpFUnordNotEqual:
6137 case spv::OpSampledImage:
6138 case spv::OpFunctionCall:
6139 case spv::OpConstantTrue:
6140 case spv::OpConstantFalse:
6141 case spv::OpConstant:
6142 case spv::OpSpecConstant:
6143 case spv::OpConstantComposite:
6144 case spv::OpSpecConstantComposite:
6145 case spv::OpConstantNull:
6146 case spv::OpLogicalOr:
6147 case spv::OpLogicalAnd:
6148 case spv::OpLogicalNot:
6149 case spv::OpLogicalNotEqual:
6150 case spv::OpUndef:
6151 case spv::OpIsInf:
6152 case spv::OpIsNan:
6153 case spv::OpAny:
6154 case spv::OpAll:
David Neto5c22a252018-03-15 16:07:41 -04006155 case spv::OpImageQuerySize:
David Neto22f144c2017-06-12 14:26:21 -04006156 case spv::OpAtomicIAdd:
6157 case spv::OpAtomicISub:
6158 case spv::OpAtomicExchange:
6159 case spv::OpAtomicIIncrement:
6160 case spv::OpAtomicIDecrement:
6161 case spv::OpAtomicCompareExchange:
6162 case spv::OpAtomicUMin:
6163 case spv::OpAtomicSMin:
6164 case spv::OpAtomicUMax:
6165 case spv::OpAtomicSMax:
6166 case spv::OpAtomicAnd:
6167 case spv::OpAtomicOr:
6168 case spv::OpAtomicXor:
6169 case spv::OpDot: {
6170 PrintResID(Inst);
6171 out << " = ";
6172 PrintOpcode(Inst);
6173 for (uint32_t i = 0; i < Ops.size(); i++) {
6174 out << " ";
6175 PrintOperand(Ops[i]);
6176 }
6177 out << "\n";
6178 break;
6179 }
6180 }
6181 }
6182}
6183
6184void SPIRVProducerPass::WriteOneWord(uint32_t Word) {
David Neto0676e6f2017-07-11 18:47:44 -04006185 binaryOut->write(reinterpret_cast<const char *>(&Word), sizeof(uint32_t));
David Neto22f144c2017-06-12 14:26:21 -04006186}
6187
6188void SPIRVProducerPass::WriteResultID(SPIRVInstruction *Inst) {
6189 WriteOneWord(Inst->getResultID());
6190}
6191
6192void SPIRVProducerPass::WriteWordCountAndOpcode(SPIRVInstruction *Inst) {
6193 // High 16 bit : Word Count
6194 // Low 16 bit : Opcode
6195 uint32_t Word = Inst->getOpcode();
David Netoee2660d2018-06-28 16:31:29 -04006196 const uint32_t count = Inst->getWordCount();
6197 if (count > 65535) {
6198 errs() << "Word count limit of 65535 exceeded: " << count << "\n";
6199 llvm_unreachable("Word count too high");
6200 }
David Neto22f144c2017-06-12 14:26:21 -04006201 Word |= Inst->getWordCount() << 16;
6202 WriteOneWord(Word);
6203}
6204
6205void SPIRVProducerPass::WriteOperand(SPIRVOperand *Op) {
6206 SPIRVOperandType OpTy = Op->getType();
6207 switch (OpTy) {
6208 default: {
6209 llvm_unreachable("Unsupported SPIRV Operand Type???");
6210 break;
6211 }
6212 case SPIRVOperandType::NUMBERID: {
6213 WriteOneWord(Op->getNumID());
6214 break;
6215 }
6216 case SPIRVOperandType::LITERAL_STRING: {
6217 std::string Str = Op->getLiteralStr();
6218 const char *Data = Str.c_str();
6219 size_t WordSize = Str.size() / 4;
6220 for (unsigned Idx = 0; Idx < WordSize; Idx++) {
6221 WriteOneWord(*reinterpret_cast<const uint32_t *>(&Data[4 * Idx]));
6222 }
6223
6224 uint32_t Remainder = Str.size() % 4;
6225 uint32_t LastWord = 0;
6226 if (Remainder) {
6227 for (unsigned Idx = 0; Idx < Remainder; Idx++) {
6228 LastWord |= Data[4 * WordSize + Idx] << 8 * Idx;
6229 }
6230 }
6231
6232 WriteOneWord(LastWord);
6233 break;
6234 }
6235 case SPIRVOperandType::LITERAL_INTEGER:
6236 case SPIRVOperandType::LITERAL_FLOAT: {
6237 auto LiteralNum = Op->getLiteralNum();
6238 // TODO: Handle LiteranNum carefully.
6239 for (auto Word : LiteralNum) {
6240 WriteOneWord(Word);
6241 }
6242 break;
6243 }
6244 }
6245}
6246
6247void SPIRVProducerPass::WriteSPIRVBinary() {
6248 SPIRVInstructionList &SPIRVInstList = getSPIRVInstList();
6249
6250 for (auto Inst : SPIRVInstList) {
David Netoc6f3ab22018-04-06 18:02:31 -04006251 SPIRVOperandList Ops{Inst->getOperands()};
David Neto22f144c2017-06-12 14:26:21 -04006252 spv::Op Opcode = static_cast<spv::Op>(Inst->getOpcode());
6253
6254 switch (Opcode) {
6255 default: {
David Neto5c22a252018-03-15 16:07:41 -04006256 errs() << "Unsupported SPIR-V instruction opcode " << int(Opcode) << "\n";
David Neto22f144c2017-06-12 14:26:21 -04006257 llvm_unreachable("Unsupported SPIRV instruction");
6258 break;
6259 }
6260 case spv::OpCapability:
6261 case spv::OpExtension:
6262 case spv::OpMemoryModel:
6263 case spv::OpEntryPoint:
6264 case spv::OpExecutionMode:
6265 case spv::OpSource:
6266 case spv::OpDecorate:
6267 case spv::OpMemberDecorate:
6268 case spv::OpBranch:
6269 case spv::OpBranchConditional:
6270 case spv::OpSelectionMerge:
6271 case spv::OpLoopMerge:
6272 case spv::OpStore:
6273 case spv::OpImageWrite:
6274 case spv::OpReturnValue:
6275 case spv::OpControlBarrier:
6276 case spv::OpMemoryBarrier:
6277 case spv::OpReturn:
6278 case spv::OpFunctionEnd:
6279 case spv::OpCopyMemory: {
6280 WriteWordCountAndOpcode(Inst);
6281 for (uint32_t i = 0; i < Ops.size(); i++) {
6282 WriteOperand(Ops[i]);
6283 }
6284 break;
6285 }
6286 case spv::OpTypeBool:
6287 case spv::OpTypeVoid:
6288 case spv::OpTypeSampler:
6289 case spv::OpLabel:
6290 case spv::OpExtInstImport:
6291 case spv::OpTypePointer:
6292 case spv::OpTypeRuntimeArray:
6293 case spv::OpTypeStruct:
6294 case spv::OpTypeImage:
6295 case spv::OpTypeSampledImage:
6296 case spv::OpTypeInt:
6297 case spv::OpTypeFloat:
6298 case spv::OpTypeArray:
6299 case spv::OpTypeVector:
6300 case spv::OpTypeFunction: {
6301 WriteWordCountAndOpcode(Inst);
6302 WriteResultID(Inst);
6303 for (uint32_t i = 0; i < Ops.size(); i++) {
6304 WriteOperand(Ops[i]);
6305 }
6306 break;
6307 }
6308 case spv::OpFunction:
6309 case spv::OpFunctionParameter:
6310 case spv::OpAccessChain:
6311 case spv::OpPtrAccessChain:
6312 case spv::OpInBoundsAccessChain:
6313 case spv::OpUConvert:
6314 case spv::OpSConvert:
6315 case spv::OpConvertFToU:
6316 case spv::OpConvertFToS:
6317 case spv::OpConvertUToF:
6318 case spv::OpConvertSToF:
6319 case spv::OpFConvert:
6320 case spv::OpConvertPtrToU:
6321 case spv::OpConvertUToPtr:
6322 case spv::OpBitcast:
6323 case spv::OpIAdd:
6324 case spv::OpFAdd:
6325 case spv::OpISub:
6326 case spv::OpFSub:
6327 case spv::OpIMul:
6328 case spv::OpFMul:
6329 case spv::OpUDiv:
6330 case spv::OpSDiv:
6331 case spv::OpFDiv:
6332 case spv::OpUMod:
6333 case spv::OpSRem:
6334 case spv::OpFRem:
6335 case spv::OpBitwiseOr:
6336 case spv::OpBitwiseXor:
6337 case spv::OpBitwiseAnd:
David Netoa394f392017-08-26 20:45:29 -04006338 case spv::OpNot:
David Neto22f144c2017-06-12 14:26:21 -04006339 case spv::OpShiftLeftLogical:
6340 case spv::OpShiftRightLogical:
6341 case spv::OpShiftRightArithmetic:
6342 case spv::OpBitCount:
David Netoab03f432017-11-03 17:00:44 -04006343 case spv::OpCompositeConstruct:
David Neto22f144c2017-06-12 14:26:21 -04006344 case spv::OpCompositeExtract:
6345 case spv::OpVectorExtractDynamic:
6346 case spv::OpCompositeInsert:
David Neto0a2f98d2017-09-15 19:38:40 -04006347 case spv::OpCopyObject:
David Neto22f144c2017-06-12 14:26:21 -04006348 case spv::OpVectorInsertDynamic:
6349 case spv::OpVectorShuffle:
6350 case spv::OpIEqual:
6351 case spv::OpINotEqual:
6352 case spv::OpUGreaterThan:
6353 case spv::OpUGreaterThanEqual:
6354 case spv::OpULessThan:
6355 case spv::OpULessThanEqual:
6356 case spv::OpSGreaterThan:
6357 case spv::OpSGreaterThanEqual:
6358 case spv::OpSLessThan:
6359 case spv::OpSLessThanEqual:
6360 case spv::OpFOrdEqual:
6361 case spv::OpFOrdGreaterThan:
6362 case spv::OpFOrdGreaterThanEqual:
6363 case spv::OpFOrdLessThan:
6364 case spv::OpFOrdLessThanEqual:
6365 case spv::OpFOrdNotEqual:
6366 case spv::OpFUnordEqual:
6367 case spv::OpFUnordGreaterThan:
6368 case spv::OpFUnordGreaterThanEqual:
6369 case spv::OpFUnordLessThan:
6370 case spv::OpFUnordLessThanEqual:
6371 case spv::OpFUnordNotEqual:
6372 case spv::OpExtInst:
6373 case spv::OpIsInf:
6374 case spv::OpIsNan:
6375 case spv::OpAny:
6376 case spv::OpAll:
6377 case spv::OpUndef:
6378 case spv::OpConstantNull:
6379 case spv::OpLogicalOr:
6380 case spv::OpLogicalAnd:
6381 case spv::OpLogicalNot:
6382 case spv::OpLogicalNotEqual:
6383 case spv::OpConstantComposite:
6384 case spv::OpSpecConstantComposite:
6385 case spv::OpConstantTrue:
6386 case spv::OpConstantFalse:
6387 case spv::OpConstant:
6388 case spv::OpSpecConstant:
6389 case spv::OpVariable:
6390 case spv::OpFunctionCall:
6391 case spv::OpSampledImage:
6392 case spv::OpImageSampleExplicitLod:
David Neto5c22a252018-03-15 16:07:41 -04006393 case spv::OpImageQuerySize:
David Neto22f144c2017-06-12 14:26:21 -04006394 case spv::OpSelect:
6395 case spv::OpPhi:
6396 case spv::OpLoad:
6397 case spv::OpAtomicIAdd:
6398 case spv::OpAtomicISub:
6399 case spv::OpAtomicExchange:
6400 case spv::OpAtomicIIncrement:
6401 case spv::OpAtomicIDecrement:
6402 case spv::OpAtomicCompareExchange:
6403 case spv::OpAtomicUMin:
6404 case spv::OpAtomicSMin:
6405 case spv::OpAtomicUMax:
6406 case spv::OpAtomicSMax:
6407 case spv::OpAtomicAnd:
6408 case spv::OpAtomicOr:
6409 case spv::OpAtomicXor:
6410 case spv::OpDot: {
6411 WriteWordCountAndOpcode(Inst);
6412 WriteOperand(Ops[0]);
6413 WriteResultID(Inst);
6414 for (uint32_t i = 1; i < Ops.size(); i++) {
6415 WriteOperand(Ops[i]);
6416 }
6417 break;
6418 }
6419 }
6420 }
6421}
Alan Baker9bf93fb2018-08-28 16:59:26 -04006422
alan-bakerb6b09dc2018-11-08 16:59:28 -05006423bool SPIRVProducerPass::IsTypeNullable(const Type *type) const {
Alan Baker9bf93fb2018-08-28 16:59:26 -04006424 switch (type->getTypeID()) {
alan-bakerb6b09dc2018-11-08 16:59:28 -05006425 case Type::HalfTyID:
6426 case Type::FloatTyID:
6427 case Type::DoubleTyID:
6428 case Type::IntegerTyID:
6429 case Type::VectorTyID:
6430 return true;
6431 case Type::PointerTyID: {
6432 const PointerType *pointer_type = cast<PointerType>(type);
6433 if (pointer_type->getPointerAddressSpace() !=
6434 AddressSpace::UniformConstant) {
6435 auto pointee_type = pointer_type->getPointerElementType();
6436 if (pointee_type->isStructTy() &&
6437 cast<StructType>(pointee_type)->isOpaque()) {
6438 // Images and samplers are not nullable.
6439 return false;
Alan Baker9bf93fb2018-08-28 16:59:26 -04006440 }
Alan Baker9bf93fb2018-08-28 16:59:26 -04006441 }
alan-bakerb6b09dc2018-11-08 16:59:28 -05006442 return true;
6443 }
6444 case Type::ArrayTyID:
6445 return IsTypeNullable(cast<CompositeType>(type)->getTypeAtIndex(0u));
6446 case Type::StructTyID: {
6447 const StructType *struct_type = cast<StructType>(type);
6448 // Images and samplers are not nullable.
6449 if (struct_type->isOpaque())
Alan Baker9bf93fb2018-08-28 16:59:26 -04006450 return false;
alan-bakerb6b09dc2018-11-08 16:59:28 -05006451 for (const auto element : struct_type->elements()) {
6452 if (!IsTypeNullable(element))
6453 return false;
6454 }
6455 return true;
6456 }
6457 default:
6458 return false;
Alan Baker9bf93fb2018-08-28 16:59:26 -04006459 }
6460}
Alan Bakerfcda9482018-10-02 17:09:59 -04006461
6462void SPIRVProducerPass::PopulateUBOTypeMaps(Module &module) {
6463 if (auto *offsets_md =
6464 module.getNamedMetadata(clspv::RemappedTypeOffsetMetadataName())) {
6465 // Metdata is stored as key-value pair operands. The first element of each
6466 // operand is the type and the second is a vector of offsets.
6467 for (const auto *operand : offsets_md->operands()) {
6468 const auto *pair = cast<MDTuple>(operand);
6469 auto *type =
6470 cast<ConstantAsMetadata>(pair->getOperand(0))->getValue()->getType();
6471 const auto *offset_vector = cast<MDTuple>(pair->getOperand(1));
6472 std::vector<uint32_t> offsets;
6473 for (const Metadata *offset_md : offset_vector->operands()) {
6474 const auto *constant_md = cast<ConstantAsMetadata>(offset_md);
alan-bakerb6b09dc2018-11-08 16:59:28 -05006475 offsets.push_back(static_cast<uint32_t>(
6476 cast<ConstantInt>(constant_md->getValue())->getZExtValue()));
Alan Bakerfcda9482018-10-02 17:09:59 -04006477 }
6478 RemappedUBOTypeOffsets.insert(std::make_pair(type, offsets));
6479 }
6480 }
6481
6482 if (auto *sizes_md =
6483 module.getNamedMetadata(clspv::RemappedTypeSizesMetadataName())) {
6484 // Metadata is stored as key-value pair operands. The first element of each
6485 // operand is the type and the second is a triple of sizes: type size in
6486 // bits, store size and alloc size.
6487 for (const auto *operand : sizes_md->operands()) {
6488 const auto *pair = cast<MDTuple>(operand);
6489 auto *type =
6490 cast<ConstantAsMetadata>(pair->getOperand(0))->getValue()->getType();
6491 const auto *size_triple = cast<MDTuple>(pair->getOperand(1));
6492 uint64_t type_size_in_bits =
6493 cast<ConstantInt>(
6494 cast<ConstantAsMetadata>(size_triple->getOperand(0))->getValue())
6495 ->getZExtValue();
6496 uint64_t type_store_size =
6497 cast<ConstantInt>(
6498 cast<ConstantAsMetadata>(size_triple->getOperand(1))->getValue())
6499 ->getZExtValue();
6500 uint64_t type_alloc_size =
6501 cast<ConstantInt>(
6502 cast<ConstantAsMetadata>(size_triple->getOperand(2))->getValue())
6503 ->getZExtValue();
6504 RemappedUBOTypeSizes.insert(std::make_pair(
6505 type, std::make_tuple(type_size_in_bits, type_store_size,
6506 type_alloc_size)));
6507 }
6508 }
6509}
6510
6511uint64_t SPIRVProducerPass::GetTypeSizeInBits(Type *type,
6512 const DataLayout &DL) {
6513 auto iter = RemappedUBOTypeSizes.find(type);
6514 if (iter != RemappedUBOTypeSizes.end()) {
6515 return std::get<0>(iter->second);
6516 }
6517
6518 return DL.getTypeSizeInBits(type);
6519}
6520
6521uint64_t SPIRVProducerPass::GetTypeStoreSize(Type *type, const DataLayout &DL) {
6522 auto iter = RemappedUBOTypeSizes.find(type);
6523 if (iter != RemappedUBOTypeSizes.end()) {
6524 return std::get<1>(iter->second);
6525 }
6526
6527 return DL.getTypeStoreSize(type);
6528}
6529
6530uint64_t SPIRVProducerPass::GetTypeAllocSize(Type *type, const DataLayout &DL) {
6531 auto iter = RemappedUBOTypeSizes.find(type);
6532 if (iter != RemappedUBOTypeSizes.end()) {
6533 return std::get<2>(iter->second);
6534 }
6535
6536 return DL.getTypeAllocSize(type);
6537}
alan-baker5b86ed72019-02-15 08:26:50 -05006538
6539void SPIRVProducerPass::setVariablePointersCapabilities(unsigned address_space) {
6540 if (GetStorageClass(address_space) == spv::StorageClassStorageBuffer) {
6541 setVariablePointersStorageBuffer(true);
6542 } else {
6543 setVariablePointers(true);
6544 }
6545}
6546
6547Value *SPIRVProducerPass::GetBasePointer(Value* v) {
6548 if (auto *gep = dyn_cast<GetElementPtrInst>(v)) {
6549 return GetBasePointer(gep->getPointerOperand());
6550 }
6551
6552 // Conservatively return |v|.
6553 return v;
6554}
6555
6556bool SPIRVProducerPass::sameResource(Value *lhs, Value *rhs) const {
6557 if (auto *lhs_call = dyn_cast<CallInst>(lhs)) {
6558 if (auto *rhs_call = dyn_cast<CallInst>(rhs)) {
6559 if (lhs_call->getCalledFunction()->getName().startswith(
6560 clspv::ResourceAccessorFunction()) &&
6561 rhs_call->getCalledFunction()->getName().startswith(
6562 clspv::ResourceAccessorFunction())) {
6563 // For resource accessors, match descriptor set and binding.
6564 if (lhs_call->getOperand(0) == rhs_call->getOperand(0) &&
6565 lhs_call->getOperand(1) == rhs_call->getOperand(1))
6566 return true;
6567 } else if (lhs_call->getCalledFunction()->getName().startswith(
6568 clspv::WorkgroupAccessorFunction()) &&
6569 rhs_call->getCalledFunction()->getName().startswith(
6570 clspv::WorkgroupAccessorFunction())) {
6571 // For workgroup resources, match spec id.
6572 if (lhs_call->getOperand(0) == rhs_call->getOperand(0))
6573 return true;
6574 }
6575 }
6576 }
6577
6578 return false;
6579}
6580
6581bool SPIRVProducerPass::selectFromSameObject(Instruction *inst) {
6582 assert(inst->getType()->isPointerTy());
6583 assert(GetStorageClass(inst->getType()->getPointerAddressSpace()) ==
6584 spv::StorageClassStorageBuffer);
6585 const bool hack_undef = clspv::Option::HackUndef();
6586 if (auto *select = dyn_cast<SelectInst>(inst)) {
6587 auto *true_base = GetBasePointer(select->getTrueValue());
6588 auto *false_base = GetBasePointer(select->getFalseValue());
6589
6590 if (true_base == false_base)
6591 return true;
6592
6593 // If either the true or false operand is a null, then we satisfy the same
6594 // object constraint.
6595 if (auto *true_cst = dyn_cast<Constant>(true_base)) {
6596 if (true_cst->isNullValue() || (hack_undef && isa<UndefValue>(true_base)))
6597 return true;
6598 }
6599
6600 if (auto *false_cst = dyn_cast<Constant>(false_base)) {
6601 if (false_cst->isNullValue() ||
6602 (hack_undef && isa<UndefValue>(false_base)))
6603 return true;
6604 }
6605
6606 if (sameResource(true_base, false_base))
6607 return true;
6608 } else if (auto *phi = dyn_cast<PHINode>(inst)) {
6609 Value *value = nullptr;
6610 bool ok = true;
6611 for (unsigned i = 0; ok && i != phi->getNumIncomingValues(); ++i) {
6612 auto *base = GetBasePointer(phi->getIncomingValue(i));
6613 // Null values satisfy the constraint of selecting of selecting from the
6614 // same object.
6615 if (!value) {
6616 if (auto *cst = dyn_cast<Constant>(base)) {
6617 if (!cst->isNullValue() && !(hack_undef && isa<UndefValue>(base)))
6618 value = base;
6619 } else {
6620 value = base;
6621 }
6622 } else if (base != value) {
6623 if (auto *base_cst = dyn_cast<Constant>(base)) {
6624 if (base_cst->isNullValue() || (hack_undef && isa<UndefValue>(base)))
6625 continue;
6626 }
6627
6628 if (sameResource(value, base))
6629 continue;
6630
6631 // Values don't represent the same base.
6632 ok = false;
6633 }
6634 }
6635
6636 return ok;
6637 }
6638
6639 // Conservatively return false.
6640 return false;
6641}
alan-bakere9308012019-03-15 10:25:13 -04006642
6643bool SPIRVProducerPass::CalledWithCoherentResource(Argument &Arg) {
6644 if (!Arg.getType()->isPointerTy() ||
6645 Arg.getType()->getPointerAddressSpace() != clspv::AddressSpace::Global) {
6646 // Only SSBOs need to be annotated as coherent.
6647 return false;
6648 }
6649
6650 DenseSet<Value *> visited;
6651 std::vector<Value *> stack;
6652 for (auto *U : Arg.getParent()->users()) {
6653 if (auto *call = dyn_cast<CallInst>(U)) {
6654 stack.push_back(call->getOperand(Arg.getArgNo()));
6655 }
6656 }
6657
6658 while (!stack.empty()) {
6659 Value *v = stack.back();
6660 stack.pop_back();
6661
6662 if (!visited.insert(v).second)
6663 continue;
6664
6665 auto *resource_call = dyn_cast<CallInst>(v);
6666 if (resource_call &&
6667 resource_call->getCalledFunction()->getName().startswith(
6668 clspv::ResourceAccessorFunction())) {
6669 // If this is a resource accessor function, check if the coherent operand
6670 // is set.
6671 const auto coherent =
6672 unsigned(dyn_cast<ConstantInt>(resource_call->getArgOperand(5))
6673 ->getZExtValue());
6674 if (coherent == 1)
6675 return true;
6676 } else if (auto *arg = dyn_cast<Argument>(v)) {
6677 // If this is a function argument, trace through its callers.
6678 for (auto U : arg->users()) {
6679 if (auto *call = dyn_cast<CallInst>(U)) {
6680 stack.push_back(call->getOperand(arg->getArgNo()));
6681 }
6682 }
6683 } else if (auto *user = dyn_cast<User>(v)) {
6684 // If this is a user, traverse all operands that could lead to resource
6685 // variables.
6686 for (unsigned i = 0; i != user->getNumOperands(); ++i) {
6687 Value *operand = user->getOperand(i);
6688 if (operand->getType()->isPointerTy() &&
6689 operand->getType()->getPointerAddressSpace() ==
6690 clspv::AddressSpace::Global) {
6691 stack.push_back(operand);
6692 }
6693 }
6694 }
6695 }
6696
6697 // No coherent resource variables encountered.
6698 return false;
6699}