Index: llvm/lib/Transforms/IPO/FunctionSpecialization.cpp =================================================================== --- llvm/lib/Transforms/IPO/FunctionSpecialization.cpp +++ llvm/lib/Transforms/IPO/FunctionSpecialization.cpp @@ -659,6 +659,8 @@ if (!isa(U) && !isa(U)) continue; auto &CS = *cast(U); + if (CS.hasFnAttr(Attribute::MinSize)) + continue; // If the parent of the call site will never be executed, we don't need // to worry about the passed value. @@ -688,6 +690,9 @@ /// This function modifies calls to function \p F whose argument at index \p /// ArgNo is equal to constant \p C. The calls are rewritten to call function /// \p Clone instead. + /// + /// Callsites that have been marked with the MinSize function attribute won't + /// be specialized and rewritten. void rewriteCallSites(Function *F, Function *Clone, Argument &Arg, Constant *C) { unsigned ArgNo = Arg.getArgNo(); Index: llvm/test/Transforms/FunctionSpecialization/function-specialization-minsize2.ll =================================================================== --- /dev/null +++ llvm/test/Transforms/FunctionSpecialization/function-specialization-minsize2.ll @@ -0,0 +1,44 @@ +; RUN: opt -function-specialization -func-specialization-size-threshold=3 -S < %s | FileCheck %s + +; Checks for callsites that have been annotated with MinSize. No specialisation +; expected here: +; +; CHECK-NOT: @compute.1 +; CHECK-NOT: @compute.2 + +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) #0 + br label %merge + +minus: + %tmp1 = call i64 @compute(i64 %x, i64 (i64)* @minus) #0 + 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 +} + +attributes #0 = { minsize optsize } Index: llvm/test/Transforms/FunctionSpecialization/function-specialization-minsize3.ll =================================================================== --- /dev/null +++ llvm/test/Transforms/FunctionSpecialization/function-specialization-minsize3.ll @@ -0,0 +1,48 @@ +; RUN: opt -function-specialization -func-specialization-size-threshold=3 -S < %s | FileCheck %s + +; Checks for callsites that have been annotated with MinSize. We only expect +; specialisation for the call that does not have the attribute: +; +; CHECK: plus: +; CHECK: %tmp0 = call i64 @compute.1(i64 %x, i64 (i64)* @plus) +; CHECK: br label %merge +; CHECK: minus: +; CHECK: %tmp1 = call i64 @compute(i64 %x, i64 (i64)* @minus) #0 +; CHECK: br label %merge +; +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) #0 + 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 +} + +attributes #0 = { minsize optsize }