1 /*
2 * Copyright (c) 2023 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 "data_dep_base.h"
17
18 namespace maplebe {
ProcessNonMachineInsn(Insn & insn,MapleVector<Insn * > & comments,MapleVector<DepNode * > & dataNodes,const Insn * & locInsn)19 void DataDepBase::ProcessNonMachineInsn(Insn &insn, MapleVector<Insn *> &comments, MapleVector<DepNode *> &dataNodes,
20 const Insn *&locInsn)
21 {
22 CHECK_FATAL(!insn.IsMachineInstruction(), "need non-machine-instruction");
23 if (insn.IsImmaterialInsn()) {
24 if (!insn.IsComment()) {
25 locInsn = &insn;
26 } else {
27 (void)comments.emplace_back(&insn);
28 }
29 } else if (insn.IsCfiInsn()) {
30 if (!dataNodes.empty()) {
31 dataNodes.back()->AddCfiInsn(insn);
32 }
33 }
34 }
35
BuildDepsLastCallInsn(Insn & insn)36 void DataDepBase::BuildDepsLastCallInsn(Insn &insn)
37 {
38 Insn *lastCallInsn = curCDGNode->GetLastCallInsn();
39 if (lastCallInsn != nullptr && !lastCallInsn->IsSpecialCall()) {
40 AddDependence(*lastCallInsn->GetDepNode(), *insn.GetDepNode(), kDependenceTypeControl);
41 }
42 if (insn.IsCall() || insn.IsTailCall()) {
43 curCDGNode->SetLastCallInsn(&insn);
44 }
45 }
46
BuildAmbiInsnDependency(Insn & insn)47 void DataDepBase::BuildAmbiInsnDependency(Insn &insn)
48 {
49 const auto &defRegnos = insn.GetDepNode()->GetDefRegnos();
50 for (const auto ®NO : defRegnos) {
51 if (IfInAmbiRegs(regNO)) {
52 break;
53 }
54 }
55 }
56
57 // Build data dependence between control register and last call instruction.
58 // insn : instruction that with control register operand.
59 // isDest : if the control register operand is a destination operand.
BuildDepsBetweenControlRegAndCall(Insn & insn,bool isDest)60 void DataDepBase::BuildDepsBetweenControlRegAndCall(Insn &insn, bool isDest)
61 {
62 Insn *lastCallInsn = curCDGNode->GetLastCallInsn();
63 if (lastCallInsn == nullptr) {
64 return;
65 }
66 if (isDest) {
67 AddDependence(*lastCallInsn->GetDepNode(), *insn.GetDepNode(), kDependenceTypeOutput);
68 return;
69 }
70 AddDependence(*lastCallInsn->GetDepNode(), *insn.GetDepNode(), kDependenceTypeAnti);
71 }
72
73 // Build control data dependence for branch/ret instructions
BuildDepsControlAll(Insn & insn,const MapleVector<DepNode * > & nodes)74 void DataDepBase::BuildDepsControlAll(Insn &insn, const MapleVector<DepNode *> &nodes)
75 {
76 DepNode *depNode = insn.GetDepNode();
77 // For rest instructions, we build control dependency
78 for (auto *dataNode : nodes) {
79 AddDependence(*dataNode, *depNode, kDependenceTypeControl);
80 }
81 }
82
83 // Build data dependence of destination register operand
BuildDepsDefReg(Insn & insn,regno_t regNO)84 void DataDepBase::BuildDepsDefReg(Insn &insn, regno_t regNO)
85 {
86 DepNode *node = insn.GetDepNode();
87 node->AddDefReg(regNO);
88 // 1. For building intra-block data dependence, only require the data flow info of the curBB(cur CDGNode)
89 // 2. For building inter-block data dependence, require the data flow info of all BBs on the pred path in CFG
90 // Build anti dependence
91 if (isIntra || curRegion->GetRegionNodeSize() == 1 || curRegion->GetRegionRoot() == curCDGNode) {
92 RegList *regList = curCDGNode->GetUseInsnChain(regNO);
93 while (regList != nullptr) {
94 CHECK_NULL_FATAL(regList->insn);
95 AddDependence(*regList->insn->GetDepNode(), *node, kDependenceTypeAnti);
96 regList = regList->next;
97 }
98 } else if (curRegion->GetRegionRoot() != curCDGNode) {
99 BuildInterBlockDefUseDependency(*node, regNO, kDependenceTypeAnti, false);
100 }
101
102 // Build output dependence
103 // Build intra block data dependence
104 Insn *defInsn = curCDGNode->GetLatestDefInsn(regNO);
105 if (defInsn != nullptr) {
106 AddDependence(*defInsn->GetDepNode(), *node, kDependenceTypeOutput);
107 } else if (!isIntra && curRegion->GetRegionRoot() != curCDGNode) {
108 // Build inter block data dependence
109 BuildInterBlockDefUseDependency(*node, regNO, kDependenceTypeOutput, true);
110 }
111 }
112
113 // Build data dependence of source register operand
BuildDepsUseReg(Insn & insn,regno_t regNO)114 void DataDepBase::BuildDepsUseReg(Insn &insn, regno_t regNO)
115 {
116 DepNode *node = insn.GetDepNode();
117 node->AddUseReg(regNO);
118
119 // Build intra block data dependence
120 Insn *defInsn = curCDGNode->GetLatestDefInsn(regNO);
121 if (defInsn != nullptr) {
122 AddDependence(*defInsn->GetDepNode(), *node, kDependenceTypeTrue);
123 } else if (!isIntra && curRegion->GetRegionRoot() != curCDGNode) {
124 // Build inter block data dependence
125 BuildInterBlockDefUseDependency(*node, regNO, kDependenceTypeTrue, true);
126 }
127 }
128
129 // For inter data dependence analysis
BuildInterBlockDefUseDependency(DepNode & curDepNode,regno_t regNO,DepType depType,bool isDef)130 void DataDepBase::BuildInterBlockDefUseDependency(DepNode &curDepNode, regno_t regNO, DepType depType, bool isDef)
131 {
132 CHECK_FATAL(!isIntra, "must be inter block data dependence analysis");
133 CHECK_FATAL(curRegion->GetRegionRoot() != curCDGNode, "for the root node, cross-BB search is not required");
134 BB *curBB = curCDGNode->GetBB();
135 CHECK_FATAL(curBB != nullptr, "get bb from cdgNode failed");
136 std::vector<bool> visited(curRegion->GetMaxBBIdInRegion() + 1, false);
137 if (isDef) {
138 BuildPredPathDefDependencyDFS(*curBB, visited, curDepNode, regNO, depType);
139 } else {
140 BuildPredPathUseDependencyDFS(*curBB, visited, curDepNode, regNO, depType);
141 }
142 }
143
BuildPredPathDefDependencyDFS(BB & curBB,std::vector<bool> & visited,DepNode & depNode,regno_t regNO,DepType depType)144 void DataDepBase::BuildPredPathDefDependencyDFS(BB &curBB, std::vector<bool> &visited, DepNode &depNode, regno_t regNO,
145 DepType depType)
146 {
147 if (visited[curBB.GetId()]) {
148 return;
149 }
150 CDGNode *cdgNode = curBB.GetCDGNode();
151 CHECK_FATAL(cdgNode != nullptr, "get cdgNode from bb failed");
152 CDGRegion *region = cdgNode->GetRegion();
153 CHECK_FATAL(region != nullptr, "get region from cdgNode failed");
154 if (region->GetRegionId() != curRegion->GetRegionId()) {
155 return;
156 }
157 Insn *curDefInsn = cdgNode->GetLatestDefInsn(regNO);
158 if (curDefInsn != nullptr) {
159 visited[curBB.GetId()] = true;
160 AddDependence(*curDefInsn->GetDepNode(), depNode, depType);
161 return;
162 }
163 // Ignore back-edge
164 if (cdgNode == curRegion->GetRegionRoot()) {
165 return;
166 }
167 for (auto predIt = curBB.GetPredsBegin(); predIt != curBB.GetPredsEnd(); ++predIt) {
168 // Ignore back-edge of self-loop
169 if (*predIt != &curBB) {
170 BuildPredPathDefDependencyDFS(**predIt, visited, depNode, regNO, depType);
171 }
172 }
173 }
174
BuildPredPathUseDependencyDFS(BB & curBB,std::vector<bool> & visited,DepNode & depNode,regno_t regNO,DepType depType)175 void DataDepBase::BuildPredPathUseDependencyDFS(BB &curBB, std::vector<bool> &visited, DepNode &depNode, regno_t regNO,
176 DepType depType)
177 {
178 if (visited[curBB.GetId()]) {
179 return;
180 }
181 CDGNode *cdgNode = curBB.GetCDGNode();
182 CHECK_FATAL(cdgNode != nullptr, "get cdgNode from bb failed");
183 CDGRegion *region = cdgNode->GetRegion();
184 CHECK_FATAL(region != nullptr, "get region from cdgNode failed");
185 if (region->GetRegionId() != curRegion->GetRegionId()) {
186 return;
187 }
188 visited[curBB.GetId()] = true;
189 RegList *useChain = cdgNode->GetUseInsnChain(regNO);
190 while (useChain != nullptr) {
191 Insn *useInsn = useChain->insn;
192 CHECK_FATAL(useInsn != nullptr, "get useInsn failed");
193 AddDependence(*useInsn->GetDepNode(), depNode, depType);
194 useChain = useChain->next;
195 }
196 // Ignore back-edge
197 if (cdgNode == curRegion->GetRegionRoot()) {
198 return;
199 }
200 for (auto predIt = curBB.GetPredsBegin(); predIt != curBB.GetPredsEnd(); ++predIt) {
201 // Ignore back-edge of self-loop
202 if (*predIt != &curBB) {
203 BuildPredPathUseDependencyDFS(**predIt, visited, depNode, regNO, depType);
204 }
205 }
206 }
207
BuildInterBlockSpecialDataInfoDependency(DepNode & curDepNode,bool needCmp,DepType depType,DataDepBase::DataFlowInfoType infoType)208 void DataDepBase::BuildInterBlockSpecialDataInfoDependency(DepNode &curDepNode, bool needCmp, DepType depType,
209 DataDepBase::DataFlowInfoType infoType)
210 {
211 CHECK_FATAL(!isIntra, "must be inter block data dependence analysis");
212 CHECK_FATAL(curRegion->GetRegionRoot() != curCDGNode, "for the root node, cross-BB search is not required");
213 BB *curBB = curCDGNode->GetBB();
214 CHECK_FATAL(curBB != nullptr, "get bb from cdgNode failed");
215 std::vector<bool> visited(curRegion->GetMaxBBIdInRegion() + 1, false);
216 BuildPredPathSpecialDataInfoDependencyDFS(*curBB, visited, needCmp, curDepNode, depType, infoType);
217 }
218
219 // Generate a data depNode.
220 // insn : create depNode for the instruction.
221 // nodes : a vector to store depNode.
222 // nodeSum : the new depNode's index.
223 // comments : those comment insn between last no-comment's insn and insn.
GenerateDepNode(Insn & insn,MapleVector<DepNode * > & nodes,uint32 & nodeSum,MapleVector<Insn * > & comments)224 DepNode *DataDepBase::GenerateDepNode(Insn &insn, MapleVector<DepNode *> &nodes, uint32 &nodeSum,
225 MapleVector<Insn *> &comments)
226 {
227 Reservation *rev = mad.FindReservation(insn);
228 DEBUG_ASSERT(rev != nullptr, "get reservation of insn failed");
229 auto *depNode = memPool.New<DepNode>(insn, alloc, rev->GetUnit(), rev->GetUnitNum(), *rev);
230 depNode->SetIndex(nodeSum++);
231 (void)nodes.emplace_back(depNode);
232 insn.SetDepNode(*depNode);
233
234 constexpr size_t vectorSize = 5;
235 depNode->ReservePreds(vectorSize);
236 depNode->ReserveSuccs(vectorSize);
237
238 if (!comments.empty()) {
239 depNode->SetComments(comments);
240 comments.clear();
241 }
242 return depNode;
243 }
244
BuildPredPathSpecialDataInfoDependencyDFS(BB & curBB,std::vector<bool> & visited,bool needCmp,DepNode & depNode,DepType depType,DataDepBase::DataFlowInfoType infoType)245 void DataDepBase::BuildPredPathSpecialDataInfoDependencyDFS(BB &curBB, std::vector<bool> &visited, bool needCmp,
246 DepNode &depNode, DepType depType,
247 DataDepBase::DataFlowInfoType infoType)
248 {
249 if (visited[curBB.GetId()]) {
250 return;
251 }
252 CDGNode *cdgNode = curBB.GetCDGNode();
253 CHECK_FATAL(cdgNode != nullptr, "get cdgNode from bb failed");
254 CDGRegion *region = cdgNode->GetRegion();
255 CHECK_FATAL(region != nullptr, "get region from cdgNode failed");
256 if (region != curCDGNode->GetRegion()) {
257 return;
258 }
259
260 switch (infoType) {
261 case kMembar: {
262 Insn *membarInsn = cdgNode->GetMembarInsn();
263 if (membarInsn != nullptr) {
264 visited[curBB.GetId()] = true;
265 AddDependence(*membarInsn->GetDepNode(), depNode, depType);
266 }
267 break;
268 }
269 case kLastCall: {
270 Insn *lastCallInsn = cdgNode->GetLastCallInsn();
271 if (lastCallInsn != nullptr) {
272 visited[curBB.GetId()] = true;
273 AddDependence(*lastCallInsn->GetDepNode(), depNode, depType);
274 }
275 break;
276 }
277 case kLastFrameDef: {
278 Insn *lastFrameDef = cdgNode->GetLastFrameDefInsn();
279 if (lastFrameDef != nullptr) {
280 visited[curBB.GetId()] = true;
281 AddDependence(*lastFrameDef->GetDepNode(), depNode, depType);
282 }
283 break;
284 }
285 case kStackUses: {
286 visited[curBB.GetId()] = true;
287 MapleVector<Insn *> stackUses = cdgNode->GetStackUseInsns();
288 BuildForStackHeapDefUseInfoData(needCmp, stackUses, depNode, depType);
289 break;
290 }
291 case kStackDefs: {
292 visited[curBB.GetId()] = true;
293 MapleVector<Insn *> stackDefs = cdgNode->GetStackDefInsns();
294 BuildForStackHeapDefUseInfoData(needCmp, stackDefs, depNode, depType);
295 break;
296 }
297 case kHeapUses: {
298 visited[curBB.GetId()] = true;
299 MapleVector<Insn *> &heapUses = cdgNode->GetHeapUseInsns();
300 BuildForStackHeapDefUseInfoData(needCmp, heapUses, depNode, depType);
301 break;
302 }
303 case kHeapDefs: {
304 visited[curBB.GetId()] = true;
305 MapleVector<Insn *> &heapDefs = cdgNode->GetHeapDefInsns();
306 BuildForStackHeapDefUseInfoData(needCmp, heapDefs, depNode, depType);
307 break;
308 }
309 default: {
310 visited[curBB.GetId()] = true;
311 break;
312 }
313 }
314 // Ignore back-edge
315 if (cdgNode == curRegion->GetRegionRoot()) {
316 return;
317 }
318 for (auto predIt = curBB.GetPredsBegin(); predIt != curBB.GetPredsEnd(); ++predIt) {
319 // Ignore back-edge of self-loop
320 if (*predIt != &curBB) {
321 BuildPredPathSpecialDataInfoDependencyDFS(**predIt, visited, needCmp, depNode, depType, infoType);
322 }
323 }
324 }
325
BuildForStackHeapDefUseInfoData(bool needCmp,MapleVector<Insn * > & insns,DepNode & depNode,DepType depType)326 void DataDepBase::BuildForStackHeapDefUseInfoData(bool needCmp, MapleVector<Insn *> &insns, DepNode &depNode,
327 DepType depType)
328 {
329 if (needCmp) {
330 AddDependence4InsnInVectorByTypeAndCmp(insns, *depNode.GetInsn(), depType);
331 } else {
332 AddDependence4InsnInVectorByType(insns, *depNode.GetInsn(), depType);
333 }
334 }
335
336 // Build data dependency edge from FromNode to ToNode:
337 // Two data dependency node has a unique edge.
338 // These two dependencies will set the latency on the dependency edge:
339 // 1. True data dependency overwrites other dependency;
340 // 2. Output data dependency overwrites other dependency except true dependency;
341 // The latency of the other dependencies is 0.
AddDependence(DepNode & fromNode,DepNode & toNode,DepType depType)342 void DataDepBase::AddDependence(DepNode &fromNode, DepNode &toNode, DepType depType)
343 {
344 // Can not build a self loop dependence
345 if (&fromNode == &toNode) {
346 return;
347 }
348 // Check if exist edge between the two node
349 if (!fromNode.GetSuccs().empty()) {
350 DepLink *depLink = fromNode.GetSuccs().back();
351 if (&(depLink->GetTo()) == &toNode) {
352 // If there exists edges, only replace with the true or output dependency
353 if (depLink->GetDepType() != kDependenceTypeTrue && depType == kDependenceTypeTrue) {
354 depLink->SetDepType(kDependenceTypeTrue);
355 // Set latency on true dependency edge:
356 // 1. if there exists bypass between defInsn and useInsn, the latency of dependency is bypass default;
357 // 2. otherwise, the latency of dependency is cost of defInsn
358 depLink->SetLatency(static_cast<uint32>(mad.GetLatency(*fromNode.GetInsn(), *toNode.GetInsn())));
359 } else if (depLink->GetDepType() != kDependenceTypeOutput && depType == kDependenceTypeOutput) {
360 depLink->SetDepType(kDependenceTypeOutput);
361 // Set latency on output dependency edge:
362 // 1. set (fromInsn_default_latency - toInsn_default_latency), if it greater than 0;
363 // 2. set 1 by default.
364 int latency = (fromNode.GetReservation()->GetLatency() - toNode.GetReservation()->GetLatency()) > 0
365 ? fromNode.GetReservation()->GetLatency() - toNode.GetReservation()->GetLatency()
366 : 1;
367 depLink->SetLatency(static_cast<uint32>(latency));
368 }
369 return;
370 }
371 }
372 auto *depLink = memPool.New<DepLink>(fromNode, toNode, depType);
373 if (depType == kDependenceTypeTrue) {
374 depLink->SetLatency(static_cast<uint32>(mad.GetLatency(*fromNode.GetInsn(), *toNode.GetInsn())));
375 } else if (depType == kDependenceTypeOutput) {
376 int latency = (fromNode.GetReservation()->GetLatency() - toNode.GetReservation()->GetLatency()) > 0
377 ? fromNode.GetReservation()->GetLatency() - toNode.GetReservation()->GetLatency()
378 : 1;
379 depLink->SetLatency(static_cast<uint32>(latency));
380 }
381 fromNode.AddSucc(*depLink);
382 toNode.AddPred(*depLink);
383 }
384
AddDependence4InsnInVectorByType(MapleVector<Insn * > & insns,Insn & insn,const DepType & type)385 void DataDepBase::AddDependence4InsnInVectorByType(MapleVector<Insn *> &insns, Insn &insn, const DepType &type)
386 {
387 for (auto anyInsn : insns) {
388 AddDependence(*anyInsn->GetDepNode(), *insn.GetDepNode(), type);
389 }
390 }
391
AddDependence4InsnInVectorByTypeAndCmp(MapleVector<Insn * > & insns,Insn & insn,const DepType & type)392 void DataDepBase::AddDependence4InsnInVectorByTypeAndCmp(MapleVector<Insn *> &insns, Insn &insn, const DepType &type)
393 {
394 for (auto anyInsn : insns) {
395 if (anyInsn != &insn) {
396 AddDependence(*anyInsn->GetDepNode(), *insn.GetDepNode(), type);
397 }
398 }
399 }
400
401 // Remove self data dependence (self loop) in data dependence graph.
RemoveSelfDeps(Insn & insn)402 void DataDepBase::RemoveSelfDeps(Insn &insn)
403 {
404 DepNode *node = insn.GetDepNode();
405 DEBUG_ASSERT(node->GetSuccs().back()->GetTo().GetInsn() == &insn, "Is not a self dependence.");
406 DEBUG_ASSERT(node->GetPreds().back()->GetFrom().GetInsn() == &insn, "Is not a self dependence.");
407 node->RemoveSucc();
408 node->RemovePred();
409 }
410
411 // Check if regNO is in ehInRegs.
IfInAmbiRegs(regno_t regNO) const412 bool DataDepBase::IfInAmbiRegs(regno_t regNO) const
413 {
414 return false;
415 }
416
417 // Return data dependence type name
GetDepTypeName(DepType depType) const418 const std::string &DataDepBase::GetDepTypeName(DepType depType) const
419 {
420 DEBUG_ASSERT(depType <= kDependenceTypeNone, "array boundary check failed");
421 return kDepTypeName[depType];
422 }
423 } // namespace maplebe
424