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 @@ -6945,6 +6945,19 @@ } else return SDValue(); + // If this is a single value copied into all lanes (a splat), we can just sign + // extend that single value + SDValue FirstOp = Op.getOperand(0); + if (!isa(FirstOp) && + std::all_of(std::next(Op->op_begin()), Op->op_end(), + [&FirstOp](SDUse &U) { + return U.get().isUndef() || U.get() == FirstOp; + })) { + SDValue Ext = DAG.getNode(ISD::SIGN_EXTEND_INREG, dl, MVT::i32, FirstOp, + DAG.getValueType(MVT::i1)); + return DAG.getNode(ARMISD::PREDICATE_CAST, dl, Op.getValueType(), Ext); + } + // First create base with bits set where known unsigned Bits32 = 0; for (unsigned i = 0; i < NumElts; ++i) { @@ -6957,7 +6970,6 @@ } // Add in unknown nodes - // FIXME: Handle splats of the same value better. SDValue Base = DAG.getNode(ARMISD::PREDICATE_CAST, dl, VT, DAG.getConstant(Bits32, dl, MVT::i32)); for (unsigned i = 0; i < NumElts; ++i) { diff --git a/llvm/test/CodeGen/Thumb2/mve-pred-build-var.ll b/llvm/test/CodeGen/Thumb2/mve-pred-build-var.ll --- a/llvm/test/CodeGen/Thumb2/mve-pred-build-var.ll +++ b/llvm/test/CodeGen/Thumb2/mve-pred-build-var.ll @@ -44,15 +44,10 @@ ; CHECK-LABEL: build_varN_v4i1: ; CHECK: @ %bb.0: @ %entry ; CHECK-NEXT: cmp r0, r1 -; CHECK-NEXT: mov.w r1, #0 ; CHECK-NEXT: cset r0, lo ; CHECK-NEXT: and r0, r0, #1 ; CHECK-NEXT: rsbs r0, r0, #0 -; CHECK-NEXT: bfi r1, r0, #0, #4 -; CHECK-NEXT: bfi r1, r0, #4, #4 -; CHECK-NEXT: bfi r1, r0, #8, #4 -; CHECK-NEXT: bfi r1, r0, #12, #4 -; CHECK-NEXT: vmsr p0, r1 +; CHECK-NEXT: vmsr p0, r0 ; CHECK-NEXT: vpsel q0, q0, q1 ; CHECK-NEXT: bx lr entry: @@ -106,19 +101,10 @@ ; CHECK-LABEL: build_varN_v8i1: ; CHECK: @ %bb.0: @ %entry ; CHECK-NEXT: cmp r0, r1 -; CHECK-NEXT: mov.w r1, #0 ; CHECK-NEXT: cset r0, lo ; CHECK-NEXT: and r0, r0, #1 ; CHECK-NEXT: rsbs r0, r0, #0 -; CHECK-NEXT: bfi r1, r0, #0, #2 -; CHECK-NEXT: bfi r1, r0, #2, #2 -; CHECK-NEXT: bfi r1, r0, #4, #2 -; CHECK-NEXT: bfi r1, r0, #6, #2 -; CHECK-NEXT: bfi r1, r0, #8, #2 -; CHECK-NEXT: bfi r1, r0, #10, #2 -; CHECK-NEXT: bfi r1, r0, #12, #2 -; CHECK-NEXT: bfi r1, r0, #14, #2 -; CHECK-NEXT: vmsr p0, r1 +; CHECK-NEXT: vmsr p0, r0 ; CHECK-NEXT: vpsel q0, q0, q1 ; CHECK-NEXT: bx lr entry: @@ -172,27 +158,10 @@ ; CHECK-LABEL: build_varN_v16i1: ; CHECK: @ %bb.0: @ %entry ; CHECK-NEXT: cmp r0, r1 -; CHECK-NEXT: mov.w r1, #0 ; CHECK-NEXT: cset r0, lo ; CHECK-NEXT: and r0, r0, #1 ; CHECK-NEXT: rsbs r0, r0, #0 -; CHECK-NEXT: bfi r1, r0, #0, #1 -; CHECK-NEXT: bfi r1, r0, #1, #1 -; CHECK-NEXT: bfi r1, r0, #2, #1 -; CHECK-NEXT: bfi r1, r0, #3, #1 -; CHECK-NEXT: bfi r1, r0, #4, #1 -; CHECK-NEXT: bfi r1, r0, #5, #1 -; CHECK-NEXT: bfi r1, r0, #6, #1 -; CHECK-NEXT: bfi r1, r0, #7, #1 -; CHECK-NEXT: bfi r1, r0, #8, #1 -; CHECK-NEXT: bfi r1, r0, #9, #1 -; CHECK-NEXT: bfi r1, r0, #10, #1 -; CHECK-NEXT: bfi r1, r0, #11, #1 -; CHECK-NEXT: bfi r1, r0, #12, #1 -; CHECK-NEXT: bfi r1, r0, #13, #1 -; CHECK-NEXT: bfi r1, r0, #14, #1 -; CHECK-NEXT: bfi r1, r0, #15, #1 -; CHECK-NEXT: vmsr p0, r1 +; CHECK-NEXT: vmsr p0, r0 ; CHECK-NEXT: vpsel q0, q0, q1 ; CHECK-NEXT: bx lr entry: