Runtime: Support multi-dim arrays with the InitializeArray intrinsic

Created on 21 Mar 2016  路  10Comments  路  Source: dotnet/runtime

Compiler::impInitializeArrayIntrinsic in jit/importer.cpp has an early out for multi-dimensional arrays.

// In order to simplify the code, we won't support the multi-dim
// case.  Instead we simply return NULL, and the caller will insert 
// a run-time call to the helper.  Note that we can't assert
// failure here, because this is a valid case.

It would be nice if RyuJIT supported this. It would bring it to parity with the C++ codegen backend
used for .NET Native for UWP apps.

area-CodeGen-coreclr optimization up-for-grabs

Most helpful comment

I've put together a PR that adds support for multi-dimensional arrays that have all lower bounds = 0. It's not done yet but it seems to work fine with an example I tested:

``` C#
int[,] a = new int[,] { { 1, 2, 3 }, { 4, 3, 4 }, { 4, 5, 6 }, { 1, 2, 3 } };


   48B972EE27E0FD7F0000 mov      rcx, 0x7FFDE027EE72
   BA02000000           mov      edx, 2
   41B804000000         mov      r8d, 4
   41B903000000         mov      r9d, 3
   E8D0F9D05E           call     CORINFO_HELP_NEW_MDARR
   48BA582559A311020000 mov      rdx, 0x211A3592558
   4883C020             add      rax, 32
   C4E17A6F02           vmovdqu  ymm0, qword ptr [rdx]
   C4E17A7F00           vmovdqu  qword ptr [rax], ymm0
   C4E17A6F4210         vmovdqu  ymm0, qword ptr [rdx+16]
   C4E17A7F4010         vmovdqu  qword ptr [rax+16], ymm0
   C4E17A6F4220         vmovdqu  ymm0, qword ptr [rdx+32]
   C4E17A7F4020         vmovdqu  qword ptr [rax+32], ymm0

```

The question is... is it reasonable to compute the pointer to the array data by using a GT_ADD(TYP_REF, TYP_I_IMPL) -> TYP_BYREF node? Using a GenTreeArrElem node would work but it only supports arrays up to rank 3 and generates a lot of code.

All 10 comments

If the @dotnet/jit-contrib team agrees, we might want to tag this as "up-for-grabs". From my uneducated look, this doesn't seem too difficult to implement.

@dotnet/jit-contrib

Sounds like a good idea. "Up for grabs" sounds right without a pressing customer scenario and test case to justify doing this work sooner. Is there a particular test case from .NET native UWP where you noticed this missing with RyuJIT?

I think "up for grabs" sounds good, though it would probably be a non-trivial work item for someone not very familiar with the JIT. That said, I'm not sure there are other, more accessible, work items to designate as "up for grabs".

I noticed it on CoreRT. The .NET Native base class library doesn't have a fallback implementation of InitializeArray and relies on codegen to always expand it. A general purpose fallback implementation for a minimal runtime like CoreRT is relatively costly to implement (both in terms of size on disk hit from generating supporting data structures, and the amount of work to actually do it). We never had the need for it on .NET Native for UWP.

That said, there is a workitem to implement it on CoreRT (dotnet/corert#364), but codegen expansion will always be better.

An up-for-grabs JIT issue? I'll take a look as soon as I have some time :)

I've put together a PR that adds support for multi-dimensional arrays that have all lower bounds = 0. It's not done yet but it seems to work fine with an example I tested:

``` C#
int[,] a = new int[,] { { 1, 2, 3 }, { 4, 3, 4 }, { 4, 5, 6 }, { 1, 2, 3 } };


   48B972EE27E0FD7F0000 mov      rcx, 0x7FFDE027EE72
   BA02000000           mov      edx, 2
   41B804000000         mov      r8d, 4
   41B903000000         mov      r9d, 3
   E8D0F9D05E           call     CORINFO_HELP_NEW_MDARR
   48BA582559A311020000 mov      rdx, 0x211A3592558
   4883C020             add      rax, 32
   C4E17A6F02           vmovdqu  ymm0, qword ptr [rdx]
   C4E17A7F00           vmovdqu  qword ptr [rax], ymm0
   C4E17A6F4210         vmovdqu  ymm0, qword ptr [rdx+16]
   C4E17A7F4010         vmovdqu  qword ptr [rax+16], ymm0
   C4E17A6F4220         vmovdqu  ymm0, qword ptr [rdx+32]
   C4E17A7F4020         vmovdqu  qword ptr [rax+32], ymm0

```

The question is... is it reasonable to compute the pointer to the array data by using a GT_ADD(TYP_REF, TYP_I_IMPL) -> TYP_BYREF node? Using a GenTreeArrElem node would work but it only supports arrays up to rank 3 and generates a lot of code.

@MichalStrehovsky Do you think it's worth supporting arrays with lower bounds != 0? C# doesn't directly support such arrays so the compiler will never generate a call to InitializeArray.

Do you think it's worth supporting arrays with lower bounds != 0? C# doesn't directly support such arrays

C# doesn't, but there could be a different compiler that does support it (VB used to allow that, but now it screams at me when I try anything but 0, so I guess they dropped it).

That said, .NET Native currently doesn't support non-zero lower bounds and since I'm a .NET Native guy, I don't have concerns about not supporting it in the codegen.

OK, I ended up adding support for such arrays anyway. The whole thing is trivial anyway except the IL tests and the pesky x86 call arg ordering. I'll have it ready for review by Monday, assuming that anyone from the JIT team has time for review...

Was this page helpful?
0 / 5 - 0 ratings

Related issues

matty-hall picture matty-hall  路  3Comments

sahithreddyk picture sahithreddyk  路  3Comments

omajid picture omajid  路  3Comments

GitAntoinee picture GitAntoinee  路  3Comments

jkotas picture jkotas  路  3Comments