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 |
| 11 /// \brief Implements the Cfg class. | 11 /// \brief Implements the Cfg class. |
| 12 /// | 12 /// |
| 13 //===----------------------------------------------------------------------===// | 13 //===----------------------------------------------------------------------===// |
| 14 | 14 |
| 15 #include "IceCfg.h" | 15 #include "IceCfg.h" |
| 16 | 16 |
| 17 #include "IceAssembler.h" | 17 #include "IceAssembler.h" |
| 18 #include "IceBitVector.h" | 18 #include "IceBitVector.h" |
| 19 #include "IceCfgNode.h" | 19 #include "IceCfgNode.h" |
| 20 #include "IceClFlags.h" | 20 #include "IceClFlags.h" |
| 21 #include "IceDefs.h" | 21 #include "IceDefs.h" |
| 22 #include "IceELFObjectWriter.h" | 22 #include "IceELFObjectWriter.h" |
| 23 #include "IceGlobalInits.h" | 23 #include "IceGlobalInits.h" |
| 24 #include "IceInst.h" | 24 #include "IceInst.h" |
| 25 #include "IceInstVarIter.h" | 25 #include "IceInstVarIter.h" |
| 26 #include "IceLiveness.h" | 26 #include "IceLiveness.h" |
| 27 #include "IceLoopAnalyzer.h" | 27 #include "IceLoopAnalyzer.h" |
| 28 #include "IceOperand.h" | 28 #include "IceOperand.h" |
| 29 #include "IceTargetLowering.h" | 29 #include "IceTargetLowering.h" |
| 30 | |
|
Jim Stichnoth
2016/05/19 01:35:50
don't remove this separator blank line
manasijm
2016/05/19 17:50:16
Done.
| |
| 31 #include <memory> | 30 #include <memory> |
| 32 #include <utility> | 31 #include <utility> |
| 33 | 32 |
| 34 namespace Ice { | 33 namespace Ice { |
| 35 | 34 |
| 36 Cfg::Cfg(GlobalContext *Ctx, uint32_t SequenceNumber) | 35 Cfg::Cfg(GlobalContext *Ctx, uint32_t SequenceNumber) |
| 37 : Ctx(Ctx), SequenceNumber(SequenceNumber), VMask(getFlags().getVerbose()), | 36 : Ctx(Ctx), SequenceNumber(SequenceNumber), VMask(getFlags().getVerbose()), |
| 38 FunctionName(), NextInstNumber(Inst::NumberInitial), Live(nullptr) { | 37 FunctionName(), NextInstNumber(Inst::NumberInitial), Live(nullptr) { |
| 39 Allocator.reset(new ArenaAllocator()); | 38 Allocator.reset(new ArenaAllocator()); |
| 40 NodeStrings.reset(new StringPool); | 39 NodeStrings.reset(new StringPool); |
| (...skipping 459 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 500 for (CfgNode *Node : reverse_range(ReversedReachable)) | 499 for (CfgNode *Node : reverse_range(ReversedReachable)) |
| 501 Shuffled.push_back(Node); | 500 Shuffled.push_back(Node); |
| 502 for (CfgNode *Node : Unreachable) | 501 for (CfgNode *Node : Unreachable) |
| 503 Shuffled.push_back(Node); | 502 Shuffled.push_back(Node); |
| 504 assert(Nodes.size() == Shuffled.size()); | 503 assert(Nodes.size() == Shuffled.size()); |
| 505 swapNodes(Shuffled); | 504 swapNodes(Shuffled); |
| 506 | 505 |
| 507 dump("After basic block shuffling"); | 506 dump("After basic block shuffling"); |
| 508 } | 507 } |
| 509 | 508 |
| 509 void Cfg::localCSE() { | |
|
Jim Stichnoth
2016/05/19 01:35:49
(putting this comment here for lack of a better pl
manasijm
2016/05/19 02:01:52
I have not managed to isolate a small example yet
| |
| 510 TimerMarker T(TimerStack::TT_localCse, this); | |
| 511 struct InstHash { | |
| 512 size_t operator()(const Inst *Instr) const { | |
| 513 auto Kind = Instr->getKind(); | |
| 514 auto Result = | |
| 515 std::hash<typename std::underlying_type<Inst::InstKind>::type>()( | |
| 516 Kind); | |
| 517 for (unsigned int i = 0; i < Instr->getSrcSize(); ++i) { | |
|
Jim Stichnoth
2016/05/19 01:35:50
SizeT instead of unsigned int
| |
| 518 Operand *Opr = Instr->getSrc(i); | |
|
Jim Stichnoth
2016/05/19 01:35:49
I would name it not "Opr", but "Op" or "Opnd" to f
| |
| 519 if (Variable *Var = llvm::dyn_cast<Variable>(Opr)) { | |
|
Jim Stichnoth
2016/05/19 01:35:49
auto *Var
because the type is already clear from t
manasijm
2016/05/19 17:50:16
Done.
| |
| 520 Result ^= std::hash<uint32_t>()(Var->getIndex()); | |
|
Jim Stichnoth
2016/05/19 01:35:49
Can you use SizeT instead of uint32_t, to match th
manasijm
2016/05/19 17:50:16
Done.
| |
| 521 } else if (Constant *Cst = llvm::dyn_cast<Constant>(Opr)) { | |
|
Jim Stichnoth
2016/05/19 01:35:49
Name it "Const" instead of "Cst" for consistency.
manasijm
2016/05/19 02:01:53
Ok, didn't do that in the first place because cons
| |
| 522 Result ^= std::hash<Constant *>()( | |
| 523 Cst); // TODO : get Value ConstantPrimitive | |
|
Jim Stichnoth
2016/05/19 01:35:49
TODO(manasijm): get ...
Also, probably put the TO
| |
| 524 } else | |
| 525 Result ^= std::hash<Operand *>()(Opr); | |
| 526 } | |
| 527 return Result; | |
|
Jim Stichnoth
2016/05/19 01:35:49
Use early returns more aggressively, per http://ll
manasijm
2016/05/19 17:50:16
Not applicable here, all the sources has to be inc
| |
| 528 } | |
| 529 }; | |
| 530 struct InstEq { | |
| 531 bool operator()(Inst *const InstrA, Inst *const InstrB) const { | |
|
Jim Stichnoth
2016/05/19 01:35:48
Shouldn't this be "const Inst *InstrA"? Those are
manasijm
2016/05/19 02:01:53
I had some const correctness trouble with that. Wi
manasijm
2016/05/19 17:50:16
Done.
| |
| 532 bool Result = (InstrA->getKind() == InstrB->getKind()) && | |
| 533 (InstrA->getSrcSize() == InstrB->getSrcSize()); | |
|
Jim Stichnoth
2016/05/19 01:35:48
I think this can be made clearer and more efficien
| |
| 534 | |
| 535 if (llvm::isa<InstArithmetic>(InstrA)) { | |
|
Jim Stichnoth
2016/05/19 01:35:49
if (auto *A = llvm::dyn_cast<InstArithmetic>(Instr
| |
| 536 auto A = llvm::dyn_cast<InstArithmetic>(InstrA); | |
|
Jim Stichnoth
2016/05/19 01:35:49
auto *A
auto *B
| |
| 537 auto B = llvm::dyn_cast<InstArithmetic>(InstrB); | |
|
Jim Stichnoth
2016/05/19 01:35:50
use llvm::cast<> instead of llvm::dyn_cast<> here.
| |
| 538 Result = Result && (A->getOp() == B->getOp()); | |
| 539 } | |
| 540 // Does not enter loop if different kind or number of operands | |
| 541 for (unsigned int i = 0; i < InstrA->getSrcSize() && Result; ++i) { | |
|
Jim Stichnoth
2016/05/19 01:35:49
SizeT i
| |
| 542 Result = Result && (InstrA->getSrc(i) == InstrB->getSrc(i)); | |
|
Jim Stichnoth
2016/05/19 01:35:48
Be aware that Operand* pointer equality is fine wi
manasijm
2016/05/19 02:01:52
Or just returning false if they are not Constant*
| |
| 543 } | |
| 544 return Result; | |
| 545 } | |
| 546 }; | |
| 547 struct VariableHash { | |
| 548 size_t operator()(Variable *Var) const { | |
|
Jim Stichnoth
2016/05/19 01:35:49
const Variable *
?
| |
| 549 return std::hash<uint32_t>()(Var->getIndex()); | |
|
Jim Stichnoth
2016/05/19 01:35:49
Can this be SizeT instead of uint32_t?
| |
| 550 } | |
| 551 }; | |
| 552 for (CfgNode *Node : getNodes()) { | |
| 553 std::unordered_map<Inst *, Variable *, InstHash, InstEq, | |
|
Jim Stichnoth
2016/05/19 01:35:49
You should be able to do:
CfgUnorderedMap<Inst *,
| |
| 554 CfgLocalAllocator<std::pair<Inst *const, Variable *>>> | |
| 555 Seen; | |
| 556 // This could be converted to an unordered_set without much effort. | |
|
Jim Stichnoth
2016/05/19 01:35:48
If that's true, and reasonable, then just do it?
Y
| |
| 557 std::unordered_map< | |
| 558 Variable *, Variable *, VariableHash, std::equal_to<Variable *>, | |
| 559 CfgLocalAllocator<std::pair<Variable *const, Variable *>>> Replacements; | |
| 560 // Combining the above two into a single data structure | |
|
Jim Stichnoth
2016/05/19 01:35:50
Reflow comment to 80-col
| |
| 561 // might consume less memory but will be slower | |
| 562 // i.e map of Instruction -> Vector/Set of Variables | |
| 563 std::unordered_map< | |
| 564 Variable *, std::vector<Inst *>, VariableHash, | |
| 565 std::equal_to<Variable *>, | |
| 566 CfgLocalAllocator<std::pair<Variable *const, std::vector<Inst *>>>> | |
| 567 Dependency; | |
| 568 // Not necessary for SSA, still keeping it in case this pass is | |
|
Jim Stichnoth
2016/05/19 01:35:50
reflow comment
| |
| 569 // not run at the beginning. Remove to improve performace. | |
| 570 | |
| 571 for (Inst &Instr : Node->getInsts()) { | |
| 572 if (Instr.isDeleted() || !llvm::isa<InstArithmetic>(&Instr)) | |
| 573 continue; | |
| 574 | |
| 575 auto Iter = Replacements.find(Instr.getDest()); | |
| 576 if (Iter != Replacements.end()) { | |
| 577 Replacements.erase(Iter); | |
| 578 } | |
| 579 | |
| 580 auto DIter = Dependency.find(Instr.getDest()); | |
| 581 if (DIter != Dependency.end()) { | |
| 582 for (auto Dep : DIter->second) { | |
| 583 Seen.erase(Dep); | |
| 584 } | |
| 585 } | |
| 586 | |
| 587 // replace - doing this before checking for repitions | |
|
Jim Stichnoth
2016/05/19 01:35:49
repetitions
and reflow to 80-col
| |
| 588 // might enable more optimizations | |
| 589 for (unsigned int i = 0; i < Instr.getSrcSize(); ++i) { | |
|
Jim Stichnoth
2016/05/19 01:35:48
SizeT
| |
| 590 Operand *Opr = Instr.getSrc(i); | |
| 591 if (Variable *const Var = llvm::dyn_cast<Variable>(Opr)) { | |
|
Jim Stichnoth
2016/05/19 01:35:48
auto *
| |
| 592 if (Replacements.find(Var) != Replacements.end()) { | |
| 593 Instr.replaceSource(i, Replacements[Var]); | |
| 594 } | |
| 595 } | |
| 596 } | |
| 597 | |
| 598 // check for repititions | |
|
Jim Stichnoth
2016/05/19 01:35:48
repetitions
manasijm
2016/05/19 02:01:53
typo, will update on next patchset.
manasijm
2016/05/19 17:50:16
Done.
| |
| 599 | |
| 600 if (Seen.find(&Instr) != Seen.end()) { // seen before | |
| 601 Replacements[Instr.getDest()] = Seen[&Instr]; | |
| 602 // Instr.setDeleted(); | |
|
Jim Stichnoth
2016/05/19 01:35:49
remove commented-out line
manasijm
2016/05/19 17:50:16
Done.
| |
| 603 } else { // new | |
| 604 Seen[&Instr] = Instr.getDest(); | |
| 605 | |
| 606 for (unsigned int i = 0; i < Instr.getSrcSize(); ++i) { | |
|
Jim Stichnoth
2016/05/19 01:35:49
SizeT
manasijm
2016/05/19 17:50:16
Done.
| |
| 607 Operand *Opr = Instr.getSrc(i); | |
| 608 if (Variable *Var = llvm::dyn_cast<Variable>(Opr)) { | |
|
Jim Stichnoth
2016/05/19 01:35:49
auto *Var
manasijm
2016/05/19 17:50:16
Done.
| |
| 609 Dependency[Var].push_back(&Instr); | |
| 610 } | |
| 611 } | |
| 612 } | |
| 613 } | |
| 614 } | |
| 615 } | |
| 616 | |
| 510 void Cfg::doArgLowering() { | 617 void Cfg::doArgLowering() { |
| 511 TimerMarker T(TimerStack::TT_doArgLowering, this); | 618 TimerMarker T(TimerStack::TT_doArgLowering, this); |
| 512 getTarget()->lowerArguments(); | 619 getTarget()->lowerArguments(); |
| 513 } | 620 } |
| 514 | 621 |
| 515 void Cfg::sortAndCombineAllocas(CfgVector<Inst *> &Allocas, | 622 void Cfg::sortAndCombineAllocas(CfgVector<Inst *> &Allocas, |
| 516 uint32_t CombinedAlignment, InstList &Insts, | 623 uint32_t CombinedAlignment, InstList &Insts, |
| 517 AllocaBaseVariableType BaseVariableType) { | 624 AllocaBaseVariableType BaseVariableType) { |
| 518 if (Allocas.empty()) | 625 if (Allocas.empty()) |
| 519 return; | 626 return; |
| (...skipping 958 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1478 } | 1585 } |
| 1479 } | 1586 } |
| 1480 // Print each basic block | 1587 // Print each basic block |
| 1481 for (CfgNode *Node : Nodes) | 1588 for (CfgNode *Node : Nodes) |
| 1482 Node->dump(this); | 1589 Node->dump(this); |
| 1483 if (isVerbose(IceV_Instructions)) | 1590 if (isVerbose(IceV_Instructions)) |
| 1484 Str << "}\n"; | 1591 Str << "}\n"; |
| 1485 } | 1592 } |
| 1486 | 1593 |
| 1487 } // end of namespace Ice | 1594 } // end of namespace Ice |
| OLD | NEW |