[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