; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6 ; RUN: opt < %s -passes="default" -S -mattr=+sse2 | FileCheck %s ; RUN: opt < %s -passes="default" -S -mattr=+avx | FileCheck %s ; RUN: opt < %s -passes="default" -S -mattr=+avx2 | FileCheck %s ; RUN: opt < %s -passes="default" -S -mattr=+avx512f | FileCheck %s ; RUN: opt < %s -passes="default" -S -mattr=+avx512bw | FileCheck %s define i32 @_Z10test_shortPsS_i_128(ptr nocapture readonly %i0, ptr nocapture readonly %i1, i32 %i2) local_unnamed_addr #0 { ; CHECK-LABEL: define i32 @_Z10test_shortPsS_i_128( ; CHECK-SAME: ptr readonly captures(none) [[I0:%.*]], ptr readonly captures(none) [[I1:%.*]], i32 [[I2:%.*]]) local_unnamed_addr #[[ATTR0:[0-9]+]] { ; CHECK-NEXT: [[ENTRY:.*]]: ; CHECK-NEXT: [[TMP3:%.*]] = zext i32 [[I2]] to i64 ; CHECK-NEXT: br label %[[VECTOR_BODY:.*]] ; CHECK: [[VECTOR_BODY]]: ; CHECK-NEXT: [[INDEX:%.*]] = phi i64 [ [[INDEX_NEXT:%.*]], %[[VECTOR_BODY]] ], [ 0, %[[ENTRY]] ] ; CHECK-NEXT: [[VEC_PHI:%.*]] = phi <4 x i32> [ [[TMP9:%.*]], %[[VECTOR_BODY]] ], [ zeroinitializer, %[[ENTRY]] ] ; CHECK-NEXT: [[TMP4:%.*]] = getelementptr inbounds [2 x i8], ptr [[I0]], i64 [[INDEX]] ; CHECK-NEXT: [[WIDE_LOAD:%.*]] = load <4 x i16>, ptr [[TMP4]], align 2 ; CHECK-NEXT: [[TMP5:%.*]] = sext <4 x i16> [[WIDE_LOAD]] to <4 x i32> ; CHECK-NEXT: [[TMP6:%.*]] = getelementptr inbounds [2 x i8], ptr [[I1]], i64 [[INDEX]] ; CHECK-NEXT: [[WIDE_LOAD14:%.*]] = load <4 x i16>, ptr [[TMP6]], align 2 ; CHECK-NEXT: [[TMP7:%.*]] = sext <4 x i16> [[WIDE_LOAD14]] to <4 x i32> ; CHECK-NEXT: [[TMP8:%.*]] = mul nsw <4 x i32> [[TMP7]], [[TMP5]] ; CHECK-NEXT: [[TMP9]] = add nsw <4 x i32> [[TMP8]], [[VEC_PHI]] ; CHECK-NEXT: [[INDEX_NEXT]] = add i64 [[INDEX]], 8 ; CHECK-NEXT: [[TMP10:%.*]] = icmp eq i64 [[INDEX_NEXT]], [[TMP3]] ; CHECK-NEXT: br i1 [[TMP10]], label %[[MIDDLE_BLOCK:.*]], label %[[VECTOR_BODY]] ; CHECK: [[MIDDLE_BLOCK]]: ; CHECK-NEXT: [[TMP11:%.*]] = tail call i32 @llvm.vector.reduce.add.v4i32(<4 x i32> [[TMP9]]) ; CHECK-NEXT: ret i32 [[TMP11]] ; entry: %i3 = zext i32 %i2 to i64 br label %vector.body vector.body: %index = phi i64 [ %index.next, %vector.body ], [ 0, %entry ] %vec.phi = phi <4 x i32> [ %i11, %vector.body ], [ zeroinitializer, %entry ] %i4 = getelementptr inbounds i16, ptr %i0, i64 %index %i5 = bitcast ptr %i4 to ptr %wide.load = load <4 x i16>, ptr %i5, align 2 %i6 = sext <4 x i16> %wide.load to <4 x i32> %i7 = getelementptr inbounds i16, ptr %i1, i64 %index %i8 = bitcast ptr %i7 to ptr %wide.load14 = load <4 x i16>, ptr %i8, align 2 %i9 = sext <4 x i16> %wide.load14 to <4 x i32> %i10 = mul nsw <4 x i32> %i9, %i6 %i11 = add nsw <4 x i32> %i10, %vec.phi %index.next = add i64 %index, 8 %i12 = icmp eq i64 %index.next, %i3 br i1 %i12, label %middle.block, label %vector.body middle.block: %rdx.shuf15 = shufflevector <4 x i32> %i11, <4 x i32> undef, <4 x i32> %bin.rdx16 = add <4 x i32> %i11, %rdx.shuf15 %rdx.shuf17 = shufflevector <4 x i32> %bin.rdx16, <4 x i32> undef, <4 x i32> %bin.rdx18 = add <4 x i32> %bin.rdx16, %rdx.shuf17 %i13 = extractelement <4 x i32> %bin.rdx18, i32 0 ret i32 %i13 } define i32 @_Z10test_shortPsS_i_256(ptr nocapture readonly %i0, ptr nocapture readonly %i1, i32 %i2) local_unnamed_addr #0 { ; CHECK-LABEL: define i32 @_Z10test_shortPsS_i_256( ; CHECK-SAME: ptr readonly captures(none) [[I0:%.*]], ptr readonly captures(none) [[I1:%.*]], i32 [[I2:%.*]]) local_unnamed_addr #[[ATTR0]] { ; CHECK-NEXT: [[ENTRY:.*]]: ; CHECK-NEXT: [[TMP3:%.*]] = zext i32 [[I2]] to i64 ; CHECK-NEXT: br label %[[VECTOR_BODY:.*]] ; CHECK: [[VECTOR_BODY]]: ; CHECK-NEXT: [[INDEX:%.*]] = phi i64 [ [[INDEX_NEXT:%.*]], %[[VECTOR_BODY]] ], [ 0, %[[ENTRY]] ] ; CHECK-NEXT: [[VEC_PHI:%.*]] = phi <8 x i32> [ [[TMP9:%.*]], %[[VECTOR_BODY]] ], [ zeroinitializer, %[[ENTRY]] ] ; CHECK-NEXT: [[TMP4:%.*]] = getelementptr inbounds [2 x i8], ptr [[I0]], i64 [[INDEX]] ; CHECK-NEXT: [[WIDE_LOAD:%.*]] = load <8 x i16>, ptr [[TMP4]], align 2 ; CHECK-NEXT: [[TMP5:%.*]] = sext <8 x i16> [[WIDE_LOAD]] to <8 x i32> ; CHECK-NEXT: [[TMP6:%.*]] = getelementptr inbounds [2 x i8], ptr [[I1]], i64 [[INDEX]] ; CHECK-NEXT: [[WIDE_LOAD14:%.*]] = load <8 x i16>, ptr [[TMP6]], align 2 ; CHECK-NEXT: [[TMP7:%.*]] = sext <8 x i16> [[WIDE_LOAD14]] to <8 x i32> ; CHECK-NEXT: [[TMP8:%.*]] = mul nsw <8 x i32> [[TMP7]], [[TMP5]] ; CHECK-NEXT: [[TMP9]] = add nsw <8 x i32> [[TMP8]], [[VEC_PHI]] ; CHECK-NEXT: [[INDEX_NEXT]] = add i64 [[INDEX]], 8 ; CHECK-NEXT: [[TMP10:%.*]] = icmp eq i64 [[INDEX_NEXT]], [[TMP3]] ; CHECK-NEXT: br i1 [[TMP10]], label %[[MIDDLE_BLOCK:.*]], label %[[VECTOR_BODY]] ; CHECK: [[MIDDLE_BLOCK]]: ; CHECK-NEXT: [[TMP11:%.*]] = tail call i32 @llvm.vector.reduce.add.v8i32(<8 x i32> [[TMP9]]) ; CHECK-NEXT: ret i32 [[TMP11]] ; entry: %i3 = zext i32 %i2 to i64 br label %vector.body vector.body: %index = phi i64 [ %index.next, %vector.body ], [ 0, %entry ] %vec.phi = phi <8 x i32> [ %i11, %vector.body ], [ zeroinitializer, %entry ] %i4 = getelementptr inbounds i16, ptr %i0, i64 %index %i5 = bitcast ptr %i4 to ptr %wide.load = load <8 x i16>, ptr %i5, align 2 %i6 = sext <8 x i16> %wide.load to <8 x i32> %i7 = getelementptr inbounds i16, ptr %i1, i64 %index %i8 = bitcast ptr %i7 to ptr %wide.load14 = load <8 x i16>, ptr %i8, align 2 %i9 = sext <8 x i16> %wide.load14 to <8 x i32> %i10 = mul nsw <8 x i32> %i9, %i6 %i11 = add nsw <8 x i32> %i10, %vec.phi %index.next = add i64 %index, 8 %i12 = icmp eq i64 %index.next, %i3 br i1 %i12, label %middle.block, label %vector.body middle.block: %rdx.shuf = shufflevector <8 x i32> %i11, <8 x i32> undef, <8 x i32> %bin.rdx = add <8 x i32> %i11, %rdx.shuf %rdx.shuf15 = shufflevector <8 x i32> %bin.rdx, <8 x i32> undef, <8 x i32> %bin.rdx16 = add <8 x i32> %bin.rdx, %rdx.shuf15 %rdx.shuf17 = shufflevector <8 x i32> %bin.rdx16, <8 x i32> undef, <8 x i32> %bin.rdx18 = add <8 x i32> %bin.rdx16, %rdx.shuf17 %i13 = extractelement <8 x i32> %bin.rdx18, i32 0 ret i32 %i13 } define i32 @_Z10test_shortPsS_i_512(ptr nocapture readonly %i0, ptr nocapture readonly %i1, i32 %i2) local_unnamed_addr #0 { ; CHECK-LABEL: define i32 @_Z10test_shortPsS_i_512( ; CHECK-SAME: ptr readonly captures(none) [[I0:%.*]], ptr readonly captures(none) [[I1:%.*]], i32 [[I2:%.*]]) local_unnamed_addr #[[ATTR0]] { ; CHECK-NEXT: [[ENTRY:.*]]: ; CHECK-NEXT: [[TMP3:%.*]] = zext i32 [[I2]] to i64 ; CHECK-NEXT: br label %[[VECTOR_BODY:.*]] ; CHECK: [[VECTOR_BODY]]: ; CHECK-NEXT: [[INDEX:%.*]] = phi i64 [ [[INDEX_NEXT:%.*]], %[[VECTOR_BODY]] ], [ 0, %[[ENTRY]] ] ; CHECK-NEXT: [[VEC_PHI:%.*]] = phi <16 x i32> [ [[TMP9:%.*]], %[[VECTOR_BODY]] ], [ zeroinitializer, %[[ENTRY]] ] ; CHECK-NEXT: [[TMP4:%.*]] = getelementptr inbounds [2 x i8], ptr [[I0]], i64 [[INDEX]] ; CHECK-NEXT: [[WIDE_LOAD:%.*]] = load <16 x i16>, ptr [[TMP4]], align 2 ; CHECK-NEXT: [[TMP5:%.*]] = sext <16 x i16> [[WIDE_LOAD]] to <16 x i32> ; CHECK-NEXT: [[TMP6:%.*]] = getelementptr inbounds [2 x i8], ptr [[I1]], i64 [[INDEX]] ; CHECK-NEXT: [[WIDE_LOAD14:%.*]] = load <16 x i16>, ptr [[TMP6]], align 2 ; CHECK-NEXT: [[TMP7:%.*]] = sext <16 x i16> [[WIDE_LOAD14]] to <16 x i32> ; CHECK-NEXT: [[TMP8:%.*]] = mul nsw <16 x i32> [[TMP7]], [[TMP5]] ; CHECK-NEXT: [[TMP9]] = add nsw <16 x i32> [[TMP8]], [[VEC_PHI]] ; CHECK-NEXT: [[INDEX_NEXT]] = add i64 [[INDEX]], 16 ; CHECK-NEXT: [[TMP10:%.*]] = icmp eq i64 [[INDEX_NEXT]], [[TMP3]] ; CHECK-NEXT: br i1 [[TMP10]], label %[[MIDDLE_BLOCK:.*]], label %[[VECTOR_BODY]] ; CHECK: [[MIDDLE_BLOCK]]: ; CHECK-NEXT: [[TMP11:%.*]] = tail call i32 @llvm.vector.reduce.add.v16i32(<16 x i32> [[TMP9]]) ; CHECK-NEXT: ret i32 [[TMP11]] ; entry: %i3 = zext i32 %i2 to i64 br label %vector.body vector.body: %index = phi i64 [ %index.next, %vector.body ], [ 0, %entry ] %vec.phi = phi <16 x i32> [ %i11, %vector.body ], [ zeroinitializer, %entry ] %i4 = getelementptr inbounds i16, ptr %i0, i64 %index %i5 = bitcast ptr %i4 to ptr %wide.load = load <16 x i16>, ptr %i5, align 2 %i6 = sext <16 x i16> %wide.load to <16 x i32> %i7 = getelementptr inbounds i16, ptr %i1, i64 %index %i8 = bitcast ptr %i7 to ptr %wide.load14 = load <16 x i16>, ptr %i8, align 2 %i9 = sext <16 x i16> %wide.load14 to <16 x i32> %i10 = mul nsw <16 x i32> %i9, %i6 %i11 = add nsw <16 x i32> %i10, %vec.phi %index.next = add i64 %index, 16 %i12 = icmp eq i64 %index.next, %i3 br i1 %i12, label %middle.block, label %vector.body middle.block: %rdx.shuf1 = shufflevector <16 x i32> %i11, <16 x i32> undef, <16 x i32> %bin.rdx1 = add <16 x i32> %i11, %rdx.shuf1 %rdx.shuf = shufflevector <16 x i32> %bin.rdx1, <16 x i32> undef, <16 x i32> %bin.rdx = add <16 x i32> %bin.rdx1, %rdx.shuf %rdx.shuf15 = shufflevector <16 x i32> %bin.rdx, <16 x i32> undef, <16 x i32> %bin.rdx16 = add <16 x i32> %bin.rdx, %rdx.shuf15 %rdx.shuf17 = shufflevector <16 x i32> %bin.rdx16, <16 x i32> undef, <16 x i32> %bin.rdx18 = add <16 x i32> %bin.rdx16, %rdx.shuf17 %i13 = extractelement <16 x i32> %bin.rdx18, i32 0 ret i32 %i13 } define i32 @_Z10test_shortPsS_i_1024(ptr nocapture readonly %i0, ptr nocapture readonly %i1, i32 %i2) local_unnamed_addr #0 { ; CHECK-LABEL: define i32 @_Z10test_shortPsS_i_1024( ; CHECK-SAME: ptr readonly captures(none) [[I0:%.*]], ptr readonly captures(none) [[I1:%.*]], i32 [[I2:%.*]]) local_unnamed_addr #[[ATTR0]] { ; CHECK-NEXT: [[ENTRY:.*]]: ; CHECK-NEXT: [[TMP3:%.*]] = zext i32 [[I2]] to i64 ; CHECK-NEXT: br label %[[VECTOR_BODY:.*]] ; CHECK: [[VECTOR_BODY]]: ; CHECK-NEXT: [[INDEX:%.*]] = phi i64 [ [[INDEX_NEXT:%.*]], %[[VECTOR_BODY]] ], [ 0, %[[ENTRY]] ] ; CHECK-NEXT: [[VEC_PHI:%.*]] = phi <32 x i32> [ [[TMP9:%.*]], %[[VECTOR_BODY]] ], [ zeroinitializer, %[[ENTRY]] ] ; CHECK-NEXT: [[TMP4:%.*]] = getelementptr inbounds [2 x i8], ptr [[I0]], i64 [[INDEX]] ; CHECK-NEXT: [[WIDE_LOAD:%.*]] = load <32 x i16>, ptr [[TMP4]], align 2 ; CHECK-NEXT: [[TMP5:%.*]] = sext <32 x i16> [[WIDE_LOAD]] to <32 x i32> ; CHECK-NEXT: [[TMP6:%.*]] = getelementptr inbounds [2 x i8], ptr [[I1]], i64 [[INDEX]] ; CHECK-NEXT: [[WIDE_LOAD14:%.*]] = load <32 x i16>, ptr [[TMP6]], align 2 ; CHECK-NEXT: [[TMP7:%.*]] = sext <32 x i16> [[WIDE_LOAD14]] to <32 x i32> ; CHECK-NEXT: [[TMP8:%.*]] = mul nsw <32 x i32> [[TMP7]], [[TMP5]] ; CHECK-NEXT: [[TMP9]] = add nsw <32 x i32> [[TMP8]], [[VEC_PHI]] ; CHECK-NEXT: [[INDEX_NEXT]] = add i64 [[INDEX]], 16 ; CHECK-NEXT: [[TMP10:%.*]] = icmp eq i64 [[INDEX_NEXT]], [[TMP3]] ; CHECK-NEXT: br i1 [[TMP10]], label %[[MIDDLE_BLOCK:.*]], label %[[VECTOR_BODY]] ; CHECK: [[MIDDLE_BLOCK]]: ; CHECK-NEXT: [[TMP11:%.*]] = tail call i32 @llvm.vector.reduce.add.v32i32(<32 x i32> [[TMP9]]) ; CHECK-NEXT: ret i32 [[TMP11]] ; entry: %i3 = zext i32 %i2 to i64 br label %vector.body vector.body: %index = phi i64 [ %index.next, %vector.body ], [ 0, %entry ] %vec.phi = phi <32 x i32> [ %i11, %vector.body ], [ zeroinitializer, %entry ] %i4 = getelementptr inbounds i16, ptr %i0, i64 %index %i5 = bitcast ptr %i4 to ptr %wide.load = load <32 x i16>, ptr %i5, align 2 %i6 = sext <32 x i16> %wide.load to <32 x i32> %i7 = getelementptr inbounds i16, ptr %i1, i64 %index %i8 = bitcast ptr %i7 to ptr %wide.load14 = load <32 x i16>, ptr %i8, align 2 %i9 = sext <32 x i16> %wide.load14 to <32 x i32> %i10 = mul nsw <32 x i32> %i9, %i6 %i11 = add nsw <32 x i32> %i10, %vec.phi %index.next = add i64 %index, 16 %i12 = icmp eq i64 %index.next, %i3 br i1 %i12, label %middle.block, label %vector.body middle.block: %rdx.shuf2 = shufflevector <32 x i32> %i11, <32 x i32> undef, <32 x i32> %bin.rdx2 = add <32 x i32> %i11, %rdx.shuf2 %rdx.shuf1 = shufflevector <32 x i32> %bin.rdx2, <32 x i32> undef, <32 x i32> %bin.rdx1 = add <32 x i32> %bin.rdx2, %rdx.shuf1 %rdx.shuf = shufflevector <32 x i32> %bin.rdx1, <32 x i32> undef, <32 x i32> %bin.rdx = add <32 x i32> %bin.rdx1, %rdx.shuf %rdx.shuf15 = shufflevector <32 x i32> %bin.rdx, <32 x i32> undef, <32 x i32> %bin.rdx16 = add <32 x i32> %bin.rdx, %rdx.shuf15 %rdx.shuf17 = shufflevector <32 x i32> %bin.rdx16, <32 x i32> undef, <32 x i32> %bin.rdx18 = add <32 x i32> %bin.rdx16, %rdx.shuf17 %i13 = extractelement <32 x i32> %bin.rdx18, i32 0 ret i32 %i13 } define i32 @_Z9test_charPcS_i_128(ptr nocapture readonly %i0, ptr nocapture readonly %i1, i32 %i2) local_unnamed_addr #0 { ; CHECK-LABEL: define i32 @_Z9test_charPcS_i_128( ; CHECK-SAME: ptr readonly captures(none) [[I0:%.*]], ptr readonly captures(none) [[I1:%.*]], i32 [[I2:%.*]]) local_unnamed_addr #[[ATTR0]] { ; CHECK-NEXT: [[ENTRY:.*]]: ; CHECK-NEXT: [[TMP3:%.*]] = zext i32 [[I2]] to i64 ; CHECK-NEXT: br label %[[VECTOR_BODY:.*]] ; CHECK: [[VECTOR_BODY]]: ; CHECK-NEXT: [[INDEX:%.*]] = phi i64 [ [[INDEX_NEXT:%.*]], %[[VECTOR_BODY]] ], [ 0, %[[ENTRY]] ] ; CHECK-NEXT: [[VEC_PHI:%.*]] = phi <4 x i32> [ [[TMP9:%.*]], %[[VECTOR_BODY]] ], [ zeroinitializer, %[[ENTRY]] ] ; CHECK-NEXT: [[TMP4:%.*]] = getelementptr inbounds i8, ptr [[I0]], i64 [[INDEX]] ; CHECK-NEXT: [[WIDE_LOAD:%.*]] = load <4 x i8>, ptr [[TMP4]], align 1 ; CHECK-NEXT: [[TMP5:%.*]] = sext <4 x i8> [[WIDE_LOAD]] to <4 x i32> ; CHECK-NEXT: [[TMP6:%.*]] = getelementptr inbounds i8, ptr [[I1]], i64 [[INDEX]] ; CHECK-NEXT: [[WIDE_LOAD14:%.*]] = load <4 x i8>, ptr [[TMP6]], align 1 ; CHECK-NEXT: [[TMP7:%.*]] = sext <4 x i8> [[WIDE_LOAD14]] to <4 x i32> ; CHECK-NEXT: [[TMP8:%.*]] = mul nsw <4 x i32> [[TMP7]], [[TMP5]] ; CHECK-NEXT: [[TMP9]] = add nsw <4 x i32> [[TMP8]], [[VEC_PHI]] ; CHECK-NEXT: [[INDEX_NEXT]] = add i64 [[INDEX]], 16 ; CHECK-NEXT: [[TMP10:%.*]] = icmp eq i64 [[INDEX_NEXT]], [[TMP3]] ; CHECK-NEXT: br i1 [[TMP10]], label %[[MIDDLE_BLOCK:.*]], label %[[VECTOR_BODY]] ; CHECK: [[MIDDLE_BLOCK]]: ; CHECK-NEXT: [[TMP11:%.*]] = tail call i32 @llvm.vector.reduce.add.v4i32(<4 x i32> [[TMP9]]) ; CHECK-NEXT: ret i32 [[TMP11]] ; entry: %i3 = zext i32 %i2 to i64 br label %vector.body vector.body: %index = phi i64 [ %index.next, %vector.body ], [ 0, %entry ] %vec.phi = phi <4 x i32> [ %i11, %vector.body ], [ zeroinitializer, %entry ] %i4 = getelementptr inbounds i8, ptr %i0, i64 %index %i5 = bitcast ptr %i4 to ptr %wide.load = load <4 x i8>, ptr %i5, align 1 %i6 = sext <4 x i8> %wide.load to <4 x i32> %i7 = getelementptr inbounds i8, ptr %i1, i64 %index %i8 = bitcast ptr %i7 to ptr %wide.load14 = load <4 x i8>, ptr %i8, align 1 %i9 = sext <4 x i8> %wide.load14 to <4 x i32> %i10 = mul nsw <4 x i32> %i9, %i6 %i11 = add nsw <4 x i32> %i10, %vec.phi %index.next = add i64 %index, 16 %i12 = icmp eq i64 %index.next, %i3 br i1 %i12, label %middle.block, label %vector.body middle.block: %rdx.shuf17 = shufflevector <4 x i32> %i11, <4 x i32> undef, <4 x i32> %bin.rdx18 = add <4 x i32> %i11, %rdx.shuf17 %rdx.shuf19 = shufflevector <4 x i32> %bin.rdx18, <4 x i32> undef, <4 x i32> %bin.rdx20 = add <4 x i32> %bin.rdx18, %rdx.shuf19 %i13 = extractelement <4 x i32> %bin.rdx20, i32 0 ret i32 %i13 } define i32 @_Z9test_charPcS_i_256(ptr nocapture readonly %i0, ptr nocapture readonly %i1, i32 %i2) local_unnamed_addr #0 { ; CHECK-LABEL: define i32 @_Z9test_charPcS_i_256( ; CHECK-SAME: ptr readonly captures(none) [[I0:%.*]], ptr readonly captures(none) [[I1:%.*]], i32 [[I2:%.*]]) local_unnamed_addr #[[ATTR0]] { ; CHECK-NEXT: [[ENTRY:.*]]: ; CHECK-NEXT: [[TMP3:%.*]] = zext i32 [[I2]] to i64 ; CHECK-NEXT: br label %[[VECTOR_BODY:.*]] ; CHECK: [[VECTOR_BODY]]: ; CHECK-NEXT: [[INDEX:%.*]] = phi i64 [ [[INDEX_NEXT:%.*]], %[[VECTOR_BODY]] ], [ 0, %[[ENTRY]] ] ; CHECK-NEXT: [[VEC_PHI:%.*]] = phi <8 x i32> [ [[TMP9:%.*]], %[[VECTOR_BODY]] ], [ zeroinitializer, %[[ENTRY]] ] ; CHECK-NEXT: [[TMP4:%.*]] = getelementptr inbounds i8, ptr [[I0]], i64 [[INDEX]] ; CHECK-NEXT: [[WIDE_LOAD:%.*]] = load <8 x i8>, ptr [[TMP4]], align 1 ; CHECK-NEXT: [[TMP5:%.*]] = sext <8 x i8> [[WIDE_LOAD]] to <8 x i32> ; CHECK-NEXT: [[TMP6:%.*]] = getelementptr inbounds i8, ptr [[I1]], i64 [[INDEX]] ; CHECK-NEXT: [[WIDE_LOAD14:%.*]] = load <8 x i8>, ptr [[TMP6]], align 1 ; CHECK-NEXT: [[TMP7:%.*]] = sext <8 x i8> [[WIDE_LOAD14]] to <8 x i32> ; CHECK-NEXT: [[TMP8:%.*]] = mul nsw <8 x i32> [[TMP7]], [[TMP5]] ; CHECK-NEXT: [[TMP9]] = add nsw <8 x i32> [[TMP8]], [[VEC_PHI]] ; CHECK-NEXT: [[INDEX_NEXT]] = add i64 [[INDEX]], 16 ; CHECK-NEXT: [[TMP10:%.*]] = icmp eq i64 [[INDEX_NEXT]], [[TMP3]] ; CHECK-NEXT: br i1 [[TMP10]], label %[[MIDDLE_BLOCK:.*]], label %[[VECTOR_BODY]] ; CHECK: [[MIDDLE_BLOCK]]: ; CHECK-NEXT: [[TMP11:%.*]] = tail call i32 @llvm.vector.reduce.add.v8i32(<8 x i32> [[TMP9]]) ; CHECK-NEXT: ret i32 [[TMP11]] ; entry: %i3 = zext i32 %i2 to i64 br label %vector.body vector.body: %index = phi i64 [ %index.next, %vector.body ], [ 0, %entry ] %vec.phi = phi <8 x i32> [ %i11, %vector.body ], [ zeroinitializer, %entry ] %i4 = getelementptr inbounds i8, ptr %i0, i64 %index %i5 = bitcast ptr %i4 to ptr %wide.load = load <8 x i8>, ptr %i5, align 1 %i6 = sext <8 x i8> %wide.load to <8 x i32> %i7 = getelementptr inbounds i8, ptr %i1, i64 %index %i8 = bitcast ptr %i7 to ptr %wide.load14 = load <8 x i8>, ptr %i8, align 1 %i9 = sext <8 x i8> %wide.load14 to <8 x i32> %i10 = mul nsw <8 x i32> %i9, %i6 %i11 = add nsw <8 x i32> %i10, %vec.phi %index.next = add i64 %index, 16 %i12 = icmp eq i64 %index.next, %i3 br i1 %i12, label %middle.block, label %vector.body middle.block: %rdx.shuf15 = shufflevector <8 x i32> %i11, <8 x i32> undef, <8 x i32> %bin.rdx16 = add <8 x i32> %i11, %rdx.shuf15 %rdx.shuf17 = shufflevector <8 x i32> %bin.rdx16, <8 x i32> undef, <8 x i32> %bin.rdx18 = add <8 x i32> %bin.rdx16, %rdx.shuf17 %rdx.shuf19 = shufflevector <8 x i32> %bin.rdx18, <8 x i32> undef, <8 x i32> %bin.rdx20 = add <8 x i32> %bin.rdx18, %rdx.shuf19 %i13 = extractelement <8 x i32> %bin.rdx20, i32 0 ret i32 %i13 } define i32 @_Z9test_charPcS_i_512(ptr nocapture readonly %i0, ptr nocapture readonly %i1, i32 %i2) local_unnamed_addr #0 { ; CHECK-LABEL: define i32 @_Z9test_charPcS_i_512( ; CHECK-SAME: ptr readonly captures(none) [[I0:%.*]], ptr readonly captures(none) [[I1:%.*]], i32 [[I2:%.*]]) local_unnamed_addr #[[ATTR0]] { ; CHECK-NEXT: [[ENTRY:.*]]: ; CHECK-NEXT: [[TMP3:%.*]] = zext i32 [[I2]] to i64 ; CHECK-NEXT: br label %[[VECTOR_BODY:.*]] ; CHECK: [[VECTOR_BODY]]: ; CHECK-NEXT: [[INDEX:%.*]] = phi i64 [ [[INDEX_NEXT:%.*]], %[[VECTOR_BODY]] ], [ 0, %[[ENTRY]] ] ; CHECK-NEXT: [[VEC_PHI:%.*]] = phi <16 x i32> [ [[TMP9:%.*]], %[[VECTOR_BODY]] ], [ zeroinitializer, %[[ENTRY]] ] ; CHECK-NEXT: [[TMP4:%.*]] = getelementptr inbounds i8, ptr [[I0]], i64 [[INDEX]] ; CHECK-NEXT: [[WIDE_LOAD:%.*]] = load <16 x i8>, ptr [[TMP4]], align 1 ; CHECK-NEXT: [[TMP5:%.*]] = sext <16 x i8> [[WIDE_LOAD]] to <16 x i32> ; CHECK-NEXT: [[TMP6:%.*]] = getelementptr inbounds i8, ptr [[I1]], i64 [[INDEX]] ; CHECK-NEXT: [[WIDE_LOAD14:%.*]] = load <16 x i8>, ptr [[TMP6]], align 1 ; CHECK-NEXT: [[TMP7:%.*]] = sext <16 x i8> [[WIDE_LOAD14]] to <16 x i32> ; CHECK-NEXT: [[TMP8:%.*]] = mul nsw <16 x i32> [[TMP7]], [[TMP5]] ; CHECK-NEXT: [[TMP9]] = add nsw <16 x i32> [[TMP8]], [[VEC_PHI]] ; CHECK-NEXT: [[INDEX_NEXT]] = add i64 [[INDEX]], 16 ; CHECK-NEXT: [[TMP10:%.*]] = icmp eq i64 [[INDEX_NEXT]], [[TMP3]] ; CHECK-NEXT: br i1 [[TMP10]], label %[[MIDDLE_BLOCK:.*]], label %[[VECTOR_BODY]] ; CHECK: [[MIDDLE_BLOCK]]: ; CHECK-NEXT: [[TMP11:%.*]] = tail call i32 @llvm.vector.reduce.add.v16i32(<16 x i32> [[TMP9]]) ; CHECK-NEXT: ret i32 [[TMP11]] ; entry: %i3 = zext i32 %i2 to i64 br label %vector.body vector.body: %index = phi i64 [ %index.next, %vector.body ], [ 0, %entry ] %vec.phi = phi <16 x i32> [ %i11, %vector.body ], [ zeroinitializer, %entry ] %i4 = getelementptr inbounds i8, ptr %i0, i64 %index %i5 = bitcast ptr %i4 to ptr %wide.load = load <16 x i8>, ptr %i5, align 1 %i6 = sext <16 x i8> %wide.load to <16 x i32> %i7 = getelementptr inbounds i8, ptr %i1, i64 %index %i8 = bitcast ptr %i7 to ptr %wide.load14 = load <16 x i8>, ptr %i8, align 1 %i9 = sext <16 x i8> %wide.load14 to <16 x i32> %i10 = mul nsw <16 x i32> %i9, %i6 %i11 = add nsw <16 x i32> %i10, %vec.phi %index.next = add i64 %index, 16 %i12 = icmp eq i64 %index.next, %i3 br i1 %i12, label %middle.block, label %vector.body middle.block: %rdx.shuf = shufflevector <16 x i32> %i11, <16 x i32> undef, <16 x i32> %bin.rdx = add <16 x i32> %i11, %rdx.shuf %rdx.shuf15 = shufflevector <16 x i32> %bin.rdx, <16 x i32> undef, <16 x i32> %bin.rdx16 = add <16 x i32> %bin.rdx, %rdx.shuf15 %rdx.shuf17 = shufflevector <16 x i32> %bin.rdx16, <16 x i32> undef, <16 x i32> %bin.rdx18 = add <16 x i32> %bin.rdx16, %rdx.shuf17 %rdx.shuf19 = shufflevector <16 x i32> %bin.rdx18, <16 x i32> undef, <16 x i32> %bin.rdx20 = add <16 x i32> %bin.rdx18, %rdx.shuf19 %i13 = extractelement <16 x i32> %bin.rdx20, i32 0 ret i32 %i13 } define i32 @_Z9test_charPcS_i_1024(ptr nocapture readonly %i0, ptr nocapture readonly %i1, i32 %i2) local_unnamed_addr #0 { ; CHECK-LABEL: define i32 @_Z9test_charPcS_i_1024( ; CHECK-SAME: ptr readonly captures(none) [[I0:%.*]], ptr readonly captures(none) [[I1:%.*]], i32 [[I2:%.*]]) local_unnamed_addr #[[ATTR0]] { ; CHECK-NEXT: [[ENTRY:.*]]: ; CHECK-NEXT: [[TMP3:%.*]] = zext i32 [[I2]] to i64 ; CHECK-NEXT: br label %[[VECTOR_BODY:.*]] ; CHECK: [[VECTOR_BODY]]: ; CHECK-NEXT: [[INDEX:%.*]] = phi i64 [ [[INDEX_NEXT:%.*]], %[[VECTOR_BODY]] ], [ 0, %[[ENTRY]] ] ; CHECK-NEXT: [[VEC_PHI:%.*]] = phi <32 x i32> [ [[TMP9:%.*]], %[[VECTOR_BODY]] ], [ zeroinitializer, %[[ENTRY]] ] ; CHECK-NEXT: [[TMP4:%.*]] = getelementptr inbounds i8, ptr [[I0]], i64 [[INDEX]] ; CHECK-NEXT: [[WIDE_LOAD:%.*]] = load <32 x i8>, ptr [[TMP4]], align 1 ; CHECK-NEXT: [[TMP5:%.*]] = sext <32 x i8> [[WIDE_LOAD]] to <32 x i32> ; CHECK-NEXT: [[TMP6:%.*]] = getelementptr inbounds i8, ptr [[I1]], i64 [[INDEX]] ; CHECK-NEXT: [[WIDE_LOAD14:%.*]] = load <32 x i8>, ptr [[TMP6]], align 1 ; CHECK-NEXT: [[TMP7:%.*]] = sext <32 x i8> [[WIDE_LOAD14]] to <32 x i32> ; CHECK-NEXT: [[TMP8:%.*]] = mul nsw <32 x i32> [[TMP7]], [[TMP5]] ; CHECK-NEXT: [[TMP9]] = add nsw <32 x i32> [[TMP8]], [[VEC_PHI]] ; CHECK-NEXT: [[INDEX_NEXT]] = add i64 [[INDEX]], 32 ; CHECK-NEXT: [[TMP10:%.*]] = icmp eq i64 [[INDEX_NEXT]], [[TMP3]] ; CHECK-NEXT: br i1 [[TMP10]], label %[[MIDDLE_BLOCK:.*]], label %[[VECTOR_BODY]] ; CHECK: [[MIDDLE_BLOCK]]: ; CHECK-NEXT: [[TMP11:%.*]] = tail call i32 @llvm.vector.reduce.add.v32i32(<32 x i32> [[TMP9]]) ; CHECK-NEXT: ret i32 [[TMP11]] ; entry: %i3 = zext i32 %i2 to i64 br label %vector.body vector.body: %index = phi i64 [ %index.next, %vector.body ], [ 0, %entry ] %vec.phi = phi <32 x i32> [ %i11, %vector.body ], [ zeroinitializer, %entry ] %i4 = getelementptr inbounds i8, ptr %i0, i64 %index %i5 = bitcast ptr %i4 to ptr %wide.load = load <32 x i8>, ptr %i5, align 1 %i6 = sext <32 x i8> %wide.load to <32 x i32> %i7 = getelementptr inbounds i8, ptr %i1, i64 %index %i8 = bitcast ptr %i7 to ptr %wide.load14 = load <32 x i8>, ptr %i8, align 1 %i9 = sext <32 x i8> %wide.load14 to <32 x i32> %i10 = mul nsw <32 x i32> %i9, %i6 %i11 = add nsw <32 x i32> %i10, %vec.phi %index.next = add i64 %index, 32 %i12 = icmp eq i64 %index.next, %i3 br i1 %i12, label %middle.block, label %vector.body middle.block: %rdx.shuf1 = shufflevector <32 x i32> %i11, <32 x i32> undef, <32 x i32> %bin.rdx1 = add <32 x i32> %i11, %rdx.shuf1 %rdx.shuf = shufflevector <32 x i32> %bin.rdx1, <32 x i32> undef, <32 x i32> %bin.rdx = add <32 x i32> %bin.rdx1, %rdx.shuf %rdx.shuf15 = shufflevector <32 x i32> %bin.rdx, <32 x i32> undef, <32 x i32> %bin.rdx32 = add <32 x i32> %bin.rdx, %rdx.shuf15 %rdx.shuf17 = shufflevector <32 x i32> %bin.rdx32, <32 x i32> undef, <32 x i32> %bin.rdx18 = add <32 x i32> %bin.rdx32, %rdx.shuf17 %rdx.shuf19 = shufflevector <32 x i32> %bin.rdx18, <32 x i32> undef, <32 x i32> %bin.rdx20 = add <32 x i32> %bin.rdx18, %rdx.shuf19 %i13 = extractelement <32 x i32> %bin.rdx20, i32 0 ret i32 %i13 } define i32 @test_unsigned_short_128(ptr nocapture readonly %i0, ptr nocapture readonly %i1, i32 %i2) local_unnamed_addr #0 { ; CHECK-LABEL: define i32 @test_unsigned_short_128( ; CHECK-SAME: ptr readonly captures(none) [[I0:%.*]], ptr readonly captures(none) [[I1:%.*]], i32 [[I2:%.*]]) local_unnamed_addr #[[ATTR0]] { ; CHECK-NEXT: [[ENTRY:.*]]: ; CHECK-NEXT: [[TMP3:%.*]] = zext i32 [[I2]] to i64 ; CHECK-NEXT: br label %[[VECTOR_BODY:.*]] ; CHECK: [[VECTOR_BODY]]: ; CHECK-NEXT: [[INDEX:%.*]] = phi i64 [ [[INDEX_NEXT:%.*]], %[[VECTOR_BODY]] ], [ 0, %[[ENTRY]] ] ; CHECK-NEXT: [[VEC_PHI:%.*]] = phi <4 x i32> [ [[TMP9:%.*]], %[[VECTOR_BODY]] ], [ zeroinitializer, %[[ENTRY]] ] ; CHECK-NEXT: [[TMP4:%.*]] = getelementptr inbounds [2 x i8], ptr [[I0]], i64 [[INDEX]] ; CHECK-NEXT: [[WIDE_LOAD:%.*]] = load <4 x i16>, ptr [[TMP4]], align 2 ; CHECK-NEXT: [[TMP5:%.*]] = zext <4 x i16> [[WIDE_LOAD]] to <4 x i32> ; CHECK-NEXT: [[TMP6:%.*]] = getelementptr inbounds [2 x i8], ptr [[I1]], i64 [[INDEX]] ; CHECK-NEXT: [[WIDE_LOAD14:%.*]] = load <4 x i16>, ptr [[TMP6]], align 2 ; CHECK-NEXT: [[TMP7:%.*]] = zext <4 x i16> [[WIDE_LOAD14]] to <4 x i32> ; CHECK-NEXT: [[TMP8:%.*]] = mul nuw nsw <4 x i32> [[TMP7]], [[TMP5]] ; CHECK-NEXT: [[TMP9]] = add nuw nsw <4 x i32> [[TMP8]], [[VEC_PHI]] ; CHECK-NEXT: [[INDEX_NEXT]] = add i64 [[INDEX]], 16 ; CHECK-NEXT: [[TMP10:%.*]] = icmp eq i64 [[INDEX_NEXT]], [[TMP3]] ; CHECK-NEXT: br i1 [[TMP10]], label %[[MIDDLE_BLOCK:.*]], label %[[VECTOR_BODY]] ; CHECK: [[MIDDLE_BLOCK]]: ; CHECK-NEXT: [[TMP11:%.*]] = tail call i32 @llvm.vector.reduce.add.v4i32(<4 x i32> [[TMP9]]) ; CHECK-NEXT: ret i32 [[TMP11]] ; entry: %i3 = zext i32 %i2 to i64 br label %vector.body vector.body: %index = phi i64 [ %index.next, %vector.body ], [ 0, %entry ] %vec.phi = phi <4 x i32> [ %i11, %vector.body ], [ zeroinitializer, %entry ] %i4 = getelementptr inbounds i16, ptr %i0, i64 %index %i5 = bitcast ptr %i4 to ptr %wide.load = load <4 x i16>, ptr %i5, align 2 %i6 = zext <4 x i16> %wide.load to <4 x i32> %i7 = getelementptr inbounds i16, ptr %i1, i64 %index %i8 = bitcast ptr %i7 to ptr %wide.load14 = load <4 x i16>, ptr %i8, align 2 %i9 = zext <4 x i16> %wide.load14 to <4 x i32> %i10 = mul nsw <4 x i32> %i9, %i6 %i11 = add nsw <4 x i32> %i10, %vec.phi %index.next = add i64 %index, 16 %i12 = icmp eq i64 %index.next, %i3 br i1 %i12, label %middle.block, label %vector.body middle.block: %rdx.shuf15 = shufflevector <4 x i32> %i11, <4 x i32> undef, <4 x i32> %bin.rdx16 = add <4 x i32> %i11, %rdx.shuf15 %rdx.shuf17 = shufflevector <4 x i32> %bin.rdx16, <4 x i32> undef, <4 x i32> %bin.rdx18 = add <4 x i32> %bin.rdx16, %rdx.shuf17 %i13 = extractelement <4 x i32> %bin.rdx18, i32 0 ret i32 %i13 } define i32 @test_unsigned_short_256(ptr nocapture readonly %i0, ptr nocapture readonly %i1, i32 %i2) local_unnamed_addr #0 { ; CHECK-LABEL: define i32 @test_unsigned_short_256( ; CHECK-SAME: ptr readonly captures(none) [[I0:%.*]], ptr readonly captures(none) [[I1:%.*]], i32 [[I2:%.*]]) local_unnamed_addr #[[ATTR0]] { ; CHECK-NEXT: [[ENTRY:.*]]: ; CHECK-NEXT: [[TMP3:%.*]] = zext i32 [[I2]] to i64 ; CHECK-NEXT: br label %[[VECTOR_BODY:.*]] ; CHECK: [[VECTOR_BODY]]: ; CHECK-NEXT: [[INDEX:%.*]] = phi i64 [ [[INDEX_NEXT:%.*]], %[[VECTOR_BODY]] ], [ 0, %[[ENTRY]] ] ; CHECK-NEXT: [[VEC_PHI:%.*]] = phi <8 x i32> [ [[TMP9:%.*]], %[[VECTOR_BODY]] ], [ zeroinitializer, %[[ENTRY]] ] ; CHECK-NEXT: [[TMP4:%.*]] = getelementptr inbounds [2 x i8], ptr [[I0]], i64 [[INDEX]] ; CHECK-NEXT: [[WIDE_LOAD:%.*]] = load <8 x i16>, ptr [[TMP4]], align 2 ; CHECK-NEXT: [[TMP5:%.*]] = zext <8 x i16> [[WIDE_LOAD]] to <8 x i32> ; CHECK-NEXT: [[TMP6:%.*]] = getelementptr inbounds [2 x i8], ptr [[I1]], i64 [[INDEX]] ; CHECK-NEXT: [[WIDE_LOAD14:%.*]] = load <8 x i16>, ptr [[TMP6]], align 2 ; CHECK-NEXT: [[TMP7:%.*]] = zext <8 x i16> [[WIDE_LOAD14]] to <8 x i32> ; CHECK-NEXT: [[TMP8:%.*]] = mul nuw nsw <8 x i32> [[TMP7]], [[TMP5]] ; CHECK-NEXT: [[TMP9]] = add nuw nsw <8 x i32> [[TMP8]], [[VEC_PHI]] ; CHECK-NEXT: [[INDEX_NEXT]] = add i64 [[INDEX]], 16 ; CHECK-NEXT: [[TMP10:%.*]] = icmp eq i64 [[INDEX_NEXT]], [[TMP3]] ; CHECK-NEXT: br i1 [[TMP10]], label %[[MIDDLE_BLOCK:.*]], label %[[VECTOR_BODY]] ; CHECK: [[MIDDLE_BLOCK]]: ; CHECK-NEXT: [[TMP11:%.*]] = tail call i32 @llvm.vector.reduce.add.v8i32(<8 x i32> [[TMP9]]) ; CHECK-NEXT: ret i32 [[TMP11]] ; entry: %i3 = zext i32 %i2 to i64 br label %vector.body vector.body: %index = phi i64 [ %index.next, %vector.body ], [ 0, %entry ] %vec.phi = phi <8 x i32> [ %i11, %vector.body ], [ zeroinitializer, %entry ] %i4 = getelementptr inbounds i16, ptr %i0, i64 %index %i5 = bitcast ptr %i4 to ptr %wide.load = load <8 x i16>, ptr %i5, align 2 %i6 = zext <8 x i16> %wide.load to <8 x i32> %i7 = getelementptr inbounds i16, ptr %i1, i64 %index %i8 = bitcast ptr %i7 to ptr %wide.load14 = load <8 x i16>, ptr %i8, align 2 %i9 = zext <8 x i16> %wide.load14 to <8 x i32> %i10 = mul nsw <8 x i32> %i9, %i6 %i11 = add nsw <8 x i32> %i10, %vec.phi %index.next = add i64 %index, 16 %i12 = icmp eq i64 %index.next, %i3 br i1 %i12, label %middle.block, label %vector.body middle.block: %rdx.shuf = shufflevector <8 x i32> %i11, <8 x i32> undef, <8 x i32> %bin.rdx = add <8 x i32> %i11, %rdx.shuf %rdx.shuf15 = shufflevector <8 x i32> %bin.rdx, <8 x i32> undef, <8 x i32> %bin.rdx16 = add <8 x i32> %bin.rdx, %rdx.shuf15 %rdx.shuf17 = shufflevector <8 x i32> %bin.rdx16, <8 x i32> undef, <8 x i32> %bin.rdx18 = add <8 x i32> %bin.rdx16, %rdx.shuf17 %i13 = extractelement <8 x i32> %bin.rdx18, i32 0 ret i32 %i13 } define i32 @test_unsigned_short_512(ptr nocapture readonly %i0, ptr nocapture readonly %i1, i32 %i2) local_unnamed_addr #0 { ; CHECK-LABEL: define i32 @test_unsigned_short_512( ; CHECK-SAME: ptr readonly captures(none) [[I0:%.*]], ptr readonly captures(none) [[I1:%.*]], i32 [[I2:%.*]]) local_unnamed_addr #[[ATTR0]] { ; CHECK-NEXT: [[ENTRY:.*]]: ; CHECK-NEXT: [[TMP3:%.*]] = zext i32 [[I2]] to i64 ; CHECK-NEXT: br label %[[VECTOR_BODY:.*]] ; CHECK: [[VECTOR_BODY]]: ; CHECK-NEXT: [[INDEX:%.*]] = phi i64 [ [[INDEX_NEXT:%.*]], %[[VECTOR_BODY]] ], [ 0, %[[ENTRY]] ] ; CHECK-NEXT: [[VEC_PHI:%.*]] = phi <16 x i32> [ [[TMP9:%.*]], %[[VECTOR_BODY]] ], [ zeroinitializer, %[[ENTRY]] ] ; CHECK-NEXT: [[TMP4:%.*]] = getelementptr inbounds [2 x i8], ptr [[I0]], i64 [[INDEX]] ; CHECK-NEXT: [[WIDE_LOAD:%.*]] = load <16 x i16>, ptr [[TMP4]], align 2 ; CHECK-NEXT: [[TMP5:%.*]] = zext <16 x i16> [[WIDE_LOAD]] to <16 x i32> ; CHECK-NEXT: [[TMP6:%.*]] = getelementptr inbounds [2 x i8], ptr [[I1]], i64 [[INDEX]] ; CHECK-NEXT: [[WIDE_LOAD14:%.*]] = load <16 x i16>, ptr [[TMP6]], align 2 ; CHECK-NEXT: [[TMP7:%.*]] = zext <16 x i16> [[WIDE_LOAD14]] to <16 x i32> ; CHECK-NEXT: [[TMP8:%.*]] = mul nuw nsw <16 x i32> [[TMP7]], [[TMP5]] ; CHECK-NEXT: [[TMP9]] = add nuw nsw <16 x i32> [[TMP8]], [[VEC_PHI]] ; CHECK-NEXT: [[INDEX_NEXT]] = add i64 [[INDEX]], 16 ; CHECK-NEXT: [[TMP10:%.*]] = icmp eq i64 [[INDEX_NEXT]], [[TMP3]] ; CHECK-NEXT: br i1 [[TMP10]], label %[[MIDDLE_BLOCK:.*]], label %[[VECTOR_BODY]] ; CHECK: [[MIDDLE_BLOCK]]: ; CHECK-NEXT: [[TMP11:%.*]] = tail call i32 @llvm.vector.reduce.add.v16i32(<16 x i32> [[TMP9]]) ; CHECK-NEXT: ret i32 [[TMP11]] ; entry: %i3 = zext i32 %i2 to i64 br label %vector.body vector.body: %index = phi i64 [ %index.next, %vector.body ], [ 0, %entry ] %vec.phi = phi <16 x i32> [ %i11, %vector.body ], [ zeroinitializer, %entry ] %i4 = getelementptr inbounds i16, ptr %i0, i64 %index %i5 = bitcast ptr %i4 to ptr %wide.load = load <16 x i16>, ptr %i5, align 2 %i6 = zext <16 x i16> %wide.load to <16 x i32> %i7 = getelementptr inbounds i16, ptr %i1, i64 %index %i8 = bitcast ptr %i7 to ptr %wide.load14 = load <16 x i16>, ptr %i8, align 2 %i9 = zext <16 x i16> %wide.load14 to <16 x i32> %i10 = mul nsw <16 x i32> %i9, %i6 %i11 = add nsw <16 x i32> %i10, %vec.phi %index.next = add i64 %index, 16 %i12 = icmp eq i64 %index.next, %i3 br i1 %i12, label %middle.block, label %vector.body middle.block: %rdx.shuf1 = shufflevector <16 x i32> %i11, <16 x i32> undef, <16 x i32> %bin.rdx1 = add <16 x i32> %i11, %rdx.shuf1 %rdx.shuf = shufflevector <16 x i32> %bin.rdx1, <16 x i32> undef, <16 x i32> %bin.rdx = add <16 x i32> %bin.rdx1, %rdx.shuf %rdx.shuf15 = shufflevector <16 x i32> %bin.rdx, <16 x i32> undef, <16 x i32> %bin.rdx16 = add <16 x i32> %bin.rdx, %rdx.shuf15 %rdx.shuf17 = shufflevector <16 x i32> %bin.rdx16, <16 x i32> undef, <16 x i32> %bin.rdx18 = add <16 x i32> %bin.rdx16, %rdx.shuf17 %i13 = extractelement <16 x i32> %bin.rdx18, i32 0 ret i32 %i13 } define i32 @test_unsigned_short_1024(ptr nocapture readonly %i0, ptr nocapture readonly %i1, i32 %i2) local_unnamed_addr #0 { ; CHECK-LABEL: define i32 @test_unsigned_short_1024( ; CHECK-SAME: ptr readonly captures(none) [[I0:%.*]], ptr readonly captures(none) [[I1:%.*]], i32 [[I2:%.*]]) local_unnamed_addr #[[ATTR0]] { ; CHECK-NEXT: [[ENTRY:.*]]: ; CHECK-NEXT: [[TMP3:%.*]] = zext i32 [[I2]] to i64 ; CHECK-NEXT: br label %[[VECTOR_BODY:.*]] ; CHECK: [[VECTOR_BODY]]: ; CHECK-NEXT: [[INDEX:%.*]] = phi i64 [ [[INDEX_NEXT:%.*]], %[[VECTOR_BODY]] ], [ 0, %[[ENTRY]] ] ; CHECK-NEXT: [[VEC_PHI:%.*]] = phi <32 x i32> [ [[TMP9:%.*]], %[[VECTOR_BODY]] ], [ zeroinitializer, %[[ENTRY]] ] ; CHECK-NEXT: [[TMP4:%.*]] = getelementptr inbounds [2 x i8], ptr [[I0]], i64 [[INDEX]] ; CHECK-NEXT: [[WIDE_LOAD:%.*]] = load <32 x i16>, ptr [[TMP4]], align 2 ; CHECK-NEXT: [[TMP5:%.*]] = zext <32 x i16> [[WIDE_LOAD]] to <32 x i32> ; CHECK-NEXT: [[TMP6:%.*]] = getelementptr inbounds [2 x i8], ptr [[I1]], i64 [[INDEX]] ; CHECK-NEXT: [[WIDE_LOAD14:%.*]] = load <32 x i16>, ptr [[TMP6]], align 2 ; CHECK-NEXT: [[TMP7:%.*]] = zext <32 x i16> [[WIDE_LOAD14]] to <32 x i32> ; CHECK-NEXT: [[TMP8:%.*]] = mul nuw nsw <32 x i32> [[TMP7]], [[TMP5]] ; CHECK-NEXT: [[TMP9]] = add nuw nsw <32 x i32> [[TMP8]], [[VEC_PHI]] ; CHECK-NEXT: [[INDEX_NEXT]] = add i64 [[INDEX]], 16 ; CHECK-NEXT: [[TMP10:%.*]] = icmp eq i64 [[INDEX_NEXT]], [[TMP3]] ; CHECK-NEXT: br i1 [[TMP10]], label %[[MIDDLE_BLOCK:.*]], label %[[VECTOR_BODY]] ; CHECK: [[MIDDLE_BLOCK]]: ; CHECK-NEXT: [[TMP11:%.*]] = tail call i32 @llvm.vector.reduce.add.v32i32(<32 x i32> [[TMP9]]) ; CHECK-NEXT: ret i32 [[TMP11]] ; entry: %i3 = zext i32 %i2 to i64 br label %vector.body vector.body: %index = phi i64 [ %index.next, %vector.body ], [ 0, %entry ] %vec.phi = phi <32 x i32> [ %i11, %vector.body ], [ zeroinitializer, %entry ] %i4 = getelementptr inbounds i16, ptr %i0, i64 %index %i5 = bitcast ptr %i4 to ptr %wide.load = load <32 x i16>, ptr %i5, align 2 %i6 = zext <32 x i16> %wide.load to <32 x i32> %i7 = getelementptr inbounds i16, ptr %i1, i64 %index %i8 = bitcast ptr %i7 to ptr %wide.load14 = load <32 x i16>, ptr %i8, align 2 %i9 = zext <32 x i16> %wide.load14 to <32 x i32> %i10 = mul nsw <32 x i32> %i9, %i6 %i11 = add nsw <32 x i32> %i10, %vec.phi %index.next = add i64 %index, 16 %i12 = icmp eq i64 %index.next, %i3 br i1 %i12, label %middle.block, label %vector.body middle.block: %rdx.shuf2 = shufflevector <32 x i32> %i11, <32 x i32> undef, <32 x i32> %bin.rdx2 = add <32 x i32> %i11, %rdx.shuf2 %rdx.shuf1 = shufflevector <32 x i32> %bin.rdx2, <32 x i32> undef, <32 x i32> %bin.rdx1 = add <32 x i32> %bin.rdx2, %rdx.shuf1 %rdx.shuf = shufflevector <32 x i32> %bin.rdx1, <32 x i32> undef, <32 x i32> %bin.rdx = add <32 x i32> %bin.rdx1, %rdx.shuf %rdx.shuf15 = shufflevector <32 x i32> %bin.rdx, <32 x i32> undef, <32 x i32> %bin.rdx16 = add <32 x i32> %bin.rdx, %rdx.shuf15 %rdx.shuf17 = shufflevector <32 x i32> %bin.rdx16, <32 x i32> undef, <32 x i32> %bin.rdx18 = add <32 x i32> %bin.rdx16, %rdx.shuf17 %i13 = extractelement <32 x i32> %bin.rdx18, i32 0 ret i32 %i13 } define <4 x i32> @pmaddwd_8(<8 x i16> %a0, <8 x i16> %a1) { ; CHECK-LABEL: define <4 x i32> @pmaddwd_8( ; CHECK-SAME: <8 x i16> [[A0:%.*]], <8 x i16> [[A1:%.*]]) local_unnamed_addr #[[ATTR1:[0-9]+]] { ; CHECK-NEXT: [[A:%.*]] = sext <8 x i16> [[A0]] to <8 x i32> ; CHECK-NEXT: [[B:%.*]] = sext <8 x i16> [[A1]] to <8 x i32> ; CHECK-NEXT: [[M:%.*]] = mul nsw <8 x i32> [[B]], [[A]] ; CHECK-NEXT: [[ODD:%.*]] = shufflevector <8 x i32> [[M]], <8 x i32> poison, <4 x i32> ; CHECK-NEXT: [[EVEN:%.*]] = shufflevector <8 x i32> [[M]], <8 x i32> poison, <4 x i32> ; CHECK-NEXT: [[RET:%.*]] = add <4 x i32> [[ODD]], [[EVEN]] ; CHECK-NEXT: ret <4 x i32> [[RET]] ; %a = sext <8 x i16> %a0 to <8 x i32> %b = sext <8 x i16> %a1 to <8 x i32> %m = mul nsw <8 x i32> %a, %b %odd = shufflevector <8 x i32> %m, <8 x i32> undef, <4 x i32> %even = shufflevector <8 x i32> %m, <8 x i32> undef, <4 x i32> %ret = add <4 x i32> %odd, %even ret <4 x i32> %ret } define <4 x i32> @pmaddwd_8_swapped(<8 x i16> %a0, <8 x i16> %b0) { ; CHECK-LABEL: define <4 x i32> @pmaddwd_8_swapped( ; CHECK-SAME: <8 x i16> [[A0:%.*]], <8 x i16> [[B0:%.*]]) local_unnamed_addr #[[ATTR1]] { ; CHECK-NEXT: [[A:%.*]] = sext <8 x i16> [[A0]] to <8 x i32> ; CHECK-NEXT: [[B:%.*]] = sext <8 x i16> [[B0]] to <8 x i32> ; CHECK-NEXT: [[M:%.*]] = mul nsw <8 x i32> [[B]], [[A]] ; CHECK-NEXT: [[ODD:%.*]] = shufflevector <8 x i32> [[M]], <8 x i32> poison, <4 x i32> ; CHECK-NEXT: [[EVEN:%.*]] = shufflevector <8 x i32> [[M]], <8 x i32> poison, <4 x i32> ; CHECK-NEXT: [[RET:%.*]] = add <4 x i32> [[EVEN]], [[ODD]] ; CHECK-NEXT: ret <4 x i32> [[RET]] ; %a = sext <8 x i16> %a0 to <8 x i32> %b = sext <8 x i16> %b0 to <8 x i32> %m = mul nsw <8 x i32> %a, %b %odd = shufflevector <8 x i32> %m, <8 x i32> undef, <4 x i32> %even = shufflevector <8 x i32> %m, <8 x i32> undef, <4 x i32> %ret = add <4 x i32> %even, %odd ret <4 x i32> %ret } ; FIXME: SSE fails to match PMADDWD define <4 x i32> @larger_mul(<16 x i16> %a0, <16 x i16> %b0) { ; CHECK-LABEL: define <4 x i32> @larger_mul( ; CHECK-SAME: <16 x i16> [[A0:%.*]], <16 x i16> [[B0:%.*]]) local_unnamed_addr #[[ATTR1]] { ; CHECK-NEXT: [[A:%.*]] = sext <16 x i16> [[A0]] to <16 x i32> ; CHECK-NEXT: [[B:%.*]] = sext <16 x i16> [[B0]] to <16 x i32> ; CHECK-NEXT: [[M:%.*]] = mul nsw <16 x i32> [[B]], [[A]] ; CHECK-NEXT: [[ODD:%.*]] = shufflevector <16 x i32> [[M]], <16 x i32> poison, <4 x i32> ; CHECK-NEXT: [[EVEN:%.*]] = shufflevector <16 x i32> [[M]], <16 x i32> poison, <4 x i32> ; CHECK-NEXT: [[RET:%.*]] = add <4 x i32> [[ODD]], [[EVEN]] ; CHECK-NEXT: ret <4 x i32> [[RET]] ; %a = sext <16 x i16> %a0 to <16 x i32> %b = sext <16 x i16> %b0 to <16 x i32> %m = mul nsw <16 x i32> %a, %b %odd = shufflevector <16 x i32> %m, <16 x i32> undef, <4 x i32> %even = shufflevector <16 x i32> %m, <16 x i32> undef, <4 x i32> %ret = add <4 x i32> %odd, %even ret <4 x i32> %ret } define <8 x i32> @pmaddwd_16(<16 x i16> %a0, <16 x i16> %b0) { ; CHECK-LABEL: define <8 x i32> @pmaddwd_16( ; CHECK-SAME: <16 x i16> [[A0:%.*]], <16 x i16> [[B0:%.*]]) local_unnamed_addr #[[ATTR1]] { ; CHECK-NEXT: [[A:%.*]] = sext <16 x i16> [[A0]] to <16 x i32> ; CHECK-NEXT: [[B:%.*]] = sext <16 x i16> [[B0]] to <16 x i32> ; CHECK-NEXT: [[M:%.*]] = mul nsw <16 x i32> [[B]], [[A]] ; CHECK-NEXT: [[ODD:%.*]] = shufflevector <16 x i32> [[M]], <16 x i32> poison, <8 x i32> ; CHECK-NEXT: [[EVEN:%.*]] = shufflevector <16 x i32> [[M]], <16 x i32> poison, <8 x i32> ; CHECK-NEXT: [[RET:%.*]] = add <8 x i32> [[ODD]], [[EVEN]] ; CHECK-NEXT: ret <8 x i32> [[RET]] ; %a = sext <16 x i16> %a0 to <16 x i32> %b = sext <16 x i16> %b0 to <16 x i32> %m = mul nsw <16 x i32> %a, %b %odd = shufflevector <16 x i32> %m, <16 x i32> undef, <8 x i32> %even = shufflevector <16 x i32> %m, <16 x i32> undef, <8 x i32> %ret = add <8 x i32> %odd, %even ret <8 x i32> %ret } define <16 x i32> @pmaddwd_32(<32 x i16> %a0, <32 x i16> %b0) { ; CHECK-LABEL: define <16 x i32> @pmaddwd_32( ; CHECK-SAME: <32 x i16> [[A0:%.*]], <32 x i16> [[B0:%.*]]) local_unnamed_addr #[[ATTR1]] { ; CHECK-NEXT: [[A:%.*]] = sext <32 x i16> [[A0]] to <32 x i32> ; CHECK-NEXT: [[B:%.*]] = sext <32 x i16> [[B0]] to <32 x i32> ; CHECK-NEXT: [[M:%.*]] = mul nsw <32 x i32> [[B]], [[A]] ; CHECK-NEXT: [[ODD:%.*]] = shufflevector <32 x i32> [[M]], <32 x i32> poison, <16 x i32> ; CHECK-NEXT: [[EVEN:%.*]] = shufflevector <32 x i32> [[M]], <32 x i32> poison, <16 x i32> ; CHECK-NEXT: [[RET:%.*]] = add <16 x i32> [[ODD]], [[EVEN]] ; CHECK-NEXT: ret <16 x i32> [[RET]] ; %a = sext <32 x i16> %a0 to <32 x i32> %b = sext <32 x i16> %b0 to <32 x i32> %m = mul nsw <32 x i32> %a, %b %odd = shufflevector <32 x i32> %m, <32 x i32> undef, <16 x i32> %even = shufflevector <32 x i32> %m, <32 x i32> undef, <16 x i32> %ret = add <16 x i32> %odd, %even ret <16 x i32> %ret } define <4 x i32> @pmaddwd_const(<8 x i16> %a0) { ; CHECK-LABEL: define <4 x i32> @pmaddwd_const( ; CHECK-SAME: <8 x i16> [[A0:%.*]]) local_unnamed_addr #[[ATTR1]] { ; CHECK-NEXT: [[A:%.*]] = sext <8 x i16> [[A0]] to <8 x i32> ; CHECK-NEXT: [[M:%.*]] = mul nsw <8 x i32> [[A]], ; CHECK-NEXT: [[ODD:%.*]] = shufflevector <8 x i32> [[M]], <8 x i32> poison, <4 x i32> ; CHECK-NEXT: [[EVEN:%.*]] = shufflevector <8 x i32> [[M]], <8 x i32> poison, <4 x i32> ; CHECK-NEXT: [[RET:%.*]] = add <4 x i32> [[ODD]], [[EVEN]] ; CHECK-NEXT: ret <4 x i32> [[RET]] ; %a = sext <8 x i16> %a0 to <8 x i32> %m = mul nsw <8 x i32> %a, %odd = shufflevector <8 x i32> %m, <8 x i32> undef, <4 x i32> %even = shufflevector <8 x i32> %m, <8 x i32> undef, <4 x i32> %ret = add <4 x i32> %odd, %even ret <4 x i32> %ret } ; Do not select unsigned i16 multiplication define <4 x i32> @pmaddwd_negative1(<8 x i16> %a0, <8 x i16> %b0) { ; CHECK-LABEL: define <4 x i32> @pmaddwd_negative1( ; CHECK-SAME: <8 x i16> [[A0:%.*]], <8 x i16> [[B0:%.*]]) local_unnamed_addr #[[ATTR1]] { ; CHECK-NEXT: [[A:%.*]] = zext <8 x i16> [[A0]] to <8 x i32> ; CHECK-NEXT: [[B:%.*]] = zext <8 x i16> [[B0]] to <8 x i32> ; CHECK-NEXT: [[M:%.*]] = mul nuw <8 x i32> [[B]], [[A]] ; CHECK-NEXT: [[ODD:%.*]] = shufflevector <8 x i32> [[M]], <8 x i32> poison, <4 x i32> ; CHECK-NEXT: [[EVEN:%.*]] = shufflevector <8 x i32> [[M]], <8 x i32> poison, <4 x i32> ; CHECK-NEXT: [[RET:%.*]] = add <4 x i32> [[ODD]], [[EVEN]] ; CHECK-NEXT: ret <4 x i32> [[RET]] ; %a = zext <8 x i16> %a0 to <8 x i32> %b = zext <8 x i16> %b0 to <8 x i32> %m = mul nuw <8 x i32> %a, %b %odd = shufflevector <8 x i32> %m, <8 x i32> undef, <4 x i32> %even = shufflevector <8 x i32> %m, <8 x i32> undef, <4 x i32> %ret = add <4 x i32> %odd, %even ret <4 x i32> %ret } ; Do not select if constant is too large ; Lower half is too large, upper half is in range. define <4 x i32> @pmaddwd_negative2(<8 x i16> %a0) { ; CHECK-LABEL: define <4 x i32> @pmaddwd_negative2( ; CHECK-SAME: <8 x i16> [[A0:%.*]]) local_unnamed_addr #[[ATTR1]] { ; CHECK-NEXT: [[A:%.*]] = sext <8 x i16> [[A0]] to <8 x i32> ; CHECK-NEXT: [[M:%.*]] = mul nsw <8 x i32> [[A]], ; CHECK-NEXT: [[ODD:%.*]] = shufflevector <8 x i32> [[M]], <8 x i32> poison, <4 x i32> ; CHECK-NEXT: [[EVEN:%.*]] = shufflevector <8 x i32> [[M]], <8 x i32> poison, <4 x i32> ; CHECK-NEXT: [[RET:%.*]] = add <4 x i32> [[ODD]], [[EVEN]] ; CHECK-NEXT: ret <4 x i32> [[RET]] ; %a = sext <8 x i16> %a0 to <8 x i32> %m = mul nsw <8 x i32> %a, %odd = shufflevector <8 x i32> %m, <8 x i32> undef, <4 x i32> %even = shufflevector <8 x i32> %m, <8 x i32> undef, <4 x i32> %ret = add <4 x i32> %odd, %even ret <4 x i32> %ret } define <4 x i32> @jumbled_indices4(<8 x i16> %a0, <8 x i16> %b0) { ; CHECK-LABEL: define <4 x i32> @jumbled_indices4( ; CHECK-SAME: <8 x i16> [[A0:%.*]], <8 x i16> [[B0:%.*]]) local_unnamed_addr #[[ATTR1]] { ; CHECK-NEXT: [[EXTA:%.*]] = sext <8 x i16> [[A0]] to <8 x i32> ; CHECK-NEXT: [[EXTB:%.*]] = sext <8 x i16> [[B0]] to <8 x i32> ; CHECK-NEXT: [[M:%.*]] = mul nsw <8 x i32> [[EXTB]], [[EXTA]] ; CHECK-NEXT: [[SA:%.*]] = shufflevector <8 x i32> [[M]], <8 x i32> poison, <4 x i32> ; CHECK-NEXT: [[SB:%.*]] = shufflevector <8 x i32> [[M]], <8 x i32> poison, <4 x i32> ; CHECK-NEXT: [[A:%.*]] = add <4 x i32> [[SA]], [[SB]] ; CHECK-NEXT: ret <4 x i32> [[A]] ; %exta = sext <8 x i16> %a0 to <8 x i32> %extb = sext <8 x i16> %b0 to <8 x i32> %m = mul <8 x i32> %exta, %extb %sa = shufflevector <8 x i32> %m, <8 x i32> undef, <4 x i32> %sb = shufflevector <8 x i32> %m, <8 x i32> undef, <4 x i32> %a = add <4 x i32> %sa, %sb ret <4 x i32> %a } define <8 x i32> @jumbled_indices8(<16 x i16> %a0, <16 x i16> %b0) { ; CHECK-LABEL: define <8 x i32> @jumbled_indices8( ; CHECK-SAME: <16 x i16> [[A0:%.*]], <16 x i16> [[B0:%.*]]) local_unnamed_addr #[[ATTR1]] { ; CHECK-NEXT: [[EXTA:%.*]] = sext <16 x i16> [[A0]] to <16 x i32> ; CHECK-NEXT: [[EXTB:%.*]] = sext <16 x i16> [[B0]] to <16 x i32> ; CHECK-NEXT: [[M:%.*]] = mul nsw <16 x i32> [[EXTB]], [[EXTA]] ; CHECK-NEXT: [[SA:%.*]] = shufflevector <16 x i32> [[M]], <16 x i32> poison, <8 x i32> ; CHECK-NEXT: [[SB:%.*]] = shufflevector <16 x i32> [[M]], <16 x i32> poison, <8 x i32> ; CHECK-NEXT: [[A:%.*]] = add <8 x i32> [[SA]], [[SB]] ; CHECK-NEXT: ret <8 x i32> [[A]] ; %exta = sext <16 x i16> %a0 to <16 x i32> %extb = sext <16 x i16> %b0 to <16 x i32> %m = mul <16 x i32> %exta, %extb %sa = shufflevector <16 x i32> %m, <16 x i32> undef, <8 x i32> %sb = shufflevector <16 x i32> %m, <16 x i32> undef, <8 x i32> %a = add <8 x i32> %sa, %sb ret <8 x i32> %a } define <16 x i32> @jumbled_indices16(<32 x i16> %a0, <32 x i16> %b0) { ; CHECK-LABEL: define <16 x i32> @jumbled_indices16( ; CHECK-SAME: <32 x i16> [[A0:%.*]], <32 x i16> [[B0:%.*]]) local_unnamed_addr #[[ATTR1]] { ; CHECK-NEXT: [[EXTA:%.*]] = sext <32 x i16> [[A0]] to <32 x i32> ; CHECK-NEXT: [[EXTB:%.*]] = sext <32 x i16> [[B0]] to <32 x i32> ; CHECK-NEXT: [[M:%.*]] = mul nsw <32 x i32> [[EXTB]], [[EXTA]] ; CHECK-NEXT: [[SA:%.*]] = shufflevector <32 x i32> [[M]], <32 x i32> poison, <16 x i32> ; CHECK-NEXT: [[SB:%.*]] = shufflevector <32 x i32> [[M]], <32 x i32> poison, <16 x i32> ; CHECK-NEXT: [[A:%.*]] = add <16 x i32> [[SA]], [[SB]] ; CHECK-NEXT: ret <16 x i32> [[A]] ; %exta = sext <32 x i16> %a0 to <32 x i32> %extb = sext <32 x i16> %b0 to <32 x i32> %m = mul <32 x i32> %exta, %extb %sa = shufflevector <32 x i32> %m, <32 x i32> undef, <16 x i32> %sb = shufflevector <32 x i32> %m, <32 x i32> undef, <16 x i32> %a = add <16 x i32> %sa, %sb ret <16 x i32> %a } define <32 x i32> @jumbled_indices32(<64 x i16> %a0, <64 x i16> %b0) { ; CHECK-LABEL: define <32 x i32> @jumbled_indices32( ; CHECK-SAME: <64 x i16> [[A0:%.*]], <64 x i16> [[B0:%.*]]) local_unnamed_addr #[[ATTR1]] { ; CHECK-NEXT: [[EXTA:%.*]] = sext <64 x i16> [[A0]] to <64 x i32> ; CHECK-NEXT: [[EXTB:%.*]] = sext <64 x i16> [[B0]] to <64 x i32> ; CHECK-NEXT: [[M:%.*]] = mul nsw <64 x i32> [[EXTB]], [[EXTA]] ; CHECK-NEXT: [[SA:%.*]] = shufflevector <64 x i32> [[M]], <64 x i32> poison, <32 x i32> ; CHECK-NEXT: [[SB:%.*]] = shufflevector <64 x i32> [[M]], <64 x i32> poison, <32 x i32> ; CHECK-NEXT: [[A:%.*]] = add <32 x i32> [[SA]], [[SB]] ; CHECK-NEXT: ret <32 x i32> [[A]] ; %exta = sext <64 x i16> %a0 to <64 x i32> %extb = sext <64 x i16> %b0 to <64 x i32> %m = mul <64 x i32> %exta, %extb %sa = shufflevector <64 x i32> %m, <64 x i32> undef, <32 x i32> %sb = shufflevector <64 x i32> %m, <64 x i32> undef, <32 x i32> %a = add <32 x i32> %sa, %sb ret <32 x i32> %a } ; NOTE: We're testing with loads because ABI lowering creates a concat_vectors that extract_vector_elt creation can see through. ; This would require the combine to recreate the concat_vectors. define <4 x i32> @pmaddwd_128(ptr %Aptr, ptr %Bptr) { ; CHECK-LABEL: define range(i32 -2147418112, -2147483647) <4 x i32> @pmaddwd_128( ; CHECK-SAME: ptr readonly captures(none) [[APTR:%.*]], ptr readonly captures(none) [[BPTR:%.*]]) local_unnamed_addr #[[ATTR2:[0-9]+]] { ; CHECK-NEXT: [[A:%.*]] = load <8 x i16>, ptr [[APTR]], align 16 ; CHECK-NEXT: [[B:%.*]] = load <8 x i16>, ptr [[BPTR]], align 16 ; CHECK-NEXT: [[A_EVEN:%.*]] = shufflevector <8 x i16> [[A]], <8 x i16> poison, <4 x i32> ; CHECK-NEXT: [[A_ODD:%.*]] = shufflevector <8 x i16> [[A]], <8 x i16> poison, <4 x i32> ; CHECK-NEXT: [[B_EVEN:%.*]] = shufflevector <8 x i16> [[B]], <8 x i16> poison, <4 x i32> ; CHECK-NEXT: [[B_ODD:%.*]] = shufflevector <8 x i16> [[B]], <8 x i16> poison, <4 x i32> ; CHECK-NEXT: [[A_EVEN_EXT:%.*]] = sext <4 x i16> [[A_EVEN]] to <4 x i32> ; CHECK-NEXT: [[B_EVEN_EXT:%.*]] = sext <4 x i16> [[B_EVEN]] to <4 x i32> ; CHECK-NEXT: [[A_ODD_EXT:%.*]] = sext <4 x i16> [[A_ODD]] to <4 x i32> ; CHECK-NEXT: [[B_ODD_EXT:%.*]] = sext <4 x i16> [[B_ODD]] to <4 x i32> ; CHECK-NEXT: [[EVEN_MUL:%.*]] = mul nsw <4 x i32> [[B_EVEN_EXT]], [[A_EVEN_EXT]] ; CHECK-NEXT: [[ODD_MUL:%.*]] = mul nsw <4 x i32> [[B_ODD_EXT]], [[A_ODD_EXT]] ; CHECK-NEXT: [[ADD:%.*]] = add <4 x i32> [[EVEN_MUL]], [[ODD_MUL]] ; CHECK-NEXT: ret <4 x i32> [[ADD]] ; %A = load <8 x i16>, ptr %Aptr %B = load <8 x i16>, ptr %Bptr %A_even = shufflevector <8 x i16> %A, <8 x i16> undef, <4 x i32> %A_odd = shufflevector <8 x i16> %A, <8 x i16> undef, <4 x i32> %B_even = shufflevector <8 x i16> %B, <8 x i16> undef, <4 x i32> %B_odd = shufflevector <8 x i16> %B, <8 x i16> undef, <4 x i32> %A_even_ext = sext <4 x i16> %A_even to <4 x i32> %B_even_ext = sext <4 x i16> %B_even to <4 x i32> %A_odd_ext = sext <4 x i16> %A_odd to <4 x i32> %B_odd_ext = sext <4 x i16> %B_odd to <4 x i32> %even_mul = mul <4 x i32> %A_even_ext, %B_even_ext %odd_mul = mul <4 x i32> %A_odd_ext, %B_odd_ext %add = add <4 x i32> %even_mul, %odd_mul ret <4 x i32> %add } define <8 x i32> @pmaddwd_256(ptr %Aptr, ptr %Bptr) { ; CHECK-LABEL: define range(i32 -2147418112, -2147483647) <8 x i32> @pmaddwd_256( ; CHECK-SAME: ptr readonly captures(none) [[APTR:%.*]], ptr readonly captures(none) [[BPTR:%.*]]) local_unnamed_addr #[[ATTR2]] { ; CHECK-NEXT: [[A:%.*]] = load <16 x i16>, ptr [[APTR]], align 32 ; CHECK-NEXT: [[B:%.*]] = load <16 x i16>, ptr [[BPTR]], align 32 ; CHECK-NEXT: [[A_EVEN:%.*]] = shufflevector <16 x i16> [[A]], <16 x i16> poison, <8 x i32> ; CHECK-NEXT: [[A_ODD:%.*]] = shufflevector <16 x i16> [[A]], <16 x i16> poison, <8 x i32> ; CHECK-NEXT: [[B_EVEN:%.*]] = shufflevector <16 x i16> [[B]], <16 x i16> poison, <8 x i32> ; CHECK-NEXT: [[B_ODD:%.*]] = shufflevector <16 x i16> [[B]], <16 x i16> poison, <8 x i32> ; CHECK-NEXT: [[A_EVEN_EXT:%.*]] = sext <8 x i16> [[A_EVEN]] to <8 x i32> ; CHECK-NEXT: [[B_EVEN_EXT:%.*]] = sext <8 x i16> [[B_EVEN]] to <8 x i32> ; CHECK-NEXT: [[A_ODD_EXT:%.*]] = sext <8 x i16> [[A_ODD]] to <8 x i32> ; CHECK-NEXT: [[B_ODD_EXT:%.*]] = sext <8 x i16> [[B_ODD]] to <8 x i32> ; CHECK-NEXT: [[EVEN_MUL:%.*]] = mul nsw <8 x i32> [[B_EVEN_EXT]], [[A_EVEN_EXT]] ; CHECK-NEXT: [[ODD_MUL:%.*]] = mul nsw <8 x i32> [[B_ODD_EXT]], [[A_ODD_EXT]] ; CHECK-NEXT: [[ADD:%.*]] = add <8 x i32> [[EVEN_MUL]], [[ODD_MUL]] ; CHECK-NEXT: ret <8 x i32> [[ADD]] ; %A = load <16 x i16>, ptr %Aptr %B = load <16 x i16>, ptr %Bptr %A_even = shufflevector <16 x i16> %A, <16 x i16> undef, <8 x i32> %A_odd = shufflevector <16 x i16> %A, <16 x i16> undef, <8 x i32> %B_even = shufflevector <16 x i16> %B, <16 x i16> undef, <8 x i32> %B_odd = shufflevector <16 x i16> %B, <16 x i16> undef, <8 x i32> %A_even_ext = sext <8 x i16> %A_even to <8 x i32> %B_even_ext = sext <8 x i16> %B_even to <8 x i32> %A_odd_ext = sext <8 x i16> %A_odd to <8 x i32> %B_odd_ext = sext <8 x i16> %B_odd to <8 x i32> %even_mul = mul <8 x i32> %A_even_ext, %B_even_ext %odd_mul = mul <8 x i32> %A_odd_ext, %B_odd_ext %add = add <8 x i32> %even_mul, %odd_mul ret <8 x i32> %add } define <16 x i32> @pmaddwd_512(ptr %Aptr, ptr %Bptr) { ; CHECK-LABEL: define range(i32 -2147418112, -2147483647) <16 x i32> @pmaddwd_512( ; CHECK-SAME: ptr readonly captures(none) [[APTR:%.*]], ptr readonly captures(none) [[BPTR:%.*]]) local_unnamed_addr #[[ATTR2]] { ; CHECK-NEXT: [[A:%.*]] = load <32 x i16>, ptr [[APTR]], align 64 ; CHECK-NEXT: [[B:%.*]] = load <32 x i16>, ptr [[BPTR]], align 64 ; CHECK-NEXT: [[A_EVEN:%.*]] = shufflevector <32 x i16> [[A]], <32 x i16> poison, <16 x i32> ; CHECK-NEXT: [[A_ODD:%.*]] = shufflevector <32 x i16> [[A]], <32 x i16> poison, <16 x i32> ; CHECK-NEXT: [[B_EVEN:%.*]] = shufflevector <32 x i16> [[B]], <32 x i16> poison, <16 x i32> ; CHECK-NEXT: [[B_ODD:%.*]] = shufflevector <32 x i16> [[B]], <32 x i16> poison, <16 x i32> ; CHECK-NEXT: [[A_EVEN_EXT:%.*]] = sext <16 x i16> [[A_EVEN]] to <16 x i32> ; CHECK-NEXT: [[B_EVEN_EXT:%.*]] = sext <16 x i16> [[B_EVEN]] to <16 x i32> ; CHECK-NEXT: [[A_ODD_EXT:%.*]] = sext <16 x i16> [[A_ODD]] to <16 x i32> ; CHECK-NEXT: [[B_ODD_EXT:%.*]] = sext <16 x i16> [[B_ODD]] to <16 x i32> ; CHECK-NEXT: [[EVEN_MUL:%.*]] = mul nsw <16 x i32> [[B_EVEN_EXT]], [[A_EVEN_EXT]] ; CHECK-NEXT: [[ODD_MUL:%.*]] = mul nsw <16 x i32> [[B_ODD_EXT]], [[A_ODD_EXT]] ; CHECK-NEXT: [[ADD:%.*]] = add <16 x i32> [[EVEN_MUL]], [[ODD_MUL]] ; CHECK-NEXT: ret <16 x i32> [[ADD]] ; %A = load <32 x i16>, ptr %Aptr %B = load <32 x i16>, ptr %Bptr %A_even = shufflevector <32 x i16> %A, <32 x i16> undef, <16 x i32> %A_odd = shufflevector <32 x i16> %A, <32 x i16> undef, <16 x i32> %B_even = shufflevector <32 x i16> %B, <32 x i16> undef, <16 x i32> %B_odd = shufflevector <32 x i16> %B, <32 x i16> undef, <16 x i32> %A_even_ext = sext <16 x i16> %A_even to <16 x i32> %B_even_ext = sext <16 x i16> %B_even to <16 x i32> %A_odd_ext = sext <16 x i16> %A_odd to <16 x i32> %B_odd_ext = sext <16 x i16> %B_odd to <16 x i32> %even_mul = mul <16 x i32> %A_even_ext, %B_even_ext %odd_mul = mul <16 x i32> %A_odd_ext, %B_odd_ext %add = add <16 x i32> %even_mul, %odd_mul ret <16 x i32> %add } define <32 x i32> @pmaddwd_1024(ptr %Aptr, ptr %Bptr) { ; CHECK-LABEL: define range(i32 -2147418112, -2147483647) <32 x i32> @pmaddwd_1024( ; CHECK-SAME: ptr readonly captures(none) [[APTR:%.*]], ptr readonly captures(none) [[BPTR:%.*]]) local_unnamed_addr #[[ATTR2]] { ; CHECK-NEXT: [[A:%.*]] = load <64 x i16>, ptr [[APTR]], align 128 ; CHECK-NEXT: [[B:%.*]] = load <64 x i16>, ptr [[BPTR]], align 128 ; CHECK-NEXT: [[A_EVEN:%.*]] = shufflevector <64 x i16> [[A]], <64 x i16> poison, <32 x i32> ; CHECK-NEXT: [[A_ODD:%.*]] = shufflevector <64 x i16> [[A]], <64 x i16> poison, <32 x i32> ; CHECK-NEXT: [[B_EVEN:%.*]] = shufflevector <64 x i16> [[B]], <64 x i16> poison, <32 x i32> ; CHECK-NEXT: [[B_ODD:%.*]] = shufflevector <64 x i16> [[B]], <64 x i16> poison, <32 x i32> ; CHECK-NEXT: [[A_EVEN_EXT:%.*]] = sext <32 x i16> [[A_EVEN]] to <32 x i32> ; CHECK-NEXT: [[B_EVEN_EXT:%.*]] = sext <32 x i16> [[B_EVEN]] to <32 x i32> ; CHECK-NEXT: [[A_ODD_EXT:%.*]] = sext <32 x i16> [[A_ODD]] to <32 x i32> ; CHECK-NEXT: [[B_ODD_EXT:%.*]] = sext <32 x i16> [[B_ODD]] to <32 x i32> ; CHECK-NEXT: [[EVEN_MUL:%.*]] = mul nsw <32 x i32> [[B_EVEN_EXT]], [[A_EVEN_EXT]] ; CHECK-NEXT: [[ODD_MUL:%.*]] = mul nsw <32 x i32> [[B_ODD_EXT]], [[A_ODD_EXT]] ; CHECK-NEXT: [[ADD:%.*]] = add <32 x i32> [[EVEN_MUL]], [[ODD_MUL]] ; CHECK-NEXT: ret <32 x i32> [[ADD]] ; %A = load <64 x i16>, ptr %Aptr %B = load <64 x i16>, ptr %Bptr %A_even = shufflevector <64 x i16> %A, <64 x i16> undef, <32 x i32> %A_odd = shufflevector <64 x i16> %A, <64 x i16> undef, <32 x i32> %B_even = shufflevector <64 x i16> %B, <64 x i16> undef, <32 x i32> %B_odd = shufflevector <64 x i16> %B, <64 x i16> undef, <32 x i32> %A_even_ext = sext <32 x i16> %A_even to <32 x i32> %B_even_ext = sext <32 x i16> %B_even to <32 x i32> %A_odd_ext = sext <32 x i16> %A_odd to <32 x i32> %B_odd_ext = sext <32 x i16> %B_odd to <32 x i32> %even_mul = mul <32 x i32> %A_even_ext, %B_even_ext %odd_mul = mul <32 x i32> %A_odd_ext, %B_odd_ext %add = add <32 x i32> %even_mul, %odd_mul ret <32 x i32> %add } define <4 x i32> @pmaddwd_commuted_mul(ptr %Aptr, ptr %Bptr) { ; CHECK-LABEL: define range(i32 -2147418112, -2147483647) <4 x i32> @pmaddwd_commuted_mul( ; CHECK-SAME: ptr readonly captures(none) [[APTR:%.*]], ptr readonly captures(none) [[BPTR:%.*]]) local_unnamed_addr #[[ATTR2]] { ; CHECK-NEXT: [[A:%.*]] = load <8 x i16>, ptr [[APTR]], align 16 ; CHECK-NEXT: [[B:%.*]] = load <8 x i16>, ptr [[BPTR]], align 16 ; CHECK-NEXT: [[A_EVEN:%.*]] = shufflevector <8 x i16> [[A]], <8 x i16> poison, <4 x i32> ; CHECK-NEXT: [[A_ODD:%.*]] = shufflevector <8 x i16> [[A]], <8 x i16> poison, <4 x i32> ; CHECK-NEXT: [[B_EVEN:%.*]] = shufflevector <8 x i16> [[B]], <8 x i16> poison, <4 x i32> ; CHECK-NEXT: [[B_ODD:%.*]] = shufflevector <8 x i16> [[B]], <8 x i16> poison, <4 x i32> ; CHECK-NEXT: [[A_EVEN_EXT:%.*]] = sext <4 x i16> [[A_EVEN]] to <4 x i32> ; CHECK-NEXT: [[B_EVEN_EXT:%.*]] = sext <4 x i16> [[B_EVEN]] to <4 x i32> ; CHECK-NEXT: [[A_ODD_EXT:%.*]] = sext <4 x i16> [[A_ODD]] to <4 x i32> ; CHECK-NEXT: [[B_ODD_EXT:%.*]] = sext <4 x i16> [[B_ODD]] to <4 x i32> ; CHECK-NEXT: [[EVEN_MUL:%.*]] = mul nsw <4 x i32> [[B_EVEN_EXT]], [[A_EVEN_EXT]] ; CHECK-NEXT: [[ODD_MUL:%.*]] = mul nsw <4 x i32> [[B_ODD_EXT]], [[A_ODD_EXT]] ; CHECK-NEXT: [[ADD:%.*]] = add <4 x i32> [[EVEN_MUL]], [[ODD_MUL]] ; CHECK-NEXT: ret <4 x i32> [[ADD]] ; %A = load <8 x i16>, ptr %Aptr %B = load <8 x i16>, ptr %Bptr %A_even = shufflevector <8 x i16> %A, <8 x i16> undef, <4 x i32> %A_odd = shufflevector <8 x i16> %A, <8 x i16> undef, <4 x i32> %B_even = shufflevector <8 x i16> %B, <8 x i16> undef, <4 x i32> %B_odd = shufflevector <8 x i16> %B, <8 x i16> undef, <4 x i32> %A_even_ext = sext <4 x i16> %A_even to <4 x i32> %B_even_ext = sext <4 x i16> %B_even to <4 x i32> %A_odd_ext = sext <4 x i16> %A_odd to <4 x i32> %B_odd_ext = sext <4 x i16> %B_odd to <4 x i32> %even_mul = mul <4 x i32> %A_even_ext, %B_even_ext %odd_mul = mul <4 x i32> %B_odd_ext, %A_odd_ext ; Different order than previous mul %add = add <4 x i32> %even_mul, %odd_mul ret <4 x i32> %add } define <4 x i32> @pmaddwd_swapped_indices(ptr %Aptr, ptr %Bptr) { ; CHECK-LABEL: define range(i32 -2147418112, -2147483647) <4 x i32> @pmaddwd_swapped_indices( ; CHECK-SAME: ptr readonly captures(none) [[APTR:%.*]], ptr readonly captures(none) [[BPTR:%.*]]) local_unnamed_addr #[[ATTR2]] { ; CHECK-NEXT: [[A:%.*]] = load <8 x i16>, ptr [[APTR]], align 16 ; CHECK-NEXT: [[B:%.*]] = load <8 x i16>, ptr [[BPTR]], align 16 ; CHECK-NEXT: [[A_EVEN:%.*]] = shufflevector <8 x i16> [[A]], <8 x i16> poison, <4 x i32> ; CHECK-NEXT: [[A_ODD:%.*]] = shufflevector <8 x i16> [[A]], <8 x i16> poison, <4 x i32> ; CHECK-NEXT: [[B_EVEN:%.*]] = shufflevector <8 x i16> [[B]], <8 x i16> poison, <4 x i32> ; CHECK-NEXT: [[B_ODD:%.*]] = shufflevector <8 x i16> [[B]], <8 x i16> poison, <4 x i32> ; CHECK-NEXT: [[A_EVEN_EXT:%.*]] = sext <4 x i16> [[A_EVEN]] to <4 x i32> ; CHECK-NEXT: [[B_EVEN_EXT:%.*]] = sext <4 x i16> [[B_EVEN]] to <4 x i32> ; CHECK-NEXT: [[A_ODD_EXT:%.*]] = sext <4 x i16> [[A_ODD]] to <4 x i32> ; CHECK-NEXT: [[B_ODD_EXT:%.*]] = sext <4 x i16> [[B_ODD]] to <4 x i32> ; CHECK-NEXT: [[EVEN_MUL:%.*]] = mul nsw <4 x i32> [[B_EVEN_EXT]], [[A_EVEN_EXT]] ; CHECK-NEXT: [[ODD_MUL:%.*]] = mul nsw <4 x i32> [[B_ODD_EXT]], [[A_ODD_EXT]] ; CHECK-NEXT: [[ADD:%.*]] = add <4 x i32> [[EVEN_MUL]], [[ODD_MUL]] ; CHECK-NEXT: ret <4 x i32> [[ADD]] ; %A = load <8 x i16>, ptr %Aptr %B = load <8 x i16>, ptr %Bptr %A_even = shufflevector <8 x i16> %A, <8 x i16> undef, <4 x i32> ; indices aren't all even %A_odd = shufflevector <8 x i16> %A, <8 x i16> undef, <4 x i32> ; indices aren't all odd %B_even = shufflevector <8 x i16> %B, <8 x i16> undef, <4 x i32> ; same indices as A %B_odd = shufflevector <8 x i16> %B, <8 x i16> undef, <4 x i32> ; same indices as A %A_even_ext = sext <4 x i16> %A_even to <4 x i32> %B_even_ext = sext <4 x i16> %B_even to <4 x i32> %A_odd_ext = sext <4 x i16> %A_odd to <4 x i32> %B_odd_ext = sext <4 x i16> %B_odd to <4 x i32> %even_mul = mul <4 x i32> %A_even_ext, %B_even_ext %odd_mul = mul <4 x i32> %A_odd_ext, %B_odd_ext %add = add <4 x i32> %even_mul, %odd_mul ret <4 x i32> %add } ; Negative test where indices aren't paired properly define <4 x i32> @pmaddwd_bad_indices(ptr %Aptr, ptr %Bptr) { ; CHECK-LABEL: define range(i32 -2147418112, -2147483647) <4 x i32> @pmaddwd_bad_indices( ; CHECK-SAME: ptr readonly captures(none) [[APTR:%.*]], ptr readonly captures(none) [[BPTR:%.*]]) local_unnamed_addr #[[ATTR2]] { ; CHECK-NEXT: [[A:%.*]] = load <8 x i16>, ptr [[APTR]], align 16 ; CHECK-NEXT: [[B:%.*]] = load <8 x i16>, ptr [[BPTR]], align 16 ; CHECK-NEXT: [[A_EVEN:%.*]] = shufflevector <8 x i16> [[A]], <8 x i16> poison, <4 x i32> ; CHECK-NEXT: [[A_ODD:%.*]] = shufflevector <8 x i16> [[A]], <8 x i16> poison, <4 x i32> ; CHECK-NEXT: [[B_EVEN:%.*]] = shufflevector <8 x i16> [[B]], <8 x i16> poison, <4 x i32> ; CHECK-NEXT: [[B_ODD:%.*]] = shufflevector <8 x i16> [[B]], <8 x i16> poison, <4 x i32> ; CHECK-NEXT: [[A_EVEN_EXT:%.*]] = sext <4 x i16> [[A_EVEN]] to <4 x i32> ; CHECK-NEXT: [[B_EVEN_EXT:%.*]] = sext <4 x i16> [[B_EVEN]] to <4 x i32> ; CHECK-NEXT: [[A_ODD_EXT:%.*]] = sext <4 x i16> [[A_ODD]] to <4 x i32> ; CHECK-NEXT: [[B_ODD_EXT:%.*]] = sext <4 x i16> [[B_ODD]] to <4 x i32> ; CHECK-NEXT: [[EVEN_MUL:%.*]] = mul nsw <4 x i32> [[B_EVEN_EXT]], [[A_EVEN_EXT]] ; CHECK-NEXT: [[ODD_MUL:%.*]] = mul nsw <4 x i32> [[B_ODD_EXT]], [[A_ODD_EXT]] ; CHECK-NEXT: [[ADD:%.*]] = add <4 x i32> [[EVEN_MUL]], [[ODD_MUL]] ; CHECK-NEXT: ret <4 x i32> [[ADD]] ; %A = load <8 x i16>, ptr %Aptr %B = load <8 x i16>, ptr %Bptr %A_even = shufflevector <8 x i16> %A, <8 x i16> undef, <4 x i32> %A_odd = shufflevector <8 x i16> %A, <8 x i16> undef, <4 x i32> %B_even = shufflevector <8 x i16> %B, <8 x i16> undef, <4 x i32> ; different indices than A %B_odd = shufflevector <8 x i16> %B, <8 x i16> undef, <4 x i32> ; different indices than A %A_even_ext = sext <4 x i16> %A_even to <4 x i32> %B_even_ext = sext <4 x i16> %B_even to <4 x i32> %A_odd_ext = sext <4 x i16> %A_odd to <4 x i32> %B_odd_ext = sext <4 x i16> %B_odd to <4 x i32> %even_mul = mul <4 x i32> %A_even_ext, %B_even_ext %odd_mul = mul <4 x i32> %A_odd_ext, %B_odd_ext %add = add <4 x i32> %even_mul, %odd_mul ret <4 x i32> %add } ; This test contains two multiplies joined by an add. The result of that add is then reduced to a single element. ; SelectionDAGBuilder should tag the joining add as a vector reduction. We need to recognize that both sides can use pmaddwd define i32 @madd_double_reduction(ptr %arg, ptr %arg1, ptr %arg2, ptr %arg3) { ; CHECK-LABEL: define i32 @madd_double_reduction( ; CHECK-SAME: ptr readonly captures(none) [[ARG:%.*]], ptr readonly captures(none) [[ARG1:%.*]], ptr readonly captures(none) [[ARG2:%.*]], ptr readonly captures(none) [[ARG3:%.*]]) local_unnamed_addr #[[ATTR2]] { ; CHECK-NEXT: [[TMP:%.*]] = load <8 x i16>, ptr [[ARG]], align 1 ; CHECK-NEXT: [[TMP6:%.*]] = load <8 x i16>, ptr [[ARG1]], align 1 ; CHECK-NEXT: [[TMP7:%.*]] = sext <8 x i16> [[TMP]] to <8 x i32> ; CHECK-NEXT: [[TMP17:%.*]] = sext <8 x i16> [[TMP6]] to <8 x i32> ; CHECK-NEXT: [[TMP19:%.*]] = mul nsw <8 x i32> [[TMP17]], [[TMP7]] ; CHECK-NEXT: [[TMP20:%.*]] = load <8 x i16>, ptr [[ARG2]], align 1 ; CHECK-NEXT: [[TMP21:%.*]] = load <8 x i16>, ptr [[ARG3]], align 1 ; CHECK-NEXT: [[TMP22:%.*]] = sext <8 x i16> [[TMP20]] to <8 x i32> ; CHECK-NEXT: [[TMP23:%.*]] = sext <8 x i16> [[TMP21]] to <8 x i32> ; CHECK-NEXT: [[TMP25:%.*]] = mul nsw <8 x i32> [[TMP23]], [[TMP22]] ; CHECK-NEXT: [[TMP26:%.*]] = add nuw nsw <8 x i32> [[TMP25]], [[TMP19]] ; CHECK-NEXT: [[TMP35:%.*]] = tail call i32 @llvm.vector.reduce.add.v8i32(<8 x i32> [[TMP26]]) ; CHECK-NEXT: ret i32 [[TMP35]] ; %i = load <8 x i16>, ptr %arg, align 1 %i6 = load <8 x i16>, ptr %arg1, align 1 %i7 = sext <8 x i16> %i to <8 x i32> %i17 = sext <8 x i16> %i6 to <8 x i32> %i19 = mul nsw <8 x i32> %i7, %i17 %i20 = load <8 x i16>, ptr %arg2, align 1 %i21 = load <8 x i16>, ptr %arg3, align 1 %i22 = sext <8 x i16> %i20 to <8 x i32> %i23 = sext <8 x i16> %i21 to <8 x i32> %i25 = mul nsw <8 x i32> %i22, %i23 %i26 = add nuw nsw <8 x i32> %i25, %i19 %i29 = shufflevector <8 x i32> %i26, <8 x i32> undef, <8 x i32> %i30 = add <8 x i32> %i26, %i29 %i31 = shufflevector <8 x i32> %i30, <8 x i32> undef, <8 x i32> %i32 = add <8 x i32> %i30, %i31 %i33 = shufflevector <8 x i32> %i32, <8 x i32> undef, <8 x i32> %i34 = add <8 x i32> %i32, %i33 %i35 = extractelement <8 x i32> %i34, i64 0 ret i32 %i35 } define i32 @madd_quad_reduction(ptr %arg, ptr %arg1, ptr %arg2, ptr %arg3, ptr %arg4, ptr %arg5, ptr %arg6, ptr %arg7) { ; CHECK-LABEL: define i32 @madd_quad_reduction( ; CHECK-SAME: ptr readonly captures(none) [[ARG:%.*]], ptr readonly captures(none) [[ARG1:%.*]], ptr readonly captures(none) [[ARG2:%.*]], ptr readonly captures(none) [[ARG3:%.*]], ptr readonly captures(none) [[ARG4:%.*]], ptr readonly captures(none) [[ARG5:%.*]], ptr readonly captures(none) [[ARG6:%.*]], ptr readonly captures(none) [[ARG7:%.*]]) local_unnamed_addr #[[ATTR2]] { ; CHECK-NEXT: [[TMP:%.*]] = load <8 x i16>, ptr [[ARG]], align 1 ; CHECK-NEXT: [[TMP6:%.*]] = load <8 x i16>, ptr [[ARG1]], align 1 ; CHECK-NEXT: [[TMP7:%.*]] = sext <8 x i16> [[TMP]] to <8 x i32> ; CHECK-NEXT: [[TMP17:%.*]] = sext <8 x i16> [[TMP6]] to <8 x i32> ; CHECK-NEXT: [[TMP19:%.*]] = mul nsw <8 x i32> [[TMP17]], [[TMP7]] ; CHECK-NEXT: [[TMP20:%.*]] = load <8 x i16>, ptr [[ARG2]], align 1 ; CHECK-NEXT: [[TMP21:%.*]] = load <8 x i16>, ptr [[ARG3]], align 1 ; CHECK-NEXT: [[TMP22:%.*]] = sext <8 x i16> [[TMP20]] to <8 x i32> ; CHECK-NEXT: [[TMP23:%.*]] = sext <8 x i16> [[TMP21]] to <8 x i32> ; CHECK-NEXT: [[TMP25:%.*]] = mul nsw <8 x i32> [[TMP23]], [[TMP22]] ; CHECK-NEXT: [[TMP26:%.*]] = add nuw nsw <8 x i32> [[TMP25]], [[TMP19]] ; CHECK-NEXT: [[TMP40:%.*]] = load <8 x i16>, ptr [[ARG4]], align 1 ; CHECK-NEXT: [[TMP41:%.*]] = load <8 x i16>, ptr [[ARG5]], align 1 ; CHECK-NEXT: [[TMP42:%.*]] = sext <8 x i16> [[TMP40]] to <8 x i32> ; CHECK-NEXT: [[TMP43:%.*]] = sext <8 x i16> [[TMP41]] to <8 x i32> ; CHECK-NEXT: [[TMP45:%.*]] = mul nsw <8 x i32> [[TMP43]], [[TMP42]] ; CHECK-NEXT: [[TMP56:%.*]] = add nuw nsw <8 x i32> [[TMP26]], [[TMP45]] ; CHECK-NEXT: [[TMP50:%.*]] = load <8 x i16>, ptr [[ARG6]], align 1 ; CHECK-NEXT: [[TMP51:%.*]] = load <8 x i16>, ptr [[ARG7]], align 1 ; CHECK-NEXT: [[TMP52:%.*]] = sext <8 x i16> [[TMP50]] to <8 x i32> ; CHECK-NEXT: [[TMP53:%.*]] = sext <8 x i16> [[TMP51]] to <8 x i32> ; CHECK-NEXT: [[TMP55:%.*]] = mul nsw <8 x i32> [[TMP53]], [[TMP52]] ; CHECK-NEXT: [[TMP57:%.*]] = add nuw nsw <8 x i32> [[TMP56]], [[TMP55]] ; CHECK-NEXT: [[TMP35:%.*]] = tail call i32 @llvm.vector.reduce.add.v8i32(<8 x i32> [[TMP57]]) ; CHECK-NEXT: ret i32 [[TMP35]] ; %i = load <8 x i16>, ptr %arg, align 1 %i6 = load <8 x i16>, ptr %arg1, align 1 %i7 = sext <8 x i16> %i to <8 x i32> %i17 = sext <8 x i16> %i6 to <8 x i32> %i19 = mul nsw <8 x i32> %i7, %i17 %i20 = load <8 x i16>, ptr %arg2, align 1 %i21 = load <8 x i16>, ptr %arg3, align 1 %i22 = sext <8 x i16> %i20 to <8 x i32> %i23 = sext <8 x i16> %i21 to <8 x i32> %i25 = mul nsw <8 x i32> %i22, %i23 %i26 = add nuw nsw <8 x i32> %i25, %i19 %i40 = load <8 x i16>, ptr %arg4, align 1 %i41 = load <8 x i16>, ptr %arg5, align 1 %i42 = sext <8 x i16> %i40 to <8 x i32> %i43 = sext <8 x i16> %i41 to <8 x i32> %i45 = mul nsw <8 x i32> %i42, %i43 %i56 = add nuw nsw <8 x i32> %i26, %i45 %i50 = load <8 x i16>, ptr %arg6, align 1 %i51 = load <8 x i16>, ptr %arg7, align 1 %i52 = sext <8 x i16> %i50 to <8 x i32> %i53 = sext <8 x i16> %i51 to <8 x i32> %i55 = mul nsw <8 x i32> %i52, %i53 %i57 = add nuw nsw <8 x i32> %i55, %i56 %i29 = shufflevector <8 x i32> %i57, <8 x i32> undef, <8 x i32> %i30 = add <8 x i32> %i57, %i29 %i31 = shufflevector <8 x i32> %i30, <8 x i32> undef, <8 x i32> %i32 = add <8 x i32> %i30, %i31 %i33 = shufflevector <8 x i32> %i32, <8 x i32> undef, <8 x i32> %i34 = add <8 x i32> %i32, %i33 %i35 = extractelement <8 x i32> %i34, i64 0 ret i32 %i35 } define i64 @sum_and_sum_of_squares(ptr %a, i32 %n) { ; CHECK-LABEL: define i64 @sum_and_sum_of_squares( ; CHECK-SAME: ptr readonly captures(none) [[A:%.*]], i32 [[N:%.*]]) local_unnamed_addr #[[ATTR0]] { ; CHECK-NEXT: [[ENTRY:.*]]: ; CHECK-NEXT: [[TMP0:%.*]] = zext i32 [[N]] to i64 ; CHECK-NEXT: br label %[[VECTOR_BODY:.*]] ; CHECK: [[VECTOR_BODY]]: ; CHECK-NEXT: [[INDEX:%.*]] = phi i64 [ [[INDEX_NEXT:%.*]], %[[VECTOR_BODY]] ], [ 0, %[[ENTRY]] ] ; CHECK-NEXT: [[VEC_PHI:%.*]] = phi <8 x i32> [ [[TMP5:%.*]], %[[VECTOR_BODY]] ], [ zeroinitializer, %[[ENTRY]] ] ; CHECK-NEXT: [[SUM_PHI:%.*]] = phi <8 x i32> [ [[TMP3:%.*]], %[[VECTOR_BODY]] ], [ zeroinitializer, %[[ENTRY]] ] ; CHECK-NEXT: [[TMP1:%.*]] = getelementptr inbounds i8, ptr [[A]], i64 [[INDEX]] ; CHECK-NEXT: [[WIDE_LOAD:%.*]] = load <8 x i8>, ptr [[TMP1]], align 1 ; CHECK-NEXT: [[TMP2:%.*]] = zext <8 x i8> [[WIDE_LOAD]] to <8 x i32> ; CHECK-NEXT: [[TMP3]] = add nuw nsw <8 x i32> [[SUM_PHI]], [[TMP2]] ; CHECK-NEXT: [[TMP4:%.*]] = mul nuw nsw <8 x i32> [[TMP2]], [[TMP2]] ; CHECK-NEXT: [[TMP5]] = add nuw nsw <8 x i32> [[TMP4]], [[VEC_PHI]] ; CHECK-NEXT: [[INDEX_NEXT]] = add i64 [[INDEX]], 8 ; CHECK-NEXT: [[TMP6:%.*]] = icmp eq i64 [[INDEX_NEXT]], [[TMP0]] ; CHECK-NEXT: br i1 [[TMP6]], label %[[MIDDLE_BLOCK:.*]], label %[[VECTOR_BODY]] ; CHECK: [[MIDDLE_BLOCK]]: ; CHECK-NEXT: [[TMP7:%.*]] = tail call i32 @llvm.vector.reduce.add.v8i32(<8 x i32> [[TMP3]]) ; CHECK-NEXT: [[TMP8:%.*]] = tail call i32 @llvm.vector.reduce.add.v8i32(<8 x i32> [[TMP5]]) ; CHECK-NEXT: [[TMP:%.*]] = zext i32 [[TMP7]] to i64 ; CHECK-NEXT: [[TMP28:%.*]] = shl nuw i64 [[TMP]], 32 ; CHECK-NEXT: [[TMP29:%.*]] = zext i32 [[TMP8]] to i64 ; CHECK-NEXT: [[TMP30:%.*]] = or disjoint i64 [[TMP28]], [[TMP29]] ; CHECK-NEXT: ret i64 [[TMP30]] ; entry: %i0 = zext i32 %n to i64 br label %vector.body vector.body: %index = phi i64 [ %index.next, %vector.body ], [ 0, %entry ] %vec.phi = phi <8 x i32> [ %i6, %vector.body ], [ zeroinitializer, %entry ] %sum.phi = phi <8 x i32> [ %i4, %vector.body ], [ zeroinitializer, %entry ] %i1 = getelementptr inbounds i8, ptr %a, i64 %index %i2 = bitcast ptr %i1 to ptr %wide.load = load <8 x i8>, ptr %i2, align 1 %i3 = zext <8 x i8> %wide.load to <8 x i32> %i4 = add nsw <8 x i32> %i3, %sum.phi %i5 = mul nsw <8 x i32> %i3, %i3 %i6 = add nsw <8 x i32> %i5, %vec.phi %index.next = add i64 %index, 8 %i7 = icmp eq i64 %index.next, %i0 br i1 %i7, label %middle.block, label %vector.body middle.block: %rdx.shuf35 = shufflevector <8 x i32> %i4, <8 x i32> undef, <8 x i32> %bin.rdx36 = add <8 x i32> %i4, %rdx.shuf35 %rdx.shuf37 = shufflevector <8 x i32> %bin.rdx36, <8 x i32> undef, <8 x i32> %bin.rdx38 = add <8 x i32> %bin.rdx36, %rdx.shuf37 %rdx.shuf39 = shufflevector <8 x i32> %bin.rdx38, <8 x i32> undef, <8 x i32> %bin.rdx40 = add <8 x i32> %bin.rdx38, %rdx.shuf39 %i8 = extractelement <8 x i32> %bin.rdx40, i32 0 %rdx.shuf = shufflevector <8 x i32> %i6, <8 x i32> undef, <8 x i32> %bin.rdx = add <8 x i32> %i6, %rdx.shuf %rdx.shuf31 = shufflevector <8 x i32> %bin.rdx, <8 x i32> undef, <8 x i32> %bin.rdx32 = add <8 x i32> %bin.rdx, %rdx.shuf31 %rdx.shuf33 = shufflevector <8 x i32> %bin.rdx32, <8 x i32> undef, <8 x i32> %bin.rdx34 = add <8 x i32> %bin.rdx32, %rdx.shuf33 %i9 = extractelement <8 x i32> %bin.rdx34, i32 0 %i = zext i32 %i8 to i64 %i28 = shl nuw i64 %i, 32 %i29 = zext i32 %i9 to i64 %i30 = or i64 %i28, %i29 ret i64 %i30 } define i32 @sum_of_square_differences(ptr %a, ptr %b, i32 %n) { ; CHECK-LABEL: define i32 @sum_of_square_differences( ; CHECK-SAME: ptr readonly captures(none) [[A:%.*]], ptr readonly captures(none) [[B:%.*]], i32 [[N:%.*]]) local_unnamed_addr #[[ATTR0]] { ; CHECK-NEXT: [[ENTRY:.*]]: ; CHECK-NEXT: [[TMP0:%.*]] = zext i32 [[N]] to i64 ; CHECK-NEXT: br label %[[VECTOR_BODY:.*]] ; CHECK: [[VECTOR_BODY]]: ; CHECK-NEXT: [[INDEX:%.*]] = phi i64 [ [[INDEX_NEXT:%.*]], %[[VECTOR_BODY]] ], [ 0, %[[ENTRY]] ] ; CHECK-NEXT: [[VEC_PHI:%.*]] = phi <8 x i32> [ [[TMP7:%.*]], %[[VECTOR_BODY]] ], [ zeroinitializer, %[[ENTRY]] ] ; CHECK-NEXT: [[TMP1:%.*]] = getelementptr inbounds i8, ptr [[A]], i64 [[INDEX]] ; CHECK-NEXT: [[WIDE_LOAD:%.*]] = load <8 x i8>, ptr [[TMP1]], align 1 ; CHECK-NEXT: [[TMP2:%.*]] = zext <8 x i8> [[WIDE_LOAD]] to <8 x i32> ; CHECK-NEXT: [[TMP3:%.*]] = getelementptr inbounds i8, ptr [[B]], i64 [[INDEX]] ; CHECK-NEXT: [[WIDE_LOAD2:%.*]] = load <8 x i8>, ptr [[TMP3]], align 1 ; CHECK-NEXT: [[TMP4:%.*]] = zext <8 x i8> [[WIDE_LOAD2]] to <8 x i32> ; CHECK-NEXT: [[TMP5:%.*]] = sub nsw <8 x i32> [[TMP4]], [[TMP2]] ; CHECK-NEXT: [[TMP6:%.*]] = mul nsw <8 x i32> [[TMP5]], [[TMP5]] ; CHECK-NEXT: [[TMP7]] = add nuw nsw <8 x i32> [[TMP6]], [[VEC_PHI]] ; CHECK-NEXT: [[INDEX_NEXT]] = add i64 [[INDEX]], 8 ; CHECK-NEXT: [[TMP8:%.*]] = icmp eq i64 [[INDEX_NEXT]], [[TMP0]] ; CHECK-NEXT: br i1 [[TMP8]], label %[[MIDDLE_BLOCK:.*]], label %[[VECTOR_BODY]] ; CHECK: [[MIDDLE_BLOCK]]: ; CHECK-NEXT: [[TMP9:%.*]] = tail call i32 @llvm.vector.reduce.add.v8i32(<8 x i32> [[TMP7]]) ; CHECK-NEXT: ret i32 [[TMP9]] ; entry: %i0 = zext i32 %n to i64 br label %vector.body vector.body: %index = phi i64 [ %index.next, %vector.body ], [ 0, %entry ] %vec.phi = phi <8 x i32> [ %i9, %vector.body ], [ zeroinitializer, %entry ] %i1 = getelementptr inbounds i8, ptr %a, i64 %index %i2 = bitcast ptr %i1 to ptr %wide.load = load <8 x i8>, ptr %i2, align 1 %i3 = zext <8 x i8> %wide.load to <8 x i32> %i4 = getelementptr inbounds i8, ptr %b, i64 %index %i5 = bitcast ptr %i4 to ptr %wide.load2 = load <8 x i8>, ptr %i5, align 1 %i6 = zext <8 x i8> %wide.load2 to <8 x i32> %i7 = sub <8 x i32> %i6, %i3 %i8 = mul <8 x i32> %i7, %i7 %i9 = add nsw <8 x i32> %i8, %vec.phi %index.next = add i64 %index, 8 %i10 = icmp eq i64 %index.next, %i0 br i1 %i10, label %middle.block, label %vector.body middle.block: %rdx.shuf = shufflevector <8 x i32> %i9, <8 x i32> undef, <8 x i32> %bin.rdx = add <8 x i32> %i9, %rdx.shuf %rdx.shuf31 = shufflevector <8 x i32> %bin.rdx, <8 x i32> undef, <8 x i32> %bin.rdx32 = add <8 x i32> %bin.rdx, %rdx.shuf31 %rdx.shuf33 = shufflevector <8 x i32> %bin.rdx32, <8 x i32> undef, <8 x i32> %bin.rdx34 = add <8 x i32> %bin.rdx32, %rdx.shuf33 %i11 = extractelement <8 x i32> %bin.rdx34, i32 0 ret i32 %i11 } ; PR49716 - https://llvm.org/PR49716 define <4 x i32> @input_size_mismatch(<16 x i16> %x, ptr %p) { ; CHECK-LABEL: define range(i32 -2147418112, -2147483647) <4 x i32> @input_size_mismatch( ; CHECK-SAME: <16 x i16> [[X:%.*]], ptr readonly captures(none) [[P:%.*]]) local_unnamed_addr #[[ATTR2]] { ; CHECK-NEXT: [[TMP1:%.*]] = load <8 x i16>, ptr [[P]], align 32 ; CHECK-NEXT: [[X0:%.*]] = shufflevector <16 x i16> [[X]], <16 x i16> poison, <4 x i32> ; CHECK-NEXT: [[X1:%.*]] = shufflevector <16 x i16> [[X]], <16 x i16> poison, <4 x i32> ; CHECK-NEXT: [[Y0:%.*]] = shufflevector <8 x i16> [[TMP1]], <8 x i16> poison, <4 x i32> ; CHECK-NEXT: [[Y1:%.*]] = shufflevector <8 x i16> [[TMP1]], <8 x i16> poison, <4 x i32> ; CHECK-NEXT: [[SX0:%.*]] = sext <4 x i16> [[X0]] to <4 x i32> ; CHECK-NEXT: [[SX1:%.*]] = sext <4 x i16> [[X1]] to <4 x i32> ; CHECK-NEXT: [[SY0:%.*]] = sext <4 x i16> [[Y0]] to <4 x i32> ; CHECK-NEXT: [[SY1:%.*]] = sext <4 x i16> [[Y1]] to <4 x i32> ; CHECK-NEXT: [[M0:%.*]] = mul nsw <4 x i32> [[SY0]], [[SX0]] ; CHECK-NEXT: [[M1:%.*]] = mul nsw <4 x i32> [[SY1]], [[SX1]] ; CHECK-NEXT: [[R:%.*]] = add <4 x i32> [[M0]], [[M1]] ; CHECK-NEXT: ret <4 x i32> [[R]] ; %y = load <16 x i16>, ptr %p, align 32 %x0 = shufflevector <16 x i16> %x, <16 x i16> undef, <4 x i32> %x1 = shufflevector <16 x i16> %x, <16 x i16> undef, <4 x i32> %y0 = shufflevector <16 x i16> %y, <16 x i16> undef, <4 x i32> %y1 = shufflevector <16 x i16> %y, <16 x i16> undef, <4 x i32> %sx0 = sext <4 x i16> %x0 to <4 x i32> %sx1 = sext <4 x i16> %x1 to <4 x i32> %sy0 = sext <4 x i16> %y0 to <4 x i32> %sy1 = sext <4 x i16> %y1 to <4 x i32> %m0 = mul <4 x i32> %sx0, %sy0 %m1 = mul <4 x i32> %sx1, %sy1 %r = add <4 x i32> %m0, %m1 ret <4 x i32> %r } define <4 x i32> @output_size_mismatch(<16 x i16> %x, <16 x i16> %y) { ; CHECK-LABEL: define range(i32 -2147418112, -2147483647) <4 x i32> @output_size_mismatch( ; CHECK-SAME: <16 x i16> [[X:%.*]], <16 x i16> [[Y:%.*]]) local_unnamed_addr #[[ATTR1]] { ; CHECK-NEXT: [[X0:%.*]] = shufflevector <16 x i16> [[X]], <16 x i16> poison, <4 x i32> ; CHECK-NEXT: [[X1:%.*]] = shufflevector <16 x i16> [[X]], <16 x i16> poison, <4 x i32> ; CHECK-NEXT: [[Y0:%.*]] = shufflevector <16 x i16> [[Y]], <16 x i16> poison, <4 x i32> ; CHECK-NEXT: [[Y1:%.*]] = shufflevector <16 x i16> [[Y]], <16 x i16> poison, <4 x i32> ; CHECK-NEXT: [[SX0:%.*]] = sext <4 x i16> [[X0]] to <4 x i32> ; CHECK-NEXT: [[SX1:%.*]] = sext <4 x i16> [[X1]] to <4 x i32> ; CHECK-NEXT: [[SY0:%.*]] = sext <4 x i16> [[Y0]] to <4 x i32> ; CHECK-NEXT: [[SY1:%.*]] = sext <4 x i16> [[Y1]] to <4 x i32> ; CHECK-NEXT: [[M0:%.*]] = mul nsw <4 x i32> [[SY0]], [[SX0]] ; CHECK-NEXT: [[M1:%.*]] = mul nsw <4 x i32> [[SY1]], [[SX1]] ; CHECK-NEXT: [[R:%.*]] = add <4 x i32> [[M0]], [[M1]] ; CHECK-NEXT: ret <4 x i32> [[R]] ; %x0 = shufflevector <16 x i16> %x, <16 x i16> undef, <4 x i32> %x1 = shufflevector <16 x i16> %x, <16 x i16> undef, <4 x i32> %y0 = shufflevector <16 x i16> %y, <16 x i16> undef, <4 x i32> %y1 = shufflevector <16 x i16> %y, <16 x i16> undef, <4 x i32> %sx0 = sext <4 x i16> %x0 to <4 x i32> %sx1 = sext <4 x i16> %x1 to <4 x i32> %sy0 = sext <4 x i16> %y0 to <4 x i32> %sy1 = sext <4 x i16> %y1 to <4 x i32> %m0 = mul <4 x i32> %sx0, %sy0 %m1 = mul <4 x i32> %sx1, %sy1 %r = add <4 x i32> %m0, %m1 ret <4 x i32> %r } define <4 x i32> @output_size_mismatch_high_subvector(<16 x i16> %x, <16 x i16> %y) { ; CHECK-LABEL: define range(i32 -2147418112, -2147483647) <4 x i32> @output_size_mismatch_high_subvector( ; CHECK-SAME: <16 x i16> [[X:%.*]], <16 x i16> [[Y:%.*]]) local_unnamed_addr #[[ATTR1]] { ; CHECK-NEXT: [[X0:%.*]] = shufflevector <16 x i16> [[X]], <16 x i16> poison, <4 x i32> ; CHECK-NEXT: [[X1:%.*]] = shufflevector <16 x i16> [[X]], <16 x i16> poison, <4 x i32> ; CHECK-NEXT: [[Y0:%.*]] = shufflevector <16 x i16> [[Y]], <16 x i16> poison, <4 x i32> ; CHECK-NEXT: [[Y1:%.*]] = shufflevector <16 x i16> [[Y]], <16 x i16> poison, <4 x i32> ; CHECK-NEXT: [[SX0:%.*]] = sext <4 x i16> [[X0]] to <4 x i32> ; CHECK-NEXT: [[SX1:%.*]] = sext <4 x i16> [[X1]] to <4 x i32> ; CHECK-NEXT: [[SY0:%.*]] = sext <4 x i16> [[Y0]] to <4 x i32> ; CHECK-NEXT: [[SY1:%.*]] = sext <4 x i16> [[Y1]] to <4 x i32> ; CHECK-NEXT: [[M0:%.*]] = mul nsw <4 x i32> [[SY0]], [[SX0]] ; CHECK-NEXT: [[M1:%.*]] = mul nsw <4 x i32> [[SY1]], [[SX1]] ; CHECK-NEXT: [[R:%.*]] = add <4 x i32> [[M0]], [[M1]] ; CHECK-NEXT: ret <4 x i32> [[R]] ; %x0 = shufflevector <16 x i16> %x, <16 x i16> undef, <4 x i32> %x1 = shufflevector <16 x i16> %x, <16 x i16> undef, <4 x i32> %y0 = shufflevector <16 x i16> %y, <16 x i16> undef, <4 x i32> %y1 = shufflevector <16 x i16> %y, <16 x i16> undef, <4 x i32> %sx0 = sext <4 x i16> %x0 to <4 x i32> %sx1 = sext <4 x i16> %x1 to <4 x i32> %sy0 = sext <4 x i16> %y0 to <4 x i32> %sy1 = sext <4 x i16> %y1 to <4 x i32> %m0 = mul <4 x i32> %sx0, %sy0 %m1 = mul <4 x i32> %sx1, %sy1 %r = add <4 x i32> %m0, %m1 ret <4 x i32> %r } define i32 @add_used_by_loop_phi(ptr %a, ptr %b, i64 %offset_a, i64 %offset_b, i64 %k) { ; CHECK-LABEL: define i32 @add_used_by_loop_phi( ; CHECK-SAME: ptr readonly captures(none) [[A:%.*]], ptr readonly captures(none) [[B:%.*]], i64 [[OFFSET_A:%.*]], i64 [[OFFSET_B:%.*]], i64 [[K:%.*]]) local_unnamed_addr #[[ATTR0]] { ; CHECK-NEXT: [[ENTRY:.*]]: ; CHECK-NEXT: [[SCEVGEP_A:%.*]] = getelementptr i8, ptr [[A]], i64 [[OFFSET_A]] ; CHECK-NEXT: [[SCEVGEP_B:%.*]] = getelementptr i8, ptr [[B]], i64 [[OFFSET_B]] ; CHECK-NEXT: br label %[[LOOP:.*]] ; CHECK: [[LOOP]]: ; CHECK-NEXT: [[T0:%.*]] = phi <16 x i32> [ [[TMP3:%.*]], %[[LOOP]] ], [ zeroinitializer, %[[ENTRY]] ] ; CHECK-NEXT: [[IVLOOP:%.*]] = phi i64 [ [[NEXTIVLOOP:%.*]], %[[LOOP]] ], [ 0, %[[ENTRY]] ] ; CHECK-NEXT: [[SCEVGEP_A1:%.*]] = getelementptr i8, ptr [[SCEVGEP_A]], i64 [[IVLOOP]] ; CHECK-NEXT: [[GEPLOAD_A:%.*]] = load <16 x i8>, ptr [[SCEVGEP_A1]], align 1 ; CHECK-NEXT: [[SCEVGEP_B1:%.*]] = getelementptr i8, ptr [[SCEVGEP_B]], i64 [[IVLOOP]] ; CHECK-NEXT: [[GEPLOAD_B:%.*]] = load <16 x i8>, ptr [[SCEVGEP_B1]], align 1 ; CHECK-NEXT: [[TMP0:%.*]] = sext <16 x i8> [[GEPLOAD_A]] to <16 x i32> ; CHECK-NEXT: [[TMP1:%.*]] = sext <16 x i8> [[GEPLOAD_B]] to <16 x i32> ; CHECK-NEXT: [[TMP2:%.*]] = mul nsw <16 x i32> [[TMP1]], [[TMP0]] ; CHECK-NEXT: [[TMP3]] = add <16 x i32> [[TMP2]], [[T0]] ; CHECK-NEXT: [[NEXTIVLOOP]] = add nuw nsw i64 [[IVLOOP]], 16 ; CHECK-NEXT: [[CONDLOOP:%.*]] = icmp ult i64 [[NEXTIVLOOP]], [[K]] ; CHECK-NEXT: br i1 [[CONDLOOP]], label %[[LOOP]], label %[[AFTERLOOP:.*]] ; CHECK: [[AFTERLOOP]]: ; CHECK-NEXT: [[SUM:%.*]] = tail call i32 @llvm.vector.reduce.add.v16i32(<16 x i32> [[TMP3]]) ; CHECK-NEXT: ret i32 [[SUM]] ; entry: %scevgep_a = getelementptr i8, ptr %a, i64 %offset_a %scevgep_b = getelementptr i8, ptr %b, i64 %offset_b br label %loop loop: %t0 = phi <16 x i32> [ %i3, %loop ], [ zeroinitializer, %entry ] %ivloop = phi i64 [ %nextivloop, %loop ], [ 0, %entry ] %scevgep_a1 = getelementptr i8, ptr %scevgep_a, i64 %ivloop %scevgep_a2 = bitcast ptr %scevgep_a1 to ptr %gepload_a = load <16 x i8>, ptr %scevgep_a2, align 1 %scevgep_b1 = getelementptr i8, ptr %scevgep_b, i64 %ivloop %scevgep_b2 = bitcast ptr %scevgep_b1 to ptr %gepload_b = load <16 x i8>, ptr %scevgep_b2, align 1 %i0 = sext <16 x i8> %gepload_a to <16 x i32> %i1 = sext <16 x i8> %gepload_b to <16 x i32> %i2 = mul nsw <16 x i32> %i0, %i1 %i3 = add <16 x i32> %i2, %t0 %nextivloop = add nuw nsw i64 %ivloop, 16 %condloop = icmp ult i64 %nextivloop, %k br i1 %condloop, label %loop, label %afterloop afterloop: %.lcssa = phi <16 x i32> [ %i3, %loop ] %rdx.shuf = shufflevector <16 x i32> %.lcssa, <16 x i32> poison, <16 x i32> %bin.rdx = add <16 x i32> %.lcssa, %rdx.shuf %rdx.shuf90 = shufflevector <16 x i32> %bin.rdx, <16 x i32> poison, <16 x i32> %bin.rdx91 = add <16 x i32> %bin.rdx, %rdx.shuf90 %rdx.shuf92 = shufflevector <16 x i32> %bin.rdx91, <16 x i32> poison, <16 x i32> %bin.rdx93 = add <16 x i32> %bin.rdx91, %rdx.shuf92 %rdx.shuf94 = shufflevector <16 x i32> %bin.rdx93, <16 x i32> poison, <16 x i32> %bin.rdx95 = add <16 x i32> %bin.rdx93, %rdx.shuf94 %sum = extractelement <16 x i32> %bin.rdx95, i32 0 ret i32 %sum }