summaryrefslogtreecommitdiff
path: root/chromium/v8/src/compiler/branch-elimination.cc
diff options
context:
space:
mode:
Diffstat (limited to 'chromium/v8/src/compiler/branch-elimination.cc')
-rw-r--r--chromium/v8/src/compiler/branch-elimination.cc81
1 files changed, 73 insertions, 8 deletions
diff --git a/chromium/v8/src/compiler/branch-elimination.cc b/chromium/v8/src/compiler/branch-elimination.cc
index 2583262c074..ffc149ea5d9 100644
--- a/chromium/v8/src/compiler/branch-elimination.cc
+++ b/chromium/v8/src/compiler/branch-elimination.cc
@@ -4,6 +4,7 @@
#include "src/compiler/branch-elimination.h"
+#include "src/base/small-vector.h"
#include "src/compiler/js-graph.h"
#include "src/compiler/node-properties.h"
#include "src/compiler/simplified-operator.h"
@@ -13,17 +14,17 @@ namespace internal {
namespace compiler {
BranchElimination::BranchElimination(Editor* editor, JSGraph* js_graph,
- Zone* zone)
+ Zone* zone, Phase phase)
: AdvancedReducer(editor),
jsgraph_(js_graph),
node_conditions_(js_graph->graph()->NodeCount(), zone),
reduced_(js_graph->graph()->NodeCount(), zone),
zone_(zone),
- dead_(js_graph->Dead()) {}
+ dead_(js_graph->Dead()),
+ phase_(phase) {}
BranchElimination::~BranchElimination() = default;
-
Reduction BranchElimination::Reduce(Node* node) {
switch (node->opcode()) {
case IrOpcode::kDead:
@@ -52,6 +53,74 @@ Reduction BranchElimination::Reduce(Node* node) {
return NoChange();
}
+void BranchElimination::SimplifyBranchCondition(Node* branch) {
+ // Try to use a phi as a branch condition if the control flow from the branch
+ // is known from previous branches. For example, in the graph below, the
+ // control flow of the second_branch is predictable because the first_branch
+ // use the same branch condition. In such case, create a new phi with constant
+ // inputs and let the second branch use the phi as its branch condition. From
+ // this transformation, more branch folding opportunities would be exposed to
+ // later passes through branch cloning in effect-control-linearizer.
+ //
+ // condition condition
+ // | \ |
+ // | first_branch first_branch
+ // | / \ / \
+ // | / \ / \
+ // |first_true first_false first_true first_false
+ // | \ / \ /
+ // | \ / \ /
+ // | first_merge ==> first_merge
+ // | | |
+ // second_branch 1 0 |
+ // / \ \ / |
+ // / \ phi |
+ // second_true second_false \ |
+ // second_branch
+ // / \
+ // / \
+ // second_true second_false
+ //
+
+ DCHECK_EQ(IrOpcode::kBranch, branch->opcode());
+ Node* merge = NodeProperties::GetControlInput(branch);
+ if (merge->opcode() != IrOpcode::kMerge) return;
+
+ Node* branch_condition = branch->InputAt(0);
+ Node* previous_branch;
+ bool condition_value;
+ Graph* graph = jsgraph()->graph();
+ base::SmallVector<Node*, 2> phi_inputs;
+
+ Node::Inputs inputs = merge->inputs();
+ int input_count = inputs.count();
+ for (int i = 0; i != input_count; ++i) {
+ Node* input = inputs[i];
+ ControlPathConditions from_input = node_conditions_.Get(input);
+ if (!from_input.LookupCondition(branch_condition, &previous_branch,
+ &condition_value))
+ return;
+
+ if (phase_ == kEARLY) {
+ phi_inputs.emplace_back(condition_value ? jsgraph()->TrueConstant()
+ : jsgraph()->FalseConstant());
+ } else {
+ phi_inputs.emplace_back(
+ condition_value
+ ? graph->NewNode(jsgraph()->common()->Int32Constant(1))
+ : graph->NewNode(jsgraph()->common()->Int32Constant(0)));
+ }
+ }
+ phi_inputs.emplace_back(merge);
+ Node* new_phi = graph->NewNode(
+ common()->Phi(phase_ == kEARLY ? MachineRepresentation::kTagged
+ : MachineRepresentation::kWord32,
+ input_count),
+ input_count + 1, &phi_inputs.at(0));
+
+ // Replace the branch condition with the new phi.
+ NodeProperties::ReplaceValueInput(branch, new_phi, 0);
+}
Reduction BranchElimination::ReduceBranch(Node* node) {
Node* condition = node->InputAt(0);
@@ -87,6 +156,7 @@ Reduction BranchElimination::ReduceBranch(Node* node) {
}
return Replace(dead());
}
+ SimplifyBranchCondition(node);
return TakeConditionsFromFirstControl(node);
}
@@ -151,7 +221,6 @@ Reduction BranchElimination::ReduceIf(Node* node, bool is_true_branch) {
return UpdateConditions(node, from_branch, condition, branch, is_true_branch);
}
-
Reduction BranchElimination::ReduceLoop(Node* node) {
// Here we rely on having only reducible loops:
// The loop entry edge always dominates the header, so we can just use
@@ -159,7 +228,6 @@ Reduction BranchElimination::ReduceLoop(Node* node) {
return TakeConditionsFromFirstControl(node);
}
-
Reduction BranchElimination::ReduceMerge(Node* node) {
// Shortcut for the case when we do not know anything about some
// input.
@@ -188,18 +256,15 @@ Reduction BranchElimination::ReduceMerge(Node* node) {
return UpdateConditions(node, conditions);
}
-
Reduction BranchElimination::ReduceStart(Node* node) {
return UpdateConditions(node, {});
}
-
Reduction BranchElimination::ReduceOtherControl(Node* node) {
DCHECK_EQ(1, node->op()->ControlInputCount());
return TakeConditionsFromFirstControl(node);
}
-
Reduction BranchElimination::TakeConditionsFromFirstControl(Node* node) {
// We just propagate the information from the control input (ideally,
// we would only revisit control uses if there is change).