diff --git a/llvm/lib/Analysis/AliasAnalysis.cpp b/llvm/lib/Analysis/AliasAnalysis.cpp --- a/llvm/lib/Analysis/AliasAnalysis.cpp +++ b/llvm/lib/Analysis/AliasAnalysis.cpp @@ -477,6 +477,11 @@ if (AR == AliasResult::NoAlias) return ModRefInfo::NoModRef; } + + // If the load is from constant memory, it doesn't mod/ref anything. + if (!isRefSet(getModRefInfoMask(MemoryLocation::get(L)))) + return ModRefInfo::NoModRef; + // Otherwise, a load just reads. return ModRefInfo::Ref; } diff --git a/llvm/lib/Target/AMDGPU/Utils/AMDGPUMemoryUtils.cpp b/llvm/lib/Target/AMDGPU/Utils/AMDGPUMemoryUtils.cpp --- a/llvm/lib/Target/AMDGPU/Utils/AMDGPUMemoryUtils.cpp +++ b/llvm/lib/Target/AMDGPU/Utils/AMDGPUMemoryUtils.cpp @@ -98,6 +98,8 @@ bool isClobberedInFunction(const LoadInst *Load, MemorySSA *MSSA, AAResults *AA) { + if (!MSSA->getMemoryAccess(Load)) + return false; MemorySSAWalker *Walker = MSSA->getWalker(); SmallVector WorkList{Walker->getClobberingMemoryAccess(Load)}; SmallSet Visited; diff --git a/llvm/lib/Transforms/Scalar/GVN.cpp b/llvm/lib/Transforms/Scalar/GVN.cpp --- a/llvm/lib/Transforms/Scalar/GVN.cpp +++ b/llvm/lib/Transforms/Scalar/GVN.cpp @@ -1422,15 +1422,17 @@ // MemoryDef (e.g. because it is volatile). The inserted loads are // guaranteed to load from the same definition. auto *LoadAcc = MSSA->getMemoryAccess(Load); - auto *DefiningAcc = - isa(LoadAcc) ? LoadAcc : LoadAcc->getDefiningAccess(); - auto *NewAccess = MSSAU->createMemoryAccessInBB( - NewLoad, DefiningAcc, NewLoad->getParent(), - MemorySSA::BeforeTerminator); - if (auto *NewDef = dyn_cast(NewAccess)) - MSSAU->insertDef(NewDef, /*RenameUses=*/true); - else - MSSAU->insertUse(cast(NewAccess), /*RenameUses=*/true); + if (LoadAcc) { + auto *DefiningAcc = + isa(LoadAcc) ? LoadAcc : LoadAcc->getDefiningAccess(); + auto *NewAccess = MSSAU->createMemoryAccessInBB( + NewLoad, DefiningAcc, NewLoad->getParent(), + MemorySSA::BeforeTerminator); + if (auto *NewDef = dyn_cast(NewAccess)) + MSSAU->insertDef(NewDef, /*RenameUses=*/true); + else + MSSAU->insertUse(cast(NewAccess), /*RenameUses=*/true); + } } // Transfer the old load's AA tags to the new load. diff --git a/llvm/lib/Transforms/Scalar/NewGVN.cpp b/llvm/lib/Transforms/Scalar/NewGVN.cpp --- a/llvm/lib/Transforms/Scalar/NewGVN.cpp +++ b/llvm/lib/Transforms/Scalar/NewGVN.cpp @@ -1522,7 +1522,8 @@ return createConstantExpression(PoisonValue::get(LI->getType())); MemoryAccess *OriginalAccess = getMemoryAccess(I); MemoryAccess *DefiningAccess = - MSSAWalker->getClobberingMemoryAccess(OriginalAccess); + OriginalAccess ? MSSAWalker->getClobberingMemoryAccess(OriginalAccess) + : MSSA->getLiveOnEntryDef(); if (!MSSA->isLiveOnEntryDef(DefiningAccess)) { if (auto *MD = dyn_cast(DefiningAccess)) { @@ -1545,7 +1546,7 @@ DefiningAccess); // If our MemoryLeader is not our defining access, add a use to the // MemoryLeader, so that we get reprocessed when it changes. - if (LE->getMemoryLeader() != DefiningAccess) + if (OriginalAccess && LE->getMemoryLeader() != DefiningAccess) addMemoryUsers(LE->getMemoryLeader(), OriginalAccess); return LE; } diff --git a/llvm/test/Analysis/MemorySSA/constant-memory.ll b/llvm/test/Analysis/MemorySSA/constant-memory.ll --- a/llvm/test/Analysis/MemorySSA/constant-memory.ll +++ b/llvm/test/Analysis/MemorySSA/constant-memory.ll @@ -1,7 +1,6 @@ -; RUN: opt -aa-pipeline=basic-aa -passes='print' -verify-memoryssa < %s 2>&1 | FileCheck %s +; RUN: opt -aa-pipeline=basic-aa -passes='print' -verify-memoryssa < %s 2>&1 | FileCheck %s --implicit-check-not=MemoryUse ; -; Things that BasicAA can prove points to constant memory should be -; liveOnEntry, as well. +; Things that BasicAA can prove points to constant memory should not have MemoryAccesses. declare void @clobberAllTheThings() @@ -11,12 +10,8 @@ ; CHECK: 1 = MemoryDef(liveOnEntry) ; CHECK-NEXT: call void @clobberAllTheThings() call void @clobberAllTheThings() -; CHECK: MemoryUse(liveOnEntry) -; CHECK-NEXT: %1 = load i8 %1 = load i8, ptr @str, align 1 %2 = getelementptr [2 x i8], ptr @str, i64 0, i64 1 -; CHECK: MemoryUse(liveOnEntry) -; CHECK-NEXT: %3 = load i8 %3 = load i8, ptr %2, align 1 %4 = add i8 %1, %3 ret i8 %4 diff --git a/llvm/test/Analysis/MemorySSA/ptr-const-mem.ll b/llvm/test/Analysis/MemorySSA/ptr-const-mem.ll deleted file mode 100644 --- a/llvm/test/Analysis/MemorySSA/ptr-const-mem.ll +++ /dev/null @@ -1,22 +0,0 @@ -; RUN: opt -aa-pipeline=basic-aa -passes='print' -verify-memoryssa -disable-output -memssa-check-limit=0 < %s 2>&1 | FileCheck %s -target datalayout = "e-p:32:32-p1:64:64-p2:64:64-p3:32:32-p4:64:64-p5:32:32-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024-v2048:2048-n32:64" -target triple = "amdgcn" - -@g4 = external unnamed_addr constant i8, align 1 - -define signext i8 @cmp_constant(ptr %q, i8 %v) local_unnamed_addr { -entry: - - store i8 %v, ptr %q, align 1 -; CHECK: 1 = MemoryDef(liveOnEntry) -; CHECK-NEXT: store i8 %v, ptr %q, align 1 - - %0 = load i8, ptr @g4, align 1 -; Make sure that this load is liveOnEntry just based on the fact that @g4 is -; constant memory. -; CHECK: MemoryUse(liveOnEntry) -; CHECK-NEXT: load i8, ptr @g4, align 1 - - ret i8 %0 -} - diff --git a/llvm/test/Transforms/GVN/mssa-constant-mem.ll b/llvm/test/Transforms/GVN/mssa-constant-mem.ll new file mode 100644 --- /dev/null +++ b/llvm/test/Transforms/GVN/mssa-constant-mem.ll @@ -0,0 +1,21 @@ +; RUN: opt -passes='require,gvn' -S < %s + +; check this doesn't crash + +@global = external constant i64 + +declare void @foo(i64) + +define void @f() { +bb: + br i1 true, label %bb2, label %bb1 + +bb1: + %load = load i64, ptr @global + br label %bb2 + +bb2: + %load3 = load i64, ptr @global + call void @foo(i64 %load3) + ret void +}