constant.h 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990
  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. #ifndef CARBON_TOOLCHAIN_SEM_IR_CONSTANT_H_
  5. #define CARBON_TOOLCHAIN_SEM_IR_CONSTANT_H_
  6. #include "llvm/ADT/FoldingSet.h"
  7. #include "toolchain/sem_ir/ids.h"
  8. #include "toolchain/sem_ir/inst.h"
  9. namespace Carbon::SemIR {
  10. // Provides a ValueStore wrapper for tracking the constant values of
  11. // instructions.
  12. class ConstantValueStore {
  13. public:
  14. explicit ConstantValueStore(ConstantId default_value)
  15. : default_(default_value) {}
  16. // Returns the constant value of the requested instruction, which is default_
  17. // if unallocated.
  18. auto Get(InstId inst_id) const -> ConstantId {
  19. CARBON_CHECK(inst_id.index >= 0);
  20. return static_cast<size_t>(inst_id.index) >= values_.size()
  21. ? default_
  22. : values_[inst_id.index];
  23. }
  24. // Sets the constant value of the given instruction, or sets that it is known
  25. // to not be a constant.
  26. auto Set(InstId inst_id, ConstantId const_id) -> void {
  27. CARBON_CHECK(inst_id.index >= 0);
  28. if (static_cast<size_t>(inst_id.index) >= values_.size()) {
  29. values_.resize(inst_id.index + 1, default_);
  30. }
  31. values_[inst_id.index] = const_id;
  32. }
  33. private:
  34. const ConstantId default_;
  35. // A mapping from `InstId::index` to the corresponding constant value. This is
  36. // expected to be sparse, and may be smaller than the list of instructions if
  37. // there are trailing non-constant instructions.
  38. //
  39. // Set inline size to 0 because these will typically be too large for the
  40. // stack, while this does make File smaller.
  41. llvm::SmallVector<ConstantId, 0> values_;
  42. };
  43. // Provides storage for instructions representing deduplicated global constants.
  44. class ConstantStore {
  45. public:
  46. explicit ConstantStore(File& sem_ir, llvm::BumpPtrAllocator& allocator)
  47. : allocator_(&allocator), constants_(&sem_ir) {}
  48. // Adds a new constant instruction, or gets the existing constant with this
  49. // value. Returns the ID of the constant.
  50. //
  51. // This updates `sem_ir.insts()` and `sem_ir.constant_values()` if the
  52. // constant is new.
  53. auto GetOrAdd(Inst inst, bool is_symbolic) -> ConstantId;
  54. // Returns a copy of the constant IDs as a vector, in an arbitrary but
  55. // stable order. This should not be used anywhere performance-sensitive.
  56. auto GetAsVector() const -> llvm::SmallVector<InstId, 0>;
  57. auto size() const -> int { return constants_.size(); }
  58. private:
  59. // TODO: We store two copies of each constant instruction: one in insts() and
  60. // one here. We could avoid one of those copies and store just an InstId here,
  61. // at the cost of some more indirection when recomputing profiles during
  62. // lookup. Once we have a representative data set, we should measure the
  63. // impact on compile time from that change.
  64. struct ConstantNode : llvm::FoldingSetNode {
  65. Inst inst;
  66. ConstantId constant_id;
  67. auto Profile(llvm::FoldingSetNodeID& id, File* sem_ir) -> void;
  68. };
  69. llvm::BumpPtrAllocator* allocator_;
  70. llvm::ContextualFoldingSet<ConstantNode, File*> constants_;
  71. };
  72. } // namespace Carbon::SemIR
  73. #endif // CARBON_TOOLCHAIN_SEM_IR_CONSTANT_H_