Skip to content

[DAG] isKnownToBeAPowerOfTwo - Power of 2 value is known to be power of 2 after BSWAP/BITREVERSE - #182207

Merged
RKSimon merged 8 commits into
llvm:mainfrom
manueldun:isKnownBSwapBReverse
Mar 4, 2026
Merged

RKSimon merged 8 commits into
llvm:mainfrom
manueldun:isKnownBSwapBReverse

Conversation

@manueldun

Copy link
Copy Markdown
Contributor

This is my first pr specifically for llvm
Fixes #181657
Allows the isKnownToBeAPowerOfTwo function to handle BSWAP and BITREVERSE dag operations.
Any feedback is welcome.

@github-actions

Copy link
Copy Markdown

Thank you for submitting a Pull Request (PR) to the LLVM Project!

This PR will be automatically labeled and the relevant teams will be notified.

If you wish to, you can add reviewers by using the "Reviewers" section on this page.

If this is not working for you, it is probably because you do not have write permissions for the repository. In which case you can instead tag reviewers by name in a comment by using @ followed by their GitHub username.

If you have received no comments on your PR for a week, you can request a review by "ping"ing the PR by adding a comment “Ping”. The common courtesy "ping" rate is once a week. Please remember that you are asking for valuable time from other developers.

If you have further questions, they may be answered by the LLVM GitHub User Guide.

You can also ask questions in a comment on this PR, on the LLVM Discord or on the forums.

@llvmbot llvmbot added the llvm:SelectionDAG SelectionDAGISel as well label Feb 19, 2026
@llvmbot

llvmbot commented Feb 19, 2026

Copy link
Copy Markdown
Member

@llvm/pr-subscribers-backend-x86

@llvm/pr-subscribers-llvm-selectiondag

Author: Manuel Dun (manueldun)

Changes

This is my first pr specifically for llvm
Fixes #181657
Allows the isKnownToBeAPowerOfTwo function to handle BSWAP and BITREVERSE dag operations.
Any feedback is welcome.


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

2 Files Affected:

  • (modified) llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp (+4)
  • (modified) llvm/unittests/Target/AArch64/AArch64SelectionDAGTest.cpp (+11)
diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
index 581553d41cb6d..b24468fbc42a4 100644
--- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
@@ -4762,6 +4762,10 @@ bool SelectionDAG::isKnownToBeAPowerOfTwo(SDValue Val,
         isKnownToBeAPowerOfTwo(Val.getOperand(0), /*OrZero=*/false, Depth + 1))
       return true;
     break;
+  case ISD::BSWAP:
+  case ISD::BITREVERSE:
+    isKnownToBeAPowerOfTwo(Val.getOperand(0), /*OrZero=*/false, Depth + 1);
+    break;
   }
 
   // More could be done here, though the above checks are enough
diff --git a/llvm/unittests/Target/AArch64/AArch64SelectionDAGTest.cpp b/llvm/unittests/Target/AArch64/AArch64SelectionDAGTest.cpp
index b2b8dfb0c21fc..0fa4b9dcbcbf5 100644
--- a/llvm/unittests/Target/AArch64/AArch64SelectionDAGTest.cpp
+++ b/llvm/unittests/Target/AArch64/AArch64SelectionDAGTest.cpp
@@ -914,6 +914,17 @@ TEST_F(AArch64SelectionDAGTest, KnownToBeAPowerOfTwo_Constants) {
   EXPECT_TRUE(DAG->isKnownToBeAPowerOfTwo(SplatBig, /*OrZero=*/true));
 }
 
