[llvm] [InstCombine] `A == MIN_INT ? B != MIN_INT : A < B` to `A < B` (PR #120177)

via llvm-commits llvm-commits at lists.llvm.org
Tue Dec 17 20:10:20 PST 2024


https://github.com/veera-sivarajan updated https://github.com/llvm/llvm-project/pull/120177

>From 6dca2fe1dca3aab044247ecd7bf4d94101bf8e0c Mon Sep 17 00:00:00 2001
From: Veera <sveera.2001 at gmail.com>
Date: Sun, 15 Dec 2024 06:19:31 +0000
Subject: [PATCH 1/2] Add Test

---
 .../select-with-extreme-eq-cond.ll            | 424 ++++++++++++++++++
 1 file changed, 424 insertions(+)
 create mode 100644 llvm/test/Transforms/InstCombine/select-with-extreme-eq-cond.ll

diff --git a/llvm/test/Transforms/InstCombine/select-with-extreme-eq-cond.ll b/llvm/test/Transforms/InstCombine/select-with-extreme-eq-cond.ll
new file mode 100644
index 00000000000000..9351e34ea33dc0
--- /dev/null
+++ b/llvm/test/Transforms/InstCombine/select-with-extreme-eq-cond.ll
@@ -0,0 +1,424 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 5
+; RUN: opt < %s -passes=instcombine -S | FileCheck %s
+
+define i1 @compare_unsigned_min(i8 %0, i8 %1) {
+; CHECK-LABEL: define i1 @compare_unsigned_min(
+; CHECK-SAME: i8 [[TMP0:%.*]], i8 [[TMP1:%.*]]) {
+; CHECK-NEXT:  [[START:.*:]]
+; CHECK-NEXT:    [[TMP4:%.*]] = icmp eq i8 [[TMP0]], 0
+; CHECK-NEXT:    [[TMP3:%.*]] = icmp ne i8 [[TMP1]], 0
+; CHECK-NEXT:    [[TMP2:%.*]] = icmp ult i8 [[TMP0]], [[TMP1]]
+; CHECK-NEXT:    [[RESULT:%.*]] = select i1 [[TMP4]], i1 [[TMP3]], i1 [[TMP2]]
+; CHECK-NEXT:    ret i1 [[RESULT]]
+;
+start:
+  %2 = icmp eq i8 %0, 0
+  %3 = icmp ne i8 %1, 0
+  %4 = icmp ult i8 %0, %1
+  %result = select i1 %2, i1 %3, i1 %4
+  ret i1 %result
+}
+
+define i1 @compare_signed_min(i8 %0, i8 %1) {
+; CHECK-LABEL: define i1 @compare_signed_min(
+; CHECK-SAME: i8 [[TMP0:%.*]], i8 [[TMP1:%.*]]) {
+; CHECK-NEXT:  [[START:.*:]]
+; CHECK-NEXT:    [[TMP2:%.*]] = icmp eq i8 [[TMP0]], -128
+; CHECK-NEXT:    [[TMP3:%.*]] = icmp ne i8 [[TMP1]], -128
+; CHECK-NEXT:    [[TMP4:%.*]] = icmp slt i8 [[TMP0]], [[TMP1]]
+; CHECK-NEXT:    [[RESULT:%.*]] = select i1 [[TMP2]], i1 [[TMP3]], i1 [[TMP4]]
+; CHECK-NEXT:    ret i1 [[RESULT]]
+;
+start:
+  %2 = icmp eq i8 %0, -128
+  %3 = icmp ne i8 %1, -128
+  %4 = icmp slt i8 %0, %1
+  %result = select i1 %2, i1 %3, i1 %4
+  ret i1 %result
+}
+
+define i1 @compare_unsigned_max(i8 %0, i8 %1) {
+; CHECK-LABEL: define i1 @compare_unsigned_max(
+; CHECK-SAME: i8 [[TMP0:%.*]], i8 [[TMP1:%.*]]) {
+; CHECK-NEXT:  [[START:.*:]]
+; CHECK-NEXT:    [[TMP2:%.*]] = icmp eq i8 [[TMP0]], -1
+; CHECK-NEXT:    [[TMP3:%.*]] = icmp ne i8 [[TMP1]], -1
+; CHECK-NEXT:    [[TMP4:%.*]] = icmp ugt i8 [[TMP0]], [[TMP1]]
+; CHECK-NEXT:    [[RESULT:%.*]] = select i1 [[TMP2]], i1 [[TMP3]], i1 [[TMP4]]
+; CHECK-NEXT:    ret i1 [[RESULT]]
+;
+start:
+  %2 = icmp eq i8 %0, 255
+  %3 = icmp ne i8 %1, 255
+  %4 = icmp ugt i8 %0, %1
+  %result = select i1 %2, i1 %3, i1 %4
+  ret i1 %result
+}
+
+define i1 @compare_signed_max(i8 %0, i8 %1) {
+; CHECK-LABEL: define i1 @compare_signed_max(
+; CHECK-SAME: i8 [[TMP0:%.*]], i8 [[TMP1:%.*]]) {
+; CHECK-NEXT:  [[START:.*:]]
+; CHECK-NEXT:    [[TMP2:%.*]] = icmp eq i8 [[TMP0]], 127
+; CHECK-NEXT:    [[TMP3:%.*]] = icmp ne i8 [[TMP1]], 127
+; CHECK-NEXT:    [[TMP4:%.*]] = icmp sgt i8 [[TMP0]], [[TMP1]]
+; CHECK-NEXT:    [[RESULT:%.*]] = select i1 [[TMP2]], i1 [[TMP3]], i1 [[TMP4]]
+; CHECK-NEXT:    ret i1 [[RESULT]]
+;
+start:
+  %2 = icmp eq i8 %0, 127
+  %3 = icmp ne i8 %1, 127
+  %4 = icmp sgt i8 %0, %1
+  %result = select i1 %2, i1 %3, i1 %4
+  ret i1 %result
+}
+
+define i1 @relational_cmp_unsigned_min(i8 %0, i8 %1) {
+; CHECK-LABEL: define i1 @relational_cmp_unsigned_min(
+; CHECK-SAME: i8 [[TMP0:%.*]], i8 [[TMP1:%.*]]) {
+; CHECK-NEXT:  [[START:.*:]]
+; CHECK-NEXT:    [[TMP2:%.*]] = icmp eq i8 [[TMP0]], 0
+; CHECK-NEXT:    [[TMP3:%.*]] = icmp ne i8 [[TMP1]], 0
+; CHECK-NEXT:    [[TMP4:%.*]] = icmp ult i8 [[TMP0]], [[TMP1]]
+; CHECK-NEXT:    [[RESULT:%.*]] = select i1 [[TMP2]], i1 [[TMP3]], i1 [[TMP4]]
+; CHECK-NEXT:    ret i1 [[RESULT]]
+;
+start:
+  %2 = icmp ule i8 %0, 0
+  %3 = icmp ugt i8 %1, 0
+  %4 = icmp ult i8 %0, %1
+  %result = select i1 %2, i1 %3, i1 %4
+  ret i1 %result
+}
+
+define i1 @relational_cmp_signed_min(i8 %0, i8 %1) {
+; CHECK-LABEL: define i1 @relational_cmp_signed_min(
+; CHECK-SAME: i8 [[TMP0:%.*]], i8 [[TMP1:%.*]]) {
+; CHECK-NEXT:  [[START:.*:]]
+; CHECK-NEXT:    [[TMP2:%.*]] = icmp eq i8 [[TMP0]], -128
+; CHECK-NEXT:    [[TMP3:%.*]] = icmp ne i8 [[TMP1]], -128
+; CHECK-NEXT:    [[TMP4:%.*]] = icmp slt i8 [[TMP0]], [[TMP1]]
+; CHECK-NEXT:    [[RESULT:%.*]] = select i1 [[TMP2]], i1 [[TMP3]], i1 [[TMP4]]
+; CHECK-NEXT:    ret i1 [[RESULT]]
+;
+start:
+  %2 = icmp sle i8 %0, -128
+  %3 = icmp sgt i8 %1, -128
+  %4 = icmp slt i8 %0, %1
+  %result = select i1 %2, i1 %3, i1 %4
+  ret i1 %result
+}
+
+define i1 @relational_cmp_unsigned_max(i8 %0, i8 %1) {
+; CHECK-LABEL: define i1 @relational_cmp_unsigned_max(
+; CHECK-SAME: i8 [[TMP0:%.*]], i8 [[TMP1:%.*]]) {
+; CHECK-NEXT:  [[START:.*:]]
+; CHECK-NEXT:    [[TMP2:%.*]] = icmp eq i8 [[TMP0]], -1
+; CHECK-NEXT:    [[TMP3:%.*]] = icmp ne i8 [[TMP1]], -1
+; CHECK-NEXT:    [[TMP4:%.*]] = icmp ugt i8 [[TMP0]], [[TMP1]]
+; CHECK-NEXT:    [[RESULT:%.*]] = select i1 [[TMP2]], i1 [[TMP3]], i1 [[TMP4]]
+; CHECK-NEXT:    ret i1 [[RESULT]]
+;
+start:
+  %2 = icmp uge i8 %0, 255
+  %3 = icmp ult i8 %1, 255
+  %4 = icmp ugt i8 %0, %1
+  %result = select i1 %2, i1 %3, i1 %4
+  ret i1 %result
+}
+
+define i1 @relational_cmp_signed_max(i8 %0, i8 %1) {
+; CHECK-LABEL: define i1 @relational_cmp_signed_max(
+; CHECK-SAME: i8 [[TMP0:%.*]], i8 [[TMP1:%.*]]) {
+; CHECK-NEXT:  [[START:.*:]]
+; CHECK-NEXT:    [[TMP2:%.*]] = icmp eq i8 [[TMP0]], 127
+; CHECK-NEXT:    [[TMP3:%.*]] = icmp ne i8 [[TMP1]], 127
+; CHECK-NEXT:    [[TMP4:%.*]] = icmp sgt i8 [[TMP0]], [[TMP1]]
+; CHECK-NEXT:    [[RESULT:%.*]] = select i1 [[TMP2]], i1 [[TMP3]], i1 [[TMP4]]
+; CHECK-NEXT:    ret i1 [[RESULT]]
+;
+start:
+  %2 = icmp sge i8 %0, 127
+  %3 = icmp slt i8 %1, 127
+  %4 = icmp sgt i8 %0, %1
+  %result = select i1 %2, i1 %3, i1 %4
+  ret i1 %result
+}
+
+declare void @use(i1)
+
+define i1 @compare_signed_max_multiuse(i8 %0, i8 %1) {
+; CHECK-LABEL: define i1 @compare_signed_max_multiuse(
+; CHECK-SAME: i8 [[TMP0:%.*]], i8 [[TMP1:%.*]]) {
+; CHECK-NEXT:  [[START:.*:]]
+; CHECK-NEXT:    [[TMP2:%.*]] = icmp eq i8 [[TMP0]], 127
+; CHECK-NEXT:    [[TMP3:%.*]] = icmp ne i8 [[TMP1]], 127
+; CHECK-NEXT:    [[TMP4:%.*]] = icmp sgt i8 [[TMP0]], [[TMP1]]
+; CHECK-NEXT:    call void @use(i1 [[TMP4]])
+; CHECK-NEXT:    [[RESULT:%.*]] = select i1 [[TMP2]], i1 [[TMP3]], i1 [[TMP4]]
+; CHECK-NEXT:    ret i1 [[RESULT]]
+;
+start:
+  %2 = icmp eq i8 %0, 127
+  %3 = icmp ne i8 %1, 127
+  %4 = icmp sgt i8 %0, %1
+  call void @use(i1 %4)
+  %result = select i1 %2, i1 %3, i1 %4
+  ret i1 %result
+}
+
+define i1 @compare_signed_min_samesign(i8 %0, i8 %1) {
+; CHECK-LABEL: define i1 @compare_signed_min_samesign(
+; CHECK-SAME: i8 [[TMP0:%.*]], i8 [[TMP1:%.*]]) {
+; CHECK-NEXT:  [[START:.*:]]
+; CHECK-NEXT:    [[TMP2:%.*]] = icmp eq i8 [[TMP0]], -128
+; CHECK-NEXT:    [[TMP3:%.*]] = icmp ne i8 [[TMP1]], -128
+; CHECK-NEXT:    [[TMP4:%.*]] = icmp samesign slt i8 [[TMP0]], [[TMP1]]
+; CHECK-NEXT:    [[RESULT:%.*]] = select i1 [[TMP2]], i1 [[TMP3]], i1 [[TMP4]]
+; CHECK-NEXT:    ret i1 [[RESULT]]
+;
+start:
+  %2 = icmp eq i8 %0, -128
+  %3 = icmp ne i8 %1, -128
+  %4 = icmp samesign slt i8 %0, %1
+  %result = select i1 %2, i1 %3, i1 %4
+  ret i1 %result
+}
+
+define i1 @compare_flipped(i8 %0, i8 %1) {
+; CHECK-LABEL: define i1 @compare_flipped(
+; CHECK-SAME: i8 [[TMP0:%.*]], i8 [[TMP1:%.*]]) {
+; CHECK-NEXT:  [[START:.*:]]
+; CHECK-NEXT:    [[TMP2:%.*]] = icmp eq i8 [[TMP0]], 0
+; CHECK-NEXT:    [[TMP3:%.*]] = icmp ne i8 [[TMP1]], 0
+; CHECK-NEXT:    [[TMP4:%.*]] = icmp ugt i8 [[TMP1]], [[TMP0]]
+; CHECK-NEXT:    [[RESULT:%.*]] = select i1 [[TMP2]], i1 [[TMP3]], i1 [[TMP4]]
+; CHECK-NEXT:    ret i1 [[RESULT]]
+;
+start:
+  %2 = icmp eq i8 %0, 0
+  %3 = icmp ne i8 %1, 0
+  %4 = icmp ugt i8 %1, %0
+  %result = select i1 %2, i1 %3, i1 %4
+  ret i1 %result
+}
+
+define i1 @compare_swapped(i8 %0, i8 %1) {
+; CHECK-LABEL: define i1 @compare_swapped(
+; CHECK-SAME: i8 [[TMP0:%.*]], i8 [[TMP1:%.*]]) {
+; CHECK-NEXT:  [[START:.*:]]
+; CHECK-NEXT:    [[DOTNOT:%.*]] = icmp eq i8 [[TMP0]], 0
+; CHECK-NEXT:    [[TMP2:%.*]] = icmp ne i8 [[TMP1]], 0
+; CHECK-NEXT:    [[RESULT:%.*]] = icmp ult i8 [[TMP0]], [[TMP1]]
+; CHECK-NEXT:    [[RESULT1:%.*]] = select i1 [[DOTNOT]], i1 [[TMP2]], i1 [[RESULT]]
+; CHECK-NEXT:    ret i1 [[RESULT1]]
+;
+start:
+  %2 = icmp ne i8 %0, 0
+  %3 = icmp ne i8 %1, 0
+  %4 = icmp ult i8 %0, %1
+  %result = select i1 %2, i1 %4, i1 %3
+  ret i1 %result
+}
+
+define i1 @compare_swapped_flipped_unsigned_max(i8 %0, i8 %1) {
+; CHECK-LABEL: define i1 @compare_swapped_flipped_unsigned_max(
+; CHECK-SAME: i8 [[TMP0:%.*]], i8 [[TMP1:%.*]]) {
+; CHECK-NEXT:  [[START:.*:]]
+; CHECK-NEXT:    [[DOTNOT:%.*]] = icmp eq i8 [[TMP0]], -1
+; CHECK-NEXT:    [[TMP3:%.*]] = icmp ne i8 [[TMP1]], -1
+; CHECK-NEXT:    [[TMP2:%.*]] = icmp ult i8 [[TMP1]], [[TMP0]]
+; CHECK-NEXT:    [[RESULT:%.*]] = select i1 [[DOTNOT]], i1 [[TMP3]], i1 [[TMP2]]
+; CHECK-NEXT:    ret i1 [[RESULT]]
+;
+start:
+  %2 = icmp ne i8 %0, 255
+  %3 = icmp ne i8 %1, 255
+  %4 = icmp ult i8 %1, %0
+  %result = select i1 %2, i1 %4, i1 %3
+  ret i1 %result
+}
+
+define i1 @compare_unsigned_min_illegal_type(i9 %0, i9 %1) {
+; CHECK-LABEL: define i1 @compare_unsigned_min_illegal_type(
+; CHECK-SAME: i9 [[TMP0:%.*]], i9 [[TMP1:%.*]]) {
+; CHECK-NEXT:  [[START:.*:]]
+; CHECK-NEXT:    [[TMP4:%.*]] = icmp eq i9 [[TMP0]], 0
+; CHECK-NEXT:    [[TMP3:%.*]] = icmp ne i9 [[TMP1]], 0
+; CHECK-NEXT:    [[TMP2:%.*]] = icmp ult i9 [[TMP0]], [[TMP1]]
+; CHECK-NEXT:    [[RESULT:%.*]] = select i1 [[TMP4]], i1 [[TMP3]], i1 [[TMP2]]
+; CHECK-NEXT:    ret i1 [[RESULT]]
+;
+start:
+  %2 = icmp eq i9 %0, 0
+  %3 = icmp ne i9 %1, 0
+  %4 = icmp ult i9 %0, %1
+  %result = select i1 %2, i1 %3, i1 %4
+  ret i1 %result
+}
+
+define <2 x i1> @compare_vector(<2 x i8> %x, <2 x i8> %y) {
+; CHECK-LABEL: define <2 x i1> @compare_vector(
+; CHECK-SAME: <2 x i8> [[X:%.*]], <2 x i8> [[Y:%.*]]) {
+; CHECK-NEXT:    [[TMP3:%.*]] = icmp eq <2 x i8> [[X]], zeroinitializer
+; CHECK-NEXT:    [[TMP2:%.*]] = icmp ne <2 x i8> [[Y]], zeroinitializer
+; CHECK-NEXT:    [[TMP1:%.*]] = icmp ult <2 x i8> [[X]], [[Y]]
+; CHECK-NEXT:    [[RESULT:%.*]] = select <2 x i1> [[TMP3]], <2 x i1> [[TMP2]], <2 x i1> [[TMP1]]
+; CHECK-NEXT:    ret <2 x i1> [[RESULT]]
+;
+  %2 = icmp eq <2 x i8> %x, <i8 0, i8 0>
+  %3 = icmp ne <2 x i8> %y, <i8 0, i8 0>
+  %4 = icmp ult <2 x i8> %x, %y
+  %result = select <2 x i1> %2, <2 x i1> %3, <2 x i1> %4
+  ret <2 x i1> %result
+}
+
+define i1 @compare_pointer_negative(ptr %0, ptr %1) {
+; CHECK-LABEL: define i1 @compare_pointer_negative(
+; CHECK-SAME: ptr [[TMP0:%.*]], ptr [[TMP1:%.*]]) {
+; CHECK-NEXT:  [[START:.*:]]
+; CHECK-NEXT:    [[TMP2:%.*]] = icmp eq ptr [[TMP0]], inttoptr (i8 127 to ptr)
+; CHECK-NEXT:    [[TMP3:%.*]] = icmp ne ptr [[TMP1]], inttoptr (i8 127 to ptr)
+; CHECK-NEXT:    [[TMP4:%.*]] = icmp sgt ptr [[TMP0]], [[TMP1]]
+; CHECK-NEXT:    [[RESULT:%.*]] = select i1 [[TMP2]], i1 [[TMP3]], i1 [[TMP4]]
+; CHECK-NEXT:    ret i1 [[RESULT]]
+;
+start:
+  %X = inttoptr i8 127 to ptr
+  %2 = icmp eq ptr %0, %X
+  %3 = icmp ne ptr %1, %X
+  %4 = icmp sgt ptr %0, %1
+  %result = select i1 %2, i1 %3, i1 %4
+  ret i1 %result
+}
+
+define i1 @compare_float_negative(half %0, half %1) {
+; CHECK-LABEL: define i1 @compare_float_negative(
+; CHECK-SAME: half [[TMP0:%.*]], half [[TMP1:%.*]]) {
+; CHECK-NEXT:  [[START:.*:]]
+; CHECK-NEXT:    [[TMP2:%.*]] = fcmp oeq half [[TMP0]], 0xH0000
+; CHECK-NEXT:    [[TMP3:%.*]] = fcmp one half [[TMP1]], 0xH0000
+; CHECK-NEXT:    [[TMP4:%.*]] = fcmp ult half [[TMP0]], [[TMP1]]
+; CHECK-NEXT:    [[RESULT:%.*]] = select i1 [[TMP2]], i1 [[TMP3]], i1 [[TMP4]]
+; CHECK-NEXT:    ret i1 [[RESULT]]
+;
+start:
+  %2 = fcmp oeq half %0, 0.0
+  %3 = fcmp one half %1, 0.0
+  %4 = fcmp ult half %0, %1
+  %result = select i1 %2, i1 %3, i1 %4
+  ret i1 %result
+}
+
+define i1 @compare_unsigned_max_swapped_lhs_rhs_negative(i8 %0, i8 %1) {
+; CHECK-LABEL: define i1 @compare_unsigned_max_swapped_lhs_rhs_negative(
+; CHECK-SAME: i8 [[TMP0:%.*]], i8 [[TMP1:%.*]]) {
+; CHECK-NEXT:  [[START:.*:]]
+; CHECK-NEXT:    [[TMP2:%.*]] = icmp eq i8 [[TMP0]], -1
+; CHECK-NEXT:    [[DOTNOT:%.*]] = icmp ne i8 [[TMP1]], -1
+; CHECK-NEXT:    [[RESULT:%.*]] = select i1 [[DOTNOT]], i1 [[TMP2]], i1 false
+; CHECK-NEXT:    ret i1 [[RESULT]]
+;
+start:
+  %2 = icmp eq i8 %0, 255
+  %3 = icmp ne i8 %1, 255
+  %4 = icmp ugt i8 %0, %1
+  %result = select i1 %3, i1 %2, i1 %4
+  ret i1 %result
+}
+
+define i1 @compare_signed_min_negative(i8 %0, i8 %1) {
+; CHECK-LABEL: define i1 @compare_signed_min_negative(
+; CHECK-SAME: i8 [[TMP0:%.*]], i8 [[TMP1:%.*]]) {
+; CHECK-NEXT:  [[START:.*:]]
+; CHECK-NEXT:    [[TMP2:%.*]] = icmp eq i8 [[TMP0]], -127
+; CHECK-NEXT:    [[TMP3:%.*]] = icmp ne i8 [[TMP1]], -127
+; CHECK-NEXT:    [[TMP4:%.*]] = icmp slt i8 [[TMP0]], [[TMP1]]
+; CHECK-NEXT:    [[RESULT:%.*]] = select i1 [[TMP2]], i1 [[TMP3]], i1 [[TMP4]]
+; CHECK-NEXT:    ret i1 [[RESULT]]
+;
+start:
+  %2 = icmp eq i8 %0, -127
+  %3 = icmp ne i8 %1, -127
+  %4 = icmp slt i8 %0, %1
+  %result = select i1 %2, i1 %3, i1 %4
+  ret i1 %result
+}
+
+define i1 @compare_unsigned_max_negative(i8 %0, i8 %1) {
+; CHECK-LABEL: define i1 @compare_unsigned_max_negative(
+; CHECK-SAME: i8 [[TMP0:%.*]], i8 [[TMP1:%.*]]) {
+; CHECK-NEXT:  [[START:.*:]]
+; CHECK-NEXT:    [[TMP2:%.*]] = icmp eq i8 [[TMP0]], -1
+; CHECK-NEXT:    [[TMP3:%.*]] = icmp ne i8 [[TMP1]], -1
+; CHECK-NEXT:    [[TMP4:%.*]] = icmp ult i8 [[TMP0]], [[TMP1]]
+; CHECK-NEXT:    [[RESULT:%.*]] = select i1 [[TMP2]], i1 [[TMP3]], i1 [[TMP4]]
+; CHECK-NEXT:    ret i1 [[RESULT]]
+;
+start:
+  %2 = icmp eq i8 %0, 255
+  %3 = icmp ne i8 %1, 255
+  %4 = icmp ult i8 %0, %1
+  %result = select i1 %2, i1 %3, i1 %4
+  ret i1 %result
+}
+
+define i1 @non_strict_op_negative(i8 %0, i8 %1) {
+; CHECK-LABEL: define i1 @non_strict_op_negative(
+; CHECK-SAME: i8 [[TMP0:%.*]], i8 [[TMP1:%.*]]) {
+; CHECK-NEXT:  [[START:.*:]]
+; CHECK-NEXT:    [[TMP2:%.*]] = icmp eq i8 [[TMP0]], 0
+; CHECK-NEXT:    [[TMP3:%.*]] = icmp ne i8 [[TMP1]], 0
+; CHECK-NEXT:    [[TMP4:%.*]] = icmp ule i8 [[TMP0]], [[TMP1]]
+; CHECK-NEXT:    [[RESULT:%.*]] = select i1 [[TMP2]], i1 [[TMP3]], i1 [[TMP4]]
+; CHECK-NEXT:    ret i1 [[RESULT]]
+;
+start:
+  %2 = icmp eq i8 %0, 0
+  %3 = icmp ne i8 %1, 0
+  %4 = icmp ule i8 %0, %1
+  %result = select i1 %2, i1 %3, i1 %4
+  ret i1 %result
+}
+
+define i1 @compare_poison_negative(i8 %0, i8 %1) {
+; CHECK-LABEL: define i1 @compare_poison_negative(
+; CHECK-SAME: i8 [[TMP0:%.*]], i8 [[TMP1:%.*]]) {
+; CHECK-NEXT:  [[START:.*:]]
+; CHECK-NEXT:    ret i1 poison
+;
+start:
+  %2 = icmp eq i8 %0, 0
+  %3 = icmp ne i8 poison, 0
+  %4 = icmp ult i8 %0, poison
+  %result = select i1 %2, i1 %3, i1 %4
+  ret i1 %result
+}
+
+define i1 @compare_cond_poison_negative(i8 %0, i8 %1) {
+; CHECK-LABEL: define i1 @compare_cond_poison_negative(
+; CHECK-SAME: i8 [[TMP0:%.*]], i8 [[TMP1:%.*]]) {
+; CHECK-NEXT:  [[START:.*:]]
+; CHECK-NEXT:    ret i1 poison
+;
+start:
+  %2 = icmp eq i8 %0, poison
+  %3 = icmp ne i8 %1, 0
+  %4 = icmp ult i8 %0, %1
+  %result = select i1 %2, i1 %3, i1 %4
+  ret i1 %result
+}
+
+define i1 @compare_true_poison_negative(i8 %0, i8 %1) {
+; CHECK-LABEL: define i1 @compare_true_poison_negative(
+; CHECK-SAME: i8 [[TMP0:%.*]], i8 [[TMP1:%.*]]) {
+; CHECK-NEXT:  [[START:.*:]]
+; CHECK-NEXT:    ret i1 poison
+;
+start:
+  %2 = icmp eq i8 %0, poison
+  %3 = icmp ne i8 %1, 0
+  %4 = icmp ult i8 %0, %1
+  %result = select i1 %2, i1 poison, i1 %4
+  ret i1 %result
+}

>From 8b0239b52229defb6cbca8df9c8533cfae30a681 Mon Sep 17 00:00:00 2001
From: Veera <sveera.2001 at gmail.com>
Date: Wed, 18 Dec 2024 03:24:18 +0000
Subject: [PATCH 2/2] Fold `A == MIN_INT ? B != MIN_INT : A < B` to `A < B`

---
 llvm/lib/Analysis/InstructionSimplify.cpp     |  1 -
 .../InstCombine/InstCombineSelect.cpp         | 49 ++++++++++++
 .../select-with-extreme-eq-cond.ll            | 74 ++++---------------
 3 files changed, 64 insertions(+), 60 deletions(-)

diff --git a/llvm/lib/Analysis/InstructionSimplify.cpp b/llvm/lib/Analysis/InstructionSimplify.cpp
index 3325cd972cf1eb..0b8ce7fa4cd813 100644
--- a/llvm/lib/Analysis/InstructionSimplify.cpp
+++ b/llvm/lib/Analysis/InstructionSimplify.cpp
@@ -7141,7 +7141,6 @@ static Value *simplifyInstructionWithOperands(Instruction *I,
                             NewOps[1], I->getFastMathFlags(), Q, MaxRecurse);
   case Instruction::Select:
     return simplifySelectInst(NewOps[0], NewOps[1], NewOps[2], Q, MaxRecurse);
-    break;
   case Instruction::GetElementPtr: {
     auto *GEPI = cast<GetElementPtrInst>(I);
     return simplifyGEPInst(GEPI->getSourceElementType(), NewOps[0],
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp b/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp
index 50dfb58cadb17b..9ff46cad1b26fa 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp
@@ -1781,6 +1781,51 @@ static Value *foldSelectInstWithICmpConst(SelectInst &SI, ICmpInst *ICI,
   return nullptr;
 }
 
+/// `A == MIN_INT ? B != MIN_INT : A < B` --> `A < B`
+/// `A == MAX_INT ? B != MAX_INT : A > B` --> `A > B`
+static Value *foldSelectWithExtremeEqCond(Value *CmpLHS, Value *CmpRHS,
+                                          Value *TrueVal, Value *FalseVal,
+                                          IRBuilderBase &Builder) {
+  CmpPredicate Pred;
+  Value *A, *B;
+
+  if (!match(FalseVal, m_ICmp(Pred, m_Value(A), m_Value(B))))
+    return nullptr;
+
+  Type *Ty = A->getType();
+
+  if (Ty->isPointerTy())
+    return nullptr;
+
+  // make sure `CmpLHS` is on the LHS of `FalseVal`.
+  if (CmpLHS == B) {
+    std::swap(A, B);
+    Pred = CmpInst::getSwappedPredicate(Pred);
+  }
+
+  APInt C;
+  unsigned BitWidth = Ty->getScalarSizeInBits();
+
+  if (ICmpInst::isLT(Pred)) {
+    C = CmpInst::isSigned(Pred) ? APInt::getSignedMinValue(BitWidth)
+                                : APInt::getMinValue(BitWidth);
+  } else if (ICmpInst::isGT(Pred)) {
+    C = CmpInst::isSigned(Pred) ? APInt::getSignedMaxValue(BitWidth)
+                                : APInt::getMaxValue(BitWidth);
+  } else {
+    return nullptr;
+  }
+
+  if (!match(CmpLHS, m_Specific(A)) || !match(CmpRHS, m_SpecificInt(C)))
+    return nullptr;
+
+  if (!match(TrueVal, m_SpecificICmp(ICmpInst::ICMP_NE, m_Specific(B),
+                                     m_SpecificInt(C))))
+    return nullptr;
+
+  return Builder.CreateICmp(Pred, A, B);
+}
+
 static Instruction *foldSelectICmpEq(SelectInst &SI, ICmpInst *ICI,
                                      InstCombinerImpl &IC) {
   ICmpInst::Predicate Pred = ICI->getPredicate();
@@ -1795,6 +1840,10 @@ static Instruction *foldSelectICmpEq(SelectInst &SI, ICmpInst *ICI,
   if (Pred == ICmpInst::ICMP_NE)
     std::swap(TrueVal, FalseVal);
 
+  if (Value *V = foldSelectWithExtremeEqCond(CmpLHS, CmpRHS, TrueVal, FalseVal,
+                                             IC.Builder))
+    return IC.replaceInstUsesWith(SI, V);
+
   // Transform (X == C) ? X : Y -> (X == C) ? C : Y
   // specific handling for Bitwise operation.
   // x&y -> (x|y) ^ (x^y)  or  (x|y) & ~(x^y)
diff --git a/llvm/test/Transforms/InstCombine/select-with-extreme-eq-cond.ll b/llvm/test/Transforms/InstCombine/select-with-extreme-eq-cond.ll
index 9351e34ea33dc0..d1046b6d44d1cb 100644
--- a/llvm/test/Transforms/InstCombine/select-with-extreme-eq-cond.ll
+++ b/llvm/test/Transforms/InstCombine/select-with-extreme-eq-cond.ll
@@ -5,11 +5,8 @@ define i1 @compare_unsigned_min(i8 %0, i8 %1) {
 ; CHECK-LABEL: define i1 @compare_unsigned_min(
 ; CHECK-SAME: i8 [[TMP0:%.*]], i8 [[TMP1:%.*]]) {
 ; CHECK-NEXT:  [[START:.*:]]
-; CHECK-NEXT:    [[TMP4:%.*]] = icmp eq i8 [[TMP0]], 0
-; CHECK-NEXT:    [[TMP3:%.*]] = icmp ne i8 [[TMP1]], 0
 ; CHECK-NEXT:    [[TMP2:%.*]] = icmp ult i8 [[TMP0]], [[TMP1]]
-; CHECK-NEXT:    [[RESULT:%.*]] = select i1 [[TMP4]], i1 [[TMP3]], i1 [[TMP2]]
-; CHECK-NEXT:    ret i1 [[RESULT]]
+; CHECK-NEXT:    ret i1 [[TMP2]]
 ;
 start:
   %2 = icmp eq i8 %0, 0
@@ -23,11 +20,8 @@ define i1 @compare_signed_min(i8 %0, i8 %1) {
 ; CHECK-LABEL: define i1 @compare_signed_min(
 ; CHECK-SAME: i8 [[TMP0:%.*]], i8 [[TMP1:%.*]]) {
 ; CHECK-NEXT:  [[START:.*:]]
-; CHECK-NEXT:    [[TMP2:%.*]] = icmp eq i8 [[TMP0]], -128
-; CHECK-NEXT:    [[TMP3:%.*]] = icmp ne i8 [[TMP1]], -128
 ; CHECK-NEXT:    [[TMP4:%.*]] = icmp slt i8 [[TMP0]], [[TMP1]]
-; CHECK-NEXT:    [[RESULT:%.*]] = select i1 [[TMP2]], i1 [[TMP3]], i1 [[TMP4]]
-; CHECK-NEXT:    ret i1 [[RESULT]]
+; CHECK-NEXT:    ret i1 [[TMP4]]
 ;
 start:
   %2 = icmp eq i8 %0, -128
@@ -41,11 +35,8 @@ define i1 @compare_unsigned_max(i8 %0, i8 %1) {
 ; CHECK-LABEL: define i1 @compare_unsigned_max(
 ; CHECK-SAME: i8 [[TMP0:%.*]], i8 [[TMP1:%.*]]) {
 ; CHECK-NEXT:  [[START:.*:]]
-; CHECK-NEXT:    [[TMP2:%.*]] = icmp eq i8 [[TMP0]], -1
-; CHECK-NEXT:    [[TMP3:%.*]] = icmp ne i8 [[TMP1]], -1
 ; CHECK-NEXT:    [[TMP4:%.*]] = icmp ugt i8 [[TMP0]], [[TMP1]]
-; CHECK-NEXT:    [[RESULT:%.*]] = select i1 [[TMP2]], i1 [[TMP3]], i1 [[TMP4]]
-; CHECK-NEXT:    ret i1 [[RESULT]]
+; CHECK-NEXT:    ret i1 [[TMP4]]
 ;
 start:
   %2 = icmp eq i8 %0, 255
@@ -59,11 +50,8 @@ define i1 @compare_signed_max(i8 %0, i8 %1) {
 ; CHECK-LABEL: define i1 @compare_signed_max(
 ; CHECK-SAME: i8 [[TMP0:%.*]], i8 [[TMP1:%.*]]) {
 ; CHECK-NEXT:  [[START:.*:]]
-; CHECK-NEXT:    [[TMP2:%.*]] = icmp eq i8 [[TMP0]], 127
-; CHECK-NEXT:    [[TMP3:%.*]] = icmp ne i8 [[TMP1]], 127
 ; CHECK-NEXT:    [[TMP4:%.*]] = icmp sgt i8 [[TMP0]], [[TMP1]]
-; CHECK-NEXT:    [[RESULT:%.*]] = select i1 [[TMP2]], i1 [[TMP3]], i1 [[TMP4]]
-; CHECK-NEXT:    ret i1 [[RESULT]]
+; CHECK-NEXT:    ret i1 [[TMP4]]
 ;
 start:
   %2 = icmp eq i8 %0, 127
@@ -77,11 +65,8 @@ define i1 @relational_cmp_unsigned_min(i8 %0, i8 %1) {
 ; CHECK-LABEL: define i1 @relational_cmp_unsigned_min(
 ; CHECK-SAME: i8 [[TMP0:%.*]], i8 [[TMP1:%.*]]) {
 ; CHECK-NEXT:  [[START:.*:]]
-; CHECK-NEXT:    [[TMP2:%.*]] = icmp eq i8 [[TMP0]], 0
-; CHECK-NEXT:    [[TMP3:%.*]] = icmp ne i8 [[TMP1]], 0
 ; CHECK-NEXT:    [[TMP4:%.*]] = icmp ult i8 [[TMP0]], [[TMP1]]
-; CHECK-NEXT:    [[RESULT:%.*]] = select i1 [[TMP2]], i1 [[TMP3]], i1 [[TMP4]]
-; CHECK-NEXT:    ret i1 [[RESULT]]
+; CHECK-NEXT:    ret i1 [[TMP4]]
 ;
 start:
   %2 = icmp ule i8 %0, 0
@@ -95,11 +80,8 @@ define i1 @relational_cmp_signed_min(i8 %0, i8 %1) {
 ; CHECK-LABEL: define i1 @relational_cmp_signed_min(
 ; CHECK-SAME: i8 [[TMP0:%.*]], i8 [[TMP1:%.*]]) {
 ; CHECK-NEXT:  [[START:.*:]]
-; CHECK-NEXT:    [[TMP2:%.*]] = icmp eq i8 [[TMP0]], -128
-; CHECK-NEXT:    [[TMP3:%.*]] = icmp ne i8 [[TMP1]], -128
 ; CHECK-NEXT:    [[TMP4:%.*]] = icmp slt i8 [[TMP0]], [[TMP1]]
-; CHECK-NEXT:    [[RESULT:%.*]] = select i1 [[TMP2]], i1 [[TMP3]], i1 [[TMP4]]
-; CHECK-NEXT:    ret i1 [[RESULT]]
+; CHECK-NEXT:    ret i1 [[TMP4]]
 ;
 start:
   %2 = icmp sle i8 %0, -128
@@ -113,11 +95,8 @@ define i1 @relational_cmp_unsigned_max(i8 %0, i8 %1) {
 ; CHECK-LABEL: define i1 @relational_cmp_unsigned_max(
 ; CHECK-SAME: i8 [[TMP0:%.*]], i8 [[TMP1:%.*]]) {
 ; CHECK-NEXT:  [[START:.*:]]
-; CHECK-NEXT:    [[TMP2:%.*]] = icmp eq i8 [[TMP0]], -1
-; CHECK-NEXT:    [[TMP3:%.*]] = icmp ne i8 [[TMP1]], -1
 ; CHECK-NEXT:    [[TMP4:%.*]] = icmp ugt i8 [[TMP0]], [[TMP1]]
-; CHECK-NEXT:    [[RESULT:%.*]] = select i1 [[TMP2]], i1 [[TMP3]], i1 [[TMP4]]
-; CHECK-NEXT:    ret i1 [[RESULT]]
+; CHECK-NEXT:    ret i1 [[TMP4]]
 ;
 start:
   %2 = icmp uge i8 %0, 255
@@ -131,11 +110,8 @@ define i1 @relational_cmp_signed_max(i8 %0, i8 %1) {
 ; CHECK-LABEL: define i1 @relational_cmp_signed_max(
 ; CHECK-SAME: i8 [[TMP0:%.*]], i8 [[TMP1:%.*]]) {
 ; CHECK-NEXT:  [[START:.*:]]
-; CHECK-NEXT:    [[TMP2:%.*]] = icmp eq i8 [[TMP0]], 127
-; CHECK-NEXT:    [[TMP3:%.*]] = icmp ne i8 [[TMP1]], 127
 ; CHECK-NEXT:    [[TMP4:%.*]] = icmp sgt i8 [[TMP0]], [[TMP1]]
-; CHECK-NEXT:    [[RESULT:%.*]] = select i1 [[TMP2]], i1 [[TMP3]], i1 [[TMP4]]
-; CHECK-NEXT:    ret i1 [[RESULT]]
+; CHECK-NEXT:    ret i1 [[TMP4]]
 ;
 start:
   %2 = icmp sge i8 %0, 127
@@ -151,11 +127,9 @@ define i1 @compare_signed_max_multiuse(i8 %0, i8 %1) {
 ; CHECK-LABEL: define i1 @compare_signed_max_multiuse(
 ; CHECK-SAME: i8 [[TMP0:%.*]], i8 [[TMP1:%.*]]) {
 ; CHECK-NEXT:  [[START:.*:]]
-; CHECK-NEXT:    [[TMP2:%.*]] = icmp eq i8 [[TMP0]], 127
-; CHECK-NEXT:    [[TMP3:%.*]] = icmp ne i8 [[TMP1]], 127
 ; CHECK-NEXT:    [[TMP4:%.*]] = icmp sgt i8 [[TMP0]], [[TMP1]]
 ; CHECK-NEXT:    call void @use(i1 [[TMP4]])
-; CHECK-NEXT:    [[RESULT:%.*]] = select i1 [[TMP2]], i1 [[TMP3]], i1 [[TMP4]]
+; CHECK-NEXT:    [[RESULT:%.*]] = icmp sgt i8 [[TMP0]], [[TMP1]]
 ; CHECK-NEXT:    ret i1 [[RESULT]]
 ;
 start:
@@ -171,10 +145,7 @@ define i1 @compare_signed_min_samesign(i8 %0, i8 %1) {
 ; CHECK-LABEL: define i1 @compare_signed_min_samesign(
 ; CHECK-SAME: i8 [[TMP0:%.*]], i8 [[TMP1:%.*]]) {
 ; CHECK-NEXT:  [[START:.*:]]
-; CHECK-NEXT:    [[TMP2:%.*]] = icmp eq i8 [[TMP0]], -128
-; CHECK-NEXT:    [[TMP3:%.*]] = icmp ne i8 [[TMP1]], -128
-; CHECK-NEXT:    [[TMP4:%.*]] = icmp samesign slt i8 [[TMP0]], [[TMP1]]
-; CHECK-NEXT:    [[RESULT:%.*]] = select i1 [[TMP2]], i1 [[TMP3]], i1 [[TMP4]]
+; CHECK-NEXT:    [[RESULT:%.*]] = icmp slt i8 [[TMP0]], [[TMP1]]
 ; CHECK-NEXT:    ret i1 [[RESULT]]
 ;
 start:
@@ -189,10 +160,7 @@ define i1 @compare_flipped(i8 %0, i8 %1) {
 ; CHECK-LABEL: define i1 @compare_flipped(
 ; CHECK-SAME: i8 [[TMP0:%.*]], i8 [[TMP1:%.*]]) {
 ; CHECK-NEXT:  [[START:.*:]]
-; CHECK-NEXT:    [[TMP2:%.*]] = icmp eq i8 [[TMP0]], 0
-; CHECK-NEXT:    [[TMP3:%.*]] = icmp ne i8 [[TMP1]], 0
-; CHECK-NEXT:    [[TMP4:%.*]] = icmp ugt i8 [[TMP1]], [[TMP0]]
-; CHECK-NEXT:    [[RESULT:%.*]] = select i1 [[TMP2]], i1 [[TMP3]], i1 [[TMP4]]
+; CHECK-NEXT:    [[RESULT:%.*]] = icmp ult i8 [[TMP0]], [[TMP1]]
 ; CHECK-NEXT:    ret i1 [[RESULT]]
 ;
 start:
@@ -207,11 +175,8 @@ define i1 @compare_swapped(i8 %0, i8 %1) {
 ; CHECK-LABEL: define i1 @compare_swapped(
 ; CHECK-SAME: i8 [[TMP0:%.*]], i8 [[TMP1:%.*]]) {
 ; CHECK-NEXT:  [[START:.*:]]
-; CHECK-NEXT:    [[DOTNOT:%.*]] = icmp eq i8 [[TMP0]], 0
-; CHECK-NEXT:    [[TMP2:%.*]] = icmp ne i8 [[TMP1]], 0
 ; CHECK-NEXT:    [[RESULT:%.*]] = icmp ult i8 [[TMP0]], [[TMP1]]
-; CHECK-NEXT:    [[RESULT1:%.*]] = select i1 [[DOTNOT]], i1 [[TMP2]], i1 [[RESULT]]
-; CHECK-NEXT:    ret i1 [[RESULT1]]
+; CHECK-NEXT:    ret i1 [[RESULT]]
 ;
 start:
   %2 = icmp ne i8 %0, 0
@@ -225,10 +190,7 @@ define i1 @compare_swapped_flipped_unsigned_max(i8 %0, i8 %1) {
 ; CHECK-LABEL: define i1 @compare_swapped_flipped_unsigned_max(
 ; CHECK-SAME: i8 [[TMP0:%.*]], i8 [[TMP1:%.*]]) {
 ; CHECK-NEXT:  [[START:.*:]]
-; CHECK-NEXT:    [[DOTNOT:%.*]] = icmp eq i8 [[TMP0]], -1
-; CHECK-NEXT:    [[TMP3:%.*]] = icmp ne i8 [[TMP1]], -1
-; CHECK-NEXT:    [[TMP2:%.*]] = icmp ult i8 [[TMP1]], [[TMP0]]
-; CHECK-NEXT:    [[RESULT:%.*]] = select i1 [[DOTNOT]], i1 [[TMP3]], i1 [[TMP2]]
+; CHECK-NEXT:    [[RESULT:%.*]] = icmp ugt i8 [[TMP0]], [[TMP1]]
 ; CHECK-NEXT:    ret i1 [[RESULT]]
 ;
 start:
@@ -243,11 +205,8 @@ define i1 @compare_unsigned_min_illegal_type(i9 %0, i9 %1) {
 ; CHECK-LABEL: define i1 @compare_unsigned_min_illegal_type(
 ; CHECK-SAME: i9 [[TMP0:%.*]], i9 [[TMP1:%.*]]) {
 ; CHECK-NEXT:  [[START:.*:]]
-; CHECK-NEXT:    [[TMP4:%.*]] = icmp eq i9 [[TMP0]], 0
-; CHECK-NEXT:    [[TMP3:%.*]] = icmp ne i9 [[TMP1]], 0
 ; CHECK-NEXT:    [[TMP2:%.*]] = icmp ult i9 [[TMP0]], [[TMP1]]
-; CHECK-NEXT:    [[RESULT:%.*]] = select i1 [[TMP4]], i1 [[TMP3]], i1 [[TMP2]]
-; CHECK-NEXT:    ret i1 [[RESULT]]
+; CHECK-NEXT:    ret i1 [[TMP2]]
 ;
 start:
   %2 = icmp eq i9 %0, 0
@@ -260,11 +219,8 @@ start:
 define <2 x i1> @compare_vector(<2 x i8> %x, <2 x i8> %y) {
 ; CHECK-LABEL: define <2 x i1> @compare_vector(
 ; CHECK-SAME: <2 x i8> [[X:%.*]], <2 x i8> [[Y:%.*]]) {
-; CHECK-NEXT:    [[TMP3:%.*]] = icmp eq <2 x i8> [[X]], zeroinitializer
-; CHECK-NEXT:    [[TMP2:%.*]] = icmp ne <2 x i8> [[Y]], zeroinitializer
 ; CHECK-NEXT:    [[TMP1:%.*]] = icmp ult <2 x i8> [[X]], [[Y]]
-; CHECK-NEXT:    [[RESULT:%.*]] = select <2 x i1> [[TMP3]], <2 x i1> [[TMP2]], <2 x i1> [[TMP1]]
-; CHECK-NEXT:    ret <2 x i1> [[RESULT]]
+; CHECK-NEXT:    ret <2 x i1> [[TMP1]]
 ;
   %2 = icmp eq <2 x i8> %x, <i8 0, i8 0>
   %3 = icmp ne <2 x i8> %y, <i8 0, i8 0>



More information about the llvm-commits mailing list