Momchil Velikov via llvm-dev
2022-Jan-05 15:56 UTC
[llvm-dev] Should MemorySSA be updated when load/store address changes ?
This is a test case from `Transforms/GVN/PRE/pre-after-rle.ll`. Before GVN, the MemorySSA beginning looks like: define void @fn1(i32** noalias %start, i32* %width, i32 %h) { entry: ; 1 = MemoryDef(liveOnEntry) %call = tail call noalias i8* @malloc(i64 1024) %call.cast = bitcast i8* %call to i32* ; 2 = MemoryDef(1) store i32* %call.cast, i32** %start, align 8 br label %preheader preheader: ; preds = %body, %entry ; 5 = MemoryPhi({entry,2},{body,3}) %cmp = icmp slt i32 1, %h br i1 %cmp, label %body, label %exit body: ; preds = %body, %preheader ; 4 = MemoryPhi({preheader,5},{body,3}) %j = phi i32 [ 0, %preheader ], [ %j.next, %body ] ; MemoryUse(2) MayAlias %s = load i32*, i32** %start, align 8 %idx = getelementptr inbounds i32, i32* %s, i64 0 ; 3 = MemoryDef(4) store i32 0, i32* %idx, align 4 %j.next = add nuw nsw i32 %j, 1 ; MemoryUse(3) MayAlias %w = load i32, i32* %width, align 8 %cmp3 = icmp slt i32 %j.next, %w br i1 %cmp3, label %body, label %preheader exit: ; preds = %preheader ret void } Note that `%w = load ...` is a `MemoryUse` of `store i32 0, i32* %idx`. After GVN has removed the fully redundant load `%s = ...`, the MemorySSA looks like: define void @fn1(i32** noalias %start, i32* %width, i32 %h) { entry: ; 1 = MemoryDef(liveOnEntry) %call = tail call noalias i8* @malloc(i64 1024) %call.cast = bitcast i8* %call to i32* ; 2 = MemoryDef(1) store i32* %call.cast, i32** %start, align 8 br label %preheader preheader: ; preds = %body, %entry ; 5 = MemoryPhi({entry,2},{body,3}) %cmp = icmp slt i32 1, %h br i1 %cmp, label %body, label %exit body: ; preds = %body, %preheader ; 4 = MemoryPhi({preheader,5},{body,3}) %j = phi i32 [ 0, %preheader ], [ %j.next, %body ] ; 3 = MemoryDef(4) store i32 0, i32* %call.cast, align 4 %j.next = add nuw nsw i32 %j, 1 ; MemoryUse(3) MayAlias %w = load i32, i32* %width, align 8 %cmp3 = icmp slt i32 %j.next, %w br i1 %cmp3, label %body, label %preheader exit: ; preds = %preheader ret void } The `%w = load ...` is still a use of the `store i32 0, i32*...`. However, the locations now can be determined to not alias, and the MemorySSA walker in fact skips `3 = MemoryDef(4)` and returns `liveOnEntry` when queried for the clobber of `%w = load ...`. So far so good, but then the `%w = load ... ` is not among the uses of `liveOnEntry`. This seems to contradict this part from the MemorySSA docs: "Unlike other partitioned forms, LLVM’s MemorySSA does make one useful guarantee - all loads are optimized to point at the thing that actually clobbers them. This gives some nice properties. For example, for a given store, you can find all loads actually clobbered by that store by walking the immediate uses of the store." Is this the intended behaviour? Should MemorySSAUpdater have an update API for when the address operands of loads/stores change? ~chill -- Compiler scrub, Arm -------------- next part -------------- An HTML attachment was scrubbed... URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20220105/67d2e1aa/attachment.html>