Replace the SetOperand() with SetInOperand() and SetResultType()
authorqining <qining@google.com>
Tue, 16 Aug 2016 15:04:32 +0000 (11:04 -0400)
committerqining <qining@google.com>
Tue, 16 Aug 2016 19:05:07 +0000 (15:05 -0400)
source/opt/def_use_manager.cpp
source/opt/instruction.h

index d0bf79c..455a51b 100644 (file)
@@ -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});
index 73ac828..bf7d13b 100644 (file)
@@ -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<uint32_t>&& data);
+  // Sets the |index|-th in-operand's data to the given |data|.
+  inline void SetInOperand(uint32_t index, std::vector<uint32_t>&& 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<uint32_t>&& 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<uint32_t>&& 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 {