diff --git a/llvm/lib/Target/ARM/ARMISelLowering.cpp b/llvm/lib/Target/ARM/ARMISelLowering.cpp --- a/llvm/lib/Target/ARM/ARMISelLowering.cpp +++ b/llvm/lib/Target/ARM/ARMISelLowering.cpp @@ -443,6 +443,7 @@ setOperationAction(ISD::SCALAR_TO_VECTOR, VT, Expand); setOperationAction(ISD::LOAD, VT, Custom); setOperationAction(ISD::STORE, VT, Custom); + setOperationAction(ISD::TRUNCATE, VT, Custom); } } @@ -8660,6 +8661,23 @@ DAG.getConstant(ARMCC::NE, dl, MVT::i32)); } +// Turn a truncate into a predicate (an i1 vector) into icmp(and(x, 1), 0). +static SDValue LowerTruncatei1(SDValue N, SelectionDAG &DAG, + const ARMSubtarget *ST) { + assert(ST->hasMVEIntegerOps() && "Expected MVE!"); + EVT VT = N.getValueType(); + assert((VT == MVT::v16i1 || VT == MVT::v8i1 || VT == MVT::v4i1) && + "Expected a vector i1 type!"); + SDValue Op = N.getOperand(0); + EVT FromVT = Op.getValueType(); + SDLoc DL(N); + + SDValue And = + DAG.getNode(ISD::AND, DL, FromVT, Op, DAG.getConstant(1, DL, FromVT)); + return DAG.getNode(ISD::SETCC, DL, VT, And, DAG.getConstant(0, DL, FromVT), + DAG.getCondCode(ISD::SETNE)); +} + /// isExtendedBUILD_VECTOR - Check if N is a constant BUILD_VECTOR where each /// element has been zero/sign-extended, depending on the isSigned parameter, /// from an integer type half its size. @@ -9771,6 +9789,7 @@ case ISD::INSERT_VECTOR_ELT: return LowerINSERT_VECTOR_ELT(Op, DAG); case ISD::EXTRACT_VECTOR_ELT: return LowerEXTRACT_VECTOR_ELT(Op, DAG, Subtarget); case ISD::CONCAT_VECTORS: return LowerCONCAT_VECTORS(Op, DAG, Subtarget); + case ISD::TRUNCATE: return LowerTruncatei1(Op, DAG, Subtarget); case ISD::FLT_ROUNDS_: return LowerFLT_ROUNDS_(Op, DAG); case ISD::MUL: return LowerMUL(Op, DAG); case ISD::SDIV: diff --git a/llvm/lib/Target/ARM/ARMInstrMVE.td b/llvm/lib/Target/ARM/ARMInstrMVE.td --- a/llvm/lib/Target/ARM/ARMInstrMVE.td +++ b/llvm/lib/Target/ARM/ARMInstrMVE.td @@ -6759,13 +6759,6 @@ (v8i16 (MVE_VPSEL (MVE_VMOVimmi16 1), (MVE_VMOVimmi16 0), ARMVCCNone, VCCR:$pred))>; def : Pat<(v4i32 (anyext (v4i1 VCCR:$pred))), (v4i32 (MVE_VPSEL (MVE_VMOVimmi32 1), (MVE_VMOVimmi32 0), ARMVCCNone, VCCR:$pred))>; - - def : Pat<(v16i1 (trunc (v16i8 MQPR:$v1))), - (v16i1 (MVE_VCMPi32r (v16i8 MQPR:$v1), ZR, ARMCCne))>; - def : Pat<(v8i1 (trunc (v8i16 MQPR:$v1))), - (v8i1 (MVE_VCMPi32r (v8i16 MQPR:$v1), ZR, ARMCCne))>; - def : Pat<(v4i1 (trunc (v4i32 MQPR:$v1))), - (v4i1 (MVE_VCMPi32r (v4i32 MQPR:$v1), ZR, ARMCCne))>; } let Predicates = [HasMVEFloat] in { diff --git a/llvm/test/CodeGen/Thumb2/mve-pred-ext.ll b/llvm/test/CodeGen/Thumb2/mve-pred-ext.ll --- a/llvm/test/CodeGen/Thumb2/mve-pred-ext.ll +++ b/llvm/test/CodeGen/Thumb2/mve-pred-ext.ll @@ -159,8 +159,10 @@ define arm_aapcs_vfpcc <4 x i32> @trunc_v4i1_v4i32(<4 x i32> %src) { ; CHECK-LABEL: trunc_v4i1_v4i32: ; CHECK: @ %bb.0: @ %entry +; CHECK-NEXT: vmov.i32 q2, #0x1 ; CHECK-NEXT: vmov.i32 q1, #0x0 -; CHECK-NEXT: vcmp.i32 ne, q0, zr +; CHECK-NEXT: vand q2, q0, q2 +; CHECK-NEXT: vcmp.i32 ne, q2, zr ; CHECK-NEXT: vpsel q0, q0, q1 ; CHECK-NEXT: bx lr entry: @@ -172,8 +174,10 @@ define arm_aapcs_vfpcc <8 x i16> @trunc_v8i1_v8i16(<8 x i16> %src) { ; CHECK-LABEL: trunc_v8i1_v8i16: ; CHECK: @ %bb.0: @ %entry +; CHECK-NEXT: vmov.i16 q2, #0x1 ; CHECK-NEXT: vmov.i32 q1, #0x0 -; CHECK-NEXT: vcmp.i32 ne, q0, zr +; CHECK-NEXT: vand q2, q0, q2 +; CHECK-NEXT: vcmp.i16 ne, q2, zr ; CHECK-NEXT: vpsel q0, q0, q1 ; CHECK-NEXT: bx lr entry: @@ -185,8 +189,10 @@ define arm_aapcs_vfpcc <16 x i8> @trunc_v16i1_v16i8(<16 x i8> %src) { ; CHECK-LABEL: trunc_v16i1_v16i8: ; CHECK: @ %bb.0: @ %entry +; CHECK-NEXT: vmov.i8 q2, #0x1 ; CHECK-NEXT: vmov.i32 q1, #0x0 -; CHECK-NEXT: vcmp.i32 ne, q0, zr +; CHECK-NEXT: vand q2, q0, q2 +; CHECK-NEXT: vcmp.i8 ne, q2, zr ; CHECK-NEXT: vpsel q0, q0, q1 ; CHECK-NEXT: bx lr entry: