Skip to content

JIT: Support constant folding back into SELECT (or branches in general) #132876

Description

@BoyBaykiller

Example: We could constant fold the addition by ten back into the SELECT arms (so basically int sel = wide ? 13 : 14):

https://godbolt.org/z/TdqzqbrcY

static int GetRex(bool wide)
{
    int sel = wide ? 3 : 4;
    int res = sel + 10;

    return res;
}
Program:GetRex(bool):int (FullOpts):
       mov      eax, 3
       mov      ecx, 4
       test     dil, dil
       cmove    eax, ecx
       add      eax, 10
       ret      

I've encountered this type of thing a few times now dealing with bit-op stuff.
Seems easy in theory, but lack of SSA folding or if-conversion currently running so late makes it near-unfeasible to recognize the shape.

------------ BB01 [0000] [000..003) -> BB04(1) (always), preds={} succs={BB04}

***** BB01 [0000]
STMT00003 ( 0x003[E--] ... 0x004 )
N008 ( 12, 12) [000012] DA---+-----                         *  STORE_LCL_VAR int    V02 tmp1         d:2 $VN.Void
N007 (  8,  9) [000019] -----------                         \--*  SELECT    int   
N004 (  5,  6) [000002] J----+-N---                            +--*  NE        int    $101
N002 (  3,  4) [000014] -----+-----                            |  +--*  CAST      int <- ubyte <- int $100
N001 (  2,  2) [000000] -----+-----                            |  |  \--*  LCL_VAR   int    V00 arg0         u:1 (last use) $80
N003 (  1,  1) [000001] -----+-----                            |  \--*  CNS_INT   int    0 $40
N005 (  1,  1) [000004] -----+-----                            +--*  CNS_INT   int    3 $43
N006 (  1,  1) [000011] -----+-----                            \--*  CNS_INT   int    4 $44

------------ BB04 [0003] [007..00B) (return), preds={BB01} succs={}

***** BB04 [0003]
STMT00002 ( ??? ... 0x00A )
N004 (  6,  5) [000010] -----+-----                         *  RETURN    int    $VN.Void
N003 (  5,  4) [000009] -----+-----                         \--*  ADD       int    $102
N001 (  3,  2) [000007] -----+-----                            +--*  LCL_VAR   int    V02 tmp1         u:3 (last use) $140
N002 (  1,  1) [000008] -----+-----                            \--*  CNS_INT   int    10 $45

Of course this could be applied to branches in general but that seems even harder without SSA, e.g:

static int ConstantFoldNoSelect(int a, int b)
{
    int res;
    if (a < b)
    {
        res = 3;
        Call();
    }
    else
    {
        res = 4;
    }
    res += 10;
    return res;

    static extern void Call();
}

Metadata

Metadata

Assignees

No one assigned

    Labels

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

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions