inst_profile.cpp 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118
  1. // Part of the Carbon Language project, under the Apache License v2.0 with LLVM
  2. // Exceptions. See /LICENSE for license information.
  3. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  4. #include "toolchain/sem_ir/inst_profile.h"
  5. #include "toolchain/sem_ir/file.h"
  6. #include "toolchain/sem_ir/inst.h"
  7. #include "toolchain/sem_ir/typed_insts.h"
  8. namespace Carbon::SemIR {
  9. // A function to profile an argument of an instruction.
  10. using ProfileArgFunction = auto(llvm::FoldingSetNodeID&, const File& sem_ir,
  11. int32_t arg) -> void;
  12. // Profiling for unused arguments.
  13. static auto NullProfileArgFunction(llvm::FoldingSetNodeID& /*id*/,
  14. const File& /*sem_ir*/, int32_t arg)
  15. -> void {
  16. CARBON_CHECK(arg == IdBase::InvalidIndex)
  17. << "Unexpected value for unused argument.";
  18. }
  19. // Profiling for ID arguments that should participate in the instruction's
  20. // value.
  21. static auto DefaultProfileArgFunction(llvm::FoldingSetNodeID& id,
  22. const File& /*sem_ir*/, int32_t arg)
  23. -> void {
  24. id.AddInteger(arg);
  25. }
  26. // Profiling for block ID arguments for which the content of the block should be
  27. // included.
  28. static auto InstBlockProfileArgFunction(llvm::FoldingSetNodeID& id,
  29. const File& sem_ir, int32_t arg)
  30. -> void {
  31. for (auto inst_id : sem_ir.inst_blocks().Get(InstBlockId(arg))) {
  32. id.AddInteger(inst_id.index);
  33. }
  34. }
  35. // Profiling for type block ID arguments for which the content of the block
  36. // should be included.
  37. static auto TypeBlockProfileArgFunction(llvm::FoldingSetNodeID& id,
  38. const File& sem_ir, int32_t arg)
  39. -> void {
  40. for (auto type_id : sem_ir.type_blocks().Get(TypeBlockId(arg))) {
  41. id.AddInteger(type_id.index);
  42. }
  43. }
  44. // Profiling for integer IDs.
  45. static auto IntProfileArgFunction(llvm::FoldingSetNodeID& id,
  46. const File& sem_ir, int32_t arg) -> void {
  47. sem_ir.ints().Get(IntId(arg)).Profile(id);
  48. }
  49. // Profiling for real number IDs.
  50. static auto RealProfileArgFunction(llvm::FoldingSetNodeID& id,
  51. const File& sem_ir, int32_t arg) -> void {
  52. const auto& real = sem_ir.reals().Get(RealId(arg));
  53. // TODO: Profile the value rather than the syntactic form.
  54. real.mantissa.Profile(id);
  55. real.exponent.Profile(id);
  56. id.AddBoolean(real.is_decimal);
  57. }
  58. // Selects the function to use to profile argument N of instruction InstT. We
  59. // compute this in advance so that we can reuse the profiling code for all
  60. // instructions that are profiled in the same way. For example, all instructions
  61. // that take two IDs that are profiled by value use the same profiling code,
  62. // namely `ProfileArgs<DefaultProfileArgFunction, DefaultProfileArgFunction>`.
  63. template <typename InstT, int N>
  64. static constexpr auto SelectProfileArgFunction() -> ProfileArgFunction* {
  65. if constexpr (N >= InstLikeTypeInfo<InstT>::NumArgs) {
  66. // This argument is not used by this instruction; don't profile it.
  67. return NullProfileArgFunction;
  68. } else {
  69. using ArgT = typename InstLikeTypeInfo<InstT>::template ArgType<N>;
  70. if constexpr (std::is_same_v<ArgT, InstBlockId>) {
  71. return InstBlockProfileArgFunction;
  72. } else if constexpr (std::is_same_v<ArgT, TypeBlockId>) {
  73. return TypeBlockProfileArgFunction;
  74. } else if constexpr (std::is_same_v<ArgT, IntId>) {
  75. return IntProfileArgFunction;
  76. } else if constexpr (std::is_same_v<ArgT, RealId>) {
  77. return RealProfileArgFunction;
  78. } else {
  79. return DefaultProfileArgFunction;
  80. }
  81. }
  82. }
  83. // Profiles the given instruction arguments using the specified functions.
  84. template <ProfileArgFunction* ProfileArg0, ProfileArgFunction* ProfileArg1>
  85. static auto ProfileArgs(llvm::FoldingSetNodeID& id, const File& sem_ir,
  86. int32_t arg0, int32_t arg1) -> void {
  87. ProfileArg0(id, sem_ir, arg0);
  88. ProfileArg1(id, sem_ir, arg1);
  89. }
  90. auto ProfileConstant(llvm::FoldingSetNodeID& id, const File& sem_ir, Inst inst)
  91. -> void {
  92. using ProfileArgsFunction =
  93. auto(llvm::FoldingSetNodeID&, const File&, int32_t, int32_t)->void;
  94. static constexpr ProfileArgsFunction* ProfileFunctions[] = {
  95. #define CARBON_SEM_IR_INST_KIND(KindName) \
  96. ProfileArgs<SelectProfileArgFunction<KindName, 0>(), \
  97. SelectProfileArgFunction<KindName, 1>()>,
  98. #include "toolchain/sem_ir/inst_kind.def"
  99. };
  100. inst.kind().Profile(id);
  101. ProfileFunctions[inst.kind().AsInt()](id, sem_ir, inst.arg0(), inst.arg1());
  102. }
  103. } // namespace Carbon::SemIR