[llvm-commits] [llvm] r168893 - in /llvm/trunk: lib/Transforms/Scalar/SimplifyLibCalls.cpp lib/Transforms/Utils/SimplifyLibCalls.cpp test/Transforms/InstCombine/fprintf-1.ll test/Transforms/InstCombine/fputs-1.ll test/Transforms/SimplifyLibCalls/FPuts.ll

Nadav Rotem nrotem at apple.com
Tue Mar 5 14:52:29 PST 2013


Hi Meador, 

I am now working on improving the clang compile time and I ran into a severe compile time regression in InstCombine and I think that it is due to your LibCallOptimization changes.  The problem is that InstCombiner::visitCallSite() calls LibCallSimplifier::initOptimizations().  InitOptimizations inserts dozens of function names into string map. It rehashes the map and allocates memory very often, and this initialization takes a long time.  I am profiling a typical C++ programs that uses STL, and I see lots of functions don't do much beside calling other functions. I already optimized the memory allocation, but not the insertion into the StringMap. On my program, initOptimizations takes 13.5% of the execution time of InstCombine.  I understand that we only initialize this data structure once per function, but many c++ programs have lots of small functions and the cost of initialization is still high. Can you please look into this problem ? 

Thanks,
Nadav
 


On Nov 29, 2012, at 7:45 AM, Meador Inge <meadori at codesourcery.com> wrote:

