Use address-taken to disambiguate global variable and indirect memops.

Major steps include:
 1). introduces a not-addr-taken bit-field in GlobalVariable
 2). GlobalOpt pass sets "not-address-taken" if it proves a global varirable 
    dosen't have its address taken.
 3). AA use this info for disambiguation. 

llvm-svn: 193251
This commit is contained in:
Shuxin Yang 2013-10-23 17:28:19 +00:00
parent 2ea0f2cdae
commit e4fb375995
18 changed files with 72 additions and 11 deletions

View File

@ -511,6 +511,9 @@ module, including those with external linkage or appearing in
``@llvm.used``. This assumption may be suppressed by marking the ``@llvm.used``. This assumption may be suppressed by marking the
variable with ``externally_initialized``. variable with ``externally_initialized``.
If a global variable dose not have its address taken, it will be optionally
flagged ``notaddrtaken``.
An explicit alignment may be specified for a global, which must be a An explicit alignment may be specified for a global, which must be a
power of 2. If not present, or if the alignment is set to zero, the power of 2. If not present, or if the alignment is set to zero, the
alignment of the global is set by the target to whatever it feels alignment of the global is set by the target to whatever it feels

View File

@ -48,6 +48,7 @@ class GlobalVariable : public GlobalValue, public ilist_node<GlobalVariable> {
// can change from its initial // can change from its initial
// value before global // value before global
// initializers are run? // initializers are run?
bool notAddrTaken : 1; // Dose not have address taken.
public: public:
// allocate space for exactly one operand // allocate space for exactly one operand
@ -174,6 +175,9 @@ public:
isExternallyInitializedConstant = Val; isExternallyInitializedConstant = Val;
} }
void setAddressMaybeTaken(bool Val) { notAddrTaken = !Val; }
bool AddressMaybeTaken(void) const { return !notAddrTaken; }
/// copyAttributesFrom - copy all additional attributes (those not needed to /// copyAttributesFrom - copy all additional attributes (those not needed to
/// create a GlobalVariable) from the GlobalVariable Src to this one. /// create a GlobalVariable) from the GlobalVariable Src to this one.
void copyAttributesFrom(const GlobalValue *Src); void copyAttributesFrom(const GlobalValue *Src);

View File

@ -1238,6 +1238,17 @@ BasicAliasAnalysis::aliasCheck(const Value *V1, uint64_t V1Size,
return NoAlias; return NoAlias;
if (isEscapeSource(O2) && isNonEscapingLocalObject(O1)) if (isEscapeSource(O2) && isNonEscapingLocalObject(O1))
return NoAlias; return NoAlias;
// If one object is a global variable without address taken, the other one
// is a different object, they will not alias because the global variable
// in question cannot be indirectly accessed.
if (const GlobalVariable *GV = dyn_cast<GlobalVariable>(O1))
if (!GV->AddressMaybeTaken())
return NoAlias;
if (const GlobalVariable *GV = dyn_cast<GlobalVariable>(O2))
if (!GV->AddressMaybeTaken())
return NoAlias;
} }
// If the size of one access is larger than the entire object on the other // If the size of one access is larger than the entire object on the other

View File

