xref: /aosp_15_r20/art/compiler/optimizing/common_dominator.h (revision 795d594fd825385562da6b089ea9b2033f3abf5a)
1*795d594fSAndroid Build Coastguard Worker /*
2*795d594fSAndroid Build Coastguard Worker  * Copyright (C) 2015 The Android Open Source Project
3*795d594fSAndroid Build Coastguard Worker  *
4*795d594fSAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
5*795d594fSAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
6*795d594fSAndroid Build Coastguard Worker  * You may obtain a copy of the License at
7*795d594fSAndroid Build Coastguard Worker  *
8*795d594fSAndroid Build Coastguard Worker  *      http://www.apache.org/licenses/LICENSE-2.0
9*795d594fSAndroid Build Coastguard Worker  *
10*795d594fSAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
11*795d594fSAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
12*795d594fSAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*795d594fSAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
14*795d594fSAndroid Build Coastguard Worker  * limitations under the License.
15*795d594fSAndroid Build Coastguard Worker  */
16*795d594fSAndroid Build Coastguard Worker 
17*795d594fSAndroid Build Coastguard Worker #ifndef ART_COMPILER_OPTIMIZING_COMMON_DOMINATOR_H_
18*795d594fSAndroid Build Coastguard Worker #define ART_COMPILER_OPTIMIZING_COMMON_DOMINATOR_H_
19*795d594fSAndroid Build Coastguard Worker 
20*795d594fSAndroid Build Coastguard Worker #include "base/macros.h"
21*795d594fSAndroid Build Coastguard Worker #include "nodes.h"
22*795d594fSAndroid Build Coastguard Worker 
23*795d594fSAndroid Build Coastguard Worker namespace art HIDDEN {
24*795d594fSAndroid Build Coastguard Worker 
25*795d594fSAndroid Build Coastguard Worker // Helper class for finding common dominators of two or more blocks in a graph.
26*795d594fSAndroid Build Coastguard Worker // The domination information of a graph must not be modified while there is
27*795d594fSAndroid Build Coastguard Worker // a CommonDominator object as it's internal state could become invalid.
28*795d594fSAndroid Build Coastguard Worker class CommonDominator {
29*795d594fSAndroid Build Coastguard Worker  public:
30*795d594fSAndroid Build Coastguard Worker   // Convenience function to find the common dominator of 2 blocks.
ForPair(HBasicBlock * block1,HBasicBlock * block2)31*795d594fSAndroid Build Coastguard Worker   static HBasicBlock* ForPair(HBasicBlock* block1, HBasicBlock* block2) {
32*795d594fSAndroid Build Coastguard Worker     CommonDominator finder(block1);
33*795d594fSAndroid Build Coastguard Worker     finder.Update(block2);
34*795d594fSAndroid Build Coastguard Worker     return finder.Get();
35*795d594fSAndroid Build Coastguard Worker   }
36*795d594fSAndroid Build Coastguard Worker 
37*795d594fSAndroid Build Coastguard Worker   // Create a finder starting with a given block.
CommonDominator(HBasicBlock * block)38*795d594fSAndroid Build Coastguard Worker   explicit CommonDominator(HBasicBlock* block)
39*795d594fSAndroid Build Coastguard Worker       : dominator_(block), chain_length_(ChainLength(block)) {
40*795d594fSAndroid Build Coastguard Worker   }
41*795d594fSAndroid Build Coastguard Worker 
42*795d594fSAndroid Build Coastguard Worker   // Update the common dominator with another block.
Update(HBasicBlock * block)43*795d594fSAndroid Build Coastguard Worker   void Update(HBasicBlock* block) {
44*795d594fSAndroid Build Coastguard Worker     DCHECK(block != nullptr);
45*795d594fSAndroid Build Coastguard Worker     if (dominator_ == nullptr) {
46*795d594fSAndroid Build Coastguard Worker       dominator_ = block;
47*795d594fSAndroid Build Coastguard Worker       chain_length_ = ChainLength(block);
48*795d594fSAndroid Build Coastguard Worker       return;
49*795d594fSAndroid Build Coastguard Worker     }
50*795d594fSAndroid Build Coastguard Worker     HBasicBlock* block2 = dominator_;
51*795d594fSAndroid Build Coastguard Worker     DCHECK(block2 != nullptr);
52*795d594fSAndroid Build Coastguard Worker     if (block == block2) {
53*795d594fSAndroid Build Coastguard Worker       return;
54*795d594fSAndroid Build Coastguard Worker     }
55*795d594fSAndroid Build Coastguard Worker     size_t chain_length = ChainLength(block);
56*795d594fSAndroid Build Coastguard Worker     size_t chain_length2 = chain_length_;
57*795d594fSAndroid Build Coastguard Worker     // Equalize the chain lengths
58*795d594fSAndroid Build Coastguard Worker     for ( ; chain_length > chain_length2; --chain_length) {
59*795d594fSAndroid Build Coastguard Worker       block = block->GetDominator();
60*795d594fSAndroid Build Coastguard Worker       DCHECK(block != nullptr);
61*795d594fSAndroid Build Coastguard Worker     }
62*795d594fSAndroid Build Coastguard Worker     for ( ; chain_length2 > chain_length; --chain_length2) {
63*795d594fSAndroid Build Coastguard Worker       block2 = block2->GetDominator();
64*795d594fSAndroid Build Coastguard Worker       DCHECK(block2 != nullptr);
65*795d594fSAndroid Build Coastguard Worker     }
66*795d594fSAndroid Build Coastguard Worker     // Now run up the chain until we hit the common dominator.
67*795d594fSAndroid Build Coastguard Worker     while (block != block2) {
68*795d594fSAndroid Build Coastguard Worker       --chain_length;
69*795d594fSAndroid Build Coastguard Worker       block = block->GetDominator();
70*795d594fSAndroid Build Coastguard Worker       DCHECK(block != nullptr);
71*795d594fSAndroid Build Coastguard Worker       block2 = block2->GetDominator();
72*795d594fSAndroid Build Coastguard Worker       DCHECK(block2 != nullptr);
73*795d594fSAndroid Build Coastguard Worker     }
74*795d594fSAndroid Build Coastguard Worker     dominator_ = block;
75*795d594fSAndroid Build Coastguard Worker     chain_length_ = chain_length;
76*795d594fSAndroid Build Coastguard Worker   }
77*795d594fSAndroid Build Coastguard Worker 
Get()78*795d594fSAndroid Build Coastguard Worker   HBasicBlock* Get() const {
79*795d594fSAndroid Build Coastguard Worker     return dominator_;
80*795d594fSAndroid Build Coastguard Worker   }
81*795d594fSAndroid Build Coastguard Worker 
82*795d594fSAndroid Build Coastguard Worker  private:
ChainLength(HBasicBlock * block)83*795d594fSAndroid Build Coastguard Worker   static size_t ChainLength(HBasicBlock* block) {
84*795d594fSAndroid Build Coastguard Worker     size_t result = 0;
85*795d594fSAndroid Build Coastguard Worker     while (block != nullptr) {
86*795d594fSAndroid Build Coastguard Worker       ++result;
87*795d594fSAndroid Build Coastguard Worker       block = block->GetDominator();
88*795d594fSAndroid Build Coastguard Worker     }
89*795d594fSAndroid Build Coastguard Worker     return result;
90*795d594fSAndroid Build Coastguard Worker   }
91*795d594fSAndroid Build Coastguard Worker 
92*795d594fSAndroid Build Coastguard Worker   HBasicBlock* dominator_;
93*795d594fSAndroid Build Coastguard Worker   size_t chain_length_;
94*795d594fSAndroid Build Coastguard Worker };
95*795d594fSAndroid Build Coastguard Worker 
96*795d594fSAndroid Build Coastguard Worker }  // namespace art
97*795d594fSAndroid Build Coastguard Worker 
98*795d594fSAndroid Build Coastguard Worker #endif  // ART_COMPILER_OPTIMIZING_COMMON_DOMINATOR_H_
99