[llvm] [InstCombine] Add ctpop(A | B) + ctpop(A & B) -> ctpop(A) + ctpop(B) (PR #79089)
via llvm-commits
llvm-commits at lists.llvm.org
Sat Jan 27 09:40:28 PST 2024
https://github.com/AtariDreams updated https://github.com/llvm/llvm-project/pull/79089
>From 11f1eabdff9995dc010bd35f507c0108723e5ac3 Mon Sep 17 00:00:00 2001
From: Rose <83477269+AtariDreams at users.noreply.github.com>
Date: Mon, 22 Jan 2024 22:06:36 -0500
Subject: [PATCH 1/2] [InstCombine] Add pre-commit tests (NFC)
---
llvm/test/Transforms/InstCombine/ctpop.ll | 41 +++++++++++++++++++++--
1 file changed, 39 insertions(+), 2 deletions(-)
diff --git a/llvm/test/Transforms/InstCombine/ctpop.ll b/llvm/test/Transforms/InstCombine/ctpop.ll
index dcea5fa87479eb4..63d30c1b346957d 100644
--- a/llvm/test/Transforms/InstCombine/ctpop.ll
+++ b/llvm/test/Transforms/InstCombine/ctpop.ll
@@ -264,6 +264,43 @@ define <2 x i32> @ctpop_add_no_common_bits_vec_use2(<2 x i32> %a, <2 x i32> %b,
ret <2 x i32> %res
}
+define i32 @ctpop_and_or_combine(i32 %a, i32 %b) {
+; CHECK-LABEL: @ctpop_and_or_combine(
+; CHECK-NEXT: [[AND:%.*]] = and i32 [[A:%.*]], [[B:%.*]]
+; CHECK-NEXT: [[CTPOP1:%.*]] = tail call i32 @llvm.ctpop.i32(i32 [[AND]]), !range [[RNG1]]
+; CHECK-NEXT: [[OR:%.*]] = or i32 [[A]], [[B]]
+; CHECK-NEXT: [[CTPOP2:%.*]] = tail call i32 @llvm.ctpop.i32(i32 [[OR]]), !range [[RNG1]]
+; CHECK-NEXT: [[RES:%.*]] = add nuw nsw i32 [[CTPOP1]], [[CTPOP2]]
+; CHECK-NEXT: ret i32 [[RES]]
+;
+ %and = and i32 %a, %b
+ %ctpop1 = tail call i32 @llvm.ctpop.i32(i32 %and)
+ %or = or i32 %a, %b
+ %ctpop2 = tail call i32 @llvm.ctpop.i32(i32 %or)
+ %res = add nuw nsw i32 %ctpop1, %ctpop2
+ ret i32 %res
+}
+
+define i32 @ctpop_and_or_combine_neg(i32 %a, i32 %b) {
+; CHECK-LABEL: @ctpop_and_or_combine_neg(
+; CHECK-NEXT: [[AND:%.*]] = and i32 [[A:%.*]], [[B:%.*]]
+; CHECK-NEXT: [[CTPOP1:%.*]] = tail call i32 @llvm.ctpop.i32(i32 [[AND]]), !range [[RNG1]]
+; CHECK-NEXT: [[ADD:%.*]] = add i32 [[B]], 1
+; CHECK-NEXT: [[OR:%.*]] = or i32 [[ADD]], [[A]]
+; CHECK-NEXT: [[CTPOP2:%.*]] = tail call i32 @llvm.ctpop.i32(i32 [[OR]]), !range [[RNG1]]
+; CHECK-NEXT: [[RES:%.*]] = add nuw nsw i32 [[CTPOP1]], [[CTPOP2]]
+; CHECK-NEXT: ret i32 [[RES]]
+;
+ %and = and i32 %a, %b
+ %ctpop1 = tail call i32 @llvm.ctpop.i32(i32 %and)
+ %add = add i32 %b, 1
+ %or = or i32 %a, %add
+ %ctpop2 = tail call i32 @llvm.ctpop.i32(i32 %or)
+ %res = add nuw nsw i32 %ctpop1, %ctpop2
+ ret i32 %res
+}
+
+
define i8 @ctpop_rotate_left(i8 %a, i8 %amt) {
; CHECK-LABEL: @ctpop_rotate_left(
; CHECK-NEXT: [[RES:%.*]] = tail call i8 @llvm.ctpop.i8(i8 [[A:%.*]]), !range [[RNG0]]
@@ -346,7 +383,7 @@ define <2 x i32> @sub_ctpop_vec_extra_use(<2 x i32> %a, ptr %p) {
define i32 @zext_ctpop(i16 %x) {
; CHECK-LABEL: @zext_ctpop(
-; CHECK-NEXT: [[TMP1:%.*]] = call i16 @llvm.ctpop.i16(i16 [[X:%.*]]), !range [[RNG4:![0-9]+]]
+; CHECK-NEXT: [[TMP1:%.*]] = call i16 @llvm.ctpop.i16(i16 [[X:%.*]]), !range [[RNG6:![0-9]+]]
; CHECK-NEXT: [[P:%.*]] = zext nneg i16 [[TMP1]] to i32
; CHECK-NEXT: ret i32 [[P]]
;
@@ -396,7 +433,7 @@ define i32 @parity_xor(i32 %arg, i32 %arg1) {
define i32 @parity_xor_trunc(i64 %arg, i64 %arg1) {
; CHECK-LABEL: @parity_xor_trunc(
; CHECK-NEXT: [[TMP1:%.*]] = xor i64 [[ARG1:%.*]], [[ARG:%.*]]
-; CHECK-NEXT: [[TMP2:%.*]] = call i64 @llvm.ctpop.i64(i64 [[TMP1]]), !range [[RNG5:![0-9]+]]
+; CHECK-NEXT: [[TMP2:%.*]] = call i64 @llvm.ctpop.i64(i64 [[TMP1]]), !range [[RNG7:![0-9]+]]
; CHECK-NEXT: [[I4:%.*]] = trunc i64 [[TMP2]] to i32
; CHECK-NEXT: [[I5:%.*]] = and i32 [[I4]], 1
; CHECK-NEXT: ret i32 [[I5]]
>From 2d4b3f8355acf30df4a7912f1a6c41d288232c0d Mon Sep 17 00:00:00 2001
From: Rose <83477269+AtariDreams at users.noreply.github.com>
Date: Fri, 26 Jan 2024 01:06:25 -0500
Subject: [PATCH 2/2] [InstCombine] Add ctpop(A | B) + ctpop(A & B) -> ctpop(A)
+ ctpop(B)
---
.../Transforms/InstCombine/InstCombineAddSub.cpp | 14 ++++++++++++++
llvm/test/Transforms/InstCombine/ctpop.ll | 12 +++++-------
2 files changed, 19 insertions(+), 7 deletions(-)
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp b/llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp
index 8a00b75a1f74042..72961cad4b97d8f 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp
@@ -1718,6 +1718,20 @@ Instruction *InstCombinerImpl::visitAdd(BinaryOperator &I) {
Builder.CreateIntrinsic(Intrinsic::umax, {I.getType()}, {A, B}));
}
+ // ctpop(A | B) + ctpop(A & B) => ctpop(A) + ctpop(B)
+ if ((match(LHS, m_OneUse(m_Intrinsic<Intrinsic::ctpop>(
+ m_c_Or(m_Value(A), m_Value(B))))) &&
+ (match(RHS, m_OneUse(m_Intrinsic<Intrinsic::ctpop>(
+ m_c_And(m_Specific(A), m_Specific(B))))))) ||
+ (match(LHS, m_OneUse(m_Intrinsic<Intrinsic::ctpop>(
+ m_c_And(m_Value(A), m_Value(B))))) &&
+ (match(RHS, m_OneUse(m_Intrinsic<Intrinsic::ctpop>(
+ m_c_Or(m_Specific(A), m_Specific(B)))))))) {
+ return BinaryOperator::CreateAdd(
+ Builder.CreateUnaryIntrinsic(Intrinsic::ctpop, A),
+ Builder.CreateUnaryIntrinsic(Intrinsic::ctpop, B));
+ }
+
// ctpop(A) + ctpop(B) => ctpop(A | B) if A and B have no bits set in common.
if (match(LHS, m_OneUse(m_Intrinsic<Intrinsic::ctpop>(m_Value(A)))) &&
match(RHS, m_OneUse(m_Intrinsic<Intrinsic::ctpop>(m_Value(B)))) &&
diff --git a/llvm/test/Transforms/InstCombine/ctpop.ll b/llvm/test/Transforms/InstCombine/ctpop.ll
index 63d30c1b346957d..d3324eb4554ea29 100644
--- a/llvm/test/Transforms/InstCombine/ctpop.ll
+++ b/llvm/test/Transforms/InstCombine/ctpop.ll
@@ -266,11 +266,9 @@ define <2 x i32> @ctpop_add_no_common_bits_vec_use2(<2 x i32> %a, <2 x i32> %b,
define i32 @ctpop_and_or_combine(i32 %a, i32 %b) {
; CHECK-LABEL: @ctpop_and_or_combine(
-; CHECK-NEXT: [[AND:%.*]] = and i32 [[A:%.*]], [[B:%.*]]
-; CHECK-NEXT: [[CTPOP1:%.*]] = tail call i32 @llvm.ctpop.i32(i32 [[AND]]), !range [[RNG1]]
-; CHECK-NEXT: [[OR:%.*]] = or i32 [[A]], [[B]]
-; CHECK-NEXT: [[CTPOP2:%.*]] = tail call i32 @llvm.ctpop.i32(i32 [[OR]]), !range [[RNG1]]
-; CHECK-NEXT: [[RES:%.*]] = add nuw nsw i32 [[CTPOP1]], [[CTPOP2]]
+; CHECK-NEXT: [[TMP1:%.*]] = call i32 @llvm.ctpop.i32(i32 [[A:%.*]]), !range [[RNG1]]
+; CHECK-NEXT: [[TMP2:%.*]] = call i32 @llvm.ctpop.i32(i32 [[B:%.*]]), !range [[RNG1]]
+; CHECK-NEXT: [[RES:%.*]] = add nuw nsw i32 [[TMP1]], [[TMP2]]
; CHECK-NEXT: ret i32 [[RES]]
;
%and = and i32 %a, %b
@@ -383,7 +381,7 @@ define <2 x i32> @sub_ctpop_vec_extra_use(<2 x i32> %a, ptr %p) {
define i32 @zext_ctpop(i16 %x) {
; CHECK-LABEL: @zext_ctpop(
-; CHECK-NEXT: [[TMP1:%.*]] = call i16 @llvm.ctpop.i16(i16 [[X:%.*]]), !range [[RNG6:![0-9]+]]
+; CHECK-NEXT: [[TMP1:%.*]] = call i16 @llvm.ctpop.i16(i16 [[X:%.*]]), !range [[RNG4:![0-9]+]]
; CHECK-NEXT: [[P:%.*]] = zext nneg i16 [[TMP1]] to i32
; CHECK-NEXT: ret i32 [[P]]
;
@@ -433,7 +431,7 @@ define i32 @parity_xor(i32 %arg, i32 %arg1) {
define i32 @parity_xor_trunc(i64 %arg, i64 %arg1) {
; CHECK-LABEL: @parity_xor_trunc(
; CHECK-NEXT: [[TMP1:%.*]] = xor i64 [[ARG1:%.*]], [[ARG:%.*]]
-; CHECK-NEXT: [[TMP2:%.*]] = call i64 @llvm.ctpop.i64(i64 [[TMP1]]), !range [[RNG7:![0-9]+]]
+; CHECK-NEXT: [[TMP2:%.*]] = call i64 @llvm.ctpop.i64(i64 [[TMP1]]), !range [[RNG5:![0-9]+]]
; CHECK-NEXT: [[I4:%.*]] = trunc i64 [[TMP2]] to i32
; CHECK-NEXT: [[I5:%.*]] = and i32 [[I4]], 1
; CHECK-NEXT: ret i32 [[I5]]
More information about the llvm-commits
mailing list