This is an archive of the discontinued LLVM Phabricator instance.

DAGCombiner: Assume invariant load cannot alias a store
ClosedPublic

Authored by arsenm on Jun 25 2015, 3:02 PM.

Details

Reviewers
hfinkel
Summary

The motivation is to allow GatherAllAliases / FindBetterChain
to not give up on dependent loads of a pointer from constant memory.

This is important for AMDGPU, because most loads are pointers
derived from a load of a kernel argument from constant memory.

Diff Detail

Event Timeline

arsenm updated this revision to Diff 28505.Jun 25 2015, 3:02 PM
arsenm retitled this revision from to DAGCombiner: Assume invariant load cannot alias a store .
arsenm updated this object.
arsenm edited the test plan for this revision. (Show Details)
arsenm added a reviewer: hfinkel.
arsenm added a subscriber: Unknown Object (MLST).

This seems to uncover another problem with FindBetterChain.

A simple case of merging 4 constants stores looks like this:

A, ch = CopyFromReg ...
B, ch = load A:1, (add A:0, ...) invariant
C = store B:1, K0, B
D = store C:1, K1, (add B, 4)
E = store D:1, K2, (add B, 8)
F = store E:1, K3, (add B, 12)

Now that the store is known to not alias the load, GatherAllAliases decides that the best chain for the store at chain F is the CopyFromReg chain, putting it on the same chain as the load. This seems broken, but I don't think it will cause any actual problems.

The store at chain C correctly remains on the chain from the load of the pointer, and the other two stores are untouched because they give up on the MemSDNode of the other stores.

However, if I only have 2 stores,
A, ch = CopyFromReg ...
B, ch = load A:1, (add A:0, ...) invariant
C = store B:1, K0, B
D = store C:1, K1, (add B, 4)

The 2nd store correctly has its chain moved to be the same as the 1st's, which is the correct chain out of the load of the pointer

reames added a subscriber: reames.Jun 26 2015, 11:38 AM
reames added inline comments.
lib/CodeGen/SelectionDAG/DAGCombiner.cpp
13821

Not sure about this, but is writeMem correct here? At least most places, we use a conservative notion for writes. i.e. it *may* write, not it *must* write. If we had an instruction which may write, but actually just reads in this context, the aliasing could be wrong.

!mayLoad might be a possibility.

13832

Is this case handled by the UseAA option below? I'd really expect it to be. Is enabling that for your target an option?

arsenm added inline comments.Jun 26 2015, 11:59 AM
lib/CodeGen/SelectionDAG/DAGCombiner.cpp
13821

The mayLoad/mayStore are properties on a MachineInstr, but these are DAG nodes which I don't think have the same concept.

13832

That's actually the source of the set of problems I'm working on now.

The short version is enabling AA results in worse code partially because of this check.

UseAA enables trying to use FindBetterChain to try to move loads and stores to the same chain, but it doesn't work very well. Pretty much all loads are dependent on the constant kernel argument load, so this fix allows it to work sometimes. However, I run into more problems from that because both the existing code in MergeConsecutiveStores assumes stores are on consecutive chains, and FindBetterChain doesn't do a great job at finding the same chain for all of the adjacent stores.

Now that the store is known to not alias the load, GatherAllAliases decides that the best chain for the store at chain F is the CopyFromReg chain, putting it on the same chain as the load. This seems broken, but I don't think it will cause any actual problems.

This patch seems to solve the problem of moving the store’s chain to the CopyFromReg’s chain by not continuing the chain search unless the chained node is a MemSDNode. This seems only break 2 tests (PPC/ppc64-align-long-double.ll and SystemZ/spill-01.ll)

hfinkel added inline comments.Jul 8 2015, 8:57 PM
lib/CodeGen/SelectionDAG/DAGCombiner.cpp
13821

The situation here is somewhat subtle. writeMem delegates to MachineMemOperand::isStore(), which checks whether the MOStore flag is set. What has this flag set? For the most part, just actual stores (trunc stores, atomic stores, etc.). However, this does include the MMOs on masked stores (which might or might not actually store anything), and also include all memory intrinsic nodes that might write to memory. The intrinsics include things like ISD::PREFETCH (which is tagged as writing for dependency reasons, but never writes anything). In short, care is required. But I think this does not hurt anything assuming you special-case ISD::PREFETCH here, so please do that.

arsenm added inline comments.Jul 10 2015, 12:38 PM
lib/CodeGen/SelectionDAG/DAGCombiner.cpp
13821

I don't think prefetch matters here. isAlias's operands are LSBaseSDNode, so this seems to only handle loads and stores. It seems ISD::PREFETCH is a MemSDNode

hfinkel accepted this revision.Jul 10 2015, 12:45 PM
hfinkel edited edge metadata.

LGTM.

lib/CodeGen/SelectionDAG/DAGCombiner.cpp
13821

Ah, okay. In that case, then yes, it does not matter here. You may want to add a comment to this effect, however, just in case someone later decides to extend isAlias to handle intrinsics too. That does not seem unlikely. I'm not insisting on it.

This revision is now accepted and ready to land.Jul 10 2015, 12:45 PM
arsenm closed this revision.Jul 10 2015, 3:18 PM

r241948