[llvm] [InstCombine] simplify `icmp pred x, ~x` (PR #73990)

via llvm-commits llvm-commits at lists.llvm.org
Fri Aug 23 02:42:21 PDT 2024


https://github.com/ParkHanbum updated https://github.com/llvm/llvm-project/pull/73990

>From 8e0c9b9d4eb23c85a2e134fe0be0ca3bc02999cc Mon Sep 17 00:00:00 2001
From: Hanbum Park <kese111 at gmail.com>
Date: Fri, 1 Dec 2023 06:28:23 +0900
Subject: [PATCH 1/2] [InstCombine] Add test for simplify `X comp X^Neg_C`

This patch add testcase for comparison between X and X^Neg_X.

comparison between X and X^Neg_C is determined solely by
presence of the sign bit, so we can simplify it to checking
whether X is negative or not.
---
 .../Transforms/InstCombine/icmp-of-xor-x.ll   | 417 ++++++++++++++++++
 1 file changed, 417 insertions(+)

diff --git a/llvm/test/Transforms/InstCombine/icmp-of-xor-x.ll b/llvm/test/Transforms/InstCombine/icmp-of-xor-x.ll
index fd61c8a301662e..d8706ef1655957 100644
--- a/llvm/test/Transforms/InstCombine/icmp-of-xor-x.ll
+++ b/llvm/test/Transforms/InstCombine/icmp-of-xor-x.ll
@@ -4,6 +4,423 @@
 declare void @llvm.assume(i1)
 declare void @barrier()
 declare void @use.i8(i8)
+declare void @use.i1(i1)
+declare void @use.vec.i1(<2 x i1>)
+
+; X comp X^Neg_C tests, signed.
+; X s< X^Neg_C  -->  X s< 0
+define i1 @src_slt(i8 %x, i128 %x.128) {
+; CHECK-LABEL: @src_slt(
+; CHECK-NEXT:    [[NOT:%.*]] = xor i8 [[X:%.*]], -1
+; CHECK-NEXT:    [[CMP:%.*]] = icmp sgt i8 [[NOT]], [[X]]
+; CHECK-NEXT:    call void @use.i1(i1 [[CMP]])
+; CHECK-NEXT:    [[NOT_128:%.*]] = xor i128 [[X_128:%.*]], -170141183460469231731687303715884105728
+; CHECK-NEXT:    [[CMP_128:%.*]] = icmp sgt i128 [[NOT_128]], [[X_128]]
+; CHECK-NEXT:    ret i1 [[CMP_128]]
+;
+  %not = xor i8 %x, -1
+  %cmp = icmp slt i8 %x, %not
+  call void @use.i1(i1 %cmp)
+  %not.128 = xor i128 -170141183460469231731687303715884105728, %x.128
+  %cmp.128 = icmp slt i128 %x.128, %not.128
+  ret i1 %cmp.128
+}
+
+define <2 x i1> @src_slt_vec(<2 x i8> %x) {
+; CHECK-LABEL: @src_slt_vec(
+; CHECK-NEXT:    [[NOT:%.*]] = xor <2 x i8> [[X:%.*]], <i8 -1, i8 -1>
+; CHECK-NEXT:    [[CMP:%.*]] = icmp sgt <2 x i8> [[NOT]], [[X]]
+; CHECK-NEXT:    call void @use.vec.i1(<2 x i1> [[CMP]])
+; CHECK-NEXT:    [[NOT_MIN:%.*]] = xor <2 x i8> [[X]], <i8 -128, i8 -128>
+; CHECK-NEXT:    [[CMP_MIN:%.*]] = icmp sgt <2 x i8> [[NOT_MIN]], [[X]]
+; CHECK-NEXT:    ret <2 x i1> [[CMP_MIN]]
+;
+  %not = xor <2 x i8> %x, <i8 -1, i8 -1>
+  %cmp = icmp slt <2 x i8> %x, %not
+  call void @use.vec.i1(<2 x i1> %cmp)
+  %not_min = xor <2 x i8> %x, <i8 -128, i8 -128>
+  %cmp_min = icmp slt <2 x i8> %x, %not_min
+  ret <2 x i1> %cmp_min
+}
+
+; X s> X^Neg_C  -->  X s> -1
+define i1 @src_sgt(i8 %x, i128 %x.128) {
+; CHECK-LABEL: @src_sgt(
+; CHECK-NEXT:    [[NOT:%.*]] = xor i8 [[X:%.*]], -1
+; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i8 [[NOT]], [[X]]
+; CHECK-NEXT:    call void @use.i1(i1 [[CMP]])
+; CHECK-NEXT:    [[NOT_128:%.*]] = xor i128 [[X_128:%.*]], -170141183460469231731687303715884105728
+; CHECK-NEXT:    [[CMP_128:%.*]] = icmp slt i128 [[NOT_128]], [[X_128]]
+; CHECK-NEXT:    ret i1 [[CMP_128]]
+;
+  %not = xor i8 %x, -1
+  %cmp = icmp sgt i8 %x, %not
+  call void @use.i1(i1 %cmp)
+  %not.128 = xor i128 -170141183460469231731687303715884105728, %x.128
+  %cmp.128 = icmp sgt i128 %x.128, %not.128
+  ret i1 %cmp.128
+}
+
+define <2 x i1> @src_sgt_vec(<2 x i8> %x) {
+; CHECK-LABEL: @src_sgt_vec(
+; CHECK-NEXT:    [[NOT:%.*]] = xor <2 x i8> [[X:%.*]], <i8 -1, i8 -1>
+; CHECK-NEXT:    [[CMP:%.*]] = icmp slt <2 x i8> [[NOT]], [[X]]
+; CHECK-NEXT:    call void @use.vec.i1(<2 x i1> [[CMP]])
+; CHECK-NEXT:    [[NOT_MIN:%.*]] = xor <2 x i8> [[X]], <i8 -128, i8 -128>
+; CHECK-NEXT:    [[CMP_MIN:%.*]] = icmp slt <2 x i8> [[NOT_MIN]], [[X]]
+; CHECK-NEXT:    ret <2 x i1> [[CMP_MIN]]
+;
+  %not = xor <2 x i8> %x, <i8 -1, i8 -1>
+  %cmp = icmp sgt <2 x i8> %x, %not
+  call void @use.vec.i1(<2 x i1> %cmp)
+  %not_min = xor <2 x i8> %x, <i8 -128, i8 -128>
+  %cmp_min = icmp sgt <2 x i8> %x, %not_min
+  ret <2 x i1> %cmp_min
+}
+
+; X s<= X^Neg_C  -->  X s< 0
+define i1 @src_sle(i8 %x, i128 %x.128) {
+; CHECK-LABEL: @src_sle(
+; CHECK-NEXT:    [[NOT:%.*]] = xor i8 [[X:%.*]], -1
+; CHECK-NEXT:    [[CMP:%.*]] = icmp sgt i8 [[NOT]], [[X]]
+; CHECK-NEXT:    call void @use.i1(i1 [[CMP]])
+; CHECK-NEXT:    [[NOT_128:%.*]] = xor i128 [[X_128:%.*]], -170141183460469231731687303715884105728
+; CHECK-NEXT:    [[CMP_128:%.*]] = icmp sgt i128 [[NOT_128]], [[X_128]]
+; CHECK-NEXT:    ret i1 [[CMP_128]]
+;
+  %not = xor i8 %x, -1
+  %cmp = icmp sle i8 %x, %not
+  call void @use.i1(i1 %cmp)
+  %not.128 = xor i128 -170141183460469231731687303715884105728, %x.128
+  %cmp.128 = icmp sle i128 %x.128, %not.128
+  ret i1 %cmp.128
+}
+
+define <2 x i1> @src_sle_vec(<2 x i8> %x) {
+; CHECK-LABEL: @src_sle_vec(
+; CHECK-NEXT:    [[NOT:%.*]] = xor <2 x i8> [[X:%.*]], <i8 -1, i8 -1>
+; CHECK-NEXT:    [[CMP:%.*]] = icmp sgt <2 x i8> [[NOT]], [[X]]
+; CHECK-NEXT:    call void @use.vec.i1(<2 x i1> [[CMP]])
+; CHECK-NEXT:    [[NOT_MIN:%.*]] = xor <2 x i8> [[X]], <i8 -128, i8 -128>
+; CHECK-NEXT:    [[CMP_MIN:%.*]] = icmp sgt <2 x i8> [[NOT_MIN]], [[X]]
+; CHECK-NEXT:    ret <2 x i1> [[CMP_MIN]]
+;
+  %not = xor <2 x i8> %x, <i8 -1, i8 -1>
+  %cmp = icmp sle <2 x i8> %x, %not
+  call void @use.vec.i1(<2 x i1> %cmp)
+  %not_min = xor <2 x i8> %x, <i8 -128, i8 -128>
+  %cmp_min = icmp sle <2 x i8> %x, %not_min
+  ret <2 x i1> %cmp_min
+}
+
+; X s>= X^Neg_C  -->  X s> -1
+define i1 @src_sge(i8 %x, i128 %x.128) {
+; CHECK-LABEL: @src_sge(
+; CHECK-NEXT:    [[NOT:%.*]] = xor i8 [[X:%.*]], -1
+; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i8 [[NOT]], [[X]]
+; CHECK-NEXT:    call void @use.i1(i1 [[CMP]])
+; CHECK-NEXT:    [[NOT_128:%.*]] = xor i128 [[X_128:%.*]], -170141183460469231731687303715884105728
+; CHECK-NEXT:    [[CMP_128:%.*]] = icmp slt i128 [[NOT_128]], [[X_128]]
+; CHECK-NEXT:    ret i1 [[CMP_128]]
+;
+  %not = xor i8 %x, -1
+  %cmp = icmp sge i8 %x, %not
+  call void @use.i1(i1 %cmp)
+  %not.128 = xor i128 -170141183460469231731687303715884105728, %x.128
+  %cmp.128 = icmp sge i128 %x.128, %not.128
+  ret i1 %cmp.128
+}
+
+define <2 x i1> @src_sge_vec(<2 x i8> %x) {
+; CHECK-LABEL: @src_sge_vec(
+; CHECK-NEXT:    [[NOT:%.*]] = xor <2 x i8> [[X:%.*]], <i8 -1, i8 -1>
+; CHECK-NEXT:    [[CMP:%.*]] = icmp slt <2 x i8> [[NOT]], [[X]]
+; CHECK-NEXT:    call void @use.vec.i1(<2 x i1> [[CMP]])
+; CHECK-NEXT:    [[NOT_MIN:%.*]] = xor <2 x i8> [[X]], <i8 -128, i8 -128>
+; CHECK-NEXT:    [[CMP_MIN:%.*]] = icmp slt <2 x i8> [[NOT_MIN]], [[X]]
+; CHECK-NEXT:    ret <2 x i1> [[CMP_MIN]]
+;
+  %not = xor <2 x i8> %x, <i8 -1, i8 -1>
+  %cmp = icmp sge <2 x i8> %x, %not
+  call void @use.vec.i1(<2 x i1> %cmp)
+  %not_min = xor <2 x i8> %x, <i8 -128, i8 -128>
+  %cmp_min = icmp sge <2 x i8> %x, %not_min
+  ret <2 x i1> %cmp_min
+}
+
+; X comp X^Neg_C tests, unsigned.
+; X u< X^Neg_C  -->  X s> -1
+define i1 @src_ult(i8 %x, i128 %x.128) {
+; CHECK-LABEL: @src_ult(
+; CHECK-NEXT:    [[NOT:%.*]] = xor i8 [[X:%.*]], -1
+; CHECK-NEXT:    [[CMP:%.*]] = icmp ugt i8 [[NOT]], [[X]]
+; CHECK-NEXT:    call void @use.i1(i1 [[CMP]])
+; CHECK-NEXT:    [[NOT_128:%.*]] = xor i128 [[X_128:%.*]], -170141183460469231731687303715884105728
+; CHECK-NEXT:    [[CMP_128:%.*]] = icmp ugt i128 [[NOT_128]], [[X_128]]
+; CHECK-NEXT:    ret i1 [[CMP_128]]
+;
+  %not = xor i8 %x, -1
+  %cmp = icmp ult i8 %x, %not
+  call void @use.i1(i1 %cmp)
+  %not.128 = xor i128 -170141183460469231731687303715884105728, %x.128
+  %cmp.128 = icmp ult i128 %x.128, %not.128
+  ret i1 %cmp.128
+}
+
+define <2 x i1> @src_ult_vec(<2 x i8> %x) {
+; CHECK-LABEL: @src_ult_vec(
+; CHECK-NEXT:    [[NOT:%.*]] = xor <2 x i8> [[X:%.*]], <i8 -1, i8 -1>
+; CHECK-NEXT:    [[CMP:%.*]] = icmp ugt <2 x i8> [[NOT]], [[X]]
+; CHECK-NEXT:    call void @use.vec.i1(<2 x i1> [[CMP]])
+; CHECK-NEXT:    [[NOT_MIN:%.*]] = xor <2 x i8> [[X]], <i8 -128, i8 -128>
+; CHECK-NEXT:    [[CMP_MIN:%.*]] = icmp ugt <2 x i8> [[NOT_MIN]], [[X]]
+; CHECK-NEXT:    ret <2 x i1> [[CMP_MIN]]
+;
+  %not = xor <2 x i8> %x, <i8 -1, i8 -1>
+  %cmp = icmp ult <2 x i8> %x, %not
+  call void @use.vec.i1(<2 x i1> %cmp)
+  %not_min = xor <2 x i8> %x, <i8 -128, i8 -128>
+  %cmp_min = icmp ult <2 x i8> %x, %not_min
+  ret <2 x i1> %cmp_min
+}
+
+; X u> X^Neg_C  -->  X s< 0
+define i1 @src_ugt(i8 %x, i128 %x.128) {
+; CHECK-LABEL: @src_ugt(
+; CHECK-NEXT:    [[NOT:%.*]] = xor i8 [[X:%.*]], -1
+; CHECK-NEXT:    [[CMP:%.*]] = icmp ult i8 [[NOT]], [[X]]
+; CHECK-NEXT:    call void @use.i1(i1 [[CMP]])
+; CHECK-NEXT:    [[NOT_128:%.*]] = xor i128 [[X_128:%.*]], -170141183460469231731687303715884105728
+; CHECK-NEXT:    [[CMP_128:%.*]] = icmp ult i128 [[NOT_128]], [[X_128]]
+; CHECK-NEXT:    ret i1 [[CMP_128]]
+;
+  %not = xor i8 %x, -1
+  %cmp = icmp ugt i8 %x, %not
+  call void @use.i1(i1 %cmp)
+  %not.128 = xor i128 -170141183460469231731687303715884105728, %x.128
+  %cmp.128 = icmp ugt i128 %x.128, %not.128
+  ret i1 %cmp.128
+}
+
+define <2 x i1> @src_ugt_vec(<2 x i8> %x) {
+; CHECK-LABEL: @src_ugt_vec(
+; CHECK-NEXT:    [[NOT:%.*]] = xor <2 x i8> [[X:%.*]], <i8 -1, i8 -1>
+; CHECK-NEXT:    [[CMP:%.*]] = icmp ult <2 x i8> [[NOT]], [[X]]
+; CHECK-NEXT:    call void @use.vec.i1(<2 x i1> [[CMP]])
+; CHECK-NEXT:    [[NOT_MIN:%.*]] = xor <2 x i8> [[X]], <i8 -128, i8 -128>
+; CHECK-NEXT:    [[CMP_MIN:%.*]] = icmp ult <2 x i8> [[NOT_MIN]], [[X]]
+; CHECK-NEXT:    ret <2 x i1> [[CMP_MIN]]
+;
+  %not = xor <2 x i8> %x, <i8 -1, i8 -1>
+  %cmp = icmp ugt <2 x i8> %x, %not
+  call void @use.vec.i1(<2 x i1> %cmp)
+  %not_min = xor <2 x i8> %x, <i8 -128, i8 -128>
+  %cmp_min = icmp ugt <2 x i8> %x, %not_min
+  ret <2 x i1> %cmp_min
+}
+
+; X u<= X^Neg_C  -->  X s> -1
+define i1 @src_ule(i8 %x, i128 %x.128) {
+; CHECK-LABEL: @src_ule(
+; CHECK-NEXT:    [[NOT:%.*]] = xor i8 [[X:%.*]], -1
+; CHECK-NEXT:    [[CMP:%.*]] = icmp ugt i8 [[NOT]], [[X]]
+; CHECK-NEXT:    call void @use.i1(i1 [[CMP]])
+; CHECK-NEXT:    [[NOT_128:%.*]] = xor i128 [[X_128:%.*]], -170141183460469231731687303715884105728
+; CHECK-NEXT:    [[CMP_128:%.*]] = icmp ugt i128 [[NOT_128]], [[X_128]]
+; CHECK-NEXT:    ret i1 [[CMP_128]]
+;
+  %not = xor i8 %x, -1
+  %cmp = icmp ule i8 %x, %not
+  call void @use.i1(i1 %cmp)
+  %not.128 = xor i128 -170141183460469231731687303715884105728, %x.128
+  %cmp.128 = icmp ule i128 %x.128, %not.128
+  ret i1 %cmp.128
+}
+
+define <2 x i1> @src_ule_vec(<2 x i8> %x) {
+; CHECK-LABEL: @src_ule_vec(
+; CHECK-NEXT:    [[NOT:%.*]] = xor <2 x i8> [[X:%.*]], <i8 -1, i8 -1>
+; CHECK-NEXT:    [[CMP:%.*]] = icmp ugt <2 x i8> [[NOT]], [[X]]
+; CHECK-NEXT:    call void @use.vec.i1(<2 x i1> [[CMP]])
+; CHECK-NEXT:    [[NOT_MIN:%.*]] = xor <2 x i8> [[X]], <i8 -128, i8 -128>
+; CHECK-NEXT:    [[CMP_MIN:%.*]] = icmp ugt <2 x i8> [[NOT_MIN]], [[X]]
+; CHECK-NEXT:    ret <2 x i1> [[CMP_MIN]]
+;
+  %not = xor <2 x i8> %x, <i8 -1, i8 -1>
+  %cmp = icmp ule <2 x i8> %x, %not
+  call void @use.vec.i1(<2 x i1> %cmp)
+  %not_min = xor <2 x i8> %x, <i8 -128, i8 -128>
+  %cmp_min = icmp ule <2 x i8> %x, %not_min
+  ret <2 x i1> %cmp_min
+}
+
+; X u>= X^Neg_C  -->  X s< 0
+define i1 @src_uge(i8 %x, i128 %x.128) {
+; CHECK-LABEL: @src_uge(
+; CHECK-NEXT:    [[NOT:%.*]] = xor i8 [[X:%.*]], -1
+; CHECK-NEXT:    [[CMP:%.*]] = icmp ult i8 [[NOT]], [[X]]
+; CHECK-NEXT:    call void @use.i1(i1 [[CMP]])
+; CHECK-NEXT:    [[NOT_128:%.*]] = xor i128 [[X_128:%.*]], -170141183460469231731687303715884105728
+; CHECK-NEXT:    [[CMP_128:%.*]] = icmp ult i128 [[NOT_128]], [[X_128]]
+; CHECK-NEXT:    ret i1 [[CMP_128]]
+;
+  %not = xor i8 %x, -1
+  %cmp = icmp uge i8 %x, %not
+  call void @use.i1(i1 %cmp)
+  %not.128 = xor i128 -170141183460469231731687303715884105728, %x.128
+  %cmp.128 = icmp uge i128 %x.128, %not.128
+  ret i1 %cmp.128
+}
+
+define <2 x i1> @src_uge_vec(<2 x i8> %x) {
+; CHECK-LABEL: @src_uge_vec(
+; CHECK-NEXT:    [[NOT:%.*]] = xor <2 x i8> [[X:%.*]], <i8 -1, i8 -1>
+; CHECK-NEXT:    [[CMP:%.*]] = icmp ult <2 x i8> [[NOT]], [[X]]
+; CHECK-NEXT:    call void @use.vec.i1(<2 x i1> [[CMP]])
+; CHECK-NEXT:    [[NOT_MIN:%.*]] = xor <2 x i8> [[X]], <i8 -128, i8 -128>
+; CHECK-NEXT:    [[CMP_MIN:%.*]] = icmp ult <2 x i8> [[NOT_MIN]], [[X]]
+; CHECK-NEXT:    ret <2 x i1> [[CMP_MIN]]
+;
+  %not = xor <2 x i8> %x, <i8 -1, i8 -1>
+  %cmp = icmp uge <2 x i8> %x, %not
+  call void @use.vec.i1(<2 x i1> %cmp)
+  %not_min = xor <2 x i8> %x, <i8 -128, i8 -128>
+  %cmp_min = icmp uge <2 x i8> %x, %not_min
+  ret <2 x i1> %cmp_min
+}
+
+; X comp X^Neg_C tests. negative
+; X comp Y
+define i1 @src_sle_xny(i8 %x, i8 %y) {
+; CHECK-LABEL: @src_sle_xny(
+; CHECK-NEXT:    [[Y_NOT:%.*]] = xor i8 [[Y:%.*]], -1
+; CHECK-NEXT:    [[CMP:%.*]] = icmp sge i8 [[Y_NOT]], [[X:%.*]]
+; CHECK-NEXT:    ret i1 [[CMP]]
+;
+  %y.not = xor i8 %y, -1
+  %cmp = icmp sle i8 %x, %y.not
+  ret i1 %cmp
+}
+define i1 @src_sle_nyx(i8 %x, i8 %y) {
+; CHECK-LABEL: @src_sle_nyx(
+; CHECK-NEXT:    [[Y_NOT:%.*]] = xor i8 [[Y:%.*]], -1
+; CHECK-NEXT:    [[CMP:%.*]] = icmp sle i8 [[Y_NOT]], [[X:%.*]]
+; CHECK-NEXT:    ret i1 [[CMP]]
+;
+  %y.not = xor i8 %y, -1
+  %cmp = icmp sle i8 %y.not, %x
+  ret i1 %cmp
+}
+define i1 @src_sge_xny(i8 %x, i8 %y) {
+; CHECK-LABEL: @src_sge_xny(
+; CHECK-NEXT:    [[Y_NOT:%.*]] = xor i8 [[Y:%.*]], -1
+; CHECK-NEXT:    [[CMP:%.*]] = icmp sle i8 [[Y_NOT]], [[X:%.*]]
+; CHECK-NEXT:    ret i1 [[CMP]]
+;
+  %y.not = xor i8 %y, -1
+  %cmp = icmp sge i8 %x, %y.not
+  ret i1 %cmp
+}
+define i1 @src_sge_nyx(i8 %x, i8 %y) {
+; CHECK-LABEL: @src_sge_nyx(
+; CHECK-NEXT:    [[Y_NOT:%.*]] = xor i8 [[Y:%.*]], -1
+; CHECK-NEXT:    [[CMP:%.*]] = icmp sge i8 [[Y_NOT]], [[X:%.*]]
+; CHECK-NEXT:    ret i1 [[CMP]]
+;
+  %y.not = xor i8 %y, -1
+  %cmp = icmp sge i8 %y.not, %x
+  ret i1 %cmp
+}
+define i1 @src_ule_xny(i8 %x, i8 %y) {
+; CHECK-LABEL: @src_ule_xny(
+; CHECK-NEXT:    [[Y_NOT:%.*]] = xor i8 [[Y:%.*]], -1
+; CHECK-NEXT:    [[CMP:%.*]] = icmp uge i8 [[Y_NOT]], [[X:%.*]]
+; CHECK-NEXT:    ret i1 [[CMP]]
+;
+  %y.not = xor i8 %y, -1
+  %cmp = icmp ule i8 %x, %y.not
+  ret i1 %cmp
+}
+define i1 @src_ule_nyx(i8 %x, i8 %y) {
+; CHECK-LABEL: @src_ule_nyx(
+; CHECK-NEXT:    [[Y_NOT:%.*]] = xor i8 [[Y:%.*]], -1
+; CHECK-NEXT:    [[CMP:%.*]] = icmp ule i8 [[Y_NOT]], [[X:%.*]]
+; CHECK-NEXT:    ret i1 [[CMP]]
+;
+  %y.not = xor i8 %y, -1
+  %cmp = icmp ule i8 %y.not, %x
+  ret i1 %cmp
+}
+define i1 @src_uge_xny(i8 %x, i8 %y) {
+; CHECK-LABEL: @src_uge_xny(
+; CHECK-NEXT:    [[Y_NOT:%.*]] = xor i8 [[Y:%.*]], -1
+; CHECK-NEXT:    [[CMP:%.*]] = icmp ule i8 [[Y_NOT]], [[X:%.*]]
+; CHECK-NEXT:    ret i1 [[CMP]]
+;
+  %y.not = xor i8 %y, -1
+  %cmp = icmp uge i8 %x, %y.not
+  ret i1 %cmp
+}
+define i1 @src_uge_nyx(i8 %x, i8 %y) {
+; CHECK-LABEL: @src_uge_nyx(
+; CHECK-NEXT:    [[Y_NOT:%.*]] = xor i8 [[Y:%.*]], -1
+; CHECK-NEXT:    [[CMP:%.*]] = icmp uge i8 [[Y_NOT]], [[X:%.*]]
+; CHECK-NEXT:    ret i1 [[CMP]]
+;
+  %y.not = xor i8 %y, -1
+  %cmp = icmp uge i8 %y.not, %x
+  ret i1 %cmp
+}
+
+; X comp X^Neg_C tests. negative
+; (X+1) comp X^Neg_C
+define i1 @src_sle_incx_nx(i8 %x) {
+; CHECK-LABEL: @src_sle_incx_nx(
+; CHECK-NEXT:    [[TMP1:%.*]] = sub i8 -2, [[X:%.*]]
+; CHECK-NEXT:    [[CMP:%.*]] = icmp sge i8 [[TMP1]], [[X]]
+; CHECK-NEXT:    ret i1 [[CMP]]
+;
+  %nx = xor i8 %x, -1
+  %inc.x = add i8 %x, 1
+  %cmp = icmp sle i8 %inc.x, %nx
+  ret i1 %cmp
+}
+; (X-1) comp X^Neg_C
+define i1 @src_sle_decx_nx(i8 %x) {
+; CHECK-LABEL: @src_sle_decx_nx(
+; CHECK-NEXT:    [[TMP1:%.*]] = sub i8 0, [[X:%.*]]
+; CHECK-NEXT:    [[CMP:%.*]] = icmp sge i8 [[TMP1]], [[X]]
+; CHECK-NEXT:    ret i1 [[CMP]]
+;
+  %nx = xor i8 %x, -1
+  %dec.x = add i8 %x, -1
+  %cmp = icmp sle i8 %dec.x, %nx
+  ret i1 %cmp
+}
+; X comp (X+1)^Neg_C
+define i1 @src_sle_x_nincx(i8 %x) {
+; CHECK-LABEL: @src_sle_x_nincx(
+; CHECK-NEXT:    [[NOT_INC_X:%.*]] = sub i8 -2, [[X:%.*]]
+; CHECK-NEXT:    [[CMP:%.*]] = icmp sge i8 [[NOT_INC_X]], [[X]]
+; CHECK-NEXT:    ret i1 [[CMP]]
+;
+  %inc.x = add i8 %x, 1
+  %not.inc.x = xor i8 %inc.x, -1
+  %cmp = icmp sle i8 %x, %not.inc.x
+  ret i1 %cmp
+}
+; X comp (X-1)^Neg_C
+define i1 @src_sle_x_ndecx(i8 %x) {
+; CHECK-LABEL: @src_sle_x_ndecx(
+; CHECK-NEXT:    [[NOT_DEC_X:%.*]] = sub i8 0, [[X:%.*]]
+; CHECK-NEXT:    [[CMP:%.*]] = icmp sge i8 [[NOT_DEC_X]], [[X]]
+; CHECK-NEXT:    ret i1 [[CMP]]
+;
+  %dec.x = add i8 %x, -1
+  %not.dec.x = xor i8 %dec.x, -1
+  %cmp = icmp sle i8 %x, %not.dec.x
+  ret i1 %cmp
+}
 
 ; test for (~x ^ y) < ~z
 define i1 @test_xor1(i8 %x, i8 %y, i8 %z) {

>From 8e845e3b497e06733022966be5611b3b2aedc5b7 Mon Sep 17 00:00:00 2001
From: Hanbum Park <kese111 at gmail.com>
Date: Fri, 1 Dec 2023 06:32:35 +0900
Subject: [PATCH 2/2] [InstCombine] simplify `X (comp) X^Neg_C` (#57532)

This patch simplifies the comparison between X and X^Neg_X.

comparison between X and X^Neg_C is determined solely by
presence of the sign bit, so we can simplify it to checking
whether X is negative or not.

Proof: https://alive2.llvm.org/ce/z/SnNdem
---
 .../InstCombine/InstCombineCompares.cpp       | 21 ++++
 .../Transforms/InstCombine/icmp-of-xor-x.ll   | 96 +++++++------------
 2 files changed, 53 insertions(+), 64 deletions(-)

diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
index 280c4d77b6dfca..cf2d110f7d6d15 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
@@ -4605,6 +4605,27 @@ static Instruction *foldICmpXorXX(ICmpInst &I, const SimplifyQuery &Q,
       isKnownNonZero(A, Q.DL, /*Depth=*/0, Q.AC, Q.CxtI, Q.DT))
     return new ICmpInst(PredOut, Op0, Op1);
 
+  // These transform works when C is negative.
+  // X s< X^C, X s<= X^C, X u> X^C, X u>= X^C  --> X s< 0
+  // X s> X^C, X s>= X^C, X u< X^C, X u<= X^C  --> X s>= 0
+  if (match(A, m_Negative())) {
+    CmpInst::Predicate NewPred;
+    switch (ICmpInst::getStrictPredicate(Pred)) {
+    default:
+      llvm_unreachable("not a valid predicate");
+    case ICmpInst::ICMP_SLT:
+    case ICmpInst::ICMP_UGT:
+      NewPred = ICmpInst::ICMP_SLT;
+      break;
+    case ICmpInst::ICMP_SGT:
+    case ICmpInst::ICMP_ULT:
+      NewPred = ICmpInst::ICMP_SGE;
+      break;
+    }
+    Constant *Const = Constant::getNullValue(Op0->getType());
+    return new ICmpInst(NewPred, Op0, Const);
+  }
+
   return nullptr;
 }
 
diff --git a/llvm/test/Transforms/InstCombine/icmp-of-xor-x.ll b/llvm/test/Transforms/InstCombine/icmp-of-xor-x.ll
index d8706ef1655957..6b80b09e88151c 100644
--- a/llvm/test/Transforms/InstCombine/icmp-of-xor-x.ll
+++ b/llvm/test/Transforms/InstCombine/icmp-of-xor-x.ll
@@ -11,11 +11,9 @@ declare void @use.vec.i1(<2 x i1>)
 ; X s< X^Neg_C  -->  X s< 0
 define i1 @src_slt(i8 %x, i128 %x.128) {
 ; CHECK-LABEL: @src_slt(
-; CHECK-NEXT:    [[NOT:%.*]] = xor i8 [[X:%.*]], -1
-; CHECK-NEXT:    [[CMP:%.*]] = icmp sgt i8 [[NOT]], [[X]]
+; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i8 [[X:%.*]], 0
 ; CHECK-NEXT:    call void @use.i1(i1 [[CMP]])
-; CHECK-NEXT:    [[NOT_128:%.*]] = xor i128 [[X_128:%.*]], -170141183460469231731687303715884105728
-; CHECK-NEXT:    [[CMP_128:%.*]] = icmp sgt i128 [[NOT_128]], [[X_128]]
+; CHECK-NEXT:    [[CMP_128:%.*]] = icmp slt i128 [[X_128:%.*]], 0
 ; CHECK-NEXT:    ret i1 [[CMP_128]]
 ;
   %not = xor i8 %x, -1
@@ -28,11 +26,9 @@ define i1 @src_slt(i8 %x, i128 %x.128) {
 
 define <2 x i1> @src_slt_vec(<2 x i8> %x) {
 ; CHECK-LABEL: @src_slt_vec(
-; CHECK-NEXT:    [[NOT:%.*]] = xor <2 x i8> [[X:%.*]], <i8 -1, i8 -1>
-; CHECK-NEXT:    [[CMP:%.*]] = icmp sgt <2 x i8> [[NOT]], [[X]]
+; CHECK-NEXT:    [[CMP:%.*]] = icmp slt <2 x i8> [[X:%.*]], zeroinitializer
 ; CHECK-NEXT:    call void @use.vec.i1(<2 x i1> [[CMP]])
-; CHECK-NEXT:    [[NOT_MIN:%.*]] = xor <2 x i8> [[X]], <i8 -128, i8 -128>
-; CHECK-NEXT:    [[CMP_MIN:%.*]] = icmp sgt <2 x i8> [[NOT_MIN]], [[X]]
+; CHECK-NEXT:    [[CMP_MIN:%.*]] = icmp slt <2 x i8> [[X]], zeroinitializer
 ; CHECK-NEXT:    ret <2 x i1> [[CMP_MIN]]
 ;
   %not = xor <2 x i8> %x, <i8 -1, i8 -1>
@@ -46,11 +42,9 @@ define <2 x i1> @src_slt_vec(<2 x i8> %x) {
 ; X s> X^Neg_C  -->  X s> -1
 define i1 @src_sgt(i8 %x, i128 %x.128) {
 ; CHECK-LABEL: @src_sgt(
-; CHECK-NEXT:    [[NOT:%.*]] = xor i8 [[X:%.*]], -1
-; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i8 [[NOT]], [[X]]
+; CHECK-NEXT:    [[CMP:%.*]] = icmp sgt i8 [[X:%.*]], -1
 ; CHECK-NEXT:    call void @use.i1(i1 [[CMP]])
-; CHECK-NEXT:    [[NOT_128:%.*]] = xor i128 [[X_128:%.*]], -170141183460469231731687303715884105728
-; CHECK-NEXT:    [[CMP_128:%.*]] = icmp slt i128 [[NOT_128]], [[X_128]]
+; CHECK-NEXT:    [[CMP_128:%.*]] = icmp sgt i128 [[X_128:%.*]], -1
 ; CHECK-NEXT:    ret i1 [[CMP_128]]
 ;
   %not = xor i8 %x, -1
@@ -63,11 +57,9 @@ define i1 @src_sgt(i8 %x, i128 %x.128) {
 
 define <2 x i1> @src_sgt_vec(<2 x i8> %x) {
 ; CHECK-LABEL: @src_sgt_vec(
-; CHECK-NEXT:    [[NOT:%.*]] = xor <2 x i8> [[X:%.*]], <i8 -1, i8 -1>
-; CHECK-NEXT:    [[CMP:%.*]] = icmp slt <2 x i8> [[NOT]], [[X]]
+; CHECK-NEXT:    [[CMP:%.*]] = icmp sgt <2 x i8> [[X:%.*]], <i8 -1, i8 -1>
 ; CHECK-NEXT:    call void @use.vec.i1(<2 x i1> [[CMP]])
-; CHECK-NEXT:    [[NOT_MIN:%.*]] = xor <2 x i8> [[X]], <i8 -128, i8 -128>
-; CHECK-NEXT:    [[CMP_MIN:%.*]] = icmp slt <2 x i8> [[NOT_MIN]], [[X]]
+; CHECK-NEXT:    [[CMP_MIN:%.*]] = icmp sgt <2 x i8> [[X]], <i8 -1, i8 -1>
 ; CHECK-NEXT:    ret <2 x i1> [[CMP_MIN]]
 ;
   %not = xor <2 x i8> %x, <i8 -1, i8 -1>
@@ -81,11 +73,9 @@ define <2 x i1> @src_sgt_vec(<2 x i8> %x) {
 ; X s<= X^Neg_C  -->  X s< 0
 define i1 @src_sle(i8 %x, i128 %x.128) {
 ; CHECK-LABEL: @src_sle(
-; CHECK-NEXT:    [[NOT:%.*]] = xor i8 [[X:%.*]], -1
-; CHECK-NEXT:    [[CMP:%.*]] = icmp sgt i8 [[NOT]], [[X]]
+; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i8 [[X:%.*]], 0
 ; CHECK-NEXT:    call void @use.i1(i1 [[CMP]])
-; CHECK-NEXT:    [[NOT_128:%.*]] = xor i128 [[X_128:%.*]], -170141183460469231731687303715884105728
-; CHECK-NEXT:    [[CMP_128:%.*]] = icmp sgt i128 [[NOT_128]], [[X_128]]
+; CHECK-NEXT:    [[CMP_128:%.*]] = icmp slt i128 [[X_128:%.*]], 0
 ; CHECK-NEXT:    ret i1 [[CMP_128]]
 ;
   %not = xor i8 %x, -1
@@ -98,11 +88,9 @@ define i1 @src_sle(i8 %x, i128 %x.128) {
 
 define <2 x i1> @src_sle_vec(<2 x i8> %x) {
 ; CHECK-LABEL: @src_sle_vec(
-; CHECK-NEXT:    [[NOT:%.*]] = xor <2 x i8> [[X:%.*]], <i8 -1, i8 -1>
-; CHECK-NEXT:    [[CMP:%.*]] = icmp sgt <2 x i8> [[NOT]], [[X]]
+; CHECK-NEXT:    [[CMP:%.*]] = icmp slt <2 x i8> [[X:%.*]], zeroinitializer
 ; CHECK-NEXT:    call void @use.vec.i1(<2 x i1> [[CMP]])
-; CHECK-NEXT:    [[NOT_MIN:%.*]] = xor <2 x i8> [[X]], <i8 -128, i8 -128>
-; CHECK-NEXT:    [[CMP_MIN:%.*]] = icmp sgt <2 x i8> [[NOT_MIN]], [[X]]
+; CHECK-NEXT:    [[CMP_MIN:%.*]] = icmp slt <2 x i8> [[X]], zeroinitializer
 ; CHECK-NEXT:    ret <2 x i1> [[CMP_MIN]]
 ;
   %not = xor <2 x i8> %x, <i8 -1, i8 -1>
@@ -116,11 +104,9 @@ define <2 x i1> @src_sle_vec(<2 x i8> %x) {
 ; X s>= X^Neg_C  -->  X s> -1
 define i1 @src_sge(i8 %x, i128 %x.128) {
 ; CHECK-LABEL: @src_sge(
-; CHECK-NEXT:    [[NOT:%.*]] = xor i8 [[X:%.*]], -1
-; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i8 [[NOT]], [[X]]
+; CHECK-NEXT:    [[CMP:%.*]] = icmp sgt i8 [[X:%.*]], -1
 ; CHECK-NEXT:    call void @use.i1(i1 [[CMP]])
-; CHECK-NEXT:    [[NOT_128:%.*]] = xor i128 [[X_128:%.*]], -170141183460469231731687303715884105728
-; CHECK-NEXT:    [[CMP_128:%.*]] = icmp slt i128 [[NOT_128]], [[X_128]]
+; CHECK-NEXT:    [[CMP_128:%.*]] = icmp sgt i128 [[X_128:%.*]], -1
 ; CHECK-NEXT:    ret i1 [[CMP_128]]
 ;
   %not = xor i8 %x, -1
@@ -133,11 +119,9 @@ define i1 @src_sge(i8 %x, i128 %x.128) {
 
 define <2 x i1> @src_sge_vec(<2 x i8> %x) {
 ; CHECK-LABEL: @src_sge_vec(
-; CHECK-NEXT:    [[NOT:%.*]] = xor <2 x i8> [[X:%.*]], <i8 -1, i8 -1>
-; CHECK-NEXT:    [[CMP:%.*]] = icmp slt <2 x i8> [[NOT]], [[X]]
+; CHECK-NEXT:    [[CMP:%.*]] = icmp sgt <2 x i8> [[X:%.*]], <i8 -1, i8 -1>
 ; CHECK-NEXT:    call void @use.vec.i1(<2 x i1> [[CMP]])
-; CHECK-NEXT:    [[NOT_MIN:%.*]] = xor <2 x i8> [[X]], <i8 -128, i8 -128>
-; CHECK-NEXT:    [[CMP_MIN:%.*]] = icmp slt <2 x i8> [[NOT_MIN]], [[X]]
+; CHECK-NEXT:    [[CMP_MIN:%.*]] = icmp sgt <2 x i8> [[X]], <i8 -1, i8 -1>
 ; CHECK-NEXT:    ret <2 x i1> [[CMP_MIN]]
 ;
   %not = xor <2 x i8> %x, <i8 -1, i8 -1>
@@ -152,11 +136,9 @@ define <2 x i1> @src_sge_vec(<2 x i8> %x) {
 ; X u< X^Neg_C  -->  X s> -1
 define i1 @src_ult(i8 %x, i128 %x.128) {
 ; CHECK-LABEL: @src_ult(
-; CHECK-NEXT:    [[NOT:%.*]] = xor i8 [[X:%.*]], -1
-; CHECK-NEXT:    [[CMP:%.*]] = icmp ugt i8 [[NOT]], [[X]]
+; CHECK-NEXT:    [[CMP:%.*]] = icmp sgt i8 [[X:%.*]], -1
 ; CHECK-NEXT:    call void @use.i1(i1 [[CMP]])
-; CHECK-NEXT:    [[NOT_128:%.*]] = xor i128 [[X_128:%.*]], -170141183460469231731687303715884105728
-; CHECK-NEXT:    [[CMP_128:%.*]] = icmp ugt i128 [[NOT_128]], [[X_128]]
+; CHECK-NEXT:    [[CMP_128:%.*]] = icmp sgt i128 [[X_128:%.*]], -1
 ; CHECK-NEXT:    ret i1 [[CMP_128]]
 ;
   %not = xor i8 %x, -1
@@ -169,11 +151,9 @@ define i1 @src_ult(i8 %x, i128 %x.128) {
 
 define <2 x i1> @src_ult_vec(<2 x i8> %x) {
 ; CHECK-LABEL: @src_ult_vec(
-; CHECK-NEXT:    [[NOT:%.*]] = xor <2 x i8> [[X:%.*]], <i8 -1, i8 -1>
-; CHECK-NEXT:    [[CMP:%.*]] = icmp ugt <2 x i8> [[NOT]], [[X]]
+; CHECK-NEXT:    [[CMP:%.*]] = icmp sgt <2 x i8> [[X:%.*]], <i8 -1, i8 -1>
 ; CHECK-NEXT:    call void @use.vec.i1(<2 x i1> [[CMP]])
-; CHECK-NEXT:    [[NOT_MIN:%.*]] = xor <2 x i8> [[X]], <i8 -128, i8 -128>
-; CHECK-NEXT:    [[CMP_MIN:%.*]] = icmp ugt <2 x i8> [[NOT_MIN]], [[X]]
+; CHECK-NEXT:    [[CMP_MIN:%.*]] = icmp sgt <2 x i8> [[X]], <i8 -1, i8 -1>
 ; CHECK-NEXT:    ret <2 x i1> [[CMP_MIN]]
 ;
   %not = xor <2 x i8> %x, <i8 -1, i8 -1>
@@ -187,11 +167,9 @@ define <2 x i1> @src_ult_vec(<2 x i8> %x) {
 ; X u> X^Neg_C  -->  X s< 0
 define i1 @src_ugt(i8 %x, i128 %x.128) {
 ; CHECK-LABEL: @src_ugt(
-; CHECK-NEXT:    [[NOT:%.*]] = xor i8 [[X:%.*]], -1
-; CHECK-NEXT:    [[CMP:%.*]] = icmp ult i8 [[NOT]], [[X]]
+; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i8 [[X:%.*]], 0
 ; CHECK-NEXT:    call void @use.i1(i1 [[CMP]])
-; CHECK-NEXT:    [[NOT_128:%.*]] = xor i128 [[X_128:%.*]], -170141183460469231731687303715884105728
-; CHECK-NEXT:    [[CMP_128:%.*]] = icmp ult i128 [[NOT_128]], [[X_128]]
+; CHECK-NEXT:    [[CMP_128:%.*]] = icmp slt i128 [[X_128:%.*]], 0
 ; CHECK-NEXT:    ret i1 [[CMP_128]]
 ;
   %not = xor i8 %x, -1
@@ -204,11 +182,9 @@ define i1 @src_ugt(i8 %x, i128 %x.128) {
 
 define <2 x i1> @src_ugt_vec(<2 x i8> %x) {
 ; CHECK-LABEL: @src_ugt_vec(
-; CHECK-NEXT:    [[NOT:%.*]] = xor <2 x i8> [[X:%.*]], <i8 -1, i8 -1>
-; CHECK-NEXT:    [[CMP:%.*]] = icmp ult <2 x i8> [[NOT]], [[X]]
+; CHECK-NEXT:    [[CMP:%.*]] = icmp slt <2 x i8> [[X:%.*]], zeroinitializer
 ; CHECK-NEXT:    call void @use.vec.i1(<2 x i1> [[CMP]])
-; CHECK-NEXT:    [[NOT_MIN:%.*]] = xor <2 x i8> [[X]], <i8 -128, i8 -128>
-; CHECK-NEXT:    [[CMP_MIN:%.*]] = icmp ult <2 x i8> [[NOT_MIN]], [[X]]
+; CHECK-NEXT:    [[CMP_MIN:%.*]] = icmp slt <2 x i8> [[X]], zeroinitializer
 ; CHECK-NEXT:    ret <2 x i1> [[CMP_MIN]]
 ;
   %not = xor <2 x i8> %x, <i8 -1, i8 -1>
@@ -222,11 +198,9 @@ define <2 x i1> @src_ugt_vec(<2 x i8> %x) {
 ; X u<= X^Neg_C  -->  X s> -1
 define i1 @src_ule(i8 %x, i128 %x.128) {
 ; CHECK-LABEL: @src_ule(
-; CHECK-NEXT:    [[NOT:%.*]] = xor i8 [[X:%.*]], -1
-; CHECK-NEXT:    [[CMP:%.*]] = icmp ugt i8 [[NOT]], [[X]]
+; CHECK-NEXT:    [[CMP:%.*]] = icmp sgt i8 [[X:%.*]], -1
 ; CHECK-NEXT:    call void @use.i1(i1 [[CMP]])
-; CHECK-NEXT:    [[NOT_128:%.*]] = xor i128 [[X_128:%.*]], -170141183460469231731687303715884105728
-; CHECK-NEXT:    [[CMP_128:%.*]] = icmp ugt i128 [[NOT_128]], [[X_128]]
+; CHECK-NEXT:    [[CMP_128:%.*]] = icmp sgt i128 [[X_128:%.*]], -1
 ; CHECK-NEXT:    ret i1 [[CMP_128]]
 ;
   %not = xor i8 %x, -1
@@ -239,11 +213,9 @@ define i1 @src_ule(i8 %x, i128 %x.128) {
 
 define <2 x i1> @src_ule_vec(<2 x i8> %x) {
 ; CHECK-LABEL: @src_ule_vec(
-; CHECK-NEXT:    [[NOT:%.*]] = xor <2 x i8> [[X:%.*]], <i8 -1, i8 -1>
-; CHECK-NEXT:    [[CMP:%.*]] = icmp ugt <2 x i8> [[NOT]], [[X]]
+; CHECK-NEXT:    [[CMP:%.*]] = icmp sgt <2 x i8> [[X:%.*]], <i8 -1, i8 -1>
 ; CHECK-NEXT:    call void @use.vec.i1(<2 x i1> [[CMP]])
-; CHECK-NEXT:    [[NOT_MIN:%.*]] = xor <2 x i8> [[X]], <i8 -128, i8 -128>
-; CHECK-NEXT:    [[CMP_MIN:%.*]] = icmp ugt <2 x i8> [[NOT_MIN]], [[X]]
+; CHECK-NEXT:    [[CMP_MIN:%.*]] = icmp sgt <2 x i8> [[X]], <i8 -1, i8 -1>
 ; CHECK-NEXT:    ret <2 x i1> [[CMP_MIN]]
 ;
   %not = xor <2 x i8> %x, <i8 -1, i8 -1>
@@ -257,11 +229,9 @@ define <2 x i1> @src_ule_vec(<2 x i8> %x) {
 ; X u>= X^Neg_C  -->  X s< 0
 define i1 @src_uge(i8 %x, i128 %x.128) {
 ; CHECK-LABEL: @src_uge(
-; CHECK-NEXT:    [[NOT:%.*]] = xor i8 [[X:%.*]], -1
-; CHECK-NEXT:    [[CMP:%.*]] = icmp ult i8 [[NOT]], [[X]]
+; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i8 [[X:%.*]], 0
 ; CHECK-NEXT:    call void @use.i1(i1 [[CMP]])
-; CHECK-NEXT:    [[NOT_128:%.*]] = xor i128 [[X_128:%.*]], -170141183460469231731687303715884105728
-; CHECK-NEXT:    [[CMP_128:%.*]] = icmp ult i128 [[NOT_128]], [[X_128]]
+; CHECK-NEXT:    [[CMP_128:%.*]] = icmp slt i128 [[X_128:%.*]], 0
 ; CHECK-NEXT:    ret i1 [[CMP_128]]
 ;
   %not = xor i8 %x, -1
@@ -274,11 +244,9 @@ define i1 @src_uge(i8 %x, i128 %x.128) {
 
 define <2 x i1> @src_uge_vec(<2 x i8> %x) {
 ; CHECK-LABEL: @src_uge_vec(
-; CHECK-NEXT:    [[NOT:%.*]] = xor <2 x i8> [[X:%.*]], <i8 -1, i8 -1>
-; CHECK-NEXT:    [[CMP:%.*]] = icmp ult <2 x i8> [[NOT]], [[X]]
+; CHECK-NEXT:    [[CMP:%.*]] = icmp slt <2 x i8> [[X:%.*]], zeroinitializer
 ; CHECK-NEXT:    call void @use.vec.i1(<2 x i1> [[CMP]])
-; CHECK-NEXT:    [[NOT_MIN:%.*]] = xor <2 x i8> [[X]], <i8 -128, i8 -128>
-; CHECK-NEXT:    [[CMP_MIN:%.*]] = icmp ult <2 x i8> [[NOT_MIN]], [[X]]
+; CHECK-NEXT:    [[CMP_MIN:%.*]] = icmp slt <2 x i8> [[X]], zeroinitializer
 ; CHECK-NEXT:    ret <2 x i1> [[CMP_MIN]]
 ;
   %not = xor <2 x i8> %x, <i8 -1, i8 -1>



More information about the llvm-commits mailing list