[llvm-branch-commits] [llvm-branch] r84104 - in /llvm/branches/Apple/Leela: lib/Analysis/BasicAliasAnalysis.cpp test/Analysis/BasicAA/2009-10-13-GEP-BaseNoAlias.ll test/Analysis/BasicAA/phi-aa.ll
Bob Wilson
bob.wilson at apple.com
Wed Oct 14 08:55:03 PDT 2009
Author: bwilson
Date: Wed Oct 14 10:55:02 2009
New Revision: 84104
URL: http://llvm.org/viewvc/llvm-project?rev=84104&view=rev
Log:
$ svn merge -c 84000 https://bwilson@llvm.org/svn/llvm-project/llvm/trunk
--- Merging r84000 into '.':
U lib/Analysis/BasicAliasAnalysis.cpp
$ svn merge -c 84038 https://bwilson@llvm.org/svn/llvm-project/llvm/trunk
--- Merging r84038 into '.':
A test/Analysis/BasicAA/phi-aa.ll
G lib/Analysis/BasicAliasAnalysis.cpp
$ svn merge -c 84069 https://bwilson@llvm.org/svn/llvm-project/llvm/trunk
--- Merging r84069 into '.':
U test/Analysis/BasicAA/phi-aa.ll
$ svn merge -c 84072 https://bwilson@llvm.org/svn/llvm-project/llvm/trunk
--- Merging r84072 into '.':
G lib/Analysis/BasicAliasAnalysis.cpp
$ svn merge -c 84074 https://bwilson@llvm.org/svn/llvm-project/llvm/trunk
--- Merging r84074 into '.':
G lib/Analysis/BasicAliasAnalysis.cpp
$ svn merge -c 84079 https://bwilson@llvm.org/svn/llvm-project/llvm/trunk
--- Merging r84079 into '.':
A test/Analysis/BasicAA/2009-10-13-GEP-BaseNoAlias.ll
G lib/Analysis/BasicAliasAnalysis.cpp
$ svn merge -c 84080 https://bwilson@llvm.org/svn/llvm-project/llvm/trunk
--- Merging r84080 into '.':
G lib/Analysis/BasicAliasAnalysis.cpp
Added:
llvm/branches/Apple/Leela/test/Analysis/BasicAA/2009-10-13-GEP-BaseNoAlias.ll
- copied unchanged from r84079, llvm/trunk/test/Analysis/BasicAA/2009-10-13-GEP-BaseNoAlias.ll
llvm/branches/Apple/Leela/test/Analysis/BasicAA/phi-aa.ll
- copied, changed from r84038, llvm/trunk/test/Analysis/BasicAA/phi-aa.ll
Modified:
llvm/branches/Apple/Leela/lib/Analysis/BasicAliasAnalysis.cpp
Modified: llvm/branches/Apple/Leela/lib/Analysis/BasicAliasAnalysis.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/branches/Apple/Leela/lib/Analysis/BasicAliasAnalysis.cpp?rev=84104&r1=84103&r2=84104&view=diff
==============================================================================
--- llvm/branches/Apple/Leela/lib/Analysis/BasicAliasAnalysis.cpp (original)
+++ llvm/branches/Apple/Leela/lib/Analysis/BasicAliasAnalysis.cpp Wed Oct 14 10:55:02 2009
@@ -27,6 +27,7 @@
#include "llvm/Operator.h"
#include "llvm/Pass.h"
#include "llvm/Target/TargetData.h"
+#include "llvm/ADT/SmallSet.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/Support/Compiler.h"
@@ -201,7 +202,12 @@
static char ID; // Class identification, replacement for typeinfo
BasicAliasAnalysis() : NoAA(&ID) {}
AliasResult alias(const Value *V1, unsigned V1Size,
- const Value *V2, unsigned V2Size);
+ const Value *V2, unsigned V2Size) {
+ assert(VisitedPHIs.empty() && "VisitedPHIs must be cleared after use!");
+ AliasResult Alias = aliasCheck(V1, V1Size, V2, V2Size);
+ VisitedPHIs.clear();
+ return Alias;
+ }
ModRefResult getModRefInfo(CallSite CS, Value *P, unsigned Size);
ModRefResult getModRefInfo(CallSite CS1, CallSite CS2);
@@ -215,6 +221,22 @@
bool pointsToConstantMemory(const Value *P);
private:
+ // VisitedPHIs - Track PHI nodes visited by a aliasCheck() call.
+ SmallSet<const PHINode*, 16> VisitedPHIs;
+
+ // aliasGEP - Provide a bunch of ad-hoc rules to disambiguate a GEP instruction
+ // against another.
+ AliasResult aliasGEP(const Value *V1, unsigned V1Size,
+ const Value *V2, unsigned V2Size);
+
+ // aliasPHI - Provide a bunch of ad-hoc rules to disambiguate a PHI instruction
+ // against another.
+ AliasResult aliasPHI(const PHINode *PN, unsigned PNSize,
+ const Value *V2, unsigned V2Size);
+
+ AliasResult aliasCheck(const Value *V1, unsigned V1Size,
+ const Value *V2, unsigned V2Size);
+
// CheckGEPInstructions - Check two GEP instructions with known
// must-aliasing base pointers. This checks to see if the index expressions
// preclude the pointers from aliasing...
@@ -308,61 +330,12 @@
return NoAA::getModRefInfo(CS1, CS2);
}
-
-// alias - Provide a bunch of ad-hoc rules to disambiguate in common cases, such
-// as array references.
+// aliasGEP - Provide a bunch of ad-hoc rules to disambiguate a GEP instruction
+// against another.
//
AliasAnalysis::AliasResult
-BasicAliasAnalysis::alias(const Value *V1, unsigned V1Size,
- const Value *V2, unsigned V2Size) {
- // Strip off any casts if they exist.
- V1 = V1->stripPointerCasts();
- V2 = V2->stripPointerCasts();
-
- // Are we checking for alias of the same value?
- if (V1 == V2) return MustAlias;
-
- if (!isa<PointerType>(V1->getType()) || !isa<PointerType>(V2->getType()))
- return NoAlias; // Scalars cannot alias each other
-
- // Figure out what objects these things are pointing to if we can.
- const Value *O1 = V1->getUnderlyingObject();
- const Value *O2 = V2->getUnderlyingObject();
-
- if (O1 != O2) {
- // If V1/V2 point to two different objects we know that we have no alias.
- if (isIdentifiedObject(O1) && isIdentifiedObject(O2))
- return NoAlias;
-
- // Arguments can't alias with local allocations or noalias calls.
- if ((isa<Argument>(O1) && (isa<AllocationInst>(O2) || isNoAliasCall(O2))) ||
- (isa<Argument>(O2) && (isa<AllocationInst>(O1) || isNoAliasCall(O1))))
- return NoAlias;
-
- // Most objects can't alias null.
- if ((isa<ConstantPointerNull>(V2) && isKnownNonNull(O1)) ||
- (isa<ConstantPointerNull>(V1) && isKnownNonNull(O2)))
- return NoAlias;
- }
-
- // If the size of one access is larger than the entire object on the other
- // side, then we know such behavior is undefined and can assume no alias.
- LLVMContext &Context = V1->getContext();
- if (TD)
- if ((V1Size != ~0U && isObjectSmallerThan(O2, V1Size, Context, *TD)) ||
- (V2Size != ~0U && isObjectSmallerThan(O1, V2Size, Context, *TD)))
- return NoAlias;
-
- // If one pointer is the result of a call/invoke and the other is a
- // non-escaping local object, then we know the object couldn't escape to a
- // point where the call could return it.
- if ((isa<CallInst>(O1) || isa<InvokeInst>(O1)) &&
- isNonEscapingLocalObject(O2) && O1 != O2)
- return NoAlias;
- if ((isa<CallInst>(O2) || isa<InvokeInst>(O2)) &&
- isNonEscapingLocalObject(O1) && O1 != O2)
- return NoAlias;
-
+BasicAliasAnalysis::aliasGEP(const Value *V1, unsigned V1Size,
+ const Value *V2, unsigned V2Size) {
// If we have two gep instructions with must-alias'ing base pointers, figure
// out if the indexes to the GEP tell us anything about the derived pointer.
// Note that we also handle chains of getelementptr instructions as well as
@@ -382,8 +355,8 @@
GEP1->getOperand(0)->getType() == GEP2->getOperand(0)->getType() &&
// All operands are the same, ignoring the base.
std::equal(GEP1->op_begin()+1, GEP1->op_end(), GEP2->op_begin()+1))
- return alias(GEP1->getOperand(0), V1Size, GEP2->getOperand(0), V2Size);
-
+ return aliasCheck(GEP1->getOperand(0), V1Size,
+ GEP2->getOperand(0), V2Size);
// Drill down into the first non-gep value, to test for must-aliasing of
// the base pointers.
@@ -400,7 +373,7 @@
const Value *BasePtr2 = GEP2->getOperand(0);
// Do the base pointers alias?
- AliasResult BaseAlias = alias(BasePtr1, ~0U, BasePtr2, ~0U);
+ AliasResult BaseAlias = aliasCheck(BasePtr1, ~0U, BasePtr2, ~0U);
if (BaseAlias == NoAlias) return NoAlias;
if (BaseAlias == MustAlias) {
// If the base pointers alias each other exactly, check to see if we can
@@ -430,63 +403,174 @@
// instruction. If one pointer is a GEP with a non-zero index of the other
// pointer, we know they cannot alias.
//
- if (isGEP(V2)) {
- std::swap(V1, V2);
- std::swap(V1Size, V2Size);
- }
+ if (V1Size == ~0U || V2Size == ~0U)
+ return MayAlias;
- if (V1Size != ~0U && V2Size != ~0U)
- if (isGEP(V1)) {
- SmallVector<Value*, 16> GEPOperands;
- const Value *BasePtr = GetGEPOperands(V1, GEPOperands);
-
- AliasResult R = alias(BasePtr, V1Size, V2, V2Size);
- if (R == MustAlias) {
- // If there is at least one non-zero constant index, we know they cannot
- // alias.
- bool ConstantFound = false;
- bool AllZerosFound = true;
- for (unsigned i = 0, e = GEPOperands.size(); i != e; ++i)
- if (const Constant *C = dyn_cast<Constant>(GEPOperands[i])) {
- if (!C->isNullValue()) {
- ConstantFound = true;
- AllZerosFound = false;
- break;
- }
- } else {
- AllZerosFound = false;
- }
+ SmallVector<Value*, 16> GEPOperands;
+ const Value *BasePtr = GetGEPOperands(V1, GEPOperands);
+
+ AliasResult R = aliasCheck(BasePtr, ~0U, V2, V2Size);
+ if (R != MustAlias)
+ // If V2 may alias GEP base pointer, conservatively returns MayAlias.
+ // If V2 is known not to alias GEP base pointer, then the two values
+ // cannot alias per GEP semantics: "A pointer value formed from a
+ // getelementptr instruction is associated with the addresses associated
+ // with the first operand of the getelementptr".
+ return R;
+
+ // If there is at least one non-zero constant index, we know they cannot
+ // alias.
+ bool ConstantFound = false;
+ bool AllZerosFound = true;
+ for (unsigned i = 0, e = GEPOperands.size(); i != e; ++i)
+ if (const Constant *C = dyn_cast<Constant>(GEPOperands[i])) {
+ if (!C->isNullValue()) {
+ ConstantFound = true;
+ AllZerosFound = false;
+ break;
+ }
+ } else {
+ AllZerosFound = false;
+ }
- // If we have getelementptr <ptr>, 0, 0, 0, 0, ... and V2 must aliases
- // the ptr, the end result is a must alias also.
- if (AllZerosFound)
- return MustAlias;
+ // If we have getelementptr <ptr>, 0, 0, 0, 0, ... and V2 must aliases
+ // the ptr, the end result is a must alias also.
+ if (AllZerosFound)
+ return MustAlias;
- if (ConstantFound) {
- if (V2Size <= 1 && V1Size <= 1) // Just pointer check?
- return NoAlias;
+ if (ConstantFound) {
+ if (V2Size <= 1 && V1Size <= 1) // Just pointer check?
+ return NoAlias;
- // Otherwise we have to check to see that the distance is more than
- // the size of the argument... build an index vector that is equal to
- // the arguments provided, except substitute 0's for any variable
- // indexes we find...
- if (TD && cast<PointerType>(
- BasePtr->getType())->getElementType()->isSized()) {
- for (unsigned i = 0; i != GEPOperands.size(); ++i)
- if (!isa<ConstantInt>(GEPOperands[i]))
- GEPOperands[i] =
- Constant::getNullValue(GEPOperands[i]->getType());
- int64_t Offset =
- TD->getIndexedOffset(BasePtr->getType(),
- &GEPOperands[0],
- GEPOperands.size());
+ // Otherwise we have to check to see that the distance is more than
+ // the size of the argument... build an index vector that is equal to
+ // the arguments provided, except substitute 0's for any variable
+ // indexes we find...
+ if (TD &&
+ cast<PointerType>(BasePtr->getType())->getElementType()->isSized()) {
+ for (unsigned i = 0; i != GEPOperands.size(); ++i)
+ if (!isa<ConstantInt>(GEPOperands[i]))
+ GEPOperands[i] = Constant::getNullValue(GEPOperands[i]->getType());
+ int64_t Offset = TD->getIndexedOffset(BasePtr->getType(),
+ &GEPOperands[0],
+ GEPOperands.size());
- if (Offset >= (int64_t)V2Size || Offset <= -(int64_t)V1Size)
- return NoAlias;
- }
- }
- }
+ if (Offset >= (int64_t)V2Size || Offset <= -(int64_t)V1Size)
+ return NoAlias;
}
+ }
+
+ return MayAlias;
+}
+
+// aliasPHI - Provide a bunch of ad-hoc rules to disambiguate a PHI instruction
+// against another.
+AliasAnalysis::AliasResult
+BasicAliasAnalysis::aliasPHI(const PHINode *PN, unsigned PNSize,
+ const Value *V2, unsigned V2Size) {
+ // The PHI node has already been visited, avoid recursion any further.
+ if (!VisitedPHIs.insert(PN))
+ return MayAlias;
+
+ SmallSet<Value*, 4> UniqueSrc;
+ SmallVector<Value*, 4> V1Srcs;
+ for (unsigned i = 0, e = PN->getNumIncomingValues(); i != e; ++i) {
+ Value *PV1 = PN->getIncomingValue(i);
+ if (isa<PHINode>(PV1))
+ // If any of the source itself is a PHI, return MayAlias conservatively
+ // to avoid compile time explosion. The worst possible case is if both
+ // sides are PHI nodes. In which case, this is O(m x n) time where 'm'
+ // and 'n' are the number of PHI sources.
+ return MayAlias;
+ if (UniqueSrc.insert(PV1))
+ V1Srcs.push_back(PV1);
+ }
+
+ AliasResult Alias = aliasCheck(V1Srcs[0], PNSize, V2, V2Size);
+ // Early exit if the check of the first PHI source against V2 is MayAlias.
+ // Other results are not possible.
+ if (Alias == MayAlias)
+ return MayAlias;
+
+ // If all sources of the PHI node NoAlias or MustAlias V2, then returns
+ // NoAlias / MustAlias. Otherwise, returns MayAlias.
+ for (unsigned i = 1, e = V1Srcs.size(); i != e; ++i) {
+ Value *V = V1Srcs[i];
+ AliasResult ThisAlias = aliasCheck(V, PNSize, V2, V2Size);
+ if (ThisAlias != Alias || ThisAlias == MayAlias)
+ return MayAlias;
+ }
+
+ return Alias;
+}
+
+// aliasCheck - Provide a bunch of ad-hoc rules to disambiguate in common cases,
+// such as array references.
+//
+AliasAnalysis::AliasResult
+BasicAliasAnalysis::aliasCheck(const Value *V1, unsigned V1Size,
+ const Value *V2, unsigned V2Size) {
+ // Strip off any casts if they exist.
+ V1 = V1->stripPointerCasts();
+ V2 = V2->stripPointerCasts();
+
+ // Are we checking for alias of the same value?
+ if (V1 == V2) return MustAlias;
+
+ if (!isa<PointerType>(V1->getType()) || !isa<PointerType>(V2->getType()))
+ return NoAlias; // Scalars cannot alias each other
+
+ // Figure out what objects these things are pointing to if we can.
+ const Value *O1 = V1->getUnderlyingObject();
+ const Value *O2 = V2->getUnderlyingObject();
+
+ if (O1 != O2) {
+ // If V1/V2 point to two different objects we know that we have no alias.
+ if (isIdentifiedObject(O1) && isIdentifiedObject(O2))
+ return NoAlias;
+
+ // Arguments can't alias with local allocations or noalias calls.
+ if ((isa<Argument>(O1) && (isa<AllocationInst>(O2) || isNoAliasCall(O2))) ||
+ (isa<Argument>(O2) && (isa<AllocationInst>(O1) || isNoAliasCall(O1))))
+ return NoAlias;
+
+ // Most objects can't alias null.
+ if ((isa<ConstantPointerNull>(V2) && isKnownNonNull(O1)) ||
+ (isa<ConstantPointerNull>(V1) && isKnownNonNull(O2)))
+ return NoAlias;
+ }
+
+ // If the size of one access is larger than the entire object on the other
+ // side, then we know such behavior is undefined and can assume no alias.
+ LLVMContext &Context = V1->getContext();
+ if (TD)
+ if ((V1Size != ~0U && isObjectSmallerThan(O2, V1Size, Context, *TD)) ||
+ (V2Size != ~0U && isObjectSmallerThan(O1, V2Size, Context, *TD)))
+ return NoAlias;
+
+ // If one pointer is the result of a call/invoke and the other is a
+ // non-escaping local object, then we know the object couldn't escape to a
+ // point where the call could return it.
+ if ((isa<CallInst>(O1) || isa<InvokeInst>(O1)) &&
+ isNonEscapingLocalObject(O2) && O1 != O2)
+ return NoAlias;
+ if ((isa<CallInst>(O2) || isa<InvokeInst>(O2)) &&
+ isNonEscapingLocalObject(O1) && O1 != O2)
+ return NoAlias;
+
+ if (!isGEP(V1) && isGEP(V2)) {
+ std::swap(V1, V2);
+ std::swap(V1Size, V2Size);
+ }
+ if (isGEP(V1))
+ return aliasGEP(V1, V1Size, V2, V2Size);
+
+ if (isa<PHINode>(V2) && !isa<PHINode>(V1)) {
+ std::swap(V1, V2);
+ std::swap(V1Size, V2Size);
+ }
+ if (const PHINode *PN = dyn_cast<PHINode>(V1))
+ return aliasPHI(PN, V1Size, V2, V2Size);
return MayAlias;
}
Copied: llvm/branches/Apple/Leela/test/Analysis/BasicAA/phi-aa.ll (from r84038, llvm/trunk/test/Analysis/BasicAA/phi-aa.ll)
URL: http://llvm.org/viewvc/llvm-project/llvm/branches/Apple/Leela/test/Analysis/BasicAA/phi-aa.ll?p2=llvm/branches/Apple/Leela/test/Analysis/BasicAA/phi-aa.ll&p1=llvm/trunk/test/Analysis/BasicAA/phi-aa.ll&r1=84038&r2=84104&rev=84104&view=diff
==============================================================================
--- llvm/trunk/test/Analysis/BasicAA/phi-aa.ll (original)
+++ llvm/branches/Apple/Leela/test/Analysis/BasicAA/phi-aa.ll Wed Oct 14 10:55:02 2009
@@ -1,86 +1,29 @@
-; RUN: opt < %s -basicaa -licm -S | FileCheck %s
+; RUN: opt < %s -basicaa -aa-eval -print-all-alias-modref-info -disable-output |& grep {NoAlias:.*%P,.*@Z}
; rdar://7282591
-%struct.CFRuntimeBase = type { i32, [4 x i8] }
-%struct.XXXAffineTransform = type { float, float, float, float, float, float }
-%struct.XXXContext = type { %struct.CFRuntimeBase, i32, i32, i32, i8*, %struct.XXXContextDelegate*, void (%struct.XXXContext*)*, void (%struct.XXXContext*)*, %struct.XXXImage* (%struct.XXXContext*, %struct.XXXRect*, %struct.XXXImage*, i8*)*, i8*, %struct.__CFDictionary*, i32, %struct.XXXGState*, %struct.XXXGStack*, %struct.XXXRenderingState*, %struct.XXXAffineTransform, %struct.XXXPath*, %struct.__CFDictionary*, %struct.XXXPixelAccess* }
-%struct.XXXContextDelegate = type opaque
-%struct.XXXGStack = type opaque
-%struct.XXXGState = type opaque
-%struct.XXXImage = type opaque
-%struct.XXXPath = type opaque
-%struct.XXXPixelAccess = type opaque
-%struct.XXXPoint = type { float, float }
-%struct.XXXRect = type { %struct.XXXPoint, %struct.XXXPoint }
-%struct.XXXRenderingState = type opaque
-%struct.__CFDictionary = type opaque
-
-define void @t(%struct.XXXContext* %context, i16* %glyphs, %struct.XXXPoint* %advances, i32 %count) nounwind optsize ssp {
-; CHECK: @t
-; CHECK: bb21.preheader:
-; CHECK: %tmp28 = getelementptr
-; CHECK: %tmp28.promoted = load
-entry:
- br i1 undef, label %bb1, label %bb
-
-bb: ; preds = %entry
- br i1 undef, label %bb2, label %bb1
-
-bb1: ; preds = %bb, %entry
- ret void
-
-bb2: ; preds = %bb
- br i1 undef, label %bb35, label %bb7
+ at X = common global i32 0
+ at Y = common global i32 0
+ at Z = common global i32 0
-bb7: ; preds = %bb2
- br i1 undef, label %bb35, label %bb10
-
-bb10: ; preds = %bb7
- %tmp18 = alloca i8, i32 undef, align 1 ; <i8*> [#uses=1]
- br i1 undef, label %bb35, label %bb15
-
-bb15: ; preds = %bb10
- br i1 undef, label %bb17, label %bb16
-
-bb16: ; preds = %bb15
- %tmp21 = bitcast i8* %tmp18 to %struct.XXXPoint* ; <%struct.XXXPoint*> [#uses=1]
- br label %bb18
-
-bb17: ; preds = %bb15
- %tmp22 = malloc %struct.XXXPoint, i32 %count ; <%struct.XXXPoint*> [#uses=1]
- br label %bb18
-
-bb18: ; preds = %bb17, %bb16
- %positions.0 = phi %struct.XXXPoint* [ %tmp21, %bb16 ], [ %tmp22, %bb17 ] ; <%struct.XXXPoint*> [#uses=1]
- br i1 undef, label %bb35, label %bb20
-
-bb20: ; preds = %bb18
- br i1 undef, label %bb21, label %bb25
-
-bb21: ; preds = %bb21, %bb20
- %tmp28 = getelementptr inbounds %struct.XXXPoint* %positions.0, i32 undef, i32 0 ; <float*> [#uses=1]
- store float undef, float* %tmp28, align 4
- %elt22 = getelementptr inbounds %struct.XXXPoint* %advances, i32 undef, i32 1 ; <float*> [#uses=1]
- %val23 = load float* %elt22 ; <float> [#uses=0]
- br i1 undef, label %bb21, label %bb25
-
-bb25: ; preds = %bb21, %bb20
- switch i32 undef, label %bb26 [
- i32 4, label %bb27
- i32 5, label %bb27
- i32 6, label %bb27
- i32 7, label %bb28
- ]
-
-bb26: ; preds = %bb25
- unreachable
-
-bb27: ; preds = %bb25, %bb25, %bb25
- unreachable
-
-bb28: ; preds = %bb25
- unreachable
+define void @foo(i32 %cond) nounwind ssp {
+entry:
+ %"alloca point" = bitcast i32 0 to i32
+ %tmp = icmp ne i32 %cond, 0
+ br i1 %tmp, label %bb, label %bb1
+
+bb:
+ br label %bb2
+
+bb1:
+ br label %bb2
+
+bb2:
+ %P = phi i32* [ @X, %bb ], [ @Y, %bb1 ]
+ %tmp1 = load i32* @Z, align 4
+ store i32 123, i32* %P, align 4
+ %tmp2 = load i32* @Z, align 4
+ br label %return
-bb35: ; preds = %bb18, %bb10, %bb7, %bb2
+return:
ret void
}
More information about the llvm-branch-commits
mailing list