diff options
author | Hal Finkel <hfinkel@anl.gov> | 2014-12-01 23:38:06 +0000 |
---|---|---|
committer | Hal Finkel <hfinkel@anl.gov> | 2014-12-01 23:38:06 +0000 |
commit | afcd8dbbcfca4cb0024cd116828ec0a803678f9d (patch) | |
tree | fba5d76fa383e25f05c754dc40f0a03c5b373bb2 /llvm/lib/Analysis/InstructionSimplify.cpp | |
parent | 8e302cdb453e55e09b7ca0c5163286916c32df43 (diff) | |
download | bcm5719-llvm-afcd8dbbcfca4cb0024cd116828ec0a803678f9d.tar.gz bcm5719-llvm-afcd8dbbcfca4cb0024cd116828ec0a803678f9d.zip |
Simplify pointer comparisons involving memory allocation functions
System memory allocation functions, which are identified at the IR level by the
noalias attribute on the return value, must return a pointer into a memory region
disjoint from any other memory accessible to the caller. We can use this
property to simplify pointer comparisons between allocated memory and local
stack addresses and the addresses of global variables. Neither the stack nor
global variables can overlap with the region used by the memory allocator.
Fixes PR21556.
llvm-svn: 223093
Diffstat (limited to 'llvm/lib/Analysis/InstructionSimplify.cpp')
-rw-r--r-- | llvm/lib/Analysis/InstructionSimplify.cpp | 35 |
1 files changed, 35 insertions, 0 deletions
diff --git a/llvm/lib/Analysis/InstructionSimplify.cpp b/llvm/lib/Analysis/InstructionSimplify.cpp index 3c61cd16cd5..85ebf694e69 100644 --- a/llvm/lib/Analysis/InstructionSimplify.cpp +++ b/llvm/lib/Analysis/InstructionSimplify.cpp @@ -20,6 +20,7 @@ #include "llvm/Analysis/InstructionSimplify.h" #include "llvm/ADT/SetVector.h" #include "llvm/ADT/Statistic.h" +#include "llvm/Analysis/AliasAnalysis.h" #include "llvm/Analysis/ConstantFolding.h" #include "llvm/Analysis/MemoryBuiltins.h" #include "llvm/Analysis/ValueTracking.h" @@ -31,6 +32,7 @@ #include "llvm/IR/Operator.h" #include "llvm/IR/PatternMatch.h" #include "llvm/IR/ValueHandle.h" +#include <algorithm> using namespace llvm; using namespace llvm::PatternMatch; @@ -2007,6 +2009,39 @@ static Constant *computePointerICmp(const DataLayout *DL, return ConstantExpr::getICmp(Pred, ConstantExpr::getAdd(LHSOffset, LHSNoBound), ConstantExpr::getAdd(RHSOffset, RHSNoBound)); + + // If one side of the equality comparison must come from a noalias call + // (meaning a system memory allocation function), and the other side must + // come from a pointer that cannot overlap with dynamically-allocated + // memory within the lifetime of the current function (allocas, byval + // arguments, globals), then determine the comparison result here. + SmallVector<Value *, 8> LHSUObjs, RHSUObjs; + GetUnderlyingObjects(LHS, LHSUObjs, DL); + GetUnderlyingObjects(RHS, RHSUObjs, DL); + + // Is the set of underlying objects all noalias calls? + auto IsNAC = [](SmallVectorImpl<Value *> &Objects) { + return std::all_of(Objects.begin(), Objects.end(), + [](Value *V){ return isNoAliasCall(V); }); + }; + + // Is the set of underlying objects all things which must be disjoint from + // noalias calls. + auto IsAllocDisjoint = [](SmallVectorImpl<Value *> &Objects) { + return std::all_of(Objects.begin(), Objects.end(), + [](Value *V){ + if (isa<AllocaInst>(V) || isa<GlobalValue>(V)) + return true; + if (const Argument *A = dyn_cast<Argument>(V)) + return A->hasByValAttr(); + return false; + }); + }; + + if ((IsNAC(LHSUObjs) && IsAllocDisjoint(RHSUObjs)) || + (IsNAC(RHSUObjs) && IsAllocDisjoint(LHSUObjs))) + return ConstantInt::get(GetCompareTy(LHS), + !CmpInst::isTrueWhenEqual(Pred)); } // Otherwise, fail. |