This is an archive of the discontinued LLVM Phabricator instance.

[LICM] Don't silently ignore constant expressions in promoteLoopAccessesToScalars()
AbandonedPublic

Authored by mkuper on Mar 7 2016, 12:18 PM.

Details

Reviewers
bruno
hfinkel
Summary

Right now, the loop that iterates over the pointers in each alias set ignores constantexpr uses of these pointers - which is unfortunate, since it misses the case where the pointer is a constant, and a constant expression that uses the pointer is present inside the loop.

I'm not too happy with this patch - it seems like there should be a simpler way to do this. Any suggestions are welcome, especially if I'm missing an obvious one.

Also, it is intentionally conservative, since it'll bail even when the constantexpr is harmless (e.g. a bitcast from i32* to float* that goes into a load). Ideally, it should probably just feed the instructions that use the constantexpr into the same loop as the rest of the pointer's users, but I'm afraid that may introduce other edge cases.

This fixes PR26843.

Diff Detail

Event Timeline

mkuper updated this revision to Diff 49985.Mar 7 2016, 12:18 PM
mkuper retitled this revision from to [LICM] Don't silently ignore constant expressions in promoteLoopAccessesToScalars().
mkuper updated this object.
mkuper added reviewers: bruno, hfinkel.
mkuper added a subscriber: llvm-commits.
reames added a subscriber: reames.Mar 11 2016, 5:17 PM

I'm a bit confused by this patch. Specifically, it looks like you're expecting ASIV to be @v, whereas the pointer being used is actually "i32* getelementptr inbounds ([4 x i32], [4 x i32]* @v" which should be handled perfectly fine by the loop promotion code. I feel like you've probably misidentified the issue, but I can't tell from your test case what the actually issue is.

Can you explain a bit of your reasoning by which you arrived at this patch?

As a guess, are you possibly seeing @v and "i32* getelementptr inbounds ([4 x i32], [4 x i32]* @v" in a single must alias alias set? If so, that would be a bug somewhere in the aliasing because those two are not must alias.

@sanjoy - That looks possible. I'd need to see a dump of the alias sets to see for sure.

mkuper added a comment.EditedMar 11 2016, 5:49 PM

Thanks for looking at it, Philip and Sanjoy.

For the test case, there's a single value in the alias set:

Alias Set Tracker: 1 alias sets for 1 pointer values.
  AliasSet[0xa0b5d8, 1] must alias, Mod       Pointers: (i32* getelementptr inbounds ([4 x i32], [4 x i32]* @v, i32 0, i32 1), 12)

The constant expr that seems to confuse LICM isn't the GEP, it's the bitcast.
Actually, it's possible the GEP is just noise. I'd expect the same to happen when directly bitcasting from @v. I'll check, and simplify the test if that's the case.

Ah, that was really helpful. This is definitely an AST bug.
"bitcast (i32* getelementptr inbounds ([4 x i32], [4 x i32]* @v, i32 0, i32 1) to i8*" and "getelementptr inbounds ([4 x i32], [4 x i32]* @v, i32 0, i32 1)" are the same address and thus must be must alias. Both of them should be appearing in the alias set. The fact they're not is very surprising.

mkuper abandoned this revision.Mar 11 2016, 6:19 PM

It was so surprising that I figured AST ignores these bitcasts intentionally, and expects the clients to handle them.
Abandoning this patch, I'll look into what's going on in AST.

Ah, that was really helpful. This is definitely an AST bug.
"bitcast (i32* getelementptr inbounds ([4 x i32], [4 x i32]* @v, i32 0, i32 1) to i8*" and "getelementptr inbounds ([4 x i32], [4 x i32]* @v, i32 0, i32 1)" are the same address and thus must be must alias. Both of them should be appearing in the alias set. The fact they're not is very surprising.

The problem is that AST calls MemIntrinsic::getDest to get the pointer it should add, which returns the pointer after stripPointerCasts (though I'm not convinced (either way) that differentiating x and (bitcast x to Y) in AST is a good idea, since they're the same value at runtime).

Well, apparently it does differentiate them when MemIntrinsics are not involved.
E.g. if the memcpy were a store, we'd get:

AliasSet[0x6ad8c0, 2] must alias, Mod       Pointers: (i32* getelementptr inbounds ([4 x i32], [4 x i32]* @v, i32 0, i32 1), 4), (i8* bitcast (i32* getelementptr inbounds ([4 x i32], [4 x i32]* @v, i32 0, i32 1) to i8*), 1)

So we have to be consistent, at least.

The easiest answer is probably to use getRawDest. The use of the stripPointerCasts is inconsistent with the rest of AST and LICM.

Yeah, I'll just change it to getRawDest().
Turns out the code that handles memset this way is new, so now I doubt there's any code elsewhere that expects pointer casts to be missing.