diff --git a/source/opt/loop_descriptor.cpp b/source/opt/loop_descriptor.cpp index 9bc495e51..4feb64e86 100644 --- a/source/opt/loop_descriptor.cpp +++ b/source/opt/loop_descriptor.cpp @@ -754,6 +754,10 @@ bool Loop::FindNumberOfIterations(const Instruction* induction, // |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 e88ff9363..df012274c 100644 --- a/source/opt/loop_descriptor.h +++ b/source/opt/loop_descriptor.h @@ -398,7 +398,8 @@ class Loop { // 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 b72305c87..299fb2d5c 100644 --- a/test/opt/loop_optimizations/unroll_simple.cpp +++ b/test/opt/loop_optimizations/unroll_simple.cpp @@ -3789,6 +3789,40 @@ TEST_F(PassClassTest, PartialUnrollWithPhiReferencesPhi) { SinglePassRunAndMatch>(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(text, text, false); +} + } // namespace } // namespace opt } // namespace spvtools