Skip to content

Commit 5b2a732

Browse files
author
James Molloy
committed
[GlobalsAA] Loosen an overly conservative bailout
Instead of bailing out when we see loads, analyze them. If we can prove that the loaded-from address must escape, then we can conclude that a load from that address must escape too and therefore cannot alias a non-addr-taken global. When checking if a Value can alias a non-addr-taken global, if the Value is a LoadInst of a non-global, recurse instead of bailing. If we can follow a trail of loads up to some base that is captured, we know by inference that all the loads we followed are also captured. llvm-svn: 251017
1 parent 5a4d8cd commit 5b2a732

File tree

2 files changed

+88
-9
lines changed

2 files changed

+88
-9
lines changed

llvm/lib/Analysis/GlobalsModRef.cpp

Lines changed: 71 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -595,6 +595,66 @@ void GlobalsAAResult::AnalyzeCallGraph(CallGraph &CG, Module &M) {
595595
}
596596
}
597597

598+
// GV is a non-escaping global. V is a pointer address that has been loaded from.
599+
// If we can prove that V must escape, we can conclude that a load from V cannot
600+
// alias GV.
601+
static bool isNonEscapingGlobalNoAliasWithLoad(const GlobalValue *GV,
602+
const Value *V,
603+
int &Depth,
604+
const DataLayout &DL) {
605+
SmallPtrSet<const Value *, 8> Visited;
606+
SmallVector<const Value *, 8> Inputs;
607+
Visited.insert(V);
608+
Inputs.push_back(V);
609+
do {
610+
const Value *Input = Inputs.pop_back_val();
611+
612+
if (isa<GlobalValue>(Input) || isa<Argument>(Input) || isa<CallInst>(Input) ||
613+
isa<InvokeInst>(Input))
614+
// Arguments to functions or returns from functions are inherently
615+
// escaping, so we can immediately classify those as not aliasing any
616+
// non-addr-taken globals.
617+
//
618+
// (Transitive) loads from a global are also safe - if this aliased
619+
// another global, its address would escape, so no alias.
620+
continue;
621+
622+
// Recurse through a limited number of selects, loads and PHIs. This is an
623+
// arbitrary depth of 4, lower numbers could be used to fix compile time
624+
// issues if needed, but this is generally expected to be only be important
625+
// for small depths.
626+
if (++Depth > 4)
627+
return false;
628+
629+
if (auto *LI = dyn_cast<LoadInst>(Input)) {
630+
Inputs.push_back(GetUnderlyingObject(LI->getPointerOperand(), DL));
631+
continue;
632+
}
633+
if (auto *SI = dyn_cast<SelectInst>(Input)) {
634+
const Value *LHS = GetUnderlyingObject(SI->getTrueValue(), DL);
635+
const Value *RHS = GetUnderlyingObject(SI->getFalseValue(), DL);
636+
if (Visited.insert(LHS).second)
637+
Inputs.push_back(LHS);
638+
if (Visited.insert(RHS).second)
639+
Inputs.push_back(RHS);
640+
continue;
641+
}
642+
if (auto *PN = dyn_cast<PHINode>(Input)) {
643+
for (const Value *Op : PN->incoming_values()) {
644+
Op = GetUnderlyingObject(Op, DL);
645+
if (Visited.insert(Op).second)
646+
Inputs.push_back(Op);
647+
}
648+
continue;
649+
}
650+
651+
return false;
652+
} while (!Inputs.empty());
653+
654+
// All inputs were known to be no-alias.
655+
return true;
656+
}
657+
598658
// There are particular cases where we can conclude no-alias between
599659
// a non-addr-taken global and some other underlying object. Specifically,
600660
// a non-addr-taken global is known to not be escaped from any function. It is
@@ -669,22 +729,24 @@ bool GlobalsAAResult::isNonEscapingGlobalNoAlias(const GlobalValue *GV,
669729
// non-addr-taken globals.
670730
continue;
671731
}
732+
733+
// Recurse through a limited number of selects, loads and PHIs. This is an
734+
// arbitrary depth of 4, lower numbers could be used to fix compile time
735+
// issues if needed, but this is generally expected to be only be important
736+
// for small depths.
737+
if (++Depth > 4)
738+
return false;
739+
672740
if (auto *LI = dyn_cast<LoadInst>(Input)) {
673741
// A pointer loaded from a global would have been captured, and we know
674742
// that the global is non-escaping, so no alias.
675-
if (isa<GlobalValue>(GetUnderlyingObject(LI->getPointerOperand(), DL)))
743+
const Value *Ptr = GetUnderlyingObject(LI->getPointerOperand(), DL);
744+
if (isNonEscapingGlobalNoAliasWithLoad(GV, Ptr, Depth, DL))
745+
// The load does not alias with GV.
676746
continue;
677-
678747
// Otherwise, a load could come from anywhere, so bail.
679748
return false;
680749
}
681-
682-
// Recurse through a limited number of selects and PHIs. This is an
683-
// arbitrary depth of 4, lower numbers could be used to fix compile time
684-
// issues if needed, but this is generally expected to be only be important
685-
// for small depths.
686-
if (++Depth > 4)
687-
return false;
688750
if (auto *SI = dyn_cast<SelectInst>(Input)) {
689751
const Value *LHS = GetUnderlyingObject(SI->getTrueValue(), DL);
690752
const Value *RHS = GetUnderlyingObject(SI->getFalseValue(), DL);

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

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,3 +97,20 @@ exit:
9797
%v = load i32, i32* @g1
9898
ret i32 %v
9999
}
100+
101+
define i32 @test5(i32** %param) {
102+
; Ensure that we can fold a store to a load of a global across a store to
103+
; a parameter that has been dereferenced when the global is non-escaping.
104+
;
105+
; CHECK-LABEL: @test5(
106+
; CHECK: %p = load i32*
107+
; CHECK: store i32 42, i32* @g1
108+
; CHECK-NOT: load i32
109+
; CHECK: ret i32 42
110+
entry:
111+
%p = load i32*, i32** %param
112+
store i32 42, i32* @g1
113+
store i32 7, i32* %p
114+
%v = load i32, i32* @g1
115+
ret i32 %v
116+
}

0 commit comments

Comments
 (0)