@@ -595,6 +595,66 @@ void GlobalsAAResult::AnalyzeCallGraph(CallGraph &CG, Module &M) {
595
595
}
596
596
}
597
597
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
+
598
658
// There are particular cases where we can conclude no-alias between
599
659
// a non-addr-taken global and some other underlying object. Specifically,
600
660
// 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,
669
729
// non-addr-taken globals.
670
730
continue ;
671
731
}
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
+
672
740
if (auto *LI = dyn_cast<LoadInst>(Input)) {
673
741
// A pointer loaded from a global would have been captured, and we know
674
742
// 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.
676
746
continue ;
677
-
678
747
// Otherwise, a load could come from anywhere, so bail.
679
748
return false ;
680
749
}
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 ;
688
750
if (auto *SI = dyn_cast<SelectInst>(Input)) {
689
751
const Value *LHS = GetUnderlyingObject (SI->getTrueValue (), DL);
690
752
const Value *RHS = GetUnderlyingObject (SI->getFalseValue (), DL);
0 commit comments