Don't try to unroll loop with step count 0. (#4769)
These loop are infinite loop, so there is no reason to unroll the loop.
Fixes #4711.
diff --git a/source/opt/loop_descriptor.cpp b/source/opt/loop_descriptor.cpp
index 9bc495e..4feb64e 100644
--- a/source/opt/loop_descriptor.cpp
+++ b/source/opt/loop_descriptor.cpp
@@ -754,6 +754,10 @@
// |step_value| is NOT cleanly divisible then we add one to the sum.
int64_t Loop::GetIterations(SpvOp condition, int64_t condition_value,
int64_t init_value, int64_t step_value) const {
+ if (step_value == 0) {
+ return 0;
+ }
+
int64_t diff = 0;
switch (condition) {
diff --git a/source/opt/loop_descriptor.h b/source/opt/loop_descriptor.h
index e88ff93..df01227 100644
--- a/source/opt/loop_descriptor.h
+++ b/source/opt/loop_descriptor.h
@@ -398,7 +398,8 @@
// Each different loop |condition| affects how we calculate the number of
// iterations using the |condition_value|, |init_value|, and |step_values| of
// the induction variable. This method will return the number of iterations in
- // a loop with those values for a given |condition|.
+ // a loop with those values for a given |condition|. Returns 0 if the number
+ // of iterations could not be computed.
int64_t GetIterations(SpvOp condition, int64_t condition_value,
int64_t init_value, int64_t step_value) const;
diff --git a/test/opt/loop_optimizations/unroll_simple.cpp b/test/opt/loop_optimizations/unroll_simple.cpp
index b72305c..299fb2d 100644
--- a/test/opt/loop_optimizations/unroll_simple.cpp
+++ b/test/opt/loop_optimizations/unroll_simple.cpp
@@ -3789,6 +3789,40 @@
SinglePassRunAndMatch<PartialUnrollerTestPass<2>>(text, true);
}
+TEST_F(PassClassTest, DontUnrollInfiteLoop) {
+ // This is an infinite loop that because the step is 0. We want to make sure
+ // the unroller does not try to unroll it.
+ 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
+%int = OpTypeInt 32 1
+%int_0 = OpConstant %int 0
+%int_50 = OpConstant %int 50
+%bool = OpTypeBool
+%int_0_0 = OpConstant %int 0
+%2 = OpFunction %void None %4
+%10 = OpLabel
+OpBranch %11
+%11 = OpLabel
+%12 = OpPhi %int %int_0 %10 %13 %14
+%15 = OpSLessThan %bool %12 %int_50
+OpLoopMerge %16 %14 Unroll
+OpBranchConditional %15 %14 %16
+%14 = OpLabel
+%13 = OpIAdd %int %12 %int_0_0
+OpBranch %11
+%16 = OpLabel
+OpReturn
+OpFunctionEnd
+)";
+
+ SinglePassRunAndCheck<LoopUnroller>(text, text, false);
+}
+
} // namespace
} // namespace opt
} // namespace spvtools