From 45611c195a4699b654d21ed0c84e2d9e13b5de4c Mon Sep 17 00:00:00 2001 From: Will Smith Date: Thu, 3 Feb 2022 16:05:51 -0800 Subject: [PATCH 01/14] Normalizing instructions with an implicit vector zero as the second operand --- src/coreclr/jit/hwintrinsiccodegenarm64.cpp | 64 +++++++++++++-------- src/coreclr/jit/hwintrinsiclistarm64.h | 6 +- 2 files changed, 43 insertions(+), 27 deletions(-) diff --git a/src/coreclr/jit/hwintrinsiccodegenarm64.cpp b/src/coreclr/jit/hwintrinsiccodegenarm64.cpp index 6dfe48047c094e..d5234e638106c8 100644 --- a/src/coreclr/jit/hwintrinsiccodegenarm64.cpp +++ b/src/coreclr/jit/hwintrinsiccodegenarm64.cpp @@ -364,7 +364,46 @@ void CodeGen::genHWIntrinsic(GenTreeHWIntrinsic* node) { assert(!hasImmediateOperand); - switch (intrin.numOperands) + size_t numOperands = intrin.numOperands; + + // This handles optimizations for instructions that have + // an implicit 'zero' vector of what would be the second operand. + if ((intrin.op2->IsVectorZero() && intrin.op2->isContained()) || + (intrin.op1->IsVectorZero() && intrin.op1->isContained() && + HWIntrinsicInfo::IsCommutative(intrin.id))) + { + assert(HWIntrinsicInfo::SupportsContainment(intrin.id)); + + if (intrin.op1->IsVectorZero() && intrin.op1->isContained() && + HWIntrinsicInfo::IsCommutative(intrin.id)) + { + // The intrinsic is commutative, swap the registers. + op1Reg = op2Reg; + } + + switch (ins) + { + case INS_cmeq: + case INS_cmge: + case INS_cmgt: + case INS_cmle: + case INS_cmlt: + case INS_fcmeq: + case INS_fcmge: + case INS_fcmgt: + case INS_fcmle: + case INS_fcmlt: + { + assert(numOperands == 2); + numOperands -= 1; + } + + default: + unreached(); + } + } + + switch (numOperands) { case 1: GetEmitter()->emitIns_R_R(ins, emitSize, targetReg, op1Reg, opt); @@ -499,29 +538,6 @@ void CodeGen::genHWIntrinsic(GenTreeHWIntrinsic* node) GetEmitter()->emitIns_R_R_R(ins, emitSize, targetReg, op1Reg, op2Reg, opt); break; - case NI_AdvSimd_CompareEqual: - case NI_AdvSimd_Arm64_CompareEqual: - case NI_AdvSimd_Arm64_CompareEqualScalar: - if (intrin.op1->isContained()) - { - assert(HWIntrinsicInfo::SupportsContainment(intrin.id)); - assert(intrin.op1->IsVectorZero()); - - GetEmitter()->emitIns_R_R(ins, emitSize, targetReg, op2Reg, opt); - } - else if (intrin.op2->isContained()) - { - assert(HWIntrinsicInfo::SupportsContainment(intrin.id)); - assert(intrin.op2->IsVectorZero()); - - GetEmitter()->emitIns_R_R(ins, emitSize, targetReg, op1Reg, opt); - } - else - { - GetEmitter()->emitIns_R_R_R(ins, emitSize, targetReg, op1Reg, op2Reg, opt); - } - break; - case NI_AdvSimd_AbsoluteCompareLessThan: case NI_AdvSimd_AbsoluteCompareLessThanOrEqual: case NI_AdvSimd_CompareLessThan: diff --git a/src/coreclr/jit/hwintrinsiclistarm64.h b/src/coreclr/jit/hwintrinsiclistarm64.h index 7d4582db97616a..8bf189d0b19472 100644 --- a/src/coreclr/jit/hwintrinsiclistarm64.h +++ b/src/coreclr/jit/hwintrinsiclistarm64.h @@ -240,7 +240,7 @@ HARDWARE_INTRINSIC(AdvSimd, BitwiseClear, HARDWARE_INTRINSIC(AdvSimd, BitwiseSelect, -1, 3, {INS_bsl, INS_bsl, INS_bsl, INS_bsl, INS_bsl, INS_bsl, INS_bsl, INS_bsl, INS_bsl, INS_bsl}, HW_Category_SIMD, HW_Flag_SpecialCodeGen) HARDWARE_INTRINSIC(AdvSimd, Ceiling, -1, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_frintp, INS_invalid}, HW_Category_SIMD, HW_Flag_NoFlag) HARDWARE_INTRINSIC(AdvSimd, CeilingScalar, 8, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_frintp, INS_frintp}, HW_Category_SIMD, HW_Flag_SIMDScalar) -HARDWARE_INTRINSIC(AdvSimd, CompareEqual, -1, 2, {INS_cmeq, INS_cmeq, INS_cmeq, INS_cmeq, INS_cmeq, INS_cmeq, INS_invalid, INS_invalid, INS_fcmeq, INS_invalid}, HW_Category_SIMD, HW_Flag_Commutative|HW_Flag_SpecialCodeGen|HW_Flag_SupportsContainment) +HARDWARE_INTRINSIC(AdvSimd, CompareEqual, -1, 2, {INS_cmeq, INS_cmeq, INS_cmeq, INS_cmeq, INS_cmeq, INS_cmeq, INS_invalid, INS_invalid, INS_fcmeq, INS_invalid}, HW_Category_SIMD, HW_Flag_Commutative|HW_Flag_SupportsContainment) HARDWARE_INTRINSIC(AdvSimd, CompareGreaterThan, -1, 2, {INS_cmgt, INS_cmhi, INS_cmgt, INS_cmhi, INS_cmgt, INS_cmhi, INS_invalid, INS_invalid, INS_fcmgt, INS_invalid}, HW_Category_SIMD, HW_Flag_NoFlag) HARDWARE_INTRINSIC(AdvSimd, CompareGreaterThanOrEqual, -1, 2, {INS_cmge, INS_cmhs, INS_cmge, INS_cmhs, INS_cmge, INS_cmhs, INS_invalid, INS_invalid, INS_fcmge, INS_invalid}, HW_Category_SIMD, HW_Flag_NoFlag) HARDWARE_INTRINSIC(AdvSimd, CompareLessThan, -1, 2, {INS_cmgt, INS_cmhi, INS_cmgt, INS_cmhi, INS_cmgt, INS_cmhi, INS_invalid, INS_invalid, INS_fcmgt, INS_invalid}, HW_Category_SIMD, HW_Flag_SpecialCodeGen) @@ -492,8 +492,8 @@ HARDWARE_INTRINSIC(AdvSimd_Arm64, AddPairwiseScalar, HARDWARE_INTRINSIC(AdvSimd_Arm64, AddSaturate, -1, 2, {INS_suqadd, INS_usqadd, INS_suqadd, INS_usqadd, INS_suqadd, INS_usqadd, INS_suqadd, INS_usqadd, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_BaseTypeFromFirstArg|HW_Flag_HasRMWSemantics) HARDWARE_INTRINSIC(AdvSimd_Arm64, AddSaturateScalar, 8, 2, {INS_sqadd, INS_uqadd, INS_sqadd, INS_uqadd, INS_sqadd, INS_uqadd, INS_suqadd, INS_usqadd, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_BaseTypeFromFirstArg|HW_Flag_HasRMWSemantics|HW_Flag_SIMDScalar|HW_Flag_SpecialCodeGen) HARDWARE_INTRINSIC(AdvSimd_Arm64, Ceiling, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_frintp}, HW_Category_SIMD, HW_Flag_NoFlag) -HARDWARE_INTRINSIC(AdvSimd_Arm64, CompareEqual, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cmeq, INS_cmeq, INS_invalid, INS_fcmeq}, HW_Category_SIMD, HW_Flag_Commutative|HW_Flag_SpecialCodeGen|HW_Flag_SupportsContainment) -HARDWARE_INTRINSIC(AdvSimd_Arm64, CompareEqualScalar, 8, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cmeq, INS_cmeq, INS_fcmeq, INS_fcmeq}, HW_Category_SIMD, HW_Flag_Commutative|HW_Flag_SIMDScalar|HW_Flag_SpecialCodeGen|HW_Flag_SupportsContainment) +HARDWARE_INTRINSIC(AdvSimd_Arm64, CompareEqual, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cmeq, INS_cmeq, INS_invalid, INS_fcmeq}, HW_Category_SIMD, HW_Flag_Commutative|HW_Flag_SupportsContainment) +HARDWARE_INTRINSIC(AdvSimd_Arm64, CompareEqualScalar, 8, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cmeq, INS_cmeq, INS_fcmeq, INS_fcmeq}, HW_Category_SIMD, HW_Flag_Commutative|HW_Flag_SIMDScalar|HW_Flag_SupportsContainment) HARDWARE_INTRINSIC(AdvSimd_Arm64, CompareGreaterThan, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cmgt, INS_cmhi, INS_invalid, INS_fcmgt}, HW_Category_SIMD, HW_Flag_NoFlag) HARDWARE_INTRINSIC(AdvSimd_Arm64, CompareGreaterThanOrEqual, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cmge, INS_cmhs, INS_invalid, INS_fcmge}, HW_Category_SIMD, HW_Flag_NoFlag) HARDWARE_INTRINSIC(AdvSimd_Arm64, CompareGreaterThanOrEqualScalar, 8, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cmge, INS_cmhs, INS_fcmge, INS_fcmge}, HW_Category_SIMD, HW_Flag_SIMDScalar) From fcabd8fd6c17772cfc19d04b9de8c36d159758cb Mon Sep 17 00:00:00 2001 From: Will Smith Date: Thu, 3 Feb 2022 16:32:00 -0800 Subject: [PATCH 02/14] Checking number of operands before looking at opernads --- src/coreclr/jit/hwintrinsiccodegenarm64.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/coreclr/jit/hwintrinsiccodegenarm64.cpp b/src/coreclr/jit/hwintrinsiccodegenarm64.cpp index d5234e638106c8..cbfebb90c57bd2 100644 --- a/src/coreclr/jit/hwintrinsiccodegenarm64.cpp +++ b/src/coreclr/jit/hwintrinsiccodegenarm64.cpp @@ -368,9 +368,10 @@ void CodeGen::genHWIntrinsic(GenTreeHWIntrinsic* node) // This handles optimizations for instructions that have // an implicit 'zero' vector of what would be the second operand. - if ((intrin.op2->IsVectorZero() && intrin.op2->isContained()) || + if ((numOperands == 2) && + ((intrin.op2->IsVectorZero() && intrin.op2->isContained()) || (intrin.op1->IsVectorZero() && intrin.op1->isContained() && - HWIntrinsicInfo::IsCommutative(intrin.id))) + HWIntrinsicInfo::IsCommutative(intrin.id)))) { assert(HWIntrinsicInfo::SupportsContainment(intrin.id)); @@ -378,7 +379,9 @@ void CodeGen::genHWIntrinsic(GenTreeHWIntrinsic* node) HWIntrinsicInfo::IsCommutative(intrin.id)) { // The intrinsic is commutative, swap the registers. + assert(op1Reg == REG_NA); op1Reg = op2Reg; + op2Reg = REG_NA; } switch (ins) @@ -396,6 +399,7 @@ void CodeGen::genHWIntrinsic(GenTreeHWIntrinsic* node) { assert(numOperands == 2); numOperands -= 1; + break; } default: From b46af4ba4ef8e6a078cbba466a6b5cee864def54 Mon Sep 17 00:00:00 2001 From: Will Smith Date: Thu, 3 Feb 2022 16:33:20 -0800 Subject: [PATCH 03/14] Remove assert --- src/coreclr/jit/hwintrinsiccodegenarm64.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/coreclr/jit/hwintrinsiccodegenarm64.cpp b/src/coreclr/jit/hwintrinsiccodegenarm64.cpp index cbfebb90c57bd2..b9e4c34fa6dea9 100644 --- a/src/coreclr/jit/hwintrinsiccodegenarm64.cpp +++ b/src/coreclr/jit/hwintrinsiccodegenarm64.cpp @@ -397,7 +397,6 @@ void CodeGen::genHWIntrinsic(GenTreeHWIntrinsic* node) case INS_fcmle: case INS_fcmlt: { - assert(numOperands == 2); numOperands -= 1; break; } From 9fe70b11052705325930198a4a31e6a6fc85d9de Mon Sep 17 00:00:00 2001 From: Will Smith Date: Thu, 3 Feb 2022 16:34:30 -0800 Subject: [PATCH 04/14] Check commutative flag --- src/coreclr/jit/lowerarmarch.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/coreclr/jit/lowerarmarch.cpp b/src/coreclr/jit/lowerarmarch.cpp index 41b80fbee67233..80d24bc032f980 100644 --- a/src/coreclr/jit/lowerarmarch.cpp +++ b/src/coreclr/jit/lowerarmarch.cpp @@ -1968,7 +1968,7 @@ void Lowering::ContainCheckHWIntrinsic(GenTreeHWIntrinsic* node) case NI_AdvSimd_Arm64_CompareEqual: case NI_AdvSimd_Arm64_CompareEqualScalar: { - if (intrin.op1->IsVectorZero()) + if (intrin.op1->IsVectorZero() && intrin.op1->isCommutativeHWIntrinsic()) { MakeSrcContained(node, intrin.op1); } From 1c5808800757e7c5058fcf6ae5353099fbf52e83 Mon Sep 17 00:00:00 2001 From: Will Smith Date: Thu, 3 Feb 2022 16:53:29 -0800 Subject: [PATCH 05/14] Fixed commutative check --- src/coreclr/jit/emitarm64.cpp | 2 +- src/coreclr/jit/instrsarm64.h | 42 ++++++++++++++++---------------- src/coreclr/jit/lowerarmarch.cpp | 2 +- 3 files changed, 23 insertions(+), 23 deletions(-) diff --git a/src/coreclr/jit/emitarm64.cpp b/src/coreclr/jit/emitarm64.cpp index 52f24d4524279d..884f03c14c132f 100644 --- a/src/coreclr/jit/emitarm64.cpp +++ b/src/coreclr/jit/emitarm64.cpp @@ -12995,7 +12995,7 @@ void emitter::emitDispIns( emitDispVectorReg(id->idReg1(), id->idInsOpt(), true); emitDispVectorReg(id->idReg2(), id->idInsOpt(), false); } - if (ins == INS_cmeq) + if (ins == INS_cmeq || ins == INS_cmge || ins == INS_cmgt || ins == INS_cmle || ins == INS_cmlt) { printf(", "); emitDispImm(0, false); diff --git a/src/coreclr/jit/instrsarm64.h b/src/coreclr/jit/instrsarm64.h index d4e7ef5b10c8d6..294dcf0b219d8a 100644 --- a/src/coreclr/jit/instrsarm64.h +++ b/src/coreclr/jit/instrsarm64.h @@ -318,33 +318,33 @@ INST4(cmeq, "cmeq", 0, IF_EN4H, 0x7EE08C00, 0x2E208C00, INST4(cmge, "cmge", 0, IF_EN4H, 0x5EE03C00, 0x0E203C00, 0x7E208800, 0x2E208800) // cmge Vd,Vn,Vm DV_3E 01011110111mmmmm 001111nnnnnddddd 5EE0 3C00 Vd,Vn,Vm (scalar) // cmge Vd,Vn,Vm DV_3A 0Q001110XX1mmmmm 001111nnnnnddddd 0E20 3C00 Vd,Vn,Vm (vector) - // cmge Vd,Vn DV_2L 01111110XX100000 100010nnnnnddddd 5E20 8800 Vd,Vn (scalar) - // cmge Vd,Vn DV_2M 0Q101110XX100000 100010nnnnnddddd 2E20 8800 Vd,Vn (vector) + // cmge Vd,Vn,#0 DV_2L 01111110XX100000 100010nnnnnddddd 5E20 8800 Vd,Vn,#0 (scalar - with zero) + // cmge Vd,Vn,#0 DV_2M 0Q101110XX100000 100010nnnnnddddd 2E20 8800 Vd,Vn,#0 (vector - with zero) INST4(cmgt, "cmgt", 0, IF_EN4H, 0x5EE03400, 0x0E203400, 0x5E208800, 0x0E208800) // cmgt Vd,Vn,Vm DV_3E 01011110111mmmmm 001101nnnnnddddd 5EE0 3400 Vd,Vn,Vm (scalar) // cmgt Vd,Vn,Vm DV_3A 0Q001110XX1mmmmm 001101nnnnnddddd 0E20 3400 Vd,Vn,Vm (vector) - // cmgt Vd,Vn DV_2L 01011110XX100000 100010nnnnnddddd 5E20 8800 Vd,Vn (scalar) - // cmgt Vd,Vn DV_2M 0Q001110XX100000 101110nnnnnddddd 0E20 8800 Vd,Vn (vector) + // cmgt Vd,Vn,#0 DV_2L 01011110XX100000 100010nnnnnddddd 5E20 8800 Vd,Vn,#0 (scalar - with zero) + // cmgt Vd,Vn,#0 DV_2M 0Q001110XX100000 101110nnnnnddddd 0E20 8800 Vd,Vn,#0 (vector - with zero) // enum name info DV_3D DV_3B DV_2G DV_2A INST4(fcmeq, "fcmeq", 0, IF_EN4I, 0x5E20E400, 0x0E20E400, 0x5EA0D800, 0x0EA0D800) - // fcmeq Vd,Vn,Vm DV_3D 010111100X1mmmmm 111001nnnnnddddd 5E20 E400 Vd Vn Vm (scalar) + // fcmeq Vd,Vn,Vm DV_3D 010111100X1mmmmm 111001nnnnnddddd 5E20 E400 Vd,Vn,Vm (scalar) // fcmeq Vd,Vn,Vm DV_3B 0Q0011100X1mmmmm 111001nnnnnddddd 0E20 E400 Vd,Vn,Vm (vector) - // fcmeq Vd,Vn,#0 DV_2G 010111101X100000 110110nnnnnddddd 5EA0 D800 Vd Vn,#0 (scalar - with zero) - // fcmeq Vd,Vn,#0 DV_2A 0Q0011101X100000 110110nnnnnddddd 0EA0 D800 Vd Vn,#0 (vector - with zero) + // fcmeq Vd,Vn,#0 DV_2G 010111101X100000 110110nnnnnddddd 5EA0 D800 Vd,Vn,#0 (scalar - with zero) + // fcmeq Vd,Vn,#0 DV_2A 0Q0011101X100000 110110nnnnnddddd 0EA0 D800 Vd,Vn,#0 (vector - with zero) INST4(fcmge, "fcmge", 0, IF_EN4I, 0x7E20E400, 0x2E20E400, 0x7EA0C800, 0x2EA0C800) - // fcmge Vd,Vn,Vm DV_3D 011111100X1mmmmm 111001nnnnnddddd 7E20 E400 Vd Vn Vm (scalar) + // fcmge Vd,Vn,Vm DV_3D 011111100X1mmmmm 111001nnnnnddddd 7E20 E400 Vd,Vn,Vm (scalar) // fcmge Vd,Vn,Vm DV_3B 0Q1011100X1mmmmm 111001nnnnnddddd 2E20 E400 Vd,Vn,Vm (vector) - // fcmge Vd,Vn DV_2G 011111101X100000 110010nnnnnddddd 7EA0 E800 Vd Vn (scalar) - // fcmge Vd,Vn DV_2A 0Q1011101X100000 110010nnnnnddddd 2EA0 C800 Vd Vn (vector) + // fcmge Vd,Vn,#0 DV_2G 011111101X100000 110010nnnnnddddd 7EA0 E800 Vd,Vn,#0 (scalar - with zero) + // fcmge Vd,Vn,#0 DV_2A 0Q1011101X100000 110010nnnnnddddd 2EA0 C800 Vd,Vn,#0 (vector - with zero) INST4(fcmgt, "fcmgt", 0, IF_EN4I, 0x7EA0E400, 0x2EA0E400, 0x5EA0C800, 0x0EA0C800) - // fcmgt Vd,Vn,Vm DV_3D 011111101X1mmmmm 111001nnnnnddddd 7EA0 E400 Vd Vn Vm (scalar) + // fcmgt Vd,Vn,Vm DV_3D 011111101X1mmmmm 111001nnnnnddddd 7EA0 E400 Vd,Vn,Vm (scalar) // fcmgt Vd,Vn,Vm DV_3B 0Q1011101X1mmmmm 111001nnnnnddddd 2EA0 E400 Vd,Vn,Vm (vector) - // fcmgt Vd,Vn DV_2G 010111101X100000 110010nnnnnddddd 5EA0 E800 Vd Vn (scalar) - // fcmgt Vd,Vn DV_2A 0Q0011101X100000 110010nnnnnddddd 0EA0 C800 Vd Vn (vector) + // fcmgt Vd,Vn,#0 DV_2G 010111101X100000 110010nnnnnddddd 5EA0 E800 Vd,Vn,#0 (scalar - with zero) + // fcmgt Vd,Vn,#0 DV_2A 0Q0011101X100000 110010nnnnnddddd 0EA0 C800 Vd,Vn,#0 (vector - with zero) // enum name info DV_2N DV_2O DV_3E DV_3A INST4(sqshl, "sqshl", 0, IF_EN4J, 0x5F007400, 0x0F007400, 0x5E204C00, 0x0E204C00) @@ -707,12 +707,12 @@ INST2(fabs, "fabs", 0, IF_EN2J, 0x0EA0F800, 0x1E20C000) // fabs Vd,Vn DV_2G 000111100X100000 110000nnnnnddddd 1E20 C000 Vd,Vn (scalar) INST2(fcmle, "fcmle", 0, IF_EN2J, 0x2EA0D800, 0x7EA0D800) - // fcmle Vd,Vn DV_2A 0Q1011101X100000 111110nnnnnddddd 2EA0 D800 Vd,Vn (vector) - // fcmle Vd,Vn DV_2G 011111101X100000 110110nnnnnddddd 7EA0 D800 Vd,Vn (scalar) + // fcmle Vd,Vn,#0 DV_2A 0Q1011101X100000 111110nnnnnddddd 2EA0 D800 Vd,Vn,#0 (vector - with zero) + // fcmle Vd,Vn,#0 DV_2G 011111101X100000 110110nnnnnddddd 7EA0 D800 Vd,Vn,#0 (scalar - with zero) INST2(fcmlt, "fcmlt", 0, IF_EN2J, 0x0EA0E800, 0x5EA0E800) - // fcmlt Vd,Vn DV_2A 0Q0011101X100000 111110nnnnnddddd 0EA0 E800 Vd,Vn (vector) - // fcmlt Vd,Vn DV_2G 010111101X100000 111010nnnnnddddd 5EA0 E800 Vd,Vn (scalar) + // fcmlt Vd,Vn,#0 DV_2A 0Q0011101X100000 111110nnnnnddddd 0EA0 E800 Vd,Vn,#0 (vector - with zero) + // fcmlt Vd,Vn,#0 DV_2G 010111101X100000 111010nnnnnddddd 5EA0 E800 Vd,Vn,#0 (scalar - with zero) INST2(fcvtxn, "fcvtxn", NRW, IF_EN2J, 0x2E616800, 0x7E616800) // fcvtxn Vd,Vn DV_2A 0010111001100001 011010nnnnnddddd 2E61 6800 Vd,Vn (vector) @@ -768,12 +768,12 @@ INST2(abs, "abs", 0, IF_EN2K, 0x0E20B800, 0x5E20B800) // abs Vd,Vn DV_2L 01011110XX100000 101110nnnnnddddd 5E20 B800 Vd,Vn (scalar) INST2(cmle, "cmle", 0, IF_EN2K, 0x2E209800, 0x7E209800) - // cmle Vd,Vn DV_2M 0Q101110XX100000 100110nnnnnddddd 2E20 9800 Vd,Vn (vector) - // cmle Vd,Vn DV_2L 01111110XX100000 100110nnnnnddddd 7E20 9800 Vd,Vn (scalar) + // cmle Vd,Vn,#0 DV_2M 0Q101110XX100000 100110nnnnnddddd 2E20 9800 Vd,Vn,#0 (vector - with zero) + // cmle Vd,Vn,#0 DV_2L 01111110XX100000 100110nnnnnddddd 7E20 9800 Vd,Vn,#0 (scalar - wtih zero) INST2(cmlt, "cmlt", 0, IF_EN2K, 0x0E20A800, 0x5E20A800) - // cmlt Vd,Vn DV_2M 0Q101110XX100000 101010nnnnnddddd 0E20 A800 Vd,Vn (vector) - // cmlt Vd,Vn DV_2L 01011110XX100000 101010nnnnnddddd 5E20 A800 Vd,Vn (scalar) + // cmlt Vd,Vn,#0 DV_2M 0Q101110XX100000 101010nnnnnddddd 0E20 A800 Vd,Vn,#0 (vector - with zero) + // cmlt Vd,Vn,#0 DV_2L 01011110XX100000 101010nnnnnddddd 5E20 A800 Vd,Vn,#0 (scalar - with zero) INST2(sqabs, "sqabs", 0, IF_EN2K, 0x0E207800, 0x5E207800) // sqabs Vd,Vn DV_2M 0Q001110XX100000 011110nnnnnddddd 0E20 7800 Vd,Vn (vector) diff --git a/src/coreclr/jit/lowerarmarch.cpp b/src/coreclr/jit/lowerarmarch.cpp index 80d24bc032f980..eb644d80c30987 100644 --- a/src/coreclr/jit/lowerarmarch.cpp +++ b/src/coreclr/jit/lowerarmarch.cpp @@ -1968,7 +1968,7 @@ void Lowering::ContainCheckHWIntrinsic(GenTreeHWIntrinsic* node) case NI_AdvSimd_Arm64_CompareEqual: case NI_AdvSimd_Arm64_CompareEqualScalar: { - if (intrin.op1->IsVectorZero() && intrin.op1->isCommutativeHWIntrinsic()) + if (intrin.op1->IsVectorZero() && HWIntrinsicInfo::IsCommutative(intrin.id)) { MakeSrcContained(node, intrin.op1); } From ea9c1f86622f51f23cf6d0f27ac2ff672fe68306 Mon Sep 17 00:00:00 2001 From: Will Smith Date: Thu, 3 Feb 2022 17:11:11 -0800 Subject: [PATCH 06/14] Handling more HW intrinsics --- src/coreclr/jit/emitarm64.cpp | 3 ++- src/coreclr/jit/hwintrinsiccodegenarm64.cpp | 4 ---- src/coreclr/jit/hwintrinsiclistarm64.h | 12 ++++++------ src/coreclr/jit/lowerarmarch.cpp | 6 ++++++ 4 files changed, 14 insertions(+), 11 deletions(-) diff --git a/src/coreclr/jit/emitarm64.cpp b/src/coreclr/jit/emitarm64.cpp index 884f03c14c132f..fc2606d2c62a90 100644 --- a/src/coreclr/jit/emitarm64.cpp +++ b/src/coreclr/jit/emitarm64.cpp @@ -13136,7 +13136,8 @@ void emitter::emitDispIns( emitDispReg(id->idReg1(), size, true); emitDispReg(id->idReg2(), size, false); } - if (fmt == IF_DV_2L && ins == INS_cmeq) + if (fmt == IF_DV_2L && + (ins == INS_cmeq || ins == INS_cmge || ins == INS_cmgt || ins == INS_cmle || ins == INS_cmlt)) { printf(", "); emitDispImm(0, false); diff --git a/src/coreclr/jit/hwintrinsiccodegenarm64.cpp b/src/coreclr/jit/hwintrinsiccodegenarm64.cpp index b9e4c34fa6dea9..9196ba8572a4fd 100644 --- a/src/coreclr/jit/hwintrinsiccodegenarm64.cpp +++ b/src/coreclr/jit/hwintrinsiccodegenarm64.cpp @@ -389,13 +389,9 @@ void CodeGen::genHWIntrinsic(GenTreeHWIntrinsic* node) case INS_cmeq: case INS_cmge: case INS_cmgt: - case INS_cmle: - case INS_cmlt: case INS_fcmeq: case INS_fcmge: case INS_fcmgt: - case INS_fcmle: - case INS_fcmlt: { numOperands -= 1; break; diff --git a/src/coreclr/jit/hwintrinsiclistarm64.h b/src/coreclr/jit/hwintrinsiclistarm64.h index 8bf189d0b19472..11ad5bda0d26b2 100644 --- a/src/coreclr/jit/hwintrinsiclistarm64.h +++ b/src/coreclr/jit/hwintrinsiclistarm64.h @@ -241,8 +241,8 @@ HARDWARE_INTRINSIC(AdvSimd, BitwiseSelect, HARDWARE_INTRINSIC(AdvSimd, Ceiling, -1, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_frintp, INS_invalid}, HW_Category_SIMD, HW_Flag_NoFlag) HARDWARE_INTRINSIC(AdvSimd, CeilingScalar, 8, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_frintp, INS_frintp}, HW_Category_SIMD, HW_Flag_SIMDScalar) HARDWARE_INTRINSIC(AdvSimd, CompareEqual, -1, 2, {INS_cmeq, INS_cmeq, INS_cmeq, INS_cmeq, INS_cmeq, INS_cmeq, INS_invalid, INS_invalid, INS_fcmeq, INS_invalid}, HW_Category_SIMD, HW_Flag_Commutative|HW_Flag_SupportsContainment) -HARDWARE_INTRINSIC(AdvSimd, CompareGreaterThan, -1, 2, {INS_cmgt, INS_cmhi, INS_cmgt, INS_cmhi, INS_cmgt, INS_cmhi, INS_invalid, INS_invalid, INS_fcmgt, INS_invalid}, HW_Category_SIMD, HW_Flag_NoFlag) -HARDWARE_INTRINSIC(AdvSimd, CompareGreaterThanOrEqual, -1, 2, {INS_cmge, INS_cmhs, INS_cmge, INS_cmhs, INS_cmge, INS_cmhs, INS_invalid, INS_invalid, INS_fcmge, INS_invalid}, HW_Category_SIMD, HW_Flag_NoFlag) +HARDWARE_INTRINSIC(AdvSimd, CompareGreaterThan, -1, 2, {INS_cmgt, INS_cmhi, INS_cmgt, INS_cmhi, INS_cmgt, INS_cmhi, INS_invalid, INS_invalid, INS_fcmgt, INS_invalid}, HW_Category_SIMD, HW_Flag_SupportsContainment) +HARDWARE_INTRINSIC(AdvSimd, CompareGreaterThanOrEqual, -1, 2, {INS_cmge, INS_cmhs, INS_cmge, INS_cmhs, INS_cmge, INS_cmhs, INS_invalid, INS_invalid, INS_fcmge, INS_invalid}, HW_Category_SIMD, HW_Flag_SupportsContainment) HARDWARE_INTRINSIC(AdvSimd, CompareLessThan, -1, 2, {INS_cmgt, INS_cmhi, INS_cmgt, INS_cmhi, INS_cmgt, INS_cmhi, INS_invalid, INS_invalid, INS_fcmgt, INS_invalid}, HW_Category_SIMD, HW_Flag_SpecialCodeGen) HARDWARE_INTRINSIC(AdvSimd, CompareLessThanOrEqual, -1, 2, {INS_cmge, INS_cmhs, INS_cmge, INS_cmhs, INS_cmge, INS_cmhs, INS_invalid, INS_invalid, INS_fcmge, INS_invalid}, HW_Category_SIMD, HW_Flag_SpecialCodeGen) HARDWARE_INTRINSIC(AdvSimd, CompareTest, -1, 2, {INS_cmtst, INS_cmtst, INS_cmtst, INS_cmtst, INS_cmtst, INS_cmtst, INS_invalid, INS_invalid, INS_cmtst, INS_invalid}, HW_Category_SIMD, HW_Flag_Commutative) @@ -494,10 +494,10 @@ HARDWARE_INTRINSIC(AdvSimd_Arm64, AddSaturateScalar, HARDWARE_INTRINSIC(AdvSimd_Arm64, Ceiling, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_frintp}, HW_Category_SIMD, HW_Flag_NoFlag) HARDWARE_INTRINSIC(AdvSimd_Arm64, CompareEqual, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cmeq, INS_cmeq, INS_invalid, INS_fcmeq}, HW_Category_SIMD, HW_Flag_Commutative|HW_Flag_SupportsContainment) HARDWARE_INTRINSIC(AdvSimd_Arm64, CompareEqualScalar, 8, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cmeq, INS_cmeq, INS_fcmeq, INS_fcmeq}, HW_Category_SIMD, HW_Flag_Commutative|HW_Flag_SIMDScalar|HW_Flag_SupportsContainment) -HARDWARE_INTRINSIC(AdvSimd_Arm64, CompareGreaterThan, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cmgt, INS_cmhi, INS_invalid, INS_fcmgt}, HW_Category_SIMD, HW_Flag_NoFlag) -HARDWARE_INTRINSIC(AdvSimd_Arm64, CompareGreaterThanOrEqual, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cmge, INS_cmhs, INS_invalid, INS_fcmge}, HW_Category_SIMD, HW_Flag_NoFlag) -HARDWARE_INTRINSIC(AdvSimd_Arm64, CompareGreaterThanOrEqualScalar, 8, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cmge, INS_cmhs, INS_fcmge, INS_fcmge}, HW_Category_SIMD, HW_Flag_SIMDScalar) -HARDWARE_INTRINSIC(AdvSimd_Arm64, CompareGreaterThanScalar, 8, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cmgt, INS_cmhi, INS_fcmgt, INS_fcmgt}, HW_Category_SIMD, HW_Flag_SIMDScalar) +HARDWARE_INTRINSIC(AdvSimd_Arm64, CompareGreaterThan, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cmgt, INS_cmhi, INS_invalid, INS_fcmgt}, HW_Category_SIMD, HW_Flag_SupportsContainment) +HARDWARE_INTRINSIC(AdvSimd_Arm64, CompareGreaterThanOrEqual, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cmge, INS_cmhs, INS_invalid, INS_fcmge}, HW_Category_SIMD, HW_Flag_SupportsContainment) +HARDWARE_INTRINSIC(AdvSimd_Arm64, CompareGreaterThanOrEqualScalar, 8, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cmge, INS_cmhs, INS_fcmge, INS_fcmge}, HW_Category_SIMD, HW_Flag_SIMDScalar|HW_Flag_SupportsContainment) +HARDWARE_INTRINSIC(AdvSimd_Arm64, CompareGreaterThanScalar, 8, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cmgt, INS_cmhi, INS_fcmgt, INS_fcmgt}, HW_Category_SIMD, HW_Flag_SIMDScalar|HW_Flag_SupportsContainment) HARDWARE_INTRINSIC(AdvSimd_Arm64, CompareLessThan, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cmgt, INS_cmhi, INS_invalid, INS_fcmgt}, HW_Category_SIMD, HW_Flag_SpecialCodeGen) HARDWARE_INTRINSIC(AdvSimd_Arm64, CompareLessThanOrEqual, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cmge, INS_cmhs, INS_invalid, INS_fcmge}, HW_Category_SIMD, HW_Flag_SpecialCodeGen) HARDWARE_INTRINSIC(AdvSimd_Arm64, CompareLessThanOrEqualScalar, 8, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cmge, INS_cmhs, INS_fcmge, INS_fcmge}, HW_Category_SIMD, HW_Flag_SIMDScalar|HW_Flag_SpecialCodeGen) diff --git a/src/coreclr/jit/lowerarmarch.cpp b/src/coreclr/jit/lowerarmarch.cpp index eb644d80c30987..1e83bafeda9934 100644 --- a/src/coreclr/jit/lowerarmarch.cpp +++ b/src/coreclr/jit/lowerarmarch.cpp @@ -1965,8 +1965,14 @@ void Lowering::ContainCheckHWIntrinsic(GenTreeHWIntrinsic* node) break; case NI_AdvSimd_CompareEqual: + case NI_AdvSimd_CompareGreaterThan: + case NI_AdvSimd_CompareGreaterThanOrEqual: case NI_AdvSimd_Arm64_CompareEqual: case NI_AdvSimd_Arm64_CompareEqualScalar: + case NI_AdvSimd_Arm64_CompareGreaterThan: + case NI_AdvSimd_Arm64_CompareGreaterThanOrEqual: + case NI_AdvSimd_Arm64_CompareGreaterThanScalar: + case NI_AdvSimd_Arm64_CompareGreaterThanOrEqualScalar: { if (intrin.op1->IsVectorZero() && HWIntrinsicInfo::IsCommutative(intrin.id)) { From e6dfa7e21ff310078cf2a03e13f79a1ccb2deb16 Mon Sep 17 00:00:00 2001 From: Will Smith Date: Thu, 3 Feb 2022 18:12:59 -0800 Subject: [PATCH 07/14] Finishing up --- src/coreclr/jit/lowerarmarch.cpp | 27 ++- .../JitBlue/Runtime_33972/Runtime_33972.cs | 204 ++++++++++++++++++ 2 files changed, 224 insertions(+), 7 deletions(-) diff --git a/src/coreclr/jit/lowerarmarch.cpp b/src/coreclr/jit/lowerarmarch.cpp index 1e83bafeda9934..3ba3667954abdb 100644 --- a/src/coreclr/jit/lowerarmarch.cpp +++ b/src/coreclr/jit/lowerarmarch.cpp @@ -1965,17 +1965,12 @@ void Lowering::ContainCheckHWIntrinsic(GenTreeHWIntrinsic* node) break; case NI_AdvSimd_CompareEqual: - case NI_AdvSimd_CompareGreaterThan: - case NI_AdvSimd_CompareGreaterThanOrEqual: case NI_AdvSimd_Arm64_CompareEqual: case NI_AdvSimd_Arm64_CompareEqualScalar: - case NI_AdvSimd_Arm64_CompareGreaterThan: - case NI_AdvSimd_Arm64_CompareGreaterThanOrEqual: - case NI_AdvSimd_Arm64_CompareGreaterThanScalar: - case NI_AdvSimd_Arm64_CompareGreaterThanOrEqualScalar: { - if (intrin.op1->IsVectorZero() && HWIntrinsicInfo::IsCommutative(intrin.id)) + if (intrin.op1->IsVectorZero()) { + assert(HWIntrinsicInfo::IsCommutative(intrin.id)); MakeSrcContained(node, intrin.op1); } else if (intrin.op2->IsVectorZero()) @@ -1985,6 +1980,24 @@ void Lowering::ContainCheckHWIntrinsic(GenTreeHWIntrinsic* node) break; } + case NI_AdvSimd_CompareGreaterThan: + case NI_AdvSimd_CompareGreaterThanOrEqual: + case NI_AdvSimd_Arm64_CompareGreaterThan: + case NI_AdvSimd_Arm64_CompareGreaterThanOrEqual: + case NI_AdvSimd_Arm64_CompareGreaterThanScalar: + case NI_AdvSimd_Arm64_CompareGreaterThanOrEqualScalar: + { + // Containment is not supported for unsigned base types as the corresponding instructions: + // - cmhi + // - cmhs + // require both operands; they do not have a 'with zero'. + if (intrin.op2->IsVectorZero() && !varTypeIsUnsigned(intrin.baseType)) + { + MakeSrcContained(node, intrin.op2); + } + break; + } + case NI_Vector64_CreateScalarUnsafe: case NI_Vector128_CreateScalarUnsafe: case NI_AdvSimd_DuplicateToVector64: diff --git a/src/tests/JIT/Regression/JitBlue/Runtime_33972/Runtime_33972.cs b/src/tests/JIT/Regression/JitBlue/Runtime_33972/Runtime_33972.cs index 7535cd334d9624..6e995575f534ca 100644 --- a/src/tests/JIT/Regression/JitBlue/Runtime_33972/Runtime_33972.cs +++ b/src/tests/JIT/Regression/JitBlue/Runtime_33972/Runtime_33972.cs @@ -264,6 +264,106 @@ static Vector64 AdvSimd_Arm64_CompareEqualScalar_Vector64_Int64_Zero_Swapp return AdvSimd.Arm64.CompareEqualScalar(Vector64.Zero, right); } + // CompareGreaterThan + + [MethodImpl(MethodImplOptions.NoInlining)] + static Vector64 AdvSimd_CompareGreaterThan_Vector64_Byte_Zero(Vector64 left) + { + return AdvSimd.CompareGreaterThan(left, Vector64.Zero); + } + + [MethodImpl(MethodImplOptions.NoInlining)] + static Vector64 AdvSimd_CompareGreaterThan_Vector64_Single_Zero(Vector64 left) + { + return AdvSimd.CompareGreaterThan(left, Vector64.Zero); + } + + [MethodImpl(MethodImplOptions.NoInlining)] + static Vector128 AdvSimd_CompareGreaterThan_Vector128_Byte_Zero(Vector128 left) + { + return AdvSimd.CompareGreaterThan(left, Vector128.Zero); + } + + [MethodImpl(MethodImplOptions.NoInlining)] + static Vector128 AdvSimd_CompareGreaterThan_Vector128_Single_Zero(Vector128 left) + { + return AdvSimd.CompareGreaterThan(left, Vector128.Zero); + } + + [MethodImpl(MethodImplOptions.NoInlining)] + static Vector128 AdvSimd_Arm64_CompareGreaterThan_Vector128_Double_Zero(Vector128 left) + { + return AdvSimd.Arm64.CompareGreaterThan(left, Vector128.Zero); + } + + [MethodImpl(MethodImplOptions.NoInlining)] + static Vector128 AdvSimd_Arm64_CompareGreaterThan_Vector128_Int64_Zero(Vector128 left) + { + return AdvSimd.Arm64.CompareGreaterThan(left, Vector128.Zero); + } + + [MethodImpl(MethodImplOptions.NoInlining)] + static Vector64 AdvSimd_Arm64_CompareGreaterThanScalar_Vector64_Double_Zero(Vector64 left) + { + return AdvSimd.Arm64.CompareGreaterThanScalar(left, Vector64.Zero); + } + + [MethodImpl(MethodImplOptions.NoInlining)] + static Vector64 AdvSimd_Arm64_CompareGreaterThanScalar_Vector64_Int64_Zero(Vector64 left) + { + return AdvSimd.Arm64.CompareGreaterThanScalar(left, Vector64.Zero); + } + + // CompareGreaterThanOrEqual + + [MethodImpl(MethodImplOptions.NoInlining)] + static Vector64 AdvSimd_CompareGreaterThanOrEqual_Vector64_Byte_Zero(Vector64 left) + { + return AdvSimd.CompareGreaterThanOrEqual(left, Vector64.Zero); + } + + [MethodImpl(MethodImplOptions.NoInlining)] + static Vector64 AdvSimd_CompareGreaterThanOrEqual_Vector64_Single_Zero(Vector64 left) + { + return AdvSimd.CompareGreaterThanOrEqual(left, Vector64.Zero); + } + + [MethodImpl(MethodImplOptions.NoInlining)] + static Vector128 AdvSimd_CompareGreaterThanOrEqual_Vector128_Byte_Zero(Vector128 left) + { + return AdvSimd.CompareGreaterThanOrEqual(left, Vector128.Zero); + } + + [MethodImpl(MethodImplOptions.NoInlining)] + static Vector128 AdvSimd_CompareGreaterThanOrEqual_Vector128_Single_Zero(Vector128 left) + { + return AdvSimd.CompareGreaterThanOrEqual(left, Vector128.Zero); + } + + [MethodImpl(MethodImplOptions.NoInlining)] + static Vector128 AdvSimd_Arm64_CompareGreaterThanOrEqual_Vector128_Double_Zero(Vector128 left) + { + return AdvSimd.Arm64.CompareGreaterThanOrEqual(left, Vector128.Zero); + } + + [MethodImpl(MethodImplOptions.NoInlining)] + static Vector128 AdvSimd_Arm64_CompareGreaterThanOrEqual_Vector128_Int64_Zero(Vector128 left) + { + return AdvSimd.Arm64.CompareGreaterThanOrEqual(left, Vector128.Zero); + } + + [MethodImpl(MethodImplOptions.NoInlining)] + static Vector64 AdvSimd_Arm64_CompareGreaterThanOrEqualScalar_Vector64_Double_Zero(Vector64 left) + { + return AdvSimd.Arm64.CompareGreaterThanOrEqualScalar(left, Vector64.Zero); + } + + [MethodImpl(MethodImplOptions.NoInlining)] + static Vector64 AdvSimd_Arm64_CompareGreaterThanOrEqualScalar_Vector64_Int64_Zero(Vector64 left) + { + return AdvSimd.Arm64.CompareGreaterThanOrEqualScalar(left, Vector64.Zero); + } + // Validation unsafe static bool ValidateResult_Vector64(Vector64 result, T expectedElementValue) where T : unmanaged @@ -376,6 +476,110 @@ static int Tests_AdvSimd() // End CompareEqual Tests + // Begin CompareGreaterThan Tests + + if (!ValidateResult_Vector64(AdvSimd_CompareGreaterThan_Vector64_Byte_Zero(Vector64.Create((byte)1)), Byte.MaxValue)) + result = -1; + + if (!ValidateResult_Vector64(AdvSimd_CompareGreaterThan_Vector64_Single_Zero(Vector64.Create(1.0f)), Single.NaN)) + result = -1; + + if (!ValidateResult_Vector128(AdvSimd_CompareGreaterThan_Vector128_Byte_Zero(Vector128.Create((byte)1)), Byte.MaxValue)) + result = -1; + + if (!ValidateResult_Vector128(AdvSimd_CompareGreaterThan_Vector128_Single_Zero(Vector128.Create(1.0f)), Single.NaN)) + result = -1; + + if (!ValidateResult_Vector128(AdvSimd_Arm64_CompareGreaterThan_Vector128_Double_Zero(Vector128.Create(1.0)), Double.NaN)) + result = -1; + + if (!ValidateResult_Vector128(AdvSimd_Arm64_CompareGreaterThan_Vector128_Int64_Zero(Vector128.Create(1L)), -1)) + result = -1; + + if (!ValidateResult_Vector64(AdvSimd_Arm64_CompareGreaterThanScalar_Vector64_Double_Zero(Vector64.Create(1.0)), Double.NaN)) + result = -1; + + if (!ValidateResult_Vector64(AdvSimd_Arm64_CompareGreaterThanScalar_Vector64_Int64_Zero(Vector64.Create(1L)), -1)) + result = -1; + + if (ValidateResult_Vector64(AdvSimd_CompareGreaterThan_Vector64_Byte_Zero(Vector64.Zero), Byte.MaxValue)) + result = -1; + + if (ValidateResult_Vector64(AdvSimd_CompareGreaterThan_Vector64_Single_Zero(Vector64.Zero), Single.NaN)) + result = -1; + + if (ValidateResult_Vector128(AdvSimd_CompareGreaterThan_Vector128_Byte_Zero(Vector128.Zero), Byte.MaxValue)) + result = -1; + + if (ValidateResult_Vector128(AdvSimd_CompareGreaterThan_Vector128_Single_Zero(Vector128.Zero), Single.NaN)) + result = -1; + + if (ValidateResult_Vector128(AdvSimd_Arm64_CompareGreaterThan_Vector128_Double_Zero(Vector128.Zero), Double.NaN)) + result = -1; + + if (ValidateResult_Vector128(AdvSimd_Arm64_CompareGreaterThan_Vector128_Int64_Zero(Vector128.Zero), -1)) + result = -1; + + if (ValidateResult_Vector64(AdvSimd_Arm64_CompareGreaterThanScalar_Vector64_Double_Zero(Vector64.Zero), Double.NaN)) + result = -1; + + if (ValidateResult_Vector64(AdvSimd_Arm64_CompareGreaterThanScalar_Vector64_Int64_Zero(Vector64.Zero), -1)) + result = -1; + + // End CompareGreaterThan Tests + + // Begin CompareGreaterThanOrEqual Tests + + if (!ValidateResult_Vector64(AdvSimd_CompareGreaterThanOrEqual_Vector64_Byte_Zero(Vector64.Create((byte)1)), Byte.MaxValue)) + result = -1; + + if (!ValidateResult_Vector64(AdvSimd_CompareGreaterThanOrEqual_Vector64_Single_Zero(Vector64.Create(1.0f)), Single.NaN)) + result = -1; + + if (!ValidateResult_Vector128(AdvSimd_CompareGreaterThanOrEqual_Vector128_Byte_Zero(Vector128.Create((byte)1)), Byte.MaxValue)) + result = -1; + + if (!ValidateResult_Vector128(AdvSimd_CompareGreaterThanOrEqual_Vector128_Single_Zero(Vector128.Create(1.0f)), Single.NaN)) + result = -1; + + if (!ValidateResult_Vector128(AdvSimd_Arm64_CompareGreaterThanOrEqual_Vector128_Double_Zero(Vector128.Create(1.0)), Double.NaN)) + result = -1; + + if (!ValidateResult_Vector128(AdvSimd_Arm64_CompareGreaterThanOrEqual_Vector128_Int64_Zero(Vector128.Create(1L)), -1)) + result = -1; + + if (!ValidateResult_Vector64(AdvSimd_Arm64_CompareGreaterThanOrEqualScalar_Vector64_Double_Zero(Vector64.Create(1.0)), Double.NaN)) + result = -1; + + if (!ValidateResult_Vector64(AdvSimd_Arm64_CompareGreaterThanOrEqualScalar_Vector64_Int64_Zero(Vector64.Create(1L)), -1)) + result = -1; + + if (!ValidateResult_Vector64(AdvSimd_CompareGreaterThanOrEqual_Vector64_Byte_Zero(Vector64.Zero), Byte.MaxValue)) + result = -1; + + if (!ValidateResult_Vector64(AdvSimd_CompareGreaterThanOrEqual_Vector64_Single_Zero(Vector64.Zero), Single.NaN)) + result = -1; + + if (!ValidateResult_Vector128(AdvSimd_CompareGreaterThanOrEqual_Vector128_Byte_Zero(Vector128.Zero), Byte.MaxValue)) + result = -1; + + if (!ValidateResult_Vector128(AdvSimd_CompareGreaterThanOrEqual_Vector128_Single_Zero(Vector128.Zero), Single.NaN)) + result = -1; + + if (!ValidateResult_Vector128(AdvSimd_Arm64_CompareGreaterThanOrEqual_Vector128_Double_Zero(Vector128.Zero), Double.NaN)) + result = -1; + + if (!ValidateResult_Vector128(AdvSimd_Arm64_CompareGreaterThanOrEqual_Vector128_Int64_Zero(Vector128.Zero), -1)) + result = -1; + + if (!ValidateResult_Vector64(AdvSimd_Arm64_CompareGreaterThanOrEqualScalar_Vector64_Double_Zero(Vector64.Zero), Double.NaN)) + result = -1; + + if (!ValidateResult_Vector64(AdvSimd_Arm64_CompareGreaterThanOrEqualScalar_Vector64_Int64_Zero(Vector64.Zero), -1)) + result = -1; + + // End CompareGreaterThanOrEqual Tests + return result; } From f9f8dd20a8a24cdb22d35aa42842cb73c9eb16b1 Mon Sep 17 00:00:00 2001 From: Will Smith Date: Thu, 3 Feb 2022 18:21:02 -0800 Subject: [PATCH 08/14] Finishing up --- src/coreclr/jit/emitarm64.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/coreclr/jit/emitarm64.cpp b/src/coreclr/jit/emitarm64.cpp index fc2606d2c62a90..8bd91acc0305b0 100644 --- a/src/coreclr/jit/emitarm64.cpp +++ b/src/coreclr/jit/emitarm64.cpp @@ -12971,7 +12971,7 @@ void emitter::emitDispIns( emitDispVectorReg(id->idReg1(), id->idInsOpt(), true); emitDispVectorReg(id->idReg2(), id->idInsOpt(), false); } - if (ins == INS_fcmeq) + if (ins == INS_fcmeq || ins == INS_fcmge || ins == INS_fcmgt || ins == INS_fcmle || ins == INS_fcmlt) { printf(", "); emitDispImm(0, false); From 7d47671578cfa88350c0dfefe3aeff2e2cb3119f Mon Sep 17 00:00:00 2001 From: Will Smith Date: Thu, 3 Feb 2022 18:56:55 -0800 Subject: [PATCH 09/14] Formatting --- src/coreclr/jit/hwintrinsiccodegenarm64.cpp | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/coreclr/jit/hwintrinsiccodegenarm64.cpp b/src/coreclr/jit/hwintrinsiccodegenarm64.cpp index 9196ba8572a4fd..cc50653ba41d50 100644 --- a/src/coreclr/jit/hwintrinsiccodegenarm64.cpp +++ b/src/coreclr/jit/hwintrinsiccodegenarm64.cpp @@ -368,10 +368,9 @@ void CodeGen::genHWIntrinsic(GenTreeHWIntrinsic* node) // This handles optimizations for instructions that have // an implicit 'zero' vector of what would be the second operand. - if ((numOperands == 2) && - ((intrin.op2->IsVectorZero() && intrin.op2->isContained()) || - (intrin.op1->IsVectorZero() && intrin.op1->isContained() && - HWIntrinsicInfo::IsCommutative(intrin.id)))) + if ((numOperands == 2) && ((intrin.op2->IsVectorZero() && intrin.op2->isContained()) || + (intrin.op1->IsVectorZero() && intrin.op1->isContained() && + HWIntrinsicInfo::IsCommutative(intrin.id)))) { assert(HWIntrinsicInfo::SupportsContainment(intrin.id)); From cdf3d60e4a9507fe34ba830502505b637d6f35e0 Mon Sep 17 00:00:00 2001 From: Will Smith Date: Thu, 3 Feb 2022 19:11:32 -0800 Subject: [PATCH 10/14] numOperands = 1 --- src/coreclr/jit/hwintrinsiccodegenarm64.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/coreclr/jit/hwintrinsiccodegenarm64.cpp b/src/coreclr/jit/hwintrinsiccodegenarm64.cpp index cc50653ba41d50..e1bf00e2aeebfa 100644 --- a/src/coreclr/jit/hwintrinsiccodegenarm64.cpp +++ b/src/coreclr/jit/hwintrinsiccodegenarm64.cpp @@ -392,7 +392,7 @@ void CodeGen::genHWIntrinsic(GenTreeHWIntrinsic* node) case INS_fcmge: case INS_fcmgt: { - numOperands -= 1; + numOperands = 1; break; } From a9c2989afdac9cd9a06a2321dfcd33d92fbe5460 Mon Sep 17 00:00:00 2001 From: Will Smith Date: Tue, 15 Feb 2022 18:19:35 -0800 Subject: [PATCH 11/14] Feedback --- src/coreclr/jit/hwintrinsiccodegenarm64.cpp | 13 +------------ src/coreclr/jit/lowerarmarch.cpp | 9 ++++++++- 2 files changed, 9 insertions(+), 13 deletions(-) diff --git a/src/coreclr/jit/hwintrinsiccodegenarm64.cpp b/src/coreclr/jit/hwintrinsiccodegenarm64.cpp index e1bf00e2aeebfa..3db7249a2656c1 100644 --- a/src/coreclr/jit/hwintrinsiccodegenarm64.cpp +++ b/src/coreclr/jit/hwintrinsiccodegenarm64.cpp @@ -368,21 +368,10 @@ void CodeGen::genHWIntrinsic(GenTreeHWIntrinsic* node) // This handles optimizations for instructions that have // an implicit 'zero' vector of what would be the second operand. - if ((numOperands == 2) && ((intrin.op2->IsVectorZero() && intrin.op2->isContained()) || - (intrin.op1->IsVectorZero() && intrin.op1->isContained() && - HWIntrinsicInfo::IsCommutative(intrin.id)))) + if ((numOperands == 2) && intrin.op2->IsVectorZero() && intrin.op2->isContained()) { assert(HWIntrinsicInfo::SupportsContainment(intrin.id)); - if (intrin.op1->IsVectorZero() && intrin.op1->isContained() && - HWIntrinsicInfo::IsCommutative(intrin.id)) - { - // The intrinsic is commutative, swap the registers. - assert(op1Reg == REG_NA); - op1Reg = op2Reg; - op2Reg = REG_NA; - } - switch (ins) { case INS_cmeq: diff --git a/src/coreclr/jit/lowerarmarch.cpp b/src/coreclr/jit/lowerarmarch.cpp index 3ba3667954abdb..433046e98a01aa 100644 --- a/src/coreclr/jit/lowerarmarch.cpp +++ b/src/coreclr/jit/lowerarmarch.cpp @@ -1970,8 +1970,15 @@ void Lowering::ContainCheckHWIntrinsic(GenTreeHWIntrinsic* node) { if (intrin.op1->IsVectorZero()) { + GenTree* op1 = intrin.op1; + GenTree* op2 = intrin.op2; + assert(HWIntrinsicInfo::IsCommutative(intrin.id)); - MakeSrcContained(node, intrin.op1); + MakeSrcContained(node, op1); + + // Swap the operands here to make the containment checks in codegen simpler + node->Op(1) = op2; + node->Op(2) = op1; } else if (intrin.op2->IsVectorZero()) { From 9877252b85067a501a8c93cb0b3fa22b96d5da77 Mon Sep 17 00:00:00 2001 From: Will Smith Date: Tue, 15 Feb 2022 21:16:53 -0800 Subject: [PATCH 12/14] Added HW_Flag_SupportsContainmentZero --- src/coreclr/jit/hwintrinsic.h | 15 ++++++++++++++- src/coreclr/jit/hwintrinsiccodegenarm64.cpp | 21 ++++----------------- src/coreclr/jit/hwintrinsiclistarm64.h | 18 +++++++++--------- 3 files changed, 27 insertions(+), 27 deletions(-) diff --git a/src/coreclr/jit/hwintrinsic.h b/src/coreclr/jit/hwintrinsic.h index 4551ed9e4e1ce1..197cd35ed8f021 100644 --- a/src/coreclr/jit/hwintrinsic.h +++ b/src/coreclr/jit/hwintrinsic.h @@ -155,7 +155,8 @@ enum HWIntrinsicFlag : unsigned int HW_Flag_SIMDScalar = 0x800, // The intrinsic supports some sort of containment analysis - HW_Flag_SupportsContainment = 0x1000 + HW_Flag_SupportsContainment = 0x1000, + HW_Flag_SupportsContainmentZero = 0x2000 #else #error Unsupported platform @@ -638,6 +639,18 @@ struct HWIntrinsicInfo #endif } + static bool SupportsContainmentZero(NamedIntrinsic id) + { + HWIntrinsicFlag flags = lookupFlags(id); +#if defined(TARGET_XARCH) + return false; +#elif defined(TARGET_ARM64) + return (flags & HW_Flag_SupportsContainmentZero) != 0; +#else +#error Unsupported platform +#endif + } + static bool BaseTypeFromFirstArg(NamedIntrinsic id) { HWIntrinsicFlag flags = lookupFlags(id); diff --git a/src/coreclr/jit/hwintrinsiccodegenarm64.cpp b/src/coreclr/jit/hwintrinsiccodegenarm64.cpp index 3db7249a2656c1..da66c5d4764ef0 100644 --- a/src/coreclr/jit/hwintrinsiccodegenarm64.cpp +++ b/src/coreclr/jit/hwintrinsiccodegenarm64.cpp @@ -368,25 +368,12 @@ void CodeGen::genHWIntrinsic(GenTreeHWIntrinsic* node) // This handles optimizations for instructions that have // an implicit 'zero' vector of what would be the second operand. - if ((numOperands == 2) && intrin.op2->IsVectorZero() && intrin.op2->isContained()) + if (HWIntrinsicInfo::SupportsContainmentZero(intrin.id)) { - assert(HWIntrinsicInfo::SupportsContainment(intrin.id)); - - switch (ins) + assert(numOperands == 2); + if (intrin.op2->isContained() && intrin.op2->IsVectorZero()) { - case INS_cmeq: - case INS_cmge: - case INS_cmgt: - case INS_fcmeq: - case INS_fcmge: - case INS_fcmgt: - { - numOperands = 1; - break; - } - - default: - unreached(); + numOperands = 1; } } diff --git a/src/coreclr/jit/hwintrinsiclistarm64.h b/src/coreclr/jit/hwintrinsiclistarm64.h index 11ad5bda0d26b2..e4fc49d93c6760 100644 --- a/src/coreclr/jit/hwintrinsiclistarm64.h +++ b/src/coreclr/jit/hwintrinsiclistarm64.h @@ -240,9 +240,9 @@ HARDWARE_INTRINSIC(AdvSimd, BitwiseClear, HARDWARE_INTRINSIC(AdvSimd, BitwiseSelect, -1, 3, {INS_bsl, INS_bsl, INS_bsl, INS_bsl, INS_bsl, INS_bsl, INS_bsl, INS_bsl, INS_bsl, INS_bsl}, HW_Category_SIMD, HW_Flag_SpecialCodeGen) HARDWARE_INTRINSIC(AdvSimd, Ceiling, -1, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_frintp, INS_invalid}, HW_Category_SIMD, HW_Flag_NoFlag) HARDWARE_INTRINSIC(AdvSimd, CeilingScalar, 8, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_frintp, INS_frintp}, HW_Category_SIMD, HW_Flag_SIMDScalar) -HARDWARE_INTRINSIC(AdvSimd, CompareEqual, -1, 2, {INS_cmeq, INS_cmeq, INS_cmeq, INS_cmeq, INS_cmeq, INS_cmeq, INS_invalid, INS_invalid, INS_fcmeq, INS_invalid}, HW_Category_SIMD, HW_Flag_Commutative|HW_Flag_SupportsContainment) -HARDWARE_INTRINSIC(AdvSimd, CompareGreaterThan, -1, 2, {INS_cmgt, INS_cmhi, INS_cmgt, INS_cmhi, INS_cmgt, INS_cmhi, INS_invalid, INS_invalid, INS_fcmgt, INS_invalid}, HW_Category_SIMD, HW_Flag_SupportsContainment) -HARDWARE_INTRINSIC(AdvSimd, CompareGreaterThanOrEqual, -1, 2, {INS_cmge, INS_cmhs, INS_cmge, INS_cmhs, INS_cmge, INS_cmhs, INS_invalid, INS_invalid, INS_fcmge, INS_invalid}, HW_Category_SIMD, HW_Flag_SupportsContainment) +HARDWARE_INTRINSIC(AdvSimd, CompareEqual, -1, 2, {INS_cmeq, INS_cmeq, INS_cmeq, INS_cmeq, INS_cmeq, INS_cmeq, INS_invalid, INS_invalid, INS_fcmeq, INS_invalid}, HW_Category_SIMD, HW_Flag_Commutative|HW_Flag_SupportsContainment|HW_Flag_SupportsContainmentZero) +HARDWARE_INTRINSIC(AdvSimd, CompareGreaterThan, -1, 2, {INS_cmgt, INS_cmhi, INS_cmgt, INS_cmhi, INS_cmgt, INS_cmhi, INS_invalid, INS_invalid, INS_fcmgt, INS_invalid}, HW_Category_SIMD, HW_Flag_SupportsContainment|HW_Flag_SupportsContainmentZero) +HARDWARE_INTRINSIC(AdvSimd, CompareGreaterThanOrEqual, -1, 2, {INS_cmge, INS_cmhs, INS_cmge, INS_cmhs, INS_cmge, INS_cmhs, INS_invalid, INS_invalid, INS_fcmge, INS_invalid}, HW_Category_SIMD, HW_Flag_SupportsContainment|HW_Flag_SupportsContainmentZero) HARDWARE_INTRINSIC(AdvSimd, CompareLessThan, -1, 2, {INS_cmgt, INS_cmhi, INS_cmgt, INS_cmhi, INS_cmgt, INS_cmhi, INS_invalid, INS_invalid, INS_fcmgt, INS_invalid}, HW_Category_SIMD, HW_Flag_SpecialCodeGen) HARDWARE_INTRINSIC(AdvSimd, CompareLessThanOrEqual, -1, 2, {INS_cmge, INS_cmhs, INS_cmge, INS_cmhs, INS_cmge, INS_cmhs, INS_invalid, INS_invalid, INS_fcmge, INS_invalid}, HW_Category_SIMD, HW_Flag_SpecialCodeGen) HARDWARE_INTRINSIC(AdvSimd, CompareTest, -1, 2, {INS_cmtst, INS_cmtst, INS_cmtst, INS_cmtst, INS_cmtst, INS_cmtst, INS_invalid, INS_invalid, INS_cmtst, INS_invalid}, HW_Category_SIMD, HW_Flag_Commutative) @@ -492,12 +492,12 @@ HARDWARE_INTRINSIC(AdvSimd_Arm64, AddPairwiseScalar, HARDWARE_INTRINSIC(AdvSimd_Arm64, AddSaturate, -1, 2, {INS_suqadd, INS_usqadd, INS_suqadd, INS_usqadd, INS_suqadd, INS_usqadd, INS_suqadd, INS_usqadd, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_BaseTypeFromFirstArg|HW_Flag_HasRMWSemantics) HARDWARE_INTRINSIC(AdvSimd_Arm64, AddSaturateScalar, 8, 2, {INS_sqadd, INS_uqadd, INS_sqadd, INS_uqadd, INS_sqadd, INS_uqadd, INS_suqadd, INS_usqadd, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_BaseTypeFromFirstArg|HW_Flag_HasRMWSemantics|HW_Flag_SIMDScalar|HW_Flag_SpecialCodeGen) HARDWARE_INTRINSIC(AdvSimd_Arm64, Ceiling, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_frintp}, HW_Category_SIMD, HW_Flag_NoFlag) -HARDWARE_INTRINSIC(AdvSimd_Arm64, CompareEqual, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cmeq, INS_cmeq, INS_invalid, INS_fcmeq}, HW_Category_SIMD, HW_Flag_Commutative|HW_Flag_SupportsContainment) -HARDWARE_INTRINSIC(AdvSimd_Arm64, CompareEqualScalar, 8, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cmeq, INS_cmeq, INS_fcmeq, INS_fcmeq}, HW_Category_SIMD, HW_Flag_Commutative|HW_Flag_SIMDScalar|HW_Flag_SupportsContainment) -HARDWARE_INTRINSIC(AdvSimd_Arm64, CompareGreaterThan, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cmgt, INS_cmhi, INS_invalid, INS_fcmgt}, HW_Category_SIMD, HW_Flag_SupportsContainment) -HARDWARE_INTRINSIC(AdvSimd_Arm64, CompareGreaterThanOrEqual, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cmge, INS_cmhs, INS_invalid, INS_fcmge}, HW_Category_SIMD, HW_Flag_SupportsContainment) -HARDWARE_INTRINSIC(AdvSimd_Arm64, CompareGreaterThanOrEqualScalar, 8, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cmge, INS_cmhs, INS_fcmge, INS_fcmge}, HW_Category_SIMD, HW_Flag_SIMDScalar|HW_Flag_SupportsContainment) -HARDWARE_INTRINSIC(AdvSimd_Arm64, CompareGreaterThanScalar, 8, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cmgt, INS_cmhi, INS_fcmgt, INS_fcmgt}, HW_Category_SIMD, HW_Flag_SIMDScalar|HW_Flag_SupportsContainment) +HARDWARE_INTRINSIC(AdvSimd_Arm64, CompareEqual, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cmeq, INS_cmeq, INS_invalid, INS_fcmeq}, HW_Category_SIMD, HW_Flag_Commutative|HW_Flag_SupportsContainment|HW_Flag_SupportsContainmentZero) +HARDWARE_INTRINSIC(AdvSimd_Arm64, CompareEqualScalar, 8, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cmeq, INS_cmeq, INS_fcmeq, INS_fcmeq}, HW_Category_SIMD, HW_Flag_Commutative|HW_Flag_SIMDScalar|HW_Flag_SupportsContainment|HW_Flag_SupportsContainmentZero) +HARDWARE_INTRINSIC(AdvSimd_Arm64, CompareGreaterThan, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cmgt, INS_cmhi, INS_invalid, INS_fcmgt}, HW_Category_SIMD, HW_Flag_SupportsContainment|HW_Flag_SupportsContainmentZero) +HARDWARE_INTRINSIC(AdvSimd_Arm64, CompareGreaterThanOrEqual, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cmge, INS_cmhs, INS_invalid, INS_fcmge}, HW_Category_SIMD, HW_Flag_SupportsContainment|HW_Flag_SupportsContainmentZero) +HARDWARE_INTRINSIC(AdvSimd_Arm64, CompareGreaterThanOrEqualScalar, 8, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cmge, INS_cmhs, INS_fcmge, INS_fcmge}, HW_Category_SIMD, HW_Flag_SIMDScalar|HW_Flag_SupportsContainment||HW_Flag_SupportsContainmentZero) +HARDWARE_INTRINSIC(AdvSimd_Arm64, CompareGreaterThanScalar, 8, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cmgt, INS_cmhi, INS_fcmgt, INS_fcmgt}, HW_Category_SIMD, HW_Flag_SIMDScalar|HW_Flag_SupportsContainment|HW_Flag_SupportsContainmentZero) HARDWARE_INTRINSIC(AdvSimd_Arm64, CompareLessThan, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cmgt, INS_cmhi, INS_invalid, INS_fcmgt}, HW_Category_SIMD, HW_Flag_SpecialCodeGen) HARDWARE_INTRINSIC(AdvSimd_Arm64, CompareLessThanOrEqual, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cmge, INS_cmhs, INS_invalid, INS_fcmge}, HW_Category_SIMD, HW_Flag_SpecialCodeGen) HARDWARE_INTRINSIC(AdvSimd_Arm64, CompareLessThanOrEqualScalar, 8, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cmge, INS_cmhs, INS_fcmge, INS_fcmge}, HW_Category_SIMD, HW_Flag_SIMDScalar|HW_Flag_SpecialCodeGen) From d7e31d4ba39af095b9947a72badeb67280a2b330 Mon Sep 17 00:00:00 2001 From: Will Smith Date: Wed, 16 Feb 2022 10:37:41 -0800 Subject: [PATCH 13/14] Added extra assert --- src/coreclr/jit/hwintrinsiccodegenarm64.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/coreclr/jit/hwintrinsiccodegenarm64.cpp b/src/coreclr/jit/hwintrinsiccodegenarm64.cpp index da66c5d4764ef0..77c21b8123d2c1 100644 --- a/src/coreclr/jit/hwintrinsiccodegenarm64.cpp +++ b/src/coreclr/jit/hwintrinsiccodegenarm64.cpp @@ -370,6 +370,7 @@ void CodeGen::genHWIntrinsic(GenTreeHWIntrinsic* node) // an implicit 'zero' vector of what would be the second operand. if (HWIntrinsicInfo::SupportsContainmentZero(intrin.id)) { + assert(HWIntrinsicInfo::SupportsContainment(intrin.id)); assert(numOperands == 2); if (intrin.op2->isContained() && intrin.op2->IsVectorZero()) { From 1567e1c5d2312065543e4fe97497017195d2f0c7 Mon Sep 17 00:00:00 2001 From: Will Smith Date: Wed, 16 Feb 2022 12:15:10 -0800 Subject: [PATCH 14/14] Removing flag and simplifying codegen for containment with zeros --- src/coreclr/jit/hwintrinsic.h | 15 +------------ src/coreclr/jit/hwintrinsiccodegenarm64.cpp | 25 ++++++++------------- src/coreclr/jit/hwintrinsiclistarm64.h | 18 +++++++-------- 3 files changed, 19 insertions(+), 39 deletions(-) diff --git a/src/coreclr/jit/hwintrinsic.h b/src/coreclr/jit/hwintrinsic.h index 4de61d43097ff3..53c392084653ee 100644 --- a/src/coreclr/jit/hwintrinsic.h +++ b/src/coreclr/jit/hwintrinsic.h @@ -158,8 +158,7 @@ enum HWIntrinsicFlag : unsigned int HW_Flag_SIMDScalar = 0x1000, // The intrinsic supports some sort of containment analysis - HW_Flag_SupportsContainment = 0x2000, - HW_Flag_SupportsContainmentZero = 0x4000 + HW_Flag_SupportsContainment = 0x2000 #else #error Unsupported platform @@ -642,18 +641,6 @@ struct HWIntrinsicInfo #endif } - static bool SupportsContainmentZero(NamedIntrinsic id) - { - HWIntrinsicFlag flags = lookupFlags(id); -#if defined(TARGET_XARCH) - return false; -#elif defined(TARGET_ARM64) - return (flags & HW_Flag_SupportsContainmentZero) != 0; -#else -#error Unsupported platform -#endif - } - static bool BaseTypeFromFirstArg(NamedIntrinsic id) { HWIntrinsicFlag flags = lookupFlags(id); diff --git a/src/coreclr/jit/hwintrinsiccodegenarm64.cpp b/src/coreclr/jit/hwintrinsiccodegenarm64.cpp index 7265b658602246..f9bddea8f30105 100644 --- a/src/coreclr/jit/hwintrinsiccodegenarm64.cpp +++ b/src/coreclr/jit/hwintrinsiccodegenarm64.cpp @@ -364,28 +364,21 @@ void CodeGen::genHWIntrinsic(GenTreeHWIntrinsic* node) { assert(!hasImmediateOperand); - size_t numOperands = intrin.numOperands; - - // This handles optimizations for instructions that have - // an implicit 'zero' vector of what would be the second operand. - if (HWIntrinsicInfo::SupportsContainmentZero(intrin.id)) - { - assert(HWIntrinsicInfo::SupportsContainment(intrin.id)); - assert(numOperands == 2); - if (intrin.op2->isContained() && intrin.op2->IsVectorZero()) - { - numOperands = 1; - } - } - - switch (numOperands) + switch (intrin.numOperands) { case 1: GetEmitter()->emitIns_R_R(ins, emitSize, targetReg, op1Reg, opt); break; case 2: - if (isRMW) + // This handles optimizations for instructions that have + // an implicit 'zero' vector of what would be the second operand. + if (HWIntrinsicInfo::SupportsContainment(intrin.id) && intrin.op2->isContained() && + intrin.op2->IsVectorZero()) + { + GetEmitter()->emitIns_R_R(ins, emitSize, targetReg, op1Reg, opt); + } + else if (isRMW) { assert(targetReg != op2Reg); diff --git a/src/coreclr/jit/hwintrinsiclistarm64.h b/src/coreclr/jit/hwintrinsiclistarm64.h index 700c5b8ef7f3fc..b5960c905ea681 100644 --- a/src/coreclr/jit/hwintrinsiclistarm64.h +++ b/src/coreclr/jit/hwintrinsiclistarm64.h @@ -240,9 +240,9 @@ HARDWARE_INTRINSIC(AdvSimd, BitwiseClear, HARDWARE_INTRINSIC(AdvSimd, BitwiseSelect, -1, 3, {INS_bsl, INS_bsl, INS_bsl, INS_bsl, INS_bsl, INS_bsl, INS_bsl, INS_bsl, INS_bsl, INS_bsl}, HW_Category_SIMD, HW_Flag_SpecialCodeGen) HARDWARE_INTRINSIC(AdvSimd, Ceiling, -1, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_frintp, INS_invalid}, HW_Category_SIMD, HW_Flag_NoFlag) HARDWARE_INTRINSIC(AdvSimd, CeilingScalar, 8, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_frintp, INS_frintp}, HW_Category_SIMD, HW_Flag_SIMDScalar) -HARDWARE_INTRINSIC(AdvSimd, CompareEqual, -1, 2, {INS_cmeq, INS_cmeq, INS_cmeq, INS_cmeq, INS_cmeq, INS_cmeq, INS_invalid, INS_invalid, INS_fcmeq, INS_invalid}, HW_Category_SIMD, HW_Flag_Commutative|HW_Flag_SupportsContainment|HW_Flag_SupportsContainmentZero) -HARDWARE_INTRINSIC(AdvSimd, CompareGreaterThan, -1, 2, {INS_cmgt, INS_cmhi, INS_cmgt, INS_cmhi, INS_cmgt, INS_cmhi, INS_invalid, INS_invalid, INS_fcmgt, INS_invalid}, HW_Category_SIMD, HW_Flag_SupportsContainment|HW_Flag_SupportsContainmentZero) -HARDWARE_INTRINSIC(AdvSimd, CompareGreaterThanOrEqual, -1, 2, {INS_cmge, INS_cmhs, INS_cmge, INS_cmhs, INS_cmge, INS_cmhs, INS_invalid, INS_invalid, INS_fcmge, INS_invalid}, HW_Category_SIMD, HW_Flag_SupportsContainment|HW_Flag_SupportsContainmentZero) +HARDWARE_INTRINSIC(AdvSimd, CompareEqual, -1, 2, {INS_cmeq, INS_cmeq, INS_cmeq, INS_cmeq, INS_cmeq, INS_cmeq, INS_invalid, INS_invalid, INS_fcmeq, INS_invalid}, HW_Category_SIMD, HW_Flag_Commutative|HW_Flag_SupportsContainment) +HARDWARE_INTRINSIC(AdvSimd, CompareGreaterThan, -1, 2, {INS_cmgt, INS_cmhi, INS_cmgt, INS_cmhi, INS_cmgt, INS_cmhi, INS_invalid, INS_invalid, INS_fcmgt, INS_invalid}, HW_Category_SIMD, HW_Flag_SupportsContainment) +HARDWARE_INTRINSIC(AdvSimd, CompareGreaterThanOrEqual, -1, 2, {INS_cmge, INS_cmhs, INS_cmge, INS_cmhs, INS_cmge, INS_cmhs, INS_invalid, INS_invalid, INS_fcmge, INS_invalid}, HW_Category_SIMD, HW_Flag_SupportsContainment) HARDWARE_INTRINSIC(AdvSimd, CompareLessThan, -1, 2, {INS_cmgt, INS_cmhi, INS_cmgt, INS_cmhi, INS_cmgt, INS_cmhi, INS_invalid, INS_invalid, INS_fcmgt, INS_invalid}, HW_Category_SIMD, HW_Flag_SpecialCodeGen) HARDWARE_INTRINSIC(AdvSimd, CompareLessThanOrEqual, -1, 2, {INS_cmge, INS_cmhs, INS_cmge, INS_cmhs, INS_cmge, INS_cmhs, INS_invalid, INS_invalid, INS_fcmge, INS_invalid}, HW_Category_SIMD, HW_Flag_SpecialCodeGen) HARDWARE_INTRINSIC(AdvSimd, CompareTest, -1, 2, {INS_cmtst, INS_cmtst, INS_cmtst, INS_cmtst, INS_cmtst, INS_cmtst, INS_invalid, INS_invalid, INS_cmtst, INS_invalid}, HW_Category_SIMD, HW_Flag_Commutative) @@ -492,12 +492,12 @@ HARDWARE_INTRINSIC(AdvSimd_Arm64, AddPairwiseScalar, HARDWARE_INTRINSIC(AdvSimd_Arm64, AddSaturate, -1, 2, {INS_suqadd, INS_usqadd, INS_suqadd, INS_usqadd, INS_suqadd, INS_usqadd, INS_suqadd, INS_usqadd, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_BaseTypeFromFirstArg|HW_Flag_HasRMWSemantics) HARDWARE_INTRINSIC(AdvSimd_Arm64, AddSaturateScalar, 8, 2, {INS_sqadd, INS_uqadd, INS_sqadd, INS_uqadd, INS_sqadd, INS_uqadd, INS_suqadd, INS_usqadd, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_BaseTypeFromFirstArg|HW_Flag_HasRMWSemantics|HW_Flag_SIMDScalar|HW_Flag_SpecialCodeGen) HARDWARE_INTRINSIC(AdvSimd_Arm64, Ceiling, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_frintp}, HW_Category_SIMD, HW_Flag_NoFlag) -HARDWARE_INTRINSIC(AdvSimd_Arm64, CompareEqual, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cmeq, INS_cmeq, INS_invalid, INS_fcmeq}, HW_Category_SIMD, HW_Flag_Commutative|HW_Flag_SupportsContainment|HW_Flag_SupportsContainmentZero) -HARDWARE_INTRINSIC(AdvSimd_Arm64, CompareEqualScalar, 8, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cmeq, INS_cmeq, INS_fcmeq, INS_fcmeq}, HW_Category_SIMD, HW_Flag_Commutative|HW_Flag_SIMDScalar|HW_Flag_SupportsContainment|HW_Flag_SupportsContainmentZero) -HARDWARE_INTRINSIC(AdvSimd_Arm64, CompareGreaterThan, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cmgt, INS_cmhi, INS_invalid, INS_fcmgt}, HW_Category_SIMD, HW_Flag_SupportsContainment|HW_Flag_SupportsContainmentZero) -HARDWARE_INTRINSIC(AdvSimd_Arm64, CompareGreaterThanOrEqual, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cmge, INS_cmhs, INS_invalid, INS_fcmge}, HW_Category_SIMD, HW_Flag_SupportsContainment|HW_Flag_SupportsContainmentZero) -HARDWARE_INTRINSIC(AdvSimd_Arm64, CompareGreaterThanOrEqualScalar, 8, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cmge, INS_cmhs, INS_fcmge, INS_fcmge}, HW_Category_SIMD, HW_Flag_SIMDScalar|HW_Flag_SupportsContainment||HW_Flag_SupportsContainmentZero) -HARDWARE_INTRINSIC(AdvSimd_Arm64, CompareGreaterThanScalar, 8, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cmgt, INS_cmhi, INS_fcmgt, INS_fcmgt}, HW_Category_SIMD, HW_Flag_SIMDScalar|HW_Flag_SupportsContainment|HW_Flag_SupportsContainmentZero) +HARDWARE_INTRINSIC(AdvSimd_Arm64, CompareEqual, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cmeq, INS_cmeq, INS_invalid, INS_fcmeq}, HW_Category_SIMD, HW_Flag_Commutative|HW_Flag_SupportsContainment) +HARDWARE_INTRINSIC(AdvSimd_Arm64, CompareEqualScalar, 8, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cmeq, INS_cmeq, INS_fcmeq, INS_fcmeq}, HW_Category_SIMD, HW_Flag_Commutative|HW_Flag_SIMDScalar|HW_Flag_SupportsContainment) +HARDWARE_INTRINSIC(AdvSimd_Arm64, CompareGreaterThan, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cmgt, INS_cmhi, INS_invalid, INS_fcmgt}, HW_Category_SIMD, HW_Flag_SupportsContainment) +HARDWARE_INTRINSIC(AdvSimd_Arm64, CompareGreaterThanOrEqual, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cmge, INS_cmhs, INS_invalid, INS_fcmge}, HW_Category_SIMD, HW_Flag_SupportsContainment) +HARDWARE_INTRINSIC(AdvSimd_Arm64, CompareGreaterThanOrEqualScalar, 8, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cmge, INS_cmhs, INS_fcmge, INS_fcmge}, HW_Category_SIMD, HW_Flag_SIMDScalar|HW_Flag_SupportsContainment) +HARDWARE_INTRINSIC(AdvSimd_Arm64, CompareGreaterThanScalar, 8, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cmgt, INS_cmhi, INS_fcmgt, INS_fcmgt}, HW_Category_SIMD, HW_Flag_SIMDScalar|HW_Flag_SupportsContainment) HARDWARE_INTRINSIC(AdvSimd_Arm64, CompareLessThan, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cmgt, INS_cmhi, INS_invalid, INS_fcmgt}, HW_Category_SIMD, HW_Flag_SpecialCodeGen) HARDWARE_INTRINSIC(AdvSimd_Arm64, CompareLessThanOrEqual, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cmge, INS_cmhs, INS_invalid, INS_fcmge}, HW_Category_SIMD, HW_Flag_SpecialCodeGen) HARDWARE_INTRINSIC(AdvSimd_Arm64, CompareLessThanOrEqualScalar, 8, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cmge, INS_cmhs, INS_fcmge, INS_fcmge}, HW_Category_SIMD, HW_Flag_SIMDScalar|HW_Flag_SpecialCodeGen)