1 /** 2 * Copyright (c) 2021-2022 Huawei Device Co., Ltd. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 16 #ifndef COMPILER_OPTIMIZER_IR_MARKER_H 17 #define COMPILER_OPTIMIZER_IR_MARKER_H 18 19 #include <array> 20 #include <bitset> 21 #include <cstdint> 22 #include "macros.h" 23 24 namespace panda::compiler { 25 using Marker = uint32_t; 26 constexpr uint32_t MARKERS_SHIFT = 2; 27 constexpr uint32_t MARKERS_NUM = (1U << MARKERS_SHIFT); 28 constexpr uint32_t MARKERS_MASK = (MARKERS_NUM - 1U); 29 constexpr uint32_t MARKER_SIZE = 32; 30 constexpr uint32_t MAX_MARKER = ((1U << (MARKER_SIZE - MARKERS_NUM)) - 1U); 31 constexpr uint32_t UNDEF_MARKER = 0; 32 33 class MarkerMgr { 34 public: MarkerMgr()35 MarkerMgr() : current_index_(0) {} 36 37 NO_COPY_SEMANTIC(MarkerMgr); 38 NO_MOVE_SEMANTIC(MarkerMgr); 39 virtual ~MarkerMgr() = default; 40 NewMarker()41 Marker NewMarker() const 42 { 43 ASSERT_PRINT(current_index_ < MAX_MARKER, "Markers overflow. Please check recursion"); 44 ++current_index_; 45 for (uint32_t i = 0; i < MARKERS_NUM; i++) { 46 if (!spaces_[i]) { 47 Marker mrk = (current_index_ << MARKERS_SHIFT) | i; 48 spaces_[i] = true; 49 ASSERT(mrk != UNDEF_MARKER); 50 return mrk; 51 } 52 } 53 UNREACHABLE(); 54 } 55 EraseMarker(Marker mrk)56 void EraseMarker(Marker mrk) const 57 { 58 spaces_[mrk & MARKERS_MASK] = false; 59 } 60 GetCurrentMarkerIdx()61 uint32_t GetCurrentMarkerIdx() 62 { 63 return current_index_; 64 } SetMaxMarkerIdx(uint32_t ixd)65 void SetMaxMarkerIdx(uint32_t ixd) 66 { 67 current_index_ = std::max(current_index_, ixd); 68 } 69 70 private: 71 mutable uint32_t current_index_ {0}; 72 mutable std::bitset<MARKERS_NUM> spaces_ {}; 73 }; 74 75 class MarkerSet { 76 public: MarkerSet()77 MarkerSet() 78 { 79 ClearMarkers(); 80 } 81 82 NO_COPY_SEMANTIC(MarkerSet); 83 NO_MOVE_SEMANTIC(MarkerSet); 84 virtual ~MarkerSet() = default; 85 86 // returns true if the marker was set before, otherwise set marker and return false SetMarker(Marker mrk)87 bool SetMarker(Marker mrk) 88 { 89 uint32_t index = mrk & MARKERS_MASK; 90 uint32_t value = mrk >> MARKERS_SHIFT; 91 ASSERT(index < MARKERS_NUM); 92 if (markers_[index] == value) { 93 return true; 94 } 95 markers_[index] = value; 96 return false; 97 } 98 99 // returns true if the marker was set before, otherwise false IsMarked(Marker mrk)100 bool IsMarked(Marker mrk) 101 { 102 uint32_t index = mrk & MARKERS_MASK; 103 uint32_t value = mrk >> MARKERS_SHIFT; 104 ASSERT(index < MARKERS_NUM); 105 return markers_[index] == value; 106 } 107 108 // unset marker and returns true if the marker was set before, otherwise false ResetMarker(Marker mrk)109 bool ResetMarker(Marker mrk) 110 { 111 uint32_t index = mrk & MARKERS_MASK; 112 uint32_t value = mrk >> MARKERS_SHIFT; 113 bool was_set = (markers_[index] == value); 114 ASSERT(index < MARKERS_NUM); 115 markers_[index] = UNDEF_MARKER; 116 return was_set; 117 } 118 ClearMarkers()119 void ClearMarkers() 120 { 121 for (unsigned int &marker : markers_) { 122 marker = UNDEF_MARKER; 123 } 124 } 125 126 private: 127 friend class MarkerMgr; 128 std::array<Marker, MARKERS_NUM> markers_ {}; 129 }; 130 } // namespace panda::compiler 131 132 #endif // COMPILER_OPTIMIZER_IR_MARKER_H 133