Chromium Code Reviews| 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 |