diff --git a/lib/Analysis/InstructionSimplify.cpp b/lib/Analysis/InstructionSimplify.cpp index 3c61cd16cd5..85ebf694e69 100644 --- a/lib/Analysis/InstructionSimplify.cpp +++ b/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 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 LHSUObjs, RHSUObjs; + GetUnderlyingObjects(LHS, LHSUObjs, DL); + GetUnderlyingObjects(RHS, RHSUObjs, DL); + + // Is the set of underlying objects all noalias calls? + auto IsNAC = [](SmallVectorImpl &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 &Objects) { + return std::all_of(Objects.begin(), Objects.end(), + [](Value *V){ + if (isa(V) || isa(V)) + return true; + if (const Argument *A = dyn_cast(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. diff --git a/test/Transforms/InstSimplify/noalias-ptr.ll b/test/Transforms/InstSimplify/noalias-ptr.ll new file mode 100644 index 00000000000..e3435097880 --- /dev/null +++ b/test/Transforms/InstSimplify/noalias-ptr.ll @@ -0,0 +1,108 @@ +; RUN: opt -instsimplify -S < %s | FileCheck %s +target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" +target triple = "x86_64-unknown-linux-gnu" + +@g1 = global i32 0, align 4 + +; Make sure we can simplify away a pointer comparison between +; dynamically-allocated memory and a local stack allocation. +; void p() +; { +; int *mData; +; int mStackData[10]; +; mData = new int[12]; +; if (mData != mStackData) { +; delete[] mData; +; } +; } + +define void @_Z2p1v() #0 { + %mStackData = alloca [10 x i32], align 16 + %1 = bitcast [10 x i32]* %mStackData to i8* + %2 = tail call noalias i8* @_Znam(i64 48) #4 + %3 = bitcast i8* %2 to i32* + %4 = getelementptr inbounds [10 x i32]* %mStackData, i64 0, i64 0 + %5 = icmp eq i32* %3, %4 + br i1 %5, label %7, label %6 + +; CHECK-LABEL: @_Z2p1v +; CHECK-NOT: icmp +; CHECK: ret void + +;