[llvm] [SLP][NFC]Add tests for interchange compares, NFC (PR #218169)

Alexey Bataev via llvm-commits llvm-commits at lists.llvm.org
Sat Aug 22 16:14:24 PDT 2026


https://github.com/alexey-bataev created https://github.com/llvm/llvm-project/pull/218169

None

>From b885f30f9a68a80a5d83026b0de558f830dcbf73 Mon Sep 17 00:00:00 2001
From: Alexey Bataev <a.bataev at outlook.com>
Date: Sat, 22 Aug 2026 16:14:12 -0700
Subject: [PATCH] =?UTF-8?q?[=F0=9D=98=80=F0=9D=97=BD=F0=9D=97=BF]=20initia?=
 =?UTF-8?q?l=20version?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Created using spr 1.3.7
---
 .../X86/interchangeable-cmp-predicates.ll     | 359 ++++++++++++++++++
 1 file changed, 359 insertions(+)
 create mode 100644 llvm/test/Transforms/SLPVectorizer/X86/interchangeable-cmp-predicates.ll

diff --git a/llvm/test/Transforms/SLPVectorizer/X86/interchangeable-cmp-predicates.ll b/llvm/test/Transforms/SLPVectorizer/X86/interchangeable-cmp-predicates.ll
new file mode 100644
index 0000000000000..51156bc66d2c3
--- /dev/null
+++ b/llvm/test/Transforms/SLPVectorizer/X86/interchangeable-cmp-predicates.ll
@@ -0,0 +1,359 @@
+; 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> <i16 0, 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:    [[TMP6:%.*]] = 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]], [[TMP6]]
+; CHECK-NEXT:    [[TMP5:%.*]] = icmp ult <8 x i16> [[TMP2]], [[TMP6]]
+; CHECK-NEXT:    [[TMP3:%.*]] = 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> [[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> <i16 0, 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:    [[TMP6:%.*]] = insertelement <8 x i16> <i16 poison, i16 1, i16 2, i16 3, i16 4, i16 5, i16 6, i16 7>, i16 [[X]], i64 0
+; CHECK-NEXT:    [[TMP4:%.*]] = icmp ne <8 x i16> [[TMP2]], [[TMP6]]
+; CHECK-NEXT:    [[TMP5:%.*]] = icmp ugt <8 x i16> [[TMP2]], [[TMP6]]
+; CHECK-NEXT:    [[TMP3:%.*]] = 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> [[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> <i16 -32768, 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:    [[TMP6:%.*]] = insertelement <8 x i16> <i16 poison, i16 -32766, i16 -32765, i16 -32764, i16 -32763, i16 -32762, i16 -32761, i16 -32760>, i16 [[X]], i64 0
+; CHECK-NEXT:    [[TMP4:%.*]] = icmp eq <8 x i16> [[TMP2]], [[TMP6]]
+; CHECK-NEXT:    [[TMP5:%.*]] = icmp slt <8 x i16> [[TMP2]], [[TMP6]]
+; CHECK-NEXT:    [[TMP3:%.*]] = 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> [[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> <i16 32767, 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:    [[TMP6:%.*]] = insertelement <8 x i16> <i16 poison, i16 32765, i16 32764, i16 32763, i16 32762, i16 32761, i16 32760, i16 32759>, i16 [[X]], i64 0
+; CHECK-NEXT:    [[TMP4:%.*]] = icmp ne <8 x i16> [[TMP2]], [[TMP6]]
+; CHECK-NEXT:    [[TMP5:%.*]] = icmp sle <8 x i16> [[TMP2]], [[TMP6]]
+; CHECK-NEXT:    [[TMP3:%.*]] = 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> [[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:    [[TMP5:%.*]] = icmp ule <8 x i16> [[TMP2]], <i16 0, i16 2, i16 3, i16 4, i16 5, i16 6, i16 7, i16 8>
+; CHECK-NEXT:    [[TMP4:%.*]] = icmp ult <8 x i16> [[TMP2]], <i16 0, i16 2, i16 3, i16 4, i16 5, i16 6, i16 7, i16 8>
+; CHECK-NEXT:    [[TMP3:%.*]] = shufflevector <8 x i1> [[TMP5]], <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> [[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:    [[C1:%.*]] = icmp samesign eq i8 [[X]], 0
+; CHECK-NEXT:    [[C2:%.*]] = icmp samesign ult i8 [[X]], 2
+; CHECK-NEXT:    [[C3:%.*]] = icmp samesign ult i8 [[X]], 3
+; CHECK-NEXT:    [[C4:%.*]] = icmp samesign ult i8 [[X]], 4
+; 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:    [[TMP5:%.*]] = icmp ult <4 x i8> [[TMP2]], <i8 5, i8 6, i8 7, i8 8>
+; 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:    [[I3:%.*]] = insertelement <8 x i1> [[I2]], i1 [[C3]], i32 2
+; CHECK-NEXT:    [[I4:%.*]] = insertelement <8 x i1> [[I3]], i1 [[C4]], i32 3
+; CHECK-NEXT:    [[TMP4:%.*]] = shufflevector <4 x i1> [[TMP5]], <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:    [[TMP3:%.*]] = shufflevector <8 x i1> [[I4]], <8 x i1> [[TMP4]], <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> [[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:    [[C1:%.*]] = icmp samesign eq i1 [[X]], false
+; CHECK-NEXT:    [[C2:%.*]] = icmp samesign ult i1 [[Y]], true
+; CHECK-NEXT:    [[C3:%.*]] = icmp samesign ult i1 [[Z]], true
+; CHECK-NEXT:    [[C4:%.*]] = icmp samesign ult i1 [[W]], true
+; CHECK-NEXT:    [[I1:%.*]] = insertelement <4 x i1> poison, i1 [[C1]], i32 0
+; CHECK-NEXT:    [[I2:%.*]] = insertelement <4 x i1> [[I1]], i1 [[C2]], i32 1
+; CHECK-NEXT:    [[I3:%.*]] = insertelement <4 x i1> [[I2]], i1 [[C3]], i32 2
+; CHECK-NEXT:    [[TMP5:%.*]] = insertelement <4 x i1> [[I3]], i1 [[C4]], i32 3
+; 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> <i16 0, i16 poison, i16 poison, i16 poison>, i16 [[X]], i64 1
+; CHECK-NEXT:    [[TMP2:%.*]] = shufflevector <4 x i16> [[TMP1]], <4 x i16> poison, <4 x i32> <i32 0, i32 1, i32 1, i32 1>
+; CHECK-NEXT:    [[TMP7:%.*]] = insertelement <4 x i16> <i16 poison, i16 2, i16 3, i16 4>, i16 [[X]], i64 0
+; CHECK-NEXT:    [[TMP8:%.*]] = icmp eq <4 x i16> [[TMP2]], [[TMP7]]
+; CHECK-NEXT:    [[TMP9:%.*]] = icmp ult <4 x i16> [[TMP2]], [[TMP7]]
+; CHECK-NEXT:    [[TMP3:%.*]] = shufflevector <4 x i1> [[TMP8]], <4 x i1> [[TMP9]], <4 x i32> <i32 0, i32 5, i32 6, i32 7>
+; 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
+}



More information about the llvm-commits mailing list