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.
102 lines
4.5 KiB
LLVM
102 lines
4.5 KiB
LLVM
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6
|
|
; 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
|
|
|
|
; Checks the handling of users outside the vectorized graph.
|
|
|
|
define void @external_users(ptr %ptr) {
|
|
; CHECK-LABEL: define void @external_users(
|
|
; 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: [[VEC:%.*]] = fsub <2 x float> [[VECL]], zeroinitializer, !sandboxvec [[META0]]
|
|
; CHECK-NEXT: [[SUB0:%.*]] = extractelement <2 x float> [[VEC]], i32 0, !sandboxvec [[META0]]
|
|
; CHECK-NEXT: store <2 x float> [[VEC]], ptr [[PTR0]], align 4, !sandboxvec [[META0]]
|
|
; CHECK-NEXT: [[USER:%.*]] = fneg float [[SUB0]]
|
|
; 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, 0.0
|
|
%sub1 = fsub float %ld1, 0.0
|
|
store float %sub0, ptr %ptr0
|
|
store float %sub1, ptr %ptr1
|
|
%user = fneg float %sub0
|
|
ret void
|
|
}
|
|
|
|
; The zexts get vectorized into a constant zero-initializer so the external
|
|
; user is extracting from the constant. Such extracts though get folded.
|
|
define void @external_user_of_constant(ptr %ptr, ptr %ptrX) {
|
|
; CHECK-LABEL: define void @external_user_of_constant(
|
|
; CHECK-SAME: ptr [[PTR:%.*]], ptr [[PTRX:%.*]]) {
|
|
; CHECK-NEXT: [[PTR0:%.*]] = getelementptr float, ptr [[PTR]], i32 0
|
|
; CHECK-NEXT: store <2 x i32> zeroinitializer, ptr [[PTR0]], align 4, !sandboxvec [[META1:![0-9]+]]
|
|
; CHECK-NEXT: store i32 0, ptr [[PTRX]], align 4
|
|
; CHECK-NEXT: ret void
|
|
;
|
|
%ptr0 = getelementptr float, ptr %ptr, i32 0
|
|
%ptr1 = getelementptr float, ptr %ptr, i32 1
|
|
%zext0 = zext i16 0 to i32
|
|
%zext1 = zext i16 0 to i32
|
|
store i32 %zext0, ptr %ptr0
|
|
store i32 %zext1, ptr %ptr1
|
|
|
|
store i32 %zext0, ptr %ptrX ; External user
|
|
ret void
|
|
}
|
|
|
|
define void @vector_external_users(ptr %ptr) {
|
|
; CHECK-LABEL: define void @vector_external_users(
|
|
; CHECK-SAME: ptr [[PTR:%.*]]) {
|
|
; CHECK-NEXT: [[PTR0:%.*]] = getelementptr float, ptr [[PTR]], i32 0
|
|
; CHECK-NEXT: [[VECL:%.*]] = load <3 x float>, ptr [[PTR0]], align 4, !sandboxvec [[META2:![0-9]+]]
|
|
; CHECK-NEXT: [[VEC:%.*]] = fsub <3 x float> [[VECL]], zeroinitializer, !sandboxvec [[META2]]
|
|
; CHECK-NEXT: [[UNPACKINS2:%.*]] = shufflevector <3 x float> [[VEC]], <3 x float> poison, <2 x i32> <i32 1, i32 2>, !sandboxvec [[META2]]
|
|
; CHECK-NEXT: store <3 x float> [[VEC]], ptr [[PTR0]], align 4, !sandboxvec [[META2]]
|
|
; CHECK-NEXT: [[USER:%.*]] = fneg <2 x float> [[UNPACKINS2]]
|
|
; 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 <2 x float>, ptr %ptr1
|
|
%sub0 = fsub float %ld0, 0.0
|
|
%sub1 = fsub <2 x float> %ld1, <float 0.0, float 0.0>
|
|
store float %sub0, ptr %ptr0
|
|
store <2 x float> %sub1, ptr %ptr1
|
|
%user = fneg <2 x float> %sub1
|
|
ret void
|
|
}
|
|
|
|
define void @vector_external_users_lane_and_index_differ(ptr %ptr) {
|
|
; CHECK-LABEL: define void @vector_external_users_lane_and_index_differ(
|
|
; 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 [[META3:![0-9]+]]
|
|
; CHECK-NEXT: [[VEC:%.*]] = fsub <4 x float> [[VECL]], zeroinitializer, !sandboxvec [[META3]]
|
|
; CHECK-NEXT: [[UNPACK:%.*]] = shufflevector <4 x float> [[VEC]], <4 x float> poison, <2 x i32> <i32 2, i32 3>, !sandboxvec [[META3]]
|
|
; CHECK-NEXT: store <4 x float> [[VEC]], ptr [[PTR0]], align 8, !sandboxvec [[META3]]
|
|
; CHECK-NEXT: [[USER:%.*]] = fneg <2 x float> [[UNPACK]]
|
|
; 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, <float 0.0, float 0.0>
|
|
%sub1 = fsub <2 x float> %ld1, <float 0.0, float 0.0>
|
|
store <2 x float> %sub0, ptr %ptr0
|
|
store <2 x float> %sub1, ptr %ptr1
|
|
%user = fneg <2 x float> %sub1
|
|
ret void
|
|
}
|
|
|
|
;.
|
|
; CHECK: [[META0]] = distinct !{!"sandboxregion"}
|
|
; CHECK: [[META1]] = distinct !{!"sandboxregion"}
|
|
; CHECK: [[META2]] = distinct !{!"sandboxregion"}
|
|
; CHECK: [[META3]] = distinct !{!"sandboxregion"}
|
|
;.
|