> Author: meadori
> Date: Thu Nov 29 09:45:43 2012
> New Revision: 168893
> 
> URL: http://llvm.org/viewvc/llvm-project?rev=168893&view=rev
> Log:
> instcombine: Migrate fputs optimizations
> 
> This patch migrates the fputs optimizations from the simplify-libcalls
> pass into the instcombine library call simplifier.
> 
> Added:
>    llvm/trunk/test/Transforms/InstCombine/fputs-1.ll
> Removed:
>    llvm/trunk/test/Transforms/SimplifyLibCalls/FPuts.ll
> Modified:
>    llvm/trunk/lib/Transforms/Scalar/SimplifyLibCalls.cpp
>    llvm/trunk/lib/Transforms/Utils/SimplifyLibCalls.cpp
>    llvm/trunk/test/Transforms/InstCombine/fprintf-1.ll
> 
> Modified: llvm/trunk/lib/Transforms/Scalar/SimplifyLibCalls.cpp
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/SimplifyLibCalls.cpp?rev=168893&r1=168892&r2=168893&view=diff
> ==============================================================================
> --- llvm/trunk/lib/Transforms/Scalar/SimplifyLibCalls.cpp (original)
> +++ llvm/trunk/lib/Transforms/Scalar/SimplifyLibCalls.cpp Thu Nov 29 09:45:43 2012
> @@ -87,31 +87,6 @@
> //===----------------------------------------------------------------------===//
> 
> //===---------------------------------------===//
> -// 'fputs' Optimizations
> -
> -struct FPutsOpt : public LibCallOptimization {
> -  virtual Value *CallOptimizer(Function *Callee, CallInst *CI, IRBuilder<> &B) {
> -    // These optimizations require DataLayout.
> -    if (!TD) return 0;
> -
> -    // Require two pointers.  Also, we can't optimize if return value is used.
> -    FunctionType *FT = Callee->getFunctionType();
> -    if (FT->getNumParams() != 2 || !FT->getParamType(0)->isPointerTy() ||
> -        !FT->getParamType(1)->isPointerTy() ||
> -        !CI->use_empty())
> -      return 0;
> -
> -    // fputs(s,F) --> fwrite(s,1,strlen(s),F)
> -    uint64_t Len = GetStringLength(CI->getArgOperand(0));
> -    if (!Len) return 0;
> -    // Known to have no uses (see above).
> -    return EmitFWrite(CI->getArgOperand(0),
> -                      ConstantInt::get(TD->getIntPtrType(*Context), Len-1),
> -                      CI->getArgOperand(1), B, TD, TLI);
> -  }
> -};
> -
> -//===---------------------------------------===//
> // 'puts' Optimizations
> 
> struct PutsOpt : public LibCallOptimization {
> @@ -153,7 +128,6 @@
> 
>     StringMap<LibCallOptimization*> Optimizations;
>     // Formatting and IO Optimizations
> -    FPutsOpt FPuts;
>     PutsOpt Puts;
> 
>     bool Modified;  // This is only used by doInitialization.
> @@ -210,7 +184,6 @@
> /// we know.
> void SimplifyLibCalls::InitOptimizations() {
>   // Formatting and IO Optimizations
> -  AddOpt(LibFunc::fputs, &FPuts);
>   Optimizations["puts"] = &Puts;
> }
> 
> 
> Modified: llvm/trunk/lib/Transforms/Utils/SimplifyLibCalls.cpp
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Utils/SimplifyLibCalls.cpp?rev=168893&r1=168892&r2=168893&view=diff
> ==============================================================================
> --- llvm/trunk/lib/Transforms/Utils/SimplifyLibCalls.cpp (original)
> +++ llvm/trunk/lib/Transforms/Utils/SimplifyLibCalls.cpp Thu Nov 29 09:45:43 2012
> @@ -1610,6 +1610,28 @@
>   }
> };
> 
> +struct FPutsOpt : public LibCallOptimization {
> +  virtual Value *callOptimizer(Function *Callee, CallInst *CI, IRBuilder<> &B) {
> +    // These optimizations require DataLayout.
> +    if (!TD) return 0;
> +
> +    // Require two pointers.  Also, we can't optimize if return value is used.
> +    FunctionType *FT = Callee->getFunctionType();
> +    if (FT->getNumParams() != 2 || !FT->getParamType(0)->isPointerTy() ||
> +        !FT->getParamType(1)->isPointerTy() ||
> +        !CI->use_empty())
> +      return 0;
> +
> +    // fputs(s,F) --> fwrite(s,1,strlen(s),F)
> +    uint64_t Len = GetStringLength(CI->getArgOperand(0));
> +    if (!Len) return 0;
> +    // Known to have no uses (see above).
> +    return EmitFWrite(CI->getArgOperand(0),
> +                      ConstantInt::get(TD->getIntPtrType(*Context), Len-1),
> +                      CI->getArgOperand(1), B, TD, TLI);
> +  }
> +};
> +
> } // End anonymous namespace.
> 
> namespace llvm {
> @@ -1668,6 +1690,7 @@
>   SPrintFOpt SPrintF;
>   FPrintFOpt FPrintF;
>   FWriteOpt FWrite;
> +  FPutsOpt FPuts;
> 
>   void initOptimizations();
>   void addOpt(LibFunc::Func F, LibCallOptimization* Opt);
> @@ -1795,6 +1818,7 @@
>   addOpt(LibFunc::sprintf, &SPrintF);
>   addOpt(LibFunc::fprintf, &FPrintF);
>   addOpt(LibFunc::fwrite, &FWrite);
> +  addOpt(LibFunc::fputs, &FPuts);
> }
> 
> Value *LibCallSimplifierImpl::optimizeCall(CallInst *CI) {
> 
> Modified: llvm/trunk/test/Transforms/InstCombine/fprintf-1.ll
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/InstCombine/fprintf-1.ll?rev=168893&r1=168892&r2=168893&view=diff
> ==============================================================================
> --- llvm/trunk/test/Transforms/InstCombine/fprintf-1.ll (original)
> +++ llvm/trunk/test/Transforms/InstCombine/fprintf-1.ll Thu Nov 29 09:45:43 2012
> @@ -38,13 +38,14 @@
> }
> 
> ; Check fprintf(fp, "%s", str) -> fputs(str, fp).
> +; NOTE: The fputs simplifier simplifies this further to fwrite.
> 
> define void @test_simplify3(%FILE* %fp) {
> ; CHECK: @test_simplify3
>   %fmt = getelementptr [3 x i8]* @percent_s, i32 0, i32 0
>   %str = getelementptr [13 x i8]* @hello_world, i32 0, i32 0
>   call i32 (%FILE*, i8*, ...)* @fprintf(%FILE* %fp, i8* %fmt, i8* %str)
> -; CHECK-NEXT: call i32 @fputs(i8* getelementptr inbounds ([13 x i8]* @hello_world, i32 0, i32 0), %FILE* %fp)
> +; CHECK-NEXT: call i32 @fwrite(i8* getelementptr inbounds ([13 x i8]* @hello_world, i32 0, i32 0), i32 12, i32 1, %FILE* %fp)
>   ret void
> ; CHECK-NEXT: ret void
> }
> 
> Added: llvm/trunk/test/Transforms/InstCombine/fputs-1.ll
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/InstCombine/fputs-1.ll?rev=168893&view=auto
> ==============================================================================
> --- llvm/trunk/test/Transforms/InstCombine/fputs-1.ll (added)
> +++ llvm/trunk/test/Transforms/InstCombine/fputs-1.ll Thu Nov 29 09:45:43 2012
> @@ -0,0 +1,43 @@
> +; Test that the fputs library call simplifier works correctly.
> +;
> +; RUN: opt < %s -instcombine -S | FileCheck %s
> +
> +target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:128:128"
> +
> +%FILE = type { }
> +
> + at empty = constant [1 x i8] zeroinitializer
> + at A = constant [2 x i8] c"A\00"
> + at hello = constant [7 x i8] c"hello\0A\00"
> +
> +declare i32 @fputs(i8*, %FILE*)
> +
> +; Check fputs(str, fp) --> fwrite(str, 1, strlen(s), fp).
> +
> +define void @test_simplify1(%FILE* %fp) {
> +; CHECK: @test_simplify1
> +  %str = getelementptr [1 x i8]* @empty, i32 0, i32 0
> +  call i32 @fputs(i8* %str, %FILE* %fp)
> +  ret void
> +; CHECK-NEXT: ret void
> +}
> +
> +; NOTE: The fwrite simplifier simplifies this further to fputc.
> +
> +define void @test_simplify2(%FILE* %fp) {
> +; CHECK: @test_simplify2
> +  %str = getelementptr [2 x i8]* @A, i32 0, i32 0
> +  call i32 @fputs(i8* %str, %FILE* %fp)
> +; CHECK-NEXT: call i32 @fputc(i32 65, %FILE* %fp)
> +  ret void
> +; CHECK-NEXT: ret void
> +}
> +
> +define void @test_simplify3(%FILE* %fp) {
> +; CHECK: @test_simplify3
> +  %str = getelementptr [7 x i8]* @hello, i32 0, i32 0
> +  call i32 @fputs(i8* %str, %FILE* %fp)
> +; CHECK-NEXT: call i32 @fwrite(i8* getelementptr inbounds ([7 x i8]* @hello, i32 0, i32 0), i32 6, i32 1, %FILE* %fp)
> +  ret void
> +; CHECK-NEXT: ret void
> +}
> 
> Removed: llvm/trunk/test/Transforms/SimplifyLibCalls/FPuts.ll
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/SimplifyLibCalls/FPuts.ll?rev=168892&view=auto
> ==============================================================================
> --- llvm/trunk/test/Transforms/SimplifyLibCalls/FPuts.ll (original)
> +++ llvm/trunk/test/Transforms/SimplifyLibCalls/FPuts.ll (removed)
> @@ -1,30 +0,0 @@
> -; Test that the FPutsOptimizer works correctly
> -; RUN: opt < %s -simplify-libcalls -S | FileCheck %s
> -
> -; This transformation requires the pointer size, as it assumes that size_t is
> -; the size of a pointer.
> -target datalayout = "p:64:64:64"
> -
> -	%struct._IO_FILE = type { i32, i8*, i8*, i8*, i8*, i8*, i8*, i8*, i8*, i8*, i8*, i8*, %struct._IO_marker*, %struct._IO_FILE*, i32, i32, i32, i16, i8, [1 x i8], i8*, i64, i8*, i8*, i32, [52 x i8] }
> -	%struct._IO_marker = type { %struct._IO_marker*, %struct._IO_FILE*, i32 }
> - at stdout = external global %struct._IO_FILE*		; <%struct._IO_FILE**> [#uses=1]
> - at empty = constant [1 x i8] zeroinitializer		; <[1 x i8]*> [#uses=1]
> - at len1 = constant [2 x i8] c"A\00"		; <[2 x i8]*> [#uses=1]
> - at long = constant [7 x i8] c"hello\0A\00"		; <[7 x i8]*> [#uses=1]
> -
> -declare i32 @fputs(i8*, %struct._IO_FILE*)
> -
> -define i32 @main() {
> -; CHECK: define i32 @main() {
> -entry:
> -	%out = load %struct._IO_FILE** @stdout		; <%struct._IO_FILE*> [#uses=3]
> -	%s1 = getelementptr [1 x i8]* @empty, i32 0, i32 0		; <i8*> [#uses=1]
> -	%s2 = getelementptr [2 x i8]* @len1, i32 0, i32 0		; <i8*> [#uses=1]
> -	%s3 = getelementptr [7 x i8]* @long, i32 0, i32 0		; <i8*> [#uses=1]
> -	%a = call i32 @fputs( i8* %s1, %struct._IO_FILE* %out )		; <i32> [#uses=0]
> -	%b = call i32 @fputs( i8* %s2, %struct._IO_FILE* %out )		; <i32> [#uses=0]
> -	%c = call i32 @fputs( i8* %s3, %struct._IO_FILE* %out )		; <i32> [#uses=0]
> -	ret i32 0
> -
> -; CHECK-NOT: @fputs(
> -}
> 
> 
> _______________________________________________
> llvm-commits mailing list
> llvm-commits at cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20130305/a65c5db4/attachment.html>


More information about the llvm-commits mailing list