diff --git a/llvm/lib/Transforms/IPO/FunctionSpecialization.cpp b/llvm/lib/Transforms/IPO/FunctionSpecialization.cpp --- a/llvm/lib/Transforms/IPO/FunctionSpecialization.cpp +++ b/llvm/lib/Transforms/IPO/FunctionSpecialization.cpp @@ -41,7 +41,7 @@ #define DEBUG_TYPE "function-specialization" -STATISTIC(NumFuncSpecialized, "Number of Functions Specialized"); +STATISTIC(NumFuncSpecialized, "Number of functions specialized"); static cl::opt ForceFunctionSpecialization( "force-function-specialization", cl::init(false), cl::Hidden, @@ -121,6 +121,8 @@ LLVM_DEBUG(dbgs() << "FnSpecialization: Replaced constant argument: " << Arg.getName() << "\n"); } + + NumFuncSpecialized += NbFunctionsSpecialized; return Changed; } @@ -142,6 +144,10 @@ } private: + // The number of functions specialised, used for collecting statistics and + // also in the cost model. + unsigned NbFunctionsSpecialized = 0; + /// This function decides whether to specialize function \p F based on the /// known constant values its arguments can take on. Specialization is /// performed on the first interesting argument. Specializations based on @@ -218,7 +224,7 @@ // Mark all the specialized functions Specializations.push_back(Clone); - NumFuncSpecialized++; + NbFunctionsSpecialized++; } // TODO: if we want to support specialize specialized functions, and if @@ -248,7 +254,7 @@ // Otherwise, set the specialization cost to be the cost of all the // instructions in the function and penalty for specializing more functions. - unsigned Penalty = NumFuncSpecialized + 1; + unsigned Penalty = NbFunctionsSpecialized + 1; return Metrics.NumInsts * InlineConstants::InstrCost * Penalty; } @@ -632,6 +638,5 @@ // Clean up the IR by removing ssa_copy intrinsics. cleanup(M); - return Changed; } diff --git a/llvm/test/Transforms/FunctionSpecialization/function-specialization-stats.ll b/llvm/test/Transforms/FunctionSpecialization/function-specialization-stats.ll new file mode 100644 --- /dev/null +++ b/llvm/test/Transforms/FunctionSpecialization/function-specialization-stats.ll @@ -0,0 +1,45 @@ +; REQUIRES: asserts + +; RUN: opt -stats -function-specialization -deadargelim -inline -S < %s 2>&1 | FileCheck %s + +; CHECK: 2 deadargelim - Number of unread args removed +; CHECK: 1 deadargelim - Number of unused return values removed +; CHECK: 2 function-specialization - Number of functions specialized +; CHECK: 4 inline - Number of functions deleted because all callers found +; CHECK: 4 inline - Number of functions inlined +; CHECK: 6 inline-cost - Number of call sites analyzed + +define i64 @main(i64 %x, i1 %flag) { +entry: + br i1 %flag, label %plus, label %minus + +plus: + %tmp0 = call i64 @compute(i64 %x, i64 (i64)* @plus) + br label %merge + +minus: + %tmp1 = call i64 @compute(i64 %x, i64 (i64)* @minus) + br label %merge + +merge: + %tmp2 = phi i64 [ %tmp0, %plus ], [ %tmp1, %minus] + ret i64 %tmp2 +} + +define internal i64 @compute(i64 %x, i64 (i64)* %binop) { +entry: + %tmp0 = call i64 %binop(i64 %x) + ret i64 %tmp0 +} + +define internal i64 @plus(i64 %x) { +entry: + %tmp0 = add i64 %x, 1 + ret i64 %tmp0 +} + +define internal i64 @minus(i64 %x) { +entry: + %tmp0 = sub i64 %x, 1 + ret i64 %tmp0 +}