Index: lib/CodeGen/CGCall.cpp =================================================================== --- lib/CodeGen/CGCall.cpp +++ lib/CodeGen/CGCall.cpp @@ -3464,6 +3464,27 @@ Attrs.addAttribute(getLLVMContext(), llvm::AttributeSet::FunctionIndex, llvm::Attribute::NoInline); + // As of now, IsColdRegion is true only while handling throw statements. + // It might be reasonable to avoid inlining CallSites invoked in exception + // handling context so that we can reduce code size blow-up in EH regions + // as well as indirectly increase inline opportunities for unwinding + // functions containing exception handling code. + if (IsColdRegion) { + // FIXME: We add both NoInline and Cold because the inline cold-threshold + // is not tuned yet (r200898). As of now, considering that CallSites in + // exception handling regions are very cold is not unreasonable even without + // profiling, and avoiding inlining in exception handling region may not + // have significant impacts on performance unless a program execution logic + // really depends on exception handling flows. However, when the inline + // cold-threshold is tuned, we may need to remove NoInline here so that we + // can allow a trivial constructor to be inlined. + Attrs = + Attrs.addAttribute(getLLVMContext(), llvm::AttributeSet::FunctionIndex, + llvm::Attribute::NoInline); + Attrs = + Attrs.addAttribute(getLLVMContext(), llvm::AttributeSet::FunctionIndex, + llvm::Attribute::Cold); + } CS.setAttributes(Attrs); CS.setCallingConv(static_cast(CallingConv)); Index: lib/CodeGen/CGException.cpp =================================================================== --- lib/CodeGen/CGException.cpp +++ lib/CodeGen/CGException.cpp @@ -400,6 +400,11 @@ void CodeGenFunction::EmitCXXThrowExpr(const CXXThrowExpr *E, bool KeepInsertionPoint) { + // While handling the throw statement, inform that the insertion point is in + // cold regions so that we could perform cold region specific IR generation. + // For example, the NoInline attribute could be added in CallSites in throw + // statements. + IsColdRegion = true; if (const Expr *SubExpr = E->getSubExpr()) { QualType ThrowType = SubExpr->getType(); if (ThrowType->isObjCObjectPointerType()) { @@ -417,6 +422,10 @@ // to leave ourselves at a valid insertion point. if (KeepInsertionPoint) EmitBlock(createBasicBlock("throw.cont")); + + IsColdRegion = false; + // FIXME: Similarly, we could set IsColdRegion for catch blocks in + // ExitCXXTryStmt(). } void CodeGenFunction::EmitStartEHSpec(const Decl *D) { Index: lib/CodeGen/CodeGenFunction.h =================================================================== --- lib/CodeGen/CodeGenFunction.h +++ lib/CodeGen/CodeGenFunction.h @@ -283,6 +283,11 @@ /// finally block or filter expression. bool IsOutlinedSEHHelper; + // True if the current insertion point is in cold regions (e.g., exception + // handling regions). As of now, this flag is true only when handling throw + // statements. + bool IsColdRegion; + const CodeGen::CGBlockInfo *BlockInfo; llvm::Value *BlockPointer; Index: lib/CodeGen/CodeGenFunction.cpp =================================================================== --- lib/CodeGen/CodeGenFunction.cpp +++ lib/CodeGen/CodeGenFunction.cpp @@ -44,7 +44,7 @@ CapturedStmtInfo(nullptr), SanOpts(CGM.getLangOpts().Sanitize), IsSanitizerScope(false), CurFuncIsThunk(false), AutoreleaseResult(false), SawAsmBlock(false), - IsOutlinedSEHHelper(false), + IsOutlinedSEHHelper(false), IsColdRegion(false), BlockInfo(nullptr), BlockPointer(nullptr), LambdaThisCaptureField(nullptr), NormalCleanupDest(nullptr), NextCleanupDestIndex(1), FirstBlockInfo(nullptr), EHResumeBlock(nullptr), Index: test/CodeGenCXX/throw-expressions.cpp =================================================================== --- test/CodeGenCXX/throw-expressions.cpp +++ test/CodeGenCXX/throw-expressions.cpp @@ -112,3 +112,14 @@ // CHECK: ret i32* @val return cond ? val : ((throw "foo")); } + +// CHECK-LABEL: _Z5test9v +// CHECK: invoke void @_ZN2EHC1Ev(%class.EH* %0) [[ATTR_NUM:#[0-9]+]] +// CHECK: attributes [[ATTR_NUM]] = { cold noinline } +class EH { +public : + EH(); +}; +void test9() { + throw EH(); +}