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

via llvm-commits llvm-commits at lists.llvm.org
Tue Jan 9 16:07:01 PST 2024


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

>From e51a20997bfb7dc46f078159002659456d7d9c83 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`

simplify compare between specific variable `X` and  `NOT(X)`

Proof: https://alive2.llvm.org/ce/z/AXlRm5
---
 .../Transforms/InstCombine/icmp-of-xor-x.ll   | 554 ++++++++++++++++++
 1 file changed, 554 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..6c05906980d158 100644
--- a/llvm/test/Transforms/InstCombine/icmp-of-xor-x.ll
+++ b/llvm/test/Transforms/InstCombine/icmp-of-xor-x.ll
@@ -5,6 +5,560 @@ declare void @llvm.assume(i1)
 declare void @barrier()
 declare void @use.i8(i8)
 
+; X op ~X tests. op signed
+; https://alive2.llvm.org/ce/z/ZcDMKE
+; X s< ~X   -->      X s< 0
+define i1 @src_slt(i8 %x) {
+; CHECK-LABEL: @src_slt(
+; CHECK-NEXT:    [[NOT:%.*]] = xor i8 [[X:%.*]], -1
+; CHECK-NEXT:    [[CMP:%.*]] = icmp sgt i8 [[NOT]], [[X]]
+; CHECK-NEXT:    ret i1 [[CMP]]
+;
+  %not = xor i8 %x, -1
+  %cmp = icmp slt i8 %x, %not
+  ret i1 %cmp
+}
+define i1 @src_slt_i128(i128 %x) {
+; CHECK-LABEL: @src_slt_i128(
+; CHECK-NEXT:    [[NOT:%.*]] = xor i128 [[X:%.*]], -1
+; CHECK-NEXT:    [[CMP:%.*]] = icmp sgt i128 [[NOT]], [[X]]
+; CHECK-NEXT:    ret i1 [[CMP]]
+;
+  %not = xor i128 %x, -1
+  %cmp = icmp slt i128 %x, %not
+  ret i1 %cmp
+}
+; X s> ~X   -->     X s> -1
+define i1 @src_sgt(i8 %x) {
+; CHECK-LABEL: @src_sgt(
+; CHECK-NEXT:    [[NOT:%.*]] = xor i8 [[X:%.*]], -1
+; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i8 [[NOT]], [[X]]
+; CHECK-NEXT:    ret i1 [[CMP]]
+;
+  %not = xor i8 %x, -1
+  %cmp = icmp sgt i8 %x, %not
+  ret i1 %cmp
+}
+define i1 @src_sgt_i128(i128 %x) {
+; CHECK-LABEL: @src_sgt_i128(
+; CHECK-NEXT:    [[NOT:%.*]] = xor i128 [[X:%.*]], -1
+; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i128 [[NOT]], [[X]]
+; CHECK-NEXT:    ret i1 [[CMP]]
+;
+  %not = xor i128 %x, -1
+  %cmp = icmp sgt i128 %x, %not
+  ret i1 %cmp
+}
+; X s<= ~X   -->      X s< 0
+define i1 @src_sle(i8 %x) {
+; CHECK-LABEL: @src_sle(
+; CHECK-NEXT:    [[NOT:%.*]] = xor i8 [[X:%.*]], -1
+; CHECK-NEXT:    [[CMP:%.*]] = icmp sgt i8 [[NOT]], [[X]]
+; CHECK-NEXT:    ret i1 [[CMP]]
+;
+  %not = xor i8 %x, -1
+  %cmp = icmp sle i8 %x, %not
+  ret i1 %cmp
+}
+define i1 @src_sle_i128(i128 %x) {
+; CHECK-LABEL: @src_sle_i128(
+; CHECK-NEXT:    [[NOT:%.*]] = xor i128 [[X:%.*]], -1
+; CHECK-NEXT:    [[CMP:%.*]] = icmp sgt i128 [[NOT]], [[X]]
+; CHECK-NEXT:    ret i1 [[CMP]]
+;
+  %not = xor i128 %x, -1
+  %cmp = icmp sle i128 %x, %not
+  ret i1 %cmp
+}
+; X s>= ~X   -->      X s> -1
+define i1 @src_sge(i8 %x) {
+; CHECK-LABEL: @src_sge(
+; CHECK-NEXT:    [[NOT:%.*]] = xor i8 [[X:%.*]], -1
+; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i8 [[NOT]], [[X]]
+; CHECK-NEXT:    ret i1 [[CMP]]
+;
+  %not = xor i8 %x, -1
+  %cmp = icmp sge i8 %x, %not
+  ret i1 %cmp
+}
+define i1 @src_sge_i128(i128 %x) {
+; CHECK-LABEL: @src_sge_i128(
+; CHECK-NEXT:    [[NOT:%.*]] = xor i128 [[X:%.*]], -1
+; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i128 [[NOT]], [[X]]
+; CHECK-NEXT:    ret i1 [[CMP]]
+;
+  %not = xor i128 %x, -1
+  %cmp = icmp sge i128 %x, %not
+  ret i1 %cmp
+}
+; X op ~X tests. op signed. commutative
+; https://alive2.llvm.org/ce/z/u_useB
+; ~X s< X   -->      X s> -1
+define i1 @src_slt_comm(i8 %x) {
+; CHECK-LABEL: @src_slt_comm(
+; CHECK-NEXT:    [[NOT:%.*]] = xor i8 [[X:%.*]], -1
+; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i8 [[NOT]], [[X]]
+; CHECK-NEXT:    ret i1 [[CMP]]
+;
+  %not = xor i8 %x, -1
+  %cmp = icmp slt i8 %not, %x
+  ret i1 %cmp
+}
+define i1 @src_slt_i128_comm(i128 %x) {
+; CHECK-LABEL: @src_slt_i128_comm(
+; CHECK-NEXT:    [[NOT:%.*]] = xor i128 [[X:%.*]], -1
+; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i128 [[NOT]], [[X]]
+; CHECK-NEXT:    ret i1 [[CMP]]
+;
+  %not = xor i128 %x, -1
+  %cmp = icmp slt i128 %not, %x
+  ret i1 %cmp
+}
+; ~X s> X   -->     X s< 0
+define i1 @src_sgt_comm(i8 %x) {
+; CHECK-LABEL: @src_sgt_comm(
+; CHECK-NEXT:    [[NOT:%.*]] = xor i8 [[X:%.*]], -1
+; CHECK-NEXT:    [[CMP:%.*]] = icmp sgt i8 [[NOT]], [[X]]
+; CHECK-NEXT:    ret i1 [[CMP]]
+;
+  %not = xor i8 %x, -1
+  %cmp = icmp sgt i8 %not, %x
+  ret i1 %cmp
+}
+define i1 @src_sgt_i128_comm(i128 %x) {
+; CHECK-LABEL: @src_sgt_i128_comm(
+; CHECK-NEXT:    [[NOT:%.*]] = xor i128 [[X:%.*]], -1
+; CHECK-NEXT:    [[CMP:%.*]] = icmp sgt i128 [[NOT]], [[X]]
+; CHECK-NEXT:    ret i1 [[CMP]]
+;
+  %not = xor i128 %x, -1
+  %cmp = icmp sgt i128 %not, %x
+  ret i1 %cmp
+}
+; ~X s<= X   -->      X s> -1
+define i1 @src_sle_comm(i8 %x) {
+; CHECK-LABEL: @src_sle_comm(
+; CHECK-NEXT:    [[NOT:%.*]] = xor i8 [[X:%.*]], -1
+; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i8 [[NOT]], [[X]]
+; CHECK-NEXT:    ret i1 [[CMP]]
+;
+  %not = xor i8 %x, -1
+  %cmp = icmp sle i8 %not, %x
+  ret i1 %cmp
+}
+define i1 @src_sle_i128_comm(i128 %x) {
+; CHECK-LABEL: @src_sle_i128_comm(
+; CHECK-NEXT:    [[NOT:%.*]] = xor i128 [[X:%.*]], -1
+; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i128 [[NOT]], [[X]]
+; CHECK-NEXT:    ret i1 [[CMP]]
+;
+  %not = xor i128 %x, -1
+  %cmp = icmp sle i128 %not, %x
+  ret i1 %cmp
+}
+; ~X s>= X   -->      X s< 0
+define i1 @src_sge_comm(i8 %x) {
+; CHECK-LABEL: @src_sge_comm(
+; CHECK-NEXT:    [[NOT:%.*]] = xor i8 [[X:%.*]], -1
+; CHECK-NEXT:    [[CMP:%.*]] = icmp sgt i8 [[NOT]], [[X]]
+; CHECK-NEXT:    ret i1 [[CMP]]
+;
+  %not = xor i8 %x, -1
+  %cmp = icmp sge i8 %not, %x
+  ret i1 %cmp
+}
+define i1 @src_sge_i128_comm(i128 %x) {
+; CHECK-LABEL: @src_sge_i128_comm(
+; CHECK-NEXT:    [[NOT:%.*]] = xor i128 [[X:%.*]], -1
+; CHECK-NEXT:    [[CMP:%.*]] = icmp sgt i128 [[NOT]], [[X]]
+; CHECK-NEXT:    ret i1 [[CMP]]
+;
+  %not = xor i128 %x, -1
+  %cmp = icmp sge i128 %not, %x
+  ret i1 %cmp
+}
+
+; X op ~X tests. op unsigned
+; https://alive2.llvm.org/ce/z/YbHNwu
+; X u< ~X   -->      X s> -1
+define i1 @src_ult(i8 %x) {
+; CHECK-LABEL: @src_ult(
+; CHECK-NEXT:    [[NOT:%.*]] = xor i8 [[X:%.*]], -1
+; CHECK-NEXT:    [[CMP:%.*]] = icmp ugt i8 [[NOT]], [[X]]
+; CHECK-NEXT:    ret i1 [[CMP]]
+;
+  %not = xor i8 %x, -1
+  %cmp = icmp ult i8 %x, %not
+  ret i1 %cmp
+}
+define i1 @src_ult_i128(i128 %x) {
+; CHECK-LABEL: @src_ult_i128(
+; CHECK-NEXT:    [[NOT:%.*]] = xor i128 [[X:%.*]], -1
+; CHECK-NEXT:    [[CMP:%.*]] = icmp ugt i128 [[NOT]], [[X]]
+; CHECK-NEXT:    ret i1 [[CMP]]
+;
+  %not = xor i128 %x, -1
+  %cmp = icmp ult i128 %x, %not
+  ret i1 %cmp
+}
+; X u> ~X   -->     X s< 0
+define i1 @src_ugt(i8 %x) {
+; CHECK-LABEL: @src_ugt(
+; CHECK-NEXT:    [[NOT:%.*]] = xor i8 [[X:%.*]], -1
+; CHECK-NEXT:    [[CMP:%.*]] = icmp ult i8 [[NOT]], [[X]]
+; CHECK-NEXT:    ret i1 [[CMP]]
+;
+  %not = xor i8 %x, -1
+  %cmp = icmp ugt i8 %x, %not
+  ret i1 %cmp
+}
+define i1 @src_ugt_i128(i128 %x) {
+; CHECK-LABEL: @src_ugt_i128(
+; CHECK-NEXT:    [[NOT:%.*]] = xor i128 [[X:%.*]], -1
+; CHECK-NEXT:    [[CMP:%.*]] = icmp ult i128 [[NOT]], [[X]]
+; CHECK-NEXT:    ret i1 [[CMP]]
+;
+  %not = xor i128 %x, -1
+  %cmp = icmp ugt i128 %x, %not
+  ret i1 %cmp
+}
+; X u<= ~X   -->      X s> -1
+define i1 @src_ule(i8 %x) {
+; CHECK-LABEL: @src_ule(
+; CHECK-NEXT:    [[NOT:%.*]] = xor i8 [[X:%.*]], -1
+; CHECK-NEXT:    [[CMP:%.*]] = icmp ugt i8 [[NOT]], [[X]]
+; CHECK-NEXT:    ret i1 [[CMP]]
+;
+  %not = xor i8 %x, -1
+  %cmp = icmp ule i8 %x, %not
+  ret i1 %cmp
+}
+define i1 @src_ule_i128(i128 %x) {
+; CHECK-LABEL: @src_ule_i128(
+; CHECK-NEXT:    [[NOT:%.*]] = xor i128 [[X:%.*]], -1
+; CHECK-NEXT:    [[CMP:%.*]] = icmp ugt i128 [[NOT]], [[X]]
+; CHECK-NEXT:    ret i1 [[CMP]]
+;
+  %not = xor i128 %x, -1
+  %cmp = icmp ule i128 %x, %not
+  ret i1 %cmp
+}
+; X u>= ~X   -->      X s< 0
+define i1 @src_uge(i8 %x) {
+; CHECK-LABEL: @src_uge(
+; CHECK-NEXT:    [[NOT:%.*]] = xor i8 [[X:%.*]], -1
+; CHECK-NEXT:    [[CMP:%.*]] = icmp ult i8 [[NOT]], [[X]]
+; CHECK-NEXT:    ret i1 [[CMP]]
+;
+  %not = xor i8 %x, -1
+  %cmp = icmp uge i8 %x, %not
+  ret i1 %cmp
+}
+define i1 @src_uge_i128(i128 %x) {
+; CHECK-LABEL: @src_uge_i128(
+; CHECK-NEXT:    [[NOT:%.*]] = xor i128 [[X:%.*]], -1
+; CHECK-NEXT:    [[CMP:%.*]] = icmp ult i128 [[NOT]], [[X]]
+; CHECK-NEXT:    ret i1 [[CMP]]
+;
+  %not = xor i128 %x, -1
+  %cmp = icmp uge i128 %x, %not
+  ret i1 %cmp
+}
+; X op ~X tests. op unsigned. commutative
+; https://alive2.llvm.org/ce/z/qwbBur
+; ~X u< X   -->      X s< 0
+define i1 @src_ult_comm(i8 %x) {
+; CHECK-LABEL: @src_ult_comm(
+; CHECK-NEXT:    [[NOT:%.*]] = xor i8 [[X:%.*]], -1
+; CHECK-NEXT:    [[CMP:%.*]] = icmp ult i8 [[NOT]], [[X]]
+; CHECK-NEXT:    ret i1 [[CMP]]
+;
+  %not = xor i8 %x, -1
+  %cmp = icmp ult i8 %not, %x
+  ret i1 %cmp
+}
+define i1 @src_ult_i128_comm(i128 %x) {
+; CHECK-LABEL: @src_ult_i128_comm(
+; CHECK-NEXT:    [[NOT:%.*]] = xor i128 [[X:%.*]], -1
+; CHECK-NEXT:    [[CMP:%.*]] = icmp ult i128 [[NOT]], [[X]]
+; CHECK-NEXT:    ret i1 [[CMP]]
+;
+  %not = xor i128 %x, -1
+  %cmp = icmp ult i128 %not, %x
+  ret i1 %cmp
+}
+; ~X u> X   -->     X s> -1
+define i1 @src_ugt_comm(i8 %x) {
+; CHECK-LABEL: @src_ugt_comm(
+; CHECK-NEXT:    [[NOT:%.*]] = xor i8 [[X:%.*]], -1
+; CHECK-NEXT:    [[CMP:%.*]] = icmp ugt i8 [[NOT]], [[X]]
+; CHECK-NEXT:    ret i1 [[CMP]]
+;
+  %not = xor i8 %x, -1
+  %cmp = icmp ugt i8 %not, %x
+  ret i1 %cmp
+}
+define i1 @src_ugt_i128_comm(i128 %x) {
+; CHECK-LABEL: @src_ugt_i128_comm(
+; CHECK-NEXT:    [[NOT:%.*]] = xor i128 [[X:%.*]], -1
+; CHECK-NEXT:    [[CMP:%.*]] = icmp ugt i128 [[NOT]], [[X]]
+; CHECK-NEXT:    ret i1 [[CMP]]
+;
+  %not = xor i128 %x, -1
+  %cmp = icmp ugt i128 %not, %x
+  ret i1 %cmp
+}
+; ~X u<= X   -->      X s< 0
+define i1 @src_ule_comm(i8 %x) {
+; CHECK-LABEL: @src_ule_comm(
+; CHECK-NEXT:    [[NOT:%.*]] = xor i8 [[X:%.*]], -1
+; CHECK-NEXT:    [[CMP:%.*]] = icmp ult i8 [[NOT]], [[X]]
+; CHECK-NEXT:    ret i1 [[CMP]]
+;
+  %not = xor i8 %x, -1
+  %cmp = icmp ule i8 %not, %x
+  ret i1 %cmp
+}
+define i1 @src_ule_i128_comm(i128 %x) {
+; CHECK-LABEL: @src_ule_i128_comm(
+; CHECK-NEXT:    [[NOT:%.*]] = xor i128 [[X:%.*]], -1
+; CHECK-NEXT:    [[CMP:%.*]] = icmp ult i128 [[NOT]], [[X]]
+; CHECK-NEXT:    ret i1 [[CMP]]
+;
+  %not = xor i128 %x, -1
+  %cmp = icmp ule i128 %not, %x
+  ret i1 %cmp
+}
+; ~X u>= X   -->      X s> -1
+define i1 @src_uge_comm(i8 %x) {
+; CHECK-LABEL: @src_uge_comm(
+; CHECK-NEXT:    [[NOT:%.*]] = xor i8 [[X:%.*]], -1
+; CHECK-NEXT:    [[CMP:%.*]] = icmp ugt i8 [[NOT]], [[X]]
+; CHECK-NEXT:    ret i1 [[CMP]]
+;
+  %not = xor i8 %x, -1
+  %cmp = icmp uge i8 %not, %x
+  ret i1 %cmp
+}
+define i1 @src_uge_i128_comm(i128 %x) {
+; CHECK-LABEL: @src_uge_i128_comm(
+; CHECK-NEXT:    [[NOT:%.*]] = xor i128 [[X:%.*]], -1
+; CHECK-NEXT:    [[CMP:%.*]] = icmp ugt i128 [[NOT]], [[X]]
+; CHECK-NEXT:    ret i1 [[CMP]]
+;
+  %not = xor i128 %x, -1
+  %cmp = icmp uge i128 %not, %x
+  ret i1 %cmp
+}
+
+; X op ~X tests. euqality
+; https://alive2.llvm.org/ce/z/xiEzXg
+; X == ~X  -> false
+define i1 @src_eq(i8 %x) {
+; CHECK-LABEL: @src_eq(
+; CHECK-NEXT:    ret i1 false
+;
+  %not = xor i8 %x, -1
+  %cmp = icmp eq i8 %x, %not
+  ret i1 %cmp
+}
+define i1 @src_eq_i128(i128 %x) {
+; CHECK-LABEL: @src_eq_i128(
+; CHECK-NEXT:    ret i1 false
+;
+  %not = xor i128 %x, -1
+  %cmp = icmp eq i128 %x, %not
+  ret i1 %cmp
+}
+; X != ~X -> true
+define i1 @src_ne(i8 %x) {
+; CHECK-LABEL: @src_ne(
+; CHECK-NEXT:    ret i1 true
+;
+  %not = xor i8 %x, -1
+  %cmp = icmp ne i8 %x, %not
+  ret i1 %cmp
+}
+define i1 @src_ne_i128(i128 %x) {
+; CHECK-LABEL: @src_ne_i128(
+; CHECK-NEXT:    ret i1 true
+;
+  %not = xor i128 %x, -1
+  %cmp = icmp ne i128 %x, %not
+  ret i1 %cmp
+}
+
+; X op ~X tests. euqality. commutative
+; https://alive2.llvm.org/ce/z/9-nw7i
+; ~X == X  -> false
+define i1 @src_eq_comm(i8 %x) {
+; CHECK-LABEL: @src_eq_comm(
+; CHECK-NEXT:    ret i1 false
+;
+  %not = xor i8 %x, -1
+  %cmp = icmp eq i8 %not, %x
+  ret i1 %cmp
+}
+define i1 @src_eq_i128_comm(i128 %x) {
+; CHECK-LABEL: @src_eq_i128_comm(
+; CHECK-NEXT:    ret i1 false
+;
+  %not = xor i128 %x, -1
+  %cmp = icmp eq i128 %not, %x
+  ret i1 %cmp
+}
+; ~X != X -> true
+define i1 @src_ne_comm(i8 %x) {
+; CHECK-LABEL: @src_ne_comm(
+; CHECK-NEXT:    ret i1 true
+;
+  %not = xor i8 %x, -1
+  %cmp = icmp ne i8 %not, %x
+  ret i1 %cmp
+}
+define i1 @src_ne_i128_comm(i128 %x) {
+; CHECK-LABEL: @src_ne_i128_comm(
+; CHECK-NEXT:    ret i1 true
+;
+  %not = xor i128 %x, -1
+  %cmp = icmp ne i128 %not, %x
+  ret i1 %cmp
+}
+
+; X op ~X tests. negative
+; https://alive2.llvm.org/ce/z/bpGQBU
+; X op 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 op ~X tests. negative
+; (X+1) op ~X
+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) op ~X
+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 op ~(X+1)
+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 op ~(X-1)
+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) {
 ; CHECK-LABEL: @test_xor1(

>From c2c55c656b4ea4a249a6c7449ebcc86dcbbc4a50 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`

simplify compare between specific variable `X` and  `NOT(X)`

Proof: https://alive2.llvm.org/ce/z/eW-L_G

Fixed #57532.
---
 .../InstCombine/InstCombineCompares.cpp       | 37 ++++++-
 .../Transforms/InstCombine/icmp-of-xor-x.ll   | 96 +++++++------------
 2 files changed, 66 insertions(+), 67 deletions(-)

diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
index a2ff8f3eef8199..5bd3849857c972 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
@@ -4540,14 +4540,45 @@ static Instruction *foldICmpXorXX(ICmpInst &I, const SimplifyQuery &Q,
   if (!match(Op0, m_c_Xor(m_Specific(Op1), m_Value(A))))
     return nullptr;
 
+  CmpInst::Predicate StrictPred = ICmpInst::getStrictPredicate(Pred);
+  // Transform
+  // X s< ~X, X s<= ~X, X u> ~X, X u>= ~X
+  // --> X s< 0
+  // X s> ~X, X s>= ~X, X u< ~X, X u<= ~X
+  // --> X s> -1
+  // X ==  ~X  -->   false
+  // X !=  ~X  -->   true
+  if (match(Op0, m_Not(m_Specific(Op1)))) {
+    CmpInst::Predicate NewPred;
+    switch (StrictPred) {
+    case ICmpInst::ICMP_EQ:
+      return IC.replaceInstUsesWith(I, ConstantInt::getFalse(I.getType()));
+    case ICmpInst::ICMP_NE:
+      return IC.replaceInstUsesWith(I, ConstantInt::getTrue(I.getType()));
+    case ICmpInst::ICMP_SLT:
+    case ICmpInst::ICMP_UGT:
+      NewPred = ICmpInst::ICMP_SGT;
+      break;
+    case ICmpInst::ICMP_SGT:
+    case ICmpInst::ICMP_ULT:
+      NewPred = ICmpInst::ICMP_SLT;
+      break;
+    default:
+      llvm_unreachable("not a valid predicate");
+    }
+    Constant *Const = NewPred == ICmpInst::ICMP_SLT
+                          ? Constant::getNullValue(Op1->getType())
+                          : Constant::getAllOnesValue(Op1->getType());
+    return new ICmpInst(NewPred, Op1, Const);
+  }
+
   // icmp (X ^ Y_NonZero) u>= X --> icmp (X ^ Y_NonZero) u> X
   // icmp (X ^ Y_NonZero) u<= X --> icmp (X ^ Y_NonZero) u< X
   // icmp (X ^ Y_NonZero) s>= X --> icmp (X ^ Y_NonZero) s> X
   // icmp (X ^ Y_NonZero) s<= X --> icmp (X ^ Y_NonZero) s< X
-  CmpInst::Predicate PredOut = CmpInst::getStrictPredicate(Pred);
-  if (PredOut != Pred &&
+  if (StrictPred != Pred &&
       isKnownNonZero(A, Q.DL, /*Depth=*/0, Q.AC, Q.CxtI, Q.DT))
-    return new ICmpInst(PredOut, Op0, Op1);
+    return new ICmpInst(StrictPred, Op0, Op1);
 
   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 6c05906980d158..d8ca1fb1c041d7 100644
--- a/llvm/test/Transforms/InstCombine/icmp-of-xor-x.ll
+++ b/llvm/test/Transforms/InstCombine/icmp-of-xor-x.ll
@@ -10,8 +10,7 @@ declare void @use.i8(i8)
 ; X s< ~X   -->      X s< 0
 define i1 @src_slt(i8 %x) {
 ; 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:    ret i1 [[CMP]]
 ;
   %not = xor i8 %x, -1
@@ -20,8 +19,7 @@ define i1 @src_slt(i8 %x) {
 }
 define i1 @src_slt_i128(i128 %x) {
 ; CHECK-LABEL: @src_slt_i128(
-; CHECK-NEXT:    [[NOT:%.*]] = xor i128 [[X:%.*]], -1
-; CHECK-NEXT:    [[CMP:%.*]] = icmp sgt i128 [[NOT]], [[X]]
+; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i128 [[X:%.*]], 0
 ; CHECK-NEXT:    ret i1 [[CMP]]
 ;
   %not = xor i128 %x, -1
@@ -31,8 +29,7 @@ define i1 @src_slt_i128(i128 %x) {
 ; X s> ~X   -->     X s> -1
 define i1 @src_sgt(i8 %x) {
 ; 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:    ret i1 [[CMP]]
 ;
   %not = xor i8 %x, -1
@@ -41,8 +38,7 @@ define i1 @src_sgt(i8 %x) {
 }
 define i1 @src_sgt_i128(i128 %x) {
 ; CHECK-LABEL: @src_sgt_i128(
-; CHECK-NEXT:    [[NOT:%.*]] = xor i128 [[X:%.*]], -1
-; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i128 [[NOT]], [[X]]
+; CHECK-NEXT:    [[CMP:%.*]] = icmp sgt i128 [[X:%.*]], -1
 ; CHECK-NEXT:    ret i1 [[CMP]]
 ;
   %not = xor i128 %x, -1
@@ -52,8 +48,7 @@ define i1 @src_sgt_i128(i128 %x) {
 ; X s<= ~X   -->      X s< 0
 define i1 @src_sle(i8 %x) {
 ; 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:    ret i1 [[CMP]]
 ;
   %not = xor i8 %x, -1
@@ -62,8 +57,7 @@ define i1 @src_sle(i8 %x) {
 }
 define i1 @src_sle_i128(i128 %x) {
 ; CHECK-LABEL: @src_sle_i128(
-; CHECK-NEXT:    [[NOT:%.*]] = xor i128 [[X:%.*]], -1
-; CHECK-NEXT:    [[CMP:%.*]] = icmp sgt i128 [[NOT]], [[X]]
+; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i128 [[X:%.*]], 0
 ; CHECK-NEXT:    ret i1 [[CMP]]
 ;
   %not = xor i128 %x, -1
@@ -73,8 +67,7 @@ define i1 @src_sle_i128(i128 %x) {
 ; X s>= ~X   -->      X s> -1
 define i1 @src_sge(i8 %x) {
 ; 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:    ret i1 [[CMP]]
 ;
   %not = xor i8 %x, -1
@@ -83,8 +76,7 @@ define i1 @src_sge(i8 %x) {
 }
 define i1 @src_sge_i128(i128 %x) {
 ; CHECK-LABEL: @src_sge_i128(
-; CHECK-NEXT:    [[NOT:%.*]] = xor i128 [[X:%.*]], -1
-; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i128 [[NOT]], [[X]]
+; CHECK-NEXT:    [[CMP:%.*]] = icmp sgt i128 [[X:%.*]], -1
 ; CHECK-NEXT:    ret i1 [[CMP]]
 ;
   %not = xor i128 %x, -1
@@ -96,8 +88,7 @@ define i1 @src_sge_i128(i128 %x) {
 ; ~X s< X   -->      X s> -1
 define i1 @src_slt_comm(i8 %x) {
 ; CHECK-LABEL: @src_slt_comm(
-; 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:    ret i1 [[CMP]]
 ;
   %not = xor i8 %x, -1
@@ -106,8 +97,7 @@ define i1 @src_slt_comm(i8 %x) {
 }
 define i1 @src_slt_i128_comm(i128 %x) {
 ; CHECK-LABEL: @src_slt_i128_comm(
-; CHECK-NEXT:    [[NOT:%.*]] = xor i128 [[X:%.*]], -1
-; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i128 [[NOT]], [[X]]
+; CHECK-NEXT:    [[CMP:%.*]] = icmp sgt i128 [[X:%.*]], -1
 ; CHECK-NEXT:    ret i1 [[CMP]]
 ;
   %not = xor i128 %x, -1
@@ -117,8 +107,7 @@ define i1 @src_slt_i128_comm(i128 %x) {
 ; ~X s> X   -->     X s< 0
 define i1 @src_sgt_comm(i8 %x) {
 ; CHECK-LABEL: @src_sgt_comm(
-; 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:    ret i1 [[CMP]]
 ;
   %not = xor i8 %x, -1
@@ -127,8 +116,7 @@ define i1 @src_sgt_comm(i8 %x) {
 }
 define i1 @src_sgt_i128_comm(i128 %x) {
 ; CHECK-LABEL: @src_sgt_i128_comm(
-; CHECK-NEXT:    [[NOT:%.*]] = xor i128 [[X:%.*]], -1
-; CHECK-NEXT:    [[CMP:%.*]] = icmp sgt i128 [[NOT]], [[X]]
+; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i128 [[X:%.*]], 0
 ; CHECK-NEXT:    ret i1 [[CMP]]
 ;
   %not = xor i128 %x, -1
@@ -138,8 +126,7 @@ define i1 @src_sgt_i128_comm(i128 %x) {
 ; ~X s<= X   -->      X s> -1
 define i1 @src_sle_comm(i8 %x) {
 ; CHECK-LABEL: @src_sle_comm(
-; 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:    ret i1 [[CMP]]
 ;
   %not = xor i8 %x, -1
@@ -148,8 +135,7 @@ define i1 @src_sle_comm(i8 %x) {
 }
 define i1 @src_sle_i128_comm(i128 %x) {
 ; CHECK-LABEL: @src_sle_i128_comm(
-; CHECK-NEXT:    [[NOT:%.*]] = xor i128 [[X:%.*]], -1
-; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i128 [[NOT]], [[X]]
+; CHECK-NEXT:    [[CMP:%.*]] = icmp sgt i128 [[X:%.*]], -1
 ; CHECK-NEXT:    ret i1 [[CMP]]
 ;
   %not = xor i128 %x, -1
@@ -159,8 +145,7 @@ define i1 @src_sle_i128_comm(i128 %x) {
 ; ~X s>= X   -->      X s< 0
 define i1 @src_sge_comm(i8 %x) {
 ; CHECK-LABEL: @src_sge_comm(
-; 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:    ret i1 [[CMP]]
 ;
   %not = xor i8 %x, -1
@@ -169,8 +154,7 @@ define i1 @src_sge_comm(i8 %x) {
 }
 define i1 @src_sge_i128_comm(i128 %x) {
 ; CHECK-LABEL: @src_sge_i128_comm(
-; CHECK-NEXT:    [[NOT:%.*]] = xor i128 [[X:%.*]], -1
-; CHECK-NEXT:    [[CMP:%.*]] = icmp sgt i128 [[NOT]], [[X]]
+; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i128 [[X:%.*]], 0
 ; CHECK-NEXT:    ret i1 [[CMP]]
 ;
   %not = xor i128 %x, -1
@@ -183,8 +167,7 @@ define i1 @src_sge_i128_comm(i128 %x) {
 ; X u< ~X   -->      X s> -1
 define i1 @src_ult(i8 %x) {
 ; 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:    ret i1 [[CMP]]
 ;
   %not = xor i8 %x, -1
@@ -193,8 +176,7 @@ define i1 @src_ult(i8 %x) {
 }
 define i1 @src_ult_i128(i128 %x) {
 ; CHECK-LABEL: @src_ult_i128(
-; CHECK-NEXT:    [[NOT:%.*]] = xor i128 [[X:%.*]], -1
-; CHECK-NEXT:    [[CMP:%.*]] = icmp ugt i128 [[NOT]], [[X]]
+; CHECK-NEXT:    [[CMP:%.*]] = icmp sgt i128 [[X:%.*]], -1
 ; CHECK-NEXT:    ret i1 [[CMP]]
 ;
   %not = xor i128 %x, -1
@@ -204,8 +186,7 @@ define i1 @src_ult_i128(i128 %x) {
 ; X u> ~X   -->     X s< 0
 define i1 @src_ugt(i8 %x) {
 ; 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:    ret i1 [[CMP]]
 ;
   %not = xor i8 %x, -1
@@ -214,8 +195,7 @@ define i1 @src_ugt(i8 %x) {
 }
 define i1 @src_ugt_i128(i128 %x) {
 ; CHECK-LABEL: @src_ugt_i128(
-; CHECK-NEXT:    [[NOT:%.*]] = xor i128 [[X:%.*]], -1
-; CHECK-NEXT:    [[CMP:%.*]] = icmp ult i128 [[NOT]], [[X]]
+; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i128 [[X:%.*]], 0
 ; CHECK-NEXT:    ret i1 [[CMP]]
 ;
   %not = xor i128 %x, -1
@@ -225,8 +205,7 @@ define i1 @src_ugt_i128(i128 %x) {
 ; X u<= ~X   -->      X s> -1
 define i1 @src_ule(i8 %x) {
 ; 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:    ret i1 [[CMP]]
 ;
   %not = xor i8 %x, -1
@@ -235,8 +214,7 @@ define i1 @src_ule(i8 %x) {
 }
 define i1 @src_ule_i128(i128 %x) {
 ; CHECK-LABEL: @src_ule_i128(
-; CHECK-NEXT:    [[NOT:%.*]] = xor i128 [[X:%.*]], -1
-; CHECK-NEXT:    [[CMP:%.*]] = icmp ugt i128 [[NOT]], [[X]]
+; CHECK-NEXT:    [[CMP:%.*]] = icmp sgt i128 [[X:%.*]], -1
 ; CHECK-NEXT:    ret i1 [[CMP]]
 ;
   %not = xor i128 %x, -1
@@ -246,8 +224,7 @@ define i1 @src_ule_i128(i128 %x) {
 ; X u>= ~X   -->      X s< 0
 define i1 @src_uge(i8 %x) {
 ; 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:    ret i1 [[CMP]]
 ;
   %not = xor i8 %x, -1
@@ -256,8 +233,7 @@ define i1 @src_uge(i8 %x) {
 }
 define i1 @src_uge_i128(i128 %x) {
 ; CHECK-LABEL: @src_uge_i128(
-; CHECK-NEXT:    [[NOT:%.*]] = xor i128 [[X:%.*]], -1
-; CHECK-NEXT:    [[CMP:%.*]] = icmp ult i128 [[NOT]], [[X]]
+; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i128 [[X:%.*]], 0
 ; CHECK-NEXT:    ret i1 [[CMP]]
 ;
   %not = xor i128 %x, -1
@@ -269,8 +245,7 @@ define i1 @src_uge_i128(i128 %x) {
 ; ~X u< X   -->      X s< 0
 define i1 @src_ult_comm(i8 %x) {
 ; CHECK-LABEL: @src_ult_comm(
-; 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:    ret i1 [[CMP]]
 ;
   %not = xor i8 %x, -1
@@ -279,8 +254,7 @@ define i1 @src_ult_comm(i8 %x) {
 }
 define i1 @src_ult_i128_comm(i128 %x) {
 ; CHECK-LABEL: @src_ult_i128_comm(
-; CHECK-NEXT:    [[NOT:%.*]] = xor i128 [[X:%.*]], -1
-; CHECK-NEXT:    [[CMP:%.*]] = icmp ult i128 [[NOT]], [[X]]
+; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i128 [[X:%.*]], 0
 ; CHECK-NEXT:    ret i1 [[CMP]]
 ;
   %not = xor i128 %x, -1
@@ -290,8 +264,7 @@ define i1 @src_ult_i128_comm(i128 %x) {
 ; ~X u> X   -->     X s> -1
 define i1 @src_ugt_comm(i8 %x) {
 ; CHECK-LABEL: @src_ugt_comm(
-; 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:    ret i1 [[CMP]]
 ;
   %not = xor i8 %x, -1
@@ -300,8 +273,7 @@ define i1 @src_ugt_comm(i8 %x) {
 }
 define i1 @src_ugt_i128_comm(i128 %x) {
 ; CHECK-LABEL: @src_ugt_i128_comm(
-; CHECK-NEXT:    [[NOT:%.*]] = xor i128 [[X:%.*]], -1
-; CHECK-NEXT:    [[CMP:%.*]] = icmp ugt i128 [[NOT]], [[X]]
+; CHECK-NEXT:    [[CMP:%.*]] = icmp sgt i128 [[X:%.*]], -1
 ; CHECK-NEXT:    ret i1 [[CMP]]
 ;
   %not = xor i128 %x, -1
@@ -311,8 +283,7 @@ define i1 @src_ugt_i128_comm(i128 %x) {
 ; ~X u<= X   -->      X s< 0
 define i1 @src_ule_comm(i8 %x) {
 ; CHECK-LABEL: @src_ule_comm(
-; 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:    ret i1 [[CMP]]
 ;
   %not = xor i8 %x, -1
@@ -321,8 +292,7 @@ define i1 @src_ule_comm(i8 %x) {
 }
 define i1 @src_ule_i128_comm(i128 %x) {
 ; CHECK-LABEL: @src_ule_i128_comm(
-; CHECK-NEXT:    [[NOT:%.*]] = xor i128 [[X:%.*]], -1
-; CHECK-NEXT:    [[CMP:%.*]] = icmp ult i128 [[NOT]], [[X]]
+; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i128 [[X:%.*]], 0
 ; CHECK-NEXT:    ret i1 [[CMP]]
 ;
   %not = xor i128 %x, -1
@@ -332,8 +302,7 @@ define i1 @src_ule_i128_comm(i128 %x) {
 ; ~X u>= X   -->      X s> -1
 define i1 @src_uge_comm(i8 %x) {
 ; CHECK-LABEL: @src_uge_comm(
-; 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:    ret i1 [[CMP]]
 ;
   %not = xor i8 %x, -1
@@ -342,8 +311,7 @@ define i1 @src_uge_comm(i8 %x) {
 }
 define i1 @src_uge_i128_comm(i128 %x) {
 ; CHECK-LABEL: @src_uge_i128_comm(
-; CHECK-NEXT:    [[NOT:%.*]] = xor i128 [[X:%.*]], -1
-; CHECK-NEXT:    [[CMP:%.*]] = icmp ugt i128 [[NOT]], [[X]]
+; CHECK-NEXT:    [[CMP:%.*]] = icmp sgt i128 [[X:%.*]], -1
 ; CHECK-NEXT:    ret i1 [[CMP]]
 ;
   %not = xor i128 %x, -1



More information about the llvm-commits mailing list