From 726bae9a6616a8395a79f4346c17aaab6886eb1a Mon Sep 17 00:00:00 2001 From: Reid Kleckner Date: Wed, 26 Feb 2014 19:57:30 +0000 Subject: [PATCH] GlobalOpt: Apply fastcc to internal x86_thiscallcc functions We should apply fastcc whenever profitable. We can expand this list, but there are lots of conventions with performance implications that we don't want to change. Differential Revision: http://llvm-reviews.chandlerc.com/D2705 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@202293 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Transforms/IPO/GlobalOpt.cpp | 19 ++++++++---- test/Transforms/GlobalOpt/fastcc.ll | 46 +++++++++++++++++++++++++++++ 2 files changed, 60 insertions(+), 5 deletions(-) create mode 100644 test/Transforms/GlobalOpt/fastcc.ll diff --git a/lib/Transforms/IPO/GlobalOpt.cpp b/lib/Transforms/IPO/GlobalOpt.cpp index 1935a7225ac..7b9015b2d7d 100644 --- a/lib/Transforms/IPO/GlobalOpt.cpp +++ b/lib/Transforms/IPO/GlobalOpt.cpp @@ -1902,6 +1902,16 @@ static void RemoveNestAttribute(Function *F) { } } +/// Return true if this is a calling convention that we'd like to change. The +/// idea here is that we don't want to mess with the convention if the user +/// explicitly requested something with performance implications like coldcc, +/// GHC, or anyregcc. +static bool isProfitableToMakeFastCC(Function *F) { + CallingConv::ID CC = F->getCallingConv(); + // FIXME: Is it worth transforming x86_stdcallcc and x86_fastcallcc? + return CC == CallingConv::C || CC == CallingConv::X86_ThisCall; +} + bool GlobalOpt::OptimizeFunctions(Module &M) { bool Changed = false; // Optimize functions. @@ -1916,11 +1926,10 @@ bool GlobalOpt::OptimizeFunctions(Module &M) { Changed = true; ++NumFnDeleted; } else if (F->hasLocalLinkage()) { - if (F->getCallingConv() == CallingConv::C && !F->isVarArg() && - !F->hasAddressTaken()) { - // If this function has C calling conventions, is not a varargs - // function, and is only called directly, promote it to use the Fast - // calling convention. + if (isProfitableToMakeFastCC(F) && !F->isVarArg() && !F->hasAddressTaken()) { + // If this function has a calling convention worth changing, is not a + // varargs function, and is only called directly, promote it to use the + // Fast calling convention. F->setCallingConv(CallingConv::Fast); ChangeCalleesToFastCall(F); ++NumFastCallFns; diff --git a/test/Transforms/GlobalOpt/fastcc.ll b/test/Transforms/GlobalOpt/fastcc.ll new file mode 100644 index 00000000000..76122b203d7 --- /dev/null +++ b/test/Transforms/GlobalOpt/fastcc.ll @@ -0,0 +1,46 @@ +; RUN: opt < %s -globalopt -S | FileCheck %s + +define internal i32 @f(i32* %m) { +; CHECK-LABEL: define internal fastcc i32 @f + %v = load i32* %m + ret i32 %v +} + +define internal x86_thiscallcc i32 @g(i32* %m) { +; CHECK-LABEL: define internal fastcc i32 @g + %v = load i32* %m + ret i32 %v +} + +; Leave this one alone, because the user went out of their way to request this +; convention. +define internal coldcc i32 @h(i32* %m) { +; CHECK-LABEL: define internal coldcc i32 @h + %v = load i32* %m + ret i32 %v +} + +define internal i32 @j(i32* %m) { +; CHECK-LABEL: define internal i32 @j + %v = load i32* %m + ret i32 %v +} + +define void @call_things() { + %m = alloca i32 + call i32 @f(i32* %m) + call x86_thiscallcc i32 @g(i32* %m) + call coldcc i32 @h(i32* %m) + call i32 @j(i32* %m) + ret void +} + +@llvm.used = appending global [1 x i8*] [ + i8* bitcast (i32(i32*)* @j to i8*) +], section "llvm.metadata" + +; CHECK-LABEL: define void @call_things() +; CHECK: call fastcc i32 @f +; CHECK: call fastcc i32 @g +; CHECK: call coldcc i32 @h +; CHECK: call i32 @j