Simplifying code for adding instructions to worklist
* AddToWorklist can now be called unconditionally
* It will only add instructions that have not already been marked as
live
* Fixes a case where a merge was not added to the worklist because the
branch was already marked as live
* Added two similar tests that fail without the fix
diff --git a/source/opt/aggressive_dead_code_elim_pass.cpp b/source/opt/aggressive_dead_code_elim_pass.cpp
index 2e79fe6..8125d57 100644
--- a/source/opt/aggressive_dead_code_elim_pass.cpp
+++ b/source/opt/aggressive_dead_code_elim_pass.cpp
@@ -117,7 +117,7 @@
// If default, assume it stores e.g. frexp, modf, function call
case SpvOpStore:
default:
- if (!IsLive(user)) AddToWorklist(user);
+ AddToWorklist(user);
break;
}
});
@@ -251,12 +251,10 @@
if (hdrMerge == loopMerge) break;
branchInst = hdrBranch;
}
- if (!IsLive(user)) {
- AddToWorklist(user);
- // Add branch's merge if there is one
- ir::Instruction* userMerge = branch2merge_[user];
- if (userMerge != nullptr) AddToWorklist(userMerge);
- }
+ AddToWorklist(user);
+ // Add branch's merge if there is one
+ ir::Instruction* userMerge = branch2merge_[user];
+ if (userMerge != nullptr) AddToWorklist(userMerge);
});
const uint32_t contId =
loopMerge->GetSingleWordInOperand(kLoopMergeContinueBlockIdInIdx);
@@ -272,7 +270,7 @@
hdrMerge->GetSingleWordInOperand(kSelectionMergeMergeBlockIdInIdx);
if (hdrMergeId == contId) return;
// Need to mark merge instruction too
- if (!IsLive(hdrMerge)) AddToWorklist(hdrMerge);
+ AddToWorklist(hdrMerge);
}
} else if (op == SpvOpBranch) {
// An unconditional branch can only be a continue if it is not
@@ -288,7 +286,7 @@
} else {
return;
}
- if (!IsLive(user)) AddToWorklist(user);
+ AddToWorklist(user);
});
}
@@ -392,7 +390,7 @@
// as part of live code discovery and can create false live code,
// for example, the branch to a header of a loop.
if (inInst->opcode() == SpvOpLabel && liveInst->IsBranch()) return;
- if (!IsLive(inInst)) AddToWorklist(inInst);
+ AddToWorklist(inInst);
});
if (liveInst->type_id() != 0) {
AddToWorklist(get_def_use_mgr()->GetDef(liveInst->type_id()));
@@ -403,7 +401,7 @@
// worklist.
ir::BasicBlock* blk = context()->get_instr_block(liveInst);
ir::Instruction* branchInst = block2headerBranch_[blk];
- if (branchInst != nullptr && !IsLive(branchInst)) {
+ if (branchInst != nullptr) {
AddToWorklist(branchInst);
ir::Instruction* mergeInst = branch2merge_[branchInst];
AddToWorklist(mergeInst);
diff --git a/source/opt/aggressive_dead_code_elim_pass.h b/source/opt/aggressive_dead_code_elim_pass.h
index 3669752..e3ae3bb 100644
--- a/source/opt/aggressive_dead_code_elim_pass.h
+++ b/source/opt/aggressive_dead_code_elim_pass.h
@@ -72,8 +72,7 @@
// Add |inst| to worklist_ and live_insts_.
void AddToWorklist(ir::Instruction* inst) {
- live_insts_.insert(inst);
- worklist_.push(inst);
+ if (live_insts_.insert(inst).second) worklist_.push(inst);
}
// Add all store instruction which use |ptrId|, directly or indirectly,
diff --git a/test/opt/aggressive_dead_code_elim_test.cpp b/test/opt/aggressive_dead_code_elim_test.cpp
index dd079d9..b79eed3 100644
--- a/test/opt/aggressive_dead_code_elim_test.cpp
+++ b/test/opt/aggressive_dead_code_elim_test.cpp
@@ -5176,6 +5176,7 @@
SinglePassRunAndMatch<opt::AggressiveDCEPass>(text, true);
}
+#endif // SPIRV_EFFCEE
TEST_F(AggressiveDCETest, BreaksDontVisitPhis) {
const std::string text = R"(
@@ -5219,7 +5220,84 @@
std::get<1>(SinglePassRunAndDisassemble<opt::AggressiveDCEPass>(
text, false, true)));
}
-#endif // SPIRV_EFFCEE
+
+// Test for #1212
+TEST_F(AggressiveDCETest, ConstStoreInnerLoop) {
+ const std::string text = R"(OpCapability Shader
+OpMemoryModel Logical GLSL450
+OpEntryPoint Vertex %1 "main" %2
+%void = OpTypeVoid
+%4 = OpTypeFunction %void
+%float = OpTypeFloat 32
+%bool = OpTypeBool
+%true = OpConstantTrue %bool
+%_ptr_Output_float = OpTypePointer Output %float
+%2 = OpVariable %_ptr_Output_float Output
+%float_3 = OpConstant %float 3
+%1 = OpFunction %void None %4
+%13 = OpLabel
+OpBranch %14
+%14 = OpLabel
+OpLoopMerge %15 %16 None
+OpBranchConditional %true %17 %15
+%17 = OpLabel
+OpStore %2 %float_3
+OpLoopMerge %18 %17 None
+OpBranchConditional %true %18 %17
+%18 = OpLabel
+OpBranch %15
+%16 = OpLabel
+OpBranch %14
+%15 = OpLabel
+OpBranch %20
+%20 = OpLabel
+OpReturn
+OpFunctionEnd
+)";
+
+ SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
+ SinglePassRunAndCheck<opt::AggressiveDCEPass>(text, text, true, true);
+}
+
+// Test for #1212
+TEST_F(AggressiveDCETest, InnerLoopCopy) {
+ const std::string text = R"(OpCapability Shader
+OpMemoryModel Logical GLSL450
+OpEntryPoint Vertex %1 "main" %2 %3
+%void = OpTypeVoid
+%5 = OpTypeFunction %void
+%float = OpTypeFloat 32
+%bool = OpTypeBool
+%true = OpConstantTrue %bool
+%_ptr_Output_float = OpTypePointer Output %float
+%_ptr_Input_float = OpTypePointer Input %float
+%2 = OpVariable %_ptr_Output_float Output
+%3 = OpVariable %_ptr_Input_float Input
+%1 = OpFunction %void None %5
+%14 = OpLabel
+OpBranch %15
+%15 = OpLabel
+OpLoopMerge %16 %17 None
+OpBranchConditional %true %18 %16
+%18 = OpLabel
+%19 = OpLoad %float %3
+OpStore %2 %19
+OpLoopMerge %20 %18 None
+OpBranchConditional %true %20 %18
+%20 = OpLabel
+OpBranch %16
+%17 = OpLabel
+OpBranch %15
+%16 = OpLabel
+OpBranch %22
+%22 = OpLabel
+OpReturn
+OpFunctionEnd
+)";
+
+ SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
+ SinglePassRunAndCheck<opt::AggressiveDCEPass>(text, text, true, true);
+}
// TODO(greg-lunarg): Add tests to verify handling of these cases:
//