[clang-tools-extra] [RISCV] Eliminate dead li after emitting VSETVLIs (PR #65934)

2023-10-11 Thread Yingwei Zheng via cfe-commits

dtcxzyw wrote:

Gentle ping.

https://github.com/llvm/llvm-project/pull/65934
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang][RISCV] Fix the condition of checking signature in getIndex (PR #67403)

2023-10-11 Thread Yingwei Zheng via cfe-commits

https://github.com/dtcxzyw approved this pull request.

LGTM

https://github.com/llvm/llvm-project/pull/67403
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang-tools-extra] [InstCombine] Simplify the pattern `a ne/eq (zext/sext (a ne/eq c))` (PR #65852)

2023-10-06 Thread Yingwei Zheng via cfe-commits

https://github.com/dtcxzyw closed 
https://github.com/llvm/llvm-project/pull/65852
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [InstCombine] Simplify the pattern `a ne/eq (zext/sext (a ne/eq c))` (PR #65852)

2023-10-06 Thread Yingwei Zheng via cfe-commits

https://github.com/dtcxzyw closed 
https://github.com/llvm/llvm-project/pull/65852
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [InstCombine] Canonicalize `(X +/- Y) & Y` into `~X & Y` when Y is a power of 2 (PR #67915)

2023-10-06 Thread Yingwei Zheng via cfe-commits

https://github.com/dtcxzyw updated 
https://github.com/llvm/llvm-project/pull/67915

>From c4ce28c942c172e5646b5922f0b02b4169197840 Mon Sep 17 00:00:00 2001
From: Yingwei Zheng 
Date: Sun, 1 Oct 2023 21:52:47 +0800
Subject: [PATCH 1/2] [InstCombine] Canonicalize `(X +/- Y) & Y` into `~X & Y`
 when Y is a power of 2

---
 .../InstCombine/InstCombineAndOrXor.cpp   |  8 
 llvm/test/Transforms/InstCombine/and.ll   | 44 +--
 2 files changed, 48 insertions(+), 4 deletions(-)

diff --git a/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp 
b/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
index cbdab3e9c5fb91d..4322cc96f5a2b6c 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
@@ -2250,6 +2250,14 @@ Instruction *InstCombinerImpl::visitAnd(BinaryOperator 
) {
 return SelectInst::Create(Cmp, ConstantInt::getNullValue(Ty), Y);
   }
 
+  // Canonicalize:
+  // (X +/- Y) & Y --> ~X & Y when Y is a power of 2.
+  if (match(, m_c_And(m_Value(Y), m_OneUse(m_CombineOr(
+m_c_Add(m_Value(X), m_Deferred(Y)),
+m_Sub(m_Value(X), m_Deferred(Y)) &&
+  isKnownToBeAPowerOfTwo(Y, /*OrZero*/ true, /*Depth*/ 0, ))
+return BinaryOperator::CreateAnd(Builder.CreateNot(X), Y);
+
   const APInt *C;
   if (match(Op1, m_APInt(C))) {
 const APInt *XorC;
diff --git a/llvm/test/Transforms/InstCombine/and.ll 
b/llvm/test/Transforms/InstCombine/and.ll
index 90f027010e2aea6..eb39ff9014ff3a4 100644
--- a/llvm/test/Transforms/InstCombine/and.ll
+++ b/llvm/test/Transforms/InstCombine/and.ll
@@ -1595,8 +1595,8 @@ define <2 x i8> @flip_masked_bit_uniform(<2 x i8> %A) {
 
 define <2 x i8> @flip_masked_bit_undef(<2 x i8> %A) {
 ; CHECK-LABEL: @flip_masked_bit_undef(
-; CHECK-NEXT:[[B:%.*]] = add <2 x i8> [[A:%.*]], 
-; CHECK-NEXT:[[C:%.*]] = and <2 x i8> [[B]], 
+; CHECK-NEXT:[[TMP1:%.*]] = xor <2 x i8> [[A:%.*]], 
+; CHECK-NEXT:[[C:%.*]] = and <2 x i8> [[TMP1]], 
 ; CHECK-NEXT:ret <2 x i8> [[C]]
 ;
   %B = add <2 x i8> %A, 
@@ -1606,8 +1606,8 @@ define <2 x i8> @flip_masked_bit_undef(<2 x i8> %A) {
 
 define <2 x i8> @flip_masked_bit_nonuniform(<2 x i8> %A) {
 ; CHECK-LABEL: @flip_masked_bit_nonuniform(
-; CHECK-NEXT:[[B:%.*]] = add <2 x i8> [[A:%.*]], 
-; CHECK-NEXT:[[C:%.*]] = and <2 x i8> [[B]], 
+; CHECK-NEXT:[[TMP1:%.*]] = xor <2 x i8> [[A:%.*]], 
+; CHECK-NEXT:[[C:%.*]] = and <2 x i8> [[TMP1]], 
 ; CHECK-NEXT:ret <2 x i8> [[C]]
 ;
   %B = add <2 x i8> %A, 
@@ -2546,3 +2546,39 @@ define i32 @and_zext_eq_zero(i32 %A, i32 %C)  {
   %5 = and i32 %2, %4
   ret i32 %5
 }
+
+define i32 @canonicalize_and_add_power2_or_zero(i32 %x, i32 %y) {
+; CHECK-LABEL: @canonicalize_and_add_power2_or_zero(
+; CHECK-NEXT:[[NY:%.*]] = sub i32 0, [[Y:%.*]]
+; CHECK-NEXT:[[P2:%.*]] = and i32 [[NY]], [[Y]]
+; CHECK-NEXT:call void @use32(i32 [[P2]])
+; CHECK-NEXT:[[TMP1:%.*]] = xor i32 [[X:%.*]], -1
+; CHECK-NEXT:[[AND:%.*]] = and i32 [[P2]], [[TMP1]]
+; CHECK-NEXT:ret i32 [[AND]]
+;
+  %ny = sub i32 0, %y
+  %p2 = and i32 %y, %ny
+  call void @use32(i32 %p2) ; keep p2
+
+  %val = add i32 %x, %p2
+  %and = and i32 %val, %p2
+  ret i32 %and
+}
+
+define i32 @canonicalize_and_sub_power2_or_zero(i32 %x, i32 %y) {
+; CHECK-LABEL: @canonicalize_and_sub_power2_or_zero(
+; CHECK-NEXT:[[NY:%.*]] = sub i32 0, [[Y:%.*]]
+; CHECK-NEXT:[[P2:%.*]] = and i32 [[NY]], [[Y]]
+; CHECK-NEXT:call void @use32(i32 [[P2]])
+; CHECK-NEXT:[[TMP1:%.*]] = xor i32 [[X:%.*]], -1
+; CHECK-NEXT:[[AND:%.*]] = and i32 [[P2]], [[TMP1]]
+; CHECK-NEXT:ret i32 [[AND]]
+;
+  %ny = sub i32 0, %y
+  %p2 = and i32 %y, %ny
+  call void @use32(i32 %p2) ; keep p2
+
+  %val = sub i32 %x, %p2
+  %and = and i32 %val, %p2
+  ret i32 %and
+}

>From b64ca5b5f743e6a935f4ea09154c3a08c6e65c47 Mon Sep 17 00:00:00 2001
From: Yingwei Zheng 
Date: Fri, 6 Oct 2023 17:32:46 +0800
Subject: [PATCH 2/2] fixup! [InstCombine] Canonicalize `(X +/- Y) & Y` into
 `~X & Y` when Y is a power of 2

Add additional tests.
---
 llvm/test/Transforms/InstCombine/and.ll | 123 
 1 file changed, 123 insertions(+)

diff --git a/llvm/test/Transforms/InstCombine/and.ll 
b/llvm/test/Transforms/InstCombine/and.ll
index eb39ff9014ff3a4..989640ed41f2d2e 100644
--- a/llvm/test/Transforms/InstCombine/and.ll
+++ b/llvm/test/Transforms/InstCombine/and.ll
@@ -2582,3 +2582,126 @@ define i32 @canonicalize_and_sub_power2_or_zero(i32 %x, 
i32 %y) {
   %and = and i32 %val, %p2
   ret i32 %and
 }
+
+define i32 @canonicalize_and_add_power2_or_zero_commuted1(i32 %x, i32 %y) {
+; CHECK-LABEL: @canonicalize_and_add_power2_or_zero_commuted1(
+; CHECK-NEXT:[[NY:%.*]] = sub i32 0, [[Y:%.*]]
+; CHECK-NEXT:[[P2:%.*]] = and i32 [[NY]], [[Y]]
+; CHECK-NEXT:call void @use32(i32 [[P2]])
+; CHECK-NEXT:[[TMP1:%.*]] = xor i32 [[X:%.*]], 

[clang-tools-extra] [InstCombine] Canonicalize `(X +/- Y) & Y` into `~X & Y` when Y is a power of 2 (PR #67915)

2023-10-06 Thread Yingwei Zheng via cfe-commits

https://github.com/dtcxzyw updated 
https://github.com/llvm/llvm-project/pull/67915

>From c4ce28c942c172e5646b5922f0b02b4169197840 Mon Sep 17 00:00:00 2001
From: Yingwei Zheng 
Date: Sun, 1 Oct 2023 21:52:47 +0800
Subject: [PATCH 1/2] [InstCombine] Canonicalize `(X +/- Y) & Y` into `~X & Y`
 when Y is a power of 2

---
 .../InstCombine/InstCombineAndOrXor.cpp   |  8 
 llvm/test/Transforms/InstCombine/and.ll   | 44 +--
 2 files changed, 48 insertions(+), 4 deletions(-)

diff --git a/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp 
b/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
index cbdab3e9c5fb91d..4322cc96f5a2b6c 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
@@ -2250,6 +2250,14 @@ Instruction *InstCombinerImpl::visitAnd(BinaryOperator 
) {
 return SelectInst::Create(Cmp, ConstantInt::getNullValue(Ty), Y);
   }
 
+  // Canonicalize:
+  // (X +/- Y) & Y --> ~X & Y when Y is a power of 2.
+  if (match(, m_c_And(m_Value(Y), m_OneUse(m_CombineOr(
+m_c_Add(m_Value(X), m_Deferred(Y)),
+m_Sub(m_Value(X), m_Deferred(Y)) &&
+  isKnownToBeAPowerOfTwo(Y, /*OrZero*/ true, /*Depth*/ 0, ))
+return BinaryOperator::CreateAnd(Builder.CreateNot(X), Y);
+
   const APInt *C;
   if (match(Op1, m_APInt(C))) {
 const APInt *XorC;
diff --git a/llvm/test/Transforms/InstCombine/and.ll 
b/llvm/test/Transforms/InstCombine/and.ll
index 90f027010e2aea6..eb39ff9014ff3a4 100644
--- a/llvm/test/Transforms/InstCombine/and.ll
+++ b/llvm/test/Transforms/InstCombine/and.ll
@@ -1595,8 +1595,8 @@ define <2 x i8> @flip_masked_bit_uniform(<2 x i8> %A) {
 
 define <2 x i8> @flip_masked_bit_undef(<2 x i8> %A) {
 ; CHECK-LABEL: @flip_masked_bit_undef(
-; CHECK-NEXT:[[B:%.*]] = add <2 x i8> [[A:%.*]], 
-; CHECK-NEXT:[[C:%.*]] = and <2 x i8> [[B]], 
+; CHECK-NEXT:[[TMP1:%.*]] = xor <2 x i8> [[A:%.*]], 
+; CHECK-NEXT:[[C:%.*]] = and <2 x i8> [[TMP1]], 
 ; CHECK-NEXT:ret <2 x i8> [[C]]
 ;
   %B = add <2 x i8> %A, 
@@ -1606,8 +1606,8 @@ define <2 x i8> @flip_masked_bit_undef(<2 x i8> %A) {
 
 define <2 x i8> @flip_masked_bit_nonuniform(<2 x i8> %A) {
 ; CHECK-LABEL: @flip_masked_bit_nonuniform(
-; CHECK-NEXT:[[B:%.*]] = add <2 x i8> [[A:%.*]], 
-; CHECK-NEXT:[[C:%.*]] = and <2 x i8> [[B]], 
+; CHECK-NEXT:[[TMP1:%.*]] = xor <2 x i8> [[A:%.*]], 
+; CHECK-NEXT:[[C:%.*]] = and <2 x i8> [[TMP1]], 
 ; CHECK-NEXT:ret <2 x i8> [[C]]
 ;
   %B = add <2 x i8> %A, 
@@ -2546,3 +2546,39 @@ define i32 @and_zext_eq_zero(i32 %A, i32 %C)  {
   %5 = and i32 %2, %4
   ret i32 %5
 }
+
+define i32 @canonicalize_and_add_power2_or_zero(i32 %x, i32 %y) {
+; CHECK-LABEL: @canonicalize_and_add_power2_or_zero(
+; CHECK-NEXT:[[NY:%.*]] = sub i32 0, [[Y:%.*]]
+; CHECK-NEXT:[[P2:%.*]] = and i32 [[NY]], [[Y]]
+; CHECK-NEXT:call void @use32(i32 [[P2]])
+; CHECK-NEXT:[[TMP1:%.*]] = xor i32 [[X:%.*]], -1
+; CHECK-NEXT:[[AND:%.*]] = and i32 [[P2]], [[TMP1]]
+; CHECK-NEXT:ret i32 [[AND]]
+;
+  %ny = sub i32 0, %y
+  %p2 = and i32 %y, %ny
+  call void @use32(i32 %p2) ; keep p2
+
+  %val = add i32 %x, %p2
+  %and = and i32 %val, %p2
+  ret i32 %and
+}
+
+define i32 @canonicalize_and_sub_power2_or_zero(i32 %x, i32 %y) {
+; CHECK-LABEL: @canonicalize_and_sub_power2_or_zero(
+; CHECK-NEXT:[[NY:%.*]] = sub i32 0, [[Y:%.*]]
+; CHECK-NEXT:[[P2:%.*]] = and i32 [[NY]], [[Y]]
+; CHECK-NEXT:call void @use32(i32 [[P2]])
+; CHECK-NEXT:[[TMP1:%.*]] = xor i32 [[X:%.*]], -1
+; CHECK-NEXT:[[AND:%.*]] = and i32 [[P2]], [[TMP1]]
+; CHECK-NEXT:ret i32 [[AND]]
+;
+  %ny = sub i32 0, %y
+  %p2 = and i32 %y, %ny
+  call void @use32(i32 %p2) ; keep p2
+
+  %val = sub i32 %x, %p2
+  %and = and i32 %val, %p2
+  ret i32 %and
+}

>From b64ca5b5f743e6a935f4ea09154c3a08c6e65c47 Mon Sep 17 00:00:00 2001
From: Yingwei Zheng 
Date: Fri, 6 Oct 2023 17:32:46 +0800
Subject: [PATCH 2/2] fixup! [InstCombine] Canonicalize `(X +/- Y) & Y` into
 `~X & Y` when Y is a power of 2

Add additional tests.
---
 llvm/test/Transforms/InstCombine/and.ll | 123 
 1 file changed, 123 insertions(+)

diff --git a/llvm/test/Transforms/InstCombine/and.ll 
b/llvm/test/Transforms/InstCombine/and.ll
index eb39ff9014ff3a4..989640ed41f2d2e 100644
--- a/llvm/test/Transforms/InstCombine/and.ll
+++ b/llvm/test/Transforms/InstCombine/and.ll
@@ -2582,3 +2582,126 @@ define i32 @canonicalize_and_sub_power2_or_zero(i32 %x, 
i32 %y) {
   %and = and i32 %val, %p2
   ret i32 %and
 }
+
+define i32 @canonicalize_and_add_power2_or_zero_commuted1(i32 %x, i32 %y) {
+; CHECK-LABEL: @canonicalize_and_add_power2_or_zero_commuted1(
+; CHECK-NEXT:[[NY:%.*]] = sub i32 0, [[Y:%.*]]
+; CHECK-NEXT:[[P2:%.*]] = and i32 [[NY]], [[Y]]
+; CHECK-NEXT:call void @use32(i32 [[P2]])
+; CHECK-NEXT:[[TMP1:%.*]] = xor i32 [[X:%.*]], 

[clang-tools-extra] [InstCombine] Simplify the pattern `a ne/eq (zext/sext (a ne/eq c))` (PR #65852)

2023-10-06 Thread Yingwei Zheng via cfe-commits

dtcxzyw wrote:

The conflict resolution should be correct now.


https://github.com/llvm/llvm-project/pull/65852
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [InstCombine] Simplify the pattern `a ne/eq (zext/sext (a ne/eq c))` (PR #65852)

2023-10-06 Thread Yingwei Zheng via cfe-commits

dtcxzyw wrote:

The conflict resolution should be correct now.


https://github.com/llvm/llvm-project/pull/65852
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [InstCombine] Simplify the pattern `a ne/eq (zext/sext (a ne/eq c))` (PR #65852)

2023-10-06 Thread Yingwei Zheng via cfe-commits

https://github.com/dtcxzyw updated 
https://github.com/llvm/llvm-project/pull/65852

>From d9d8bcbb98e8f5aecb9733329389d61a489bd731 Mon Sep 17 00:00:00 2001
From: Yingwei Zheng 
Date: Sat, 9 Sep 2023 23:07:29 +0800
Subject: [PATCH 01/10] [InstCombine] Simplify the pattern `a ne/eq (zext (a
 ne/eq c))`

---
 .../InstCombine/InstCombineCompares.cpp   |  62 ++
 .../test/Transforms/InstCombine/icmp-range.ll | 181 ++
 2 files changed, 243 insertions(+)

diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp 
b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
index 9fdc46fec631679..837b8e6d2619989 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
@@ -6309,7 +6309,69 @@ Instruction 
*InstCombinerImpl::foldICmpUsingBoolRange(ICmpInst ) {
   Y->getType()->isIntOrIntVectorTy(1) && Pred == ICmpInst::ICMP_ULE)
 return BinaryOperator::CreateOr(Builder.CreateIsNull(X), Y);
 
+  ICmpInst::Predicate Pred1, Pred2;
   const APInt *C;
+  // icmp eq/ne X, (zext (icmp eq/ne X, C))
+  if (match(, m_c_ICmp(Pred1, m_Value(X),
+ m_ZExt(m_ICmp(Pred2, m_Deferred(X), m_APInt(C) &&
+  ICmpInst::isEquality(Pred1) && ICmpInst::isEquality(Pred2)) {
+if (C->isZero()) {
+  if (Pred2 == ICmpInst::ICMP_EQ) {
+// icmp eq X, (zext (icmp eq X, 0)) --> false
+// icmp ne X, (zext (icmp eq X, 0)) --> true
+return replaceInstUsesWith(
+I,
+Constant::getIntegerValue(
+I.getType(),
+APInt(1U, static_cast(Pred1 == ICmpInst::ICMP_NE;
+  } else {
+// icmp eq X, (zext (icmp ne X, 0)) --> icmp ult X, 2
+// icmp ne X, (zext (icmp ne X, 0)) --> icmp ugt X, 1
+return ICmpInst::Create(
+Instruction::ICmp,
+Pred1 == ICmpInst::ICMP_NE ? ICmpInst::ICMP_UGT
+   : ICmpInst::ICMP_ULT,
+X,
+Constant::getIntegerValue(
+X->getType(), APInt(X->getType()->getScalarSizeInBits(),
+Pred1 == ICmpInst::ICMP_NE ? 1 : 2)));
+  }
+} else if (C->isOne()) {
+  if (Pred2 == ICmpInst::ICMP_NE) {
+// icmp eq X, (zext (icmp ne X, 1)) --> false
+// icmp ne X, (zext (icmp ne X, 1)) --> true
+return replaceInstUsesWith(
+I,
+Constant::getIntegerValue(
+I.getType(),
+APInt(1U, static_cast(Pred1 == ICmpInst::ICMP_NE;
+  } else {
+// icmp eq X, (zext (icmp eq X, 1)) --> icmp ult X, 2
+// icmp ne X, (zext (icmp eq X, 1)) --> icmp ugt X, 1
+return ICmpInst::Create(
+Instruction::ICmp,
+Pred1 == ICmpInst::ICMP_NE ? ICmpInst::ICMP_UGT
+   : ICmpInst::ICMP_ULT,
+X,
+Constant::getIntegerValue(
+X->getType(), APInt(X->getType()->getScalarSizeInBits(),
+Pred1 == ICmpInst::ICMP_NE ? 1 : 2)));
+  }
+} else {
+  // C != 0 && C != 1
+  // icmp eq X, (zext (icmp eq X, C)) --> icmp eq X, 0
+  // icmp eq X, (zext (icmp ne X, C)) --> icmp eq X, 1
+  // icmp ne X, (zext (icmp eq X, C)) --> icmp ne X, 0
+  // icmp ne X, (zext (icmp ne X, C)) --> icmp ne X, 1
+  return ICmpInst::Create(
+  Instruction::ICmp, Pred1, X,
+  Constant::getIntegerValue(
+  X->getType(),
+  APInt(X->getType()->getScalarSizeInBits(),
+static_cast(Pred2 == ICmpInst::ICMP_NE;
+}
+  }
+
   if (match(I.getOperand(0), m_c_Add(m_ZExt(m_Value(X)), m_SExt(m_Value(Y 
&&
   match(I.getOperand(1), m_APInt(C)) &&
   X->getType()->isIntOrIntVectorTy(1) &&
diff --git a/llvm/test/Transforms/InstCombine/icmp-range.ll 
b/llvm/test/Transforms/InstCombine/icmp-range.ll
index 4281e09cb0309c8..15424fce33fdeea 100644
--- a/llvm/test/Transforms/InstCombine/icmp-range.ll
+++ b/llvm/test/Transforms/InstCombine/icmp-range.ll
@@ -1034,6 +1034,187 @@ define i1 @icmp_ne_bool_1(ptr %ptr) {
   ret i1 %cmp
 }
 
+define i1 @icmp_ne_zext_eq_zero(i32 %a) {
+; CHECK-LABEL: @icmp_ne_zext_eq_zero(
+; CHECK-NEXT:ret i1 true
+;
+  %cmp = icmp eq i32 %a, 0
+  %conv = zext i1 %cmp to i32
+  %cmp1 = icmp ne i32 %conv, %a
+  ret i1 %cmp1
+}
+
+define i1 @icmp_ne_zext_ne_zero(i32 %a) {
+; CHECK-LABEL: @icmp_ne_zext_ne_zero(
+; CHECK-NEXT:[[CMP1:%.*]] = icmp ugt i32 [[A:%.*]], 1
+; CHECK-NEXT:ret i1 [[CMP1]]
+;
+  %cmp = icmp ne i32 %a, 0
+  %conv = zext i1 %cmp to i32
+  %cmp1 = icmp ne i32 %conv, %a
+  ret i1 %cmp1
+}
+
+define i1 @icmp_eq_zext_eq_zero(i32 %a) {
+; CHECK-LABEL: @icmp_eq_zext_eq_zero(
+; CHECK-NEXT:ret i1 false
+;
+  %cmp = icmp eq i32 %a, 0
+  %conv = zext i1 %cmp to i32
+  %cmp1 = icmp eq i32 %conv, %a
+  ret i1 %cmp1
+}
+
+define i1 @icmp_eq_zext_ne_zero(i32 

[clang-tools-extra] [InstCombine] Simplify the pattern `a ne/eq (zext/sext (a ne/eq c))` (PR #65852)

2023-10-06 Thread Yingwei Zheng via cfe-commits

https://github.com/dtcxzyw updated 
https://github.com/llvm/llvm-project/pull/65852

>From d9d8bcbb98e8f5aecb9733329389d61a489bd731 Mon Sep 17 00:00:00 2001
From: Yingwei Zheng 
Date: Sat, 9 Sep 2023 23:07:29 +0800
Subject: [PATCH 01/10] [InstCombine] Simplify the pattern `a ne/eq (zext (a
 ne/eq c))`

---
 .../InstCombine/InstCombineCompares.cpp   |  62 ++
 .../test/Transforms/InstCombine/icmp-range.ll | 181 ++
 2 files changed, 243 insertions(+)

diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp 
b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
index 9fdc46fec631679..837b8e6d2619989 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
@@ -6309,7 +6309,69 @@ Instruction 
*InstCombinerImpl::foldICmpUsingBoolRange(ICmpInst ) {
   Y->getType()->isIntOrIntVectorTy(1) && Pred == ICmpInst::ICMP_ULE)
 return BinaryOperator::CreateOr(Builder.CreateIsNull(X), Y);
 
+  ICmpInst::Predicate Pred1, Pred2;
   const APInt *C;
+  // icmp eq/ne X, (zext (icmp eq/ne X, C))
+  if (match(, m_c_ICmp(Pred1, m_Value(X),
+ m_ZExt(m_ICmp(Pred2, m_Deferred(X), m_APInt(C) &&
+  ICmpInst::isEquality(Pred1) && ICmpInst::isEquality(Pred2)) {
+if (C->isZero()) {
+  if (Pred2 == ICmpInst::ICMP_EQ) {
+// icmp eq X, (zext (icmp eq X, 0)) --> false
+// icmp ne X, (zext (icmp eq X, 0)) --> true
+return replaceInstUsesWith(
+I,
+Constant::getIntegerValue(
+I.getType(),
+APInt(1U, static_cast(Pred1 == ICmpInst::ICMP_NE;
+  } else {
+// icmp eq X, (zext (icmp ne X, 0)) --> icmp ult X, 2
+// icmp ne X, (zext (icmp ne X, 0)) --> icmp ugt X, 1
+return ICmpInst::Create(
+Instruction::ICmp,
+Pred1 == ICmpInst::ICMP_NE ? ICmpInst::ICMP_UGT
+   : ICmpInst::ICMP_ULT,
+X,
+Constant::getIntegerValue(
+X->getType(), APInt(X->getType()->getScalarSizeInBits(),
+Pred1 == ICmpInst::ICMP_NE ? 1 : 2)));
+  }
+} else if (C->isOne()) {
+  if (Pred2 == ICmpInst::ICMP_NE) {
+// icmp eq X, (zext (icmp ne X, 1)) --> false
+// icmp ne X, (zext (icmp ne X, 1)) --> true
+return replaceInstUsesWith(
+I,
+Constant::getIntegerValue(
+I.getType(),
+APInt(1U, static_cast(Pred1 == ICmpInst::ICMP_NE;
+  } else {
+// icmp eq X, (zext (icmp eq X, 1)) --> icmp ult X, 2
+// icmp ne X, (zext (icmp eq X, 1)) --> icmp ugt X, 1
+return ICmpInst::Create(
+Instruction::ICmp,
+Pred1 == ICmpInst::ICMP_NE ? ICmpInst::ICMP_UGT
+   : ICmpInst::ICMP_ULT,
+X,
+Constant::getIntegerValue(
+X->getType(), APInt(X->getType()->getScalarSizeInBits(),
+Pred1 == ICmpInst::ICMP_NE ? 1 : 2)));
+  }
+} else {
+  // C != 0 && C != 1
+  // icmp eq X, (zext (icmp eq X, C)) --> icmp eq X, 0
+  // icmp eq X, (zext (icmp ne X, C)) --> icmp eq X, 1
+  // icmp ne X, (zext (icmp eq X, C)) --> icmp ne X, 0
+  // icmp ne X, (zext (icmp ne X, C)) --> icmp ne X, 1
+  return ICmpInst::Create(
+  Instruction::ICmp, Pred1, X,
+  Constant::getIntegerValue(
+  X->getType(),
+  APInt(X->getType()->getScalarSizeInBits(),
+static_cast(Pred2 == ICmpInst::ICMP_NE;
+}
+  }
+
   if (match(I.getOperand(0), m_c_Add(m_ZExt(m_Value(X)), m_SExt(m_Value(Y 
&&
   match(I.getOperand(1), m_APInt(C)) &&
   X->getType()->isIntOrIntVectorTy(1) &&
diff --git a/llvm/test/Transforms/InstCombine/icmp-range.ll 
b/llvm/test/Transforms/InstCombine/icmp-range.ll
index 4281e09cb0309c8..15424fce33fdeea 100644
--- a/llvm/test/Transforms/InstCombine/icmp-range.ll
+++ b/llvm/test/Transforms/InstCombine/icmp-range.ll
@@ -1034,6 +1034,187 @@ define i1 @icmp_ne_bool_1(ptr %ptr) {
   ret i1 %cmp
 }
 
+define i1 @icmp_ne_zext_eq_zero(i32 %a) {
+; CHECK-LABEL: @icmp_ne_zext_eq_zero(
+; CHECK-NEXT:ret i1 true
+;
+  %cmp = icmp eq i32 %a, 0
+  %conv = zext i1 %cmp to i32
+  %cmp1 = icmp ne i32 %conv, %a
+  ret i1 %cmp1
+}
+
+define i1 @icmp_ne_zext_ne_zero(i32 %a) {
+; CHECK-LABEL: @icmp_ne_zext_ne_zero(
+; CHECK-NEXT:[[CMP1:%.*]] = icmp ugt i32 [[A:%.*]], 1
+; CHECK-NEXT:ret i1 [[CMP1]]
+;
+  %cmp = icmp ne i32 %a, 0
+  %conv = zext i1 %cmp to i32
+  %cmp1 = icmp ne i32 %conv, %a
+  ret i1 %cmp1
+}
+
+define i1 @icmp_eq_zext_eq_zero(i32 %a) {
+; CHECK-LABEL: @icmp_eq_zext_eq_zero(
+; CHECK-NEXT:ret i1 false
+;
+  %cmp = icmp eq i32 %a, 0
+  %conv = zext i1 %cmp to i32
+  %cmp1 = icmp eq i32 %conv, %a
+  ret i1 %cmp1
+}
+
+define i1 @icmp_eq_zext_ne_zero(i32 

[clang-tools-extra] [InstCombine] Simplify the pattern `a ne/eq (zext/sext (a ne/eq c))` (PR #65852)

2023-10-06 Thread Yingwei Zheng via cfe-commits

https://github.com/dtcxzyw updated 
https://github.com/llvm/llvm-project/pull/65852

>From d9d8bcbb98e8f5aecb9733329389d61a489bd731 Mon Sep 17 00:00:00 2001
From: Yingwei Zheng 
Date: Sat, 9 Sep 2023 23:07:29 +0800
Subject: [PATCH 01/10] [InstCombine] Simplify the pattern `a ne/eq (zext (a
 ne/eq c))`

---
 .../InstCombine/InstCombineCompares.cpp   |  62 ++
 .../test/Transforms/InstCombine/icmp-range.ll | 181 ++
 2 files changed, 243 insertions(+)

diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp 
b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
index 9fdc46fec631679..837b8e6d2619989 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
@@ -6309,7 +6309,69 @@ Instruction 
*InstCombinerImpl::foldICmpUsingBoolRange(ICmpInst ) {
   Y->getType()->isIntOrIntVectorTy(1) && Pred == ICmpInst::ICMP_ULE)
 return BinaryOperator::CreateOr(Builder.CreateIsNull(X), Y);
 
+  ICmpInst::Predicate Pred1, Pred2;
   const APInt *C;
+  // icmp eq/ne X, (zext (icmp eq/ne X, C))
+  if (match(, m_c_ICmp(Pred1, m_Value(X),
+ m_ZExt(m_ICmp(Pred2, m_Deferred(X), m_APInt(C) &&
+  ICmpInst::isEquality(Pred1) && ICmpInst::isEquality(Pred2)) {
+if (C->isZero()) {
+  if (Pred2 == ICmpInst::ICMP_EQ) {
+// icmp eq X, (zext (icmp eq X, 0)) --> false
+// icmp ne X, (zext (icmp eq X, 0)) --> true
+return replaceInstUsesWith(
+I,
+Constant::getIntegerValue(
+I.getType(),
+APInt(1U, static_cast(Pred1 == ICmpInst::ICMP_NE;
+  } else {
+// icmp eq X, (zext (icmp ne X, 0)) --> icmp ult X, 2
+// icmp ne X, (zext (icmp ne X, 0)) --> icmp ugt X, 1
+return ICmpInst::Create(
+Instruction::ICmp,
+Pred1 == ICmpInst::ICMP_NE ? ICmpInst::ICMP_UGT
+   : ICmpInst::ICMP_ULT,
+X,
+Constant::getIntegerValue(
+X->getType(), APInt(X->getType()->getScalarSizeInBits(),
+Pred1 == ICmpInst::ICMP_NE ? 1 : 2)));
+  }
+} else if (C->isOne()) {
+  if (Pred2 == ICmpInst::ICMP_NE) {
+// icmp eq X, (zext (icmp ne X, 1)) --> false
+// icmp ne X, (zext (icmp ne X, 1)) --> true
+return replaceInstUsesWith(
+I,
+Constant::getIntegerValue(
+I.getType(),
+APInt(1U, static_cast(Pred1 == ICmpInst::ICMP_NE;
+  } else {
+// icmp eq X, (zext (icmp eq X, 1)) --> icmp ult X, 2
+// icmp ne X, (zext (icmp eq X, 1)) --> icmp ugt X, 1
+return ICmpInst::Create(
+Instruction::ICmp,
+Pred1 == ICmpInst::ICMP_NE ? ICmpInst::ICMP_UGT
+   : ICmpInst::ICMP_ULT,
+X,
+Constant::getIntegerValue(
+X->getType(), APInt(X->getType()->getScalarSizeInBits(),
+Pred1 == ICmpInst::ICMP_NE ? 1 : 2)));
+  }
+} else {
+  // C != 0 && C != 1
+  // icmp eq X, (zext (icmp eq X, C)) --> icmp eq X, 0
+  // icmp eq X, (zext (icmp ne X, C)) --> icmp eq X, 1
+  // icmp ne X, (zext (icmp eq X, C)) --> icmp ne X, 0
+  // icmp ne X, (zext (icmp ne X, C)) --> icmp ne X, 1
+  return ICmpInst::Create(
+  Instruction::ICmp, Pred1, X,
+  Constant::getIntegerValue(
+  X->getType(),
+  APInt(X->getType()->getScalarSizeInBits(),
+static_cast(Pred2 == ICmpInst::ICMP_NE;
+}
+  }
+
   if (match(I.getOperand(0), m_c_Add(m_ZExt(m_Value(X)), m_SExt(m_Value(Y 
&&
   match(I.getOperand(1), m_APInt(C)) &&
   X->getType()->isIntOrIntVectorTy(1) &&
diff --git a/llvm/test/Transforms/InstCombine/icmp-range.ll 
b/llvm/test/Transforms/InstCombine/icmp-range.ll
index 4281e09cb0309c8..15424fce33fdeea 100644
--- a/llvm/test/Transforms/InstCombine/icmp-range.ll
+++ b/llvm/test/Transforms/InstCombine/icmp-range.ll
@@ -1034,6 +1034,187 @@ define i1 @icmp_ne_bool_1(ptr %ptr) {
   ret i1 %cmp
 }
 
+define i1 @icmp_ne_zext_eq_zero(i32 %a) {
+; CHECK-LABEL: @icmp_ne_zext_eq_zero(
+; CHECK-NEXT:ret i1 true
+;
+  %cmp = icmp eq i32 %a, 0
+  %conv = zext i1 %cmp to i32
+  %cmp1 = icmp ne i32 %conv, %a
+  ret i1 %cmp1
+}
+
+define i1 @icmp_ne_zext_ne_zero(i32 %a) {
+; CHECK-LABEL: @icmp_ne_zext_ne_zero(
+; CHECK-NEXT:[[CMP1:%.*]] = icmp ugt i32 [[A:%.*]], 1
+; CHECK-NEXT:ret i1 [[CMP1]]
+;
+  %cmp = icmp ne i32 %a, 0
+  %conv = zext i1 %cmp to i32
+  %cmp1 = icmp ne i32 %conv, %a
+  ret i1 %cmp1
+}
+
+define i1 @icmp_eq_zext_eq_zero(i32 %a) {
+; CHECK-LABEL: @icmp_eq_zext_eq_zero(
+; CHECK-NEXT:ret i1 false
+;
+  %cmp = icmp eq i32 %a, 0
+  %conv = zext i1 %cmp to i32
+  %cmp1 = icmp eq i32 %conv, %a
+  ret i1 %cmp1
+}
+
+define i1 @icmp_eq_zext_ne_zero(i32 

[clang] [InstCombine] Simplify the pattern `a ne/eq (zext/sext (a ne/eq c))` (PR #65852)

2023-10-06 Thread Yingwei Zheng via cfe-commits

https://github.com/dtcxzyw updated 
https://github.com/llvm/llvm-project/pull/65852

>From d9d8bcbb98e8f5aecb9733329389d61a489bd731 Mon Sep 17 00:00:00 2001
From: Yingwei Zheng 
Date: Sat, 9 Sep 2023 23:07:29 +0800
Subject: [PATCH 01/10] [InstCombine] Simplify the pattern `a ne/eq (zext (a
 ne/eq c))`

---
 .../InstCombine/InstCombineCompares.cpp   |  62 ++
 .../test/Transforms/InstCombine/icmp-range.ll | 181 ++
 2 files changed, 243 insertions(+)

diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp 
b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
index 9fdc46fec631679..837b8e6d2619989 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
@@ -6309,7 +6309,69 @@ Instruction 
*InstCombinerImpl::foldICmpUsingBoolRange(ICmpInst ) {
   Y->getType()->isIntOrIntVectorTy(1) && Pred == ICmpInst::ICMP_ULE)
 return BinaryOperator::CreateOr(Builder.CreateIsNull(X), Y);
 
+  ICmpInst::Predicate Pred1, Pred2;
   const APInt *C;
+  // icmp eq/ne X, (zext (icmp eq/ne X, C))
+  if (match(, m_c_ICmp(Pred1, m_Value(X),
+ m_ZExt(m_ICmp(Pred2, m_Deferred(X), m_APInt(C) &&
+  ICmpInst::isEquality(Pred1) && ICmpInst::isEquality(Pred2)) {
+if (C->isZero()) {
+  if (Pred2 == ICmpInst::ICMP_EQ) {
+// icmp eq X, (zext (icmp eq X, 0)) --> false
+// icmp ne X, (zext (icmp eq X, 0)) --> true
+return replaceInstUsesWith(
+I,
+Constant::getIntegerValue(
+I.getType(),
+APInt(1U, static_cast(Pred1 == ICmpInst::ICMP_NE;
+  } else {
+// icmp eq X, (zext (icmp ne X, 0)) --> icmp ult X, 2
+// icmp ne X, (zext (icmp ne X, 0)) --> icmp ugt X, 1
+return ICmpInst::Create(
+Instruction::ICmp,
+Pred1 == ICmpInst::ICMP_NE ? ICmpInst::ICMP_UGT
+   : ICmpInst::ICMP_ULT,
+X,
+Constant::getIntegerValue(
+X->getType(), APInt(X->getType()->getScalarSizeInBits(),
+Pred1 == ICmpInst::ICMP_NE ? 1 : 2)));
+  }
+} else if (C->isOne()) {
+  if (Pred2 == ICmpInst::ICMP_NE) {
+// icmp eq X, (zext (icmp ne X, 1)) --> false
+// icmp ne X, (zext (icmp ne X, 1)) --> true
+return replaceInstUsesWith(
+I,
+Constant::getIntegerValue(
+I.getType(),
+APInt(1U, static_cast(Pred1 == ICmpInst::ICMP_NE;
+  } else {
+// icmp eq X, (zext (icmp eq X, 1)) --> icmp ult X, 2
+// icmp ne X, (zext (icmp eq X, 1)) --> icmp ugt X, 1
+return ICmpInst::Create(
+Instruction::ICmp,
+Pred1 == ICmpInst::ICMP_NE ? ICmpInst::ICMP_UGT
+   : ICmpInst::ICMP_ULT,
+X,
+Constant::getIntegerValue(
+X->getType(), APInt(X->getType()->getScalarSizeInBits(),
+Pred1 == ICmpInst::ICMP_NE ? 1 : 2)));
+  }
+} else {
+  // C != 0 && C != 1
+  // icmp eq X, (zext (icmp eq X, C)) --> icmp eq X, 0
+  // icmp eq X, (zext (icmp ne X, C)) --> icmp eq X, 1
+  // icmp ne X, (zext (icmp eq X, C)) --> icmp ne X, 0
+  // icmp ne X, (zext (icmp ne X, C)) --> icmp ne X, 1
+  return ICmpInst::Create(
+  Instruction::ICmp, Pred1, X,
+  Constant::getIntegerValue(
+  X->getType(),
+  APInt(X->getType()->getScalarSizeInBits(),
+static_cast(Pred2 == ICmpInst::ICMP_NE;
+}
+  }
+
   if (match(I.getOperand(0), m_c_Add(m_ZExt(m_Value(X)), m_SExt(m_Value(Y 
&&
   match(I.getOperand(1), m_APInt(C)) &&
   X->getType()->isIntOrIntVectorTy(1) &&
diff --git a/llvm/test/Transforms/InstCombine/icmp-range.ll 
b/llvm/test/Transforms/InstCombine/icmp-range.ll
index 4281e09cb0309c8..15424fce33fdeea 100644
--- a/llvm/test/Transforms/InstCombine/icmp-range.ll
+++ b/llvm/test/Transforms/InstCombine/icmp-range.ll
@@ -1034,6 +1034,187 @@ define i1 @icmp_ne_bool_1(ptr %ptr) {
   ret i1 %cmp
 }
 
+define i1 @icmp_ne_zext_eq_zero(i32 %a) {
+; CHECK-LABEL: @icmp_ne_zext_eq_zero(
+; CHECK-NEXT:ret i1 true
+;
+  %cmp = icmp eq i32 %a, 0
+  %conv = zext i1 %cmp to i32
+  %cmp1 = icmp ne i32 %conv, %a
+  ret i1 %cmp1
+}
+
+define i1 @icmp_ne_zext_ne_zero(i32 %a) {
+; CHECK-LABEL: @icmp_ne_zext_ne_zero(
+; CHECK-NEXT:[[CMP1:%.*]] = icmp ugt i32 [[A:%.*]], 1
+; CHECK-NEXT:ret i1 [[CMP1]]
+;
+  %cmp = icmp ne i32 %a, 0
+  %conv = zext i1 %cmp to i32
+  %cmp1 = icmp ne i32 %conv, %a
+  ret i1 %cmp1
+}
+
+define i1 @icmp_eq_zext_eq_zero(i32 %a) {
+; CHECK-LABEL: @icmp_eq_zext_eq_zero(
+; CHECK-NEXT:ret i1 false
+;
+  %cmp = icmp eq i32 %a, 0
+  %conv = zext i1 %cmp to i32
+  %cmp1 = icmp eq i32 %conv, %a
+  ret i1 %cmp1
+}
+
+define i1 @icmp_eq_zext_ne_zero(i32 

[clang] [InstCombine] Canonicalize `(X +/- Y) & Y` into `~X & Y` when Y is a power of 2 (PR #67915)

2023-10-06 Thread Yingwei Zheng via cfe-commits

https://github.com/dtcxzyw updated 
https://github.com/llvm/llvm-project/pull/67915

>From c4ce28c942c172e5646b5922f0b02b4169197840 Mon Sep 17 00:00:00 2001
From: Yingwei Zheng 
Date: Sun, 1 Oct 2023 21:52:47 +0800
Subject: [PATCH 1/2] [InstCombine] Canonicalize `(X +/- Y) & Y` into `~X & Y`
 when Y is a power of 2

---
 .../InstCombine/InstCombineAndOrXor.cpp   |  8 
 llvm/test/Transforms/InstCombine/and.ll   | 44 +--
 2 files changed, 48 insertions(+), 4 deletions(-)

diff --git a/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp 
b/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
index cbdab3e9c5fb91d..4322cc96f5a2b6c 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
@@ -2250,6 +2250,14 @@ Instruction *InstCombinerImpl::visitAnd(BinaryOperator 
) {
 return SelectInst::Create(Cmp, ConstantInt::getNullValue(Ty), Y);
   }
 
+  // Canonicalize:
+  // (X +/- Y) & Y --> ~X & Y when Y is a power of 2.
+  if (match(, m_c_And(m_Value(Y), m_OneUse(m_CombineOr(
+m_c_Add(m_Value(X), m_Deferred(Y)),
+m_Sub(m_Value(X), m_Deferred(Y)) &&
+  isKnownToBeAPowerOfTwo(Y, /*OrZero*/ true, /*Depth*/ 0, ))
+return BinaryOperator::CreateAnd(Builder.CreateNot(X), Y);
+
   const APInt *C;
   if (match(Op1, m_APInt(C))) {
 const APInt *XorC;
diff --git a/llvm/test/Transforms/InstCombine/and.ll 
b/llvm/test/Transforms/InstCombine/and.ll
index 90f027010e2aea6..eb39ff9014ff3a4 100644
--- a/llvm/test/Transforms/InstCombine/and.ll
+++ b/llvm/test/Transforms/InstCombine/and.ll
@@ -1595,8 +1595,8 @@ define <2 x i8> @flip_masked_bit_uniform(<2 x i8> %A) {
 
 define <2 x i8> @flip_masked_bit_undef(<2 x i8> %A) {
 ; CHECK-LABEL: @flip_masked_bit_undef(
-; CHECK-NEXT:[[B:%.*]] = add <2 x i8> [[A:%.*]], 
-; CHECK-NEXT:[[C:%.*]] = and <2 x i8> [[B]], 
+; CHECK-NEXT:[[TMP1:%.*]] = xor <2 x i8> [[A:%.*]], 
+; CHECK-NEXT:[[C:%.*]] = and <2 x i8> [[TMP1]], 
 ; CHECK-NEXT:ret <2 x i8> [[C]]
 ;
   %B = add <2 x i8> %A, 
@@ -1606,8 +1606,8 @@ define <2 x i8> @flip_masked_bit_undef(<2 x i8> %A) {
 
 define <2 x i8> @flip_masked_bit_nonuniform(<2 x i8> %A) {
 ; CHECK-LABEL: @flip_masked_bit_nonuniform(
-; CHECK-NEXT:[[B:%.*]] = add <2 x i8> [[A:%.*]], 
-; CHECK-NEXT:[[C:%.*]] = and <2 x i8> [[B]], 
+; CHECK-NEXT:[[TMP1:%.*]] = xor <2 x i8> [[A:%.*]], 
+; CHECK-NEXT:[[C:%.*]] = and <2 x i8> [[TMP1]], 
 ; CHECK-NEXT:ret <2 x i8> [[C]]
 ;
   %B = add <2 x i8> %A, 
@@ -2546,3 +2546,39 @@ define i32 @and_zext_eq_zero(i32 %A, i32 %C)  {
   %5 = and i32 %2, %4
   ret i32 %5
 }
+
+define i32 @canonicalize_and_add_power2_or_zero(i32 %x, i32 %y) {
+; CHECK-LABEL: @canonicalize_and_add_power2_or_zero(
+; CHECK-NEXT:[[NY:%.*]] = sub i32 0, [[Y:%.*]]
+; CHECK-NEXT:[[P2:%.*]] = and i32 [[NY]], [[Y]]
+; CHECK-NEXT:call void @use32(i32 [[P2]])
+; CHECK-NEXT:[[TMP1:%.*]] = xor i32 [[X:%.*]], -1
+; CHECK-NEXT:[[AND:%.*]] = and i32 [[P2]], [[TMP1]]
+; CHECK-NEXT:ret i32 [[AND]]
+;
+  %ny = sub i32 0, %y
+  %p2 = and i32 %y, %ny
+  call void @use32(i32 %p2) ; keep p2
+
+  %val = add i32 %x, %p2
+  %and = and i32 %val, %p2
+  ret i32 %and
+}
+
+define i32 @canonicalize_and_sub_power2_or_zero(i32 %x, i32 %y) {
+; CHECK-LABEL: @canonicalize_and_sub_power2_or_zero(
+; CHECK-NEXT:[[NY:%.*]] = sub i32 0, [[Y:%.*]]
+; CHECK-NEXT:[[P2:%.*]] = and i32 [[NY]], [[Y]]
+; CHECK-NEXT:call void @use32(i32 [[P2]])
+; CHECK-NEXT:[[TMP1:%.*]] = xor i32 [[X:%.*]], -1
+; CHECK-NEXT:[[AND:%.*]] = and i32 [[P2]], [[TMP1]]
+; CHECK-NEXT:ret i32 [[AND]]
+;
+  %ny = sub i32 0, %y
+  %p2 = and i32 %y, %ny
+  call void @use32(i32 %p2) ; keep p2
+
+  %val = sub i32 %x, %p2
+  %and = and i32 %val, %p2
+  ret i32 %and
+}

>From b64ca5b5f743e6a935f4ea09154c3a08c6e65c47 Mon Sep 17 00:00:00 2001
From: Yingwei Zheng 
Date: Fri, 6 Oct 2023 17:32:46 +0800
Subject: [PATCH 2/2] fixup! [InstCombine] Canonicalize `(X +/- Y) & Y` into
 `~X & Y` when Y is a power of 2

Add additional tests.
---
 llvm/test/Transforms/InstCombine/and.ll | 123 
 1 file changed, 123 insertions(+)

diff --git a/llvm/test/Transforms/InstCombine/and.ll 
b/llvm/test/Transforms/InstCombine/and.ll
index eb39ff9014ff3a4..989640ed41f2d2e 100644
--- a/llvm/test/Transforms/InstCombine/and.ll
+++ b/llvm/test/Transforms/InstCombine/and.ll
@@ -2582,3 +2582,126 @@ define i32 @canonicalize_and_sub_power2_or_zero(i32 %x, 
i32 %y) {
   %and = and i32 %val, %p2
   ret i32 %and
 }
+
+define i32 @canonicalize_and_add_power2_or_zero_commuted1(i32 %x, i32 %y) {
+; CHECK-LABEL: @canonicalize_and_add_power2_or_zero_commuted1(
+; CHECK-NEXT:[[NY:%.*]] = sub i32 0, [[Y:%.*]]
+; CHECK-NEXT:[[P2:%.*]] = and i32 [[NY]], [[Y]]
+; CHECK-NEXT:call void @use32(i32 [[P2]])
+; CHECK-NEXT:[[TMP1:%.*]] = xor i32 [[X:%.*]], 

[clang-tools-extra] [InstCombine] Simplify the pattern `a ne/eq (zext/sext (a ne/eq c))` (PR #65852)

2023-10-06 Thread Yingwei Zheng via cfe-commits

https://github.com/dtcxzyw updated 
https://github.com/llvm/llvm-project/pull/65852

>From d9d8bcbb98e8f5aecb9733329389d61a489bd731 Mon Sep 17 00:00:00 2001
From: Yingwei Zheng 
Date: Sat, 9 Sep 2023 23:07:29 +0800
Subject: [PATCH 01/10] [InstCombine] Simplify the pattern `a ne/eq (zext (a
 ne/eq c))`

---
 .../InstCombine/InstCombineCompares.cpp   |  62 ++
 .../test/Transforms/InstCombine/icmp-range.ll | 181 ++
 2 files changed, 243 insertions(+)

diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp 
b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
index 9fdc46fec631679..837b8e6d2619989 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
@@ -6309,7 +6309,69 @@ Instruction 
*InstCombinerImpl::foldICmpUsingBoolRange(ICmpInst ) {
   Y->getType()->isIntOrIntVectorTy(1) && Pred == ICmpInst::ICMP_ULE)
 return BinaryOperator::CreateOr(Builder.CreateIsNull(X), Y);
 
+  ICmpInst::Predicate Pred1, Pred2;
   const APInt *C;
+  // icmp eq/ne X, (zext (icmp eq/ne X, C))
+  if (match(, m_c_ICmp(Pred1, m_Value(X),
+ m_ZExt(m_ICmp(Pred2, m_Deferred(X), m_APInt(C) &&
+  ICmpInst::isEquality(Pred1) && ICmpInst::isEquality(Pred2)) {
+if (C->isZero()) {
+  if (Pred2 == ICmpInst::ICMP_EQ) {
+// icmp eq X, (zext (icmp eq X, 0)) --> false
+// icmp ne X, (zext (icmp eq X, 0)) --> true
+return replaceInstUsesWith(
+I,
+Constant::getIntegerValue(
+I.getType(),
+APInt(1U, static_cast(Pred1 == ICmpInst::ICMP_NE;
+  } else {
+// icmp eq X, (zext (icmp ne X, 0)) --> icmp ult X, 2
+// icmp ne X, (zext (icmp ne X, 0)) --> icmp ugt X, 1
+return ICmpInst::Create(
+Instruction::ICmp,
+Pred1 == ICmpInst::ICMP_NE ? ICmpInst::ICMP_UGT
+   : ICmpInst::ICMP_ULT,
+X,
+Constant::getIntegerValue(
+X->getType(), APInt(X->getType()->getScalarSizeInBits(),
+Pred1 == ICmpInst::ICMP_NE ? 1 : 2)));
+  }
+} else if (C->isOne()) {
+  if (Pred2 == ICmpInst::ICMP_NE) {
+// icmp eq X, (zext (icmp ne X, 1)) --> false
+// icmp ne X, (zext (icmp ne X, 1)) --> true
+return replaceInstUsesWith(
+I,
+Constant::getIntegerValue(
+I.getType(),
+APInt(1U, static_cast(Pred1 == ICmpInst::ICMP_NE;
+  } else {
+// icmp eq X, (zext (icmp eq X, 1)) --> icmp ult X, 2
+// icmp ne X, (zext (icmp eq X, 1)) --> icmp ugt X, 1
+return ICmpInst::Create(
+Instruction::ICmp,
+Pred1 == ICmpInst::ICMP_NE ? ICmpInst::ICMP_UGT
+   : ICmpInst::ICMP_ULT,
+X,
+Constant::getIntegerValue(
+X->getType(), APInt(X->getType()->getScalarSizeInBits(),
+Pred1 == ICmpInst::ICMP_NE ? 1 : 2)));
+  }
+} else {
+  // C != 0 && C != 1
+  // icmp eq X, (zext (icmp eq X, C)) --> icmp eq X, 0
+  // icmp eq X, (zext (icmp ne X, C)) --> icmp eq X, 1
+  // icmp ne X, (zext (icmp eq X, C)) --> icmp ne X, 0
+  // icmp ne X, (zext (icmp ne X, C)) --> icmp ne X, 1
+  return ICmpInst::Create(
+  Instruction::ICmp, Pred1, X,
+  Constant::getIntegerValue(
+  X->getType(),
+  APInt(X->getType()->getScalarSizeInBits(),
+static_cast(Pred2 == ICmpInst::ICMP_NE;
+}
+  }
+
   if (match(I.getOperand(0), m_c_Add(m_ZExt(m_Value(X)), m_SExt(m_Value(Y 
&&
   match(I.getOperand(1), m_APInt(C)) &&
   X->getType()->isIntOrIntVectorTy(1) &&
diff --git a/llvm/test/Transforms/InstCombine/icmp-range.ll 
b/llvm/test/Transforms/InstCombine/icmp-range.ll
index 4281e09cb0309c8..15424fce33fdeea 100644
--- a/llvm/test/Transforms/InstCombine/icmp-range.ll
+++ b/llvm/test/Transforms/InstCombine/icmp-range.ll
@@ -1034,6 +1034,187 @@ define i1 @icmp_ne_bool_1(ptr %ptr) {
   ret i1 %cmp
 }
 
+define i1 @icmp_ne_zext_eq_zero(i32 %a) {
+; CHECK-LABEL: @icmp_ne_zext_eq_zero(
+; CHECK-NEXT:ret i1 true
+;
+  %cmp = icmp eq i32 %a, 0
+  %conv = zext i1 %cmp to i32
+  %cmp1 = icmp ne i32 %conv, %a
+  ret i1 %cmp1
+}
+
+define i1 @icmp_ne_zext_ne_zero(i32 %a) {
+; CHECK-LABEL: @icmp_ne_zext_ne_zero(
+; CHECK-NEXT:[[CMP1:%.*]] = icmp ugt i32 [[A:%.*]], 1
+; CHECK-NEXT:ret i1 [[CMP1]]
+;
+  %cmp = icmp ne i32 %a, 0
+  %conv = zext i1 %cmp to i32
+  %cmp1 = icmp ne i32 %conv, %a
+  ret i1 %cmp1
+}
+
+define i1 @icmp_eq_zext_eq_zero(i32 %a) {
+; CHECK-LABEL: @icmp_eq_zext_eq_zero(
+; CHECK-NEXT:ret i1 false
+;
+  %cmp = icmp eq i32 %a, 0
+  %conv = zext i1 %cmp to i32
+  %cmp1 = icmp eq i32 %conv, %a
+  ret i1 %cmp1
+}
+
+define i1 @icmp_eq_zext_ne_zero(i32 

[clang] [InstCombine] Simplify the pattern `a ne/eq (zext/sext (a ne/eq c))` (PR #65852)

2023-10-06 Thread Yingwei Zheng via cfe-commits

https://github.com/dtcxzyw updated 
https://github.com/llvm/llvm-project/pull/65852

>From d9d8bcbb98e8f5aecb9733329389d61a489bd731 Mon Sep 17 00:00:00 2001
From: Yingwei Zheng 
Date: Sat, 9 Sep 2023 23:07:29 +0800
Subject: [PATCH 01/10] [InstCombine] Simplify the pattern `a ne/eq (zext (a
 ne/eq c))`

---
 .../InstCombine/InstCombineCompares.cpp   |  62 ++
 .../test/Transforms/InstCombine/icmp-range.ll | 181 ++
 2 files changed, 243 insertions(+)

diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp 
b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
index 9fdc46fec631679..837b8e6d2619989 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
@@ -6309,7 +6309,69 @@ Instruction 
*InstCombinerImpl::foldICmpUsingBoolRange(ICmpInst ) {
   Y->getType()->isIntOrIntVectorTy(1) && Pred == ICmpInst::ICMP_ULE)
 return BinaryOperator::CreateOr(Builder.CreateIsNull(X), Y);
 
+  ICmpInst::Predicate Pred1, Pred2;
   const APInt *C;
+  // icmp eq/ne X, (zext (icmp eq/ne X, C))
+  if (match(, m_c_ICmp(Pred1, m_Value(X),
+ m_ZExt(m_ICmp(Pred2, m_Deferred(X), m_APInt(C) &&
+  ICmpInst::isEquality(Pred1) && ICmpInst::isEquality(Pred2)) {
+if (C->isZero()) {
+  if (Pred2 == ICmpInst::ICMP_EQ) {
+// icmp eq X, (zext (icmp eq X, 0)) --> false
+// icmp ne X, (zext (icmp eq X, 0)) --> true
+return replaceInstUsesWith(
+I,
+Constant::getIntegerValue(
+I.getType(),
+APInt(1U, static_cast(Pred1 == ICmpInst::ICMP_NE;
+  } else {
+// icmp eq X, (zext (icmp ne X, 0)) --> icmp ult X, 2
+// icmp ne X, (zext (icmp ne X, 0)) --> icmp ugt X, 1
+return ICmpInst::Create(
+Instruction::ICmp,
+Pred1 == ICmpInst::ICMP_NE ? ICmpInst::ICMP_UGT
+   : ICmpInst::ICMP_ULT,
+X,
+Constant::getIntegerValue(
+X->getType(), APInt(X->getType()->getScalarSizeInBits(),
+Pred1 == ICmpInst::ICMP_NE ? 1 : 2)));
+  }
+} else if (C->isOne()) {
+  if (Pred2 == ICmpInst::ICMP_NE) {
+// icmp eq X, (zext (icmp ne X, 1)) --> false
+// icmp ne X, (zext (icmp ne X, 1)) --> true
+return replaceInstUsesWith(
+I,
+Constant::getIntegerValue(
+I.getType(),
+APInt(1U, static_cast(Pred1 == ICmpInst::ICMP_NE;
+  } else {
+// icmp eq X, (zext (icmp eq X, 1)) --> icmp ult X, 2
+// icmp ne X, (zext (icmp eq X, 1)) --> icmp ugt X, 1
+return ICmpInst::Create(
+Instruction::ICmp,
+Pred1 == ICmpInst::ICMP_NE ? ICmpInst::ICMP_UGT
+   : ICmpInst::ICMP_ULT,
+X,
+Constant::getIntegerValue(
+X->getType(), APInt(X->getType()->getScalarSizeInBits(),
+Pred1 == ICmpInst::ICMP_NE ? 1 : 2)));
+  }
+} else {
+  // C != 0 && C != 1
+  // icmp eq X, (zext (icmp eq X, C)) --> icmp eq X, 0
+  // icmp eq X, (zext (icmp ne X, C)) --> icmp eq X, 1
+  // icmp ne X, (zext (icmp eq X, C)) --> icmp ne X, 0
+  // icmp ne X, (zext (icmp ne X, C)) --> icmp ne X, 1
+  return ICmpInst::Create(
+  Instruction::ICmp, Pred1, X,
+  Constant::getIntegerValue(
+  X->getType(),
+  APInt(X->getType()->getScalarSizeInBits(),
+static_cast(Pred2 == ICmpInst::ICMP_NE;
+}
+  }
+
   if (match(I.getOperand(0), m_c_Add(m_ZExt(m_Value(X)), m_SExt(m_Value(Y 
&&
   match(I.getOperand(1), m_APInt(C)) &&
   X->getType()->isIntOrIntVectorTy(1) &&
diff --git a/llvm/test/Transforms/InstCombine/icmp-range.ll 
b/llvm/test/Transforms/InstCombine/icmp-range.ll
index 4281e09cb0309c8..15424fce33fdeea 100644
--- a/llvm/test/Transforms/InstCombine/icmp-range.ll
+++ b/llvm/test/Transforms/InstCombine/icmp-range.ll
@@ -1034,6 +1034,187 @@ define i1 @icmp_ne_bool_1(ptr %ptr) {
   ret i1 %cmp
 }
 
+define i1 @icmp_ne_zext_eq_zero(i32 %a) {
+; CHECK-LABEL: @icmp_ne_zext_eq_zero(
+; CHECK-NEXT:ret i1 true
+;
+  %cmp = icmp eq i32 %a, 0
+  %conv = zext i1 %cmp to i32
+  %cmp1 = icmp ne i32 %conv, %a
+  ret i1 %cmp1
+}
+
+define i1 @icmp_ne_zext_ne_zero(i32 %a) {
+; CHECK-LABEL: @icmp_ne_zext_ne_zero(
+; CHECK-NEXT:[[CMP1:%.*]] = icmp ugt i32 [[A:%.*]], 1
+; CHECK-NEXT:ret i1 [[CMP1]]
+;
+  %cmp = icmp ne i32 %a, 0
+  %conv = zext i1 %cmp to i32
+  %cmp1 = icmp ne i32 %conv, %a
+  ret i1 %cmp1
+}
+
+define i1 @icmp_eq_zext_eq_zero(i32 %a) {
+; CHECK-LABEL: @icmp_eq_zext_eq_zero(
+; CHECK-NEXT:ret i1 false
+;
+  %cmp = icmp eq i32 %a, 0
+  %conv = zext i1 %cmp to i32
+  %cmp1 = icmp eq i32 %conv, %a
+  ret i1 %cmp1
+}
+
+define i1 @icmp_eq_zext_ne_zero(i32 

[clang] [ConstantRange] Handle `Intrinsic::cttz` (PR #67917)

2023-10-05 Thread Yingwei Zheng via cfe-commits

https://github.com/dtcxzyw edited 
https://github.com/llvm/llvm-project/pull/67917
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang-tools-extra] [ConstantRange] Handle `Intrinsic::cttz` (PR #67917)

2023-10-05 Thread Yingwei Zheng via cfe-commits

https://github.com/dtcxzyw edited 
https://github.com/llvm/llvm-project/pull/67917
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [ConstantRange] Handle `Intrinsic::cttz` (PR #67917)

2023-10-05 Thread Yingwei Zheng via cfe-commits


@@ -1735,6 +1746,122 @@ ConstantRange ConstantRange::ctlz(bool ZeroIsPoison) 
const {
   return getNonEmpty(APInt(getBitWidth(), getUnsignedMax().countl_zero()),
  APInt(getBitWidth(), getUnsignedMin().countl_zero() + 1));
 }
+static ConstantRange getUnsignedCountTrailingZerosRange(const APInt ,
+const APInt ) {
+  assert(Lower.ule(Upper));
+  unsigned BitWidth = Lower.getBitWidth();
+  if (Lower == Upper)
+return ConstantRange::getEmpty(BitWidth);
+  if (Lower + 1 == Upper)
+return ConstantRange(APInt(BitWidth, Lower.countr_zero()));
+  if (Lower.isZero())
+return ConstantRange(APInt::getZero(BitWidth),
+ APInt(BitWidth, BitWidth + 1));
+
+  // Calculate longest common prefix.
+  unsigned LCPLength = (Lower ^ (Upper - 1)).countl_zero();
+  // If Lower is {LCP, 000...}, the maximum is Lower.countr_zero().
+  // Otherwise, the maximum is BitWidth - LCPLength - 1 ({LCP, 100...}).
+  return ConstantRange(
+  APInt::getZero(BitWidth),
+  APInt(BitWidth, std::max(BitWidth - LCPLength, Lower.countr_zero() + 
1)));
+}
+
+ConstantRange ConstantRange::cttz(bool ZeroIsPoison) const {
+  if (isEmptySet())
+return getEmpty();
+
+  APInt Zero = APInt::getZero(getBitWidth());
+
+  if (ZeroIsPoison && contains(Zero)) {
+// ZeroIsPoison is set, and zero is contained. We discern three cases, in
+// which a zero can appear:
+// 1) Lower is zero, handling cases of kind [0, 1), [0, 2), etc.
+// 2) Upper is zero, wrapped set, handling cases of kind [3, 0], etc.
+// 3) Zero contained in a wrapped set, e.g., [3, 2), [3, 1), etc.
+
+if (getLower().isZero()) {
+  if ((getUpper() - 1).isZero()) {
+// We have in input interval of kind [0, 1). In this case we cannot
+// really help but return empty-set.
+return getEmpty();
+  }
+
+  // Compute the resulting range by excluding zero from Lower.
+  return getUnsignedCountTrailingZerosRange(getLower() + 1, getUpper());
+} else if ((getUpper() - 1).isZero()) {
+  // Compute the resulting range by excluding zero from Upper.
+  return ConstantRange(
+  Zero, APInt(getBitWidth(),
+  (getUnsignedMax() - getLower() + 1).logBase2() + 1));
+} else {
+  ConstantRange CR1(
+  Zero, APInt(getBitWidth(),
+  (getUnsignedMax() - getLower() + 1).logBase2() + 1));
+  ConstantRange CR2 = getUnsignedCountTrailingZerosRange(
+  APInt(getBitWidth(), 1), getUpper());
+  return CR1.unionWith(CR2);
+}
+  }
+
+  if (isFullSet()) {
+return getNonEmpty(Zero, APInt(getBitWidth(), getBitWidth() + 1));
+  }
+  if (!isUpperWrapped()) {
+return getUnsignedCountTrailingZerosRange(getLower(), getUpper());
+  }
+  ConstantRange CR1(
+  Zero,
+  APInt(getBitWidth(), (getUnsignedMax() - getLower() + 1).logBase2() + 
1));
+  ConstantRange CR2 = getUnsignedCountTrailingZerosRange(Zero, getUpper());
+  return CR1.unionWith(CR2);
+}
+
+static ConstantRange getUnsignedPopCountRange(const APInt ,
+  const APInt ) {
+  assert(Lower.ule(Upper));
+  unsigned BitWidth = Lower.getBitWidth();
+  if (Lower == Upper)
+return ConstantRange::getEmpty(BitWidth);
+  if (Lower + 1 == Upper)
+return ConstantRange(APInt(BitWidth, Lower.popcount()));
+
+  APInt Max = Upper - 1;
+  // Calculate longest common prefix.
+  unsigned LCPLength = (Lower ^ Max).countl_zero();
+  unsigned LCPPopCount = Lower.getHiBits(LCPLength).popcount();
+  // If Lower is {LCP, 000...}, the minimum is the popcount of LCP.
+  // Otherwise, the minimum is the popcount of LCP + 1.
+  unsigned MinBits =
+  LCPPopCount + (Lower.countr_zero() < BitWidth - LCPLength ? 1 : 0);
+  // If Max is {LCP, 111...}, the maximum is the popcount of LCP + (BitWidth -
+  // length of LCP).
+  // Otherwise, the minimum is the popcount of LCP + (BitWidth -
+  // length of LCP - 1).
+  unsigned MaxBits = LCPPopCount + (BitWidth - LCPLength) +
+ (Max.countr_one() >= BitWidth - LCPLength ? 1 : 0);

dtcxzyw wrote:

I am sure that the implementation is precise. As nikic commented in 
[D153505](https://reviews.llvm.org/D153505), non-constant-time methods were 
unacceptable.
Please move to #68310 for further review of the `ctpop` parts.

https://github.com/llvm/llvm-project/pull/67917
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang-tools-extra] [ConstantRange] Handle `Intrinsic::cttz` (PR #67917)

2023-10-05 Thread Yingwei Zheng via cfe-commits


@@ -1735,6 +1746,122 @@ ConstantRange ConstantRange::ctlz(bool ZeroIsPoison) 
const {
   return getNonEmpty(APInt(getBitWidth(), getUnsignedMax().countl_zero()),
  APInt(getBitWidth(), getUnsignedMin().countl_zero() + 1));
 }
+static ConstantRange getUnsignedCountTrailingZerosRange(const APInt ,
+const APInt ) {
+  assert(Lower.ule(Upper));
+  unsigned BitWidth = Lower.getBitWidth();
+  if (Lower == Upper)
+return ConstantRange::getEmpty(BitWidth);
+  if (Lower + 1 == Upper)
+return ConstantRange(APInt(BitWidth, Lower.countr_zero()));
+  if (Lower.isZero())
+return ConstantRange(APInt::getZero(BitWidth),
+ APInt(BitWidth, BitWidth + 1));
+
+  // Calculate longest common prefix.
+  unsigned LCPLength = (Lower ^ (Upper - 1)).countl_zero();
+  // If Lower is {LCP, 000...}, the maximum is Lower.countr_zero().
+  // Otherwise, the maximum is BitWidth - LCPLength - 1 ({LCP, 100...}).
+  return ConstantRange(
+  APInt::getZero(BitWidth),
+  APInt(BitWidth, std::max(BitWidth - LCPLength, Lower.countr_zero() + 
1)));
+}
+
+ConstantRange ConstantRange::cttz(bool ZeroIsPoison) const {
+  if (isEmptySet())
+return getEmpty();
+
+  APInt Zero = APInt::getZero(getBitWidth());
+
+  if (ZeroIsPoison && contains(Zero)) {
+// ZeroIsPoison is set, and zero is contained. We discern three cases, in
+// which a zero can appear:
+// 1) Lower is zero, handling cases of kind [0, 1), [0, 2), etc.
+// 2) Upper is zero, wrapped set, handling cases of kind [3, 0], etc.
+// 3) Zero contained in a wrapped set, e.g., [3, 2), [3, 1), etc.
+
+if (getLower().isZero()) {
+  if ((getUpper() - 1).isZero()) {
+// We have in input interval of kind [0, 1). In this case we cannot
+// really help but return empty-set.
+return getEmpty();
+  }
+
+  // Compute the resulting range by excluding zero from Lower.
+  return getUnsignedCountTrailingZerosRange(getLower() + 1, getUpper());
+} else if ((getUpper() - 1).isZero()) {
+  // Compute the resulting range by excluding zero from Upper.
+  return ConstantRange(
+  Zero, APInt(getBitWidth(),
+  (getUnsignedMax() - getLower() + 1).logBase2() + 1));
+} else {
+  ConstantRange CR1(
+  Zero, APInt(getBitWidth(),
+  (getUnsignedMax() - getLower() + 1).logBase2() + 1));
+  ConstantRange CR2 = getUnsignedCountTrailingZerosRange(
+  APInt(getBitWidth(), 1), getUpper());
+  return CR1.unionWith(CR2);
+}
+  }
+
+  if (isFullSet()) {
+return getNonEmpty(Zero, APInt(getBitWidth(), getBitWidth() + 1));
+  }
+  if (!isUpperWrapped()) {
+return getUnsignedCountTrailingZerosRange(getLower(), getUpper());
+  }
+  ConstantRange CR1(
+  Zero,
+  APInt(getBitWidth(), (getUnsignedMax() - getLower() + 1).logBase2() + 
1));
+  ConstantRange CR2 = getUnsignedCountTrailingZerosRange(Zero, getUpper());
+  return CR1.unionWith(CR2);
+}
+
+static ConstantRange getUnsignedPopCountRange(const APInt ,
+  const APInt ) {
+  assert(Lower.ule(Upper));
+  unsigned BitWidth = Lower.getBitWidth();
+  if (Lower == Upper)
+return ConstantRange::getEmpty(BitWidth);
+  if (Lower + 1 == Upper)
+return ConstantRange(APInt(BitWidth, Lower.popcount()));
+
+  APInt Max = Upper - 1;
+  // Calculate longest common prefix.
+  unsigned LCPLength = (Lower ^ Max).countl_zero();
+  unsigned LCPPopCount = Lower.getHiBits(LCPLength).popcount();
+  // If Lower is {LCP, 000...}, the minimum is the popcount of LCP.
+  // Otherwise, the minimum is the popcount of LCP + 1.
+  unsigned MinBits =
+  LCPPopCount + (Lower.countr_zero() < BitWidth - LCPLength ? 1 : 0);
+  // If Max is {LCP, 111...}, the maximum is the popcount of LCP + (BitWidth -
+  // length of LCP).
+  // Otherwise, the minimum is the popcount of LCP + (BitWidth -
+  // length of LCP - 1).
+  unsigned MaxBits = LCPPopCount + (BitWidth - LCPLength) +
+ (Max.countr_one() >= BitWidth - LCPLength ? 1 : 0);

dtcxzyw wrote:

I am sure that the implementation is precise. As nikic commented in 
[D153505](https://reviews.llvm.org/D153505), non-constant-time methods were 
unacceptable.
Please move to #68310 for further review of the `ctpop` parts.

https://github.com/llvm/llvm-project/pull/67917
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [ConstantRange] Handle `Intrinsic::cttz` (PR #67917)

2023-10-05 Thread Yingwei Zheng via cfe-commits

https://github.com/dtcxzyw updated 
https://github.com/llvm/llvm-project/pull/67917

>From b5d134c88a04c524b1d9120a1c1a5dae3722904c Mon Sep 17 00:00:00 2001
From: Yingwei Zheng 
Date: Sun, 1 Oct 2023 22:17:35 +0800
Subject: [PATCH 1/4] [ConstantRange] Handle `Intrinsic::cttz` and
 `Intrinsic::ctpop`

---
 llvm/include/llvm/IR/ConstantRange.h  |   7 +
 llvm/lib/IR/ConstantRange.cpp | 127 ++
 .../CorrelatedValuePropagation/range.ll   |  54 
 llvm/unittests/IR/ConstantRangeTest.cpp   |  20 +++
 4 files changed, 208 insertions(+)

diff --git a/llvm/include/llvm/IR/ConstantRange.h 
b/llvm/include/llvm/IR/ConstantRange.h
index ca36732e4e2e8c2..e718e6e7e3403de 100644
--- a/llvm/include/llvm/IR/ConstantRange.h
+++ b/llvm/include/llvm/IR/ConstantRange.h
@@ -530,6 +530,13 @@ class [[nodiscard]] ConstantRange {
   /// ignoring a possible zero value contained in the input range.
   ConstantRange ctlz(bool ZeroIsPoison = false) const;
 
+  /// Calculate cttz range. If \p ZeroIsPoison is set, the range is computed
+  /// ignoring a possible zero value contained in the input range.
+  ConstantRange cttz(bool ZeroIsPoison = false) const;
+
+  /// Calculate ctpop range.
+  ConstantRange ctpop() const;
+
   /// Represents whether an operation on the given constant range is known to
   /// always or never overflow.
   enum class OverflowResult {
diff --git a/llvm/lib/IR/ConstantRange.cpp b/llvm/lib/IR/ConstantRange.cpp
index 3d71b20f7e853e0..f34a2749543c321 100644
--- a/llvm/lib/IR/ConstantRange.cpp
+++ b/llvm/lib/IR/ConstantRange.cpp
@@ -949,6 +949,8 @@ bool ConstantRange::isIntrinsicSupported(Intrinsic::ID 
IntrinsicID) {
   case Intrinsic::smax:
   case Intrinsic::abs:
   case Intrinsic::ctlz:
+  case Intrinsic::cttz:
+  case Intrinsic::ctpop:
 return true;
   default:
 return false;
@@ -986,6 +988,15 @@ ConstantRange ConstantRange::intrinsic(Intrinsic::ID 
IntrinsicID,
 assert(ZeroIsPoison->getBitWidth() == 1 && "Must be boolean");
 return Ops[0].ctlz(ZeroIsPoison->getBoolValue());
   }
+  case Intrinsic::cttz: {
+const APInt *ZeroIsPoison = Ops[1].getSingleElement();
+assert(ZeroIsPoison && "Must be known (immarg)");
+assert(ZeroIsPoison->getBitWidth() == 1 && "Must be boolean");
+return Ops[0].cttz(ZeroIsPoison->getBoolValue());
+  }
+  case Intrinsic::ctpop: {
+return Ops[0].ctpop();
+  }
   default:
 assert(!isIntrinsicSupported(IntrinsicID) && "Shouldn't be supported");
 llvm_unreachable("Unsupported intrinsic");
@@ -1735,6 +1746,122 @@ ConstantRange ConstantRange::ctlz(bool ZeroIsPoison) 
const {
   return getNonEmpty(APInt(getBitWidth(), getUnsignedMax().countl_zero()),
  APInt(getBitWidth(), getUnsignedMin().countl_zero() + 1));
 }
+static ConstantRange getUnsignedCountTrailingZerosRange(const APInt ,
+const APInt ) {
+  assert(Lower.ule(Upper));
+  unsigned BitWidth = Lower.getBitWidth();
+  if (Lower == Upper)
+return ConstantRange::getEmpty(BitWidth);
+  if (Lower + 1 == Upper)
+return ConstantRange(APInt(BitWidth, Lower.countr_zero()));
+  if (Lower.isZero())
+return ConstantRange(APInt::getZero(BitWidth),
+ APInt(BitWidth, BitWidth + 1));
+
+  // Calculate longest common prefix.
+  unsigned LCPLength = (Lower ^ (Upper - 1)).countl_zero();
+  // If Lower is {LCP, 000...}, the maximum is Lower.countr_zero().
+  // Otherwise, the maximum is BitWidth - LCPLength - 1 ({LCP, 100...}).
+  return ConstantRange(
+  APInt::getZero(BitWidth),
+  APInt(BitWidth, std::max(BitWidth - LCPLength, Lower.countr_zero() + 
1)));
+}
+
+ConstantRange ConstantRange::cttz(bool ZeroIsPoison) const {
+  if (isEmptySet())
+return getEmpty();
+
+  APInt Zero = APInt::getZero(getBitWidth());
+
+  if (ZeroIsPoison && contains(Zero)) {
+// ZeroIsPoison is set, and zero is contained. We discern three cases, in
+// which a zero can appear:
+// 1) Lower is zero, handling cases of kind [0, 1), [0, 2), etc.
+// 2) Upper is zero, wrapped set, handling cases of kind [3, 0], etc.
+// 3) Zero contained in a wrapped set, e.g., [3, 2), [3, 1), etc.
+
+if (getLower().isZero()) {
+  if ((getUpper() - 1).isZero()) {
+// We have in input interval of kind [0, 1). In this case we cannot
+// really help but return empty-set.
+return getEmpty();
+  }
+
+  // Compute the resulting range by excluding zero from Lower.
+  return getUnsignedCountTrailingZerosRange(getLower() + 1, getUpper());
+} else if ((getUpper() - 1).isZero()) {
+  // Compute the resulting range by excluding zero from Upper.
+  return ConstantRange(
+  Zero, APInt(getBitWidth(),
+  (getUnsignedMax() - getLower() + 1).logBase2() + 1));
+} else {
+  ConstantRange CR1(
+  Zero, APInt(getBitWidth(),
+  (getUnsignedMax() - getLower() + 

[clang-tools-extra] [ConstantRange] Handle `Intrinsic::cttz` (PR #67917)

2023-10-05 Thread Yingwei Zheng via cfe-commits

https://github.com/dtcxzyw updated 
https://github.com/llvm/llvm-project/pull/67917

>From b5d134c88a04c524b1d9120a1c1a5dae3722904c Mon Sep 17 00:00:00 2001
From: Yingwei Zheng 
Date: Sun, 1 Oct 2023 22:17:35 +0800
Subject: [PATCH 1/4] [ConstantRange] Handle `Intrinsic::cttz` and
 `Intrinsic::ctpop`

---
 llvm/include/llvm/IR/ConstantRange.h  |   7 +
 llvm/lib/IR/ConstantRange.cpp | 127 ++
 .../CorrelatedValuePropagation/range.ll   |  54 
 llvm/unittests/IR/ConstantRangeTest.cpp   |  20 +++
 4 files changed, 208 insertions(+)

diff --git a/llvm/include/llvm/IR/ConstantRange.h 
b/llvm/include/llvm/IR/ConstantRange.h
index ca36732e4e2e8c2..e718e6e7e3403de 100644
--- a/llvm/include/llvm/IR/ConstantRange.h
+++ b/llvm/include/llvm/IR/ConstantRange.h
@@ -530,6 +530,13 @@ class [[nodiscard]] ConstantRange {
   /// ignoring a possible zero value contained in the input range.
   ConstantRange ctlz(bool ZeroIsPoison = false) const;
 
+  /// Calculate cttz range. If \p ZeroIsPoison is set, the range is computed
+  /// ignoring a possible zero value contained in the input range.
+  ConstantRange cttz(bool ZeroIsPoison = false) const;
+
+  /// Calculate ctpop range.
+  ConstantRange ctpop() const;
+
   /// Represents whether an operation on the given constant range is known to
   /// always or never overflow.
   enum class OverflowResult {
diff --git a/llvm/lib/IR/ConstantRange.cpp b/llvm/lib/IR/ConstantRange.cpp
index 3d71b20f7e853e0..f34a2749543c321 100644
--- a/llvm/lib/IR/ConstantRange.cpp
+++ b/llvm/lib/IR/ConstantRange.cpp
@@ -949,6 +949,8 @@ bool ConstantRange::isIntrinsicSupported(Intrinsic::ID 
IntrinsicID) {
   case Intrinsic::smax:
   case Intrinsic::abs:
   case Intrinsic::ctlz:
+  case Intrinsic::cttz:
+  case Intrinsic::ctpop:
 return true;
   default:
 return false;
@@ -986,6 +988,15 @@ ConstantRange ConstantRange::intrinsic(Intrinsic::ID 
IntrinsicID,
 assert(ZeroIsPoison->getBitWidth() == 1 && "Must be boolean");
 return Ops[0].ctlz(ZeroIsPoison->getBoolValue());
   }
+  case Intrinsic::cttz: {
+const APInt *ZeroIsPoison = Ops[1].getSingleElement();
+assert(ZeroIsPoison && "Must be known (immarg)");
+assert(ZeroIsPoison->getBitWidth() == 1 && "Must be boolean");
+return Ops[0].cttz(ZeroIsPoison->getBoolValue());
+  }
+  case Intrinsic::ctpop: {
+return Ops[0].ctpop();
+  }
   default:
 assert(!isIntrinsicSupported(IntrinsicID) && "Shouldn't be supported");
 llvm_unreachable("Unsupported intrinsic");
@@ -1735,6 +1746,122 @@ ConstantRange ConstantRange::ctlz(bool ZeroIsPoison) 
const {
   return getNonEmpty(APInt(getBitWidth(), getUnsignedMax().countl_zero()),
  APInt(getBitWidth(), getUnsignedMin().countl_zero() + 1));
 }
+static ConstantRange getUnsignedCountTrailingZerosRange(const APInt ,
+const APInt ) {
+  assert(Lower.ule(Upper));
+  unsigned BitWidth = Lower.getBitWidth();
+  if (Lower == Upper)
+return ConstantRange::getEmpty(BitWidth);
+  if (Lower + 1 == Upper)
+return ConstantRange(APInt(BitWidth, Lower.countr_zero()));
+  if (Lower.isZero())
+return ConstantRange(APInt::getZero(BitWidth),
+ APInt(BitWidth, BitWidth + 1));
+
+  // Calculate longest common prefix.
+  unsigned LCPLength = (Lower ^ (Upper - 1)).countl_zero();
+  // If Lower is {LCP, 000...}, the maximum is Lower.countr_zero().
+  // Otherwise, the maximum is BitWidth - LCPLength - 1 ({LCP, 100...}).
+  return ConstantRange(
+  APInt::getZero(BitWidth),
+  APInt(BitWidth, std::max(BitWidth - LCPLength, Lower.countr_zero() + 
1)));
+}
+
+ConstantRange ConstantRange::cttz(bool ZeroIsPoison) const {
+  if (isEmptySet())
+return getEmpty();
+
+  APInt Zero = APInt::getZero(getBitWidth());
+
+  if (ZeroIsPoison && contains(Zero)) {
+// ZeroIsPoison is set, and zero is contained. We discern three cases, in
+// which a zero can appear:
+// 1) Lower is zero, handling cases of kind [0, 1), [0, 2), etc.
+// 2) Upper is zero, wrapped set, handling cases of kind [3, 0], etc.
+// 3) Zero contained in a wrapped set, e.g., [3, 2), [3, 1), etc.
+
+if (getLower().isZero()) {
+  if ((getUpper() - 1).isZero()) {
+// We have in input interval of kind [0, 1). In this case we cannot
+// really help but return empty-set.
+return getEmpty();
+  }
+
+  // Compute the resulting range by excluding zero from Lower.
+  return getUnsignedCountTrailingZerosRange(getLower() + 1, getUpper());
+} else if ((getUpper() - 1).isZero()) {
+  // Compute the resulting range by excluding zero from Upper.
+  return ConstantRange(
+  Zero, APInt(getBitWidth(),
+  (getUnsignedMax() - getLower() + 1).logBase2() + 1));
+} else {
+  ConstantRange CR1(
+  Zero, APInt(getBitWidth(),
+  (getUnsignedMax() - getLower() + 

[clang] [ConstantRange] Handle `Intrinsic::cttz` (PR #67917)

2023-10-05 Thread Yingwei Zheng via cfe-commits


@@ -1735,6 +1746,122 @@ ConstantRange ConstantRange::ctlz(bool ZeroIsPoison) 
const {
   return getNonEmpty(APInt(getBitWidth(), getUnsignedMax().countl_zero()),
  APInt(getBitWidth(), getUnsignedMin().countl_zero() + 1));
 }
+static ConstantRange getUnsignedCountTrailingZerosRange(const APInt ,
+const APInt ) {
+  assert(Lower.ule(Upper));
+  unsigned BitWidth = Lower.getBitWidth();
+  if (Lower == Upper)
+return ConstantRange::getEmpty(BitWidth);
+  if (Lower + 1 == Upper)
+return ConstantRange(APInt(BitWidth, Lower.countr_zero()));
+  if (Lower.isZero())
+return ConstantRange(APInt::getZero(BitWidth),
+ APInt(BitWidth, BitWidth + 1));
+
+  // Calculate longest common prefix.
+  unsigned LCPLength = (Lower ^ (Upper - 1)).countl_zero();
+  // If Lower is {LCP, 000...}, the maximum is Lower.countr_zero().
+  // Otherwise, the maximum is BitWidth - LCPLength - 1 ({LCP, 100...}).
+  return ConstantRange(
+  APInt::getZero(BitWidth),
+  APInt(BitWidth, std::max(BitWidth - LCPLength, Lower.countr_zero() + 
1)));
+}
+
+ConstantRange ConstantRange::cttz(bool ZeroIsPoison) const {
+  if (isEmptySet())
+return getEmpty();
+
+  APInt Zero = APInt::getZero(getBitWidth());
+
+  if (ZeroIsPoison && contains(Zero)) {
+// ZeroIsPoison is set, and zero is contained. We discern three cases, in
+// which a zero can appear:
+// 1) Lower is zero, handling cases of kind [0, 1), [0, 2), etc.
+// 2) Upper is zero, wrapped set, handling cases of kind [3, 0], etc.
+// 3) Zero contained in a wrapped set, e.g., [3, 2), [3, 1), etc.
+
+if (getLower().isZero()) {
+  if ((getUpper() - 1).isZero()) {
+// We have in input interval of kind [0, 1). In this case we cannot
+// really help but return empty-set.
+return getEmpty();
+  }
+
+  // Compute the resulting range by excluding zero from Lower.
+  return getUnsignedCountTrailingZerosRange(getLower() + 1, getUpper());
+} else if ((getUpper() - 1).isZero()) {
+  // Compute the resulting range by excluding zero from Upper.
+  return ConstantRange(
+  Zero, APInt(getBitWidth(),
+  (getUnsignedMax() - getLower() + 1).logBase2() + 1));

dtcxzyw wrote:

It calculates the range of `cttz` for the input range `[Lower, UnsignedMax]`.
See also https://godbolt.org/z/jMhcs5375

https://github.com/llvm/llvm-project/pull/67917
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang-tools-extra] [ConstantRange] Handle `Intrinsic::cttz` (PR #67917)

2023-10-05 Thread Yingwei Zheng via cfe-commits


@@ -1735,6 +1746,122 @@ ConstantRange ConstantRange::ctlz(bool ZeroIsPoison) 
const {
   return getNonEmpty(APInt(getBitWidth(), getUnsignedMax().countl_zero()),
  APInt(getBitWidth(), getUnsignedMin().countl_zero() + 1));
 }
+static ConstantRange getUnsignedCountTrailingZerosRange(const APInt ,
+const APInt ) {
+  assert(Lower.ule(Upper));
+  unsigned BitWidth = Lower.getBitWidth();
+  if (Lower == Upper)
+return ConstantRange::getEmpty(BitWidth);
+  if (Lower + 1 == Upper)
+return ConstantRange(APInt(BitWidth, Lower.countr_zero()));
+  if (Lower.isZero())
+return ConstantRange(APInt::getZero(BitWidth),
+ APInt(BitWidth, BitWidth + 1));
+
+  // Calculate longest common prefix.
+  unsigned LCPLength = (Lower ^ (Upper - 1)).countl_zero();
+  // If Lower is {LCP, 000...}, the maximum is Lower.countr_zero().
+  // Otherwise, the maximum is BitWidth - LCPLength - 1 ({LCP, 100...}).
+  return ConstantRange(
+  APInt::getZero(BitWidth),
+  APInt(BitWidth, std::max(BitWidth - LCPLength, Lower.countr_zero() + 
1)));
+}
+
+ConstantRange ConstantRange::cttz(bool ZeroIsPoison) const {
+  if (isEmptySet())
+return getEmpty();
+
+  APInt Zero = APInt::getZero(getBitWidth());
+
+  if (ZeroIsPoison && contains(Zero)) {
+// ZeroIsPoison is set, and zero is contained. We discern three cases, in
+// which a zero can appear:
+// 1) Lower is zero, handling cases of kind [0, 1), [0, 2), etc.
+// 2) Upper is zero, wrapped set, handling cases of kind [3, 0], etc.
+// 3) Zero contained in a wrapped set, e.g., [3, 2), [3, 1), etc.
+
+if (getLower().isZero()) {
+  if ((getUpper() - 1).isZero()) {
+// We have in input interval of kind [0, 1). In this case we cannot
+// really help but return empty-set.
+return getEmpty();
+  }
+
+  // Compute the resulting range by excluding zero from Lower.
+  return getUnsignedCountTrailingZerosRange(getLower() + 1, getUpper());
+} else if ((getUpper() - 1).isZero()) {
+  // Compute the resulting range by excluding zero from Upper.
+  return ConstantRange(
+  Zero, APInt(getBitWidth(),
+  (getUnsignedMax() - getLower() + 1).logBase2() + 1));

dtcxzyw wrote:

It calculates the range of `cttz` for the input range `[Lower, UnsignedMax]`.
See also https://godbolt.org/z/jMhcs5375

https://github.com/llvm/llvm-project/pull/67917
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [ConstantRange] Handle `Intrinsic::cttz` (PR #67917)

2023-10-05 Thread Yingwei Zheng via cfe-commits

https://github.com/dtcxzyw edited 
https://github.com/llvm/llvm-project/pull/67917
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [ConstantRange] Handle `Intrinsic::cttz` (PR #67917)

2023-10-05 Thread Yingwei Zheng via cfe-commits

https://github.com/dtcxzyw updated 
https://github.com/llvm/llvm-project/pull/67917

>From b5d134c88a04c524b1d9120a1c1a5dae3722904c Mon Sep 17 00:00:00 2001
From: Yingwei Zheng 
Date: Sun, 1 Oct 2023 22:17:35 +0800
Subject: [PATCH 1/3] [ConstantRange] Handle `Intrinsic::cttz` and
 `Intrinsic::ctpop`

---
 llvm/include/llvm/IR/ConstantRange.h  |   7 +
 llvm/lib/IR/ConstantRange.cpp | 127 ++
 .../CorrelatedValuePropagation/range.ll   |  54 
 llvm/unittests/IR/ConstantRangeTest.cpp   |  20 +++
 4 files changed, 208 insertions(+)

diff --git a/llvm/include/llvm/IR/ConstantRange.h 
b/llvm/include/llvm/IR/ConstantRange.h
index ca36732e4e2e8c2..e718e6e7e3403de 100644
--- a/llvm/include/llvm/IR/ConstantRange.h
+++ b/llvm/include/llvm/IR/ConstantRange.h
@@ -530,6 +530,13 @@ class [[nodiscard]] ConstantRange {
   /// ignoring a possible zero value contained in the input range.
   ConstantRange ctlz(bool ZeroIsPoison = false) const;
 
+  /// Calculate cttz range. If \p ZeroIsPoison is set, the range is computed
+  /// ignoring a possible zero value contained in the input range.
+  ConstantRange cttz(bool ZeroIsPoison = false) const;
+
+  /// Calculate ctpop range.
+  ConstantRange ctpop() const;
+
   /// Represents whether an operation on the given constant range is known to
   /// always or never overflow.
   enum class OverflowResult {
diff --git a/llvm/lib/IR/ConstantRange.cpp b/llvm/lib/IR/ConstantRange.cpp
index 3d71b20f7e853e0..f34a2749543c321 100644
--- a/llvm/lib/IR/ConstantRange.cpp
+++ b/llvm/lib/IR/ConstantRange.cpp
@@ -949,6 +949,8 @@ bool ConstantRange::isIntrinsicSupported(Intrinsic::ID 
IntrinsicID) {
   case Intrinsic::smax:
   case Intrinsic::abs:
   case Intrinsic::ctlz:
+  case Intrinsic::cttz:
+  case Intrinsic::ctpop:
 return true;
   default:
 return false;
@@ -986,6 +988,15 @@ ConstantRange ConstantRange::intrinsic(Intrinsic::ID 
IntrinsicID,
 assert(ZeroIsPoison->getBitWidth() == 1 && "Must be boolean");
 return Ops[0].ctlz(ZeroIsPoison->getBoolValue());
   }
+  case Intrinsic::cttz: {
+const APInt *ZeroIsPoison = Ops[1].getSingleElement();
+assert(ZeroIsPoison && "Must be known (immarg)");
+assert(ZeroIsPoison->getBitWidth() == 1 && "Must be boolean");
+return Ops[0].cttz(ZeroIsPoison->getBoolValue());
+  }
+  case Intrinsic::ctpop: {
+return Ops[0].ctpop();
+  }
   default:
 assert(!isIntrinsicSupported(IntrinsicID) && "Shouldn't be supported");
 llvm_unreachable("Unsupported intrinsic");
@@ -1735,6 +1746,122 @@ ConstantRange ConstantRange::ctlz(bool ZeroIsPoison) 
const {
   return getNonEmpty(APInt(getBitWidth(), getUnsignedMax().countl_zero()),
  APInt(getBitWidth(), getUnsignedMin().countl_zero() + 1));
 }
+static ConstantRange getUnsignedCountTrailingZerosRange(const APInt ,
+const APInt ) {
+  assert(Lower.ule(Upper));
+  unsigned BitWidth = Lower.getBitWidth();
+  if (Lower == Upper)
+return ConstantRange::getEmpty(BitWidth);
+  if (Lower + 1 == Upper)
+return ConstantRange(APInt(BitWidth, Lower.countr_zero()));
+  if (Lower.isZero())
+return ConstantRange(APInt::getZero(BitWidth),
+ APInt(BitWidth, BitWidth + 1));
+
+  // Calculate longest common prefix.
+  unsigned LCPLength = (Lower ^ (Upper - 1)).countl_zero();
+  // If Lower is {LCP, 000...}, the maximum is Lower.countr_zero().
+  // Otherwise, the maximum is BitWidth - LCPLength - 1 ({LCP, 100...}).
+  return ConstantRange(
+  APInt::getZero(BitWidth),
+  APInt(BitWidth, std::max(BitWidth - LCPLength, Lower.countr_zero() + 
1)));
+}
+
+ConstantRange ConstantRange::cttz(bool ZeroIsPoison) const {
+  if (isEmptySet())
+return getEmpty();
+
+  APInt Zero = APInt::getZero(getBitWidth());
+
+  if (ZeroIsPoison && contains(Zero)) {
+// ZeroIsPoison is set, and zero is contained. We discern three cases, in
+// which a zero can appear:
+// 1) Lower is zero, handling cases of kind [0, 1), [0, 2), etc.
+// 2) Upper is zero, wrapped set, handling cases of kind [3, 0], etc.
+// 3) Zero contained in a wrapped set, e.g., [3, 2), [3, 1), etc.
+
+if (getLower().isZero()) {
+  if ((getUpper() - 1).isZero()) {
+// We have in input interval of kind [0, 1). In this case we cannot
+// really help but return empty-set.
+return getEmpty();
+  }
+
+  // Compute the resulting range by excluding zero from Lower.
+  return getUnsignedCountTrailingZerosRange(getLower() + 1, getUpper());
+} else if ((getUpper() - 1).isZero()) {
+  // Compute the resulting range by excluding zero from Upper.
+  return ConstantRange(
+  Zero, APInt(getBitWidth(),
+  (getUnsignedMax() - getLower() + 1).logBase2() + 1));
+} else {
+  ConstantRange CR1(
+  Zero, APInt(getBitWidth(),
+  (getUnsignedMax() - getLower() + 

[clang-tools-extra] [ConstantRange] Handle `Intrinsic::cttz` (PR #67917)

2023-10-05 Thread Yingwei Zheng via cfe-commits

https://github.com/dtcxzyw updated 
https://github.com/llvm/llvm-project/pull/67917

>From b5d134c88a04c524b1d9120a1c1a5dae3722904c Mon Sep 17 00:00:00 2001
From: Yingwei Zheng 
Date: Sun, 1 Oct 2023 22:17:35 +0800
Subject: [PATCH 1/3] [ConstantRange] Handle `Intrinsic::cttz` and
 `Intrinsic::ctpop`

---
 llvm/include/llvm/IR/ConstantRange.h  |   7 +
 llvm/lib/IR/ConstantRange.cpp | 127 ++
 .../CorrelatedValuePropagation/range.ll   |  54 
 llvm/unittests/IR/ConstantRangeTest.cpp   |  20 +++
 4 files changed, 208 insertions(+)

diff --git a/llvm/include/llvm/IR/ConstantRange.h 
b/llvm/include/llvm/IR/ConstantRange.h
index ca36732e4e2e8c2..e718e6e7e3403de 100644
--- a/llvm/include/llvm/IR/ConstantRange.h
+++ b/llvm/include/llvm/IR/ConstantRange.h
@@ -530,6 +530,13 @@ class [[nodiscard]] ConstantRange {
   /// ignoring a possible zero value contained in the input range.
   ConstantRange ctlz(bool ZeroIsPoison = false) const;
 
+  /// Calculate cttz range. If \p ZeroIsPoison is set, the range is computed
+  /// ignoring a possible zero value contained in the input range.
+  ConstantRange cttz(bool ZeroIsPoison = false) const;
+
+  /// Calculate ctpop range.
+  ConstantRange ctpop() const;
+
   /// Represents whether an operation on the given constant range is known to
   /// always or never overflow.
   enum class OverflowResult {
diff --git a/llvm/lib/IR/ConstantRange.cpp b/llvm/lib/IR/ConstantRange.cpp
index 3d71b20f7e853e0..f34a2749543c321 100644
--- a/llvm/lib/IR/ConstantRange.cpp
+++ b/llvm/lib/IR/ConstantRange.cpp
@@ -949,6 +949,8 @@ bool ConstantRange::isIntrinsicSupported(Intrinsic::ID 
IntrinsicID) {
   case Intrinsic::smax:
   case Intrinsic::abs:
   case Intrinsic::ctlz:
+  case Intrinsic::cttz:
+  case Intrinsic::ctpop:
 return true;
   default:
 return false;
@@ -986,6 +988,15 @@ ConstantRange ConstantRange::intrinsic(Intrinsic::ID 
IntrinsicID,
 assert(ZeroIsPoison->getBitWidth() == 1 && "Must be boolean");
 return Ops[0].ctlz(ZeroIsPoison->getBoolValue());
   }
+  case Intrinsic::cttz: {
+const APInt *ZeroIsPoison = Ops[1].getSingleElement();
+assert(ZeroIsPoison && "Must be known (immarg)");
+assert(ZeroIsPoison->getBitWidth() == 1 && "Must be boolean");
+return Ops[0].cttz(ZeroIsPoison->getBoolValue());
+  }
+  case Intrinsic::ctpop: {
+return Ops[0].ctpop();
+  }
   default:
 assert(!isIntrinsicSupported(IntrinsicID) && "Shouldn't be supported");
 llvm_unreachable("Unsupported intrinsic");
@@ -1735,6 +1746,122 @@ ConstantRange ConstantRange::ctlz(bool ZeroIsPoison) 
const {
   return getNonEmpty(APInt(getBitWidth(), getUnsignedMax().countl_zero()),
  APInt(getBitWidth(), getUnsignedMin().countl_zero() + 1));
 }
+static ConstantRange getUnsignedCountTrailingZerosRange(const APInt ,
+const APInt ) {
+  assert(Lower.ule(Upper));
+  unsigned BitWidth = Lower.getBitWidth();
+  if (Lower == Upper)
+return ConstantRange::getEmpty(BitWidth);
+  if (Lower + 1 == Upper)
+return ConstantRange(APInt(BitWidth, Lower.countr_zero()));
+  if (Lower.isZero())
+return ConstantRange(APInt::getZero(BitWidth),
+ APInt(BitWidth, BitWidth + 1));
+
+  // Calculate longest common prefix.
+  unsigned LCPLength = (Lower ^ (Upper - 1)).countl_zero();
+  // If Lower is {LCP, 000...}, the maximum is Lower.countr_zero().
+  // Otherwise, the maximum is BitWidth - LCPLength - 1 ({LCP, 100...}).
+  return ConstantRange(
+  APInt::getZero(BitWidth),
+  APInt(BitWidth, std::max(BitWidth - LCPLength, Lower.countr_zero() + 
1)));
+}
+
+ConstantRange ConstantRange::cttz(bool ZeroIsPoison) const {
+  if (isEmptySet())
+return getEmpty();
+
+  APInt Zero = APInt::getZero(getBitWidth());
+
+  if (ZeroIsPoison && contains(Zero)) {
+// ZeroIsPoison is set, and zero is contained. We discern three cases, in
+// which a zero can appear:
+// 1) Lower is zero, handling cases of kind [0, 1), [0, 2), etc.
+// 2) Upper is zero, wrapped set, handling cases of kind [3, 0], etc.
+// 3) Zero contained in a wrapped set, e.g., [3, 2), [3, 1), etc.
+
+if (getLower().isZero()) {
+  if ((getUpper() - 1).isZero()) {
+// We have in input interval of kind [0, 1). In this case we cannot
+// really help but return empty-set.
+return getEmpty();
+  }
+
+  // Compute the resulting range by excluding zero from Lower.
+  return getUnsignedCountTrailingZerosRange(getLower() + 1, getUpper());
+} else if ((getUpper() - 1).isZero()) {
+  // Compute the resulting range by excluding zero from Upper.
+  return ConstantRange(
+  Zero, APInt(getBitWidth(),
+  (getUnsignedMax() - getLower() + 1).logBase2() + 1));
+} else {
+  ConstantRange CR1(
+  Zero, APInt(getBitWidth(),
+  (getUnsignedMax() - getLower() + 

[clang-tools-extra] [ConstantRange] Handle `Intrinsic::cttz` (PR #67917)

2023-10-05 Thread Yingwei Zheng via cfe-commits

https://github.com/dtcxzyw edited 
https://github.com/llvm/llvm-project/pull/67917
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [ConstantRange] Handle `Intrinsic::cttz` (PR #67917)

2023-10-05 Thread Yingwei Zheng via cfe-commits

https://github.com/dtcxzyw edited 
https://github.com/llvm/llvm-project/pull/67917
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang-tools-extra] [ConstantRange] Handle `Intrinsic::cttz` and `Intrinsic::ctpop` (PR #67917)

2023-10-05 Thread Yingwei Zheng via cfe-commits

https://github.com/dtcxzyw updated 
https://github.com/llvm/llvm-project/pull/67917

>From b5d134c88a04c524b1d9120a1c1a5dae3722904c Mon Sep 17 00:00:00 2001
From: Yingwei Zheng 
Date: Sun, 1 Oct 2023 22:17:35 +0800
Subject: [PATCH 1/2] [ConstantRange] Handle `Intrinsic::cttz` and
 `Intrinsic::ctpop`

---
 llvm/include/llvm/IR/ConstantRange.h  |   7 +
 llvm/lib/IR/ConstantRange.cpp | 127 ++
 .../CorrelatedValuePropagation/range.ll   |  54 
 llvm/unittests/IR/ConstantRangeTest.cpp   |  20 +++
 4 files changed, 208 insertions(+)

diff --git a/llvm/include/llvm/IR/ConstantRange.h 
b/llvm/include/llvm/IR/ConstantRange.h
index ca36732e4e2e8c2..e718e6e7e3403de 100644
--- a/llvm/include/llvm/IR/ConstantRange.h
+++ b/llvm/include/llvm/IR/ConstantRange.h
@@ -530,6 +530,13 @@ class [[nodiscard]] ConstantRange {
   /// ignoring a possible zero value contained in the input range.
   ConstantRange ctlz(bool ZeroIsPoison = false) const;
 
+  /// Calculate cttz range. If \p ZeroIsPoison is set, the range is computed
+  /// ignoring a possible zero value contained in the input range.
+  ConstantRange cttz(bool ZeroIsPoison = false) const;
+
+  /// Calculate ctpop range.
+  ConstantRange ctpop() const;
+
   /// Represents whether an operation on the given constant range is known to
   /// always or never overflow.
   enum class OverflowResult {
diff --git a/llvm/lib/IR/ConstantRange.cpp b/llvm/lib/IR/ConstantRange.cpp
index 3d71b20f7e853e0..f34a2749543c321 100644
--- a/llvm/lib/IR/ConstantRange.cpp
+++ b/llvm/lib/IR/ConstantRange.cpp
@@ -949,6 +949,8 @@ bool ConstantRange::isIntrinsicSupported(Intrinsic::ID 
IntrinsicID) {
   case Intrinsic::smax:
   case Intrinsic::abs:
   case Intrinsic::ctlz:
+  case Intrinsic::cttz:
+  case Intrinsic::ctpop:
 return true;
   default:
 return false;
@@ -986,6 +988,15 @@ ConstantRange ConstantRange::intrinsic(Intrinsic::ID 
IntrinsicID,
 assert(ZeroIsPoison->getBitWidth() == 1 && "Must be boolean");
 return Ops[0].ctlz(ZeroIsPoison->getBoolValue());
   }
+  case Intrinsic::cttz: {
+const APInt *ZeroIsPoison = Ops[1].getSingleElement();
+assert(ZeroIsPoison && "Must be known (immarg)");
+assert(ZeroIsPoison->getBitWidth() == 1 && "Must be boolean");
+return Ops[0].cttz(ZeroIsPoison->getBoolValue());
+  }
+  case Intrinsic::ctpop: {
+return Ops[0].ctpop();
+  }
   default:
 assert(!isIntrinsicSupported(IntrinsicID) && "Shouldn't be supported");
 llvm_unreachable("Unsupported intrinsic");
@@ -1735,6 +1746,122 @@ ConstantRange ConstantRange::ctlz(bool ZeroIsPoison) 
const {
   return getNonEmpty(APInt(getBitWidth(), getUnsignedMax().countl_zero()),
  APInt(getBitWidth(), getUnsignedMin().countl_zero() + 1));
 }
+static ConstantRange getUnsignedCountTrailingZerosRange(const APInt ,
+const APInt ) {
+  assert(Lower.ule(Upper));
+  unsigned BitWidth = Lower.getBitWidth();
+  if (Lower == Upper)
+return ConstantRange::getEmpty(BitWidth);
+  if (Lower + 1 == Upper)
+return ConstantRange(APInt(BitWidth, Lower.countr_zero()));
+  if (Lower.isZero())
+return ConstantRange(APInt::getZero(BitWidth),
+ APInt(BitWidth, BitWidth + 1));
+
+  // Calculate longest common prefix.
+  unsigned LCPLength = (Lower ^ (Upper - 1)).countl_zero();
+  // If Lower is {LCP, 000...}, the maximum is Lower.countr_zero().
+  // Otherwise, the maximum is BitWidth - LCPLength - 1 ({LCP, 100...}).
+  return ConstantRange(
+  APInt::getZero(BitWidth),
+  APInt(BitWidth, std::max(BitWidth - LCPLength, Lower.countr_zero() + 
1)));
+}
+
+ConstantRange ConstantRange::cttz(bool ZeroIsPoison) const {
+  if (isEmptySet())
+return getEmpty();
+
+  APInt Zero = APInt::getZero(getBitWidth());
+
+  if (ZeroIsPoison && contains(Zero)) {
+// ZeroIsPoison is set, and zero is contained. We discern three cases, in
+// which a zero can appear:
+// 1) Lower is zero, handling cases of kind [0, 1), [0, 2), etc.
+// 2) Upper is zero, wrapped set, handling cases of kind [3, 0], etc.
+// 3) Zero contained in a wrapped set, e.g., [3, 2), [3, 1), etc.
+
+if (getLower().isZero()) {
+  if ((getUpper() - 1).isZero()) {
+// We have in input interval of kind [0, 1). In this case we cannot
+// really help but return empty-set.
+return getEmpty();
+  }
+
+  // Compute the resulting range by excluding zero from Lower.
+  return getUnsignedCountTrailingZerosRange(getLower() + 1, getUpper());
+} else if ((getUpper() - 1).isZero()) {
+  // Compute the resulting range by excluding zero from Upper.
+  return ConstantRange(
+  Zero, APInt(getBitWidth(),
+  (getUnsignedMax() - getLower() + 1).logBase2() + 1));
+} else {
+  ConstantRange CR1(
+  Zero, APInt(getBitWidth(),
+  (getUnsignedMax() - getLower() + 

[clang] [ConstantRange] Handle `Intrinsic::cttz` and `Intrinsic::ctpop` (PR #67917)

2023-10-05 Thread Yingwei Zheng via cfe-commits

https://github.com/dtcxzyw updated 
https://github.com/llvm/llvm-project/pull/67917

>From b5d134c88a04c524b1d9120a1c1a5dae3722904c Mon Sep 17 00:00:00 2001
From: Yingwei Zheng 
Date: Sun, 1 Oct 2023 22:17:35 +0800
Subject: [PATCH 1/2] [ConstantRange] Handle `Intrinsic::cttz` and
 `Intrinsic::ctpop`

---
 llvm/include/llvm/IR/ConstantRange.h  |   7 +
 llvm/lib/IR/ConstantRange.cpp | 127 ++
 .../CorrelatedValuePropagation/range.ll   |  54 
 llvm/unittests/IR/ConstantRangeTest.cpp   |  20 +++
 4 files changed, 208 insertions(+)

diff --git a/llvm/include/llvm/IR/ConstantRange.h 
b/llvm/include/llvm/IR/ConstantRange.h
index ca36732e4e2e8c2..e718e6e7e3403de 100644
--- a/llvm/include/llvm/IR/ConstantRange.h
+++ b/llvm/include/llvm/IR/ConstantRange.h
@@ -530,6 +530,13 @@ class [[nodiscard]] ConstantRange {
   /// ignoring a possible zero value contained in the input range.
   ConstantRange ctlz(bool ZeroIsPoison = false) const;
 
+  /// Calculate cttz range. If \p ZeroIsPoison is set, the range is computed
+  /// ignoring a possible zero value contained in the input range.
+  ConstantRange cttz(bool ZeroIsPoison = false) const;
+
+  /// Calculate ctpop range.
+  ConstantRange ctpop() const;
+
   /// Represents whether an operation on the given constant range is known to
   /// always or never overflow.
   enum class OverflowResult {
diff --git a/llvm/lib/IR/ConstantRange.cpp b/llvm/lib/IR/ConstantRange.cpp
index 3d71b20f7e853e0..f34a2749543c321 100644
--- a/llvm/lib/IR/ConstantRange.cpp
+++ b/llvm/lib/IR/ConstantRange.cpp
@@ -949,6 +949,8 @@ bool ConstantRange::isIntrinsicSupported(Intrinsic::ID 
IntrinsicID) {
   case Intrinsic::smax:
   case Intrinsic::abs:
   case Intrinsic::ctlz:
+  case Intrinsic::cttz:
+  case Intrinsic::ctpop:
 return true;
   default:
 return false;
@@ -986,6 +988,15 @@ ConstantRange ConstantRange::intrinsic(Intrinsic::ID 
IntrinsicID,
 assert(ZeroIsPoison->getBitWidth() == 1 && "Must be boolean");
 return Ops[0].ctlz(ZeroIsPoison->getBoolValue());
   }
+  case Intrinsic::cttz: {
+const APInt *ZeroIsPoison = Ops[1].getSingleElement();
+assert(ZeroIsPoison && "Must be known (immarg)");
+assert(ZeroIsPoison->getBitWidth() == 1 && "Must be boolean");
+return Ops[0].cttz(ZeroIsPoison->getBoolValue());
+  }
+  case Intrinsic::ctpop: {
+return Ops[0].ctpop();
+  }
   default:
 assert(!isIntrinsicSupported(IntrinsicID) && "Shouldn't be supported");
 llvm_unreachable("Unsupported intrinsic");
@@ -1735,6 +1746,122 @@ ConstantRange ConstantRange::ctlz(bool ZeroIsPoison) 
const {
   return getNonEmpty(APInt(getBitWidth(), getUnsignedMax().countl_zero()),
  APInt(getBitWidth(), getUnsignedMin().countl_zero() + 1));
 }
+static ConstantRange getUnsignedCountTrailingZerosRange(const APInt ,
+const APInt ) {
+  assert(Lower.ule(Upper));
+  unsigned BitWidth = Lower.getBitWidth();
+  if (Lower == Upper)
+return ConstantRange::getEmpty(BitWidth);
+  if (Lower + 1 == Upper)
+return ConstantRange(APInt(BitWidth, Lower.countr_zero()));
+  if (Lower.isZero())
+return ConstantRange(APInt::getZero(BitWidth),
+ APInt(BitWidth, BitWidth + 1));
+
+  // Calculate longest common prefix.
+  unsigned LCPLength = (Lower ^ (Upper - 1)).countl_zero();
+  // If Lower is {LCP, 000...}, the maximum is Lower.countr_zero().
+  // Otherwise, the maximum is BitWidth - LCPLength - 1 ({LCP, 100...}).
+  return ConstantRange(
+  APInt::getZero(BitWidth),
+  APInt(BitWidth, std::max(BitWidth - LCPLength, Lower.countr_zero() + 
1)));
+}
+
+ConstantRange ConstantRange::cttz(bool ZeroIsPoison) const {
+  if (isEmptySet())
+return getEmpty();
+
+  APInt Zero = APInt::getZero(getBitWidth());
+
+  if (ZeroIsPoison && contains(Zero)) {
+// ZeroIsPoison is set, and zero is contained. We discern three cases, in
+// which a zero can appear:
+// 1) Lower is zero, handling cases of kind [0, 1), [0, 2), etc.
+// 2) Upper is zero, wrapped set, handling cases of kind [3, 0], etc.
+// 3) Zero contained in a wrapped set, e.g., [3, 2), [3, 1), etc.
+
+if (getLower().isZero()) {
+  if ((getUpper() - 1).isZero()) {
+// We have in input interval of kind [0, 1). In this case we cannot
+// really help but return empty-set.
+return getEmpty();
+  }
+
+  // Compute the resulting range by excluding zero from Lower.
+  return getUnsignedCountTrailingZerosRange(getLower() + 1, getUpper());
+} else if ((getUpper() - 1).isZero()) {
+  // Compute the resulting range by excluding zero from Upper.
+  return ConstantRange(
+  Zero, APInt(getBitWidth(),
+  (getUnsignedMax() - getLower() + 1).logBase2() + 1));
+} else {
+  ConstantRange CR1(
+  Zero, APInt(getBitWidth(),
+  (getUnsignedMax() - getLower() + 

[clang] [InstCombine] Canonicalize `(X +/- Y) & Y` into `~X & Y` when Y is a power of 2 (PR #67915)

2023-10-05 Thread Yingwei Zheng via cfe-commits

https://github.com/dtcxzyw updated 
https://github.com/llvm/llvm-project/pull/67915

>From c4ce28c942c172e5646b5922f0b02b4169197840 Mon Sep 17 00:00:00 2001
From: Yingwei Zheng 
Date: Sun, 1 Oct 2023 21:52:47 +0800
Subject: [PATCH] [InstCombine] Canonicalize `(X +/- Y) & Y` into `~X & Y` when
 Y is a power of 2

---
 .../InstCombine/InstCombineAndOrXor.cpp   |  8 
 llvm/test/Transforms/InstCombine/and.ll   | 44 +--
 2 files changed, 48 insertions(+), 4 deletions(-)

diff --git a/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp 
b/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
index cbdab3e9c5fb91d..4322cc96f5a2b6c 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
@@ -2250,6 +2250,14 @@ Instruction *InstCombinerImpl::visitAnd(BinaryOperator 
) {
 return SelectInst::Create(Cmp, ConstantInt::getNullValue(Ty), Y);
   }
 
+  // Canonicalize:
+  // (X +/- Y) & Y --> ~X & Y when Y is a power of 2.
+  if (match(, m_c_And(m_Value(Y), m_OneUse(m_CombineOr(
+m_c_Add(m_Value(X), m_Deferred(Y)),
+m_Sub(m_Value(X), m_Deferred(Y)) &&
+  isKnownToBeAPowerOfTwo(Y, /*OrZero*/ true, /*Depth*/ 0, ))
+return BinaryOperator::CreateAnd(Builder.CreateNot(X), Y);
+
   const APInt *C;
   if (match(Op1, m_APInt(C))) {
 const APInt *XorC;
diff --git a/llvm/test/Transforms/InstCombine/and.ll 
b/llvm/test/Transforms/InstCombine/and.ll
index 90f027010e2aea6..eb39ff9014ff3a4 100644
--- a/llvm/test/Transforms/InstCombine/and.ll
+++ b/llvm/test/Transforms/InstCombine/and.ll
@@ -1595,8 +1595,8 @@ define <2 x i8> @flip_masked_bit_uniform(<2 x i8> %A) {
 
 define <2 x i8> @flip_masked_bit_undef(<2 x i8> %A) {
 ; CHECK-LABEL: @flip_masked_bit_undef(
-; CHECK-NEXT:[[B:%.*]] = add <2 x i8> [[A:%.*]], 
-; CHECK-NEXT:[[C:%.*]] = and <2 x i8> [[B]], 
+; CHECK-NEXT:[[TMP1:%.*]] = xor <2 x i8> [[A:%.*]], 
+; CHECK-NEXT:[[C:%.*]] = and <2 x i8> [[TMP1]], 
 ; CHECK-NEXT:ret <2 x i8> [[C]]
 ;
   %B = add <2 x i8> %A, 
@@ -1606,8 +1606,8 @@ define <2 x i8> @flip_masked_bit_undef(<2 x i8> %A) {
 
 define <2 x i8> @flip_masked_bit_nonuniform(<2 x i8> %A) {
 ; CHECK-LABEL: @flip_masked_bit_nonuniform(
-; CHECK-NEXT:[[B:%.*]] = add <2 x i8> [[A:%.*]], 
-; CHECK-NEXT:[[C:%.*]] = and <2 x i8> [[B]], 
+; CHECK-NEXT:[[TMP1:%.*]] = xor <2 x i8> [[A:%.*]], 
+; CHECK-NEXT:[[C:%.*]] = and <2 x i8> [[TMP1]], 
 ; CHECK-NEXT:ret <2 x i8> [[C]]
 ;
   %B = add <2 x i8> %A, 
@@ -2546,3 +2546,39 @@ define i32 @and_zext_eq_zero(i32 %A, i32 %C)  {
   %5 = and i32 %2, %4
   ret i32 %5
 }
+
+define i32 @canonicalize_and_add_power2_or_zero(i32 %x, i32 %y) {
+; CHECK-LABEL: @canonicalize_and_add_power2_or_zero(
+; CHECK-NEXT:[[NY:%.*]] = sub i32 0, [[Y:%.*]]
+; CHECK-NEXT:[[P2:%.*]] = and i32 [[NY]], [[Y]]
+; CHECK-NEXT:call void @use32(i32 [[P2]])
+; CHECK-NEXT:[[TMP1:%.*]] = xor i32 [[X:%.*]], -1
+; CHECK-NEXT:[[AND:%.*]] = and i32 [[P2]], [[TMP1]]
+; CHECK-NEXT:ret i32 [[AND]]
+;
+  %ny = sub i32 0, %y
+  %p2 = and i32 %y, %ny
+  call void @use32(i32 %p2) ; keep p2
+
+  %val = add i32 %x, %p2
+  %and = and i32 %val, %p2
+  ret i32 %and
+}
+
+define i32 @canonicalize_and_sub_power2_or_zero(i32 %x, i32 %y) {
+; CHECK-LABEL: @canonicalize_and_sub_power2_or_zero(
+; CHECK-NEXT:[[NY:%.*]] = sub i32 0, [[Y:%.*]]
+; CHECK-NEXT:[[P2:%.*]] = and i32 [[NY]], [[Y]]
+; CHECK-NEXT:call void @use32(i32 [[P2]])
+; CHECK-NEXT:[[TMP1:%.*]] = xor i32 [[X:%.*]], -1
+; CHECK-NEXT:[[AND:%.*]] = and i32 [[P2]], [[TMP1]]
+; CHECK-NEXT:ret i32 [[AND]]
+;
+  %ny = sub i32 0, %y
+  %p2 = and i32 %y, %ny
+  call void @use32(i32 %p2) ; keep p2
+
+  %val = sub i32 %x, %p2
+  %and = and i32 %val, %p2
+  ret i32 %and
+}

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [InstCombine] Simplify the pattern `a ne/eq (zext/sext (a ne/eq c))` (PR #65852)

2023-10-05 Thread Yingwei Zheng via cfe-commits

dtcxzyw wrote:

Ping.

https://github.com/llvm/llvm-project/pull/65852
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang-tools-extra] [InstCombine] Simplify the pattern `a ne/eq (zext/sext (a ne/eq c))` (PR #65852)

2023-10-05 Thread Yingwei Zheng via cfe-commits

dtcxzyw wrote:

Ping.

https://github.com/llvm/llvm-project/pull/65852
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang-tools-extra] [RISCV] Eliminate dead li after emitting VSETVLIs (PR #65934)

2023-10-03 Thread Yingwei Zheng via cfe-commits

dtcxzyw wrote:

Ping.

https://github.com/llvm/llvm-project/pull/65934
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang-tools-extra] [InstCombine] Simplify the pattern `a ne/eq (zext/sext (a ne/eq c))` (PR #65852)

2023-10-01 Thread Yingwei Zheng via cfe-commits

https://github.com/dtcxzyw updated 
https://github.com/llvm/llvm-project/pull/65852

>From d9d8bcbb98e8f5aecb9733329389d61a489bd731 Mon Sep 17 00:00:00 2001
From: Yingwei Zheng 
Date: Sat, 9 Sep 2023 23:07:29 +0800
Subject: [PATCH 1/9] [InstCombine] Simplify the pattern `a ne/eq (zext (a
 ne/eq c))`

---
 .../InstCombine/InstCombineCompares.cpp   |  62 ++
 .../test/Transforms/InstCombine/icmp-range.ll | 181 ++
 2 files changed, 243 insertions(+)

diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp 
b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
index 9fdc46fec631679..837b8e6d2619989 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
@@ -6309,7 +6309,69 @@ Instruction 
*InstCombinerImpl::foldICmpUsingBoolRange(ICmpInst ) {
   Y->getType()->isIntOrIntVectorTy(1) && Pred == ICmpInst::ICMP_ULE)
 return BinaryOperator::CreateOr(Builder.CreateIsNull(X), Y);
 
+  ICmpInst::Predicate Pred1, Pred2;
   const APInt *C;
+  // icmp eq/ne X, (zext (icmp eq/ne X, C))
+  if (match(, m_c_ICmp(Pred1, m_Value(X),
+ m_ZExt(m_ICmp(Pred2, m_Deferred(X), m_APInt(C) &&
+  ICmpInst::isEquality(Pred1) && ICmpInst::isEquality(Pred2)) {
+if (C->isZero()) {
+  if (Pred2 == ICmpInst::ICMP_EQ) {
+// icmp eq X, (zext (icmp eq X, 0)) --> false
+// icmp ne X, (zext (icmp eq X, 0)) --> true
+return replaceInstUsesWith(
+I,
+Constant::getIntegerValue(
+I.getType(),
+APInt(1U, static_cast(Pred1 == ICmpInst::ICMP_NE;
+  } else {
+// icmp eq X, (zext (icmp ne X, 0)) --> icmp ult X, 2
+// icmp ne X, (zext (icmp ne X, 0)) --> icmp ugt X, 1
+return ICmpInst::Create(
+Instruction::ICmp,
+Pred1 == ICmpInst::ICMP_NE ? ICmpInst::ICMP_UGT
+   : ICmpInst::ICMP_ULT,
+X,
+Constant::getIntegerValue(
+X->getType(), APInt(X->getType()->getScalarSizeInBits(),
+Pred1 == ICmpInst::ICMP_NE ? 1 : 2)));
+  }
+} else if (C->isOne()) {
+  if (Pred2 == ICmpInst::ICMP_NE) {
+// icmp eq X, (zext (icmp ne X, 1)) --> false
+// icmp ne X, (zext (icmp ne X, 1)) --> true
+return replaceInstUsesWith(
+I,
+Constant::getIntegerValue(
+I.getType(),
+APInt(1U, static_cast(Pred1 == ICmpInst::ICMP_NE;
+  } else {
+// icmp eq X, (zext (icmp eq X, 1)) --> icmp ult X, 2
+// icmp ne X, (zext (icmp eq X, 1)) --> icmp ugt X, 1
+return ICmpInst::Create(
+Instruction::ICmp,
+Pred1 == ICmpInst::ICMP_NE ? ICmpInst::ICMP_UGT
+   : ICmpInst::ICMP_ULT,
+X,
+Constant::getIntegerValue(
+X->getType(), APInt(X->getType()->getScalarSizeInBits(),
+Pred1 == ICmpInst::ICMP_NE ? 1 : 2)));
+  }
+} else {
+  // C != 0 && C != 1
+  // icmp eq X, (zext (icmp eq X, C)) --> icmp eq X, 0
+  // icmp eq X, (zext (icmp ne X, C)) --> icmp eq X, 1
+  // icmp ne X, (zext (icmp eq X, C)) --> icmp ne X, 0
+  // icmp ne X, (zext (icmp ne X, C)) --> icmp ne X, 1
+  return ICmpInst::Create(
+  Instruction::ICmp, Pred1, X,
+  Constant::getIntegerValue(
+  X->getType(),
+  APInt(X->getType()->getScalarSizeInBits(),
+static_cast(Pred2 == ICmpInst::ICMP_NE;
+}
+  }
+
   if (match(I.getOperand(0), m_c_Add(m_ZExt(m_Value(X)), m_SExt(m_Value(Y 
&&
   match(I.getOperand(1), m_APInt(C)) &&
   X->getType()->isIntOrIntVectorTy(1) &&
diff --git a/llvm/test/Transforms/InstCombine/icmp-range.ll 
b/llvm/test/Transforms/InstCombine/icmp-range.ll
index 4281e09cb0309c8..15424fce33fdeea 100644
--- a/llvm/test/Transforms/InstCombine/icmp-range.ll
+++ b/llvm/test/Transforms/InstCombine/icmp-range.ll
@@ -1034,6 +1034,187 @@ define i1 @icmp_ne_bool_1(ptr %ptr) {
   ret i1 %cmp
 }
 
+define i1 @icmp_ne_zext_eq_zero(i32 %a) {
+; CHECK-LABEL: @icmp_ne_zext_eq_zero(
+; CHECK-NEXT:ret i1 true
+;
+  %cmp = icmp eq i32 %a, 0
+  %conv = zext i1 %cmp to i32
+  %cmp1 = icmp ne i32 %conv, %a
+  ret i1 %cmp1
+}
+
+define i1 @icmp_ne_zext_ne_zero(i32 %a) {
+; CHECK-LABEL: @icmp_ne_zext_ne_zero(
+; CHECK-NEXT:[[CMP1:%.*]] = icmp ugt i32 [[A:%.*]], 1
+; CHECK-NEXT:ret i1 [[CMP1]]
+;
+  %cmp = icmp ne i32 %a, 0
+  %conv = zext i1 %cmp to i32
+  %cmp1 = icmp ne i32 %conv, %a
+  ret i1 %cmp1
+}
+
+define i1 @icmp_eq_zext_eq_zero(i32 %a) {
+; CHECK-LABEL: @icmp_eq_zext_eq_zero(
+; CHECK-NEXT:ret i1 false
+;
+  %cmp = icmp eq i32 %a, 0
+  %conv = zext i1 %cmp to i32
+  %cmp1 = icmp eq i32 %conv, %a
+  ret i1 %cmp1
+}
+
+define i1 @icmp_eq_zext_ne_zero(i32 %a) 

[clang] [InstCombine] Simplify the pattern `a ne/eq (zext/sext (a ne/eq c))` (PR #65852)

2023-10-01 Thread Yingwei Zheng via cfe-commits

https://github.com/dtcxzyw updated 
https://github.com/llvm/llvm-project/pull/65852

>From d9d8bcbb98e8f5aecb9733329389d61a489bd731 Mon Sep 17 00:00:00 2001
From: Yingwei Zheng 
Date: Sat, 9 Sep 2023 23:07:29 +0800
Subject: [PATCH 1/9] [InstCombine] Simplify the pattern `a ne/eq (zext (a
 ne/eq c))`

---
 .../InstCombine/InstCombineCompares.cpp   |  62 ++
 .../test/Transforms/InstCombine/icmp-range.ll | 181 ++
 2 files changed, 243 insertions(+)

diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp 
b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
index 9fdc46fec631679..837b8e6d2619989 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
@@ -6309,7 +6309,69 @@ Instruction 
*InstCombinerImpl::foldICmpUsingBoolRange(ICmpInst ) {
   Y->getType()->isIntOrIntVectorTy(1) && Pred == ICmpInst::ICMP_ULE)
 return BinaryOperator::CreateOr(Builder.CreateIsNull(X), Y);
 
+  ICmpInst::Predicate Pred1, Pred2;
   const APInt *C;
+  // icmp eq/ne X, (zext (icmp eq/ne X, C))
+  if (match(, m_c_ICmp(Pred1, m_Value(X),
+ m_ZExt(m_ICmp(Pred2, m_Deferred(X), m_APInt(C) &&
+  ICmpInst::isEquality(Pred1) && ICmpInst::isEquality(Pred2)) {
+if (C->isZero()) {
+  if (Pred2 == ICmpInst::ICMP_EQ) {
+// icmp eq X, (zext (icmp eq X, 0)) --> false
+// icmp ne X, (zext (icmp eq X, 0)) --> true
+return replaceInstUsesWith(
+I,
+Constant::getIntegerValue(
+I.getType(),
+APInt(1U, static_cast(Pred1 == ICmpInst::ICMP_NE;
+  } else {
+// icmp eq X, (zext (icmp ne X, 0)) --> icmp ult X, 2
+// icmp ne X, (zext (icmp ne X, 0)) --> icmp ugt X, 1
+return ICmpInst::Create(
+Instruction::ICmp,
+Pred1 == ICmpInst::ICMP_NE ? ICmpInst::ICMP_UGT
+   : ICmpInst::ICMP_ULT,
+X,
+Constant::getIntegerValue(
+X->getType(), APInt(X->getType()->getScalarSizeInBits(),
+Pred1 == ICmpInst::ICMP_NE ? 1 : 2)));
+  }
+} else if (C->isOne()) {
+  if (Pred2 == ICmpInst::ICMP_NE) {
+// icmp eq X, (zext (icmp ne X, 1)) --> false
+// icmp ne X, (zext (icmp ne X, 1)) --> true
+return replaceInstUsesWith(
+I,
+Constant::getIntegerValue(
+I.getType(),
+APInt(1U, static_cast(Pred1 == ICmpInst::ICMP_NE;
+  } else {
+// icmp eq X, (zext (icmp eq X, 1)) --> icmp ult X, 2
+// icmp ne X, (zext (icmp eq X, 1)) --> icmp ugt X, 1
+return ICmpInst::Create(
+Instruction::ICmp,
+Pred1 == ICmpInst::ICMP_NE ? ICmpInst::ICMP_UGT
+   : ICmpInst::ICMP_ULT,
+X,
+Constant::getIntegerValue(
+X->getType(), APInt(X->getType()->getScalarSizeInBits(),
+Pred1 == ICmpInst::ICMP_NE ? 1 : 2)));
+  }
+} else {
+  // C != 0 && C != 1
+  // icmp eq X, (zext (icmp eq X, C)) --> icmp eq X, 0
+  // icmp eq X, (zext (icmp ne X, C)) --> icmp eq X, 1
+  // icmp ne X, (zext (icmp eq X, C)) --> icmp ne X, 0
+  // icmp ne X, (zext (icmp ne X, C)) --> icmp ne X, 1
+  return ICmpInst::Create(
+  Instruction::ICmp, Pred1, X,
+  Constant::getIntegerValue(
+  X->getType(),
+  APInt(X->getType()->getScalarSizeInBits(),
+static_cast(Pred2 == ICmpInst::ICMP_NE;
+}
+  }
+
   if (match(I.getOperand(0), m_c_Add(m_ZExt(m_Value(X)), m_SExt(m_Value(Y 
&&
   match(I.getOperand(1), m_APInt(C)) &&
   X->getType()->isIntOrIntVectorTy(1) &&
diff --git a/llvm/test/Transforms/InstCombine/icmp-range.ll 
b/llvm/test/Transforms/InstCombine/icmp-range.ll
index 4281e09cb0309c8..15424fce33fdeea 100644
--- a/llvm/test/Transforms/InstCombine/icmp-range.ll
+++ b/llvm/test/Transforms/InstCombine/icmp-range.ll
@@ -1034,6 +1034,187 @@ define i1 @icmp_ne_bool_1(ptr %ptr) {
   ret i1 %cmp
 }
 
+define i1 @icmp_ne_zext_eq_zero(i32 %a) {
+; CHECK-LABEL: @icmp_ne_zext_eq_zero(
+; CHECK-NEXT:ret i1 true
+;
+  %cmp = icmp eq i32 %a, 0
+  %conv = zext i1 %cmp to i32
+  %cmp1 = icmp ne i32 %conv, %a
+  ret i1 %cmp1
+}
+
+define i1 @icmp_ne_zext_ne_zero(i32 %a) {
+; CHECK-LABEL: @icmp_ne_zext_ne_zero(
+; CHECK-NEXT:[[CMP1:%.*]] = icmp ugt i32 [[A:%.*]], 1
+; CHECK-NEXT:ret i1 [[CMP1]]
+;
+  %cmp = icmp ne i32 %a, 0
+  %conv = zext i1 %cmp to i32
+  %cmp1 = icmp ne i32 %conv, %a
+  ret i1 %cmp1
+}
+
+define i1 @icmp_eq_zext_eq_zero(i32 %a) {
+; CHECK-LABEL: @icmp_eq_zext_eq_zero(
+; CHECK-NEXT:ret i1 false
+;
+  %cmp = icmp eq i32 %a, 0
+  %conv = zext i1 %cmp to i32
+  %cmp1 = icmp eq i32 %conv, %a
+  ret i1 %cmp1
+}
+
+define i1 @icmp_eq_zext_ne_zero(i32 %a) 

[clang-tools-extra] [InstCombine] Simplify the pattern `a ne/eq (zext/sext (a ne/eq c))` (PR #65852)

2023-10-01 Thread Yingwei Zheng via cfe-commits

https://github.com/dtcxzyw updated 
https://github.com/llvm/llvm-project/pull/65852

>From d9d8bcbb98e8f5aecb9733329389d61a489bd731 Mon Sep 17 00:00:00 2001
From: Yingwei Zheng 
Date: Sat, 9 Sep 2023 23:07:29 +0800
Subject: [PATCH 1/9] [InstCombine] Simplify the pattern `a ne/eq (zext (a
 ne/eq c))`

---
 .../InstCombine/InstCombineCompares.cpp   |  62 ++
 .../test/Transforms/InstCombine/icmp-range.ll | 181 ++
 2 files changed, 243 insertions(+)

diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp 
b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
index 9fdc46fec631679..837b8e6d2619989 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
@@ -6309,7 +6309,69 @@ Instruction 
*InstCombinerImpl::foldICmpUsingBoolRange(ICmpInst ) {
   Y->getType()->isIntOrIntVectorTy(1) && Pred == ICmpInst::ICMP_ULE)
 return BinaryOperator::CreateOr(Builder.CreateIsNull(X), Y);
 
+  ICmpInst::Predicate Pred1, Pred2;
   const APInt *C;
+  // icmp eq/ne X, (zext (icmp eq/ne X, C))
+  if (match(, m_c_ICmp(Pred1, m_Value(X),
+ m_ZExt(m_ICmp(Pred2, m_Deferred(X), m_APInt(C) &&
+  ICmpInst::isEquality(Pred1) && ICmpInst::isEquality(Pred2)) {
+if (C->isZero()) {
+  if (Pred2 == ICmpInst::ICMP_EQ) {
+// icmp eq X, (zext (icmp eq X, 0)) --> false
+// icmp ne X, (zext (icmp eq X, 0)) --> true
+return replaceInstUsesWith(
+I,
+Constant::getIntegerValue(
+I.getType(),
+APInt(1U, static_cast(Pred1 == ICmpInst::ICMP_NE;
+  } else {
+// icmp eq X, (zext (icmp ne X, 0)) --> icmp ult X, 2
+// icmp ne X, (zext (icmp ne X, 0)) --> icmp ugt X, 1
+return ICmpInst::Create(
+Instruction::ICmp,
+Pred1 == ICmpInst::ICMP_NE ? ICmpInst::ICMP_UGT
+   : ICmpInst::ICMP_ULT,
+X,
+Constant::getIntegerValue(
+X->getType(), APInt(X->getType()->getScalarSizeInBits(),
+Pred1 == ICmpInst::ICMP_NE ? 1 : 2)));
+  }
+} else if (C->isOne()) {
+  if (Pred2 == ICmpInst::ICMP_NE) {
+// icmp eq X, (zext (icmp ne X, 1)) --> false
+// icmp ne X, (zext (icmp ne X, 1)) --> true
+return replaceInstUsesWith(
+I,
+Constant::getIntegerValue(
+I.getType(),
+APInt(1U, static_cast(Pred1 == ICmpInst::ICMP_NE;
+  } else {
+// icmp eq X, (zext (icmp eq X, 1)) --> icmp ult X, 2
+// icmp ne X, (zext (icmp eq X, 1)) --> icmp ugt X, 1
+return ICmpInst::Create(
+Instruction::ICmp,
+Pred1 == ICmpInst::ICMP_NE ? ICmpInst::ICMP_UGT
+   : ICmpInst::ICMP_ULT,
+X,
+Constant::getIntegerValue(
+X->getType(), APInt(X->getType()->getScalarSizeInBits(),
+Pred1 == ICmpInst::ICMP_NE ? 1 : 2)));
+  }
+} else {
+  // C != 0 && C != 1
+  // icmp eq X, (zext (icmp eq X, C)) --> icmp eq X, 0
+  // icmp eq X, (zext (icmp ne X, C)) --> icmp eq X, 1
+  // icmp ne X, (zext (icmp eq X, C)) --> icmp ne X, 0
+  // icmp ne X, (zext (icmp ne X, C)) --> icmp ne X, 1
+  return ICmpInst::Create(
+  Instruction::ICmp, Pred1, X,
+  Constant::getIntegerValue(
+  X->getType(),
+  APInt(X->getType()->getScalarSizeInBits(),
+static_cast(Pred2 == ICmpInst::ICMP_NE;
+}
+  }
+
   if (match(I.getOperand(0), m_c_Add(m_ZExt(m_Value(X)), m_SExt(m_Value(Y 
&&
   match(I.getOperand(1), m_APInt(C)) &&
   X->getType()->isIntOrIntVectorTy(1) &&
diff --git a/llvm/test/Transforms/InstCombine/icmp-range.ll 
b/llvm/test/Transforms/InstCombine/icmp-range.ll
index 4281e09cb0309c8..15424fce33fdeea 100644
--- a/llvm/test/Transforms/InstCombine/icmp-range.ll
+++ b/llvm/test/Transforms/InstCombine/icmp-range.ll
@@ -1034,6 +1034,187 @@ define i1 @icmp_ne_bool_1(ptr %ptr) {
   ret i1 %cmp
 }
 
+define i1 @icmp_ne_zext_eq_zero(i32 %a) {
+; CHECK-LABEL: @icmp_ne_zext_eq_zero(
+; CHECK-NEXT:ret i1 true
+;
+  %cmp = icmp eq i32 %a, 0
+  %conv = zext i1 %cmp to i32
+  %cmp1 = icmp ne i32 %conv, %a
+  ret i1 %cmp1
+}
+
+define i1 @icmp_ne_zext_ne_zero(i32 %a) {
+; CHECK-LABEL: @icmp_ne_zext_ne_zero(
+; CHECK-NEXT:[[CMP1:%.*]] = icmp ugt i32 [[A:%.*]], 1
+; CHECK-NEXT:ret i1 [[CMP1]]
+;
+  %cmp = icmp ne i32 %a, 0
+  %conv = zext i1 %cmp to i32
+  %cmp1 = icmp ne i32 %conv, %a
+  ret i1 %cmp1
+}
+
+define i1 @icmp_eq_zext_eq_zero(i32 %a) {
+; CHECK-LABEL: @icmp_eq_zext_eq_zero(
+; CHECK-NEXT:ret i1 false
+;
+  %cmp = icmp eq i32 %a, 0
+  %conv = zext i1 %cmp to i32
+  %cmp1 = icmp eq i32 %conv, %a
+  ret i1 %cmp1
+}
+
+define i1 @icmp_eq_zext_ne_zero(i32 %a) 

[clang] [InstCombine] Simplify the pattern `a ne/eq (zext/sext (a ne/eq c))` (PR #65852)

2023-10-01 Thread Yingwei Zheng via cfe-commits

https://github.com/dtcxzyw updated 
https://github.com/llvm/llvm-project/pull/65852

>From d9d8bcbb98e8f5aecb9733329389d61a489bd731 Mon Sep 17 00:00:00 2001
From: Yingwei Zheng 
Date: Sat, 9 Sep 2023 23:07:29 +0800
Subject: [PATCH 1/9] [InstCombine] Simplify the pattern `a ne/eq (zext (a
 ne/eq c))`

---
 .../InstCombine/InstCombineCompares.cpp   |  62 ++
 .../test/Transforms/InstCombine/icmp-range.ll | 181 ++
 2 files changed, 243 insertions(+)

diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp 
b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
index 9fdc46fec631679..837b8e6d2619989 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
@@ -6309,7 +6309,69 @@ Instruction 
*InstCombinerImpl::foldICmpUsingBoolRange(ICmpInst ) {
   Y->getType()->isIntOrIntVectorTy(1) && Pred == ICmpInst::ICMP_ULE)
 return BinaryOperator::CreateOr(Builder.CreateIsNull(X), Y);
 
+  ICmpInst::Predicate Pred1, Pred2;
   const APInt *C;
+  // icmp eq/ne X, (zext (icmp eq/ne X, C))
+  if (match(, m_c_ICmp(Pred1, m_Value(X),
+ m_ZExt(m_ICmp(Pred2, m_Deferred(X), m_APInt(C) &&
+  ICmpInst::isEquality(Pred1) && ICmpInst::isEquality(Pred2)) {
+if (C->isZero()) {
+  if (Pred2 == ICmpInst::ICMP_EQ) {
+// icmp eq X, (zext (icmp eq X, 0)) --> false
+// icmp ne X, (zext (icmp eq X, 0)) --> true
+return replaceInstUsesWith(
+I,
+Constant::getIntegerValue(
+I.getType(),
+APInt(1U, static_cast(Pred1 == ICmpInst::ICMP_NE;
+  } else {
+// icmp eq X, (zext (icmp ne X, 0)) --> icmp ult X, 2
+// icmp ne X, (zext (icmp ne X, 0)) --> icmp ugt X, 1
+return ICmpInst::Create(
+Instruction::ICmp,
+Pred1 == ICmpInst::ICMP_NE ? ICmpInst::ICMP_UGT
+   : ICmpInst::ICMP_ULT,
+X,
+Constant::getIntegerValue(
+X->getType(), APInt(X->getType()->getScalarSizeInBits(),
+Pred1 == ICmpInst::ICMP_NE ? 1 : 2)));
+  }
+} else if (C->isOne()) {
+  if (Pred2 == ICmpInst::ICMP_NE) {
+// icmp eq X, (zext (icmp ne X, 1)) --> false
+// icmp ne X, (zext (icmp ne X, 1)) --> true
+return replaceInstUsesWith(
+I,
+Constant::getIntegerValue(
+I.getType(),
+APInt(1U, static_cast(Pred1 == ICmpInst::ICMP_NE;
+  } else {
+// icmp eq X, (zext (icmp eq X, 1)) --> icmp ult X, 2
+// icmp ne X, (zext (icmp eq X, 1)) --> icmp ugt X, 1
+return ICmpInst::Create(
+Instruction::ICmp,
+Pred1 == ICmpInst::ICMP_NE ? ICmpInst::ICMP_UGT
+   : ICmpInst::ICMP_ULT,
+X,
+Constant::getIntegerValue(
+X->getType(), APInt(X->getType()->getScalarSizeInBits(),
+Pred1 == ICmpInst::ICMP_NE ? 1 : 2)));
+  }
+} else {
+  // C != 0 && C != 1
+  // icmp eq X, (zext (icmp eq X, C)) --> icmp eq X, 0
+  // icmp eq X, (zext (icmp ne X, C)) --> icmp eq X, 1
+  // icmp ne X, (zext (icmp eq X, C)) --> icmp ne X, 0
+  // icmp ne X, (zext (icmp ne X, C)) --> icmp ne X, 1
+  return ICmpInst::Create(
+  Instruction::ICmp, Pred1, X,
+  Constant::getIntegerValue(
+  X->getType(),
+  APInt(X->getType()->getScalarSizeInBits(),
+static_cast(Pred2 == ICmpInst::ICMP_NE;
+}
+  }
+
   if (match(I.getOperand(0), m_c_Add(m_ZExt(m_Value(X)), m_SExt(m_Value(Y 
&&
   match(I.getOperand(1), m_APInt(C)) &&
   X->getType()->isIntOrIntVectorTy(1) &&
diff --git a/llvm/test/Transforms/InstCombine/icmp-range.ll 
b/llvm/test/Transforms/InstCombine/icmp-range.ll
index 4281e09cb0309c8..15424fce33fdeea 100644
--- a/llvm/test/Transforms/InstCombine/icmp-range.ll
+++ b/llvm/test/Transforms/InstCombine/icmp-range.ll
@@ -1034,6 +1034,187 @@ define i1 @icmp_ne_bool_1(ptr %ptr) {
   ret i1 %cmp
 }
 
+define i1 @icmp_ne_zext_eq_zero(i32 %a) {
+; CHECK-LABEL: @icmp_ne_zext_eq_zero(
+; CHECK-NEXT:ret i1 true
+;
+  %cmp = icmp eq i32 %a, 0
+  %conv = zext i1 %cmp to i32
+  %cmp1 = icmp ne i32 %conv, %a
+  ret i1 %cmp1
+}
+
+define i1 @icmp_ne_zext_ne_zero(i32 %a) {
+; CHECK-LABEL: @icmp_ne_zext_ne_zero(
+; CHECK-NEXT:[[CMP1:%.*]] = icmp ugt i32 [[A:%.*]], 1
+; CHECK-NEXT:ret i1 [[CMP1]]
+;
+  %cmp = icmp ne i32 %a, 0
+  %conv = zext i1 %cmp to i32
+  %cmp1 = icmp ne i32 %conv, %a
+  ret i1 %cmp1
+}
+
+define i1 @icmp_eq_zext_eq_zero(i32 %a) {
+; CHECK-LABEL: @icmp_eq_zext_eq_zero(
+; CHECK-NEXT:ret i1 false
+;
+  %cmp = icmp eq i32 %a, 0
+  %conv = zext i1 %cmp to i32
+  %cmp1 = icmp eq i32 %conv, %a
+  ret i1 %cmp1
+}
+
+define i1 @icmp_eq_zext_ne_zero(i32 %a) 

[clang] [InstCombine] Simplify the pattern `a ne/eq (zext/sext (a ne/eq c))` (PR #65852)

2023-10-01 Thread Yingwei Zheng via cfe-commits


@@ -6380,7 +6380,71 @@ Instruction 
*InstCombinerImpl::foldICmpUsingBoolRange(ICmpInst ) {
   Y->getType()->isIntOrIntVectorTy(1) && Pred == ICmpInst::ICMP_ULE)
 return BinaryOperator::CreateOr(Builder.CreateIsNull(X), Y);
 
+  // icmp eq/ne X, (zext/sext (icmp eq/ne X, C))
+  ICmpInst::Predicate Pred1, Pred2;
   const APInt *C;
+  Instruction *ExtI;
+  if (match(, m_c_ICmp(Pred1, m_Value(X),
+ m_CombineAnd(m_Instruction(ExtI),
+  m_ZExtOrSExt(m_ICmp(Pred2, m_Deferred(X),
+  m_APInt(C))) {

dtcxzyw wrote:

Sorry, I accidentally dropped the checks in 
70a70fb44d0e628a1cf485e1767ada3eaaa26b0f.

https://github.com/llvm/llvm-project/pull/65852
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [RISCV] Eliminate dead li after emitting VSETVLIs (PR #65934)

2023-10-01 Thread Yingwei Zheng via cfe-commits

https://github.com/dtcxzyw updated 
https://github.com/llvm/llvm-project/pull/65934

>From 2fe5756dd4d49580d3a23b0ff1b72535f725915e Mon Sep 17 00:00:00 2001
From: Yingwei Zheng 
Date: Mon, 11 Sep 2023 15:51:46 +0800
Subject: [PATCH 1/4] [RISCV] Eliminate dead li after emitting VSETVLIs

---
 llvm/lib/Target/RISCV/RISCVInsertVSETVLI.cpp  | 22 ++---
 .../RISCV/rvv/fixed-vectors-masked-gather.ll  | 24 ---
 2 files changed, 19 insertions(+), 27 deletions(-)

diff --git a/llvm/lib/Target/RISCV/RISCVInsertVSETVLI.cpp 
b/llvm/lib/Target/RISCV/RISCVInsertVSETVLI.cpp
index b42ad269c18de6f..918c96beb29afca 100644
--- a/llvm/lib/Target/RISCV/RISCVInsertVSETVLI.cpp
+++ b/llvm/lib/Target/RISCV/RISCVInsertVSETVLI.cpp
@@ -757,7 +757,8 @@ class RISCVInsertVSETVLI : public MachineFunctionPass {
   bool computeVLVTYPEChanges(const MachineBasicBlock ,
  VSETVLIInfo ) const;
   void computeIncomingVLVTYPE(const MachineBasicBlock );
-  void emitVSETVLIs(MachineBasicBlock );
+  void emitVSETVLIs(MachineBasicBlock ,
+SmallVectorImpl );
   void doLocalPostpass(MachineBasicBlock );
   void doPRE(MachineBasicBlock );
   void insertReadVL(MachineBasicBlock );
@@ -1216,7 +1217,8 @@ bool RISCVInsertVSETVLI::needVSETVLIPHI(const VSETVLIInfo 
,
   return false;
 }
 
-void RISCVInsertVSETVLI::emitVSETVLIs(MachineBasicBlock ) {
+void RISCVInsertVSETVLI::emitVSETVLIs(
+MachineBasicBlock , SmallVectorImpl ) {
   VSETVLIInfo CurInfo = BlockInfo[MBB.getNumber()].Pred;
   // Track whether the prefix of the block we've scanned is transparent
   // (meaning has not yet changed the abstract state).
@@ -1255,6 +1257,13 @@ void RISCVInsertVSETVLI::emitVSETVLIs(MachineBasicBlock 
) {
 MachineOperand  = MI.getOperand(getVLOpNum(MI));
 if (VLOp.isReg()) {
   // Erase the AVL operand from the instruction.
+  if (MachineInstr *MI = MRI->getVRegDef(VLOp.getReg());
+  MI && MI->getOpcode() == RISCV::ADDI &&
+  MI->getOperand(1).isReg() && MI->getOperand(2).isImm() &&
+  MI->getOperand(1).getReg() == RISCV::X0 &&
+  MI->getOperand(2).getImm() != 0)
+DeadVLInstrs.push_back(MI);
+
   VLOp.setReg(RISCV::NoRegister);
   VLOp.setIsKill(false);
 }
@@ -1580,8 +1589,9 @@ bool 
RISCVInsertVSETVLI::runOnMachineFunction(MachineFunction ) {
   // Phase 2 information to avoid adding vsetvlis before the first vector
   // instruction in the block if the VL/VTYPE is satisfied by its
   // predecessors.
+  SmallVector DeadVLInstrs;
   for (MachineBasicBlock  : MF)
-emitVSETVLIs(MBB);
+emitVSETVLIs(MBB, DeadVLInstrs);
 
   // Now that all vsetvlis are explicit, go through and do block local
   // DSE and peephole based demanded fields based transforms.  Note that
@@ -1592,6 +1602,12 @@ bool 
RISCVInsertVSETVLI::runOnMachineFunction(MachineFunction ) {
   for (MachineBasicBlock  : MF)
 doLocalPostpass(MBB);
 
+  // Remove dead LI instructions that set VL.
+  for (MachineInstr *MI : DeadVLInstrs) {
+if (MRI->use_nodbg_empty(MI->getOperand(0).getReg()))
+  MI->eraseFromParent();
+  }
+
   // Once we're fully done rewriting all the instructions, do a final pass
   // through to check for VSETVLIs which write to an unused destination.
   // For the non X0, X0 variant, we can replace the destination register
diff --git a/llvm/test/CodeGen/RISCV/rvv/fixed-vectors-masked-gather.ll 
b/llvm/test/CodeGen/RISCV/rvv/fixed-vectors-masked-gather.ll
index f7352b4659e5a9b..0d306775528ed86 100644
--- a/llvm/test/CodeGen/RISCV/rvv/fixed-vectors-masked-gather.ll
+++ b/llvm/test/CodeGen/RISCV/rvv/fixed-vectors-masked-gather.ll
@@ -12393,7 +12393,6 @@ define <32 x i8> @mgather_baseidx_v32i8(ptr %base, <32 
x i8> %idxs, <32 x i1> %m
 ; RV64ZVE32F-NEXT:vmv.x.s a2, v12
 ; RV64ZVE32F-NEXT:add a2, a0, a2
 ; RV64ZVE32F-NEXT:lbu a2, 0(a2)
-; RV64ZVE32F-NEXT:li a3, 32
 ; RV64ZVE32F-NEXT:vmv.s.x v12, a2
 ; RV64ZVE32F-NEXT:vsetivli zero, 2, e8, m2, tu, ma
 ; RV64ZVE32F-NEXT:vslideup.vi v10, v12, 1
@@ -12431,7 +12430,6 @@ define <32 x i8> @mgather_baseidx_v32i8(ptr %base, <32 
x i8> %idxs, <32 x i1> %m
 ; RV64ZVE32F-NEXT:vmv.x.s a2, v14
 ; RV64ZVE32F-NEXT:add a2, a0, a2
 ; RV64ZVE32F-NEXT:lbu a2, 0(a2)
-; RV64ZVE32F-NEXT:li a3, 32
 ; RV64ZVE32F-NEXT:vmv.s.x v14, a2
 ; RV64ZVE32F-NEXT:vsetivli zero, 6, e8, m2, tu, ma
 ; RV64ZVE32F-NEXT:vslideup.vi v10, v14, 5
@@ -12455,7 +12453,6 @@ define <32 x i8> @mgather_baseidx_v32i8(ptr %base, <32 
x i8> %idxs, <32 x i1> %m
 ; RV64ZVE32F-NEXT:vmv.x.s a2, v13
 ; RV64ZVE32F-NEXT:add a2, a0, a2
 ; RV64ZVE32F-NEXT:lbu a2, 0(a2)
-; RV64ZVE32F-NEXT:li a3, 32
 ; RV64ZVE32F-NEXT:vmv.s.x v14, a2
 ; RV64ZVE32F-NEXT:vsetivli zero, 10, e8, m2, tu, ma
 ; RV64ZVE32F-NEXT:vslideup.vi v10, v14, 9
@@ -12470,7 +12467,6 @@ define <32 x i8> @mgather_baseidx_v32i8(ptr %base, <32 
x i8> 

[clang-tools-extra] [InstCombine] Simplify the pattern `a ne/eq (zext/sext (a ne/eq c))` (PR #65852)

2023-09-30 Thread Yingwei Zheng via cfe-commits

dtcxzyw wrote:

Ping.

https://github.com/llvm/llvm-project/pull/65852
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [InstCombine] Canonicalize `and(zext(A), B)` into `select A, B & 1, 0` (PR #66740)

2023-09-28 Thread Yingwei Zheng via cfe-commits

https://github.com/dtcxzyw closed 
https://github.com/llvm/llvm-project/pull/66740
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang-tools-extra] [InstCombine] Canonicalize `and(zext(A), B)` into `select A, B & 1, 0` (PR #66740)

2023-09-28 Thread Yingwei Zheng via cfe-commits

https://github.com/dtcxzyw closed 
https://github.com/llvm/llvm-project/pull/66740
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang-tools-extra] [ValueTracking] Simplify uaddo pattern (PR #65910)

2023-09-28 Thread Yingwei Zheng via cfe-commits

https://github.com/dtcxzyw closed 
https://github.com/llvm/llvm-project/pull/65910
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [InstCombine] Canonicalize `and(zext(A), B)` into `select A, B & 1, 0` (PR #66740)

2023-09-28 Thread Yingwei Zheng via cfe-commits

https://github.com/dtcxzyw updated 
https://github.com/llvm/llvm-project/pull/66740

>From 85f7911dfe0f1e9112881a9f503bcd68edfde580 Mon Sep 17 00:00:00 2001
From: Yingwei Zheng 
Date: Tue, 19 Sep 2023 10:19:46 +0800
Subject: [PATCH 1/3] [InstCombine] Canonicalize `and(zext(A), B)` into `select
 A, B & 1, 0`

---
 .../InstCombine/InstCombineAndOrXor.cpp   |  6 
 .../Transforms/InstCombine/and-or-icmps.ll| 12 +++
 llvm/test/Transforms/InstCombine/icmp.ll  | 31 ++-
 llvm/test/Transforms/InstCombine/narrow.ll|  3 +-
 .../Transforms/InstCombine/zext-or-icmp.ll| 10 +++---
 5 files changed, 33 insertions(+), 29 deletions(-)

diff --git a/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp 
b/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
index ca7dfa82ab5a5d7..7fa432e1fdc1790 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
@@ -2654,6 +2654,12 @@ Instruction *InstCombinerImpl::visitAnd(BinaryOperator 
) {
   A->getType()->isIntOrIntVectorTy(1))
 return SelectInst::Create(A, Constant::getNullValue(Ty), B);
 
+  // and(zext(A), B) -> A ? (B & 1) : 0
+  if (match(, m_c_And(m_OneUse(m_ZExt(m_Value(A))), m_Value(B))) &&
+  A->getType()->isIntOrIntVectorTy(1))
+return SelectInst::Create(A, Builder.CreateAnd(B, ConstantInt::get(Ty, 1)),
+  Constant::getNullValue(Ty));
+
   // (iN X s>> (N-1)) & Y --> (X s< 0) ? Y : 0 -- with optional sext
   if (match(, m_c_And(m_OneUse(m_SExtOrSelf(
 m_AShr(m_Value(X), m_APIntAllowUndef(C,
diff --git a/llvm/test/Transforms/InstCombine/and-or-icmps.ll 
b/llvm/test/Transforms/InstCombine/and-or-icmps.ll
index 065dbf261e131bf..881a9b7ff129dbb 100644
--- a/llvm/test/Transforms/InstCombine/and-or-icmps.ll
+++ b/llvm/test/Transforms/InstCombine/and-or-icmps.ll
@@ -2769,9 +2769,9 @@ define i64 @icmp_slt_0_and_icmp_sgt_neg1_i64(i64 %x) {
 define i64 @icmp_slt_0_and_icmp_sge_neg1_i64_fail(i64 %x) {
 ; CHECK-LABEL: @icmp_slt_0_and_icmp_sge_neg1_i64_fail(
 ; CHECK-NEXT:[[A:%.*]] = icmp sgt i64 [[X:%.*]], -2
-; CHECK-NEXT:[[B:%.*]] = zext i1 [[A]] to i64
 ; CHECK-NEXT:[[C:%.*]] = lshr i64 [[X]], 62
-; CHECK-NEXT:[[D:%.*]] = and i64 [[C]], [[B]]
+; CHECK-NEXT:[[TMP1:%.*]] = and i64 [[C]], 1
+; CHECK-NEXT:[[D:%.*]] = select i1 [[A]], i64 [[TMP1]], i64 0
 ; CHECK-NEXT:ret i64 [[D]]
 ;
   %A = icmp sge i64 %x, -1
@@ -2871,9 +2871,8 @@ define i32 
@icmp_slt_0_and_icmp_sge_neg2_i32_multiuse1(i32 %x) {
 define i32 @icmp_slt_0_and_icmp_sge_neg2_i32_multiuse2(i32 %x) {
 ; CHECK-LABEL: @icmp_slt_0_and_icmp_sge_neg2_i32_multiuse2(
 ; CHECK-NEXT:[[A:%.*]] = icmp sgt i32 [[X:%.*]], -3
-; CHECK-NEXT:[[B:%.*]] = zext i1 [[A]] to i32
 ; CHECK-NEXT:[[C:%.*]] = lshr i32 [[X]], 31
-; CHECK-NEXT:[[D:%.*]] = and i32 [[C]], [[B]]
+; CHECK-NEXT:[[D:%.*]] = select i1 [[A]], i32 [[C]], i32 0
 ; CHECK-NEXT:call void @use32(i32 [[C]])
 ; CHECK-NEXT:ret i32 [[D]]
 ;
@@ -2923,10 +2922,9 @@ define i32 
@icmp_slt_0_or_icmp_eq_100_i32_multiuse_fail1(i32 %x) {
 
 define i32 @icmp_x_slt_0_and_icmp_y_ne_neg2_i32_multiuse_fail2(i32 %x, i32 %y) 
{
 ; CHECK-LABEL: @icmp_x_slt_0_and_icmp_y_ne_neg2_i32_multiuse_fail2(
-; CHECK-NEXT:[[A:%.*]] = icmp ne i32 [[X:%.*]], -2
-; CHECK-NEXT:[[B:%.*]] = zext i1 [[A]] to i32
+; CHECK-NEXT:[[A_NOT:%.*]] = icmp eq i32 [[X:%.*]], -2
 ; CHECK-NEXT:[[C:%.*]] = lshr i32 [[Y:%.*]], 31
-; CHECK-NEXT:[[D:%.*]] = and i32 [[C]], [[B]]
+; CHECK-NEXT:[[D:%.*]] = select i1 [[A_NOT]], i32 0, i32 [[C]]
 ; CHECK-NEXT:call void @use32(i32 [[C]])
 ; CHECK-NEXT:ret i32 [[D]]
 ;
diff --git a/llvm/test/Transforms/InstCombine/icmp.ll 
b/llvm/test/Transforms/InstCombine/icmp.ll
index 666d85d6cc32103..a5c05278f4232e8 100644
--- a/llvm/test/Transforms/InstCombine/icmp.ll
+++ b/llvm/test/Transforms/InstCombine/icmp.ll
@@ -4441,9 +4441,9 @@ define i1 @redundant_sign_bit_count_ugt_31_30(i32 %x) {
 define i1 @zext_bool_and_eq0(i1 %x, i8 %y) {
 ; CHECK-LABEL: @zext_bool_and_eq0(
 ; CHECK-NEXT:[[TMP1:%.*]] = and i8 [[Y:%.*]], 1
-; CHECK-NEXT:[[TMP2:%.*]] = icmp ne i8 [[TMP1]], 0
-; CHECK-NEXT:[[TMP3:%.*]] = and i1 [[TMP2]], [[X:%.*]]
-; CHECK-NEXT:[[R:%.*]] = xor i1 [[TMP3]], true
+; CHECK-NEXT:[[R1:%.*]] = icmp eq i8 [[TMP1]], 0
+; CHECK-NEXT:[[NOT_X:%.*]] = xor i1 [[X:%.*]], true
+; CHECK-NEXT:[[R:%.*]] = select i1 [[NOT_X]], i1 true, i1 [[R1]]
 ; CHECK-NEXT:ret i1 [[R]]
 ;
   %zx = zext i1 %x to i8
@@ -4454,9 +4454,10 @@ define i1 @zext_bool_and_eq0(i1 %x, i8 %y) {
 
 define <2 x i1> @zext_bool_and_eq0_commute(<2 x i1> %x, <2 x i8> %p) {
 ; CHECK-LABEL: @zext_bool_and_eq0_commute(
-; CHECK-NEXT:[[TMP1:%.*]] = trunc <2 x i8> [[P:%.*]] to <2 x i1>
-; CHECK-NEXT:[[TMP2:%.*]] = and <2 x i1> [[TMP1]], [[X:%.*]]
-; CHECK-NEXT:[[R:%.*]] = xor <2 x i1> [[TMP2]], 
+; CHECK-NEXT:

[clang] [ValueTracking] Simplify uaddo pattern (PR #65910)

2023-09-28 Thread Yingwei Zheng via cfe-commits

https://github.com/dtcxzyw resolved 
https://github.com/llvm/llvm-project/pull/65910
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang-tools-extra] [ValueTracking] Simplify uaddo pattern (PR #65910)

2023-09-28 Thread Yingwei Zheng via cfe-commits

https://github.com/dtcxzyw resolved 
https://github.com/llvm/llvm-project/pull/65910
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [InstCombine] Add combines/simplifications for `llvm.ptrmask` (PR #67166)

2023-09-25 Thread Yingwei Zheng via cfe-commits

https://github.com/dtcxzyw resolved 
https://github.com/llvm/llvm-project/pull/67166
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [InstCombine] Add combines/simplifications for `llvm.ptrmask` (PR #67166)

2023-09-25 Thread Yingwei Zheng via cfe-commits

https://github.com/dtcxzyw resolved 
https://github.com/llvm/llvm-project/pull/67166
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [RISCV] Eliminate dead li after emitting VSETVLIs (PR #65934)

2023-09-24 Thread Yingwei Zheng via cfe-commits

https://github.com/dtcxzyw resolved 
https://github.com/llvm/llvm-project/pull/65934
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang-tools-extra] [RISCV] Eliminate dead li after emitting VSETVLIs (PR #65934)

2023-09-24 Thread Yingwei Zheng via cfe-commits

https://github.com/dtcxzyw resolved 
https://github.com/llvm/llvm-project/pull/65934
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [RISCV] Eliminate dead li after emitting VSETVLIs (PR #65934)

2023-09-24 Thread Yingwei Zheng via cfe-commits

https://github.com/dtcxzyw resolved 
https://github.com/llvm/llvm-project/pull/65934
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang-tools-extra] [RISCV] Eliminate dead li after emitting VSETVLIs (PR #65934)

2023-09-24 Thread Yingwei Zheng via cfe-commits

https://github.com/dtcxzyw resolved 
https://github.com/llvm/llvm-project/pull/65934
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [RISCV] Eliminate dead li after emitting VSETVLIs (PR #65934)

2023-09-24 Thread Yingwei Zheng via cfe-commits


@@ -757,7 +757,8 @@ class RISCVInsertVSETVLI : public MachineFunctionPass {
   bool computeVLVTYPEChanges(const MachineBasicBlock ,
  VSETVLIInfo ) const;
   void computeIncomingVLVTYPE(const MachineBasicBlock );
-  void emitVSETVLIs(MachineBasicBlock );
+  void emitVSETVLIs(MachineBasicBlock ,
+SmallVectorImpl );

dtcxzyw wrote:

I don't think it is a typo.


https://github.com/llvm/llvm-project/pull/65934
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [RISCV] Eliminate dead li after emitting VSETVLIs (PR #65934)

2023-09-24 Thread Yingwei Zheng via cfe-commits

https://github.com/dtcxzyw resolved 
https://github.com/llvm/llvm-project/pull/65934
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang-tools-extra] [RISCV] Eliminate dead li after emitting VSETVLIs (PR #65934)

2023-09-24 Thread Yingwei Zheng via cfe-commits


@@ -757,7 +757,8 @@ class RISCVInsertVSETVLI : public MachineFunctionPass {
   bool computeVLVTYPEChanges(const MachineBasicBlock ,
  VSETVLIInfo ) const;
   void computeIncomingVLVTYPE(const MachineBasicBlock );
-  void emitVSETVLIs(MachineBasicBlock );
+  void emitVSETVLIs(MachineBasicBlock ,
+SmallVectorImpl );

dtcxzyw wrote:

I don't think it is a typo.


https://github.com/llvm/llvm-project/pull/65934
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [RISCV] Eliminate dead li after emitting VSETVLIs (PR #65934)

2023-09-24 Thread Yingwei Zheng via cfe-commits

https://github.com/dtcxzyw resolved 
https://github.com/llvm/llvm-project/pull/65934
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang-tools-extra] [RISCV] Eliminate dead li after emitting VSETVLIs (PR #65934)

2023-09-24 Thread Yingwei Zheng via cfe-commits

https://github.com/dtcxzyw resolved 
https://github.com/llvm/llvm-project/pull/65934
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [RISCV] Eliminate dead li after emitting VSETVLIs (PR #65934)

2023-09-24 Thread Yingwei Zheng via cfe-commits

https://github.com/dtcxzyw updated 
https://github.com/llvm/llvm-project/pull/65934

>From 2fe5756dd4d49580d3a23b0ff1b72535f725915e Mon Sep 17 00:00:00 2001
From: Yingwei Zheng 
Date: Mon, 11 Sep 2023 15:51:46 +0800
Subject: [PATCH 1/4] [RISCV] Eliminate dead li after emitting VSETVLIs

---
 llvm/lib/Target/RISCV/RISCVInsertVSETVLI.cpp  | 22 ++---
 .../RISCV/rvv/fixed-vectors-masked-gather.ll  | 24 ---
 2 files changed, 19 insertions(+), 27 deletions(-)

diff --git a/llvm/lib/Target/RISCV/RISCVInsertVSETVLI.cpp 
b/llvm/lib/Target/RISCV/RISCVInsertVSETVLI.cpp
index b42ad269c18de6f..918c96beb29afca 100644
--- a/llvm/lib/Target/RISCV/RISCVInsertVSETVLI.cpp
+++ b/llvm/lib/Target/RISCV/RISCVInsertVSETVLI.cpp
@@ -757,7 +757,8 @@ class RISCVInsertVSETVLI : public MachineFunctionPass {
   bool computeVLVTYPEChanges(const MachineBasicBlock ,
  VSETVLIInfo ) const;
   void computeIncomingVLVTYPE(const MachineBasicBlock );
-  void emitVSETVLIs(MachineBasicBlock );
+  void emitVSETVLIs(MachineBasicBlock ,
+SmallVectorImpl );
   void doLocalPostpass(MachineBasicBlock );
   void doPRE(MachineBasicBlock );
   void insertReadVL(MachineBasicBlock );
@@ -1216,7 +1217,8 @@ bool RISCVInsertVSETVLI::needVSETVLIPHI(const VSETVLIInfo 
,
   return false;
 }
 
-void RISCVInsertVSETVLI::emitVSETVLIs(MachineBasicBlock ) {
+void RISCVInsertVSETVLI::emitVSETVLIs(
+MachineBasicBlock , SmallVectorImpl ) {
   VSETVLIInfo CurInfo = BlockInfo[MBB.getNumber()].Pred;
   // Track whether the prefix of the block we've scanned is transparent
   // (meaning has not yet changed the abstract state).
@@ -1255,6 +1257,13 @@ void RISCVInsertVSETVLI::emitVSETVLIs(MachineBasicBlock 
) {
 MachineOperand  = MI.getOperand(getVLOpNum(MI));
 if (VLOp.isReg()) {
   // Erase the AVL operand from the instruction.
+  if (MachineInstr *MI = MRI->getVRegDef(VLOp.getReg());
+  MI && MI->getOpcode() == RISCV::ADDI &&
+  MI->getOperand(1).isReg() && MI->getOperand(2).isImm() &&
+  MI->getOperand(1).getReg() == RISCV::X0 &&
+  MI->getOperand(2).getImm() != 0)
+DeadVLInstrs.push_back(MI);
+
   VLOp.setReg(RISCV::NoRegister);
   VLOp.setIsKill(false);
 }
@@ -1580,8 +1589,9 @@ bool 
RISCVInsertVSETVLI::runOnMachineFunction(MachineFunction ) {
   // Phase 2 information to avoid adding vsetvlis before the first vector
   // instruction in the block if the VL/VTYPE is satisfied by its
   // predecessors.
+  SmallVector DeadVLInstrs;
   for (MachineBasicBlock  : MF)
-emitVSETVLIs(MBB);
+emitVSETVLIs(MBB, DeadVLInstrs);
 
   // Now that all vsetvlis are explicit, go through and do block local
   // DSE and peephole based demanded fields based transforms.  Note that
@@ -1592,6 +1602,12 @@ bool 
RISCVInsertVSETVLI::runOnMachineFunction(MachineFunction ) {
   for (MachineBasicBlock  : MF)
 doLocalPostpass(MBB);
 
+  // Remove dead LI instructions that set VL.
+  for (MachineInstr *MI : DeadVLInstrs) {
+if (MRI->use_nodbg_empty(MI->getOperand(0).getReg()))
+  MI->eraseFromParent();
+  }
+
   // Once we're fully done rewriting all the instructions, do a final pass
   // through to check for VSETVLIs which write to an unused destination.
   // For the non X0, X0 variant, we can replace the destination register
diff --git a/llvm/test/CodeGen/RISCV/rvv/fixed-vectors-masked-gather.ll 
b/llvm/test/CodeGen/RISCV/rvv/fixed-vectors-masked-gather.ll
index f7352b4659e5a9b..0d306775528ed86 100644
--- a/llvm/test/CodeGen/RISCV/rvv/fixed-vectors-masked-gather.ll
+++ b/llvm/test/CodeGen/RISCV/rvv/fixed-vectors-masked-gather.ll
@@ -12393,7 +12393,6 @@ define <32 x i8> @mgather_baseidx_v32i8(ptr %base, <32 
x i8> %idxs, <32 x i1> %m
 ; RV64ZVE32F-NEXT:vmv.x.s a2, v12
 ; RV64ZVE32F-NEXT:add a2, a0, a2
 ; RV64ZVE32F-NEXT:lbu a2, 0(a2)
-; RV64ZVE32F-NEXT:li a3, 32
 ; RV64ZVE32F-NEXT:vmv.s.x v12, a2
 ; RV64ZVE32F-NEXT:vsetivli zero, 2, e8, m2, tu, ma
 ; RV64ZVE32F-NEXT:vslideup.vi v10, v12, 1
@@ -12431,7 +12430,6 @@ define <32 x i8> @mgather_baseidx_v32i8(ptr %base, <32 
x i8> %idxs, <32 x i1> %m
 ; RV64ZVE32F-NEXT:vmv.x.s a2, v14
 ; RV64ZVE32F-NEXT:add a2, a0, a2
 ; RV64ZVE32F-NEXT:lbu a2, 0(a2)
-; RV64ZVE32F-NEXT:li a3, 32
 ; RV64ZVE32F-NEXT:vmv.s.x v14, a2
 ; RV64ZVE32F-NEXT:vsetivli zero, 6, e8, m2, tu, ma
 ; RV64ZVE32F-NEXT:vslideup.vi v10, v14, 5
@@ -12455,7 +12453,6 @@ define <32 x i8> @mgather_baseidx_v32i8(ptr %base, <32 
x i8> %idxs, <32 x i1> %m
 ; RV64ZVE32F-NEXT:vmv.x.s a2, v13
 ; RV64ZVE32F-NEXT:add a2, a0, a2
 ; RV64ZVE32F-NEXT:lbu a2, 0(a2)
-; RV64ZVE32F-NEXT:li a3, 32
 ; RV64ZVE32F-NEXT:vmv.s.x v14, a2
 ; RV64ZVE32F-NEXT:vsetivli zero, 10, e8, m2, tu, ma
 ; RV64ZVE32F-NEXT:vslideup.vi v10, v14, 9
@@ -12470,7 +12467,6 @@ define <32 x i8> @mgather_baseidx_v32i8(ptr %base, <32 
x i8> 

[clang-tools-extra] [RISCV] Eliminate dead li after emitting VSETVLIs (PR #65934)

2023-09-24 Thread Yingwei Zheng via cfe-commits

https://github.com/dtcxzyw updated 
https://github.com/llvm/llvm-project/pull/65934

>From 2fe5756dd4d49580d3a23b0ff1b72535f725915e Mon Sep 17 00:00:00 2001
From: Yingwei Zheng 
Date: Mon, 11 Sep 2023 15:51:46 +0800
Subject: [PATCH 1/4] [RISCV] Eliminate dead li after emitting VSETVLIs

---
 llvm/lib/Target/RISCV/RISCVInsertVSETVLI.cpp  | 22 ++---
 .../RISCV/rvv/fixed-vectors-masked-gather.ll  | 24 ---
 2 files changed, 19 insertions(+), 27 deletions(-)

diff --git a/llvm/lib/Target/RISCV/RISCVInsertVSETVLI.cpp 
b/llvm/lib/Target/RISCV/RISCVInsertVSETVLI.cpp
index b42ad269c18de6f..918c96beb29afca 100644
--- a/llvm/lib/Target/RISCV/RISCVInsertVSETVLI.cpp
+++ b/llvm/lib/Target/RISCV/RISCVInsertVSETVLI.cpp
@@ -757,7 +757,8 @@ class RISCVInsertVSETVLI : public MachineFunctionPass {
   bool computeVLVTYPEChanges(const MachineBasicBlock ,
  VSETVLIInfo ) const;
   void computeIncomingVLVTYPE(const MachineBasicBlock );
-  void emitVSETVLIs(MachineBasicBlock );
+  void emitVSETVLIs(MachineBasicBlock ,
+SmallVectorImpl );
   void doLocalPostpass(MachineBasicBlock );
   void doPRE(MachineBasicBlock );
   void insertReadVL(MachineBasicBlock );
@@ -1216,7 +1217,8 @@ bool RISCVInsertVSETVLI::needVSETVLIPHI(const VSETVLIInfo 
,
   return false;
 }
 
-void RISCVInsertVSETVLI::emitVSETVLIs(MachineBasicBlock ) {
+void RISCVInsertVSETVLI::emitVSETVLIs(
+MachineBasicBlock , SmallVectorImpl ) {
   VSETVLIInfo CurInfo = BlockInfo[MBB.getNumber()].Pred;
   // Track whether the prefix of the block we've scanned is transparent
   // (meaning has not yet changed the abstract state).
@@ -1255,6 +1257,13 @@ void RISCVInsertVSETVLI::emitVSETVLIs(MachineBasicBlock 
) {
 MachineOperand  = MI.getOperand(getVLOpNum(MI));
 if (VLOp.isReg()) {
   // Erase the AVL operand from the instruction.
+  if (MachineInstr *MI = MRI->getVRegDef(VLOp.getReg());
+  MI && MI->getOpcode() == RISCV::ADDI &&
+  MI->getOperand(1).isReg() && MI->getOperand(2).isImm() &&
+  MI->getOperand(1).getReg() == RISCV::X0 &&
+  MI->getOperand(2).getImm() != 0)
+DeadVLInstrs.push_back(MI);
+
   VLOp.setReg(RISCV::NoRegister);
   VLOp.setIsKill(false);
 }
@@ -1580,8 +1589,9 @@ bool 
RISCVInsertVSETVLI::runOnMachineFunction(MachineFunction ) {
   // Phase 2 information to avoid adding vsetvlis before the first vector
   // instruction in the block if the VL/VTYPE is satisfied by its
   // predecessors.
+  SmallVector DeadVLInstrs;
   for (MachineBasicBlock  : MF)
-emitVSETVLIs(MBB);
+emitVSETVLIs(MBB, DeadVLInstrs);
 
   // Now that all vsetvlis are explicit, go through and do block local
   // DSE and peephole based demanded fields based transforms.  Note that
@@ -1592,6 +1602,12 @@ bool 
RISCVInsertVSETVLI::runOnMachineFunction(MachineFunction ) {
   for (MachineBasicBlock  : MF)
 doLocalPostpass(MBB);
 
+  // Remove dead LI instructions that set VL.
+  for (MachineInstr *MI : DeadVLInstrs) {
+if (MRI->use_nodbg_empty(MI->getOperand(0).getReg()))
+  MI->eraseFromParent();
+  }
+
   // Once we're fully done rewriting all the instructions, do a final pass
   // through to check for VSETVLIs which write to an unused destination.
   // For the non X0, X0 variant, we can replace the destination register
diff --git a/llvm/test/CodeGen/RISCV/rvv/fixed-vectors-masked-gather.ll 
b/llvm/test/CodeGen/RISCV/rvv/fixed-vectors-masked-gather.ll
index f7352b4659e5a9b..0d306775528ed86 100644
--- a/llvm/test/CodeGen/RISCV/rvv/fixed-vectors-masked-gather.ll
+++ b/llvm/test/CodeGen/RISCV/rvv/fixed-vectors-masked-gather.ll
@@ -12393,7 +12393,6 @@ define <32 x i8> @mgather_baseidx_v32i8(ptr %base, <32 
x i8> %idxs, <32 x i1> %m
 ; RV64ZVE32F-NEXT:vmv.x.s a2, v12
 ; RV64ZVE32F-NEXT:add a2, a0, a2
 ; RV64ZVE32F-NEXT:lbu a2, 0(a2)
-; RV64ZVE32F-NEXT:li a3, 32
 ; RV64ZVE32F-NEXT:vmv.s.x v12, a2
 ; RV64ZVE32F-NEXT:vsetivli zero, 2, e8, m2, tu, ma
 ; RV64ZVE32F-NEXT:vslideup.vi v10, v12, 1
@@ -12431,7 +12430,6 @@ define <32 x i8> @mgather_baseidx_v32i8(ptr %base, <32 
x i8> %idxs, <32 x i1> %m
 ; RV64ZVE32F-NEXT:vmv.x.s a2, v14
 ; RV64ZVE32F-NEXT:add a2, a0, a2
 ; RV64ZVE32F-NEXT:lbu a2, 0(a2)
-; RV64ZVE32F-NEXT:li a3, 32
 ; RV64ZVE32F-NEXT:vmv.s.x v14, a2
 ; RV64ZVE32F-NEXT:vsetivli zero, 6, e8, m2, tu, ma
 ; RV64ZVE32F-NEXT:vslideup.vi v10, v14, 5
@@ -12455,7 +12453,6 @@ define <32 x i8> @mgather_baseidx_v32i8(ptr %base, <32 
x i8> %idxs, <32 x i1> %m
 ; RV64ZVE32F-NEXT:vmv.x.s a2, v13
 ; RV64ZVE32F-NEXT:add a2, a0, a2
 ; RV64ZVE32F-NEXT:lbu a2, 0(a2)
-; RV64ZVE32F-NEXT:li a3, 32
 ; RV64ZVE32F-NEXT:vmv.s.x v14, a2
 ; RV64ZVE32F-NEXT:vsetivli zero, 10, e8, m2, tu, ma
 ; RV64ZVE32F-NEXT:vslideup.vi v10, v14, 9
@@ -12470,7 +12467,6 @@ define <32 x i8> @mgather_baseidx_v32i8(ptr %base, <32 
x i8> 

[clang-tools-extra] [InstCombine] Simplify the pattern `a ne/eq (zext/sext (a ne/eq c))` (PR #65852)

2023-09-24 Thread Yingwei Zheng via cfe-commits

https://github.com/dtcxzyw resolved 
https://github.com/llvm/llvm-project/pull/65852
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [InstCombine] Simplify the pattern `a ne/eq (zext/sext (a ne/eq c))` (PR #65852)

2023-09-24 Thread Yingwei Zheng via cfe-commits

https://github.com/dtcxzyw resolved 
https://github.com/llvm/llvm-project/pull/65852
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang-tools-extra] [InstCombine] Simplify the pattern `a ne/eq (zext/sext (a ne/eq c))` (PR #65852)

2023-09-24 Thread Yingwei Zheng via cfe-commits

https://github.com/dtcxzyw updated 
https://github.com/llvm/llvm-project/pull/65852

>From d9d8bcbb98e8f5aecb9733329389d61a489bd731 Mon Sep 17 00:00:00 2001
From: Yingwei Zheng 
Date: Sat, 9 Sep 2023 23:07:29 +0800
Subject: [PATCH 1/8] [InstCombine] Simplify the pattern `a ne/eq (zext (a
 ne/eq c))`

---
 .../InstCombine/InstCombineCompares.cpp   |  62 ++
 .../test/Transforms/InstCombine/icmp-range.ll | 181 ++
 2 files changed, 243 insertions(+)

diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp 
b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
index 9fdc46fec631679..837b8e6d2619989 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
@@ -6309,7 +6309,69 @@ Instruction 
*InstCombinerImpl::foldICmpUsingBoolRange(ICmpInst ) {
   Y->getType()->isIntOrIntVectorTy(1) && Pred == ICmpInst::ICMP_ULE)
 return BinaryOperator::CreateOr(Builder.CreateIsNull(X), Y);
 
+  ICmpInst::Predicate Pred1, Pred2;
   const APInt *C;
+  // icmp eq/ne X, (zext (icmp eq/ne X, C))
+  if (match(, m_c_ICmp(Pred1, m_Value(X),
+ m_ZExt(m_ICmp(Pred2, m_Deferred(X), m_APInt(C) &&
+  ICmpInst::isEquality(Pred1) && ICmpInst::isEquality(Pred2)) {
+if (C->isZero()) {
+  if (Pred2 == ICmpInst::ICMP_EQ) {
+// icmp eq X, (zext (icmp eq X, 0)) --> false
+// icmp ne X, (zext (icmp eq X, 0)) --> true
+return replaceInstUsesWith(
+I,
+Constant::getIntegerValue(
+I.getType(),
+APInt(1U, static_cast(Pred1 == ICmpInst::ICMP_NE;
+  } else {
+// icmp eq X, (zext (icmp ne X, 0)) --> icmp ult X, 2
+// icmp ne X, (zext (icmp ne X, 0)) --> icmp ugt X, 1
+return ICmpInst::Create(
+Instruction::ICmp,
+Pred1 == ICmpInst::ICMP_NE ? ICmpInst::ICMP_UGT
+   : ICmpInst::ICMP_ULT,
+X,
+Constant::getIntegerValue(
+X->getType(), APInt(X->getType()->getScalarSizeInBits(),
+Pred1 == ICmpInst::ICMP_NE ? 1 : 2)));
+  }
+} else if (C->isOne()) {
+  if (Pred2 == ICmpInst::ICMP_NE) {
+// icmp eq X, (zext (icmp ne X, 1)) --> false
+// icmp ne X, (zext (icmp ne X, 1)) --> true
+return replaceInstUsesWith(
+I,
+Constant::getIntegerValue(
+I.getType(),
+APInt(1U, static_cast(Pred1 == ICmpInst::ICMP_NE;
+  } else {
+// icmp eq X, (zext (icmp eq X, 1)) --> icmp ult X, 2
+// icmp ne X, (zext (icmp eq X, 1)) --> icmp ugt X, 1
+return ICmpInst::Create(
+Instruction::ICmp,
+Pred1 == ICmpInst::ICMP_NE ? ICmpInst::ICMP_UGT
+   : ICmpInst::ICMP_ULT,
+X,
+Constant::getIntegerValue(
+X->getType(), APInt(X->getType()->getScalarSizeInBits(),
+Pred1 == ICmpInst::ICMP_NE ? 1 : 2)));
+  }
+} else {
+  // C != 0 && C != 1
+  // icmp eq X, (zext (icmp eq X, C)) --> icmp eq X, 0
+  // icmp eq X, (zext (icmp ne X, C)) --> icmp eq X, 1
+  // icmp ne X, (zext (icmp eq X, C)) --> icmp ne X, 0
+  // icmp ne X, (zext (icmp ne X, C)) --> icmp ne X, 1
+  return ICmpInst::Create(
+  Instruction::ICmp, Pred1, X,
+  Constant::getIntegerValue(
+  X->getType(),
+  APInt(X->getType()->getScalarSizeInBits(),
+static_cast(Pred2 == ICmpInst::ICMP_NE;
+}
+  }
+
   if (match(I.getOperand(0), m_c_Add(m_ZExt(m_Value(X)), m_SExt(m_Value(Y 
&&
   match(I.getOperand(1), m_APInt(C)) &&
   X->getType()->isIntOrIntVectorTy(1) &&
diff --git a/llvm/test/Transforms/InstCombine/icmp-range.ll 
b/llvm/test/Transforms/InstCombine/icmp-range.ll
index 4281e09cb0309c8..15424fce33fdeea 100644
--- a/llvm/test/Transforms/InstCombine/icmp-range.ll
+++ b/llvm/test/Transforms/InstCombine/icmp-range.ll
@@ -1034,6 +1034,187 @@ define i1 @icmp_ne_bool_1(ptr %ptr) {
   ret i1 %cmp
 }
 
+define i1 @icmp_ne_zext_eq_zero(i32 %a) {
+; CHECK-LABEL: @icmp_ne_zext_eq_zero(
+; CHECK-NEXT:ret i1 true
+;
+  %cmp = icmp eq i32 %a, 0
+  %conv = zext i1 %cmp to i32
+  %cmp1 = icmp ne i32 %conv, %a
+  ret i1 %cmp1
+}
+
+define i1 @icmp_ne_zext_ne_zero(i32 %a) {
+; CHECK-LABEL: @icmp_ne_zext_ne_zero(
+; CHECK-NEXT:[[CMP1:%.*]] = icmp ugt i32 [[A:%.*]], 1
+; CHECK-NEXT:ret i1 [[CMP1]]
+;
+  %cmp = icmp ne i32 %a, 0
+  %conv = zext i1 %cmp to i32
+  %cmp1 = icmp ne i32 %conv, %a
+  ret i1 %cmp1
+}
+
+define i1 @icmp_eq_zext_eq_zero(i32 %a) {
+; CHECK-LABEL: @icmp_eq_zext_eq_zero(
+; CHECK-NEXT:ret i1 false
+;
+  %cmp = icmp eq i32 %a, 0
+  %conv = zext i1 %cmp to i32
+  %cmp1 = icmp eq i32 %conv, %a
+  ret i1 %cmp1
+}
+
+define i1 @icmp_eq_zext_ne_zero(i32 %a) 

[clang] [InstCombine] Simplify the pattern `a ne/eq (zext/sext (a ne/eq c))` (PR #65852)

2023-09-24 Thread Yingwei Zheng via cfe-commits

https://github.com/dtcxzyw updated 
https://github.com/llvm/llvm-project/pull/65852

>From d9d8bcbb98e8f5aecb9733329389d61a489bd731 Mon Sep 17 00:00:00 2001
From: Yingwei Zheng 
Date: Sat, 9 Sep 2023 23:07:29 +0800
Subject: [PATCH 1/8] [InstCombine] Simplify the pattern `a ne/eq (zext (a
 ne/eq c))`

---
 .../InstCombine/InstCombineCompares.cpp   |  62 ++
 .../test/Transforms/InstCombine/icmp-range.ll | 181 ++
 2 files changed, 243 insertions(+)

diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp 
b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
index 9fdc46fec631679..837b8e6d2619989 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
@@ -6309,7 +6309,69 @@ Instruction 
*InstCombinerImpl::foldICmpUsingBoolRange(ICmpInst ) {
   Y->getType()->isIntOrIntVectorTy(1) && Pred == ICmpInst::ICMP_ULE)
 return BinaryOperator::CreateOr(Builder.CreateIsNull(X), Y);
 
+  ICmpInst::Predicate Pred1, Pred2;
   const APInt *C;
+  // icmp eq/ne X, (zext (icmp eq/ne X, C))
+  if (match(, m_c_ICmp(Pred1, m_Value(X),
+ m_ZExt(m_ICmp(Pred2, m_Deferred(X), m_APInt(C) &&
+  ICmpInst::isEquality(Pred1) && ICmpInst::isEquality(Pred2)) {
+if (C->isZero()) {
+  if (Pred2 == ICmpInst::ICMP_EQ) {
+// icmp eq X, (zext (icmp eq X, 0)) --> false
+// icmp ne X, (zext (icmp eq X, 0)) --> true
+return replaceInstUsesWith(
+I,
+Constant::getIntegerValue(
+I.getType(),
+APInt(1U, static_cast(Pred1 == ICmpInst::ICMP_NE;
+  } else {
+// icmp eq X, (zext (icmp ne X, 0)) --> icmp ult X, 2
+// icmp ne X, (zext (icmp ne X, 0)) --> icmp ugt X, 1
+return ICmpInst::Create(
+Instruction::ICmp,
+Pred1 == ICmpInst::ICMP_NE ? ICmpInst::ICMP_UGT
+   : ICmpInst::ICMP_ULT,
+X,
+Constant::getIntegerValue(
+X->getType(), APInt(X->getType()->getScalarSizeInBits(),
+Pred1 == ICmpInst::ICMP_NE ? 1 : 2)));
+  }
+} else if (C->isOne()) {
+  if (Pred2 == ICmpInst::ICMP_NE) {
+// icmp eq X, (zext (icmp ne X, 1)) --> false
+// icmp ne X, (zext (icmp ne X, 1)) --> true
+return replaceInstUsesWith(
+I,
+Constant::getIntegerValue(
+I.getType(),
+APInt(1U, static_cast(Pred1 == ICmpInst::ICMP_NE;
+  } else {
+// icmp eq X, (zext (icmp eq X, 1)) --> icmp ult X, 2
+// icmp ne X, (zext (icmp eq X, 1)) --> icmp ugt X, 1
+return ICmpInst::Create(
+Instruction::ICmp,
+Pred1 == ICmpInst::ICMP_NE ? ICmpInst::ICMP_UGT
+   : ICmpInst::ICMP_ULT,
+X,
+Constant::getIntegerValue(
+X->getType(), APInt(X->getType()->getScalarSizeInBits(),
+Pred1 == ICmpInst::ICMP_NE ? 1 : 2)));
+  }
+} else {
+  // C != 0 && C != 1
+  // icmp eq X, (zext (icmp eq X, C)) --> icmp eq X, 0
+  // icmp eq X, (zext (icmp ne X, C)) --> icmp eq X, 1
+  // icmp ne X, (zext (icmp eq X, C)) --> icmp ne X, 0
+  // icmp ne X, (zext (icmp ne X, C)) --> icmp ne X, 1
+  return ICmpInst::Create(
+  Instruction::ICmp, Pred1, X,
+  Constant::getIntegerValue(
+  X->getType(),
+  APInt(X->getType()->getScalarSizeInBits(),
+static_cast(Pred2 == ICmpInst::ICMP_NE;
+}
+  }
+
   if (match(I.getOperand(0), m_c_Add(m_ZExt(m_Value(X)), m_SExt(m_Value(Y 
&&
   match(I.getOperand(1), m_APInt(C)) &&
   X->getType()->isIntOrIntVectorTy(1) &&
diff --git a/llvm/test/Transforms/InstCombine/icmp-range.ll 
b/llvm/test/Transforms/InstCombine/icmp-range.ll
index 4281e09cb0309c8..15424fce33fdeea 100644
--- a/llvm/test/Transforms/InstCombine/icmp-range.ll
+++ b/llvm/test/Transforms/InstCombine/icmp-range.ll
@@ -1034,6 +1034,187 @@ define i1 @icmp_ne_bool_1(ptr %ptr) {
   ret i1 %cmp
 }
 
+define i1 @icmp_ne_zext_eq_zero(i32 %a) {
+; CHECK-LABEL: @icmp_ne_zext_eq_zero(
+; CHECK-NEXT:ret i1 true
+;
+  %cmp = icmp eq i32 %a, 0
+  %conv = zext i1 %cmp to i32
+  %cmp1 = icmp ne i32 %conv, %a
+  ret i1 %cmp1
+}
+
+define i1 @icmp_ne_zext_ne_zero(i32 %a) {
+; CHECK-LABEL: @icmp_ne_zext_ne_zero(
+; CHECK-NEXT:[[CMP1:%.*]] = icmp ugt i32 [[A:%.*]], 1
+; CHECK-NEXT:ret i1 [[CMP1]]
+;
+  %cmp = icmp ne i32 %a, 0
+  %conv = zext i1 %cmp to i32
+  %cmp1 = icmp ne i32 %conv, %a
+  ret i1 %cmp1
+}
+
+define i1 @icmp_eq_zext_eq_zero(i32 %a) {
+; CHECK-LABEL: @icmp_eq_zext_eq_zero(
+; CHECK-NEXT:ret i1 false
+;
+  %cmp = icmp eq i32 %a, 0
+  %conv = zext i1 %cmp to i32
+  %cmp1 = icmp eq i32 %conv, %a
+  ret i1 %cmp1
+}
+
+define i1 @icmp_eq_zext_ne_zero(i32 %a) 

[clang] [ValueTracking] Simplify uaddo pattern (PR #65910)

2023-09-24 Thread Yingwei Zheng via cfe-commits

https://github.com/dtcxzyw unresolved 
https://github.com/llvm/llvm-project/pull/65910
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [ValueTracking] Simplify uaddo pattern (PR #65910)

2023-09-24 Thread Yingwei Zheng via cfe-commits


@@ -8291,6 +8291,29 @@ static std::optional isImpliedCondICmps(const 
ICmpInst *LHS,
   if (L0 == R0 && match(L1, m_APInt(LC)) && match(R1, m_APInt(RC)))
 return isImpliedCondCommonOperandWithConstants(LPred, *LC, RPred, *RC);
 
+  // L0 = R0 = L1 + R1, L0 >=u L1 implies R0 >=u R1, L0 https://alive2.llvm.org/ce/z/eWsJH2.


https://github.com/llvm/llvm-project/pull/65910
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang-tools-extra] [InstCombine] Simplify the pattern `a ne/eq (zext/sext (a ne/eq c))` (PR #65852)

2023-09-24 Thread Yingwei Zheng via cfe-commits

https://github.com/dtcxzyw resolved 
https://github.com/llvm/llvm-project/pull/65852
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [InstCombine] Simplify the pattern `a ne/eq (zext/sext (a ne/eq c))` (PR #65852)

2023-09-24 Thread Yingwei Zheng via cfe-commits

https://github.com/dtcxzyw resolved 
https://github.com/llvm/llvm-project/pull/65852
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [InstCombine] Simplify the pattern `a ne/eq (zext/sext (a ne/eq c))` (PR #65852)

2023-09-24 Thread Yingwei Zheng via cfe-commits

https://github.com/dtcxzyw updated 
https://github.com/llvm/llvm-project/pull/65852

>From d9d8bcbb98e8f5aecb9733329389d61a489bd731 Mon Sep 17 00:00:00 2001
From: Yingwei Zheng 
Date: Sat, 9 Sep 2023 23:07:29 +0800
Subject: [PATCH 1/7] [InstCombine] Simplify the pattern `a ne/eq (zext (a
 ne/eq c))`

---
 .../InstCombine/InstCombineCompares.cpp   |  62 ++
 .../test/Transforms/InstCombine/icmp-range.ll | 181 ++
 2 files changed, 243 insertions(+)

diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp 
b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
index 9fdc46fec631679..837b8e6d2619989 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
@@ -6309,7 +6309,69 @@ Instruction 
*InstCombinerImpl::foldICmpUsingBoolRange(ICmpInst ) {
   Y->getType()->isIntOrIntVectorTy(1) && Pred == ICmpInst::ICMP_ULE)
 return BinaryOperator::CreateOr(Builder.CreateIsNull(X), Y);
 
+  ICmpInst::Predicate Pred1, Pred2;
   const APInt *C;
+  // icmp eq/ne X, (zext (icmp eq/ne X, C))
+  if (match(, m_c_ICmp(Pred1, m_Value(X),
+ m_ZExt(m_ICmp(Pred2, m_Deferred(X), m_APInt(C) &&
+  ICmpInst::isEquality(Pred1) && ICmpInst::isEquality(Pred2)) {
+if (C->isZero()) {
+  if (Pred2 == ICmpInst::ICMP_EQ) {
+// icmp eq X, (zext (icmp eq X, 0)) --> false
+// icmp ne X, (zext (icmp eq X, 0)) --> true
+return replaceInstUsesWith(
+I,
+Constant::getIntegerValue(
+I.getType(),
+APInt(1U, static_cast(Pred1 == ICmpInst::ICMP_NE;
+  } else {
+// icmp eq X, (zext (icmp ne X, 0)) --> icmp ult X, 2
+// icmp ne X, (zext (icmp ne X, 0)) --> icmp ugt X, 1
+return ICmpInst::Create(
+Instruction::ICmp,
+Pred1 == ICmpInst::ICMP_NE ? ICmpInst::ICMP_UGT
+   : ICmpInst::ICMP_ULT,
+X,
+Constant::getIntegerValue(
+X->getType(), APInt(X->getType()->getScalarSizeInBits(),
+Pred1 == ICmpInst::ICMP_NE ? 1 : 2)));
+  }
+} else if (C->isOne()) {
+  if (Pred2 == ICmpInst::ICMP_NE) {
+// icmp eq X, (zext (icmp ne X, 1)) --> false
+// icmp ne X, (zext (icmp ne X, 1)) --> true
+return replaceInstUsesWith(
+I,
+Constant::getIntegerValue(
+I.getType(),
+APInt(1U, static_cast(Pred1 == ICmpInst::ICMP_NE;
+  } else {
+// icmp eq X, (zext (icmp eq X, 1)) --> icmp ult X, 2
+// icmp ne X, (zext (icmp eq X, 1)) --> icmp ugt X, 1
+return ICmpInst::Create(
+Instruction::ICmp,
+Pred1 == ICmpInst::ICMP_NE ? ICmpInst::ICMP_UGT
+   : ICmpInst::ICMP_ULT,
+X,
+Constant::getIntegerValue(
+X->getType(), APInt(X->getType()->getScalarSizeInBits(),
+Pred1 == ICmpInst::ICMP_NE ? 1 : 2)));
+  }
+} else {
+  // C != 0 && C != 1
+  // icmp eq X, (zext (icmp eq X, C)) --> icmp eq X, 0
+  // icmp eq X, (zext (icmp ne X, C)) --> icmp eq X, 1
+  // icmp ne X, (zext (icmp eq X, C)) --> icmp ne X, 0
+  // icmp ne X, (zext (icmp ne X, C)) --> icmp ne X, 1
+  return ICmpInst::Create(
+  Instruction::ICmp, Pred1, X,
+  Constant::getIntegerValue(
+  X->getType(),
+  APInt(X->getType()->getScalarSizeInBits(),
+static_cast(Pred2 == ICmpInst::ICMP_NE;
+}
+  }
+
   if (match(I.getOperand(0), m_c_Add(m_ZExt(m_Value(X)), m_SExt(m_Value(Y 
&&
   match(I.getOperand(1), m_APInt(C)) &&
   X->getType()->isIntOrIntVectorTy(1) &&
diff --git a/llvm/test/Transforms/InstCombine/icmp-range.ll 
b/llvm/test/Transforms/InstCombine/icmp-range.ll
index 4281e09cb0309c8..15424fce33fdeea 100644
--- a/llvm/test/Transforms/InstCombine/icmp-range.ll
+++ b/llvm/test/Transforms/InstCombine/icmp-range.ll
@@ -1034,6 +1034,187 @@ define i1 @icmp_ne_bool_1(ptr %ptr) {
   ret i1 %cmp
 }
 
+define i1 @icmp_ne_zext_eq_zero(i32 %a) {
+; CHECK-LABEL: @icmp_ne_zext_eq_zero(
+; CHECK-NEXT:ret i1 true
+;
+  %cmp = icmp eq i32 %a, 0
+  %conv = zext i1 %cmp to i32
+  %cmp1 = icmp ne i32 %conv, %a
+  ret i1 %cmp1
+}
+
+define i1 @icmp_ne_zext_ne_zero(i32 %a) {
+; CHECK-LABEL: @icmp_ne_zext_ne_zero(
+; CHECK-NEXT:[[CMP1:%.*]] = icmp ugt i32 [[A:%.*]], 1
+; CHECK-NEXT:ret i1 [[CMP1]]
+;
+  %cmp = icmp ne i32 %a, 0
+  %conv = zext i1 %cmp to i32
+  %cmp1 = icmp ne i32 %conv, %a
+  ret i1 %cmp1
+}
+
+define i1 @icmp_eq_zext_eq_zero(i32 %a) {
+; CHECK-LABEL: @icmp_eq_zext_eq_zero(
+; CHECK-NEXT:ret i1 false
+;
+  %cmp = icmp eq i32 %a, 0
+  %conv = zext i1 %cmp to i32
+  %cmp1 = icmp eq i32 %conv, %a
+  ret i1 %cmp1
+}
+
+define i1 @icmp_eq_zext_ne_zero(i32 %a) 

[clang-tools-extra] [InstCombine] Simplify the pattern `a ne/eq (zext/sext (a ne/eq c))` (PR #65852)

2023-09-24 Thread Yingwei Zheng via cfe-commits

https://github.com/dtcxzyw updated 
https://github.com/llvm/llvm-project/pull/65852

>From d9d8bcbb98e8f5aecb9733329389d61a489bd731 Mon Sep 17 00:00:00 2001
From: Yingwei Zheng 
Date: Sat, 9 Sep 2023 23:07:29 +0800
Subject: [PATCH 1/7] [InstCombine] Simplify the pattern `a ne/eq (zext (a
 ne/eq c))`

---
 .../InstCombine/InstCombineCompares.cpp   |  62 ++
 .../test/Transforms/InstCombine/icmp-range.ll | 181 ++
 2 files changed, 243 insertions(+)

diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp 
b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
index 9fdc46fec631679..837b8e6d2619989 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
@@ -6309,7 +6309,69 @@ Instruction 
*InstCombinerImpl::foldICmpUsingBoolRange(ICmpInst ) {
   Y->getType()->isIntOrIntVectorTy(1) && Pred == ICmpInst::ICMP_ULE)
 return BinaryOperator::CreateOr(Builder.CreateIsNull(X), Y);
 
+  ICmpInst::Predicate Pred1, Pred2;
   const APInt *C;
+  // icmp eq/ne X, (zext (icmp eq/ne X, C))
+  if (match(, m_c_ICmp(Pred1, m_Value(X),
+ m_ZExt(m_ICmp(Pred2, m_Deferred(X), m_APInt(C) &&
+  ICmpInst::isEquality(Pred1) && ICmpInst::isEquality(Pred2)) {
+if (C->isZero()) {
+  if (Pred2 == ICmpInst::ICMP_EQ) {
+// icmp eq X, (zext (icmp eq X, 0)) --> false
+// icmp ne X, (zext (icmp eq X, 0)) --> true
+return replaceInstUsesWith(
+I,
+Constant::getIntegerValue(
+I.getType(),
+APInt(1U, static_cast(Pred1 == ICmpInst::ICMP_NE;
+  } else {
+// icmp eq X, (zext (icmp ne X, 0)) --> icmp ult X, 2
+// icmp ne X, (zext (icmp ne X, 0)) --> icmp ugt X, 1
+return ICmpInst::Create(
+Instruction::ICmp,
+Pred1 == ICmpInst::ICMP_NE ? ICmpInst::ICMP_UGT
+   : ICmpInst::ICMP_ULT,
+X,
+Constant::getIntegerValue(
+X->getType(), APInt(X->getType()->getScalarSizeInBits(),
+Pred1 == ICmpInst::ICMP_NE ? 1 : 2)));
+  }
+} else if (C->isOne()) {
+  if (Pred2 == ICmpInst::ICMP_NE) {
+// icmp eq X, (zext (icmp ne X, 1)) --> false
+// icmp ne X, (zext (icmp ne X, 1)) --> true
+return replaceInstUsesWith(
+I,
+Constant::getIntegerValue(
+I.getType(),
+APInt(1U, static_cast(Pred1 == ICmpInst::ICMP_NE;
+  } else {
+// icmp eq X, (zext (icmp eq X, 1)) --> icmp ult X, 2
+// icmp ne X, (zext (icmp eq X, 1)) --> icmp ugt X, 1
+return ICmpInst::Create(
+Instruction::ICmp,
+Pred1 == ICmpInst::ICMP_NE ? ICmpInst::ICMP_UGT
+   : ICmpInst::ICMP_ULT,
+X,
+Constant::getIntegerValue(
+X->getType(), APInt(X->getType()->getScalarSizeInBits(),
+Pred1 == ICmpInst::ICMP_NE ? 1 : 2)));
+  }
+} else {
+  // C != 0 && C != 1
+  // icmp eq X, (zext (icmp eq X, C)) --> icmp eq X, 0
+  // icmp eq X, (zext (icmp ne X, C)) --> icmp eq X, 1
+  // icmp ne X, (zext (icmp eq X, C)) --> icmp ne X, 0
+  // icmp ne X, (zext (icmp ne X, C)) --> icmp ne X, 1
+  return ICmpInst::Create(
+  Instruction::ICmp, Pred1, X,
+  Constant::getIntegerValue(
+  X->getType(),
+  APInt(X->getType()->getScalarSizeInBits(),
+static_cast(Pred2 == ICmpInst::ICMP_NE;
+}
+  }
+
   if (match(I.getOperand(0), m_c_Add(m_ZExt(m_Value(X)), m_SExt(m_Value(Y 
&&
   match(I.getOperand(1), m_APInt(C)) &&
   X->getType()->isIntOrIntVectorTy(1) &&
diff --git a/llvm/test/Transforms/InstCombine/icmp-range.ll 
b/llvm/test/Transforms/InstCombine/icmp-range.ll
index 4281e09cb0309c8..15424fce33fdeea 100644
--- a/llvm/test/Transforms/InstCombine/icmp-range.ll
+++ b/llvm/test/Transforms/InstCombine/icmp-range.ll
@@ -1034,6 +1034,187 @@ define i1 @icmp_ne_bool_1(ptr %ptr) {
   ret i1 %cmp
 }
 
+define i1 @icmp_ne_zext_eq_zero(i32 %a) {
+; CHECK-LABEL: @icmp_ne_zext_eq_zero(
+; CHECK-NEXT:ret i1 true
+;
+  %cmp = icmp eq i32 %a, 0
+  %conv = zext i1 %cmp to i32
+  %cmp1 = icmp ne i32 %conv, %a
+  ret i1 %cmp1
+}
+
+define i1 @icmp_ne_zext_ne_zero(i32 %a) {
+; CHECK-LABEL: @icmp_ne_zext_ne_zero(
+; CHECK-NEXT:[[CMP1:%.*]] = icmp ugt i32 [[A:%.*]], 1
+; CHECK-NEXT:ret i1 [[CMP1]]
+;
+  %cmp = icmp ne i32 %a, 0
+  %conv = zext i1 %cmp to i32
+  %cmp1 = icmp ne i32 %conv, %a
+  ret i1 %cmp1
+}
+
+define i1 @icmp_eq_zext_eq_zero(i32 %a) {
+; CHECK-LABEL: @icmp_eq_zext_eq_zero(
+; CHECK-NEXT:ret i1 false
+;
+  %cmp = icmp eq i32 %a, 0
+  %conv = zext i1 %cmp to i32
+  %cmp1 = icmp eq i32 %conv, %a
+  ret i1 %cmp1
+}
+
+define i1 @icmp_eq_zext_ne_zero(i32 %a) 

[clang-tools-extra] [ValueTracking] Simplify uaddo pattern (PR #65910)

2023-09-24 Thread Yingwei Zheng via cfe-commits

https://github.com/dtcxzyw resolved 
https://github.com/llvm/llvm-project/pull/65910
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang-tools-extra] [ValueTracking] Simplify uaddo pattern (PR #65910)

2023-09-24 Thread Yingwei Zheng via cfe-commits


@@ -8291,6 +8291,29 @@ static std::optional isImpliedCondICmps(const 
ICmpInst *LHS,
   if (L0 == R0 && match(L1, m_APInt(LC)) && match(R1, m_APInt(RC)))
 return isImpliedCondCommonOperandWithConstants(LPred, *LC, RPred, *RC);
 
+  // L0 = R0 = L1 + R1, L0 >=u L1 implies R0 >=u R1, L0 u L1 -> R0 >u R1` and  `L0 <=u L1 -> R0 <=u R1`.
Alive2: https://alive2.llvm.org/ce/z/VKtFkD

https://github.com/llvm/llvm-project/pull/65910
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [ValueTracking] Simplify uaddo pattern (PR #65910)

2023-09-24 Thread Yingwei Zheng via cfe-commits


@@ -8291,6 +8291,29 @@ static std::optional isImpliedCondICmps(const 
ICmpInst *LHS,
   if (L0 == R0 && match(L1, m_APInt(LC)) && match(R1, m_APInt(RC)))
 return isImpliedCondCommonOperandWithConstants(LPred, *LC, RPred, *RC);
 
+  // L0 = R0 = L1 + R1, L0 >=u L1 implies R0 >=u R1, L0 u L1 -> R0 >u R1` and  `L0 <=u L1 -> R0 <=u R1`.
Alive2: https://alive2.llvm.org/ce/z/VKtFkD

https://github.com/llvm/llvm-project/pull/65910
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang-tools-extra] [ValueTracking] Simplify uaddo pattern (PR #65910)

2023-09-24 Thread Yingwei Zheng via cfe-commits

https://github.com/dtcxzyw resolved 
https://github.com/llvm/llvm-project/pull/65910
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [ValueTracking] Simplify uaddo pattern (PR #65910)

2023-09-24 Thread Yingwei Zheng via cfe-commits

https://github.com/dtcxzyw resolved 
https://github.com/llvm/llvm-project/pull/65910
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang-tools-extra] [ValueTracking] Simplify uaddo pattern (PR #65910)

2023-09-24 Thread Yingwei Zheng via cfe-commits

https://github.com/dtcxzyw updated 
https://github.com/llvm/llvm-project/pull/65910

>From 9bb817aa40dd9bc1bbb18b4cf4bc079145c8ecaa Mon Sep 17 00:00:00 2001
From: Yingwei Zheng 
Date: Mon, 11 Sep 2023 03:58:02 +0800
Subject: [PATCH 1/2] [ValueTracking] Simplify uaddo pattern

---
 llvm/lib/Analysis/ValueTracking.cpp   |  23 
 .../InstSimplify/and-or-implied-cond.ll   | 104 ++
 2 files changed, 127 insertions(+)

diff --git a/llvm/lib/Analysis/ValueTracking.cpp 
b/llvm/lib/Analysis/ValueTracking.cpp
index c4153b824c37e0a..5aaff4ee81be969 100644
--- a/llvm/lib/Analysis/ValueTracking.cpp
+++ b/llvm/lib/Analysis/ValueTracking.cpp
@@ -8291,6 +8291,29 @@ static std::optional isImpliedCondICmps(const 
ICmpInst *LHS,
   if (L0 == R0 && match(L1, m_APInt(LC)) && match(R1, m_APInt(RC)))
 return isImpliedCondCommonOperandWithConstants(LPred, *LC, RPred, *RC);
 
+  // L0 = R0 = L1 + R1, L0 >=u L1 implies R0 >=u R1, L0 From 83fa03f89c69a0a13336f6761023bb1415f92505 Mon Sep 17 00:00:00 2001
From: Yingwei Zheng 
Date: Sun, 24 Sep 2023 17:04:32 +0800
Subject: [PATCH 2/2] fixup! [ValueTracking] Simplify uaddo pattern

---
 llvm/lib/Analysis/ValueTracking.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/llvm/lib/Analysis/ValueTracking.cpp 
b/llvm/lib/Analysis/ValueTracking.cpp
index 5aaff4ee81be969..f2278f3b7097dac 100644
--- a/llvm/lib/Analysis/ValueTracking.cpp
+++ b/llvm/lib/Analysis/ValueTracking.cpp
@@ -8308,7 +8308,7 @@ static std::optional isImpliedCondICmps(const 
ICmpInst *LHS,
   RPred = ICmpInst::getSwappedPredicate(RPred);
 }
 if (L0 == R0 &&
-(LPred == ICmpInst::ICMP_UGE || LPred == ICmpInst::ICMP_ULT) &&
+(LPred == ICmpInst::ICMP_ULT || LPred == ICmpInst::ICMP_UGE) &&
 (RPred == ICmpInst::ICMP_ULT || RPred == ICmpInst::ICMP_UGE) &&
 match(L0, m_c_Add(m_Specific(L1), m_Specific(R1
   return LPred == RPred;

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [ValueTracking] Simplify uaddo pattern (PR #65910)

2023-09-24 Thread Yingwei Zheng via cfe-commits

https://github.com/dtcxzyw updated 
https://github.com/llvm/llvm-project/pull/65910

>From 9bb817aa40dd9bc1bbb18b4cf4bc079145c8ecaa Mon Sep 17 00:00:00 2001
From: Yingwei Zheng 
Date: Mon, 11 Sep 2023 03:58:02 +0800
Subject: [PATCH 1/2] [ValueTracking] Simplify uaddo pattern

---
 llvm/lib/Analysis/ValueTracking.cpp   |  23 
 .../InstSimplify/and-or-implied-cond.ll   | 104 ++
 2 files changed, 127 insertions(+)

diff --git a/llvm/lib/Analysis/ValueTracking.cpp 
b/llvm/lib/Analysis/ValueTracking.cpp
index c4153b824c37e0a..5aaff4ee81be969 100644
--- a/llvm/lib/Analysis/ValueTracking.cpp
+++ b/llvm/lib/Analysis/ValueTracking.cpp
@@ -8291,6 +8291,29 @@ static std::optional isImpliedCondICmps(const 
ICmpInst *LHS,
   if (L0 == R0 && match(L1, m_APInt(LC)) && match(R1, m_APInt(RC)))
 return isImpliedCondCommonOperandWithConstants(LPred, *LC, RPred, *RC);
 
+  // L0 = R0 = L1 + R1, L0 >=u L1 implies R0 >=u R1, L0 From 83fa03f89c69a0a13336f6761023bb1415f92505 Mon Sep 17 00:00:00 2001
From: Yingwei Zheng 
Date: Sun, 24 Sep 2023 17:04:32 +0800
Subject: [PATCH 2/2] fixup! [ValueTracking] Simplify uaddo pattern

---
 llvm/lib/Analysis/ValueTracking.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/llvm/lib/Analysis/ValueTracking.cpp 
b/llvm/lib/Analysis/ValueTracking.cpp
index 5aaff4ee81be969..f2278f3b7097dac 100644
--- a/llvm/lib/Analysis/ValueTracking.cpp
+++ b/llvm/lib/Analysis/ValueTracking.cpp
@@ -8308,7 +8308,7 @@ static std::optional isImpliedCondICmps(const 
ICmpInst *LHS,
   RPred = ICmpInst::getSwappedPredicate(RPred);
 }
 if (L0 == R0 &&
-(LPred == ICmpInst::ICMP_UGE || LPred == ICmpInst::ICMP_ULT) &&
+(LPred == ICmpInst::ICMP_ULT || LPred == ICmpInst::ICMP_UGE) &&
 (RPred == ICmpInst::ICMP_ULT || RPred == ICmpInst::ICMP_UGE) &&
 match(L0, m_c_Add(m_Specific(L1), m_Specific(R1
   return LPred == RPred;

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [InstCombine] Add combines/simplifications for `llvm.ptrmask` (PR #67166)

2023-09-24 Thread Yingwei Zheng via cfe-commits


@@ -1964,18 +1964,78 @@ Instruction *InstCombinerImpl::visitCallInst(CallInst 
) {
 break;
   }
   case Intrinsic::ptrmask: {
+KnownBits Known(DL.getPointerTypeSizeInBits(II->getType()));
+if (SimplifyDemandedInstructionBits(*II, Known))
+  return II;
+
+Value *Op0 = II->getArgOperand(0);
+Value *Op1 = II->getArgOperand(1);
+// Fail loudly in case this is ever changed.
+// TODO: If vector types are supported the merging of (ptrmask (ptrmask))
+// need to ensure we don't merge a vectype with non-vec type.
+assert(!Op0->getType()->isVectorTy() && !Op1->getType()->isVectorTy() &&
+   "These combines where written at a time when ptrmask did not "
+   "support vector types and may not work for vectors");
+
 Value *InnerPtr, *InnerMask;
-if (match(II->getArgOperand(0),
-  m_OneUse(m_Intrinsic(m_Value(InnerPtr),
-   m_Value(InnerMask) {
-  if (II->getArgOperand(1)->getType() == InnerMask->getType()) {
-Value *NewMask = Builder.CreateAnd(II->getArgOperand(1), InnerMask);
-return replaceInstUsesWith(
-*II,
-Builder.CreateIntrinsic(InnerPtr->getType(), Intrinsic::ptrmask,
-{InnerPtr, NewMask}));
+bool Changed = false;
+// Combine:
+// (ptrmask (ptrmask p, A), B)
+//-> (ptrmask p, (and A, B))
+if (match(Op0, m_OneUse(m_Intrinsic(
+   m_Value(InnerPtr), m_Value(InnerMask) {
+  // See if combining the two masks is free.
+  bool OkayToMerge = InnerMask->getType() == Op1->getType();
+  bool NeedsNew = false;
+  if (!OkayToMerge) {
+if (match(InnerMask, m_ImmConstant())) {
+  InnerMask = Builder.CreateZExtOrTrunc(InnerMask, Op1->getType());
+  OkayToMerge = true;
+} else if (match(Op1, m_ImmConstant())) {
+  Op1 = Builder.CreateZExtOrTrunc(Op1, InnerMask->getType());
+  OkayToMerge = true;
+  // Need to create a new one here, as the intrinsic id needs to 
change.
+  NeedsNew = true;
+}
+  }
+  if (InnerMask->getType() == Op1->getType()) {

dtcxzyw wrote:

`OkayToMerge` is unused?

https://github.com/llvm/llvm-project/pull/67166
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [InstCombine] Canonicalize `and(zext(A), B)` into `select A, B & 1, 0` (PR #66740)

2023-09-21 Thread Yingwei Zheng via cfe-commits

dtcxzyw wrote:

To avoid backend regressions, I will merge this PR after #66793.


https://github.com/llvm/llvm-project/pull/66740
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang-tools-extra] [InstCombine] Canonicalize `and(zext(A), B)` into `select A, B & 1, 0` (PR #66740)

2023-09-21 Thread Yingwei Zheng via cfe-commits

dtcxzyw wrote:

> You might want to check whether this also fixes #66740 and if so add a test.

Confirmed. I have added a pre-commit test for 66733 in 
1a73a6b80b54cd23ee8380c6fa3304847e5cb5d1.

https://github.com/llvm/llvm-project/pull/66740
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [InstCombine] Canonicalize `and(zext(A), B)` into `select A, B & 1, 0` (PR #66740)

2023-09-21 Thread Yingwei Zheng via cfe-commits

dtcxzyw wrote:

> You might want to check whether this also fixes #66740 and if so add a test.

Confirmed. I have added a pre-commit test for 66733 in 
1a73a6b80b54cd23ee8380c6fa3304847e5cb5d1.

https://github.com/llvm/llvm-project/pull/66740
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [InstCombine] Canonicalize `and(zext(A), B)` into `select A, B & 1, 0` (PR #66740)

2023-09-21 Thread Yingwei Zheng via cfe-commits

https://github.com/dtcxzyw edited 
https://github.com/llvm/llvm-project/pull/66740
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [InstCombine] Canonicalize `and(zext(A), B)` into `select A, B & 1, 0` (PR #66740)

2023-09-21 Thread Yingwei Zheng via cfe-commits

https://github.com/dtcxzyw updated 
https://github.com/llvm/llvm-project/pull/66740

>From 85f7911dfe0f1e9112881a9f503bcd68edfde580 Mon Sep 17 00:00:00 2001
From: Yingwei Zheng 
Date: Tue, 19 Sep 2023 10:19:46 +0800
Subject: [PATCH 1/3] [InstCombine] Canonicalize `and(zext(A), B)` into `select
 A, B & 1, 0`

---
 .../InstCombine/InstCombineAndOrXor.cpp   |  6 
 .../Transforms/InstCombine/and-or-icmps.ll| 12 +++
 llvm/test/Transforms/InstCombine/icmp.ll  | 31 ++-
 llvm/test/Transforms/InstCombine/narrow.ll|  3 +-
 .../Transforms/InstCombine/zext-or-icmp.ll| 10 +++---
 5 files changed, 33 insertions(+), 29 deletions(-)

diff --git a/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp 
b/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
index ca7dfa82ab5a5d7..7fa432e1fdc1790 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
@@ -2654,6 +2654,12 @@ Instruction *InstCombinerImpl::visitAnd(BinaryOperator 
) {
   A->getType()->isIntOrIntVectorTy(1))
 return SelectInst::Create(A, Constant::getNullValue(Ty), B);
 
+  // and(zext(A), B) -> A ? (B & 1) : 0
+  if (match(, m_c_And(m_OneUse(m_ZExt(m_Value(A))), m_Value(B))) &&
+  A->getType()->isIntOrIntVectorTy(1))
+return SelectInst::Create(A, Builder.CreateAnd(B, ConstantInt::get(Ty, 1)),
+  Constant::getNullValue(Ty));
+
   // (iN X s>> (N-1)) & Y --> (X s< 0) ? Y : 0 -- with optional sext
   if (match(, m_c_And(m_OneUse(m_SExtOrSelf(
 m_AShr(m_Value(X), m_APIntAllowUndef(C,
diff --git a/llvm/test/Transforms/InstCombine/and-or-icmps.ll 
b/llvm/test/Transforms/InstCombine/and-or-icmps.ll
index 065dbf261e131bf..881a9b7ff129dbb 100644
--- a/llvm/test/Transforms/InstCombine/and-or-icmps.ll
+++ b/llvm/test/Transforms/InstCombine/and-or-icmps.ll
@@ -2769,9 +2769,9 @@ define i64 @icmp_slt_0_and_icmp_sgt_neg1_i64(i64 %x) {
 define i64 @icmp_slt_0_and_icmp_sge_neg1_i64_fail(i64 %x) {
 ; CHECK-LABEL: @icmp_slt_0_and_icmp_sge_neg1_i64_fail(
 ; CHECK-NEXT:[[A:%.*]] = icmp sgt i64 [[X:%.*]], -2
-; CHECK-NEXT:[[B:%.*]] = zext i1 [[A]] to i64
 ; CHECK-NEXT:[[C:%.*]] = lshr i64 [[X]], 62
-; CHECK-NEXT:[[D:%.*]] = and i64 [[C]], [[B]]
+; CHECK-NEXT:[[TMP1:%.*]] = and i64 [[C]], 1
+; CHECK-NEXT:[[D:%.*]] = select i1 [[A]], i64 [[TMP1]], i64 0
 ; CHECK-NEXT:ret i64 [[D]]
 ;
   %A = icmp sge i64 %x, -1
@@ -2871,9 +2871,8 @@ define i32 
@icmp_slt_0_and_icmp_sge_neg2_i32_multiuse1(i32 %x) {
 define i32 @icmp_slt_0_and_icmp_sge_neg2_i32_multiuse2(i32 %x) {
 ; CHECK-LABEL: @icmp_slt_0_and_icmp_sge_neg2_i32_multiuse2(
 ; CHECK-NEXT:[[A:%.*]] = icmp sgt i32 [[X:%.*]], -3
-; CHECK-NEXT:[[B:%.*]] = zext i1 [[A]] to i32
 ; CHECK-NEXT:[[C:%.*]] = lshr i32 [[X]], 31
-; CHECK-NEXT:[[D:%.*]] = and i32 [[C]], [[B]]
+; CHECK-NEXT:[[D:%.*]] = select i1 [[A]], i32 [[C]], i32 0
 ; CHECK-NEXT:call void @use32(i32 [[C]])
 ; CHECK-NEXT:ret i32 [[D]]
 ;
@@ -2923,10 +2922,9 @@ define i32 
@icmp_slt_0_or_icmp_eq_100_i32_multiuse_fail1(i32 %x) {
 
 define i32 @icmp_x_slt_0_and_icmp_y_ne_neg2_i32_multiuse_fail2(i32 %x, i32 %y) 
{
 ; CHECK-LABEL: @icmp_x_slt_0_and_icmp_y_ne_neg2_i32_multiuse_fail2(
-; CHECK-NEXT:[[A:%.*]] = icmp ne i32 [[X:%.*]], -2
-; CHECK-NEXT:[[B:%.*]] = zext i1 [[A]] to i32
+; CHECK-NEXT:[[A_NOT:%.*]] = icmp eq i32 [[X:%.*]], -2
 ; CHECK-NEXT:[[C:%.*]] = lshr i32 [[Y:%.*]], 31
-; CHECK-NEXT:[[D:%.*]] = and i32 [[C]], [[B]]
+; CHECK-NEXT:[[D:%.*]] = select i1 [[A_NOT]], i32 0, i32 [[C]]
 ; CHECK-NEXT:call void @use32(i32 [[C]])
 ; CHECK-NEXT:ret i32 [[D]]
 ;
diff --git a/llvm/test/Transforms/InstCombine/icmp.ll 
b/llvm/test/Transforms/InstCombine/icmp.ll
index 666d85d6cc32103..a5c05278f4232e8 100644
--- a/llvm/test/Transforms/InstCombine/icmp.ll
+++ b/llvm/test/Transforms/InstCombine/icmp.ll
@@ -4441,9 +4441,9 @@ define i1 @redundant_sign_bit_count_ugt_31_30(i32 %x) {
 define i1 @zext_bool_and_eq0(i1 %x, i8 %y) {
 ; CHECK-LABEL: @zext_bool_and_eq0(
 ; CHECK-NEXT:[[TMP1:%.*]] = and i8 [[Y:%.*]], 1
-; CHECK-NEXT:[[TMP2:%.*]] = icmp ne i8 [[TMP1]], 0
-; CHECK-NEXT:[[TMP3:%.*]] = and i1 [[TMP2]], [[X:%.*]]
-; CHECK-NEXT:[[R:%.*]] = xor i1 [[TMP3]], true
+; CHECK-NEXT:[[R1:%.*]] = icmp eq i8 [[TMP1]], 0
+; CHECK-NEXT:[[NOT_X:%.*]] = xor i1 [[X:%.*]], true
+; CHECK-NEXT:[[R:%.*]] = select i1 [[NOT_X]], i1 true, i1 [[R1]]
 ; CHECK-NEXT:ret i1 [[R]]
 ;
   %zx = zext i1 %x to i8
@@ -4454,9 +4454,10 @@ define i1 @zext_bool_and_eq0(i1 %x, i8 %y) {
 
 define <2 x i1> @zext_bool_and_eq0_commute(<2 x i1> %x, <2 x i8> %p) {
 ; CHECK-LABEL: @zext_bool_and_eq0_commute(
-; CHECK-NEXT:[[TMP1:%.*]] = trunc <2 x i8> [[P:%.*]] to <2 x i1>
-; CHECK-NEXT:[[TMP2:%.*]] = and <2 x i1> [[TMP1]], [[X:%.*]]
-; CHECK-NEXT:[[R:%.*]] = xor <2 x i1> [[TMP2]], 
+; CHECK-NEXT:

[clang] [InstCombine] Canonicalize `and(zext(A), B)` into `select A, B & 1, 0` (PR #66740)

2023-09-21 Thread Yingwei Zheng via cfe-commits

https://github.com/dtcxzyw edited 
https://github.com/llvm/llvm-project/pull/66740
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [InstCombine] Canonicalize `and(zext(A), B)` into `select A, B & 1, 0` (PR #66740)

2023-09-19 Thread Yingwei Zheng via cfe-commits

dtcxzyw wrote:

> We should use rebase instead of merge. And I recommend force push to change 
> the code before the review starts.

I am confused with the LLVM GitHub user guide. I witnessed someone mess up by 
doing rebase + force push.
Examples: #65853 #65543 #65535


https://github.com/llvm/llvm-project/pull/66740
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [ValueTracking] Simplify uaddo pattern (PR #65910)

2023-09-19 Thread Yingwei Zheng via cfe-commits

dtcxzyw wrote:

Ping.


https://github.com/llvm/llvm-project/pull/65910
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang-tools-extra] [ValueTracking] Simplify uaddo pattern (PR #65910)

2023-09-19 Thread Yingwei Zheng via cfe-commits

dtcxzyw wrote:

Ping.


https://github.com/llvm/llvm-project/pull/65910
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang-tools-extra] [InstCombine] Simplify the pattern `a ne/eq (zext/sext (a ne/eq c))` (PR #65852)

2023-09-18 Thread Yingwei Zheng via cfe-commits

https://github.com/dtcxzyw resolved 
https://github.com/llvm/llvm-project/pull/65852
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [InstCombine] Simplify the pattern `a ne/eq (zext/sext (a ne/eq c))` (PR #65852)

2023-09-18 Thread Yingwei Zheng via cfe-commits

https://github.com/dtcxzyw resolved 
https://github.com/llvm/llvm-project/pull/65852
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [InstCombine] Simplify the pattern `a ne/eq (zext/sext (a ne/eq c))` (PR #65852)

2023-09-18 Thread Yingwei Zheng via cfe-commits

https://github.com/dtcxzyw resolved 
https://github.com/llvm/llvm-project/pull/65852
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang-tools-extra] [InstCombine] Simplify the pattern `a ne/eq (zext/sext (a ne/eq c))` (PR #65852)

2023-09-18 Thread Yingwei Zheng via cfe-commits

https://github.com/dtcxzyw resolved 
https://github.com/llvm/llvm-project/pull/65852
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang-tools-extra] [InstCombine] Simplify the pattern `a ne/eq (zext/sext (a ne/eq c))` (PR #65852)

2023-09-18 Thread Yingwei Zheng via cfe-commits

https://github.com/dtcxzyw updated 
https://github.com/llvm/llvm-project/pull/65852

>From d9d8bcbb98e8f5aecb9733329389d61a489bd731 Mon Sep 17 00:00:00 2001
From: Yingwei Zheng 
Date: Sat, 9 Sep 2023 23:07:29 +0800
Subject: [PATCH 1/6] [InstCombine] Simplify the pattern `a ne/eq (zext (a
 ne/eq c))`

---
 .../InstCombine/InstCombineCompares.cpp   |  62 ++
 .../test/Transforms/InstCombine/icmp-range.ll | 181 ++
 2 files changed, 243 insertions(+)

diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp 
b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
index 9fdc46fec631679..837b8e6d2619989 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
@@ -6309,7 +6309,69 @@ Instruction 
*InstCombinerImpl::foldICmpUsingBoolRange(ICmpInst ) {
   Y->getType()->isIntOrIntVectorTy(1) && Pred == ICmpInst::ICMP_ULE)
 return BinaryOperator::CreateOr(Builder.CreateIsNull(X), Y);
 
+  ICmpInst::Predicate Pred1, Pred2;
   const APInt *C;
+  // icmp eq/ne X, (zext (icmp eq/ne X, C))
+  if (match(, m_c_ICmp(Pred1, m_Value(X),
+ m_ZExt(m_ICmp(Pred2, m_Deferred(X), m_APInt(C) &&
+  ICmpInst::isEquality(Pred1) && ICmpInst::isEquality(Pred2)) {
+if (C->isZero()) {
+  if (Pred2 == ICmpInst::ICMP_EQ) {
+// icmp eq X, (zext (icmp eq X, 0)) --> false
+// icmp ne X, (zext (icmp eq X, 0)) --> true
+return replaceInstUsesWith(
+I,
+Constant::getIntegerValue(
+I.getType(),
+APInt(1U, static_cast(Pred1 == ICmpInst::ICMP_NE;
+  } else {
+// icmp eq X, (zext (icmp ne X, 0)) --> icmp ult X, 2
+// icmp ne X, (zext (icmp ne X, 0)) --> icmp ugt X, 1
+return ICmpInst::Create(
+Instruction::ICmp,
+Pred1 == ICmpInst::ICMP_NE ? ICmpInst::ICMP_UGT
+   : ICmpInst::ICMP_ULT,
+X,
+Constant::getIntegerValue(
+X->getType(), APInt(X->getType()->getScalarSizeInBits(),
+Pred1 == ICmpInst::ICMP_NE ? 1 : 2)));
+  }
+} else if (C->isOne()) {
+  if (Pred2 == ICmpInst::ICMP_NE) {
+// icmp eq X, (zext (icmp ne X, 1)) --> false
+// icmp ne X, (zext (icmp ne X, 1)) --> true
+return replaceInstUsesWith(
+I,
+Constant::getIntegerValue(
+I.getType(),
+APInt(1U, static_cast(Pred1 == ICmpInst::ICMP_NE;
+  } else {
+// icmp eq X, (zext (icmp eq X, 1)) --> icmp ult X, 2
+// icmp ne X, (zext (icmp eq X, 1)) --> icmp ugt X, 1
+return ICmpInst::Create(
+Instruction::ICmp,
+Pred1 == ICmpInst::ICMP_NE ? ICmpInst::ICMP_UGT
+   : ICmpInst::ICMP_ULT,
+X,
+Constant::getIntegerValue(
+X->getType(), APInt(X->getType()->getScalarSizeInBits(),
+Pred1 == ICmpInst::ICMP_NE ? 1 : 2)));
+  }
+} else {
+  // C != 0 && C != 1
+  // icmp eq X, (zext (icmp eq X, C)) --> icmp eq X, 0
+  // icmp eq X, (zext (icmp ne X, C)) --> icmp eq X, 1
+  // icmp ne X, (zext (icmp eq X, C)) --> icmp ne X, 0
+  // icmp ne X, (zext (icmp ne X, C)) --> icmp ne X, 1
+  return ICmpInst::Create(
+  Instruction::ICmp, Pred1, X,
+  Constant::getIntegerValue(
+  X->getType(),
+  APInt(X->getType()->getScalarSizeInBits(),
+static_cast(Pred2 == ICmpInst::ICMP_NE;
+}
+  }
+
   if (match(I.getOperand(0), m_c_Add(m_ZExt(m_Value(X)), m_SExt(m_Value(Y 
&&
   match(I.getOperand(1), m_APInt(C)) &&
   X->getType()->isIntOrIntVectorTy(1) &&
diff --git a/llvm/test/Transforms/InstCombine/icmp-range.ll 
b/llvm/test/Transforms/InstCombine/icmp-range.ll
index 4281e09cb0309c8..15424fce33fdeea 100644
--- a/llvm/test/Transforms/InstCombine/icmp-range.ll
+++ b/llvm/test/Transforms/InstCombine/icmp-range.ll
@@ -1034,6 +1034,187 @@ define i1 @icmp_ne_bool_1(ptr %ptr) {
   ret i1 %cmp
 }
 
+define i1 @icmp_ne_zext_eq_zero(i32 %a) {
+; CHECK-LABEL: @icmp_ne_zext_eq_zero(
+; CHECK-NEXT:ret i1 true
+;
+  %cmp = icmp eq i32 %a, 0
+  %conv = zext i1 %cmp to i32
+  %cmp1 = icmp ne i32 %conv, %a
+  ret i1 %cmp1
+}
+
+define i1 @icmp_ne_zext_ne_zero(i32 %a) {
+; CHECK-LABEL: @icmp_ne_zext_ne_zero(
+; CHECK-NEXT:[[CMP1:%.*]] = icmp ugt i32 [[A:%.*]], 1
+; CHECK-NEXT:ret i1 [[CMP1]]
+;
+  %cmp = icmp ne i32 %a, 0
+  %conv = zext i1 %cmp to i32
+  %cmp1 = icmp ne i32 %conv, %a
+  ret i1 %cmp1
+}
+
+define i1 @icmp_eq_zext_eq_zero(i32 %a) {
+; CHECK-LABEL: @icmp_eq_zext_eq_zero(
+; CHECK-NEXT:ret i1 false
+;
+  %cmp = icmp eq i32 %a, 0
+  %conv = zext i1 %cmp to i32
+  %cmp1 = icmp eq i32 %conv, %a
+  ret i1 %cmp1
+}
+
+define i1 @icmp_eq_zext_ne_zero(i32 %a) 

[clang] [InstCombine] Simplify the pattern `a ne/eq (zext/sext (a ne/eq c))` (PR #65852)

2023-09-18 Thread Yingwei Zheng via cfe-commits

https://github.com/dtcxzyw updated 
https://github.com/llvm/llvm-project/pull/65852

>From d9d8bcbb98e8f5aecb9733329389d61a489bd731 Mon Sep 17 00:00:00 2001
From: Yingwei Zheng 
Date: Sat, 9 Sep 2023 23:07:29 +0800
Subject: [PATCH 1/6] [InstCombine] Simplify the pattern `a ne/eq (zext (a
 ne/eq c))`

---
 .../InstCombine/InstCombineCompares.cpp   |  62 ++
 .../test/Transforms/InstCombine/icmp-range.ll | 181 ++
 2 files changed, 243 insertions(+)

diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp 
b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
index 9fdc46fec631679..837b8e6d2619989 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
@@ -6309,7 +6309,69 @@ Instruction 
*InstCombinerImpl::foldICmpUsingBoolRange(ICmpInst ) {
   Y->getType()->isIntOrIntVectorTy(1) && Pred == ICmpInst::ICMP_ULE)
 return BinaryOperator::CreateOr(Builder.CreateIsNull(X), Y);
 
+  ICmpInst::Predicate Pred1, Pred2;
   const APInt *C;
+  // icmp eq/ne X, (zext (icmp eq/ne X, C))
+  if (match(, m_c_ICmp(Pred1, m_Value(X),
+ m_ZExt(m_ICmp(Pred2, m_Deferred(X), m_APInt(C) &&
+  ICmpInst::isEquality(Pred1) && ICmpInst::isEquality(Pred2)) {
+if (C->isZero()) {
+  if (Pred2 == ICmpInst::ICMP_EQ) {
+// icmp eq X, (zext (icmp eq X, 0)) --> false
+// icmp ne X, (zext (icmp eq X, 0)) --> true
+return replaceInstUsesWith(
+I,
+Constant::getIntegerValue(
+I.getType(),
+APInt(1U, static_cast(Pred1 == ICmpInst::ICMP_NE;
+  } else {
+// icmp eq X, (zext (icmp ne X, 0)) --> icmp ult X, 2
+// icmp ne X, (zext (icmp ne X, 0)) --> icmp ugt X, 1
+return ICmpInst::Create(
+Instruction::ICmp,
+Pred1 == ICmpInst::ICMP_NE ? ICmpInst::ICMP_UGT
+   : ICmpInst::ICMP_ULT,
+X,
+Constant::getIntegerValue(
+X->getType(), APInt(X->getType()->getScalarSizeInBits(),
+Pred1 == ICmpInst::ICMP_NE ? 1 : 2)));
+  }
+} else if (C->isOne()) {
+  if (Pred2 == ICmpInst::ICMP_NE) {
+// icmp eq X, (zext (icmp ne X, 1)) --> false
+// icmp ne X, (zext (icmp ne X, 1)) --> true
+return replaceInstUsesWith(
+I,
+Constant::getIntegerValue(
+I.getType(),
+APInt(1U, static_cast(Pred1 == ICmpInst::ICMP_NE;
+  } else {
+// icmp eq X, (zext (icmp eq X, 1)) --> icmp ult X, 2
+// icmp ne X, (zext (icmp eq X, 1)) --> icmp ugt X, 1
+return ICmpInst::Create(
+Instruction::ICmp,
+Pred1 == ICmpInst::ICMP_NE ? ICmpInst::ICMP_UGT
+   : ICmpInst::ICMP_ULT,
+X,
+Constant::getIntegerValue(
+X->getType(), APInt(X->getType()->getScalarSizeInBits(),
+Pred1 == ICmpInst::ICMP_NE ? 1 : 2)));
+  }
+} else {
+  // C != 0 && C != 1
+  // icmp eq X, (zext (icmp eq X, C)) --> icmp eq X, 0
+  // icmp eq X, (zext (icmp ne X, C)) --> icmp eq X, 1
+  // icmp ne X, (zext (icmp eq X, C)) --> icmp ne X, 0
+  // icmp ne X, (zext (icmp ne X, C)) --> icmp ne X, 1
+  return ICmpInst::Create(
+  Instruction::ICmp, Pred1, X,
+  Constant::getIntegerValue(
+  X->getType(),
+  APInt(X->getType()->getScalarSizeInBits(),
+static_cast(Pred2 == ICmpInst::ICMP_NE;
+}
+  }
+
   if (match(I.getOperand(0), m_c_Add(m_ZExt(m_Value(X)), m_SExt(m_Value(Y 
&&
   match(I.getOperand(1), m_APInt(C)) &&
   X->getType()->isIntOrIntVectorTy(1) &&
diff --git a/llvm/test/Transforms/InstCombine/icmp-range.ll 
b/llvm/test/Transforms/InstCombine/icmp-range.ll
index 4281e09cb0309c8..15424fce33fdeea 100644
--- a/llvm/test/Transforms/InstCombine/icmp-range.ll
+++ b/llvm/test/Transforms/InstCombine/icmp-range.ll
@@ -1034,6 +1034,187 @@ define i1 @icmp_ne_bool_1(ptr %ptr) {
   ret i1 %cmp
 }
 
+define i1 @icmp_ne_zext_eq_zero(i32 %a) {
+; CHECK-LABEL: @icmp_ne_zext_eq_zero(
+; CHECK-NEXT:ret i1 true
+;
+  %cmp = icmp eq i32 %a, 0
+  %conv = zext i1 %cmp to i32
+  %cmp1 = icmp ne i32 %conv, %a
+  ret i1 %cmp1
+}
+
+define i1 @icmp_ne_zext_ne_zero(i32 %a) {
+; CHECK-LABEL: @icmp_ne_zext_ne_zero(
+; CHECK-NEXT:[[CMP1:%.*]] = icmp ugt i32 [[A:%.*]], 1
+; CHECK-NEXT:ret i1 [[CMP1]]
+;
+  %cmp = icmp ne i32 %a, 0
+  %conv = zext i1 %cmp to i32
+  %cmp1 = icmp ne i32 %conv, %a
+  ret i1 %cmp1
+}
+
+define i1 @icmp_eq_zext_eq_zero(i32 %a) {
+; CHECK-LABEL: @icmp_eq_zext_eq_zero(
+; CHECK-NEXT:ret i1 false
+;
+  %cmp = icmp eq i32 %a, 0
+  %conv = zext i1 %cmp to i32
+  %cmp1 = icmp eq i32 %conv, %a
+  ret i1 %cmp1
+}
+
+define i1 @icmp_eq_zext_ne_zero(i32 %a) 

[clang] [InstCombine] Simplify the pattern `a ne/eq (zext/sext (a ne/eq c))` (PR #65852)

2023-09-18 Thread Yingwei Zheng via cfe-commits

https://github.com/dtcxzyw resolved 
https://github.com/llvm/llvm-project/pull/65852
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang-tools-extra] [InstCombine] Simplify the pattern `a ne/eq (zext/sext (a ne/eq c))` (PR #65852)

2023-09-18 Thread Yingwei Zheng via cfe-commits

https://github.com/dtcxzyw resolved 
https://github.com/llvm/llvm-project/pull/65852
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [InstCombine] Simplify the pattern `a ne/eq (zext/sext (a ne/eq c))` (PR #65852)

2023-09-18 Thread Yingwei Zheng via cfe-commits

https://github.com/dtcxzyw resolved 
https://github.com/llvm/llvm-project/pull/65852
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang-tools-extra] [InstCombine] Simplify the pattern `a ne/eq (zext/sext (a ne/eq c))` (PR #65852)

2023-09-18 Thread Yingwei Zheng via cfe-commits

https://github.com/dtcxzyw resolved 
https://github.com/llvm/llvm-project/pull/65852
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang-tools-extra] [InstCombine] Simplify the pattern `a ne/eq (zext/sext (a ne/eq c))` (PR #65852)

2023-09-18 Thread Yingwei Zheng via cfe-commits


@@ -366,19 +366,10 @@ define void @simplify_before_foldAndOfICmps(ptr %p) {
 ; CHECK-LABEL: @simplify_before_foldAndOfICmps(
 ; CHECK-NEXT:[[A8:%.*]] = alloca i16, align 2
 ; CHECK-NEXT:[[L7:%.*]] = load i16, ptr [[A8]], align 2
-; CHECK-NEXT:[[TMP1:%.*]] = icmp eq i16 [[L7]], -1
-; CHECK-NEXT:[[B11:%.*]] = zext i1 [[TMP1]] to i16
-; CHECK-NEXT:[[C10:%.*]] = icmp ugt i16 [[L7]], [[B11]]
-; CHECK-NEXT:[[C5:%.*]] = icmp slt i16 [[L7]], 1
-; CHECK-NEXT:[[C7:%.*]] = icmp slt i16 [[L7]], 0
-; CHECK-NEXT:[[B15:%.*]] = xor i1 [[C7]], [[C10]]
-; CHECK-NEXT:[[C6:%.*]] = xor i1 [[B15]], true
-; CHECK-NEXT:[[TMP2:%.*]] = and i1 [[C5]], [[C6]]
-; CHECK-NEXT:[[C3:%.*]] = and i1 [[TMP2]], [[C10]]
-; CHECK-NEXT:[[TMP3:%.*]] = xor i1 [[C10]], true
-; CHECK-NEXT:[[C18:%.*]] = or i1 [[C7]], [[TMP3]]
-; CHECK-NEXT:[[TMP4:%.*]] = sext i1 [[C3]] to i64
-; CHECK-NEXT:[[G26:%.*]] = getelementptr i1, ptr null, i64 [[TMP4]]
+; CHECK-NEXT:[[C18:%.*]] = icmp slt i16 [[L7]], 1
+; CHECK-NEXT:[[L7_LOBIT:%.*]] = ashr i16 [[L7]], 15
+; CHECK-NEXT:[[TMP1:%.*]] = sext i16 [[L7_LOBIT]] to i64
+; CHECK-NEXT:[[G26:%.*]] = getelementptr i1, ptr null, i64 [[TMP1]]
 ; CHECK-NEXT:store i16 [[L7]], ptr [[P:%.*]], align 2

dtcxzyw wrote:

Proof: https://alive2.llvm.org/ce/z/wBGCFz

https://github.com/llvm/llvm-project/pull/65852
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang-tools-extra] [InstCombine] Simplify the pattern `a ne/eq (zext/sext (a ne/eq c))` (PR #65852)

2023-09-18 Thread Yingwei Zheng via cfe-commits

https://github.com/dtcxzyw edited 
https://github.com/llvm/llvm-project/pull/65852
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang-tools-extra] [InstCombine] Simplify the pattern `a ne/eq (zext/sext (a ne/eq c))` (PR #65852)

2023-09-18 Thread Yingwei Zheng via cfe-commits

https://github.com/dtcxzyw edited 
https://github.com/llvm/llvm-project/pull/65852
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


<    1   2   3   4   >