This is an archive of the discontinued LLVM Phabricator instance.

[InstCombine] Generate better code for std::bit_floor from libstdc++
ClosedPublic

Authored by kazu on Mar 12 2023, 6:03 PM.

Details

Summary

Without this patch, std::bit_floor<uint32_t> in libstdc++ is compiled
as:

%eq0 = icmp eq i32 %x, 0
%lshr = lshr i32 %x, 1
%ctlz = tail call i32 @llvm.ctlz.i32(i32 %lshr, i1 false)
%sub = sub i32 32, %ctlz
%shl = shl i32 1, %sub
%sel = select i1 %eq0, i32 0, i32 %shl

With this patch:

%eq0 = icmp eq i32 %x, 0
%ctlz = call i32 @llvm.ctlz.i32(i32 %x, i1 false)
%lshr = lshr i32 -2147483648, %1
%sel = select i1 %eq0, i32 0, i32 %lshr

This patch recognizes the specific pattern emitted for std::bit_floor
in libstdc++.

https://alive2.llvm.org/ce/z/piMdFX

This patch fixes:

https://github.com/llvm/llvm-project/issues/61183

Diff Detail

Unit TestsFailed

Event Timeline

kazu created this revision.Mar 12 2023, 6:03 PM
Herald added a project: Restricted Project. · View Herald TranscriptMar 12 2023, 6:03 PM
Herald added a subscriber: hiraditya. · View Herald Transcript
kazu requested review of this revision.Mar 12 2023, 6:03 PM
Herald added a project: Restricted Project. · View Herald TranscriptMar 12 2023, 6:03 PM
kazu updated this revision to Diff 506425.Mar 19 2023, 2:09 PM

Combine some "if" statements.

kazu added a comment.Mar 19 2023, 2:09 PM

Please take a look. Thanks!

please can you add vector test coverage?

kazu updated this revision to Diff 507623.Mar 22 2023, 11:42 PM

Added a vector test and some negative tests.

kazu added a comment.Mar 22 2023, 11:44 PM

Please take look. Thanks!

kazu updated this revision to Diff 507949.Mar 23 2023, 7:37 PM

Rebased.

goldstein.w.n added inline comments.Mar 26 2023, 3:35 PM
llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp
3296

'32' -> 'BitWidth'.

3304

I would prefer this as a more generic function for replacing 1 << (BitWidth - ctlz(X >> 1)) -> (SignBit >> ctlz(X) which we can do anytime we know X is non-zero: https://alive2.llvm.org/ce/z/PDxghx

Then use the helper for the select case, but then it can also be used with an IsKnownNonZero query.

goldstein.w.n added inline comments.Mar 26 2023, 3:41 PM
llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp
3323

Instead of matching exact BitWidth can you implement this more generically: https://alive2.llvm.org/ce/z/q2hCjC

1 << (C - ctlz(X >> 1)) -> ((1 << (C-1)) >> ctlz(X)

kazu updated this revision to Diff 509538.Mar 29 2023, 8:13 PM

Addressed feedback.

kazu marked 3 inline comments as done.Mar 29 2023, 8:14 PM

Please take a look. Thanks!

goldstein.w.n added inline comments.Apr 2 2023, 8:52 PM
llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp
3312

Doesn't need to be added now, but please add TODO for C==0 case if we have a mask i.e:
https://alive2.llvm.org/ce/z/epLwX_

In general, you could either match C - CTZL with C > 0 && C <= BitWidth or match (C - CTLZ) % BitWidth for any C (then set bit (C->getZExtValue() - 1) % BitWidth.

3318
APInt ShiftedBit = APInt::getOneBitSet(BitWidth, C->getZExtValue() - 1);
3325

This can be exact:
https://alive2.llvm.org/ce/z/Enurag

I think:

BinaryOperator *BO = BinaryOperator::CreateLShr(ConstantInt::get(NType, ShiftedBit), NewCTLZ);
  BO->setIsExact();
  return BO;

Should work.

kazu updated this revision to Diff 512040.Apr 9 2023, 3:11 PM

Start using getOneBitSet.

Add a TODO comment.

kazu marked 2 inline comments as done.Apr 9 2023, 3:13 PM

Please take a look. Thanks!

llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp
3325

If I do this, I get:

llvm/include/llvm/Transforms/Utils/InstructionWorklist.h:60: void llvm::InstructionWorklist::push(llvm::Instruction *): Assertion `I->getParent() && "Instruction not inserted yet?"' failed.
goldstein.w.n added inline comments.Apr 9 2023, 3:22 PM
llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp
3325

If I do this, I get:

llvm/include/llvm/Transforms/Utils/InstructionWorklist.h:60: void llvm::InstructionWorklist::push(llvm::Instruction *): Assertion `I->getParent() && "Instruction not inserted yet?"' failed.

Ahh, because you use replaceoperand below I believe.

Then just cast what you are turning to a BinaryOperator and setIsExact.

kazu updated this revision to Diff 512043.Apr 9 2023, 4:16 PM

Call setIsExact on Instruction.

kazu marked 2 inline comments as done.Apr 9 2023, 4:17 PM

Please take a look. Thanks!

goldstein.w.n accepted this revision.Apr 10 2023, 12:57 PM

LGTM.

I'm not a maintainer so please way a few days to push to give others a chance
to look it over.

llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp
3302

One more note:

X doesn't actually need to be nonzero. Either X nonzero OR ctlz with zero->poison (second arg is true):
https://alive2.llvm.org/ce/z/gDJ_yT

Can you just add that is a todo?

This revision is now accepted and ready to land.Apr 10 2023, 12:57 PM
kazu updated this revision to Diff 512300.Apr 10 2023, 6:13 PM

Add a comment to relax the requirement that X be nonzero.

kazu marked an inline comment as done.Apr 10 2023, 6:14 PM

Thank you for the review!

I'm not a maintainer so please way a few days to push to give others a chance
to look it over.

Will do.

This revision was landed with ongoing or failed builds.Apr 15 2023, 11:32 AM
This revision was automatically updated to reflect the committed changes.