}
}
+/// 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.
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;
--- /dev/null
+; 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