Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 8 additions & 5 deletions llvm/docs/LangRef.rst
Original file line number Diff line number Diff line change
Expand Up @@ -333,11 +333,14 @@ added in the future:
(e.g., by passing things in registers). This calling convention
allows the target to use whatever tricks it wants to produce fast
code for the target, without having to conform to an externally
specified ABI (Application Binary Interface). `Tail calls can only
be optimized when this, the tailcc, the GHC or the HiPE convention is
used. <CodeGenerator.html#tail-call-optimization>`_ This calling
convention does not support varargs and requires the prototype of all
callees to exactly match the prototype of the function definition.
specified ABI (Application Binary Interface). Targets may use different
implementations according to different features. In this case, a
TTI interface ``useFastCCForInternalCall`` must return false when
any caller functions and the callee belong to different implementations.
`Tail calls can only be optimized when this, the tailcc, the GHC or the
HiPE convention is used. <CodeGenerator.html#tail-call-optimization>`_
This calling convention does not support varargs and requires the prototype
of all callees to exactly match the prototype of the function definition.
"``coldcc``" - The cold calling convention
This calling convention attempts to make code in the caller as
efficient as possible under the assumption that the call is not
Expand Down
4 changes: 4 additions & 0 deletions llvm/include/llvm/Analysis/TargetTransformInfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -946,6 +946,10 @@ class TargetTransformInfo {
/// should use coldcc calling convention.
LLVM_ABI bool useColdCCForColdCall(Function &F) const;

/// Return true if the input function is internal, should use fastcc calling
/// convention.
LLVM_ABI bool useFastCCForInternalCall(Function &F) const;

LLVM_ABI bool isTargetIntrinsicTriviallyScalarizable(Intrinsic::ID ID) const;

/// Identifies if the vector form of the intrinsic has a scalar operand.
Expand Down
2 changes: 2 additions & 0 deletions llvm/include/llvm/Analysis/TargetTransformInfoImpl.h
Original file line number Diff line number Diff line change
Expand Up @@ -431,6 +431,8 @@ class TargetTransformInfoImplBase {

virtual bool useColdCCForColdCall(Function &F) const { return false; }

virtual bool useFastCCForInternalCall(Function &F) const { return true; }

virtual bool isTargetIntrinsicTriviallyScalarizable(Intrinsic::ID ID) const {
return false;
}
Expand Down
4 changes: 4 additions & 0 deletions llvm/lib/Analysis/TargetTransformInfo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -609,6 +609,10 @@ bool TargetTransformInfo::useColdCCForColdCall(Function &F) const {
return TTIImpl->useColdCCForColdCall(F);
}

bool TargetTransformInfo::useFastCCForInternalCall(Function &F) const {
return TTIImpl->useFastCCForInternalCall(F);
}

bool TargetTransformInfo::isTargetIntrinsicTriviallyScalarizable(
Intrinsic::ID ID) const {
return TTIImpl->isTargetIntrinsicTriviallyScalarizable(ID);
Expand Down
16 changes: 16 additions & 0 deletions llvm/lib/Target/X86/X86TargetTransformInfo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7223,3 +7223,19 @@ bool X86TTIImpl::isProfitableToSinkOperands(Instruction *I,

return false;
}

bool X86TTIImpl::useFastCCForInternalCall(Function &F) const {
bool HasEGPR = ST->hasEGPR();
const TargetMachine &TM = getTLI()->getTargetMachine();

for (User *U : F.users()) {
CallBase *CB = dyn_cast<CallBase>(U);
if (!CB || CB->getCalledOperand() != &F)
continue;
Function *CallerFunc = CB->getFunction();
if (TM.getSubtarget<X86Subtarget>(*CallerFunc).hasEGPR() != HasEGPR)
return false;
}

return true;
}
2 changes: 2 additions & 0 deletions llvm/lib/Target/X86/X86TargetTransformInfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -319,6 +319,8 @@ class X86TTIImpl final : public BasicTTIImplBase<X86TTIImpl> {
unsigned getStoreMinimumVF(unsigned VF, Type *ScalarMemTy,
Type *ScalarValTy) const override;

bool useFastCCForInternalCall(Function &F) const override;

private:
bool supportsGather() const;
InstructionCost getGSVectorCost(unsigned Opcode, TTI::TargetCostKind CostKind,
Expand Down
15 changes: 9 additions & 6 deletions llvm/lib/Transforms/IPO/GlobalOpt.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2018,12 +2018,15 @@ OptimizeFunctions(Module &M,

if (hasChangeableCC(&F, ChangeableCCCache)) {
// 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;
Changed = true;
// varargs function, is only called directly, and is supported by the
// target, promote it to use the Fast calling convention.
TargetTransformInfo &TTI = GetTTI(F);
if (TTI.useFastCCForInternalCall(F)) {
F.setCallingConv(CallingConv::Fast);
ChangeCalleesToFastCall(&F);
++NumFastCallFns;
Changed = true;
}
}

if (F.getAttributes().hasAttrSomewhere(Attribute::Nest) &&
Expand Down
54 changes: 54 additions & 0 deletions llvm/test/Transforms/GlobalOpt/X86/apx.ll
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6
; RUN: opt -mtriple=x86_64 -S -passes=globalopt -o - < %s | FileCheck %s

define void @caller1() {
; CHECK-LABEL: define void @caller1() local_unnamed_addr {
; CHECK-NEXT: call void @callee1()
; CHECK-NEXT: ret void
;
call void @callee1()
ret void
}

define internal void @callee1() "target-features"="+egpr" {
; CHECK-LABEL: define internal void @callee1(
; CHECK-SAME: ) unnamed_addr #[[ATTR0:[0-9]+]] {
; CHECK-NEXT: ret void
;
ret void
}

define void @caller2() "target-features"="+egpr" {
; CHECK-LABEL: define void @caller2(
; CHECK-SAME: ) local_unnamed_addr #[[ATTR0]] {
; CHECK-NEXT: call void @callee2()
; CHECK-NEXT: ret void
;
call void @callee2()
ret void
}

define internal void @callee2() {
; CHECK-LABEL: define internal void @callee2() unnamed_addr {
; CHECK-NEXT: ret void
;
ret void
}

define void @caller3() "target-features"="+egpr" {
; CHECK-LABEL: define void @caller3(
; CHECK-SAME: ) local_unnamed_addr #[[ATTR0]] {
; CHECK-NEXT: call fastcc void @callee3()
; CHECK-NEXT: ret void
;
call void @callee3()
ret void
}

define internal void @callee3() "target-features"="+egpr" {
; CHECK-LABEL: define internal fastcc void @callee3(
; CHECK-SAME: ) unnamed_addr #[[ATTR0]] {
; CHECK-NEXT: ret void
;
ret void
}