blob: d441af63c36ad65ce9608957a0619a188e90b3e8 [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
}
define <2 x i1> @trunc_as_icmp_ne_and(i8 %x) {
; CHECK-LABEL: define <2 x i1> @trunc_as_icmp_ne_and(
; CHECK-SAME: i8 [[X:%.*]]) {
; CHECK-NEXT: [[TMP1:%.*]] = insertelement <2 x i8> poison, i8 [[X]], i64 0
; CHECK-NEXT: [[TMP2:%.*]] = shufflevector <2 x i8> [[TMP1]], <2 x i8> poison, <2 x i32> zeroinitializer
; CHECK-NEXT: [[TMP3:%.*]] = and <2 x i8> [[TMP2]], <i8 1, i8 2>
; CHECK-NEXT: [[TMP4:%.*]] = icmp ne <2 x i8> [[TMP3]], zeroinitializer
; CHECK-NEXT: ret <2 x i1> [[TMP4]]
;
%c1 = trunc i8 %x to i1
%m2 = and i8 %x, 2
%c2 = icmp ne i8 %m2, 0
%i1 = insertelement <2 x i1> poison, i1 %c1, i32 0
%i2 = insertelement <2 x i1> %i1, i1 %c2, i32 1
ret <2 x i1> %i2
}
define <4 x i1> @trunc_as_icmp_ne_and_mixed_preds(i8 %x) {
; CHECK-LABEL: define <4 x i1> @trunc_as_icmp_ne_and_mixed_preds(
; CHECK-SAME: i8 [[X:%.*]]) {
; CHECK-NEXT: [[TMP1:%.*]] = insertelement <4 x i8> poison, i8 [[X]], i64 0
; CHECK-NEXT: [[TMP2:%.*]] = shufflevector <4 x i8> [[TMP1]], <4 x i8> poison, <4 x i32> zeroinitializer
; CHECK-NEXT: [[TMP3:%.*]] = and <4 x i8> [[TMP2]], <i8 1, i8 2, i8 12, i8 48>
; CHECK-NEXT: [[TMP4:%.*]] = icmp ne <4 x i8> [[TMP3]], zeroinitializer
; CHECK-NEXT: ret <4 x i1> [[TMP4]]
;
%c1 = trunc i8 %x to i1
%m2 = and i8 %x, 2
%c2 = icmp ne i8 %m2, 0
%m3 = and i8 %x, 12
%c3 = icmp ugt i8 %m3, 0
%m4 = and i8 %x, 48
%c4 = icmp uge i8 %m4, 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
}
define void @trunc_as_icmp_ne_and_reused_operand(i16 %x, ptr %out) {
; CHECK-LABEL: define void @trunc_as_icmp_ne_and_reused_operand(
; CHECK-SAME: i16 [[X:%.*]], ptr [[OUT:%.*]]) {
; CHECK-NEXT: [[C1:%.*]] = trunc i16 [[X]] to i1
; CHECK-NEXT: [[TMP1:%.*]] = insertelement <2 x i16> poison, i16 [[X]], i64 0
; CHECK-NEXT: [[TMP2:%.*]] = shufflevector <2 x i16> [[TMP1]], <2 x i16> poison, <2 x i32> zeroinitializer
; CHECK-NEXT: [[TMP3:%.*]] = and <2 x i16> [[TMP2]], <i16 2, i16 4>
; CHECK-NEXT: [[M4:%.*]] = and i16 [[X]], 8
; CHECK-NEXT: [[C4:%.*]] = icmp ne i16 [[M4]], 0
; CHECK-NEXT: [[S1:%.*]] = select i1 [[C1]], i16 [[X]], i16 7
; CHECK-NEXT: [[S4:%.*]] = select i1 [[C4]], i16 [[M4]], i16 13
; CHECK-NEXT: store i16 [[S1]], ptr [[OUT]], align 2
; CHECK-NEXT: [[P2:%.*]] = getelementptr inbounds i16, ptr [[OUT]], i64 1
; CHECK-NEXT: [[TMP4:%.*]] = icmp ne <2 x i16> [[TMP3]], zeroinitializer
; CHECK-NEXT: [[TMP5:%.*]] = select <2 x i1> [[TMP4]], <2 x i16> [[TMP3]], <2 x i16> <i16 9, i16 11>
; CHECK-NEXT: store <2 x i16> [[TMP5]], ptr [[P2]], align 2
; CHECK-NEXT: [[P4:%.*]] = getelementptr inbounds i16, ptr [[OUT]], i64 3
; CHECK-NEXT: store i16 [[S4]], ptr [[P4]], align 2
; CHECK-NEXT: ret void
;
%c1 = trunc i16 %x to i1
%m2 = and i16 %x, 2
%c2 = icmp ne i16 %m2, 0
%m3 = and i16 %x, 4
%c3 = icmp ne i16 %m3, 0
%m4 = and i16 %x, 8
%c4 = icmp ne i16 %m4, 0
%s1 = select i1 %c1, i16 %x, i16 7
%s2 = select i1 %c2, i16 %m2, i16 9
%s3 = select i1 %c3, i16 %m3, i16 11
%s4 = select i1 %c4, i16 %m4, i16 13
store i16 %s1, ptr %out, align 2
%p2 = getelementptr inbounds i16, ptr %out, i64 1
store i16 %s2, ptr %p2, align 2
%p3 = getelementptr inbounds i16, ptr %out, i64 2
store i16 %s3, ptr %p3, align 2
%p4 = getelementptr inbounds i16, ptr %out, i64 3
store i16 %s4, ptr %p4, align 2
ret void
}
define <4 x i1> @trunc_as_icmp_ne_and_commuted_operands(i8 %x, i1 %a, i1 %b, i1 %c, i1 %d) {
; CHECK-LABEL: define <4 x i1> @trunc_as_icmp_ne_and_commuted_operands(
; CHECK-SAME: i8 [[X:%.*]], i1 [[A:%.*]], i1 [[B:%.*]], i1 [[C:%.*]], i1 [[D:%.*]]) {
; CHECK-NEXT: [[TMP1:%.*]] = insertelement <4 x i8> poison, i8 [[X]], i64 0
; CHECK-NEXT: [[TMP2:%.*]] = shufflevector <4 x i8> [[TMP1]], <4 x i8> poison, <4 x i32> zeroinitializer
; CHECK-NEXT: [[TMP3:%.*]] = and <4 x i8> [[TMP2]], <i8 1, i8 2, i8 4, i8 8>
; CHECK-NEXT: [[TMP4:%.*]] = icmp ne <4 x i8> [[TMP3]], zeroinitializer
; CHECK-NEXT: [[TMP5:%.*]] = insertelement <4 x i1> poison, i1 [[A]], i64 0
; CHECK-NEXT: [[TMP6:%.*]] = insertelement <4 x i1> [[TMP5]], i1 [[B]], i64 1
; CHECK-NEXT: [[TMP7:%.*]] = insertelement <4 x i1> [[TMP6]], i1 [[C]], i64 2
; CHECK-NEXT: [[TMP8:%.*]] = insertelement <4 x i1> [[TMP7]], i1 [[D]], i64 3
; CHECK-NEXT: [[TMP9:%.*]] = or <4 x i1> [[TMP4]], [[TMP8]]
; CHECK-NEXT: ret <4 x i1> [[TMP9]]
;
%c1 = trunc i8 %x to i1
%o1 = or i1 %c1, %a
%m2 = and i8 %x, 2
%c2 = icmp ne i8 %m2, 0
%o2 = or i1 %b, %c2
%m3 = and i8 %x, 4
%c3 = icmp ne i8 %m3, 0
%o3 = or i1 %c, %c3
%m4 = and i8 %x, 8
%c4 = icmp ne i8 %m4, 0
%o4 = or i1 %d, %c4
%i1 = insertelement <4 x i1> poison, i1 %o1, i32 0
%i2 = insertelement <4 x i1> %i1, i1 %o2, i32 1
%i3 = insertelement <4 x i1> %i2, i1 %o3, i32 2
%i4 = insertelement <4 x i1> %i3, i1 %o4, i32 3
ret <4 x i1> %i4
}
define <8 x i1> @trunc_as_icmp_ne_and_non_const_rhs(i16 %x, i16 %y, i16 %z) {
; CHECK-LABEL: define <8 x i1> @trunc_as_icmp_ne_and_non_const_rhs(
; CHECK-SAME: i16 [[X:%.*]], i16 [[Y:%.*]], i16 [[Z:%.*]]) {
; CHECK-NEXT: [[C1:%.*]] = trunc i16 [[X]] to i1
; CHECK-NEXT: [[M2:%.*]] = and i16 [[Y]], 2
; CHECK-NEXT: [[C2:%.*]] = icmp ne i16 [[M2]], [[X]]
; CHECK-NEXT: [[TMP1:%.*]] = insertelement <2 x i16> poison, i16 [[Z]], i64 0
; CHECK-NEXT: [[TMP2:%.*]] = shufflevector <2 x i16> [[TMP1]], <2 x i16> poison, <2 x i32> zeroinitializer
; CHECK-NEXT: [[TMP3:%.*]] = and <2 x i16> [[TMP2]], <i16 4, i16 8>
; CHECK-NEXT: [[TMP4:%.*]] = icmp ne <2 x i16> [[TMP3]], zeroinitializer
; CHECK-NEXT: [[TMP5:%.*]] = insertelement <4 x i16> poison, i16 [[Z]], i64 0
; CHECK-NEXT: [[TMP6:%.*]] = shufflevector <4 x i16> [[TMP5]], <4 x i16> poison, <4 x i32> zeroinitializer
; CHECK-NEXT: [[TMP11:%.*]] = and <4 x i16> [[TMP6]], <i16 16, i16 32, i16 64, i16 128>
; CHECK-NEXT: [[TMP8:%.*]] = icmp ne <4 x i16> [[TMP11]], zeroinitializer
; CHECK-NEXT: [[I1:%.*]] = insertelement <8 x i1> poison, i1 [[C1]], i32 0
; CHECK-NEXT: [[I2:%.*]] = insertelement <8 x i1> [[I1]], i1 [[C2]], i32 1
; CHECK-NEXT: [[TMP9:%.*]] = shufflevector <2 x i1> [[TMP4]], <2 x i1> poison, <8 x i32> <i32 0, i32 1, i32 poison, i32 poison, i32 poison, i32 poison, i32 poison, i32 poison>
; CHECK-NEXT: [[I42:%.*]] = shufflevector <8 x i1> [[I2]], <8 x i1> [[TMP9]], <8 x i32> <i32 0, i32 1, i32 8, i32 9, i32 poison, i32 poison, i32 poison, i32 poison>
; CHECK-NEXT: [[TMP10:%.*]] = shufflevector <4 x i1> [[TMP8]], <4 x i1> poison, <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 poison, i32 poison, i32 poison, i32 poison>
; CHECK-NEXT: [[TMP7:%.*]] = shufflevector <8 x i1> [[I42]], <8 x i1> [[TMP10]], <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 8, i32 9, i32 10, i32 11>
; CHECK-NEXT: ret <8 x i1> [[TMP7]]
;
%c1 = trunc i16 %x to i1
%m2 = and i16 %y, 2
%c2 = icmp ne i16 %m2, %x
%m3 = and i16 %z, 4
%c3 = icmp ne i16 %m3, 0
%m4 = and i16 %z, 8
%c4 = icmp ne i16 %m4, 0
%m5 = and i16 %z, 16
%c5 = icmp ne i16 %m5, 0
%m6 = and i16 %z, 32
%c6 = icmp ne i16 %m6, 0
%m7 = and i16 %z, 64
%c7 = icmp ne i16 %m7, 0
%m8 = and i16 %z, 128
%c8 = icmp ne i16 %m8, 0
%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> @trunc_as_icmp_ne_and_split_preds(i8 %x, i8 %y, i8 %z) {
; CHECK-LABEL: define <8 x i1> @trunc_as_icmp_ne_and_split_preds(
; CHECK-SAME: i8 [[X:%.*]], i8 [[Y:%.*]], i8 [[Z:%.*]]) {
; CHECK-NEXT: [[C1:%.*]] = trunc i8 [[X]] to i1
; CHECK-NEXT: [[TMP1:%.*]] = insertelement <4 x i8> poison, i8 [[Y]], i64 0
; CHECK-NEXT: [[TMP2:%.*]] = shufflevector <4 x i8> [[TMP1]], <4 x i8> poison, <4 x i32> zeroinitializer
; CHECK-NEXT: [[TMP3:%.*]] = and <4 x i8> [[TMP2]], <i8 64, i8 16, i8 8, i8 2>
; CHECK-NEXT: [[M3:%.*]] = and i8 [[Z]], 7
; CHECK-NEXT: [[C3:%.*]] = icmp ugt i8 [[M3]], 4
; CHECK-NEXT: [[M6:%.*]] = and i8 [[Z]], 56
; CHECK-NEXT: [[C6:%.*]] = icmp ugt i8 [[M6]], 40
; CHECK-NEXT: [[TMP4:%.*]] = icmp ne <4 x i8> [[TMP3]], zeroinitializer
; CHECK-NEXT: [[C8:%.*]] = trunc i8 [[Z]] to i1
; CHECK-NEXT: [[I1:%.*]] = insertelement <8 x i1> poison, i1 [[C1]], i32 0
; CHECK-NEXT: [[TMP5:%.*]] = shufflevector <4 x i1> [[TMP4]], <4 x i1> poison, <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 poison, i32 poison, i32 poison, i32 poison>
; CHECK-NEXT: [[TMP6:%.*]] = shufflevector <8 x i1> [[I1]], <8 x i1> [[TMP5]], <8 x i32> <i32 0, i32 11, i32 poison, i32 10, i32 9, i32 poison, i32 8, i32 poison>
; CHECK-NEXT: [[I3:%.*]] = insertelement <8 x i1> [[TMP6]], i1 [[C3]], i32 2
; CHECK-NEXT: [[I6:%.*]] = insertelement <8 x i1> [[I3]], i1 [[C6]], i32 5
; CHECK-NEXT: [[I8:%.*]] = insertelement <8 x i1> [[I6]], i1 [[C8]], i32 7
; CHECK-NEXT: ret <8 x i1> [[I8]]
;
%c1 = trunc i8 %x to i1
%m2 = and i8 %y, 2
%c2 = icmp ne i8 %m2, 0
%m3 = and i8 %z, 7
%c3 = icmp ugt i8 %m3, 4
%m4 = and i8 %y, 8
%c4 = icmp ne i8 %m4, 0
%m5 = and i8 %y, 16
%c5 = icmp ne i8 %m5, 0
%m6 = and i8 %z, 56
%c6 = icmp ugt i8 %m6, 40
%m7 = and i8 %y, 64
%c7 = icmp ne i8 %m7, 0
%c8 = trunc i8 %z to i1
%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 <4 x i1> @trunc_as_icmp_ne_and_inst_operand(i8 %x, i8 %y) {
; CHECK-LABEL: define <4 x i1> @trunc_as_icmp_ne_and_inst_operand(
; CHECK-SAME: i8 [[X:%.*]], i8 [[Y:%.*]]) {
; CHECK-NEXT: [[A:%.*]] = add i8 [[X]], [[Y]]
; CHECK-NEXT: [[TMP1:%.*]] = insertelement <4 x i8> poison, i8 [[A]], i64 0
; CHECK-NEXT: [[TMP2:%.*]] = shufflevector <4 x i8> [[TMP1]], <4 x i8> poison, <4 x i32> zeroinitializer
; CHECK-NEXT: [[TMP3:%.*]] = and <4 x i8> [[TMP2]], <i8 1, i8 2, i8 4, i8 8>
; CHECK-NEXT: [[TMP4:%.*]] = icmp ne <4 x i8> [[TMP3]], zeroinitializer
; CHECK-NEXT: ret <4 x i1> [[TMP4]]
;
%a = add i8 %x, %y
%c1 = trunc i8 %a to i1
%m2 = and i8 %a, 2
%c2 = icmp ne i8 %m2, 0
%m3 = and i8 %a, 4
%c3 = icmp ne i8 %m3, 0
%m4 = and i8 %a, 8
%c4 = icmp ne i8 %m4, 0
%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
}
define <4 x i1> @trunc_as_icmp_eq_and(i8 %x) {
; CHECK-LABEL: define <4 x i1> @trunc_as_icmp_eq_and(
; CHECK-SAME: i8 [[X:%.*]]) {
; CHECK-NEXT: [[TMP1:%.*]] = insertelement <4 x i8> poison, i8 [[X]], i64 0
; CHECK-NEXT: [[TMP2:%.*]] = shufflevector <4 x i8> [[TMP1]], <4 x i8> poison, <4 x i32> zeroinitializer
; CHECK-NEXT: [[TMP3:%.*]] = and <4 x i8> [[TMP2]], <i8 1, i8 2, i8 4, i8 8>
; CHECK-NEXT: [[TMP4:%.*]] = icmp eq <4 x i8> [[TMP3]], <i8 1, i8 0, i8 0, i8 0>
; CHECK-NEXT: ret <4 x i1> [[TMP4]]
;
%c1 = trunc i8 %x to i1
%m2 = and i8 %x, 2
%c2 = icmp eq i8 %m2, 0
%m3 = and i8 %x, 4
%c3 = icmp eq i8 %m3, 0
%m4 = and i8 %x, 8
%c4 = icmp ult i8 %m4, 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
}
define <2 x float> @select_trunc_as_icmp_eq_and_swapped_arms(i32 %flags, float %a, float %b) {
; CHECK-LABEL: define <2 x float> @select_trunc_as_icmp_eq_and_swapped_arms(
; CHECK-SAME: i32 [[FLAGS:%.*]], float [[A:%.*]], float [[B:%.*]]) {
; CHECK-NEXT: [[C0:%.*]] = trunc i32 [[FLAGS]] to i1
; CHECK-NEXT: [[S0:%.*]] = select i1 [[C0]], float 0.000000e+00, float [[A]]
; CHECK-NEXT: [[M1:%.*]] = and i32 [[FLAGS]], 2
; CHECK-NEXT: [[C1:%.*]] = icmp eq i32 [[M1]], 0
; CHECK-NEXT: [[S1:%.*]] = select i1 [[C1]], float [[B]], float 0.000000e+00
; CHECK-NEXT: [[V0:%.*]] = insertelement <2 x float> poison, float [[S0]], i64 0
; CHECK-NEXT: [[V1:%.*]] = insertelement <2 x float> [[V0]], float [[S1]], i64 1
; CHECK-NEXT: ret <2 x float> [[V1]]
;
%c0 = trunc i32 %flags to i1
%s0 = select i1 %c0, float 0.0, float %a
%m1 = and i32 %flags, 2
%c1 = icmp eq i32 %m1, 0
%s1 = select i1 %c1, float %b, float 0.0
%v0 = insertelement <2 x float> poison, float %s0, i64 0
%v1 = insertelement <2 x float> %v0, float %s1, i64 1
ret <2 x float> %v1
}
define <4 x float> @select_trunc_as_icmp_eq_and_multi_use(i32 %flags, float %a, float %b, float %c, float %d, ptr %p) {
; CHECK-LABEL: define <4 x float> @select_trunc_as_icmp_eq_and_multi_use(
; CHECK-SAME: i32 [[FLAGS:%.*]], float [[A:%.*]], float [[B:%.*]], float [[C:%.*]], float [[D:%.*]], ptr [[P:%.*]]) {
; CHECK-NEXT: [[TMP1:%.*]] = insertelement <4 x i32> poison, i32 [[FLAGS]], i64 0
; CHECK-NEXT: [[TMP2:%.*]] = shufflevector <4 x i32> [[TMP1]], <4 x i32> poison, <4 x i32> zeroinitializer
; CHECK-NEXT: [[TMP3:%.*]] = and <4 x i32> [[TMP2]], <i32 1, i32 2, i32 4, i32 8>
; CHECK-NEXT: [[TMP4:%.*]] = icmp eq <4 x i32> [[TMP3]], <i32 1, i32 0, i32 0, i32 0>
; CHECK-NEXT: [[C0:%.*]] = trunc i32 [[FLAGS]] to i1
; CHECK-NEXT: store i1 [[C0]], ptr [[P]], align 1
; CHECK-NEXT: [[TMP5:%.*]] = insertelement <4 x float> <float 0.000000e+00, float poison, float poison, float poison>, float [[B]], i64 1
; CHECK-NEXT: [[TMP6:%.*]] = insertelement <4 x float> [[TMP5]], float [[C]], i64 2
; CHECK-NEXT: [[TMP7:%.*]] = insertelement <4 x float> [[TMP6]], float [[D]], i64 3
; CHECK-NEXT: [[TMP8:%.*]] = insertelement <4 x float> <float poison, float 0.000000e+00, float 0.000000e+00, float 0.000000e+00>, float [[A]], i64 0
; CHECK-NEXT: [[TMP9:%.*]] = select <4 x i1> [[TMP4]], <4 x float> [[TMP7]], <4 x float> [[TMP8]]
; CHECK-NEXT: ret <4 x float> [[TMP9]]
;
%c0 = trunc i32 %flags to i1
store i1 %c0, ptr %p
%s0 = select i1 %c0, float 0.0, float %a
%m1 = and i32 %flags, 2
%c1 = icmp eq i32 %m1, 0
%s1 = select i1 %c1, float %b, float 0.0
%m2 = and i32 %flags, 4
%c2 = icmp eq i32 %m2, 0
%s2 = select i1 %c2, float %c, float 0.0
%m3 = and i32 %flags, 8
%c3 = icmp eq i32 %m3, 0
%s3 = select i1 %c3, float %d, float 0.0
%v0 = insertelement <4 x float> poison, float %s0, i64 0
%v1 = insertelement <4 x float> %v0, float %s1, i64 1
%v2 = insertelement <4 x float> %v1, float %s2, i64 2
%v3 = insertelement <4 x float> %v2, float %s3, i64 3
ret <4 x float> %v3
}