dotnet / dotnet/runtime

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

Open
#132,876 2 comments 0 reactions 0 assignees View on GitHub
area-CodeGen-coreclr
Dominant language
C#
Stars
18.3k
Forks
5.6k
PR merge metrics
PR metrics pending

Description

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
```cs
static int GetRex(bool wide)
{
int sel = wide ? 3 : 4;
int res = sel + 10;

return res;
}
```
```assembly
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:
```cs
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();
}
```

Contributor guide

Open the contributing guide

Research direction

Start with the linked Godbolt reproduction and compare the generated assembly for GetRex with the shown SELECT IR; the issue also provides ConstantFoldNoSelect as a harder branch case. Done means constant additions can fold into SELECT arms where valid, with the branch example remaining behaviorally correct.

Written by the indexing model from the issue text.

Assessment

Tech stack
csharp
Domain
compilers
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Active
Clarity
Mostly clear
Newbie friendliness
45/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.