[BasicAA] Extend inbound GEP negative offset logic to GlobalVariables
r270777 improved the precision of alloca vs. inbounbds GEP alias queries: if we have (a) an inbounds GEP and (b) a pointer based on an alloca, and the beginning of the object the GEP points to would have a negative offset with respect to the alloca, then the GEP can not alias pointer (b). This makes the same logic fire when (b) is based on a GlobalVariable instead of an alloca. Differential Revision: http://reviews.llvm.org/D20652 llvm-svn: 270893
This commit is contained in:
parent
d99068d26d
commit
ae21491819
|
@ -157,8 +157,8 @@ private:
|
||||||
const DataLayout &DL, AssumptionCache *AC, DominatorTree *DT);
|
const DataLayout &DL, AssumptionCache *AC, DominatorTree *DT);
|
||||||
|
|
||||||
static bool isGEPBaseAtNegativeOffset(const GEPOperator *GEPOp,
|
static bool isGEPBaseAtNegativeOffset(const GEPOperator *GEPOp,
|
||||||
const DecomposedGEP &DecompGEP, const DecomposedGEP &DecompAlloca,
|
const DecomposedGEP &DecompGEP, const DecomposedGEP &DecompObject,
|
||||||
uint64_t AllocaAccessSize);
|
uint64_t ObjectAccessSize);
|
||||||
|
|
||||||
/// \brief A Heuristic for aliasGEP that searches for a constant offset
|
/// \brief A Heuristic for aliasGEP that searches for a constant offset
|
||||||
/// between the variables.
|
/// between the variables.
|
||||||
|
|
|
@ -955,6 +955,11 @@ static AliasResult aliasSameBasePointerGEPs(const GEPOperator *GEP1,
|
||||||
// repsect to the alloca, that means the GEP can not alias pointer (b).
|
// repsect to the alloca, that means the GEP can not alias pointer (b).
|
||||||
// Note that the pointer based on the alloca may not be a GEP. For
|
// Note that the pointer based on the alloca may not be a GEP. For
|
||||||
// example, it may be the alloca itself.
|
// example, it may be the alloca itself.
|
||||||
|
// The same applies if (b) is based on a GlobalVariable. Note that just being
|
||||||
|
// based on isIdentifiedObject() is not enough - we need an identified object
|
||||||
|
// that does not permit access to negative offsets. For example, a negative
|
||||||
|
// offset from a noalias argument or call can be inbounds w.r.t the actual
|
||||||
|
// underlying object.
|
||||||
//
|
//
|
||||||
// For example, consider:
|
// For example, consider:
|
||||||
//
|
//
|
||||||
|
@ -977,19 +982,22 @@ static AliasResult aliasSameBasePointerGEPs(const GEPOperator *GEP1,
|
||||||
// the highest %f1 can be is (%alloca + 3). This means %random can not be higher
|
// the highest %f1 can be is (%alloca + 3). This means %random can not be higher
|
||||||
// than (%alloca - 1), and so is not inbounds, a contradiction.
|
// than (%alloca - 1), and so is not inbounds, a contradiction.
|
||||||
bool BasicAAResult::isGEPBaseAtNegativeOffset(const GEPOperator *GEPOp,
|
bool BasicAAResult::isGEPBaseAtNegativeOffset(const GEPOperator *GEPOp,
|
||||||
const DecomposedGEP &DecompGEP, const DecomposedGEP &DecompAlloca,
|
const DecomposedGEP &DecompGEP, const DecomposedGEP &DecompObject,
|
||||||
uint64_t AllocaAccessSize) {
|
uint64_t ObjectAccessSize) {
|
||||||
// If the alloca access size is unknown, or the GEP isn't inbounds, bail.
|
// If the object access size is unknown, or the GEP isn't inbounds, bail.
|
||||||
if (AllocaAccessSize == MemoryLocation::UnknownSize || !GEPOp->isInBounds())
|
if (ObjectAccessSize == MemoryLocation::UnknownSize || !GEPOp->isInBounds())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// We need an alloca, and want to know the offset of the pointer
|
// We need the object to be an alloca or a globalvariable, and want to know
|
||||||
// from the alloca precisely, so no variable indices are allowed.
|
// the offset of the pointer from the object precisely, so no variable
|
||||||
if (!isa<AllocaInst>(DecompAlloca.Base) || !DecompAlloca.VarIndices.empty())
|
// indices are allowed.
|
||||||
|
if (!(isa<AllocaInst>(DecompObject.Base) ||
|
||||||
|
isa<GlobalVariable>(DecompObject.Base)) ||
|
||||||
|
!DecompObject.VarIndices.empty())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
int64_t AllocaBaseOffset = DecompAlloca.StructOffset +
|
int64_t ObjectBaseOffset = DecompObject.StructOffset +
|
||||||
DecompAlloca.OtherOffset;
|
DecompObject.OtherOffset;
|
||||||
|
|
||||||
// If the GEP has no variable indices, we know the precise offset
|
// If the GEP has no variable indices, we know the precise offset
|
||||||
// from the base, then use it. If the GEP has variable indices, we're in
|
// from the base, then use it. If the GEP has variable indices, we're in
|
||||||
|
@ -1000,7 +1008,7 @@ bool BasicAAResult::isGEPBaseAtNegativeOffset(const GEPOperator *GEPOp,
|
||||||
if (DecompGEP.VarIndices.empty())
|
if (DecompGEP.VarIndices.empty())
|
||||||
GEPBaseOffset += DecompGEP.OtherOffset;
|
GEPBaseOffset += DecompGEP.OtherOffset;
|
||||||
|
|
||||||
return (GEPBaseOffset >= AllocaBaseOffset + (int64_t)AllocaAccessSize);
|
return (GEPBaseOffset >= ObjectBaseOffset + (int64_t)ObjectAccessSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Provides a bunch of ad-hoc rules to disambiguate a GEP instruction against
|
/// Provides a bunch of ad-hoc rules to disambiguate a GEP instruction against
|
||||||
|
|
|
@ -26,6 +26,17 @@ define void @arg(i32* %arg) {
|
||||||
ret void
|
ret void
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@gv = global i32 1
|
||||||
|
; CHECK-LABEL: Function: global:
|
||||||
|
; CHECK-DAG: MayAlias: i32* %p0, i32* @gv
|
||||||
|
; CHECK-DAG: NoAlias: i32* %p1, i32* @gv
|
||||||
|
define void @global() {
|
||||||
|
%random = call i32* @random.i32(i32* @gv)
|
||||||
|
%p0 = getelementptr inbounds i32, i32* %random, i32 0
|
||||||
|
%p1 = getelementptr inbounds i32, i32* %random, i32 1
|
||||||
|
ret void
|
||||||
|
}
|
||||||
|
|
||||||
; CHECK-LABEL: Function: struct:
|
; CHECK-LABEL: Function: struct:
|
||||||
; CHECK-DAG: MayAlias: i32* %f0, i32* %p0
|
; CHECK-DAG: MayAlias: i32* %f0, i32* %p0
|
||||||
; CHECK-DAG: MayAlias: i32* %f1, i32* %p0
|
; CHECK-DAG: MayAlias: i32* %f1, i32* %p0
|
||||||
|
|
Loading…
Reference in New Issue