diff --git a/src/FindIntrinsics.cpp b/src/FindIntrinsics.cpp index 3aa495e5a621..9d8c2f028d18 100644 --- a/src/FindIntrinsics.cpp +++ b/src/FindIntrinsics.cpp @@ -128,6 +128,13 @@ class FindIntrinsics : public IRMutator { Expr a = c->args[0]; Expr b = c->args[1]; + if (Call::as_intrinsic(b, {Call::signed_integer_overflow})) { + // Letting signed integer overflow through here would result in + // infinite recursion when we try to construct the rounding + // terms. + return Expr{}; + } + // Helper to make the appropriate shift. auto rounding_shift = [&](const Expr &a, const Expr &b) { if (c->is_intrinsic(Call::shift_right)) { @@ -203,7 +210,7 @@ class FindIntrinsics : public IRMutator { } } - return Expr(); + return Expr{}; } template diff --git a/test/correctness/intrinsics.cpp b/test/correctness/intrinsics.cpp index 76166c3fb4c5..00ca47d113ce 100644 --- a/test/correctness/intrinsics.cpp +++ b/test/correctness/intrinsics.cpp @@ -346,6 +346,11 @@ int main(int argc, char **argv) { check_intrinsics_over_range(); check_intrinsics_over_range(); + // Signed integer overflow on the RHS of a shift used to cause infinite + // recursion (issue #9108) + Expr e = simplify(i32x << (i32x << 67)); + check(e, e); + // The intrinsics-matching pass substitutes in widening lets. At // one point this caused a missing symbol bug for the code below // due to a subexpression not getting mutated.