This is an archive of the discontinued LLVM Phabricator instance.

[SVE] Fix invalid uses of VectorType::getNumElements() in ValueTracking
ClosedPublic

Authored by ctetreau on Apr 28 2020, 4:18 PM.

Details

Summary

Any function in this module that make use of DemandedElts laregely does
not work with scalable vectors. DemandedElts is used to define which
elements of the vector to look at. At best, for scalable vectors, we can
express the first N elements of the vector. However, in practice, most
code that uses these functions expect to be able to talk about the
entire vector. In principle, this module should be able to be extended
to work with scalable vectors. However, before we can do that, we should
ensure that it does not cause code with scalable vectors to miscompile.
All functions that use a DemandedElts will bail out if the vector is
scalable. Usages of getNumElements() are updated to go through
FixedVectorType pointers.

Diff Detail

Event Timeline

ctetreau created this revision.Apr 28 2020, 4:18 PM
Herald added a reviewer: efriedma. · View Herald Transcript
Herald added a project: Restricted Project. · View Herald Transcript

We probably should support computeKnownBits with scalable vectors; the functionality mostly just works. The one part that doesn't is the "DemandedElts", but really it's a minor part, and we can just ignore it for scalable vectors. (So essentially, drop the new assertion from computeKnownBits, and bail out in the few places in the implementation that actually care.)

llvm/lib/Analysis/ValueTracking.cpp
211

I'm surprised this assertion doesn't break anything else; computeKnownBits has a lot of callers.

spatel added inline comments.Apr 29 2020, 6:43 AM
llvm/lib/Analysis/ValueTracking.cpp
211

Yes, I think that's the reason for this failure:
https://reviews.llvm.org/harbormaster/unit/view/73867/

We probably should support computeKnownBits with scalable vectors; the functionality mostly just works. The one part that doesn't is the "DemandedElts", but really it's a minor part, and we can just ignore it for scalable vectors. (So essentially, drop the new assertion from computeKnownBits, and bail out in the few places in the implementation that actually care.)

Yeah, it looks like there are some parts of computeKnownBits that should work for scalable vectors. I'll update it to do the right thing.

ctetreau updated this revision to Diff 260972.Apr 29 2020, 11:32 AM
ctetreau edited the summary of this revision. (Show Details)
ctetreau removed reviewers: sdesmalen, c-rhodes, spatel.

address code review issues

It's not obvious what DemandedElts should actually mean for a scalable vector. How do you decide whether elements past the minimum length are actually demanded? I can think of the following possibilities:

  1. The elements beyond the minimum are always demanded
  2. The demanded elements is a repeating pattern
  3. We shouldn't use DemandedElts for scalable vectors at all.

It probably makes sense to just choose the last one until we actually have some real-world testscases that would benefit. Also saves some implementation work short-term.

Given that, it probably makes sense to only construct DemandedElts for FixedVectorTypes, and just use APInt(1, 1) for scalable vectors.

llvm/lib/Analysis/ValueTracking.cpp
1952

No reason to check Scalable; a ConstantVector is never scalable anyway.

ctetreau marked an inline comment as done.Apr 29 2020, 12:41 PM

It's not obvious what DemandedElts should actually mean for a scalable vector. How do you decide whether elements past the minimum length are actually demanded? I can think of the following possibilities:

  1. The elements beyond the minimum are always demanded
  2. The demanded elements is a repeating pattern
  3. We shouldn't use DemandedElts for scalable vectors at all.

It probably makes sense to just choose the last one until we actually have some real-world testscases that would benefit. Also saves some implementation work short-term.

Given that, it probably makes sense to only construct DemandedElts for FixedVectorTypes, and just use APInt(1, 1) for scalable vectors.

So your proposal is that for scalable vectors, DemandedElts can have any value?

llvm/lib/Analysis/ValueTracking.cpp
1952

ConstantVector::getSplat() can return a scalable ConstantVector

ctetreau marked an inline comment as done.Apr 29 2020, 12:43 PM
ctetreau marked an inline comment as done.Apr 29 2020, 12:45 PM
ctetreau added inline comments.
llvm/lib/Analysis/ValueTracking.cpp
1952

I guess it actually returns a ConstantExpr?

So your proposal is that for scalable vectors, DemandedElts can have any value?

We'd ignore the value, yes.

Probably, for the sake of assertions etc., it would make sense to require it to be APInt(1, 1), as opposed to actually making it unconstrained. But that's not really important.

llvm/lib/Analysis/ValueTracking.cpp
1952

Yes, The fact that getSplat is an API on ConstantVector is a historical accident, I think.

ctetreau updated this revision to Diff 261021.Apr 29 2020, 1:51 PM
ctetreau edited the summary of this revision. (Show Details)

address code review issues

Sorry, didn't mean to remove these reviewers. arc diff --verbatim did this to you :(

ctetreau updated this revision to Diff 261025.Apr 29 2020, 1:57 PM

fix missed code review issue

ctetreau updated this revision to Diff 261079.Apr 29 2020, 4:08 PM
ctetreau retitled this revision from [SVE] Fix invalid use of VectorType::getNumElements() in Value Tracking to [SVE] Fix invalid uses of VectorType::getNumElements().
ctetreau edited the summary of this revision. (Show Details)

fix new failure

This revision is now accepted and ready to land.Apr 29 2020, 5:40 PM
ctetreau updated this revision to Diff 261364.Apr 30 2020, 2:56 PM

split shufflevector stuff into a separate commit

ctetreau updated this revision to Diff 261572.May 1 2020, 4:15 PM
ctetreau retitled this revision from [SVE] Fix invalid uses of VectorType::getNumElements() to [SVE] Fix invalid uses of VectorType::getNumElements() in ValueTracking.
ctetreau edited the summary of this revision. (Show Details)
ctetreau removed a subscriber: david-arm.

fairly major overhaul

After spending some time considering how to deal with some breakages caused by my previous version of this patch, I've decided to change my approach.

For the most part, any function that uses a DemandedElts does not actually do the right thing for scalable vectors. An obvious bandaid that can be applied to this to do *something* is to just ignore the DemandedElts for scalable vectors and do some default behavior (such as considering the entire vector). However, I think this is dangerous because code may break if this function returns results for vector elements that the caller does not expect to get results for. Regardless, I would like to see a real fix be implemented rather than time being spent on applying many layers of band aids.

efriedma accepted this revision.May 1 2020, 5:58 PM

LGTM

I still think enabling it for scalable vectors is worth pursuing, as a relatively small amount of work; see D79264. But we probably want the other changes here anyway, so this seems fine for now.

I still think enabling it for scalable vectors is worth pursuing, as a relatively small amount of work; see D79264. But we probably want the other changes here anyway, so this seems fine for now.

I agree. I'm just saying that step 1 is to remove the broken uses of getNumElements().

ctetreau updated this revision to Diff 261829.May 4 2020, 8:20 AM

fix broken test

I recently created a patch that also hit issues with DemandedElts (https://reviews.llvm.org/D79083) in CodeGen. I pondered some of the same issues in this patch and I chose to ignore the DemandedElts values and make it work for certain cases such as SPLAT_VECTOR.

This revision was automatically updated to reflect the committed changes.