• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 &regNO : 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