mirror of
https://github.com/llvm/llvm-project.git
synced 2025-04-19 13:26:45 +00:00
[globals-aa] Improved isNonEscapingGlobalNoAlias. (#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.
This commit is contained in:
parent
19bad2ac4a
commit
75bd46e01f
@ -118,7 +118,8 @@ private:
|
||||
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);
|
||||
};
|
||||
|
@ -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);
|
||||
@ -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
|
||||
@ -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());
|
||||
@ -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;
|
||||
}
|
||||
|
||||
@ -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;
|
||||
|
||||
|
@ -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 }
|
||||
|
Loading…
x
Reference in New Issue
Block a user