This is an archive of the discontinued LLVM Phabricator instance.

[InstCombine] Fold and-reduce idiom
ClosedPublic

Authored by mkazantsev on Jan 26 2022, 10:52 PM.

Details

Summary

This patch introduces folding of and-reduce idiom and generates code
that is easier to read and which is lest costly in terms of icmp operations.
The folding is

icmp eq (bitcast(icmp ne (lhs, rhs)), 0)

into

icmp eq(bitcast(lhs), bitcast(rhs))

See https://github.com/llvm/llvm-project/issues/53419

Diff Detail

Event Timeline

mkazantsev created this revision.Jan 26 2022, 10:52 PM
mkazantsev requested review of this revision.Jan 26 2022, 10:52 PM
Herald added a project: Restricted Project. · View Herald TranscriptJan 26 2022, 10:52 PM

Description says "add-reduce"

mkazantsev edited the summary of this revision. (Show Details)Jan 26 2022, 11:11 PM

Description says "add-reduce"

Thanks, fixed!

TBH I'm not sure about converting legal vector types (e.g. <8 x i64>) into massive integer (i512).

mkazantsev planned changes to this revision.Jan 27 2022, 3:48 AM

You're right, need to check if the new scalar type is a legal type. I'll add DL & negative tests & rebase on top. Thanks!

This comment was removed by lebedev.ri.
lebedev.ri edited the summary of this revision. (Show Details)Jan 27 2022, 4:08 AM

Added DL check that we only produce legal scalar types & rebased on top of new (negative) tests.

I think it would make most sense to do at backend level, but i suppose it would be fine to do it here too.

llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
5885

Add a comment explaining what this does?

5894

This should probably be InnerICmp

5897–5898

I think the LHSTy should just be hoisted here, and used instead.

5907

I suspect this should be relaxed to something like "is less than a legal integer"

mkazantsev added inline comments.Jan 27 2022, 4:29 AM
llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
5907

I'm not sure what happens if smth like i63 lives through the pipeline to codegen. Is it ok?

mkazantsev marked 4 inline comments as done.
mkazantsev added a reviewer: lebedev.ri.

Addressed Roman's comments:

  • LHS type hoisted
  • Comments added
  • Vars renamed
  • As for relaxation of legal type to "not wider than max legal type" - I could not find proper API easily. Maybe it needs some extra infrastructure work, and need to check legality. So I added TODO, lets postpone this. I think in most practical cases vector width is power of 2 and all such types are legal.
lebedev.ri added inline comments.Jan 27 2022, 5:08 AM
llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
5885
5887
5907

Not sure, but at least something like "is a power of two that is smaller than the largest legal integer" should be fine.

mkazantsev added inline comments.Jan 27 2022, 5:24 AM
llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
5885

Ahaha, good catch! :)

5907

I didn't find good API to get this largest legal integer. Let's postpone.

Fixed typos.

mkazantsev marked 2 inline comments as done.Jan 27 2022, 5:26 AM
RKSimon added inline comments.Jan 27 2022, 5:30 AM
llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
5910

Why not just use NumBits < getMinVectorRegisterBitWidth() ?

spatel added inline comments.Jan 27 2022, 5:32 AM
llvm/test/Transforms/InstCombine/icmp-vec.ll
431

If this had a power-of-2 type with this pattern, would we handle it? Would be good to add a few more test comments, so the intent is clear.
https://alive2.llvm.org/ce/z/rDeaif

mkazantsev added inline comments.Jan 27 2022, 7:41 AM
llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
5910

And what if some platform has scalar types wider than vector types? Theoretically, it's possible I think. Or, say,i66 is less than i128, should be be allowed?

I suggest to leave this thing alone for now. We can have a separate discussion on what is the less restrictive check here. I really don't want this to be blocked by this particular thing.

llvm/test/Transforms/InstCombine/icmp-vec.ll
431

Yup. It was going to make this as 2nd step of this activity and support or-base ne pattern.

431

I mean, it's a slightly different pattern with -1 in the original cmp, but we can support it in a very similar manner.

spatel added inline comments.Jan 27 2022, 8:02 AM
llvm/test/Transforms/InstCombine/icmp-vec.ll
431

I think we'll always canonicalize it to a 0 constant (as shown in the current CHECK lines) - only the predicate is different, so it would be a very small adjustment to make this work?

mkazantsev added inline comments.Jan 27 2022, 8:56 AM
llvm/test/Transforms/InstCombine/icmp-vec.ll
431

Sure. Do you mind if I do it in a separate follow-up patch? Need to precommit tests anyways.

lebedev.ri accepted this revision.Jan 27 2022, 9:07 AM

The legality check probably needs refinement, but other than that this seems fine to me.
@spatel ?

llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
5922

I'm guessing you are expecting to handle other patterns?
Otherwise, early-return.

This revision is now accepted and ready to land.Jan 27 2022, 9:07 AM
RKSimon added inline comments.Jan 27 2022, 9:12 AM
llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
5902

Is it worth using the pattern match helpers to match all of this?

mkazantsev added inline comments.Jan 27 2022, 9:40 AM
llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
5902

That's what I tried initially, but for single use checks we'd still need to extract all intermediate values and cast them to instructions.

mkazantsev added inline comments.Jan 27 2022, 9:44 AM
llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
5902

Let's give it another try, maybe will be better after all refactoring we've done...

NFC refactoring. Used pattern match following @RKSimon's comment. Looks not so ugly, and it makes support of further transform proposed by @spatel easier.

llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
5922

Yes, there will be others. One of them was mentioned by Sanjay already.

NFC: replaced m_Constant with m_Zero as it seems that it'll be enough for all planned patterns.

spatel accepted this revision.Jan 27 2022, 12:20 PM

LGTM - if you don't plan to extend the predicate match to isEquality soon, please put a TODO comment on it.

llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
5915

You could roll these checks into the match line above with m_OneUse()...and that removes the need to capture the bitcast and inner icmp?

I'll extend the predicate in the follow-up later today, thanks!

llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
5915

I didn't know we had this, thanks!

This revision was landed with ongoing or failed builds.Jan 27 2022, 8:44 PM
This revision was automatically updated to reflect the committed changes.
hans added a subscriber: hans.Jan 28 2022, 3:18 AM

This is causing asserts to fire in Chromium builds. See https://bugs.chromium.org/p/chromium/issues/detail?id=1291929#c2 for a reproducer.

I've reverted back to green in fabaca10b86f77f7d2d34db91fa6b284da924395 until it can be fixed.

mkazantsev reopened this revision.Jan 28 2022, 3:27 AM

Thanks for the repro, I'll take a look.

This revision is now accepted and ready to land.Jan 28 2022, 3:27 AM

I didn't look at the crasher, but in hindsight, it seems clear that we need to check the bitcast source types more thoroughly.
This will crash:

define i1 @eq_cast_eq-1(<2 x i4*> %x, <2 x i4*> %y) {
  %ic = icmp eq <2 x i4*> %x, %y
  %b = bitcast <2 x i1> %ic to i2
  %r = icmp eq i2 %b, -1
  ret i1 %r
}
This revision was automatically updated to reflect the committed changes.