Up until now the generation of vector instructions was taking place during the top-down post-order traversal of vectorizeRec(). The issue with this approach is that the vector instructions emitted during the traversal can be reordered by the scheduler, making it challenging to place them without breaking the def-before-uses rule. With this patch we separate the vectorization decisions (done in `vectorizeRec()`) from the code generation phase (`emitVectors()`). The vectorization decisions are stored in the `Actions` vector and are used by `emitVectors()` to drive code generation.
77 lines
3.8 KiB
LLVM
77 lines
3.8 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
|
|
|
|
; This used to crash because the newly added pack instructions would not update
|
|
; the DAG and scheduler, leading to def-after-use.
|
|
define void @check_dag_scheduler_update(ptr noalias %p, ptr noalias %p1) {
|
|
; CHECK-LABEL: define void @check_dag_scheduler_update(
|
|
; CHECK-SAME: ptr noalias [[P:%.*]], ptr noalias [[P1:%.*]]) {
|
|
; CHECK-NEXT: [[I:%.*]] = load i32, ptr [[P]], align 4
|
|
; CHECK-NEXT: [[VECL:%.*]] = load <4 x i32>, ptr [[P]], align 4
|
|
; CHECK-NEXT: [[ARRAYIDX4:%.*]] = getelementptr i32, ptr [[P]], i64 34
|
|
; CHECK-NEXT: [[I2:%.*]] = load i32, ptr [[ARRAYIDX4]], align 4
|
|
; CHECK-NEXT: [[ARRAYIDX11:%.*]] = getelementptr i32, ptr [[P]], i64 33
|
|
; CHECK-NEXT: [[I4:%.*]] = load i32, ptr [[ARRAYIDX11]], align 4
|
|
; CHECK-NEXT: [[ARRAYIDX18:%.*]] = getelementptr i32, ptr [[P]], i64 32
|
|
; CHECK-NEXT: [[I6:%.*]] = load i32, ptr [[ARRAYIDX18]], align 4
|
|
; CHECK-NEXT: [[PACK:%.*]] = insertelement <4 x i32> poison, i32 [[I]], i32 0
|
|
; CHECK-NEXT: [[PACK1:%.*]] = insertelement <4 x i32> [[PACK]], i32 [[I6]], i32 1
|
|
; CHECK-NEXT: [[PACK2:%.*]] = insertelement <4 x i32> [[PACK1]], i32 [[I4]], i32 2
|
|
; CHECK-NEXT: [[PACK3:%.*]] = insertelement <4 x i32> [[PACK2]], i32 [[I2]], i32 3
|
|
; CHECK-NEXT: [[VEC:%.*]] = add nsw <4 x i32> [[PACK3]], [[VECL]]
|
|
; CHECK-NEXT: store <4 x i32> [[VEC]], ptr [[P1]], align 4
|
|
; CHECK-NEXT: ret void
|
|
;
|
|
%i = load i32, ptr %p
|
|
%i1 = load i32, ptr %p
|
|
%add = add nsw i32 %i, %i1
|
|
store i32 %add, ptr %p1
|
|
%arrayidx4 = getelementptr i32, ptr %p, i64 32
|
|
%i2 = load i32, ptr %arrayidx4
|
|
%arrayidx6 = getelementptr i32, ptr %p, i64 1
|
|
%i3 = load i32, ptr %arrayidx6
|
|
%add7 = add nsw i32 %i2, %i3
|
|
%arrayidx9 = getelementptr i32, ptr %p1, i64 1
|
|
store i32 %add7, ptr %arrayidx9
|
|
%arrayidx11 = getelementptr i32, ptr %p, i64 33
|
|
%i4 = load i32, ptr %arrayidx11
|
|
%arrayidx13 = getelementptr i32, ptr %p, i64 2
|
|
%i5 = load i32, ptr %arrayidx13
|
|
%add14 = add nsw i32 %i4, %i5
|
|
%arrayidx16 = getelementptr i32, ptr %p1, i64 2
|
|
store i32 %add14, ptr %arrayidx16
|
|
%arrayidx18 = getelementptr i32, ptr %p, i64 34
|
|
%i6 = load i32, ptr %arrayidx18
|
|
%arrayidx19 = getelementptr i32, ptr %p, i64 3
|
|
%i7 = load i32, ptr %arrayidx19
|
|
%add21 = add nsw i32 %i6, %i7
|
|
%arrayidx23 = getelementptr i32, ptr %p1, i64 3
|
|
store i32 %add21, ptr %arrayidx23
|
|
ret void
|
|
}
|
|
|
|
; This used to generate use-before-def because of a buggy update of the
|
|
; top-of-schedule variable.
|
|
define <4 x float> @check_top_of_schedule(ptr %0) {
|
|
; CHECK-LABEL: define <4 x float> @check_top_of_schedule(
|
|
; CHECK-SAME: ptr [[TMP0:%.*]]) {
|
|
; CHECK-NEXT: [[INS_1:%.*]] = insertelement <4 x float> zeroinitializer, float poison, i64 0
|
|
; CHECK-NEXT: [[TRUNC_1:%.*]] = fptrunc double 0.000000e+00 to float
|
|
; CHECK-NEXT: [[INS_2:%.*]] = insertelement <4 x float> [[INS_1]], float [[TRUNC_1]], i64 0
|
|
; CHECK-NEXT: [[GEP_1:%.*]] = getelementptr double, ptr [[TMP0]], i64 1
|
|
; CHECK-NEXT: store <2 x double> <double 0.000000e+00, double 1.000000e+00>, ptr [[GEP_1]], align 8
|
|
; CHECK-NEXT: ret <4 x float> [[INS_2]]
|
|
;
|
|
%trunc.1 = fptrunc double 0.000000e+00 to float
|
|
%trunc.2 = fptrunc double 1.000000e+00 to float
|
|
%ins.1 = insertelement <4 x float> zeroinitializer, float poison, i64 0
|
|
%ins.2 = insertelement <4 x float> %ins.1, float %trunc.1, i64 0
|
|
%ext.1 = fpext float %trunc.1 to double
|
|
%gep.1 = getelementptr double, ptr %0, i64 1
|
|
store double %ext.1, ptr %gep.1, align 8
|
|
%ext.2 = fpext float %trunc.2 to double
|
|
%gep.2 = getelementptr double, ptr %0, i64 2
|
|
store double %ext.2, ptr %gep.2, align 8
|
|
ret <4 x float> %ins.2
|
|
}
|