Path: blob/main/contrib/llvm-project/compiler-rt/lib/orc/interval_map.h
39566 views
//===--------- interval_map.h - A sorted interval map -----------*- C++ -*-===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//7//8// Implements a coalescing interval map.9//10//===----------------------------------------------------------------------===//1112#ifndef ORC_RT_INTERVAL_MAP_H13#define ORC_RT_INTERVAL_MAP_H1415#include "adt.h"16#include <cassert>17#include <map>1819namespace __orc_rt {2021enum class IntervalCoalescing { Enabled, Disabled };2223/// Maps intervals to keys with optional coalescing.24///25/// NOTE: The interface is kept mostly compatible with LLVM's IntervalMap26/// collection to make it easy to swap over in the future if we choose27/// to.28template <typename KeyT, typename ValT> class IntervalMapBase {29private:30using KeyPairT = std::pair<KeyT, KeyT>;3132struct Compare {33using is_transparent = std::true_type;34bool operator()(const KeyPairT &LHS, const KeyPairT &RHS) const {35return LHS < RHS;36}37bool operator()(const KeyPairT &LHS, const KeyT &RHS) const {38return LHS.first < RHS;39}40bool operator()(const KeyT &LHS, const KeyPairT &RHS) const {41return LHS < RHS.first;42}43};4445using ImplMap = std::map<KeyPairT, ValT, Compare>;4647public:48using iterator = typename ImplMap::iterator;49using const_iterator = typename ImplMap::const_iterator;50using size_type = typename ImplMap::size_type;5152bool empty() const { return Impl.empty(); }5354void clear() { Impl.clear(); }5556iterator begin() { return Impl.begin(); }57iterator end() { return Impl.end(); }5859const_iterator begin() const { return Impl.begin(); }60const_iterator end() const { return Impl.end(); }6162iterator find(KeyT K) {63// Early out if the key is clearly outside the range.64if (empty() || K < begin()->first.first ||65K >= std::prev(end())->first.second)66return end();6768auto I = Impl.upper_bound(K);69assert(I != begin() && "Should have hit early out above");70I = std::prev(I);71if (K < I->first.second)72return I;73return end();74}7576const_iterator find(KeyT K) const {77return const_cast<IntervalMapBase<KeyT, ValT> *>(this)->find(K);78}7980ValT lookup(KeyT K, ValT NotFound = ValT()) const {81auto I = find(K);82if (I == end())83return NotFound;84return I->second;85}8687// Erase [KS, KE), which must be entirely containing within one existing88// range in the map. Removal is allowed to split the range.89void erase(KeyT KS, KeyT KE) {90if (empty())91return;9293auto J = Impl.upper_bound(KS);9495// Check previous range. Bail out if range to remove is entirely after96// it.97auto I = std::prev(J);98if (KS >= I->first.second)99return;100101// Assert that range is wholly contained.102assert(KE <= I->first.second);103104auto Tmp = std::move(*I);105Impl.erase(I);106107// Split-right -- introduce right-split range.108if (KE < Tmp.first.second) {109Impl.insert(110J, std::make_pair(std::make_pair(KE, Tmp.first.second), Tmp.second));111J = std::prev(J);112}113114// Split-left -- introduce left-split range.115if (KS > Tmp.first.first)116Impl.insert(117J, std::make_pair(std::make_pair(Tmp.first.first, KS), Tmp.second));118}119120protected:121ImplMap Impl;122};123124template <typename KeyT, typename ValT, IntervalCoalescing Coalescing>125class IntervalMap;126127template <typename KeyT, typename ValT>128class IntervalMap<KeyT, ValT, IntervalCoalescing::Enabled>129: public IntervalMapBase<KeyT, ValT> {130public:131// Coalescing insert. Requires that ValTs be equality-comparable.132void insert(KeyT KS, KeyT KE, ValT V) {133auto J = this->Impl.upper_bound(KS);134135// Coalesce-right if possible. Either way, J points at our insertion136// point.137if (J != this->end() && KE == J->first.first && J->second == V) {138KE = J->first.second;139auto Tmp = J++;140this->Impl.erase(Tmp);141}142143// Coalesce-left if possible.144if (J != this->begin()) {145auto I = std::prev(J);146if (I->first.second == KS && I->second == V) {147KS = I->first.first;148this->Impl.erase(I);149}150}151this->Impl.insert(J, std::make_pair(std::make_pair(KS, KE), std::move(V)));152}153};154155template <typename KeyT, typename ValT>156class IntervalMap<KeyT, ValT, IntervalCoalescing::Disabled>157: public IntervalMapBase<KeyT, ValT> {158public:159// Non-coalescing insert. Does not require ValT to be equality-comparable.160void insert(KeyT KS, KeyT KE, ValT V) {161this->Impl.insert(std::make_pair(std::make_pair(KS, KE), std::move(V)));162}163};164165} // End namespace __orc_rt166167#endif // ORC_RT_INTERVAL_MAP_H168169170