; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 5
; RUN: opt -passes=sandbox-vectorizer -sbvec-vec-reg-bits=1024 -sbvec-allow-non-pow2 -sbvec-passes="seed-collection<tr-save,bottom-up-vec,tr-accept>" %s -S | FileCheck %s

define void @store_load(ptr %ptr) {
; CHECK-LABEL: define void @store_load(
; CHECK-SAME: ptr [[PTR:%.*]]) {
; CHECK-NEXT:    [[PTR0:%.*]] = getelementptr float, ptr [[PTR]], i32 0
; CHECK-NEXT:    [[VECL:%.*]] = load <2 x float>, ptr [[PTR0]], align 4
; CHECK-NEXT:    store <2 x float> [[VECL]], ptr [[PTR0]], align 4
; CHECK-NEXT:    ret void
;
  %ptr0 = getelementptr float, ptr %ptr, i32 0
  %ptr1 = getelementptr float, ptr %ptr, i32 1
  %ld0 = load float, ptr %ptr0
  %ld1 = load float, ptr %ptr1
  store float %ld0, ptr %ptr0
  store float %ld1, ptr %ptr1
  ret void
}


define void @store_fpext_load(ptr %ptr) {
; CHECK-LABEL: define void @store_fpext_load(
; CHECK-SAME: ptr [[PTR:%.*]]) {
; CHECK-NEXT:    [[PTR0:%.*]] = getelementptr float, ptr [[PTR]], i32 0
; CHECK-NEXT:    [[PTRD0:%.*]] = getelementptr double, ptr [[PTR]], i32 0
; CHECK-NEXT:    [[VECL:%.*]] = load <2 x float>, ptr [[PTR0]], align 4
; CHECK-NEXT:    [[VCAST:%.*]] = fpext <2 x float> [[VECL]] to <2 x double>
; CHECK-NEXT:    store <2 x double> [[VCAST]], ptr [[PTRD0]], align 8
; CHECK-NEXT:    ret void
;
  %ptr0 = getelementptr float, ptr %ptr, i32 0
  %ptr1 = getelementptr float, ptr %ptr, i32 1
  %ptrd0 = getelementptr double, ptr %ptr, i32 0
  %ptrd1 = getelementptr double, ptr %ptr, i32 1
  %ld0 = load float, ptr %ptr0
  %ld1 = load float, ptr %ptr1
  %fpext0 = fpext float %ld0 to double
  %fpext1 = fpext float %ld1 to double
  store double %fpext0, ptr %ptrd0
  store double %fpext1, ptr %ptrd1
  ret void
}

define void @store_fcmp_zext_load(ptr %ptr) {
; CHECK-LABEL: define void @store_fcmp_zext_load(
; CHECK-SAME: ptr [[PTR:%.*]]) {
; CHECK-NEXT:    [[PTR0:%.*]] = getelementptr float, ptr [[PTR]], i32 0
; CHECK-NEXT:    [[PTRB0:%.*]] = getelementptr i32, ptr [[PTR]], i32 0
; CHECK-NEXT:    [[VECL1:%.*]] = load <2 x float>, ptr [[PTR0]], align 4
; CHECK-NEXT:    [[VECL:%.*]] = load <2 x float>, ptr [[PTR0]], align 4
; CHECK-NEXT:    [[VCMP:%.*]] = fcmp ogt <2 x float> [[VECL]], [[VECL1]]
; CHECK-NEXT:    [[VCAST:%.*]] = zext <2 x i1> [[VCMP]] to <2 x i32>
; CHECK-NEXT:    store <2 x i32> [[VCAST]], ptr [[PTRB0]], align 4
; CHECK-NEXT:    ret void
;
  %ptr0 = getelementptr float, ptr %ptr, i32 0
  %ptr1 = getelementptr float, ptr %ptr, i32 1
  %ptrb0 = getelementptr i32, ptr %ptr, i32 0
  %ptrb1 = getelementptr i32, ptr %ptr, i32 1
  %ldB0 = load float, ptr %ptr0
  %ldB1 = load float, ptr %ptr1
  %ldA0 = load float, ptr %ptr0
  %ldA1 = load float, ptr %ptr1
  %fcmp0 = fcmp ogt float %ldA0, %ldB0
  %fcmp1 = fcmp ogt float %ldA1, %ldB1
  %zext0 = zext i1 %fcmp0 to i32
  %zext1 = zext i1 %fcmp1 to i32
  store i32 %zext0, ptr %ptrb0
  store i32 %zext1, ptr %ptrb1
  ret void
}

define void @store_fadd_load(ptr %ptr) {
; CHECK-LABEL: define void @store_fadd_load(
; CHECK-SAME: ptr [[PTR:%.*]]) {
; CHECK-NEXT:    [[PTR0:%.*]] = getelementptr float, ptr [[PTR]], i32 0
; CHECK-NEXT:    [[VECL:%.*]] = load <2 x float>, ptr [[PTR0]], align 4
; CHECK-NEXT:    [[VECL1:%.*]] = load <2 x float>, ptr [[PTR0]], align 4
; CHECK-NEXT:    [[VEC:%.*]] = fadd <2 x float> [[VECL1]], [[VECL]]
; CHECK-NEXT:    store <2 x float> [[VEC]], ptr [[PTR0]], align 4
; CHECK-NEXT:    ret void
;
  %ptr0 = getelementptr float, ptr %ptr, i32 0
  %ptr1 = getelementptr float, ptr %ptr, i32 1
  %ldA0 = load float, ptr %ptr0
  %ldA1 = load float, ptr %ptr1
  %ldB0 = load float, ptr %ptr0
  %ldB1 = load float, ptr %ptr1
  %fadd0 = fadd float %ldA0, %ldB0
  %fadd1 = fadd float %ldA1, %ldB1
  store float %fadd0, ptr %ptr0
  store float %fadd1, ptr %ptr1
  ret void
}

define void @store_fneg_load(ptr %ptr) {
; CHECK-LABEL: define void @store_fneg_load(
; CHECK-SAME: ptr [[PTR:%.*]]) {
; CHECK-NEXT:    [[PTR0:%.*]] = getelementptr float, ptr [[PTR]], i32 0
; CHECK-NEXT:    [[VECL:%.*]] = load <2 x float>, ptr [[PTR0]], align 4
; CHECK-NEXT:    [[VEC:%.*]] = fneg <2 x float> [[VECL]]
; CHECK-NEXT:    store <2 x float> [[VEC]], ptr [[PTR0]], align 4
; CHECK-NEXT:    ret void
;
  %ptr0 = getelementptr float, ptr %ptr, i32 0
  %ptr1 = getelementptr float, ptr %ptr, i32 1
  %ld0 = load float, ptr %ptr0
  %ld1 = load float, ptr %ptr1
  %fneg0 = fneg float %ld0
  %fneg1 = fneg float %ld1
  store float %fneg0, ptr %ptr0
  store float %fneg1, ptr %ptr1
  ret void
}

define float @scalars_with_external_uses_not_dead(ptr %ptr) {
; CHECK-LABEL: define float @scalars_with_external_uses_not_dead(
; CHECK-SAME: ptr [[PTR:%.*]]) {
; CHECK-NEXT:    [[PTR0:%.*]] = getelementptr float, ptr [[PTR]], i32 0
; CHECK-NEXT:    [[PTR1:%.*]] = getelementptr float, ptr [[PTR]], i32 1
; CHECK-NEXT:    [[LD0:%.*]] = load float, ptr [[PTR0]], align 4
; CHECK-NEXT:    [[LD1:%.*]] = load float, ptr [[PTR1]], align 4
; CHECK-NEXT:    [[VECL:%.*]] = load <2 x float>, ptr [[PTR0]], align 4
; CHECK-NEXT:    store <2 x float> [[VECL]], ptr [[PTR0]], align 4
; CHECK-NEXT:    [[USER:%.*]] = fneg float [[LD1]]
; CHECK-NEXT:    ret float [[LD0]]
;
  %ptr0 = getelementptr float, ptr %ptr, i32 0
  %ptr1 = getelementptr float, ptr %ptr, i32 1
  %ld0 = load float, ptr %ptr0
  %ld1 = load float, ptr %ptr1
  store float %ld0, ptr %ptr0
  store float %ld1, ptr %ptr1
  %user = fneg float %ld1
  ret float %ld0
}

define void @pack_scalars(ptr %ptr, ptr %ptr2) {
; CHECK-LABEL: define void @pack_scalars(
; CHECK-SAME: ptr [[PTR:%.*]], ptr [[PTR2:%.*]]) {
; CHECK-NEXT:    [[PTR0:%.*]] = getelementptr float, ptr [[PTR]], i32 0
; CHECK-NEXT:    [[LD0:%.*]] = load float, ptr [[PTR0]], align 4
; CHECK-NEXT:    [[LD1:%.*]] = load float, ptr [[PTR2]], align 4
; CHECK-NEXT:    [[PACK:%.*]] = insertelement <2 x float> poison, float [[LD0]], i32 0
; CHECK-NEXT:    [[PACK1:%.*]] = insertelement <2 x float> [[PACK]], float [[LD1]], i32 1
; CHECK-NEXT:    store <2 x float> [[PACK1]], ptr [[PTR0]], align 4
; CHECK-NEXT:    ret void
;
  %ptr0 = getelementptr float, ptr %ptr, i32 0
  %ptr1 = getelementptr float, ptr %ptr, i32 1
  %ld0 = load float, ptr %ptr0
  %ld1 = load float, ptr %ptr2
  store float %ld0, ptr %ptr0
  store float %ld1, ptr %ptr1
  ret void
}

declare void @foo()
define void @cant_vectorize_seeds(ptr %ptr) {
; CHECK-LABEL: define void @cant_vectorize_seeds(
; CHECK-SAME: ptr [[PTR:%.*]]) {
; CHECK-NEXT:    [[PTR0:%.*]] = getelementptr float, ptr [[PTR]], i32 0
; CHECK-NEXT:    [[PTR1:%.*]] = getelementptr float, ptr [[PTR]], i32 1
; CHECK-NEXT:    [[LD0:%.*]] = load float, ptr [[PTR0]], align 4
; CHECK-NEXT:    [[LD1:%.*]] = load float, ptr [[PTR1]], align 4
; CHECK-NEXT:    store float [[LD1]], ptr [[PTR1]], align 4
; CHECK-NEXT:    call void @foo()
; CHECK-NEXT:    store float [[LD1]], ptr [[PTR1]], align 4
; CHECK-NEXT:    ret void
;
  %ptr0 = getelementptr float, ptr %ptr, i32 0
  %ptr1 = getelementptr float, ptr %ptr, i32 1
  %ld0 = load float, ptr %ptr0
  %ld1 = load float, ptr %ptr1
  store float %ld1, ptr %ptr1
  call void @foo() ; This call blocks scheduling of the store seeds.
  store float %ld1, ptr %ptr1
  ret void
}

define void @pack_vectors(ptr %ptr, ptr %ptr2) {
; CHECK-LABEL: define void @pack_vectors(
; CHECK-SAME: ptr [[PTR:%.*]], ptr [[PTR2:%.*]]) {
; CHECK-NEXT:    [[PTR0:%.*]] = getelementptr <2 x float>, ptr [[PTR]], i32 0
; CHECK-NEXT:    [[LD0:%.*]] = load <2 x float>, ptr [[PTR0]], align 8
; CHECK-NEXT:    [[LD1:%.*]] = load float, ptr [[PTR2]], align 4
; CHECK-NEXT:    [[VPACK:%.*]] = extractelement <2 x float> [[LD0]], i32 0
; CHECK-NEXT:    [[VPACK1:%.*]] = insertelement <3 x float> poison, float [[VPACK]], i32 0
; CHECK-NEXT:    [[VPACK2:%.*]] = extractelement <2 x float> [[LD0]], i32 1
; CHECK-NEXT:    [[VPACK3:%.*]] = insertelement <3 x float> [[VPACK1]], float [[VPACK2]], i32 1
; CHECK-NEXT:    [[PACK:%.*]] = insertelement <3 x float> [[VPACK3]], float [[LD1]], i32 2
; CHECK-NEXT:    store <3 x float> [[PACK]], ptr [[PTR0]], align 8
; CHECK-NEXT:    ret void
;
  %ptr0 = getelementptr <2 x float>, ptr %ptr, i32 0
  %ptr1 = getelementptr float, ptr %ptr, i32 2
  %ld0 = load <2 x float>, ptr %ptr0
  %ld1 = load float, ptr %ptr2
  store <2 x float> %ld0, ptr %ptr0
  store float %ld1, ptr %ptr1
  ret void
}

define void @diamond(ptr %ptr) {
; CHECK-LABEL: define void @diamond(
; CHECK-SAME: ptr [[PTR:%.*]]) {
; CHECK-NEXT:    [[PTR0:%.*]] = getelementptr float, ptr [[PTR]], i32 0
; CHECK-NEXT:    [[VECL:%.*]] = load <2 x float>, ptr [[PTR0]], align 4
; CHECK-NEXT:    [[VEC:%.*]] = fsub <2 x float> [[VECL]], [[VECL]]
; CHECK-NEXT:    store <2 x float> [[VEC]], ptr [[PTR0]], align 4
; CHECK-NEXT:    ret void
;
  %ptr0 = getelementptr float, ptr %ptr, i32 0
  %ptr1 = getelementptr float, ptr %ptr, i32 1
  %ld0 = load float, ptr %ptr0
  %ld1 = load float, ptr %ptr1
  %sub0 = fsub float %ld0, %ld0
  %sub1 = fsub float %ld1, %ld1
  store float %sub0, ptr %ptr0
  store float %sub1, ptr %ptr1
  ret void
}

define void @diamondWithShuffle(ptr %ptr) {
; CHECK-LABEL: define void @diamondWithShuffle(
; CHECK-SAME: ptr [[PTR:%.*]]) {
; CHECK-NEXT:    [[PTR0:%.*]] = getelementptr float, ptr [[PTR]], i32 0
; CHECK-NEXT:    [[VECL:%.*]] = load <2 x float>, ptr [[PTR0]], align 4
; CHECK-NEXT:    [[VSHUF:%.*]] = shufflevector <2 x float> [[VECL]], <2 x float> [[VECL]], <2 x i32> <i32 1, i32 0>
; CHECK-NEXT:    [[VEC:%.*]] = fsub <2 x float> [[VECL]], [[VSHUF]]
; CHECK-NEXT:    store <2 x float> [[VEC]], ptr [[PTR0]], align 4
; CHECK-NEXT:    ret void
;
  %ptr0 = getelementptr float, ptr %ptr, i32 0
  %ptr1 = getelementptr float, ptr %ptr, i32 1
  %ld0 = load float, ptr %ptr0
  %ld1 = load float, ptr %ptr1
  %sub0 = fsub float %ld0, %ld1
  %sub1 = fsub float %ld1, %ld0
  store float %sub0, ptr %ptr0
  store float %sub1, ptr %ptr1
  ret void
}

; Same but with <2 x float> elements instead of scalars.
define void @diamondWithShuffleFromVec(ptr %ptr) {
; CHECK-LABEL: define void @diamondWithShuffleFromVec(
; CHECK-SAME: ptr [[PTR:%.*]]) {
; CHECK-NEXT:    [[PTR0:%.*]] = getelementptr <2 x float>, ptr [[PTR]], i32 0
; CHECK-NEXT:    [[VECL:%.*]] = load <4 x float>, ptr [[PTR0]], align 8
; CHECK-NEXT:    [[VSHUF:%.*]] = shufflevector <4 x float> [[VECL]], <4 x float> [[VECL]], <4 x i32> <i32 2, i32 3, i32 0, i32 1>
; CHECK-NEXT:    [[VEC:%.*]] = fsub <4 x float> [[VECL]], [[VSHUF]]
; CHECK-NEXT:    store <4 x float> [[VEC]], ptr [[PTR0]], align 8
; CHECK-NEXT:    ret void
;
  %ptr0 = getelementptr <2 x float>, ptr %ptr, i32 0
  %ptr1 = getelementptr <2 x float>, ptr %ptr, i32 1
  %ld0 = load <2 x float>, ptr %ptr0
  %ld1 = load <2 x float>, ptr %ptr1
  %sub0 = fsub <2 x float> %ld0, %ld1
  %sub1 = fsub <2 x float> %ld1, %ld0
  store <2 x float> %sub0, ptr %ptr0
  store <2 x float> %sub1, ptr %ptr1
  ret void
}

define void @diamondMultiInput(ptr %ptr, ptr %ptrX) {
; CHECK-LABEL: define void @diamondMultiInput(
; CHECK-SAME: ptr [[PTR:%.*]], ptr [[PTRX:%.*]]) {
; CHECK-NEXT:    [[PTR0:%.*]] = getelementptr float, ptr [[PTR]], i32 0
; CHECK-NEXT:    [[LDX:%.*]] = load float, ptr [[PTRX]], align 4
; CHECK-NEXT:    [[VECL:%.*]] = load <2 x float>, ptr [[PTR0]], align 4
; CHECK-NEXT:    [[VINS:%.*]] = insertelement <2 x float> poison, float [[LDX]], i32 0
; CHECK-NEXT:    [[VEXT:%.*]] = extractelement <2 x float> [[VECL]], i32 0
; CHECK-NEXT:    [[VINS1:%.*]] = insertelement <2 x float> [[VINS]], float [[VEXT]], i32 1
; CHECK-NEXT:    [[VEC:%.*]] = fsub <2 x float> [[VECL]], [[VINS1]]
; CHECK-NEXT:    store <2 x float> [[VEC]], ptr [[PTR0]], align 4
; CHECK-NEXT:    ret void
;
  %ptr0 = getelementptr float, ptr %ptr, i32 0
  %ptr1 = getelementptr float, ptr %ptr, i32 1
  %ld0 = load float, ptr %ptr0
  %ld1 = load float, ptr %ptr1

  %ldX = load float, ptr %ptrX

  %sub0 = fsub float %ld0, %ldX
  %sub1 = fsub float %ld1, %ld0
  store float %sub0, ptr %ptr0
  store float %sub1, ptr %ptr1
  ret void
}

; Same but vectorizing <2 x float> vectors instead of scalars.
define void @diamondMultiInputVector(ptr %ptr, ptr %ptrX) {
; CHECK-LABEL: define void @diamondMultiInputVector(
; CHECK-SAME: ptr [[PTR:%.*]], ptr [[PTRX:%.*]]) {
; CHECK-NEXT:    [[PTR0:%.*]] = getelementptr <2 x float>, ptr [[PTR]], i32 0
; CHECK-NEXT:    [[LDX:%.*]] = load <2 x float>, ptr [[PTRX]], align 8
; CHECK-NEXT:    [[VECL:%.*]] = load <4 x float>, ptr [[PTR0]], align 8
; CHECK-NEXT:    [[VEXT:%.*]] = extractelement <2 x float> [[LDX]], i32 0
; CHECK-NEXT:    [[INSI:%.*]] = insertelement <4 x float> poison, float [[VEXT]], i32 0
; CHECK-NEXT:    [[VEXT1:%.*]] = extractelement <2 x float> [[LDX]], i32 1
; CHECK-NEXT:    [[INSI2:%.*]] = insertelement <4 x float> [[INSI]], float [[VEXT1]], i32 1
; CHECK-NEXT:    [[VEXT3:%.*]] = extractelement <4 x float> [[VECL]], i32 0
; CHECK-NEXT:    [[VINS4:%.*]] = insertelement <4 x float> [[INSI2]], float [[VEXT3]], i32 2
; CHECK-NEXT:    [[VEXT4:%.*]] = extractelement <4 x float> [[VECL]], i32 1
; CHECK-NEXT:    [[VINS5:%.*]] = insertelement <4 x float> [[VINS4]], float [[VEXT4]], i32 3
; CHECK-NEXT:    [[VEC:%.*]] = fsub <4 x float> [[VECL]], [[VINS5]]
; CHECK-NEXT:    store <4 x float> [[VEC]], ptr [[PTR0]], align 8
; CHECK-NEXT:    ret void
;
  %ptr0 = getelementptr <2 x float>, ptr %ptr, i32 0
  %ptr1 = getelementptr <2 x float>, ptr %ptr, i32 1
  %ld0 = load <2 x float>, ptr %ptr0
  %ld1 = load <2 x float>, ptr %ptr1

  %ldX = load <2 x float>, ptr %ptrX

  %sub0 = fsub <2 x float> %ld0, %ldX
  %sub1 = fsub <2 x float> %ld1, %ld0
  store <2 x float> %sub0, ptr %ptr0
  store <2 x float> %sub1, ptr %ptr1
  ret void
}

define void @diamondWithConstantVector(ptr %ptr) {
; CHECK-LABEL: define void @diamondWithConstantVector(
; CHECK-SAME: ptr [[PTR:%.*]]) {
; CHECK-NEXT:    [[GEPA0:%.*]] = getelementptr i32, ptr [[PTR]], i64 0
; CHECK-NEXT:    [[GEPB0:%.*]] = getelementptr i32, ptr [[PTR]], i64 10
; CHECK-NEXT:    store <2 x i32> zeroinitializer, ptr [[GEPA0]], align 4
; CHECK-NEXT:    store <2 x i32> zeroinitializer, ptr [[GEPB0]], align 4
; CHECK-NEXT:    ret void
;
  %gepA0 = getelementptr i32, ptr %ptr, i64 0
  %gepA1 = getelementptr i32, ptr %ptr, i64 1

  %gepB0 = getelementptr i32, ptr %ptr, i64 10
  %gepB1 = getelementptr i32, ptr %ptr, i64 11

  %zext0 = zext i16 0 to i32
  %zext1 = zext i16 0 to i32

  store i32 %zext0, ptr %gepA0
  store i32 %zext1, ptr %gepA1

  %orB0 = or i32 0, %zext0
  %orB1 = or i32 0, %zext1
  store i32 %orB0, ptr %gepB0
  store i32 %orB1, ptr %gepB1
  ret void
}

; Check that we don't get def-after-use errors due to wrong placement
; of new vector instructions.
define void @vecInstrsPlacement(ptr %ptr0) {
; CHECK-LABEL: define void @vecInstrsPlacement(
; CHECK-SAME: ptr [[PTR0:%.*]]) {
; CHECK-NEXT:    [[VECL2:%.*]] = load <2 x double>, ptr [[PTR0]], align 8
; CHECK-NEXT:    [[VECL:%.*]] = load <2 x double>, ptr [[PTR0]], align 8
; CHECK-NEXT:    [[VEC2:%.*]] = fmul <2 x double> [[VECL2]], [[VECL]]
; CHECK-NEXT:    [[VEC:%.*]] = fmul <2 x double> [[VECL2]], [[VECL]]
; CHECK-NEXT:    [[VEC5:%.*]] = fadd <2 x double> [[VEC]], [[VEC2]]
; CHECK-NEXT:    store <2 x double> [[VEC5]], ptr [[PTR0]], align 8
; CHECK-NEXT:    ret void
;
  %ptr1 = getelementptr inbounds double, ptr %ptr0, i64 1
  %ldA_0 = load double, ptr %ptr0
  %ldA_1 = load double, ptr %ptr1

  %ldB_0 = load double, ptr %ptr0
  %ldB_1 = load double, ptr %ptr1

  %mul0 = fmul double %ldA_0, %ldB_0
  %mul1 = fmul double %ldA_1, %ldB_1

  %mul2 = fmul double %ldA_0, %ldB_0
  %mul3 = fmul double %ldA_1, %ldB_1

  %add0 = fadd double %mul0, %mul2
  %add1 = fadd double %mul1, %mul3

  store double %add0, ptr %ptr0
  store double %add1, ptr %ptr1
  ret void
}

; During the bottom-up traversal we form bundle {ldA0,ldA1} but later when we
; visit the RHS operands of the additions we try to form {ldA1,ldA2}
; which is not allowed.
define void @instrsInMultipleBundles(ptr noalias %ptr) {
; CHECK-LABEL: define void @instrsInMultipleBundles(
; CHECK-SAME: ptr noalias [[PTR:%.*]]) {
; CHECK-NEXT:    [[GEP0:%.*]] = getelementptr i8, ptr [[PTR]], i64 0
; CHECK-NEXT:    [[GEP2:%.*]] = getelementptr i8, ptr [[PTR]], i64 2
; CHECK-NEXT:    [[LDA2:%.*]] = load i8, ptr [[GEP2]], align 1
; CHECK-NEXT:    [[VECL:%.*]] = load <2 x i8>, ptr [[GEP0]], align 1
; CHECK-NEXT:    [[VEXT:%.*]] = extractelement <2 x i8> [[VECL]], i32 1
; CHECK-NEXT:    [[VINS:%.*]] = insertelement <2 x i8> poison, i8 [[VEXT]], i32 0
; CHECK-NEXT:    [[VINS1:%.*]] = insertelement <2 x i8> [[VINS]], i8 [[LDA2]], i32 1
; CHECK-NEXT:    [[VEC:%.*]] = add <2 x i8> [[VECL]], [[VINS1]]
; CHECK-NEXT:    store <2 x i8> [[VEC]], ptr [[GEP0]], align 1
; CHECK-NEXT:    ret void
;
  %gep0 = getelementptr i8, ptr %ptr, i64 0
  %gep1 = getelementptr i8, ptr %ptr, i64 1
  %gep2 = getelementptr i8, ptr %ptr, i64 2
  %ldA0 = load i8, ptr %gep0
  %ldA1 = load i8, ptr %gep1
  %ldA2 = load i8, ptr %gep2
  %add0 = add i8 %ldA0, %ldA1
  %add1 = add i8 %ldA1, %ldA2
  store i8 %add0, ptr %gep0
  store i8 %add1, ptr %gep1
  ret void
}

define void @vectorize_constants(ptr %ptr) {
; CHECK-LABEL: define void @vectorize_constants(
; CHECK-SAME: ptr [[PTR:%.*]]) {
; CHECK-NEXT:    [[PTR0:%.*]] = getelementptr i8, ptr [[PTR]], i32 0
; CHECK-NEXT:    [[VECL:%.*]] = load <2 x i8>, ptr [[PTR0]], align 1
; CHECK-NEXT:    [[VEC:%.*]] = add <2 x i8> [[VECL]], <i8 0, i8 1>
; CHECK-NEXT:    store <2 x i8> [[VEC]], ptr [[PTR0]], align 1
; CHECK-NEXT:    ret void
;
  %ptr0 = getelementptr i8, ptr %ptr, i32 0
  %ptr1 = getelementptr i8, ptr %ptr, i32 1
  %ld0 = load i8, ptr %ptr0
  %ld1 = load i8, ptr %ptr1
  %add0 = add i8 %ld0, 0
  %add1 = add i8 %ld1, 1
  store i8 %add0, ptr %ptr0
  store i8 %add1, ptr %ptr1
  ret void
}

define void @vectorize_constant_vectors(ptr %ptr) {
; CHECK-LABEL: define void @vectorize_constant_vectors(
; CHECK-SAME: ptr [[PTR:%.*]]) {
; CHECK-NEXT:    [[PTR0:%.*]] = getelementptr <2 x i8>, ptr [[PTR]], i32 0
; CHECK-NEXT:    [[VECL:%.*]] = load <4 x i8>, ptr [[PTR0]], align 2
; CHECK-NEXT:    [[VEC:%.*]] = sub <4 x i8> [[VECL]], <i8 0, i8 0, i8 1, i8 1>
; CHECK-NEXT:    store <4 x i8> [[VEC]], ptr [[PTR0]], align 2
; CHECK-NEXT:    ret void
;
  %ptr0 = getelementptr <2 x i8>, ptr %ptr, i32 0
  %ptr1 = getelementptr <2 x i8>, ptr %ptr, i32 1
  %ld0 = load <2 x i8>, ptr %ptr0
  %ld1 = load <2 x i8>, ptr %ptr1
  %sub0 = sub <2 x i8> %ld0, splat(i8 0)
  %sub1 = sub <2 x i8> %ld1, splat(i8 1)
  store <2 x i8> %sub0, ptr %ptr0
  store <2 x i8> %sub1, ptr %ptr1
  ret void
}
