Geoff Berry via llvm-dev
2016-Apr-29 21:55 UTC
[llvm-dev] [MemorySSA] Potential CachingMemorySSAWalker bug
Hi guys, I think I have run into another CachingMemorySSAWalker cache bug. It's a bit tricky to reproduce, so I'd like to start by trying to show you what is happening when running EarlyCSE with my local changes to use MemorySSA. I've attached a debug log that shows that the value returned by getClobberingMemoryAccess(Inst) after a call to removeMemoryAccess is wrong. The MemorySSA node in question is MemoryUse(7), and the corruption happens after a call to remove MemoryUse(2), at which point its clobber value changes to '1 = MemoryDef(liveOnEntry)'. The interesting thing is that is doesn't seem to be the first call to getClobberingMemoryAccess after the removal that causes the corruption, but rather the second. You'll notice that I added calls to getClobberingMemoryAccess when doing MSSA.dump(), which is what I'm using to attempt to figure out when the cache gets corrupted. Hopefully this is enough information to debug the problem. If not perhaps we can look at getting my EarlyCSE changes checked in in a disabled state so you can reproduce the problem directly. I'm also happy to help debug it farther. -- Geoff Berry Employee of Qualcomm Innovation Center, Inc. Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, a Linux Foundation Collaborative Project -------------- next part -------------- An HTML attachment was scrubbed... URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20160429/f4c64f9b/attachment.html> -------------- next part -------------- ; opt -early-cse -S < LoadShorts-simple2.ll target triple = "aarch64--linux-gnu" %S1 = type { i32, i32, i16, i16, i8, i8 } define void @test() { entry: %call1 = call noalias i8* @malloc() %0 = bitcast i8* %call1 to %S1* %ui = getelementptr inbounds %S1, %S1* %0, i32 0, i32 0 store i32 undef, i32* %ui, align 4 %us = getelementptr inbounds %S1, %S1* %0, i32 0, i32 2 store i16 undef, i16* %us, align 4 %s = getelementptr inbounds %S1, %S1* %0, i32 0, i32 3 store i16 undef, i16* %s, align 2 %ub = getelementptr inbounds %S1, %S1* %0, i32 0, i32 4 store i8 undef, i8* %ub, align 4 %b = getelementptr inbounds %S1, %S1* %0, i32 0, i32 5 store i8 undef, i8* %b, align 1 %ui8 = getelementptr inbounds %S1, %S1* %0, i32 0, i32 0 %1 = load i32, i32* %ui8, align 4 %ui9 = getelementptr inbounds %S1, %S1* %0, i32 0, i32 0 %ui11 = getelementptr inbounds %S1, %S1* %0, i32 0, i32 0 call void @foo(i32 %1) %ui15 = getelementptr inbounds %S1, %S1* %0, i32 0, i32 0 %ui16 = getelementptr inbounds %S1, %S1* %0, i32 0, i32 0 %ui17 = getelementptr inbounds %S1, %S1* %0, i32 0, i32 0 %ui18 = getelementptr inbounds %S1, %S1* %0, i32 0, i32 0 %ui20 = getelementptr inbounds %S1, %S1* %0, i32 0, i32 0 %ui22 = getelementptr inbounds %S1, %S1* %0, i32 0, i32 0 %i26 = getelementptr inbounds %S1, %S1* %0, i32 0, i32 1 %i27 = getelementptr inbounds %S1, %S1* %0, i32 0, i32 1 %2 = load i32, i32* %i27, align 4 %i28 = getelementptr inbounds %S1, %S1* %0, i32 0, i32 1 %3 = load i32, i32* %i28, align 4 %conv29 = sext i32 %3 to i64 call void @foo(i32 %2) %i35 = getelementptr inbounds %S1, %S1* %0, i32 0, i32 1 %i36 = getelementptr inbounds %S1, %S1* %0, i32 0, i32 1 %i39 = getelementptr inbounds %S1, %S1* %0, i32 0, i32 1 %i41 = getelementptr inbounds %S1, %S1* %0, i32 0, i32 1 %i44 = getelementptr inbounds %S1, %S1* %0, i32 0, i32 1 ret void } declare noalias i8* @malloc() declare void @foo(i32) -------------- next part -------------- Args: ./install-memssa-earlycse/bin/opt -early-cse -S -debug Features: CPU:generic EarlyCSE CSE: %ui8 = getelementptr inbounds %S1, %S1* %0, i32 0, i32 0 to: %ui = getelementptr inbounds %S1, %S1* %0, i32 0, i32 0 Starting Memory SSA clobber for %1 = load i32, i32* %ui, align 4 is 6 = MemoryDef(5) Final Memory SSA clobber for %1 = load i32, i32* %ui, align 4 is 2 = MemoryDef(1) Starting Memory SSA clobber for %2 = load i32, i32* %i27, align 4 is 7 = MemoryDef(6) Final Memory SSA clobber for %2 = load i32, i32* %i27, align 4 is 7 = MemoryDef(6) Starting Memory SSA clobber for %3 = load i32, i32* %i28, align 4 is 7 = MemoryDef(6) Final Memory SSA clobber for %3 = load i32, i32* %i28, align 4 is 7 = MemoryDef(6) After call to getClobberingMemoryAccess(Inst): %1 = load i32, i32* %ui, align 4 define void @test() { entry: ; 1 = MemoryDef(liveOnEntry); clobber: 0 = MemoryDef(liveOnEntry) %call1 = call noalias i8* @malloc() %0 = bitcast i8* %call1 to %S1* %ui = getelementptr inbounds %S1, %S1* %0, i32 0, i32 0 Starting Memory SSA clobber for store i32 undef, i32* %ui, align 4 is 1 = MemoryDef(liveOnEntry) Final Memory SSA clobber for store i32 undef, i32* %ui, align 4 is 1 = MemoryDef(liveOnEntry) ; 2 = MemoryDef(1); clobber: 1 = MemoryDef(liveOnEntry) store i32 undef, i32* %ui, align 4 %us = getelementptr inbounds %S1, %S1* %0, i32 0, i32 2 Starting Memory SSA clobber for store i16 undef, i16* %us, align 4 is 2 = MemoryDef(1) Final Memory SSA clobber for store i16 undef, i16* %us, align 4 is 1 = MemoryDef(liveOnEntry) ; 3 = MemoryDef(2); clobber: 1 = MemoryDef(liveOnEntry) store i16 undef, i16* %us, align 4 %s = getelementptr inbounds %S1, %S1* %0, i32 0, i32 3 Starting Memory SSA clobber for store i16 undef, i16* %s, align 2 is 3 = MemoryDef(2) Final Memory SSA clobber for store i16 undef, i16* %s, align 2 is 1 = MemoryDef(liveOnEntry) ; 4 = MemoryDef(3); clobber: 1 = MemoryDef(liveOnEntry) store i16 undef, i16* %s, align 2 %ub = getelementptr inbounds %S1, %S1* %0, i32 0, i32 4 Starting Memory SSA clobber for store i8 undef, i8* %ub, align 4 is 4 = MemoryDef(3) Final Memory SSA clobber for store i8 undef, i8* %ub, align 4 is 1 = MemoryDef(liveOnEntry) ; 5 = MemoryDef(4); clobber: 1 = MemoryDef(liveOnEntry) store i8 undef, i8* %ub, align 4 %b = getelementptr inbounds %S1, %S1* %0, i32 0, i32 5 Starting Memory SSA clobber for store i8 undef, i8* %b, align 1 is 5 = MemoryDef(4) Final Memory SSA clobber for store i8 undef, i8* %b, align 1 is 1 = MemoryDef(liveOnEntry) ; 6 = MemoryDef(5); clobber: 1 = MemoryDef(liveOnEntry) store i8 undef, i8* %b, align 1 ; MemoryUse(2); clobber: 2 = MemoryDef(1) %1 = load i32, i32* %ui, align 4 %ui9 = getelementptr inbounds %S1, %S1* %0, i32 0, i32 0 %ui11 = getelementptr inbounds %S1, %S1* %0, i32 0, i32 0 Starting Memory SSA clobber for call void @foo(i32 %1) is 6 = MemoryDef(5) Final Memory SSA clobber for call void @foo(i32 %1) is 6 = MemoryDef(5) ; 7 = MemoryDef(6); clobber: 6 = MemoryDef(5) call void @foo(i32 %1) %ui15 = getelementptr inbounds %S1, %S1* %0, i32 0, i32 0 %ui16 = getelementptr inbounds %S1, %S1* %0, i32 0, i32 0 %ui17 = getelementptr inbounds %S1, %S1* %0, i32 0, i32 0 %ui18 = getelementptr inbounds %S1, %S1* %0, i32 0, i32 0 %ui20 = getelementptr inbounds %S1, %S1* %0, i32 0, i32 0 %ui22 = getelementptr inbounds %S1, %S1* %0, i32 0, i32 0 %i26 = getelementptr inbounds %S1, %S1* %0, i32 0, i32 1 %i27 = getelementptr inbounds %S1, %S1* %0, i32 0, i32 1 ; MemoryUse(7); clobber: 7 = MemoryDef(6) %2 = load i32, i32* %i27, align 4 %i28 = getelementptr inbounds %S1, %S1* %0, i32 0, i32 1 ; MemoryUse(7); clobber: 7 = MemoryDef(6) %3 = load i32, i32* %i28, align 4 %conv29 = sext i32 %3 to i64 Starting Memory SSA clobber for call void @foo(i32 %2) is 7 = MemoryDef(6) Final Memory SSA clobber for call void @foo(i32 %2) is 7 = MemoryDef(6) ; 8 = MemoryDef(7); clobber: 7 = MemoryDef(6) call void @foo(i32 %2) %i35 = getelementptr inbounds %S1, %S1* %0, i32 0, i32 1 %i36 = getelementptr inbounds %S1, %S1* %0, i32 0, i32 1 %i39 = getelementptr inbounds %S1, %S1* %0, i32 0, i32 1 %i41 = getelementptr inbounds %S1, %S1* %0, i32 0, i32 1 %i44 = getelementptr inbounds %S1, %S1* %0, i32 0, i32 1 ret void } isSameMemGeneration: EarlierInst: store i32 undef, i32* %ui, align 4 LaterInst: %1 = load i32, i32* %ui, align 4 LaterHeapGen: 2 = MemoryDef(1) EarlierMA: 2 = MemoryDef(1) EarlyCSE CSE LOAD: %1 = load i32, i32* %ui, align 4 to: store i32 undef, i32* %ui, align 4 define void @test() { entry: ; 1 = MemoryDef(liveOnEntry); clobber: 0 = MemoryDef(liveOnEntry) %call1 = call noalias i8* @malloc() %0 = bitcast i8* %call1 to %S1* %ui = getelementptr inbounds %S1, %S1* %0, i32 0, i32 0 ; 2 = MemoryDef(1); clobber: 1 = MemoryDef(liveOnEntry) store i32 undef, i32* %ui, align 4 %us = getelementptr inbounds %S1, %S1* %0, i32 0, i32 2 ; 3 = MemoryDef(2); clobber: 1 = MemoryDef(liveOnEntry) store i16 undef, i16* %us, align 4 %s = getelementptr inbounds %S1, %S1* %0, i32 0, i32 3 ; 4 = MemoryDef(3); clobber: 1 = MemoryDef(liveOnEntry) store i16 undef, i16* %s, align 2 %ub = getelementptr inbounds %S1, %S1* %0, i32 0, i32 4 ; 5 = MemoryDef(4); clobber: 1 = MemoryDef(liveOnEntry) store i8 undef, i8* %ub, align 4 %b = getelementptr inbounds %S1, %S1* %0, i32 0, i32 5 ; 6 = MemoryDef(5); clobber: 1 = MemoryDef(liveOnEntry) store i8 undef, i8* %b, align 1 ; MemoryUse(2); clobber: 2 = MemoryDef(1) %1 = load i32, i32* %ui, align 4 %ui9 = getelementptr inbounds %S1, %S1* %0, i32 0, i32 0 %ui11 = getelementptr inbounds %S1, %S1* %0, i32 0, i32 0 ; 7 = MemoryDef(6); clobber: 6 = MemoryDef(5) call void @foo(i32 undef) %ui15 = getelementptr inbounds %S1, %S1* %0, i32 0, i32 0 %ui16 = getelementptr inbounds %S1, %S1* %0, i32 0, i32 0 %ui17 = getelementptr inbounds %S1, %S1* %0, i32 0, i32 0 %ui18 = getelementptr inbounds %S1, %S1* %0, i32 0, i32 0 %ui20 = getelementptr inbounds %S1, %S1* %0, i32 0, i32 0 %ui22 = getelementptr inbounds %S1, %S1* %0, i32 0, i32 0 %i26 = getelementptr inbounds %S1, %S1* %0, i32 0, i32 1 %i27 = getelementptr inbounds %S1, %S1* %0, i32 0, i32 1 ; MemoryUse(7); clobber: 7 = MemoryDef(6) %2 = load i32, i32* %i27, align 4 %i28 = getelementptr inbounds %S1, %S1* %0, i32 0, i32 1 ; MemoryUse(7); clobber: 7 = MemoryDef(6) %3 = load i32, i32* %i28, align 4 %conv29 = sext i32 %3 to i64 ; 8 = MemoryDef(7); clobber: 7 = MemoryDef(6) call void @foo(i32 %2) %i35 = getelementptr inbounds %S1, %S1* %0, i32 0, i32 1 %i36 = getelementptr inbounds %S1, %S1* %0, i32 0, i32 1 %i39 = getelementptr inbounds %S1, %S1* %0, i32 0, i32 1 %i41 = getelementptr inbounds %S1, %S1* %0, i32 0, i32 1 %i44 = getelementptr inbounds %S1, %S1* %0, i32 0, i32 1 ret void } Removing MemoryUse(2) define void @test() { entry: ; 1 = MemoryDef(liveOnEntry); clobber: 0 = MemoryDef(liveOnEntry) %call1 = call noalias i8* @malloc() %0 = bitcast i8* %call1 to %S1* %ui = getelementptr inbounds %S1, %S1* %0, i32 0, i32 0 ; 2 = MemoryDef(1); clobber: 1 = MemoryDef(liveOnEntry) store i32 undef, i32* %ui, align 4 %us = getelementptr inbounds %S1, %S1* %0, i32 0, i32 2 ; 3 = MemoryDef(2); clobber: 1 = MemoryDef(liveOnEntry) store i16 undef, i16* %us, align 4 %s = getelementptr inbounds %S1, %S1* %0, i32 0, i32 3 ; 4 = MemoryDef(3); clobber: 1 = MemoryDef(liveOnEntry) store i16 undef, i16* %s, align 2 %ub = getelementptr inbounds %S1, %S1* %0, i32 0, i32 4 ; 5 = MemoryDef(4); clobber: 1 = MemoryDef(liveOnEntry) store i8 undef, i8* %ub, align 4 %b = getelementptr inbounds %S1, %S1* %0, i32 0, i32 5 ; 6 = MemoryDef(5); clobber: 1 = MemoryDef(liveOnEntry) store i8 undef, i8* %b, align 1 %1 = load i32, i32* %ui, align 4 %ui9 = getelementptr inbounds %S1, %S1* %0, i32 0, i32 0 %ui11 = getelementptr inbounds %S1, %S1* %0, i32 0, i32 0 ; 7 = MemoryDef(6); clobber: 6 = MemoryDef(5) call void @foo(i32 undef) %ui15 = getelementptr inbounds %S1, %S1* %0, i32 0, i32 0 %ui16 = getelementptr inbounds %S1, %S1* %0, i32 0, i32 0 %ui17 = getelementptr inbounds %S1, %S1* %0, i32 0, i32 0 %ui18 = getelementptr inbounds %S1, %S1* %0, i32 0, i32 0 %ui20 = getelementptr inbounds %S1, %S1* %0, i32 0, i32 0 %ui22 = getelementptr inbounds %S1, %S1* %0, i32 0, i32 0 %i26 = getelementptr inbounds %S1, %S1* %0, i32 0, i32 1 %i27 = getelementptr inbounds %S1, %S1* %0, i32 0, i32 1 ; MemoryUse(7); clobber: 7 = MemoryDef(6) %2 = load i32, i32* %i27, align 4 %i28 = getelementptr inbounds %S1, %S1* %0, i32 0, i32 1 ; MemoryUse(7); clobber: 7 = MemoryDef(6) %3 = load i32, i32* %i28, align 4 %conv29 = sext i32 %3 to i64 ; 8 = MemoryDef(7); clobber: 7 = MemoryDef(6) call void @foo(i32 %2) %i35 = getelementptr inbounds %S1, %S1* %0, i32 0, i32 1 %i36 = getelementptr inbounds %S1, %S1* %0, i32 0, i32 1 %i39 = getelementptr inbounds %S1, %S1* %0, i32 0, i32 1 %i41 = getelementptr inbounds %S1, %S1* %0, i32 0, i32 1 %i44 = getelementptr inbounds %S1, %S1* %0, i32 0, i32 1 ret void } EarlyCSE DCE: %ui9 = getelementptr inbounds %S1, %S1* %0, i32 0, i32 0 EarlyCSE DCE: %ui11 = getelementptr inbounds %S1, %S1* %0, i32 0, i32 0 EarlyCSE DCE: %ui15 = getelementptr inbounds %S1, %S1* %0, i32 0, i32 0 EarlyCSE DCE: %ui16 = getelementptr inbounds %S1, %S1* %0, i32 0, i32 0 EarlyCSE DCE: %ui17 = getelementptr inbounds %S1, %S1* %0, i32 0, i32 0 EarlyCSE DCE: %ui18 = getelementptr inbounds %S1, %S1* %0, i32 0, i32 0 EarlyCSE DCE: %ui20 = getelementptr inbounds %S1, %S1* %0, i32 0, i32 0 EarlyCSE DCE: %ui22 = getelementptr inbounds %S1, %S1* %0, i32 0, i32 0 EarlyCSE DCE: %i26 = getelementptr inbounds %S1, %S1* %0, i32 0, i32 1 EarlyCSE CSE: %i28 = getelementptr inbounds %S1, %S1* %0, i32 0, i32 1 to: %i27 = getelementptr inbounds %S1, %S1* %0, i32 0, i32 1 Starting Memory SSA clobber for %2 = load i32, i32* %i27, align 4 is 7 = MemoryDef(6) Final Memory SSA clobber for %2 = load i32, i32* %i27, align 4 is 1 = MemoryDef(liveOnEntry) After call to getClobberingMemoryAccess(Inst): %2 = load i32, i32* %i27, align 4 define void @test() { entry: ; 1 = MemoryDef(liveOnEntry); clobber: 0 = MemoryDef(liveOnEntry) %call1 = call noalias i8* @malloc() %0 = bitcast i8* %call1 to %S1* %ui = getelementptr inbounds %S1, %S1* %0, i32 0, i32 0 ; 2 = MemoryDef(1); clobber: 1 = MemoryDef(liveOnEntry) store i32 undef, i32* %ui, align 4 %us = getelementptr inbounds %S1, %S1* %0, i32 0, i32 2 ; 3 = MemoryDef(2); clobber: 1 = MemoryDef(liveOnEntry) store i16 undef, i16* %us, align 4 %s = getelementptr inbounds %S1, %S1* %0, i32 0, i32 3 ; 4 = MemoryDef(3); clobber: 1 = MemoryDef(liveOnEntry) store i16 undef, i16* %s, align 2 %ub = getelementptr inbounds %S1, %S1* %0, i32 0, i32 4 ; 5 = MemoryDef(4); clobber: 1 = MemoryDef(liveOnEntry) store i8 undef, i8* %ub, align 4 %b = getelementptr inbounds %S1, %S1* %0, i32 0, i32 5 ; 6 = MemoryDef(5); clobber: 1 = MemoryDef(liveOnEntry) store i8 undef, i8* %b, align 1 ; 7 = MemoryDef(6); clobber: 6 = MemoryDef(5) call void @foo(i32 undef) %i27 = getelementptr inbounds %S1, %S1* %0, i32 0, i32 1 ; MemoryUse(7); clobber: 7 = MemoryDef(6) %1 = load i32, i32* %i27, align 4 ; MemoryUse(7); clobber: 1 = MemoryDef(liveOnEntry) %2 = load i32, i32* %i27, align 4 %conv29 = sext i32 %2 to i64 ; 8 = MemoryDef(7); clobber: 7 = MemoryDef(6) call void @foo(i32 %1) %i35 = getelementptr inbounds %S1, %S1* %0, i32 0, i32 1 %i36 = getelementptr inbounds %S1, %S1* %0, i32 0, i32 1 %i39 = getelementptr inbounds %S1, %S1* %0, i32 0, i32 1 %i41 = getelementptr inbounds %S1, %S1* %0, i32 0, i32 1 %i44 = getelementptr inbounds %S1, %S1* %0, i32 0, i32 1 ret void } isSameMemGeneration: EarlierInst: %1 = load i32, i32* %i27, align 4 LaterInst: %2 = load i32, i32* %i27, align 4 LaterHeapGen: 1 = MemoryDef(liveOnEntry) EarlierMA: MemoryUse(7) After call to getClobberingMemoryAccess(Inst): %1 = load i32, i32* %i27, align 4 define void @test() { entry: ; 1 = MemoryDef(liveOnEntry); clobber: 0 = MemoryDef(liveOnEntry) %call1 = call noalias i8* @malloc() %0 = bitcast i8* %call1 to %S1* %ui = getelementptr inbounds %S1, %S1* %0, i32 0, i32 0 ; 2 = MemoryDef(1); clobber: 1 = MemoryDef(liveOnEntry) store i32 undef, i32* %ui, align 4 %us = getelementptr inbounds %S1, %S1* %0, i32 0, i32 2 ; 3 = MemoryDef(2); clobber: 1 = MemoryDef(liveOnEntry) store i16 undef, i16* %us, align 4 %s = getelementptr inbounds %S1, %S1* %0, i32 0, i32 3 ; 4 = MemoryDef(3); clobber: 1 = MemoryDef(liveOnEntry) store i16 undef, i16* %s, align 2 %ub = getelementptr inbounds %S1, %S1* %0, i32 0, i32 4 ; 5 = MemoryDef(4); clobber: 1 = MemoryDef(liveOnEntry) store i8 undef, i8* %ub, align 4 %b = getelementptr inbounds %S1, %S1* %0, i32 0, i32 5 ; 6 = MemoryDef(5); clobber: 1 = MemoryDef(liveOnEntry) store i8 undef, i8* %b, align 1 ; 7 = MemoryDef(6); clobber: 6 = MemoryDef(5) call void @foo(i32 undef) %i27 = getelementptr inbounds %S1, %S1* %0, i32 0, i32 1 ; MemoryUse(7); clobber: 7 = MemoryDef(6) %1 = load i32, i32* %i27, align 4 ; MemoryUse(7); clobber: 1 = MemoryDef(liveOnEntry) %2 = load i32, i32* %i27, align 4 %conv29 = sext i32 %2 to i64 ; 8 = MemoryDef(7); clobber: 7 = MemoryDef(6) call void @foo(i32 %1) %i35 = getelementptr inbounds %S1, %S1* %0, i32 0, i32 1 %i36 = getelementptr inbounds %S1, %S1* %0, i32 0, i32 1 %i39 = getelementptr inbounds %S1, %S1* %0, i32 0, i32 1 %i41 = getelementptr inbounds %S1, %S1* %0, i32 0, i32 1 %i44 = getelementptr inbounds %S1, %S1* %0, i32 0, i32 1 ret void } EarlierHeapGen: 7 = MemoryDef(6) define void @test() { entry: ; 1 = MemoryDef(liveOnEntry); clobber: 0 = MemoryDef(liveOnEntry) %call1 = call noalias i8* @malloc() %0 = bitcast i8* %call1 to %S1* %ui = getelementptr inbounds %S1, %S1* %0, i32 0, i32 0 ; 2 = MemoryDef(1); clobber: 1 = MemoryDef(liveOnEntry) store i32 undef, i32* %ui, align 4 %us = getelementptr inbounds %S1, %S1* %0, i32 0, i32 2 ; 3 = MemoryDef(2); clobber: 1 = MemoryDef(liveOnEntry) store i16 undef, i16* %us, align 4 %s = getelementptr inbounds %S1, %S1* %0, i32 0, i32 3 ; 4 = MemoryDef(3); clobber: 1 = MemoryDef(liveOnEntry) store i16 undef, i16* %s, align 2 %ub = getelementptr inbounds %S1, %S1* %0, i32 0, i32 4 ; 5 = MemoryDef(4); clobber: 1 = MemoryDef(liveOnEntry) store i8 undef, i8* %ub, align 4 %b = getelementptr inbounds %S1, %S1* %0, i32 0, i32 5 ; 6 = MemoryDef(5); clobber: 1 = MemoryDef(liveOnEntry) store i8 undef, i8* %b, align 1 ; 7 = MemoryDef(6); clobber: 6 = MemoryDef(5) call void @foo(i32 undef) %i27 = getelementptr inbounds %S1, %S1* %0, i32 0, i32 1 ; MemoryUse(7); clobber: 7 = MemoryDef(6) %1 = load i32, i32* %i27, align 4 ; MemoryUse(7); clobber: 1 = MemoryDef(liveOnEntry) %2 = load i32, i32* %i27, align 4 %conv29 = sext i32 %2 to i64 ; 8 = MemoryDef(7); clobber: 7 = MemoryDef(6) call void @foo(i32 %1) %i35 = getelementptr inbounds %S1, %S1* %0, i32 0, i32 1 %i36 = getelementptr inbounds %S1, %S1* %0, i32 0, i32 1 %i39 = getelementptr inbounds %S1, %S1* %0, i32 0, i32 1 %i41 = getelementptr inbounds %S1, %S1* %0, i32 0, i32 1 %i44 = getelementptr inbounds %S1, %S1* %0, i32 0, i32 1 ret void } opt: /usr2/gberry/local/astar-regress/llvm/lib/Transforms/Scalar/EarlyCSE.cpp:613: bool (anonymous namespace)::EarlyCSE::isSameMemGeneration(unsigned int, unsigned int, llvm::Instruction *, llvm::Instruction *, bool): Assertion `EarlierGeneration != LaterGeneration' failed. 0 opt 0x000000000180f548 llvm::sys::PrintStackTrace(llvm::raw_ostream&) + 40 1 opt 0x000000000180dd36 llvm::sys::RunSignalHandlers() + 54 2 opt 0x0000000001810076 3 libpthread.so.0 0x00007fec79cb8cb0 4 libc.so.6 0x00007fec78e7d0d5 gsignal + 53 5 libc.so.6 0x00007fec78e8083b abort + 379 6 libc.so.6 0x00007fec78e75d9e 7 libc.so.6 0x00007fec78e75e42 8 opt 0x000000000166f5dd 9 opt 0x000000000166c7d5 10 opt 0x0000000001669dc5 11 opt 0x000000000166acce 12 opt 0x0000000001433148 llvm::FPPassManager::runOnFunction(llvm::Function&) + 344 13 opt 0x000000000143338b llvm::FPPassManager::runOnModule(llvm::Module&) + 43 14 opt 0x0000000001433848 llvm::legacy::PassManagerImpl::run(llvm::Module&) + 872 15 opt 0x0000000000642722 main + 9282 16 libc.so.6 0x00007fec78e6876d __libc_start_main + 237 17 opt 0x000000000062e18d Stack dump: 0. Program arguments: ./install-memssa-earlycse/bin/opt -early-cse -S -debug 1. Running pass 'Function Pass Manager' on module '<stdin>'. 2. Running pass 'Early CSE' on function '@test'
George Burgess IV via llvm-dev
2016-May-02 18:16 UTC
[llvm-dev] [MemorySSA] Potential CachingMemorySSAWalker bug
Yeah, that sounds like a fun bug. I'll take a look later today and see what I can find out. :) On Fri, Apr 29, 2016 at 2:55 PM, Geoff Berry <gberry at codeaurora.org> wrote:> Hi guys, > > I think I have run into another CachingMemorySSAWalker cache bug. It's a > bit tricky to reproduce, so I'd like to start by trying to show you what is > happening when running EarlyCSE with my local changes to use MemorySSA. > I've attached a debug log that shows that the value returned by > getClobberingMemoryAccess(Inst) after a call to removeMemoryAccess is > wrong. The MemorySSA node in question is MemoryUse(7), and the corruption > happens after a call to remove MemoryUse(2), at which point its clobber > value changes to '1 = MemoryDef(liveOnEntry)'. The interesting thing is > that is doesn't seem to be the first call to getClobberingMemoryAccess > after the removal that causes the corruption, but rather the second. > You'll notice that I added calls to getClobberingMemoryAccess when doing > MSSA.dump(), which is what I'm using to attempt to figure out when the > cache gets corrupted. > Hopefully this is enough information to debug the problem. If not perhaps > we can look at getting my EarlyCSE changes checked in in a disabled state > so you can reproduce the problem directly. I'm also happy to help debug it > farther. > > -- > Geoff Berry > Employee of Qualcomm Innovation Center, Inc. > Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, a Linux Foundation Collaborative Project > >-------------- next part -------------- An HTML attachment was scrubbed... URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20160502/0be6f783/attachment.html>
Daniel Berlin via llvm-dev
2016-May-02 18:32 UTC
[llvm-dev] [MemorySSA] Potential CachingMemorySSAWalker bug
I suspect something is pulling the RHS of the memorydef and caching it for calls it should not be used for. In particular, i suspect we are about to discover we can't cache the results from both versions of getClobberingMemoryAccess together, or that the cache is not always getting consistently written. On Mon, May 2, 2016 at 11:16 AM, George Burgess IV < george.burgess.iv at gmail.com> wrote:> Yeah, that sounds like a fun bug. I'll take a look later today and see > what I can find out. :) > > On Fri, Apr 29, 2016 at 2:55 PM, Geoff Berry <gberry at codeaurora.org> > wrote: > >> Hi guys, >> >> I think I have run into another CachingMemorySSAWalker cache bug. It's a >> bit tricky to reproduce, so I'd like to start by trying to show you what is >> happening when running EarlyCSE with my local changes to use MemorySSA. >> I've attached a debug log that shows that the value returned by >> getClobberingMemoryAccess(Inst) after a call to removeMemoryAccess is >> wrong. The MemorySSA node in question is MemoryUse(7), and the corruption >> happens after a call to remove MemoryUse(2), at which point its clobber >> value changes to '1 = MemoryDef(liveOnEntry)'. The interesting thing is >> that is doesn't seem to be the first call to getClobberingMemoryAccess >> after the removal that causes the corruption, but rather the second. >> You'll notice that I added calls to getClobberingMemoryAccess when doing >> MSSA.dump(), which is what I'm using to attempt to figure out when the >> cache gets corrupted. >> Hopefully this is enough information to debug the problem. If not >> perhaps we can look at getting my EarlyCSE changes checked in in a disabled >> state so you can reproduce the problem directly. I'm also happy to help >> debug it farther. >> >> -- >> Geoff Berry >> Employee of Qualcomm Innovation Center, Inc. >> Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, a Linux Foundation Collaborative Project >> >> >-------------- next part -------------- An HTML attachment was scrubbed... URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20160502/71c3c4db/attachment.html>