Skip to content

Support loop cloning with struct arrays #48897

@BruceForstall

Description

@BruceForstall

Loop cloning, in optExtractArrIndex(), determines if there are interesting, optimizable array index expressions in a loop that can be optimized by removing the bounds check. It does not support array index expressions for arrays of structs.

E.g., for a simple byte array index b[i], it matches:

 *  COMMA     ubyte
 +--*  ARR_BOUNDS_CHECK_Rng void
 |  +--*  LCL_VAR   int    V03 loc2
 |  \--*  ARR_LENGTH int
 |     \--*  LCL_VAR   ref    V00 arg0
 \--*  IND       ubyte
    \--*  ADD       byref
       +--*  LCL_VAR   ref    V00 arg0
       \--*  ADD       long
          +--*  CAST      long <- int
          |  \--*  LCL_VAR   int    V03 loc2
          \--*  CNS_INT   long   16 Fseq[#FirstElem]

for a simple struct public struct B1 { public byte b1; }

accessing a[i] (such as in a b[i] = a[i] operation) gives:

\--*  COMMA     byref
   +--*  ARR_BOUNDS_CHECK_Rng void
   |  +--*  LCL_VAR   int    V03 loc0
   |  \--*  ARR_LENGTH int
   |     \--*  LCL_VAR   ref    V00 arg0
   \--*  ADDR      byref  Zero Fseq[b1]
      \--*  IND       struct
         \--*  ADD       byref
            +--*  LCL_VAR   ref    V00 arg0
            \--*  ADD       long
               +--*  CAST      long <- int
               |  \--*  LCL_VAR   int    V03 loc0
               \--*  CNS_INT   long   16 Fseq[#FirstElem]

or, accessing a[i].b1 gives:

\--*  COMMA     ubyte
   +--*  ARR_BOUNDS_CHECK_Rng void
   |  +--*  LCL_VAR   int    V03 loc1
   |  \--*  ARR_LENGTH int
   |     \--*  LCL_VAR   ref    V00 arg0
   \--*  IND       ubyte
      \--*  ADDR      byref  Zero Fseq[b1]
         \--*  IND       struct
            \--*  ADD       byref
               +--*  LCL_VAR   ref    V00 arg0
               \--*  ADD       long
                  +--*  CAST      long <- int
                  |  \--*  LCL_VAR   int    V03 loc1
                  \--*  CNS_INT   long   16 Fseq[#FirstElem]

Neither of these will be recognized.

There is also this code which is specifically trying to prevent handling structs, but it's not clear if it ever kicks in, given the current patterns:

    // It used to be the case that arrBndsChks for struct types would fail the previous check because
    // after->gtOper was an address (for a block op).  In order to avoid asmDiffs we will for now
    // return false if the type of 'after' is a struct type.  (This was causing us to clone loops
    // that we were not previously cloning.)
    // TODO-1stClassStructs: Remove this check to enable optimization of array bounds checks for struct
    // types.
    if (varTypeIsStruct(after))
    {
        return false;
    }

category:cq
theme:loop-opt
skill-level:expert
cost:large

Metadata

Metadata

Assignees

Labels

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

Type

No type

Projects

Status

Done

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions