[llvm] [InstCombine] Fold comparison of adding two z/sext booleans (PR #67895)

via llvm-commits llvm-commits at lists.llvm.org
Mon Oct 2 02:15:07 PDT 2023


https://github.com/elhewaty updated https://github.com/llvm/llvm-project/pull/67895

>From 57f5806ef1f587f01d5b08cf92fd11a974bd950e Mon Sep 17 00:00:00 2001
From: Mohamed Atef <mohamedatef1698 at gmail.com>
Date: Sun, 1 Oct 2023 00:42:12 +0300
Subject: [PATCH 1/4] Add test coverage for sext/zext boolean additions

---
 llvm/test/Transforms/InstCombine/icmp-add.ll | 792 +++++++++++++++++++
 1 file changed, 792 insertions(+)

diff --git a/llvm/test/Transforms/InstCombine/icmp-add.ll b/llvm/test/Transforms/InstCombine/icmp-add.ll
index a2d0c3eb39d69ec..ec8d7d14d3b51f7 100644
--- a/llvm/test/Transforms/InstCombine/icmp-add.ll
+++ b/llvm/test/Transforms/InstCombine/icmp-add.ll
@@ -5,6 +5,798 @@ declare void @use(i32)
 
 ; PR1949
 
+define i1 @cvt_icmp_0_zext_plus_zext_eq(i1 %arg, i1 %arg1) {
+; CHECK-LABEL: @cvt_icmp_0_zext_plus_zext_eq(
+; CHECK-NEXT:  bb:
+; CHECK-NEXT:    [[TMP0:%.*]] = or i1 [[ARG1:%.*]], [[ARG:%.*]]
+; CHECK-NEXT:    [[I4:%.*]] = xor i1 [[TMP0]], true
+; CHECK-NEXT:    ret i1 [[I4]]
+;
+bb:
+  %i = zext i1 %arg to i32
+  %i2 = zext i1 %arg1 to i32
+  %i3 = add i32 %i2, %i
+  %i4 = icmp eq i32 %i3, 0
+  ret i1 %i4
+}
+
+define i1 @cvt_icmp_1_zext_plus_zext_eq(i1 %arg, i1 %arg1) {
+; CHECK-LABEL: @cvt_icmp_1_zext_plus_zext_eq(
+; CHECK-NEXT:  bb:
+; CHECK-NEXT:    [[I:%.*]] = zext i1 [[ARG:%.*]] to i32
+; CHECK-NEXT:    [[I2:%.*]] = zext i1 [[ARG1:%.*]] to i32
+; CHECK-NEXT:    [[I3:%.*]] = add nuw nsw i32 [[I2]], [[I]]
+; CHECK-NEXT:    [[I4:%.*]] = icmp eq i32 [[I3]], 1
+; CHECK-NEXT:    ret i1 [[I4]]
+;
+bb:
+  %i = zext i1 %arg to i32
+  %i2 = zext i1 %arg1 to i32
+  %i3 = add i32 %i2, %i
+  %i4 = icmp eq i32 %i3, 1
+  ret i1 %i4
+}
+
+define i1 @cvt_icmp_2_zext_plus_zext_eq(i1 %arg, i1 %arg1) {
+; CHECK-LABEL: @cvt_icmp_2_zext_plus_zext_eq(
+; CHECK-NEXT:  bb:
+; CHECK-NEXT:    [[I:%.*]] = zext i1 [[ARG:%.*]] to i32
+; CHECK-NEXT:    [[I2:%.*]] = zext i1 [[ARG1:%.*]] to i32
+; CHECK-NEXT:    [[I3:%.*]] = add nuw nsw i32 [[I]], [[I2]]
+; CHECK-NEXT:    [[T:%.*]] = icmp eq i32 [[I3]], 2
+; CHECK-NEXT:    ret i1 [[T]]
+;
+bb:
+  %i = zext i1 %arg to i32
+  %i2 = zext i1 %arg1 to i32
+  %i3 = add i32 %i, %i2
+  %t = icmp eq i32 %i3, 2
+  ret i1 %t
+}
+
+define i1 @cvt_icmp_0_sext_plus_sext_eq(i1 %arg, i1 %arg1) {
+; CHECK-LABEL: @cvt_icmp_0_sext_plus_sext_eq(
+; CHECK-NEXT:  bb:
+; CHECK-NEXT:    [[TMP0:%.*]] = or i1 [[ARG:%.*]], [[ARG1:%.*]]
+; CHECK-NEXT:    [[T:%.*]] = xor i1 [[TMP0]], true
+; CHECK-NEXT:    ret i1 [[T]]
+;
+bb:
+  %i = sext i1 %arg to i32
+  %i2 = sext i1 %arg1 to i32
+  %i3 = add i32 %i, %i2
+  %t = icmp eq i32 %i3, 0
+  ret i1 %t
+}
+
+define i1 @cvt_icmp_1_sext_plus_sext_eq(i1 %arg, i1 %arg1) {
+; CHECK-LABEL: @cvt_icmp_1_sext_plus_sext_eq(
+; CHECK-NEXT:  bb:
+; CHECK-NEXT:    [[I:%.*]] = sext i1 [[ARG:%.*]] to i32
+; CHECK-NEXT:    [[I2:%.*]] = sext i1 [[ARG1:%.*]] to i32
+; CHECK-NEXT:    [[I3:%.*]] = add nsw i32 [[I]], [[I2]]
+; CHECK-NEXT:    [[T:%.*]] = icmp eq i32 [[I3]], 1
+; CHECK-NEXT:    ret i1 [[T]]
+;
+bb:
+  %i = sext i1 %arg to i32
+  %i2 = sext i1 %arg1 to i32
+  %i3 = add i32 %i, %i2
+  %t = icmp eq i32 %i3, 1
+  ret i1 %t
+}
+
+define i1 @cvt_icmp_2_sext_plus_sext_eq(i1 %arg, i1 %arg1) {
+; CHECK-LABEL: @cvt_icmp_2_sext_plus_sext_eq(
+; CHECK-NEXT:  bb:
+; CHECK-NEXT:    [[I:%.*]] = sext i1 [[ARG:%.*]] to i32
+; CHECK-NEXT:    [[I2:%.*]] = sext i1 [[ARG1:%.*]] to i32
+; CHECK-NEXT:    [[I3:%.*]] = add nsw i32 [[I]], [[I2]]
+; CHECK-NEXT:    [[T:%.*]] = icmp eq i32 [[I3]], 2
+; CHECK-NEXT:    ret i1 [[T]]
+;
+bb:
+  %i = sext i1 %arg to i32
+  %i2 = sext i1 %arg1 to i32
+  %i3 = add i32 %i, %i2
+  %t = icmp eq i32 %i3, 2
+  ret i1 %t
+}
+
+define i1 @cvt_icmp_0_sext_plus_zext_eq(i1 %arg, i1 %arg1) {
+; CHECK-LABEL: @cvt_icmp_0_sext_plus_zext_eq(
+; CHECK-NEXT:  bb:
+; CHECK-NEXT:    [[TMP0:%.*]] = xor i1 [[ARG:%.*]], [[ARG1:%.*]]
+; CHECK-NEXT:    [[T:%.*]] = xor i1 [[TMP0]], true
+; CHECK-NEXT:    ret i1 [[T]]
+;
+bb:
+  %i = sext i1 %arg to i32
+  %i2 = zext i1 %arg1 to i32
+  %i3 = add i32 %i, %i2
+  %t = icmp eq i32 %i3, 0
+  ret i1 %t
+}
+
+define i1 @cvt_icmp_1_sext_plus_zext_eq(i1 %arg, i1 %arg1) {
+; CHECK-LABEL: @cvt_icmp_1_sext_plus_zext_eq(
+; CHECK-NEXT:  bb:
+; CHECK-NEXT:    [[TMP0:%.*]] = xor i1 [[ARG:%.*]], true
+; CHECK-NEXT:    [[T:%.*]] = and i1 [[TMP0]], [[ARG1:%.*]]
+; CHECK-NEXT:    ret i1 [[T]]
+;
+bb:
+  %i = sext i1 %arg to i32
+  %i2 = zext i1 %arg1 to i32
+  %i3 = add i32 %i, %i2
+  %t = icmp eq i32 %i3, 1
+  ret i1 %t
+}
+
+define i1 @cvt_icmp_2_sext_plus_zext_eq(i1 %arg, i1 %arg1) {
+; CHECK-LABEL: @cvt_icmp_2_sext_plus_zext_eq(
+; CHECK-NEXT:  bb:
+; CHECK-NEXT:    [[I:%.*]] = sext i1 [[ARG:%.*]] to i32
+; CHECK-NEXT:    [[I2:%.*]] = zext i1 [[ARG1:%.*]] to i32
+; CHECK-NEXT:    [[I3:%.*]] = add nsw i32 [[I]], [[I2]]
+; CHECK-NEXT:    [[T:%.*]] = icmp eq i32 [[I3]], 2
+; CHECK-NEXT:    ret i1 [[T]]
+;
+bb:
+  %i = sext i1 %arg to i32
+  %i2 = zext i1 %arg1 to i32
+  %i3 = add i32 %i, %i2
+  %t = icmp eq i32 %i3, 2
+  ret i1 %t
+}
+
+define i1 @cvt_icmp_0_zext_plus_zext_ne(i1 %arg, i1 %arg1) {
+; CHECK-LABEL: @cvt_icmp_0_zext_plus_zext_ne(
+; CHECK-NEXT:  bb:
+; CHECK-NEXT:    [[TMP0:%.*]] = or i1 [[ARG1:%.*]], [[ARG:%.*]]
+; CHECK-NEXT:    ret i1 [[TMP0]]
+;
+bb:
+  %i = zext i1 %arg to i32
+  %i2 = zext i1 %arg1 to i32
+  %i3 = add i32 %i2, %i
+  %i4 = icmp ne i32 %i3, 0
+  ret i1 %i4
+}
+
+define i1 @cvt_icmp_1_zext_plus_zext_ne(i1 %arg, i1 %arg1) {
+; CHECK-LABEL: @cvt_icmp_1_zext_plus_zext_ne(
+; CHECK-NEXT:  bb:
+; CHECK-NEXT:    [[I:%.*]] = zext i1 [[ARG:%.*]] to i32
+; CHECK-NEXT:    [[I2:%.*]] = zext i1 [[ARG1:%.*]] to i32
+; CHECK-NEXT:    [[I3:%.*]] = add nuw nsw i32 [[I2]], [[I]]
+; CHECK-NEXT:    [[I4:%.*]] = icmp ne i32 [[I3]], 1
+; CHECK-NEXT:    ret i1 [[I4]]
+;
+bb:
+  %i = zext i1 %arg to i32
+  %i2 = zext i1 %arg1 to i32
+  %i3 = add i32 %i2, %i
+  %i4 = icmp ne i32 %i3, 1
+  ret i1 %i4
+}
+
+define i1 @cvt_icmp_2_zext_plus_zext_ne(i1 %arg, i1 %arg1) {
+; CHECK-LABEL: @cvt_icmp_2_zext_plus_zext_ne(
+; CHECK-NEXT:  bb:
+; CHECK-NEXT:    [[I:%.*]] = zext i1 [[ARG:%.*]] to i32
+; CHECK-NEXT:    [[I2:%.*]] = zext i1 [[ARG1:%.*]] to i32
+; CHECK-NEXT:    [[I3:%.*]] = add nuw nsw i32 [[I]], [[I2]]
+; CHECK-NEXT:    [[T:%.*]] = icmp ne i32 [[I3]], 2
+; CHECK-NEXT:    ret i1 [[T]]
+;
+bb:
+  %i = zext i1 %arg to i32
+  %i2 = zext i1 %arg1 to i32
+  %i3 = add i32 %i, %i2
+  %t = icmp ne i32 %i3, 2
+  ret i1 %t
+}
+
+define i1 @cvt_icmp_0_sext_plus_sext_ne(i1 %arg, i1 %arg1) {
+; CHECK-LABEL: @cvt_icmp_0_sext_plus_sext_ne(
+; CHECK-NEXT:  bb:
+; CHECK-NEXT:    [[TMP0:%.*]] = or i1 [[ARG:%.*]], [[ARG1:%.*]]
+; CHECK-NEXT:    ret i1 [[TMP0]]
+;
+bb:
+  %i = sext i1 %arg to i32
+  %i2 = sext i1 %arg1 to i32
+  %i3 = add i32 %i, %i2
+  %t = icmp ne i32 %i3, 0
+  ret i1 %t
+}
+
+define i1 @cvt_icmp_1_sext_plus_sext_ne(i1 %arg, i1 %arg1) {
+; CHECK-LABEL: @cvt_icmp_1_sext_plus_sext_ne(
+; CHECK-NEXT:  bb:
+; CHECK-NEXT:    [[I:%.*]] = sext i1 [[ARG:%.*]] to i32
+; CHECK-NEXT:    [[I2:%.*]] = sext i1 [[ARG1:%.*]] to i32
+; CHECK-NEXT:    [[I3:%.*]] = add nsw i32 [[I]], [[I2]]
+; CHECK-NEXT:    [[T:%.*]] = icmp ne i32 [[I3]], 1
+; CHECK-NEXT:    ret i1 [[T]]
+;
+bb:
+  %i = sext i1 %arg to i32
+  %i2 = sext i1 %arg1 to i32
+  %i3 = add i32 %i, %i2
+  %t = icmp ne i32 %i3, 1
+  ret i1 %t
+}
+
+define i1 @cvt_icmp_2_sext_plus_sext_ne(i1 %arg, i1 %arg1) {
+; CHECK-LABEL: @cvt_icmp_2_sext_plus_sext_ne(
+; CHECK-NEXT:  bb:
+; CHECK-NEXT:    [[I:%.*]] = sext i1 [[ARG:%.*]] to i32
+; CHECK-NEXT:    [[I2:%.*]] = sext i1 [[ARG1:%.*]] to i32
+; CHECK-NEXT:    [[I3:%.*]] = add nsw i32 [[I]], [[I2]]
+; CHECK-NEXT:    [[T:%.*]] = icmp ne i32 [[I3]], 2
+; CHECK-NEXT:    ret i1 [[T]]
+;
+bb:
+  %i = sext i1 %arg to i32
+  %i2 = sext i1 %arg1 to i32
+  %i3 = add i32 %i, %i2
+  %t = icmp ne i32 %i3, 2
+  ret i1 %t
+}
+
+define i1 @cvt_icmp_0_sext_plus_zext_ne(i1 %arg, i1 %arg1) {
+; CHECK-LABEL: @cvt_icmp_0_sext_plus_zext_ne(
+; CHECK-NEXT:  bb:
+; CHECK-NEXT:    [[T:%.*]] = xor i1 [[ARG:%.*]], [[ARG1:%.*]]
+; CHECK-NEXT:    ret i1 [[T]]
+;
+bb:
+  %i = sext i1 %arg to i32
+  %i2 = zext i1 %arg1 to i32
+  %i3 = add i32 %i, %i2
+  %t = icmp ne i32 %i3, 0
+  ret i1 %t
+}
+
+define i1 @cvt_icmp_1_sext_plus_zext_ne(i1 %arg, i1 %arg1) {
+; CHECK-LABEL: @cvt_icmp_1_sext_plus_zext_ne(
+; CHECK-NEXT:  bb:
+; CHECK-NEXT:    [[TMP0:%.*]] = xor i1 [[ARG1:%.*]], true
+; CHECK-NEXT:    [[T:%.*]] = or i1 [[TMP0]], [[ARG:%.*]]
+; CHECK-NEXT:    ret i1 [[T]]
+;
+bb:
+  %i = sext i1 %arg to i32
+  %i2 = zext i1 %arg1 to i32
+  %i3 = add i32 %i, %i2
+  %t = icmp ne i32 %i3, 1
+  ret i1 %t
+}
+
+define i1 @cvt_icmp_2_sext_plus_zext_ne(i1 %arg, i1 %arg1) {
+; CHECK-LABEL: @cvt_icmp_2_sext_plus_zext_ne(
+; CHECK-NEXT:  bb:
+; CHECK-NEXT:    [[I:%.*]] = sext i1 [[ARG:%.*]] to i32
+; CHECK-NEXT:    [[I2:%.*]] = zext i1 [[ARG1:%.*]] to i32
+; CHECK-NEXT:    [[I3:%.*]] = add nsw i32 [[I]], [[I2]]
+; CHECK-NEXT:    [[T:%.*]] = icmp ne i32 [[I3]], 2
+; CHECK-NEXT:    ret i1 [[T]]
+;
+bb:
+  %i = sext i1 %arg to i32
+  %i2 = zext i1 %arg1 to i32
+  %i3 = add i32 %i, %i2
+  %t = icmp ne i32 %i3, 2
+  ret i1 %t
+}
+
+; test if zext i1 X + sext i1 Y converted to sext i1 X + zext i1 Y
+; and then processed
+
+define i1 @cvt_icmp_0_zext_plus_sext_eq(i1 %arg, i1 %arg1) {
+; CHECK-LABEL: @cvt_icmp_0_zext_plus_sext_eq(
+; CHECK-NEXT:  bb:
+; CHECK-NEXT:    [[TMP0:%.*]] = xor i1 [[ARG:%.*]], [[ARG1:%.*]]
+; CHECK-NEXT:    [[T:%.*]] = xor i1 [[TMP0]], true
+; CHECK-NEXT:    ret i1 [[T]]
+;
+bb:
+  %i = zext i1 %arg to i32
+  %i2 = sext i1 %arg1 to i32
+  %i3 = add i32 %i, %i2
+  %t = icmp eq i32 %i3, 0
+  ret i1 %t
+}
+
+define i1 @cvt_icmp_1_zext_plus_sext_eq(i1 %arg, i1 %arg1) {
+; CHECK-LABEL: @cvt_icmp_1_zext_plus_sext_eq(
+; CHECK-NEXT:  bb:
+; CHECK-NEXT:    [[TMP0:%.*]] = xor i1 [[ARG1:%.*]], true
+; CHECK-NEXT:    [[T:%.*]] = and i1 [[TMP0]], [[ARG:%.*]]
+; CHECK-NEXT:    ret i1 [[T]]
+;
+bb:
+  %i = zext i1 %arg to i32
+  %i2 = sext i1 %arg1 to i32
+  %i3 = add i32 %i, %i2
+  %t = icmp eq i32 %i3, 1
+  ret i1 %t
+}
+
+define i1 @cvt_icmp_2_zext_plus_sext_eq(i1 %arg, i1 %arg1) {
+; CHECK-LABEL: @cvt_icmp_2_zext_plus_sext_eq(
+; CHECK-NEXT:  bb:
+; CHECK-NEXT:    [[I:%.*]] = zext i1 [[ARG:%.*]] to i32
+; CHECK-NEXT:    [[I2:%.*]] = sext i1 [[ARG1:%.*]] to i32
+; CHECK-NEXT:    [[I3:%.*]] = add nsw i32 [[I]], [[I2]]
+; CHECK-NEXT:    [[T:%.*]] = icmp eq i32 [[I3]], 2
+; CHECK-NEXT:    ret i1 [[T]]
+;
+bb:
+  %i = zext i1 %arg to i32
+  %i2 = sext i1 %arg1 to i32
+  %i3 = add i32 %i, %i2
+  %t = icmp eq i32 %i3, 2
+  ret i1 %t
+}
+
+define i1 @cvt_icmp_0_zext_plus_sext_ne(i1 %arg, i1 %arg1) {
+; CHECK-LABEL: @cvt_icmp_0_zext_plus_sext_ne(
+; CHECK-NEXT:  bb:
+; CHECK-NEXT:    [[T:%.*]] = xor i1 [[ARG:%.*]], [[ARG1:%.*]]
+; CHECK-NEXT:    ret i1 [[T]]
+;
+bb:
+  %i = zext i1 %arg to i32
+  %i2 = sext i1 %arg1 to i32
+  %i3 = add i32 %i, %i2
+  %t = icmp ne i32 %i3, 0
+  ret i1 %t
+}
+
+define i1 @cvt_icmp_1_zext_plus_sext_ne(i1 %arg, i1 %arg1) {
+; CHECK-LABEL: @cvt_icmp_1_zext_plus_sext_ne(
+; CHECK-NEXT:  bb:
+; CHECK-NEXT:    [[TMP0:%.*]] = xor i1 [[ARG:%.*]], true
+; CHECK-NEXT:    [[T:%.*]] = or i1 [[TMP0]], [[ARG1:%.*]]
+; CHECK-NEXT:    ret i1 [[T]]
+;
+bb:
+  %i = zext i1 %arg to i32
+  %i2 = sext i1 %arg1 to i32
+  %i3 = add i32 %i, %i2
+  %t = icmp ne i32 %i3, 1
+  ret i1 %t
+}
+
+define i1 @cvt_icmp_2_zext_plus_sext_ne(i1 %arg, i1 %arg1) {
+; CHECK-LABEL: @cvt_icmp_2_zext_plus_sext_ne(
+; CHECK-NEXT:  bb:
+; CHECK-NEXT:    [[I:%.*]] = zext i1 [[ARG:%.*]] to i32
+; CHECK-NEXT:    [[I2:%.*]] = sext i1 [[ARG1:%.*]] to i32
+; CHECK-NEXT:    [[I3:%.*]] = add nsw i32 [[I]], [[I2]]
+; CHECK-NEXT:    [[T:%.*]] = icmp ne i32 [[I3]], 2
+; CHECK-NEXT:    ret i1 [[T]]
+;
+bb:
+  %i = zext i1 %arg to i32
+  %i2 = sext i1 %arg1 to i32
+  %i3 = add i32 %i, %i2
+  %t = icmp ne i32 %i3, 2
+  ret i1 %t
+}
+
+; test zext/zext additions with more than one use
+
+define i1 @test_cvt_icmp1(i1 %arg, i1 %arg1, ptr %p) {
+; CHECK-LABEL: @test_cvt_icmp1(
+; CHECK-NEXT:  bb:
+; CHECK-NEXT:    [[I:%.*]] = zext i1 [[ARG:%.*]] to i32
+; CHECK-NEXT:    [[I2:%.*]] = zext i1 [[ARG]] to i32
+; CHECK-NEXT:    store i32 [[I2]], ptr [[P:%.*]], align 4
+; CHECK-NEXT:    [[I4:%.*]] = add nuw nsw i32 [[I2]], [[I]]
+; CHECK-NEXT:    [[T:%.*]] = icmp eq i32 [[I4]], 1
+; CHECK-NEXT:    ret i1 [[T]]
+;
+bb:
+  %i = zext i1 %arg to i32
+  %i2 = zext i1 %arg to i32
+  store i32 %i2, ptr %p
+  %i3 = load i32, ptr %p
+  %i4 = add i32 %i3, %i
+  %t = icmp eq i32 %i4, 1
+  ret i1 %t
+}
+
+define i1 @test_cvt_icmp2(i1 %arg, i1 %arg1, ptr %p) {
+; CHECK-LABEL: @test_cvt_icmp2(
+; CHECK-NEXT:  bb:
+; CHECK-NEXT:    [[I2:%.*]] = zext i1 [[ARG:%.*]] to i32
+; CHECK-NEXT:    store i32 [[I2]], ptr [[P:%.*]], align 4
+; CHECK-NEXT:    ret i1 false
+;
+bb:
+  %i = sext i1 %arg to i32
+  %i2 = zext i1 %arg to i32
+  store i32 %i2, ptr %p
+  %i3 = load i32, ptr %p
+  %i4 = add i32 %i3, %i
+  %t = icmp eq i32 %i4, 1
+  ret i1 %t
+}
+
+; tests for negative comparisons
+define i1 @test_cvt_icmp3(i1 %arg, i1 %arg1) {
+; CHECK-LABEL: @test_cvt_icmp3(
+; CHECK-NEXT:  bb:
+; CHECK-NEXT:    ret i1 false
+;
+bb:
+  %i = zext i1 %arg to i32
+  %i2 = zext i1 %arg1 to i32
+  %i3 = add i32 %i2, %i
+  %i4 = icmp ult i32 %i3, 0
+  ret i1 %i4
+}
+
+define i1 @test_cvt_icmp4(i1 %arg, i1 %arg1) {
+; CHECK-LABEL: @test_cvt_icmp4(
+; CHECK-NEXT:  bb:
+; CHECK-NEXT:    [[TMP0:%.*]] = or i1 [[ARG1:%.*]], [[ARG:%.*]]
+; CHECK-NEXT:    ret i1 [[TMP0]]
+;
+bb:
+  %i = zext i1 %arg to i32
+  %i2 = zext i1 %arg1 to i32
+  %i3 = add i32 %i2, %i
+  %i4 = icmp ugt i32 %i3, 0
+  ret i1 %i4
+}
+
+define i1 @test_cvt_icmp5(i1 %arg, i1 %arg1) {
+; CHECK-LABEL: @test_cvt_icmp5(
+; CHECK-NEXT:  bb:
+; CHECK-NEXT:    [[TMP0:%.*]] = or i1 [[ARG1:%.*]], [[ARG:%.*]]
+; CHECK-NEXT:    ret i1 [[TMP0]]
+;
+bb:
+  %i = zext i1 %arg to i32
+  %i2 = zext i1 %arg1 to i32
+  %i3 = add i32 %i2, %i
+  %i4 = icmp uge i32 %i3, 1
+  ret i1 %i4
+}
+
+define i1 @test_cvt_icmp6(i1 %arg, i1 %arg1) {
+; CHECK-LABEL: @test_cvt_icmp6(
+; CHECK-NEXT:  bb:
+; CHECK-NEXT:    [[I:%.*]] = zext i1 [[ARG:%.*]] to i32
+; CHECK-NEXT:    [[I2:%.*]] = zext i1 [[ARG1:%.*]] to i32
+; CHECK-NEXT:    [[I3:%.*]] = add nuw nsw i32 [[I2]], [[I]]
+; CHECK-NEXT:    [[I4:%.*]] = icmp ult i32 [[I3]], 2
+; CHECK-NEXT:    ret i1 [[I4]]
+;
+bb:
+  %i = zext i1 %arg to i32
+  %i2 = zext i1 %arg1 to i32
+  %i3 = add i32 %i2, %i
+  %i4 = icmp ule i32 %i3, 1
+  ret i1 %i4
+}
+
+define i1 @test_cvt_icmp7(i1 %arg, i1 %arg1) {
+; CHECK-LABEL: @test_cvt_icmp7(
+; CHECK-NEXT:  bb:
+; CHECK-NEXT:    [[I:%.*]] = zext i1 [[ARG:%.*]] to i32
+; CHECK-NEXT:    [[I2:%.*]] = zext i1 [[ARG1:%.*]] to i32
+; CHECK-NEXT:    [[I3:%.*]] = add nuw nsw i32 [[I2]], [[I]]
+; CHECK-NEXT:    [[I4:%.*]] = icmp ugt i32 [[I3]], 1
+; CHECK-NEXT:    ret i1 [[I4]]
+;
+bb:
+  %i = zext i1 %arg to i32
+  %i2 = zext i1 %arg1 to i32
+  %i3 = add i32 %i2, %i
+  %i4 = icmp sgt i32 %i3, 1
+  ret i1 %i4
+}
+
+define i1 @test_cvt_icmp8(i1 %arg, i1 %arg1) {
+; CHECK-LABEL: @test_cvt_icmp8(
+; CHECK-NEXT:  bb:
+; CHECK-NEXT:    [[TMP0:%.*]] = or i1 [[ARG1:%.*]], [[ARG:%.*]]
+; CHECK-NEXT:    ret i1 [[TMP0]]
+;
+bb:
+  %i = zext i1 %arg to i32
+  %i2 = zext i1 %arg1 to i32
+  %i3 = add i32 %i2, %i
+  %i4 = icmp sge i32 %i3, 1
+  ret i1 %i4
+}
+
+define i1 @test_cvt_icmp9(i1 %arg, i1 %arg1) {
+; CHECK-LABEL: @test_cvt_icmp9(
+; CHECK-NEXT:  bb:
+; CHECK-NEXT:    [[TMP0:%.*]] = or i1 [[ARG1:%.*]], [[ARG:%.*]]
+; CHECK-NEXT:    [[I4:%.*]] = xor i1 [[TMP0]], true
+; CHECK-NEXT:    ret i1 [[I4]]
+;
+bb:
+  %i = zext i1 %arg to i32
+  %i2 = zext i1 %arg1 to i32
+  %i3 = add i32 %i2, %i
+  %i4 = icmp slt i32 %i3, 1
+  ret i1 %i4
+}
+
+define i1 @test_cvt_icmp10(i1 %arg, i1 %arg1) {
+; CHECK-LABEL: @test_cvt_icmp10(
+; CHECK-NEXT:  bb:
+; CHECK-NEXT:    [[I:%.*]] = zext i1 [[ARG:%.*]] to i32
+; CHECK-NEXT:    [[I2:%.*]] = zext i1 [[ARG1:%.*]] to i32
+; CHECK-NEXT:    [[I3:%.*]] = add nuw nsw i32 [[I2]], [[I]]
+; CHECK-NEXT:    [[I4:%.*]] = icmp ult i32 [[I3]], 2
+; CHECK-NEXT:    ret i1 [[I4]]
+;
+bb:
+  %i = zext i1 %arg to i32
+  %i2 = zext i1 %arg1 to i32
+  %i3 = add i32 %i2, %i
+  %i4 = icmp sle i32 %i3, 1
+  ret i1 %i4
+}
+
+define i1 @test_cvt_icmp11(i1 %arg, i1 %arg1) {
+; CHECK-LABEL: @test_cvt_icmp11(
+; CHECK-NEXT:  bb:
+; CHECK-NEXT:    [[I:%.*]] = sext i1 [[ARG:%.*]] to i32
+; CHECK-NEXT:    [[I2:%.*]] = sext i1 [[ARG1:%.*]] to i32
+; CHECK-NEXT:    [[I3:%.*]] = add nsw i32 [[I2]], [[I]]
+; CHECK-NEXT:    [[I4:%.*]] = icmp ugt i32 [[I3]], 2
+; CHECK-NEXT:    ret i1 [[I4]]
+;
+bb:
+  %i = sext i1 %arg to i32
+  %i2 = sext i1 %arg1 to i32
+  %i3 = add i32 %i2, %i
+  %i4 = icmp ugt i32 %i3, 2
+  ret i1 %i4
+}
+
+define i1 @test_cvt_icmp12(i1 %arg, i1 %arg1) {
+; CHECK-LABEL: @test_cvt_icmp12(
+; CHECK-NEXT:  bb:
+; CHECK-NEXT:    [[TMP0:%.*]] = or i1 [[ARG1:%.*]], [[ARG:%.*]]
+; CHECK-NEXT:    ret i1 [[TMP0]]
+;
+bb:
+  %i = sext i1 %arg to i32
+  %i2 = sext i1 %arg1 to i32
+  %i3 = add i32 %i2, %i
+  %i4 = icmp uge i32 %i3, 1
+  ret i1 %i4
+}
+
+define i1 @test_cvt_icmp13(i1 %arg, i1 %arg1) {
+; CHECK-LABEL: @test_cvt_icmp13(
+; CHECK-NEXT:  bb:
+; CHECK-NEXT:    [[TMP0:%.*]] = or i1 [[ARG1:%.*]], [[ARG:%.*]]
+; CHECK-NEXT:    [[I4:%.*]] = xor i1 [[TMP0]], true
+; CHECK-NEXT:    ret i1 [[I4]]
+;
+bb:
+  %i = sext i1 %arg to i32
+  %i2 = sext i1 %arg1 to i32
+  %i3 = add i32 %i2, %i
+  %i4 = icmp ult i32 %i3, 1
+  ret i1 %i4
+}
+
+define i1 @test_cvt_icmp14(i1 %arg, i1 %arg1) {
+; CHECK-LABEL: @test_cvt_icmp14(
+; CHECK-NEXT:  bb:
+; CHECK-NEXT:    [[I:%.*]] = sext i1 [[ARG:%.*]] to i32
+; CHECK-NEXT:    [[I2:%.*]] = sext i1 [[ARG1:%.*]] to i32
+; CHECK-NEXT:    [[I3:%.*]] = add nsw i32 [[I2]], [[I]]
+; CHECK-NEXT:    [[I4:%.*]] = icmp ult i32 [[I3]], 3
+; CHECK-NEXT:    ret i1 [[I4]]
+;
+bb:
+  %i = sext i1 %arg to i32
+  %i2 = sext i1 %arg1 to i32
+  %i3 = add i32 %i2, %i
+  %i4 = icmp ule i32 %i3, 2
+  ret i1 %i4
+}
+
+define i1 @test_cvt_icmp15(i1 %arg, i1 %arg1) {
+; CHECK-LABEL: @test_cvt_icmp15(
+; CHECK-NEXT:  bb:
+; CHECK-NEXT:    [[I:%.*]] = sext i1 [[ARG:%.*]] to i32
+; CHECK-NEXT:    [[I2:%.*]] = sext i1 [[ARG1:%.*]] to i32
+; CHECK-NEXT:    [[I3:%.*]] = add nsw i32 [[I2]], [[I]]
+; CHECK-NEXT:    [[I4:%.*]] = icmp sgt i32 [[I3]], 2
+; CHECK-NEXT:    ret i1 [[I4]]
+;
+bb:
+  %i = sext i1 %arg to i32
+  %i2 = sext i1 %arg1 to i32
+  %i3 = add i32 %i2, %i
+  %i4 = icmp sgt i32 %i3, 2
+  ret i1 %i4
+}
+
+define i1 @test_cvt_icmp16(i1 %arg, i1 %arg1) {
+; CHECK-LABEL: @test_cvt_icmp16(
+; CHECK-NEXT:  bb:
+; CHECK-NEXT:    [[I:%.*]] = sext i1 [[ARG:%.*]] to i32
+; CHECK-NEXT:    [[I2:%.*]] = sext i1 [[ARG1:%.*]] to i32
+; CHECK-NEXT:    [[I3:%.*]] = add nsw i32 [[I2]], [[I]]
+; CHECK-NEXT:    [[I4:%.*]] = icmp sgt i32 [[I3]], 1
+; CHECK-NEXT:    ret i1 [[I4]]
+;
+bb:
+  %i = sext i1 %arg to i32
+  %i2 = sext i1 %arg1 to i32
+  %i3 = add i32 %i2, %i
+  %i4 = icmp sge i32 %i3, 2
+  ret i1 %i4
+}
+
+define i1 @test_cvt_icmp17(i1 %arg, i1 %arg1) {
+; CHECK-LABEL: @test_cvt_icmp17(
+; CHECK-NEXT:  bb:
+; CHECK-NEXT:    [[I:%.*]] = sext i1 [[ARG:%.*]] to i32
+; CHECK-NEXT:    [[I2:%.*]] = sext i1 [[ARG1:%.*]] to i32
+; CHECK-NEXT:    [[I3:%.*]] = add nsw i32 [[I2]], [[I]]
+; CHECK-NEXT:    [[I4:%.*]] = icmp slt i32 [[I3]], 2
+; CHECK-NEXT:    ret i1 [[I4]]
+;
+bb:
+  %i = sext i1 %arg to i32
+  %i2 = sext i1 %arg1 to i32
+  %i3 = add i32 %i2, %i
+  %i4 = icmp slt i32 %i3, 2
+  ret i1 %i4
+}
+
+define i1 @test_cvt_icmp18(i1 %arg, i1 %arg1) {
+; CHECK-LABEL: @test_cvt_icmp18(
+; CHECK-NEXT:  bb:
+; CHECK-NEXT:    [[I:%.*]] = sext i1 [[ARG:%.*]] to i32
+; CHECK-NEXT:    [[I2:%.*]] = sext i1 [[ARG1:%.*]] to i32
+; CHECK-NEXT:    [[I3:%.*]] = add nsw i32 [[I2]], [[I]]
+; CHECK-NEXT:    [[I4:%.*]] = icmp slt i32 [[I3]], 3
+; CHECK-NEXT:    ret i1 [[I4]]
+;
+bb:
+  %i = sext i1 %arg to i32
+  %i2 = sext i1 %arg1 to i32
+  %i3 = add i32 %i2, %i
+  %i4 = icmp sle i32 %i3, 2
+  ret i1 %i4
+}
+
+define i1 @test_cvt_icmp19(i1 %arg, i1 %arg1) {
+; CHECK-LABEL: @test_cvt_icmp19(
+; CHECK-NEXT:  bb:
+; CHECK-NEXT:    [[TMP0:%.*]] = xor i1 [[ARG1:%.*]], true
+; CHECK-NEXT:    [[I4:%.*]] = and i1 [[TMP0]], [[ARG:%.*]]
+; CHECK-NEXT:    ret i1 [[I4]]
+;
+bb:
+  %i = sext i1 %arg to i32
+  %i2 = zext i1 %arg1 to i32
+  %i3 = add i32 %i2, %i
+  %i4 = icmp ugt i32 %i3, 2
+  ret i1 %i4
+}
+
+define i1 @test_cvt_icmp20(i1 %arg, i1 %arg1) {
+; CHECK-LABEL: @test_cvt_icmp20(
+; CHECK-NEXT:  bb:
+; CHECK-NEXT:    [[I4:%.*]] = xor i1 [[ARG1:%.*]], [[ARG:%.*]]
+; CHECK-NEXT:    ret i1 [[I4]]
+;
+bb:
+  %i = sext i1 %arg to i32
+  %i2 = zext i1 %arg1 to i32
+  %i3 = add i32 %i2, %i
+  %i4 = icmp uge i32 %i3, 1
+  ret i1 %i4
+}
+
+define i1 @test_cvt_icmp21(i1 %arg, i1 %arg1) {
+; CHECK-LABEL: @test_cvt_icmp21(
+; CHECK-NEXT:  bb:
+; CHECK-NEXT:    [[ARG_NOT:%.*]] = xor i1 [[ARG:%.*]], true
+; CHECK-NEXT:    [[I4:%.*]] = or i1 [[ARG_NOT]], [[ARG1:%.*]]
+; CHECK-NEXT:    ret i1 [[I4]]
+;
+bb:
+  %i = sext i1 %arg to i32
+  %i2 = zext i1 %arg1 to i32
+  %i3 = add i32 %i2, %i
+  %i4 = icmp ult i32 %i3, 2
+  ret i1 %i4
+}
+
+define i1 @test_cvt_icmp22(i1 %arg, i1 %arg1) {
+; CHECK-LABEL: @test_cvt_icmp22(
+; CHECK-NEXT:  bb:
+; CHECK-NEXT:    [[I:%.*]] = sext i1 [[ARG:%.*]] to i32
+; CHECK-NEXT:    [[I2:%.*]] = zext i1 [[ARG1:%.*]] to i32
+; CHECK-NEXT:    [[I3:%.*]] = add nsw i32 [[I2]], [[I]]
+; CHECK-NEXT:    [[I4:%.*]] = icmp ult i32 [[I3]], 3
+; CHECK-NEXT:    ret i1 [[I4]]
+;
+bb:
+  %i = sext i1 %arg to i32
+  %i2 = zext i1 %arg1 to i32
+  %i3 = add i32 %i2, %i
+  %i4 = icmp ule i32 %i3, 2
+  ret i1 %i4
+}
+
+define i1 @test_cvt_icmp23(i1 %arg, i1 %arg1) {
+; CHECK-LABEL: @test_cvt_icmp23(
+; CHECK-NEXT:  bb:
+; CHECK-NEXT:    ret i1 false
+;
+bb:
+  %i = sext i1 %arg to i32
+  %i2 = zext i1 %arg1 to i32
+  %i3 = add i32 %i2, %i
+  %i4 = icmp sgt i32 %i3, 2
+  ret i1 %i4
+}
+
+define i1 @test_cvt_icmp24(i1 %arg, i1 %arg1) {
+; CHECK-LABEL: @test_cvt_icmp24(
+; CHECK-NEXT:  bb:
+; CHECK-NEXT:    [[TMP0:%.*]] = xor i1 [[ARG:%.*]], true
+; CHECK-NEXT:    [[I4:%.*]] = or i1 [[TMP0]], [[ARG1:%.*]]
+; CHECK-NEXT:    ret i1 [[I4]]
+;
+bb:
+  %i = sext i1 %arg to i32
+  %i2 = zext i1 %arg1 to i32
+  %i3 = add i32 %i2, %i
+  %i4 = icmp sge i32 %i3, 0
+  ret i1 %i4
+}
+
+define i1 @test_cvt_icmp25(i1 %arg, i1 %arg1) {
+; CHECK-LABEL: @test_cvt_icmp25(
+; CHECK-NEXT:  bb:
+; CHECK-NEXT:    [[TMP0:%.*]] = xor i1 [[ARG1:%.*]], true
+; CHECK-NEXT:    [[I4:%.*]] = and i1 [[TMP0]], [[ARG:%.*]]
+; CHECK-NEXT:    ret i1 [[I4]]
+;
+bb:
+  %i = sext i1 %arg to i32
+  %i2 = zext i1 %arg1 to i32
+  %i3 = add i32 %i2, %i
+  %i4 = icmp slt i32 %i3, 0
+  ret i1 %i4
+}
+
+define i1 @test_cvt_icmp26(i1 %arg, i1 %arg1) {
+; CHECK-LABEL: @test_cvt_icmp26(
+; CHECK-NEXT:  bb:
+; CHECK-NEXT:    ret i1 true
+;
+bb:
+  %i = sext i1 %arg to i32
+  %i2 = zext i1 %arg1 to i32
+  %i3 = add i32 %i2, %i
+  %i4 = icmp sle i32 %i3, 1
+  ret i1 %i4
+}
+
 define i1 @test1(i32 %a) {
 ; CHECK-LABEL: @test1(
 ; CHECK-NEXT:    [[C:%.*]] = icmp ugt i32 [[A:%.*]], -5

>From 7cca836e722de44d9863fd073e8112be6d9e9164 Mon Sep 17 00:00:00 2001
From: Mohamed Atef <mohamedatef1698 at gmail.com>
Date: Sun, 1 Oct 2023 01:35:26 +0300
Subject: [PATCH 2/4] [InstCombine] Fold comparison of adding two z/sext
 booleans

---
 .../InstCombine/InstCombineCompares.cpp       | 104 +++++++++++++++++-
 llvm/test/Transforms/InstCombine/icmp-add.ll  | 100 +++++------------
 2 files changed, 131 insertions(+), 73 deletions(-)

diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
index 9f034aba874a8c4..cb828d0a6fc2a37 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
@@ -2900,14 +2900,114 @@ Instruction *InstCombinerImpl::foldICmpAddConstant(ICmpInst &Cmp,
                                                    BinaryOperator *Add,
                                                    const APInt &C) {
   Value *Y = Add->getOperand(1);
+  Value *X = Add->getOperand(0);
+
+  Value *Op0 = X, *Op1 = Y;
+  const CmpInst::Predicate Pred = Cmp.getPredicate();
+
+  // We handle all (s/zext i1 Op0 + s/zext i1 Op1 ==/!= 0/1/2) here.
+  // TODO: sext -1, sext -2
+  // sext i1 X + sext i1 Y == -1 --> xor i1 X, Y
+  // https://alive2.llvm.org/ce/z/2nSJ22
+  // sext i1 X + sext i1 Y == -2 --> and i1 X, Y
+  // https://alive2.llvm.org/ce/z/rasQlX
+  if (Cmp.isEquality() &&
+      match(Add, m_c_Add(m_OneUse(m_ZExtOrSExt(m_Value(Op0))),
+                         m_OneUse(m_ZExtOrSExt(m_Value(Op1))))) &&
+      Op0->getType()->isIntOrIntVectorTy(1) &&
+      Op1->getType()->isIntOrIntVectorTy(1) &&
+      (C.isZero() || C.isOne() || (C.exactLogBase2() == 1))) {
+    Value *Cond = Builder.getFalse();
+    // Handle zext/zext additions
+    if (match(X, m_OneUse(m_ZExt(m_Value(Op0)))) &&
+        match(Y, m_OneUse(m_ZExt(m_Value(Op1))))) {
+      if (Pred == ICmpInst::ICMP_EQ) {
+        // Case 1: zext i1 Op0 + zext i1 Op1 == 0 --> !(or i1 Op0, Op1)
+        if (C.isZero())
+          Cond = Builder.CreateNot(Builder.CreateOr(Op0, Op1));
+        else if (C.isOne())
+          // Case 2:  zext i1 Op0 + zext i1 Op1 == 1 --> xor i1 Op0, Op1
+          Cond = Builder.CreateXor(Op0, Op1);
+        else
+          // Case 3: zext i1 Op0 + zext i1 Op1 == 2 --> xor i1 Op0, Op1
+          Cond = Builder.CreateAnd(Op0, Op1);
+      } else {
+        // Case 1: zext i1 Op0 + zext i1 Op1 != 0 --> or i1 Op0, Op1
+        if (C.isZero())
+          Cond = Builder.CreateOr(Op0, Op1);
+        else if (C.isOne())
+          // Case 2: zext i1 Op0 + zext i1 Op1 != 1 --> !(xor i1 Op0, Op1)
+          Cond = Builder.CreateNot(Builder.CreateXor(Op0, Op1));
+        else
+          // Case 3: zext i1 Op0 + zext i1 Op1 != 2 --> !(and i1 Op0, Op1)
+          Cond = Builder.CreateNot(Builder.CreateAnd(Op0, Op1));
+      }
+      return replaceInstUsesWith(Cmp, Cond);
+    }
+
+    // Handles sext i1 Op0 + sext i1 Op1 ==/!= 0/1/2
+    if (match(X, m_OneUse(m_SExt(m_Value(Op0)))) &&
+        match(Y, m_OneUse(m_SExt(m_Value(Op1))))) {
+      if (Pred == ICmpInst::ICMP_EQ) {
+        // Case 1: sext i1 Op0 + sext i1 Op1 == 0 --> !(or i1 Op0, Op1)
+        if (C.isZero())
+          Cond = Builder.CreateNot(Builder.CreateOr(Op0, Op1));
+        // Case 2: sext i1 Op0 + sext i1 Op1 == 1 --> false
+        // Case 3: sext i1 Op0 + sext i1 Op2 == 2 --> false,
+        else
+          Cond = Builder.getFalse();
+      } else {
+        // Case 1: sext i1 Op0 + sext i1 Op1 != 0 --> or i1 Op0, Op1
+        if (C.isZero())
+          Cond = Builder.CreateOr(Op0, Op1);
+        else
+          // Case 2: sext i1 Op0 + sext i1 Op1 != 1 --> true
+          // Case 3: sext i1 Op0 + sext i1 Op2 != 2 --> true
+          Cond = Builder.getTrue();
+      }
+      return replaceInstUsesWith(Cmp, Cond);
+    }
+
+    // Sum is cummulative so swap the operations to avoid recompuations
+    if (match(X, m_OneUse(m_ZExt(m_OneUse(m_Value(Op0))))) &&
+        match(Y, m_OneUse(m_SExt(m_OneUse(m_Value(Op1)))))) {
+      std::swap(Op0, Op1);
+      std::swap(X, Y);
+    }
+    // Handles sext i1 Op0 + zext Op1 == 0/1/2
+    if (match(X, m_OneUse(m_SExt(m_Value(Op0)))) &&
+        match(Y, m_OneUse(m_ZExt(m_Value(Op1))))) {
+      if (Pred == ICmpInst::ICMP_EQ) {
+        // Case 1: sext i1 Op0 + zext i1 Op1 == 0 --> !(xor i1 Op0, Op1)
+        if (C.isZero())
+          Cond = Builder.CreateNot(Builder.CreateXor(Op0, Op1));
+        else if (C.isOne())
+          // Case 2: sext i1 Op0 + zext i1 Op1 == 1 --> (!Op0) & Op1
+          Cond = Builder.CreateAnd(Builder.CreateNot(Op0), Op1);
+        else
+          // Case 3: sext i1 Op0 + zext i1 Op1 == 2 --> false
+          Cond = Builder.getFalse();
+      } else {
+        // Case 1: sext i1 Op0 + zext i1 Op1 != 0 --> xor i1 Op0, Op1
+        if (C.isZero())
+          Cond = Builder.CreateXor(Op0, Op1);
+        else if (C.isOne())
+          // Case 2: sext i1 Op0 + zext i1 Op1 != 1 --> Op0 | (!Op1)
+          Cond = Builder.CreateOr(Op0, Builder.CreateNot(Op1));
+        else
+          // Case 3: sext i1 Op0 + zext i1 Op1 != 2 --> true
+          Cond = Builder.getTrue();
+      }
+      return replaceInstUsesWith(Cmp, Cond);
+    }
+    return nullptr;
+  }
   const APInt *C2;
   if (Cmp.isEquality() || !match(Y, m_APInt(C2)))
     return nullptr;
 
   // Fold icmp pred (add X, C2), C.
-  Value *X = Add->getOperand(0);
   Type *Ty = Add->getType();
-  const CmpInst::Predicate Pred = Cmp.getPredicate();
 
   // If the add does not wrap, we can always adjust the compare by subtracting
   // the constants. Equality comparisons are handled elsewhere. SGE/SLE/UGE/ULE
diff --git a/llvm/test/Transforms/InstCombine/icmp-add.ll b/llvm/test/Transforms/InstCombine/icmp-add.ll
index ec8d7d14d3b51f7..fae6fb0daec9ed9 100644
--- a/llvm/test/Transforms/InstCombine/icmp-add.ll
+++ b/llvm/test/Transforms/InstCombine/icmp-add.ll
@@ -23,10 +23,7 @@ bb:
 define i1 @cvt_icmp_1_zext_plus_zext_eq(i1 %arg, i1 %arg1) {
 ; CHECK-LABEL: @cvt_icmp_1_zext_plus_zext_eq(
 ; CHECK-NEXT:  bb:
-; CHECK-NEXT:    [[I:%.*]] = zext i1 [[ARG:%.*]] to i32
-; CHECK-NEXT:    [[I2:%.*]] = zext i1 [[ARG1:%.*]] to i32
-; CHECK-NEXT:    [[I3:%.*]] = add nuw nsw i32 [[I2]], [[I]]
-; CHECK-NEXT:    [[I4:%.*]] = icmp eq i32 [[I3]], 1
+; CHECK-NEXT:    [[I4:%.*]] = xor i1 [[ARG1:%.*]], [[ARG:%.*]]
 ; CHECK-NEXT:    ret i1 [[I4]]
 ;
 bb:
@@ -40,10 +37,7 @@ bb:
 define i1 @cvt_icmp_2_zext_plus_zext_eq(i1 %arg, i1 %arg1) {
 ; CHECK-LABEL: @cvt_icmp_2_zext_plus_zext_eq(
 ; CHECK-NEXT:  bb:
-; CHECK-NEXT:    [[I:%.*]] = zext i1 [[ARG:%.*]] to i32
-; CHECK-NEXT:    [[I2:%.*]] = zext i1 [[ARG1:%.*]] to i32
-; CHECK-NEXT:    [[I3:%.*]] = add nuw nsw i32 [[I]], [[I2]]
-; CHECK-NEXT:    [[T:%.*]] = icmp eq i32 [[I3]], 2
+; CHECK-NEXT:    [[T:%.*]] = and i1 [[ARG:%.*]], [[ARG1:%.*]]
 ; CHECK-NEXT:    ret i1 [[T]]
 ;
 bb:
@@ -72,11 +66,7 @@ bb:
 define i1 @cvt_icmp_1_sext_plus_sext_eq(i1 %arg, i1 %arg1) {
 ; CHECK-LABEL: @cvt_icmp_1_sext_plus_sext_eq(
 ; CHECK-NEXT:  bb:
-; CHECK-NEXT:    [[I:%.*]] = sext i1 [[ARG:%.*]] to i32
-; CHECK-NEXT:    [[I2:%.*]] = sext i1 [[ARG1:%.*]] to i32
-; CHECK-NEXT:    [[I3:%.*]] = add nsw i32 [[I]], [[I2]]
-; CHECK-NEXT:    [[T:%.*]] = icmp eq i32 [[I3]], 1
-; CHECK-NEXT:    ret i1 [[T]]
+; CHECK-NEXT:    ret i1 false
 ;
 bb:
   %i = sext i1 %arg to i32
@@ -89,11 +79,7 @@ bb:
 define i1 @cvt_icmp_2_sext_plus_sext_eq(i1 %arg, i1 %arg1) {
 ; CHECK-LABEL: @cvt_icmp_2_sext_plus_sext_eq(
 ; CHECK-NEXT:  bb:
-; CHECK-NEXT:    [[I:%.*]] = sext i1 [[ARG:%.*]] to i32
-; CHECK-NEXT:    [[I2:%.*]] = sext i1 [[ARG1:%.*]] to i32
-; CHECK-NEXT:    [[I3:%.*]] = add nsw i32 [[I]], [[I2]]
-; CHECK-NEXT:    [[T:%.*]] = icmp eq i32 [[I3]], 2
-; CHECK-NEXT:    ret i1 [[T]]
+; CHECK-NEXT:    ret i1 false
 ;
 bb:
   %i = sext i1 %arg to i32
@@ -136,11 +122,7 @@ bb:
 define i1 @cvt_icmp_2_sext_plus_zext_eq(i1 %arg, i1 %arg1) {
 ; CHECK-LABEL: @cvt_icmp_2_sext_plus_zext_eq(
 ; CHECK-NEXT:  bb:
-; CHECK-NEXT:    [[I:%.*]] = sext i1 [[ARG:%.*]] to i32
-; CHECK-NEXT:    [[I2:%.*]] = zext i1 [[ARG1:%.*]] to i32
-; CHECK-NEXT:    [[I3:%.*]] = add nsw i32 [[I]], [[I2]]
-; CHECK-NEXT:    [[T:%.*]] = icmp eq i32 [[I3]], 2
-; CHECK-NEXT:    ret i1 [[T]]
+; CHECK-NEXT:    ret i1 false
 ;
 bb:
   %i = sext i1 %arg to i32
@@ -153,8 +135,8 @@ bb:
 define i1 @cvt_icmp_0_zext_plus_zext_ne(i1 %arg, i1 %arg1) {
 ; CHECK-LABEL: @cvt_icmp_0_zext_plus_zext_ne(
 ; CHECK-NEXT:  bb:
-; CHECK-NEXT:    [[TMP0:%.*]] = or i1 [[ARG1:%.*]], [[ARG:%.*]]
-; CHECK-NEXT:    ret i1 [[TMP0]]
+; CHECK-NEXT:    [[I4:%.*]] = or i1 [[ARG1:%.*]], [[ARG:%.*]]
+; CHECK-NEXT:    ret i1 [[I4]]
 ;
 bb:
   %i = zext i1 %arg to i32
@@ -167,10 +149,8 @@ bb:
 define i1 @cvt_icmp_1_zext_plus_zext_ne(i1 %arg, i1 %arg1) {
 ; CHECK-LABEL: @cvt_icmp_1_zext_plus_zext_ne(
 ; CHECK-NEXT:  bb:
-; CHECK-NEXT:    [[I:%.*]] = zext i1 [[ARG:%.*]] to i32
-; CHECK-NEXT:    [[I2:%.*]] = zext i1 [[ARG1:%.*]] to i32
-; CHECK-NEXT:    [[I3:%.*]] = add nuw nsw i32 [[I2]], [[I]]
-; CHECK-NEXT:    [[I4:%.*]] = icmp ne i32 [[I3]], 1
+; CHECK-NEXT:    [[TMP0:%.*]] = xor i1 [[ARG1:%.*]], [[ARG:%.*]]
+; CHECK-NEXT:    [[I4:%.*]] = xor i1 [[TMP0]], true
 ; CHECK-NEXT:    ret i1 [[I4]]
 ;
 bb:
@@ -184,10 +164,8 @@ bb:
 define i1 @cvt_icmp_2_zext_plus_zext_ne(i1 %arg, i1 %arg1) {
 ; CHECK-LABEL: @cvt_icmp_2_zext_plus_zext_ne(
 ; CHECK-NEXT:  bb:
-; CHECK-NEXT:    [[I:%.*]] = zext i1 [[ARG:%.*]] to i32
-; CHECK-NEXT:    [[I2:%.*]] = zext i1 [[ARG1:%.*]] to i32
-; CHECK-NEXT:    [[I3:%.*]] = add nuw nsw i32 [[I]], [[I2]]
-; CHECK-NEXT:    [[T:%.*]] = icmp ne i32 [[I3]], 2
+; CHECK-NEXT:    [[TMP0:%.*]] = and i1 [[ARG:%.*]], [[ARG1:%.*]]
+; CHECK-NEXT:    [[T:%.*]] = xor i1 [[TMP0]], true
 ; CHECK-NEXT:    ret i1 [[T]]
 ;
 bb:
@@ -201,8 +179,8 @@ bb:
 define i1 @cvt_icmp_0_sext_plus_sext_ne(i1 %arg, i1 %arg1) {
 ; CHECK-LABEL: @cvt_icmp_0_sext_plus_sext_ne(
 ; CHECK-NEXT:  bb:
-; CHECK-NEXT:    [[TMP0:%.*]] = or i1 [[ARG:%.*]], [[ARG1:%.*]]
-; CHECK-NEXT:    ret i1 [[TMP0]]
+; CHECK-NEXT:    [[T:%.*]] = or i1 [[ARG:%.*]], [[ARG1:%.*]]
+; CHECK-NEXT:    ret i1 [[T]]
 ;
 bb:
   %i = sext i1 %arg to i32
@@ -215,11 +193,7 @@ bb:
 define i1 @cvt_icmp_1_sext_plus_sext_ne(i1 %arg, i1 %arg1) {
 ; CHECK-LABEL: @cvt_icmp_1_sext_plus_sext_ne(
 ; CHECK-NEXT:  bb:
-; CHECK-NEXT:    [[I:%.*]] = sext i1 [[ARG:%.*]] to i32
-; CHECK-NEXT:    [[I2:%.*]] = sext i1 [[ARG1:%.*]] to i32
-; CHECK-NEXT:    [[I3:%.*]] = add nsw i32 [[I]], [[I2]]
-; CHECK-NEXT:    [[T:%.*]] = icmp ne i32 [[I3]], 1
-; CHECK-NEXT:    ret i1 [[T]]
+; CHECK-NEXT:    ret i1 true
 ;
 bb:
   %i = sext i1 %arg to i32
@@ -232,11 +206,7 @@ bb:
 define i1 @cvt_icmp_2_sext_plus_sext_ne(i1 %arg, i1 %arg1) {
 ; CHECK-LABEL: @cvt_icmp_2_sext_plus_sext_ne(
 ; CHECK-NEXT:  bb:
-; CHECK-NEXT:    [[I:%.*]] = sext i1 [[ARG:%.*]] to i32
-; CHECK-NEXT:    [[I2:%.*]] = sext i1 [[ARG1:%.*]] to i32
-; CHECK-NEXT:    [[I3:%.*]] = add nsw i32 [[I]], [[I2]]
-; CHECK-NEXT:    [[T:%.*]] = icmp ne i32 [[I3]], 2
-; CHECK-NEXT:    ret i1 [[T]]
+; CHECK-NEXT:    ret i1 true
 ;
 bb:
   %i = sext i1 %arg to i32
@@ -278,11 +248,7 @@ bb:
 define i1 @cvt_icmp_2_sext_plus_zext_ne(i1 %arg, i1 %arg1) {
 ; CHECK-LABEL: @cvt_icmp_2_sext_plus_zext_ne(
 ; CHECK-NEXT:  bb:
-; CHECK-NEXT:    [[I:%.*]] = sext i1 [[ARG:%.*]] to i32
-; CHECK-NEXT:    [[I2:%.*]] = zext i1 [[ARG1:%.*]] to i32
-; CHECK-NEXT:    [[I3:%.*]] = add nsw i32 [[I]], [[I2]]
-; CHECK-NEXT:    [[T:%.*]] = icmp ne i32 [[I3]], 2
-; CHECK-NEXT:    ret i1 [[T]]
+; CHECK-NEXT:    ret i1 true
 ;
 bb:
   %i = sext i1 %arg to i32
@@ -298,7 +264,7 @@ bb:
 define i1 @cvt_icmp_0_zext_plus_sext_eq(i1 %arg, i1 %arg1) {
 ; CHECK-LABEL: @cvt_icmp_0_zext_plus_sext_eq(
 ; CHECK-NEXT:  bb:
-; CHECK-NEXT:    [[TMP0:%.*]] = xor i1 [[ARG:%.*]], [[ARG1:%.*]]
+; CHECK-NEXT:    [[TMP0:%.*]] = xor i1 [[ARG1:%.*]], [[ARG:%.*]]
 ; CHECK-NEXT:    [[T:%.*]] = xor i1 [[TMP0]], true
 ; CHECK-NEXT:    ret i1 [[T]]
 ;
@@ -328,11 +294,7 @@ bb:
 define i1 @cvt_icmp_2_zext_plus_sext_eq(i1 %arg, i1 %arg1) {
 ; CHECK-LABEL: @cvt_icmp_2_zext_plus_sext_eq(
 ; CHECK-NEXT:  bb:
-; CHECK-NEXT:    [[I:%.*]] = zext i1 [[ARG:%.*]] to i32
-; CHECK-NEXT:    [[I2:%.*]] = sext i1 [[ARG1:%.*]] to i32
-; CHECK-NEXT:    [[I3:%.*]] = add nsw i32 [[I]], [[I2]]
-; CHECK-NEXT:    [[T:%.*]] = icmp eq i32 [[I3]], 2
-; CHECK-NEXT:    ret i1 [[T]]
+; CHECK-NEXT:    ret i1 false
 ;
 bb:
   %i = zext i1 %arg to i32
@@ -345,7 +307,7 @@ bb:
 define i1 @cvt_icmp_0_zext_plus_sext_ne(i1 %arg, i1 %arg1) {
 ; CHECK-LABEL: @cvt_icmp_0_zext_plus_sext_ne(
 ; CHECK-NEXT:  bb:
-; CHECK-NEXT:    [[T:%.*]] = xor i1 [[ARG:%.*]], [[ARG1:%.*]]
+; CHECK-NEXT:    [[T:%.*]] = xor i1 [[ARG1:%.*]], [[ARG:%.*]]
 ; CHECK-NEXT:    ret i1 [[T]]
 ;
 bb:
@@ -374,11 +336,7 @@ bb:
 define i1 @cvt_icmp_2_zext_plus_sext_ne(i1 %arg, i1 %arg1) {
 ; CHECK-LABEL: @cvt_icmp_2_zext_plus_sext_ne(
 ; CHECK-NEXT:  bb:
-; CHECK-NEXT:    [[I:%.*]] = zext i1 [[ARG:%.*]] to i32
-; CHECK-NEXT:    [[I2:%.*]] = sext i1 [[ARG1:%.*]] to i32
-; CHECK-NEXT:    [[I3:%.*]] = add nsw i32 [[I]], [[I2]]
-; CHECK-NEXT:    [[T:%.*]] = icmp ne i32 [[I3]], 2
-; CHECK-NEXT:    ret i1 [[T]]
+; CHECK-NEXT:    ret i1 true
 ;
 bb:
   %i = zext i1 %arg to i32
@@ -444,8 +402,8 @@ bb:
 define i1 @test_cvt_icmp4(i1 %arg, i1 %arg1) {
 ; CHECK-LABEL: @test_cvt_icmp4(
 ; CHECK-NEXT:  bb:
-; CHECK-NEXT:    [[TMP0:%.*]] = or i1 [[ARG1:%.*]], [[ARG:%.*]]
-; CHECK-NEXT:    ret i1 [[TMP0]]
+; CHECK-NEXT:    [[I4:%.*]] = or i1 [[ARG1:%.*]], [[ARG:%.*]]
+; CHECK-NEXT:    ret i1 [[I4]]
 ;
 bb:
   %i = zext i1 %arg to i32
@@ -458,8 +416,8 @@ bb:
 define i1 @test_cvt_icmp5(i1 %arg, i1 %arg1) {
 ; CHECK-LABEL: @test_cvt_icmp5(
 ; CHECK-NEXT:  bb:
-; CHECK-NEXT:    [[TMP0:%.*]] = or i1 [[ARG1:%.*]], [[ARG:%.*]]
-; CHECK-NEXT:    ret i1 [[TMP0]]
+; CHECK-NEXT:    [[I4:%.*]] = or i1 [[ARG1:%.*]], [[ARG:%.*]]
+; CHECK-NEXT:    ret i1 [[I4]]
 ;
 bb:
   %i = zext i1 %arg to i32
@@ -506,8 +464,8 @@ bb:
 define i1 @test_cvt_icmp8(i1 %arg, i1 %arg1) {
 ; CHECK-LABEL: @test_cvt_icmp8(
 ; CHECK-NEXT:  bb:
-; CHECK-NEXT:    [[TMP0:%.*]] = or i1 [[ARG1:%.*]], [[ARG:%.*]]
-; CHECK-NEXT:    ret i1 [[TMP0]]
+; CHECK-NEXT:    [[I4:%.*]] = or i1 [[ARG1:%.*]], [[ARG:%.*]]
+; CHECK-NEXT:    ret i1 [[I4]]
 ;
 bb:
   %i = zext i1 %arg to i32
@@ -569,8 +527,8 @@ bb:
 define i1 @test_cvt_icmp12(i1 %arg, i1 %arg1) {
 ; CHECK-LABEL: @test_cvt_icmp12(
 ; CHECK-NEXT:  bb:
-; CHECK-NEXT:    [[TMP0:%.*]] = or i1 [[ARG1:%.*]], [[ARG:%.*]]
-; CHECK-NEXT:    ret i1 [[TMP0]]
+; CHECK-NEXT:    [[I4:%.*]] = or i1 [[ARG1:%.*]], [[ARG:%.*]]
+; CHECK-NEXT:    ret i1 [[I4]]
 ;
 bb:
   %i = sext i1 %arg to i32
@@ -698,7 +656,7 @@ bb:
 define i1 @test_cvt_icmp20(i1 %arg, i1 %arg1) {
 ; CHECK-LABEL: @test_cvt_icmp20(
 ; CHECK-NEXT:  bb:
-; CHECK-NEXT:    [[I4:%.*]] = xor i1 [[ARG1:%.*]], [[ARG:%.*]]
+; CHECK-NEXT:    [[I4:%.*]] = xor i1 [[ARG:%.*]], [[ARG1:%.*]]
 ; CHECK-NEXT:    ret i1 [[I4]]
 ;
 bb:

>From 213cee06f6fcfc4d854536ce44d2321bd324e3b2 Mon Sep 17 00:00:00 2001
From: Mohamed Atef <mohamedatef1698 at gmail.com>
Date: Sun, 1 Oct 2023 01:35:26 +0300
Subject: [PATCH 3/4] [InstCombine] Add more test coverage for sext/zext
 boolean additions

---
 llvm/test/Transforms/InstCombine/icmp-add.ll | 1014 +++++++++++++++++-
 1 file changed, 987 insertions(+), 27 deletions(-)

diff --git a/llvm/test/Transforms/InstCombine/icmp-add.ll b/llvm/test/Transforms/InstCombine/icmp-add.ll
index fae6fb0daec9ed9..429a4979f2ce1e5 100644
--- a/llvm/test/Transforms/InstCombine/icmp-add.ll
+++ b/llvm/test/Transforms/InstCombine/icmp-add.ll
@@ -5,6 +5,32 @@ declare void @use(i32)
 
 ; PR1949
 
+define i1 @cvt_icmp_neg_2_zext_plus_zext_eq(i1 %arg, i1 %arg1) {
+; CHECK-LABEL: @cvt_icmp_neg_2_zext_plus_zext_eq(
+; CHECK-NEXT:  bb:
+; CHECK-NEXT:    ret i1 false
+;
+bb:
+  %i = zext i1 %arg to i32
+  %i2 = zext i1 %arg1 to i32
+  %i3 = add i32 %i2, %i
+  %i4 = icmp eq i32 %i3, -2
+  ret i1 %i4
+}
+
+define i1 @cvt_icmp_neg_1_zext_plus_zext_eq(i1 %arg, i1 %arg1) {
+; CHECK-LABEL: @cvt_icmp_neg_1_zext_plus_zext_eq(
+; CHECK-NEXT:  bb:
+; CHECK-NEXT:    ret i1 false
+;
+bb:
+  %i = zext i1 %arg to i32
+  %i2 = zext i1 %arg1 to i32
+  %i3 = add i32 %i2, %i
+  %i4 = icmp eq i32 %i3, -1
+  ret i1 %i4
+}
+
 define i1 @cvt_icmp_0_zext_plus_zext_eq(i1 %arg, i1 %arg1) {
 ; CHECK-LABEL: @cvt_icmp_0_zext_plus_zext_eq(
 ; CHECK-NEXT:  bb:
@@ -48,6 +74,40 @@ bb:
   ret i1 %t
 }
 
+define i1 @cvt_icmp_neg_2_sext_plus_sext_eq(i1 %arg, i1 %arg1) {
+; CHECK-LABEL: @cvt_icmp_neg_2_sext_plus_sext_eq(
+; CHECK-NEXT:  bb:
+; CHECK-NEXT:    [[I:%.*]] = sext i1 [[ARG:%.*]] to i32
+; CHECK-NEXT:    [[I2:%.*]] = sext i1 [[ARG1:%.*]] to i32
+; CHECK-NEXT:    [[I3:%.*]] = add nsw i32 [[I]], [[I2]]
+; CHECK-NEXT:    [[T:%.*]] = icmp eq i32 [[I3]], -2
+; CHECK-NEXT:    ret i1 [[T]]
+;
+bb:
+  %i = sext i1 %arg to i32
+  %i2 = sext i1 %arg1 to i32
+  %i3 = add i32 %i, %i2
+  %t = icmp eq i32 %i3, -2
+  ret i1 %t
+}
+
+define i1 @cvt_icmp_neg_1_sext_plus_sext_eq(i1 %arg, i1 %arg1) {
+; CHECK-LABEL: @cvt_icmp_neg_1_sext_plus_sext_eq(
+; CHECK-NEXT:  bb:
+; CHECK-NEXT:    [[I:%.*]] = sext i1 [[ARG:%.*]] to i32
+; CHECK-NEXT:    [[I2:%.*]] = sext i1 [[ARG1:%.*]] to i32
+; CHECK-NEXT:    [[I3:%.*]] = add nsw i32 [[I]], [[I2]]
+; CHECK-NEXT:    [[T:%.*]] = icmp eq i32 [[I3]], -1
+; CHECK-NEXT:    ret i1 [[T]]
+;
+bb:
+  %i = sext i1 %arg to i32
+  %i2 = sext i1 %arg1 to i32
+  %i3 = add i32 %i, %i2
+  %t = icmp eq i32 %i3, -1
+  ret i1 %t
+}
+
 define i1 @cvt_icmp_0_sext_plus_sext_eq(i1 %arg, i1 %arg1) {
 ; CHECK-LABEL: @cvt_icmp_0_sext_plus_sext_eq(
 ; CHECK-NEXT:  bb:
@@ -89,6 +149,38 @@ bb:
   ret i1 %t
 }
 
+define i1 @cvt_icmp_neg_2_sext_plus_zext_eq(i1 %arg, i1 %arg1) {
+; CHECK-LABEL: @cvt_icmp_neg_2_sext_plus_zext_eq(
+; CHECK-NEXT:  bb:
+; CHECK-NEXT:    [[I:%.*]] = sext i1 [[ARG:%.*]] to i32
+; CHECK-NEXT:    [[I2:%.*]] = zext i1 [[ARG1:%.*]] to i32
+; CHECK-NEXT:    [[I3:%.*]] = add nsw i32 [[I]], [[I2]]
+; CHECK-NEXT:    [[T:%.*]] = icmp eq i32 [[I3]], -2
+; CHECK-NEXT:    ret i1 [[T]]
+;
+bb:
+  %i = sext i1 %arg to i32
+  %i2 = zext i1 %arg1 to i32
+  %i3 = add i32 %i, %i2
+  %t = icmp eq i32 %i3, -2
+  ret i1 %t
+}
+
+define i1 @cvt_icmp_neg_1_sext_plus_zext_eq(i1 %arg, i1 %arg1) {
+; CHECK-LABEL: @cvt_icmp_neg_1_sext_plus_zext_eq(
+; CHECK-NEXT:  bb:
+; CHECK-NEXT:    [[TMP0:%.*]] = xor i1 [[ARG1:%.*]], true
+; CHECK-NEXT:    [[T:%.*]] = and i1 [[TMP0]], [[ARG:%.*]]
+; CHECK-NEXT:    ret i1 [[T]]
+;
+bb:
+  %i = sext i1 %arg to i32
+  %i2 = zext i1 %arg1 to i32
+  %i3 = add i32 %i, %i2
+  %t = icmp eq i32 %i3, -1
+  ret i1 %t
+}
+
 define i1 @cvt_icmp_0_sext_plus_zext_eq(i1 %arg, i1 %arg1) {
 ; CHECK-LABEL: @cvt_icmp_0_sext_plus_zext_eq(
 ; CHECK-NEXT:  bb:
@@ -132,6 +224,32 @@ bb:
   ret i1 %t
 }
 
+define i1 @cvt_icmp_neg_2_zext_plus_zext_ne(i1 %arg, i1 %arg1) {
+; CHECK-LABEL: @cvt_icmp_neg_2_zext_plus_zext_ne(
+; CHECK-NEXT:  bb:
+; CHECK-NEXT:    ret i1 true
+;
+bb:
+  %i = zext i1 %arg to i32
+  %i2 = zext i1 %arg1 to i32
+  %i3 = add i32 %i2, %i
+  %i4 = icmp ne i32 %i3, -2
+  ret i1 %i4
+}
+
+define i1 @cvt_icmp_neg_1_zext_plus_zext_ne(i1 %arg, i1 %arg1) {
+; CHECK-LABEL: @cvt_icmp_neg_1_zext_plus_zext_ne(
+; CHECK-NEXT:  bb:
+; CHECK-NEXT:    ret i1 true
+;
+bb:
+  %i = zext i1 %arg to i32
+  %i2 = zext i1 %arg1 to i32
+  %i3 = add i32 %i2, %i
+  %i4 = icmp ne i32 %i3, -1
+  ret i1 %i4
+}
+
 define i1 @cvt_icmp_0_zext_plus_zext_ne(i1 %arg, i1 %arg1) {
 ; CHECK-LABEL: @cvt_icmp_0_zext_plus_zext_ne(
 ; CHECK-NEXT:  bb:
@@ -176,6 +294,40 @@ bb:
   ret i1 %t
 }
 
+define i1 @cvt_icmp_neg_2_sext_plus_sext_ne(i1 %arg, i1 %arg1) {
+; CHECK-LABEL: @cvt_icmp_neg_2_sext_plus_sext_ne(
+; CHECK-NEXT:  bb:
+; CHECK-NEXT:    [[I:%.*]] = sext i1 [[ARG:%.*]] to i32
+; CHECK-NEXT:    [[I2:%.*]] = sext i1 [[ARG1:%.*]] to i32
+; CHECK-NEXT:    [[I3:%.*]] = add nsw i32 [[I]], [[I2]]
+; CHECK-NEXT:    [[T:%.*]] = icmp ne i32 [[I3]], -2
+; CHECK-NEXT:    ret i1 [[T]]
+;
+bb:
+  %i = sext i1 %arg to i32
+  %i2 = sext i1 %arg1 to i32
+  %i3 = add i32 %i, %i2
+  %t = icmp ne i32 %i3, -2
+  ret i1 %t
+}
+
+define i1 @cvt_icmp_neg_1_sext_plus_sext_ne(i1 %arg, i1 %arg1) {
+; CHECK-LABEL: @cvt_icmp_neg_1_sext_plus_sext_ne(
+; CHECK-NEXT:  bb:
+; CHECK-NEXT:    [[I:%.*]] = sext i1 [[ARG:%.*]] to i32
+; CHECK-NEXT:    [[I2:%.*]] = sext i1 [[ARG1:%.*]] to i32
+; CHECK-NEXT:    [[I3:%.*]] = add nsw i32 [[I]], [[I2]]
+; CHECK-NEXT:    [[T:%.*]] = icmp ne i32 [[I3]], -1
+; CHECK-NEXT:    ret i1 [[T]]
+;
+bb:
+  %i = sext i1 %arg to i32
+  %i2 = sext i1 %arg1 to i32
+  %i3 = add i32 %i, %i2
+  %t = icmp ne i32 %i3, -1
+  ret i1 %t
+}
+
 define i1 @cvt_icmp_0_sext_plus_sext_ne(i1 %arg, i1 %arg1) {
 ; CHECK-LABEL: @cvt_icmp_0_sext_plus_sext_ne(
 ; CHECK-NEXT:  bb:
@@ -216,6 +368,38 @@ bb:
   ret i1 %t
 }
 
+define i1 @cvt_icmp_neg_2_sext_plus_zext_ne(i1 %arg, i1 %arg1) {
+; CHECK-LABEL: @cvt_icmp_neg_2_sext_plus_zext_ne(
+; CHECK-NEXT:  bb:
+; CHECK-NEXT:    [[I:%.*]] = sext i1 [[ARG:%.*]] to i32
+; CHECK-NEXT:    [[I2:%.*]] = zext i1 [[ARG1:%.*]] to i32
+; CHECK-NEXT:    [[I3:%.*]] = add nsw i32 [[I]], [[I2]]
+; CHECK-NEXT:    [[T:%.*]] = icmp ne i32 [[I3]], -2
+; CHECK-NEXT:    ret i1 [[T]]
+;
+bb:
+  %i = sext i1 %arg to i32
+  %i2 = zext i1 %arg1 to i32
+  %i3 = add i32 %i, %i2
+  %t = icmp ne i32 %i3, -2
+  ret i1 %t
+}
+
+define i1 @cvt_icmp_neg_1_sext_plus_zext_ne(i1 %arg, i1 %arg1) {
+; CHECK-LABEL: @cvt_icmp_neg_1_sext_plus_zext_ne(
+; CHECK-NEXT:  bb:
+; CHECK-NEXT:    [[TMP0:%.*]] = xor i1 [[ARG:%.*]], true
+; CHECK-NEXT:    [[T:%.*]] = or i1 [[TMP0]], [[ARG1:%.*]]
+; CHECK-NEXT:    ret i1 [[T]]
+;
+bb:
+  %i = sext i1 %arg to i32
+  %i2 = zext i1 %arg1 to i32
+  %i3 = add i32 %i, %i2
+  %t = icmp ne i32 %i3, -1
+  ret i1 %t
+}
+
 define i1 @cvt_icmp_0_sext_plus_zext_ne(i1 %arg, i1 %arg1) {
 ; CHECK-LABEL: @cvt_icmp_0_sext_plus_zext_ne(
 ; CHECK-NEXT:  bb:
@@ -261,6 +445,38 @@ bb:
 ; test if zext i1 X + sext i1 Y converted to sext i1 X + zext i1 Y
 ; and then processed
 
+define i1 @cvt_icmp_neg_2_zext_plus_sext_eq(i1 %arg, i1 %arg1) {
+; CHECK-LABEL: @cvt_icmp_neg_2_zext_plus_sext_eq(
+; CHECK-NEXT:  bb:
+; CHECK-NEXT:    [[I:%.*]] = zext i1 [[ARG:%.*]] to i32
+; CHECK-NEXT:    [[I2:%.*]] = sext i1 [[ARG1:%.*]] to i32
+; CHECK-NEXT:    [[I3:%.*]] = add nsw i32 [[I]], [[I2]]
+; CHECK-NEXT:    [[T:%.*]] = icmp eq i32 [[I3]], -2
+; CHECK-NEXT:    ret i1 [[T]]
+;
+bb:
+  %i = zext i1 %arg to i32
+  %i2 = sext i1 %arg1 to i32
+  %i3 = add i32 %i, %i2
+  %t = icmp eq i32 %i3, -2
+  ret i1 %t
+}
+
+define i1 @cvt_icmp_neg_1_zext_plus_sext_eq(i1 %arg, i1 %arg1) {
+; CHECK-LABEL: @cvt_icmp_neg_1_zext_plus_sext_eq(
+; CHECK-NEXT:  bb:
+; CHECK-NEXT:    [[TMP0:%.*]] = xor i1 [[ARG:%.*]], true
+; CHECK-NEXT:    [[T:%.*]] = and i1 [[TMP0]], [[ARG1:%.*]]
+; CHECK-NEXT:    ret i1 [[T]]
+;
+bb:
+  %i = zext i1 %arg to i32
+  %i2 = sext i1 %arg1 to i32
+  %i3 = add i32 %i, %i2
+  %t = icmp eq i32 %i3, -1
+  ret i1 %t
+}
+
 define i1 @cvt_icmp_0_zext_plus_sext_eq(i1 %arg, i1 %arg1) {
 ; CHECK-LABEL: @cvt_icmp_0_zext_plus_sext_eq(
 ; CHECK-NEXT:  bb:
@@ -304,6 +520,38 @@ bb:
   ret i1 %t
 }
 
+define i1 @cvt_icmp_neg_2_zext_plus_sext_ne(i1 %arg, i1 %arg1) {
+; CHECK-LABEL: @cvt_icmp_neg_2_zext_plus_sext_ne(
+; CHECK-NEXT:  bb:
+; CHECK-NEXT:    [[I:%.*]] = zext i1 [[ARG:%.*]] to i32
+; CHECK-NEXT:    [[I2:%.*]] = sext i1 [[ARG1:%.*]] to i32
+; CHECK-NEXT:    [[I3:%.*]] = add nsw i32 [[I]], [[I2]]
+; CHECK-NEXT:    [[T:%.*]] = icmp ne i32 [[I3]], -2
+; CHECK-NEXT:    ret i1 [[T]]
+;
+bb:
+  %i = zext i1 %arg to i32
+  %i2 = sext i1 %arg1 to i32
+  %i3 = add i32 %i, %i2
+  %t = icmp ne i32 %i3, -2
+  ret i1 %t
+}
+
+define i1 @cvt_icmp_neg_1_zext_plus_sext_ne(i1 %arg, i1 %arg1) {
+; CHECK-LABEL: @cvt_icmp_neg_1_zext_plus_sext_ne(
+; CHECK-NEXT:  bb:
+; CHECK-NEXT:    [[TMP0:%.*]] = xor i1 [[ARG1:%.*]], true
+; CHECK-NEXT:    [[T:%.*]] = or i1 [[TMP0]], [[ARG:%.*]]
+; CHECK-NEXT:    ret i1 [[T]]
+;
+bb:
+  %i = zext i1 %arg to i32
+  %i2 = sext i1 %arg1 to i32
+  %i3 = add i32 %i, %i2
+  %t = icmp ne i32 %i3, -1
+  ret i1 %t
+}
+
 define i1 @cvt_icmp_0_zext_plus_sext_ne(i1 %arg, i1 %arg1) {
 ; CHECK-LABEL: @cvt_icmp_0_zext_plus_sext_ne(
 ; CHECK-NEXT:  bb:
@@ -385,50 +633,48 @@ bb:
   ret i1 %t
 }
 
-; tests for negative comparisons
-define i1 @test_cvt_icmp3(i1 %arg, i1 %arg1) {
-; CHECK-LABEL: @test_cvt_icmp3(
+; tests for ult
+define i1 @test_zext_zext_cvt_neg_2_ult_icmp(i1 %arg, i1 %arg1) {
+; CHECK-LABEL: @test_zext_zext_cvt_neg_2_ult_icmp(
 ; CHECK-NEXT:  bb:
-; CHECK-NEXT:    ret i1 false
+; CHECK-NEXT:    ret i1 true
 ;
 bb:
   %i = zext i1 %arg to i32
   %i2 = zext i1 %arg1 to i32
   %i3 = add i32 %i2, %i
-  %i4 = icmp ult i32 %i3, 0
+  %i4 = icmp ult i32 %i3, -2
   ret i1 %i4
 }
 
-define i1 @test_cvt_icmp4(i1 %arg, i1 %arg1) {
-; CHECK-LABEL: @test_cvt_icmp4(
+define i1 @test_zext_zext_cvt_neg_1_ult_icmp(i1 %arg, i1 %arg1) {
+; CHECK-LABEL: @test_zext_zext_cvt_neg_1_ult_icmp(
 ; CHECK-NEXT:  bb:
-; CHECK-NEXT:    [[I4:%.*]] = or i1 [[ARG1:%.*]], [[ARG:%.*]]
-; CHECK-NEXT:    ret i1 [[I4]]
+; CHECK-NEXT:    ret i1 true
 ;
 bb:
   %i = zext i1 %arg to i32
   %i2 = zext i1 %arg1 to i32
   %i3 = add i32 %i2, %i
-  %i4 = icmp ugt i32 %i3, 0
+  %i4 = icmp ult i32 %i3, -1
   ret i1 %i4
 }
 
-define i1 @test_cvt_icmp5(i1 %arg, i1 %arg1) {
-; CHECK-LABEL: @test_cvt_icmp5(
+define i1 @test_zext_zext_cvt_0_ult_icmp(i1 %arg, i1 %arg1) {
+; CHECK-LABEL: @test_zext_zext_cvt_0_ult_icmp(
 ; CHECK-NEXT:  bb:
-; CHECK-NEXT:    [[I4:%.*]] = or i1 [[ARG1:%.*]], [[ARG:%.*]]
-; CHECK-NEXT:    ret i1 [[I4]]
+; CHECK-NEXT:    ret i1 false
 ;
 bb:
   %i = zext i1 %arg to i32
   %i2 = zext i1 %arg1 to i32
   %i3 = add i32 %i2, %i
-  %i4 = icmp uge i32 %i3, 1
+  %i4 = icmp ult i32 %i3, 0
   ret i1 %i4
 }
 
-define i1 @test_cvt_icmp6(i1 %arg, i1 %arg1) {
-; CHECK-LABEL: @test_cvt_icmp6(
+define i1 @test_zext_zext_cvt_2_ult_icmp(i1 %arg, i1 %arg1) {
+; CHECK-LABEL: @test_zext_zext_cvt_2_ult_icmp(
 ; CHECK-NEXT:  bb:
 ; CHECK-NEXT:    [[I:%.*]] = zext i1 [[ARG:%.*]] to i32
 ; CHECK-NEXT:    [[I2:%.*]] = zext i1 [[ARG1:%.*]] to i32
@@ -440,24 +686,738 @@ bb:
   %i = zext i1 %arg to i32
   %i2 = zext i1 %arg1 to i32
   %i3 = add i32 %i2, %i
-  %i4 = icmp ule i32 %i3, 1
+  %i4 = icmp ult i32 %i3, 2
   ret i1 %i4
 }
 
-define i1 @test_cvt_icmp7(i1 %arg, i1 %arg1) {
-; CHECK-LABEL: @test_cvt_icmp7(
+define i1 @test_sext_sext_cvt_neg_2_ult_icmp(i1 %arg, i1 %arg1) {
+; CHECK-LABEL: @test_sext_sext_cvt_neg_2_ult_icmp(
 ; CHECK-NEXT:  bb:
-; CHECK-NEXT:    [[I:%.*]] = zext i1 [[ARG:%.*]] to i32
-; CHECK-NEXT:    [[I2:%.*]] = zext i1 [[ARG1:%.*]] to i32
-; CHECK-NEXT:    [[I3:%.*]] = add nuw nsw i32 [[I2]], [[I]]
-; CHECK-NEXT:    [[I4:%.*]] = icmp ugt i32 [[I3]], 1
+; CHECK-NEXT:    [[TMP0:%.*]] = or i1 [[ARG1:%.*]], [[ARG:%.*]]
+; CHECK-NEXT:    [[I4:%.*]] = xor i1 [[TMP0]], true
 ; CHECK-NEXT:    ret i1 [[I4]]
 ;
 bb:
-  %i = zext i1 %arg to i32
-  %i2 = zext i1 %arg1 to i32
+  %i = sext i1 %arg to i32
+  %i2 = sext i1 %arg1 to i32
   %i3 = add i32 %i2, %i
-  %i4 = icmp sgt i32 %i3, 1
+  %i4 = icmp ult i32 %i3, -2
+  ret i1 %i4
+}
+
+define i1 @test_sext_sext_cvt_neg_1_ult_icmp(i1 %arg, i1 %arg1) {
+; CHECK-LABEL: @test_sext_sext_cvt_neg_1_ult_icmp(
+; CHECK-NEXT:  bb:
+; CHECK-NEXT:    [[I:%.*]] = sext i1 [[ARG:%.*]] to i32
+; CHECK-NEXT:    [[I2:%.*]] = sext i1 [[ARG1:%.*]] to i32
+; CHECK-NEXT:    [[I3:%.*]] = add nsw i32 [[I2]], [[I]]
+; CHECK-NEXT:    [[I4:%.*]] = icmp ne i32 [[I3]], -1
+; CHECK-NEXT:    ret i1 [[I4]]
+;
+bb:
+  %i = sext i1 %arg to i32
+  %i2 = sext i1 %arg1 to i32
+  %i3 = add i32 %i2, %i
+  %i4 = icmp ult i32 %i3, -1
+  ret i1 %i4
+}
+
+define i1 @test_sext_sext_cvt_0_ult_icmp(i1 %arg, i1 %arg1) {
+; CHECK-LABEL: @test_sext_sext_cvt_0_ult_icmp(
+; CHECK-NEXT:  bb:
+; CHECK-NEXT:    ret i1 false
+;
+bb:
+  %i = sext i1 %arg to i32
+  %i2 = sext i1 %arg1 to i32
+  %i3 = add i32 %i2, %i
+  %i4 = icmp ult i32 %i3, 0
+  ret i1 %i4
+}
+
+define i1 @test_sext_sext_cvt_1_ult_icmp(i1 %arg, i1 %arg1) {
+; CHECK-LABEL: @test_sext_sext_cvt_1_ult_icmp(
+; CHECK-NEXT:  bb:
+; CHECK-NEXT:    [[TMP0:%.*]] = or i1 [[ARG1:%.*]], [[ARG:%.*]]
+; CHECK-NEXT:    [[I4:%.*]] = xor i1 [[TMP0]], true
+; CHECK-NEXT:    ret i1 [[I4]]
+;
+bb:
+  %i = sext i1 %arg to i32
+  %i2 = sext i1 %arg1 to i32
+  %i3 = add i32 %i2, %i
+  %i4 = icmp ult i32 %i3, 1
+  ret i1 %i4
+}
+
+define i1 @test_sext_sext_cvt_2_ult_icmp(i1 %arg, i1 %arg1) {
+; CHECK-LABEL: @test_sext_sext_cvt_2_ult_icmp(
+; CHECK-NEXT:  bb:
+; CHECK-NEXT:    [[TMP0:%.*]] = or i1 [[ARG1:%.*]], [[ARG:%.*]]
+; CHECK-NEXT:    [[I4:%.*]] = xor i1 [[TMP0]], true
+; CHECK-NEXT:    ret i1 [[I4]]
+;
+bb:
+  %i = sext i1 %arg to i32
+  %i2 = sext i1 %arg1 to i32
+  %i3 = add i32 %i2, %i
+  %i4 = icmp ult i32 %i3, 2
+  ret i1 %i4
+}
+
+define i1 @test_sext_zext_cvt_neg_2_ult_icmp(i1 %arg, i1 %arg1) {
+; CHECK-LABEL: @test_sext_zext_cvt_neg_2_ult_icmp(
+; CHECK-NEXT:  bb:
+; CHECK-NEXT:    [[ARG_NOT:%.*]] = xor i1 [[ARG:%.*]], true
+; CHECK-NEXT:    [[I4:%.*]] = or i1 [[ARG_NOT]], [[ARG1:%.*]]
+; CHECK-NEXT:    ret i1 [[I4]]
+;
+bb:
+  %i = sext i1 %arg to i32
+  %i2 = zext i1 %arg1 to i32
+  %i3 = add i32 %i2, %i
+  %i4 = icmp ult i32 %i3, -2
+  ret i1 %i4
+}
+
+define i1 @test_sext_zext_cvt_neg_1_ult_icmp(i1 %arg, i1 %arg1) {
+; CHECK-LABEL: @test_sext_zext_cvt_neg_1_ult_icmp(
+; CHECK-NEXT:  bb:
+; CHECK-NEXT:    [[TMP0:%.*]] = xor i1 [[ARG:%.*]], true
+; CHECK-NEXT:    [[I4:%.*]] = or i1 [[TMP0]], [[ARG1:%.*]]
+; CHECK-NEXT:    ret i1 [[I4]]
+;
+bb:
+  %i = sext i1 %arg to i32
+  %i2 = zext i1 %arg1 to i32
+  %i3 = add i32 %i2, %i
+  %i4 = icmp ult i32 %i3, -1
+  ret i1 %i4
+}
+
+define i1 @test_sext_zext_cvt_0_ult_icmp(i1 %arg, i1 %arg1) {
+; CHECK-LABEL: @test_sext_zext_cvt_0_ult_icmp(
+; CHECK-NEXT:  bb:
+; CHECK-NEXT:    ret i1 false
+;
+bb:
+  %i = sext i1 %arg to i32
+  %i2 = zext i1 %arg1 to i32
+  %i3 = add i32 %i2, %i
+  %i4 = icmp ult i32 %i3, 0
+  ret i1 %i4
+}
+
+define i1 @test_sext_zext_cvt_2_ult_icmp(i1 %arg, i1 %arg1) {
+; CHECK-LABEL: @test_sext_zext_cvt_2_ult_icmp(
+; CHECK-NEXT:  bb:
+; CHECK-NEXT:    [[ARG_NOT:%.*]] = xor i1 [[ARG:%.*]], true
+; CHECK-NEXT:    [[I4:%.*]] = or i1 [[ARG_NOT]], [[ARG1:%.*]]
+; CHECK-NEXT:    ret i1 [[I4]]
+;
+bb:
+  %i = sext i1 %arg to i32
+  %i2 = zext i1 %arg1 to i32
+  %i3 = add i32 %i2, %i
+  %i4 = icmp ult i32 %i3, 2
+  ret i1 %i4
+}
+
+define i1 @test_zext_sext_cvt_neg_1_ult_icmp(i1 %arg, i1 %arg1) {
+; CHECK-LABEL: @test_zext_sext_cvt_neg_1_ult_icmp(
+; CHECK-NEXT:  bb:
+; CHECK-NEXT:    [[TMP0:%.*]] = xor i1 [[ARG1:%.*]], true
+; CHECK-NEXT:    [[I4:%.*]] = or i1 [[TMP0]], [[ARG:%.*]]
+; CHECK-NEXT:    ret i1 [[I4]]
+;
+bb:
+  %i = zext i1 %arg to i32
+  %i2 = sext i1 %arg1 to i32
+  %i3 = add i32 %i2, %i
+  %i4 = icmp ult i32 %i3, -1
+  ret i1 %i4
+}
+
+define i1 @test_zext_sext_cvt_0_ult_icmp(i1 %arg, i1 %arg1) {
+; CHECK-LABEL: @test_zext_sext_cvt_0_ult_icmp(
+; CHECK-NEXT:  bb:
+; CHECK-NEXT:    ret i1 false
+;
+bb:
+  %i = zext i1 %arg to i32
+  %i2 = sext i1 %arg1 to i32
+  %i3 = add i32 %i2, %i
+  %i4 = icmp ult i32 %i3, 0
+  ret i1 %i4
+}
+
+define i1 @test_zext_sext_cvt_1_ult_icmp(i1 %arg, i1 %arg1) {
+; CHECK-LABEL: @test_zext_sext_cvt_1_ult_icmp(
+; CHECK-NEXT:  bb:
+; CHECK-NEXT:    [[TMP0:%.*]] = xor i1 [[ARG1:%.*]], [[ARG:%.*]]
+; CHECK-NEXT:    [[I4:%.*]] = xor i1 [[TMP0]], true
+; CHECK-NEXT:    ret i1 [[I4]]
+;
+bb:
+  %i = zext i1 %arg to i32
+  %i2 = sext i1 %arg1 to i32
+  %i3 = add i32 %i2, %i
+  %i4 = icmp ult i32 %i3, 1
+  ret i1 %i4
+}
+
+; tests for ugt
+define i1 @test_cvt_icmp4(i1 %arg, i1 %arg1) {
+; CHECK-LABEL: @test_cvt_icmp4(
+; CHECK-NEXT:  bb:
+; CHECK-NEXT:    [[I4:%.*]] = or i1 [[ARG1:%.*]], [[ARG:%.*]]
+; CHECK-NEXT:    ret i1 [[I4]]
+;
+bb:
+  %i = zext i1 %arg to i32
+  %i2 = zext i1 %arg1 to i32
+  %i3 = add i32 %i2, %i
+  %i4 = icmp ugt i32 %i3, 0
+  ret i1 %i4
+}
+
+define i1 @test_zext_zext_cvt_neg_2_ugt_icmp(i1 %arg, i1 %arg1) {
+; CHECK-LABEL: @test_zext_zext_cvt_neg_2_ugt_icmp(
+; CHECK-NEXT:  bb:
+; CHECK-NEXT:    ret i1 false
+;
+bb:
+  %i = zext i1 %arg to i32
+  %i2 = zext i1 %arg1 to i32
+  %i3 = add i32 %i2, %i
+  %i4 = icmp ugt i32 %i3, -2
+  ret i1 %i4
+}
+
+define i1 @test_zext_zext_cvt_1_ugt_icmp(i1 %arg, i1 %arg1) {
+; CHECK-LABEL: @test_zext_zext_cvt_1_ugt_icmp(
+; CHECK-NEXT:  bb:
+; CHECK-NEXT:    [[I:%.*]] = zext i1 [[ARG:%.*]] to i32
+; CHECK-NEXT:    [[I2:%.*]] = zext i1 [[ARG1:%.*]] to i32
+; CHECK-NEXT:    [[I3:%.*]] = add nuw nsw i32 [[I2]], [[I]]
+; CHECK-NEXT:    [[I4:%.*]] = icmp ugt i32 [[I3]], 1
+; CHECK-NEXT:    ret i1 [[I4]]
+;
+bb:
+  %i = zext i1 %arg to i32
+  %i2 = zext i1 %arg1 to i32
+  %i3 = add i32 %i2, %i
+  %i4 = icmp ugt i32 %i3, 1
+  ret i1 %i4
+}
+
+define i1 @test_zext_zext_cvt_2_ugt_icmp(i1 %arg, i1 %arg1) {
+; CHECK-LABEL: @test_zext_zext_cvt_2_ugt_icmp(
+; CHECK-NEXT:  bb:
+; CHECK-NEXT:    [[I:%.*]] = zext i1 [[ARG:%.*]] to i32
+; CHECK-NEXT:    [[I2:%.*]] = zext i1 [[ARG1:%.*]] to i32
+; CHECK-NEXT:    [[I3:%.*]] = add nuw nsw i32 [[I2]], [[I]]
+; CHECK-NEXT:    [[I4:%.*]] = icmp eq i32 [[I3]], 3
+; CHECK-NEXT:    ret i1 [[I4]]
+;
+bb:
+  %i = zext i1 %arg to i32
+  %i2 = zext i1 %arg1 to i32
+  %i3 = add i32 %i2, %i
+  %i4 = icmp ugt i32 %i3, 2
+  ret i1 %i4
+}
+
+define i1 @test_sext_sext_cvt_neg_2_ugt_icmp(i1 %arg, i1 %arg1) {
+; CHECK-LABEL: @test_sext_sext_cvt_neg_2_ugt_icmp(
+; CHECK-NEXT:  bb:
+; CHECK-NEXT:    [[I:%.*]] = sext i1 [[ARG:%.*]] to i32
+; CHECK-NEXT:    [[I2:%.*]] = sext i1 [[ARG1:%.*]] to i32
+; CHECK-NEXT:    [[I3:%.*]] = add nsw i32 [[I2]], [[I]]
+; CHECK-NEXT:    [[I4:%.*]] = icmp eq i32 [[I3]], -1
+; CHECK-NEXT:    ret i1 [[I4]]
+;
+bb:
+  %i = sext i1 %arg to i32
+  %i2 = sext i1 %arg1 to i32
+  %i3 = add i32 %i2, %i
+  %i4 = icmp ugt i32 %i3, -2
+  ret i1 %i4
+}
+
+define i1 @test_sext_sext_cvt_0_ugt_icmp(i1 %arg, i1 %arg1) {
+; CHECK-LABEL: @test_sext_sext_cvt_0_ugt_icmp(
+; CHECK-NEXT:  bb:
+; CHECK-NEXT:    [[TMP0:%.*]] = or i1 [[ARG1:%.*]], [[ARG:%.*]]
+; CHECK-NEXT:    ret i1 [[TMP0]]
+;
+bb:
+  %i = sext i1 %arg to i32
+  %i2 = sext i1 %arg1 to i32
+  %i3 = add i32 %i2, %i
+  %i4 = icmp ugt i32 %i3, 0
+  ret i1 %i4
+}
+
+define i1 @test_sext_sext_cvt_2_ugt_icmp(i1 %arg, i1 %arg1) {
+; CHECK-LABEL: @test_sext_sext_cvt_2_ugt_icmp(
+; CHECK-NEXT:  bb:
+; CHECK-NEXT:    [[I:%.*]] = sext i1 [[ARG:%.*]] to i32
+; CHECK-NEXT:    [[I2:%.*]] = sext i1 [[ARG1:%.*]] to i32
+; CHECK-NEXT:    [[I3:%.*]] = add nsw i32 [[I2]], [[I]]
+; CHECK-NEXT:    [[I4:%.*]] = icmp ugt i32 [[I3]], 2
+; CHECK-NEXT:    ret i1 [[I4]]
+;
+bb:
+  %i = sext i1 %arg to i32
+  %i2 = sext i1 %arg1 to i32
+  %i3 = add i32 %i2, %i
+  %i4 = icmp ugt i32 %i3, 2
+  ret i1 %i4
+}
+
+define i1 @test_zext_sext_cvt_neg_2_ugt_icmp(i1 %arg, i1 %arg1) {
+; CHECK-LABEL: @test_zext_sext_cvt_neg_2_ugt_icmp(
+; CHECK-NEXT:  bb:
+; CHECK-NEXT:    [[TMP0:%.*]] = xor i1 [[ARG:%.*]], true
+; CHECK-NEXT:    [[I4:%.*]] = and i1 [[TMP0]], [[ARG1:%.*]]
+; CHECK-NEXT:    ret i1 [[I4]]
+;
+bb:
+  %i = zext i1 %arg to i32
+  %i2 = sext i1 %arg1 to i32
+  %i3 = add i32 %i2, %i
+  %i4 = icmp ugt i32 %i3, -2
+  ret i1 %i4
+}
+
+define i1 @test_zext_sext_cvt_neg_1_ugt_icmp(i1 %arg, i1 %arg1) {
+; CHECK-LABEL: @test_zext_sext_cvt_neg_1_ugt_icmp(
+; CHECK-NEXT:  bb:
+; CHECK-NEXT:    ret i1 false
+;
+bb:
+  %i = zext i1 %arg to i32
+  %i2 = sext i1 %arg1 to i32
+  %i3 = add i32 %i2, %i
+  %i4 = icmp ugt i32 %i3, -1
+  ret i1 %i4
+}
+
+define i1 @test_zext_sext_cvt_0_ugt_icmp(i1 %arg, i1 %arg1) {
+; CHECK-LABEL: @test_zext_sext_cvt_0_ugt_icmp(
+; CHECK-NEXT:  bb:
+; CHECK-NEXT:    [[I4:%.*]] = xor i1 [[ARG1:%.*]], [[ARG:%.*]]
+; CHECK-NEXT:    ret i1 [[I4]]
+;
+bb:
+  %i = zext i1 %arg to i32
+  %i2 = sext i1 %arg1 to i32
+  %i3 = add i32 %i2, %i
+  %i4 = icmp ugt i32 %i3, 0
+  ret i1 %i4
+}
+
+define i1 @test_zext_sext_cvt_1_ugt_icmp(i1 %arg, i1 %arg1) {
+; CHECK-LABEL: @test_zext_sext_cvt_1_ugt_icmp(
+; CHECK-NEXT:  bb:
+; CHECK-NEXT:    [[TMP0:%.*]] = xor i1 [[ARG:%.*]], true
+; CHECK-NEXT:    [[I4:%.*]] = and i1 [[TMP0]], [[ARG1:%.*]]
+; CHECK-NEXT:    ret i1 [[I4]]
+;
+bb:
+  %i = zext i1 %arg to i32
+  %i2 = sext i1 %arg1 to i32
+  %i3 = add i32 %i2, %i
+  %i4 = icmp ugt i32 %i3, 1
+  ret i1 %i4
+}
+
+define i1 @test_zext_sext_cvt_2_ugt_icmp(i1 %arg, i1 %arg1) {
+; CHECK-LABEL: @test_zext_sext_cvt_2_ugt_icmp(
+; CHECK-NEXT:  bb:
+; CHECK-NEXT:    [[TMP0:%.*]] = xor i1 [[ARG:%.*]], true
+; CHECK-NEXT:    [[I4:%.*]] = and i1 [[TMP0]], [[ARG1:%.*]]
+; CHECK-NEXT:    ret i1 [[I4]]
+;
+bb:
+  %i = zext i1 %arg to i32
+  %i2 = sext i1 %arg1 to i32
+  %i3 = add i32 %i2, %i
+  %i4 = icmp ugt i32 %i3, 2
+  ret i1 %i4
+}
+
+define i1 @test_cvt_icmp5(i1 %arg, i1 %arg1) {
+; CHECK-LABEL: @test_cvt_icmp5(
+; CHECK-NEXT:  bb:
+; CHECK-NEXT:    [[I4:%.*]] = or i1 [[ARG1:%.*]], [[ARG:%.*]]
+; CHECK-NEXT:    ret i1 [[I4]]
+;
+bb:
+  %i = zext i1 %arg to i32
+  %i2 = zext i1 %arg1 to i32
+  %i3 = add i32 %i2, %i
+  %i4 = icmp uge i32 %i3, 1
+  ret i1 %i4
+}
+
+define i1 @test_cvt_icmp6(i1 %arg, i1 %arg1) {
+; CHECK-LABEL: @test_cvt_icmp6(
+; CHECK-NEXT:  bb:
+; CHECK-NEXT:    [[I:%.*]] = zext i1 [[ARG:%.*]] to i32
+; CHECK-NEXT:    [[I2:%.*]] = zext i1 [[ARG1:%.*]] to i32
+; CHECK-NEXT:    [[I3:%.*]] = add nuw nsw i32 [[I2]], [[I]]
+; CHECK-NEXT:    [[I4:%.*]] = icmp ult i32 [[I3]], 2
+; CHECK-NEXT:    ret i1 [[I4]]
+;
+bb:
+  %i = zext i1 %arg to i32
+  %i2 = zext i1 %arg1 to i32
+  %i3 = add i32 %i2, %i
+  %i4 = icmp ule i32 %i3, 1
+  ret i1 %i4
+}
+
+; tests for sgt
+define i1 @test_cvt_icmp7(i1 %arg, i1 %arg1) {
+; CHECK-LABEL: @test_cvt_icmp7(
+; CHECK-NEXT:  bb:
+; CHECK-NEXT:    [[I:%.*]] = zext i1 [[ARG:%.*]] to i32
+; CHECK-NEXT:    [[I2:%.*]] = zext i1 [[ARG1:%.*]] to i32
+; CHECK-NEXT:    [[I3:%.*]] = add nuw nsw i32 [[I2]], [[I]]
+; CHECK-NEXT:    [[I4:%.*]] = icmp ugt i32 [[I3]], 1
+; CHECK-NEXT:    ret i1 [[I4]]
+;
+bb:
+  %i = zext i1 %arg to i32
+  %i2 = zext i1 %arg1 to i32
+  %i3 = add i32 %i2, %i
+  %i4 = icmp sgt i32 %i3, 1
+  ret i1 %i4
+}
+
+define i1 @test_zext_zext_cvt_neg_2_sgt_icmp(i1 %arg, i1 %arg1) {
+; CHECK-LABEL: @test_zext_zext_cvt_neg_2_sgt_icmp(
+; CHECK-NEXT:  bb:
+; CHECK-NEXT:    ret i1 true
+;
+bb:
+  %i = zext i1 %arg to i32
+  %i2 = zext i1 %arg1 to i32
+  %i3 = add i32 %i2, %i
+  %i4 = icmp sgt i32 %i3, -2
+  ret i1 %i4
+}
+
+define i1 @test_zext_zext_cvt_neg_1_sgt_icmp(i1 %arg, i1 %arg1) {
+; CHECK-LABEL: @test_zext_zext_cvt_neg_1_sgt_icmp(
+; CHECK-NEXT:  bb:
+; CHECK-NEXT:    ret i1 true
+;
+bb:
+  %i = zext i1 %arg to i32
+  %i2 = zext i1 %arg1 to i32
+  %i3 = add i32 %i2, %i
+  %i4 = icmp sgt i32 %i3, -1
+  ret i1 %i4
+}
+
+define i1 @test_zext_zext_cvt_2_sgt_icmp(i1 %arg, i1 %arg1) {
+; CHECK-LABEL: @test_zext_zext_cvt_2_sgt_icmp(
+; CHECK-NEXT:  bb:
+; CHECK-NEXT:    [[I:%.*]] = zext i1 [[ARG:%.*]] to i32
+; CHECK-NEXT:    [[I2:%.*]] = zext i1 [[ARG1:%.*]] to i32
+; CHECK-NEXT:    [[I3:%.*]] = add nuw nsw i32 [[I2]], [[I]]
+; CHECK-NEXT:    [[I4:%.*]] = icmp eq i32 [[I3]], 3
+; CHECK-NEXT:    ret i1 [[I4]]
+;
+bb:
+  %i = zext i1 %arg to i32
+  %i2 = zext i1 %arg1 to i32
+  %i3 = add i32 %i2, %i
+  %i4 = icmp sgt i32 %i3, 2
+  ret i1 %i4
+}
+
+define i1 @test_sext_sext_cvt_neg_2_sgt_icmp(i1 %arg, i1 %arg1) {
+; CHECK-LABEL: @test_sext_sext_cvt_neg_2_sgt_icmp(
+; CHECK-NEXT:  bb:
+; CHECK-NEXT:    [[I:%.*]] = sext i1 [[ARG:%.*]] to i32
+; CHECK-NEXT:    [[I2:%.*]] = sext i1 [[ARG1:%.*]] to i32
+; CHECK-NEXT:    [[I3:%.*]] = add nsw i32 [[I2]], [[I]]
+; CHECK-NEXT:    [[I4:%.*]] = icmp sgt i32 [[I3]], -2
+; CHECK-NEXT:    ret i1 [[I4]]
+;
+bb:
+  %i = sext i1 %arg to i32
+  %i2 = sext i1 %arg1 to i32
+  %i3 = add i32 %i2, %i
+  %i4 = icmp sgt i32 %i3, -2
+  ret i1 %i4
+}
+
+define i1 @test_sext_sext_cvt_0_sgt_icmp(i1 %arg, i1 %arg1) {
+; CHECK-LABEL: @test_sext_sext_cvt_0_sgt_icmp(
+; CHECK-NEXT:  bb:
+; CHECK-NEXT:    [[I:%.*]] = sext i1 [[ARG:%.*]] to i32
+; CHECK-NEXT:    [[I2:%.*]] = sext i1 [[ARG1:%.*]] to i32
+; CHECK-NEXT:    [[I3:%.*]] = add nsw i32 [[I2]], [[I]]
+; CHECK-NEXT:    [[I4:%.*]] = icmp sgt i32 [[I3]], 0
+; CHECK-NEXT:    ret i1 [[I4]]
+;
+bb:
+  %i = sext i1 %arg to i32
+  %i2 = sext i1 %arg1 to i32
+  %i3 = add i32 %i2, %i
+  %i4 = icmp sgt i32 %i3, 0
+  ret i1 %i4
+}
+
+define i1 @test_sext_sext_cvt_2_sgt_icmp(i1 %arg, i1 %arg1) {
+; CHECK-LABEL: @test_sext_sext_cvt_2_sgt_icmp(
+; CHECK-NEXT:  bb:
+; CHECK-NEXT:    [[I:%.*]] = sext i1 [[ARG:%.*]] to i32
+; CHECK-NEXT:    [[I2:%.*]] = sext i1 [[ARG1:%.*]] to i32
+; CHECK-NEXT:    [[I3:%.*]] = add nsw i32 [[I2]], [[I]]
+; CHECK-NEXT:    [[I4:%.*]] = icmp sgt i32 [[I3]], 2
+; CHECK-NEXT:    ret i1 [[I4]]
+;
+bb:
+  %i = sext i1 %arg to i32
+  %i2 = sext i1 %arg1 to i32
+  %i3 = add i32 %i2, %i
+  %i4 = icmp sgt i32 %i3, 2
+  ret i1 %i4
+}
+
+define i1 @test_zext_sext_cvt_neg_2_sgt_icmp(i1 %arg, i1 %arg1) {
+; CHECK-LABEL: @test_zext_sext_cvt_neg_2_sgt_icmp(
+; CHECK-NEXT:  bb:
+; CHECK-NEXT:    ret i1 true
+;
+bb:
+  %i = zext i1 %arg to i32
+  %i2 = sext i1 %arg1 to i32
+  %i3 = add i32 %i2, %i
+  %i4 = icmp sgt i32 %i3, -2
+  ret i1 %i4
+}
+
+define i1 @test_zext_sext_cvt_neg_1_sgt_icmp(i1 %arg, i1 %arg1) {
+; CHECK-LABEL: @test_zext_sext_cvt_neg_1_sgt_icmp(
+; CHECK-NEXT:  bb:
+; CHECK-NEXT:    [[TMP0:%.*]] = xor i1 [[ARG1:%.*]], true
+; CHECK-NEXT:    [[I4:%.*]] = or i1 [[TMP0]], [[ARG:%.*]]
+; CHECK-NEXT:    ret i1 [[I4]]
+;
+bb:
+  %i = zext i1 %arg to i32
+  %i2 = sext i1 %arg1 to i32
+  %i3 = add i32 %i2, %i
+  %i4 = icmp sgt i32 %i3, -1
+  ret i1 %i4
+}
+
+define i1 @test_zext_sext_cvt_0_sgt_icmp(i1 %arg, i1 %arg1) {
+; CHECK-LABEL: @test_zext_sext_cvt_0_sgt_icmp(
+; CHECK-NEXT:  bb:
+; CHECK-NEXT:    [[TMP0:%.*]] = xor i1 [[ARG1:%.*]], true
+; CHECK-NEXT:    [[I4:%.*]] = and i1 [[TMP0]], [[ARG:%.*]]
+; CHECK-NEXT:    ret i1 [[I4]]
+;
+bb:
+  %i = zext i1 %arg to i32
+  %i2 = sext i1 %arg1 to i32
+  %i3 = add i32 %i2, %i
+  %i4 = icmp sgt i32 %i3, 0
+  ret i1 %i4
+}
+
+define i1 @test_zext_sext_cvt_1_sgt_icmp(i1 %arg, i1 %arg1) {
+; CHECK-LABEL: @test_zext_sext_cvt_1_sgt_icmp(
+; CHECK-NEXT:  bb:
+; CHECK-NEXT:    ret i1 false
+;
+bb:
+  %i = zext i1 %arg to i32
+  %i2 = sext i1 %arg1 to i32
+  %i3 = add i32 %i2, %i
+  %i4 = icmp sgt i32 %i3, 1
+  ret i1 %i4
+}
+
+define i1 @test_zext_sext_cvt_2_sgt_icmp(i1 %arg, i1 %arg1) {
+; CHECK-LABEL: @test_zext_sext_cvt_2_sgt_icmp(
+; CHECK-NEXT:  bb:
+; CHECK-NEXT:    ret i1 false
+;
+bb:
+  %i = zext i1 %arg to i32
+  %i2 = sext i1 %arg1 to i32
+  %i3 = add i32 %i2, %i
+  %i4 = icmp sgt i32 %i3, 2
+  ret i1 %i4
+}
+
+; tests for slt
+define i1 @test_zext_zext_cvt_neg_2_slt_icmp(i1 %arg, i1 %arg1) {
+; CHECK-LABEL: @test_zext_zext_cvt_neg_2_slt_icmp(
+; CHECK-NEXT:  bb:
+; CHECK-NEXT:    ret i1 false
+;
+bb:
+  %i = zext i1 %arg to i32
+  %i2 = zext i1 %arg1 to i32
+  %i3 = add i32 %i2, %i
+  %i4 = icmp slt i32 %i3, -2
+  ret i1 %i4
+}
+
+define i1 @test_zext_zext_cvt_neg_1_slt_icmp(i1 %arg, i1 %arg1) {
+; CHECK-LABEL: @test_zext_zext_cvt_neg_1_slt_icmp(
+; CHECK-NEXT:  bb:
+; CHECK-NEXT:    ret i1 false
+;
+bb:
+  %i = zext i1 %arg to i32
+  %i2 = zext i1 %arg1 to i32
+  %i3 = add i32 %i2, %i
+  %i4 = icmp slt i32 %i3, -1
+  ret i1 %i4
+}
+
+define i1 @test_zext_zext_cvt_2_slt_icmp(i1 %arg, i1 %arg1) {
+; CHECK-LABEL: @test_zext_zext_cvt_2_slt_icmp(
+; CHECK-NEXT:  bb:
+; CHECK-NEXT:    [[I:%.*]] = zext i1 [[ARG:%.*]] to i32
+; CHECK-NEXT:    [[I2:%.*]] = zext i1 [[ARG1:%.*]] to i32
+; CHECK-NEXT:    [[I3:%.*]] = add nuw nsw i32 [[I2]], [[I]]
+; CHECK-NEXT:    [[I4:%.*]] = icmp ult i32 [[I3]], 2
+; CHECK-NEXT:    ret i1 [[I4]]
+;
+bb:
+  %i = zext i1 %arg to i32
+  %i2 = zext i1 %arg1 to i32
+  %i3 = add i32 %i2, %i
+  %i4 = icmp slt i32 %i3, 2
+  ret i1 %i4
+}
+
+define i1 @test_sext_sext_cvt_neg_2_slt_icmp(i1 %arg, i1 %arg1) {
+; CHECK-LABEL: @test_sext_sext_cvt_neg_2_slt_icmp(
+; CHECK-NEXT:  bb:
+; CHECK-NEXT:    [[I:%.*]] = sext i1 [[ARG:%.*]] to i32
+; CHECK-NEXT:    [[I2:%.*]] = sext i1 [[ARG1:%.*]] to i32
+; CHECK-NEXT:    [[I3:%.*]] = add nsw i32 [[I2]], [[I]]
+; CHECK-NEXT:    [[I4:%.*]] = icmp slt i32 [[I3]], -2
+; CHECK-NEXT:    ret i1 [[I4]]
+;
+bb:
+  %i = sext i1 %arg to i32
+  %i2 = sext i1 %arg1 to i32
+  %i3 = add i32 %i2, %i
+  %i4 = icmp slt i32 %i3, -2
+  ret i1 %i4
+}
+
+define i1 @test_sext_sext_cvt_0_slt_icmp(i1 %arg, i1 %arg1) {
+; CHECK-LABEL: @test_sext_sext_cvt_0_slt_icmp(
+; CHECK-NEXT:  bb:
+; CHECK-NEXT:    [[TMP0:%.*]] = or i1 [[ARG1:%.*]], [[ARG:%.*]]
+; CHECK-NEXT:    ret i1 [[TMP0]]
+;
+bb:
+  %i = sext i1 %arg to i32
+  %i2 = sext i1 %arg1 to i32
+  %i3 = add i32 %i2, %i
+  %i4 = icmp slt i32 %i3, 0
+  ret i1 %i4
+}
+
+define i1 @test_sext_sext_cvt_2_slt_icmp(i1 %arg, i1 %arg1) {
+; CHECK-LABEL: @test_sext_sext_cvt_2_slt_icmp(
+; CHECK-NEXT:  bb:
+; CHECK-NEXT:    [[I:%.*]] = sext i1 [[ARG:%.*]] to i32
+; CHECK-NEXT:    [[I2:%.*]] = sext i1 [[ARG1:%.*]] to i32
+; CHECK-NEXT:    [[I3:%.*]] = add nsw i32 [[I2]], [[I]]
+; CHECK-NEXT:    [[I4:%.*]] = icmp slt i32 [[I3]], 2
+; CHECK-NEXT:    ret i1 [[I4]]
+;
+bb:
+  %i = sext i1 %arg to i32
+  %i2 = sext i1 %arg1 to i32
+  %i3 = add i32 %i2, %i
+  %i4 = icmp slt i32 %i3, 2
+  ret i1 %i4
+}
+
+define i1 @test_zext_sext_cvt_neg_2_slt_icmp(i1 %arg, i1 %arg1) {
+; CHECK-LABEL: @test_zext_sext_cvt_neg_2_slt_icmp(
+; CHECK-NEXT:  bb:
+; CHECK-NEXT:    ret i1 false
+;
+bb:
+  %i = zext i1 %arg to i32
+  %i2 = sext i1 %arg1 to i32
+  %i3 = add i32 %i2, %i
+  %i4 = icmp slt i32 %i3, -2
+  ret i1 %i4
+}
+
+define i1 @test_zext_sext_cvt_neg_1_slt_icmp(i1 %arg, i1 %arg1) {
+; CHECK-LABEL: @test_zext_sext_cvt_neg_1_slt_icmp(
+; CHECK-NEXT:  bb:
+; CHECK-NEXT:    ret i1 false
+;
+bb:
+  %i = zext i1 %arg to i32
+  %i2 = sext i1 %arg1 to i32
+  %i3 = add i32 %i2, %i
+  %i4 = icmp slt i32 %i3, -1
+  ret i1 %i4
+}
+
+define i1 @test_zext_sext_cvt_0_slt_icmp(i1 %arg, i1 %arg1) {
+; CHECK-LABEL: @test_zext_sext_cvt_0_slt_icmp(
+; CHECK-NEXT:  bb:
+; CHECK-NEXT:    [[TMP0:%.*]] = xor i1 [[ARG:%.*]], true
+; CHECK-NEXT:    [[I4:%.*]] = and i1 [[TMP0]], [[ARG1:%.*]]
+; CHECK-NEXT:    ret i1 [[I4]]
+;
+bb:
+  %i = zext i1 %arg to i32
+  %i2 = sext i1 %arg1 to i32
+  %i3 = add i32 %i2, %i
+  %i4 = icmp slt i32 %i3, 0
+  ret i1 %i4
+}
+
+define i1 @test_zext_sext_cvt_1_slt_icmp(i1 %arg, i1 %arg1) {
+; CHECK-LABEL: @test_zext_sext_cvt_1_slt_icmp(
+; CHECK-NEXT:  bb:
+; CHECK-NEXT:    [[TMP0:%.*]] = xor i1 [[ARG:%.*]], true
+; CHECK-NEXT:    [[I4:%.*]] = or i1 [[TMP0]], [[ARG1:%.*]]
+; CHECK-NEXT:    ret i1 [[I4]]
+;
+bb:
+  %i = zext i1 %arg to i32
+  %i2 = sext i1 %arg1 to i32
+  %i3 = add i32 %i2, %i
+  %i4 = icmp slt i32 %i3, 1
+  ret i1 %i4
+}
+
+define i1 @test_zext_sext_cvt_2_slt_icmp(i1 %arg, i1 %arg1) {
+; CHECK-LABEL: @test_zext_sext_cvt_2_slt_icmp(
+; CHECK-NEXT:  bb:
+; CHECK-NEXT:    ret i1 true
+;
+bb:
+  %i = zext i1 %arg to i32
+  %i2 = sext i1 %arg1 to i32
+  %i3 = add i32 %i2, %i
+  %i4 = icmp slt i32 %i3, 2
   ret i1 %i4
 }
 

>From b0db0ba941e07225d89884a85d76a074b7068fd9 Mon Sep 17 00:00:00 2001
From: Mohamed Atef <mohamedatef1698 at gmail.com>
Date: Mon, 2 Oct 2023 11:38:44 +0300
Subject: [PATCH 4/4] [InstCombine] Fold comparison of adding two z/sext
 booleans

---
 .../InstCombine/InstCombineCompares.cpp       | 162 +++++++-----------
 llvm/test/Transforms/InstCombine/icmp-add.ll  | 153 ++++-------------
 .../test/Transforms/InstCombine/icmp-range.ll |   3 +-
 3 files changed, 103 insertions(+), 215 deletions(-)

diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
index cb828d0a6fc2a37..464ea2175132a6a 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
@@ -26,6 +26,7 @@
 #include "llvm/IR/PatternMatch.h"
 #include "llvm/Support/KnownBits.h"
 #include "llvm/Transforms/InstCombine/InstCombiner.h"
+#include <bitset>
 
 using namespace llvm;
 using namespace PatternMatch;
@@ -2895,6 +2896,45 @@ Instruction *InstCombinerImpl::foldICmpSubConstant(ICmpInst &Cmp,
   return new ICmpInst(SwappedPred, Add, ConstantInt::get(Ty, ~C));
 }
 
+static Value *createLogicFromTable(const std::bitset<4> &Table, Value *Op0,
+                                   Value *Op1, IRBuilderBase &Builder) {
+  switch (Table.to_ulong()) {
+    case 0: // 0 0 0 0
+      return Builder.getFalse();
+    case 1: // 0 0 0 1
+      return Builder.CreateNot(Builder.CreateOr(Op0, Op1));
+    case 2: // 0 0 1 0
+      return Builder.CreateAnd(Builder.CreateNot(Op0), Op1);
+    case 3: // 0 0 1 1
+      return Op1;
+    case 4: // 0 1 0 0
+      return Builder.CreateAnd(Op0, Builder.CreateNot(Op1));
+    case 5: // 0 1 0 1
+      return Op0;
+    case 6: // 0 1 1 0
+      return Builder.CreateXor(Op0, Op1);
+    case 7: // 0 1 1 1
+      return Builder.CreateNot(Builder.CreateAnd(Op0, Op1));
+    case 8: // 1 0 0 0
+      return Builder.CreateAnd(Op0, Op1);
+    case 9: // 1 0 0 1
+      return Builder.CreateNot(Builder.CreateXor(Op0, Op1));
+    case 10: // 1 0 1 0
+      return Builder.CreateNot(Op1);
+    case 11: // 1 0 1 1
+      return Builder.CreateOr(Builder.CreateNot(Op0), Op1);
+    case 12: // 1 1 0 0
+      return Builder.CreateNot(Op1);
+    case 13: // 1 1 0 1
+      return Builder.CreateOr(Op0, Builder.CreateNot(Op1));
+    case 14: // 1 1 1 0
+      return Builder.CreateOr(Op0, Op1);
+    case 15: // 1 1 1 1
+      return Builder.getTrue();
+  }
+  return nullptr;
+}
+
 /// Fold icmp (add X, Y), C.
 Instruction *InstCombinerImpl::foldICmpAddConstant(ICmpInst &Cmp,
                                                    BinaryOperator *Add,
@@ -2902,105 +2942,33 @@ Instruction *InstCombinerImpl::foldICmpAddConstant(ICmpInst &Cmp,
   Value *Y = Add->getOperand(1);
   Value *X = Add->getOperand(0);
 
-  Value *Op0 = X, *Op1 = Y;
+  Value *Op0, *Op1;
+  Instruction *Ext0, *Ext1;
   const CmpInst::Predicate Pred = Cmp.getPredicate();
+  if (match(Add, m_c_Add(m_CombineAnd(m_Instruction(Ext0),
+                                      m_OneUse(m_ZExtOrSExt(m_Value(Op0)))),
+                         m_CombineAnd(m_Instruction(Ext1),
+                                      m_OneUse(m_ZExtOrSExt(m_Value(Op1)))))) &&
+    Op0->getType()->isIntOrIntVectorTy(1) &&
+    Op1->getType()->isIntOrIntVectorTy(1) &&
+    C.sge(-2) && C.sle(2)) {
+    unsigned BW = C.getBitWidth();
+    std::bitset<4> Table;
+    auto ComputeTable = [&](bool Op0Val, bool Op1Val) {
+      int Res = 0;
+      if (Op0Val)
+        Res += isa<ZExtInst>(Ext0) ? 1 : -1;
+      if (Op1Val)
+        Res += isa<ZExtInst>(Ext1) ? 1 : -1;
+      return ICmpInst::compare(APInt(BW, Res, true), C, Pred);
+    };
 
-  // We handle all (s/zext i1 Op0 + s/zext i1 Op1 ==/!= 0/1/2) here.
-  // TODO: sext -1, sext -2
-  // sext i1 X + sext i1 Y == -1 --> xor i1 X, Y
-  // https://alive2.llvm.org/ce/z/2nSJ22
-  // sext i1 X + sext i1 Y == -2 --> and i1 X, Y
-  // https://alive2.llvm.org/ce/z/rasQlX
-  if (Cmp.isEquality() &&
-      match(Add, m_c_Add(m_OneUse(m_ZExtOrSExt(m_Value(Op0))),
-                         m_OneUse(m_ZExtOrSExt(m_Value(Op1))))) &&
-      Op0->getType()->isIntOrIntVectorTy(1) &&
-      Op1->getType()->isIntOrIntVectorTy(1) &&
-      (C.isZero() || C.isOne() || (C.exactLogBase2() == 1))) {
-    Value *Cond = Builder.getFalse();
-    // Handle zext/zext additions
-    if (match(X, m_OneUse(m_ZExt(m_Value(Op0)))) &&
-        match(Y, m_OneUse(m_ZExt(m_Value(Op1))))) {
-      if (Pred == ICmpInst::ICMP_EQ) {
-        // Case 1: zext i1 Op0 + zext i1 Op1 == 0 --> !(or i1 Op0, Op1)
-        if (C.isZero())
-          Cond = Builder.CreateNot(Builder.CreateOr(Op0, Op1));
-        else if (C.isOne())
-          // Case 2:  zext i1 Op0 + zext i1 Op1 == 1 --> xor i1 Op0, Op1
-          Cond = Builder.CreateXor(Op0, Op1);
-        else
-          // Case 3: zext i1 Op0 + zext i1 Op1 == 2 --> xor i1 Op0, Op1
-          Cond = Builder.CreateAnd(Op0, Op1);
-      } else {
-        // Case 1: zext i1 Op0 + zext i1 Op1 != 0 --> or i1 Op0, Op1
-        if (C.isZero())
-          Cond = Builder.CreateOr(Op0, Op1);
-        else if (C.isOne())
-          // Case 2: zext i1 Op0 + zext i1 Op1 != 1 --> !(xor i1 Op0, Op1)
-          Cond = Builder.CreateNot(Builder.CreateXor(Op0, Op1));
-        else
-          // Case 3: zext i1 Op0 + zext i1 Op1 != 2 --> !(and i1 Op0, Op1)
-          Cond = Builder.CreateNot(Builder.CreateAnd(Op0, Op1));
-      }
-      return replaceInstUsesWith(Cmp, Cond);
-    }
-
-    // Handles sext i1 Op0 + sext i1 Op1 ==/!= 0/1/2
-    if (match(X, m_OneUse(m_SExt(m_Value(Op0)))) &&
-        match(Y, m_OneUse(m_SExt(m_Value(Op1))))) {
-      if (Pred == ICmpInst::ICMP_EQ) {
-        // Case 1: sext i1 Op0 + sext i1 Op1 == 0 --> !(or i1 Op0, Op1)
-        if (C.isZero())
-          Cond = Builder.CreateNot(Builder.CreateOr(Op0, Op1));
-        // Case 2: sext i1 Op0 + sext i1 Op1 == 1 --> false
-        // Case 3: sext i1 Op0 + sext i1 Op2 == 2 --> false,
-        else
-          Cond = Builder.getFalse();
-      } else {
-        // Case 1: sext i1 Op0 + sext i1 Op1 != 0 --> or i1 Op0, Op1
-        if (C.isZero())
-          Cond = Builder.CreateOr(Op0, Op1);
-        else
-          // Case 2: sext i1 Op0 + sext i1 Op1 != 1 --> true
-          // Case 3: sext i1 Op0 + sext i1 Op2 != 2 --> true
-          Cond = Builder.getTrue();
-      }
-      return replaceInstUsesWith(Cmp, Cond);
-    }
-
-    // Sum is cummulative so swap the operations to avoid recompuations
-    if (match(X, m_OneUse(m_ZExt(m_OneUse(m_Value(Op0))))) &&
-        match(Y, m_OneUse(m_SExt(m_OneUse(m_Value(Op1)))))) {
-      std::swap(Op0, Op1);
-      std::swap(X, Y);
-    }
-    // Handles sext i1 Op0 + zext Op1 == 0/1/2
-    if (match(X, m_OneUse(m_SExt(m_Value(Op0)))) &&
-        match(Y, m_OneUse(m_ZExt(m_Value(Op1))))) {
-      if (Pred == ICmpInst::ICMP_EQ) {
-        // Case 1: sext i1 Op0 + zext i1 Op1 == 0 --> !(xor i1 Op0, Op1)
-        if (C.isZero())
-          Cond = Builder.CreateNot(Builder.CreateXor(Op0, Op1));
-        else if (C.isOne())
-          // Case 2: sext i1 Op0 + zext i1 Op1 == 1 --> (!Op0) & Op1
-          Cond = Builder.CreateAnd(Builder.CreateNot(Op0), Op1);
-        else
-          // Case 3: sext i1 Op0 + zext i1 Op1 == 2 --> false
-          Cond = Builder.getFalse();
-      } else {
-        // Case 1: sext i1 Op0 + zext i1 Op1 != 0 --> xor i1 Op0, Op1
-        if (C.isZero())
-          Cond = Builder.CreateXor(Op0, Op1);
-        else if (C.isOne())
-          // Case 2: sext i1 Op0 + zext i1 Op1 != 1 --> Op0 | (!Op1)
-          Cond = Builder.CreateOr(Op0, Builder.CreateNot(Op1));
-        else
-          // Case 3: sext i1 Op0 + zext i1 Op1 != 2 --> true
-          Cond = Builder.getTrue();
-      }
-      return replaceInstUsesWith(Cmp, Cond);
-    }
-    return nullptr;
+    Table[0] = ComputeTable(false, false);
+    Table[1] = ComputeTable(false, true);
+    Table[2] = ComputeTable(true, false);
+    Table[3] = ComputeTable(true, true);
+    auto *Cond = createLogicFromTable(Table, Op0, Op1, Builder);
+    return replaceInstUsesWith(Cmp, Cond);
   }
   const APInt *C2;
   if (Cmp.isEquality() || !match(Y, m_APInt(C2)))
diff --git a/llvm/test/Transforms/InstCombine/icmp-add.ll b/llvm/test/Transforms/InstCombine/icmp-add.ll
index 429a4979f2ce1e5..8ec37f4126ee0cd 100644
--- a/llvm/test/Transforms/InstCombine/icmp-add.ll
+++ b/llvm/test/Transforms/InstCombine/icmp-add.ll
@@ -77,10 +77,7 @@ bb:
 define i1 @cvt_icmp_neg_2_sext_plus_sext_eq(i1 %arg, i1 %arg1) {
 ; CHECK-LABEL: @cvt_icmp_neg_2_sext_plus_sext_eq(
 ; CHECK-NEXT:  bb:
-; CHECK-NEXT:    [[I:%.*]] = sext i1 [[ARG:%.*]] to i32
-; CHECK-NEXT:    [[I2:%.*]] = sext i1 [[ARG1:%.*]] to i32
-; CHECK-NEXT:    [[I3:%.*]] = add nsw i32 [[I]], [[I2]]
-; CHECK-NEXT:    [[T:%.*]] = icmp eq i32 [[I3]], -2
+; CHECK-NEXT:    [[T:%.*]] = and i1 [[ARG:%.*]], [[ARG1:%.*]]
 ; CHECK-NEXT:    ret i1 [[T]]
 ;
 bb:
@@ -94,10 +91,7 @@ bb:
 define i1 @cvt_icmp_neg_1_sext_plus_sext_eq(i1 %arg, i1 %arg1) {
 ; CHECK-LABEL: @cvt_icmp_neg_1_sext_plus_sext_eq(
 ; CHECK-NEXT:  bb:
-; CHECK-NEXT:    [[I:%.*]] = sext i1 [[ARG:%.*]] to i32
-; CHECK-NEXT:    [[I2:%.*]] = sext i1 [[ARG1:%.*]] to i32
-; CHECK-NEXT:    [[I3:%.*]] = add nsw i32 [[I]], [[I2]]
-; CHECK-NEXT:    [[T:%.*]] = icmp eq i32 [[I3]], -1
+; CHECK-NEXT:    [[T:%.*]] = xor i1 [[ARG:%.*]], [[ARG1:%.*]]
 ; CHECK-NEXT:    ret i1 [[T]]
 ;
 bb:
@@ -152,11 +146,7 @@ bb:
 define i1 @cvt_icmp_neg_2_sext_plus_zext_eq(i1 %arg, i1 %arg1) {
 ; CHECK-LABEL: @cvt_icmp_neg_2_sext_plus_zext_eq(
 ; CHECK-NEXT:  bb:
-; CHECK-NEXT:    [[I:%.*]] = sext i1 [[ARG:%.*]] to i32
-; CHECK-NEXT:    [[I2:%.*]] = zext i1 [[ARG1:%.*]] to i32
-; CHECK-NEXT:    [[I3:%.*]] = add nsw i32 [[I]], [[I2]]
-; CHECK-NEXT:    [[T:%.*]] = icmp eq i32 [[I3]], -2
-; CHECK-NEXT:    ret i1 [[T]]
+; CHECK-NEXT:    ret i1 false
 ;
 bb:
   %i = sext i1 %arg to i32
@@ -297,10 +287,8 @@ bb:
 define i1 @cvt_icmp_neg_2_sext_plus_sext_ne(i1 %arg, i1 %arg1) {
 ; CHECK-LABEL: @cvt_icmp_neg_2_sext_plus_sext_ne(
 ; CHECK-NEXT:  bb:
-; CHECK-NEXT:    [[I:%.*]] = sext i1 [[ARG:%.*]] to i32
-; CHECK-NEXT:    [[I2:%.*]] = sext i1 [[ARG1:%.*]] to i32
-; CHECK-NEXT:    [[I3:%.*]] = add nsw i32 [[I]], [[I2]]
-; CHECK-NEXT:    [[T:%.*]] = icmp ne i32 [[I3]], -2
+; CHECK-NEXT:    [[TMP0:%.*]] = and i1 [[ARG:%.*]], [[ARG1:%.*]]
+; CHECK-NEXT:    [[T:%.*]] = xor i1 [[TMP0]], true
 ; CHECK-NEXT:    ret i1 [[T]]
 ;
 bb:
@@ -314,10 +302,8 @@ bb:
 define i1 @cvt_icmp_neg_1_sext_plus_sext_ne(i1 %arg, i1 %arg1) {
 ; CHECK-LABEL: @cvt_icmp_neg_1_sext_plus_sext_ne(
 ; CHECK-NEXT:  bb:
-; CHECK-NEXT:    [[I:%.*]] = sext i1 [[ARG:%.*]] to i32
-; CHECK-NEXT:    [[I2:%.*]] = sext i1 [[ARG1:%.*]] to i32
-; CHECK-NEXT:    [[I3:%.*]] = add nsw i32 [[I]], [[I2]]
-; CHECK-NEXT:    [[T:%.*]] = icmp ne i32 [[I3]], -1
+; CHECK-NEXT:    [[TMP0:%.*]] = xor i1 [[ARG:%.*]], [[ARG1:%.*]]
+; CHECK-NEXT:    [[T:%.*]] = xor i1 [[TMP0]], true
 ; CHECK-NEXT:    ret i1 [[T]]
 ;
 bb:
@@ -371,11 +357,7 @@ bb:
 define i1 @cvt_icmp_neg_2_sext_plus_zext_ne(i1 %arg, i1 %arg1) {
 ; CHECK-LABEL: @cvt_icmp_neg_2_sext_plus_zext_ne(
 ; CHECK-NEXT:  bb:
-; CHECK-NEXT:    [[I:%.*]] = sext i1 [[ARG:%.*]] to i32
-; CHECK-NEXT:    [[I2:%.*]] = zext i1 [[ARG1:%.*]] to i32
-; CHECK-NEXT:    [[I3:%.*]] = add nsw i32 [[I]], [[I2]]
-; CHECK-NEXT:    [[T:%.*]] = icmp ne i32 [[I3]], -2
-; CHECK-NEXT:    ret i1 [[T]]
+; CHECK-NEXT:    ret i1 true
 ;
 bb:
   %i = sext i1 %arg to i32
@@ -448,11 +430,7 @@ bb:
 define i1 @cvt_icmp_neg_2_zext_plus_sext_eq(i1 %arg, i1 %arg1) {
 ; CHECK-LABEL: @cvt_icmp_neg_2_zext_plus_sext_eq(
 ; CHECK-NEXT:  bb:
-; CHECK-NEXT:    [[I:%.*]] = zext i1 [[ARG:%.*]] to i32
-; CHECK-NEXT:    [[I2:%.*]] = sext i1 [[ARG1:%.*]] to i32
-; CHECK-NEXT:    [[I3:%.*]] = add nsw i32 [[I]], [[I2]]
-; CHECK-NEXT:    [[T:%.*]] = icmp eq i32 [[I3]], -2
-; CHECK-NEXT:    ret i1 [[T]]
+; CHECK-NEXT:    ret i1 false
 ;
 bb:
   %i = zext i1 %arg to i32
@@ -523,11 +501,7 @@ bb:
 define i1 @cvt_icmp_neg_2_zext_plus_sext_ne(i1 %arg, i1 %arg1) {
 ; CHECK-LABEL: @cvt_icmp_neg_2_zext_plus_sext_ne(
 ; CHECK-NEXT:  bb:
-; CHECK-NEXT:    [[I:%.*]] = zext i1 [[ARG:%.*]] to i32
-; CHECK-NEXT:    [[I2:%.*]] = sext i1 [[ARG1:%.*]] to i32
-; CHECK-NEXT:    [[I3:%.*]] = add nsw i32 [[I]], [[I2]]
-; CHECK-NEXT:    [[T:%.*]] = icmp ne i32 [[I3]], -2
-; CHECK-NEXT:    ret i1 [[T]]
+; CHECK-NEXT:    ret i1 true
 ;
 bb:
   %i = zext i1 %arg to i32
@@ -676,10 +650,8 @@ bb:
 define i1 @test_zext_zext_cvt_2_ult_icmp(i1 %arg, i1 %arg1) {
 ; CHECK-LABEL: @test_zext_zext_cvt_2_ult_icmp(
 ; CHECK-NEXT:  bb:
-; CHECK-NEXT:    [[I:%.*]] = zext i1 [[ARG:%.*]] to i32
-; CHECK-NEXT:    [[I2:%.*]] = zext i1 [[ARG1:%.*]] to i32
-; CHECK-NEXT:    [[I3:%.*]] = add nuw nsw i32 [[I2]], [[I]]
-; CHECK-NEXT:    [[I4:%.*]] = icmp ult i32 [[I3]], 2
+; CHECK-NEXT:    [[TMP0:%.*]] = and i1 [[ARG1:%.*]], [[ARG:%.*]]
+; CHECK-NEXT:    [[I4:%.*]] = xor i1 [[TMP0]], true
 ; CHECK-NEXT:    ret i1 [[I4]]
 ;
 bb:
@@ -708,10 +680,8 @@ bb:
 define i1 @test_sext_sext_cvt_neg_1_ult_icmp(i1 %arg, i1 %arg1) {
 ; CHECK-LABEL: @test_sext_sext_cvt_neg_1_ult_icmp(
 ; CHECK-NEXT:  bb:
-; CHECK-NEXT:    [[I:%.*]] = sext i1 [[ARG:%.*]] to i32
-; CHECK-NEXT:    [[I2:%.*]] = sext i1 [[ARG1:%.*]] to i32
-; CHECK-NEXT:    [[I3:%.*]] = add nsw i32 [[I2]], [[I]]
-; CHECK-NEXT:    [[I4:%.*]] = icmp ne i32 [[I3]], -1
+; CHECK-NEXT:    [[TMP0:%.*]] = xor i1 [[ARG1:%.*]], [[ARG:%.*]]
+; CHECK-NEXT:    [[I4:%.*]] = xor i1 [[TMP0]], true
 ; CHECK-NEXT:    ret i1 [[I4]]
 ;
 bb:
@@ -897,10 +867,7 @@ bb:
 define i1 @test_zext_zext_cvt_1_ugt_icmp(i1 %arg, i1 %arg1) {
 ; CHECK-LABEL: @test_zext_zext_cvt_1_ugt_icmp(
 ; CHECK-NEXT:  bb:
-; CHECK-NEXT:    [[I:%.*]] = zext i1 [[ARG:%.*]] to i32
-; CHECK-NEXT:    [[I2:%.*]] = zext i1 [[ARG1:%.*]] to i32
-; CHECK-NEXT:    [[I3:%.*]] = add nuw nsw i32 [[I2]], [[I]]
-; CHECK-NEXT:    [[I4:%.*]] = icmp ugt i32 [[I3]], 1
+; CHECK-NEXT:    [[I4:%.*]] = and i1 [[ARG1:%.*]], [[ARG:%.*]]
 ; CHECK-NEXT:    ret i1 [[I4]]
 ;
 bb:
@@ -931,10 +898,7 @@ bb:
 define i1 @test_sext_sext_cvt_neg_2_ugt_icmp(i1 %arg, i1 %arg1) {
 ; CHECK-LABEL: @test_sext_sext_cvt_neg_2_ugt_icmp(
 ; CHECK-NEXT:  bb:
-; CHECK-NEXT:    [[I:%.*]] = sext i1 [[ARG:%.*]] to i32
-; CHECK-NEXT:    [[I2:%.*]] = sext i1 [[ARG1:%.*]] to i32
-; CHECK-NEXT:    [[I3:%.*]] = add nsw i32 [[I2]], [[I]]
-; CHECK-NEXT:    [[I4:%.*]] = icmp eq i32 [[I3]], -1
+; CHECK-NEXT:    [[I4:%.*]] = xor i1 [[ARG1:%.*]], [[ARG:%.*]]
 ; CHECK-NEXT:    ret i1 [[I4]]
 ;
 bb:
@@ -948,8 +912,8 @@ bb:
 define i1 @test_sext_sext_cvt_0_ugt_icmp(i1 %arg, i1 %arg1) {
 ; CHECK-LABEL: @test_sext_sext_cvt_0_ugt_icmp(
 ; CHECK-NEXT:  bb:
-; CHECK-NEXT:    [[TMP0:%.*]] = or i1 [[ARG1:%.*]], [[ARG:%.*]]
-; CHECK-NEXT:    ret i1 [[TMP0]]
+; CHECK-NEXT:    [[I4:%.*]] = or i1 [[ARG1:%.*]], [[ARG:%.*]]
+; CHECK-NEXT:    ret i1 [[I4]]
 ;
 bb:
   %i = sext i1 %arg to i32
@@ -962,10 +926,7 @@ bb:
 define i1 @test_sext_sext_cvt_2_ugt_icmp(i1 %arg, i1 %arg1) {
 ; CHECK-LABEL: @test_sext_sext_cvt_2_ugt_icmp(
 ; CHECK-NEXT:  bb:
-; CHECK-NEXT:    [[I:%.*]] = sext i1 [[ARG:%.*]] to i32
-; CHECK-NEXT:    [[I2:%.*]] = sext i1 [[ARG1:%.*]] to i32
-; CHECK-NEXT:    [[I3:%.*]] = add nsw i32 [[I2]], [[I]]
-; CHECK-NEXT:    [[I4:%.*]] = icmp ugt i32 [[I3]], 2
+; CHECK-NEXT:    [[I4:%.*]] = or i1 [[ARG1:%.*]], [[ARG:%.*]]
 ; CHECK-NEXT:    ret i1 [[I4]]
 ;
 bb:
@@ -1065,10 +1026,8 @@ bb:
 define i1 @test_cvt_icmp6(i1 %arg, i1 %arg1) {
 ; CHECK-LABEL: @test_cvt_icmp6(
 ; CHECK-NEXT:  bb:
-; CHECK-NEXT:    [[I:%.*]] = zext i1 [[ARG:%.*]] to i32
-; CHECK-NEXT:    [[I2:%.*]] = zext i1 [[ARG1:%.*]] to i32
-; CHECK-NEXT:    [[I3:%.*]] = add nuw nsw i32 [[I2]], [[I]]
-; CHECK-NEXT:    [[I4:%.*]] = icmp ult i32 [[I3]], 2
+; CHECK-NEXT:    [[TMP0:%.*]] = and i1 [[ARG1:%.*]], [[ARG:%.*]]
+; CHECK-NEXT:    [[I4:%.*]] = xor i1 [[TMP0]], true
 ; CHECK-NEXT:    ret i1 [[I4]]
 ;
 bb:
@@ -1083,10 +1042,7 @@ bb:
 define i1 @test_cvt_icmp7(i1 %arg, i1 %arg1) {
 ; CHECK-LABEL: @test_cvt_icmp7(
 ; CHECK-NEXT:  bb:
-; CHECK-NEXT:    [[I:%.*]] = zext i1 [[ARG:%.*]] to i32
-; CHECK-NEXT:    [[I2:%.*]] = zext i1 [[ARG1:%.*]] to i32
-; CHECK-NEXT:    [[I3:%.*]] = add nuw nsw i32 [[I2]], [[I]]
-; CHECK-NEXT:    [[I4:%.*]] = icmp ugt i32 [[I3]], 1
+; CHECK-NEXT:    [[I4:%.*]] = and i1 [[ARG1:%.*]], [[ARG:%.*]]
 ; CHECK-NEXT:    ret i1 [[I4]]
 ;
 bb:
@@ -1143,10 +1099,8 @@ bb:
 define i1 @test_sext_sext_cvt_neg_2_sgt_icmp(i1 %arg, i1 %arg1) {
 ; CHECK-LABEL: @test_sext_sext_cvt_neg_2_sgt_icmp(
 ; CHECK-NEXT:  bb:
-; CHECK-NEXT:    [[I:%.*]] = sext i1 [[ARG:%.*]] to i32
-; CHECK-NEXT:    [[I2:%.*]] = sext i1 [[ARG1:%.*]] to i32
-; CHECK-NEXT:    [[I3:%.*]] = add nsw i32 [[I2]], [[I]]
-; CHECK-NEXT:    [[I4:%.*]] = icmp sgt i32 [[I3]], -2
+; CHECK-NEXT:    [[TMP0:%.*]] = and i1 [[ARG1:%.*]], [[ARG:%.*]]
+; CHECK-NEXT:    [[I4:%.*]] = xor i1 [[TMP0]], true
 ; CHECK-NEXT:    ret i1 [[I4]]
 ;
 bb:
@@ -1160,11 +1114,7 @@ bb:
 define i1 @test_sext_sext_cvt_0_sgt_icmp(i1 %arg, i1 %arg1) {
 ; CHECK-LABEL: @test_sext_sext_cvt_0_sgt_icmp(
 ; CHECK-NEXT:  bb:
-; CHECK-NEXT:    [[I:%.*]] = sext i1 [[ARG:%.*]] to i32
-; CHECK-NEXT:    [[I2:%.*]] = sext i1 [[ARG1:%.*]] to i32
-; CHECK-NEXT:    [[I3:%.*]] = add nsw i32 [[I2]], [[I]]
-; CHECK-NEXT:    [[I4:%.*]] = icmp sgt i32 [[I3]], 0
-; CHECK-NEXT:    ret i1 [[I4]]
+; CHECK-NEXT:    ret i1 false
 ;
 bb:
   %i = sext i1 %arg to i32
@@ -1177,11 +1127,7 @@ bb:
 define i1 @test_sext_sext_cvt_2_sgt_icmp(i1 %arg, i1 %arg1) {
 ; CHECK-LABEL: @test_sext_sext_cvt_2_sgt_icmp(
 ; CHECK-NEXT:  bb:
-; CHECK-NEXT:    [[I:%.*]] = sext i1 [[ARG:%.*]] to i32
-; CHECK-NEXT:    [[I2:%.*]] = sext i1 [[ARG1:%.*]] to i32
-; CHECK-NEXT:    [[I3:%.*]] = add nsw i32 [[I2]], [[I]]
-; CHECK-NEXT:    [[I4:%.*]] = icmp sgt i32 [[I3]], 2
-; CHECK-NEXT:    ret i1 [[I4]]
+; CHECK-NEXT:    ret i1 false
 ;
 bb:
   %i = sext i1 %arg to i32
@@ -1290,10 +1236,8 @@ bb:
 define i1 @test_zext_zext_cvt_2_slt_icmp(i1 %arg, i1 %arg1) {
 ; CHECK-LABEL: @test_zext_zext_cvt_2_slt_icmp(
 ; CHECK-NEXT:  bb:
-; CHECK-NEXT:    [[I:%.*]] = zext i1 [[ARG:%.*]] to i32
-; CHECK-NEXT:    [[I2:%.*]] = zext i1 [[ARG1:%.*]] to i32
-; CHECK-NEXT:    [[I3:%.*]] = add nuw nsw i32 [[I2]], [[I]]
-; CHECK-NEXT:    [[I4:%.*]] = icmp ult i32 [[I3]], 2
+; CHECK-NEXT:    [[TMP0:%.*]] = and i1 [[ARG1:%.*]], [[ARG:%.*]]
+; CHECK-NEXT:    [[I4:%.*]] = xor i1 [[TMP0]], true
 ; CHECK-NEXT:    ret i1 [[I4]]
 ;
 bb:
@@ -1307,11 +1251,7 @@ bb:
 define i1 @test_sext_sext_cvt_neg_2_slt_icmp(i1 %arg, i1 %arg1) {
 ; CHECK-LABEL: @test_sext_sext_cvt_neg_2_slt_icmp(
 ; CHECK-NEXT:  bb:
-; CHECK-NEXT:    [[I:%.*]] = sext i1 [[ARG:%.*]] to i32
-; CHECK-NEXT:    [[I2:%.*]] = sext i1 [[ARG1:%.*]] to i32
-; CHECK-NEXT:    [[I3:%.*]] = add nsw i32 [[I2]], [[I]]
-; CHECK-NEXT:    [[I4:%.*]] = icmp slt i32 [[I3]], -2
-; CHECK-NEXT:    ret i1 [[I4]]
+; CHECK-NEXT:    ret i1 false
 ;
 bb:
   %i = sext i1 %arg to i32
@@ -1338,11 +1278,7 @@ bb:
 define i1 @test_sext_sext_cvt_2_slt_icmp(i1 %arg, i1 %arg1) {
 ; CHECK-LABEL: @test_sext_sext_cvt_2_slt_icmp(
 ; CHECK-NEXT:  bb:
-; CHECK-NEXT:    [[I:%.*]] = sext i1 [[ARG:%.*]] to i32
-; CHECK-NEXT:    [[I2:%.*]] = sext i1 [[ARG1:%.*]] to i32
-; CHECK-NEXT:    [[I3:%.*]] = add nsw i32 [[I2]], [[I]]
-; CHECK-NEXT:    [[I4:%.*]] = icmp slt i32 [[I3]], 2
-; CHECK-NEXT:    ret i1 [[I4]]
+; CHECK-NEXT:    ret i1 true
 ;
 bb:
   %i = sext i1 %arg to i32
@@ -1453,10 +1389,8 @@ bb:
 define i1 @test_cvt_icmp10(i1 %arg, i1 %arg1) {
 ; CHECK-LABEL: @test_cvt_icmp10(
 ; CHECK-NEXT:  bb:
-; CHECK-NEXT:    [[I:%.*]] = zext i1 [[ARG:%.*]] to i32
-; CHECK-NEXT:    [[I2:%.*]] = zext i1 [[ARG1:%.*]] to i32
-; CHECK-NEXT:    [[I3:%.*]] = add nuw nsw i32 [[I2]], [[I]]
-; CHECK-NEXT:    [[I4:%.*]] = icmp ult i32 [[I3]], 2
+; CHECK-NEXT:    [[TMP0:%.*]] = and i1 [[ARG1:%.*]], [[ARG:%.*]]
+; CHECK-NEXT:    [[I4:%.*]] = xor i1 [[TMP0]], true
 ; CHECK-NEXT:    ret i1 [[I4]]
 ;
 bb:
@@ -1470,10 +1404,7 @@ bb:
 define i1 @test_cvt_icmp11(i1 %arg, i1 %arg1) {
 ; CHECK-LABEL: @test_cvt_icmp11(
 ; CHECK-NEXT:  bb:
-; CHECK-NEXT:    [[I:%.*]] = sext i1 [[ARG:%.*]] to i32
-; CHECK-NEXT:    [[I2:%.*]] = sext i1 [[ARG1:%.*]] to i32
-; CHECK-NEXT:    [[I3:%.*]] = add nsw i32 [[I2]], [[I]]
-; CHECK-NEXT:    [[I4:%.*]] = icmp ugt i32 [[I3]], 2
+; CHECK-NEXT:    [[I4:%.*]] = or i1 [[ARG1:%.*]], [[ARG:%.*]]
 ; CHECK-NEXT:    ret i1 [[I4]]
 ;
 bb:
@@ -1533,11 +1464,7 @@ bb:
 define i1 @test_cvt_icmp15(i1 %arg, i1 %arg1) {
 ; CHECK-LABEL: @test_cvt_icmp15(
 ; CHECK-NEXT:  bb:
-; CHECK-NEXT:    [[I:%.*]] = sext i1 [[ARG:%.*]] to i32
-; CHECK-NEXT:    [[I2:%.*]] = sext i1 [[ARG1:%.*]] to i32
-; CHECK-NEXT:    [[I3:%.*]] = add nsw i32 [[I2]], [[I]]
-; CHECK-NEXT:    [[I4:%.*]] = icmp sgt i32 [[I3]], 2
-; CHECK-NEXT:    ret i1 [[I4]]
+; CHECK-NEXT:    ret i1 false
 ;
 bb:
   %i = sext i1 %arg to i32
@@ -1550,11 +1477,7 @@ bb:
 define i1 @test_cvt_icmp16(i1 %arg, i1 %arg1) {
 ; CHECK-LABEL: @test_cvt_icmp16(
 ; CHECK-NEXT:  bb:
-; CHECK-NEXT:    [[I:%.*]] = sext i1 [[ARG:%.*]] to i32
-; CHECK-NEXT:    [[I2:%.*]] = sext i1 [[ARG1:%.*]] to i32
-; CHECK-NEXT:    [[I3:%.*]] = add nsw i32 [[I2]], [[I]]
-; CHECK-NEXT:    [[I4:%.*]] = icmp sgt i32 [[I3]], 1
-; CHECK-NEXT:    ret i1 [[I4]]
+; CHECK-NEXT:    ret i1 false
 ;
 bb:
   %i = sext i1 %arg to i32
@@ -1567,11 +1490,7 @@ bb:
 define i1 @test_cvt_icmp17(i1 %arg, i1 %arg1) {
 ; CHECK-LABEL: @test_cvt_icmp17(
 ; CHECK-NEXT:  bb:
-; CHECK-NEXT:    [[I:%.*]] = sext i1 [[ARG:%.*]] to i32
-; CHECK-NEXT:    [[I2:%.*]] = sext i1 [[ARG1:%.*]] to i32
-; CHECK-NEXT:    [[I3:%.*]] = add nsw i32 [[I2]], [[I]]
-; CHECK-NEXT:    [[I4:%.*]] = icmp slt i32 [[I3]], 2
-; CHECK-NEXT:    ret i1 [[I4]]
+; CHECK-NEXT:    ret i1 true
 ;
 bb:
   %i = sext i1 %arg to i32
diff --git a/llvm/test/Transforms/InstCombine/icmp-range.ll b/llvm/test/Transforms/InstCombine/icmp-range.ll
index a6b629373946e30..1e809fadbd87908 100644
--- a/llvm/test/Transforms/InstCombine/icmp-range.ll
+++ b/llvm/test/Transforms/InstCombine/icmp-range.ll
@@ -945,7 +945,8 @@ define i1 @zext_sext_add_icmp_slt_1_no_oneuse(i1 %a, i1 %b) {
 ; CHECK-NEXT:    [[SEXT_B:%.*]] = sext i1 [[B:%.*]] to i8
 ; CHECK-NEXT:    [[ADD:%.*]] = add nsw i8 [[ZEXT_A]], [[SEXT_B]]
 ; CHECK-NEXT:    call void @use(i8 [[ADD]])
-; CHECK-NEXT:    [[R:%.*]] = icmp slt i8 [[ADD]], 1
+; CHECK-NEXT:    [[TMP1:%.*]] = xor i1 [[A]], true
+; CHECK-NEXT:    [[R:%.*]] = or i1 [[TMP1]], [[B]]
 ; CHECK-NEXT:    ret i1 [[R]]
 ;
   %zext.a = zext i1 %a to i8



More information about the llvm-commits mailing list