From 7e32aa1015b0553a486af05780235ae60ac2df21 Mon Sep 17 00:00:00 2001 From: Hal Finkel Date: Mon, 1 Dec 2014 23:38:06 +0000 Subject: [PATCH] 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. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@223093 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Analysis/InstructionSimplify.cpp | 35 +++++++ test/Transforms/InstSimplify/noalias-ptr.ll | 108 ++++++++++++++++++++ 2 files changed, 143 insertions(+) create mode 100644 test/Transforms/InstSimplify/noalias-ptr.ll 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 + +;