Commit ae95f46d authored by Z Nguyen-Huu's avatar Z Nguyen-Huu Committed by V8 LUCI CQ

Use type feedback to improve exponentiation.

With this change, we use Float64Pow for both Smi and Float inputs, also
introduce new speculative operator.

For this PoC
==========================================================
let result = [NaN]; // Avoid HeapNumber-boxing the results.

function slow(){
  for(let i = 0; i < 100000000; i++) {
    result[0] = i ** 2;
  }
}

start = Date.now();
slow();
console.log(Date.now() - start);
==========================================================
Before: 1313
After: 112

Bug: v8:11731
Change-Id: I07a1bde068bef8184b9f556be9d1fe2d6a288705
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2960064
Commit-Queue: Z Nguyen-Huu <duongn@microsoft.com>
Reviewed-by: 's avatarJakob Kummerow <jkummerow@chromium.org>
Reviewed-by: 's avatarGeorg Neis <neis@chromium.org>
Cr-Commit-Position: refs/heads/master@{#75590}
parent 1d9be5dc
......@@ -128,6 +128,8 @@ class JSSpeculativeBinopBuilder final {
}
case IrOpcode::kJSMultiply:
return simplified()->SpeculativeNumberMultiply(hint);
case IrOpcode::kJSExponentiate:
return simplified()->SpeculativeNumberPow(hint);
case IrOpcode::kJSDivide:
return simplified()->SpeculativeNumberDivide(hint);
case IrOpcode::kJSModulus:
......@@ -388,7 +390,8 @@ JSTypeHintLowering::LoweringResult JSTypeHintLowering::ReduceBinaryOperation(
case IrOpcode::kJSSubtract:
case IrOpcode::kJSMultiply:
case IrOpcode::kJSDivide:
case IrOpcode::kJSModulus: {
case IrOpcode::kJSModulus:
case IrOpcode::kJSExponentiate: {
if (Node* node = TryBuildSoftDeopt(
slot, effect, control,
DeoptimizeReason::kInsufficientTypeFeedbackForBinaryOperation)) {
......@@ -406,15 +409,6 @@ JSTypeHintLowering::LoweringResult JSTypeHintLowering::ReduceBinaryOperation(
}
break;
}
case IrOpcode::kJSExponentiate: {
if (Node* node = TryBuildSoftDeopt(
slot, effect, control,
DeoptimizeReason::kInsufficientTypeFeedbackForBinaryOperation)) {
return LoweringResult::Exit(node);
}
// TODO(neis): Introduce a SpeculativeNumberPow operator?
break;
}
default:
UNREACHABLE();
}
......
......@@ -337,6 +337,7 @@
V(SpeculativeNumberAdd) \
V(SpeculativeNumberSubtract) \
V(SpeculativeNumberMultiply) \
V(SpeculativeNumberPow) \
V(SpeculativeNumberDivide) \
V(SpeculativeNumberModulus) \
V(SpeculativeNumberBitwiseAnd) \
......
......@@ -1114,6 +1114,7 @@ Type OperationTyper::NumberPow(Type lhs, Type rhs) {
SPECULATIVE_NUMBER_BINOP(NumberAdd)
SPECULATIVE_NUMBER_BINOP(NumberSubtract)
SPECULATIVE_NUMBER_BINOP(NumberMultiply)
SPECULATIVE_NUMBER_BINOP(NumberPow)
SPECULATIVE_NUMBER_BINOP(NumberDivide)
SPECULATIVE_NUMBER_BINOP(NumberModulus)
SPECULATIVE_NUMBER_BINOP(NumberBitwiseOr)
......
......@@ -1456,6 +1456,7 @@ const Operator* RepresentationChanger::Float64OperatorFor(
return machine()->Float64Max();
case IrOpcode::kNumberMin:
return machine()->Float64Min();
case IrOpcode::kSpeculativeNumberPow:
case IrOpcode::kNumberPow:
return machine()->Float64Pow();
case IrOpcode::kNumberSin:
......
......@@ -2802,6 +2802,15 @@ class RepresentationSelector {
}
return;
}
case IrOpcode::kSpeculativeNumberPow: {
// Checked float64 ** float64 => float64
VisitBinop<T>(node,
UseInfo::CheckedNumberOrOddballAsFloat64(
kDistinguishZeros, FeedbackSource()),
MachineRepresentation::kFloat64, Type::Number());
if (lower<T>()) ChangeToPureOp(node, Float64Op(node));
return;
}
case IrOpcode::kNumberAtan2:
case IrOpcode::kNumberPow: {
VisitBinop<T>(node, UseInfo::TruncatingFloat64(),
......
......@@ -577,6 +577,7 @@ NumberOperationHint NumberOperationHintOf(const Operator* op) {
DCHECK(op->opcode() == IrOpcode::kSpeculativeNumberAdd ||
op->opcode() == IrOpcode::kSpeculativeNumberSubtract ||
op->opcode() == IrOpcode::kSpeculativeNumberMultiply ||
op->opcode() == IrOpcode::kSpeculativeNumberPow ||
op->opcode() == IrOpcode::kSpeculativeNumberDivide ||
op->opcode() == IrOpcode::kSpeculativeNumberModulus ||
op->opcode() == IrOpcode::kSpeculativeNumberShiftLeft ||
......
......@@ -829,6 +829,7 @@ class V8_EXPORT_PRIVATE SimplifiedOperatorBuilder final
const Operator* SpeculativeNumberBitwiseAnd(NumberOperationHint hint);
const Operator* SpeculativeNumberBitwiseOr(NumberOperationHint hint);
const Operator* SpeculativeNumberBitwiseXor(NumberOperationHint hint);
const Operator* SpeculativeNumberPow(NumberOperationHint hint);
const Operator* SpeculativeNumberLessThan(NumberOperationHint hint);
const Operator* SpeculativeNumberLessThanOrEqual(NumberOperationHint hint);
......
......@@ -91,6 +91,7 @@ Reduction TypedOptimization::Reduce(Node* node) {
return ReduceSpeculativeNumberAdd(node);
case IrOpcode::kSpeculativeNumberSubtract:
case IrOpcode::kSpeculativeNumberMultiply:
case IrOpcode::kSpeculativeNumberPow:
case IrOpcode::kSpeculativeNumberDivide:
case IrOpcode::kSpeculativeNumberModulus:
return ReduceSpeculativeNumberBinop(node);
......@@ -769,6 +770,8 @@ const Operator* NumberOpFromSpeculativeNumberOp(
return simplified->NumberSubtract();
case IrOpcode::kSpeculativeNumberMultiply:
return simplified->NumberMultiply();
case IrOpcode::kSpeculativeNumberPow:
return simplified->NumberPow();
case IrOpcode::kSpeculativeNumberDivide:
return simplified->NumberDivide();
case IrOpcode::kSpeculativeNumberModulus:
......
......@@ -64,6 +64,7 @@ class V8_EXPORT_PRIVATE TypedOptimization final
Reduction ReduceToBoolean(Node* node);
Reduction ReduceSpeculativeNumberAdd(Node* node);
Reduction ReduceSpeculativeNumberMultiply(Node* node);
Reduction ReduceSpeculativeNumberPow(Node* node);
Reduction ReduceSpeculativeNumberBinop(Node* node);
Reduction ReduceSpeculativeNumberComparison(Node* node);
......
......@@ -950,6 +950,7 @@ void Verifier::Visitor::Check(Node* node, const AllNodes& all) {
case IrOpcode::kSpeculativeNumberAdd:
case IrOpcode::kSpeculativeNumberSubtract:
case IrOpcode::kSpeculativeNumberMultiply:
case IrOpcode::kSpeculativeNumberPow:
case IrOpcode::kSpeculativeNumberDivide:
case IrOpcode::kSpeculativeNumberModulus:
CheckTypeIs(node, Type::Number());
......
......@@ -446,6 +446,9 @@ TNode<Object> BinaryOpAssembler::Generate_BinaryOperationWithFeedback(
case Operation::kModulus:
result = CallBuiltin(Builtin::kModulus, context(), lhs, rhs);
break;
case Operation::kExponentiate:
result = CallBuiltin(Builtin::kExponentiate, context(), lhs, rhs);
break;
default:
UNREACHABLE();
}
......@@ -576,11 +579,19 @@ TNode<Object> BinaryOpAssembler::Generate_ExponentiateWithFeedback(
TNode<Object> exponent, TNode<UintPtrT> slot_id,
const LazyNode<HeapObject>& maybe_feedback_vector,
UpdateFeedbackMode update_feedback_mode, bool rhs_known_smi) {
// We currently don't optimize exponentiation based on feedback.
TNode<Smi> dummy_feedback = SmiConstant(BinaryOperationFeedback::kAny);
UpdateFeedback(dummy_feedback, maybe_feedback_vector(), slot_id,
update_feedback_mode);
return CallBuiltin(Builtin::kExponentiate, context(), base, exponent);
auto smiFunction = [=](TNode<Smi> base, TNode<Smi> exponent,
TVariable<Smi>* var_type_feedback) {
*var_type_feedback = SmiConstant(BinaryOperationFeedback::kNumber);
return AllocateHeapNumberWithValue(
Float64Pow(SmiToFloat64(base), SmiToFloat64(exponent)));
};
auto floatFunction = [=](TNode<Float64T> base, TNode<Float64T> exponent) {
return Float64Pow(base, exponent);
};
return Generate_BinaryOperationWithFeedback(
context, base, exponent, slot_id, maybe_feedback_vector, smiFunction,
floatFunction, Operation::kExponentiate, update_feedback_mode,
rhs_known_smi);
}
TNode<Object> BinaryOpAssembler::Generate_BitwiseBinaryOpWithOptionalFeedback(
......
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