Files
vporpo 7bfd54ac25 [SandboxVec][BottomUpVec] Improve handling of external uses (#185468)
Up until now the bottom-up vectorizer pass would not delete the scalar
instructions that have external uses after being vectorized, because it
lacked the ability to generate extracts from the vectors.
With the term "external uses", we refer to uses outside the currently
vectorized graph.

This patch fixes this. We can now properly handle external uses by
extracting from the vectors.

This change relies on the recent changes to the DAG's callbacks because
the external user may not be within the current DAG's interval.
2026-03-24 13:17:36 -07:00

792 lines
41 KiB
LLVM

; 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
; RUN: opt -passes=sandbox-vectorizer -sbvec-vec-reg-bits=1024 -sbvec-allow-non-pow2 -sbvec-passes="seed-collection<tr-save,bottom-up-vec,tr-revert>" %s -S | FileCheck %s --check-prefix REVERT
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, !sandboxvec [[META0:![0-9]+]]
; CHECK-NEXT: store <2 x float> [[VECL]], ptr [[PTR0]], align 4, !sandboxvec [[META0]]
; CHECK-NEXT: ret void
;
; REVERT-LABEL: define void @store_load(
; REVERT-SAME: ptr [[PTR:%.*]]) {
; REVERT-NEXT: [[PTR0:%.*]] = getelementptr float, ptr [[PTR]], i32 0
; REVERT-NEXT: [[PTR1:%.*]] = getelementptr float, ptr [[PTR]], i32 1, !sandboxvec [[META0:![0-9]+]]
; REVERT-NEXT: [[LD0:%.*]] = load float, ptr [[PTR0]], align 4, !sandboxvec [[META0]]
; REVERT-NEXT: [[LD1:%.*]] = load float, ptr [[PTR1]], align 4, !sandboxvec [[META0]]
; REVERT-NEXT: store float [[LD0]], ptr [[PTR0]], align 4, !sandboxvec [[META0]]
; REVERT-NEXT: store float [[LD1]], ptr [[PTR1]], align 4, !sandboxvec [[META0]]
; REVERT-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, !sandboxvec [[META1:![0-9]+]]
; CHECK-NEXT: [[VCAST:%.*]] = fpext <2 x float> [[VECL]] to <2 x double>, !sandboxvec [[META1]]
; CHECK-NEXT: store <2 x double> [[VCAST]], ptr [[PTRD0]], align 8, !sandboxvec [[META1]]
; CHECK-NEXT: ret void
;
; REVERT-LABEL: define void @store_fpext_load(
; REVERT-SAME: ptr [[PTR:%.*]]) {
; REVERT-NEXT: [[PTR0:%.*]] = getelementptr float, ptr [[PTR]], i32 0
; REVERT-NEXT: [[PTR1:%.*]] = getelementptr float, ptr [[PTR]], i32 1, !sandboxvec [[META1:![0-9]+]]
; REVERT-NEXT: [[PTRD0:%.*]] = getelementptr double, ptr [[PTR]], i32 0
; REVERT-NEXT: [[PTRD1:%.*]] = getelementptr double, ptr [[PTR]], i32 1, !sandboxvec [[META1]]
; REVERT-NEXT: [[LD0:%.*]] = load float, ptr [[PTR0]], align 4, !sandboxvec [[META1]]
; REVERT-NEXT: [[LD1:%.*]] = load float, ptr [[PTR1]], align 4, !sandboxvec [[META1]]
; REVERT-NEXT: [[FPEXT0:%.*]] = fpext float [[LD0]] to double, !sandboxvec [[META1]]
; REVERT-NEXT: [[FPEXT1:%.*]] = fpext float [[LD1]] to double, !sandboxvec [[META1]]
; REVERT-NEXT: store double [[FPEXT0]], ptr [[PTRD0]], align 8, !sandboxvec [[META1]]
; REVERT-NEXT: store double [[FPEXT1]], ptr [[PTRD1]], align 8, !sandboxvec [[META1]]
; REVERT-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, !sandboxvec [[META2:![0-9]+]]
; CHECK-NEXT: [[VECL:%.*]] = load <2 x float>, ptr [[PTR0]], align 4, !sandboxvec [[META2]]
; CHECK-NEXT: [[VCMP:%.*]] = fcmp ogt <2 x float> [[VECL]], [[VECL1]], !sandboxvec [[META2]]
; CHECK-NEXT: [[VCAST:%.*]] = zext <2 x i1> [[VCMP]] to <2 x i32>, !sandboxvec [[META2]]
; CHECK-NEXT: store <2 x i32> [[VCAST]], ptr [[PTRB0]], align 4, !sandboxvec [[META2]]
; CHECK-NEXT: ret void
;
; REVERT-LABEL: define void @store_fcmp_zext_load(
; REVERT-SAME: ptr [[PTR:%.*]]) {
; REVERT-NEXT: [[PTR0:%.*]] = getelementptr float, ptr [[PTR]], i32 0
; REVERT-NEXT: [[PTR1:%.*]] = getelementptr float, ptr [[PTR]], i32 1, !sandboxvec [[META2:![0-9]+]]
; REVERT-NEXT: [[PTRB0:%.*]] = getelementptr i32, ptr [[PTR]], i32 0
; REVERT-NEXT: [[PTRB1:%.*]] = getelementptr i32, ptr [[PTR]], i32 1, !sandboxvec [[META2]]
; REVERT-NEXT: [[LDB0:%.*]] = load float, ptr [[PTR0]], align 4, !sandboxvec [[META2]]
; REVERT-NEXT: [[LDB1:%.*]] = load float, ptr [[PTR1]], align 4, !sandboxvec [[META2]]
; REVERT-NEXT: [[LDA0:%.*]] = load float, ptr [[PTR0]], align 4, !sandboxvec [[META2]]
; REVERT-NEXT: [[LDA1:%.*]] = load float, ptr [[PTR1]], align 4, !sandboxvec [[META2]]
; REVERT-NEXT: [[FCMP0:%.*]] = fcmp ogt float [[LDA0]], [[LDB0]], !sandboxvec [[META2]]
; REVERT-NEXT: [[FCMP1:%.*]] = fcmp ogt float [[LDA1]], [[LDB1]], !sandboxvec [[META2]]
; REVERT-NEXT: [[ZEXT0:%.*]] = zext i1 [[FCMP0]] to i32, !sandboxvec [[META2]]
; REVERT-NEXT: [[ZEXT1:%.*]] = zext i1 [[FCMP1]] to i32, !sandboxvec [[META2]]
; REVERT-NEXT: store i32 [[ZEXT0]], ptr [[PTRB0]], align 4, !sandboxvec [[META2]]
; REVERT-NEXT: store i32 [[ZEXT1]], ptr [[PTRB1]], align 4, !sandboxvec [[META2]]
; REVERT-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: [[VECL1:%.*]] = load <2 x float>, ptr [[PTR0]], align 4, !sandboxvec [[META3:![0-9]+]]
; CHECK-NEXT: [[VECL:%.*]] = load <2 x float>, ptr [[PTR0]], align 4, !sandboxvec [[META3]]
; CHECK-NEXT: [[VEC:%.*]] = fadd <2 x float> [[VECL]], [[VECL1]], !sandboxvec [[META3]]
; CHECK-NEXT: store <2 x float> [[VEC]], ptr [[PTR0]], align 4, !sandboxvec [[META3]]
; CHECK-NEXT: ret void
;
; REVERT-LABEL: define void @store_fadd_load(
; REVERT-SAME: ptr [[PTR:%.*]]) {
; REVERT-NEXT: [[PTR0:%.*]] = getelementptr float, ptr [[PTR]], i32 0
; REVERT-NEXT: [[PTR1:%.*]] = getelementptr float, ptr [[PTR]], i32 1, !sandboxvec [[META3:![0-9]+]]
; REVERT-NEXT: [[LDA0:%.*]] = load float, ptr [[PTR0]], align 4, !sandboxvec [[META3]]
; REVERT-NEXT: [[LDA1:%.*]] = load float, ptr [[PTR1]], align 4, !sandboxvec [[META3]]
; REVERT-NEXT: [[LDB0:%.*]] = load float, ptr [[PTR0]], align 4, !sandboxvec [[META3]]
; REVERT-NEXT: [[LDB1:%.*]] = load float, ptr [[PTR1]], align 4, !sandboxvec [[META3]]
; REVERT-NEXT: [[FADD0:%.*]] = fadd float [[LDA0]], [[LDB0]], !sandboxvec [[META3]]
; REVERT-NEXT: [[FADD1:%.*]] = fadd float [[LDA1]], [[LDB1]], !sandboxvec [[META3]]
; REVERT-NEXT: store float [[FADD0]], ptr [[PTR0]], align 4, !sandboxvec [[META3]]
; REVERT-NEXT: store float [[FADD1]], ptr [[PTR1]], align 4, !sandboxvec [[META3]]
; REVERT-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, !sandboxvec [[META4:![0-9]+]]
; CHECK-NEXT: [[VEC:%.*]] = fneg <2 x float> [[VECL]], !sandboxvec [[META4]]
; CHECK-NEXT: store <2 x float> [[VEC]], ptr [[PTR0]], align 4, !sandboxvec [[META4]]
; CHECK-NEXT: ret void
;
; REVERT-LABEL: define void @store_fneg_load(
; REVERT-SAME: ptr [[PTR:%.*]]) {
; REVERT-NEXT: [[PTR0:%.*]] = getelementptr float, ptr [[PTR]], i32 0
; REVERT-NEXT: [[PTR1:%.*]] = getelementptr float, ptr [[PTR]], i32 1, !sandboxvec [[META4:![0-9]+]]
; REVERT-NEXT: [[LD0:%.*]] = load float, ptr [[PTR0]], align 4, !sandboxvec [[META4]]
; REVERT-NEXT: [[LD1:%.*]] = load float, ptr [[PTR1]], align 4, !sandboxvec [[META4]]
; REVERT-NEXT: [[FNEG0:%.*]] = fneg float [[LD0]], !sandboxvec [[META4]]
; REVERT-NEXT: [[FNEG1:%.*]] = fneg float [[LD1]], !sandboxvec [[META4]]
; REVERT-NEXT: store float [[FNEG0]], ptr [[PTR0]], align 4, !sandboxvec [[META4]]
; REVERT-NEXT: store float [[FNEG1]], ptr [[PTR1]], align 4, !sandboxvec [[META4]]
; REVERT-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: [[VECL:%.*]] = load <2 x float>, ptr [[PTR0]], align 4, !sandboxvec [[META5:![0-9]+]]
; CHECK-NEXT: [[LD0:%.*]] = extractelement <2 x float> [[VECL]], i32 0, !sandboxvec [[META5]]
; CHECK-NEXT: [[LD1:%.*]] = extractelement <2 x float> [[VECL]], i32 1, !sandboxvec [[META5]]
; CHECK-NEXT: store <2 x float> [[VECL]], ptr [[PTR0]], align 4, !sandboxvec [[META5]]
; CHECK-NEXT: [[USER:%.*]] = fneg float [[LD1]]
; CHECK-NEXT: ret float [[LD0]]
;
; REVERT-LABEL: define float @scalars_with_external_uses_not_dead(
; REVERT-SAME: ptr [[PTR:%.*]]) {
; REVERT-NEXT: [[PTR0:%.*]] = getelementptr float, ptr [[PTR]], i32 0
; REVERT-NEXT: [[PTR1:%.*]] = getelementptr float, ptr [[PTR]], i32 1, !sandboxvec [[META5:![0-9]+]]
; REVERT-NEXT: [[LD0:%.*]] = load float, ptr [[PTR0]], align 4, !sandboxvec [[META5]]
; REVERT-NEXT: [[LD1:%.*]] = load float, ptr [[PTR1]], align 4, !sandboxvec [[META5]]
; REVERT-NEXT: store float [[LD0]], ptr [[PTR0]], align 4, !sandboxvec [[META5]]
; REVERT-NEXT: store float [[LD1]], ptr [[PTR1]], align 4, !sandboxvec [[META5]]
; REVERT-NEXT: [[USER:%.*]] = fneg float [[LD1]]
; REVERT-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, !sandboxvec [[META6:![0-9]+]]
; CHECK-NEXT: [[PACK1:%.*]] = insertelement <2 x float> [[PACK]], float [[LD1]], i32 1, !sandboxvec [[META6]]
; CHECK-NEXT: store <2 x float> [[PACK1]], ptr [[PTR0]], align 4, !sandboxvec [[META6]]
; CHECK-NEXT: ret void
;
; REVERT-LABEL: define void @pack_scalars(
; REVERT-SAME: ptr [[PTR:%.*]], ptr [[PTR2:%.*]]) {
; REVERT-NEXT: [[PTR0:%.*]] = getelementptr float, ptr [[PTR]], i32 0
; REVERT-NEXT: [[PTR1:%.*]] = getelementptr float, ptr [[PTR]], i32 1, !sandboxvec [[META6:![0-9]+]]
; REVERT-NEXT: [[LD0:%.*]] = load float, ptr [[PTR0]], align 4
; REVERT-NEXT: [[LD1:%.*]] = load float, ptr [[PTR2]], align 4
; REVERT-NEXT: store float [[LD0]], ptr [[PTR0]], align 4, !sandboxvec [[META6]]
; REVERT-NEXT: store float [[LD1]], ptr [[PTR1]], align 4, !sandboxvec [[META6]]
; REVERT-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, !sandboxvec [[META7:![0-9]+]]
; CHECK-NEXT: call void @foo()
; CHECK-NEXT: store float [[LD1]], ptr [[PTR1]], align 4, !sandboxvec [[META7]]
; CHECK-NEXT: ret void
;
; REVERT-LABEL: define void @cant_vectorize_seeds(
; REVERT-SAME: ptr [[PTR:%.*]]) {
; REVERT-NEXT: [[PTR0:%.*]] = getelementptr float, ptr [[PTR]], i32 0
; REVERT-NEXT: [[PTR1:%.*]] = getelementptr float, ptr [[PTR]], i32 1
; REVERT-NEXT: [[LD0:%.*]] = load float, ptr [[PTR0]], align 4
; REVERT-NEXT: [[LD1:%.*]] = load float, ptr [[PTR1]], align 4
; REVERT-NEXT: store float [[LD1]], ptr [[PTR1]], align 4, !sandboxvec [[META7:![0-9]+]]
; REVERT-NEXT: call void @foo()
; REVERT-NEXT: store float [[LD1]], ptr [[PTR1]], align 4, !sandboxvec [[META7]]
; REVERT-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, !sandboxvec [[META8:![0-9]+]]
; CHECK-NEXT: [[VPACK1:%.*]] = insertelement <3 x float> poison, float [[VPACK]], i32 0, !sandboxvec [[META8]]
; CHECK-NEXT: [[VPACK2:%.*]] = extractelement <2 x float> [[LD0]], i32 1, !sandboxvec [[META8]]
; CHECK-NEXT: [[VPACK3:%.*]] = insertelement <3 x float> [[VPACK1]], float [[VPACK2]], i32 1, !sandboxvec [[META8]]
; CHECK-NEXT: [[PACK:%.*]] = insertelement <3 x float> [[VPACK3]], float [[LD1]], i32 2, !sandboxvec [[META8]]
; CHECK-NEXT: store <3 x float> [[PACK]], ptr [[PTR0]], align 8, !sandboxvec [[META8]]
; CHECK-NEXT: ret void
;
; REVERT-LABEL: define void @pack_vectors(
; REVERT-SAME: ptr [[PTR:%.*]], ptr [[PTR2:%.*]]) {
; REVERT-NEXT: [[PTR0:%.*]] = getelementptr <2 x float>, ptr [[PTR]], i32 0
; REVERT-NEXT: [[PTR1:%.*]] = getelementptr float, ptr [[PTR]], i32 2, !sandboxvec [[META8:![0-9]+]]
; REVERT-NEXT: [[LD0:%.*]] = load <2 x float>, ptr [[PTR0]], align 8
; REVERT-NEXT: [[LD1:%.*]] = load float, ptr [[PTR2]], align 4
; REVERT-NEXT: store <2 x float> [[LD0]], ptr [[PTR0]], align 8, !sandboxvec [[META8]]
; REVERT-NEXT: store float [[LD1]], ptr [[PTR1]], align 4, !sandboxvec [[META8]]
; REVERT-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, !sandboxvec [[META9:![0-9]+]]
; CHECK-NEXT: [[VEC:%.*]] = fsub <2 x float> [[VECL]], [[VECL]], !sandboxvec [[META9]]
; CHECK-NEXT: store <2 x float> [[VEC]], ptr [[PTR0]], align 4, !sandboxvec [[META9]]
; CHECK-NEXT: ret void
;
; REVERT-LABEL: define void @diamond(
; REVERT-SAME: ptr [[PTR:%.*]]) {
; REVERT-NEXT: [[PTR0:%.*]] = getelementptr float, ptr [[PTR]], i32 0
; REVERT-NEXT: [[PTR1:%.*]] = getelementptr float, ptr [[PTR]], i32 1, !sandboxvec [[META9:![0-9]+]]
; REVERT-NEXT: [[LD0:%.*]] = load float, ptr [[PTR0]], align 4, !sandboxvec [[META9]]
; REVERT-NEXT: [[LD1:%.*]] = load float, ptr [[PTR1]], align 4, !sandboxvec [[META9]]
; REVERT-NEXT: [[SUB0:%.*]] = fsub float [[LD0]], [[LD0]], !sandboxvec [[META9]]
; REVERT-NEXT: [[SUB1:%.*]] = fsub float [[LD1]], [[LD1]], !sandboxvec [[META9]]
; REVERT-NEXT: store float [[SUB0]], ptr [[PTR0]], align 4, !sandboxvec [[META9]]
; REVERT-NEXT: store float [[SUB1]], ptr [[PTR1]], align 4, !sandboxvec [[META9]]
; REVERT-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, !sandboxvec [[META10:![0-9]+]]
; CHECK-NEXT: [[VSHUF:%.*]] = shufflevector <2 x float> [[VECL]], <2 x float> [[VECL]], <2 x i32> <i32 1, i32 0>, !sandboxvec [[META10]]
; CHECK-NEXT: [[VEC:%.*]] = fsub <2 x float> [[VECL]], [[VSHUF]], !sandboxvec [[META10]]
; CHECK-NEXT: store <2 x float> [[VEC]], ptr [[PTR0]], align 4, !sandboxvec [[META10]]
; CHECK-NEXT: ret void
;
; REVERT-LABEL: define void @diamondWithShuffle(
; REVERT-SAME: ptr [[PTR:%.*]]) {
; REVERT-NEXT: [[PTR0:%.*]] = getelementptr float, ptr [[PTR]], i32 0
; REVERT-NEXT: [[PTR1:%.*]] = getelementptr float, ptr [[PTR]], i32 1, !sandboxvec [[META10:![0-9]+]]
; REVERT-NEXT: [[LD0:%.*]] = load float, ptr [[PTR0]], align 4, !sandboxvec [[META10]]
; REVERT-NEXT: [[LD1:%.*]] = load float, ptr [[PTR1]], align 4, !sandboxvec [[META10]]
; REVERT-NEXT: [[SUB0:%.*]] = fsub float [[LD0]], [[LD1]], !sandboxvec [[META10]]
; REVERT-NEXT: [[SUB1:%.*]] = fsub float [[LD1]], [[LD0]], !sandboxvec [[META10]]
; REVERT-NEXT: store float [[SUB0]], ptr [[PTR0]], align 4, !sandboxvec [[META10]]
; REVERT-NEXT: store float [[SUB1]], ptr [[PTR1]], align 4, !sandboxvec [[META10]]
; REVERT-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, !sandboxvec [[META11:![0-9]+]]
; CHECK-NEXT: [[VSHUF:%.*]] = shufflevector <4 x float> [[VECL]], <4 x float> [[VECL]], <4 x i32> <i32 2, i32 3, i32 0, i32 1>, !sandboxvec [[META11]]
; CHECK-NEXT: [[VEC:%.*]] = fsub <4 x float> [[VECL]], [[VSHUF]], !sandboxvec [[META11]]
; CHECK-NEXT: store <4 x float> [[VEC]], ptr [[PTR0]], align 8, !sandboxvec [[META11]]
; CHECK-NEXT: ret void
;
; REVERT-LABEL: define void @diamondWithShuffleFromVec(
; REVERT-SAME: ptr [[PTR:%.*]]) {
; REVERT-NEXT: [[PTR0:%.*]] = getelementptr <2 x float>, ptr [[PTR]], i32 0
; REVERT-NEXT: [[PTR1:%.*]] = getelementptr <2 x float>, ptr [[PTR]], i32 1, !sandboxvec [[META11:![0-9]+]]
; REVERT-NEXT: [[LD0:%.*]] = load <2 x float>, ptr [[PTR0]], align 8, !sandboxvec [[META11]]
; REVERT-NEXT: [[LD1:%.*]] = load <2 x float>, ptr [[PTR1]], align 8, !sandboxvec [[META11]]
; REVERT-NEXT: [[SUB0:%.*]] = fsub <2 x float> [[LD0]], [[LD1]], !sandboxvec [[META11]]
; REVERT-NEXT: [[SUB1:%.*]] = fsub <2 x float> [[LD1]], [[LD0]], !sandboxvec [[META11]]
; REVERT-NEXT: store <2 x float> [[SUB0]], ptr [[PTR0]], align 8, !sandboxvec [[META11]]
; REVERT-NEXT: store <2 x float> [[SUB1]], ptr [[PTR1]], align 8, !sandboxvec [[META11]]
; REVERT-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, !sandboxvec [[META12:![0-9]+]]
; CHECK-NEXT: [[VINS:%.*]] = insertelement <2 x float> poison, float [[LDX]], i32 0, !sandboxvec [[META12]]
; CHECK-NEXT: [[VEXT:%.*]] = extractelement <2 x float> [[VECL]], i32 0, !sandboxvec [[META12]]
; CHECK-NEXT: [[VINS1:%.*]] = insertelement <2 x float> [[VINS]], float [[VEXT]], i32 1, !sandboxvec [[META12]]
; CHECK-NEXT: [[VEC:%.*]] = fsub <2 x float> [[VECL]], [[VINS1]], !sandboxvec [[META12]]
; CHECK-NEXT: store <2 x float> [[VEC]], ptr [[PTR0]], align 4, !sandboxvec [[META12]]
; CHECK-NEXT: ret void
;
; REVERT-LABEL: define void @diamondMultiInput(
; REVERT-SAME: ptr [[PTR:%.*]], ptr [[PTRX:%.*]]) {
; REVERT-NEXT: [[PTR0:%.*]] = getelementptr float, ptr [[PTR]], i32 0
; REVERT-NEXT: [[PTR1:%.*]] = getelementptr float, ptr [[PTR]], i32 1, !sandboxvec [[META12:![0-9]+]]
; REVERT-NEXT: [[LD0:%.*]] = load float, ptr [[PTR0]], align 4, !sandboxvec [[META12]]
; REVERT-NEXT: [[LD1:%.*]] = load float, ptr [[PTR1]], align 4, !sandboxvec [[META12]]
; REVERT-NEXT: [[LDX:%.*]] = load float, ptr [[PTRX]], align 4
; REVERT-NEXT: [[SUB0:%.*]] = fsub float [[LD0]], [[LDX]], !sandboxvec [[META12]]
; REVERT-NEXT: [[SUB1:%.*]] = fsub float [[LD1]], [[LD0]], !sandboxvec [[META12]]
; REVERT-NEXT: store float [[SUB0]], ptr [[PTR0]], align 4, !sandboxvec [[META12]]
; REVERT-NEXT: store float [[SUB1]], ptr [[PTR1]], align 4, !sandboxvec [[META12]]
; REVERT-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, !sandboxvec [[META13:![0-9]+]]
; CHECK-NEXT: [[VEXT:%.*]] = extractelement <2 x float> [[LDX]], i32 0, !sandboxvec [[META13]]
; CHECK-NEXT: [[VINS:%.*]] = insertelement <4 x float> poison, float [[VEXT]], i32 0, !sandboxvec [[META13]]
; CHECK-NEXT: [[VEXT1:%.*]] = extractelement <2 x float> [[LDX]], i32 1, !sandboxvec [[META13]]
; CHECK-NEXT: [[VINS2:%.*]] = insertelement <4 x float> [[VINS]], float [[VEXT1]], i32 1, !sandboxvec [[META13]]
; CHECK-NEXT: [[VEXT3:%.*]] = extractelement <4 x float> [[VECL]], i32 0, !sandboxvec [[META13]]
; CHECK-NEXT: [[VINS4:%.*]] = insertelement <4 x float> [[VINS2]], float [[VEXT3]], i32 2, !sandboxvec [[META13]]
; CHECK-NEXT: [[VEXT5:%.*]] = extractelement <4 x float> [[VECL]], i32 1, !sandboxvec [[META13]]
; CHECK-NEXT: [[VINS6:%.*]] = insertelement <4 x float> [[VINS4]], float [[VEXT5]], i32 3, !sandboxvec [[META13]]
; CHECK-NEXT: [[VEC:%.*]] = fsub <4 x float> [[VECL]], [[VINS6]], !sandboxvec [[META13]]
; CHECK-NEXT: store <4 x float> [[VEC]], ptr [[PTR0]], align 8, !sandboxvec [[META13]]
; CHECK-NEXT: ret void
;
; REVERT-LABEL: define void @diamondMultiInputVector(
; REVERT-SAME: ptr [[PTR:%.*]], ptr [[PTRX:%.*]]) {
; REVERT-NEXT: [[PTR0:%.*]] = getelementptr <2 x float>, ptr [[PTR]], i32 0
; REVERT-NEXT: [[PTR1:%.*]] = getelementptr <2 x float>, ptr [[PTR]], i32 1, !sandboxvec [[META13:![0-9]+]]
; REVERT-NEXT: [[LD0:%.*]] = load <2 x float>, ptr [[PTR0]], align 8, !sandboxvec [[META13]]
; REVERT-NEXT: [[LD1:%.*]] = load <2 x float>, ptr [[PTR1]], align 8, !sandboxvec [[META13]]
; REVERT-NEXT: [[LDX:%.*]] = load <2 x float>, ptr [[PTRX]], align 8
; REVERT-NEXT: [[SUB0:%.*]] = fsub <2 x float> [[LD0]], [[LDX]], !sandboxvec [[META13]]
; REVERT-NEXT: [[SUB1:%.*]] = fsub <2 x float> [[LD1]], [[LD0]], !sandboxvec [[META13]]
; REVERT-NEXT: store <2 x float> [[SUB0]], ptr [[PTR0]], align 8, !sandboxvec [[META13]]
; REVERT-NEXT: store <2 x float> [[SUB1]], ptr [[PTR1]], align 8, !sandboxvec [[META13]]
; REVERT-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, !sandboxvec [[META14:![0-9]+]]
; CHECK-NEXT: store <2 x i32> zeroinitializer, ptr [[GEPB0]], align 4, !sandboxvec [[META15:![0-9]+]]
; CHECK-NEXT: ret void
;
; REVERT-LABEL: define void @diamondWithConstantVector(
; REVERT-SAME: ptr [[PTR:%.*]]) {
; REVERT-NEXT: [[GEPA0:%.*]] = getelementptr i32, ptr [[PTR]], i64 0
; REVERT-NEXT: [[GEPA1:%.*]] = getelementptr i32, ptr [[PTR]], i64 1, !sandboxvec [[META14:![0-9]+]]
; REVERT-NEXT: [[GEPB0:%.*]] = getelementptr i32, ptr [[PTR]], i64 10
; REVERT-NEXT: [[GEPB1:%.*]] = getelementptr i32, ptr [[PTR]], i64 11, !sandboxvec [[META15:![0-9]+]]
; REVERT-NEXT: [[ZEXT0:%.*]] = zext i16 0 to i32, !sandboxvec [[META14]]
; REVERT-NEXT: [[ZEXT1:%.*]] = zext i16 0 to i32, !sandboxvec [[META14]]
; REVERT-NEXT: store i32 [[ZEXT0]], ptr [[GEPA0]], align 4, !sandboxvec [[META14]]
; REVERT-NEXT: store i32 [[ZEXT1]], ptr [[GEPA1]], align 4, !sandboxvec [[META14]]
; REVERT-NEXT: [[ORB0:%.*]] = or i32 0, [[ZEXT0]], !sandboxvec [[META15]]
; REVERT-NEXT: [[ORB1:%.*]] = or i32 0, [[ZEXT1]], !sandboxvec [[META15]]
; REVERT-NEXT: store i32 [[ORB0]], ptr [[GEPB0]], align 4, !sandboxvec [[META15]]
; REVERT-NEXT: store i32 [[ORB1]], ptr [[GEPB1]], align 4, !sandboxvec [[META15]]
; REVERT-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: [[VECL:%.*]] = load <2 x double>, ptr [[PTR0]], align 8, !sandboxvec [[META16:![0-9]+]]
; CHECK-NEXT: [[VECL1:%.*]] = load <2 x double>, ptr [[PTR0]], align 8, !sandboxvec [[META16]]
; CHECK-NEXT: [[VEC2:%.*]] = fmul <2 x double> [[VECL]], [[VECL1]], !sandboxvec [[META16]]
; CHECK-NEXT: [[VEC:%.*]] = fmul <2 x double> [[VECL]], [[VECL1]], !sandboxvec [[META16]]
; CHECK-NEXT: [[VEC3:%.*]] = fadd <2 x double> [[VEC]], [[VEC2]], !sandboxvec [[META16]]
; CHECK-NEXT: store <2 x double> [[VEC3]], ptr [[PTR0]], align 8, !sandboxvec [[META16]]
; CHECK-NEXT: ret void
;
; REVERT-LABEL: define void @vecInstrsPlacement(
; REVERT-SAME: ptr [[PTR0:%.*]]) {
; REVERT-NEXT: [[PTR1:%.*]] = getelementptr inbounds double, ptr [[PTR0]], i64 1, !sandboxvec [[META16:![0-9]+]]
; REVERT-NEXT: [[LDA_0:%.*]] = load double, ptr [[PTR0]], align 8, !sandboxvec [[META16]]
; REVERT-NEXT: [[LDA_1:%.*]] = load double, ptr [[PTR1]], align 8, !sandboxvec [[META16]]
; REVERT-NEXT: [[LDB_0:%.*]] = load double, ptr [[PTR0]], align 8, !sandboxvec [[META16]]
; REVERT-NEXT: [[LDB_1:%.*]] = load double, ptr [[PTR1]], align 8, !sandboxvec [[META16]]
; REVERT-NEXT: [[MUL0:%.*]] = fmul double [[LDA_0]], [[LDB_0]], !sandboxvec [[META16]]
; REVERT-NEXT: [[MUL1:%.*]] = fmul double [[LDA_1]], [[LDB_1]], !sandboxvec [[META16]]
; REVERT-NEXT: [[MUL2:%.*]] = fmul double [[LDA_0]], [[LDB_0]], !sandboxvec [[META16]]
; REVERT-NEXT: [[MUL3:%.*]] = fmul double [[LDA_1]], [[LDB_1]], !sandboxvec [[META16]]
; REVERT-NEXT: [[ADD0:%.*]] = fadd double [[MUL0]], [[MUL2]], !sandboxvec [[META16]]
; REVERT-NEXT: [[ADD1:%.*]] = fadd double [[MUL1]], [[MUL3]], !sandboxvec [[META16]]
; REVERT-NEXT: store double [[ADD0]], ptr [[PTR0]], align 8, !sandboxvec [[META16]]
; REVERT-NEXT: store double [[ADD1]], ptr [[PTR1]], align 8, !sandboxvec [[META16]]
; REVERT-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, !sandboxvec [[META17:![0-9]+]]
; CHECK-NEXT: [[VEXT:%.*]] = extractelement <2 x i8> [[VECL]], i32 1, !sandboxvec [[META17]]
; CHECK-NEXT: [[VINS:%.*]] = insertelement <2 x i8> poison, i8 [[VEXT]], i32 0, !sandboxvec [[META17]]
; CHECK-NEXT: [[VINS1:%.*]] = insertelement <2 x i8> [[VINS]], i8 [[LDA2]], i32 1, !sandboxvec [[META17]]
; CHECK-NEXT: [[VEC:%.*]] = add <2 x i8> [[VECL]], [[VINS1]], !sandboxvec [[META17]]
; CHECK-NEXT: store <2 x i8> [[VEC]], ptr [[GEP0]], align 1, !sandboxvec [[META17]]
; CHECK-NEXT: ret void
;
; REVERT-LABEL: define void @instrsInMultipleBundles(
; REVERT-SAME: ptr noalias [[PTR:%.*]]) {
; REVERT-NEXT: [[GEP0:%.*]] = getelementptr i8, ptr [[PTR]], i64 0
; REVERT-NEXT: [[GEP1:%.*]] = getelementptr i8, ptr [[PTR]], i64 1, !sandboxvec [[META17:![0-9]+]]
; REVERT-NEXT: [[GEP2:%.*]] = getelementptr i8, ptr [[PTR]], i64 2
; REVERT-NEXT: [[LDA0:%.*]] = load i8, ptr [[GEP0]], align 1, !sandboxvec [[META17]]
; REVERT-NEXT: [[LDA1:%.*]] = load i8, ptr [[GEP1]], align 1, !sandboxvec [[META17]]
; REVERT-NEXT: [[LDA2:%.*]] = load i8, ptr [[GEP2]], align 1
; REVERT-NEXT: [[ADD0:%.*]] = add i8 [[LDA0]], [[LDA1]], !sandboxvec [[META17]]
; REVERT-NEXT: [[ADD1:%.*]] = add i8 [[LDA1]], [[LDA2]], !sandboxvec [[META17]]
; REVERT-NEXT: store i8 [[ADD0]], ptr [[GEP0]], align 1, !sandboxvec [[META17]]
; REVERT-NEXT: store i8 [[ADD1]], ptr [[GEP1]], align 1, !sandboxvec [[META17]]
; REVERT-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, !sandboxvec [[META18:![0-9]+]]
; CHECK-NEXT: [[VEC:%.*]] = add <2 x i8> [[VECL]], <i8 0, i8 1>, !sandboxvec [[META18]]
; CHECK-NEXT: store <2 x i8> [[VEC]], ptr [[PTR0]], align 1, !sandboxvec [[META18]]
; CHECK-NEXT: ret void
;
; REVERT-LABEL: define void @vectorize_constants(
; REVERT-SAME: ptr [[PTR:%.*]]) {
; REVERT-NEXT: [[PTR0:%.*]] = getelementptr i8, ptr [[PTR]], i32 0
; REVERT-NEXT: [[PTR1:%.*]] = getelementptr i8, ptr [[PTR]], i32 1, !sandboxvec [[META18:![0-9]+]]
; REVERT-NEXT: [[LD0:%.*]] = load i8, ptr [[PTR0]], align 1, !sandboxvec [[META18]]
; REVERT-NEXT: [[LD1:%.*]] = load i8, ptr [[PTR1]], align 1, !sandboxvec [[META18]]
; REVERT-NEXT: [[ADD0:%.*]] = add i8 [[LD0]], 0, !sandboxvec [[META18]]
; REVERT-NEXT: [[ADD1:%.*]] = add i8 [[LD1]], 1, !sandboxvec [[META18]]
; REVERT-NEXT: store i8 [[ADD0]], ptr [[PTR0]], align 1, !sandboxvec [[META18]]
; REVERT-NEXT: store i8 [[ADD1]], ptr [[PTR1]], align 1, !sandboxvec [[META18]]
; REVERT-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, !sandboxvec [[META19:![0-9]+]]
; CHECK-NEXT: [[VEC:%.*]] = sub <4 x i8> [[VECL]], <i8 0, i8 0, i8 1, i8 1>, !sandboxvec [[META19]]
; CHECK-NEXT: store <4 x i8> [[VEC]], ptr [[PTR0]], align 2, !sandboxvec [[META19]]
; CHECK-NEXT: ret void
;
; REVERT-LABEL: define void @vectorize_constant_vectors(
; REVERT-SAME: ptr [[PTR:%.*]]) {
; REVERT-NEXT: [[PTR0:%.*]] = getelementptr <2 x i8>, ptr [[PTR]], i32 0
; REVERT-NEXT: [[PTR1:%.*]] = getelementptr <2 x i8>, ptr [[PTR]], i32 1, !sandboxvec [[META19:![0-9]+]]
; REVERT-NEXT: [[LD0:%.*]] = load <2 x i8>, ptr [[PTR0]], align 2, !sandboxvec [[META19]]
; REVERT-NEXT: [[LD1:%.*]] = load <2 x i8>, ptr [[PTR1]], align 2, !sandboxvec [[META19]]
; REVERT-NEXT: [[SUB0:%.*]] = sub <2 x i8> [[LD0]], zeroinitializer, !sandboxvec [[META19]]
; REVERT-NEXT: [[SUB1:%.*]] = sub <2 x i8> [[LD1]], splat (i8 1), !sandboxvec [[META19]]
; REVERT-NEXT: store <2 x i8> [[SUB0]], ptr [[PTR0]], align 2, !sandboxvec [[META19]]
; REVERT-NEXT: store <2 x i8> [[SUB1]], ptr [[PTR1]], align 2, !sandboxvec [[META19]]
; REVERT-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
}
; ZExt's operands can be of different types.
define void @diff_types(ptr %ptr, ptr %ptrX, ptr %ptrY) {
; CHECK-LABEL: define void @diff_types(
; CHECK-SAME: ptr [[PTR:%.*]], ptr [[PTRX:%.*]], ptr [[PTRY:%.*]]) {
; CHECK-NEXT: [[PTR0:%.*]] = getelementptr float, ptr [[PTR]], i32 0
; CHECK-NEXT: [[LDX:%.*]] = load i16, ptr [[PTRX]], align 2
; CHECK-NEXT: [[LDY:%.*]] = load i8, ptr [[PTRY]], align 1
; CHECK-NEXT: [[CMP0:%.*]] = icmp eq i16 [[LDX]], 0
; CHECK-NEXT: [[CMP1:%.*]] = icmp eq i8 [[LDY]], 0
; CHECK-NEXT: [[PACK:%.*]] = insertelement <2 x i1> poison, i1 [[CMP0]], i32 0, !sandboxvec [[META20:![0-9]+]]
; CHECK-NEXT: [[PACK1:%.*]] = insertelement <2 x i1> [[PACK]], i1 [[CMP1]], i32 1, !sandboxvec [[META20]]
; CHECK-NEXT: [[VCAST:%.*]] = zext <2 x i1> [[PACK1]] to <2 x i32>, !sandboxvec [[META20]]
; CHECK-NEXT: store <2 x i32> [[VCAST]], ptr [[PTR0]], align 4, !sandboxvec [[META20]]
; CHECK-NEXT: ret void
;
; REVERT-LABEL: define void @diff_types(
; REVERT-SAME: ptr [[PTR:%.*]], ptr [[PTRX:%.*]], ptr [[PTRY:%.*]]) {
; REVERT-NEXT: [[PTR0:%.*]] = getelementptr float, ptr [[PTR]], i32 0
; REVERT-NEXT: [[PTR1:%.*]] = getelementptr float, ptr [[PTR]], i32 1, !sandboxvec [[META20:![0-9]+]]
; REVERT-NEXT: [[LDX:%.*]] = load i16, ptr [[PTRX]], align 2
; REVERT-NEXT: [[LDY:%.*]] = load i8, ptr [[PTRY]], align 1
; REVERT-NEXT: [[CMP0:%.*]] = icmp eq i16 [[LDX]], 0
; REVERT-NEXT: [[CMP1:%.*]] = icmp eq i8 [[LDY]], 0
; REVERT-NEXT: [[ZEXT0:%.*]] = zext i1 [[CMP0]] to i32, !sandboxvec [[META20]]
; REVERT-NEXT: [[ZEXT1:%.*]] = zext i1 [[CMP1]] to i32, !sandboxvec [[META20]]
; REVERT-NEXT: store i32 [[ZEXT0]], ptr [[PTR0]], align 4, !sandboxvec [[META20]]
; REVERT-NEXT: store i32 [[ZEXT1]], ptr [[PTR1]], align 4, !sandboxvec [[META20]]
; REVERT-NEXT: ret void
;
%ptr0 = getelementptr float, ptr %ptr, i32 0
%ptr1 = getelementptr float, ptr %ptr, i32 1
%ldX = load i16, ptr %ptrX
%ldY = load i8, ptr %ptrY
%cmp0 = icmp eq i16 %ldX, 0
%cmp1 = icmp eq i8 %ldY, 0
%zext0 = zext i1 %cmp0 to i32
%zext1 = zext i1 %cmp1 to i32
store i32 %zext0, ptr %ptr0
store i32 %zext1, ptr %ptr1
ret void
}
;.
; CHECK: [[META0]] = distinct !{!"sandboxregion"}
; CHECK: [[META1]] = distinct !{!"sandboxregion"}
; CHECK: [[META2]] = distinct !{!"sandboxregion"}
; CHECK: [[META3]] = distinct !{!"sandboxregion"}
; CHECK: [[META4]] = distinct !{!"sandboxregion"}
; CHECK: [[META5]] = distinct !{!"sandboxregion"}
; CHECK: [[META6]] = distinct !{!"sandboxregion"}
; CHECK: [[META7]] = distinct !{!"sandboxregion"}
; CHECK: [[META8]] = distinct !{!"sandboxregion"}
; CHECK: [[META9]] = distinct !{!"sandboxregion"}
; CHECK: [[META10]] = distinct !{!"sandboxregion"}
; CHECK: [[META11]] = distinct !{!"sandboxregion"}
; CHECK: [[META12]] = distinct !{!"sandboxregion"}
; CHECK: [[META13]] = distinct !{!"sandboxregion"}
; CHECK: [[META14]] = distinct !{!"sandboxregion"}
; CHECK: [[META15]] = distinct !{!"sandboxregion"}
; CHECK: [[META16]] = distinct !{!"sandboxregion"}
; CHECK: [[META17]] = distinct !{!"sandboxregion"}
; CHECK: [[META18]] = distinct !{!"sandboxregion"}
; CHECK: [[META19]] = distinct !{!"sandboxregion"}
; CHECK: [[META20]] = distinct !{!"sandboxregion"}
;.
; REVERT: [[META0]] = distinct !{!"sandboxregion"}
; REVERT: [[META1]] = distinct !{!"sandboxregion"}
; REVERT: [[META2]] = distinct !{!"sandboxregion"}
; REVERT: [[META3]] = distinct !{!"sandboxregion"}
; REVERT: [[META4]] = distinct !{!"sandboxregion"}
; REVERT: [[META5]] = distinct !{!"sandboxregion"}
; REVERT: [[META6]] = distinct !{!"sandboxregion"}
; REVERT: [[META7]] = distinct !{!"sandboxregion"}
; REVERT: [[META8]] = distinct !{!"sandboxregion"}
; REVERT: [[META9]] = distinct !{!"sandboxregion"}
; REVERT: [[META10]] = distinct !{!"sandboxregion"}
; REVERT: [[META11]] = distinct !{!"sandboxregion"}
; REVERT: [[META12]] = distinct !{!"sandboxregion"}
; REVERT: [[META13]] = distinct !{!"sandboxregion"}
; REVERT: [[META14]] = distinct !{!"sandboxregion"}
; REVERT: [[META15]] = distinct !{!"sandboxregion"}
; REVERT: [[META16]] = distinct !{!"sandboxregion"}
; REVERT: [[META17]] = distinct !{!"sandboxregion"}
; REVERT: [[META18]] = distinct !{!"sandboxregion"}
; REVERT: [[META19]] = distinct !{!"sandboxregion"}
; REVERT: [[META20]] = distinct !{!"sandboxregion"}
;.