Commit 677f3d5f authored by svenpanne's avatar svenpanne Committed by Commit bot

Added %_Likely/%_Unlikely intrinsics (special cases of GCC's __builin_expect).

Currently this only sets branch hints, so we get unlikely code "out of
the way", but in the long run the register allocator needs some love
to treat the unlikely code as, well, unlikely. :-)

Review URL: https://codereview.chromium.org/1048063002

Cr-Commit-Position: refs/heads/master@{#27540}
parent a5522eaf
......@@ -5,6 +5,8 @@
#include "src/compiler/js-intrinsic-lowering.h"
#include <stack>
#include "src/compiler/access-builder.h"
#include "src/compiler/js-graph.h"
#include "src/compiler/node-matchers.h"
......@@ -48,6 +50,8 @@ Reduction JSIntrinsicLowering::Reduce(Node* node) {
return ReduceIsSmi(node);
case Runtime::kInlineJSValueGetValue:
return ReduceJSValueGetValue(node);
case Runtime::kInlineLikely:
return ReduceUnLikely(node, BranchHint::kTrue);
case Runtime::kInlineMapGetInstanceType:
return ReduceMapGetInstanceType(node);
case Runtime::kInlineMathClz32:
......@@ -66,6 +70,8 @@ Reduction JSIntrinsicLowering::Reduce(Node* node) {
return ReduceSeqStringGetChar(node, String::TWO_BYTE_ENCODING);
case Runtime::kInlineTwoByteSeqStringSetChar:
return ReduceSeqStringSetChar(node, String::TWO_BYTE_ENCODING);
case Runtime::kInlineUnlikely:
return ReduceUnLikely(node, BranchHint::kFalse);
case Runtime::kInlineValueOf:
return ReduceValueOf(node);
default:
......@@ -293,6 +299,29 @@ Reduction JSIntrinsicLowering::ReduceStringGetLength(Node* node) {
}
Reduction JSIntrinsicLowering::ReduceUnLikely(Node* node, BranchHint hint) {
std::stack<Node*> nodes_to_visit;
nodes_to_visit.push(node);
while (!nodes_to_visit.empty()) {
Node* current = nodes_to_visit.top();
nodes_to_visit.pop();
for (Node* use : current->uses()) {
if (use->opcode() == IrOpcode::kJSToBoolean) {
// We have to "look through" ToBoolean calls.
nodes_to_visit.push(use);
} else if (use->opcode() == IrOpcode::kBranch) {
// Actually set the hint on any branch using the intrinsic node.
use->set_op(common()->Branch(hint));
}
}
}
// Apart from adding hints to branchs nodes, this is the identity function.
Node* value = NodeProperties::GetValueInput(node, 0);
NodeProperties::ReplaceWithValue(node, value);
return Changed(value);
}
Reduction JSIntrinsicLowering::ReduceValueOf(Node* node) {
// if (%_IsSmi(value)) {
// return value;
......
......@@ -5,6 +5,7 @@
#ifndef V8_COMPILER_JS_INTRINSIC_LOWERING_H_
#define V8_COMPILER_JS_INTRINSIC_LOWERING_H_
#include "src/compiler/common-operator.h"
#include "src/compiler/graph-reducer.h"
#include "src/compiler/simplified-operator.h"
......@@ -44,6 +45,7 @@ class JSIntrinsicLowering FINAL : public Reducer {
Reduction ReduceSeqStringGetChar(Node* node, String::Encoding encoding);
Reduction ReduceSeqStringSetChar(Node* node, String::Encoding encoding);
Reduction ReduceStringGetLength(Node* node);
Reduction ReduceUnLikely(Node* node, BranchHint hint);
Reduction ReduceValueOf(Node* node);
Reduction Change(Node* node, const Operator* op);
......
......@@ -12044,6 +12044,17 @@ void HOptimizedGraphBuilder::GenerateMathSqrt(CallRuntime* call) {
}
void HOptimizedGraphBuilder::GenerateLikely(CallRuntime* call) {
DCHECK(call->arguments()->length() == 1);
Visit(call->arguments()->at(0));
}
void HOptimizedGraphBuilder::GenerateUnlikely(CallRuntime* call) {
return GenerateLikely(call);
}
HValue* HOptimizedGraphBuilder::BuildOrderedHashTableHashToBucket(
HValue* hash, HValue* num_buckets) {
HValue* mask = AddUncasted<HSub>(num_buckets, graph()->GetConstant1());
......
......@@ -2200,6 +2200,8 @@ class HOptimizedGraphBuilder : public HGraphBuilder, public AstVisitor {
F(GetFromCache) \
F(NumberToString) \
F(DebugIsActive) \
F(Likely) \
F(Unlikely) \
/* Typed Arrays */ \
F(TypedArrayInitialize) \
F(DataViewInitialize) \
......
......@@ -330,5 +330,17 @@ RUNTIME_FUNCTION(Runtime_IncrementStatsCounter) {
}
return isolate->heap()->undefined_value();
}
RUNTIME_FUNCTION(Runtime_Likely) {
DCHECK(args.length() == 1);
return args[0];
}
RUNTIME_FUNCTION(Runtime_Unlikely) {
DCHECK(args.length() == 1);
return args[0];
}
}
} // namespace v8::internal
......@@ -88,6 +88,8 @@ namespace internal {
F(NotifyContextDisposed, 0, 1) \
F(ThrowIteratorResultNotAnObject, 1, 1) \
F(IncrementStatsCounter, 1, 1) \
F(Likely, 1, 1) \
F(Unlikely, 1, 1) \
\
/* Array join support */ \
F(PushIfAbsent, 2, 1) \
......
......@@ -3,6 +3,7 @@
// found in the LICENSE file.
#include "src/compiler/access-builder.h"
#include "src/compiler/diamond.h"
#include "src/compiler/js-graph.h"
#include "src/compiler/js-intrinsic-lowering.h"
#include "src/compiler/js-operator.h"
......@@ -10,6 +11,7 @@
#include "test/unittests/compiler/node-test-utils.h"
#include "testing/gmock-support.h"
using testing::_;
using testing::AllOf;
using testing::BitEq;
......@@ -242,6 +244,30 @@ TEST_F(JSIntrinsicLoweringTest, InlineJSValueGetValue) {
}
// -----------------------------------------------------------------------------
// %_Likely
TEST_F(JSIntrinsicLoweringTest, Likely) {
Node* const input = Parameter(0);
Node* const context = Parameter(1);
Node* const effect = graph()->start();
Node* const control = graph()->start();
Node* const likely =
graph()->NewNode(javascript()->CallRuntime(Runtime::kInlineLikely, 1),
input, context, effect, control);
Node* const to_boolean =
graph()->NewNode(javascript()->ToBoolean(), likely, context);
Diamond d(graph(), common(), to_boolean);
graph()->SetEnd(graph()->NewNode(common()->End(), d.merge));
ASSERT_EQ(BranchHint::kNone, BranchHintOf(d.branch->op()));
Reduction const r = Reduce(likely);
ASSERT_TRUE(r.Changed());
EXPECT_THAT(r.replacement(), input);
ASSERT_EQ(BranchHint::kTrue, BranchHintOf(d.branch->op()));
}
// -----------------------------------------------------------------------------
// %_MathFloor
......@@ -312,6 +338,30 @@ TEST_F(JSIntrinsicLoweringTest, InlineMathClz32) {
}
// -----------------------------------------------------------------------------
// %_Unlikely
TEST_F(JSIntrinsicLoweringTest, Unlikely) {
Node* const input = Parameter(0);
Node* const context = Parameter(1);
Node* const effect = graph()->start();
Node* const control = graph()->start();
Node* const unlikely =
graph()->NewNode(javascript()->CallRuntime(Runtime::kInlineUnlikely, 1),
input, context, effect, control);
Node* const to_boolean =
graph()->NewNode(javascript()->ToBoolean(), unlikely, context);
Diamond d(graph(), common(), to_boolean);
graph()->SetEnd(graph()->NewNode(common()->End(), d.merge));
ASSERT_EQ(BranchHint::kNone, BranchHintOf(d.branch->op()));
Reduction const r = Reduce(unlikely);
ASSERT_TRUE(r.Changed());
EXPECT_THAT(r.replacement(), input);
ASSERT_EQ(BranchHint::kFalse, BranchHintOf(d.branch->op()));
}
// -----------------------------------------------------------------------------
// %_ValueOf
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment