[llvm-commits] [llvm] r164561 - in /llvm/trunk: lib/Transforms/Scalar/DeadStoreElimination.cpp test/Transforms/DeadStoreElimination/libcalls.ll
Jim Grosbach
grosbach at apple.com
Mon Sep 24 16:41:04 PDT 2012
On Sep 24, 2012, at 3:09 PM, Nick Lewycky <nicholas at mxc.ca> wrote:
> Author: nicholas
> Date: Mon Sep 24 17:09:10 2012
> New Revision: 164561
>
> URL: http://llvm.org/viewvc/llvm-project?rev=164561&view=rev
> Log:
> Teach DSE that strcpy, strncpy, strcat and strncat are all stores which may be
> dead.
>
> Added:
> llvm/trunk/test/Transforms/DeadStoreElimination/libcalls.ll
> Modified:
> llvm/trunk/lib/Transforms/Scalar/DeadStoreElimination.cpp
>
> Modified: llvm/trunk/lib/Transforms/Scalar/DeadStoreElimination.cpp
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/DeadStoreElimination.cpp?rev=164561&r1=164560&r2=164561&view=diff
> ==============================================================================
> --- llvm/trunk/lib/Transforms/Scalar/DeadStoreElimination.cpp (original)
> +++ llvm/trunk/lib/Transforms/Scalar/DeadStoreElimination.cpp Mon Sep 24 17:09:10 2012
> @@ -30,6 +30,7 @@
> #include "llvm/Analysis/MemoryDependenceAnalysis.h"
> #include "llvm/Analysis/ValueTracking.h"
> #include "llvm/Target/TargetData.h"
> +#include "llvm/Target/TargetLibraryInfo.h"
> #include "llvm/Transforms/Utils/Local.h"
> #include "llvm/Support/Debug.h"
> #include "llvm/ADT/SetVector.h"
> @@ -146,7 +147,7 @@
>
> /// hasMemoryWrite - Does this instruction write some memory? This only returns
> /// true for things that we can analyze with other helpers below.
> -static bool hasMemoryWrite(Instruction *I) {
> +static bool hasMemoryWrite(Instruction *I, const TargetLibraryInfo *TLI) {
> if (isa<StoreInst>(I))
> return true;
> if (IntrinsicInst *II = dyn_cast<IntrinsicInst>(I)) {
> @@ -161,6 +162,26 @@
> return true;
> }
> }
> + if (CallSite CS = I) {
> + if (Function *F = CS.getCalledFunction()) {
> + if (TLI && TLI->has(LibFunc::strcpy) &&
> + F->getName() == TLI->getName(LibFunc::strcpy)) {
> + return true;
> + }
> + if (TLI && TLI->has(LibFunc::strncpy) &&
> + F->getName() == TLI->getName(LibFunc::strncpy)) {
> + return true;
> + }
> + if (TLI && TLI->has(LibFunc::strcat) &&
> + F->getName() == TLI->getName(LibFunc::strcat)) {
> + return true;
> + }
> + if (TLI && TLI->has(LibFunc::strncat) &&
> + F->getName() == TLI->getName(LibFunc::strncat)) {
> + return true;
> + }
> + }
> + }
> return false;
> }
>
> @@ -208,7 +229,8 @@
> /// instruction if any.
> static AliasAnalysis::Location
> getLocForRead(Instruction *Inst, AliasAnalysis &AA) {
> - assert(hasMemoryWrite(Inst) && "Unknown instruction case");
> + assert(hasMemoryWrite(Inst, AA.getTargetLibraryInfo()) &&
> + "Unknown instruction case");
>
> // The only instructions that both read and write are the mem transfer
> // instructions (memcpy/memmove).
> @@ -225,23 +247,29 @@
> if (StoreInst *SI = dyn_cast<StoreInst>(I))
> return SI->isUnordered();
>
> - IntrinsicInst *II = cast<IntrinsicInst>(I);
> - switch (II->getIntrinsicID()) {
> - default: llvm_unreachable("doesn't pass 'hasMemoryWrite' predicate");
> - case Intrinsic::lifetime_end:
> - // Never remove dead lifetime_end's, e.g. because it is followed by a
> - // free.
> - return false;
> - case Intrinsic::init_trampoline:
> - // Always safe to remove init_trampoline.
> - return true;
> + if (IntrinsicInst *II = dyn_cast<IntrinsicInst>(I)) {
> + switch (II->getIntrinsicID()) {
> + default: llvm_unreachable("doesn't pass 'hasMemoryWrite' predicate");
> + case Intrinsic::lifetime_end:
> + // Never remove dead lifetime_end's, e.g. because it is followed by a
> + // free.
> + return false;
> + case Intrinsic::init_trampoline:
> + // Always safe to remove init_trampoline.
> + return true;
>
> - case Intrinsic::memset:
> - case Intrinsic::memmove:
> - case Intrinsic::memcpy:
> - // Don't remove volatile memory intrinsics.
> - return !cast<MemIntrinsic>(II)->isVolatile();
> + case Intrinsic::memset:
> + case Intrinsic::memmove:
> + case Intrinsic::memcpy:
> + // Don't remove volatile memory intrinsics.
> + return !cast<MemIntrinsic>(II)->isVolatile();
> + }
> }
> +
> + if (CallSite CS = I) // If we assume hasMemoryWrite(I) is true,
> + return true; // then there's nothing left to check.
warning: unused
variable 'CS' [-Wunused-variable]
if (CallSite CS = I) // If we assume hasMemoryWrite(I) is true,
^
> +
> + return false;
> }
>
>
> @@ -252,14 +280,19 @@
> if (isa<StoreInst>(I))
> return false;
>
> - IntrinsicInst *II = cast<IntrinsicInst>(I);
> - switch (II->getIntrinsicID()) {
> - default: return false;
> - case Intrinsic::memset:
> - case Intrinsic::memcpy:
> - // Do shorten memory intrinsics.
> - return true;
> + if (IntrinsicInst *II = dyn_cast<IntrinsicInst>(I)) {
> + switch (II->getIntrinsicID()) {
> + default: return false;
> + case Intrinsic::memset:
> + case Intrinsic::memcpy:
> + // Do shorten memory intrinsics.
> + return true;
> + }
> }
> +
> + // Don't shorten libcalls calls for now.
> +
> + return false;
> }
>
> /// getStoredPointerOperand - Return the pointer that is being written to.
> @@ -269,12 +302,18 @@
> if (MemIntrinsic *MI = dyn_cast<MemIntrinsic>(I))
> return MI->getDest();
>
> - IntrinsicInst *II = cast<IntrinsicInst>(I);
> - switch (II->getIntrinsicID()) {
> - default: llvm_unreachable("Unexpected intrinsic!");
> - case Intrinsic::init_trampoline:
> - return II->getArgOperand(0);
> + if (IntrinsicInst *II = dyn_cast<IntrinsicInst>(I)) {
> + switch (II->getIntrinsicID()) {
> + default: llvm_unreachable("Unexpected intrinsic!");
> + case Intrinsic::init_trampoline:
> + return II->getArgOperand(0);
> + }
> }
> +
> + CallSite CS(I);
> + // All the supported functions so far happen to have dest as their first
> + // argument.
> + return CS.getArgument(0);
> }
>
> static uint64_t getPointerSize(const Value *V, AliasAnalysis &AA) {
> @@ -463,7 +502,7 @@
> }
>
> // If we find something that writes memory, get its memory dependence.
> - if (!hasMemoryWrite(Inst))
> + if (!hasMemoryWrite(Inst, TLI))
> continue;
>
> MemDepResult InstDep = MD->getDependency(Inst);
> @@ -630,7 +669,7 @@
> MemDepResult Dep = MD->getPointerDependencyFrom(Loc, false, InstPt, BB);
> while (Dep.isDef() || Dep.isClobber()) {
> Instruction *Dependency = Dep.getInst();
> - if (!hasMemoryWrite(Dependency) || !isRemovable(Dependency))
> + if (!hasMemoryWrite(Dependency, TLI) || !isRemovable(Dependency))
> break;
>
> Value *DepPointer =
> @@ -699,7 +738,7 @@
> --BBI;
>
> // If we find a store, check to see if it points into a dead stack value.
> - if (hasMemoryWrite(BBI) && isRemovable(BBI)) {
> + if (hasMemoryWrite(BBI, TLI) && isRemovable(BBI)) {
> // See through pointer-to-pointer bitcasts
> SmallVector<Value *, 4> Pointers;
> GetUnderlyingObjects(getStoredPointerOperand(BBI), Pointers);
>
> Added: llvm/trunk/test/Transforms/DeadStoreElimination/libcalls.ll
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/DeadStoreElimination/libcalls.ll?rev=164561&view=auto
> ==============================================================================
> --- llvm/trunk/test/Transforms/DeadStoreElimination/libcalls.ll (added)
> +++ llvm/trunk/test/Transforms/DeadStoreElimination/libcalls.ll Mon Sep 24 17:09:10 2012
> @@ -0,0 +1,46 @@
> +; RUN: opt -S -basicaa -dse < %s | FileCheck %s
> +
> +declare i8* @strcpy(i8* %dest, i8* %src) nounwind
> +define void @test1(i8* %src) {
> +; CHECK: @test1
> + %B = alloca [16 x i8]
> + %dest = getelementptr inbounds [16 x i8]* %B, i64 0, i64 0
> +; CHECK-NOT: @strcpy
> + %call = call i8* @strcpy(i8* %dest, i8* %src)
> +; CHECK: ret void
> + ret void
> +}
> +
> +declare i8* @strncpy(i8* %dest, i8* %src, i32 %n) nounwind
> +define void @test2(i8* %src) {
> +; CHECK: @test2
> + %B = alloca [16 x i8]
> + %dest = getelementptr inbounds [16 x i8]* %B, i64 0, i64 0
> +; CHECK-NOT: @strcpy
> + %call = call i8* @strncpy(i8* %dest, i8* %src, i32 12)
> +; CHECK: ret void
> + ret void
> +}
> +
> +declare i8* @strcat(i8* %dest, i8* %src) nounwind
> +define void @test3(i8* %src) {
> +; CHECK: @test3
> + %B = alloca [16 x i8]
> + %dest = getelementptr inbounds [16 x i8]* %B, i64 0, i64 0
> +; CHECK-NOT: @strcpy
> + %call = call i8* @strcat(i8* %dest, i8* %src)
> +; CHECK: ret void
> + ret void
> +}
> +
> +declare i8* @strncat(i8* %dest, i8* %src, i32 %n) nounwind
> +define void @test4(i8* %src) {
> +; CHECK: @test4
> + %B = alloca [16 x i8]
> + %dest = getelementptr inbounds [16 x i8]* %B, i64 0, i64 0
> +; CHECK-NOT: @strcpy
> + %call = call i8* @strncat(i8* %dest, i8* %src, i32 12)
> +; CHECK: ret void
> + ret void
> +}
> +
>
>
> _______________________________________________
> llvm-commits mailing list
> llvm-commits at cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits
More information about the llvm-commits
mailing list