Repository navigation
JIT: suboptimal block layout #76872
Copy link
Copy link
Closed
Labels
area-CodeGen-coreclrCLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMICLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMIhelp wanted[up-for-grabs] Good issue for external contributors[up-for-grabs] Good issue for external contributors
Milestone
Description
bool M(string a) => "b" == a;Emits:
; Method P:M(System.String):bool:this
G_M31338_IG01:
G_M31338_IG02:
test rdx, rdx
je SHORT G_M31338_IG06
G_M31338_IG03:
cmp dword ptr [rdx+08H], 1
jne SHORT G_M31338_IG05
G_M31338_IG04:
xor eax, eax
cmp word ptr [rdx+0CH], 98
sete al
jmp SHORT G_M31338_IG07
G_M31338_IG05:
xor eax, eax
jmp SHORT G_M31338_IG07
G_M31338_IG06:
xor eax, eax
G_M31338_IG07:
ret
; Total bytes of code: 30It seems like IG05 (BB05) block is redundant:
Trees after Optimize layout
-----------------------------------------------------------------------------------------------------------------------------------------
BBnum BBid ref try hnd preds weight lp [IL range] [jump] [EH region] [flags]
-----------------------------------------------------------------------------------------------------------------------------------------
BB01 [0000] 1 1 [000..000)-> BB05 ( cond ) i
BB02 [0005] 1 BB01 0.25 [???..???)-> BB04 ( cond ) i
BB03 [0009] 1 BB02 0.12 [???..???)-> BB06 (always) i
BB04 [0008] 1 BB02 0.25 [???..???)-> BB06 (always) i
BB05 [0004] 1 BB01 0.25 [???..???) i
BB06 [0002] 3 BB03,BB04,BB05 1 [000..00C) (return) i
-----------------------------------------------------------------------------------------------------------------------------------------
------------ BB01 [000..000) -> BB05 (cond), preds={} succs={BB02,BB05}
***** BB01
STMT00004 ( INL01 @ ??? ... ??? ) <- INLRT @ 0x000[E-]
N004 ( 5, 5) [000034] ----------- * JTRUE void $VN.Void
N003 ( 3, 3) [000025] J------N--- \--* EQ int $100
N001 ( 1, 1) [000010] ----------- +--* LCL_VAR ref V01 arg1 u:1 $80
N002 ( 1, 1) [000024] ----------- \--* CNS_INT ref null $VN.Null
------------ BB02 [???..???) -> BB04 (cond), preds={BB01} succs={BB03,BB04}
***** BB02
STMT00007 ( INL01 @ ??? ... ??? ) <- INLRT @ 0x000[E-]
N007 ( 8, 8) [000039] -----O----- * JTRUE void $241
N006 ( 6, 6) [000020] J----O?N--- \--* NE int <l:$106, c:$105>
N004 ( 4, 4) [000009] n----O?---- +--* IND int <l:$102, c:$101>
N003 ( 2, 2) [000008] ------?N--- | \--* ADD byref $180
N001 ( 1, 1) [000006] ------?---- | +--* LCL_VAR ref V01 arg1 u:1 $80
N002 ( 1, 1) [000007] ------?---- | \--* CNS_INT long 8 $140
N005 ( 1, 1) [000011] ------?---- \--* CNS_INT int 1 $40
------------ BB03 [???..???) -> BB06 (always), preds={BB02} succs={BB06}
***** BB03
STMT00008 ( INL01 @ ??? ... ??? ) <- INLRT @ 0x000[E-]
N008 ( 10, 7) [000041] -A---O--R-- * ASG int $241
N007 ( 1, 1) [000040] D------N--- +--* LCL_VAR int V04 tmp2 d:4 $VN.Void
N006 ( 10, 7) [000017] -----O?---- \--* EQ int <l:$10a, c:$109>
N004 ( 5, 5) [000015] n----O?---- +--* IND short <l:$301, c:$300>
N003 ( 2, 2) [000014] ------?N--- | \--* ADD byref $181
N001 ( 1, 1) [000012] ------?---- | +--* LCL_VAR ref V01 arg1 u:1 (last use) $80
N002 ( 1, 1) [000013] ------?---- | \--* CNS_INT long 12 $141
N005 ( 1, 1) [000016] ------?---- \--* CNS_INT int 98 $45
------------ BB04 [???..???) -> BB06 (always), preds={BB02} succs={BB06}
***** BB04
STMT00009 ( INL01 @ ??? ... ??? ) <- INLRT @ 0x000[E-]
N003 ( 1, 3) [000043] -A------R-- * ASG int $VN.Void
N002 ( 1, 1) [000042] D------N--- +--* LCL_VAR int V04 tmp2 d:3 $VN.Void
N001 ( 1, 1) [000018] ------?---- \--* CNS_INT int 0 $42
------------ BB05 [???..???), preds={BB01} succs={BB06}
***** BB05
STMT00006 ( INL01 @ ??? ... ??? ) <- INLRT @ 0x000[E-]
N003 ( 1, 3) [000038] -A------R-- * ASG int $VN.Void
N002 ( 1, 1) [000037] D------N--- +--* LCL_VAR int V04 tmp2 d:2 $VN.Void
N001 ( 1, 1) [000022] ------?---- \--* CNS_INT int 0 $42
------------ BB06 [000..00C) (return), preds={BB03,BB04,BB05} succs={}
***** BB06
STMT00010 ( ??? ... ??? )
N006 ( 0, 0) [000046] -A------R-- * ASG int $VN.Void
N005 ( 0, 0) [000044] D------N--- +--* LCL_VAR int V04 tmp2 d:1 $VN.Void
N004 ( 0, 0) [000045] ----------- \--* PHI int $1c1
N001 ( 0, 0) [000049] ----------- pred BB03 +--* PHI_ARG int V04 tmp2 u:4 <l:$107, c:$108>
N002 ( 0, 0) [000048] ----------- pred BB04 +--* PHI_ARG int V04 tmp2 u:3 $42
N003 ( 0, 0) [000047] ----------- pred BB05 \--* PHI_ARG int V04 tmp2 u:2 $42
***** BB06
STMT00001 ( 0x000[E-] ... ??? )
N002 ( 2, 2) [000004] ----------- * RETURN int $VN.Void
N001 ( 1, 1) [000031] ----------- \--* LCL_VAR int V04 tmp2 u:1 (last use) $1c1
BB04 and BB05 are exactly the same and have the same successor
Metadata
Metadata
Assignees
Labels
area-CodeGen-coreclrCLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMICLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMIhelp wanted[up-for-grabs] Good issue for external contributors[up-for-grabs] Good issue for external contributors

