11cb0ef41Sopenharmony_ci// Copyright 2015 the V8 project authors. All rights reserved. 21cb0ef41Sopenharmony_ci// Use of this source code is governed by a BSD-style license that can be 31cb0ef41Sopenharmony_ci// found in the LICENSE file. 41cb0ef41Sopenharmony_ci 51cb0ef41Sopenharmony_ci#include "src/compiler/control-equivalence.h" 61cb0ef41Sopenharmony_ci#include "src/compiler/node-properties.h" 71cb0ef41Sopenharmony_ci 81cb0ef41Sopenharmony_ci#define TRACE(...) \ 91cb0ef41Sopenharmony_ci do { \ 101cb0ef41Sopenharmony_ci if (FLAG_trace_turbo_ceq) PrintF(__VA_ARGS__); \ 111cb0ef41Sopenharmony_ci } while (false) 121cb0ef41Sopenharmony_ci 131cb0ef41Sopenharmony_cinamespace v8 { 141cb0ef41Sopenharmony_cinamespace internal { 151cb0ef41Sopenharmony_cinamespace compiler { 161cb0ef41Sopenharmony_ci 171cb0ef41Sopenharmony_civoid ControlEquivalence::Run(Node* exit) { 181cb0ef41Sopenharmony_ci if (!Participates(exit) || GetClass(exit) == kInvalidClass) { 191cb0ef41Sopenharmony_ci DetermineParticipation(exit); 201cb0ef41Sopenharmony_ci RunUndirectedDFS(exit); 211cb0ef41Sopenharmony_ci } 221cb0ef41Sopenharmony_ci} 231cb0ef41Sopenharmony_ci 241cb0ef41Sopenharmony_ci 251cb0ef41Sopenharmony_ci// static 261cb0ef41Sopenharmony_ciSTATIC_CONST_MEMBER_DEFINITION const size_t ControlEquivalence::kInvalidClass; 271cb0ef41Sopenharmony_ci 281cb0ef41Sopenharmony_ci 291cb0ef41Sopenharmony_civoid ControlEquivalence::VisitPre(Node* node) { 301cb0ef41Sopenharmony_ci TRACE("CEQ: Pre-visit of #%d:%s\n", node->id(), node->op()->mnemonic()); 311cb0ef41Sopenharmony_ci} 321cb0ef41Sopenharmony_ci 331cb0ef41Sopenharmony_ci 341cb0ef41Sopenharmony_civoid ControlEquivalence::VisitMid(Node* node, DFSDirection direction) { 351cb0ef41Sopenharmony_ci TRACE("CEQ: Mid-visit of #%d:%s\n", node->id(), node->op()->mnemonic()); 361cb0ef41Sopenharmony_ci BracketList& blist = GetBracketList(node); 371cb0ef41Sopenharmony_ci 381cb0ef41Sopenharmony_ci // Remove brackets pointing to this node [line:19]. 391cb0ef41Sopenharmony_ci BracketListDelete(blist, node, direction); 401cb0ef41Sopenharmony_ci 411cb0ef41Sopenharmony_ci // Potentially introduce artificial dependency from start to end. 421cb0ef41Sopenharmony_ci if (blist.empty()) { 431cb0ef41Sopenharmony_ci DCHECK_EQ(kInputDirection, direction); 441cb0ef41Sopenharmony_ci VisitBackedge(node, graph_->end(), kInputDirection); 451cb0ef41Sopenharmony_ci } 461cb0ef41Sopenharmony_ci 471cb0ef41Sopenharmony_ci // Potentially start a new equivalence class [line:37]. 481cb0ef41Sopenharmony_ci BracketListTRACE(blist); 491cb0ef41Sopenharmony_ci Bracket* recent = &blist.back(); 501cb0ef41Sopenharmony_ci if (recent->recent_size != blist.size()) { 511cb0ef41Sopenharmony_ci recent->recent_size = blist.size(); 521cb0ef41Sopenharmony_ci recent->recent_class = NewClassNumber(); 531cb0ef41Sopenharmony_ci } 541cb0ef41Sopenharmony_ci 551cb0ef41Sopenharmony_ci // Assign equivalence class to node. 561cb0ef41Sopenharmony_ci SetClass(node, recent->recent_class); 571cb0ef41Sopenharmony_ci TRACE(" Assigned class number is %zu\n", GetClass(node)); 581cb0ef41Sopenharmony_ci} 591cb0ef41Sopenharmony_ci 601cb0ef41Sopenharmony_ci 611cb0ef41Sopenharmony_civoid ControlEquivalence::VisitPost(Node* node, Node* parent_node, 621cb0ef41Sopenharmony_ci DFSDirection direction) { 631cb0ef41Sopenharmony_ci TRACE("CEQ: Post-visit of #%d:%s\n", node->id(), node->op()->mnemonic()); 641cb0ef41Sopenharmony_ci BracketList& blist = GetBracketList(node); 651cb0ef41Sopenharmony_ci 661cb0ef41Sopenharmony_ci // Remove brackets pointing to this node [line:19]. 671cb0ef41Sopenharmony_ci BracketListDelete(blist, node, direction); 681cb0ef41Sopenharmony_ci 691cb0ef41Sopenharmony_ci // Propagate bracket list up the DFS tree [line:13]. 701cb0ef41Sopenharmony_ci if (parent_node != nullptr) { 711cb0ef41Sopenharmony_ci BracketList& parent_blist = GetBracketList(parent_node); 721cb0ef41Sopenharmony_ci parent_blist.splice(parent_blist.end(), blist); 731cb0ef41Sopenharmony_ci } 741cb0ef41Sopenharmony_ci} 751cb0ef41Sopenharmony_ci 761cb0ef41Sopenharmony_ci 771cb0ef41Sopenharmony_civoid ControlEquivalence::VisitBackedge(Node* from, Node* to, 781cb0ef41Sopenharmony_ci DFSDirection direction) { 791cb0ef41Sopenharmony_ci TRACE("CEQ: Backedge from #%d:%s to #%d:%s\n", from->id(), 801cb0ef41Sopenharmony_ci from->op()->mnemonic(), to->id(), to->op()->mnemonic()); 811cb0ef41Sopenharmony_ci 821cb0ef41Sopenharmony_ci // Push backedge onto the bracket list [line:25]. 831cb0ef41Sopenharmony_ci Bracket bracket = {direction, kInvalidClass, 0, from, to}; 841cb0ef41Sopenharmony_ci GetBracketList(from).push_back(bracket); 851cb0ef41Sopenharmony_ci} 861cb0ef41Sopenharmony_ci 871cb0ef41Sopenharmony_ci 881cb0ef41Sopenharmony_civoid ControlEquivalence::RunUndirectedDFS(Node* exit) { 891cb0ef41Sopenharmony_ci ZoneStack<DFSStackEntry> stack(zone_); 901cb0ef41Sopenharmony_ci DFSPush(stack, exit, nullptr, kInputDirection); 911cb0ef41Sopenharmony_ci VisitPre(exit); 921cb0ef41Sopenharmony_ci 931cb0ef41Sopenharmony_ci while (!stack.empty()) { // Undirected depth-first backwards traversal. 941cb0ef41Sopenharmony_ci DFSStackEntry& entry = stack.top(); 951cb0ef41Sopenharmony_ci Node* node = entry.node; 961cb0ef41Sopenharmony_ci 971cb0ef41Sopenharmony_ci if (entry.direction == kInputDirection) { 981cb0ef41Sopenharmony_ci if (entry.input != node->input_edges().end()) { 991cb0ef41Sopenharmony_ci Edge edge = *entry.input; 1001cb0ef41Sopenharmony_ci Node* input = edge.to(); 1011cb0ef41Sopenharmony_ci ++(entry.input); 1021cb0ef41Sopenharmony_ci if (NodeProperties::IsControlEdge(edge)) { 1031cb0ef41Sopenharmony_ci // Visit next control input. 1041cb0ef41Sopenharmony_ci if (!Participates(input)) continue; 1051cb0ef41Sopenharmony_ci if (GetData(input)->visited) continue; 1061cb0ef41Sopenharmony_ci if (GetData(input)->on_stack) { 1071cb0ef41Sopenharmony_ci // Found backedge if input is on stack. 1081cb0ef41Sopenharmony_ci if (input != entry.parent_node) { 1091cb0ef41Sopenharmony_ci VisitBackedge(node, input, kInputDirection); 1101cb0ef41Sopenharmony_ci } 1111cb0ef41Sopenharmony_ci } else { 1121cb0ef41Sopenharmony_ci // Push input onto stack. 1131cb0ef41Sopenharmony_ci DFSPush(stack, input, node, kInputDirection); 1141cb0ef41Sopenharmony_ci VisitPre(input); 1151cb0ef41Sopenharmony_ci } 1161cb0ef41Sopenharmony_ci } 1171cb0ef41Sopenharmony_ci continue; 1181cb0ef41Sopenharmony_ci } 1191cb0ef41Sopenharmony_ci if (entry.use != node->use_edges().end()) { 1201cb0ef41Sopenharmony_ci // Switch direction to uses. 1211cb0ef41Sopenharmony_ci entry.direction = kUseDirection; 1221cb0ef41Sopenharmony_ci VisitMid(node, kInputDirection); 1231cb0ef41Sopenharmony_ci continue; 1241cb0ef41Sopenharmony_ci } 1251cb0ef41Sopenharmony_ci } 1261cb0ef41Sopenharmony_ci 1271cb0ef41Sopenharmony_ci if (entry.direction == kUseDirection) { 1281cb0ef41Sopenharmony_ci if (entry.use != node->use_edges().end()) { 1291cb0ef41Sopenharmony_ci Edge edge = *entry.use; 1301cb0ef41Sopenharmony_ci Node* use = edge.from(); 1311cb0ef41Sopenharmony_ci ++(entry.use); 1321cb0ef41Sopenharmony_ci if (NodeProperties::IsControlEdge(edge)) { 1331cb0ef41Sopenharmony_ci // Visit next control use. 1341cb0ef41Sopenharmony_ci if (!Participates(use)) continue; 1351cb0ef41Sopenharmony_ci if (GetData(use)->visited) continue; 1361cb0ef41Sopenharmony_ci if (GetData(use)->on_stack) { 1371cb0ef41Sopenharmony_ci // Found backedge if use is on stack. 1381cb0ef41Sopenharmony_ci if (use != entry.parent_node) { 1391cb0ef41Sopenharmony_ci VisitBackedge(node, use, kUseDirection); 1401cb0ef41Sopenharmony_ci } 1411cb0ef41Sopenharmony_ci } else { 1421cb0ef41Sopenharmony_ci // Push use onto stack. 1431cb0ef41Sopenharmony_ci DFSPush(stack, use, node, kUseDirection); 1441cb0ef41Sopenharmony_ci VisitPre(use); 1451cb0ef41Sopenharmony_ci } 1461cb0ef41Sopenharmony_ci } 1471cb0ef41Sopenharmony_ci continue; 1481cb0ef41Sopenharmony_ci } 1491cb0ef41Sopenharmony_ci if (entry.input != node->input_edges().end()) { 1501cb0ef41Sopenharmony_ci // Switch direction to inputs. 1511cb0ef41Sopenharmony_ci entry.direction = kInputDirection; 1521cb0ef41Sopenharmony_ci VisitMid(node, kUseDirection); 1531cb0ef41Sopenharmony_ci continue; 1541cb0ef41Sopenharmony_ci } 1551cb0ef41Sopenharmony_ci } 1561cb0ef41Sopenharmony_ci 1571cb0ef41Sopenharmony_ci // Pop node from stack when done with all inputs and uses. 1581cb0ef41Sopenharmony_ci DCHECK(entry.input == node->input_edges().end()); 1591cb0ef41Sopenharmony_ci DCHECK(entry.use == node->use_edges().end()); 1601cb0ef41Sopenharmony_ci DFSPop(stack, node); 1611cb0ef41Sopenharmony_ci VisitPost(node, entry.parent_node, entry.direction); 1621cb0ef41Sopenharmony_ci } 1631cb0ef41Sopenharmony_ci} 1641cb0ef41Sopenharmony_ci 1651cb0ef41Sopenharmony_civoid ControlEquivalence::DetermineParticipationEnqueue(ZoneQueue<Node*>& queue, 1661cb0ef41Sopenharmony_ci Node* node) { 1671cb0ef41Sopenharmony_ci if (!Participates(node)) { 1681cb0ef41Sopenharmony_ci AllocateData(node); 1691cb0ef41Sopenharmony_ci queue.push(node); 1701cb0ef41Sopenharmony_ci } 1711cb0ef41Sopenharmony_ci} 1721cb0ef41Sopenharmony_ci 1731cb0ef41Sopenharmony_ci 1741cb0ef41Sopenharmony_civoid ControlEquivalence::DetermineParticipation(Node* exit) { 1751cb0ef41Sopenharmony_ci ZoneQueue<Node*> queue(zone_); 1761cb0ef41Sopenharmony_ci DetermineParticipationEnqueue(queue, exit); 1771cb0ef41Sopenharmony_ci while (!queue.empty()) { // Breadth-first backwards traversal. 1781cb0ef41Sopenharmony_ci Node* node = queue.front(); 1791cb0ef41Sopenharmony_ci queue.pop(); 1801cb0ef41Sopenharmony_ci int max = NodeProperties::PastControlIndex(node); 1811cb0ef41Sopenharmony_ci for (int i = NodeProperties::FirstControlIndex(node); i < max; i++) { 1821cb0ef41Sopenharmony_ci DetermineParticipationEnqueue(queue, node->InputAt(i)); 1831cb0ef41Sopenharmony_ci } 1841cb0ef41Sopenharmony_ci } 1851cb0ef41Sopenharmony_ci} 1861cb0ef41Sopenharmony_ci 1871cb0ef41Sopenharmony_ci 1881cb0ef41Sopenharmony_civoid ControlEquivalence::DFSPush(DFSStack& stack, Node* node, Node* from, 1891cb0ef41Sopenharmony_ci DFSDirection dir) { 1901cb0ef41Sopenharmony_ci DCHECK(Participates(node)); 1911cb0ef41Sopenharmony_ci DCHECK(!GetData(node)->visited); 1921cb0ef41Sopenharmony_ci GetData(node)->on_stack = true; 1931cb0ef41Sopenharmony_ci Node::InputEdges::iterator input = node->input_edges().begin(); 1941cb0ef41Sopenharmony_ci Node::UseEdges::iterator use = node->use_edges().begin(); 1951cb0ef41Sopenharmony_ci stack.push({dir, input, use, from, node}); 1961cb0ef41Sopenharmony_ci} 1971cb0ef41Sopenharmony_ci 1981cb0ef41Sopenharmony_ci 1991cb0ef41Sopenharmony_civoid ControlEquivalence::DFSPop(DFSStack& stack, Node* node) { 2001cb0ef41Sopenharmony_ci DCHECK_EQ(stack.top().node, node); 2011cb0ef41Sopenharmony_ci GetData(node)->on_stack = false; 2021cb0ef41Sopenharmony_ci GetData(node)->visited = true; 2031cb0ef41Sopenharmony_ci stack.pop(); 2041cb0ef41Sopenharmony_ci} 2051cb0ef41Sopenharmony_ci 2061cb0ef41Sopenharmony_ci 2071cb0ef41Sopenharmony_civoid ControlEquivalence::BracketListDelete(BracketList& blist, Node* to, 2081cb0ef41Sopenharmony_ci DFSDirection direction) { 2091cb0ef41Sopenharmony_ci // TODO(turbofan): Optimize this to avoid linear search. 2101cb0ef41Sopenharmony_ci for (BracketList::iterator i = blist.begin(); i != blist.end(); /*nop*/) { 2111cb0ef41Sopenharmony_ci if (i->to == to && i->direction != direction) { 2121cb0ef41Sopenharmony_ci TRACE(" BList erased: {%d->%d}\n", i->from->id(), i->to->id()); 2131cb0ef41Sopenharmony_ci i = blist.erase(i); 2141cb0ef41Sopenharmony_ci } else { 2151cb0ef41Sopenharmony_ci ++i; 2161cb0ef41Sopenharmony_ci } 2171cb0ef41Sopenharmony_ci } 2181cb0ef41Sopenharmony_ci} 2191cb0ef41Sopenharmony_ci 2201cb0ef41Sopenharmony_ci 2211cb0ef41Sopenharmony_civoid ControlEquivalence::BracketListTRACE(BracketList& blist) { 2221cb0ef41Sopenharmony_ci if (FLAG_trace_turbo_ceq) { 2231cb0ef41Sopenharmony_ci TRACE(" BList: "); 2241cb0ef41Sopenharmony_ci for (Bracket bracket : blist) { 2251cb0ef41Sopenharmony_ci TRACE("{%d->%d} ", bracket.from->id(), bracket.to->id()); 2261cb0ef41Sopenharmony_ci } 2271cb0ef41Sopenharmony_ci TRACE("\n"); 2281cb0ef41Sopenharmony_ci } 2291cb0ef41Sopenharmony_ci} 2301cb0ef41Sopenharmony_ci 2311cb0ef41Sopenharmony_ci#undef TRACE 2321cb0ef41Sopenharmony_ci 2331cb0ef41Sopenharmony_ci} // namespace compiler 2341cb0ef41Sopenharmony_ci} // namespace internal 2351cb0ef41Sopenharmony_ci} // namespace v8 236