Skip to content

Position of constant folded operand in or-statement affects codegen #123621

Closed

Description

@ovska

In the code below, placing the comparison with Environment.NewLine inline after a non-runtime constant check produces extra code compared to hoisting the newline check to a local, or placing it first.

x86: https://godbolt.org/z/oeMWrEWje
arm: https://godbolt.org/z/EY3f8cscG

using System;

static class B
{
    public static bool Hoisted(byte v)
    {
        bool isUnix = Environment.NewLine != "\r\n";
        return (v == 2 && isUnix);
    }

    public static bool Inline_Before(byte v)
    {
        return (Environment.NewLine != "\r\n" && v == 2);
    }

    public static bool Inline_After(byte v)
    {
        return (v == 2 && Environment.NewLine != "\r\n");
    }
}

x86 example:

// expected
       cmp      dil, 2
       sete     al
       movzx    rax, al
       ret      

// actual
       cmp      dil, 2
       je       SHORT G_M4495_IG05
       xor      eax, eax
       ret      
G_M4495_IG05:  ;; offset=0x0009
       mov      eax, 1
       ret      

Activity

  1. added
    area-CodeGen-coreclrCLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMI
    on Jan 26, 2026
  2. added this to the Future milestone on Jan 26, 2026
  3. added
    help wanted[up-for-grabs] Good issue for external contributors
    and removed
    untriagedNew issue has not been triaged by the area owner
    on Jan 26, 2026
  4. yykkibbb commented on Feb 20, 2026

    @yykkibbb
    Contributor

    Hi @EgorBo @JulieLeeMSFT, thank you for triaging this issue!

    I'd like to work on this and submit a PR. From my initial investigation, the constant folding itself works correctly in all three cases (the Environment.NewLine check is fully eliminated). The difference is that in the Inline_After case, the remaining BBJ_COND block with v == 2 isn't being simplified into a branchless return (sete/movzx), unlike the Hoisted and Inline_Before cases. I plan to enable JITDUMP to trace exactly where the optimization gap occurs — likely around fgFoldCondToReturnBlock or the block compaction between morph and optOptimizeBools.

    Please let me know if there are any pointers or context I should be aware of before diving in.

  5. added a commit that references this issue on Mar 23, 2026
    7c58a24
  6. added a commit that references this issue on Mar 23, 2026
    71af4f6
  7. locked and limited conversation to collaborators on Apr 22, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    area-CodeGen-coreclrCLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMIhelp wanted[up-for-grabs] Good issue for external contributors

    Type

    No type

    Projects

    No projects

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions