Skip to content

Missing opt with ctlz and shifts of power of 2 constants (#41333) #74175

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Dec 8, 2023

Conversation

snikitav
Copy link
Contributor

@snikitav snikitav commented Dec 2, 2023

This patch does the following simplifications:

cttz(shl(C, X), 1) -> add(cttz(C, 1), X)
cttz(lshr exact(C, X), 1) -> sub(cttz(C, 1), X)
ctlz(lshr(C, X), 1) --> add(ctlz(C, 1), X)
ctlz(shl nuw (C, X), 1) --> sub(ctlz(C, 1), X)

Alive2: https://alive2.llvm.org/ce/z/9KHlKc
Closes #41333

@llvmbot
Copy link
Member

llvmbot commented Dec 2, 2023

@llvm/pr-subscribers-clang

@llvm/pr-subscribers-llvm-transforms

Author: Sizov Nikita (snikitav)

Changes

Closes #41333


Full diff: https://github.com/llvm/llvm-project/pull/74175.diff

2 Files Affected:

  • (modified) llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp (+32)
  • (added) llvm/test/Transforms/InstCombine/ctlz-cttz-shifts.ll (+36)
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
index a991f0906052a30..49b55a7a0cc871e 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
@@ -514,6 +514,8 @@ static Instruction *foldCttzCtlz(IntrinsicInst &II, InstCombinerImpl &IC) {
     return IC.replaceInstUsesWith(II, ConstantInt::getNullValue(II.getType()));
   }
 
+  ConstantInt *CInt;
+
   if (IsTZ) {
     // cttz(-x) -> cttz(x)
     if (match(Op0, m_Neg(m_Value(X))))
@@ -549,6 +551,36 @@ static Instruction *foldCttzCtlz(IntrinsicInst &II, InstCombinerImpl &IC) {
 
     if (match(Op0, m_Intrinsic<Intrinsic::abs>(m_Value(X))))
       return IC.replaceOperand(II, 0, X);
+
+    // cttz(shl(%const, %val), 1) --> add(cttz(%const, 1), %val)
+    if (match(Op0, m_Shl(m_ConstantInt(CInt), m_Value(X))) &&
+        match(Op1, m_One())) {
+      Value *ConstCttz =
+          IC.Builder.CreateBinaryIntrinsic(Intrinsic::cttz, CInt, Op1);
+      return IC.replaceInstUsesWith(II, IC.Builder.CreateAdd(ConstCttz, X));
+    }
+
+    // cttz(lshr exact (%const, %val), 0) --> sub(cttz(%const, 0), %val)
+    if (match(Op0, m_Exact(m_LShr(m_ConstantInt(CInt), m_Value(X))))) {
+      Value *ConstCttz =
+          IC.Builder.CreateBinaryIntrinsic(Intrinsic::cttz, CInt, Op1);
+      return IC.replaceInstUsesWith(II, IC.Builder.CreateSub(ConstCttz, X));
+    }
+  } else {
+    // ctlz(lshr(%const, %val), 1) --> add(ctlz(%const, 1), %val)
+    if (match(Op0, m_LShr(m_ConstantInt(CInt), m_Value(X))) &&
+        match(Op1, m_One())) {
+      Value *ConstCtlz =
+          IC.Builder.CreateBinaryIntrinsic(Intrinsic::ctlz, CInt, Op1);
+      return IC.replaceInstUsesWith(II, IC.Builder.CreateAdd(ConstCtlz, X));
+    }
+
+    // ctlz(shl nuw (%const, %val), 0) --> sub(ctlz(%const, 0), %val)
+    if (match(Op0, m_NUWShl(m_ConstantInt(CInt), m_Value(X)))) {
+      Value *ConstCtlz =
+          IC.Builder.CreateBinaryIntrinsic(Intrinsic::ctlz, CInt, Op1);
+      return IC.replaceInstUsesWith(II, IC.Builder.CreateSub(ConstCtlz, X));
+    }
   }
 
   KnownBits Known = IC.computeKnownBits(Op0, 0, &II);
diff --git a/llvm/test/Transforms/InstCombine/ctlz-cttz-shifts.ll b/llvm/test/Transforms/InstCombine/ctlz-cttz-shifts.ll
new file mode 100644
index 000000000000000..32e5ee10835d90c
--- /dev/null
+++ b/llvm/test/Transforms/InstCombine/ctlz-cttz-shifts.ll
@@ -0,0 +1,36 @@
+; RUN: opt -passes=instcombine -S < %s | FileCheck %s
+
+declare i32 @llvm.ctlz.i32(i32, i1)
+declare i32 @llvm.cttz.i32(i32, i1)
+
+define i32 @lshr_ctlz_true(i32) {
+; CHECK-LABEL: @lshr_ctlz_true
+; CHECK-NEXT:  %ctlz = add
+  %lshr = lshr i32 8387584, %0
+  %ctlz = call i32 @llvm.ctlz.i32(i32 %lshr, i1 true)
+  ret i32 %ctlz
+}
+
+define i32 @shl_ctlz_false(i32) {
+; CHECK-LABEL: @shl_ctlz_false
+; CHECK-NEXT:  %ctlz = sub
+  %shl = shl nuw i32 8387584, %0
+  %ctlz = call i32 @llvm.ctlz.i32(i32 %shl, i1 false)
+  ret i32 %ctlz
+}
+
+define i32 @lshr_exact_cttz_false(i32) {
+; CHECK-LABEL: @lshr_exact_cttz_false
+; CHECK-NEXT:  %cttz = sub
+  %lshr = lshr exact i32 8387584, %0
+  %cttz = call i32 @llvm.cttz.i32(i32 %lshr, i1 false)
+  ret i32 %cttz
+}
+
+define i32 @shl_cttz_true(i32) {
+; CHECK-LABEL: @shl_cttz_true
+; CHECK-NEXT:  %cttz = add
+  %shl = shl i32 8387584, %0
+  %cttz = call i32 @llvm.cttz.i32(i32 %shl, i1 true)
+  ret i32 %cttz
+}

@snikitav snikitav force-pushed the implement-ctlz-cttz-shifts-folding branch from 4d36a81 to a0bf3e9 Compare December 2, 2023 03:29
@snikitav snikitav force-pushed the implement-ctlz-cttz-shifts-folding branch 2 times, most recently from 6961c3d to 6ecd1f4 Compare December 2, 2023 03:45
@dtcxzyw
Copy link
Member

dtcxzyw commented Dec 2, 2023

Could you please add the alive2 proof to the PR description?

@snikitav snikitav force-pushed the implement-ctlz-cttz-shifts-folding branch 4 times, most recently from ad439ef to cb2bdf4 Compare December 3, 2023 03:56
@snikitav snikitav requested a review from Endilll as a code owner December 3, 2023 03:56
@llvmbot llvmbot added the clang Clang issues not falling into any other category label Dec 3, 2023
@snikitav snikitav force-pushed the implement-ctlz-cttz-shifts-folding branch from cb2bdf4 to 4d84a42 Compare December 3, 2023 03:57
@Endilll Endilll removed their request for review December 3, 2023 06:10
@snikitav snikitav force-pushed the implement-ctlz-cttz-shifts-folding branch 3 times, most recently from f859ae7 to 02e79cc Compare December 4, 2023 01:28
@snikitav snikitav force-pushed the implement-ctlz-cttz-shifts-folding branch from 02e79cc to 8b04e03 Compare December 5, 2023 20:55
@snikitav snikitav requested a review from dtcxzyw December 6, 2023 08:34
@dtcxzyw dtcxzyw requested a review from goldsteinn December 6, 2023 12:06
@dtcxzyw dtcxzyw removed the clang Clang issues not falling into any other category label Dec 6, 2023
Copy link
Member

@dtcxzyw dtcxzyw left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM. Please wait for additional approval from other reviewers.

@snikitav snikitav force-pushed the implement-ctlz-cttz-shifts-folding branch from 8b04e03 to 42be192 Compare December 6, 2023 20:13
Copy link
Contributor

@nikic nikic left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM apart from one issue.

@snikitav snikitav force-pushed the implement-ctlz-cttz-shifts-folding branch from 42be192 to 4fbad80 Compare December 7, 2023 20:02
Copy link

github-actions bot commented Dec 7, 2023

✅ With the latest revision this PR passed the C/C++ code formatter.

@snikitav snikitav force-pushed the implement-ctlz-cttz-shifts-folding branch from 4fbad80 to 5ba822e Compare December 7, 2023 20:21
@dtcxzyw
Copy link
Member

dtcxzyw commented Dec 8, 2023

Thank you!

@dtcxzyw dtcxzyw merged commit 827f8a7 into llvm:main Dec 8, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Missing opt with ctlz and shifts of power of 2 constants
4 participants