This is an archive of the discontinued LLVM Phabricator instance.

[InstCombine] Generalize sadd.sat combine to compute sign bits.
ClosedPublic

Authored by dmgreen on Oct 22 2021, 2:09 AM.

Details

Summary

There is a combine in instcombine to transform a saturated add/sub into a saddsat/ssubsat, currently handling inputs which are both sign extended (https://alive2.llvm.org/ce/z/68qpTn). This can generalize to, for example ashr of at least the bitwidth (https://alive2.llvm.org/ce/z/4TFyX- and https://alive2.llvm.org/ce/z/qDWzFs for example). My understanding is that, this means it generalizes further to "the number of sign bits", needing to be enough to truncate to the size of the saturate. (An example using or for instance: https://alive2.llvm.org/ce/z/EI_h_A).

So this patch makes use of ComputeNumSignBits (with a newly added ComputeMinSignedBits) in matchSAddSubSat to generalize the fold to any inputs with enough sign bits known, truncating the inputs to the new size of the saturate.

Diff Detail

Event Timeline

dmgreen created this revision.Oct 22 2021, 2:09 AM
dmgreen requested review of this revision.Oct 22 2021, 2:09 AM
Herald added a project: Restricted Project. · View Herald TranscriptOct 22 2021, 2:09 AM
lebedev.ri added inline comments.Nov 3 2021, 7:40 AM
llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp
2324–2326

Should these not be CreateTruncOrBitCast?

dmgreen updated this revision to Diff 384473.Nov 3 2021, 8:52 AM

Updated to make sure there is a vector test that folds, using a splat constant.

llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp
2324–2326

I think CreateTrunc works how you imagine CreateTruncOrBitCast works, if everything is an integer type. It starts out with if (V->getType() == DestTy) return V;

lebedev.ri added inline comments.Nov 3 2021, 11:57 AM
llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp
2316–2317
2319–2322

I've spent more time trying to reason about this, which means this can be improved.
Please add ComputeMinSignedBits() wrapper next to ComputeNumSignBits(),
and use it here. Then this becomes

if (ComputeMinSignedBits(AddSub->getOperand(0), 0, AddSub) > NewBitWidth ||
    ComputeMinSignedBits(AddSub->getOperand(1), 0, AddSub) > NewBitWidth)

which at least to me is immensely more readable.

dmgreen updated this revision to Diff 384704.Nov 4 2021, 5:27 AM
dmgreen edited the summary of this revision. (Show Details)

Added ComputeMinSignedBits, just to InstCombiner for the moment.

llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp
2319–2322

Sounds good. Do you mean next to the ComputeNumSignBits in InstCombiner, or next to the base variant in ValueTracking?

I added it to InstCombiner for the moment, but can easily move it if you think that is better.

Thank you,
Is this the full diff against main, looks incomplete?

llvm/include/llvm/Transforms/InstCombine/InstCombiner.h
488–489 ↗(On Diff #384704)
lebedev.ri added inline comments.Nov 4 2021, 5:31 AM
llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp
2319–2322

Eh, probably both, instcombine-one should use the valuetracking-one.

dmgreen added inline comments.Nov 4 2021, 5:32 AM
llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp
2319–2322

OK will do.

dmgreen updated this revision to Diff 384734.Nov 4 2021, 6:53 AM

Now part of ValueTracking

lebedev.ri accepted this revision.Nov 4 2021, 7:06 AM

LGTM, thank you.

llvm/include/llvm/Analysis/ValueTracking.h
206–208 ↗(On Diff #384734)

Hm, i think this isn't strictly precise.
I.e. given 0b101 which is negative, we can't truncate it to 0b1,
even thought that doesn't change the sign. So i think you should either
talk about the algebraic value, or take inspiration from how langref,
and say something like

/// Get the minimum bit size for this Value \p Op as a signed integer.
/// i.e.  x == sext(trunc(x to MinSignedBits) to bitwidth(x))
llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
1273–1274 ↗(On Diff #384734)

I think this is a NFC change, in which case can you precommit it first?

llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp
2318–2319

These aren't using InstCombine's wrapper?

This revision is now accepted and ready to land.Nov 4 2021, 7:06 AM
dmgreen marked 8 inline comments as done.Nov 5 2021, 7:45 AM
dmgreen added inline comments.
llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
1273–1274 ↗(On Diff #384734)

Thanks. Part1: rG61225c081858

llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp
2318–2319

This function is in InstCombinerImpl, so this should go through the wrappers. The other part in processUGT_ADDCST_ADD needs to call them via IC that is passed to the function.

This revision was landed with ongoing or failed builds.Nov 5 2021, 8:05 AM
This revision was automatically updated to reflect the committed changes.
dmgreen marked 2 inline comments as done.