Commit d3db97f8 authored by Clemens Backes's avatar Clemens Backes Committed by V8 LUCI CQ

[codegen] Bring back path for non-sse4.1 and non-avx

The roundss / vroundss instruction is only available on AVX or SSE4_1
hardware. Thus bring back the old code path with much longer code for
such old hardware.

R=tebbi@chromium.org

Bug: chromium:1314363
Change-Id: I79a58627c8b406817330e9f9601234cea28182c1
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3578642Reviewed-by: 's avatarTobias Tebbi <tebbi@chromium.org>
Commit-Queue: Clemens Backes <clemensb@chromium.org>
Cr-Commit-Position: refs/heads/main@{#79914}
parent 5e431b98
...@@ -2023,23 +2023,52 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction( ...@@ -2023,23 +2023,52 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction(
} }
DCHECK_EQ(2, instr->OutputCount()); DCHECK_EQ(2, instr->OutputCount());
Register success_reg = i.OutputRegister(1); Register success_reg = i.OutputRegister(1);
DoubleRegister rounded = kScratchDoubleReg; if (CpuFeatures::IsSupported(SSE4_1) || CpuFeatures::IsSupported(AVX)) {
if (instr->InputAt(0)->IsFPRegister()) { DoubleRegister rounded = kScratchDoubleReg;
__ Roundss(rounded, i.InputDoubleRegister(0), kRoundToZero); if (instr->InputAt(0)->IsFPRegister()) {
__ Cvttss2siq(output_reg, i.InputDoubleRegister(0)); __ Roundss(rounded, i.InputDoubleRegister(0), kRoundToZero);
__ Cvttss2siq(output_reg, i.InputDoubleRegister(0));
} else {
__ Roundss(rounded, i.InputOperand(0), kRoundToZero);
// Convert {rounded} instead of the input operand, to avoid another
// load.
__ Cvttss2siq(output_reg, rounded);
}
DoubleRegister converted_back = i.TempSimd128Register(0);
__ Cvtqsi2ss(converted_back, output_reg);
// Compare the converted back value to the rounded value, set
// success_reg to 0 if they differ, or 1 on success.
__ Cmpeqss(converted_back, rounded);
__ Movq(success_reg, converted_back);
__ And(success_reg, Immediate(1));
} else { } else {
__ Roundss(rounded, i.InputOperand(0), kRoundToZero); // Less efficient code for non-AVX and non-SSE4_1 CPUs.
// Convert {rounded} instead of the input operand, to avoid another if (instr->InputAt(0)->IsFPRegister()) {
// load. __ Cvttss2siq(i.OutputRegister(), i.InputDoubleRegister(0));
__ Cvttss2siq(output_reg, rounded); } else {
__ Cvttss2siq(i.OutputRegister(), i.InputOperand(0));
}
__ Move(success_reg, 1);
Label done;
Label fail;
__ Move(kScratchDoubleReg, float{INT64_MIN});
if (instr->InputAt(0)->IsFPRegister()) {
__ Ucomiss(kScratchDoubleReg, i.InputDoubleRegister(0));
} else {
__ Ucomiss(kScratchDoubleReg, i.InputOperand(0));
}
// If the input is NaN, then the conversion fails.
__ j(parity_even, &fail, Label::kNear);
// If the input is INT64_MIN, then the conversion succeeds.
__ j(equal, &done, Label::kNear);
__ cmpq(output_reg, Immediate(1));
// If the conversion results in INT64_MIN, but the input was not
// INT64_MIN, then the conversion fails.
__ j(no_overflow, &done, Label::kNear);
__ bind(&fail);
__ Move(success_reg, 0);
__ bind(&done);
} }
DoubleRegister converted_back = i.TempSimd128Register(0);
__ Cvtqsi2ss(converted_back, output_reg);
// Compare the converted back value to the rounded value, set success_reg
// to 0 if they differ, or 1 on success.
__ Cmpeqss(converted_back, rounded);
__ Movq(success_reg, converted_back);
__ And(success_reg, Immediate(1));
break; break;
} }
case kSSEFloat64ToInt64: { case kSSEFloat64ToInt64: {
...@@ -2054,23 +2083,52 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction( ...@@ -2054,23 +2083,52 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction(
} }
DCHECK_EQ(2, instr->OutputCount()); DCHECK_EQ(2, instr->OutputCount());
Register success_reg = i.OutputRegister(1); Register success_reg = i.OutputRegister(1);
DoubleRegister rounded = kScratchDoubleReg; if (CpuFeatures::IsSupported(SSE4_1) || CpuFeatures::IsSupported(AVX)) {
if (instr->InputAt(0)->IsFPRegister()) { DoubleRegister rounded = kScratchDoubleReg;
__ Roundsd(rounded, i.InputDoubleRegister(0), kRoundToZero); if (instr->InputAt(0)->IsFPRegister()) {
__ Cvttsd2siq(output_reg, i.InputDoubleRegister(0)); __ Roundsd(rounded, i.InputDoubleRegister(0), kRoundToZero);
__ Cvttsd2siq(output_reg, i.InputDoubleRegister(0));
} else {
__ Roundsd(rounded, i.InputOperand(0), kRoundToZero);
// Convert {rounded} instead of the input operand, to avoid another
// load.
__ Cvttsd2siq(output_reg, rounded);
}
DoubleRegister converted_back = i.TempSimd128Register(0);
__ Cvtqsi2sd(converted_back, output_reg);
// Compare the converted back value to the rounded value, set
// success_reg to 0 if they differ, or 1 on success.
__ Cmpeqsd(converted_back, rounded);
__ Movq(success_reg, converted_back);
__ And(success_reg, Immediate(1));
} else { } else {
__ Roundsd(rounded, i.InputOperand(0), kRoundToZero); // Less efficient code for non-AVX and non-SSE4_1 CPUs.
// Convert {rounded} instead of the input operand, to avoid another if (instr->InputAt(0)->IsFPRegister()) {
// load. __ Cvttsd2siq(i.OutputRegister(0), i.InputDoubleRegister(0));
__ Cvttsd2siq(output_reg, rounded); } else {
} __ Cvttsd2siq(i.OutputRegister(0), i.InputOperand(0));
DoubleRegister converted_back = i.TempSimd128Register(0); }
__ Cvtqsi2sd(converted_back, output_reg); __ Move(success_reg, 1);
// Compare the converted back value to the rounded value, set success_reg Label done;
// to 0 if they differ, or 1 on success. Label fail;
__ Cmpeqsd(converted_back, rounded); __ Move(kScratchDoubleReg, double{INT64_MIN});
__ Movq(success_reg, converted_back); if (instr->InputAt(0)->IsFPRegister()) {
__ And(success_reg, Immediate(1)); __ Ucomisd(kScratchDoubleReg, i.InputDoubleRegister(0));
} else {
__ Ucomisd(kScratchDoubleReg, i.InputOperand(0));
}
// If the input is NaN, then the conversion fails.
__ j(parity_even, &fail, Label::kNear);
// If the input is INT64_MIN, then the conversion succeeds.
__ j(equal, &done, Label::kNear);
__ cmpq(output_reg, Immediate(1));
// If the conversion results in INT64_MIN, but the input was not
// INT64_MIN, then the conversion fails.
__ j(no_overflow, &done, Label::kNear);
__ bind(&fail);
__ Move(success_reg, 0);
__ bind(&done);
}
break; break;
} }
case kSSEFloat32ToUint64: { case kSSEFloat32ToUint64: {
......
// Copyright 2022 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// Flags: --no-enable-sse4-1
d8.file.execute('test/mjsunit/wasm/wasm-module-builder.js');
const builder = new WasmModuleBuilder();
builder.addFunction(undefined, makeSig([], [kWasmI64]))
.addBody([
...wasmF32Const(11.3), // f32.const
kExprI64SConvertF32, // i64.trunc_f32_s
])
.exportAs('main');
let instance = builder.instantiate();
assertEquals(11n, instance.exports.main());
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