Warning: This file is not a C or C++ file. It does not have highlighting.

1//===-- IntervalSet.h -------------------------------------------*- C++ -*-===//
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#ifndef FORTRAN_LOWER_INTERVALSET_H
10#define FORTRAN_LOWER_INTERVALSET_H
11
12#include <cassert>
13#include <map>
14
15namespace Fortran::lower {
16
17//===----------------------------------------------------------------------===//
18// Interval set
19//===----------------------------------------------------------------------===//
20
21/// Interval set to keep track of intervals, merging them when they overlap one
22/// another. Used to refine the pseudo-offset ranges of the front-end symbols
23/// into groups of aliasing variables.
24struct IntervalSet {
25 using MAP = std::map<std::size_t, std::size_t>;
26 using Iterator = MAP::const_iterator;
27
28 // Handles the merging of overlapping intervals correctly, efficiently.
29 void merge(std::size_t lo, std::size_t up) {
30 assert(lo <= up);
31 if (empty()) {
32 m.insert({lo, up});
33 return;
34 }
35 auto i = m.lower_bound(lo);
36 // i->first >= lo
37 if (i == begin()) {
38 if (up < i->first) {
39 // [lo..up] < i->first
40 m.insert({lo, up});
41 return;
42 }
43 // up >= i->first
44 if (i->second > up)
45 up = i->second;
46 fuse(lo, up, i);
47 return;
48 }
49 auto i1 = i;
50 if (i == end() || i->first > lo)
51 i = std::prev(i);
52 // i->first <= lo
53 if (i->second >= up) {
54 // i->first <= lo && up <= i->second, keep i
55 return;
56 }
57 // i->second < up
58 if (i->second < lo) {
59 if (i1 == end() || i1->first > up) {
60 // i < [lo..up] < i1
61 m.insert({lo, up});
62 return;
63 }
64 // i < [lo..up], i1->first <= up --> [lo..up] union [i1..?]
65 i = i1;
66 } else {
67 // i->first <= lo, lo <= i->second --> [i->first..up] union [i..?]
68 lo = i->first;
69 }
70 fuse(lo, up, i);
71 }
72
73 Iterator find(std::size_t pt) const {
74 auto i = m.lower_bound(pt);
75 if (i != end() && i->first == pt)
76 return i;
77 if (i == begin())
78 return end();
79 i = std::prev(i);
80 if (i->second < pt)
81 return end();
82 return i;
83 }
84
85 Iterator begin() const { return m.begin(); }
86 Iterator end() const { return m.end(); }
87 bool empty() const { return m.empty(); }
88 std::size_t size() const { return m.size(); }
89
90private:
91 // Find and fuse overlapping sets.
92 void fuse(std::size_t lo, std::size_t up, Iterator i) {
93 auto j = m.upper_bound(up);
94 // up < j->first
95 std::size_t cu = std::prev(j)->second;
96 // cu < j->first
97 if (cu > up)
98 up = cu;
99 m.erase(i, j);
100 // merge [i .. j) with [i->first, max(up, cu)]
101 m.insert({lo, up});
102 }
103
104 MAP m{};
105};
106
107} // namespace Fortran::lower
108
109#endif // FORTRAN_LOWER_INTERVALSET_H
110

Warning: This file is not a C or C++ file. It does not have highlighting.

source code of flang/include/flang/Lower/IntervalSet.h