Index: include/clang/Driver/Options.td =================================================================== --- include/clang/Driver/Options.td +++ include/clang/Driver/Options.td @@ -1332,6 +1332,12 @@ def frandom_seed_EQ : Joined<["-"], "frandom-seed=">, Group; def freg_struct_return : Flag<["-"], "freg-struct-return">, Group, Flags<[CC1Option]>, HelpText<"Override the default ABI to return small structs in registers">; +def freorder_functions : Flag <["-"], "freorder-functions">, + Group, Flags<[CC1Option]>, + HelpText<"Using special subsections for hot/cold functions to improve code " + "locality">; +def fno_reorder_functions : Flag <["-"], "fno-reorder-functions">, + Group, Flags<[CC1Option]>; def frtti : Flag<["-"], "frtti">, Group; def : Flag<["-"], "fsched-interblock">, Group; def fshort_enums : Flag<["-"], "fshort-enums">, Group, Flags<[CC1Option]>, Index: include/clang/Frontend/CodeGenOptions.def =================================================================== --- include/clang/Frontend/CodeGenOptions.def +++ include/clang/Frontend/CodeGenOptions.def @@ -174,6 +174,7 @@ CODEGENOPT(TimePasses , 1, 0) ///< Set when -ftime-report is enabled. CODEGENOPT(UnrollLoops , 1, 0) ///< Control whether loops are unrolled. CODEGENOPT(RerollLoops , 1, 0) ///< Control whether loops are rerolled. +CODEGENOPT(ReorderFunctions , 1, 1) ///< Set when -freorder-functions is enabled. CODEGENOPT(NoUseJumpTables , 1, 0) ///< Set when -fno-jump-tables is enabled. CODEGENOPT(UnsafeFPMath , 1, 0) ///< Allow unsafe floating point optzns. CODEGENOPT(UnwindTables , 1, 0) ///< Emit unwind tables. Index: lib/CodeGen/BackendUtil.cpp =================================================================== --- lib/CodeGen/BackendUtil.cpp +++ lib/CodeGen/BackendUtil.cpp @@ -431,6 +431,7 @@ Options.FunctionSections = CodeGenOpts.FunctionSections; Options.DataSections = CodeGenOpts.DataSections; Options.UniqueSectionNames = CodeGenOpts.UniqueSectionNames; + Options.ReorderFunctions = CodeGenOpts.ReorderFunctions; Options.EmulatedTLS = CodeGenOpts.EmulatedTLS; Options.DebuggerTuning = CodeGenOpts.getDebuggerTuning(); Index: lib/Driver/ToolChains/Clang.cpp =================================================================== --- lib/Driver/ToolChains/Clang.cpp +++ lib/Driver/ToolChains/Clang.cpp @@ -2861,6 +2861,10 @@ options::OPT_fno_unique_section_names, true)) CmdArgs.push_back("-fno-unique-section-names"); + if (!Args.hasFlag(options::OPT_freorder_functions, + options::OPT_fno_reorder_functions, true)) + CmdArgs.push_back("-fno-reorder-functions"); + Args.AddAllArgs(CmdArgs, options::OPT_finstrument_functions); addPGOAndCoverageFlags(C, D, Output, Args, CmdArgs); Index: lib/Frontend/CompilerInvocation.cpp =================================================================== --- lib/Frontend/CompilerInvocation.cpp +++ lib/Frontend/CompilerInvocation.cpp @@ -643,6 +643,8 @@ OPT_fno_data_sections, false); Opts.UniqueSectionNames = Args.hasFlag(OPT_funique_section_names, OPT_fno_unique_section_names, true); + Opts.ReorderFunctions = + Args.hasFlag(OPT_freorder_functions, OPT_fno_reorder_functions, true); Opts.MergeFunctions = Args.hasArg(OPT_fmerge_functions); Index: test/CodeGen/Inputs/freorder-functions.prof =================================================================== --- /dev/null +++ test/CodeGen/Inputs/freorder-functions.prof @@ -0,0 +1,5 @@ +hot_func:1000:0 + 1: 0 +cold_func:0:0 + 1: 1 + 2: 1 Index: test/CodeGen/freorder-functions.c =================================================================== --- /dev/null +++ test/CodeGen/freorder-functions.c @@ -0,0 +1,22 @@ +// REQUIRES: x86-registered-target + +// RUN: %clang_cc1 -triple x86_64-pc-linux -S -O3 -ffunction-sections -fprofile-sample-use=%S/Inputs/freorder-functions.prof -o - < %s | FileCheck %s +// RUN: %clang_cc1 -triple x86_64-pc-linux -S -O3 -ffunction-sections -fprofile-sample-use=%S/Inputs/freorder-functions.prof -fno-reorder-functions -o - < %s | FileCheck --check-prefix=CHECK-NOPREFIX %s + +// opt tool option precedes driver option. +// RUN: %clang_cc1 -triple x86_64-pc-linux -S -O3 -ffunction-sections -fprofile-sample-use=%S/Inputs/freorder-functions.prof -fno-reorder-functions -mllvm -profile-guided-section-prefix=true -o - < %s | FileCheck %s +// RUN: %clang_cc1 -triple x86_64-pc-linux -S -O3 -ffunction-sections -fprofile-sample-use=%S/Inputs/freorder-functions.prof -freorder-functions -mllvm -profile-guided-section-prefix=false -o - < %s | FileCheck --check-prefix=CHECK-NOPREFIX %s + +void hot_func() { + return; +} + +void cold_func() { + hot_func(); + return; +} + +// CHECK: .section .text.hot.hot_func,"ax",@progbits +// CHECK: .section .text.unlikely.cold_func,"ax",@progbits +// CHECK-NOPREFIX: .section .text.hot_func,"ax",@progbits +// CHECK-NOPREFIX: .section .text.cold_func,"ax",@progbits Index: test/Driver/function-sections.c =================================================================== --- test/Driver/function-sections.c +++ test/Driver/function-sections.c @@ -6,6 +6,8 @@ // CHECK-NODS-NOT: -fdata-sections // CHECK-US-NOT: -fno-unique-section-names // CHECK-NOUS: -fno-unique-section-names +// CHECK-RF-NOT: -fno-reorder-functions +// CHECK-NORF: -fno-reorder-functions // RUN: %clang -no-canonical-prefixes %s -### -fsyntax-only 2>&1 \ // RUN: -target i386-unknown-linux \ @@ -72,3 +74,13 @@ // RUN: -target i386-unknown-linux \ // RUN: -fno-unique-section-names \ // RUN: | FileCheck --check-prefix=CHECK-NOUS %s + +// RUN: %clang -no-canonical-prefixes %s -### -fsyntax-only 2>&1 \ +// RUN: -target i386-unknown-linux \ +// RUN: -freorder-functions \ +// RUN: | FileCheck --check-prefix=CHECK-RF %s + +// RUN: %clang -no-canonical-prefixes %s -### -fsyntax-only 2>&1 \ +// RUN: -target i386-unknown-linux \ +// RUN: -fno-reorder-functions \ +// RUN: | FileCheck --check-prefix=CHECK-NORF %s