@ -504,6 +504,7 @@ lltok::Kind LLLexer::LexIdentifier() {
KEYWORD(zeroinitializer); KEYWORD(zeroinitializer);
KEYWORD(undef); KEYWORD(undef);
KEYWORD(null); KEYWORD(null);
KEYWORD(notaddrtaken);
KEYWORD(to); KEYWORD(to);
KEYWORD(tail); KEYWORD(tail);
KEYWORD(target); KEYWORD(target);

View File

@ -704,7 +704,7 @@ bool LLParser::ParseGlobal(const std::string &Name, LocTy NameLoc,
unsigned Linkage, bool HasLinkage, unsigned Linkage, bool HasLinkage,
unsigned Visibility) { unsigned Visibility) {
unsigned AddrSpace; unsigned AddrSpace;
bool IsConstant, UnnamedAddr, IsExternallyInitialized; bool IsConstant, UnnamedAddr, IsExternallyInitialized, notAddrTaken;
GlobalVariable::ThreadLocalMode TLM; GlobalVariable::ThreadLocalMode TLM;
LocTy UnnamedAddrLoc; LocTy UnnamedAddrLoc;
LocTy IsExternallyInitializedLoc; LocTy IsExternallyInitializedLoc;
@ -719,6 +719,7 @@ bool LLParser::ParseGlobal(const std::string &Name, LocTy NameLoc,
IsExternallyInitialized, IsExternallyInitialized,
&IsExternallyInitializedLoc) || &IsExternallyInitializedLoc) ||
ParseGlobalType(IsConstant) || ParseGlobalType(IsConstant) ||
ParseOptionalToken(lltok::kw_notaddrtaken, notAddrTaken) ||
ParseType(Ty, TyLoc)) ParseType(Ty, TyLoc))
return true; return true;
@ -776,6 +777,7 @@ bool LLParser::ParseGlobal(const std::string &Name, LocTy NameLoc,
GV->setLinkage((GlobalValue::LinkageTypes)Linkage); GV->setLinkage((GlobalValue::LinkageTypes)Linkage);
GV->setVisibility((GlobalValue::VisibilityTypes)Visibility); GV->setVisibility((GlobalValue::VisibilityTypes)Visibility);
GV->setExternallyInitialized(IsExternallyInitialized); GV->setExternallyInitialized(IsExternallyInitialized);
GV->setAddressMaybeTaken(!notAddrTaken);
GV->setThreadLocalMode(TLM); GV->setThreadLocalMode(TLM);
GV->setUnnamedAddr(UnnamedAddr); GV->setUnnamedAddr(UnnamedAddr);

View File

@ -51,6 +51,7 @@ namespace lltok {
kw_localdynamic, kw_initialexec, kw_localexec, kw_localdynamic, kw_initialexec, kw_localexec,
kw_zeroinitializer, kw_zeroinitializer,
kw_undef, kw_null, kw_undef, kw_null,
kw_notaddrtaken,
kw_to, kw_to,
kw_tail, kw_tail,
kw_target, kw_target,

View File

@ -1848,6 +1848,9 @@ bool BitcodeReader::ParseModule(bool Resume) {
new GlobalVariable(*TheModule, Ty, isConstant, Linkage, 0, "", 0, new GlobalVariable(*TheModule, Ty, isConstant, Linkage, 0, "", 0,
TLM, AddressSpace, ExternallyInitialized); TLM, AddressSpace, ExternallyInitialized);
NewGV->setAlignment(Alignment); NewGV->setAlignment(Alignment);
if (Record.size() > 10)
NewGV->setAddressMaybeTaken(Record[10]);
if (!Section.empty()) if (!Section.empty())
NewGV->setSection(Section); NewGV->setSection(Section);
NewGV->setVisibility(Visibility); NewGV->setVisibility(Visibility);

View File

@ -616,11 +616,13 @@ static void WriteModuleInfo(const Module *M, const ValueEnumerator &VE,
Vals.push_back(GV->hasSection() ? SectionMap[GV->getSection()] : 0); Vals.push_back(GV->hasSection() ? SectionMap[GV->getSection()] : 0);
if (GV->isThreadLocal() || if (GV->isThreadLocal() ||
GV->getVisibility() != GlobalValue::DefaultVisibility || GV->getVisibility() != GlobalValue::DefaultVisibility ||
GV->hasUnnamedAddr() || GV->isExternallyInitialized()) { GV->hasUnnamedAddr() || GV->isExternallyInitialized() ||
!GV->AddressMaybeTaken()) {
Vals.push_back(getEncodedVisibility(GV)); Vals.push_back(getEncodedVisibility(GV));
Vals.push_back(getEncodedThreadLocalMode(GV)); Vals.push_back(getEncodedThreadLocalMode(GV));
Vals.push_back(GV->hasUnnamedAddr()); Vals.push_back(GV->hasUnnamedAddr());
Vals.push_back(GV->isExternallyInitialized()); Vals.push_back(GV->isExternallyInitialized());
Vals.push_back(GV->AddressMaybeTaken());
} else { } else {
AbbrevToUse = SimpleGVarAbbrev; AbbrevToUse = SimpleGVarAbbrev;
} }

View File

@ -1459,6 +1459,7 @@ void AssemblyWriter::printGlobal(const GlobalVariable *GV) {
if (GV->hasUnnamedAddr()) Out << "unnamed_addr "; if (GV->hasUnnamedAddr()) Out << "unnamed_addr ";
if (GV->isExternallyInitialized()) Out << "externally_initialized "; if (GV->isExternallyInitialized()) Out << "externally_initialized ";
Out << (GV->isConstant() ? "constant " : "global "); Out << (GV->isConstant() ? "constant " : "global ");
if (!GV->AddressMaybeTaken()) Out << "notaddrtaken ";
TypePrinter.print(GV->getType()->getElementType(), Out); TypePrinter.print(GV->getType()->getElementType(), Out);
if (GV->hasInitializer()) { if (GV->hasInitializer()) {

View File

@ -99,6 +99,7 @@ GlobalVariable::GlobalVariable(Type *Ty, bool constant, LinkageTypes Link,
} }
LeakDetector::addGarbageObject(this); LeakDetector::addGarbageObject(this);
setAddressMaybeTaken(true);
} }
GlobalVariable::GlobalVariable(Module &M, Type *Ty, bool constant, GlobalVariable::GlobalVariable(Module &M, Type *Ty, bool constant,
@ -125,6 +126,7 @@ GlobalVariable::GlobalVariable(Module &M, Type *Ty, bool constant,
Before->getParent()->getGlobalList().insert(Before, this); Before->getParent()->getGlobalList().insert(Before, this);
else else
M.getGlobalList().push_back(this); M.getGlobalList().push_back(this);
setAddressMaybeTaken(true);
} }
void GlobalVariable::setParent(Module *parent) { void GlobalVariable::setParent(Module *parent) {
@ -185,6 +187,7 @@ void GlobalVariable::copyAttributesFrom(const GlobalValue *Src) {
GlobalValue::copyAttributesFrom(Src); GlobalValue::copyAttributesFrom(Src);
const GlobalVariable *SrcVar = cast<GlobalVariable>(Src); const GlobalVariable *SrcVar = cast<GlobalVariable>(Src);
setThreadLocal(SrcVar->isThreadLocal()); setThreadLocal(SrcVar->isThreadLocal());
setAddressMaybeTaken(SrcVar->AddressMaybeTaken());
} }

View File

@ -1723,6 +1723,7 @@ bool GlobalOpt::ProcessGlobal(GlobalVariable *GV,
if (GlobalStatus::analyzeGlobal(GV, GS)) if (GlobalStatus::analyzeGlobal(GV, GS))
return false; return false;
GV->setAddressMaybeTaken(false);
if (!GS.IsCompared && !GV->hasUnnamedAddr()) { if (!GS.IsCompared && !GV->hasUnnamedAddr()) {
GV->setUnnamedAddr(true); GV->setUnnamedAddr(true);
NumUnnamed++; NumUnnamed++;

View File

@ -0,0 +1,29 @@
; RUN: opt < %s -basicaa -aa-eval -print-all-alias-modref-info 2>&1 | FileCheck %s
; ModuleID = 'b.c'
target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128"
target triple = "x86_64-apple-macosx10.8.0"
; CHECK: NoAlias: i32* %p, i32* @xyz
;@xyz = global i32 12, align 4
@xyz = internal unnamed_addr global notaddrtaken i32 12, align 4
; Function Attrs: nounwind ssp uwtable
define i32 @foo(i32* nocapture %p, i32* nocapture %q) #0 {
entry:
%0 = load i32* @xyz, align 4, !tbaa !0
%inc = add nsw i32 %0, 1
store i32 %inc, i32* @xyz, align 4, !tbaa !0
store i32 1, i32* %p, align 4, !tbaa !0
%1 = load i32* @xyz, align 4, !tbaa !0
store i32 %1, i32* %q, align 4, !tbaa !0
ret i32 undef
}
attributes #0 = { nounwind ssp uwtable "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" }
!0 = metadata !{metadata !1, metadata !1, i64 0}
!1 = metadata !{metadata !"int", metadata !2, i64 0}
!2 = metadata !{metadata !"omnipotent char", metadata !3, i64 0}
!3 = metadata !{metadata !"Simple C/C++ TBAA"}

View File

@ -1,4 +1,4 @@
; RUN: opt < %s -globalopt -S | grep "@X = internal unnamed_addr global i32" ; RUN: opt < %s -globalopt -S | grep "@X = internal unnamed_addr global notaddrtaken i32"
target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:128:128" target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:128:128"
target triple = "i386-apple-darwin7" target triple = "i386-apple-darwin7"
@X = internal global i32* null ; <i32**> [#uses=2] @X = internal global i32* null ; <i32**> [#uses=2]

View File

@ -8,7 +8,7 @@ target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f3
target triple = "x86_64-apple-darwin10.0" target triple = "x86_64-apple-darwin10.0"
@TOP = internal global i64* null ; <i64**> [#uses=2] @TOP = internal global i64* null ; <i64**> [#uses=2]
; CHECK: @TOP = internal unnamed_addr global i64* null ; CHECK: @TOP = internal unnamed_addr global notaddrtaken i64* null
@channelColumns = internal global i64 0 ; <i64*> [#uses=2] @channelColumns = internal global i64 0 ; <i64*> [#uses=2]
; Derived from @DescribeChannel() in yacr2 ; Derived from @DescribeChannel() in yacr2

View File

@ -3,8 +3,8 @@
@GV1 = internal global i64 1 @GV1 = internal global i64 1
@GV2 = internal global i32 0 @GV2 = internal global i32 0
; CHECK: @GV1 = internal unnamed_addr constant i64 1 ; CHECK: @GV1 = internal unnamed_addr constant notaddrtaken i64 1
; CHECK: @GV2 = internal unnamed_addr global i32 0 ; CHECK: @GV2 = internal unnamed_addr global notaddrtaken i32 0
define void @test1() { define void @test1() {
entry: entry:

View File

@ -1,5 +1,5 @@
; RUN: opt < %s -globalopt -S > %t ; RUN: opt < %s -globalopt -S > %t
; RUN: grep "@Y = internal unnamed_addr global \[3 x [%]struct.X\] zeroinitializer" %t ; RUN: grep "@Y = internal unnamed_addr global notaddrtaken \[3 x [%]struct.X\] zeroinitializer" %t
; RUN: grep load %t | count 6 ; RUN: grep load %t | count 6
; RUN: grep "add i32 [%]a, [%]b" %t | count 3 ; RUN: grep "add i32 [%]a, [%]b" %t | count 3

View File

@ -4,7 +4,7 @@
@G = internal addrspace(1) global i32 0 @G = internal addrspace(1) global i32 0
; CHECK: @G ; CHECK: @G
; CHECK: addrspace(1) ; CHECK: addrspace(1)
; CHECK: global i1 false ; CHECK: global notaddrtaken i1 false
define void @set1() { define void @set1() {
store i32 0, i32 addrspace(1)* @G store i32 0, i32 addrspace(1)* @G

View File

@ -6,10 +6,10 @@
@d = internal constant [4 x i8] c"foo\00", align 1 @d = internal constant [4 x i8] c"foo\00", align 1
@e = linkonce_odr global i32 0 @e = linkonce_odr global i32 0
; CHECK: @a = internal global i32 0, align 4 ; CHECK: @a = internal global notaddrtaken i32 0, align 4
; CHECK: @b = internal global i32 0, align 4 ; CHECK: @b = internal global i32 0, align 4
; CHECK: @c = internal unnamed_addr global i32 0, align 4 ; CHECK: @c = internal unnamed_addr global notaddrtaken i32 0, align 4
; CHECK: @d = internal unnamed_addr constant [4 x i8] c"foo\00", align 1 ; CHECK: @d = internal unnamed_addr constant notaddrtaken [4 x i8] c"foo\00", align 1
; CHECK: @e = linkonce_odr global i32 0 ; CHECK: @e = linkonce_odr global i32 0
define i32 @get_e() { define i32 @get_e() {