Skip to content

Commit 75bd46e

Browse files
authored
[globals-aa] Improved isNonEscapingGlobalNoAlias. (llvm#127707)
A non-escaping global should never alias with non-pointer values and `ptr null`. This should improve disambiguation of global pointers with relation to Flang runtime calls (given that `nosync nocallback` attributes are properly set). It also seems to be an obvious improvement with little overhead.
1 parent 19bad2a commit 75bd46e

File tree

3 files changed

+42
-5
lines changed

3 files changed

+42
-5
lines changed

llvm/include/llvm/Analysis/GlobalsModRef.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,8 @@ class GlobalsAAResult : public AAResultBase {
118118
bool AnalyzeIndirectGlobalMemory(GlobalVariable *GV);
119119
void CollectSCCMembership(CallGraph &CG);
120120

121-
bool isNonEscapingGlobalNoAlias(const GlobalValue *GV, const Value *V);
121+
bool isNonEscapingGlobalNoAlias(const GlobalValue *GV, const Value *V,
122+
const Instruction *CtxI);
122123
ModRefInfo getModRefInfoForArgument(const CallBase *Call,
123124
const GlobalValue *GV, AAQueryInfo &AAQI);
124125
};

llvm/lib/Analysis/GlobalsModRef.cpp

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -713,13 +713,20 @@ static bool isNonEscapingGlobalNoAliasWithLoad(const GlobalValue *GV,
713713
// active, or to be forced to operate as a module pass that cannot co-exist
714714
// with an alias analysis such as GMR.
715715
bool GlobalsAAResult::isNonEscapingGlobalNoAlias(const GlobalValue *GV,
716-
const Value *V) {
716+
const Value *V,
717+
const Instruction *CtxI) {
717718
// In order to know that the underlying object cannot alias the
718719
// non-addr-taken global, we must know that it would have to be an escape.
719720
// Thus if the underlying object is a function argument, a load from
720721
// a global, or the return of a function, it cannot alias. We can also
721722
// recurse through PHI nodes and select nodes provided all of their inputs
722723
// resolve to one of these known-escaping roots.
724+
725+
// A non-addr-taken global cannot alias with any non-pointer value.
726+
// Check this early and exit.
727+
if (!V->getType()->isPointerTy())
728+
return true;
729+
723730
SmallPtrSet<const Value *, 8> Visited;
724731
SmallVector<const Value *, 8> Inputs;
725732
Visited.insert(V);
@@ -762,6 +769,14 @@ bool GlobalsAAResult::isNonEscapingGlobalNoAlias(const GlobalValue *GV,
762769
continue;
763770
}
764771

772+
if (CtxI)
773+
if (auto *CPN = dyn_cast<ConstantPointerNull>(Input)) {
774+
// Null pointer cannot alias with a non-addr-taken global.
775+
const Function *F = CtxI->getFunction();
776+
if (!NullPointerIsDefined(F, CPN->getType()->getAddressSpace()))
777+
continue;
778+
}
779+
765780
// Recurse through a limited number of selects, loads and PHIs. This is an
766781
// arbitrary depth of 4, lower numbers could be used to fix compile time
767782
// issues if needed, but this is generally expected to be only be important
@@ -820,7 +835,7 @@ bool GlobalsAAResult::invalidate(Module &, const PreservedAnalyses &PA,
820835
/// address of the global isn't taken.
821836
AliasResult GlobalsAAResult::alias(const MemoryLocation &LocA,
822837
const MemoryLocation &LocB,
823-
AAQueryInfo &AAQI, const Instruction *) {
838+
AAQueryInfo &AAQI, const Instruction *CtxI) {
824839
// Get the base object these pointers point to.
825840
const Value *UV1 =
826841
getUnderlyingObject(LocA.Ptr->stripPointerCastsForAliasAnalysis());
@@ -856,7 +871,7 @@ AliasResult GlobalsAAResult::alias(const MemoryLocation &LocA,
856871
if ((GV1 || GV2) && GV1 != GV2) {
857872
const GlobalValue *GV = GV1 ? GV1 : GV2;
858873
const Value *UV = GV1 ? UV2 : UV1;
859-
if (isNonEscapingGlobalNoAlias(GV, UV))
874+
if (isNonEscapingGlobalNoAlias(GV, UV, CtxI))
860875
return AliasResult::NoAlias;
861876
}
862877

@@ -920,7 +935,7 @@ ModRefInfo GlobalsAAResult::getModRefInfoForArgument(const CallBase *Call,
920935
!all_of(Objects, [&](const Value *V) {
921936
return this->alias(MemoryLocation::getBeforeOrAfter(V),
922937
MemoryLocation::getBeforeOrAfter(GV), AAQI,
923-
nullptr) == AliasResult::NoAlias;
938+
Call) == AliasResult::NoAlias;
924939
}))
925940
return ConservativeResult;
926941

llvm/test/Analysis/GlobalsModRef/nonescaping-noalias.ll

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -175,3 +175,24 @@ entry:
175175
%v = load i32, ptr @g1
176176
ret i32 %v
177177
}
178+
179+
define i32 @test6(ptr %param) {
180+
; Ensure that we can fold a store to a load of a global across a set of
181+
; calls that cannot use in any way a non-escaping global.
182+
;
183+
; CHECK-LABEL: @test6(
184+
; CHECK: store i32 42, ptr @g1
185+
; CHECK-NOT: load i32
186+
; CHECK: ret i32 42
187+
entry:
188+
store i32 42, ptr @g1
189+
%1 = call ptr @_FortranAioBeginExternalFormattedOutput(ptr null, i64 3, ptr null, i32 6, ptr null, i32 2)
190+
%2 = call i1 @_FortranAioOutputAscii(ptr %1, ptr null, i64 4)
191+
%3 = call i32 @_FortranAioEndIoStatement(ptr %1)
192+
%v = load i32, ptr @g1
193+
ret i32 %v
194+
}
195+
declare ptr @_FortranAioBeginExternalFormattedOutput(ptr, i64, ptr, i32, ptr, i32) #0
196+
declare zeroext i1 @_FortranAioOutputAscii(ptr, ptr, i64) #0
197+
declare i32 @_FortranAioEndIoStatement(ptr) #0
198+
attributes #0 = { nocallback nosync }

0 commit comments

Comments
 (0)