From e4fb375995def5029b94b5af708dd181be36ca01 Mon Sep 17 00:00:00 2001 From: Shuxin Yang Date: Wed, 23 Oct 2013 17:28:19 +0000 Subject: [PATCH] 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 --- llvm/docs/LangRef.rst | 3 ++ llvm/include/llvm/IR/GlobalVariable.h | 4 +++ llvm/lib/Analysis/BasicAliasAnalysis.cpp | 11 +++++++ llvm/lib/AsmParser/LLLexer.cpp | 1 + llvm/lib/AsmParser/LLParser.cpp | 4 ++- llvm/lib/AsmParser/LLToken.h | 1 + llvm/lib/Bitcode/Reader/BitcodeReader.cpp | 3 ++ llvm/lib/Bitcode/Writer/BitcodeWriter.cpp | 4 ++- llvm/lib/IR/AsmWriter.cpp | 1 + llvm/lib/IR/Globals.cpp | 3 ++ llvm/lib/Transforms/IPO/GlobalOpt.cpp | 1 + llvm/test/Analysis/BasicAA/noaddrtaken.ll | 29 +++++++++++++++++++ .../GlobalOpt/2009-03-07-PromotePtrToBool.ll | 2 +- ...2009-11-16-MallocSingleStoreToGlobalVar.ll | 2 +- llvm/test/Transforms/GlobalOpt/atomic.ll | 4 +-- .../GlobalOpt/globalsra-unknown-index.ll | 2 +- .../test/Transforms/GlobalOpt/integer-bool.ll | 2 +- .../test/Transforms/GlobalOpt/unnamed-addr.ll | 6 ++-- 18 files changed, 72 insertions(+), 11 deletions(-) create mode 100644 llvm/test/Analysis/BasicAA/noaddrtaken.ll diff --git a/llvm/docs/LangRef.rst b/llvm/docs/LangRef.rst index b75c6b1b80f3..1e2016bfbdd6 100644 --- a/llvm/docs/LangRef.rst +++ b/llvm/docs/LangRef.rst @@ -511,6 +511,9 @@ module, including those with external linkage or appearing in ``@llvm.used``. This assumption may be suppressed by marking the 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 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 diff --git a/llvm/include/llvm/IR/GlobalVariable.h b/llvm/include/llvm/IR/GlobalVariable.h index bfed50786ea0..a5ab97db239b 100644 --- a/llvm/include/llvm/IR/GlobalVariable.h +++ b/llvm/include/llvm/IR/GlobalVariable.h @@ -48,6 +48,7 @@ class GlobalVariable : public GlobalValue, public ilist_node { // can change from its initial // value before global // initializers are run? + bool notAddrTaken : 1; // Dose not have address taken. public: // allocate space for exactly one operand @@ -174,6 +175,9 @@ public: isExternallyInitializedConstant = Val; } + void setAddressMaybeTaken(bool Val) { notAddrTaken = !Val; } + bool AddressMaybeTaken(void) const { return !notAddrTaken; } + /// copyAttributesFrom - copy all additional attributes (those not needed to /// create a GlobalVariable) from the GlobalVariable Src to this one. void copyAttributesFrom(const GlobalValue *Src); diff --git a/llvm/lib/Analysis/BasicAliasAnalysis.cpp b/llvm/lib/Analysis/BasicAliasAnalysis.cpp index bf929690ae77..4e423a787c97 100644 --- a/llvm/lib/Analysis/BasicAliasAnalysis.cpp +++ b/llvm/lib/Analysis/BasicAliasAnalysis.cpp @@ -1238,6 +1238,17 @@ BasicAliasAnalysis::aliasCheck(const Value *V1, uint64_t V1Size, return NoAlias; if (isEscapeSource(O2) && isNonEscapingLocalObject(O1)) 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(O1)) + if (!GV->AddressMaybeTaken()) + return NoAlias; + + if (const GlobalVariable *GV = dyn_cast(O2)) + if (!GV->AddressMaybeTaken()) + return NoAlias; } // If the size of one access is larger than the entire object on the other diff --git a/llvm/lib/AsmParser/LLLexer.cpp b/llvm/lib/AsmParser/LLLexer.cpp index 99bff45792c6..6d643b611c35 100644 --- a/llvm/lib/AsmParser/LLLexer.cpp +++ b/llvm/lib/AsmParser/LLLexer.cpp @@ -504,6 +504,7 @@ lltok::Kind LLLexer::LexIdentifier() { KEYWORD(zeroinitializer); KEYWORD(undef); KEYWORD(null); + KEYWORD(notaddrtaken); KEYWORD(to); KEYWORD(tail); KEYWORD(target); diff --git a/llvm/lib/AsmParser/LLParser.cpp b/llvm/lib/AsmParser/LLParser.cpp index 74c0ea4af529..9b5fb27a0567 100644 --- a/llvm/lib/AsmParser/LLParser.cpp +++ b/llvm/lib/AsmParser/LLParser.cpp @@ -704,7 +704,7 @@ bool LLParser::ParseGlobal(const std::string &Name, LocTy NameLoc, unsigned Linkage, bool HasLinkage, unsigned Visibility) { unsigned AddrSpace; - bool IsConstant, UnnamedAddr, IsExternallyInitialized; + bool IsConstant, UnnamedAddr, IsExternallyInitialized, notAddrTaken; GlobalVariable::ThreadLocalMode TLM; LocTy UnnamedAddrLoc; LocTy IsExternallyInitializedLoc; @@ -719,6 +719,7 @@ bool LLParser::ParseGlobal(const std::string &Name, LocTy NameLoc, IsExternallyInitialized, &IsExternallyInitializedLoc) || ParseGlobalType(IsConstant) || + ParseOptionalToken(lltok::kw_notaddrtaken, notAddrTaken) || ParseType(Ty, TyLoc)) return true; @@ -776,6 +777,7 @@ bool LLParser::ParseGlobal(const std::string &Name, LocTy NameLoc, GV->setLinkage((GlobalValue::LinkageTypes)Linkage); GV->setVisibility((GlobalValue::VisibilityTypes)Visibility); GV->setExternallyInitialized(IsExternallyInitialized); + GV->setAddressMaybeTaken(!notAddrTaken); GV->setThreadLocalMode(TLM); GV->setUnnamedAddr(UnnamedAddr); diff --git a/llvm/lib/AsmParser/LLToken.h b/llvm/lib/AsmParser/LLToken.h index e1382fdb5975..7832e816aa88 100644 --- a/llvm/lib/AsmParser/LLToken.h +++ b/llvm/lib/AsmParser/LLToken.h @@ -51,6 +51,7 @@ namespace lltok { kw_localdynamic, kw_initialexec, kw_localexec, kw_zeroinitializer, kw_undef, kw_null, + kw_notaddrtaken, kw_to, kw_tail, kw_target, diff --git a/llvm/lib/Bitcode/Reader/BitcodeReader.cpp b/llvm/lib/Bitcode/Reader/BitcodeReader.cpp index e408cd1f981e..3fca4ab8e0dd 100644 --- a/llvm/lib/Bitcode/Reader/BitcodeReader.cpp +++ b/llvm/lib/Bitcode/Reader/BitcodeReader.cpp @@ -1848,6 +1848,9 @@ bool BitcodeReader::ParseModule(bool Resume) { new GlobalVariable(*TheModule, Ty, isConstant, Linkage, 0, "", 0, TLM, AddressSpace, ExternallyInitialized); NewGV->setAlignment(Alignment); + if (Record.size() > 10) + NewGV->setAddressMaybeTaken(Record[10]); + if (!Section.empty()) NewGV->setSection(Section); NewGV->setVisibility(Visibility); diff --git a/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp b/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp index b082ba6bfd27..4f631b98859e 100644 --- a/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp +++ b/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp @@ -616,11 +616,13 @@ static void WriteModuleInfo(const Module *M, const ValueEnumerator &VE, Vals.push_back(GV->hasSection() ? SectionMap[GV->getSection()] : 0); if (GV->isThreadLocal() || GV->getVisibility() != GlobalValue::DefaultVisibility || - GV->hasUnnamedAddr() || GV->isExternallyInitialized()) { + GV->hasUnnamedAddr() || GV->isExternallyInitialized() || + !GV->AddressMaybeTaken()) { Vals.push_back(getEncodedVisibility(GV)); Vals.push_back(getEncodedThreadLocalMode(GV)); Vals.push_back(GV->hasUnnamedAddr()); Vals.push_back(GV->isExternallyInitialized()); + Vals.push_back(GV->AddressMaybeTaken()); } else { AbbrevToUse = SimpleGVarAbbrev; } diff --git a/llvm/lib/IR/AsmWriter.cpp b/llvm/lib/IR/AsmWriter.cpp index 6e3b853b3915..dc337c16a604 100644 --- a/llvm/lib/IR/AsmWriter.cpp +++ b/llvm/lib/IR/AsmWriter.cpp @@ -1459,6 +1459,7 @@ void AssemblyWriter::printGlobal(const GlobalVariable *GV) { if (GV->hasUnnamedAddr()) Out << "unnamed_addr "; if (GV->isExternallyInitialized()) Out << "externally_initialized "; Out << (GV->isConstant() ? "constant " : "global "); + if (!GV->AddressMaybeTaken()) Out << "notaddrtaken "; TypePrinter.print(GV->getType()->getElementType(), Out); if (GV->hasInitializer()) { diff --git a/llvm/lib/IR/Globals.cpp b/llvm/lib/IR/Globals.cpp index da3b02a0fa6d..8c28ec176f69 100644 --- a/llvm/lib/IR/Globals.cpp +++ b/llvm/lib/IR/Globals.cpp @@ -99,6 +99,7 @@ GlobalVariable::GlobalVariable(Type *Ty, bool constant, LinkageTypes Link, } LeakDetector::addGarbageObject(this); + setAddressMaybeTaken(true); } 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); else M.getGlobalList().push_back(this); + setAddressMaybeTaken(true); } void GlobalVariable::setParent(Module *parent) { @@ -185,6 +187,7 @@ void GlobalVariable::copyAttributesFrom(const GlobalValue *Src) { GlobalValue::copyAttributesFrom(Src); const GlobalVariable *SrcVar = cast(Src); setThreadLocal(SrcVar->isThreadLocal()); + setAddressMaybeTaken(SrcVar->AddressMaybeTaken()); } diff --git a/llvm/lib/Transforms/IPO/GlobalOpt.cpp b/llvm/lib/Transforms/IPO/GlobalOpt.cpp index 82a59ed562de..a259b4d39214 100644 --- a/llvm/lib/Transforms/IPO/GlobalOpt.cpp +++ b/llvm/lib/Transforms/IPO/GlobalOpt.cpp @@ -1723,6 +1723,7 @@ bool GlobalOpt::ProcessGlobal(GlobalVariable *GV, if (GlobalStatus::analyzeGlobal(GV, GS)) return false; + GV->setAddressMaybeTaken(false); if (!GS.IsCompared && !GV->hasUnnamedAddr()) { GV->setUnnamedAddr(true); NumUnnamed++; diff --git a/llvm/test/Analysis/BasicAA/noaddrtaken.ll b/llvm/test/Analysis/BasicAA/noaddrtaken.ll new file mode 100644 index 000000000000..14aa45bbf7c5 --- /dev/null +++ b/llvm/test/Analysis/BasicAA/noaddrtaken.ll @@ -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"} diff --git a/llvm/test/Transforms/GlobalOpt/2009-03-07-PromotePtrToBool.ll b/llvm/test/Transforms/GlobalOpt/2009-03-07-PromotePtrToBool.ll index 059af1cfeac8..87f28897a2da 100644 --- a/llvm/test/Transforms/GlobalOpt/2009-03-07-PromotePtrToBool.ll +++ b/llvm/test/Transforms/GlobalOpt/2009-03-07-PromotePtrToBool.ll @@ -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 triple = "i386-apple-darwin7" @X = internal global i32* null ; [#uses=2] diff --git a/llvm/test/Transforms/GlobalOpt/2009-11-16-MallocSingleStoreToGlobalVar.ll b/llvm/test/Transforms/GlobalOpt/2009-11-16-MallocSingleStoreToGlobalVar.ll index b73f62ba148b..fd7b4dd601cc 100644 --- a/llvm/test/Transforms/GlobalOpt/2009-11-16-MallocSingleStoreToGlobalVar.ll +++ b/llvm/test/Transforms/GlobalOpt/2009-11-16-MallocSingleStoreToGlobalVar.ll @@ -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" @TOP = internal global i64* null ; [#uses=2] -; CHECK: @TOP = internal unnamed_addr global i64* null +; CHECK: @TOP = internal unnamed_addr global notaddrtaken i64* null @channelColumns = internal global i64 0 ; [#uses=2] ; Derived from @DescribeChannel() in yacr2 diff --git a/llvm/test/Transforms/GlobalOpt/atomic.ll b/llvm/test/Transforms/GlobalOpt/atomic.ll index ac05bfd68d9d..d0fb9700dbb6 100644 --- a/llvm/test/Transforms/GlobalOpt/atomic.ll +++ b/llvm/test/Transforms/GlobalOpt/atomic.ll @@ -3,8 +3,8 @@ @GV1 = internal global i64 1 @GV2 = internal global i32 0 -; CHECK: @GV1 = internal unnamed_addr constant i64 1 -; CHECK: @GV2 = internal unnamed_addr global i32 0 +; CHECK: @GV1 = internal unnamed_addr constant notaddrtaken i64 1 +; CHECK: @GV2 = internal unnamed_addr global notaddrtaken i32 0 define void @test1() { entry: diff --git a/llvm/test/Transforms/GlobalOpt/globalsra-unknown-index.ll b/llvm/test/Transforms/GlobalOpt/globalsra-unknown-index.ll index cc655e9a2d1d..a854d9476da9 100644 --- a/llvm/test/Transforms/GlobalOpt/globalsra-unknown-index.ll +++ b/llvm/test/Transforms/GlobalOpt/globalsra-unknown-index.ll @@ -1,5 +1,5 @@ ; 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 "add i32 [%]a, [%]b" %t | count 3 diff --git a/llvm/test/Transforms/GlobalOpt/integer-bool.ll b/llvm/test/Transforms/GlobalOpt/integer-bool.ll index abf5fdd2ef3c..a75614e7fa8e 100644 --- a/llvm/test/Transforms/GlobalOpt/integer-bool.ll +++ b/llvm/test/Transforms/GlobalOpt/integer-bool.ll @@ -4,7 +4,7 @@ @G = internal addrspace(1) global i32 0 ; CHECK: @G ; CHECK: addrspace(1) -; CHECK: global i1 false +; CHECK: global notaddrtaken i1 false define void @set1() { store i32 0, i32 addrspace(1)* @G diff --git a/llvm/test/Transforms/GlobalOpt/unnamed-addr.ll b/llvm/test/Transforms/GlobalOpt/unnamed-addr.ll index 2ca91e50da2a..7b049ec769db 100644 --- a/llvm/test/Transforms/GlobalOpt/unnamed-addr.ll +++ b/llvm/test/Transforms/GlobalOpt/unnamed-addr.ll @@ -6,10 +6,10 @@ @d = internal constant [4 x i8] c"foo\00", align 1 @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: @c = internal unnamed_addr global i32 0, align 4 -; CHECK: @d = internal unnamed_addr constant [4 x i8] c"foo\00", align 1 +; CHECK: @c = internal unnamed_addr global notaddrtaken i32 0, align 4 +; CHECK: @d = internal unnamed_addr constant notaddrtaken [4 x i8] c"foo\00", align 1 ; CHECK: @e = linkonce_odr global i32 0 define i32 @get_e() {