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 "cgfunc.h"
17 #include "loop.h"
18 #include "cg_ssa_pre.h"
19
20 namespace maplebe {
21
22 // ================ Step 6: Code Motion ================
CodeMotion()23 void SSAPre::CodeMotion()
24 {
25 // pass 1 only doing insertion
26 for (Occ *occ : allOccs) {
27 if (occ->occTy != kAOccPhiOpnd) {
28 continue;
29 }
30 PhiOpndOcc *phiOpndOcc = static_cast<PhiOpndOcc *>(occ);
31 if (phiOpndOcc->insertHere) {
32 DEBUG_ASSERT(loop->GetBBLoopParent(phiOpndOcc->cgbb->GetId()) == nullptr,
33 "cg_ssapre: save inserted inside loop");
34 workCand->saveAtEntryBBs.insert(phiOpndOcc->cgbb->GetId());
35 }
36 }
37 // pass 2 only doing deletion
38 for (Occ *occ : realOccs) {
39 if (occ->occTy != kAOccReal) {
40 continue;
41 }
42 RealOcc *realOcc = static_cast<RealOcc *>(occ);
43 if (!realOcc->redundant) {
44 DEBUG_ASSERT(loop->GetBBLoopParent(realOcc->cgbb->GetId()) == nullptr,
45 "cg_ssapre: save in place inside loop");
46 workCand->saveAtEntryBBs.insert(realOcc->cgbb->GetId());
47 }
48 }
49 if (enabledDebug) {
50 LogInfo::MapleLogger() << " _______ output _______" << '\n';
51 LogInfo::MapleLogger() << " saveAtEntryBBs: [";
52 for (uint32 id : workCand->saveAtEntryBBs) {
53 LogInfo::MapleLogger() << id << " ";
54 }
55 LogInfo::MapleLogger() << "]\n\n";
56 }
57 }
58
59 // ================ Step 5: Finalize ================
60 // for setting RealOcc's redundant flag and PhiOpndOcc's insertHere flag
Finalize()61 void SSAPre::Finalize()
62 {
63 std::vector<Occ *> availDefVec(classCount + 1, nullptr);
64 // preorder traversal of dominator tree
65 for (Occ *occ : allOccs) {
66 size_t classId = static_cast<size_t>(occ->classId);
67 switch (occ->occTy) {
68 case kAOccPhi: {
69 PhiOcc *phiOcc = static_cast<PhiOcc *>(occ);
70 if (phiOcc->WillBeAvail()) {
71 availDefVec[classId] = phiOcc;
72 }
73 break;
74 }
75 case kAOccReal: {
76 RealOcc *realOcc = static_cast<RealOcc *>(occ);
77 if (availDefVec[classId] == nullptr || !availDefVec[classId]->IsDominate(dom, occ)) {
78 realOcc->redundant = false;
79 availDefVec[classId] = realOcc;
80 } else {
81 realOcc->redundant = true;
82 }
83 break;
84 }
85 case kAOccPhiOpnd: {
86 PhiOpndOcc *phiOpndOcc = static_cast<PhiOpndOcc *>(occ);
87 const PhiOcc *phiOcc = phiOpndOcc->defPhiOcc;
88 if (phiOcc->WillBeAvail()) {
89 if (phiOpndOcc->def == nullptr || (!phiOpndOcc->hasRealUse && phiOpndOcc->def->occTy == kAOccPhi &&
90 !static_cast<PhiOcc *>(phiOpndOcc->def)->WillBeAvail())) {
91 // insert a store
92 if (phiOpndOcc->cgbb->GetSuccs().size() != 1) { // critical edge
93 workCand->saveAtProlog = true;
94 break;
95 }
96 phiOpndOcc->insertHere = true;
97 } else {
98 phiOpndOcc->def = availDefVec[classId];
99 }
100 }
101 break;
102 }
103 case kAOccExit:
104 break;
105 default:
106 DEBUG_ASSERT(false, "Finalize: unexpected occ type");
107 break;
108 }
109 if (workCand->saveAtProlog) {
110 break;
111 }
112 }
113 if (enabledDebug) {
114 LogInfo::MapleLogger() << " _______ after finalize _______" << '\n';
115 if (workCand->saveAtProlog) {
116 LogInfo::MapleLogger() << "Giving up because of insertion at critical edge" << '\n';
117 return;
118 }
119 for (Occ *occ : allOccs) {
120 if (occ->occTy == kAOccReal) {
121 RealOcc *realOcc = static_cast<RealOcc *>(occ);
122 if (!realOcc->redundant) {
123 occ->Dump();
124 LogInfo::MapleLogger() << " non-redundant" << '\n';
125 }
126 } else if (occ->occTy == kAOccPhiOpnd) {
127 PhiOpndOcc *phiOpndOcc = static_cast<PhiOpndOcc *>(occ);
128 if (phiOpndOcc->insertHere) {
129 occ->Dump();
130 LogInfo::MapleLogger() << " insertHere" << '\n';
131 }
132 }
133 }
134 }
135 }
136
137 // ================ Step 4: WillBeAvail Computation ================
138
ResetCanBeAvail(PhiOcc * phi) const139 void SSAPre::ResetCanBeAvail(PhiOcc *phi) const
140 {
141 phi->isCanBeAvail = false;
142 // the following loop finds phi's uses and reset them
143 for (PhiOcc *phiOcc : phiOccs) {
144 for (PhiOpndOcc *phiOpndOcc : phiOcc->phiOpnds) {
145 if (phiOpndOcc->def != nullptr && phiOpndOcc->def == phi) {
146 if (!phiOpndOcc->hasRealUse && !phiOcc->isDownsafe && phiOcc->isCanBeAvail) {
147 ResetCanBeAvail(phiOcc);
148 }
149 }
150 }
151 }
152 }
153
ComputeCanBeAvail() const154 void SSAPre::ComputeCanBeAvail() const
155 {
156 for (PhiOcc *phiOcc : phiOccs) {
157 if (!phiOcc->isDownsafe && phiOcc->isCanBeAvail) {
158 bool existNullUse = false;
159 for (PhiOpndOcc *phiOpndOcc : phiOcc->phiOpnds) {
160 if (phiOpndOcc->def == nullptr) {
161 existNullUse = true;
162 break;
163 }
164 }
165 if (existNullUse) {
166 ResetCanBeAvail(phiOcc);
167 }
168 }
169 }
170 }
171
ResetLater(PhiOcc * phi) const172 void SSAPre::ResetLater(PhiOcc *phi) const
173 {
174 phi->isLater = false;
175 // the following loop finds phi's uses and reset them
176 for (PhiOcc *phiOcc : phiOccs) {
177 for (PhiOpndOcc *phiOpndOcc : phiOcc->phiOpnds) {
178 if (phiOpndOcc->def != nullptr && phiOpndOcc->def == phi) {
179 if (phiOcc->isLater) {
180 ResetLater(phiOcc);
181 }
182 }
183 }
184 }
185 }
186
ComputeLater() const187 void SSAPre::ComputeLater() const
188 {
189 for (PhiOcc *phiOcc : phiOccs) {
190 phiOcc->isLater = phiOcc->isCanBeAvail;
191 }
192 for (PhiOcc *phiOcc : phiOccs) {
193 if (phiOcc->isLater) {
194 bool existNonNullUse = false;
195 for (PhiOpndOcc *phiOpndOcc : phiOcc->phiOpnds) {
196 if (phiOpndOcc->def != nullptr && phiOpndOcc->hasRealUse) {
197 existNonNullUse = true;
198 break;
199 }
200 }
201 if (existNonNullUse || phiOcc->speculativeDownsafe) {
202 ResetLater(phiOcc);
203 }
204 }
205 }
206 if (enabledDebug) {
207 LogInfo::MapleLogger() << " _______ after later computation _______" << '\n';
208 for (PhiOcc *phiOcc : phiOccs) {
209 phiOcc->Dump();
210 if (phiOcc->isCanBeAvail) {
211 LogInfo::MapleLogger() << " canbeAvail";
212 }
213 if (phiOcc->isLater) {
214 LogInfo::MapleLogger() << " later";
215 }
216 if (phiOcc->isCanBeAvail && !phiOcc->isLater) {
217 LogInfo::MapleLogger() << " will be Avail";
218 }
219 LogInfo::MapleLogger() << '\n';
220 }
221 }
222 }
223
224 // ================ Step 3: Downsafe Computation ================
ResetDownsafe(const PhiOpndOcc * phiOpnd) const225 void SSAPre::ResetDownsafe(const PhiOpndOcc *phiOpnd) const
226 {
227 if (phiOpnd->hasRealUse) {
228 return;
229 }
230 Occ *defOcc = phiOpnd->def;
231 if (defOcc == nullptr || defOcc->occTy != kAOccPhi) {
232 return;
233 }
234 PhiOcc *defPhiOcc = static_cast<PhiOcc *>(defOcc);
235 if (defPhiOcc->speculativeDownsafe) {
236 return;
237 }
238 if (!defPhiOcc->isDownsafe) {
239 return;
240 }
241 defPhiOcc->isDownsafe = false;
242 for (PhiOpndOcc *phiOpndOcc : defPhiOcc->phiOpnds) {
243 ResetDownsafe(phiOpndOcc);
244 }
245 }
246
ComputeDownsafe() const247 void SSAPre::ComputeDownsafe() const
248 {
249 for (PhiOcc *phiOcc : phiOccs) {
250 if (!phiOcc->isDownsafe) {
251 // propagate not-Downsafe backward along use-def edges
252 for (PhiOpndOcc *phiOpndOcc : phiOcc->phiOpnds) {
253 ResetDownsafe(phiOpndOcc);
254 }
255 }
256 }
257 if (enabledDebug) {
258 LogInfo::MapleLogger() << " _______ after downsafe computation _______" << '\n';
259 for (PhiOcc *phiOcc : phiOccs) {
260 phiOcc->Dump();
261 if (phiOcc->speculativeDownsafe) {
262 LogInfo::MapleLogger() << " spec_downsafe /";
263 }
264 if (phiOcc->isDownsafe) {
265 LogInfo::MapleLogger() << " downsafe";
266 }
267 LogInfo::MapleLogger() << '\n';
268 }
269 }
270 }
271
272 // ================ Step 2: rename ================
PropagateSpeculativeDownsafe(const LoopAnalysis & loop,PhiOcc * phiOcc)273 static void PropagateSpeculativeDownsafe(const LoopAnalysis &loop, PhiOcc *phiOcc)
274 {
275 if (phiOcc->speculativeDownsafe) {
276 return;
277 }
278 phiOcc->isDownsafe = true;
279 phiOcc->speculativeDownsafe = true;
280 for (PhiOpndOcc *phiOpndOcc : phiOcc->phiOpnds) {
281 if (phiOpndOcc->def != nullptr && phiOpndOcc->def->occTy == kAOccPhi) {
282 PhiOcc *nextPhiOcc = static_cast<PhiOcc *>(phiOpndOcc->def);
283 if (loop.GetBBLoopParent(nextPhiOcc->cgbb->GetId()) != nullptr) {
284 PropagateSpeculativeDownsafe(loop, nextPhiOcc);
285 }
286 }
287 }
288 }
289
Rename()290 void SSAPre::Rename()
291 {
292 std::stack<Occ *> occStack;
293 classCount = 0;
294 // iterate thru the occurrences in order of preorder traversal of dominator
295 // tree
296 for (Occ *occ : allOccs) {
297 while (!occStack.empty() && !occStack.top()->IsDominate(dom, occ)) {
298 occStack.pop();
299 }
300 switch (occ->occTy) {
301 case kAOccExit:
302 if (!occStack.empty()) {
303 Occ *topOcc = occStack.top();
304 if (topOcc->occTy == kAOccPhi) {
305 PhiOcc *phiTopOcc = static_cast<PhiOcc *>(topOcc);
306 if (!phiTopOcc->speculativeDownsafe) {
307 phiTopOcc->isDownsafe = false;
308 }
309 }
310 }
311 break;
312 case kAOccPhi:
313 // assign new class
314 occ->classId = ++classCount;
315 occStack.push(occ);
316 break;
317 case kAOccReal: {
318 if (occStack.empty()) {
319 // assign new class
320 occ->classId = ++classCount;
321 occStack.push(occ);
322 break;
323 }
324 Occ *topOcc = occStack.top();
325 occ->classId = topOcc->classId;
326 if (topOcc->occTy == kAOccPhi) {
327 occStack.push(occ);
328 if (loop->GetBBLoopParent(occ->cgbb->GetId()) != nullptr) {
329 static_cast<PhiOcc *>(topOcc)->isDownsafe = true;
330 static_cast<PhiOcc *>(topOcc)->speculativeDownsafe = true;
331 }
332 }
333 break;
334 }
335 case kAOccPhiOpnd: {
336 if (occStack.empty()) {
337 // leave classId as 0
338 break;
339 }
340 Occ *topOcc = occStack.top();
341 occ->def = topOcc;
342 occ->classId = topOcc->classId;
343 if (topOcc->occTy == kAOccReal) {
344 static_cast<PhiOpndOcc *>(occ)->hasRealUse = true;
345 }
346 break;
347 }
348 default:
349 DEBUG_ASSERT(false, "Rename: unexpected type of occurrence");
350 break;
351 }
352 }
353 // loop thru phiOccs to propagate speculativeDownsafe
354 for (PhiOcc *phiOcc : phiOccs) {
355 if (phiOcc->speculativeDownsafe) {
356 for (PhiOpndOcc *phiOpndOcc : phiOcc->phiOpnds) {
357 if (phiOpndOcc->def != nullptr && phiOpndOcc->def->occTy == kAOccPhi) {
358 PhiOcc *nextPhiOcc = static_cast<PhiOcc *>(phiOpndOcc->def);
359 if (loop->GetBBLoopParent(nextPhiOcc->cgbb->GetId()) != nullptr) {
360 PropagateSpeculativeDownsafe(*loop, nextPhiOcc);
361 }
362 }
363 }
364 }
365 }
366 if (enabledDebug) {
367 LogInfo::MapleLogger() << " _______ after rename _______" << '\n';
368 for (Occ *occ : allOccs) {
369 occ->Dump();
370 if (occ->occTy == kAOccPhi) {
371 PhiOcc *phiOcc = static_cast<PhiOcc *>(occ);
372 if (phiOcc->speculativeDownsafe) {
373 LogInfo::MapleLogger() << " spec_downsafe /";
374 }
375 }
376 LogInfo::MapleLogger() << '\n';
377 }
378 }
379 }
380
381 // ================ Step 1: insert phis ================
382
383 // form pih occ based on the real occ in workCand->realOccs; result is
384 // stored in phiDfns
FormPhis()385 void SSAPre::FormPhis()
386 {
387 for (Occ *occ : realOccs) {
388 GetIterDomFrontier(occ->cgbb, &phiDfns);
389 }
390 }
391
392 // form allOccs inclusive of real, phi, phiOpnd, exit occurrences;
393 // form phiOccs containing only the phis
CreateSortedOccs()394 void SSAPre::CreateSortedOccs()
395 {
396 // form phiOpnd occs based on the preds of the phi occs; result is
397 // stored in phiOpndDfns
398 std::multiset<uint32> phiOpndDfns;
399 for (uint32 dfn : phiDfns) {
400 const BBId bbId = dom->GetDtPreOrderItem(dfn);
401 BB *cgbb = cgFunc->GetAllBBs()[bbId];
402 for (BB *pred : cgbb->GetPreds()) {
403 (void)phiOpndDfns.insert(dom->GetDtDfnItem(pred->GetId()));
404 }
405 }
406 std::unordered_map<BBId, std::forward_list<PhiOpndOcc *>> bb2PhiOpndMap;
407 MapleVector<Occ *>::iterator realOccIt = realOccs.begin();
408 MapleVector<ExitOcc *>::iterator exitOccIt = exitOccs.begin();
409 MapleSet<uint32>::iterator phiDfnIt = phiDfns.begin();
410 MapleSet<uint32>::iterator phiOpndDfnIt = phiOpndDfns.begin();
411 Occ *nextRealOcc = nullptr;
412 if (realOccIt != realOccs.end()) {
413 nextRealOcc = *realOccIt;
414 }
415 ExitOcc *nextExitOcc = nullptr;
416 if (exitOccIt != exitOccs.end()) {
417 nextExitOcc = *exitOccIt;
418 }
419 PhiOcc *nextPhiOcc = nullptr;
420 if (phiDfnIt != phiDfns.end()) {
421 nextPhiOcc = preMp->New<PhiOcc>(cgFunc->GetAllBBs().at(dom->GetDtPreOrderItem(*phiDfnIt)), preAllocator);
422 }
423 PhiOpndOcc *nextPhiOpndOcc = nullptr;
424 if (phiOpndDfnIt != phiOpndDfns.end()) {
425 nextPhiOpndOcc = preMp->New<PhiOpndOcc>(cgFunc->GetAllBBs().at(dom->GetDtPreOrderItem(*phiOpndDfnIt)));
426 auto it = bb2PhiOpndMap.find(dom->GetDtPreOrderItem(*phiOpndDfnIt));
427 if (it == bb2PhiOpndMap.end()) {
428 std::forward_list<PhiOpndOcc *> newlist = {nextPhiOpndOcc};
429 bb2PhiOpndMap[dom->GetDtPreOrderItem(*phiOpndDfnIt)] = newlist;
430 } else {
431 it->second.push_front(nextPhiOpndOcc);
432 }
433 }
434 Occ *pickedOcc = nullptr; // the next picked occ in order of preorder traversal of dominator tree
435 do {
436 pickedOcc = nullptr;
437 if (nextPhiOcc != nullptr) {
438 pickedOcc = nextPhiOcc;
439 }
440 if (nextRealOcc != nullptr && (pickedOcc == nullptr || dom->GetDtDfnItem(nextRealOcc->cgbb->GetId()) <
441 dom->GetDtDfnItem(pickedOcc->cgbb->GetId()))) {
442 pickedOcc = nextRealOcc;
443 }
444 if (nextPhiOpndOcc != nullptr &&
445 (pickedOcc == nullptr || *phiOpndDfnIt < dom->GetDtDfnItem(pickedOcc->cgbb->GetId()))) {
446 pickedOcc = nextPhiOpndOcc;
447 }
448 if (nextExitOcc != nullptr && (pickedOcc == nullptr || dom->GetDtDfnItem(nextExitOcc->cgbb->GetId()) <
449 dom->GetDtDfnItem(pickedOcc->cgbb->GetId()))) {
450 pickedOcc = nextExitOcc;
451 }
452 if (pickedOcc != nullptr) {
453 allOccs.push_back(pickedOcc);
454 switch (pickedOcc->occTy) {
455 case kAOccReal: {
456 // get the next real occ
457 CHECK_FATAL(realOccIt != realOccs.end(), "iterator check");
458 ++realOccIt;
459 if (realOccIt != realOccs.end()) {
460 nextRealOcc = *realOccIt;
461 } else {
462 nextRealOcc = nullptr;
463 }
464 break;
465 }
466 case kAOccExit: {
467 CHECK_FATAL(exitOccIt != exitOccs.end(), "iterator check");
468 ++exitOccIt;
469 if (exitOccIt != exitOccs.end()) {
470 nextExitOcc = *exitOccIt;
471 } else {
472 nextExitOcc = nullptr;
473 }
474 break;
475 }
476 case kAOccPhi: {
477 phiOccs.push_back(static_cast<PhiOcc *>(pickedOcc));
478 CHECK_FATAL(phiDfnIt != phiDfns.end(), "iterator check");
479 ++phiDfnIt;
480 if (phiDfnIt != phiDfns.end()) {
481 nextPhiOcc =
482 preMp->New<PhiOcc>(cgFunc->GetAllBBs().at(dom->GetDtPreOrderItem(*phiDfnIt)), preAllocator);
483 } else {
484 nextPhiOcc = nullptr;
485 }
486 break;
487 }
488 case kAOccPhiOpnd: {
489 CHECK_FATAL(phiOpndDfnIt != phiOpndDfns.end(), "iterator check");
490 ++phiOpndDfnIt;
491 if (phiOpndDfnIt != phiOpndDfns.end()) {
492 nextPhiOpndOcc =
493 preMp->New<PhiOpndOcc>(cgFunc->GetAllBBs().at(dom->GetDtPreOrderItem(*phiOpndDfnIt)));
494 auto it = bb2PhiOpndMap.find(dom->GetDtPreOrderItem(*phiOpndDfnIt));
495 if (it == bb2PhiOpndMap.end()) {
496 std::forward_list<PhiOpndOcc *> newlist = {nextPhiOpndOcc};
497 bb2PhiOpndMap[dom->GetDtPreOrderItem(*phiOpndDfnIt)] = newlist;
498 } else {
499 it->second.push_front(nextPhiOpndOcc);
500 }
501 } else {
502 nextPhiOpndOcc = nullptr;
503 }
504 break;
505 }
506 default:
507 DEBUG_ASSERT(false, "CreateSortedOccs: unexpected occTy");
508 break;
509 }
510 }
511 } while (pickedOcc != nullptr);
512 // initialize phiOpnd vector in each PhiOcc node and defPhiOcc in each PhiOpndOcc
513 for (PhiOcc *phiOcc : phiOccs) {
514 for (BB *pred : phiOcc->cgbb->GetPreds()) {
515 PhiOpndOcc *phiOpndOcc = bb2PhiOpndMap[pred->GetId()].front();
516 phiOcc->phiOpnds.push_back(phiOpndOcc);
517 phiOpndOcc->defPhiOcc = phiOcc;
518 bb2PhiOpndMap[pred->GetId()].pop_front();
519 }
520 }
521 if (enabledDebug) {
522 LogInfo::MapleLogger() << " _______ after phi insertion _______" << '\n';
523 for (Occ *occ : allOccs) {
524 occ->Dump();
525 LogInfo::MapleLogger() << '\n';
526 }
527 }
528 }
529
530 // ================ Step 0: Preparations ================
531
PropagateNotAnt(BB * bb,std::set<BB *,BBIdCmp> * visitedBBs)532 void SSAPre::PropagateNotAnt(BB *bb, std::set<BB *, BBIdCmp> *visitedBBs)
533 {
534 if (visitedBBs->count(bb) != 0) {
535 return;
536 }
537 visitedBBs->insert(bb);
538 if (workCand->occBBs.count(bb->GetId()) != 0) {
539 return;
540 }
541 fullyAntBBs[bb->GetId()] = false;
542 for (BB *predbb : bb->GetPreds()) {
543 PropagateNotAnt(predbb, visitedBBs);
544 }
545 }
546
FormRealsNExits()547 void SSAPre::FormRealsNExits()
548 {
549 std::set<BB *, BBIdCmp> visitedBBs;
550 if (asEarlyAsPossible) {
551 for (BB *cgbb : cgFunc->GetExitBBsVec()) {
552 if (!cgbb->IsUnreachable()) {
553 PropagateNotAnt(cgbb, &visitedBBs);
554 }
555 }
556 }
557
558 for (uint32 i = 0; i < dom->GetDtPreOrderSize(); i++) {
559 BBId bbid = dom->GetDtPreOrderItem(i);
560 BB *cgbb = cgFunc->GetAllBBs()[bbid];
561 if (asEarlyAsPossible) {
562 if (fullyAntBBs[cgbb->GetId()]) {
563 RealOcc *realOcc = preMp->New<RealOcc>(cgbb);
564 realOccs.push_back(realOcc);
565 }
566 } else {
567 if (workCand->occBBs.count(cgbb->GetId()) != 0) {
568 RealOcc *realOcc = preMp->New<RealOcc>(cgbb);
569 realOccs.push_back(realOcc);
570 }
571 }
572 if (!cgbb->IsUnreachable() && (cgbb->NumSuccs() == 0 || cgbb->GetKind() == BB::kBBReturn)) {
573 ExitOcc *exitOcc = preMp->New<ExitOcc>(cgbb);
574 exitOccs.push_back(exitOcc);
575 }
576 }
577 if (enabledDebug) {
578 LogInfo::MapleLogger() << "Placement Optimization for callee-save saves" << '\n';
579 LogInfo::MapleLogger() << "-----------------------------------------------" << '\n';
580 LogInfo::MapleLogger() << " _______ input _______" << '\n';
581 LogInfo::MapleLogger() << " occBBs: [";
582 for (uint32 id : workCand->occBBs) {
583 LogInfo::MapleLogger() << id << " ";
584 }
585 LogInfo::MapleLogger() << "]\n";
586 }
587 }
588
ApplySSAPre()589 void SSAPre::ApplySSAPre()
590 {
591 FormRealsNExits();
592 // #1 insert phis; results in allOccs and phiOccs
593 FormPhis(); // result put in the set phi_bbs
594 CreateSortedOccs();
595 // #2 rename
596 Rename();
597 if (!phiOccs.empty()) {
598 // #3 DownSafety
599 ComputeDownsafe();
600 // #4 CanBeAvail
601 ComputeCanBeAvail();
602 ComputeLater();
603 }
604 // #5 Finalize
605 Finalize();
606 if (!workCand->saveAtProlog) {
607 // #6 Code Motion
608 CodeMotion();
609 }
610 }
611
DoSavePlacementOpt(CGFunc * f,DomAnalysis * dom,LoopAnalysis * loop,SsaPreWorkCand * workCand)612 void DoSavePlacementOpt(CGFunc *f, DomAnalysis *dom, LoopAnalysis *loop, SsaPreWorkCand *workCand)
613 {
614 MemPool *tempMP = memPoolCtrler.NewMemPool("cg_ssa_pre", true);
615 SSAPre cgssapre(f, dom, loop, tempMP, workCand, false /*asEarlyAsPossible*/, false /*enabledDebug*/);
616
617 cgssapre.ApplySSAPre();
618
619 memPoolCtrler.DeleteMemPool(tempMP);
620 }
621
622 } // namespace maplebe
623