Skip to content

JIT: Missing deduplication of RETURN block causes switch recognition to miss JTRUEs #128514

@BoyBaykiller

Description

@BoyBaykiller

Consider this (https://godbolt.org/z/qqs1doPTT):

static bool IsLWS(byte ch)
{
    return (ch <= 32) && (ch == 32 || ch == 10 || ch == 13 || ch == 9);
}

which Roslyn turns into:

static bool IsLWS1(byte ch)
{
    if (ch <= 32)
    {
        if (ch != 32 && ch != 10 && ch != 13)
        {
            return ch == 9;
        }
        return true;
    }
    return false;
}

Codegen is:

G_M000_IG02:                ;; offset=0x0000
       movzx    rcx, cl
       cmp      ecx, 32
       jle      SHORT G_M000_IG05
 
G_M000_IG03:                ;; offset=0x0008
       xor      eax, eax
 
G_M000_IG04:                ;; offset=0x000A
       ret      
 
G_M000_IG05:                ;; offset=0x000B
       cmp      ecx, 32
       ja       SHORT G_M000_IG09
 
G_M000_IG06:                ;; offset=0x0010
       mov      eax, 0xFFFFDBFF
       bt       rax, rcx
       jb       SHORT G_M000_IG09
 
G_M000_IG07:                ;; offset=0x001B
       mov      eax, 1
 
G_M000_IG08:                ;; offset=0x0020
       ret      
 
G_M000_IG09:                ;; offset=0x0021
       cmp      ecx, 9
       sete     al
       movzx    rax, al
 
G_M000_IG10:                ;; offset=0x002A
       ret      

There are several things to improve here, but the most important is that the compare against 9 (in G_M000_IG09) is not made part of the switch - it should be part of the bittest.

The issue is that the JTRUE for the ch == 9 jumps to a different RETURN 1 block than the other JTRUEs. Tail merging only merges the RETURN 0 blocks for some reason:

*************** Starting PHASE Post-morph head and tail merge
A set of 2 return blocks end with the same tree
STMT00008 ( 0x014[E--] ... ??? )
               [000034] -----------                         *  RETURN    int   
               [000033] -----------                         \--*  CNS_INT   int    0
Will cross-jump to BB09

unlinking STMT00001 ( 0x01C[E--] ... 0x01D )
               [000005] -----+-----                         *  RETURN    int   
               [000025] -----+-----                         \--*  CNS_INT   int    0
 from BB07

BB07 becomes empty
setting likelihood of BB07 -> BB09 to 1

*************** Finishing PHASE Post-morph head and tail merge

So to fix this either tail merging should be made more aggressive (and also merge the RETURN 1) or switch recognition needs to deal with it.

Btw MSVC has the same issue.

Metadata

Metadata

Assignees

No one assigned

    Labels

    area-CodeGen-coreclrCLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMIuntriagedNew issue has not been triaged by the area owner

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions