constant.h 3.4 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495
  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. // Returns the constant values mapping as an ArrayRef whose keys are
  34. // instruction indexes. Some of the elements in this mapping may be Invalid or
  35. // NotConstant.
  36. auto array_ref() const -> llvm::ArrayRef<ConstantId> { return values_; }
  37. private:
  38. const ConstantId default_;
  39. // A mapping from `InstId::index` to the corresponding constant value. This is
  40. // expected to be sparse, and may be smaller than the list of instructions if
  41. // there are trailing non-constant instructions.
  42. //
  43. // Set inline size to 0 because these will typically be too large for the
  44. // stack, while this does make File smaller.
  45. llvm::SmallVector<ConstantId, 0> values_;
  46. };
  47. // Provides storage for instructions representing deduplicated global constants.
  48. class ConstantStore {
  49. public:
  50. explicit ConstantStore(File& sem_ir, llvm::BumpPtrAllocator& allocator)
  51. : allocator_(&allocator), constants_(&sem_ir) {}
  52. // Adds a new constant instruction, or gets the existing constant with this
  53. // value. Returns the ID of the constant.
  54. //
  55. // This updates `sem_ir.insts()` and `sem_ir.constant_values()` if the
  56. // constant is new.
  57. auto GetOrAdd(Inst inst, bool is_symbolic) -> ConstantId;
  58. // Returns a copy of the constant IDs as a vector, in an arbitrary but
  59. // stable order. This should not be used anywhere performance-sensitive.
  60. auto GetAsVector() const -> llvm::SmallVector<InstId, 0>;
  61. auto size() const -> int { return constants_.size(); }
  62. private:
  63. // TODO: We store two copies of each constant instruction: one in insts() and
  64. // one here. We could avoid one of those copies and store just an InstId here,
  65. // at the cost of some more indirection when recomputing profiles during
  66. // lookup. Once we have a representative data set, we should measure the
  67. // impact on compile time from that change.
  68. struct ConstantNode : llvm::FoldingSetNode {
  69. Inst inst;
  70. ConstantId constant_id;
  71. auto Profile(llvm::FoldingSetNodeID& id, File* sem_ir) -> void;
  72. };
  73. llvm::BumpPtrAllocator* allocator_;
  74. llvm::ContextualFoldingSet<ConstantNode, File*> constants_;
  75. };
  76. } // namespace Carbon::SemIR
  77. #endif // CARBON_TOOLCHAIN_SEM_IR_CONSTANT_H_