| Index: src/IceCfg.cpp
|
| diff --git a/src/IceCfg.cpp b/src/IceCfg.cpp
|
| index 0bcda2b0525b6e9225e2b61029249e3b6ba26d8b..35b84968aa7a70bdbb426b7b571e7cfca1250c6a 100644
|
| --- a/src/IceCfg.cpp
|
| +++ b/src/IceCfg.cpp
|
| @@ -640,6 +640,103 @@ void Cfg::localCSE() {
|
| }
|
| }
|
|
|
| +void Cfg::loopInvariantCodeMotion() {
|
| + TimerMarker T(TimerStack::TT_loopInvariantCodeMotion, this);
|
| + // Does not introduce new nodes as of now.
|
| + for (auto &Pair : LoopInfo) {
|
| + CfgNode *Header = Nodes[Pair.first];
|
| + assert(Header);
|
| + if (Header->getLoopNestDepth() < 1)
|
| + continue;
|
| + CfgNode *PreHeader = nullptr;
|
| + for (auto *Pred : Header->getInEdges()) {
|
| + if (Pred->getLoopNestDepth() == Header->getLoopNestDepth() - 1) {
|
| + if (PreHeader == nullptr) {
|
| + PreHeader = Pred;
|
| + } else {
|
| + PreHeader = nullptr;
|
| + break;
|
| + // Do not consider cases with two incoming edges.
|
| + // Will require insertion of nodes.
|
| + }
|
| + }
|
| + }
|
| + if (PreHeader == nullptr || PreHeader->getInsts().size() == 0) {
|
| + continue; // to next loop
|
| + }
|
| +
|
| + auto &Insts = PreHeader->getInsts();
|
| + auto &LastInst = Insts.back();
|
| + Insts.pop_back();
|
| +
|
| + for (auto *Inst : findLoopInvariantInstructions(Pair.first)) {
|
| + PreHeader->appendInst(Inst);
|
| + }
|
| + PreHeader->appendInst(&LastInst);
|
| + }
|
| +}
|
| +
|
| +Ice::CfgVector<Inst *>
|
| +Cfg::findLoopInvariantInstructions(Ice::SizeT LoopHeaderIndex) {
|
| + CfgUnorderedSet<Inst *> InvariantInsts;
|
| + CfgUnorderedSet<Variable *> InvariantVars;
|
| + for (auto *Var : getArgs()) {
|
| + InvariantVars.insert(Var);
|
| + }
|
| + bool Changed = false;
|
| + do {
|
| + Changed = false;
|
| + for (auto NodeIndex : LoopInfo[LoopHeaderIndex]) {
|
| + auto *Node = Nodes[NodeIndex];
|
| + CfgVector<std::reference_wrapper<Inst>> Insts(Node->getInsts().begin(),
|
| + Node->getInsts().end());
|
| +
|
| + for (auto &InstRef : Insts) {
|
| + auto &Inst = InstRef.get();
|
| + if (Inst.isDeleted() ||
|
| + InvariantInsts.find(&Inst) != InvariantInsts.end())
|
| + continue;
|
| + switch (Inst.getKind()) {
|
| + case Inst::InstKind::Alloca:
|
| + case Inst::InstKind::Br:
|
| + case Inst::InstKind::Ret:
|
| + case Inst::InstKind::Phi:
|
| + case Inst::InstKind::Call:
|
| + case Inst::InstKind::IntrinsicCall:
|
| + case Inst::InstKind::Load:
|
| + case Inst::InstKind::Store:
|
| + case Inst::InstKind::Switch:
|
| + continue;
|
| + default:
|
| + break;
|
| + }
|
| +
|
| + bool IsInvariant = true;
|
| + for (SizeT i = 0; i < Inst.getSrcSize(); ++i) {
|
| + if (auto *Var = llvm::dyn_cast<Variable>(Inst.getSrc(i))) {
|
| + if (InvariantVars.find(Var) == InvariantVars.end()) {
|
| + IsInvariant = false;
|
| + }
|
| + }
|
| + }
|
| + if (IsInvariant) {
|
| + Changed = true;
|
| + InvariantInsts.insert(&Inst);
|
| + Node->getInsts().remove(Inst);
|
| + if (Inst.getDest() != nullptr) {
|
| + InvariantVars.insert(Inst.getDest());
|
| + }
|
| + }
|
| + }
|
| + }
|
| + } while (Changed);
|
| +
|
| + CfgVector<Inst *> InstVector(InvariantInsts.begin(), InvariantInsts.end());
|
| + std::sort(InstVector.begin(), InstVector.end(),
|
| + [](Inst *A, Inst *B) { return A->getNumber() < B->getNumber(); });
|
| + return InstVector;
|
| +}
|
| +
|
| void Cfg::shortCircuitJumps() {
|
| // Split Nodes whenever an early jump is possible.
|
| // __N :
|
| @@ -1338,10 +1435,9 @@ void Cfg::genFrame() {
|
| getTarget()->addEpilog(Node);
|
| }
|
|
|
| -void Cfg::computeLoopNestDepth() {
|
| +void Cfg::generateLoopInfo() {
|
| TimerMarker T(TimerStack::TT_computeLoopNestDepth, this);
|
| - LoopAnalyzer LA(this);
|
| - LA.computeLoopNestDepth();
|
| + LoopInfo = LoopAnalyzer(this).getLoopInfo();
|
| }
|
|
|
| // This is a lightweight version of live-range-end calculation. Marks the last
|
|
|