instruction.cpp 31 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014
  1. // Copyright (c) 2016 Google Inc.
  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. #include "source/opt/instruction.h"
  15. #include <initializer_list>
  16. #include "NonSemanticVulkanDebugInfo100.h"
  17. #include "OpenCLDebugInfo100.h"
  18. #include "source/disassemble.h"
  19. #include "source/opt/fold.h"
  20. #include "source/opt/ir_context.h"
  21. #include "source/opt/reflect.h"
  22. namespace spvtools {
  23. namespace opt {
  24. namespace {
  25. // Indices used to get particular operands out of instructions using InOperand.
  26. const uint32_t kTypeImageDimIndex = 1;
  27. const uint32_t kLoadBaseIndex = 0;
  28. const uint32_t kPointerTypeStorageClassIndex = 0;
  29. const uint32_t kTypeImageSampledIndex = 5;
  30. // Constants for OpenCL.DebugInfo.100 / NonSemantic.Vulkan.DebugInfo.100
  31. // extension instructions.
  32. const uint32_t kExtInstSetIdInIdx = 0;
  33. const uint32_t kExtInstInstructionInIdx = 1;
  34. const uint32_t kDebugScopeNumWords = 7;
  35. const uint32_t kDebugScopeNumWordsWithoutInlinedAt = 6;
  36. const uint32_t kDebugNoScopeNumWords = 5;
  37. // Number of operands of an OpBranchConditional instruction
  38. // with weights.
  39. const uint32_t kOpBranchConditionalWithWeightsNumOperands = 5;
  40. } // namespace
  41. Instruction::Instruction(IRContext* c)
  42. : utils::IntrusiveNodeBase<Instruction>(),
  43. context_(c),
  44. opcode_(SpvOpNop),
  45. has_type_id_(false),
  46. has_result_id_(false),
  47. unique_id_(c->TakeNextUniqueId()),
  48. dbg_scope_(kNoDebugScope, kNoInlinedAt) {}
  49. Instruction::Instruction(IRContext* c, SpvOp op)
  50. : utils::IntrusiveNodeBase<Instruction>(),
  51. context_(c),
  52. opcode_(op),
  53. has_type_id_(false),
  54. has_result_id_(false),
  55. unique_id_(c->TakeNextUniqueId()),
  56. dbg_scope_(kNoDebugScope, kNoInlinedAt) {}
  57. Instruction::Instruction(IRContext* c, const spv_parsed_instruction_t& inst,
  58. std::vector<Instruction>&& dbg_line)
  59. : utils::IntrusiveNodeBase<Instruction>(),
  60. context_(c),
  61. opcode_(static_cast<SpvOp>(inst.opcode)),
  62. has_type_id_(inst.type_id != 0),
  63. has_result_id_(inst.result_id != 0),
  64. unique_id_(c->TakeNextUniqueId()),
  65. dbg_line_insts_(std::move(dbg_line)),
  66. dbg_scope_(kNoDebugScope, kNoInlinedAt) {
  67. assert((!IsDebugLineInst(opcode_) || dbg_line.empty()) &&
  68. "Op(No)Line attaching to Op(No)Line found");
  69. for (uint32_t i = 0; i < inst.num_operands; ++i) {
  70. const auto& current_payload = inst.operands[i];
  71. std::vector<uint32_t> words(
  72. inst.words + current_payload.offset,
  73. inst.words + current_payload.offset + current_payload.num_words);
  74. operands_.emplace_back(current_payload.type, std::move(words));
  75. }
  76. }
  77. Instruction::Instruction(IRContext* c, const spv_parsed_instruction_t& inst,
  78. const DebugScope& dbg_scope)
  79. : utils::IntrusiveNodeBase<Instruction>(),
  80. context_(c),
  81. opcode_(static_cast<SpvOp>(inst.opcode)),
  82. has_type_id_(inst.type_id != 0),
  83. has_result_id_(inst.result_id != 0),
  84. unique_id_(c->TakeNextUniqueId()),
  85. dbg_scope_(dbg_scope) {
  86. for (uint32_t i = 0; i < inst.num_operands; ++i) {
  87. const auto& current_payload = inst.operands[i];
  88. std::vector<uint32_t> words(
  89. inst.words + current_payload.offset,
  90. inst.words + current_payload.offset + current_payload.num_words);
  91. operands_.emplace_back(current_payload.type, std::move(words));
  92. }
  93. }
  94. Instruction::Instruction(IRContext* c, SpvOp op, uint32_t ty_id,
  95. uint32_t res_id, const OperandList& in_operands)
  96. : utils::IntrusiveNodeBase<Instruction>(),
  97. context_(c),
  98. opcode_(op),
  99. has_type_id_(ty_id != 0),
  100. has_result_id_(res_id != 0),
  101. unique_id_(c->TakeNextUniqueId()),
  102. operands_(),
  103. dbg_scope_(kNoDebugScope, kNoInlinedAt) {
  104. if (has_type_id_) {
  105. operands_.emplace_back(spv_operand_type_t::SPV_OPERAND_TYPE_TYPE_ID,
  106. std::initializer_list<uint32_t>{ty_id});
  107. }
  108. if (has_result_id_) {
  109. operands_.emplace_back(spv_operand_type_t::SPV_OPERAND_TYPE_RESULT_ID,
  110. std::initializer_list<uint32_t>{res_id});
  111. }
  112. operands_.insert(operands_.end(), in_operands.begin(), in_operands.end());
  113. }
  114. Instruction::Instruction(Instruction&& that)
  115. : utils::IntrusiveNodeBase<Instruction>(),
  116. context_(that.context_),
  117. opcode_(that.opcode_),
  118. has_type_id_(that.has_type_id_),
  119. has_result_id_(that.has_result_id_),
  120. unique_id_(that.unique_id_),
  121. operands_(std::move(that.operands_)),
  122. dbg_line_insts_(std::move(that.dbg_line_insts_)),
  123. dbg_scope_(that.dbg_scope_) {
  124. for (auto& i : dbg_line_insts_) {
  125. i.dbg_scope_ = that.dbg_scope_;
  126. }
  127. }
  128. Instruction& Instruction::operator=(Instruction&& that) {
  129. context_ = that.context_;
  130. opcode_ = that.opcode_;
  131. has_type_id_ = that.has_type_id_;
  132. has_result_id_ = that.has_result_id_;
  133. unique_id_ = that.unique_id_;
  134. operands_ = std::move(that.operands_);
  135. dbg_line_insts_ = std::move(that.dbg_line_insts_);
  136. dbg_scope_ = that.dbg_scope_;
  137. return *this;
  138. }
  139. Instruction* Instruction::Clone(IRContext* c) const {
  140. Instruction* clone = new Instruction(c);
  141. clone->opcode_ = opcode_;
  142. clone->has_type_id_ = has_type_id_;
  143. clone->has_result_id_ = has_result_id_;
  144. clone->unique_id_ = c->TakeNextUniqueId();
  145. clone->operands_ = operands_;
  146. clone->dbg_line_insts_ = dbg_line_insts_;
  147. clone->dbg_scope_ = dbg_scope_;
  148. return clone;
  149. }
  150. uint32_t Instruction::GetSingleWordOperand(uint32_t index) const {
  151. const auto& words = GetOperand(index).words;
  152. assert(words.size() == 1 && "expected the operand only taking one word");
  153. return words.front();
  154. }
  155. uint32_t Instruction::NumInOperandWords() const {
  156. uint32_t size = 0;
  157. for (uint32_t i = TypeResultIdCount(); i < operands_.size(); ++i)
  158. size += static_cast<uint32_t>(operands_[i].words.size());
  159. return size;
  160. }
  161. bool Instruction::HasBranchWeights() const {
  162. if (opcode_ == SpvOpBranchConditional &&
  163. NumOperands() == kOpBranchConditionalWithWeightsNumOperands) {
  164. return true;
  165. }
  166. return false;
  167. }
  168. void Instruction::ToBinaryWithoutAttachedDebugInsts(
  169. std::vector<uint32_t>* binary) const {
  170. const uint32_t num_words = 1 + NumOperandWords();
  171. binary->push_back((num_words << 16) | static_cast<uint16_t>(opcode_));
  172. for (const auto& operand : operands_) {
  173. binary->insert(binary->end(), operand.words.begin(), operand.words.end());
  174. }
  175. }
  176. void Instruction::ReplaceOperands(const OperandList& new_operands) {
  177. operands_.clear();
  178. operands_.insert(operands_.begin(), new_operands.begin(), new_operands.end());
  179. }
  180. bool Instruction::IsReadOnlyLoad() const {
  181. if (IsLoad()) {
  182. Instruction* address_def = GetBaseAddress();
  183. if (!address_def) {
  184. return false;
  185. }
  186. if (address_def->opcode() == SpvOpVariable) {
  187. if (address_def->IsReadOnlyPointer()) {
  188. return true;
  189. }
  190. }
  191. if (address_def->opcode() == SpvOpLoad) {
  192. const analysis::Type* address_type =
  193. context()->get_type_mgr()->GetType(address_def->type_id());
  194. if (address_type->AsSampledImage() != nullptr) {
  195. const auto* image_type =
  196. address_type->AsSampledImage()->image_type()->AsImage();
  197. if (image_type->sampled() == 1) {
  198. return true;
  199. }
  200. }
  201. }
  202. }
  203. return false;
  204. }
  205. Instruction* Instruction::GetBaseAddress() const {
  206. uint32_t base = GetSingleWordInOperand(kLoadBaseIndex);
  207. Instruction* base_inst = context()->get_def_use_mgr()->GetDef(base);
  208. bool done = false;
  209. while (!done) {
  210. switch (base_inst->opcode()) {
  211. case SpvOpAccessChain:
  212. case SpvOpInBoundsAccessChain:
  213. case SpvOpPtrAccessChain:
  214. case SpvOpInBoundsPtrAccessChain:
  215. case SpvOpImageTexelPointer:
  216. case SpvOpCopyObject:
  217. // All of these instructions have the base pointer use a base pointer
  218. // in in-operand 0.
  219. base = base_inst->GetSingleWordInOperand(0);
  220. base_inst = context()->get_def_use_mgr()->GetDef(base);
  221. break;
  222. default:
  223. done = true;
  224. break;
  225. }
  226. }
  227. return base_inst;
  228. }
  229. bool Instruction::IsReadOnlyPointer() const {
  230. if (context()->get_feature_mgr()->HasCapability(SpvCapabilityShader))
  231. return IsReadOnlyPointerShaders();
  232. else
  233. return IsReadOnlyPointerKernel();
  234. }
  235. bool Instruction::IsVulkanStorageImage() const {
  236. if (opcode() != SpvOpTypePointer) {
  237. return false;
  238. }
  239. uint32_t storage_class =
  240. GetSingleWordInOperand(kPointerTypeStorageClassIndex);
  241. if (storage_class != SpvStorageClassUniformConstant) {
  242. return false;
  243. }
  244. Instruction* base_type =
  245. context()->get_def_use_mgr()->GetDef(GetSingleWordInOperand(1));
  246. // Unpack the optional layer of arraying.
  247. if (base_type->opcode() == SpvOpTypeArray ||
  248. base_type->opcode() == SpvOpTypeRuntimeArray) {
  249. base_type = context()->get_def_use_mgr()->GetDef(
  250. base_type->GetSingleWordInOperand(0));
  251. }
  252. if (base_type->opcode() != SpvOpTypeImage) {
  253. return false;
  254. }
  255. if (base_type->GetSingleWordInOperand(kTypeImageDimIndex) == SpvDimBuffer) {
  256. return false;
  257. }
  258. // Check if the image is sampled. If we do not know for sure that it is,
  259. // then assume it is a storage image.
  260. return base_type->GetSingleWordInOperand(kTypeImageSampledIndex) != 1;
  261. }
  262. bool Instruction::IsVulkanSampledImage() const {
  263. if (opcode() != SpvOpTypePointer) {
  264. return false;
  265. }
  266. uint32_t storage_class =
  267. GetSingleWordInOperand(kPointerTypeStorageClassIndex);
  268. if (storage_class != SpvStorageClassUniformConstant) {
  269. return false;
  270. }
  271. Instruction* base_type =
  272. context()->get_def_use_mgr()->GetDef(GetSingleWordInOperand(1));
  273. // Unpack the optional layer of arraying.
  274. if (base_type->opcode() == SpvOpTypeArray ||
  275. base_type->opcode() == SpvOpTypeRuntimeArray) {
  276. base_type = context()->get_def_use_mgr()->GetDef(
  277. base_type->GetSingleWordInOperand(0));
  278. }
  279. if (base_type->opcode() != SpvOpTypeImage) {
  280. return false;
  281. }
  282. if (base_type->GetSingleWordInOperand(kTypeImageDimIndex) == SpvDimBuffer) {
  283. return false;
  284. }
  285. // Check if the image is sampled. If we know for sure that it is,
  286. // then return true.
  287. return base_type->GetSingleWordInOperand(kTypeImageSampledIndex) == 1;
  288. }
  289. bool Instruction::IsVulkanStorageTexelBuffer() const {
  290. if (opcode() != SpvOpTypePointer) {
  291. return false;
  292. }
  293. uint32_t storage_class =
  294. GetSingleWordInOperand(kPointerTypeStorageClassIndex);
  295. if (storage_class != SpvStorageClassUniformConstant) {
  296. return false;
  297. }
  298. Instruction* base_type =
  299. context()->get_def_use_mgr()->GetDef(GetSingleWordInOperand(1));
  300. // Unpack the optional layer of arraying.
  301. if (base_type->opcode() == SpvOpTypeArray ||
  302. base_type->opcode() == SpvOpTypeRuntimeArray) {
  303. base_type = context()->get_def_use_mgr()->GetDef(
  304. base_type->GetSingleWordInOperand(0));
  305. }
  306. if (base_type->opcode() != SpvOpTypeImage) {
  307. return false;
  308. }
  309. if (base_type->GetSingleWordInOperand(kTypeImageDimIndex) != SpvDimBuffer) {
  310. return false;
  311. }
  312. // Check if the image is sampled. If we do not know for sure that it is,
  313. // then assume it is a storage texel buffer.
  314. return base_type->GetSingleWordInOperand(kTypeImageSampledIndex) != 1;
  315. }
  316. bool Instruction::IsVulkanStorageBuffer() const {
  317. // Is there a difference between a "Storage buffer" and a "dynamic storage
  318. // buffer" in SPIR-V and do we care about the difference?
  319. if (opcode() != SpvOpTypePointer) {
  320. return false;
  321. }
  322. Instruction* base_type =
  323. context()->get_def_use_mgr()->GetDef(GetSingleWordInOperand(1));
  324. // Unpack the optional layer of arraying.
  325. if (base_type->opcode() == SpvOpTypeArray ||
  326. base_type->opcode() == SpvOpTypeRuntimeArray) {
  327. base_type = context()->get_def_use_mgr()->GetDef(
  328. base_type->GetSingleWordInOperand(0));
  329. }
  330. if (base_type->opcode() != SpvOpTypeStruct) {
  331. return false;
  332. }
  333. uint32_t storage_class =
  334. GetSingleWordInOperand(kPointerTypeStorageClassIndex);
  335. if (storage_class == SpvStorageClassUniform) {
  336. bool is_buffer_block = false;
  337. context()->get_decoration_mgr()->ForEachDecoration(
  338. base_type->result_id(), SpvDecorationBufferBlock,
  339. [&is_buffer_block](const Instruction&) { is_buffer_block = true; });
  340. return is_buffer_block;
  341. } else if (storage_class == SpvStorageClassStorageBuffer) {
  342. bool is_block = false;
  343. context()->get_decoration_mgr()->ForEachDecoration(
  344. base_type->result_id(), SpvDecorationBlock,
  345. [&is_block](const Instruction&) { is_block = true; });
  346. return is_block;
  347. }
  348. return false;
  349. }
  350. bool Instruction::IsVulkanUniformBuffer() const {
  351. if (opcode() != SpvOpTypePointer) {
  352. return false;
  353. }
  354. uint32_t storage_class =
  355. GetSingleWordInOperand(kPointerTypeStorageClassIndex);
  356. if (storage_class != SpvStorageClassUniform) {
  357. return false;
  358. }
  359. Instruction* base_type =
  360. context()->get_def_use_mgr()->GetDef(GetSingleWordInOperand(1));
  361. // Unpack the optional layer of arraying.
  362. if (base_type->opcode() == SpvOpTypeArray ||
  363. base_type->opcode() == SpvOpTypeRuntimeArray) {
  364. base_type = context()->get_def_use_mgr()->GetDef(
  365. base_type->GetSingleWordInOperand(0));
  366. }
  367. if (base_type->opcode() != SpvOpTypeStruct) {
  368. return false;
  369. }
  370. bool is_block = false;
  371. context()->get_decoration_mgr()->ForEachDecoration(
  372. base_type->result_id(), SpvDecorationBlock,
  373. [&is_block](const Instruction&) { is_block = true; });
  374. return is_block;
  375. }
  376. bool Instruction::IsReadOnlyPointerShaders() const {
  377. if (type_id() == 0) {
  378. return false;
  379. }
  380. Instruction* type_def = context()->get_def_use_mgr()->GetDef(type_id());
  381. if (type_def->opcode() != SpvOpTypePointer) {
  382. return false;
  383. }
  384. uint32_t storage_class =
  385. type_def->GetSingleWordInOperand(kPointerTypeStorageClassIndex);
  386. switch (storage_class) {
  387. case SpvStorageClassUniformConstant:
  388. if (!type_def->IsVulkanStorageImage() &&
  389. !type_def->IsVulkanStorageTexelBuffer()) {
  390. return true;
  391. }
  392. break;
  393. case SpvStorageClassUniform:
  394. if (!type_def->IsVulkanStorageBuffer()) {
  395. return true;
  396. }
  397. break;
  398. case SpvStorageClassPushConstant:
  399. case SpvStorageClassInput:
  400. return true;
  401. default:
  402. break;
  403. }
  404. bool is_nonwritable = false;
  405. context()->get_decoration_mgr()->ForEachDecoration(
  406. result_id(), SpvDecorationNonWritable,
  407. [&is_nonwritable](const Instruction&) { is_nonwritable = true; });
  408. return is_nonwritable;
  409. }
  410. bool Instruction::IsReadOnlyPointerKernel() const {
  411. if (type_id() == 0) {
  412. return false;
  413. }
  414. Instruction* type_def = context()->get_def_use_mgr()->GetDef(type_id());
  415. if (type_def->opcode() != SpvOpTypePointer) {
  416. return false;
  417. }
  418. uint32_t storage_class =
  419. type_def->GetSingleWordInOperand(kPointerTypeStorageClassIndex);
  420. return storage_class == SpvStorageClassUniformConstant;
  421. }
  422. uint32_t Instruction::GetTypeComponent(uint32_t element) const {
  423. uint32_t subtype = 0;
  424. switch (opcode()) {
  425. case SpvOpTypeStruct:
  426. subtype = GetSingleWordInOperand(element);
  427. break;
  428. case SpvOpTypeArray:
  429. case SpvOpTypeRuntimeArray:
  430. case SpvOpTypeVector:
  431. case SpvOpTypeMatrix:
  432. // These types all have uniform subtypes.
  433. subtype = GetSingleWordInOperand(0u);
  434. break;
  435. default:
  436. break;
  437. }
  438. return subtype;
  439. }
  440. void Instruction::UpdateLexicalScope(uint32_t scope) {
  441. dbg_scope_.SetLexicalScope(scope);
  442. for (auto& i : dbg_line_insts_) {
  443. i.dbg_scope_.SetLexicalScope(scope);
  444. }
  445. if (!IsDebugLineInst(opcode()) &&
  446. context()->AreAnalysesValid(IRContext::kAnalysisDebugInfo)) {
  447. context()->get_debug_info_mgr()->AnalyzeDebugInst(this);
  448. }
  449. }
  450. void Instruction::UpdateDebugInlinedAt(uint32_t new_inlined_at) {
  451. dbg_scope_.SetInlinedAt(new_inlined_at);
  452. for (auto& i : dbg_line_insts_) {
  453. i.dbg_scope_.SetInlinedAt(new_inlined_at);
  454. }
  455. if (!IsDebugLineInst(opcode()) &&
  456. context()->AreAnalysesValid(IRContext::kAnalysisDebugInfo)) {
  457. context()->get_debug_info_mgr()->AnalyzeDebugInst(this);
  458. }
  459. }
  460. void Instruction::UpdateDebugInfoFrom(const Instruction* from) {
  461. if (from == nullptr) return;
  462. clear_dbg_line_insts();
  463. if (!from->dbg_line_insts().empty())
  464. dbg_line_insts().push_back(from->dbg_line_insts().back());
  465. SetDebugScope(from->GetDebugScope());
  466. if (!IsDebugLineInst(opcode()) &&
  467. context()->AreAnalysesValid(IRContext::kAnalysisDebugInfo)) {
  468. context()->get_debug_info_mgr()->AnalyzeDebugInst(this);
  469. }
  470. }
  471. Instruction* Instruction::InsertBefore(std::unique_ptr<Instruction>&& inst) {
  472. inst.get()->InsertBefore(this);
  473. return inst.release();
  474. }
  475. Instruction* Instruction::InsertBefore(
  476. std::vector<std::unique_ptr<Instruction>>&& list) {
  477. Instruction* first_node = list.front().get();
  478. for (auto& inst : list) {
  479. inst.release()->InsertBefore(this);
  480. }
  481. list.clear();
  482. return first_node;
  483. }
  484. bool Instruction::IsValidBasePointer() const {
  485. uint32_t tid = type_id();
  486. if (tid == 0) {
  487. return false;
  488. }
  489. Instruction* type = context()->get_def_use_mgr()->GetDef(tid);
  490. if (type->opcode() != SpvOpTypePointer) {
  491. return false;
  492. }
  493. auto feature_mgr = context()->get_feature_mgr();
  494. if (feature_mgr->HasCapability(SpvCapabilityAddresses)) {
  495. // TODO: The rules here could be more restrictive.
  496. return true;
  497. }
  498. if (opcode() == SpvOpVariable || opcode() == SpvOpFunctionParameter) {
  499. return true;
  500. }
  501. // With variable pointers, there are more valid base pointer objects.
  502. // Variable pointers implicitly declares Variable pointers storage buffer.
  503. SpvStorageClass storage_class =
  504. static_cast<SpvStorageClass>(type->GetSingleWordInOperand(0));
  505. if ((feature_mgr->HasCapability(SpvCapabilityVariablePointersStorageBuffer) &&
  506. storage_class == SpvStorageClassStorageBuffer) ||
  507. (feature_mgr->HasCapability(SpvCapabilityVariablePointers) &&
  508. storage_class == SpvStorageClassWorkgroup)) {
  509. switch (opcode()) {
  510. case SpvOpPhi:
  511. case SpvOpSelect:
  512. case SpvOpFunctionCall:
  513. case SpvOpConstantNull:
  514. return true;
  515. default:
  516. break;
  517. }
  518. }
  519. uint32_t pointee_type_id = type->GetSingleWordInOperand(1);
  520. Instruction* pointee_type_inst =
  521. context()->get_def_use_mgr()->GetDef(pointee_type_id);
  522. if (pointee_type_inst->IsOpaqueType()) {
  523. return true;
  524. }
  525. return false;
  526. }
  527. OpenCLDebugInfo100Instructions Instruction::GetOpenCL100DebugOpcode() const {
  528. if (opcode() != SpvOpExtInst) {
  529. return OpenCLDebugInfo100InstructionsMax;
  530. }
  531. if (!context()->get_feature_mgr()->GetExtInstImportId_OpenCL100DebugInfo()) {
  532. return OpenCLDebugInfo100InstructionsMax;
  533. }
  534. if (GetSingleWordInOperand(kExtInstSetIdInIdx) !=
  535. context()->get_feature_mgr()->GetExtInstImportId_OpenCL100DebugInfo()) {
  536. return OpenCLDebugInfo100InstructionsMax;
  537. }
  538. return OpenCLDebugInfo100Instructions(
  539. GetSingleWordInOperand(kExtInstInstructionInIdx));
  540. }
  541. NonSemanticVulkanDebugInfo100Instructions Instruction::GetVulkan100DebugOpcode()
  542. const {
  543. if (opcode() != SpvOpExtInst) {
  544. return NonSemanticVulkanDebugInfo100InstructionsMax;
  545. }
  546. if (!context()->get_feature_mgr()->GetExtInstImportId_Vulkan100DebugInfo()) {
  547. return NonSemanticVulkanDebugInfo100InstructionsMax;
  548. }
  549. if (GetSingleWordInOperand(kExtInstSetIdInIdx) !=
  550. context()->get_feature_mgr()->GetExtInstImportId_Vulkan100DebugInfo()) {
  551. return NonSemanticVulkanDebugInfo100InstructionsMax;
  552. }
  553. return NonSemanticVulkanDebugInfo100Instructions(
  554. GetSingleWordInOperand(kExtInstInstructionInIdx));
  555. }
  556. CommonDebugInfoInstructions Instruction::GetCommonDebugOpcode() const {
  557. if (opcode() != SpvOpExtInst) {
  558. return CommonDebugInfoInstructionsMax;
  559. }
  560. const uint32_t opencl_set_id =
  561. context()->get_feature_mgr()->GetExtInstImportId_OpenCL100DebugInfo();
  562. const uint32_t vulkan_set_id =
  563. context()->get_feature_mgr()->GetExtInstImportId_Vulkan100DebugInfo();
  564. if (!opencl_set_id && !vulkan_set_id) {
  565. return CommonDebugInfoInstructionsMax;
  566. }
  567. const uint32_t used_set_id = GetSingleWordInOperand(kExtInstSetIdInIdx);
  568. if (used_set_id != opencl_set_id && used_set_id != vulkan_set_id) {
  569. return CommonDebugInfoInstructionsMax;
  570. }
  571. return CommonDebugInfoInstructions(
  572. GetSingleWordInOperand(kExtInstInstructionInIdx));
  573. }
  574. bool Instruction::IsValidBaseImage() const {
  575. uint32_t tid = type_id();
  576. if (tid == 0) {
  577. return false;
  578. }
  579. Instruction* type = context()->get_def_use_mgr()->GetDef(tid);
  580. return (type->opcode() == SpvOpTypeImage ||
  581. type->opcode() == SpvOpTypeSampledImage);
  582. }
  583. bool Instruction::IsOpaqueType() const {
  584. if (opcode() == SpvOpTypeStruct) {
  585. bool is_opaque = false;
  586. ForEachInOperand([&is_opaque, this](const uint32_t* op_id) {
  587. Instruction* type_inst = context()->get_def_use_mgr()->GetDef(*op_id);
  588. is_opaque |= type_inst->IsOpaqueType();
  589. });
  590. return is_opaque;
  591. } else if (opcode() == SpvOpTypeArray) {
  592. uint32_t sub_type_id = GetSingleWordInOperand(0);
  593. Instruction* sub_type_inst =
  594. context()->get_def_use_mgr()->GetDef(sub_type_id);
  595. return sub_type_inst->IsOpaqueType();
  596. } else {
  597. return opcode() == SpvOpTypeRuntimeArray ||
  598. spvOpcodeIsBaseOpaqueType(opcode());
  599. }
  600. }
  601. bool Instruction::IsFoldable() const {
  602. return IsFoldableByFoldScalar() ||
  603. context()->get_instruction_folder().HasConstFoldingRule(this);
  604. }
  605. bool Instruction::IsFoldableByFoldScalar() const {
  606. const InstructionFolder& folder = context()->get_instruction_folder();
  607. if (!folder.IsFoldableOpcode(opcode())) {
  608. return false;
  609. }
  610. Instruction* type = context()->get_def_use_mgr()->GetDef(type_id());
  611. if (!folder.IsFoldableType(type)) {
  612. return false;
  613. }
  614. // Even if the type of the instruction is foldable, its operands may not be
  615. // foldable (e.g., comparisons of 64bit types). Check that all operand types
  616. // are foldable before accepting the instruction.
  617. return WhileEachInOperand([&folder, this](const uint32_t* op_id) {
  618. Instruction* def_inst = context()->get_def_use_mgr()->GetDef(*op_id);
  619. Instruction* def_inst_type =
  620. context()->get_def_use_mgr()->GetDef(def_inst->type_id());
  621. return folder.IsFoldableType(def_inst_type);
  622. });
  623. }
  624. bool Instruction::IsFloatingPointFoldingAllowed() const {
  625. // TODO: Add the rules for kernels. For now it will be pessimistic.
  626. // For now, do not support capabilities introduced by SPV_KHR_float_controls.
  627. if (!context_->get_feature_mgr()->HasCapability(SpvCapabilityShader) ||
  628. context_->get_feature_mgr()->HasCapability(SpvCapabilityDenormPreserve) ||
  629. context_->get_feature_mgr()->HasCapability(
  630. SpvCapabilityDenormFlushToZero) ||
  631. context_->get_feature_mgr()->HasCapability(
  632. SpvCapabilitySignedZeroInfNanPreserve) ||
  633. context_->get_feature_mgr()->HasCapability(
  634. SpvCapabilityRoundingModeRTZ) ||
  635. context_->get_feature_mgr()->HasCapability(
  636. SpvCapabilityRoundingModeRTE)) {
  637. return false;
  638. }
  639. bool is_nocontract = false;
  640. context_->get_decoration_mgr()->WhileEachDecoration(
  641. result_id(), SpvDecorationNoContraction,
  642. [&is_nocontract](const Instruction&) {
  643. is_nocontract = true;
  644. return false;
  645. });
  646. return !is_nocontract;
  647. }
  648. std::string Instruction::PrettyPrint(uint32_t options) const {
  649. // Convert the module to binary.
  650. std::vector<uint32_t> module_binary;
  651. context()->module()->ToBinary(&module_binary, /* skip_nop = */ false);
  652. // Convert the instruction to binary. This is used to identify the correct
  653. // stream of words to output from the module.
  654. std::vector<uint32_t> inst_binary;
  655. ToBinaryWithoutAttachedDebugInsts(&inst_binary);
  656. // Do not generate a header.
  657. return spvInstructionBinaryToText(
  658. context()->grammar().target_env(), inst_binary.data(), inst_binary.size(),
  659. module_binary.data(), module_binary.size(),
  660. options | SPV_BINARY_TO_TEXT_OPTION_NO_HEADER);
  661. }
  662. std::ostream& operator<<(std::ostream& str, const Instruction& inst) {
  663. str << inst.PrettyPrint();
  664. return str;
  665. }
  666. void Instruction::Dump() const {
  667. std::cerr << "Instruction #" << unique_id() << "\n" << *this << "\n";
  668. }
  669. bool Instruction::IsOpcodeCodeMotionSafe() const {
  670. switch (opcode_) {
  671. case SpvOpNop:
  672. case SpvOpUndef:
  673. case SpvOpLoad:
  674. case SpvOpAccessChain:
  675. case SpvOpInBoundsAccessChain:
  676. case SpvOpArrayLength:
  677. case SpvOpVectorExtractDynamic:
  678. case SpvOpVectorInsertDynamic:
  679. case SpvOpVectorShuffle:
  680. case SpvOpCompositeConstruct:
  681. case SpvOpCompositeExtract:
  682. case SpvOpCompositeInsert:
  683. case SpvOpCopyObject:
  684. case SpvOpTranspose:
  685. case SpvOpConvertFToU:
  686. case SpvOpConvertFToS:
  687. case SpvOpConvertSToF:
  688. case SpvOpConvertUToF:
  689. case SpvOpUConvert:
  690. case SpvOpSConvert:
  691. case SpvOpFConvert:
  692. case SpvOpQuantizeToF16:
  693. case SpvOpBitcast:
  694. case SpvOpSNegate:
  695. case SpvOpFNegate:
  696. case SpvOpIAdd:
  697. case SpvOpFAdd:
  698. case SpvOpISub:
  699. case SpvOpFSub:
  700. case SpvOpIMul:
  701. case SpvOpFMul:
  702. case SpvOpUDiv:
  703. case SpvOpSDiv:
  704. case SpvOpFDiv:
  705. case SpvOpUMod:
  706. case SpvOpSRem:
  707. case SpvOpSMod:
  708. case SpvOpFRem:
  709. case SpvOpFMod:
  710. case SpvOpVectorTimesScalar:
  711. case SpvOpMatrixTimesScalar:
  712. case SpvOpVectorTimesMatrix:
  713. case SpvOpMatrixTimesVector:
  714. case SpvOpMatrixTimesMatrix:
  715. case SpvOpOuterProduct:
  716. case SpvOpDot:
  717. case SpvOpIAddCarry:
  718. case SpvOpISubBorrow:
  719. case SpvOpUMulExtended:
  720. case SpvOpSMulExtended:
  721. case SpvOpAny:
  722. case SpvOpAll:
  723. case SpvOpIsNan:
  724. case SpvOpIsInf:
  725. case SpvOpLogicalEqual:
  726. case SpvOpLogicalNotEqual:
  727. case SpvOpLogicalOr:
  728. case SpvOpLogicalAnd:
  729. case SpvOpLogicalNot:
  730. case SpvOpSelect:
  731. case SpvOpIEqual:
  732. case SpvOpINotEqual:
  733. case SpvOpUGreaterThan:
  734. case SpvOpSGreaterThan:
  735. case SpvOpUGreaterThanEqual:
  736. case SpvOpSGreaterThanEqual:
  737. case SpvOpULessThan:
  738. case SpvOpSLessThan:
  739. case SpvOpULessThanEqual:
  740. case SpvOpSLessThanEqual:
  741. case SpvOpFOrdEqual:
  742. case SpvOpFUnordEqual:
  743. case SpvOpFOrdNotEqual:
  744. case SpvOpFUnordNotEqual:
  745. case SpvOpFOrdLessThan:
  746. case SpvOpFUnordLessThan:
  747. case SpvOpFOrdGreaterThan:
  748. case SpvOpFUnordGreaterThan:
  749. case SpvOpFOrdLessThanEqual:
  750. case SpvOpFUnordLessThanEqual:
  751. case SpvOpFOrdGreaterThanEqual:
  752. case SpvOpFUnordGreaterThanEqual:
  753. case SpvOpShiftRightLogical:
  754. case SpvOpShiftRightArithmetic:
  755. case SpvOpShiftLeftLogical:
  756. case SpvOpBitwiseOr:
  757. case SpvOpBitwiseXor:
  758. case SpvOpBitwiseAnd:
  759. case SpvOpNot:
  760. case SpvOpBitFieldInsert:
  761. case SpvOpBitFieldSExtract:
  762. case SpvOpBitFieldUExtract:
  763. case SpvOpBitReverse:
  764. case SpvOpBitCount:
  765. case SpvOpSizeOf:
  766. return true;
  767. default:
  768. return false;
  769. }
  770. }
  771. bool Instruction::IsScalarizable() const {
  772. if (spvOpcodeIsScalarizable(opcode())) {
  773. return true;
  774. }
  775. if (opcode() == SpvOpExtInst) {
  776. uint32_t instSetId =
  777. context()->get_feature_mgr()->GetExtInstImportId_GLSLstd450();
  778. if (GetSingleWordInOperand(kExtInstSetIdInIdx) == instSetId) {
  779. switch (GetSingleWordInOperand(kExtInstInstructionInIdx)) {
  780. case GLSLstd450Round:
  781. case GLSLstd450RoundEven:
  782. case GLSLstd450Trunc:
  783. case GLSLstd450FAbs:
  784. case GLSLstd450SAbs:
  785. case GLSLstd450FSign:
  786. case GLSLstd450SSign:
  787. case GLSLstd450Floor:
  788. case GLSLstd450Ceil:
  789. case GLSLstd450Fract:
  790. case GLSLstd450Radians:
  791. case GLSLstd450Degrees:
  792. case GLSLstd450Sin:
  793. case GLSLstd450Cos:
  794. case GLSLstd450Tan:
  795. case GLSLstd450Asin:
  796. case GLSLstd450Acos:
  797. case GLSLstd450Atan:
  798. case GLSLstd450Sinh:
  799. case GLSLstd450Cosh:
  800. case GLSLstd450Tanh:
  801. case GLSLstd450Asinh:
  802. case GLSLstd450Acosh:
  803. case GLSLstd450Atanh:
  804. case GLSLstd450Atan2:
  805. case GLSLstd450Pow:
  806. case GLSLstd450Exp:
  807. case GLSLstd450Log:
  808. case GLSLstd450Exp2:
  809. case GLSLstd450Log2:
  810. case GLSLstd450Sqrt:
  811. case GLSLstd450InverseSqrt:
  812. case GLSLstd450Modf:
  813. case GLSLstd450FMin:
  814. case GLSLstd450UMin:
  815. case GLSLstd450SMin:
  816. case GLSLstd450FMax:
  817. case GLSLstd450UMax:
  818. case GLSLstd450SMax:
  819. case GLSLstd450FClamp:
  820. case GLSLstd450UClamp:
  821. case GLSLstd450SClamp:
  822. case GLSLstd450FMix:
  823. case GLSLstd450Step:
  824. case GLSLstd450SmoothStep:
  825. case GLSLstd450Fma:
  826. case GLSLstd450Frexp:
  827. case GLSLstd450Ldexp:
  828. case GLSLstd450FindILsb:
  829. case GLSLstd450FindSMsb:
  830. case GLSLstd450FindUMsb:
  831. case GLSLstd450NMin:
  832. case GLSLstd450NMax:
  833. case GLSLstd450NClamp:
  834. return true;
  835. default:
  836. return false;
  837. }
  838. }
  839. }
  840. return false;
  841. }
  842. bool Instruction::IsOpcodeSafeToDelete() const {
  843. if (context()->IsCombinatorInstruction(this)) {
  844. return true;
  845. }
  846. switch (opcode()) {
  847. case SpvOpDPdx:
  848. case SpvOpDPdy:
  849. case SpvOpFwidth:
  850. case SpvOpDPdxFine:
  851. case SpvOpDPdyFine:
  852. case SpvOpFwidthFine:
  853. case SpvOpDPdxCoarse:
  854. case SpvOpDPdyCoarse:
  855. case SpvOpFwidthCoarse:
  856. case SpvOpImageQueryLod:
  857. return true;
  858. default:
  859. return false;
  860. }
  861. }
  862. bool Instruction::IsNonSemanticInstruction() const {
  863. if (!HasResultId()) return false;
  864. if (opcode() != SpvOpExtInst) return false;
  865. auto import_inst =
  866. context()->get_def_use_mgr()->GetDef(GetSingleWordInOperand(0));
  867. std::string import_name = import_inst->GetInOperand(0).AsString();
  868. return import_name.find("NonSemantic.") == 0;
  869. }
  870. void DebugScope::ToBinary(uint32_t type_id, uint32_t result_id,
  871. uint32_t ext_set,
  872. std::vector<uint32_t>* binary) const {
  873. uint32_t num_words = kDebugScopeNumWords;
  874. CommonDebugInfoInstructions dbg_opcode = CommonDebugInfoDebugScope;
  875. if (GetLexicalScope() == kNoDebugScope) {
  876. num_words = kDebugNoScopeNumWords;
  877. dbg_opcode = CommonDebugInfoDebugNoScope;
  878. } else if (GetInlinedAt() == kNoInlinedAt) {
  879. num_words = kDebugScopeNumWordsWithoutInlinedAt;
  880. }
  881. std::vector<uint32_t> operands = {
  882. (num_words << 16) | static_cast<uint16_t>(SpvOpExtInst),
  883. type_id,
  884. result_id,
  885. ext_set,
  886. static_cast<uint32_t>(dbg_opcode),
  887. };
  888. binary->insert(binary->end(), operands.begin(), operands.end());
  889. if (GetLexicalScope() != kNoDebugScope) {
  890. binary->push_back(GetLexicalScope());
  891. if (GetInlinedAt() != kNoInlinedAt) binary->push_back(GetInlinedAt());
  892. }
  893. }
  894. } // namespace opt
  895. } // namespace spvtools