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 |