Skip to content

JIT: (bug) "Bad precondition in Compiler::optUnrollLoops()" noway_assert when the loop test is evaluated into a local #134934

Description

@EgorBo

If a counted loop's exit test is stored into a local and the loop then branches on that local, loop unrolling hits a noway_assert. Checked builds assert. Release builds silently fall back to MinOpts for the whole method, including Tier1 rejits.

Minimal Repro

using System;
using System.Runtime.CompilerServices;

public class Program
{
    public static void Main()
    {
        Console.WriteLine(Test(new int[] { 1, 2, 3, 4 }));
    }

    [MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.AggressiveOptimization)]
    public static int Test(int[] a)
    {
        int sum = 0;
        int i = 0;
        bool b;
        do
        {
            sum += a[i];
            i++;
            b = i < 4;
        } while (b);
        return b ? -1 : sum;
    }
}

Expected

Prints 10, and Test is compiled with full optimizations.

Actual

Checked:

Assertion failed '!"Bad precondition in Compiler::optUnrollLoops()"' in 'Program:Test(int[]):int' during 'Unroll loops' (IL size 29; hash 0xf8b2f420; FullOpts)
    File: src\coreclr\jit\optimizer.cpp:1450

Release prints 10, but DOTNET_JitDisasm=Test shows ; MinOpts code (or ; compiling with minopt for Tier1).

Regression?

Yes, it regressed in .NET 11. .NET 8, 9, and 10 compile Test with full optimizations. .NET 11 RC2 falls back to MinOpts, both for FullOpts and for Tier1.

Notes

optExtractTestIncr accepts the "test evaluated into temp" shape (STORE_LCL_VAR V03 (LT V02, 4) followed by JTRUE (NE V03, 0)), so iterInfo.TestTree points to the LT node. optTryUnrollLoop still requires TestBlock->lastStmt()->GetRootNode()->gtGetOp1() == TestTree, and that check fails because the operand is the NE node. The code should return false here instead of hitting the noway_assert, or it should handle this shape.

Activity

  1. added this to the 12.0.0 milestone on Sep 30, 2026
  2. added
    area-CodeGen-coreclrCLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMI
    on Sep 30, 2026
  3. dotnet-policy-service commented on Sep 30, 2026

    @dotnet-policy-service
    Contributor

    Tagging subscribers to this area: @JulieLeeMSFT, @jakobbotsch
    See info in area-owners.md if you want to be subscribed.

  4. added a commit that references this issue on Oct 2, 2026
    7693364
  5. self-assigned this
    on Oct 8, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

area-CodeGen-coreclrCLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMI

Type

No type

Projects

No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions