This is an archive of the discontinued LLVM Phabricator instance.

[InstCombine] prevent possible miscompile with negate+sdiv of vector op
ClosedPublic

Authored by spatel on Apr 8 2019, 4:11 PM.

Details

Summary
// 0 - (X sdiv C)  -> (X sdiv -C)  provided the negation doesn't overflow.

This fold has been around for many years and nobody noticed the potential vector miscompile from overflow until today...
So it seems unlikely that there's much demand for a vector sdiv optimization on arbitrary vector constants, so just limit the matching to splat constants to avoid the possible bug.

Diff Detail

Repository
rL LLVM

Event Timeline

spatel created this revision.Apr 8 2019, 4:11 PM
Herald added a project: Restricted Project. · View Herald TranscriptApr 8 2019, 4:11 PM
shchenz accepted this revision.Apr 8 2019, 10:38 PM

LGTM for this patch.

But should we also consider about the following pattern in file test/Transforms/InstCombine/div.ll

define <2 x i64> @test34(<2 x i64> %x) {
; CHECK-LABEL: @test34(
; CHECK-NEXT:    [[DIV:%.*]] = sdiv exact <2 x i64> [[X:%.*]], <i64 -3, i64 -4>
; CHECK-NEXT:    ret <2 x i64> [[DIV]]
;
  %neg = sub nsw <2 x i64> zeroinitializer, %x
  %div = sdiv exact <2 x i64> %neg, <i64 3, i64 4>
  ret <2 x i64> %div
}

This one is sdiv (neg(%x), constant), it should have same issue, right? But I think this should be another issue about sdiv combination?

This revision is now accepted and ready to land.Apr 8 2019, 10:38 PM
lebedev.ri accepted this revision.Apr 8 2019, 11:12 PM

This LG, thank you!

LGTM for this patch.

But should we also consider about the following pattern in file test/Transforms/InstCombine/div.ll

define <2 x i64> @test34(<2 x i64> %x) {
; CHECK-LABEL: @test34(
; CHECK-NEXT:    [[DIV:%.*]] = sdiv exact <2 x i64> [[X:%.*]], <i64 -3, i64 -4>
; CHECK-NEXT:    ret <2 x i64> [[DIV]]
;
  %neg = sub nsw <2 x i64> zeroinitializer, %x
  %div = sdiv exact <2 x i64> %neg, <i64 3, i64 4>
  ret <2 x i64> %div
}

This one is sdiv (neg(%x), constant), it should have same issue, right? But I think this should be another issue about sdiv combination?

Yes, that seems to have the same general problem.
https://godbolt.org/z/vPVHmh

llvm/test/Transforms/InstCombine/div.ll
820 ↗(On Diff #194218)

Could also add a test for SINT_MIN (yes, i have seen the next test here)

spatel marked an inline comment as done.Apr 9 2019, 5:55 AM
spatel added inline comments.
llvm/test/Transforms/InstCombine/div.ll
820 ↗(On Diff #194218)

Do you mean a splat of SINT_MIN (that's above here) or something else?

lebedev.ri added inline comments.Apr 9 2019, 5:59 AM
llvm/test/Transforms/InstCombine/div.ll
820 ↗(On Diff #194218)

I actually initially misread @negate_sdiv_vec_signed_min_elt, i thought it was:

define <2 x i8> @negate_sdiv_vec_signed_min_and_one_elt(<2 x i8> %x) {
  %div = sdiv <2 x i8> %x, <i8 1, i8 -128>
  %neg = sub <2 x i8> zeroinitializer, %div
  ret <2 x i8> %neg
}

and i was going to suggest to add the test that is already in @negate_sdiv_vec_signed_min_elt.
So now i guess i'd suggest maybe adding test from this comment.

spatel marked an inline comment as done.Apr 9 2019, 6:22 AM
spatel added inline comments.
llvm/test/Transforms/InstCombine/div.ll
820 ↗(On Diff #194218)

Thanks - will do.

And I'll make a similar code change for the other buggy pattern matcher if that looks like the same problem.

This revision was automatically updated to reflect the committed changes.