+TEST_F(AArch64SelectionDAGTest, KnownToBeAPowerOfTwo_BSWAP_BITREVERSE) {
+  SDLoc Loc;
+  auto Cst4 = DAG->getConstant(4, Loc, MVT::i32);
+  auto Int32Vt = MVT::i32;
+  auto BSwapOp = DAG->getNode(ISD::BSWAP, Loc, Int32Vt, Cst4);
+  EXPECT_TRUE(DAG->isKnownToBeAPowerOfTwo(BSwapOp, false));
+
+  auto BReverseOp = DAG->getNode(ISD::BSWAP, Loc, Int32Vt, BSwapOp);
+  EXPECT_TRUE(DAG->isKnownToBeAPowerOfTwo(BReverseOp, false));
+}
+
 TEST_F(AArch64SelectionDAGTest, KnownToBeAPowerOfTwo_Select) {
   SDLoc Loc;
   auto Cst0 = DAG->getConstant(0, Loc, MVT::i32);

Comment thread llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp Outdated
auto BSwapOp = DAG->getNode(ISD::BSWAP, Loc, Int32Vt, Cst4);
EXPECT_TRUE(DAG->isKnownToBeAPowerOfTwo(BSwapOp, false));

auto BReverseOp = DAG->getNode(ISD::BSWAP, Loc, Int32Vt, BSwapOp);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Forgot to change the opcode to ISD::BITREVERSE?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Still need vector tests (with and without DemandedElts) and OrZero handling tests

@@ -4762,6 +4762,10 @@ bool SelectionDAG::isKnownToBeAPowerOfTwo(SDValue Val,
isKnownToBeAPowerOfTwo(Val.getOperand(0), /*OrZero=*/false, Depth + 1))
return true;
break;
case ISD::BSWAP:
case ISD::BITREVERSE:
isKnownToBeAPowerOfTwo(Val.getOperand(0), /*OrZero=*/false, Depth + 1);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Missing return, DemandedElts and OrZero handling

auto BSwapOp = DAG->getNode(ISD::BSWAP, Loc, Int32Vt, Cst4);
EXPECT_TRUE(DAG->isKnownToBeAPowerOfTwo(BSwapOp, false));

auto BReverseOp = DAG->getNode(ISD::BSWAP, Loc, Int32Vt, BSwapOp);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Still need vector tests (with and without DemandedElts) and OrZero handling tests

@@ -914,6 +914,17 @@ TEST_F(AArch64SelectionDAGTest, KnownToBeAPowerOfTwo_Constants) {
EXPECT_TRUE(DAG->isKnownToBeAPowerOfTwo(SplatBig, /*OrZero=*/true));
}

TEST_F(AArch64SelectionDAGTest, KnownToBeAPowerOfTwo_BSWAP_BITREVERSE) {
SDLoc Loc;
auto Cst4 = DAG->getConstant(4, Loc, MVT::i32);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

No auto

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

can I ask why no auto? are we talking about auto type deduction?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

The style guide recommends avoiding them except for explicit casts or where the type is obvious:
https://llvm.org/docs/CodingStandards.html#use-auto-type-deduction-to-make-code-more-readable

@RKSimon RKSimon changed the title Power of 2 SDValue is known to be power of 2 after dag ops BSWAP/BITREVERSE [DAG] isKnownToBeAPowerOfTwo - Power of 2 value is known to be power of 2 after BSWAP/BITREVERSE Feb 19, 2026
Comment on lines +4765 to +4766
case ISD::BSWAP:
case ISD::BITREVERSE:

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Merge this into the ROTL/ROTR case above, which could also pass through the orZero flag?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

@manueldun
manueldun force-pushed the isKnownBSwapBReverse branch from 7618fd8 to dc45e74 Compare February 20, 2026 14:07
@manueldun

Copy link
Copy Markdown
Contributor Author

How about now? waiting for feedback

@RKSimon
RKSimon self-requested a review February 20, 2026 15:07

SDLoc Loc;
SDValue Cst4 = DAG->getConstant(4, Loc, MVT::i32);
SDValue BSwapOp = DAG->getNode(ISD::BSWAP, Loc, MVT::i32, Cst4);

@topperc topperc Feb 20, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Doesn't creating a BSWAP with constant inputs constant fold to a new constant inside getNode? Meaning the call to isKnownToBeAPowerOfTwo is being called on a constant, not on a BSWAP node?

I copied this block locally and it passes without the change to SelectionDAG.cpp.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

To address this I tried to use an operator that cant be folded to a constant (eg. bitcast) and use the result to a bswap, but isKnownToBeAPowerOfTwo does not return true with and without the changes.
This is what I tried:

  SDLoc Loc;
  SDValue Cst4 = DAG->getConstant(4, Loc, MVT::i32);
  EVT InTypes[] = {MVT::i32,MVT::i32};
  SDVTList IntTypes{InTypes,2};
  SDValue CastOp = DAG->getNode(ISD::BITCAST,Loc,IntTypes,Cst4);
  SDValue BSwapOp = DAG->getNode(ISD::BSWAP, Loc, MVT::i32, CastOp);
  EXPECT_TRUE(DAG->isKnownToBeAPowerOfTwo(BSwapOp, /*OrZero=*/false));

As you can see, I cast an i32 to an i32 (a noop)
I wonder if something similar to this aproach would work.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

You will need to use another isKnownToBeAPowerOfTwo pattern inside to handle the OrZero.

Try - SELECT/VSELECT - take part of a test from KnownToBeAPowerOfTwo_Select and wrap the BSWAP/BITREVERSE nodes around them. Should make it easy to do OrZero=true/false and DemandedElts tests

@RKSimon RKSimon left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

You


SDLoc Loc;
SDValue Cst4 = DAG->getConstant(4, Loc, MVT::i32);
SDValue BSwapOp = DAG->getNode(ISD::BSWAP, Loc, MVT::i32, Cst4);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

You will need to use another isKnownToBeAPowerOfTwo pattern inside to handle the OrZero.

Try - SELECT/VSELECT - take part of a test from KnownToBeAPowerOfTwo_Select and wrap the BSWAP/BITREVERSE nodes around them. Should make it easy to do OrZero=true/false and DemandedElts tests

@manueldun
manueldun force-pushed the isKnownBSwapBReverse branch from dc45e74 to 6df9786 Compare February 25, 2026 16:20
@@ -914,6 +914,113 @@ TEST_F(AArch64SelectionDAGTest, KnownToBeAPowerOfTwo_Constants) {
EXPECT_TRUE(DAG->isKnownToBeAPowerOfTwo(SplatBig, /*OrZero=*/true));
}

TEST_F(AArch64SelectionDAGTest, KnownToBeAPowerOfTwo_BSWAP_BITREVERSE) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

We can instead add this to KnownToBeAPowerOfTwo_Select (rename KnownToBeAPowerOfTwo_Ops?)

And just wraps some of the existing interesting VSelect values with bitreverse/bswap and repeat the same true/false test

This will scale much better than repeating so much duplicated setup code/.

@manueldun
manueldun force-pushed the isKnownBSwapBReverse branch from 6df9786 to 869886c Compare February 25, 2026 18:38

@RKSimon RKSimon left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Fix merge failure

@manueldun

Copy link
Copy Markdown
Contributor Author

does the merge commit need to be handle in some way? (like squashing?)

@RKSimon

RKSimon commented Feb 25, 2026

Copy link
Copy Markdown
Contributor

Merge is much preferred over rebase as rebase can lose review comments

@manueldun
manueldun force-pushed the isKnownBSwapBReverse branch from 747ddc5 to 869886c Compare February 26, 2026 00:12
@manueldun

manueldun commented Feb 26, 2026

Copy link
Copy Markdown
Contributor Author

Sorry, it is my first time resolving a merge conflict, how is the correct way to do so?

@RKSimon RKSimon left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

#181882 has now landed so you should be able to create IR tests instead of unit tests

Comment thread llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
@manueldun

Copy link
Copy Markdown
Contributor Author

Sorry for squashing commits, I assumed it was the way to go, let me create the tests and resolve conflicts

@manueldun

Copy link
Copy Markdown
Contributor Author

I will try to not do more rebasing from here

@RKSimon

RKSimon commented Feb 28, 2026

Copy link
Copy Markdown
Contributor

I will try to not do more rebasing from here

np - re-request a review when you're ready

@manueldun
manueldun requested a review from RKSimon February 28, 2026 13:47
@RKSimon

RKSimon commented Mar 1, 2026

Copy link
Copy Markdown
Contributor

please coordinate with @mirimmad as you seem to be dealing with #182744 as well

Comment thread llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
Comment thread llvm/test/CodeGen/X86/known-pow2.ll
Comment thread llvm/test/CodeGen/X86/known-pow2.ll Outdated
@manueldun
manueldun requested a review from RKSimon March 2, 2026 14:22
%and = and i32 %x, %d
%r = icmp eq i32 %and, %d
ret i1 %r
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

don't remove existing test coverage

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

sorry, I removed the wrong test, my bad

Comment thread llvm/test/CodeGen/X86/known-pow2.ll Outdated
%x_add_y = add i32 %x, %rot_y
%r = and i32 %x_add_y, %rot_y
ret i32 %r
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

remove this new rot test coverage

Comment thread llvm/test/CodeGen/X86/known-pow2.ll Outdated
%x_add_y = add i32 %x, %rot_y
%r = and i32 %x_add_y, %rot_y
ret i32 %r
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

remove this new rot test coverage

@manueldun
manueldun force-pushed the isKnownBSwapBReverse branch from 6b5d997 to 45cc6ca Compare March 3, 2026 15:24
@RKSimon
RKSimon self-requested a review March 3, 2026 17:38
RKSimon

This comment was marked as outdated.

Comment thread llvm/test/CodeGen/X86/known-pow2.ll Outdated
%sel = select i1 %cmp, i32 4, i32 8
%swap = call i32 @llvm.bswap.i32(i32 %sel)
%rev = call i32 @llvm.bitreverse.i32(i32 %sel)
%res = urem i32 %a1, %swap

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

remove swap and use rev

Comment thread llvm/test/CodeGen/X86/known-pow2.ll Outdated
; CHECK-NEXT: retq
%cmp = icmp sgt <4 x i32> zeroinitializer, %a0
%sel = select <4 x i1> %cmp, <4 x i32> <i32 4, i32 2, i32 1, i32 0>, <4 x i32> <i32 8, i32 4, i32 2, i32 -1>
%swap = call <4 x i32> @llvm.bswap.v4i32(<4 x i32> %sel)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Suggested change
%swap = call <4 x i32> @llvm.bswap.v4i32(<4 x i32> %sel)
%rev = call <4 x i32> @llvm.bitreverse.v4i32(<4 x i32> %sel)

@manueldun
manueldun requested a review from RKSimon March 4, 2026 18:01

@RKSimon RKSimon left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

LGTM

@RKSimon
RKSimon enabled auto-merge (squash) March 4, 2026 19:51
@RKSimon
RKSimon merged commit 5c08616 into llvm:main Mar 4, 2026
10 checks passed
@github-actions

github-actions Bot commented Mar 4, 2026

Copy link
Copy Markdown

@manueldun Congratulations on having your first Pull Request (PR) merged into the LLVM Project!

Your changes will be combined with recent changes from other authors, then tested by our build bots. If there is a problem with a build, you may receive a report in an email or a comment on this PR.

Please check whether problems have been caused by your change specifically, as the builds can include changes from many authors. It is not uncommon for your change to be included in a build that fails due to someone else's changes, or infrastructure issues.

How to do this, and the rest of the post-merge process, is covered in detail here.

If your change does cause a problem, it may be reverted, or you can revert it yourself. This is a normal part of LLVM development. You can fix your changes and open a new PR to merge them again.

If you don't get any reports, no action is required from you. Your changes are working as expected, well done!

sujianIBM pushed a commit to sujianIBM/llvm-project that referenced this pull request Mar 5, 2026
…of 2 after BSWAP/BITREVERSE (llvm#182207)

This is my first pr specifically for llvm
Fixes llvm#181657
Allows the isKnownToBeAPowerOfTwo function to handle BSWAP and
BITREVERSE dag operations.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

backend:X86 llvm:SelectionDAG SelectionDAGISel as well

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[DAG] SelectionDAG::isKnownToBeAPowerOfTwo - add ISD::BSWAP+BITREVERSE handling

6 participants