; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
; RUN: opt -slp-vectorizer -S < %s -mtriple=x86_64-apple-macosx -mcpu=corei7-avx | FileCheck %s

; #include <stdint.h>
;
; int foo(float *A, int n) {
;   float sum = 0;
;   for (intptr_t i=0; i < n; ++i) {
;     sum += 7*A[i*4  ] +
;            7*A[i*4+1] +
;            7*A[i*4+2] +
;            7*A[i*4+3];
;   }
;   return sum;
; }

; CHECK-LABEL: add_red
; CHECK: fmul <4 x float>
; CHECK: shufflevector <4 x float>

define i32 @add_red(float* %A, i32 %n) {
entry:
  %cmp31 = icmp sgt i32 %n, 0
  br i1 %cmp31, label %for.body.lr.ph, label %for.end

for.body.lr.ph:
  %0 = sext i32 %n to i64
  br label %for.body

for.body:
  %i.033 = phi i64 [ 0, %for.body.lr.ph ], [ %inc, %for.body ]
  %sum.032 = phi float [ 0.000000e+00, %for.body.lr.ph ], [ %add17, %for.body ]
  %mul = shl nsw i64 %i.033, 2
  %arrayidx = getelementptr inbounds float, float* %A, i64 %mul
  %1 = load float, float* %arrayidx, align 4
  %mul2 = fmul float %1, 7.000000e+00
  %add28 = or i64 %mul, 1
  %arrayidx4 = getelementptr inbounds float, float* %A, i64 %add28
  %2 = load float, float* %arrayidx4, align 4
  %mul5 = fmul float %2, 7.000000e+00
  %add6 = fadd fast float %mul2, %mul5
  %add829 = or i64 %mul, 2
  %arrayidx9 = getelementptr inbounds float, float* %A, i64 %add829
  %3 = load float, float* %arrayidx9, align 4
  %mul10 = fmul float %3, 7.000000e+00
  %add11 = fadd fast float %add6, %mul10
  %add1330 = or i64 %mul, 3
  %arrayidx14 = getelementptr inbounds float, float* %A, i64 %add1330
  %4 = load float, float* %arrayidx14, align 4
  %mul15 = fmul float %4, 7.000000e+00
  %add16 = fadd fast float %add11, %mul15
  %add17 = fadd fast float %sum.032, %add16
  %inc = add nsw i64 %i.033, 1
  %exitcond = icmp eq i64 %inc, %0
  br i1 %exitcond, label %for.cond.for.end_crit_edge, label %for.body

for.cond.for.end_crit_edge:
  %phitmp = fptosi float %add17 to i32
  br label %for.end

for.end:
  %sum.0.lcssa = phi i32 [ %phitmp, %for.cond.for.end_crit_edge ], [ 0, %entry ]
  ret i32 %sum.0.lcssa
}

; int foo(float * restrict A, float * restrict B, int n) {
;   float sum = 0;
;   for (intptr_t i=0; i < n; ++i) {
;     sum *= B[0]*A[i*4  ] +
;       B[1]*A[i*4+1] +
;       B[2]*A[i*4+2] +
;       B[3]*A[i*4+3];
;   }
;   return sum;
; }

; CHECK-LABEL: mul_red
; CHECK: fmul <4 x float>
; CHECK: shufflevector <4 x float>

define i32 @mul_red(float* noalias %A, float* noalias %B, i32 %n) {
entry:
  %cmp38 = icmp sgt i32 %n, 0
  br i1 %cmp38, label %for.body.lr.ph, label %for.end

for.body.lr.ph:
  %0 = load float, float* %B, align 4
  %arrayidx4 = getelementptr inbounds float, float* %B, i64 1
  %1 = load float, float* %arrayidx4, align 4
  %arrayidx9 = getelementptr inbounds float, float* %B, i64 2
  %2 = load float, float* %arrayidx9, align 4
  %arrayidx15 = getelementptr inbounds float, float* %B, i64 3
  %3 = load float, float* %arrayidx15, align 4
  %4 = sext i32 %n to i64
  br label %for.body

for.body:
  %i.040 = phi i64 [ 0, %for.body.lr.ph ], [ %inc, %for.body ]
  %sum.039 = phi float [ 0.000000e+00, %for.body.lr.ph ], [ %mul21, %for.body ]
  %mul = shl nsw i64 %i.040, 2
  %arrayidx2 = getelementptr inbounds float, float* %A, i64 %mul
  %5 = load float, float* %arrayidx2, align 4
  %mul3 = fmul float %0, %5
  %add35 = or i64 %mul, 1
  %arrayidx6 = getelementptr inbounds float, float* %A, i64 %add35
  %6 = load float, float* %arrayidx6, align 4
  %mul7 = fmul float %1, %6
  %add8 = fadd fast float %mul3, %mul7
  %add1136 = or i64 %mul, 2
  %arrayidx12 = getelementptr inbounds float, float* %A, i64 %add1136
  %7 = load float, float* %arrayidx12, align 4
  %mul13 = fmul float %2, %7
  %add14 = fadd fast float %add8, %mul13
  %add1737 = or i64 %mul, 3
  %arrayidx18 = getelementptr inbounds float, float* %A, i64 %add1737
  %8 = load float, float* %arrayidx18, align 4
  %mul19 = fmul float %3, %8
  %add20 = fadd fast float %add14, %mul19
  %mul21 = fmul float %sum.039, %add20
  %inc = add nsw i64 %i.040, 1
  %exitcond = icmp eq i64 %inc, %4
  br i1 %exitcond, label %for.cond.for.end_crit_edge, label %for.body

for.cond.for.end_crit_edge:
  %phitmp = fptosi float %mul21 to i32
  br label %for.end

for.end:
  %sum.0.lcssa = phi i32 [ %phitmp, %for.cond.for.end_crit_edge ], [ 0, %entry ]
  ret i32 %sum.0.lcssa
}

; int foo(float * restrict A, float * restrict B, int n) {
;   float sum = 0;
;   for (intptr_t i=0; i < n; ++i) {
;     sum += B[0]*A[i*6  ] +
;            B[1]*A[i*6+1] +
;            B[2]*A[i*6+2] +
;            B[3]*A[i*6+3] +
;            B[4]*A[i*6+4] +
;            B[5]*A[i*6+5] +
;            B[6]*A[i*6+6] +
;            B[7]*A[i*6+7] +
;            B[8]*A[i*6+8];
;   }
;   return sum;
; }

; CHECK-LABEL: long_red
; CHECK: fmul fast <8 x float>
; CHECK: shufflevector <8 x float>

