Commit 4b86e6e3 authored by marija.antic's avatar marija.antic Committed by Commit bot

MIPS: [wasm] Lowering of Int64Shl, Int64Shr, Int64Sar, Int64Add and Int64Sub.

Implementation of turbofan operators Word32PairShl, Word32PairShr,
Word32PairSar, Int32AddPair and Int32SubPair for MIPS.

Port of:
https://codereview.chromium.org/1765973002/
https://codereview.chromium.org/1778893004/
https://codereview.chromium.org/1778493004/
https://codereview.chromium.org/1778893005/
https://codereview.chromium.org/1842013002/

Added tests for Word32PairShr and Word32PairSar in test-run-machops.cc.

BUG=

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

Cr-Commit-Position: refs/heads/master@{#35307}
parent 6ac509de
......@@ -839,6 +839,36 @@ void CodeGenerator::AssembleArchInstruction(Instruction* instr) {
__ sra(i.OutputRegister(), i.InputRegister(0), imm);
}
break;
case kMipsShlPair: {
if (instr->InputAt(2)->IsRegister()) {
__ ShlPair(i.OutputRegister(0), i.OutputRegister(1), i.InputRegister(0),
i.InputRegister(1), i.InputRegister(2));
} else {
uint32_t imm = i.InputOperand(2).immediate();
__ ShlPair(i.OutputRegister(0), i.OutputRegister(1), i.InputRegister(0),
i.InputRegister(1), imm);
}
} break;
case kMipsShrPair: {
if (instr->InputAt(2)->IsRegister()) {
__ ShrPair(i.OutputRegister(0), i.OutputRegister(1), i.InputRegister(0),
i.InputRegister(1), i.InputRegister(2));
} else {
uint32_t imm = i.InputOperand(2).immediate();
__ ShrPair(i.OutputRegister(0), i.OutputRegister(1), i.InputRegister(0),
i.InputRegister(1), imm);
}
} break;
case kMipsSarPair: {
if (instr->InputAt(2)->IsRegister()) {
__ SarPair(i.OutputRegister(0), i.OutputRegister(1), i.InputRegister(0),
i.InputRegister(1), i.InputRegister(2));
} else {
uint32_t imm = i.InputOperand(2).immediate();
__ SarPair(i.OutputRegister(0), i.OutputRegister(1), i.InputRegister(0),
i.InputRegister(1), imm);
}
} break;
case kMipsExt:
__ Ext(i.OutputRegister(), i.InputRegister(0), i.InputInt8(1),
i.InputInt8(2));
......@@ -923,6 +953,14 @@ void CodeGenerator::AssembleArchInstruction(Instruction* instr) {
case kMipsCmpD:
// Psuedo-instruction used for FP cmp/branch. No opcode emitted here.
break;
case kMipsAddPair:
__ AddPair(i.OutputRegister(0), i.OutputRegister(1), i.InputRegister(0),
i.InputRegister(1), i.InputRegister(2), i.InputRegister(3));
break;
case kMipsSubPair:
__ SubPair(i.OutputRegister(0), i.OutputRegister(1), i.InputRegister(0),
i.InputRegister(1), i.InputRegister(2), i.InputRegister(3));
break;
case kMipsMulPair: {
__ Mulu(i.OutputRegister(1), i.OutputRegister(0), i.InputRegister(0),
i.InputRegister(2));
......
......@@ -33,6 +33,9 @@ namespace compiler {
V(MipsShl) \
V(MipsShr) \
V(MipsSar) \
V(MipsShlPair) \
V(MipsShrPair) \
V(MipsSarPair) \
V(MipsExt) \
V(MipsIns) \
V(MipsRor) \
......@@ -59,6 +62,8 @@ namespace compiler {
V(MipsSqrtD) \
V(MipsMaxD) \
V(MipsMinD) \
V(MipsAddPair) \
V(MipsSubPair) \
V(MipsMulPair) \
V(MipsFloat32RoundDown) \
V(MipsFloat32RoundTruncate) \
......
......@@ -395,27 +395,71 @@ void InstructionSelector::VisitWord32Sar(Node* node) {
VisitRRO(this, kMipsSar, node);
}
void InstructionSelector::VisitInt32PairAdd(Node* node) { UNIMPLEMENTED(); }
void InstructionSelector::VisitInt32PairSub(Node* node) { UNIMPLEMENTED(); }
static void VisitInt32PairBinop(InstructionSelector* selector,
InstructionCode opcode, Node* node) {
MipsOperandGenerator g(selector);
void InstructionSelector::VisitInt32PairMul(Node* node) {
MipsOperandGenerator g(this);
// We use UseUniqueRegister here to avoid register sharing with the output
// register.
InstructionOperand inputs[] = {g.UseUniqueRegister(node->InputAt(0)),
g.UseUniqueRegister(node->InputAt(1)),
g.UseUniqueRegister(node->InputAt(2)),
g.UseUniqueRegister(node->InputAt(3))};
InstructionOperand outputs[] = {
g.DefineAsRegister(node),
g.DefineAsRegister(NodeProperties::FindProjection(node, 1))};
Emit(kMipsMulPair, 2, outputs, 4, inputs);
selector->Emit(opcode, 2, outputs, 4, inputs);
}
void InstructionSelector::VisitWord32PairShl(Node* node) { UNIMPLEMENTED(); }
void InstructionSelector::VisitInt32PairAdd(Node* node) {
VisitInt32PairBinop(this, kMipsAddPair, node);
}
void InstructionSelector::VisitWord32PairShr(Node* node) { UNIMPLEMENTED(); }
void InstructionSelector::VisitInt32PairSub(Node* node) {
VisitInt32PairBinop(this, kMipsSubPair, node);
}
void InstructionSelector::VisitWord32PairSar(Node* node) { UNIMPLEMENTED(); }
void InstructionSelector::VisitInt32PairMul(Node* node) {
VisitInt32PairBinop(this, kMipsMulPair, node);
}
// Shared routine for multiple shift operations.
static void VisitWord32PairShift(InstructionSelector* selector,
InstructionCode opcode, Node* node) {
MipsOperandGenerator g(selector);
Int32Matcher m(node->InputAt(2));
InstructionOperand shift_operand;
if (m.HasValue()) {
shift_operand = g.UseImmediate(m.node());
} else {
shift_operand = g.UseUniqueRegister(m.node());
}
// We use UseUniqueRegister here to avoid register sharing with the output
// register.
InstructionOperand inputs[] = {g.UseUniqueRegister(node->InputAt(0)),
g.UseUniqueRegister(node->InputAt(1)),
shift_operand};
InstructionOperand outputs[] = {
g.DefineAsRegister(node),
g.DefineAsRegister(NodeProperties::FindProjection(node, 1))};
selector->Emit(opcode, 2, outputs, 3, inputs);
}
void InstructionSelector::VisitWord32PairShl(Node* node) {
VisitWord32PairShift(this, kMipsShlPair, node);
}
void InstructionSelector::VisitWord32PairShr(Node* node) {
VisitWord32PairShift(this, kMipsShrPair, node);
}
void InstructionSelector::VisitWord32PairSar(Node* node) {
VisitWord32PairShift(this, kMipsSarPair, node);
}
void InstructionSelector::VisitWord32Ror(Node* node) {
VisitRRO(this, kMipsRor, node);
......@@ -999,7 +1043,6 @@ void InstructionSelector::VisitCheckedStore(Node* node) {
namespace {
// Shared routine for multiple compare operations.
static void VisitCompare(InstructionSelector* selector, InstructionCode opcode,
InstructionOperand left, InstructionOperand right,
......
......@@ -1354,6 +1354,252 @@ void MacroAssembler::MultiPopReversedFPU(RegList regs) {
addiu(sp, sp, stack_offset);
}
void MacroAssembler::AddPair(Register dst_low, Register dst_high,
Register left_low, Register left_high,
Register right_low, Register right_high) {
Label no_overflow;
Register kScratchReg = s3;
Register kScratchReg2 = s4;
// Add lower word
Addu(dst_low, left_low, right_low);
Addu(dst_high, left_high, right_high);
// Check for lower word unsigned overflow
Sltu(kScratchReg, dst_low, left_low);
Sltu(kScratchReg2, dst_low, right_low);
Or(kScratchReg, kScratchReg2, kScratchReg);
Branch(&no_overflow, eq, kScratchReg, Operand(zero_reg));
// Increment higher word if there was overflow
Addu(dst_high, dst_high, 0x1);
bind(&no_overflow);
}
void MacroAssembler::SubPair(Register dst_low, Register dst_high,
Register left_low, Register left_high,
Register right_low, Register right_high) {
Label no_overflow;
Register kScratchReg = s3;
// Subtract lower word
Subu(dst_low, left_low, right_low);
Subu(dst_high, left_high, right_high);
// Check for lower word unsigned underflow
Sltu(kScratchReg, left_low, right_low);
Branch(&no_overflow, eq, kScratchReg, Operand(zero_reg));
// Decrement higher word if there was underflow
Subu(dst_high, dst_high, 0x1);
bind(&no_overflow);
}
void MacroAssembler::ShlPair(Register dst_low, Register dst_high,
Register src_low, Register src_high,
Register shift) {
Label less_than_32;
Label zero_shift;
Label word_shift;
Label done;
Register kScratchReg = s3;
And(shift, shift, 0x3F);
li(kScratchReg, 0x20);
Branch(&less_than_32, lt, shift, Operand(kScratchReg));
Branch(&word_shift, eq, shift, Operand(kScratchReg));
// Shift more than 32
Subu(kScratchReg, shift, kScratchReg);
mov(dst_low, zero_reg);
sllv(dst_high, src_low, kScratchReg);
Branch(&done);
// Word shift
bind(&word_shift);
mov(dst_low, zero_reg);
mov(dst_high, src_low);
Branch(&done);
bind(&less_than_32);
// Check if zero shift
Branch(&zero_shift, eq, shift, Operand(zero_reg));
// Shift less than 32
Subu(kScratchReg, kScratchReg, shift);
sllv(dst_high, src_high, shift);
sllv(dst_low, src_low, shift);
srlv(kScratchReg, src_low, kScratchReg);
Or(dst_high, dst_high, kScratchReg);
Branch(&done);
// Zero shift
bind(&zero_shift);
mov(dst_low, src_low);
mov(dst_high, src_high);
bind(&done);
}
void MacroAssembler::ShlPair(Register dst_low, Register dst_high,
Register src_low, Register src_high,
uint32_t shift) {
Register kScratchReg = s3;
shift = shift & 0x3F;
if (shift < 32) {
if (shift == 0) {
mov(dst_low, src_low);
mov(dst_high, src_high);
} else {
sll(dst_high, src_high, shift);
sll(dst_low, src_low, shift);
shift = 32 - shift;
srl(kScratchReg, src_low, shift);
Or(dst_high, dst_high, kScratchReg);
}
} else {
if (shift == 32) {
mov(dst_low, zero_reg);
mov(dst_high, src_low);
} else {
shift = shift - 32;
mov(dst_low, zero_reg);
sll(dst_high, src_low, shift);
}
}
}
void MacroAssembler::ShrPair(Register dst_low, Register dst_high,
Register src_low, Register src_high,
Register shift) {
Label less_than_32;
Label zero_shift;
Label word_shift;
Label done;
Register kScratchReg = s3;
And(shift, shift, 0x3F);
li(kScratchReg, 0x20);
Branch(&less_than_32, lt, shift, Operand(kScratchReg));
Branch(&word_shift, eq, shift, Operand(kScratchReg));
// Shift more than 32
Subu(kScratchReg, shift, kScratchReg);
mov(dst_high, zero_reg);
srlv(dst_low, src_high, kScratchReg);
Branch(&done);
// Word shift
bind(&word_shift);
mov(dst_high, zero_reg);
mov(dst_low, src_high);
Branch(&done);
bind(&less_than_32);
// Check if zero shift
Branch(&zero_shift, eq, shift, Operand(zero_reg));
// Shift less than 32
Subu(kScratchReg, kScratchReg, shift);
srlv(dst_high, src_high, shift);
srlv(dst_low, src_low, shift);
sllv(kScratchReg, src_high, kScratchReg);
Or(dst_low, dst_low, kScratchReg);
Branch(&done);
// Zero shift
bind(&zero_shift);
mov(dst_low, src_low);
mov(dst_high, src_high);
bind(&done);
}
void MacroAssembler::ShrPair(Register dst_low, Register dst_high,
Register src_low, Register src_high,
uint32_t shift) {
Register kScratchReg = s3;
shift = shift & 0x3F;
if (shift < 32) {
if (shift == 0) {
mov(dst_low, src_low);
mov(dst_high, src_high);
} else {
srl(dst_high, src_high, shift);
srl(dst_low, src_low, shift);
shift = 32 - shift;
sll(kScratchReg, src_high, shift);
Or(dst_low, dst_low, kScratchReg);
}
} else {
if (shift == 32) {
mov(dst_high, zero_reg);
mov(dst_low, src_high);
} else {
shift = shift - 32;
mov(dst_high, zero_reg);
srl(dst_low, src_high, shift);
}
}
}
void MacroAssembler::SarPair(Register dst_low, Register dst_high,
Register src_low, Register src_high,
Register shift) {
Label less_than_32;
Label zero_shift;
Label word_shift;
Label done;
Register kScratchReg = s3;
Register kScratchReg2 = s4;
And(shift, shift, 0x3F);
li(kScratchReg, 0x20);
Branch(&less_than_32, lt, shift, Operand(kScratchReg));
Branch(&word_shift, eq, shift, Operand(kScratchReg));
// Shift more than 32
li(kScratchReg2, 0x1F);
Subu(kScratchReg, shift, kScratchReg);
srav(dst_high, src_high, kScratchReg2);
srav(dst_low, src_high, kScratchReg);
Branch(&done);
// Word shift
bind(&word_shift);
li(kScratchReg2, 0x1F);
srav(dst_high, src_high, kScratchReg2);
mov(dst_low, src_high);
Branch(&done);
bind(&less_than_32);
// Check if zero shift
Branch(&zero_shift, eq, shift, Operand(zero_reg));
// Shift less than 32
Subu(kScratchReg, kScratchReg, shift);
srav(dst_high, src_high, shift);
srlv(dst_low, src_low, shift);
sllv(kScratchReg, src_high, kScratchReg);
Or(dst_low, dst_low, kScratchReg);
Branch(&done);
// Zero shift
bind(&zero_shift);
mov(dst_low, src_low);
mov(dst_high, src_high);
bind(&done);
}
void MacroAssembler::SarPair(Register dst_low, Register dst_high,
Register src_low, Register src_high,
uint32_t shift) {
Register kScratchReg = s3;
shift = shift & 0x3F;
if (shift < 32) {
if (shift == 0) {
mov(dst_low, src_low);
mov(dst_high, src_high);
} else {
sra(dst_high, src_high, shift);
srl(dst_low, src_low, shift);
shift = 32 - shift;
sll(kScratchReg, src_high, shift);
Or(dst_low, dst_low, kScratchReg);
}
} else {
if (shift == 32) {
sra(dst_high, src_high, 31);
mov(dst_low, src_high);
} else {
shift = shift - 32;
sra(dst_high, src_high, 31);
sra(dst_low, src_high, shift);
}
}
}
void MacroAssembler::Ext(Register rt,
Register rs,
......
......@@ -809,6 +809,31 @@ class MacroAssembler: public Assembler {
void Ins(Register rt, Register rs, uint16_t pos, uint16_t size);
void Ext(Register rt, Register rs, uint16_t pos, uint16_t size);
// Int64Lowering instructions
void AddPair(Register dst_low, Register dst_high, Register left_low,
Register left_high, Register right_low, Register right_high);
void SubPair(Register dst_low, Register dst_high, Register left_low,
Register left_high, Register right_low, Register right_high);
void ShlPair(Register dst_low, Register dst_high, Register src_low,
Register src_high, Register shift);
void ShlPair(Register dst_low, Register dst_high, Register src_low,
Register src_high, uint32_t shift);
void ShrPair(Register dst_low, Register dst_high, Register src_low,
Register src_high, Register shift);
void ShrPair(Register dst_low, Register dst_high, Register src_low,
Register src_high, uint32_t shift);
void SarPair(Register dst_low, Register dst_high, Register src_low,
Register src_high, Register shift);
void SarPair(Register dst_low, Register dst_high, Register src_low,
Register src_high, uint32_t shift);
// ---------------------------------------------------------------------------
// FPU macros. These do not handle special cases like NaN or +- inf.
......
......@@ -4201,7 +4201,7 @@ uint64_t ToInt64(uint32_t low, uint32_t high) {
return (static_cast<uint64_t>(high) << 32) | static_cast<uint64_t>(low);
}
#if V8_TARGET_ARCH_32_BIT && !V8_TARGET_ARCH_MIPS && !V8_TARGET_ARCH_X87
#if V8_TARGET_ARCH_32_BIT && !V8_TARGET_ARCH_X87
TEST(RunInt32PairAdd) {
BufferedRawMachineAssemblerTester<int32_t> m(
MachineType::Uint32(), MachineType::Uint32(), MachineType::Uint32(),
......@@ -4449,6 +4449,56 @@ TEST(RunWord32PairShlWithSharedInput) {
TestWord32PairShlWithSharedInput(1, 1);
}
TEST(RunWord32PairShr) {
BufferedRawMachineAssemblerTester<int32_t> m(
MachineType::Uint32(), MachineType::Uint32(), MachineType::Uint32());
uint32_t high;
uint32_t low;
Node* PairAdd =
m.Word32PairShr(m.Parameter(0), m.Parameter(1), m.Parameter(2));
m.StoreToPointer(&low, MachineRepresentation::kWord32,
m.Projection(0, PairAdd));
m.StoreToPointer(&high, MachineRepresentation::kWord32,
m.Projection(1, PairAdd));
m.Return(m.Int32Constant(74));
FOR_UINT64_INPUTS(i) {
for (uint32_t j = 0; j < 64; j++) {
m.Call(static_cast<uint32_t>(*i & 0xffffffff),
static_cast<uint32_t>(*i >> 32), j);
CHECK_EQ(*i >> j, ToInt64(low, high));
}
}
}
TEST(RunWord32PairSar) {
BufferedRawMachineAssemblerTester<int32_t> m(
MachineType::Uint32(), MachineType::Uint32(), MachineType::Uint32());
uint32_t high;
uint32_t low;
Node* PairAdd =
m.Word32PairSar(m.Parameter(0), m.Parameter(1), m.Parameter(2));
m.StoreToPointer(&low, MachineRepresentation::kWord32,
m.Projection(0, PairAdd));
m.StoreToPointer(&high, MachineRepresentation::kWord32,
m.Projection(1, PairAdd));
m.Return(m.Int32Constant(74));
FOR_INT64_INPUTS(i) {
for (uint32_t j = 0; j < 64; j++) {
m.Call(static_cast<uint32_t>(*i & 0xffffffff),
static_cast<uint32_t>(*i >> 32), j);
CHECK_EQ(*i >> j, ToInt64(low, high));
}
}
}
#endif
TEST(RunDeadChangeFloat64ToInt32) {
......
......@@ -34,6 +34,12 @@
#define MIPS_OR_X87 false
#endif
#if V8_TARGET_ARCH_X87
#define X87 true
#else
#define X87 false
#endif
#if V8_TARGET_ARCH_MIPS || V8_TARGET_ARCH_X87 || V8_TARGET_ARCH_ARM
#define MIPS_OR_ARM_OR_X87 true
#else
......@@ -47,8 +53,8 @@
V(I64Return, true) \
V(I64Param, true) \
V(I64LoadStore, true) \
V(I64Add, !MIPS_OR_X87) \
V(I64Sub, !MIPS_OR_X87) \
V(I64Add, !X87) \
V(I64Sub, !X87) \
V(I64Mul, !MIPS_OR_X87) \
V(I64DivS, true) \
V(I64DivU, true) \
......@@ -57,9 +63,9 @@
V(I64And, true) \
V(I64Ior, true) \
V(I64Xor, true) \
V(I64Shl, !MIPS_OR_X87) \
V(I64ShrU, !MIPS_OR_X87) \
V(I64ShrS, !MIPS_OR_X87) \
V(I64Shl, !X87) \
V(I64ShrU, !X87) \
V(I64ShrS, !X87) \
V(I64Eq, true) \
V(I64Ne, true) \
V(I64LtS, true) \
......@@ -72,7 +78,7 @@
V(I64GeU, true) \
V(I64Ctz, true) \
V(I64Clz, true) \
V(I64Popcnt, !MIPS_OR_X87) \
V(I64Popcnt, !X87) \
V(I32ConvertI64, true) \
V(I64SConvertF32, true) \
V(I64SConvertF64, true) \
......
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