MAKE_CASE(AArch64ISD::CTPOP_MERGE_PASSTHRU)
MAKE_CASE(AArch64ISD::DUP_MERGE_PASSTHRU)
MAKE_CASE(AArch64ISD::INDEX_VECTOR)
+ MAKE_CASE(AArch64ISD::SADDLP)
MAKE_CASE(AArch64ISD::UADDLP)
MAKE_CASE(AArch64ISD::CALL_RVMARKER)
MAKE_CASE(AArch64ISD::ASSERT_ZEXT_BOOL)
return DAG.getNode(Opcode, dl, Op.getValueType(), Op.getOperand(1),
Op.getOperand(2));
}
+ case Intrinsic::aarch64_neon_saddlp:
case Intrinsic::aarch64_neon_uaddlp: {
- unsigned Opcode = AArch64ISD::UADDLP;
+ unsigned Opcode = IntNo == Intrinsic::aarch64_neon_uaddlp
+ ? AArch64ISD::UADDLP
+ : AArch64ISD::SADDLP;
return DAG.getNode(Opcode, dl, Op.getValueType(), Op.getOperand(1));
}
case Intrinsic::aarch64_neon_sdot:
return DAG.getNode(ISD::VECREDUCE_ADD, DL, N->getValueType(0), Dot);
}
+// Given an (integer) vecreduce, we know the order of the inputs does not
+// matter. We can convert UADDV(add(zext(extract_lo(x)), zext(extract_hi(x))))
+// into UADDV(UADDLP(x)). This can also happen through an extra add, where we
+// transform UADDV(add(y, add(zext(extract_lo(x)), zext(extract_hi(x))))).
+static SDValue performUADDVCombine(SDNode *N, SelectionDAG &DAG) {
+ auto DetectAddExtract = [&](SDValue A) {
+ // Look for add(zext(extract_lo(x)), zext(extract_hi(x))), returning
+ // UADDLP(x) if found.
+ if (A.getOpcode() != ISD::ADD)
+ return SDValue();
+ EVT VT = A.getValueType();
+ SDValue Op0 = A.getOperand(0);
+ SDValue Op1 = A.getOperand(1);
+ if (Op0.getOpcode() != Op0.getOpcode() ||
+ (Op0.getOpcode() != ISD::ZERO_EXTEND &&
+ Op0.getOpcode() != ISD::SIGN_EXTEND))
+ return SDValue();
+ SDValue Ext0 = Op0.getOperand(0);
+ SDValue Ext1 = Op1.getOperand(0);
+ if (Ext0.getOpcode() != ISD::EXTRACT_SUBVECTOR ||
+ Ext1.getOpcode() != ISD::EXTRACT_SUBVECTOR ||
+ Ext0.getOperand(0) != Ext1.getOperand(0))
+ return SDValue();
+ // Check that the type is twice the add types, and the extract are from
+ // upper/lower parts of the same source.
+ if (Ext0.getOperand(0).getValueType().getVectorNumElements() !=
+ VT.getVectorNumElements() * 2)
+ return SDValue();
+ if ((Ext0.getConstantOperandVal(1) != 0 &&
+ Ext1.getConstantOperandVal(1) != VT.getVectorNumElements()) &&
+ (Ext1.getConstantOperandVal(1) != 0 &&
+ Ext0.getConstantOperandVal(1) != VT.getVectorNumElements()))
+ return SDValue();
+ unsigned Opcode = Op0.getOpcode() == ISD::ZERO_EXTEND ? AArch64ISD::UADDLP
+ : AArch64ISD::SADDLP;
+ return DAG.getNode(Opcode, SDLoc(A), VT, Ext0.getOperand(0));
+ };
+
+ SDValue A = N->getOperand(0);
+ if (SDValue R = DetectAddExtract(A))
+ return DAG.getNode(N->getOpcode(), SDLoc(N), N->getValueType(0), R);
+ if (A.getOpcode() == ISD::ADD) {
+ if (SDValue R = DetectAddExtract(A.getOperand(0)))
+ return DAG.getNode(N->getOpcode(), SDLoc(N), N->getValueType(0),
+ DAG.getNode(ISD::ADD, SDLoc(A), A.getValueType(), R,
+ A.getOperand(1)));
+ if (SDValue R = DetectAddExtract(A.getOperand(1)))
+ return DAG.getNode(N->getOpcode(), SDLoc(N), N->getValueType(0),
+ DAG.getNode(ISD::ADD, SDLoc(A), A.getValueType(), R,
+ A.getOperand(0)));
+ }
+ return SDValue();
+}
+
+
static SDValue performXorCombine(SDNode *N, SelectionDAG &DAG,
TargetLowering::DAGCombinerInfo &DCI,
const AArch64Subtarget *Subtarget) {
}
// ADD(UADDV a, UADDV b) --> UADDV(ADD a, b)
-static SDValue performUADDVCombine(SDNode *N, SelectionDAG &DAG) {
+static SDValue performAddUADDVCombine(SDNode *N, SelectionDAG &DAG) {
EVT VT = N->getValueType(0);
// Only scalar integer and vector types.
if (N->getOpcode() != ISD::ADD || !VT.isScalarInteger())
TargetLowering::DAGCombinerInfo &DCI,
SelectionDAG &DAG) {
// Try to change sum of two reductions.
- if (SDValue Val = performUADDVCombine(N, DAG))
+ if (SDValue Val = performAddUADDVCombine(N, DAG))
return Val;
if (SDValue Val = performAddDotCombine(N, DAG))
return Val;
return performExtractVectorEltCombine(N, DAG);
case ISD::VECREDUCE_ADD:
return performVecReduceAddCombine(N, DCI.DAG, Subtarget);
+ case AArch64ISD::UADDV:
+ return performUADDVCombine(N, DAG);
case ISD::INTRINSIC_VOID:
case ISD::INTRINSIC_W_CHAIN:
switch (cast<ConstantSDNode>(N->getOperand(1))->getZExtValue()) {
define i64 @add_v4i32_v4i64_zext(<4 x i32> %x) {
; CHECK-LABEL: add_v4i32_v4i64_zext:
; CHECK: // %bb.0: // %entry
-; CHECK-NEXT: ushll v1.2d, v0.2s, #0
-; CHECK-NEXT: uaddw2 v0.2d, v1.2d, v0.4s
-; CHECK-NEXT: addp d0, v0.2d
+; CHECK-NEXT: uaddlv d0, v0.4s
; CHECK-NEXT: fmov x0, d0
; CHECK-NEXT: ret
entry:
define i64 @add_v4i32_v4i64_sext(<4 x i32> %x) {
; CHECK-LABEL: add_v4i32_v4i64_sext:
; CHECK: // %bb.0: // %entry
-; CHECK-NEXT: sshll v1.2d, v0.2s, #0
-; CHECK-NEXT: saddw2 v0.2d, v1.2d, v0.4s
+; CHECK-NEXT: saddlp v0.2d, v0.4s
; CHECK-NEXT: addp d0, v0.2d
; CHECK-NEXT: fmov x0, d0
; CHECK-NEXT: ret
define i32 @add_v8i16_v8i32_zext(<8 x i16> %x) {
; CHECK-LABEL: add_v8i16_v8i32_zext:
; CHECK: // %bb.0: // %entry
-; CHECK-NEXT: ushll v1.4s, v0.4h, #0
-; CHECK-NEXT: uaddw2 v0.4s, v1.4s, v0.8h
-; CHECK-NEXT: addv s0, v0.4s
+; CHECK-NEXT: uaddlv s0, v0.8h
; CHECK-NEXT: fmov w0, s0
; CHECK-NEXT: ret
entry:
define i32 @add_v8i16_v8i32_sext(<8 x i16> %x) {
; CHECK-LABEL: add_v8i16_v8i32_sext:
; CHECK: // %bb.0: // %entry
-; CHECK-NEXT: sshll v1.4s, v0.4h, #0
-; CHECK-NEXT: saddw2 v0.4s, v1.4s, v0.8h
+; CHECK-NEXT: saddlp v0.4s, v0.8h
; CHECK-NEXT: addv s0, v0.4s
; CHECK-NEXT: fmov w0, s0
; CHECK-NEXT: ret
; CHECK-LABEL: add_v4i16_v4i64_zext:
; CHECK: // %bb.0: // %entry
; CHECK-NEXT: ushll v0.4s, v0.4h, #0
-; CHECK-NEXT: ushll v1.2d, v0.2s, #0
-; CHECK-NEXT: uaddw2 v0.2d, v1.2d, v0.4s
-; CHECK-NEXT: addp d0, v0.2d
+; CHECK-NEXT: uaddlv d0, v0.4s
; CHECK-NEXT: fmov x0, d0
; CHECK-NEXT: ret
entry:
; CHECK-LABEL: add_v4i16_v4i64_sext:
; CHECK: // %bb.0: // %entry
; CHECK-NEXT: sshll v0.4s, v0.4h, #0
-; CHECK-NEXT: sshll v1.2d, v0.2s, #0
-; CHECK-NEXT: saddw2 v0.2d, v1.2d, v0.4s
+; CHECK-NEXT: saddlp v0.2d, v0.4s
; CHECK-NEXT: addp d0, v0.2d
; CHECK-NEXT: fmov x0, d0
; CHECK-NEXT: ret
; CHECK-BASE-LABEL: add_v8i8_v8i32_zext:
; CHECK-BASE: // %bb.0: // %entry
; CHECK-BASE-NEXT: ushll v0.8h, v0.8b, #0
-; CHECK-BASE-NEXT: ushll v1.4s, v0.4h, #0
-; CHECK-BASE-NEXT: uaddw2 v0.4s, v1.4s, v0.8h
-; CHECK-BASE-NEXT: addv s0, v0.4s
+; CHECK-BASE-NEXT: uaddlv s0, v0.8h
; CHECK-BASE-NEXT: fmov w0, s0
; CHECK-BASE-NEXT: ret
;
; CHECK-BASE-LABEL: add_v8i8_v8i32_sext:
; CHECK-BASE: // %bb.0: // %entry
; CHECK-BASE-NEXT: sshll v0.8h, v0.8b, #0
-; CHECK-BASE-NEXT: sshll v1.4s, v0.4h, #0
-; CHECK-BASE-NEXT: saddw2 v0.4s, v1.4s, v0.8h
+; CHECK-BASE-NEXT: saddlp v0.4s, v0.8h
; CHECK-BASE-NEXT: addv s0, v0.4s
; CHECK-BASE-NEXT: fmov w0, s0
; CHECK-BASE-NEXT: ret
define zeroext i16 @add_v16i8_v16i16_zext(<16 x i8> %x) {
; CHECK-LABEL: add_v16i8_v16i16_zext:
; CHECK: // %bb.0: // %entry
-; CHECK-NEXT: ushll v1.8h, v0.8b, #0
-; CHECK-NEXT: uaddw2 v0.8h, v1.8h, v0.16b
+; CHECK-NEXT: uaddlp v0.8h, v0.16b
; CHECK-NEXT: addv h0, v0.8h
; CHECK-NEXT: fmov w0, s0
; CHECK-NEXT: ret
define signext i16 @add_v16i8_v16i16_sext(<16 x i8> %x) {
; CHECK-LABEL: add_v16i8_v16i16_sext:
; CHECK: // %bb.0: // %entry
-; CHECK-NEXT: sshll v1.8h, v0.8b, #0
-; CHECK-NEXT: saddw2 v0.8h, v1.8h, v0.16b
+; CHECK-NEXT: saddlp v0.8h, v0.16b
; CHECK-NEXT: addv h0, v0.8h
; CHECK-NEXT: smov w0, v0.h[0]
; CHECK-NEXT: ret
; CHECK: // %bb.0: // %entry
; CHECK-NEXT: bic v0.4h, #255, lsl #8
; CHECK-NEXT: ushll v0.4s, v0.4h, #0
-; CHECK-NEXT: ushll v1.2d, v0.2s, #0
-; CHECK-NEXT: uaddw2 v0.2d, v1.2d, v0.4s
-; CHECK-NEXT: addp d0, v0.2d
+; CHECK-NEXT: uaddlv d0, v0.4s
; CHECK-NEXT: fmov x0, d0
; CHECK-NEXT: ret
entry:
define i64 @add_v4i32_v4i64_acc_zext(<4 x i32> %x, i64 %a) {
; CHECK-LABEL: add_v4i32_v4i64_acc_zext:
; CHECK: // %bb.0: // %entry
-; CHECK-NEXT: ushll v1.2d, v0.2s, #0
-; CHECK-NEXT: uaddw2 v0.2d, v1.2d, v0.4s
-; CHECK-NEXT: addp d0, v0.2d
+; CHECK-NEXT: uaddlv d0, v0.4s
; CHECK-NEXT: fmov x8, d0
; CHECK-NEXT: add x0, x8, x0
; CHECK-NEXT: ret
define i64 @add_v4i32_v4i64_acc_sext(<4 x i32> %x, i64 %a) {
; CHECK-LABEL: add_v4i32_v4i64_acc_sext:
; CHECK: // %bb.0: // %entry
-; CHECK-NEXT: sshll v1.2d, v0.2s, #0
-; CHECK-NEXT: saddw2 v0.2d, v1.2d, v0.4s
+; CHECK-NEXT: saddlp v0.2d, v0.4s
; CHECK-NEXT: addp d0, v0.2d
; CHECK-NEXT: fmov x8, d0
; CHECK-NEXT: add x0, x8, x0
define i32 @add_v8i16_v8i32_acc_zext(<8 x i16> %x, i32 %a) {
; CHECK-LABEL: add_v8i16_v8i32_acc_zext:
; CHECK: // %bb.0: // %entry
-; CHECK-NEXT: ushll v1.4s, v0.4h, #0
-; CHECK-NEXT: uaddw2 v0.4s, v1.4s, v0.8h
-; CHECK-NEXT: addv s0, v0.4s
+; CHECK-NEXT: uaddlv s0, v0.8h
; CHECK-NEXT: fmov w8, s0
; CHECK-NEXT: add w0, w8, w0
; CHECK-NEXT: ret
define i32 @add_v8i16_v8i32_acc_sext(<8 x i16> %x, i32 %a) {
; CHECK-LABEL: add_v8i16_v8i32_acc_sext:
; CHECK: // %bb.0: // %entry
-; CHECK-NEXT: sshll v1.4s, v0.4h, #0
-; CHECK-NEXT: saddw2 v0.4s, v1.4s, v0.8h
+; CHECK-NEXT: saddlp v0.4s, v0.8h
; CHECK-NEXT: addv s0, v0.4s
; CHECK-NEXT: fmov w8, s0
; CHECK-NEXT: add w0, w8, w0
; CHECK-LABEL: add_v4i16_v4i64_acc_zext:
; CHECK: // %bb.0: // %entry
; CHECK-NEXT: ushll v0.4s, v0.4h, #0
-; CHECK-NEXT: ushll v1.2d, v0.2s, #0
-; CHECK-NEXT: uaddw2 v0.2d, v1.2d, v0.4s
-; CHECK-NEXT: addp d0, v0.2d
+; CHECK-NEXT: uaddlv d0, v0.4s
; CHECK-NEXT: fmov x8, d0
; CHECK-NEXT: add x0, x8, x0
; CHECK-NEXT: ret
; CHECK-LABEL: add_v4i16_v4i64_acc_sext:
; CHECK: // %bb.0: // %entry
; CHECK-NEXT: sshll v0.4s, v0.4h, #0
-; CHECK-NEXT: sshll v1.2d, v0.2s, #0
-; CHECK-NEXT: saddw2 v0.2d, v1.2d, v0.4s
+; CHECK-NEXT: saddlp v0.2d, v0.4s
; CHECK-NEXT: addp d0, v0.2d
; CHECK-NEXT: fmov x8, d0
; CHECK-NEXT: add x0, x8, x0
; CHECK-BASE-LABEL: add_v8i8_v8i32_acc_zext:
; CHECK-BASE: // %bb.0: // %entry
; CHECK-BASE-NEXT: ushll v0.8h, v0.8b, #0
-; CHECK-BASE-NEXT: ushll v1.4s, v0.4h, #0
-; CHECK-BASE-NEXT: uaddw2 v0.4s, v1.4s, v0.8h
-; CHECK-BASE-NEXT: addv s0, v0.4s
+; CHECK-BASE-NEXT: uaddlv s0, v0.8h
; CHECK-BASE-NEXT: fmov w8, s0
; CHECK-BASE-NEXT: add w0, w8, w0
; CHECK-BASE-NEXT: ret
; CHECK-BASE-LABEL: add_v8i8_v8i32_acc_sext:
; CHECK-BASE: // %bb.0: // %entry
; CHECK-BASE-NEXT: sshll v0.8h, v0.8b, #0
-; CHECK-BASE-NEXT: sshll v1.4s, v0.4h, #0
-; CHECK-BASE-NEXT: saddw2 v0.4s, v1.4s, v0.8h
+; CHECK-BASE-NEXT: saddlp v0.4s, v0.8h
; CHECK-BASE-NEXT: addv s0, v0.4s
; CHECK-BASE-NEXT: fmov w8, s0
; CHECK-BASE-NEXT: add w0, w8, w0
define zeroext i16 @add_v16i8_v16i16_acc_zext(<16 x i8> %x, i16 %a) {
; CHECK-LABEL: add_v16i8_v16i16_acc_zext:
; CHECK: // %bb.0: // %entry
-; CHECK-NEXT: ushll v1.8h, v0.8b, #0
-; CHECK-NEXT: uaddw2 v0.8h, v1.8h, v0.16b
-; CHECK-NEXT: addv h0, v0.8h
+; CHECK-NEXT: uaddlv h0, v0.16b
; CHECK-NEXT: fmov w8, s0
; CHECK-NEXT: add w8, w8, w0
; CHECK-NEXT: and w0, w8, #0xffff
define signext i16 @add_v16i8_v16i16_acc_sext(<16 x i8> %x, i16 %a) {
; CHECK-LABEL: add_v16i8_v16i16_acc_sext:
; CHECK: // %bb.0: // %entry
-; CHECK-NEXT: sshll v1.8h, v0.8b, #0
-; CHECK-NEXT: saddw2 v0.8h, v1.8h, v0.16b
+; CHECK-NEXT: saddlp v0.8h, v0.16b
; CHECK-NEXT: addv h0, v0.8h
; CHECK-NEXT: fmov w8, s0
; CHECK-NEXT: add w8, w8, w0
; CHECK: // %bb.0: // %entry
; CHECK-NEXT: bic v0.4h, #255, lsl #8
; CHECK-NEXT: ushll v0.4s, v0.4h, #0
-; CHECK-NEXT: ushll v1.2d, v0.2s, #0
-; CHECK-NEXT: uaddw2 v0.2d, v1.2d, v0.4s
-; CHECK-NEXT: addp d0, v0.2d
+; CHECK-NEXT: uaddlv d0, v0.4s
; CHECK-NEXT: fmov x8, d0
; CHECK-NEXT: add x0, x8, x0
; CHECK-NEXT: ret
define i64 @add_pair_v4i32_v4i64_zext(<4 x i32> %x, <4 x i32> %y) {
; CHECK-LABEL: add_pair_v4i32_v4i64_zext:
; CHECK: // %bb.0: // %entry
-; CHECK-NEXT: ushll v2.2d, v0.2s, #0
-; CHECK-NEXT: ushll v3.2d, v1.2s, #0
-; CHECK-NEXT: uaddw2 v0.2d, v2.2d, v0.4s
-; CHECK-NEXT: uaddw2 v1.2d, v3.2d, v1.4s
-; CHECK-NEXT: add v0.2d, v0.2d, v1.2d
+; CHECK-NEXT: uaddlp v0.2d, v0.4s
+; CHECK-NEXT: uadalp v0.2d, v1.4s
; CHECK-NEXT: addp d0, v0.2d
; CHECK-NEXT: fmov x0, d0
; CHECK-NEXT: ret
define i64 @add_pair_v4i32_v4i64_sext(<4 x i32> %x, <4 x i32> %y) {
; CHECK-LABEL: add_pair_v4i32_v4i64_sext:
; CHECK: // %bb.0: // %entry
-; CHECK-NEXT: sshll v2.2d, v0.2s, #0
-; CHECK-NEXT: sshll v3.2d, v1.2s, #0
-; CHECK-NEXT: saddw2 v0.2d, v2.2d, v0.4s
-; CHECK-NEXT: saddw2 v1.2d, v3.2d, v1.4s
-; CHECK-NEXT: add v0.2d, v0.2d, v1.2d
+; CHECK-NEXT: saddlp v0.2d, v0.4s
+; CHECK-NEXT: sadalp v0.2d, v1.4s
; CHECK-NEXT: addp d0, v0.2d
; CHECK-NEXT: fmov x0, d0
; CHECK-NEXT: ret
define i32 @add_pair_v8i16_v8i32_zext(<8 x i16> %x, <8 x i16> %y) {
; CHECK-LABEL: add_pair_v8i16_v8i32_zext:
; CHECK: // %bb.0: // %entry
-; CHECK-NEXT: ushll v2.4s, v0.4h, #0
-; CHECK-NEXT: ushll v3.4s, v1.4h, #0
-; CHECK-NEXT: uaddw2 v0.4s, v2.4s, v0.8h
-; CHECK-NEXT: uaddw2 v1.4s, v3.4s, v1.8h
-; CHECK-NEXT: add v0.4s, v0.4s, v1.4s
+; CHECK-NEXT: uaddlp v0.4s, v0.8h
+; CHECK-NEXT: uadalp v0.4s, v1.8h
; CHECK-NEXT: addv s0, v0.4s
; CHECK-NEXT: fmov w0, s0
; CHECK-NEXT: ret
define i32 @add_pair_v8i16_v8i32_sext(<8 x i16> %x, <8 x i16> %y) {
; CHECK-LABEL: add_pair_v8i16_v8i32_sext:
; CHECK: // %bb.0: // %entry
-; CHECK-NEXT: sshll v2.4s, v0.4h, #0
-; CHECK-NEXT: sshll v3.4s, v1.4h, #0
-; CHECK-NEXT: saddw2 v0.4s, v2.4s, v0.8h
-; CHECK-NEXT: saddw2 v1.4s, v3.4s, v1.8h
-; CHECK-NEXT: add v0.4s, v0.4s, v1.4s
+; CHECK-NEXT: saddlp v0.4s, v0.8h
+; CHECK-NEXT: sadalp v0.4s, v1.8h
; CHECK-NEXT: addv s0, v0.4s
; CHECK-NEXT: fmov w0, s0
; CHECK-NEXT: ret
; CHECK: // %bb.0: // %entry
; CHECK-NEXT: ushll v0.4s, v0.4h, #0
; CHECK-NEXT: ushll v1.4s, v1.4h, #0
-; CHECK-NEXT: ushll v2.2d, v0.2s, #0
-; CHECK-NEXT: ushll v3.2d, v1.2s, #0
-; CHECK-NEXT: uaddw2 v0.2d, v2.2d, v0.4s
-; CHECK-NEXT: uaddw2 v1.2d, v3.2d, v1.4s
-; CHECK-NEXT: add v0.2d, v0.2d, v1.2d
+; CHECK-NEXT: uaddlp v0.2d, v0.4s
+; CHECK-NEXT: uadalp v0.2d, v1.4s
; CHECK-NEXT: addp d0, v0.2d
; CHECK-NEXT: fmov x0, d0
; CHECK-NEXT: ret
; CHECK: // %bb.0: // %entry
; CHECK-NEXT: sshll v0.4s, v0.4h, #0
; CHECK-NEXT: sshll v1.4s, v1.4h, #0
-; CHECK-NEXT: sshll v2.2d, v0.2s, #0
-; CHECK-NEXT: sshll v3.2d, v1.2s, #0
-; CHECK-NEXT: saddw2 v0.2d, v2.2d, v0.4s
-; CHECK-NEXT: saddw2 v1.2d, v3.2d, v1.4s
-; CHECK-NEXT: add v0.2d, v0.2d, v1.2d
+; CHECK-NEXT: saddlp v0.2d, v0.4s
+; CHECK-NEXT: sadalp v0.2d, v1.4s
; CHECK-NEXT: addp d0, v0.2d
; CHECK-NEXT: fmov x0, d0
; CHECK-NEXT: ret
; CHECK-BASE: // %bb.0: // %entry
; CHECK-BASE-NEXT: ushll v0.8h, v0.8b, #0
; CHECK-BASE-NEXT: ushll v1.8h, v1.8b, #0
-; CHECK-BASE-NEXT: ushll v2.4s, v0.4h, #0
-; CHECK-BASE-NEXT: ushll v3.4s, v1.4h, #0
-; CHECK-BASE-NEXT: uaddw2 v0.4s, v2.4s, v0.8h
-; CHECK-BASE-NEXT: uaddw2 v1.4s, v3.4s, v1.8h
-; CHECK-BASE-NEXT: add v0.4s, v0.4s, v1.4s
+; CHECK-BASE-NEXT: uaddlp v0.4s, v0.8h
+; CHECK-BASE-NEXT: uadalp v0.4s, v1.8h
; CHECK-BASE-NEXT: addv s0, v0.4s
; CHECK-BASE-NEXT: fmov w0, s0
; CHECK-BASE-NEXT: ret
; CHECK-BASE: // %bb.0: // %entry
; CHECK-BASE-NEXT: sshll v0.8h, v0.8b, #0
; CHECK-BASE-NEXT: sshll v1.8h, v1.8b, #0
-; CHECK-BASE-NEXT: sshll v2.4s, v0.4h, #0
-; CHECK-BASE-NEXT: sshll v3.4s, v1.4h, #0
-; CHECK-BASE-NEXT: saddw2 v0.4s, v2.4s, v0.8h
-; CHECK-BASE-NEXT: saddw2 v1.4s, v3.4s, v1.8h
-; CHECK-BASE-NEXT: add v0.4s, v0.4s, v1.4s
+; CHECK-BASE-NEXT: saddlp v0.4s, v0.8h
+; CHECK-BASE-NEXT: sadalp v0.4s, v1.8h
; CHECK-BASE-NEXT: addv s0, v0.4s
; CHECK-BASE-NEXT: fmov w0, s0
; CHECK-BASE-NEXT: ret
define zeroext i16 @add_pair_v16i8_v16i16_zext(<16 x i8> %x, <16 x i8> %y) {
; CHECK-LABEL: add_pair_v16i8_v16i16_zext:
; CHECK: // %bb.0: // %entry
-; CHECK-NEXT: ushll v2.8h, v0.8b, #0
-; CHECK-NEXT: ushll v3.8h, v1.8b, #0
-; CHECK-NEXT: uaddw2 v0.8h, v2.8h, v0.16b
-; CHECK-NEXT: uaddw2 v1.8h, v3.8h, v1.16b
-; CHECK-NEXT: addv h0, v0.8h
-; CHECK-NEXT: addv h1, v1.8h
+; CHECK-NEXT: uaddlv h0, v0.16b
+; CHECK-NEXT: uaddlv h1, v1.16b
; CHECK-NEXT: fmov w8, s0
; CHECK-NEXT: fmov w9, s1
; CHECK-NEXT: add w8, w8, w9
define signext i16 @add_pair_v16i8_v16i16_sext(<16 x i8> %x, <16 x i8> %y) {
; CHECK-LABEL: add_pair_v16i8_v16i16_sext:
; CHECK: // %bb.0: // %entry
-; CHECK-NEXT: sshll v2.8h, v0.8b, #0
-; CHECK-NEXT: sshll v3.8h, v1.8b, #0
-; CHECK-NEXT: saddw2 v0.8h, v2.8h, v0.16b
-; CHECK-NEXT: saddw2 v1.8h, v3.8h, v1.16b
+; CHECK-NEXT: saddlp v0.8h, v0.16b
+; CHECK-NEXT: saddlp v1.8h, v1.16b
; CHECK-NEXT: addv h0, v0.8h
; CHECK-NEXT: addv h1, v1.8h
; CHECK-NEXT: fmov w8, s0
; CHECK-NEXT: bic v1.4h, #255, lsl #8
; CHECK-NEXT: ushll v0.4s, v0.4h, #0
; CHECK-NEXT: ushll v1.4s, v1.4h, #0
-; CHECK-NEXT: ushll v2.2d, v0.2s, #0
-; CHECK-NEXT: ushll v3.2d, v1.2s, #0
-; CHECK-NEXT: uaddw2 v0.2d, v2.2d, v0.4s
-; CHECK-NEXT: uaddw2 v1.2d, v3.2d, v1.4s
-; CHECK-NEXT: add v0.2d, v0.2d, v1.2d
+; CHECK-NEXT: uaddlp v0.2d, v0.4s
+; CHECK-NEXT: uadalp v0.2d, v1.4s
; CHECK-NEXT: addp d0, v0.2d
; CHECK-NEXT: fmov x0, d0
; CHECK-NEXT: ret