blob: 53fb104458c81a230ae9caeb6c6c4809de27f8d2 [file] [edit]
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6
; RUN: opt < %s -passes=slp-vectorizer -S -mtriple=x86_64-unknown-linux-gnu | FileCheck %s
; InstCombine canonicalizes boundary range comparisons to eq/ne (e.g.
; x <u 1 becomes x == 0). Such lanes are interchangeable with the rest of
; the bundle by adjusting the compared constant.
define <8 x i1> @eq_ult(i16 %x) {
; CHECK-LABEL: define <8 x i1> @eq_ult(
; CHECK-SAME: i16 [[X:%.*]]) {
; CHECK-NEXT: [[TMP1:%.*]] = insertelement <8 x i16> poison, i16 [[X]], i64 0
; CHECK-NEXT: [[TMP2:%.*]] = shufflevector <8 x i16> [[TMP1]], <8 x i16> poison, <8 x i32> zeroinitializer
; CHECK-NEXT: [[TMP3:%.*]] = icmp ult <8 x i16> [[TMP2]], <i16 1, i16 2, i16 3, i16 4, i16 5, i16 6, i16 7, i16 8>
; CHECK-NEXT: ret <8 x i1> [[TMP3]]
;
%c1 = icmp eq i16 %x, 0
%c2 = icmp ult i16 %x, 2
%c3 = icmp ult i16 %x, 3
%c4 = icmp ult i16 %x, 4
%c5 = icmp ult i16 %x, 5
%c6 = icmp ult i16 %x, 6
%c7 = icmp ult i16 %x, 7
%c8 = icmp ult i16 %x, 8
%i1 = insertelement <8 x i1> poison, i1 %c1, i32 0
%i2 = insertelement <8 x i1> %i1, i1 %c2, i32 1
%i3 = insertelement <8 x i1> %i2, i1 %c3, i32 2
%i4 = insertelement <8 x i1> %i3, i1 %c4, i32 3
%i5 = insertelement <8 x i1> %i4, i1 %c5, i32 4
%i6 = insertelement <8 x i1> %i5, i1 %c6, i32 5
%i7 = insertelement <8 x i1> %i6, i1 %c7, i32 6
%i8 = insertelement <8 x i1> %i7, i1 %c8, i32 7
ret <8 x i1> %i8
}
define <8 x i1> @ne_ugt(i16 %x) {
; CHECK-LABEL: define <8 x i1> @ne_ugt(
; CHECK-SAME: i16 [[X:%.*]]) {
; CHECK-NEXT: [[TMP1:%.*]] = insertelement <8 x i16> poison, i16 [[X]], i64 0
; CHECK-NEXT: [[TMP2:%.*]] = shufflevector <8 x i16> [[TMP1]], <8 x i16> poison, <8 x i32> zeroinitializer
; CHECK-NEXT: [[TMP3:%.*]] = icmp ugt <8 x i16> [[TMP2]], <i16 0, i16 1, i16 2, i16 3, i16 4, i16 5, i16 6, i16 7>
; CHECK-NEXT: ret <8 x i1> [[TMP3]]
;
%c1 = icmp ne i16 %x, 0
%c2 = icmp ugt i16 %x, 1
%c3 = icmp ugt i16 %x, 2
%c4 = icmp ugt i16 %x, 3
%c5 = icmp ugt i16 %x, 4
%c6 = icmp ugt i16 %x, 5
%c7 = icmp ugt i16 %x, 6
%c8 = icmp ugt i16 %x, 7
%i1 = insertelement <8 x i1> poison, i1 %c1, i32 0
%i2 = insertelement <8 x i1> %i1, i1 %c2, i32 1
%i3 = insertelement <8 x i1> %i2, i1 %c3, i32 2
%i4 = insertelement <8 x i1> %i3, i1 %c4, i32 3
%i5 = insertelement <8 x i1> %i4, i1 %c5, i32 4
%i6 = insertelement <8 x i1> %i5, i1 %c6, i32 5
%i7 = insertelement <8 x i1> %i6, i1 %c7, i32 6
%i8 = insertelement <8 x i1> %i7, i1 %c8, i32 7
ret <8 x i1> %i8
}
define <8 x i1> @eq_slt_signed_mins(i16 %x) {
; CHECK-LABEL: define <8 x i1> @eq_slt_signed_mins(
; CHECK-SAME: i16 [[X:%.*]]) {
; CHECK-NEXT: [[TMP1:%.*]] = insertelement <8 x i16> poison, i16 [[X]], i64 0
; CHECK-NEXT: [[TMP2:%.*]] = shufflevector <8 x i16> [[TMP1]], <8 x i16> poison, <8 x i32> zeroinitializer
; CHECK-NEXT: [[TMP3:%.*]] = icmp slt <8 x i16> [[TMP2]], <i16 -32767, i16 -32766, i16 -32765, i16 -32764, i16 -32763, i16 -32762, i16 -32761, i16 -32760>
; CHECK-NEXT: ret <8 x i1> [[TMP3]]
;
%c1 = icmp eq i16 %x, -32768
%c2 = icmp slt i16 %x, -32766
%c3 = icmp slt i16 %x, -32765
%c4 = icmp slt i16 %x, -32764
%c5 = icmp slt i16 %x, -32763
%c6 = icmp slt i16 %x, -32762
%c7 = icmp slt i16 %x, -32761
%c8 = icmp slt i16 %x, -32760
%i1 = insertelement <8 x i1> poison, i1 %c1, i32 0
%i2 = insertelement <8 x i1> %i1, i1 %c2, i32 1
%i3 = insertelement <8 x i1> %i2, i1 %c3, i32 2
%i4 = insertelement <8 x i1> %i3, i1 %c4, i32 3
%i5 = insertelement <8 x i1> %i4, i1 %c5, i32 4
%i6 = insertelement <8 x i1> %i5, i1 %c6, i32 5
%i7 = insertelement <8 x i1> %i6, i1 %c7, i32 6
%i8 = insertelement <8 x i1> %i7, i1 %c8, i32 7
ret <8 x i1> %i8
}
define <8 x i1> @ne_sle_signed_maxs(i16 %x) {
; CHECK-LABEL: define <8 x i1> @ne_sle_signed_maxs(
; CHECK-SAME: i16 [[X:%.*]]) {
; CHECK-NEXT: [[TMP1:%.*]] = insertelement <8 x i16> poison, i16 [[X]], i64 0
; CHECK-NEXT: [[TMP2:%.*]] = shufflevector <8 x i16> [[TMP1]], <8 x i16> poison, <8 x i32> zeroinitializer
; CHECK-NEXT: [[TMP3:%.*]] = icmp sle <8 x i16> [[TMP2]], <i16 32766, i16 32765, i16 32764, i16 32763, i16 32762, i16 32761, i16 32760, i16 32759>
; CHECK-NEXT: ret <8 x i1> [[TMP3]]
;
%c1 = icmp ne i16 %x, 32767
%c2 = icmp sle i16 %x, 32765
%c3 = icmp sle i16 %x, 32764
%c4 = icmp sle i16 %x, 32763
%c5 = icmp sle i16 %x, 32762
%c6 = icmp sle i16 %x, 32761
%c7 = icmp sle i16 %x, 32760
%c8 = icmp sle i16 %x, 32759
%i1 = insertelement <8 x i1> poison, i1 %c1, i32 0
%i2 = insertelement <8 x i1> %i1, i1 %c2, i32 1
%i3 = insertelement <8 x i1> %i2, i1 %c3, i32 2
%i4 = insertelement <8 x i1> %i3, i1 %c4, i32 3
%i5 = insertelement <8 x i1> %i4, i1 %c5, i32 4
%i6 = insertelement <8 x i1> %i5, i1 %c6, i32 5
%i7 = insertelement <8 x i1> %i6, i1 %c7, i32 6
%i8 = insertelement <8 x i1> %i7, i1 %c8, i32 7
ret <8 x i1> %i8
}
define <8 x i1> @ule_ult(i16 %x) {
; CHECK-LABEL: define <8 x i1> @ule_ult(
; CHECK-SAME: i16 [[X:%.*]]) {
; CHECK-NEXT: [[TMP1:%.*]] = insertelement <8 x i16> poison, i16 [[X]], i64 0
; CHECK-NEXT: [[TMP2:%.*]] = shufflevector <8 x i16> [[TMP1]], <8 x i16> poison, <8 x i32> zeroinitializer
; CHECK-NEXT: [[TMP3:%.*]] = icmp ult <8 x i16> [[TMP2]], <i16 1, i16 2, i16 3, i16 4, i16 5, i16 6, i16 7, i16 8>
; CHECK-NEXT: ret <8 x i1> [[TMP3]]
;
%c1 = icmp ule i16 %x, 0
%c2 = icmp ult i16 %x, 2
%c3 = icmp ult i16 %x, 3
%c4 = icmp ult i16 %x, 4
%c5 = icmp ult i16 %x, 5
%c6 = icmp ult i16 %x, 6
%c7 = icmp ult i16 %x, 7
%c8 = icmp ult i16 %x, 8
%i1 = insertelement <8 x i1> poison, i1 %c1, i32 0
%i2 = insertelement <8 x i1> %i1, i1 %c2, i32 1
%i3 = insertelement <8 x i1> %i2, i1 %c3, i32 2
%i4 = insertelement <8 x i1> %i3, i1 %c4, i32 3
%i5 = insertelement <8 x i1> %i4, i1 %c5, i32 4
%i6 = insertelement <8 x i1> %i5, i1 %c6, i32 5
%i7 = insertelement <8 x i1> %i6, i1 %c7, i32 6
%i8 = insertelement <8 x i1> %i7, i1 %c8, i32 7
ret <8 x i1> %i8
}
; Non-boundary constant: x == 5 is not interchangeable with x <u C.
define <8 x i1> @neg_eq_nonboundary(i16 %x) {
; CHECK-LABEL: define <8 x i1> @neg_eq_nonboundary(
; CHECK-SAME: i16 [[X:%.*]]) {
; CHECK-NEXT: [[TMP1:%.*]] = insertelement <8 x i16> <i16 5, i16 poison, i16 poison, i16 poison, i16 poison, i16 poison, i16 poison, i16 poison>, i16 [[X]], i64 1
; CHECK-NEXT: [[TMP2:%.*]] = shufflevector <8 x i16> [[TMP1]], <8 x i16> poison, <8 x i32> <i32 0, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1>
; CHECK-NEXT: [[TMP3:%.*]] = insertelement <8 x i16> <i16 poison, i16 2, i16 3, i16 4, i16 5, i16 6, i16 7, i16 8>, i16 [[X]], i64 0
; CHECK-NEXT: [[TMP4:%.*]] = icmp eq <8 x i16> [[TMP2]], [[TMP3]]
; CHECK-NEXT: [[TMP5:%.*]] = icmp ult <8 x i16> [[TMP2]], [[TMP3]]
; CHECK-NEXT: [[TMP6:%.*]] = shufflevector <8 x i1> [[TMP4]], <8 x i1> [[TMP5]], <8 x i32> <i32 0, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15>
; CHECK-NEXT: ret <8 x i1> [[TMP6]]
;
%c1 = icmp eq i16 %x, 5
%c2 = icmp ult i16 %x, 2
%c3 = icmp ult i16 %x, 3
%c4 = icmp ult i16 %x, 4
%c5 = icmp ult i16 %x, 5
%c6 = icmp ult i16 %x, 6
%c7 = icmp ult i16 %x, 7
%c8 = icmp ult i16 %x, 8
%i1 = insertelement <8 x i1> poison, i1 %c1, i32 0
%i2 = insertelement <8 x i1> %i1, i1 %c2, i32 1
%i3 = insertelement <8 x i1> %i2, i1 %c3, i32 2
%i4 = insertelement <8 x i1> %i3, i1 %c4, i32 3
%i5 = insertelement <8 x i1> %i4, i1 %c5, i32 4
%i6 = insertelement <8 x i1> %i5, i1 %c6, i32 5
%i7 = insertelement <8 x i1> %i6, i1 %c7, i32 6
%i8 = insertelement <8 x i1> %i7, i1 %c8, i32 7
ret <8 x i1> %i8
}
; eq and ne are complements, not interchangeable.
define <8 x i1> @neg_eq_ne(i16 %x) {
; CHECK-LABEL: define <8 x i1> @neg_eq_ne(
; CHECK-SAME: i16 [[X:%.*]]) {
; CHECK-NEXT: [[TMP1:%.*]] = insertelement <8 x i16> poison, i16 [[X]], i64 0
; CHECK-NEXT: [[TMP2:%.*]] = shufflevector <8 x i16> [[TMP1]], <8 x i16> poison, <8 x i32> zeroinitializer
; CHECK-NEXT: [[TMP3:%.*]] = icmp eq <8 x i16> [[TMP2]], <i16 0, i16 1, i16 2, i16 3, i16 4, i16 5, i16 6, i16 7>
; CHECK-NEXT: [[TMP4:%.*]] = icmp ne <8 x i16> [[TMP2]], <i16 0, i16 1, i16 2, i16 3, i16 4, i16 5, i16 6, i16 7>
; CHECK-NEXT: [[TMP5:%.*]] = shufflevector <8 x i1> [[TMP3]], <8 x i1> [[TMP4]], <8 x i32> <i32 0, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15>
; CHECK-NEXT: ret <8 x i1> [[TMP5]]
;
%c1 = icmp eq i16 %x, 0
%c2 = icmp ne i16 %x, 1
%c3 = icmp ne i16 %x, 2
%c4 = icmp ne i16 %x, 3
%c5 = icmp ne i16 %x, 4
%c6 = icmp ne i16 %x, 5
%c7 = icmp ne i16 %x, 6
%c8 = icmp ne i16 %x, 7
%i1 = insertelement <8 x i1> poison, i1 %c1, i32 0
%i2 = insertelement <8 x i1> %i1, i1 %c2, i32 1
%i3 = insertelement <8 x i1> %i2, i1 %c3, i32 2
%i4 = insertelement <8 x i1> %i3, i1 %c4, i32 3
%i5 = insertelement <8 x i1> %i4, i1 %c5, i32 4
%i6 = insertelement <8 x i1> %i5, i1 %c6, i32 5
%i7 = insertelement <8 x i1> %i6, i1 %c7, i32 6
%i8 = insertelement <8 x i1> %i7, i1 %c8, i32 7
ret <8 x i1> %i8
}
; samesign is dropped on the vector compare, like for any cmp node; the
; converted lanes stay correct since the vector lane is defined wherever the
; original samesign scalar was poison.
define <8 x i1> @samesign_lanes(i8 %x) {
; CHECK-LABEL: define <8 x i1> @samesign_lanes(
; CHECK-SAME: i8 [[X:%.*]]) {
; CHECK-NEXT: [[TMP1:%.*]] = insertelement <8 x i8> poison, i8 [[X]], i64 0
; CHECK-NEXT: [[TMP2:%.*]] = shufflevector <8 x i8> [[TMP1]], <8 x i8> poison, <8 x i32> zeroinitializer
; CHECK-NEXT: [[TMP3:%.*]] = icmp samesign ult <8 x i8> [[TMP2]], <i8 1, i8 2, i8 3, i8 4, i8 5, i8 6, i8 7, i8 8>
; CHECK-NEXT: ret <8 x i1> [[TMP3]]
;
%c1 = icmp samesign eq i8 %x, 0
%c2 = icmp samesign ult i8 %x, 2
%c3 = icmp samesign ult i8 %x, 3
%c4 = icmp samesign ult i8 %x, 4
%c5 = icmp samesign ult i8 %x, 5
%c6 = icmp samesign ult i8 %x, 6
%c7 = icmp samesign ult i8 %x, 7
%c8 = icmp samesign ult i8 %x, 8
%i1 = insertelement <8 x i1> poison, i1 %c1, i32 0
%i2 = insertelement <8 x i1> %i1, i1 %c2, i32 1
%i3 = insertelement <8 x i1> %i2, i1 %c3, i32 2
%i4 = insertelement <8 x i1> %i3, i1 %c4, i32 3
%i5 = insertelement <8 x i1> %i4, i1 %c5, i32 4
%i6 = insertelement <8 x i1> %i5, i1 %c6, i32 5
%i7 = insertelement <8 x i1> %i6, i1 %c7, i32 6
%i8 = insertelement <8 x i1> %i7, i1 %c8, i32 7
ret <8 x i1> %i8
}
; samesign is dropped: the i1 conversion flips the constant's sign.
define <4 x i1> @samesign_i1_signflip(i1 %x, i1 %y, i1 %z, i1 %w) {
; CHECK-LABEL: define <4 x i1> @samesign_i1_signflip(
; CHECK-SAME: i1 [[X:%.*]], i1 [[Y:%.*]], i1 [[Z:%.*]], i1 [[W:%.*]]) {
; CHECK-NEXT: [[TMP1:%.*]] = insertelement <4 x i1> poison, i1 [[X]], i64 0
; CHECK-NEXT: [[TMP2:%.*]] = insertelement <4 x i1> [[TMP1]], i1 [[Y]], i64 1
; CHECK-NEXT: [[TMP3:%.*]] = insertelement <4 x i1> [[TMP2]], i1 [[Z]], i64 2
; CHECK-NEXT: [[TMP4:%.*]] = insertelement <4 x i1> [[TMP3]], i1 [[W]], i64 3
; CHECK-NEXT: [[TMP5:%.*]] = icmp eq <4 x i1> [[TMP4]], zeroinitializer
; CHECK-NEXT: ret <4 x i1> [[TMP5]]
;
%c1 = icmp samesign eq i1 %x, 0
%c2 = icmp samesign ult i1 %y, 1
%c3 = icmp samesign ult i1 %z, 1
%c4 = icmp samesign ult i1 %w, 1
%i1 = insertelement <4 x i1> poison, i1 %c1, i32 0
%i2 = insertelement <4 x i1> %i1, i1 %c2, i32 1
%i3 = insertelement <4 x i1> %i2, i1 %c3, i32 2
%i4 = insertelement <4 x i1> %i3, i1 %c4, i32 3
ret <4 x i1> %i4
}
; samesign is dropped: the compared operands are narrowed.
define <4 x i1> @samesign_narrowed(i16 %a, i16 %b, i16 %c, i16 %d) {
; CHECK-LABEL: define <4 x i1> @samesign_narrowed(
; CHECK-SAME: i16 [[A:%.*]], i16 [[B:%.*]], i16 [[C:%.*]], i16 [[D:%.*]]) {
; CHECK-NEXT: [[TMP1:%.*]] = insertelement <2 x i16> poison, i16 [[A]], i64 0
; CHECK-NEXT: [[TMP2:%.*]] = insertelement <2 x i16> [[TMP1]], i16 [[C]], i64 1
; CHECK-NEXT: [[TMP3:%.*]] = shufflevector <2 x i16> [[TMP2]], <2 x i16> poison, <4 x i32> <i32 0, i32 1, i32 0, i32 1>
; CHECK-NEXT: [[TMP4:%.*]] = insertelement <2 x i16> poison, i16 [[B]], i64 0
; CHECK-NEXT: [[TMP5:%.*]] = insertelement <2 x i16> [[TMP4]], i16 [[D]], i64 1
; CHECK-NEXT: [[TMP6:%.*]] = shufflevector <2 x i16> [[TMP5]], <2 x i16> poison, <4 x i32> <i32 0, i32 1, i32 1, i32 0>
; CHECK-NEXT: [[TMP7:%.*]] = icmp ult <4 x i16> [[TMP3]], [[TMP6]]
; CHECK-NEXT: ret <4 x i1> [[TMP7]]
;
%a32 = zext i16 %a to i32
%b32 = zext i16 %b to i32
%c32 = zext i16 %c to i32
%d32 = zext i16 %d to i32
%r1 = icmp samesign ult i32 %a32, %b32
%r2 = icmp samesign ult i32 %c32, %d32
%r3 = icmp samesign ult i32 %a32, %d32
%r4 = icmp samesign ult i32 %c32, %b32
%i1 = insertelement <4 x i1> poison, i1 %r1, i32 0
%i2 = insertelement <4 x i1> %i1, i1 %r2, i32 1
%i3 = insertelement <4 x i1> %i2, i1 %r3, i32 2
%i4 = insertelement <4 x i1> %i3, i1 %r4, i32 3
ret <4 x i1> %i4
}
; The original issue pattern: compares feeding selects and stores.
define void @selects(ptr noalias %out, ptr addrspace(11) %a, ptr addrspace(11) %b, i64 %n) {
; CHECK-LABEL: define void @selects(
; CHECK-SAME: ptr noalias [[OUT:%.*]], ptr addrspace(11) [[A:%.*]], ptr addrspace(11) [[B:%.*]], i64 [[N:%.*]]) {
; CHECK-NEXT: [[X:%.*]] = trunc i64 [[N]] to i16
; CHECK-NEXT: [[TMP1:%.*]] = insertelement <4 x i16> poison, i16 [[X]], i64 0
; CHECK-NEXT: [[TMP2:%.*]] = shufflevector <4 x i16> [[TMP1]], <4 x i16> poison, <4 x i32> zeroinitializer
; CHECK-NEXT: [[TMP3:%.*]] = icmp ult <4 x i16> [[TMP2]], <i16 1, i16 2, i16 3, i16 4>
; CHECK-NEXT: [[TMP4:%.*]] = load <4 x i16>, ptr addrspace(11) [[A]], align 2
; CHECK-NEXT: [[TMP5:%.*]] = load <4 x i16>, ptr addrspace(11) [[B]], align 2
; CHECK-NEXT: [[TMP6:%.*]] = select <4 x i1> [[TMP3]], <4 x i16> [[TMP5]], <4 x i16> [[TMP4]]
; CHECK-NEXT: store <4 x i16> [[TMP6]], ptr [[OUT]], align 2
; CHECK-NEXT: ret void
;
%x = trunc i64 %n to i16
%c1 = icmp eq i16 %x, 0
%l1a = load i16, ptr addrspace(11) %a, align 2
%l1b = load i16, ptr addrspace(11) %b, align 2
%s1 = select i1 %c1, i16 %l1b, i16 %l1a
%c2 = icmp ult i16 %x, 2
%p2a = getelementptr i8, ptr addrspace(11) %a, i64 2
%p2b = getelementptr i8, ptr addrspace(11) %b, i64 2
%l2a = load i16, ptr addrspace(11) %p2a, align 2
%l2b = load i16, ptr addrspace(11) %p2b, align 2
%s2 = select i1 %c2, i16 %l2b, i16 %l2a
%c3 = icmp ult i16 %x, 3
%p3a = getelementptr i8, ptr addrspace(11) %a, i64 4
%p3b = getelementptr i8, ptr addrspace(11) %b, i64 4
%l3a = load i16, ptr addrspace(11) %p3a, align 2
%l3b = load i16, ptr addrspace(11) %p3b, align 2
%s3 = select i1 %c3, i16 %l3b, i16 %l3a
%c4 = icmp ult i16 %x, 4
%p4a = getelementptr i8, ptr addrspace(11) %a, i64 6
%p4b = getelementptr i8, ptr addrspace(11) %b, i64 6
%l4a = load i16, ptr addrspace(11) %p4a, align 2
%l4b = load i16, ptr addrspace(11) %p4b, align 2
%s4 = select i1 %c4, i16 %l4b, i16 %l4a
store i16 %s1, ptr %out, align 2
%o2 = getelementptr i8, ptr %out, i64 2
store i16 %s2, ptr %o2, align 2
%o3 = getelementptr i8, ptr %out, i64 4
store i16 %s3, ptr %o3, align 2
%o4 = getelementptr i8, ptr %out, i64 6
store i16 %s4, ptr %o4, align 2
ret void
}