define i32 @long_red(float* noalias %A, float* noalias %B, i32 %n) {
entry:
  %cmp81 = icmp sgt i32 %n, 0
  br i1 %cmp81, label %for.body.lr.ph, label %for.end

for.body.lr.ph:
  %0 = load float, float* %B, align 4
  %arrayidx4 = getelementptr inbounds float, float* %B, i64 1
  %1 = load float, float* %arrayidx4, align 4
  %arrayidx9 = getelementptr inbounds float, float* %B, i64 2
  %2 = load float, float* %arrayidx9, align 4
  %arrayidx15 = getelementptr inbounds float, float* %B, i64 3
  %3 = load float, float* %arrayidx15, align 4
  %arrayidx21 = getelementptr inbounds float, float* %B, i64 4
  %4 = load float, float* %arrayidx21, align 4
  %arrayidx27 = getelementptr inbounds float, float* %B, i64 5
  %5 = load float, float* %arrayidx27, align 4
  %arrayidx33 = getelementptr inbounds float, float* %B, i64 6
  %6 = load float, float* %arrayidx33, align 4
  %arrayidx39 = getelementptr inbounds float, float* %B, i64 7
  %7 = load float, float* %arrayidx39, align 4
  %arrayidx45 = getelementptr inbounds float, float* %B, i64 8
  %8 = load float, float* %arrayidx45, align 4
  %9 = sext i32 %n to i64
  br label %for.body

for.body:
  %i.083 = phi i64 [ 0, %for.body.lr.ph ], [ %inc, %for.body ]
  %sum.082 = phi float [ 0.000000e+00, %for.body.lr.ph ], [ %add51, %for.body ]
  %mul = mul nsw i64 %i.083, 6
  %arrayidx2 = getelementptr inbounds float, float* %A, i64 %mul
  %10 = load float, float* %arrayidx2, align 4
  %mul3 = fmul fast float %0, %10
  %add80 = or i64 %mul, 1
  %arrayidx6 = getelementptr inbounds float, float* %A, i64 %add80
  %11 = load float, float* %arrayidx6, align 4
  %mul7 = fmul fast float %1, %11
  %add8 = fadd fast float %mul3, %mul7
  %add11 = add nsw i64 %mul, 2
  %arrayidx12 = getelementptr inbounds float, float* %A, i64 %add11
  %12 = load float, float* %arrayidx12, align 4
  %mul13 = fmul fast float %2, %12
  %add14 = fadd fast float %add8, %mul13
  %add17 = add nsw i64 %mul, 3
  %arrayidx18 = getelementptr inbounds float, float* %A, i64 %add17
  %13 = load float, float* %arrayidx18, align 4
  %mul19 = fmul fast float %3, %13
  %add20 = fadd fast float %add14, %mul19
  %add23 = add nsw i64 %mul, 4
  %arrayidx24 = getelementptr inbounds float, float* %A, i64 %add23
  %14 = load float, float* %arrayidx24, align 4
  %mul25 = fmul fast float %4, %14
  %add26 = fadd fast float %add20, %mul25
  %add29 = add nsw i64 %mul, 5
  %arrayidx30 = getelementptr inbounds float, float* %A, i64 %add29
  %15 = load float, float* %arrayidx30, align 4
  %mul31 = fmul fast float %5, %15
  %add32 = fadd fast float %add26, %mul31
  %add35 = add nsw i64 %mul, 6
  %arrayidx36 = getelementptr inbounds float, float* %A, i64 %add35
  %16 = load float, float* %arrayidx36, align 4
  %mul37 = fmul fast float %6, %16
  %add38 = fadd fast float %add32, %mul37
  %add41 = add nsw i64 %mul, 7
  %arrayidx42 = getelementptr inbounds float, float* %A, i64 %add41
  %17 = load float, float* %arrayidx42, align 4
  %mul43 = fmul fast float %7, %17
  %add44 = fadd fast float %add38, %mul43
  %add47 = add nsw i64 %mul, 8
  %arrayidx48 = getelementptr inbounds float, float* %A, i64 %add47
  %18 = load float, float* %arrayidx48, align 4
  %mul49 = fmul fast float %8, %18
  %add50 = fadd fast float %add44, %mul49
  %add51 = fadd fast float %sum.082, %add50
  %inc = add nsw i64 %i.083, 1
  %exitcond = icmp eq i64 %inc, %9
  br i1 %exitcond, label %for.cond.for.end_crit_edge, label %for.body

for.cond.for.end_crit_edge:
  %phitmp = fptosi float %add51 to i32
  br label %for.end

for.end:
  %sum.0.lcssa = phi i32 [ %phitmp, %for.cond.for.end_crit_edge ], [ 0, %entry ]
  ret i32 %sum.0.lcssa
}

; int foo(float * restrict A, float * restrict B, int n) {
;   float sum = 0;
;   for (intptr_t i=0; i < n; ++i) {
;     sum += B[0]*A[i*4  ];
;     sum += B[1]*A[i*4+1];
;     sum += B[2]*A[i*4+2];
;     sum += B[3]*A[i*4+3];
;   }
;   return sum;
; }

; CHECK-LABEL: chain_red
; CHECK: fmul fast <4 x float>
; CHECK: shufflevector <4 x float>

define i32 @chain_red(float* noalias %A, float* noalias %B, i32 %n) {
entry:
  %cmp41 = icmp sgt i32 %n, 0
  br i1 %cmp41, label %for.body.lr.ph, label %for.end

for.body.lr.ph:
  %0 = load float, float* %B, align 4
  %arrayidx4 = getelementptr inbounds float, float* %B, i64 1
  %1 = load float, float* %arrayidx4, align 4
  %arrayidx10 = getelementptr inbounds float, float* %B, i64 2
  %2 = load float, float* %arrayidx10, align 4
  %arrayidx16 = getelementptr inbounds float, float* %B, i64 3
  %3 = load float, float* %arrayidx16, align 4
  %4 = sext i32 %n to i64
  br label %for.body

for.body:
  %i.043 = phi i64 [ 0, %for.body.lr.ph ], [ %inc, %for.body ]
  %sum.042 = phi float [ 0.000000e+00, %for.body.lr.ph ], [ %add21, %for.body ]
  %mul = shl nsw i64 %i.043, 2
  %arrayidx2 = getelementptr inbounds float, float* %A, i64 %mul
  %5 = load float, float* %arrayidx2, align 4
  %mul3 = fmul fast float %0, %5
  %add = fadd fast float %sum.042, %mul3
  %add638 = or i64 %mul, 1
  %arrayidx7 = getelementptr inbounds float, float* %A, i64 %add638
  %6 = load float, float* %arrayidx7, align 4
  %mul8 = fmul fast float %1, %6
  %add9 = fadd fast float %add, %mul8
  %add1239 = or i64 %mul, 2
  %arrayidx13 = getelementptr inbounds float, float* %A, i64 %add1239
  %7 = load float, float* %arrayidx13, align 4
  %mul14 = fmul fast float %2, %7
  %add15 = fadd fast float %add9, %mul14
  %add1840 = or i64 %mul, 3
  %arrayidx19 = getelementptr inbounds float, float* %A, i64 %add1840
  %8 = load float, float* %arrayidx19, align 4
  %mul20 = fmul fast float %3, %8
  %add21 = fadd fast float %add15, %mul20
  %inc = add nsw i64 %i.043, 1
  %exitcond = icmp eq i64 %inc, %4
  br i1 %exitcond, label %for.cond.for.end_crit_edge, label %for.body

for.cond.for.end_crit_edge:
  %phitmp = fptosi float %add21 to i32
  br label %for.end

for.end:
  %sum.0.lcssa = phi i32 [ %phitmp, %for.cond.for.end_crit_edge ], [ 0, %entry ]
  ret i32 %sum.0.lcssa
}

; void foo(const float *arg_A, unsigned arg_B, float *array) {
;   for (uint32_t i = 0; i < 6; ++i) {
;     const float *ptr = arg_A + i;
;     float w0 = array[i * 4 + 0];
;     float w1 = array[i * 4 + 1];
;     float w2 = array[i * 4 + 2];
;     float w3 = array[i * 4 + 3];
;
;     for (unsigned j = 0; j < arg_B; ++j) {
;       const float x1 = *ptr - (-1.1f * w0) - (1.2f * w1);
;       const float x2 = (2.1f * x1) + (-2.2f * w0) + (2.3f * w1);
;       const float x3 = x2 - (-3.1f * w2) - (3.2f * w3);
;       const float x4 = x3 + (-4.0f * w2) + w3;
;       w1 = w0;
;       w0 = x1;
;       w3 = w2;
;       w2 = x3;
;     }
;
;     array[i * 4 + 0] = w0;
;     array[i * 4 + 1] = w1;
;     array[i * 4 + 2] = w2;
;     array[i * 4 + 3] = w3;
;   }
; }

