Commit d39ba102 authored by Jakob Gruber's avatar Jakob Gruber Committed by Commit Bot

[gasm] Implement ReduceArrayPrototypeReduce using the graph assembler

Very similar to the recent ArrayPrototypeForEach port, this moves the
Reduce reduction, which previously operated directly on the graph, to
graph assembler.

Nothing too interesting here, but it's becoming clearer that we will
need more flexible Branch (multiple merge values) and If (a `break`
mechanism) handling in the future.

Bug: v8:9972
Change-Id: Ic48c85305ba721a9a43c67f7ad13c60da310487e
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/1934329
Commit-Queue: Jakob Gruber <jgruber@chromium.org>
Reviewed-by: 's avatarMichael Stanton <mvstanton@chromium.org>
Reviewed-by: 's avatarGeorg Neis <neis@chromium.org>
Cr-Commit-Position: refs/heads/master@{#65233}
parent dc3a90be
......@@ -1731,10 +1731,10 @@ void EffectControlLinearizer::LowerCheckMaps(Node* node, Node* frame_state) {
Node* map = __ HeapConstant(maps[i]);
Node* check = __ TaggedEqual(value_map, map);
if (i == map_count - 1) {
__ Branch(check, &done, &migrate, IsSafetyCheck::kCriticalSafetyCheck);
__ BranchWithCriticalSafetyCheck(check, &done, &migrate);
} else {
auto next_map = __ MakeLabel();
__ Branch(check, &done, &next_map, IsSafetyCheck::kCriticalSafetyCheck);
__ BranchWithCriticalSafetyCheck(check, &done, &next_map);
__ Bind(&next_map);
}
}
......@@ -1777,7 +1777,7 @@ void EffectControlLinearizer::LowerCheckMaps(Node* node, Node* frame_state) {
frame_state, IsSafetyCheck::kCriticalSafetyCheck);
} else {
auto next_map = __ MakeLabel();
__ Branch(check, &done, &next_map, IsSafetyCheck::kCriticalSafetyCheck);
__ BranchWithCriticalSafetyCheck(check, &done, &next_map);
__ Bind(&next_map);
}
}
......@@ -1799,7 +1799,7 @@ void EffectControlLinearizer::LowerCheckMaps(Node* node, Node* frame_state) {
frame_state, IsSafetyCheck::kCriticalSafetyCheck);
} else {
auto next_map = __ MakeLabel();
__ Branch(check, &done, &next_map, IsSafetyCheck::kCriticalSafetyCheck);
__ BranchWithCriticalSafetyCheck(check, &done, &next_map);
__ Bind(&next_map);
}
}
......@@ -1824,7 +1824,7 @@ Node* EffectControlLinearizer::LowerCompareMaps(Node* node) {
auto next_map = __ MakeLabel();
auto passed = __ MakeLabel();
__ Branch(check, &passed, &next_map, IsSafetyCheck::kCriticalSafetyCheck);
__ BranchWithCriticalSafetyCheck(check, &passed, &next_map);
__ Bind(&passed);
__ Goto(&done, __ Int32Constant(1));
......
......@@ -523,10 +523,19 @@ Node* GraphAssembler::NumberAdd(Node* lhs, Node* rhs) {
return AddNode(graph()->NewNode(simplified()->NumberAdd(), lhs, rhs));
}
Node* GraphAssembler::NumberSubtract(Node* lhs, Node* rhs) {
return AddNode(graph()->NewNode(simplified()->NumberSubtract(), lhs, rhs));
}
Node* GraphAssembler::NumberLessThan(Node* lhs, Node* rhs) {
return AddNode(graph()->NewNode(simplified()->NumberLessThan(), lhs, rhs));
}
Node* GraphAssembler::NumberLessThanOrEqual(Node* lhs, Node* rhs) {
return AddNode(
graph()->NewNode(simplified()->NumberLessThanOrEqual(), lhs, rhs));
}
Node* GraphAssembler::StringSubstring(Node* string, Node* from, Node* to) {
return AddNode(graph()->NewNode(simplified()->StringSubstring(), string, from,
to, effect(), control()));
......@@ -536,6 +545,11 @@ Node* GraphAssembler::ObjectIsCallable(Node* value) {
return AddNode(graph()->NewNode(simplified()->ObjectIsCallable(), value));
}
Node* GraphAssembler::CheckIf(Node* cond, DeoptimizeReason reason) {
return AddNode(graph()->NewNode(simplified()->CheckIf(reason), cond, effect(),
control()));
}
Node* GraphAssembler::NumberIsFloat64Hole(Node* value) {
return AddNode(graph()->NewNode(simplified()->NumberIsFloat64Hole(), value));
}
......@@ -658,50 +672,36 @@ Node* GraphAssembler::DeoptimizeIfNot(DeoptimizeReason reason,
condition, frame_state, effect(), control()));
}
void GraphAssembler::Branch(Node* condition, GraphAssemblerLabel<0u>* if_true,
GraphAssemblerLabel<0u>* if_false,
IsSafetyCheck is_safety_check) {
void GraphAssembler::BranchWithCriticalSafetyCheck(
Node* condition, GraphAssemblerLabel<0u>* if_true,
GraphAssemblerLabel<0u>* if_false) {
BranchHint hint = BranchHint::kNone;
if (if_true->IsDeferred() != if_false->IsDeferred()) {
hint = if_false->IsDeferred() ? BranchHint::kTrue : BranchHint::kFalse;
}
Branch(condition, if_true, if_false, hint, is_safety_check);
BranchImpl(condition, if_true, if_false, hint,
IsSafetyCheck::kCriticalSafetyCheck);
}
void GraphAssembler::Branch(Node* condition, GraphAssemblerLabel<0u>* if_true,
GraphAssemblerLabel<0u>* if_false, BranchHint hint,
IsSafetyCheck is_safety_check) {
DCHECK_NOT_NULL(control());
void GraphAssembler::RecordBranchInBlockUpdater(Node* branch,
Node* if_true_control,
Node* if_false_control,
BasicBlock* if_true_block,
BasicBlock* if_false_block) {
DCHECK_NOT_NULL(block_updater_);
// TODO(9684): Only split the current basic block if the label's target
// block has multiple merges.
BasicBlock* if_true_target = block_updater_->SplitBasicBlock();
BasicBlock* if_false_target = block_updater_->SplitBasicBlock();
Node* branch = graph()->NewNode(common()->Branch(hint, is_safety_check),
condition, control());
block_updater_->AddBranch(branch, if_true_target, if_false_target);
Node* if_true_control = control_ =
graph()->NewNode(common()->IfTrue(), branch);
MergeState(if_true);
block_updater_->AddNode(if_true_control, if_true_target);
block_updater_->AddGoto(if_true_target, if_true_block);
Node* if_false_control = control_ =
graph()->NewNode(common()->IfFalse(), branch);
MergeState(if_false);
if (block_updater_) {
// TODO(9684): Only split the current basic block if the label's target
// block has multiple merges.
BasicBlock* if_true_target = block_updater_->SplitBasicBlock();
BasicBlock* if_false_target = block_updater_->SplitBasicBlock();
block_updater_->AddBranch(branch, if_true_target, if_false_target);
block_updater_->AddNode(if_true_control, if_true_target);
block_updater_->AddGoto(if_true_target, if_true->basic_block());
block_updater_->AddNode(if_false_control, if_false_target);
block_updater_->AddGoto(if_false_target, if_false->basic_block());
}
control_ = nullptr;
effect_ = nullptr;
block_updater_->AddNode(if_false_control, if_false_target);
block_updater_->AddGoto(if_false_target, if_false_block);
}
void GraphAssembler::BindBasicBlock(BasicBlock* block) {
......
......@@ -264,9 +264,12 @@ class V8_EXPORT_PRIVATE GraphAssembler {
Node* NumberMin(Node* lhs, Node* rhs);
Node* NumberMax(Node* lhs, Node* rhs);
Node* NumberLessThan(Node* lhs, Node* rhs);
Node* NumberLessThanOrEqual(Node* lhs, Node* rhs);
Node* NumberAdd(Node* lhs, Node* rhs);
Node* NumberSubtract(Node* lhs, Node* rhs);
Node* StringSubstring(Node* string, Node* from, Node* to);
Node* ObjectIsCallable(Node* value);
Node* CheckIf(Node* cond, DeoptimizeReason reason);
Node* NumberIsFloat64Hole(Node* value);
Node* TypeGuard(Type type, Node* value);
......@@ -306,14 +309,21 @@ class V8_EXPORT_PRIVATE GraphAssembler {
template <typename... Vars>
void Goto(GraphAssemblerLabel<sizeof...(Vars)>* label, Vars...);
void Branch(Node* condition, GraphAssemblerLabel<0u>* if_true,
GraphAssemblerLabel<0u>* if_false, BranchHint hint,
IsSafetyCheck is_safety_check = IsSafetyCheck::kNoSafetyCheck);
// Branch hints in this version are inferred from if_true/if_false deferred
// states.
void Branch(Node* condition, GraphAssemblerLabel<0u>* if_true,
GraphAssemblerLabel<0u>* if_false,
IsSafetyCheck is_safety_check = IsSafetyCheck::kNoSafetyCheck);
// Branch hints are inferred from if_true/if_false deferred states.
void BranchWithCriticalSafetyCheck(Node* condition,
GraphAssemblerLabel<0u>* if_true,
GraphAssemblerLabel<0u>* if_false);
// Branch hints are inferred from if_true/if_false deferred states.
template <typename... Vars>
void Branch(Node* condition, GraphAssemblerLabel<sizeof...(Vars)>* if_true,
GraphAssemblerLabel<sizeof...(Vars)>* if_false, Vars...);
template <typename... Vars>
void BranchWithHint(Node* condition,
GraphAssemblerLabel<sizeof...(Vars)>* if_true,
GraphAssemblerLabel<sizeof...(Vars)>* if_false,
BranchHint hint, Vars...);
// Control helpers.
// {GotoIf(c, l)} is equivalent to {Branch(c, l, templ);Bind(templ)}.
......@@ -374,6 +384,17 @@ class V8_EXPORT_PRIVATE GraphAssembler {
return jsgraph()->simplified();
}
private:
template <typename... Vars>
void BranchImpl(Node* condition,
GraphAssemblerLabel<sizeof...(Vars)>* if_true,
GraphAssemblerLabel<sizeof...(Vars)>* if_false,
BranchHint hint, IsSafetyCheck is_safety_check, Vars...);
void RecordBranchInBlockUpdater(Node* branch, Node* if_true_control,
Node* if_false_control,
BasicBlock* if_true_block,
BasicBlock* if_false_block);
SetOncePointer<Operator const> to_number_operator_;
Zone* temp_zone_;
JSGraph* jsgraph_;
......@@ -490,6 +511,57 @@ void GraphAssembler::Bind(GraphAssemblerLabel<VarCount>* label) {
}
}
template <typename... Vars>
void GraphAssembler::Branch(Node* condition,
GraphAssemblerLabel<sizeof...(Vars)>* if_true,
GraphAssemblerLabel<sizeof...(Vars)>* if_false,
Vars... vars) {
BranchHint hint = BranchHint::kNone;
if (if_true->IsDeferred() != if_false->IsDeferred()) {
hint = if_false->IsDeferred() ? BranchHint::kTrue : BranchHint::kFalse;
}
BranchImpl(condition, if_true, if_false, hint, IsSafetyCheck::kNoSafetyCheck,
vars...);
}
template <typename... Vars>
void GraphAssembler::BranchWithHint(
Node* condition, GraphAssemblerLabel<sizeof...(Vars)>* if_true,
GraphAssemblerLabel<sizeof...(Vars)>* if_false, BranchHint hint,
Vars... vars) {
BranchImpl(condition, if_true, if_false, hint, IsSafetyCheck::kNoSafetyCheck,
vars...);
}
template <typename... Vars>
void GraphAssembler::BranchImpl(Node* condition,
GraphAssemblerLabel<sizeof...(Vars)>* if_true,
GraphAssemblerLabel<sizeof...(Vars)>* if_false,
BranchHint hint, IsSafetyCheck is_safety_check,
Vars... vars) {
DCHECK_NOT_NULL(control());
Node* branch = graph()->NewNode(common()->Branch(hint, is_safety_check),
condition, control());
Node* if_true_control = control_ =
graph()->NewNode(common()->IfTrue(), branch);
MergeState(if_true, vars...);
Node* if_false_control = control_ =
graph()->NewNode(common()->IfFalse(), branch);
MergeState(if_false, vars...);
if (block_updater_) {
RecordBranchInBlockUpdater(branch, if_true_control, if_false_control,
if_true->basic_block(), if_false->basic_block());
}
control_ = nullptr;
effect_ = nullptr;
}
template <typename... Vars>
void GraphAssembler::Goto(GraphAssemblerLabel<sizeof...(Vars)>* label,
Vars... vars) {
......
This diff is collapsed.
......@@ -84,9 +84,9 @@ class V8_EXPORT_PRIVATE JSCallReducer final : public AdvancedReducer {
Reduction ReduceReflectGetPrototypeOf(Node* node);
Reduction ReduceReflectHas(Node* node);
Reduction ReduceArrayForEach(Node* node, const SharedFunctionInfoRef& shared);
enum class ArrayReduceDirection { kLeft, kRight };
Reduction ReduceArrayReduce(Node* node, ArrayReduceDirection direction,
const SharedFunctionInfoRef& shared);
Reduction ReduceArrayReduce(Node* node, const SharedFunctionInfoRef& shared);
Reduction ReduceArrayReduceRight(Node* node,
const SharedFunctionInfoRef& shared);
Reduction ReduceArrayMap(Node* node, const SharedFunctionInfoRef& shared);
Reduction ReduceArrayFilter(Node* node, const SharedFunctionInfoRef& shared);
enum class ArrayFindVariant { kFind, kFindIndex };
......
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