Skip to content

RyuJIT: Eliminate unnecessary copies after struct fields are p-indep promoted in Frame:CreateResponseHeader(ref,bool):this #6745

Description

@sivarv

Here is the IR and code generated:

N245 (  1,  1) [000466] ------------      t466 =    const     ref    null REG rcx $VN.Null

                                                 /--*  t466   ref    
N247 (  5,  4) [000468] DA--G-------             *  st.lclVar ref    V57 tmp48        d:3 rbx REG rbx RV

N249 (  3,  2) [000987] -------N----      t987 =    lclVar    ref    V56 tmp47        u:3 rdx (last use) REG rdx RV $2aa

                                                 /--*  t987   ref    
N251 (  7,  5) [000988] DA----------             *  st.lclVar ref    V54 tmp45        d:3 rdx REG rdx RV

N253 (  3,  2) [000990] -------N----      t990 =    lclVar    ref    V57 tmp48        u:3 rbx (last use) REG rbx RV $VN.Null

                                                 /--*  t990   ref    
N255 (  7,  5) [000991] DA----------             *  st.lclVar ref    V55 tmp46        d:3 rcx REG rcx RV

N257 (  3,  2) [000994] -------N----      t994 =    lclVar    ref    V54 tmp45        u:3 rdx (last use) REG rdx RV $2aa

                                                 /--*  t994   ref    
N259 (  7,  5) [000995] DA----------             *  st.lclVar ref    V58 tmp49        d:3 rdx REG rdx RV

N261 (  3,  2) [000997] -------N----      t997 =    lclVar    ref    V55 tmp46        u:3 rcx (last use) REG rcx RV $VN.Null

                                                 /--*  t997   ref    
N263 (  7,  5) [000998] DA----------             *  st.lclVar ref    V59 tmp50        d:3 rbx REG rbx RV

Here are the assignments:
V56 = indir(some const addr)
V57 = null   ; xor rbx, rbx
V54 = V56   ; both get rdx and hence no mov gets generated. V56 last use here
V55 = V57  ;  mov rcx, rbx ; V57 last use here
V58 = V54  ;  both get rdx and hence no mov gets generated. V54 last use here. V58 is used later
V59 = V55  ;  mov rbx, rcx ; V59 was assigned rbx. V59 is used later


33DB                 xor      rbx, rbx
488BCB               mov      rcx, rbx
488BD9               mov      rbx, rcx
48B9385618DF1C010000 mov      rcx, 0x11CDF185638

As you can see we have two separate chains of assignment

  1. indir(some const addr) --> V56 --> V54 --> V58
  2. null --> V57 --> V55 --> V59

LSRA got its preferencing right for first chain and there were no redundant moves.
In the second chain, it didn't get preferencing right and lead to redundant moves.

If RyuJIT did copy prop we could reduce both chains of assignment to

i) V58 = indir(some constant addr)
ii) V59 = null

In general it is good to avoid these redundant assignments by copy propagation. Prior to rationalization, these assignments were part of a GT_COMMA tree and that could be the reason why copy propagation might have not taken palce?

***** BB10, stmt 21
     (  5,  4) [000469] ------------             *  stmtExpr  void  (IL 0x085...  ???)
N001 (  1,  1) [000466] ------------             |  /--*  const     ref    null $VN.Null
N003 (  5,  4) [000468] -A--G---R---             \--*  =         ref    $VN.Null
N002 (  3,  2) [000467] D------N----                \--*  lclVar    ref    V57 tmp48        d:3 $VN.Null

***** BB10, stmt 22
     ( 14, 10) [000339] ------------             *  stmtExpr  void  (IL   ???...  ???)
N004 (  3,  2) [000990] -------N----             |     /--*  lclVar    ref    V57 tmp48        u:3 (last use) $VN.Null
N006 (  7,  5) [000991] -A------R---             |  /--*  =         ref    $VN.Null
N005 (  3,  2) [000989] D------N----             |  |  \--*  lclVar    ref    V55 tmp46        d:3 $VN.Null
N007 ( 14, 10) [000992] -A----------             \--*  comma     void   $VN.Null
N001 (  3,  2) [000987] -------N----                |  /--*  lclVar    ref    V56 tmp47        u:3 (last use) $2aa
N003 (  7,  5) [000988] -A------R---                \--*  =         ref    $2aa
N002 (  3,  2) [000986] D------N----                   \--*  lclVar    ref    V54 tmp45        d:3 $2aa

***** BB10, stmt 23
     ( 14, 10) [000502] ------------             *  stmtExpr  void  (IL   ???...  ???)
N004 (  3,  2) [000997] -------N----             |     /--*  lclVar    ref    V55 tmp46        u:3 (last use) $VN.Null
N006 (  7,  5) [000998] -A------R---             |  /--*  =         ref    $VN.Null
N005 (  3,  2) [000996] D------N----             |  |  \--*  lclVar    ref    V59 tmp50        d:3 $VN.Null
N007 ( 14, 10) [000999] -A----------             \--*  comma     void   $VN.Null
N001 (  3,  2) [000994] -------N----                |  /--*  lclVar    ref    V54 tmp45        u:3 (last use) $2aa
N003 (  7,  5) [000995] -A------R---                \--*  =         ref    $2aa
N002 (  3,  2) [000993] D------N----                   \--*  lclVar    ref    V58 tmp49        d:3 $2aa

Similar redundant assignments/copies occur at 6 different places within the same method.

category:cq
theme:copy-prop
skill-level:expert
cost:medium

Metadata

Metadata

Assignees

No one assigned

    Labels

    area-CodeGen-coreclrCLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMIenhancementProduct code improvement that does NOT require public API changes/additionsoptimizationtenet-performancePerformance related issue

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions