diff --git a/bolt/include/bolt/Profile/ProfileYAMLMapping.h b/bolt/include/bolt/Profile/ProfileYAMLMapping.h --- a/bolt/include/bolt/Profile/ProfileYAMLMapping.h +++ b/bolt/include/bolt/Profile/ProfileYAMLMapping.h @@ -24,6 +24,8 @@ namespace yaml { namespace bolt { +enum BlocksOrderType : uint8_t { ORDER_DFS = 0, ORDER_BINARY = 1 }; + struct CallSiteInfo { llvm::yaml::Hex32 Offset{0}; uint32_t DestId{0}; @@ -178,6 +180,13 @@ } }; +template <> struct ScalarEnumerationTraits { + static void enumeration(IO &io, bolt::BlocksOrderType &value) { + io.enumCase(value, "dfs", bolt::BlocksOrderType::ORDER_DFS); + io.enumCase(value, "binary", bolt::BlocksOrderType::ORDER_BINARY); + } +}; + namespace bolt { struct BinaryProfileHeader { uint32_t Version{1}; @@ -187,6 +196,8 @@ // Type of the profile. std::string Origin; // How the profile was obtained. std::string EventNames; // Events used for sample profile. + BlocksOrderType BlocksOrder{ + BlocksOrderType::ORDER_DFS}; // The order of blocks in function profile. }; } // end namespace bolt @@ -198,6 +209,7 @@ YamlIO.mapRequired("profile-flags", Header.Flags); YamlIO.mapOptional("profile-origin", Header.Origin); YamlIO.mapOptional("profile-events", Header.EventNames); + YamlIO.mapOptional("blocks-order", Header.BlocksOrder); } }; diff --git a/bolt/include/bolt/Profile/YAMLProfileReader.h b/bolt/include/bolt/Profile/YAMLProfileReader.h --- a/bolt/include/bolt/Profile/YAMLProfileReader.h +++ b/bolt/include/bolt/Profile/YAMLProfileReader.h @@ -45,6 +45,9 @@ bool NormalizeByInsnCount{false}; bool NormalizeByCalls{false}; + /// Whether the profile uses DFS blocks order. + bool IsDFSOrder{true}; + /// Binary profile in YAML format. yaml::bolt::BinaryProfile YamlBP; diff --git a/bolt/lib/Profile/YAMLProfileReader.cpp b/bolt/lib/Profile/YAMLProfileReader.cpp --- a/bolt/lib/Profile/YAMLProfileReader.cpp +++ b/bolt/lib/Profile/YAMLProfileReader.cpp @@ -94,7 +94,7 @@ FuncRawBranchCount += YamlSI.Count; BF.setRawBranchCount(FuncRawBranchCount); - if (!opts::IgnoreHash && YamlBF.Hash != BF.computeHash(opts::ProfileUseDFS)) { + if (!opts::IgnoreHash && YamlBF.Hash != BF.computeHash(IsDFSOrder)) { if (opts::Verbosity >= 1) errs() << "BOLT-WARNING: function hash mismatch\n"; ProfileMatched = false; @@ -107,7 +107,7 @@ } BinaryFunction::BasicBlockOrderType Order; - if (opts::ProfileUseDFS) + if (IsDFSOrder) llvm::copy(BF.dfs(), std::back_inserter(Order)); else llvm::copy(BF.getLayout().blocks(), std::back_inserter(Order)); @@ -289,6 +289,9 @@ Twine("multiple events in profile are not supported"), inconvertibleErrorCode()); + IsDFSOrder = + YamlBP.Header.BlocksOrder == yaml::bolt::BlocksOrderType::ORDER_DFS; + // Match profile to function based on a function name. buildNameMaps(BC.getBinaryFunctions()); @@ -346,7 +349,7 @@ // Recompute hash once per function. if (!opts::IgnoreHash) - Function.computeHash(opts::ProfileUseDFS); + Function.computeHash(IsDFSOrder); for (StringRef FunctionName : Function.getNames()) { auto PI = ProfileNameToProfile.find(FunctionName); diff --git a/bolt/lib/Profile/YAMLProfileWriter.cpp b/bolt/lib/Profile/YAMLProfileWriter.cpp --- a/bolt/lib/Profile/YAMLProfileWriter.cpp +++ b/bolt/lib/Profile/YAMLProfileWriter.cpp @@ -169,6 +169,7 @@ } // end anonymous namespace std::error_code YAMLProfileWriter::writeProfile(const RewriteInstance &RI) { + using BlocksOrder = yaml::bolt::BlocksOrderType; const BinaryContext &BC = RI.getBinaryContext(); const auto &Functions = BC.getBinaryFunctions(); @@ -188,6 +189,8 @@ std::optional BuildID = BC.getFileBuildID(); BP.Header.Id = BuildID ? std::string(*BuildID) : ""; BP.Header.Origin = std::string(RI.getProfileReader()->getReaderName()); + BP.Header.BlocksOrder = + opts::ProfileUseDFS ? BlocksOrder::ORDER_DFS : BlocksOrder::ORDER_BINARY; StringSet<> EventNames = RI.getProfileReader()->getEventNames(); if (!EventNames.empty()) { diff --git a/bolt/test/yaml-profile-kind.s b/bolt/test/yaml-profile-kind.s new file mode 100644 --- /dev/null +++ b/bolt/test/yaml-profile-kind.s @@ -0,0 +1,18 @@ +# This test checks the handling of YAML profile with different block orders. +# RUN: %clang %cflags -Wl,-q %s -o %t.exe +# RUN: link_fdata %s %t.exe %t.fdata +# RUN: llvm-bolt %t.exe -o /dev/null -data %t.fdata -w %t.yaml +# RUN: FileCheck %s --input-file %t.yaml --check-prefix=CHECK-BINARY +# CHECK-BINARY: blocks-order: binary +# RUN: llvm-bolt %t.exe -o /dev/null -data %t.fdata -w %t.yaml --profile-use-dfs +# RUN: FileCheck %s --input-file %t.yaml --check-prefix=CHECK-DFS +# CHECK-DFS: blocks-order: dfs + + .globl main + .type main, %function +main: +# FDATA: 0 [unknown] 0 1 main 0 0 0 + .cfi_startproc + .long 0 + .cfi_endproc +.size main, .-main