OLD | NEW |
---|---|
1 //===- subzero/src/IceCfg.cpp - Control flow graph implementation ---------===// | 1 //===- subzero/src/IceCfg.cpp - Control flow graph implementation ---------===// |
2 // | 2 // |
3 // The Subzero Code Generator | 3 // The Subzero Code Generator |
4 // | 4 // |
5 // This file is distributed under the University of Illinois Open Source | 5 // This file is distributed under the University of Illinois Open Source |
6 // License. See LICENSE.TXT for details. | 6 // License. See LICENSE.TXT for details. |
7 // | 7 // |
8 //===----------------------------------------------------------------------===// | 8 //===----------------------------------------------------------------------===// |
9 /// | 9 /// |
10 /// \file | 10 /// \file |
(...skipping 489 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
500 for (CfgNode *Node : reverse_range(ReversedReachable)) | 500 for (CfgNode *Node : reverse_range(ReversedReachable)) |
501 Shuffled.push_back(Node); | 501 Shuffled.push_back(Node); |
502 for (CfgNode *Node : Unreachable) | 502 for (CfgNode *Node : Unreachable) |
503 Shuffled.push_back(Node); | 503 Shuffled.push_back(Node); |
504 assert(Nodes.size() == Shuffled.size()); | 504 assert(Nodes.size() == Shuffled.size()); |
505 swapNodes(Shuffled); | 505 swapNodes(Shuffled); |
506 | 506 |
507 dump("After basic block shuffling"); | 507 dump("After basic block shuffling"); |
508 } | 508 } |
509 | 509 |
510 void Cfg::localCSE() { | |
Jim Stichnoth
2016/05/23 16:52:56
I'd like to have a comment here briefly describing
manasijm
2016/05/23 23:13:30
Done.
| |
511 TimerMarker T(TimerStack::TT_localCse, this); | |
512 struct InstHash { | |
513 size_t operator()(const Inst *Instr) const { | |
514 auto Kind = Instr->getKind(); | |
515 auto Result = | |
516 std::hash<typename std::underlying_type<Inst::InstKind>::type>()( | |
517 Kind); | |
518 for (SizeT i = 0; i < Instr->getSrcSize(); ++i) { | |
519 auto *Opnd = Instr->getSrc(i); | |
520 if (auto *Var = llvm::dyn_cast<Variable>(Opnd)) { | |
521 Result ^= std::hash<SizeT>()(Var->getIndex()); | |
Jim Stichnoth
2016/05/23 16:52:57
This is a repetition of the VariableHash implement
manasijm
2016/05/23 23:13:30
Done.
| |
522 } else if (Constant *Const = llvm::dyn_cast<Constant>(Opnd)) { | |
523 Result ^= std::hash<Constant *>()(Const); | |
524 // TODO : get Value of ConstantPrimitive | |
Jim Stichnoth
2016/05/23 16:52:57
If I understand this correctly, your hash function
manasijm
2016/05/23 23:13:30
Done.
| |
525 } else | |
526 Result ^= std::hash<Operand *>()(Opnd); | |
527 } | |
528 return Result; | |
529 } | |
530 }; | |
531 struct InstEq { | |
532 bool srcEq(const Operand *A, const Operand *B) const { | |
533 if (!(llvm::isa<Variable>(A) || (llvm::isa<Constant>(A))) || | |
Jim Stichnoth
2016/05/23 16:52:56
This is really hard to read/understand. How about
manasijm
2016/05/23 23:13:30
Done.
| |
534 !(llvm::isa<Variable>(B) || (llvm::isa<Constant>(B)))) | |
535 return false; | |
536 // No reason this has to an error. Returning false just disables the cse | |
Jim Stichnoth
2016/05/23 16:52:57
"has to an error" ==> "has to be an error" ?
And
| |
537 // optimization for this particular case | |
538 return (A == B); | |
539 } | |
540 bool operator()(const Inst *InstrA, const Inst *InstrB) const { | |
541 if ((InstrA->getKind() != InstrB->getKind()) || | |
542 (InstrA->getSrcSize() != InstrB->getSrcSize())) | |
543 return false; | |
544 | |
545 if (auto *A = llvm::dyn_cast<InstArithmetic>(InstrA)) { | |
546 auto B = llvm::cast<InstArithmetic>(InstrB); | |
Jim Stichnoth
2016/05/23 16:52:56
auto *
manasijm
2016/05/23 23:13:30
Done.
| |
547 // A, B are guranteed to be of the same 'kind' at this point | |
Jim Stichnoth
2016/05/23 16:52:57
guaranteed
manasijm
2016/05/23 23:13:30
Done.
| |
548 // So, dyn_Cast is not needed | |
Jim Stichnoth
2016/05/23 16:52:57
dyn_cast
manasijm
2016/05/23 23:13:30
Done.
| |
549 if (A->getOp() != B->getOp()) | |
550 return false; | |
551 } | |
552 // Does not enter loop if different kind or number of operands | |
553 for (SizeT i = 0; i < InstrA->getSrcSize(); ++i) { | |
554 if (!srcEq(InstrA->getSrc(i), InstrB->getSrc(i))) | |
555 return false; | |
556 } | |
557 return true; | |
558 } | |
559 }; | |
560 struct VariableHash { | |
561 size_t operator()(const Variable *Var) const { | |
562 return std::hash<SizeT>()(Var->getIndex()); | |
563 } | |
564 }; | |
565 for (CfgNode *Node : getNodes()) { | |
566 CfgUnorderedSet<Inst *, InstHash, InstEq> Seen; | |
567 | |
568 CfgUnorderedMap<Variable *, Variable *, VariableHash> Replacements; | |
569 // Combining the above two into a single data structure might consume less | |
570 // memory but will be slower i.e map of Instruction -> Set of Variables | |
571 | |
572 CfgUnorderedMap<Variable *, std::vector<Inst *>, VariableHash> Dependency; | |
573 // Not necessary for SSA, still keeping it in case this pass is not run at | |
574 // the beginning. Remove to improve performace. | |
575 | |
576 for (Inst &Instr : Node->getInsts()) { | |
577 if (Instr.isDeleted() || !llvm::isa<InstArithmetic>(&Instr)) | |
578 continue; | |
579 | |
580 // Invalidate replacements | |
581 auto Iter = Replacements.find(Instr.getDest()); | |
582 if (Iter != Replacements.end()) { | |
583 Replacements.erase(Iter); | |
584 } | |
585 | |
586 // Invalidate 'seen' instructions whose operands were just updated. | |
587 auto DepIter = Dependency.find(Instr.getDest()); | |
588 if (DepIter != Dependency.end()) { | |
589 for (auto Dep : DepIter->second) { | |
Jim Stichnoth
2016/05/23 16:52:57
I think this use of "auto" is getting too deep for
manasijm
2016/05/23 23:13:30
Done.
| |
590 Seen.erase(Dep); | |
591 } | |
592 } | |
593 // The above two can be removed if SSA is assumed. | |
594 | |
595 // Replace - doing this before checking for repetitions might enable more | |
596 // optimizations | |
597 for (SizeT i = 0; i < Instr.getSrcSize(); ++i) { | |
598 auto *Opnd = Instr.getSrc(i); | |
599 if (Variable *const Var = llvm::dyn_cast<Variable>(Opnd)) { | |
Jim Stichnoth
2016/05/23 16:52:57
"Variable *const Var" just means that the value of
manasijm
2016/05/23 23:13:30
Artifact from first patch set.
| |
600 if (Replacements.find(Var) != Replacements.end()) { | |
601 Instr.replaceSource(i, Replacements[Var]); | |
602 } | |
603 } | |
604 } | |
605 | |
606 // Check for repetitions | |
607 auto SeenIter = Seen.find(&Instr); | |
608 if (SeenIter != Seen.end()) { // seen before | |
609 const Inst *Found = *SeenIter; | |
610 Replacements[Instr.getDest()] = Found->getDest(); | |
611 } else { // new | |
612 Seen.insert(&Instr); | |
613 | |
614 // Update dependencies | |
615 for (SizeT i = 0; i < Instr.getSrcSize(); ++i) { | |
616 auto *Opnd = Instr.getSrc(i); | |
617 if (auto *Var = llvm::dyn_cast<Variable>(Opnd)) { | |
618 Dependency[Var].push_back(&Instr); | |
619 } | |
620 } | |
621 } | |
622 } | |
623 } | |
624 } | |
625 | |
510 void Cfg::doArgLowering() { | 626 void Cfg::doArgLowering() { |
511 TimerMarker T(TimerStack::TT_doArgLowering, this); | 627 TimerMarker T(TimerStack::TT_doArgLowering, this); |
512 getTarget()->lowerArguments(); | 628 getTarget()->lowerArguments(); |
513 } | 629 } |
514 | 630 |
515 void Cfg::sortAndCombineAllocas(CfgVector<Inst *> &Allocas, | 631 void Cfg::sortAndCombineAllocas(CfgVector<Inst *> &Allocas, |
516 uint32_t CombinedAlignment, InstList &Insts, | 632 uint32_t CombinedAlignment, InstList &Insts, |
517 AllocaBaseVariableType BaseVariableType) { | 633 AllocaBaseVariableType BaseVariableType) { |
518 if (Allocas.empty()) | 634 if (Allocas.empty()) |
519 return; | 635 return; |
(...skipping 958 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1478 } | 1594 } |
1479 } | 1595 } |
1480 // Print each basic block | 1596 // Print each basic block |
1481 for (CfgNode *Node : Nodes) | 1597 for (CfgNode *Node : Nodes) |
1482 Node->dump(this); | 1598 Node->dump(this); |
1483 if (isVerbose(IceV_Instructions)) | 1599 if (isVerbose(IceV_Instructions)) |
1484 Str << "}\n"; | 1600 Str << "}\n"; |
1485 } | 1601 } |
1486 | 1602 |
1487 } // end of namespace Ice | 1603 } // end of namespace Ice |
OLD | NEW |