Skip to content

[globals-aa] Improved isNonEscapingGlobalNoAlias. #127707

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Feb 20, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion llvm/include/llvm/Analysis/GlobalsModRef.h
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,8 @@ class GlobalsAAResult : public AAResultBase {
bool AnalyzeIndirectGlobalMemory(GlobalVariable *GV);
void CollectSCCMembership(CallGraph &CG);

bool isNonEscapingGlobalNoAlias(const GlobalValue *GV, const Value *V);
bool isNonEscapingGlobalNoAlias(const GlobalValue *GV, const Value *V,
const Instruction *CtxI);
ModRefInfo getModRefInfoForArgument(const CallBase *Call,
const GlobalValue *GV, AAQueryInfo &AAQI);
};
Expand Down
23 changes: 19 additions & 4 deletions llvm/lib/Analysis/GlobalsModRef.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -713,13 +713,20 @@ static bool isNonEscapingGlobalNoAliasWithLoad(const GlobalValue *GV,
// active, or to be forced to operate as a module pass that cannot co-exist
// with an alias analysis such as GMR.
bool GlobalsAAResult::isNonEscapingGlobalNoAlias(const GlobalValue *GV,
const Value *V) {
const Value *V,
const Instruction *CtxI) {
// In order to know that the underlying object cannot alias the
// non-addr-taken global, we must know that it would have to be an escape.
// Thus if the underlying object is a function argument, a load from
// a global, or the return of a function, it cannot alias. We can also
// recurse through PHI nodes and select nodes provided all of their inputs
// resolve to one of these known-escaping roots.

// A non-addr-taken global cannot alias with any non-pointer value.
// Check this early and exit.
if (!V->getType()->isPointerTy())
return true;

SmallPtrSet<const Value *, 8> Visited;
SmallVector<const Value *, 8> Inputs;
Visited.insert(V);
Expand Down Expand Up @@ -762,6 +769,14 @@ bool GlobalsAAResult::isNonEscapingGlobalNoAlias(const GlobalValue *GV,
continue;
}

if (CtxI)
if (auto *CPN = dyn_cast<ConstantPointerNull>(Input)) {
// Null pointer cannot alias with a non-addr-taken global.
const Function *F = CtxI->getFunction();
if (!NullPointerIsDefined(F, CPN->getType()->getAddressSpace()))
continue;
}

// Recurse through a limited number of selects, loads and PHIs. This is an
// arbitrary depth of 4, lower numbers could be used to fix compile time
// issues if needed, but this is generally expected to be only be important
Expand Down Expand Up @@ -820,7 +835,7 @@ bool GlobalsAAResult::invalidate(Module &, const PreservedAnalyses &PA,
/// address of the global isn't taken.
AliasResult GlobalsAAResult::alias(const MemoryLocation &LocA,
const MemoryLocation &LocB,
AAQueryInfo &AAQI, const Instruction *) {
AAQueryInfo &AAQI, const Instruction *CtxI) {
// Get the base object these pointers point to.
const Value *UV1 =
getUnderlyingObject(LocA.Ptr->stripPointerCastsForAliasAnalysis());
Expand Down Expand Up @@ -856,7 +871,7 @@ AliasResult GlobalsAAResult::alias(const MemoryLocation &LocA,
if ((GV1 || GV2) && GV1 != GV2) {
const GlobalValue *GV = GV1 ? GV1 : GV2;
const Value *UV = GV1 ? UV2 : UV1;
if (isNonEscapingGlobalNoAlias(GV, UV))
if (isNonEscapingGlobalNoAlias(GV, UV, CtxI))
return AliasResult::NoAlias;
}

Expand Down Expand Up @@ -920,7 +935,7 @@ ModRefInfo GlobalsAAResult::getModRefInfoForArgument(const CallBase *Call,
!all_of(Objects, [&](const Value *V) {
return this->alias(MemoryLocation::getBeforeOrAfter(V),
MemoryLocation::getBeforeOrAfter(GV), AAQI,
nullptr) == AliasResult::NoAlias;
Call) == AliasResult::NoAlias;
}))
return ConservativeResult;

Expand Down
21 changes: 21 additions & 0 deletions llvm/test/Analysis/GlobalsModRef/nonescaping-noalias.ll
Original file line number Diff line number Diff line change
Expand Up @@ -175,3 +175,24 @@ entry:
%v = load i32, ptr @g1
ret i32 %v
}

define i32 @test6(ptr %param) {
; Ensure that we can fold a store to a load of a global across a set of
; calls that cannot use in any way a non-escaping global.
;
; CHECK-LABEL: @test6(
; CHECK: store i32 42, ptr @g1
; CHECK-NOT: load i32
; CHECK: ret i32 42
entry:
store i32 42, ptr @g1
%1 = call ptr @_FortranAioBeginExternalFormattedOutput(ptr null, i64 3, ptr null, i32 6, ptr null, i32 2)
%2 = call i1 @_FortranAioOutputAscii(ptr %1, ptr null, i64 4)
%3 = call i32 @_FortranAioEndIoStatement(ptr %1)
%v = load i32, ptr @g1
ret i32 %v
}
declare ptr @_FortranAioBeginExternalFormattedOutput(ptr, i64, ptr, i32, ptr, i32) #0
declare zeroext i1 @_FortranAioOutputAscii(ptr, ptr, i64) #0
declare i32 @_FortranAioEndIoStatement(ptr) #0
attributes #0 = { nocallback nosync }