[clang-tools-extra] [RISCV] Eliminate dead li after emitting VSETVLIs (PR #65934)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
@@ -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)
@@ -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)
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)
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)
@@ -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)
@@ -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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
@@ -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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
@@ -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)
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)
@@ -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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
@@ -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)
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)
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)
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)
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)
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)
@@ -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)
@@ -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)
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)
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)
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)
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)
@@ -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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
@@ -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)
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)
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