Index: src/compiler/control-reducer.cc |
diff --git a/src/compiler/control-reducer.cc b/src/compiler/control-reducer.cc |
index 1d8310316e7219bdc518fd465c9eab43052b7b43..b5acbb23e7abb6e19d509f6996b37e7930102823 100644 |
--- a/src/compiler/control-reducer.cc |
+++ b/src/compiler/control-reducer.cc |
@@ -16,6 +16,7 @@ namespace compiler { |
enum VisitState { kUnvisited = 0, kOnStack = 1, kRevisit = 2, kVisited = 3 }; |
enum Reachability { kFromStart = 8 }; |
+enum Decision { kFalse, kUnknown, kTrue }; |
#define TRACE(x) \ |
if (FLAG_trace_turbo_reduction) PrintF x |
@@ -340,29 +341,37 @@ class ControlReducerImpl { |
} |
} |
- // Reduce redundant selects. |
- Node* ReduceSelect(Node* const node) { |
- Node* const cond = node->InputAt(0); |
- Node* const tvalue = node->InputAt(1); |
- Node* const fvalue = node->InputAt(2); |
- if (tvalue == fvalue) return tvalue; |
+ // Try to statically fold a condition. |
+ Decision DecideCondition(Node* cond) { |
switch (cond->opcode()) { |
case IrOpcode::kInt32Constant: |
- return Int32Matcher(cond).Is(0) ? fvalue : tvalue; |
+ return Int32Matcher(cond).Is(0) ? kFalse : kTrue; |
case IrOpcode::kInt64Constant: |
- return Int64Matcher(cond).Is(0) ? fvalue : tvalue; |
+ return Int64Matcher(cond).Is(0) ? kFalse : kTrue; |
case IrOpcode::kNumberConstant: |
- return NumberMatcher(cond).Is(0) ? fvalue : tvalue; |
+ return NumberMatcher(cond).Is(0) ? kFalse : kTrue; |
case IrOpcode::kHeapConstant: { |
Handle<Object> object = |
HeapObjectMatcher<Object>(cond).Value().handle(); |
- if (object->IsTrue()) return tvalue; |
- if (object->IsFalse()) return fvalue; |
+ if (object->IsTrue()) return kTrue; |
+ if (object->IsFalse()) return kFalse; |
+ // TODO(turbofan): decide more conditions for heap constants. |
break; |
} |
default: |
break; |
} |
+ return kUnknown; |
+ } |
+ |
+ // Reduce redundant selects. |
+ Node* ReduceSelect(Node* const node) { |
+ Node* const tvalue = node->InputAt(1); |
+ Node* const fvalue = node->InputAt(2); |
+ if (tvalue == fvalue) return tvalue; |
+ Decision result = DecideCondition(node->InputAt(0)); |
+ if (result == kTrue) return tvalue; |
+ if (result == kFalse) return fvalue; |
return node; |
} |
@@ -436,35 +445,11 @@ class ControlReducerImpl { |
// Reduce branches if they have constant inputs. |
Node* ReduceBranch(Node* node) { |
- Node* cond = node->InputAt(0); |
- bool is_true; |
- switch (cond->opcode()) { |
- case IrOpcode::kInt32Constant: |
- is_true = !Int32Matcher(cond).Is(0); |
- break; |
- case IrOpcode::kInt64Constant: |
- is_true = !Int64Matcher(cond).Is(0); |
- break; |
- case IrOpcode::kNumberConstant: |
- is_true = !NumberMatcher(cond).Is(0); |
- break; |
- case IrOpcode::kHeapConstant: { |
- Handle<Object> object = |
- HeapObjectMatcher<Object>(cond).Value().handle(); |
- if (object->IsTrue()) |
- is_true = true; |
- else if (object->IsFalse()) |
- is_true = false; |
- else |
- return node; // TODO(turbofan): fold branches on strings, objects. |
- break; |
- } |
- default: |
- return node; |
- } |
+ Decision result = DecideCondition(node->InputAt(0)); |
+ if (result == kUnknown) return node; |
TRACE(("BranchReduce: #%d:%s = %s\n", node->id(), node->op()->mnemonic(), |
- is_true ? "true" : "false")); |
+ (result == kTrue) ? "true" : "false")); |
// Replace IfTrue and IfFalse projections from this branch. |
Node* control = NodeProperties::GetControlInput(node); |
@@ -473,11 +458,11 @@ class ControlReducerImpl { |
if (to->opcode() == IrOpcode::kIfTrue) { |
TRACE((" IfTrue: #%d:%s\n", to->id(), to->op()->mnemonic())); |
i.UpdateToAndIncrement(NULL); |
- ReplaceNode(to, is_true ? control : dead()); |
+ ReplaceNode(to, (result == kTrue) ? control : dead()); |
} else if (to->opcode() == IrOpcode::kIfFalse) { |
TRACE((" IfFalse: #%d:%s\n", to->id(), to->op()->mnemonic())); |
i.UpdateToAndIncrement(NULL); |
- ReplaceNode(to, is_true ? dead() : control); |
+ ReplaceNode(to, (result == kTrue) ? dead() : control); |
} else { |
++i; |
} |