instruction.cpp 33 KB

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