Activity
EgorBo commentedon Oct 11, 2022
cc @AndyAyersMS
jakobbotsch commentedon Oct 11, 2022
Related: #8795
EgorBo commentedon Oct 11, 2022
is it? here we don't merge tails (multiple returns) but just try to merge equal blocks with the same successor, it doesn't have to be a tail 🙂
jakobbotsch commentedon Oct 11, 2022
I don't think tail merging necessarily has to mean the tail of functions, it can cover merging the tails of two basic blocks in general (i.e. same instructions, same terminator)
#8795 seems like it uses the more general description, doesn't it? I guess its particular wording still doesn't cover this case completely though.
EgorBo commentedon Oct 11, 2022
IMO it's too abstract to ever be closed while this one represents a concrete (popular) case that we can handle
jakobbotsch commentedon Oct 11, 2022
Yeah, I think considering the special cases is valuable. But we should just be mindful that we get the mileage out of the transformation we can, for example it might not be too difficult to generalize some parts of "fold identical BBs" to be more like general tail merging.
AndyAyersMS commentedon Oct 12, 2022
It is good to keep the more general optimizations in mind. Tail merging (and its dual, head merging) require developing quick and reliable ways to compare trees, something we currently lack.
Generalizations of tail merging that consider reorderable or semantically equivalent but syntactically different computations are probably too costly for us to consider.
AndyAyersMS commentedon Oct 15, 2022
Note in debug we have
gtHashValuewhich if made available in release could be used as a preliminary screen for head or tail merge opportunities.JIT: implement tail merging
AndyAyersMS commentedon Oct 17, 2022
Codegen with #77103:
JIT: implement tail merging (#77103)