This is an archive of the discontinued LLVM Phabricator instance.

[InstSimplify] Drop leftover "division-by-zero guard" around `@llvm.umul.with.overflow` overflow bit
ClosedPublic

Authored by lebedev.ri on Jul 23 2019, 7:32 AM.

Details

Summary

Now that with D65143/D65144 we've produce @llvm.umul.with.overflow,
and with D65147 we've flattened the CFG, we now can see that
the guard may have been there to prevent division by zero is redundant.
We can simply drop it:

----------------------------------------
Name: no overflow and not zero
  %iszero = icmp ne i4 %y, 0
  %umul = umul_overflow i4 %x, %y
  %umul.ov = extractvalue {i4, i1} %umul, 1
  %retval.0 = and i1 %iszero, %umul.ov
  ret i1 %retval.0
=>
  %iszero = icmp ne i4 %y, 0
  %umul = umul_overflow i4 %x, %y
  %umul.ov = extractvalue {i4, i1} %umul, 1
  %retval.0 = and i1 %iszero, %umul.ov
  ret %umul.ov

Done: 1
Optimization is correct!

Diff Detail

Repository
rL LLVM

Event Timeline

lebedev.ri created this revision.Jul 23 2019, 7:32 AM
spatel accepted this revision.Jul 26 2019, 6:45 AM

LGTM

llvm/lib/Analysis/InstructionSimplify.cpp
1786 ↗(On Diff #211298)

Grammar nit: it's --> its

This revision is now accepted and ready to land.Jul 26 2019, 6:45 AM
lebedev.ri marked an inline comment as done.

Thank you for the review.
Nit addressed.

nikic added a comment.Jul 28 2019, 2:19 AM

I think this is something of a recurring pattern (not so much the and/or forms, but the original phi/select form), where we have select (x != C1), y, C2, where it turns out that y[x = C1] == C2 and thus the whole expression reduces to y (same with phi's). We might want to invest in a general solution to this problem. Something along the lines of finding this kind of pattern, then checking y backwards for uses of x (to a small depth) and if we find them, replace x with C1, run InstSimplify over it and see if it reduces to C2 in the end.

nikic added a comment.Jul 28 2019, 4:50 AM

I think this is something of a recurring pattern (not so much the and/or forms, but the original phi/select form), where we have select (x != C1), y, C2, where it turns out that y[x = C1] == C2 and thus the whole expression reduces to y (same with phi's). We might want to invest in a general solution to this problem. Something along the lines of finding this kind of pattern, then checking y backwards for uses of x (to a small depth) and if we find them, replace x with C1, run InstSimplify over it and see if it reduces to C2 in the end.

After thinking about this a bit more, a general solution is probably fairly hard because we would need an InstSimplify mode that does not use any UB or poison-based reasoning.

I think this is something of a recurring pattern (not so much the and/or forms, but the original phi/select form), where we have select (x != C1), y, C2, where it turns out that y[x = C1] == C2 and thus the whole expression reduces to y (same with phi's). We might want to invest in a general solution to this problem. Something along the lines of finding this kind of pattern, then checking y backwards for uses of x (to a small depth) and if we find them, replace x with C1, run InstSimplify over it and see if it reduces to C2 in the end.

After thinking about this a bit more, a general solution is probably fairly hard because we would need an InstSimplify mode that does not use any UB or poison-based reasoning.

Not sure if it's exactly what you're imagining, but we have an 'identity constant' fold for select with binops. See foldSelectBinOpIdentity(). Extend getBinOpIdentity() to handle intrinsics as well as standard binop opcodes?

Rebased, NFC.

lebedev.ri edited the summary of this revision. (Show Details)Aug 29 2019, 5:30 AM
This revision was automatically updated to reflect the committed changes.