• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021-2024 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 #include "cse.h"
17 #include "utils/logger.h"
18 #include "optimizer/analysis/rpo.h"
19 #include "optimizer/analysis/dominators_tree.h"
20 #include "algorithm"
21 #include "compiler_logger.h"
22 
23 namespace ark::compiler {
LocalCse()24 void Cse::LocalCse()
25 {
26     deletedInsts_.clear();
27     candidates_.clear();
28     for (auto bb : GetGraph()->GetBlocksRPO()) {
29         candidates_.clear();
30         for (auto inst : bb->Insts()) {
31             if (!IsLegalExp(inst)) {
32                 continue;
33             }
34             // match the insts in candidates
35             Exp exp = GetExp(inst);
36             if (AllNotIn(candidates_, inst)) {
37                 InstVector emptyTmp(GetGraph()->GetLocalAllocator()->Adapter());
38                 emptyTmp.emplace_back(inst);
39                 candidates_.emplace(exp, std::move(emptyTmp));
40                 continue;
41             }
42             if (NotIn(candidates_, exp)) {
43                 exp = GetExpCommutative(inst);
44             }
45 
46             auto &cntainer = candidates_.at(exp);
47             auto iter = std::find_if(cntainer.begin(), cntainer.end(), Finder(inst));
48             if (iter != cntainer.end()) {
49                 inst->ReplaceUsers(*iter);
50                 deletedInsts_.emplace_back(inst);
51             } else {
52                 cntainer.emplace_back(inst);
53             }
54         }
55     }
56     RemoveInstsIn(&deletedInsts_);
57 }
58 
TryAddReplacePair(Inst * inst)59 void Cse::TryAddReplacePair(Inst *inst)
60 {
61     if (!IsLegalExp(inst) || AllNotIn(candidates_, inst)) {
62         return;
63     }
64     Exp exp = NotIn(candidates_, GetExp(inst)) ? GetExpCommutative(inst) : GetExp(inst);
65     auto &cntainer = candidates_.at(exp);
66     auto iter = std::find_if(cntainer.begin(), cntainer.end(), Finder(inst));
67     if (iter != cntainer.end()) {
68         replacePair_.emplace_back(inst, *iter);
69     }
70 }
71 
CollectTreeForest()72 void Cse::CollectTreeForest()
73 {
74     replacePair_.clear();
75     for (auto bb : GetGraph()->GetBlocksRPO()) {
76         if (bb->IsEndBlock()) {
77             continue;
78         }
79         candidates_.clear();
80         for (auto inst : bb->Insts()) {
81             if (!IsLegalExp(inst)) {
82                 continue;
83             }
84             auto exp = GetExp(inst);
85             if (AllNotIn(candidates_, inst)) {
86                 InstVector vectmp(GetGraph()->GetLocalAllocator()->Adapter());
87                 vectmp.emplace_back(inst);
88                 candidates_.emplace(exp, std::move(vectmp));
89             } else if (!NotIn(candidates_, exp)) {
90                 candidates_.at(exp).emplace_back(inst);
91             } else {
92                 candidates_.at(GetExpCommutative(inst)).emplace_back(inst);
93             }
94         }
95         if (candidates_.empty()) {
96             continue;
97         }
98         for (auto domed : bb->GetDominatedBlocks()) {
99             for (auto inst : domed->Insts()) {
100                 TryAddReplacePair(inst);
101             }
102         }
103     }
104 }
105 
106 /// Convert the tree-forest structure of replace_pair into star-forest structure
ConvertTreeForestToStarForest()107 void Cse::ConvertTreeForestToStarForest()
108 {
109     minReplaceStar_.clear();
110     for (auto rpair : replacePair_) {
111         Inst *temp = rpair.second;
112         auto it = replacePair_.begin();
113         do {
114             it = replacePair_.begin();
115             while (it != replacePair_.end() && it->first != temp) {
116                 it++;
117             }
118             if (it != replacePair_.end()) {
119                 temp = it->second;
120             }
121         } while (it != replacePair_.end());
122 
123         minReplaceStar_.emplace_back(temp, rpair.first);
124     }
125 }
126 
EliminateAlongDomTree()127 void Cse::EliminateAlongDomTree()
128 {
129     // Eliminate along Dominator tree (based on star structure)
130     deletedInsts_.clear();
131     for (auto pair : minReplaceStar_) {
132         pair.second->ReplaceUsers(pair.first);
133         deletedInsts_.emplace_back(pair.second);
134     }
135     RemoveInstsIn(&deletedInsts_);
136 }
137 
BuildSetOfPairs(BasicBlock * block)138 void Cse::BuildSetOfPairs(BasicBlock *block)
139 {
140     sameExpPair_.clear();
141     auto bbl = block->GetPredsBlocks()[0];
142     auto bbr = block->GetPredsBlocks()[1];
143     for (auto instl : bbl->Insts()) {
144         if (!IsLegalExp(instl) || InVector(deletedInsts_, instl)) {
145             continue;
146         }
147         Exp expl = GetExp(instl);
148         if (!NotIn(sameExpPair_, expl)) {
149             auto &pair = sameExpPair_.at(expl);
150             pair.first.emplace_back(instl);
151             continue;
152         }
153         if (!AllNotIn(sameExpPair_, instl)) {
154             auto &pair = sameExpPair_.at(GetExpCommutative(instl));
155             pair.first.emplace_back(instl);
156             continue;
157         }
158         for (auto instr : bbr->Insts()) {
159             if (!IsLegalExp(instr) || (NotSameExp(GetExp(instr), expl) && NotSameExp(GetExpCommutative(instr), expl)) ||
160                 InVector(deletedInsts_, instr)) {
161                 continue;
162             }
163             if (!NotIn(sameExpPair_, expl)) {
164                 auto &pair = sameExpPair_.at(expl);
165                 pair.second.emplace_back(instr);
166                 continue;
167             }
168             InstVector emptyl(GetGraph()->GetLocalAllocator()->Adapter());
169             emptyl.emplace_back(instl);
170             InstVector emptyr(GetGraph()->GetLocalAllocator()->Adapter());
171             emptyr.emplace_back(instr);
172             sameExpPair_.emplace(expl, std::make_pair(std::move(emptyl), std::move(emptyr)));
173         }
174     }
175 }
176 
DomTreeCse()177 void Cse::DomTreeCse()
178 {
179     CollectTreeForest();
180     ConvertTreeForestToStarForest();
181     EliminateAlongDomTree();
182 }
183 
GlobalCse()184 void Cse::GlobalCse()
185 {
186     // Cse should not be used in OSR mode.
187     if (GetGraph()->IsOsrMode()) {
188         return;
189     }
190 
191     deletedInsts_.clear();
192     matchedTuple_.clear();
193     static constexpr size_t TWO_PREDS = 2;
194     // Find out redundant insts
195     for (auto bb : GetGraph()->GetBlocksRPO()) {
196         if (bb->GetPredsBlocks().size() != TWO_PREDS) {
197             continue;
198         }
199         BuildSetOfPairs(bb);
200         if (sameExpPair_.empty()) {
201             continue;
202         }
203         // Build the set of matched insts
204         for (auto inst : bb->Insts()) {
205             if (!IsLegalExp(inst) || AllNotIn(sameExpPair_, inst)) {
206                 continue;
207             }
208             Exp exp = NotIn(sameExpPair_, GetExp(inst)) ? GetExpCommutative(inst) : GetExp(inst);
209             auto &pair = sameExpPair_.find(exp)->second;
210             ASSERT(!pair.first.empty());
211             auto instl = *pair.first.begin();
212             // If one decides to enable Cse in OSR mode then
213             // ensure that inst's basic block is not OsrEntry.
214             deletedInsts_.emplace_back(inst);
215             auto lrpair = std::make_pair(instl, *(pair.second.begin()));
216             matchedTuple_.emplace_back(inst, std::move(lrpair));
217         }
218     }
219     // Add phi instruction
220     matchedTuple_.shrink_to_fit();
221     for (auto tuple : matchedTuple_) {
222         auto inst = tuple.first;
223         auto phi = GetGraph()->CreateInstPhi(inst->GetType(), inst->GetPc());
224         inst->ReplaceUsers(phi);
225         inst->GetBasicBlock()->AppendPhi(phi);
226         auto &pair = tuple.second;
227         phi->AppendInput(pair.first);
228         phi->AppendInput(pair.second);
229     }
230     RemoveInstsIn(&deletedInsts_);
231 }
232 
RunImpl()233 bool Cse::RunImpl()
234 {
235     LocalCse();
236     DomTreeCse();
237     GlobalCse();
238     if (!isApplied_) {
239         COMPILER_LOG(DEBUG, CSE_OPT) << "Cse does not find duplicate insts";
240     }
241     return isApplied_;
242 }
243 }  // namespace ark::compiler
244