Arm64 SVE: CreateTrueMask has extra conversions when using a variable
- Dominant language
- C#
- Stars
- 18.3k
- Forks
- 5.6k
- PR merge metrics
- PR metrics pending
Description
```
public static Vector TrueMask(SveMaskPattern mask)
{
return Sve.CreateTrueMaskByte(mask);
}
```
Because a pattern is passed in as a variable instead of a constant, a call to the hwintrinsic function (with the switch statement inside) must be used.
This looks sensible:
```
***** BB01 [0000]
STMT00000 ( 0x000[E--] ... 0x006 )
N005 ( 6, 7) [000003] --CX-+----- * RETURN simd16 $VN.Void
N004 ( 5, 6) [000002] --CX-+----- \--* HWINTRINSIC simd16 16 ubyte ConvertMaskToVector $200
N003 ( 4, 5) [000001] --CX-+----- \--* HWINTRINSIC mask 16 ubyte CreateTrueMaskByte $180
N002 ( 3, 4) [000004] -----+----- \--* CAST int <- ubyte <- int $100
N001 ( 2, 2) [000000] -----+----- \--* LCL_VAR int V00 arg0 u:1 (last use) $80
```
During rationalisation
- a `ConvertVectorToMask` is inserted after the newly added CALL
- a `ConvertMaskToVector` is inserted before the RETURN
```
------------ BB01 [0000] [000..007) (return), preds={} succs={}
[000005] ----------- IL_OFFSET void INLRT @ 0x000[E--]
N001 ( 2, 2) [000000] ----------- t0 = LCL_VAR int V00 arg0 u:1 (last use) $80
/--* t0 int
N002 ( 3, 4) [000004] ----------- t4 = * CAST int <- ubyte <- int $100
/--* t4 int arg0 x0
N003 ( 17, 7) [000006] --C-G------ t6 = * CALL simd16 System.Runtime.Intrinsics.Arm.Sve:CreateTrueMaskByte(byte):System.Numerics.Vector`1[byte]
N004 ( 1, 1) [000007] ----------- t7 = HWINTRINSIC mask 16 ubyte ConversionTrueMask
/--* t7 mask
+--* t6 simd16
N005 ( 19, 9) [000008] --C-G------ t8 = * HWINTRINSIC mask 16 ubyte ConvertVectorToMask
/--* t8 mask
N004 ( 5, 6) [000002] --CXG+----- t2 = * HWINTRINSIC simd16 16 ubyte ConvertMaskToVector $200
/--* t2 simd16
N005 ( 6, 7) [000003] --CXG+----- * RETURN simd16 $VN.Void
```
Final assembly:
```
IN000a: 000000 stp fp, lr, [sp, #-0x10]!
IN000b: 000004 mov fp, sp
IN0001: 000008 uxtb w0, w0
IN0002: 00000C movz x1, #0x4498 // code for System.Runtime.Intrinsics.Arm.Sve:CreateTrueMaskByte(byte):System.Numerics.Vector`1[byte]
IN0003: 000010 movk x1, #0xBE11 LSL #16
IN0004: 000014 movk x1, #0xE1A7 LSL #32
IN0005: 000018 ldr x1, [x1]
IN0006: 00001C blr x1
IN0007: 000020 ptrue p0.b
IN0008: 000024 cmpne p0.b, p0/z, z0.b, #0
IN0009: 000028 mov z0.b, p0/z, #1
IN000c: 00002C ldp fp, lr, [sp], #0x10
IN000d: 000030 ret lr
```
The ptrue+cmpne+mov is pointless and should be removed.
There is already an optimisation to remove `ConvertVectorToMask` followed by `ConvertMaskToVector`, but this is in morph(?). We should add similar checks to lowering.
This is not high priority issue, as calling `CreateTrueMaskByte()` with a variable is already expected to be non-optimal. However, it might allow other opportunities.
Contributor guide
Assessment
This issue has not been assessed yet.