From e8b7c7b2103a6fb57157de9f38a2a11646221c3c Mon Sep 17 00:00:00 2001 From: qining Date: Tue, 16 Aug 2016 11:04:32 -0400 Subject: [PATCH] Replace the SetOperand() with SetInOperand() and SetResultType() --- source/opt/def_use_manager.cpp | 16 ++++++++++++++-- source/opt/instruction.h | 30 ++++++++++++++++++++++-------- 2 files changed, 36 insertions(+), 10 deletions(-) diff --git a/source/opt/def_use_manager.cpp b/source/opt/def_use_manager.cpp index d0bf79c..455a51b 100644 --- a/source/opt/def_use_manager.cpp +++ b/source/opt/def_use_manager.cpp @@ -86,8 +86,20 @@ bool DefUseManager::ReplaceAllUsesWith(uint32_t before, uint32_t after) { for (auto it = id_to_uses_[before].cbegin(); it != id_to_uses_[before].cend(); ++it) { - // Make the modification in the instruction. - it->inst->SetOperand(it->operand_index, {after}); + const uint32_t type_result_id_count = + (it->inst->result_id() != 0) + (it->inst->type_id() != 0); + if (!it->operand_index) { + assert(it->inst->type_id() != 0 && + "result type id considered as using while the instruction doesn't " + "have a result type id"); + it->inst->SetResultType(after); + } else { + assert(it->operand_index >= type_result_id_count && + "the operand to be set is not an in-operand."); + uint32_t in_operand_pos = it->operand_index - type_result_id_count; + // Make the modification in the instruction. + it->inst->SetInOperand(in_operand_pos, {after}); + } // Register the use of |after| id into id_to_uses_. // TODO(antiagainst): de-duplication. id_to_uses_[after].push_back({it->inst, it->operand_index}); diff --git a/source/opt/instruction.h b/source/opt/instruction.h index 73ac828..bf7d13b 100644 --- a/source/opt/instruction.h +++ b/source/opt/instruction.h @@ -72,8 +72,11 @@ struct Operand { }; // A SPIR-V instruction. It contains the opcode and any additional logical -// operand. It may also contain line-related debug instruction (OpLine, -// OpNoLine) directly appearing before this instruction. +// operand, including the result id (if any) and result type id (if any). It +// may also contain line-related debug instruction (OpLine, OpNoLine) directly +// appearing before this instruction. Note that the result id of an instruction +// should never change after the instruction being built. If the result id +// needs to change, the user should create a new instruction instead. class Instruction { public: // Creates a default OpNop instruction. @@ -128,8 +131,10 @@ class Instruction { // not expected to be used with logical operands consisting of multiple SPIR-V // words. uint32_t GetSingleWordOperand(uint32_t index) const; - // Sets the |index|-th operand's data to the given |data|. - inline void SetOperand(uint32_t index, std::vector&& data); + // Sets the |index|-th in-operand's data to the given |data|. + inline void SetInOperand(uint32_t index, std::vector&& data); + // Sets the result type id. + inline void SetResultType(uint32_t ty_id); // The following methods are similar to the above, but are for in operands. uint32_t NumInOperands() const { @@ -179,10 +184,19 @@ inline const Operand& Instruction::GetOperand(uint32_t index) const { return operands_[index]; }; -inline void Instruction::SetOperand(uint32_t index, - std::vector&& data) { - assert(index < operands_.size() && "operand index out of bound"); - operands_[index].words = std::move(data); +inline void Instruction::SetInOperand(uint32_t index, + std::vector&& data) { + assert(index + TypeResultIdCount() < operands_.size() && + "operand index out of bound"); + operands_[index + TypeResultIdCount()].words = std::move(data); +} + +inline void Instruction::SetResultType(uint32_t ty_id) { + if (type_id_ != 0) { + type_id_ = ty_id; + assert(operands_.front().type == SPV_OPERAND_TYPE_TYPE_ID); + operands_.front().words = {ty_id}; + } } inline bool Instruction::IsNop() const { -- 2.7.4