Commit f7db2726 authored by Clemens Hammacher's avatar Clemens Hammacher Committed by Commit Bot

[Liftoff] Avoid implicit returns, return immediately instead

Instead of branching to the end merge of the outermost block, we should
return directly. This often generates shorter and faster code, since
the merge is omitted.

R=titzer@chromium.org

Bug: v8:6600, v8:8423
Change-Id: Id5e92b05d3fbbcdb69e4a8bf48629d6031d85291
Reviewed-on: https://chromium-review.googlesource.com/c/1358411Reviewed-by: 's avatarBen Titzer <titzer@chromium.org>
Commit-Queue: Clemens Hammacher <clemensh@chromium.org>
Cr-Commit-Position: refs/heads/master@{#58129}
parent dca02862
......@@ -495,6 +495,11 @@ class LiftoffCompiler {
}
void FallThruTo(FullDecoder* decoder, Control* c) {
// Liftoff never breaks to the implicit return. It returns directly
// instead. So no need to generate any code for this FallThru.
// TODO(clemensh): Simplify this by removing implicit returns from TF.
if (is_outermost(c, decoder)) return;
if (c->end_merge.reached) {
__ MergeFullStackWith(c->label_state);
} else if (c->is_onearmed_if()) {
......@@ -1077,14 +1082,7 @@ class LiftoffCompiler {
__ cache_state()->stack_state.pop_back();
}
void DoReturn(FullDecoder* decoder, Vector<Value> /*values*/, bool implicit) {
if (implicit) {
DCHECK_EQ(1, decoder->control_depth());
Control* func_block = decoder->control_at(0);
__ bind(func_block->label.get());
__ cache_state()->Steal(func_block->label_state);
TraceCacheState(decoder);
}
void ReturnImpl(FullDecoder* decoder) {
size_t num_returns = decoder->sig_->return_count();
if (num_returns > 1) return unsupported(decoder, "multi-return");
if (num_returns > 0) __ MoveToReturnRegisters(decoder->sig_);
......@@ -1093,6 +1091,16 @@ class LiftoffCompiler {
static_cast<uint32_t>(descriptor_->StackParameterCount()));
}
void DoReturn(FullDecoder* decoder, Vector<Value> /*values*/, bool implicit) {
// Liftoff never breaks to the implicit return. It returns directly
// instead. So we only need to generate return code here if we actually fall
// thru from the function block.
DCHECK_IMPLIES(implicit, decoder->control_depth() == 1);
if (implicit && !decoder->control_at(0)->reachable()) return;
ReturnImpl(decoder);
}
void GetLocal(FullDecoder* decoder, Value* result,
const LocalIndexImmediate<validate>& imm) {
auto& slot = __ cache_state()->stack_state[imm.index];
......@@ -1241,7 +1249,7 @@ class LiftoffCompiler {
__ bind(&cont);
}
void Br(Control* target) {
void BrImpl(Control* target) {
if (!target->br_merge()->reached) {
target->label_state.InitMerge(*__ cache_state(), __ num_locals(),
target->br_merge()->arity);
......@@ -1250,14 +1258,18 @@ class LiftoffCompiler {
__ jmp(target->label.get());
}
void Br(FullDecoder* decoder, Control* target) { Br(target); }
void Br(FullDecoder* decoder, Control* target) { BrImpl(target); }
void BrIf(FullDecoder* decoder, const Value& cond, Control* target) {
Label cont_false;
Register value = __ PopToRegister().gp();
__ emit_cond_jump(kEqual, &cont_false, kWasmI32, value);
Br(target);
if (is_outermost(target, decoder)) {
ReturnImpl(decoder);
} else {
BrImpl(target);
}
__ bind(&cont_false);
}
......@@ -1270,7 +1282,11 @@ class LiftoffCompiler {
__ jmp(label.get());
} else {
__ bind(label.get());
Br(decoder->control_at(br_depth));
if (br_depth == decoder->control_depth() - 1) {
ReturnImpl(decoder);
} else {
BrImpl(decoder->control_at(br_depth));
}
}
}
......@@ -1905,6 +1921,10 @@ class LiftoffCompiler {
#endif
}
bool is_outermost(Control* c, FullDecoder* decoder) {
return c == decoder->control_at(decoder->control_depth() - 1);
}
DISALLOW_IMPLICIT_CONSTRUCTORS(LiftoffCompiler);
};
......
......@@ -2573,10 +2573,11 @@ class WasmFullDecoder : public WasmDecoder<validate> {
for (int i = return_count - 1; i >= 0; --i) {
args_[i] = Pop(i, this->sig_->GetReturn(i));
}
if (!this->ok()) return;
// Simulate that an implicit return morally comes after the current block.
if (implicit && c->end_merge.reached) c->reachability = kReachable;
CALL_INTERFACE_IF_REACHABLE(DoReturn, VectorOf(args_), implicit);
bool reached = c->reachable() || (implicit && c->end_merge.reached);
if (reached) CALL_INTERFACE(DoReturn, VectorOf(args_), implicit);
EndControl();
}
......
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