ProfileSummary.cpp 11 KB

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