Implement a proper getModRefInfo for va_arg.
authorDan Gohman <gohman@apple.com>
Fri, 6 Aug 2010 18:24:38 +0000 (18:24 +0000)
committerDan Gohman <gohman@apple.com>
Fri, 6 Aug 2010 18:24:38 +0000 (18:24 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@110458 91177308-0d34-0410-b5e6-96231b3b80d8

include/llvm/Analysis/AliasAnalysis.h
lib/Analysis/AliasAnalysis.cpp
test/Analysis/BasicAA/modref.ll

index bf8f5185cbba4defbb0b50a55442b6ff0af7d228..7b003d8a6914dbb2394c0c4a06e76d4140b777d6 100644 (file)
@@ -243,6 +243,7 @@ public:
   /// Convenience functions...
   ModRefResult getModRefInfo(const LoadInst *L, const Value *P, unsigned Size);
   ModRefResult getModRefInfo(const StoreInst *S, const Value *P, unsigned Size);
+  ModRefResult getModRefInfo(const VAArgInst* I, const Value* P, unsigned Size);
   ModRefResult getModRefInfo(const CallInst *C, const Value *P, unsigned Size) {
     return getModRefInfo(ImmutableCallSite(C), P, Size);
   }
@@ -250,10 +251,6 @@ public:
                              const Value *P, unsigned Size) {
     return getModRefInfo(ImmutableCallSite(I), P, Size);
   }
-  ModRefResult getModRefInfo(const VAArgInst* I,
-                             const Value* P, unsigned Size) {
-    return AliasAnalysis::ModRef;
-  }
   ModRefResult getModRefInfo(const Instruction *I,
                              const Value *P, unsigned Size) {
     switch (I->getOpcode()) {
index 0b15334e145a11e767b54a067c8a4ff83ed94e01..1f2528fa560f24614ecb298b0f15c114f92c7223 100644 (file)
@@ -229,6 +229,23 @@ AliasAnalysis::getModRefInfo(const StoreInst *S, const Value *P, unsigned Size)
   return Mod;
 }
 
+AliasAnalysis::ModRefResult
+AliasAnalysis::getModRefInfo(const VAArgInst *V, const Value *P, unsigned Size) {
+  // If the va_arg address cannot alias the pointer in question, then the
+  // specified memory cannot be accessed by the va_arg.
+  if (!alias(V->getOperand(0), UnknownSize, P, Size))
+    return NoModRef;
+
+  // If the pointer is a pointer to constant memory, then it could not have been
+  // modified by this va_arg.
+  if (pointsToConstantMemory(P))
+    return NoModRef;
+
+  // Otherwise, a va_arg reads and writes.
+  return ModRef;
+}
+
+
 AliasAnalysis::ModRefBehavior
 AliasAnalysis::getIntrinsicModRefBehavior(unsigned iid) {
 #define GET_INTRINSIC_MODREF_BEHAVIOR
index a2aabf135f6f099c974fd53230be31b0b78eb9a9..b9a3c5e58f68ee1d4527f3a6aa35324daf2334be 100644 (file)
@@ -123,3 +123,14 @@ define i32 @test5(i8* %P, i32 %Len) {
 ; CHECK: sub i32 %tmp, %tmp
 }
 
+define i8 @test6(i8* %p, i8* noalias %a) {
+  %x = load i8* %a
+  %t = va_arg i8* %p, float
+  %y = load i8* %a
+  %z = add i8 %x, %y
+  ret i8 %z
+; CHECK: @test6
+; CHECK: load i8* %a
+; CHECK-NOT: load
+; CHECK: ret
+}