This is an archive of the discontinued LLVM Phabricator instance.

[InstCombine] Add simplifications for div/rem with `i1` operands; PR62607
ClosedPublic

Authored by goldstein.w.n on May 8 2023, 1:31 PM.

Details

Summary

This is generally handled already in early CSE.

If a specialized pipeline is used, however, its possible for i1
operand with known-zero denominator to slip through. Generally the
known-zero denominator is caught and poison is returned, but if it is
indirect enough (known zero through a phi node) we can miss this case
in InstructionSimplify and then miss handling i1. This is because
i1 is current handled with the following check:

`if(Known.countMinLeadingZeros() == Known.getBitWidth() - 1)`

which only works on the assumption we don't know the denominator to be
zero. If we know the denominator to be zero, this check fails:
https://github.com/llvm/llvm-project/issues/62607

This patch simply adds an explicit if(Known.isZero) return poison;
which fixes the issue.

Alive2 Link for tests:

https://alive2.llvm.org/ce/z/VTw54n

Diff Detail

Event Timeline

goldstein.w.n created this revision.May 8 2023, 1:31 PM
Herald added a project: Restricted Project. · View Herald TranscriptMay 8 2023, 1:31 PM
goldstein.w.n requested review of this revision.May 8 2023, 1:31 PM
Herald added a project: Restricted Project. · View Herald TranscriptMay 8 2023, 1:31 PM
nikic requested changes to this revision.May 8 2023, 1:36 PM

Missing InstSimplify tests. The check for this was dropped as part of https://github.com/llvm/llvm-project/commit/946b32680311f43a349d0199f9e286f385cd9847, and apparently had no test coverage? Though I don't really get why the new KnownBits based code doesn't cover this: For i1 type I'd expect Known.countMinLeadingZeros() == Known.getBitWidth() - 1 to evaluate to true?

This revision now requires changes to proceed.May 8 2023, 1:36 PM
goldstein.w.n added a comment.EditedMay 8 2023, 3:59 PM

Missing InstSim plify tests. The check for this was dropped as part of https://github.com/llvm/llvm-project/commit/946b32680311f43a349d0199f9e286f385cd9847, and apparently had no test coverage? Though I don't really get why the new KnownBits based code doesn't cover this: For i1 type I'd expect Known.countMinLeadingZeros() == Known.getBitWidth() - 1 to evaluate to true?

Its because the denominator is known-zero (at least in the case from the bugreport):

Known.Zero: 1
Known.One: 0 
Known.countMinLeadingZeros(): 1
Known.getBitWidth(): 1

So actually this patch should probably be returning poison?

Edit:
Hers a minimal reproduction:

define i1 @foo(i1 %c, i1 %x, i1 %y) {
  br i1 %c, label %true, label %false
true:
  %y_true = and i1 %y, 0
  br label %done
false:
  %y_false = and i1 %y, 0
  br label %done
done:
  %yy = phi i1 [ %y_false, %false ], [ %y_true, %true ]
  %r = sdiv i1 %x, %yy
  ret i1 %r
}

There needs to be some non-trivial zero pattern so it doesn't get constant folded.
Either returning poison or op0 is fine:
https://alive2.llvm.org/ce/z/9RuT_m
poison probably makes more sense though.

goldstein.w.n edited the summary of this revision. (Show Details)May 8 2023, 4:27 PM
goldstein.w.n edited the summary of this revision. (Show Details)

Add explicit tests, better explain the issue

nikic added inline comments.May 9 2023, 12:56 AM
llvm/lib/Analysis/InstructionSimplify.cpp
1143–1147

Move this comment to the if below now?

llvm/test/Transforms/InstCombine/div-i1.ll
17

Is there a more robust way to test this that doesn't rely on worklist order bugs? Something like an assume to zero in an instsimplify test? Or does that also get simplified early?

llvm/test/Transforms/InstCombine/pr62607.ll
6 ↗(On Diff #520511)

Remove triple.

86 ↗(On Diff #520511)

Is this already a minimal reduction per llvm-reduce?

floatshadow added a subscriber: floatshadow.EditedMay 9 2023, 8:34 AM

Edit:
Hers a minimal reproduction:

define i1 @foo(i1 %c, i1 %x, i1 %y) {
  br i1 %c, label %true, label %false
true:
  %y_true = and i1 %y, 0
  br label %done
false:
  %y_false = and i1 %y, 0
  br label %done
done:
  %yy = phi i1 [ %y_false, %false ], [ %y_true, %true ]
  %r = sdiv i1 %x, %yy
  ret i1 %r
}

There needs to be some non-trivial zero pattern so it doesn't get constant folded.
Either returning poison or op0 is fine:
https://alive2.llvm.org/ce/z/9RuT_m
poison probably makes more sense though.

I guess this reproduction need some refinement. KnownBits indeed neglects zero cases, but the threadBinOpOverPHI would do recursive check which later got folded in a pattern match if (match(Op1, m_Zero())) in simplifyDivRem

floatshadow added inline comments.May 9 2023, 9:10 AM
llvm/lib/Analysis/InstructionSimplify.cpp
1097

Can we remove this? I think this might also be covered by KnownBits::isZero() check now.

goldstein.w.n marked 3 inline comments as done.May 9 2023, 11:46 AM
goldstein.w.n added inline comments.
llvm/lib/Analysis/InstructionSimplify.cpp
1097

We can, although my feeling is it makes sense to have a fastpath for the common case (knownbits can be expensive).

llvm/test/Transforms/InstCombine/div-i1.ll
17

Is there a more robust way to test this that doesn't rely on worklist order bugs? Something like an assume to zero in an instsimplify test? Or does that also get simplified early?

It gets simplified early (and is handled correctly now/before). This was the simplest reproduction I could create.

llvm/test/Transforms/InstCombine/pr62607.ll
86 ↗(On Diff #520511)

Is this already a minimal reduction per llvm-reduce?

No, but updated (so yes in v3). Neat tool :)

goldstein.w.n marked an inline comment as done.

Reduce test, cleanup comments

ping. This is still an outstanding bug.

nikic accepted this revision.May 13 2023, 7:20 AM

LGTM

llvm/test/Transforms/InstCombine/pr62607.ll
17 ↗(On Diff #520775)

Most of these declarations are dead?

19 ↗(On Diff #520775)

Merge this into the other file with @pr62607 name.

50 ↗(On Diff #520775)

Attributes shouldn't be needed either.

This revision is now accepted and ready to land.May 13 2023, 7:20 AM
goldstein.w.n marked 3 inline comments as done.May 13 2023, 10:12 AM

Cleanup tests

This revision was landed with ongoing or failed builds.May 13 2023, 12:36 PM
This revision was automatically updated to reflect the committed changes.