aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorOwen Anderson <resistor@mac.com>2009-02-04 05:16:46 +0000
committerOwen Anderson <resistor@mac.com>2009-02-04 05:16:46 +0000
commitfe9388ccb4d2449e8e6a62053479a0ba74ae0b2d (patch)
tree8a3d31f8efcb67c2e815938be17abd03952a7149
parent39355f9fea790c5a1b12ef0fdcfeac3f533232ea (diff)
Finish making AliasAnalysis aware of the fact that most atomic intrinsics only dereference their arguments, and enhance
BasicAA to make use of this fact when computing ModRef info. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@63718 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--lib/Analysis/AliasAnalysis.cpp21
-rw-r--r--lib/Analysis/BasicAliasAnalysis.cpp16
-rw-r--r--test/Analysis/BasicAA/cas.ll14
3 files changed, 51 insertions, 0 deletions
diff --git a/lib/Analysis/AliasAnalysis.cpp b/lib/Analysis/AliasAnalysis.cpp
index 2571492118..3e46fccc58 100644
--- a/lib/Analysis/AliasAnalysis.cpp
+++ b/lib/Analysis/AliasAnalysis.cpp
@@ -150,6 +150,27 @@ AliasAnalysis::getModRefBehavior(CallSite CS,
AliasAnalysis::ModRefBehavior
AliasAnalysis::getModRefBehavior(Function *F,
std::vector<PointerAccessInfo> *Info) {
+ if (F->isIntrinsic()) {
+ switch (F->getIntrinsicID()) {
+ case Intrinsic::atomic_cmp_swap:
+ case Intrinsic::atomic_load_add:
+ case Intrinsic::atomic_load_and:
+ case Intrinsic::atomic_load_max:
+ case Intrinsic::atomic_load_min:
+ case Intrinsic::atomic_load_nand:
+ case Intrinsic::atomic_load_or:
+ case Intrinsic::atomic_load_sub:
+ case Intrinsic::atomic_load_umax:
+ case Intrinsic::atomic_load_umin:
+ case Intrinsic::atomic_load_xor:
+ case Intrinsic::atomic_swap:
+ // CAS and related intrinsics only access their arguments.
+ return AliasAnalysis::AccessesArguments;
+ default:
+ break;
+ }
+ }
+
if (F->doesNotAccessMemory())
// Can't do better than this.
return DoesNotAccessMemory;
diff --git a/lib/Analysis/BasicAliasAnalysis.cpp b/lib/Analysis/BasicAliasAnalysis.cpp
index ccbe338585..317e9d9e2e 100644
--- a/lib/Analysis/BasicAliasAnalysis.cpp
+++ b/lib/Analysis/BasicAliasAnalysis.cpp
@@ -256,6 +256,22 @@ bool BasicAliasAnalysis::pointsToConstantMemory(const Value *P) {
//
AliasAnalysis::ModRefResult
BasicAliasAnalysis::getModRefInfo(CallSite CS, Value *P, unsigned Size) {
+ // If the function only accesses its arguments, it suffices to check that
+ // P does not alias any of those arguments.
+ if (AliasAnalysis::getModRefBehavior(CS, 0) ==
+ AliasAnalysis::AccessesArguments) {
+ bool doesAlias = false;
+ for (CallSite::arg_iterator AI = CS.arg_begin(), AE = CS.arg_end();
+ AI != AE; ++AI)
+ if (alias(*AI, ~0U, P, Size) != NoAlias) {
+ doesAlias = true;
+ break;
+ }
+
+ if (!doesAlias)
+ return NoModRef;
+ }
+
if (!isa<Constant>(P)) {
const Value *Object = P->getUnderlyingObject();
diff --git a/test/Analysis/BasicAA/cas.ll b/test/Analysis/BasicAA/cas.ll
new file mode 100644
index 0000000000..9bbb5e7c37
--- /dev/null
+++ b/test/Analysis/BasicAA/cas.ll
@@ -0,0 +1,14 @@
+; RUN: llvm-as < %s | opt -basicaa -gvn | llvm-dis | grep load | count 1
+
+@flag0 = internal global i32 zeroinitializer
+@turn = internal global i32 zeroinitializer
+
+
+define i32 @main() {
+ %a = load i32* @flag0
+ %b = tail call i32 @llvm.atomic.swap.i32.p0i32(i32* @turn, i32 1)
+ %c = load i32* @flag0
+ ret i32 %c
+}
+
+declare i32 @llvm.atomic.swap.i32.p0i32(i32*, i32) nounwind \ No newline at end of file