This is an archive of the discontinued LLVM Phabricator instance.

[AggressiveInstCombine] Add arithmetic shift right instr to `TruncInstCombine` DAG
ClosedPublic

Authored by anton-afanasyev on Aug 19 2021, 2:02 AM.

Details

Summary
Add `ashr` instruction to the DAG post-dominated by `trunc`, allowing                                         
`TruncInstCombine` to reduce bitwidth of expressions containing                                                          
these instructions.                                                                               
                                                                                                                          
We should be shifting by less than the target bitwidth.                                            
Also it is sufficient to require that all truncated bits                                                       
of the value-to-be-shifted are sign bits (all zeros or ones) and                                                         
one sign bit is left untruncated: https://alive2.llvm.org/ce/z/Ajo2__                                           
                                                                                                        
Part of https://reviews.llvm.org/D107766

Diff Detail

Event Timeline

anton-afanasyev requested review of this revision.Aug 19 2021, 2:02 AM
Herald added a project: Restricted Project. · View Herald TranscriptAug 19 2021, 2:02 AM
lebedev.ri requested changes to this revision.Aug 19 2021, 2:10 AM

I'm pretty sure we should count the number of sign bits here, much like how we count the number of leading zeros:
https://godbolt.org/z/vGsf664Gf => https://alive2.llvm.org/ce/z/gIc43E

This revision now requires changes to proceed.Aug 19 2021, 2:10 AM

I'm pretty sure we should count the number of sign bits here, much like how we count the number of leading zeros:
https://godbolt.org/z/vGsf664Gf => https://alive2.llvm.org/ce/z/gIc43E

Ok, I've extended both lshr and ashr to use countMinSignBits(), unifying both cases, but we have to computeKnownBits() one more time here.

Use countMinSignBits()

anton-afanasyev edited the summary of this revision. (Show Details)Aug 19 2021, 7:33 AM
lebedev.ri added inline comments.Aug 19 2021, 7:53 AM
llvm/lib/Transforms/AggressiveInstCombine/TruncInstCombine.cpp
293–296

These seem like a separate change

411–412

[Why] do we have to do this?
Doesn't seem like something this transform should worry about?

lebedev.ri added inline comments.Aug 19 2021, 7:56 AM
llvm/lib/Transforms/AggressiveInstCombine/TruncInstCombine.cpp
297–307
anton-afanasyev marked 3 inline comments as done.Aug 19 2021, 9:43 AM
anton-afanasyev added inline comments.
llvm/lib/Transforms/AggressiveInstCombine/TruncInstCombine.cpp
293–296

Ok, I'm to split this

297–307

I've intentionally merged this two cases, since ashr and lshr processing doesn't differ. What really matters is positivity/negativity of their operand. This is symmetrical cases (see updated summary).

For instance, for your change we still have to replace ashr with lshr if sign bits were zeros and with ashr if sign bits were ones. Why not to do the same for lshr?

411–412

If sign bits were ones we have to replace original shift with ashr, lshr doesn't work (see @lshr_negative_operand_but_short() test).

anton-afanasyev marked 3 inline comments as done.
anton-afanasyev edited the summary of this revision. (Show Details)

Split unrelated changes

lebedev.ri requested changes to this revision.Aug 19 2021, 12:11 PM

This patch does not apply for me.
Please precommit the tests, and rebase the patch so that it applies to main.

This revision now requires changes to proceed.Aug 19 2021, 12:11 PM

Also, let's split trunc_shifts.ll into trunc_{shl,lshr,ashr}.ll.

Rebase after splitted and precommited tests

This patch does not apply for me.
Please precommit the tests, and rebase the patch so that it applies to main.

Also, let's split trunc_shifts.ll into trunc_{shl,lshr,ashr}.ll.

Ok, done

Rebase after splitted and precommited tests

This patch does not apply for me.
Please precommit the tests, and rebase the patch so that it applies to main.

Also, let's split trunc_shifts.ll into trunc_{shl,lshr,ashr}.ll.

