ProfileSummary.cpp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267
  1. //=-- Profilesummary.cpp - Profile summary support --------------------------=//
  2. //
  3. // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
  4. // See https://llvm.org/LICENSE.txt for license information.
  5. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  6. //
  7. //===----------------------------------------------------------------------===//
  8. //
  9. // This file contains support for converting profile summary data from/to
  10. // metadata.
  11. //
  12. //===----------------------------------------------------------------------===//
  13. #include "llvm/IR/ProfileSummary.h"
  14. #include "llvm/IR/Constants.h"
  15. #include "llvm/IR/DerivedTypes.h"
  16. #include "llvm/IR/Metadata.h"
  17. #include "llvm/IR/Type.h"
  18. #include "llvm/Support/Casting.h"
  19. #include "llvm/Support/Format.h"
  20. using namespace llvm;
  21. // Return an MDTuple with two elements. The first element is a string Key and
  22. // the second is a uint64_t Value.
  23. static Metadata *getKeyValMD(LLVMContext &Context, const char *Key,
  24. uint64_t Val) {
  25. Type *Int64Ty = Type::getInt64Ty(Context);
  26. Metadata *Ops[2] = {MDString::get(Context, Key),
  27. ConstantAsMetadata::get(ConstantInt::get(Int64Ty, Val))};
  28. return MDTuple::get(Context, Ops);
  29. }
  30. static Metadata *getKeyFPValMD(LLVMContext &Context, const char *Key,
  31. double Val) {
  32. Type *DoubleTy = Type::getDoubleTy(Context);
  33. Metadata *Ops[2] = {MDString::get(Context, Key),
  34. ConstantAsMetadata::get(ConstantFP::get(DoubleTy, Val))};
  35. return MDTuple::get(Context, Ops);
  36. }
  37. // Return an MDTuple with two elements. The first element is a string Key and
  38. // the second is a string Value.
  39. static Metadata *getKeyValMD(LLVMContext &Context, const char *Key,
  40. const char *Val) {
  41. Metadata *Ops[2] = {MDString::get(Context, Key), MDString::get(Context, Val)};
  42. return MDTuple::get(Context, Ops);
  43. }
  44. // This returns an MDTuple representing the detiled summary. The tuple has two
  45. // elements: a string "DetailedSummary" and an MDTuple representing the value
  46. // of the detailed summary. Each element of this tuple is again an MDTuple whose
  47. // elements are the (Cutoff, MinCount, NumCounts) triplet of the
  48. // DetailedSummaryEntry.
  49. Metadata *ProfileSummary::getDetailedSummaryMD(LLVMContext &Context) {
  50. std::vector<Metadata *> Entries;
  51. Type *Int32Ty = Type::getInt32Ty(Context);
  52. Type *Int64Ty = Type::getInt64Ty(Context);
  53. for (auto &Entry : DetailedSummary) {
  54. Metadata *EntryMD[3] = {
  55. ConstantAsMetadata::get(ConstantInt::get(Int32Ty, Entry.Cutoff)),
  56. ConstantAsMetadata::get(ConstantInt::get(Int64Ty, Entry.MinCount)),
  57. ConstantAsMetadata::get(ConstantInt::get(Int32Ty, Entry.NumCounts))};
  58. Entries.push_back(MDTuple::get(Context, EntryMD));
  59. }
  60. Metadata *Ops[2] = {MDString::get(Context, "DetailedSummary"),
  61. MDTuple::get(Context, Entries)};
  62. return MDTuple::get(Context, Ops);
  63. }
  64. // This returns an MDTuple representing this ProfileSummary object. The first
  65. // entry of this tuple is another MDTuple of two elements: a string
  66. // "ProfileFormat" and a string representing the format ("InstrProf" or
  67. // "SampleProfile"). The rest of the elements of the outer MDTuple are specific
  68. // to the kind of profile summary as returned by getFormatSpecificMD.
  69. // IsPartialProfile is an optional field and \p AddPartialField will decide
  70. // whether to add a field for it.
  71. // PartialProfileRatio is an optional field and \p AddPartialProfileRatioField
  72. // will decide whether to add a field for it.
  73. Metadata *ProfileSummary::getMD(LLVMContext &Context, bool AddPartialField,
  74. bool AddPartialProfileRatioField) {
  75. const char *KindStr[3] = {"InstrProf", "CSInstrProf", "SampleProfile"};
  76. SmallVector<Metadata *, 16> Components;
  77. Components.push_back(getKeyValMD(Context, "ProfileFormat", KindStr[PSK]));
  78. Components.push_back(getKeyValMD(Context, "TotalCount", getTotalCount()));
  79. Components.push_back(getKeyValMD(Context, "MaxCount", getMaxCount()));
  80. Components.push_back(
  81. getKeyValMD(Context, "MaxInternalCount", getMaxInternalCount()));
  82. Components.push_back(
  83. getKeyValMD(Context, "MaxFunctionCount", getMaxFunctionCount()));
  84. Components.push_back(getKeyValMD(Context, "NumCounts", getNumCounts()));
  85. Components.push_back(getKeyValMD(Context, "NumFunctions", getNumFunctions()));
  86. if (AddPartialField)
  87. Components.push_back(
  88. getKeyValMD(Context, "IsPartialProfile", isPartialProfile()));
  89. if (AddPartialProfileRatioField)
  90. Components.push_back(getKeyFPValMD(Context, "PartialProfileRatio",
  91. getPartialProfileRatio()));
  92. Components.push_back(getDetailedSummaryMD(Context));
  93. return MDTuple::get(Context, Components);
  94. }
  95. // Get the value metadata for the input MD/Key.
  96. static ConstantAsMetadata *getValMD(MDTuple *MD, const char *Key) {
  97. if (!MD)
  98. return nullptr;
  99. if (MD->getNumOperands() != 2)
  100. return nullptr;
  101. MDString *KeyMD = dyn_cast<MDString>(MD->getOperand(0));
  102. ConstantAsMetadata *ValMD = dyn_cast<ConstantAsMetadata>(MD->getOperand(1));
  103. if (!KeyMD || !ValMD)
  104. return nullptr;
  105. if (!KeyMD->getString().equals(Key))
  106. return nullptr;
  107. return ValMD;
  108. }
  109. // Parse an MDTuple representing (Key, Val) pair.
  110. static bool getVal(MDTuple *MD, const char *Key, uint64_t &Val) {
  111. if (auto *ValMD = getValMD(MD, Key)) {
  112. Val = cast<ConstantInt>(ValMD->getValue())->getZExtValue();
  113. return true;
  114. }
  115. return false;
  116. }
  117. static bool getVal(MDTuple *MD, const char *Key, double &Val) {
  118. if (auto *ValMD = getValMD(MD, Key)) {
  119. Val = cast<ConstantFP>(ValMD->getValue())->getValueAPF().convertToDouble();
  120. return true;
  121. }
  122. return false;
  123. }
  124. // Check if an MDTuple represents a (Key, Val) pair.
  125. static bool isKeyValuePair(MDTuple *MD, const char *Key, const char *Val) {
  126. if (!MD || MD->getNumOperands() != 2)
  127. return false;
  128. MDString *KeyMD = dyn_cast<MDString>(MD->getOperand(0));
  129. MDString *ValMD = dyn_cast<MDString>(MD->getOperand(1));
  130. if (!KeyMD || !ValMD)
  131. return false;
  132. if (!KeyMD->getString().equals(Key) || !ValMD->getString().equals(Val))
  133. return false;
  134. return true;
  135. }
  136. // Parse an MDTuple representing detailed summary.
  137. static bool getSummaryFromMD(MDTuple *MD, SummaryEntryVector &Summary) {
  138. if (!MD || MD->getNumOperands() != 2)
  139. return false;
  140. MDString *KeyMD = dyn_cast<MDString>(MD->getOperand(0));
  141. if (!KeyMD || !KeyMD->getString().equals("DetailedSummary"))
  142. return false;
  143. MDTuple *EntriesMD = dyn_cast<MDTuple>(MD->getOperand(1));
  144. if (!EntriesMD)
  145. return false;
  146. for (auto &&MDOp : EntriesMD->operands()) {
  147. MDTuple *EntryMD = dyn_cast<MDTuple>(MDOp);
  148. if (!EntryMD || EntryMD->getNumOperands() != 3)
  149. return false;
  150. ConstantAsMetadata *Op0 =
  151. dyn_cast<ConstantAsMetadata>(EntryMD->getOperand(0));
  152. ConstantAsMetadata *Op1 =
  153. dyn_cast<ConstantAsMetadata>(EntryMD->getOperand(1));
  154. ConstantAsMetadata *Op2 =
  155. dyn_cast<ConstantAsMetadata>(EntryMD->getOperand(2));
  156. if (!Op0 || !Op1 || !Op2)
  157. return false;
  158. Summary.emplace_back(cast<ConstantInt>(Op0->getValue())->getZExtValue(),
  159. cast<ConstantInt>(Op1->getValue())->getZExtValue(),
  160. cast<ConstantInt>(Op2->getValue())->getZExtValue());
  161. }
  162. return true;
  163. }
  164. // Get the value of an optional field. Increment 'Idx' if it was present. Return
  165. // true if we can move onto the next field.
  166. template <typename ValueType>
  167. static bool getOptionalVal(MDTuple *Tuple, unsigned &Idx, const char *Key,
  168. ValueType &Value) {
  169. if (getVal(dyn_cast<MDTuple>(Tuple->getOperand(Idx)), Key, Value)) {
  170. Idx++;
  171. // Need to make sure when the key is present, we won't step over the bound
  172. // of Tuple operand array. Since (non-optional) DetailedSummary always comes
  173. // last, the next entry in the tuple operand array must exist.
  174. return Idx < Tuple->getNumOperands();
  175. }
  176. // It was absent, keep going.
  177. return true;
  178. }
  179. ProfileSummary *ProfileSummary::getFromMD(Metadata *MD) {
  180. MDTuple *Tuple = dyn_cast_or_null<MDTuple>(MD);
  181. if (!Tuple || Tuple->getNumOperands() < 8 || Tuple->getNumOperands() > 10)
  182. return nullptr;
  183. unsigned I = 0;
  184. auto &FormatMD = Tuple->getOperand(I++);
  185. ProfileSummary::Kind SummaryKind;
  186. if (isKeyValuePair(dyn_cast_or_null<MDTuple>(FormatMD), "ProfileFormat",
  187. "SampleProfile"))
  188. SummaryKind = PSK_Sample;
  189. else if (isKeyValuePair(dyn_cast_or_null<MDTuple>(FormatMD), "ProfileFormat",
  190. "InstrProf"))
  191. SummaryKind = PSK_Instr;
  192. else if (isKeyValuePair(dyn_cast_or_null<MDTuple>(FormatMD), "ProfileFormat",
  193. "CSInstrProf"))
  194. SummaryKind = PSK_CSInstr;
  195. else
  196. return nullptr;
  197. uint64_t NumCounts, TotalCount, NumFunctions, MaxFunctionCount, MaxCount,
  198. MaxInternalCount;
  199. if (!getVal(dyn_cast<MDTuple>(Tuple->getOperand(I++)), "TotalCount",
  200. TotalCount))
  201. return nullptr;
  202. if (!getVal(dyn_cast<MDTuple>(Tuple->getOperand(I++)), "MaxCount", MaxCount))
  203. return nullptr;
  204. if (!getVal(dyn_cast<MDTuple>(Tuple->getOperand(I++)), "MaxInternalCount",
  205. MaxInternalCount))
  206. return nullptr;
  207. if (!getVal(dyn_cast<MDTuple>(Tuple->getOperand(I++)), "MaxFunctionCount",
  208. MaxFunctionCount))
  209. return nullptr;
  210. if (!getVal(dyn_cast<MDTuple>(Tuple->getOperand(I++)), "NumCounts",
  211. NumCounts))
  212. return nullptr;
  213. if (!getVal(dyn_cast<MDTuple>(Tuple->getOperand(I++)), "NumFunctions",
  214. NumFunctions))
  215. return nullptr;
  216. // Optional fields. Need to initialize because the fields are optional.
  217. uint64_t IsPartialProfile = 0;
  218. if (!getOptionalVal(Tuple, I, "IsPartialProfile", IsPartialProfile))
  219. return nullptr;
  220. double PartialProfileRatio = 0;
  221. if (!getOptionalVal(Tuple, I, "PartialProfileRatio", PartialProfileRatio))
  222. return nullptr;
  223. SummaryEntryVector Summary;
  224. if (!getSummaryFromMD(dyn_cast<MDTuple>(Tuple->getOperand(I++)), Summary))
  225. return nullptr;
  226. return new ProfileSummary(SummaryKind, std::move(Summary), TotalCount,
  227. MaxCount, MaxInternalCount, MaxFunctionCount,
  228. NumCounts, NumFunctions, IsPartialProfile,
  229. PartialProfileRatio);
  230. }
  231. void ProfileSummary::printSummary(raw_ostream &OS) const {
  232. OS << "Total functions: " << NumFunctions << "\n";
  233. OS << "Maximum function count: " << MaxFunctionCount << "\n";
  234. OS << "Maximum block count: " << MaxCount << "\n";
  235. OS << "Total number of blocks: " << NumCounts << "\n";
  236. OS << "Total count: " << TotalCount << "\n";
  237. }
  238. void ProfileSummary::printDetailedSummary(raw_ostream &OS) const {
  239. OS << "Detailed summary:\n";
  240. for (const auto &Entry : DetailedSummary) {
  241. OS << Entry.NumCounts << " blocks with count >= " << Entry.MinCount
  242. << " account for "
  243. << format("%0.6g", (float)Entry.Cutoff / Scale * 100)
  244. << " percentage of the total counts.\n";
  245. }
  246. }