Index: src/IceCfg.cpp |
diff --git a/src/IceCfg.cpp b/src/IceCfg.cpp |
index a113b95d47948ddd03c1bbe7bd864c2aa3642bd5..e21ff1be7e069f675dc0a9cd4c94582d4b6e863e 100644 |
--- a/src/IceCfg.cpp |
+++ b/src/IceCfg.cpp |
@@ -640,6 +640,69 @@ void Cfg::localCSE() { |
} |
} |
+void Cfg::shortCircuitJumps() { |
+ // Split Nodes whenever an early jump is possible. |
+ // __N : |
+ // a = <something> |
+ // Instruction 1 without side effect |
+ // ... b = <something> ... |
+ // Instruction N without side effect |
+ // t1 = or a b |
+ // br t1 __X __Y |
+ // |
+ // is transformed into: |
+ // __N : |
+ // a = <something> |
+ // br a __X __N_ext |
+ // |
+ // __N_ext : |
+ // Instruction 1 without side effect |
+ // ... b = <something> ... |
+ // Instruction N without side effect |
+ // br b __X __Y |
+ // (Similar logic for AND, jump to false instead of true target.) |
+ |
+ TimerMarker T(TimerStack::TT_shortCircuit, this); |
+ getVMetadata()->init(VMK_Uses); |
+ auto NodeStack = this->getNodes(); |
+ CfgUnorderedMap<SizeT, CfgVector<CfgNode *>> Splits; |
+ while (!NodeStack.empty()) { |
+ auto *Node = NodeStack.back(); |
+ NodeStack.pop_back(); |
+ auto NewNode = Node->shortCircuit(); |
+ if (NewNode) { |
+ NodeStack.push_back(NewNode); |
+ NodeStack.push_back(Node); |
+ Splits[Node->getIndex()].push_back(NewNode); |
+ } |
+ } |
+ |
+ // Insert nodes in the right place |
+ NodeList NewList; |
+ NewList.reserve(Nodes.size()); |
+ CfgUnorderedSet<SizeT> Inserted; |
+ for (auto *Node : Nodes) { |
+ if (Inserted.find(Node->getIndex()) != Inserted.end()) |
+ continue; // already inserted |
+ NodeList Stack{Node}; |
+ while (!Stack.empty()) { |
+ auto *Current = Stack.back(); |
+ Stack.pop_back(); |
+ Inserted.insert(Current->getIndex()); |
+ NewList.push_back(Current); |
+ for (auto *Next : Splits[Current->getIndex()]) { |
+ Stack.push_back(Next); |
+ } |
+ } |
+ } |
+ |
+ SizeT NodeIndex = 0; |
+ for (auto *Node : NewList) { |
+ Node->resetIndex(NodeIndex++); |
+ } |
+ Nodes = NewList; |
+} |
+ |
void Cfg::doArgLowering() { |
TimerMarker T(TimerStack::TT_doArgLowering, this); |
getTarget()->lowerArguments(); |