Ok, done

Thank you!

llvm/lib/Transforms/AggressiveInstCombine/TruncInstCombine.cpp
297–307

Ehrm, these two inline comments are separate.
Can you explain why we should ask for known *bits* even for ashr,
even though we then ask for known *sign* bits?

411–412

I see. Please explain all that in a code comment.

lebedev.ri added inline comments.Aug 20 2021, 2:20 AM
llvm/lib/Transforms/AggressiveInstCombine/TruncInstCombine.cpp
297–307

(note that there's a typo in my diff, it should be
MinBitWidth = std::max(MinBitWidth, MinSignedBits); not
MinBitWidth = std::max(MinBitWidth, NumSignBits);)

lebedev.ri added inline comments.Aug 20 2021, 2:30 AM
llvm/lib/Transforms/AggressiveInstCombine/TruncInstCombine.cpp
411–412

But, this brings another question - should this assert that the sign bit is known?

lebedev.ri added inline comments.Aug 20 2021, 6:25 AM
llvm/lib/Transforms/AggressiveInstCombine/TruncInstCombine.cpp
411–412

Actually, let me backtrack this.
This patch adds support for ashr truncation.
It shouldn't also suddenly subtly change reasoning for lshr.
Can we please not do that?

anton-afanasyev marked 4 inline comments as done.

Make step back, leaving lshr untouched and counting sign bits for ashr only.
The motivation is such that for natural cases unsigned values are
zexted and lshred whereas signed values are sexted and ashred.
So it is naturally to grasp only these two cases. We miss here cases like truncation of ashr(zext(*)),
but it is transformed for AIC by preceding IC to lshr(zext(*)). Also remove unrelated tests.

llvm/lib/Transforms/AggressiveInstCombine/TruncInstCombine.cpp
297–307

Ok, thanks, used CountMinSignBits() for ashr.

411–412

Ok, I've changed that lines.

anton-afanasyev edited the summary of this revision. (Show Details)Aug 20 2021, 6:55 AM
anton-afanasyev edited the summary of this revision. (Show Details)

Update comment

This comment was removed by lebedev.ri.
lebedev.ri accepted this revision.Aug 20 2021, 7:04 AM

LGTM, thank you.
@spatel ?

This revision is now accepted and ready to land.Aug 20 2021, 7:04 AM
anton-afanasyev marked an inline comment as done.Aug 20 2021, 7:08 AM
anton-afanasyev added inline comments.
llvm/lib/Transforms/AggressiveInstCombine/TruncInstCombine.cpp
411–412

Can we please not do that?

Sure, I've eventually done it that way: lshr is transformed as before, ashr transformation works for numbers treated as signed ones.

anton-afanasyev marked an inline comment as done.

Rebase against dd19f342fa21

lebedev.ri added inline comments.Aug 20 2021, 9:53 AM
llvm/lib/Transforms/AggressiveInstCombine/TruncInstCombine.cpp
405–408

FWIW i think we can generalize this like that in the future.

anton-afanasyev marked an inline comment as done.

Update setting exactness

llvm/lib/Transforms/AggressiveInstCombine/TruncInstCombine.cpp
405–408

Thanks, done.

(i don't have any further comments here, but it might be good to wait on @spatel)

spatel accepted this revision.Aug 23 2021, 2:20 PM

Sorry - I missed the earlier ping.
LGTM.

llvm/lib/Transforms/AggressiveInstCombine/TruncInstCombine.cpp
289–291
if (I->isShift()) {
anton-afanasyev marked an inline comment as done.Aug 24 2021, 12:40 AM
anton-afanasyev added inline comments.
llvm/lib/Transforms/AggressiveInstCombine/TruncInstCombine.cpp
289–291

Thanks, done

anton-afanasyev marked an inline comment as done.

Use isShift()

This revision was landed with ongoing or failed builds.Aug 24 2021, 12:41 AM
This revision was automatically updated to reflect the committed changes.