This is an archive of the discontinued LLVM Phabricator instance.

[Reassociate] Convert shl by constant into multiply during tree linearization.
AbandonedPublic

Authored by mcrosier on Feb 9 2017, 11:14 AM.

Details

Summary

If we're linearizing a multiply expression, convert any left shift by a constant into a multiply, so they can be reassociated. We already do a similar optimization where we convert a negation into a multiply by -1.

See the test case for an example of what this hits.

Also, this addresses PR30256, which is a 4.0 release blocker.

Chad

Diff Detail

Event Timeline

mcrosier created this revision.Feb 9 2017, 11:14 AM
mcrosier added a subscriber: hans.Feb 9 2017, 11:21 AM
gberry added a subscriber: gberry.Feb 9 2017, 11:39 AM

BTW, I'll be on vacation starting this afternoon and won't be returning until the 20th. In my absence, I'll have someone on my team follow up on this patch since it's a release blocker and we need to get a fix in for PR30256.

mssimpso edited edge metadata.Feb 9 2017, 12:15 PM

Chad,

This change looks good to me, but I'm not familiar enough with reassociation to approve. Maybe @majnemer can? Thanks!

hans added a comment.Feb 14 2017, 11:09 AM

What's the status here?

The patch is still awaiting approval. I'm hoping we can get more eyes on this because, although it looks good to me, I don't think I know this code well enough to approve. Has anyone else had a chance to look?

Ping. This is a fix for a release blocker (PR30256).

Unfortunately, Reassociation doesn't have a code owner, but this should be fairly simple to understand.

Add a few more reviewers.

efriedma edited edge metadata.Feb 21 2017, 12:03 PM

I'm not following why this fixes the crash. As far as I can tell, on trunk, Reassociate special-cases shl instructions in exactly one place: the check at the beginning of ReassociatePass::OptimizeInst. In that case, we replace all the uses of the shl instruction, so it shouldn't matter. (I'd like an answer to this to make sure you aren't papering over a real problem.)

lib/Transforms/Scalar/Reassociate.cpp
371

Why don't we don't erase the dead Shl here?

chandlerc edited edge metadata.Feb 21 2017, 1:44 PM

Some longer term comments here, but all of this seems reasonably in-line with how we currently do things in reassociate, but raises some long-standing issues in a potentially more concerning area.

I also think Eli's comment is important.

lib/Transforms/Scalar/Reassociate.cpp
597–598

I'm OK doing this temporarily if we need to, but we should have a FIXME to revisit this.

  • Does this create an endless cycle between reassociate and instcombine? That seems bad
  • Can we just synthesize this by teaching the reassociation itself to magically treat shifts of this form as-if they were multiplies and transforming them as necessary on the fly?
  • Alternatively, can we add some strong assurance that if we don't reassociate, we transform everything back to a shl afterward? Maybe test cases for interesting expression trees where we put everything into multiply form and then back?

Essentially, all of this is that we somehow need this to not leak out of reassociate in the cases where we don't change anything (or we need to change our canonicalization).

I'm not following why this fixes the crash. As far as I can tell, on trunk, Reassociate special-cases shl instructions in exactly one place: the check at the beginning of ReassociatePass::OptimizeInst. In that case, we replace all the uses of the shl instruction, so it shouldn't matter.

The convert only occurs if the Shl is feeding a Mul or an Add. In my test case, the Shl is feeding a negation. D30223 is an alternative solution that has the same result.

(I'd like an answer to this to make sure you aren't papering over a real problem.)

This fixes PR30256 by avoiding the particular case that is causing the assert. However, I think the underlying issue is that if a factor is a negative constant, we consider the positive value as a factor as well (because we can percolate the negate out). Thus, I think this patch does kinda papers over the issue, but I can also argue it's a reasonable optimization..

I think I've just come up with a patch that can more directly address the underlying issue.. Let me post that before we continue the review here.

lib/Transforms/Scalar/Reassociate.cpp
371

I believe this is to avoid an iterator invalidation bug (but I could be mistaken).

In the current code, the Shl is inserted into the RedoInsts list after the call to ConvertShiftToMul. This will ensure the Shl is removed as dead code. I should do the same for my code (or alternatively pass in the RedoInsts into ConvertShiftToMul and insert the Shl into RedoInsts directly in CovertShiftToMul).

Some longer term comments here, but all of this seems reasonably in-line with how we currently do things in reassociate, but raises some long-standing issues in a potentially more concerning area.

After thinking a bit and discussing this with Eli, this patch (and D30223) really are just papering over the issue. See Eli's comments in D30228 for a good description of what's going on; D30228 also directly address the problem.

mcrosier added inline comments.Feb 22 2017, 5:40 AM
lib/Transforms/Scalar/Reassociate.cpp
597–598

Yes, reassociation relies on instcombine to undo the canonicalizations that enable reassocation performed in this pass. While I'm likely going to abandon this patch in favor of D30228, I wanted to acknowledge that I agree with Chandler's comments. Specifically, we should improve reassociate to only perform these type of transforms when we know reassociation will be successful. Of course that is much easier said than done.

mcrosier abandoned this revision.Feb 23 2017, 11:49 AM

Abandon in favor of rL296003.