Alexey Bataev 69332bb899
[SLP]Improve/fix subvectors in gather/buildvector nodes handling
SLP vectorizer has an estimation for gather/buildvector nodes, which
contain some scalar loads. SLP vectorizer performs pretty similar (but
large in SLOCs) estimation, which not always correct. Instead, this
patch implements clustering analysis and actual node allocation with the
full analysis for the vectorized clustered scalars (not only loads, but
also some other instructions) with the correct cost estimation and
vector insert instructions. Improves overall vectorization quality and
simplifies analysis/estimations.

Reviewers: RKSimon

Reviewed By: RKSimon

Pull Request: https://github.com/llvm/llvm-project/pull/104144
2024-08-22 11:24:08 -04:00

427 lines
22 KiB
LLVM

; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
; RUN: opt < %s -passes=slp-vectorizer -S | FileCheck %s
target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
target triple = "x86_64-unknown-linux-gnu"
@b = common global [4 x i32] zeroinitializer, align 16
@c = common global [4 x i32] zeroinitializer, align 16
@d = common global [4 x i32] zeroinitializer, align 16
@e = common global [4 x i32] zeroinitializer, align 16
@a = common global [4 x i32] zeroinitializer, align 16
@fb = common global [4 x float] zeroinitializer, align 16
@fc = common global [4 x float] zeroinitializer, align 16
@fa = common global [4 x float] zeroinitializer, align 16
@fd = common global [4 x float] zeroinitializer, align 16
; Function Attrs: nounwind uwtable
define void @addsub() #0 {
; CHECK-LABEL: @addsub(
; CHECK-NEXT: entry:
; CHECK-NEXT: [[TMP0:%.*]] = load <4 x i32>, ptr @b, align 4
; CHECK-NEXT: [[TMP1:%.*]] = load <4 x i32>, ptr @c, align 4
; CHECK-NEXT: [[TMP2:%.*]] = add nsw <4 x i32> [[TMP0]], [[TMP1]]
; CHECK-NEXT: [[TMP3:%.*]] = load <4 x i32>, ptr @d, align 4
; CHECK-NEXT: [[TMP4:%.*]] = load <4 x i32>, ptr @e, align 4
; CHECK-NEXT: [[TMP5:%.*]] = add nsw <4 x i32> [[TMP3]], [[TMP4]]
; CHECK-NEXT: [[TMP6:%.*]] = add nsw <4 x i32> [[TMP2]], [[TMP5]]
; CHECK-NEXT: [[TMP7:%.*]] = sub nsw <4 x i32> [[TMP2]], [[TMP5]]
; CHECK-NEXT: [[TMP8:%.*]] = shufflevector <4 x i32> [[TMP6]], <4 x i32> [[TMP7]], <4 x i32> <i32 0, i32 5, i32 2, i32 7>
; CHECK-NEXT: store <4 x i32> [[TMP8]], ptr @a, align 4
; CHECK-NEXT: ret void
;
entry:
%0 = load i32, ptr @b, align 4
%1 = load i32, ptr @c, align 4
%add = add nsw i32 %0, %1
%2 = load i32, ptr @d, align 4
%3 = load i32, ptr @e, align 4
%add1 = add nsw i32 %2, %3
%add2 = add nsw i32 %add, %add1
store i32 %add2, ptr @a, align 4
%4 = load i32, ptr getelementptr inbounds ([4 x i32], ptr @b, i32 0, i64 1), align 4
%5 = load i32, ptr getelementptr inbounds ([4 x i32], ptr @c, i32 0, i64 1), align 4
%add3 = add nsw i32 %4, %5
%6 = load i32, ptr getelementptr inbounds ([4 x i32], ptr @d, i32 0, i64 1), align 4
%7 = load i32, ptr getelementptr inbounds ([4 x i32], ptr @e, i32 0, i64 1), align 4
%add4 = add nsw i32 %6, %7
%sub = sub nsw i32 %add3, %add4
store i32 %sub, ptr getelementptr inbounds ([4 x i32], ptr @a, i32 0, i64 1), align 4
%8 = load i32, ptr getelementptr inbounds ([4 x i32], ptr @b, i32 0, i64 2), align 4
%9 = load i32, ptr getelementptr inbounds ([4 x i32], ptr @c, i32 0, i64 2), align 4
%add5 = add nsw i32 %8, %9
%10 = load i32, ptr getelementptr inbounds ([4 x i32], ptr @d, i32 0, i64 2), align 4
%11 = load i32, ptr getelementptr inbounds ([4 x i32], ptr @e, i32 0, i64 2), align 4
%add6 = add nsw i32 %10, %11
%add7 = add nsw i32 %add5, %add6
store i32 %add7, ptr getelementptr inbounds ([4 x i32], ptr @a, i32 0, i64 2), align 4
%12 = load i32, ptr getelementptr inbounds ([4 x i32], ptr @b, i32 0, i64 3), align 4
%13 = load i32, ptr getelementptr inbounds ([4 x i32], ptr @c, i32 0, i64 3), align 4
%add8 = add nsw i32 %12, %13
%14 = load i32, ptr getelementptr inbounds ([4 x i32], ptr @d, i32 0, i64 3), align 4
%15 = load i32, ptr getelementptr inbounds ([4 x i32], ptr @e, i32 0, i64 3), align 4
%add9 = add nsw i32 %14, %15
%sub10 = sub nsw i32 %add8, %add9
store i32 %sub10, ptr getelementptr inbounds ([4 x i32], ptr @a, i32 0, i64 3), align 4
ret void
}
define void @addsub_freeze() #0 {
; CHECK-LABEL: @addsub_freeze(
; CHECK-NEXT: entry:
; CHECK-NEXT: [[TMP0:%.*]] = load <4 x i32>, ptr @b, align 4
; CHECK-NEXT: [[TMP1:%.*]] = load <4 x i32>, ptr @c, align 4
; CHECK-NEXT: [[TMP2:%.*]] = add nsw <4 x i32> [[TMP0]], [[TMP1]]
; CHECK-NEXT: [[TMP3:%.*]] = load <4 x i32>, ptr @d, align 4
; CHECK-NEXT: [[TMP4:%.*]] = load <4 x i32>, ptr @e, align 4
; CHECK-NEXT: [[TMP5:%.*]] = add nsw <4 x i32> [[TMP3]], [[TMP4]]
; CHECK-NEXT: [[TMP6:%.*]] = add nsw <4 x i32> [[TMP2]], [[TMP5]]
; CHECK-NEXT: [[TMP7:%.*]] = sub nsw <4 x i32> [[TMP2]], [[TMP5]]
; CHECK-NEXT: [[TMP8:%.*]] = shufflevector <4 x i32> [[TMP6]], <4 x i32> [[TMP7]], <4 x i32> <i32 0, i32 5, i32 2, i32 7>
; CHECK-NEXT: [[TMP9:%.*]] = freeze <4 x i32> [[TMP8]]
; CHECK-NEXT: store <4 x i32> [[TMP9]], ptr @a, align 4
; CHECK-NEXT: ret void
;
entry:
%0 = load i32, ptr @b, align 4
%1 = load i32, ptr @c, align 4
%add = add nsw i32 %0, %1
%2 = load i32, ptr @d, align 4
%3 = load i32, ptr @e, align 4
%add1 = add nsw i32 %2, %3
%add2 = add nsw i32 %add, %add1
%freeze.add2 = freeze i32 %add2
store i32 %freeze.add2, ptr @a, align 4
%4 = load i32, ptr getelementptr inbounds ([4 x i32], ptr @b, i32 0, i64 1), align 4
%5 = load i32, ptr getelementptr inbounds ([4 x i32], ptr @c, i32 0, i64 1), align 4
%add3 = add nsw i32 %4, %5
%6 = load i32, ptr getelementptr inbounds ([4 x i32], ptr @d, i32 0, i64 1), align 4
%7 = load i32, ptr getelementptr inbounds ([4 x i32], ptr @e, i32 0, i64 1), align 4
%add4 = add nsw i32 %6, %7
%sub = sub nsw i32 %add3, %add4
%freeze.sub = freeze i32 %sub
store i32 %freeze.sub, ptr getelementptr inbounds ([4 x i32], ptr @a, i32 0, i64 1), align 4
%8 = load i32, ptr getelementptr inbounds ([4 x i32], ptr @b, i32 0, i64 2), align 4
%9 = load i32, ptr getelementptr inbounds ([4 x i32], ptr @c, i32 0, i64 2), align 4
%add5 = add nsw i32 %8, %9
%10 = load i32, ptr getelementptr inbounds ([4 x i32], ptr @d, i32 0, i64 2), align 4
%11 = load i32, ptr getelementptr inbounds ([4 x i32], ptr @e, i32 0, i64 2), align 4
%add6 = add nsw i32 %10, %11
%add7 = add nsw i32 %add5, %add6
%freeze.add7 = freeze i32 %add7
store i32 %freeze.add7, ptr getelementptr inbounds ([4 x i32], ptr @a, i32 0, i64 2), align 4
%12 = load i32, ptr getelementptr inbounds ([4 x i32], ptr @b, i32 0, i64 3), align 4
%13 = load i32, ptr getelementptr inbounds ([4 x i32], ptr @c, i32 0, i64 3), align 4
%add8 = add nsw i32 %12, %13
%14 = load i32, ptr getelementptr inbounds ([4 x i32], ptr @d, i32 0, i64 3), align 4
%15 = load i32, ptr getelementptr inbounds ([4 x i32], ptr @e, i32 0, i64 3), align 4
%add9 = add nsw i32 %14, %15
%sub10 = sub nsw i32 %add8, %add9
%freeze.sub10 = freeze i32 %sub10
store i32 %freeze.sub10, ptr getelementptr inbounds ([4 x i32], ptr @a, i32 0, i64 3), align 4
ret void
}
; Function Attrs: nounwind uwtable
define void @subadd() #0 {
; CHECK-LABEL: @subadd(
; CHECK-NEXT: entry:
; CHECK-NEXT: [[TMP0:%.*]] = load <4 x i32>, ptr @b, align 4
; CHECK-NEXT: [[TMP1:%.*]] = load <4 x i32>, ptr @c, align 4
; CHECK-NEXT: [[TMP2:%.*]] = add nsw <4 x i32> [[TMP0]], [[TMP1]]
; CHECK-NEXT: [[TMP3:%.*]] = load <4 x i32>, ptr @d, align 4
; CHECK-NEXT: [[TMP4:%.*]] = load <4 x i32>, ptr @e, align 4
; CHECK-NEXT: [[TMP5:%.*]] = add nsw <4 x i32> [[TMP3]], [[TMP4]]
; CHECK-NEXT: [[TMP6:%.*]] = sub nsw <4 x i32> [[TMP2]], [[TMP5]]
; CHECK-NEXT: [[TMP7:%.*]] = add nsw <4 x i32> [[TMP2]], [[TMP5]]
; CHECK-NEXT: [[TMP8:%.*]] = shufflevector <4 x i32> [[TMP6]], <4 x i32> [[TMP7]], <4 x i32> <i32 0, i32 5, i32 2, i32 7>
; CHECK-NEXT: store <4 x i32> [[TMP8]], ptr @a, align 4
; CHECK-NEXT: ret void
;
entry:
%0 = load i32, ptr @b, align 4
%1 = load i32, ptr @c, align 4
%add = add nsw i32 %0, %1
%2 = load i32, ptr @d, align 4
%3 = load i32, ptr @e, align 4
%add1 = add nsw i32 %2, %3
%sub = sub nsw i32 %add, %add1
store i32 %sub, ptr @a, align 4
%4 = load i32, ptr getelementptr inbounds ([4 x i32], ptr @b, i32 0, i64 1), align 4
%5 = load i32, ptr getelementptr inbounds ([4 x i32], ptr @c, i32 0, i64 1), align 4
%add2 = add nsw i32 %4, %5
%6 = load i32, ptr getelementptr inbounds ([4 x i32], ptr @d, i32 0, i64 1), align 4
%7 = load i32, ptr getelementptr inbounds ([4 x i32], ptr @e, i32 0, i64 1), align 4
%add3 = add nsw i32 %6, %7
%add4 = add nsw i32 %add2, %add3
store i32 %add4, ptr getelementptr inbounds ([4 x i32], ptr @a, i32 0, i64 1), align 4
%8 = load i32, ptr getelementptr inbounds ([4 x i32], ptr @b, i32 0, i64 2), align 4
%9 = load i32, ptr getelementptr inbounds ([4 x i32], ptr @c, i32 0, i64 2), align 4
%add5 = add nsw i32 %8, %9
%10 = load i32, ptr getelementptr inbounds ([4 x i32], ptr @d, i32 0, i64 2), align 4
%11 = load i32, ptr getelementptr inbounds ([4 x i32], ptr @e, i32 0, i64 2), align 4
%add6 = add nsw i32 %10, %11
%sub7 = sub nsw i32 %add5, %add6
store i32 %sub7, ptr getelementptr inbounds ([4 x i32], ptr @a, i32 0, i64 2), align 4
%12 = load i32, ptr getelementptr inbounds ([4 x i32], ptr @b, i32 0, i64 3), align 4
%13 = load i32, ptr getelementptr inbounds ([4 x i32], ptr @c, i32 0, i64 3), align 4
%add8 = add nsw i32 %12, %13
%14 = load i32, ptr getelementptr inbounds ([4 x i32], ptr @d, i32 0, i64 3), align 4
%15 = load i32, ptr getelementptr inbounds ([4 x i32], ptr @e, i32 0, i64 3), align 4
%add9 = add nsw i32 %14, %15
%add10 = add nsw i32 %add8, %add9
store i32 %add10, ptr getelementptr inbounds ([4 x i32], ptr @a, i32 0, i64 3), align 4
ret void
}
; Function Attrs: nounwind uwtable
define void @faddfsub() #0 {
; CHECK-LABEL: @faddfsub(
; CHECK-NEXT: entry:
; CHECK-NEXT: [[TMP0:%.*]] = load <4 x float>, ptr @fb, align 4
; CHECK-NEXT: [[TMP1:%.*]] = load <4 x float>, ptr @fc, align 4
; CHECK-NEXT: [[TMP2:%.*]] = fadd <4 x float> [[TMP0]], [[TMP1]]
; CHECK-NEXT: [[TMP3:%.*]] = fsub <4 x float> [[TMP0]], [[TMP1]]
; CHECK-NEXT: [[TMP4:%.*]] = shufflevector <4 x float> [[TMP2]], <4 x float> [[TMP3]], <4 x i32> <i32 0, i32 5, i32 2, i32 7>
; CHECK-NEXT: store <4 x float> [[TMP4]], ptr @fa, align 4
; CHECK-NEXT: ret void
;
entry:
%0 = load float, ptr @fb, align 4
%1 = load float, ptr @fc, align 4
%add = fadd float %0, %1
store float %add, ptr @fa, align 4
%2 = load float, ptr getelementptr inbounds ([4 x float], ptr @fb, i32 0, i64 1), align 4
%3 = load float, ptr getelementptr inbounds ([4 x float], ptr @fc, i32 0, i64 1), align 4
%sub = fsub float %2, %3
store float %sub, ptr getelementptr inbounds ([4 x float], ptr @fa, i32 0, i64 1), align 4
%4 = load float, ptr getelementptr inbounds ([4 x float], ptr @fb, i32 0, i64 2), align 4
%5 = load float, ptr getelementptr inbounds ([4 x float], ptr @fc, i32 0, i64 2), align 4
%add1 = fadd float %4, %5
store float %add1, ptr getelementptr inbounds ([4 x float], ptr @fa, i32 0, i64 2), align 4
%6 = load float, ptr getelementptr inbounds ([4 x float], ptr @fb, i32 0, i64 3), align 4
%7 = load float, ptr getelementptr inbounds ([4 x float], ptr @fc, i32 0, i64 3), align 4
%sub2 = fsub float %6, %7
store float %sub2, ptr getelementptr inbounds ([4 x float], ptr @fa, i32 0, i64 3), align 4
ret void
}
; Function Attrs: nounwind uwtable
define void @fsubfadd() #0 {
; CHECK-LABEL: @fsubfadd(
; CHECK-NEXT: entry:
; CHECK-NEXT: [[TMP0:%.*]] = load <4 x float>, ptr @fb, align 4
; CHECK-NEXT: [[TMP1:%.*]] = load <4 x float>, ptr @fc, align 4
; CHECK-NEXT: [[TMP2:%.*]] = fsub <4 x float> [[TMP0]], [[TMP1]]
; CHECK-NEXT: [[TMP3:%.*]] = fadd <4 x float> [[TMP0]], [[TMP1]]
; CHECK-NEXT: [[TMP4:%.*]] = shufflevector <4 x float> [[TMP2]], <4 x float> [[TMP3]], <4 x i32> <i32 0, i32 5, i32 2, i32 7>
; CHECK-NEXT: store <4 x float> [[TMP4]], ptr @fa, align 4
; CHECK-NEXT: ret void
;
entry:
%0 = load float, ptr @fb, align 4
%1 = load float, ptr @fc, align 4
%sub = fsub float %0, %1
store float %sub, ptr @fa, align 4
%2 = load float, ptr getelementptr inbounds ([4 x float], ptr @fb, i32 0, i64 1), align 4
%3 = load float, ptr getelementptr inbounds ([4 x float], ptr @fc, i32 0, i64 1), align 4
%add = fadd float %2, %3
store float %add, ptr getelementptr inbounds ([4 x float], ptr @fa, i32 0, i64 1), align 4
%4 = load float, ptr getelementptr inbounds ([4 x float], ptr @fb, i32 0, i64 2), align 4
%5 = load float, ptr getelementptr inbounds ([4 x float], ptr @fc, i32 0, i64 2), align 4
%sub1 = fsub float %4, %5
store float %sub1, ptr getelementptr inbounds ([4 x float], ptr @fa, i32 0, i64 2), align 4
%6 = load float, ptr getelementptr inbounds ([4 x float], ptr @fb, i32 0, i64 3), align 4
%7 = load float, ptr getelementptr inbounds ([4 x float], ptr @fc, i32 0, i64 3), align 4
%add2 = fadd float %6, %7
store float %add2, ptr getelementptr inbounds ([4 x float], ptr @fa, i32 0, i64 3), align 4
ret void
}
; Function Attrs: nounwind uwtable
define void @faddfsub_select() #0 {
; CHECK-LABEL: @faddfsub_select(
; CHECK-NEXT: entry:
; CHECK-NEXT: [[TMP0:%.*]] = load <4 x float>, ptr @fb, align 4
; CHECK-NEXT: [[TMP1:%.*]] = load <4 x float>, ptr @fc, align 4
; CHECK-NEXT: [[TMP2:%.*]] = fadd <4 x float> [[TMP0]], [[TMP1]]
; CHECK-NEXT: [[TMP3:%.*]] = fsub <4 x float> [[TMP0]], [[TMP1]]
; CHECK-NEXT: [[TMP4:%.*]] = shufflevector <4 x float> [[TMP2]], <4 x float> [[TMP3]], <4 x i32> <i32 0, i32 1, i32 2, i32 7>
; CHECK-NEXT: store <4 x float> [[TMP4]], ptr @fa, align 4
; CHECK-NEXT: ret void
;
entry:
%0 = load float, ptr @fb, align 4
%1 = load float, ptr @fc, align 4
%add = fadd float %0, %1
store float %add, ptr @fa, align 4
%2 = load float, ptr getelementptr inbounds ([4 x float], ptr @fb, i32 0, i64 1), align 4
%3 = load float, ptr getelementptr inbounds ([4 x float], ptr @fc, i32 0, i64 1), align 4
%add1 = fadd float %2, %3
store float %add1, ptr getelementptr inbounds ([4 x float], ptr @fa, i32 0, i64 1), align 4
%4 = load float, ptr getelementptr inbounds ([4 x float], ptr @fb, i32 0, i64 2), align 4
%5 = load float, ptr getelementptr inbounds ([4 x float], ptr @fc, i32 0, i64 2), align 4
%add2 = fadd float %4, %5
store float %add2, ptr getelementptr inbounds ([4 x float], ptr @fa, i32 0, i64 2), align 4
%6 = load float, ptr getelementptr inbounds ([4 x float], ptr @fb, i32 0, i64 3), align 4
%7 = load float, ptr getelementptr inbounds ([4 x float], ptr @fc, i32 0, i64 3), align 4
%sub = fsub float %6, %7
store float %sub, ptr getelementptr inbounds ([4 x float], ptr @fa, i32 0, i64 3), align 4
ret void
}
; Check vectorization of following code for float data type-
; fc[0] = fb[0]+fa[0]; //swapped fb and fa
; fc[1] = fa[1]-fb[1];
; fc[2] = fa[2]+fb[2];
; fc[3] = fa[3]-fb[3];
define void @reorder_alt() #0 {
; CHECK-LABEL: @reorder_alt(
; CHECK-NEXT: [[TMP1:%.*]] = load <4 x float>, ptr @fa, align 4
; CHECK-NEXT: [[TMP2:%.*]] = load <4 x float>, ptr @fb, align 4
; CHECK-NEXT: [[TMP3:%.*]] = fadd <4 x float> [[TMP1]], [[TMP2]]
; CHECK-NEXT: [[TMP4:%.*]] = fsub <4 x float> [[TMP1]], [[TMP2]]
; CHECK-NEXT: [[TMP5:%.*]] = shufflevector <4 x float> [[TMP3]], <4 x float> [[TMP4]], <4 x i32> <i32 0, i32 5, i32 2, i32 7>
; CHECK-NEXT: store <4 x float> [[TMP5]], ptr @fc, align 4
; CHECK-NEXT: ret void
;
%1 = load float, ptr @fb, align 4
%2 = load float, ptr @fa, align 4
%3 = fadd float %1, %2
store float %3, ptr @fc, align 4
%4 = load float, ptr getelementptr inbounds ([4 x float], ptr @fa, i32 0, i64 1), align 4
%5 = load float, ptr getelementptr inbounds ([4 x float], ptr @fb, i32 0, i64 1), align 4
%6 = fsub float %4, %5
store float %6, ptr getelementptr inbounds ([4 x float], ptr @fc, i32 0, i64 1), align 4
%7 = load float, ptr getelementptr inbounds ([4 x float], ptr @fa, i32 0, i64 2), align 4
%8 = load float, ptr getelementptr inbounds ([4 x float], ptr @fb, i32 0, i64 2), align 4
%9 = fadd float %7, %8
store float %9, ptr getelementptr inbounds ([4 x float], ptr @fc, i32 0, i64 2), align 4
%10 = load float, ptr getelementptr inbounds ([4 x float], ptr @fa, i32 0, i64 3), align 4
%11 = load float, ptr getelementptr inbounds ([4 x float], ptr @fb, i32 0, i64 3), align 4
%12 = fsub float %10, %11
store float %12, ptr getelementptr inbounds ([4 x float], ptr @fc, i32 0, i64 3), align 4
ret void
}
; Check vectorization of following code for float data type-
; fc[0] = fa[0]+(fb[0]-fd[0]);
; fc[1] = fa[1]-(fb[1]+fd[1]);
; fc[2] = fa[2]+(fb[2]-fd[2]);
; fc[3] = fa[3]-(fd[3]+fb[3]); //swapped fd and fb
define void @reorder_alt_subTree() #0 {
; CHECK-LABEL: @reorder_alt_subTree(
; CHECK-NEXT: [[TMP1:%.*]] = load <4 x float>, ptr @fa, align 4
; CHECK-NEXT: [[TMP2:%.*]] = load <4 x float>, ptr @fd, align 4
; CHECK-NEXT: [[TMP3:%.*]] = load <4 x float>, ptr @fb, align 4
; CHECK-NEXT: [[TMP4:%.*]] = fsub <4 x float> [[TMP3]], [[TMP2]]
; CHECK-NEXT: [[TMP5:%.*]] = fadd <4 x float> [[TMP3]], [[TMP2]]
; CHECK-NEXT: [[TMP6:%.*]] = shufflevector <4 x float> [[TMP4]], <4 x float> [[TMP5]], <4 x i32> <i32 0, i32 5, i32 2, i32 7>
; CHECK-NEXT: [[TMP7:%.*]] = fadd <4 x float> [[TMP1]], [[TMP6]]
; CHECK-NEXT: [[TMP8:%.*]] = fsub <4 x float> [[TMP1]], [[TMP6]]
; CHECK-NEXT: [[TMP9:%.*]] = shufflevector <4 x float> [[TMP7]], <4 x float> [[TMP8]], <4 x i32> <i32 0, i32 5, i32 2, i32 7>
; CHECK-NEXT: store <4 x float> [[TMP9]], ptr @fc, align 4
; CHECK-NEXT: ret void
;
%1 = load float, ptr @fa, align 4
%2 = load float, ptr @fb, align 4
%3 = load float, ptr @fd, align 4
%4 = fsub float %2, %3
%5 = fadd float %1, %4
store float %5, ptr @fc, align 4
%6 = load float, ptr getelementptr inbounds ([4 x float], ptr @fa, i32 0, i64 1), align 4
%7 = load float, ptr getelementptr inbounds ([4 x float], ptr @fb, i32 0, i64 1), align 4
%8 = load float, ptr getelementptr inbounds ([4 x float], ptr @fd, i32 0, i64 1), align 4
%9 = fadd float %7, %8
%10 = fsub float %6, %9
store float %10, ptr getelementptr inbounds ([4 x float], ptr @fc, i32 0, i64 1), align 4
%11 = load float, ptr getelementptr inbounds ([4 x float], ptr @fa, i32 0, i64 2), align 4
%12 = load float, ptr getelementptr inbounds ([4 x float], ptr @fb, i32 0, i64 2), align 4
%13 = load float, ptr getelementptr inbounds ([4 x float], ptr @fd, i32 0, i64 2), align 4
%14 = fsub float %12, %13
%15 = fadd float %11, %14
store float %15, ptr getelementptr inbounds ([4 x float], ptr @fc, i32 0, i64 2), align 4
%16 = load float, ptr getelementptr inbounds ([4 x float], ptr @fa, i32 0, i64 3), align 4
%17 = load float, ptr getelementptr inbounds ([4 x float], ptr @fd, i32 0, i64 3), align 4
%18 = load float, ptr getelementptr inbounds ([4 x float], ptr @fb, i32 0, i64 3), align 4
%19 = fadd float %17, %18
%20 = fsub float %16, %19
store float %20, ptr getelementptr inbounds ([4 x float], ptr @fc, i32 0, i64 3), align 4
ret void
}
; Check vectorization of following code for double data type-
; c[0] = (a[0]+b[0])-d[0];
; c[1] = d[1]+(a[1]+b[1]); //swapped d[1] and (a[1]+b[1])
define void @reorder_alt_rightsubTree(ptr nocapture %c, ptr noalias nocapture readonly %a, ptr noalias nocapture readonly %b, ptr noalias nocapture readonly %d) {
; CHECK-LABEL: @reorder_alt_rightsubTree(
; CHECK-NEXT: [[TMP1:%.*]] = load <2 x double>, ptr [[D:%.*]], align 8
; CHECK-NEXT: [[TMP2:%.*]] = load <2 x double>, ptr [[A:%.*]], align 8
; CHECK-NEXT: [[TMP3:%.*]] = load <2 x double>, ptr [[B:%.*]], align 8
; CHECK-NEXT: [[TMP4:%.*]] = fadd <2 x double> [[TMP2]], [[TMP3]]
; CHECK-NEXT: [[TMP5:%.*]] = fsub <2 x double> [[TMP4]], [[TMP1]]
; CHECK-NEXT: [[TMP6:%.*]] = fadd <2 x double> [[TMP4]], [[TMP1]]
; CHECK-NEXT: [[TMP7:%.*]] = shufflevector <2 x double> [[TMP5]], <2 x double> [[TMP6]], <2 x i32> <i32 0, i32 3>
; CHECK-NEXT: store <2 x double> [[TMP7]], ptr [[C:%.*]], align 8
; CHECK-NEXT: ret void
;
%1 = load double, ptr %a
%2 = load double, ptr %b
%3 = fadd double %1, %2
%4 = load double, ptr %d
%5 = fsub double %3, %4
store double %5, ptr %c
%6 = getelementptr inbounds double, ptr %d, i64 1
%7 = load double, ptr %6
%8 = getelementptr inbounds double, ptr %a, i64 1
%9 = load double, ptr %8
%10 = getelementptr inbounds double, ptr %b, i64 1
%11 = load double, ptr %10
%12 = fadd double %9, %11
%13 = fadd double %7, %12
%14 = getelementptr inbounds double, ptr %c, i64 1
store double %13, ptr %14
ret void
}
define void @vec_shuff_reorder() #0 {
; CHECK-LABEL: @vec_shuff_reorder(
; CHECK-NEXT: [[TMP1:%.*]] = load <2 x float>, ptr @fa, align 4
; CHECK-NEXT: [[TMP2:%.*]] = load <2 x float>, ptr @fb, align 4
; CHECK-NEXT: [[TMP3:%.*]] = load <2 x float>, ptr getelementptr inbounds ([4 x float], ptr @fb, i32 0, i64 2), align 4
; CHECK-NEXT: [[TMP4:%.*]] = load <2 x float>, ptr getelementptr inbounds ([4 x float], ptr @fa, i32 0, i64 2), align 4
; CHECK-NEXT: [[TMP5:%.*]] = call <4 x float> @llvm.vector.insert.v4f32.v2f32(<4 x float> poison, <2 x float> [[TMP1]], i64 0)
; CHECK-NEXT: [[TMP6:%.*]] = call <4 x float> @llvm.vector.insert.v4f32.v2f32(<4 x float> [[TMP5]], <2 x float> [[TMP3]], i64 2)
; CHECK-NEXT: [[TMP7:%.*]] = call <4 x float> @llvm.vector.insert.v4f32.v2f32(<4 x float> poison, <2 x float> [[TMP2]], i64 0)
; CHECK-NEXT: [[TMP8:%.*]] = call <4 x float> @llvm.vector.insert.v4f32.v2f32(<4 x float> [[TMP7]], <2 x float> [[TMP4]], i64 2)
; CHECK-NEXT: [[TMP9:%.*]] = fadd <4 x float> [[TMP6]], [[TMP8]]
; CHECK-NEXT: [[TMP10:%.*]] = fsub <4 x float> [[TMP6]], [[TMP8]]
; CHECK-NEXT: [[TMP11:%.*]] = shufflevector <4 x float> [[TMP9]], <4 x float> [[TMP10]], <4 x i32> <i32 0, i32 5, i32 2, i32 7>
; CHECK-NEXT: store <4 x float> [[TMP11]], ptr @fc, align 4
; CHECK-NEXT: ret void
;
%1 = load float, ptr @fb, align 4
%2 = load float, ptr @fa, align 4
%3 = fadd float %1, %2
store float %3, ptr @fc, align 4
%4 = load float, ptr getelementptr inbounds ([4 x float], ptr @fa, i32 0, i64 1), align 4
%5 = load float, ptr getelementptr inbounds ([4 x float], ptr @fb, i32 0, i64 1), align 4
%6 = fsub float %4, %5
store float %6, ptr getelementptr inbounds ([4 x float], ptr @fc, i32 0, i64 1), align 4
%7 = load float, ptr getelementptr inbounds ([4 x float], ptr @fa, i32 0, i64 2), align 4
%8 = load float, ptr getelementptr inbounds ([4 x float], ptr @fb, i32 0, i64 2), align 4
%9 = fadd float %7, %8
store float %9, ptr getelementptr inbounds ([4 x float], ptr @fc, i32 0, i64 2), align 4
%10 = load float, ptr getelementptr inbounds ([4 x float], ptr @fb, i32 0, i64 3), align 4
%11 = load float, ptr getelementptr inbounds ([4 x float], ptr @fa, i32 0, i64 3), align 4
%12 = fsub float %10, %11
store float %12, ptr getelementptr inbounds ([4 x float], ptr @fc, i32 0, i64 3), align 4
ret void
}
attributes #0 = { nounwind }