This is an archive of the discontinued LLVM Phabricator instance.

[NewGVN][PHIOFOPS] Relax conditions when checking safety of memory accesses
ClosedPublic

Authored by ManuelJBrito on Jul 23 2023, 7:39 AM.

Details

Summary

Currently, we consider any instruction that might read from memory to be unsafe for phi-of-ops.
This patch refines that by walking the clobbering memDefs until we either hit a block that strictly dominates the phi block (safe) or we hit a clobbering memPhi (unsafe). This is analogous to how "regular " SSA values are handled.

Diff Detail

Event Timeline

ManuelJBrito created this revision.Jul 23 2023, 7:39 AM
Herald added a project: Restricted Project. · View Herald TranscriptJul 23 2023, 7:39 AM
Herald added a subscriber: hiraditya. · View Herald Transcript
ManuelJBrito requested review of this revision.Jul 23 2023, 7:39 AM
Herald added a project: Restricted Project. · View Herald TranscriptJul 23 2023, 7:39 AM
ManuelJBrito edited the summary of this revision. (Show Details)Jul 23 2023, 7:42 AM
ManuelJBrito edited the summary of this revision. (Show Details)

We don't need to check that the memPhi is in the same block to deem it unsafe.
A clobbering memPhi that doesn't strictly dominate the original access implies that there are different versions of memory reaching the load and that using the loaded value between iterations isn't safe.

Minor simplifications and comment rewriting.

nlopes accepted this revision.Jul 26 2023, 4:57 AM

LGTM

This revision is now accepted and ready to land.Jul 26 2023, 4:57 AM

LGTM :)

llvm/lib/Transforms/Scalar/NewGVN.cpp
2649

Can you please give us more details?

In the following example, the load depends on a memory phi. But, the check in line 2651 rejects phi-of-ops optimization. This can be optimized If we do some changes in findPHIOfOpsLeader().

define i32 @mytest(ptr %p, ptr %q, i1 %cond1, i32 %TC){
entry:

br label %loop.header

loop.header:

%phi = phi i32 [0, %entry], [%ind, %loop.latch]
br i1 %cond1, label %bb1, label %bb2

bb1:

store i32 100, ptr %p
br label %loop.latch

bb2:

store i32 10, ptr %p
br label %loop.latch

loop.latch:

%phi2 = phi i32 [1, %bb1], [0, %bb2]
%ld = load i32, ptr %p
%mul = mul i32 %ld, %phi2
%ind = add i32 %phi, 1
%cond2 = icmp ule i32 %ind, %TC
br i1 %cond2, label %loop.header, label %exit

exit:

ret i32 %mul

}

kmitropoulou added inline comments.Jul 28 2023, 2:12 AM
llvm/test/Transforms/NewGVN/phi-of-ops-loads.ll
80–81

clobber?

LGTM :)

Thanks for the review!

llvm/lib/Transforms/Scalar/NewGVN.cpp
2649

This comment should really say redundant stores instead of constant, my bad. It allows us to catch the test case in storeoverstore.ll. Although ideally we shouldn't need such a hack. NewGVN should be able to remove the loads and stores and then do the phi-of-ops.
If we run NewGVN back to back it does just that.[https://godbolt.org/z/Wef4WW5ec ]

Regarding your example ideally I think this should be done by phi-translating the MemoryPhis - we currently lose a few optimizations because we don't.

What changes do you propose in findPHIOfOpsLeader()?

kmitropoulou added inline comments.Jul 28 2023, 7:07 PM
llvm/lib/Transforms/Scalar/NewGVN.cpp
2649

Can you please update the comment before you commit the patch?

It is easy to support the example that I gave you by just refining the code here. We can just read the operands of the memory phi and check if they are constants. The problem is that phi-of-ops optimization will fail because findPHIOfOpsLeader() will fail to find a leader for the new phi node. This happens because findPHIOfOpsLeader() does not have the support for this test case. Anyway, I do not think that this implementation should be part of this patch because it is a special case. My understanding is that this patch aims to be more generic.

ManuelJBrito added inline comments.Jul 30 2023, 11:11 PM
llvm/lib/Transforms/Scalar/NewGVN.cpp
2649

Will do thanks!