This is an archive of the discontinued LLVM Phabricator instance.

[ConstraintElimination] Simplify ssub(a,b) if a s>=b && a s>=0.
ClosedPublic

Authored by fhahn on May 9 2022, 12:53 PM.

Details

Summary

A first patch to use the reasoning in ConstraintElimination to simplify
sub with overflow to a regular sub, if the operation is guaranteed to
not overflow.

Diff Detail

Event Timeline

fhahn created this revision.May 9 2022, 12:53 PM
Herald added a project: Restricted Project. · View Herald TranscriptMay 9 2022, 12:53 PM
Herald added a subscriber: hiraditya. · View Herald Transcript
fhahn requested review of this revision.May 9 2022, 12:53 PM
Herald added a project: Restricted Project. · View Herald TranscriptMay 9 2022, 12:53 PM
fhahn retitled this revision from [ConstraintElimination] Simplify ssub(a,b) if a s>b && a s>=0. to [ConstraintElimination] Simplify ssub(a,b) if a s>=b && a s>=0..May 9 2022, 12:54 PM
nikic added a comment.May 9 2022, 1:05 PM

Would it be sufficient to only replace the m_ExtractValue<1>? I believe that's what we usually do. (Would also work if only the extractvalue is dominated.)

fhahn added a comment.May 9 2022, 1:17 PM

Would it be sufficient to only replace the m_ExtractValue<1>? I believe that's what we usually do. (Would also work if only the extractvalue is dominated.)

And leave the removal of the actual intrinsic call to instcombine (or some other existing transform)? If that's what we do elsewhere I think it should work, the current placement in the regular optimization pipeline means we run instcombine shortly after ConstraintElimiantion.

nikic added a comment.May 9 2022, 1:22 PM

Would it be sufficient to only replace the m_ExtractValue<1>? I believe that's what we usually do. (Would also work if only the extractvalue is dominated.)

And leave the removal of the actual intrinsic call to instcombine (or some other existing transform)? If that's what we do elsewhere I think it should work, the current placement in the regular optimization pipeline means we run instcombine shortly after ConstraintElimiantion.

Yeah, that's what I had in mind. Though checking now, it looks like both CVP (https://github.com/llvm/llvm-project/blob/72831a592edf1bdcca15354181867079a17d4f76/llvm/lib/Transforms/Scalar/CorrelatedValuePropagation.cpp#L572) and SimplifyIndVars (https://github.com/llvm/llvm-project/blob/72831a592edf1bdcca15354181867079a17d4f76/llvm/lib/Transforms/Utils/SimplifyIndVar.cpp#L423) do replace the with.overflow intrinsic itself, so maybe it's fine as is.

Would it be sufficient to only replace the m_ExtractValue<1>? I believe that's what we usually do. (Would also work if only the extractvalue is dominated.)

And leave the removal of the actual intrinsic call to instcombine (or some other existing transform)? If that's what we do elsewhere I think it should work, the current placement in the regular optimization pipeline means we run instcombine shortly after ConstraintElimiantion.

Yeah, that's what I had in mind. Though checking now, it looks like both CVP (https://github.com/llvm/llvm-project/blob/72831a592edf1bdcca15354181867079a17d4f76/llvm/lib/Transforms/Scalar/CorrelatedValuePropagation.cpp#L572) and SimplifyIndVars (https://github.com/llvm/llvm-project/blob/72831a592edf1bdcca15354181867079a17d4f76/llvm/lib/Transforms/Utils/SimplifyIndVar.cpp#L423) do replace the with.overflow intrinsic itself, so maybe it's fine as is.

Those examples also do eraseFromParent(). I don't know if there's any official guideline for the behavior, but cleaning up dead values here makes it less likely that things will break if some other pass gets inserted in the pipeline between this and the next round of instcombine.

fhahn updated this revision to Diff 428672.May 11 2022, 8:23 AM

Would it be sufficient to only replace the m_ExtractValue<1>? I believe that's what we usually do. (Would also work if only the extractvalue is dominated.)

And leave the removal of the actual intrinsic call to instcombine (or some other existing transform)? If that's what we do elsewhere I think it should work, the current placement in the regular optimization pipeline means we run instcombine shortly after ConstraintElimiantion.

Yeah, that's what I had in mind. Though checking now, it looks like both CVP (https://github.com/llvm/llvm-project/blob/72831a592edf1bdcca15354181867079a17d4f76/llvm/lib/Transforms/Scalar/CorrelatedValuePropagation.cpp#L572) and SimplifyIndVars (https://github.com/llvm/llvm-project/blob/72831a592edf1bdcca15354181867079a17d4f76/llvm/lib/Transforms/Utils/SimplifyIndVar.cpp#L423) do replace the with.overflow intrinsic itself, so maybe it's fine as is.

Those examples also do eraseFromParent(). I don't know if there's any official guideline for the behavior, but cleaning up dead values here makes it less likely that things will break if some other pass gets inserted in the pipeline between this and the next round of instcombine.

That's a good point, thanks! I updated the code to remove both the extracts and the intrinsic, if possible.

spatel added inline comments.May 11 2022, 9:55 AM
llvm/lib/Transforms/Scalar/ConstraintElimination.cpp
537–538

This pre-condition is not correct - if A is 0 and B is SMIN for a given width, that overflows.

Double-check to make sure I got the right pattern, but we should have a test like this:
https://alive2.llvm.org/ce/z/t9G3TQ

fhahn updated this revision to Diff 428754.May 11 2022, 1:22 PM

Fix check to ensure B s>= 0, this also ensures A s>= 0.

fhahn marked an inline comment as done.May 11 2022, 1:25 PM
fhahn added inline comments.
llvm/lib/Transforms/Scalar/ConstraintElimination.cpp
537–538

Thanks, this needs to check if B >= 0, which also implies A >= 0. I added additional tests in 1911843c3126 based on the shared alive2 code (I think the one you shared had different compares for %c.2 in @src and @tgt, so the verification failure was about that, here's a slightly updated one: https://alive2.llvm.org/ce/z/L_K648)

spatel added inline comments.May 12 2022, 5:04 AM
llvm/lib/Transforms/Scalar/ConstraintElimination.cpp
537–538

Ah, yes - I messed up that alive code.
I think the patch is correct now, but we could do better if we check the constraints like this:

%a_is_neg = icmp slt i8 %a, 0
%b_is_neg = icmp slt i8 %b, 0
%same_sign = icmp eq i1 %a_is_neg, %b_is_neg

https://alive2.llvm.org/ce/z/D-uuBW

I'm not sure how to best translate that to the getConstraint() framework.

fhahn marked an inline comment as done.May 12 2022, 12:47 PM
fhahn added inline comments.
llvm/lib/Transforms/Scalar/ConstraintElimination.cpp
537–538

I think we would have to separately check for s>=0 and s<0 case. I could further extend this patch or do it as follow up.

spatel accepted this revision.May 12 2022, 1:03 PM

LGTM

llvm/lib/Transforms/Scalar/ConstraintElimination.cpp
537–538

A different patch is probably better.

This revision is now accepted and ready to land.May 12 2022, 1:03 PM
This revision was landed with ongoing or failed builds.May 13 2022, 5:20 AM
This revision was automatically updated to reflect the committed changes.