define void @foo(float* nocapture readonly %arg_A, i32 %arg_B, float* nocapture %array) {
; CHECK-LABEL: @foo(
; CHECK: fmul fast <4 x float>
; CHECK: shufflevector <4 x float>
;
entry:
  %cmp1495 = icmp eq i32 %arg_B, 0
  br label %for.body

for.cond.cleanup:                                 ; preds = %for.cond.cleanup15
  ret void

for.body:                                         ; preds = %for.cond.cleanup15, %entry
  %indvars.iv = phi i64 [ 0, %entry ], [ %indvars.iv.next, %for.cond.cleanup15 ]
  %0 = shl i64 %indvars.iv, 2
  %arrayidx = getelementptr inbounds float, float* %array, i64 %0
  %1 = load float, float* %arrayidx, align 4
  %2 = or i64 %0, 1
  %arrayidx4 = getelementptr inbounds float, float* %array, i64 %2
  %3 = load float, float* %arrayidx4, align 4
  %4 = or i64 %0, 2
  %arrayidx8 = getelementptr inbounds float, float* %array, i64 %4
  %5 = load float, float* %arrayidx8, align 4
  %6 = or i64 %0, 3
  %arrayidx12 = getelementptr inbounds float, float* %array, i64 %6
  %7 = load float, float* %arrayidx12, align 4
  br i1 %cmp1495, label %for.cond.cleanup15, label %for.body16.lr.ph

for.body16.lr.ph:                                 ; preds = %for.body
  %add.ptr = getelementptr inbounds float, float* %arg_A, i64 %indvars.iv
  %8 = load float, float* %add.ptr, align 4
  br label %for.body16

for.cond.cleanup15:                               ; preds = %for.body16, %for.body
  %w2.0.lcssa = phi float [ %5, %for.body ], [ %sub28, %for.body16 ]
  %w3.0.lcssa = phi float [ %7, %for.body ], [ %w2.096, %for.body16 ]
  %w1.0.lcssa = phi float [ %3, %for.body ], [ %w0.0100, %for.body16 ]
  %w0.0.lcssa = phi float [ %1, %for.body ], [ %sub19, %for.body16 ]
  store float %w0.0.lcssa, float* %arrayidx, align 4
  store float %w1.0.lcssa, float* %arrayidx4, align 4
  store float %w2.0.lcssa, float* %arrayidx8, align 4
  store float %w3.0.lcssa, float* %arrayidx12, align 4
  %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1
  %exitcond109 = icmp eq i64 %indvars.iv.next, 6
  br i1 %exitcond109, label %for.cond.cleanup, label %for.body

for.body16:                                       ; preds = %for.body16, %for.body16.lr.ph
  %w0.0100 = phi float [ %1, %for.body16.lr.ph ], [ %sub19, %for.body16 ]
  %w1.099 = phi float [ %3, %for.body16.lr.ph ], [ %w0.0100, %for.body16 ]
  %j.098 = phi i32 [ 0, %for.body16.lr.ph ], [ %inc, %for.body16 ]
  %w3.097 = phi float [ %7, %for.body16.lr.ph ], [ %w2.096, %for.body16 ]
  %w2.096 = phi float [ %5, %for.body16.lr.ph ], [ %sub28, %for.body16 ]
  %mul17 = fmul fast float %w0.0100, 0x3FF19999A0000000
  %mul18.neg = fmul fast float %w1.099, 0xBFF3333340000000
  %sub92 = fadd fast float %mul17, %mul18.neg
  %sub19 = fadd fast float %sub92, %8
  %mul20 = fmul fast float %sub19, 0x4000CCCCC0000000
  %mul21.neg = fmul fast float %w0.0100, 0xC0019999A0000000
  %mul23 = fmul fast float %w1.099, 0x4002666660000000
  %mul25 = fmul fast float %w2.096, 0x4008CCCCC0000000
  %mul27.neg = fmul fast float %w3.097, 0xC0099999A0000000
  %add2293 = fadd fast float %mul27.neg, %mul25
  %add24 = fadd fast float %add2293, %mul23
  %sub2694 = fadd fast float %add24, %mul21.neg
  %sub28 = fadd fast float %sub2694, %mul20
  %inc = add nuw i32 %j.098, 1
  %exitcond = icmp eq i32 %inc, %arg_B
  br i1 %exitcond, label %for.cond.cleanup15, label %for.body16
}

; RUN: opt -slp-vectorizer -slp-vectorize-hor -slp-vectorize-hor-store -S < %s -mtriple=x86_64-apple-macosx -mcpu=corei7-avx | FileCheck %s --check-prefix=STORE

; void foo(double * restrict A, double * restrict B, double * restrict C,
;          int n) {
;   for (intptr_t i=0; i < n; ++i) {
;     C[i] = B[0] *A[i*4  ] + B[1] *A[i*4+1];
;   }
; }

; STORE-LABEL: store_red_double
; STORE: fmul fast <2 x double>
; STORE: extractelement <2 x double>
; STORE: extractelement <2 x double>

define void @store_red_double(double* noalias %A, double* noalias %B, double* noalias %C, i32 %n) {
entry:
  %cmp17 = icmp sgt i32 %n, 0
  br i1 %cmp17, label %for.body.lr.ph, label %for.end

for.body.lr.ph:
  %0 = load double, double* %B, align 8
  %arrayidx4 = getelementptr inbounds double, double* %B, i64 1
  %1 = load double, double* %arrayidx4, align 8
  %2 = sext i32 %n to i64
  br label %for.body

for.body:
  %i.018 = phi i64 [ 0, %for.body.lr.ph ], [ %inc, %for.body ]
  %mul = shl nsw i64 %i.018, 2
  %arrayidx2 = getelementptr inbounds double, double* %A, i64 %mul
  %3 = load double, double* %arrayidx2, align 8
  %mul3 = fmul fast double %0, %3
  %add16 = or i64 %mul, 1
  %arrayidx6 = getelementptr inbounds double, double* %A, i64 %add16
  %4 = load double, double* %arrayidx6, align 8
  %mul7 = fmul fast double %1, %4
  %add8 = fadd fast double %mul3, %mul7
  %arrayidx9 = getelementptr inbounds double, double* %C, i64 %i.018
  store double %add8, double* %arrayidx9, align 8
  %inc = add nsw i64 %i.018, 1
  %exitcond = icmp eq i64 %inc, %2
  br i1 %exitcond, label %for.end, label %for.body

for.end:
  ret void
}

; int foo(float * restrict A, float * restrict B, float * restrict C, int n) {
;   float sum = 0;
;   for (intptr_t i=0; i < n; ++i) {
;     C[i] = B[0] *A[i*4  ] +
;          B[1] *A[i*4+1] +
;          B[2] *A[i*4+2] +
;          B[3] *A[i*4+3];
;   }
;   return sum;
; }

; STORE-LABEL: store_red
; STORE: fmul fast <4 x float>
; STORE: shufflevector <4 x float>

define i32 @store_red(float* noalias %A, float* noalias %B, float* noalias %C, i32 %n) {
entry:
  %cmp37 = icmp sgt i32 %n, 0
  br i1 %cmp37, label %for.body.lr.ph, label %for.end

for.body.lr.ph:
  %arrayidx4 = getelementptr inbounds float, float* %B, i64 1
  %arrayidx9 = getelementptr inbounds float, float* %B, i64 2
  %arrayidx15 = getelementptr inbounds float, float* %B, i64 3
  %0 = sext i32 %n to i64
  br label %for.body

for.body:
  %i.039 = phi i64 [ 0, %for.body.lr.ph ], [ %inc, %for.body ]
  %C.addr.038 = phi float* [ %C, %for.body.lr.ph ], [ %incdec.ptr, %for.body ]
  %1 = load float, float* %B, align 4
  %mul = shl nsw i64 %i.039, 2
  %arrayidx2 = getelementptr inbounds float, float* %A, i64 %mul
  %2 = load float, float* %arrayidx2, align 4
  %mul3 = fmul fast float %1, %2
  %3 = load float, float* %arrayidx4, align 4
  %add34 = or i64 %mul, 1
  %arrayidx6 = getelementptr inbounds float, float* %A, i64 %add34
  %4 = load float, float* %arrayidx6, align 4
  %mul7 = fmul fast float %3, %4
  %add8 = fadd fast float %mul3, %mul7
  %5 = load float, float* %arrayidx9, align 4
  %add1135 = or i64 %mul, 2
  %arrayidx12 = getelementptr inbounds float, float* %A, i64 %add1135
  %6 = load float, float* %arrayidx12, align 4
  %mul13 = fmul fast float %5, %6
  %add14 = fadd fast float %add8, %mul13
  %7 = load float, float* %arrayidx15, align 4
  %add1736 = or i64 %mul, 3
  %arrayidx18 = getelementptr inbounds float, float* %A, i64 %add1736
  %8 = load float, float* %arrayidx18, align 4
  %mul19 = fmul fast float %7, %8
  %add20 = fadd fast float %add14, %mul19
  store float %add20, float* %C.addr.038, align 4
  %incdec.ptr = getelementptr inbounds float, float* %C.addr.038, i64 1
  %inc = add nsw i64 %i.039, 1
  %exitcond = icmp eq i64 %inc, %0
  br i1 %exitcond, label %for.end, label %for.body

for.end:
  ret i32 0
}

@arr_i32 = global [32 x i32] zeroinitializer, align 16
@arr_float = global [32 x float] zeroinitializer, align 16

define void @float_red_example4(float* %res) {
; STORE-LABEL: @float_red_example4(
; STORE:         [[TMP0:%.*]] = load <4 x float>, <4 x float>* bitcast ([32 x float]* @arr_float to <4 x float>*), align 16
; STORE:         [[RDX_SHUF:%.*]] = shufflevector <4 x float> [[TMP0]], <4 x float> undef, <4 x i32> <i32 2, i32 3, i32 undef, i32 undef>
; STORE-NEXT:    [[BIN_RDX:%.*]] = fadd fast <4 x float> [[TMP0]], [[RDX_SHUF]]
; STORE-NEXT:    [[RDX_SHUF1:%.*]] = shufflevector <4 x float> [[BIN_RDX]], <4 x float> undef, <4 x i32> <i32 1, i32 undef, i32 undef, i32 undef>
; STORE-NEXT:    [[BIN_RDX2:%.*]] = fadd fast <4 x float> [[BIN_RDX]], [[RDX_SHUF1]]
; STORE-NEXT:    [[TMP1:%.*]] = extractelement <4 x float> [[BIN_RDX2]], i32 0
; STORE:         store float [[TMP1]], float* %res, align 16
; STORE-NEXT:    ret void
;
entry:
  %0 = load float, float* getelementptr inbounds ([32 x float], [32 x float]* @arr_float, i64 0, i64 0), align 16
  %1 = load float, float* getelementptr inbounds ([32 x float], [32 x float]* @arr_float, i64 0, i64 1), align 4
  %add = fadd fast float %1, %0
  %2 = load float, float* getelementptr inbounds ([32 x float], [32 x float]* @arr_float, i64 0, i64 2), align 8
  %add.1 = fadd fast float %2, %add
  %3 = load float, float* getelementptr inbounds ([32 x float], [32 x float]* @arr_float, i64 0, i64 3), align 4
  %add.2 = fadd fast float %3, %add.1
  store float %add.2, float* %res, align 16
  ret void
}

define void @float_red_example8(float* %res) {
; STORE-LABEL: @float_red_example8(
; STORE:         [[TMP0:%.*]] = load <8 x float>, <8 x float>* bitcast ([32 x float]* @arr_float to <8 x float>*), align 16
; STORE:         [[RDX_SHUF:%.*]] = shufflevector <8 x float> [[TMP0]], <8 x float> undef, <8 x i32> <i32 4, i32 5, i32 6, i32 7, i32 undef, i32 undef, i32 undef, i32 undef>
; STORE-NEXT:    [[BIN_RDX:%.*]] = fadd fast <8 x float> [[TMP0]], [[RDX_SHUF]]
; STORE-NEXT:    [[RDX_SHUF1:%.*]] = shufflevector <8 x float> [[BIN_RDX]], <8 x float> undef, <8 x i32> <i32 2, i32 3, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef>
; STORE-NEXT:    [[BIN_RDX2:%.*]] = fadd fast <8 x float> [[BIN_RDX]], [[RDX_SHUF1]]
; STORE-NEXT:    [[RDX_SHUF3:%.*]] = shufflevector <8 x float> [[BIN_RDX2]], <8 x float> undef, <8 x i32> <i32 1, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef>
; STORE-NEXT:    [[BIN_RDX4:%.*]] = fadd fast <8 x float> [[BIN_RDX2]], [[RDX_SHUF3]]
; STORE-NEXT:    [[TMP1:%.*]] = extractelement <8 x float> [[BIN_RDX4]], i32 0
; STORE:         store float [[TMP1]], float* %res, align 16
; STORE-NEXT:    ret void
;
entry:
  %0 = load float, float* getelementptr inbounds ([32 x float], [32 x float]* @arr_float, i64 0, i64 0), align 16
  %1 = load float, float* getelementptr inbounds ([32 x float], [32 x float]* @arr_float, i64 0, i64 1), align 4
  %add = fadd fast float %1, %0
  %2 = load float, float* getelementptr inbounds ([32 x float], [32 x float]* @arr_float, i64 0, i64 2), align 8
  %add.1 = fadd fast float %2, %add
  %3 = load float, float* getelementptr inbounds ([32 x float], [32 x float]* @arr_float, i64 0, i64 3), align 4
  %add.2 = fadd fast float %3, %add.1
  %4 = load float, float* getelementptr inbounds ([32 x float], [32 x float]* @arr_float, i64 0, i64 4), align 16
  %add.3 = fadd fast float %4, %add.2
  %5 = load float, float* getelementptr inbounds ([32 x float], [32 x float]* @arr_float, i64 0, i64 5), align 4
  %add.4 = fadd fast float %5, %add.3
  %6 = load float, float* getelementptr inbounds ([32 x float], [32 x float]* @arr_float, i64 0, i64 6), align 8
  %add.5 = fadd fast float %6, %add.4
  %7 = load float, float* getelementptr inbounds ([32 x float], [32 x float]* @arr_float, i64 0, i64 7), align 4
  %add.6 = fadd fast float %7, %add.5
  store float %add.6, float* %res, align 16
  ret void
}

define void @float_red_example16(float* %res) {
; STORE-LABEL: @float_red_example16(
; STORE:         [[TMP0:%.*]] = load <16 x float>, <16 x float>* bitcast ([32 x float]* @arr_float to <16 x float>*), align 16
; STORE:         [[RDX_SHUF:%.*]] = shufflevector <16 x float> [[TMP0]], <16 x float> undef, <16 x i32> <i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef>
; STORE-NEXT:    [[BIN_RDX:%.*]] = fadd fast <16 x float> [[TMP0]], [[RDX_SHUF]]
; STORE-NEXT:    [[RDX_SHUF1:%.*]] = shufflevector <16 x float> [[BIN_RDX]], <16 x float> undef, <16 x i32> <i32 4, i32 5, i32 6, i32 7, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef>
; STORE-NEXT:    [[BIN_RDX2:%.*]] = fadd fast <16 x float> [[BIN_RDX]], [[RDX_SHUF1]]
; STORE-NEXT:    [[RDX_SHUF3:%.*]] = shufflevector <16 x float> [[BIN_RDX2]], <16 x float> undef, <16 x i32> <i32 2, i32 3, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef>
; STORE-NEXT:    [[BIN_RDX4:%.*]] = fadd fast <16 x float> [[BIN_RDX2]], [[RDX_SHUF3]]
; STORE-NEXT:    [[RDX_SHUF5:%.*]] = shufflevector <16 x float> [[BIN_RDX4]], <16 x float> undef, <16 x i32> <i32 1, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef>
; STORE-NEXT:    [[BIN_RDX6:%.*]] = fadd fast <16 x float> [[BIN_RDX4]], [[RDX_SHUF5]]
; STORE-NEXT:    [[TMP1:%.*]] = extractelement <16 x float> [[BIN_RDX6]], i32 0
; STORE:         store float [[TMP1]], float* %res, align 16
; STORE-NEXT:    ret void
;
entry:
  %0 = load float, float* getelementptr inbounds ([32 x float], [32 x float]* @arr_float, i64 0, i64 0), align 16
  %1 = load float, float* getelementptr inbounds ([32 x float], [32 x float]* @arr_float, i64 0, i64 1), align 4
  %add = fadd fast float %1, %0
  %2 = load float, float* getelementptr inbounds ([32 x float], [32 x float]* @arr_float, i64 0, i64 2), align 8
  %add.1 = fadd fast float %2, %add
  %3 = load float, float* getelementptr inbounds ([32 x float], [32 x float]* @arr_float, i64 0, i64 3), align 4
  %add.2 = fadd fast float %3, %add.1
  %4 = load float, float* getelementptr inbounds ([32 x float], [32 x float]* @arr_float, i64 0, i64 4), align 16
  %add.3 = fadd fast float %4, %add.2
  %5 = load float, float* getelementptr inbounds ([32 x float], [32 x float]* @arr_float, i64 0, i64 5), align 4
  %add.4 = fadd fast float %5, %add.3
  %6 = load float, float* getelementptr inbounds ([32 x float], [32 x float]* @arr_float, i64 0, i64 6), align 8
  %add.5 = fadd fast float %6, %add.4
  %7 = load float, float* getelementptr inbounds ([32 x float], [32 x float]* @arr_float, i64 0, i64 7), align 4
  %add.6 = fadd fast float %7, %add.5
  %8 = load float, float* getelementptr inbounds ([32 x float], [32 x float]* @arr_float, i64 0, i64 8), align 16
  %add.7 = fadd fast float %8, %add.6
  %9 = load float, float* getelementptr inbounds ([32 x float], [32 x float]* @arr_float, i64 0, i64 9), align 4
  %add.8 = fadd fast float %9, %add.7
  %10 = load float, float* getelementptr inbounds ([32 x float], [32 x float]* @arr_float, i64 0, i64 10), align 8
  %add.9 = fadd fast float %10, %add.8
  %11 = load float, float* getelementptr inbounds ([32 x float], [32 x float]* @arr_float, i64 0, i64 11), align 4
  %add.10 = fadd fast float %11, %add.9
  %12 = load float, float* getelementptr inbounds ([32 x float], [32 x float]* @arr_float, i64 0, i64 12), align 16
  %add.11 = fadd fast float %12, %add.10
  %13 = load float, float* getelementptr inbounds ([32 x float], [32 x float]* @arr_float, i64 0, i64 13), align 4
  %add.12 = fadd fast float %13, %add.11
  %14 = load float, float* getelementptr inbounds ([32 x float], [32 x float]* @arr_float, i64 0, i64 14), align 8
  %add.13 = fadd fast float %14, %add.12
  %15 = load float, float* getelementptr inbounds ([32 x float], [32 x float]* @arr_float, i64 0, i64 15), align 4
  %add.14 = fadd fast float %15, %add.13
  store float %add.14, float* %res, align 16
  ret void
}

define void @i32_red_example4(i32* %res) {
; STORE-LABEL: @i32_red_example4(
; STORE:         [[TMP0:%.*]] = load <4 x i32>, <4 x i32>* bitcast ([32 x i32]* @arr_i32 to <4 x i32>*), align 16
; STORE:         [[RDX_SHUF:%.*]] = shufflevector <4 x i32> [[TMP0]], <4 x i32> undef, <4 x i32> <i32 2, i32 3, i32 undef, i32 undef>
; STORE-NEXT:    [[BIN_RDX:%.*]] = add nsw <4 x i32> [[TMP0]], [[RDX_SHUF]]
; STORE-NEXT:    [[RDX_SHUF1:%.*]] = shufflevector <4 x i32> [[BIN_RDX]], <4 x i32> undef, <4 x i32> <i32 1, i32 undef, i32 undef, i32 undef>
; STORE-NEXT:    [[BIN_RDX2:%.*]] = add nsw <4 x i32> [[BIN_RDX]], [[RDX_SHUF1]]
; STORE-NEXT:    [[TMP1:%.*]] = extractelement <4 x i32> [[BIN_RDX2]], i32 0
; STORE:         store i32 [[TMP1]], i32* %res, align 16
; STORE-NEXT:    ret void
;
entry:
  %0 = load i32, i32* getelementptr inbounds ([32 x i32], [32 x i32]* @arr_i32, i64 0, i64 0), align 16
  %1 = load i32, i32* getelementptr inbounds ([32 x i32], [32 x i32]* @arr_i32, i64 0, i64 1), align 4
  %add = add nsw i32 %1, %0
  %2 = load i32, i32* getelementptr inbounds ([32 x i32], [32 x i32]* @arr_i32, i64 0, i64 2), align 8
  %add.1 = add nsw i32 %2, %add
  %3 = load i32, i32* getelementptr inbounds ([32 x i32], [32 x i32]* @arr_i32, i64 0, i64 3), align 4
  %add.2 = add nsw i32 %3, %add.1
  store i32 %add.2, i32* %res, align 16
  ret void
}

define void @i32_red_example8(i32* %res) {
; STORE-LABEL: @i32_red_example8(
; STORE:         [[TMP0:%.*]] = load <8 x i32>, <8 x i32>* bitcast ([32 x i32]* @arr_i32 to <8 x i32>*), align 16
; STORE:         [[RDX_SHUF:%.*]] = shufflevector <8 x i32> [[TMP0]], <8 x i32> undef, <8 x i32> <i32 4, i32 5, i32 6, i32 7, i32 undef, i32 undef, i32 undef, i32 undef>
; STORE-NEXT:    [[BIN_RDX:%.*]] = add nsw <8 x i32> [[TMP0]], [[RDX_SHUF]]
; STORE-NEXT:    [[RDX_SHUF1:%.*]] = shufflevector <8 x i32> [[BIN_RDX]], <8 x i32> undef, <8 x i32> <i32 2, i32 3, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef>
; STORE-NEXT:    [[BIN_RDX2:%.*]] = add nsw <8 x i32> [[BIN_RDX]], [[RDX_SHUF1]]
; STORE-NEXT:    [[RDX_SHUF3:%.*]] = shufflevector <8 x i32> [[BIN_RDX2]], <8 x i32> undef, <8 x i32> <i32 1, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef>
; STORE-NEXT:    [[BIN_RDX4:%.*]] = add nsw <8 x i32> [[BIN_RDX2]], [[RDX_SHUF3]]
; STORE-NEXT:    [[TMP1:%.*]] = extractelement <8 x i32> [[BIN_RDX4]], i32 0
; STORE:         store i32 [[TMP1]], i32* %res, align 16
; STORE-NEXT:    ret void
;
entry:
  %0 = load i32, i32* getelementptr inbounds ([32 x i32], [32 x i32]* @arr_i32, i64 0, i64 0), align 16
  %1 = load i32, i32* getelementptr inbounds ([32 x i32], [32 x i32]* @arr_i32, i64 0, i64 1), align 4
  %add = add nsw i32 %1, %0
  %2 = load i32, i32* getelementptr inbounds ([32 x i32], [32 x i32]* @arr_i32, i64 0, i64 2), align 8
  %add.1 = add nsw i32 %2, %add
  %3 = load i32, i32* getelementptr inbounds ([32 x i32], [32 x i32]* @arr_i32, i64 0, i64 3), align 4
  %add.2 = add nsw i32 %3, %add.1
  %4 = load i32, i32* getelementptr inbounds ([32 x i32], [32 x i32]* @arr_i32, i64 0, i64 4), align 16
  %add.3 = add nsw i32 %4, %add.2
  %5 = load i32, i32* getelementptr inbounds ([32 x i32], [32 x i32]* @arr_i32, i64 0, i64 5), align 4
  %add.4 = add nsw i32 %5, %add.3
  %6 = load i32, i32* getelementptr inbounds ([32 x i32], [32 x i32]* @arr_i32, i64 0, i64 6), align 8
  %add.5 = add nsw i32 %6, %add.4
  %7 = load i32, i32* getelementptr inbounds ([32 x i32], [32 x i32]* @arr_i32, i64 0, i64 7), align 4
  %add.6 = add nsw i32 %7, %add.5
  store i32 %add.6, i32* %res, align 16
  ret void
}

define void @i32_red_example16(i32* %res) {
; STORE-LABEL: @i32_red_example16(
; STORE:         [[TMP0:%.*]] = load <16 x i32>, <16 x i32>* bitcast ([32 x i32]* @arr_i32 to <16 x i32>*), align 16
; STORE:         [[RDX_SHUF:%.*]] = shufflevector <16 x i32> [[TMP0]], <16 x i32> undef, <16 x i32> <i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef>
; STORE-NEXT:    [[BIN_RDX:%.*]] = add nsw <16 x i32> [[TMP0]], [[RDX_SHUF]]
; STORE-NEXT:    [[RDX_SHUF1:%.*]] = shufflevector <16 x i32> [[BIN_RDX]], <16 x i32> undef, <16 x i32> <i32 4, i32 5, i32 6, i32 7, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef>
; STORE-NEXT:    [[BIN_RDX2:%.*]] = add nsw <16 x i32> [[BIN_RDX]], [[RDX_SHUF1]]
; STORE-NEXT:    [[RDX_SHUF3:%.*]] = shufflevector <16 x i32> [[BIN_RDX2]], <16 x i32> undef, <16 x i32> <i32 2, i32 3, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef>
; STORE-NEXT:    [[BIN_RDX4:%.*]] = add nsw <16 x i32> [[BIN_RDX2]], [[RDX_SHUF3]]
; STORE-NEXT:    [[RDX_SHUF5:%.*]] = shufflevector <16 x i32> [[BIN_RDX4]], <16 x i32> undef, <16 x i32> <i32 1, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef>
; STORE-NEXT:    [[BIN_RDX6:%.*]] = add nsw <16 x i32> [[BIN_RDX4]], [[RDX_SHUF5]]
; STORE-NEXT:    [[TMP1:%.*]] = extractelement <16 x i32> [[BIN_RDX6]], i32 0
; STORE:         store i32 [[TMP1]], i32* %res, align 16
; STORE-NEXT:    ret void
;
entry:
  %0 = load i32, i32* getelementptr inbounds ([32 x i32], [32 x i32]* @arr_i32, i64 0, i64 0), align 16
  %1 = load i32, i32* getelementptr inbounds ([32 x i32], [32 x i32]* @arr_i32, i64 0, i64 1), align 4
  %add = add nsw i32 %1, %0
  %2 = load i32, i32* getelementptr inbounds ([32 x i32], [32 x i32]* @arr_i32, i64 0, i64 2), align 8
  %add.1 = add nsw i32 %2, %add
  %3 = load i32, i32* getelementptr inbounds ([32 x i32], [32 x i32]* @arr_i32, i64 0, i64 3), align 4
  %add.2 = add nsw i32 %3, %add.1
  %4 = load i32, i32* getelementptr inbounds ([32 x i32], [32 x i32]* @arr_i32, i64 0, i64 4), align 16
  %add.3 = add nsw i32 %4, %add.2
  %5 = load i32, i32* getelementptr inbounds ([32 x i32], [32 x i32]* @arr_i32, i64 0, i64 5), align 4
  %add.4 = add nsw i32 %5, %add.3
  %6 = load i32, i32* getelementptr inbounds ([32 x i32], [32 x i32]* @arr_i32, i64 0, i64 6), align 8
  %add.5 = add nsw i32 %6, %add.4
  %7 = load i32, i32* getelementptr inbounds ([32 x i32], [32 x i32]* @arr_i32, i64 0, i64 7), align 4
  %add.6 = add nsw i32 %7, %add.5
  %8 = load i32, i32* getelementptr inbounds ([32 x i32], [32 x i32]* @arr_i32, i64 0, i64 8), align 16
  %add.7 = add nsw i32 %8, %add.6
  %9 = load i32, i32* getelementptr inbounds ([32 x i32], [32 x i32]* @arr_i32, i64 0, i64 9), align 4
  %add.8 = add nsw i32 %9, %add.7
  %10 = load i32, i32* getelementptr inbounds ([32 x i32], [32 x i32]* @arr_i32, i64 0, i64 10), align 8
  %add.9 = add nsw i32 %10, %add.8
  %11 = load i32, i32* getelementptr inbounds ([32 x i32], [32 x i32]* @arr_i32, i64 0, i64 11), align 4
  %add.10 = add nsw i32 %11, %add.9
  %12 = load i32, i32* getelementptr inbounds ([32 x i32], [32 x i32]* @arr_i32, i64 0, i64 12), align 16
  %add.11 = add nsw i32 %12, %add.10
  %13 = load i32, i32* getelementptr inbounds ([32 x i32], [32 x i32]* @arr_i32, i64 0, i64 13), align 4
  %add.12 = add nsw i32 %13, %add.11
  %14 = load i32, i32* getelementptr inbounds ([32 x i32], [32 x i32]* @arr_i32, i64 0, i64 14), align 8
  %add.13 = add nsw i32 %14, %add.12
  %15 = load i32, i32* getelementptr inbounds ([32 x i32], [32 x i32]* @arr_i32, i64 0, i64 15), align 4
  %add.14 = add nsw i32 %15, %add.13
  store i32 %add.14, i32* %res, align 16
  ret void
}

define void @i32_red_example32(i32* %res) {
; STORE-LABEL: @i32_red_example32(
; STORE:         [[TMP0:%.*]] = load <32 x i32>, <32 x i32>* bitcast ([32 x i32]* @arr_i32 to <32 x i32>*), align 16
; STORE:         [[RDX_SHUF:%.*]] = shufflevector <32 x i32> [[TMP0]], <32 x i32> undef, <32 x i32> <i32 16, i32 17, i32 18, i32 19, i32 20, i32 21, i32 22, i32 23, i32 24, i32 25, i32 26, i32 27, i32 28, i32 29, i32 30, i32 31, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef>
; STORE-NEXT:    [[BIN_RDX:%.*]] = add nsw <32 x i32> [[TMP0]], [[RDX_SHUF]]
; STORE-NEXT:    [[RDX_SHUF1:%.*]] = shufflevector <32 x i32> [[BIN_RDX]], <32 x i32> undef, <32 x i32> <i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef>
; STORE-NEXT:    [[BIN_RDX2:%.*]] = add nsw <32 x i32> [[BIN_RDX]], [[RDX_SHUF1]]
; STORE-NEXT:    [[RDX_SHUF3:%.*]] = shufflevector <32 x i32> [[BIN_RDX2]], <32 x i32> undef, <32 x i32> <i32 4, i32 5, i32 6, i32 7, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef>
; STORE-NEXT:    [[BIN_RDX4:%.*]] = add nsw <32 x i32> [[BIN_RDX2]], [[RDX_SHUF3]]
; STORE-NEXT:    [[RDX_SHUF5:%.*]] = shufflevector <32 x i32> [[BIN_RDX4]], <32 x i32> undef, <32 x i32> <i32 2, i32 3, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef>
; STORE-NEXT:    [[BIN_RDX6:%.*]] = add nsw <32 x i32> [[BIN_RDX4]], [[RDX_SHUF5]]
; STORE-NEXT:    [[RDX_SHUF7:%.*]] = shufflevector <32 x i32> [[BIN_RDX6]], <32 x i32> undef, <32 x i32> <i32 1, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef>
; STORE-NEXT:    [[BIN_RDX8:%.*]] = add nsw <32 x i32> [[BIN_RDX6]], [[RDX_SHUF7]]
; STORE-NEXT:    [[TMP1:%.*]] = extractelement <32 x i32> [[BIN_RDX8]], i32 0
; STORE:         store i32 [[TMP1]], i32* %res, align 16
; STORE-NEXT:    ret void
;
entry:
  %0 = load i32, i32* getelementptr inbounds ([32 x i32], [32 x i32]* @arr_i32, i64 0, i64 0), align 16
  %1 = load i32, i32* getelementptr inbounds ([32 x i32], [32 x i32]* @arr_i32, i64 0, i64 1), align 4
  %add = add nsw i32 %1, %0
  %2 = load i32, i32* getelementptr inbounds ([32 x i32], [32 x i32]* @arr_i32, i64 0, i64 2), align 8
  %add.1 = add nsw i32 %2, %add
  %3 = load i32, i32* getelementptr inbounds ([32 x i32], [32 x i32]* @arr_i32, i64 0, i64 3), align 4
  %add.2 = add nsw i32 %3, %add.1
  %4 = load i32, i32* getelementptr inbounds ([32 x i32], [32 x i32]* @arr_i32, i64 0, i64 4), align 16
  %add.3 = add nsw i32 %4, %add.2
  %5 = load i32, i32* getelementptr inbounds ([32 x i32], [32 x i32]* @arr_i32, i64 0, i64 5), align 4
  %add.4 = add nsw i32 %5, %add.3
  %6 = load i32, i32* getelementptr inbounds ([32 x i32], [32 x i32]* @arr_i32, i64 0, i64 6), align 8
  %add.5 = add nsw i32 %6, %add.4
  %7 = load i32, i32* getelementptr inbounds ([32 x i32], [32 x i32]* @arr_i32, i64 0, i64 7), align 4
  %add.6 = add nsw i32 %7, %add.5
  %8 = load i32, i32* getelementptr inbounds ([32 x i32], [32 x i32]* @arr_i32, i64 0, i64 8), align 16
  %add.7 = add nsw i32 %8, %add.6
  %9 = load i32, i32* getelementptr inbounds ([32 x i32], [32 x i32]* @arr_i32, i64 0, i64 9), align 4
  %add.8 = add nsw i32 %9, %add.7
  %10 = load i32, i32* getelementptr inbounds ([32 x i32], [32 x i32]* @arr_i32, i64 0, i64 10), align 8
  %add.9 = add nsw i32 %10, %add.8
  %11 = load i32, i32* getelementptr inbounds ([32 x i32], [32 x i32]* @arr_i32, i64 0, i64 11), align 4
  %add.10 = add nsw i32 %11, %add.9
  %12 = load i32, i32* getelementptr inbounds ([32 x i32], [32 x i32]* @arr_i32, i64 0, i64 12), align 16
  %add.11 = add nsw i32 %12, %add.10
  %13 = load i32, i32* getelementptr inbounds ([32 x i32], [32 x i32]* @arr_i32, i64 0, i64 13), align 4
  %add.12 = add nsw i32 %13, %add.11
  %14 = load i32, i32* getelementptr inbounds ([32 x i32], [32 x i32]* @arr_i32, i64 0, i64 14), align 8
  %add.13 = add nsw i32 %14, %add.12
  %15 = load i32, i32* getelementptr inbounds ([32 x i32], [32 x i32]* @arr_i32, i64 0, i64 15), align 4
  %add.14 = add nsw i32 %15, %add.13
  %16 = load i32, i32* getelementptr inbounds ([32 x i32], [32 x i32]* @arr_i32, i64 0, i64 16), align 16
  %add.15 = add nsw i32 %16, %add.14
  %17 = load i32, i32* getelementptr inbounds ([32 x i32], [32 x i32]* @arr_i32, i64 0, i64 17), align 4
  %add.16 = add nsw i32 %17, %add.15
  %18 = load i32, i32* getelementptr inbounds ([32 x i32], [32 x i32]* @arr_i32, i64 0, i64 18), align 8
  %add.17 = add nsw i32 %18, %add.16
  %19 = load i32, i32* getelementptr inbounds ([32 x i32], [32 x i32]* @arr_i32, i64 0, i64 19), align 4
  %add.18 = add nsw i32 %19, %add.17
  %20 = load i32, i32* getelementptr inbounds ([32 x i32], [32 x i32]* @arr_i32, i64 0, i64 20), align 16
  %add.19 = add nsw i32 %20, %add.18
  %21 = load i32, i32* getelementptr inbounds ([32 x i32], [32 x i32]* @arr_i32, i64 0, i64 21), align 4
  %add.20 = add nsw i32 %21, %add.19
  %22 = load i32, i32* getelementptr inbounds ([32 x i32], [32 x i32]* @arr_i32, i64 0, i64 22), align 8
  %add.21 = add nsw i32 %22, %add.20
  %23 = load i32, i32* getelementptr inbounds ([32 x i32], [32 x i32]* @arr_i32, i64 0, i64 23), align 4
  %add.22 = add nsw i32 %23, %add.21
  %24 = load i32, i32* getelementptr inbounds ([32 x i32], [32 x i32]* @arr_i32, i64 0, i64 24), align 16
  %add.23 = add nsw i32 %24, %add.22
  %25 = load i32, i32* getelementptr inbounds ([32 x i32], [32 x i32]* @arr_i32, i64 0, i64 25), align 4
  %add.24 = add nsw i32 %25, %add.23
  %26 = load i32, i32* getelementptr inbounds ([32 x i32], [32 x i32]* @arr_i32, i64 0, i64 26), align 8
  %add.25 = add nsw i32 %26, %add.24
  %27 = load i32, i32* getelementptr inbounds ([32 x i32], [32 x i32]* @arr_i32, i64 0, i64 27), align 4
  %add.26 = add nsw i32 %27, %add.25
  %28 = load i32, i32* getelementptr inbounds ([32 x i32], [32 x i32]* @arr_i32, i64 0, i64 28), align 16
  %add.27 = add nsw i32 %28, %add.26
  %29 = load i32, i32* getelementptr inbounds ([32 x i32], [32 x i32]* @arr_i32, i64 0, i64 29), align 4
  %add.28 = add nsw i32 %29, %add.27
  %30 = load i32, i32* getelementptr inbounds ([32 x i32], [32 x i32]* @arr_i32, i64 0, i64 30), align 8
  %add.29 = add nsw i32 %30, %add.28
  %31 = load i32, i32* getelementptr inbounds ([32 x i32], [32 x i32]* @arr_i32, i64 0, i64 31), align 4
  %add.30 = add nsw i32 %31, %add.29
  store i32 %add.30, i32* %res, align 16
  ret void
}

declare i32 @foobar(i32)

define void @i32_red_call(i32 %val) {
; CHECK-LABEL: @i32_red_call(
; CHECK-NEXT:  entry:
; CHECK-NEXT:    [[TMP0:%.*]] = load <8 x i32>, <8 x i32>* bitcast ([32 x i32]* @arr_i32 to <8 x i32>*), align 16
; CHECK-NEXT:    [[ADD:%.*]] = add nsw i32 undef, undef
; CHECK-NEXT:    [[ADD_1:%.*]] = add nsw i32 undef, [[ADD]]
; CHECK-NEXT:    [[ADD_2:%.*]] = add nsw i32 undef, [[ADD_1]]
; CHECK-NEXT:    [[ADD_3:%.*]] = add nsw i32 undef, [[ADD_2]]
; CHECK-NEXT:    [[ADD_4:%.*]] = add nsw i32 undef, [[ADD_3]]
; CHECK-NEXT:    [[ADD_5:%.*]] = add nsw i32 undef, [[ADD_4]]
; CHECK-NEXT:    [[RDX_SHUF:%.*]] = shufflevector <8 x i32> [[TMP0]], <8 x i32> undef, <8 x i32> <i32 4, i32 5, i32 6, i32 7, i32 undef, i32 undef, i32 undef, i32 undef>
; CHECK-NEXT:    [[BIN_RDX:%.*]] = add nsw <8 x i32> [[TMP0]], [[RDX_SHUF]]
; CHECK-NEXT:    [[RDX_SHUF1:%.*]] = shufflevector <8 x i32> [[BIN_RDX]], <8 x i32> undef, <8 x i32> <i32 2, i32 3, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef>
; CHECK-NEXT:    [[BIN_RDX2:%.*]] = add nsw <8 x i32> [[BIN_RDX]], [[RDX_SHUF1]]
; CHECK-NEXT:    [[RDX_SHUF3:%.*]] = shufflevector <8 x i32> [[BIN_RDX2]], <8 x i32> undef, <8 x i32> <i32 1, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef>
; CHECK-NEXT:    [[BIN_RDX4:%.*]] = add nsw <8 x i32> [[BIN_RDX2]], [[RDX_SHUF3]]
; CHECK-NEXT:    [[TMP1:%.*]] = extractelement <8 x i32> [[BIN_RDX4]], i32 0
; CHECK-NEXT:    [[ADD_6:%.*]] = add nsw i32 undef, [[ADD_5]]
; CHECK-NEXT:    [[RES:%.*]] = call i32 @foobar(i32 [[TMP1]])
; CHECK-NEXT:    ret void
;
entry:
  %0 = load i32, i32* getelementptr inbounds ([32 x i32], [32 x i32]* @arr_i32, i64 0, i64 0), align 16
  %1 = load i32, i32* getelementptr inbounds ([32 x i32], [32 x i32]* @arr_i32, i64 0, i64 1), align 4
  %add = add nsw i32 %1, %0
  %2 = load i32, i32* getelementptr inbounds ([32 x i32], [32 x i32]* @arr_i32, i64 0, i64 2), align 8
  %add.1 = add nsw i32 %2, %add
  %3 = load i32, i32* getelementptr inbounds ([32 x i32], [32 x i32]* @arr_i32, i64 0, i64 3), align 4
  %add.2 = add nsw i32 %3, %add.1
  %4 = load i32, i32* getelementptr inbounds ([32 x i32], [32 x i32]* @arr_i32, i64 0, i64 4), align 16
  %add.3 = add nsw i32 %4, %add.2
  %5 = load i32, i32* getelementptr inbounds ([32 x i32], [32 x i32]* @arr_i32, i64 0, i64 5), align 4
  %add.4 = add nsw i32 %5, %add.3
  %6 = load i32, i32* getelementptr inbounds ([32 x i32], [32 x i32]* @arr_i32, i64 0, i64 6), align 8
  %add.5 = add nsw i32 %6, %add.4
  %7 = load i32, i32* getelementptr inbounds ([32 x i32], [32 x i32]* @arr_i32, i64 0, i64 7), align 4
  %add.6 = add nsw i32 %7, %add.5
  %res = call i32 @foobar(i32 %add.6)
  ret void
}

define void @i32_red_invoke(i32 %val) personality i32 (...)* @__gxx_personality_v0 {
; CHECK-LABEL: @i32_red_invoke(
; CHECK-NEXT:  entry:
; CHECK-NEXT:    [[TMP0:%.*]] = load <8 x i32>, <8 x i32>* bitcast ([32 x i32]* @arr_i32 to <8 x i32>*), align 16
; CHECK-NEXT:    [[ADD:%.*]] = add nsw i32 undef, undef
; CHECK-NEXT:    [[ADD_1:%.*]] = add nsw i32 undef, [[ADD]]
; CHECK-NEXT:    [[ADD_2:%.*]] = add nsw i32 undef, [[ADD_1]]
; CHECK-NEXT:    [[ADD_3:%.*]] = add nsw i32 undef, [[ADD_2]]
; CHECK-NEXT:    [[ADD_4:%.*]] = add nsw i32 undef, [[ADD_3]]
; CHECK-NEXT:    [[ADD_5:%.*]] = add nsw i32 undef, [[ADD_4]]
; CHECK-NEXT:    [[RDX_SHUF:%.*]] = shufflevector <8 x i32> [[TMP0]], <8 x i32> undef, <8 x i32> <i32 4, i32 5, i32 6, i32 7, i32 undef, i32 undef, i32 undef, i32 undef>
; CHECK-NEXT:    [[BIN_RDX:%.*]] = add nsw <8 x i32> [[TMP0]], [[RDX_SHUF]]
; CHECK-NEXT:    [[RDX_SHUF1:%.*]] = shufflevector <8 x i32> [[BIN_RDX]], <8 x i32> undef, <8 x i32> <i32 2, i32 3, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef>
; CHECK-NEXT:    [[BIN_RDX2:%.*]] = add nsw <8 x i32> [[BIN_RDX]], [[RDX_SHUF1]]
; CHECK-NEXT:    [[RDX_SHUF3:%.*]] = shufflevector <8 x i32> [[BIN_RDX2]], <8 x i32> undef, <8 x i32> <i32 1, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef>
; CHECK-NEXT:    [[BIN_RDX4:%.*]] = add nsw <8 x i32> [[BIN_RDX2]], [[RDX_SHUF3]]
; CHECK-NEXT:    [[TMP1:%.*]] = extractelement <8 x i32> [[BIN_RDX4]], i32 0
; CHECK-NEXT:    [[ADD_6:%.*]] = add nsw i32 undef, [[ADD_5]]
; CHECK-NEXT:    [[RES:%.*]] = invoke i32 @foobar(i32 [[TMP1]])
; CHECK-NEXT:    to label [[NORMAL:%.*]] unwind label [[EXCEPTION:%.*]]
; CHECK:       exception:
; CHECK-NEXT:    [[CLEANUP:%.*]] = landingpad i8
; CHECK-NEXT:    cleanup
; CHECK-NEXT:    br label [[NORMAL]]
; CHECK:       normal:
; CHECK-NEXT:    ret void
;
entry:
  %0 = load i32, i32* getelementptr inbounds ([32 x i32], [32 x i32]* @arr_i32, i64 0, i64 0), align 16
  %1 = load i32, i32* getelementptr inbounds ([32 x i32], [32 x i32]* @arr_i32, i64 0, i64 1), align 4
  %add = add nsw i32 %1, %0
  %2 = load i32, i32* getelementptr inbounds ([32 x i32], [32 x i32]* @arr_i32, i64 0, i64 2), align 8
  %add.1 = add nsw i32 %2, %add
  %3 = load i32, i32* getelementptr inbounds ([32 x i32], [32 x i32]* @arr_i32, i64 0, i64 3), align 4
  %add.2 = add nsw i32 %3, %add.1
  %4 = load i32, i32* getelementptr inbounds ([32 x i32], [32 x i32]* @arr_i32, i64 0, i64 4), align 16
  %add.3 = add nsw i32 %4, %add.2
  %5 = load i32, i32* getelementptr inbounds ([32 x i32], [32 x i32]* @arr_i32, i64 0, i64 5), align 4
  %add.4 = add nsw i32 %5, %add.3
  %6 = load i32, i32* getelementptr inbounds ([32 x i32], [32 x i32]* @arr_i32, i64 0, i64 6), align 8
  %add.5 = add nsw i32 %6, %add.4
  %7 = load i32, i32* getelementptr inbounds ([32 x i32], [32 x i32]* @arr_i32, i64 0, i64 7), align 4
  %add.6 = add nsw i32 %7, %add.5
  %res = invoke i32 @foobar(i32 %add.6) to label %normal unwind label %exception
exception:
  %cleanup = landingpad i8 cleanup
  br label %normal
normal:
  ret void
}

declare i32 @__gxx_personality_v0(...)
