Avoid if-conversion if both predecessors are the same (#4826)
If the predecessor blocks are the same, then there is only 1 value for the
OpPhi. The simplition pass will simplify it, and it causes problems for
if-conversion. In these cases, if-conversion can just punt.
Fixes #3554.
diff --git a/source/opt/if_conversion.cpp b/source/opt/if_conversion.cpp
index d1debd0..1232796 100644
--- a/source/opt/if_conversion.cpp
+++ b/source/opt/if_conversion.cpp
@@ -160,6 +160,11 @@
BasicBlock* inc1 = context()->get_instr_block(preds[1]);
if (dominators->Dominates(block, inc1)) return false;
+ if (inc0 == inc1) {
+ // If the predecessor blocks are the same, then there is only 1 value for
+ // the OpPhi. Other transformation should be able to simplify that.
+ return false;
+ }
// All phis will have the same common dominator, so cache the result
// for this block. If there is no common dominator, then we cannot transform
// any phi in this basic block.
diff --git a/test/opt/if_conversion_test.cpp b/test/opt/if_conversion_test.cpp
index 81e9bb2..dc7f831 100644
--- a/test/opt/if_conversion_test.cpp
+++ b/test/opt/if_conversion_test.cpp
@@ -591,6 +591,33 @@
SinglePassRunAndMatch<IfConversion>(text, true);
}
+TEST_F(IfConversionTest, MultipleEdgesFromSameBlock) {
+ // If a block has two out going edges that go to the same block, then there
+ // can be an OpPhi instruction with fewer entries than the number of incoming
+ // edges. This must be handled.
+ const std::string text = R"(OpCapability Shader
+%1 = OpExtInstImport "GLSL.std.450"
+OpMemoryModel Logical GLSL450
+OpEntryPoint Fragment %2 "main"
+OpExecutionMode %2 OriginUpperLeft
+%void = OpTypeVoid
+%4 = OpTypeFunction %void
+%bool = OpTypeBool
+%true = OpConstantTrue %bool
+%true_0 = OpConstantTrue %bool
+%2 = OpFunction %void None %4
+%8 = OpLabel
+OpSelectionMerge %9 None
+OpBranchConditional %true_0 %9 %9
+%9 = OpLabel
+%10 = OpPhi %bool %true %8
+OpReturn
+OpFunctionEnd
+)";
+
+ SinglePassRunAndCheck<IfConversion>(text, text, true, true);
+}
+
} // namespace
} // namespace opt
} // namespace spvtools