summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorVaivaswatha Nagaraj <vn@compilertree.com>2015-12-18 11:02:52 +0000
committerVaivaswatha Nagaraj <vn@compilertree.com>2015-12-18 11:02:52 +0000
commited237938da703c55cf83de0ca5090aa35a774a27 (patch)
treeeb8bfa0bcc5ae3b643e56c9c4284cbf7fef02eae
parent652246108005857512e1b9b38b752ea564e97811 (diff)
downloadbcm5719-llvm-ed237938da703c55cf83de0ca5090aa35a774a27.tar.gz
bcm5719-llvm-ed237938da703c55cf83de0ca5090aa35a774a27.zip
GlobalsAA: Take advantage of ArgMemOnly, InaccessibleMemOnly and InaccessibleMemOrArgMemOnly attributes
Summary: 1. Modify AnalyzeCallGraph() to retain function info for external functions if the function has [InaccessibleMemOr]ArgMemOnly flags. 2. When analyzing the use of a global is function parameter at a call site, mark the callee also as modifying the global appropriately. 3. Add additional test cases. Depends on D15499 Reviewers: hfinkel, jmolloy Subscribers: llvm-commits Differential Revision: http://reviews.llvm.org/D15605 llvm-svn: 255994
-rw-r--r--llvm/lib/Analysis/GlobalsModRef.cpp17
-rw-r--r--llvm/test/Analysis/GlobalsModRef/argmemonly-escape.ll47
-rw-r--r--llvm/test/Analysis/GlobalsModRef/modreftest.ll20
3 files changed, 83 insertions, 1 deletions
diff --git a/llvm/lib/Analysis/GlobalsModRef.cpp b/llvm/lib/Analysis/GlobalsModRef.cpp
index 86c2e501465..51a83d53277 100644
--- a/llvm/lib/Analysis/GlobalsModRef.cpp
+++ b/llvm/lib/Analysis/GlobalsModRef.cpp
@@ -376,6 +376,15 @@ bool GlobalsAAResult::AnalyzeUsesOfPointer(Value *V,
} else {
return true; // Argument of an unknown call.
}
+ // If the Callee is not ReadNone, it may read the global,
+ // and if it is not ReadOnly, it may also write to it.
+ Function *CalleeF = CS.getCalledFunction();
+ if (!CalleeF->doesNotAccessMemory()) {
+ if (Readers)
+ Readers->insert(CalleeF);
+ if (Writers && !CalleeF->onlyReadsMemory())
+ Writers->insert(CalleeF);
+ }
}
} else if (ICmpInst *ICI = dyn_cast<ICmpInst>(I)) {
if (!isa<ConstantPointerNull>(ICI->getOperand(1)))
@@ -507,7 +516,7 @@ void GlobalsAAResult::AnalyzeCallGraph(CallGraph &CG, Module &M) {
if (F->isDeclaration()) {
// Try to get mod/ref behaviour from function attributes.
- if (F->doesNotAccessMemory()) {
+ if (F->doesNotAccessMemory() || F->onlyAccessesInaccessibleMemory()) {
// Can't do better than that!
} else if (F->onlyReadsMemory()) {
FI.addModRefInfo(MRI_Ref);
@@ -515,6 +524,12 @@ void GlobalsAAResult::AnalyzeCallGraph(CallGraph &CG, Module &M) {
// This function might call back into the module and read a global -
// consider every global as possibly being read by this function.
FI.setMayReadAnyGlobal();
+ } else if (F->onlyAccessesArgMemory() ||
+ F->onlyAccessesInaccessibleMemOrArgMem()) {
+ // This function may only access (read/write) memory pointed to by its
+ // arguments. If this pointer is to a global, this escaping use of the
+ // pointer is captured in AnalyzeUsesOfPointer().
+ FI.addModRefInfo(MRI_ModRef);
} else {
FI.addModRefInfo(MRI_ModRef);
// Can't say anything useful unless it's an intrinsic - they don't
diff --git a/llvm/test/Analysis/GlobalsModRef/argmemonly-escape.ll b/llvm/test/Analysis/GlobalsModRef/argmemonly-escape.ll
new file mode 100644
index 00000000000..64c625810af
--- /dev/null
+++ b/llvm/test/Analysis/GlobalsModRef/argmemonly-escape.ll
@@ -0,0 +1,47 @@
+; RUN: opt < %s -O1 -S -enable-non-lto-gmr=true | FileCheck %s
+
+target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-apple-macosx10.10.0"
+
+@a = internal global [3 x i32] zeroinitializer, align 4
+
+; The important thing we're checking for here is the reload of (some element of)
+; @a after the memset.
+
+; CHECK-LABEL: @main
+; CHECK: load i32, i32* getelementptr {{.*}} @a
+; CHECK-NEXT: call void @memsetp0i8i64{{.*}} @a
+; CHECK-NEXT: load i32, i32* getelementptr {{.*}} @a
+; CHECK-NEXT: call void @memsetp0i8i64A{{.*}} @a
+; CHECK-NEXT: load i32, i32* getelementptr {{.*}} @a
+; CHECK: icmp eq
+; CHECK: br i1
+
+define i32 @main() {
+entry:
+ %0 = bitcast [3 x i32]* @a to i8*
+ %1 = load i32, i32* getelementptr inbounds ([3 x i32], [3 x i32]* @a, i64 0, i64 2), align 4
+ call void @memsetp0i8i64(i8* %0, i8 0, i64 4, i32 4, i1 false)
+ %2 = load i32, i32* getelementptr inbounds ([3 x i32], [3 x i32]* @a, i64 0, i64 2), align 4
+ call void @memsetp0i8i64A(i8* %0, i8 0, i64 4, i32 4, i1 false)
+ %3 = load i32, i32* getelementptr inbounds ([3 x i32], [3 x i32]* @a, i64 0, i64 2), align 4
+ %4 = add i32 %2, %3
+ %cmp1 = icmp eq i32 %1, %4
+ br i1 %cmp1, label %if.then, label %if.end
+
+if.then: ; preds = %entr
+ call void @abort() #3
+ unreachable
+
+if.end: ; preds = %entry
+ ret i32 0
+}
+
+; Function Attrs: nounwind argmemonly
+declare void @memsetp0i8i64(i8* nocapture, i8, i64, i32, i1) nounwind argmemonly
+
+; Function Attrs: nounwind inaccessiblemem_or_argmemonly
+declare void @memsetp0i8i64A(i8* nocapture, i8, i64, i32, i1) nounwind inaccessiblemem_or_argmemonly
+
+; Function Attrs: noreturn nounwind
+declare void @abort() noreturn nounwind
diff --git a/llvm/test/Analysis/GlobalsModRef/modreftest.ll b/llvm/test/Analysis/GlobalsModRef/modreftest.ll
index 07497705e65..2018b149fc0 100644
--- a/llvm/test/Analysis/GlobalsModRef/modreftest.ll
+++ b/llvm/test/Analysis/GlobalsModRef/modreftest.ll
@@ -16,3 +16,23 @@ define i32 @test(i32* %P) {
define void @doesnotmodX() {
ret void
}
+
+declare void @InaccessibleMemOnlyFunc( ) #0
+declare void @InaccessibleMemOrArgMemOnlyFunc( ) #1
+
+define i32 @test2(i32* %P) {
+; CHECK: @test2
+; CHECK-NEXT: store i32 12, i32* @X
+; CHECK-NEXT: call void @InaccessibleMemOnlyFunc()
+; CHECK-NEXT: call void @InaccessibleMemOrArgMemOnlyFunc()
+; CHECK-NOT: load i32
+; CHECK-NEXT: ret i32 12
+ store i32 12, i32* @X
+ call void @InaccessibleMemOnlyFunc( )
+ call void @InaccessibleMemOrArgMemOnlyFunc( )
+ %V = load i32, i32* @X ; <i32> [#uses=1]
+ ret i32 %V
+}
+
+attributes #0 = { inaccessiblememonly }
+attributes #1 = { inaccessiblemem_or_argmemonly }
OpenPOWER on IntegriCloud