[wasm] Int64Lowering of I64ShrU and I64ShrS on ia32.
I implemented I64ShrU and I64ShrS the same as I64Shl in https://codereview.chromium.org/1756863002 R=titzer@chromium.org Review URL: https://codereview.chromium.org/1768233002 Cr-Commit-Position: refs/heads/master@{#34630}
This commit is contained in:
parent
d7ddd35c29
commit
240b7db9c7
@ -788,6 +788,10 @@ void InstructionSelector::VisitWord32PairShl(Node* node) {
|
||||
Emit(kArmPairLsl, 2, outputs, 3, inputs);
|
||||
}
|
||||
|
||||
void InstructionSelector::VisitWord32PairShr(Node* node) { UNIMPLEMENTED(); }
|
||||
|
||||
void InstructionSelector::VisitWord32PairSar(Node* node) { UNIMPLEMENTED(); }
|
||||
|
||||
void InstructionSelector::VisitWord32Ror(Node* node) {
|
||||
VisitShift(this, node, TryMatchROR);
|
||||
}
|
||||
|
@ -680,12 +680,28 @@ void CodeGenerator::AssembleArchInstruction(Instruction* instr) {
|
||||
__ sar_cl(i.OutputOperand());
|
||||
}
|
||||
break;
|
||||
case kIA32PairShl:
|
||||
case kIA32ShlPair:
|
||||
if (HasImmediateInput(instr, 2)) {
|
||||
__ PairShl(i.InputRegister(1), i.InputRegister(0), i.InputInt6(2));
|
||||
__ ShlPair(i.InputRegister(1), i.InputRegister(0), i.InputInt6(2));
|
||||
} else {
|
||||
// Shift has been loaded into CL by the register allocator.
|
||||
__ PairShl_cl(i.InputRegister(1), i.InputRegister(0));
|
||||
__ ShlPair_cl(i.InputRegister(1), i.InputRegister(0));
|
||||
}
|
||||
break;
|
||||
case kIA32ShrPair:
|
||||
if (HasImmediateInput(instr, 2)) {
|
||||
__ ShrPair(i.InputRegister(1), i.InputRegister(0), i.InputInt6(2));
|
||||
} else {
|
||||
// Shift has been loaded into CL by the register allocator.
|
||||
__ ShrPair_cl(i.InputRegister(1), i.InputRegister(0));
|
||||
}
|
||||
break;
|
||||
case kIA32SarPair:
|
||||
if (HasImmediateInput(instr, 2)) {
|
||||
__ SarPair(i.InputRegister(1), i.InputRegister(0), i.InputInt6(2));
|
||||
} else {
|
||||
// Shift has been loaded into CL by the register allocator.
|
||||
__ SarPair_cl(i.InputRegister(1), i.InputRegister(0));
|
||||
}
|
||||
break;
|
||||
case kIA32Ror:
|
||||
|
@ -29,7 +29,9 @@ namespace compiler {
|
||||
V(IA32Shl) \
|
||||
V(IA32Shr) \
|
||||
V(IA32Sar) \
|
||||
V(IA32PairShl) \
|
||||
V(IA32ShlPair) \
|
||||
V(IA32ShrPair) \
|
||||
V(IA32SarPair) \
|
||||
V(IA32Ror) \
|
||||
V(IA32Lzcnt) \
|
||||
V(IA32Tzcnt) \
|
||||
|
@ -31,7 +31,9 @@ int InstructionScheduler::GetTargetInstructionFlags(
|
||||
case kIA32Shl:
|
||||
case kIA32Shr:
|
||||
case kIA32Sar:
|
||||
case kIA32PairShl:
|
||||
case kIA32ShlPair:
|
||||
case kIA32ShrPair:
|
||||
case kIA32SarPair:
|
||||
case kIA32Ror:
|
||||
case kIA32Lzcnt:
|
||||
case kIA32Tzcnt:
|
||||
|
@ -601,7 +601,49 @@ void InstructionSelector::VisitWord32PairShl(Node* node) {
|
||||
g.DefineAsFixed(node, eax),
|
||||
g.DefineAsFixed(NodeProperties::FindProjection(node, 1), edx)};
|
||||
|
||||
Emit(kIA32PairShl, 2, outputs, 3, inputs);
|
||||
Emit(kIA32ShlPair, 2, outputs, 3, inputs);
|
||||
}
|
||||
|
||||
void InstructionSelector::VisitWord32PairShr(Node* node) {
|
||||
IA32OperandGenerator g(this);
|
||||
|
||||
Node* shift = node->InputAt(2);
|
||||
InstructionOperand shift_operand;
|
||||
if (g.CanBeImmediate(shift)) {
|
||||
shift_operand = g.UseImmediate(shift);
|
||||
} else {
|
||||
shift_operand = g.UseFixed(shift, ecx);
|
||||
}
|
||||
InstructionOperand inputs[] = {g.UseFixed(node->InputAt(0), eax),
|
||||
g.UseFixed(node->InputAt(1), edx),
|
||||
shift_operand};
|
||||
|
||||
InstructionOperand outputs[] = {
|
||||
g.DefineAsFixed(node, eax),
|
||||
g.DefineAsFixed(NodeProperties::FindProjection(node, 1), edx)};
|
||||
|
||||
Emit(kIA32ShrPair, 2, outputs, 3, inputs);
|
||||
}
|
||||
|
||||
void InstructionSelector::VisitWord32PairSar(Node* node) {
|
||||
IA32OperandGenerator g(this);
|
||||
|
||||
Node* shift = node->InputAt(2);
|
||||
InstructionOperand shift_operand;
|
||||
if (g.CanBeImmediate(shift)) {
|
||||
shift_operand = g.UseImmediate(shift);
|
||||
} else {
|
||||
shift_operand = g.UseFixed(shift, ecx);
|
||||
}
|
||||
InstructionOperand inputs[] = {g.UseFixed(node->InputAt(0), eax),
|
||||
g.UseFixed(node->InputAt(1), edx),
|
||||
shift_operand};
|
||||
|
||||
InstructionOperand outputs[] = {
|
||||
g.DefineAsFixed(node, eax),
|
||||
g.DefineAsFixed(NodeProperties::FindProjection(node, 1), edx)};
|
||||
|
||||
Emit(kIA32SarPair, 2, outputs, 3, inputs);
|
||||
}
|
||||
|
||||
void InstructionSelector::VisitWord32Ror(Node* node) {
|
||||
|
@ -1154,6 +1154,14 @@ void InstructionSelector::VisitNode(Node* node) {
|
||||
MarkAsWord32(NodeProperties::FindProjection(node, 0));
|
||||
MarkAsWord32(NodeProperties::FindProjection(node, 1));
|
||||
return VisitWord32PairShl(node);
|
||||
case IrOpcode::kWord32PairShr:
|
||||
MarkAsWord32(NodeProperties::FindProjection(node, 0));
|
||||
MarkAsWord32(NodeProperties::FindProjection(node, 1));
|
||||
return VisitWord32PairShr(node);
|
||||
case IrOpcode::kWord32PairSar:
|
||||
MarkAsWord32(NodeProperties::FindProjection(node, 0));
|
||||
MarkAsWord32(NodeProperties::FindProjection(node, 1));
|
||||
return VisitWord32PairSar(node);
|
||||
default:
|
||||
V8_Fatal(__FILE__, __LINE__, "Unexpected operator #%d:%s @ node #%d",
|
||||
node->opcode(), node->op()->mnemonic(), node->id());
|
||||
@ -1380,6 +1388,10 @@ void InstructionSelector::VisitBitcastInt64ToFloat64(Node* node) {
|
||||
// 32 bit targets do not implement the following instructions.
|
||||
#if V8_TARGET_ARCH_64_BIT
|
||||
void InstructionSelector::VisitWord32PairShl(Node* node) { UNIMPLEMENTED(); }
|
||||
|
||||
void InstructionSelector::VisitWord32PairShr(Node* node) { UNIMPLEMENTED(); }
|
||||
|
||||
void InstructionSelector::VisitWord32PairSar(Node* node) { UNIMPLEMENTED(); }
|
||||
#endif // V8_TARGET_ARCH_64_BIT
|
||||
|
||||
void InstructionSelector::VisitFinishRegion(Node* node) {
|
||||
@ -1460,6 +1472,8 @@ void InstructionSelector::VisitProjection(Node* node) {
|
||||
case IrOpcode::kTryTruncateFloat32ToUint64:
|
||||
case IrOpcode::kTryTruncateFloat64ToUint64:
|
||||
case IrOpcode::kWord32PairShl:
|
||||
case IrOpcode::kWord32PairShr:
|
||||
case IrOpcode::kWord32PairSar:
|
||||
if (ProjectionIndexOf(node->op()) == 0u) {
|
||||
Emit(kArchNop, g.DefineSameAsFirst(node), g.Use(value));
|
||||
} else {
|
||||
|
@ -312,7 +312,51 @@ void Int64Lowering::LowerNode(Node* node) {
|
||||
break;
|
||||
}
|
||||
// kExprI64ShrU:
|
||||
case IrOpcode::kWord64Shr: {
|
||||
// TODO(turbofan): if the shift count >= 32, then we can set the low word
|
||||
// of the output to 0 and just calculate the high word.
|
||||
DCHECK(node->InputCount() == 2);
|
||||
Node* shift = node->InputAt(1);
|
||||
if (HasReplacementLow(shift)) {
|
||||
// We do not have to care about the high word replacement, because
|
||||
// the shift can only be between 0 and 63 anyways.
|
||||
node->ReplaceInput(1, GetReplacementLow(shift));
|
||||
}
|
||||
|
||||
Node* value = node->InputAt(0);
|
||||
node->ReplaceInput(0, GetReplacementLow(value));
|
||||
node->InsertInput(zone(), 1, GetReplacementHigh(value));
|
||||
|
||||
NodeProperties::ChangeOp(node, machine()->Word32PairShr());
|
||||
// We access the additional return values through projections.
|
||||
Node* low_node = graph()->NewNode(common()->Projection(0), node);
|
||||
Node* high_node = graph()->NewNode(common()->Projection(1), node);
|
||||
ReplaceNode(node, low_node, high_node);
|
||||
break;
|
||||
}
|
||||
// kExprI64ShrS:
|
||||
case IrOpcode::kWord64Sar: {
|
||||
// TODO(turbofan): if the shift count >= 32, then we can set the low word
|
||||
// of the output to 0 and just calculate the high word.
|
||||
DCHECK(node->InputCount() == 2);
|
||||
Node* shift = node->InputAt(1);
|
||||
if (HasReplacementLow(shift)) {
|
||||
// We do not have to care about the high word replacement, because
|
||||
// the shift can only be between 0 and 63 anyways.
|
||||
node->ReplaceInput(1, GetReplacementLow(shift));
|
||||
}
|
||||
|
||||
Node* value = node->InputAt(0);
|
||||
node->ReplaceInput(0, GetReplacementLow(value));
|
||||
node->InsertInput(zone(), 1, GetReplacementHigh(value));
|
||||
|
||||
NodeProperties::ChangeOp(node, machine()->Word32PairSar());
|
||||
// We access the additional return values through projections.
|
||||
Node* low_node = graph()->NewNode(common()->Projection(0), node);
|
||||
Node* high_node = graph()->NewNode(common()->Projection(1), node);
|
||||
ReplaceNode(node, low_node, high_node);
|
||||
break;
|
||||
}
|
||||
// kExprI64Eq:
|
||||
case IrOpcode::kWord64Equal: {
|
||||
DCHECK(node->InputCount() == 2);
|
||||
|
@ -196,7 +196,9 @@ MachineRepresentation StackSlotRepresentationOf(Operator const* op) {
|
||||
V(LoadStackPointer, Operator::kNoProperties, 0, 0, 1) \
|
||||
V(LoadFramePointer, Operator::kNoProperties, 0, 0, 1) \
|
||||
V(LoadParentFramePointer, Operator::kNoProperties, 0, 0, 1) \
|
||||
V(Word32PairShl, Operator::kNoProperties, 3, 0, 2)
|
||||
V(Word32PairShl, Operator::kNoProperties, 3, 0, 2) \
|
||||
V(Word32PairShr, Operator::kNoProperties, 3, 0, 2) \
|
||||
V(Word32PairSar, Operator::kNoProperties, 3, 0, 2)
|
||||
|
||||
#define PURE_OPTIONAL_OP_LIST(V) \
|
||||
V(Word32Ctz, Operator::kNoProperties, 1, 0, 1) \
|
||||
|
@ -180,6 +180,8 @@ class MachineOperatorBuilder final : public ZoneObject {
|
||||
const Operator* Word64Equal();
|
||||
|
||||
const Operator* Word32PairShl();
|
||||
const Operator* Word32PairShr();
|
||||
const Operator* Word32PairSar();
|
||||
|
||||
const Operator* Int32Add();
|
||||
const Operator* Int32AddWithOverflow();
|
||||
|
@ -397,6 +397,10 @@ void InstructionSelector::VisitWord32Sar(Node* node) {
|
||||
|
||||
void InstructionSelector::VisitWord32PairShl(Node* node) { UNIMPLEMENTED(); }
|
||||
|
||||
void InstructionSelector::VisitWord32PairShr(Node* node) { UNIMPLEMENTED(); }
|
||||
|
||||
void InstructionSelector::VisitWord32PairSar(Node* node) { UNIMPLEMENTED(); }
|
||||
|
||||
void InstructionSelector::VisitWord32Ror(Node* node) {
|
||||
VisitRRO(this, kMipsRor, node);
|
||||
}
|
||||
|
@ -334,7 +334,9 @@
|
||||
V(LoadParentFramePointer) \
|
||||
V(CheckedLoad) \
|
||||
V(CheckedStore) \
|
||||
V(Word32PairShl)
|
||||
V(Word32PairShl) \
|
||||
V(Word32PairShr) \
|
||||
V(Word32PairSar)
|
||||
|
||||
#define VALUE_OP_LIST(V) \
|
||||
COMMON_OP_LIST(V) \
|
||||
|
@ -723,6 +723,11 @@ void InstructionSelector::VisitWord32Shr(Node* node) {
|
||||
VisitRRO(this, kPPC_ShiftRight32, node, kShift32Imm);
|
||||
}
|
||||
|
||||
#if !V8_TARGET_ARCH_PPC64
|
||||
void InstructionSelector::VisitWord32PairShr(Node* node) { UNIMPLEMENTED(); }
|
||||
|
||||
void InstructionSelector::VisitWord32PairSar(Node* node) { UNIMPLEMENTED(); }
|
||||
#endif
|
||||
|
||||
#if V8_TARGET_ARCH_PPC64
|
||||
void InstructionSelector::VisitWord64Shr(Node* node) {
|
||||
|
@ -327,6 +327,12 @@ class RawMachineAssembler {
|
||||
Node* Word32PairShl(Node* low_word, Node* high_word, Node* shift) {
|
||||
return AddNode(machine()->Word32PairShl(), low_word, high_word, shift);
|
||||
}
|
||||
Node* Word32PairShr(Node* low_word, Node* high_word, Node* shift) {
|
||||
return AddNode(machine()->Word32PairShr(), low_word, high_word, shift);
|
||||
}
|
||||
Node* Word32PairSar(Node* low_word, Node* high_word, Node* shift) {
|
||||
return AddNode(machine()->Word32PairSar(), low_word, high_word, shift);
|
||||
}
|
||||
|
||||
#define INTPTR_BINOP(prefix, name) \
|
||||
Node* IntPtr##name(Node* a, Node* b) { \
|
||||
|
@ -2443,6 +2443,10 @@ Type* Typer::Visitor::TypeCheckedStore(Node* node) {
|
||||
|
||||
Type* Typer::Visitor::TypeWord32PairShl(Node* node) { return Type::Internal(); }
|
||||
|
||||
Type* Typer::Visitor::TypeWord32PairShr(Node* node) { return Type::Internal(); }
|
||||
|
||||
Type* Typer::Visitor::TypeWord32PairSar(Node* node) { return Type::Internal(); }
|
||||
|
||||
// Heap constants.
|
||||
|
||||
|
||||
|
@ -952,6 +952,8 @@ void Verifier::Visitor::Check(Node* node) {
|
||||
case IrOpcode::kFloat64InsertLowWord32:
|
||||
case IrOpcode::kFloat64InsertHighWord32:
|
||||
case IrOpcode::kWord32PairShl:
|
||||
case IrOpcode::kWord32PairShr:
|
||||
case IrOpcode::kWord32PairSar:
|
||||
case IrOpcode::kLoadStackPointer:
|
||||
case IrOpcode::kLoadFramePointer:
|
||||
case IrOpcode::kLoadParentFramePointer:
|
||||
|
@ -511,7 +511,13 @@ Node* WasmGraphBuilder::Binop(wasm::WasmOpcode opcode, Node* left,
|
||||
op = m->Word64Shl();
|
||||
break;
|
||||
// kExprI64ShrU:
|
||||
case wasm::kExprI64ShrU:
|
||||
op = m->Word64Shr();
|
||||
break;
|
||||
// kExprI64ShrS:
|
||||
case wasm::kExprI64ShrS:
|
||||
op = m->Word64Sar();
|
||||
break;
|
||||
// kExprI64Eq:
|
||||
case wasm::kExprI64Eq:
|
||||
op = m->Word64Equal();
|
||||
@ -599,12 +605,6 @@ Node* WasmGraphBuilder::Binop(wasm::WasmOpcode opcode, Node* left,
|
||||
op = m->Uint64Mod();
|
||||
return graph()->NewNode(op, left, right,
|
||||
trap_->ZeroCheck64(kTrapRemByZero, right));
|
||||
case wasm::kExprI64ShrU:
|
||||
op = m->Word64Shr();
|
||||
break;
|
||||
case wasm::kExprI64ShrS:
|
||||
op = m->Word64Sar();
|
||||
break;
|
||||
case wasm::kExprI64Ror:
|
||||
op = m->Word64Ror();
|
||||
break;
|
||||
|
@ -565,6 +565,10 @@ void InstructionSelector::VisitWord32PairShl(Node* node) {
|
||||
Emit(kX87PairShl, 2, outputs, 3, inputs);
|
||||
}
|
||||
|
||||
void InstructionSelector::VisitWord32PairShr(Node* node) { UNIMPLEMENTED(); }
|
||||
|
||||
void InstructionSelector::VisitWord32PairSar(Node* node) { UNIMPLEMENTED(); }
|
||||
|
||||
void InstructionSelector::VisitWord32Ror(Node* node) {
|
||||
VisitShift(this, node, kX87Ror);
|
||||
}
|
||||
|
@ -1068,7 +1068,6 @@ void Assembler::sar_cl(const Operand& dst) {
|
||||
emit_operand(edi, dst);
|
||||
}
|
||||
|
||||
|
||||
void Assembler::sbb(Register dst, const Operand& src) {
|
||||
EnsureSpace ensure_space(this);
|
||||
EMIT(0x1B);
|
||||
@ -1112,15 +1111,6 @@ void Assembler::shl_cl(const Operand& dst) {
|
||||
emit_operand(esp, dst);
|
||||
}
|
||||
|
||||
|
||||
void Assembler::shrd(Register dst, const Operand& src) {
|
||||
EnsureSpace ensure_space(this);
|
||||
EMIT(0x0F);
|
||||
EMIT(0xAD);
|
||||
emit_operand(dst, src);
|
||||
}
|
||||
|
||||
|
||||
void Assembler::shr(const Operand& dst, uint8_t imm8) {
|
||||
EnsureSpace ensure_space(this);
|
||||
DCHECK(is_uint5(imm8)); // illegal shift count
|
||||
@ -1141,6 +1131,21 @@ void Assembler::shr_cl(const Operand& dst) {
|
||||
emit_operand(ebp, dst);
|
||||
}
|
||||
|
||||
void Assembler::shrd(Register dst, Register src, uint8_t shift) {
|
||||
DCHECK(is_uint5(shift));
|
||||
EnsureSpace ensure_space(this);
|
||||
EMIT(0x0F);
|
||||
EMIT(0xAC);
|
||||
emit_operand(dst, Operand(src));
|
||||
EMIT(shift);
|
||||
}
|
||||
|
||||
void Assembler::shrd_cl(const Operand& dst, Register src) {
|
||||
EnsureSpace ensure_space(this);
|
||||
EMIT(0x0F);
|
||||
EMIT(0xAD);
|
||||
emit_operand(src, dst);
|
||||
}
|
||||
|
||||
void Assembler::sub(const Operand& dst, const Immediate& x) {
|
||||
EnsureSpace ensure_space(this);
|
||||
|
@ -738,21 +738,20 @@ class Assembler : public AssemblerBase {
|
||||
|
||||
void sbb(Register dst, const Operand& src);
|
||||
|
||||
void shld(Register dst, Register src, uint8_t shift);
|
||||
void shld_cl(Register dst, Register src);
|
||||
|
||||
void shl(Register dst, uint8_t imm8) { shl(Operand(dst), imm8); }
|
||||
void shl(const Operand& dst, uint8_t imm8);
|
||||
void shl_cl(Register dst) { shl_cl(Operand(dst)); }
|
||||
void shl_cl(const Operand& dst);
|
||||
|
||||
void shrd(Register dst, Register src) { shrd(dst, Operand(src)); }
|
||||
void shrd(Register dst, const Operand& src);
|
||||
void shld(Register dst, Register src, uint8_t shift);
|
||||
void shld_cl(Register dst, Register src);
|
||||
|
||||
void shr(Register dst, uint8_t imm8) { shr(Operand(dst), imm8); }
|
||||
void shr(const Operand& dst, uint8_t imm8);
|
||||
void shr_cl(Register dst) { shr_cl(Operand(dst)); }
|
||||
void shr_cl(const Operand& dst);
|
||||
void shrd(Register dst, Register src, uint8_t shift);
|
||||
void shrd_cl(Register dst, Register src) { shrd_cl(Operand(dst), src); }
|
||||
void shrd_cl(const Operand& dst, Register src);
|
||||
|
||||
void sub(Register dst, const Immediate& imm) { sub(Operand(dst), imm); }
|
||||
void sub(const Operand& dst, const Immediate& x);
|
||||
|
@ -275,7 +275,7 @@ void DoubleToIStub::Generate(MacroAssembler* masm) {
|
||||
Immediate(static_cast<uint32_t>(Double::kSignificandMask >> 32)));
|
||||
__ add(result_reg,
|
||||
Immediate(static_cast<uint32_t>(Double::kHiddenBit >> 32)));
|
||||
__ shrd(result_reg, scratch1);
|
||||
__ shrd_cl(scratch1, result_reg);
|
||||
__ shr_cl(result_reg);
|
||||
__ test(ecx, Immediate(32));
|
||||
__ cmov(not_equal, scratch1, result_reg);
|
||||
|
@ -1484,7 +1484,8 @@ int DisassemblerIA32::InstructionDecode(v8::internal::Vector<char> out_buffer,
|
||||
data += SetCC(data);
|
||||
} else if ((f0byte & 0xF0) == 0x40) {
|
||||
data += CMov(data);
|
||||
} else if (f0byte == 0xA4) {
|
||||
} else if (f0byte == 0xA4 || f0byte == 0xAC) {
|
||||
// shld, shrd
|
||||
data += 2;
|
||||
AppendToBuffer("%s ", f0mnem);
|
||||
int mod, regop, rm;
|
||||
@ -1494,7 +1495,7 @@ int DisassemblerIA32::InstructionDecode(v8::internal::Vector<char> out_buffer,
|
||||
AppendToBuffer("%s,%s,%d", NameOfCPURegister(rm),
|
||||
NameOfCPURegister(regop), static_cast<int>(imm8));
|
||||
} else if (f0byte == 0xAB || f0byte == 0xA5 || f0byte == 0xAD) {
|
||||
// shrd, shld_cl, bts
|
||||
// shrd_cl, shld_cl, bts
|
||||
data += 2;
|
||||
AppendToBuffer("%s ", f0mnem);
|
||||
int mod, regop, rm;
|
||||
|
@ -706,25 +706,69 @@ void MacroAssembler::Cvtui2ss(XMMRegister dst, Register src, Register tmp) {
|
||||
bind(&jmp_return);
|
||||
}
|
||||
|
||||
void MacroAssembler::PairShl(Register dst, Register src, uint8_t shift) {
|
||||
void MacroAssembler::ShlPair(Register high, Register low, uint8_t shift) {
|
||||
if (shift >= 32) {
|
||||
mov(dst, src);
|
||||
shl(dst, shift - 32);
|
||||
xor_(src, src);
|
||||
mov(high, low);
|
||||
shl(high, shift - 32);
|
||||
xor_(low, low);
|
||||
} else {
|
||||
shld(dst, src, shift);
|
||||
shl(src, shift);
|
||||
shld(high, low, shift);
|
||||
shl(low, shift);
|
||||
}
|
||||
}
|
||||
|
||||
void MacroAssembler::PairShl_cl(Register dst, Register src) {
|
||||
shld_cl(dst, src);
|
||||
shl_cl(src);
|
||||
void MacroAssembler::ShlPair_cl(Register high, Register low) {
|
||||
shld_cl(high, low);
|
||||
shl_cl(low);
|
||||
Label done;
|
||||
test(ecx, Immediate(0x20));
|
||||
j(equal, &done, Label::kNear);
|
||||
mov(dst, src);
|
||||
xor_(src, src);
|
||||
mov(high, low);
|
||||
xor_(low, low);
|
||||
bind(&done);
|
||||
}
|
||||
|
||||
void MacroAssembler::ShrPair(Register high, Register low, uint8_t shift) {
|
||||
if (shift >= 32) {
|
||||
mov(low, high);
|
||||
shr(low, shift - 32);
|
||||
xor_(high, high);
|
||||
} else {
|
||||
shrd(high, low, shift);
|
||||
shr(high, shift);
|
||||
}
|
||||
}
|
||||
|
||||
void MacroAssembler::ShrPair_cl(Register high, Register low) {
|
||||
shrd_cl(low, high);
|
||||
shr_cl(high);
|
||||
Label done;
|
||||
test(ecx, Immediate(0x20));
|
||||
j(equal, &done, Label::kNear);
|
||||
mov(low, high);
|
||||
xor_(high, high);
|
||||
bind(&done);
|
||||
}
|
||||
|
||||
void MacroAssembler::SarPair(Register high, Register low, uint8_t shift) {
|
||||
if (shift >= 32) {
|
||||
mov(low, high);
|
||||
sar(low, shift - 32);
|
||||
sar(high, 31);
|
||||
} else {
|
||||
shrd(high, low, shift);
|
||||
sar(high, shift);
|
||||
}
|
||||
}
|
||||
|
||||
void MacroAssembler::SarPair_cl(Register high, Register low) {
|
||||
shrd_cl(low, high);
|
||||
sar_cl(high);
|
||||
Label done;
|
||||
test(ecx, Immediate(0x20));
|
||||
j(equal, &done, Label::kNear);
|
||||
mov(low, high);
|
||||
sar(high, 31);
|
||||
bind(&done);
|
||||
}
|
||||
|
||||
|
@ -374,8 +374,12 @@ class MacroAssembler: public Assembler {
|
||||
|
||||
void Cvtui2ss(XMMRegister dst, Register src, Register tmp);
|
||||
|
||||
void PairShl(Register dst, Register src, uint8_t imm8);
|
||||
void PairShl_cl(Register dst, Register src);
|
||||
void ShlPair(Register high, Register low, uint8_t imm8);
|
||||
void ShlPair_cl(Register high, Register low);
|
||||
void ShrPair(Register high, Register low, uint8_t imm8);
|
||||
void ShrPair_cl(Register high, Register src);
|
||||
void SarPair(Register high, Register low, uint8_t imm8);
|
||||
void SarPair_cl(Register high, Register low);
|
||||
|
||||
// Support for constant splitting.
|
||||
bool IsUnsafeImmediate(const Immediate& x);
|
||||
|
@ -121,7 +121,8 @@ TEST(DisasmIa320) {
|
||||
__ imul(edx, ecx);
|
||||
__ shld(edx, ecx, 10);
|
||||
__ shld_cl(edx, ecx);
|
||||
__ shrd(edx, ecx);
|
||||
__ shrd(edx, ecx, 10);
|
||||
__ shrd_cl(edx, ecx);
|
||||
__ bts(edx, ecx);
|
||||
__ bts(Operand(ebx, ecx, times_4, 0), ecx);
|
||||
__ nop();
|
||||
@ -221,7 +222,7 @@ TEST(DisasmIa320) {
|
||||
__ shl(Operand(ebx, ecx, times_4, 10000), 1);
|
||||
__ shl(Operand(ebx, ecx, times_4, 10000), 6);
|
||||
__ shl_cl(Operand(ebx, ecx, times_4, 10000));
|
||||
__ shrd(edx, Operand(ebx, ecx, times_4, 10000));
|
||||
__ shrd_cl(Operand(ebx, ecx, times_4, 10000), edx);
|
||||
__ shr(edx, 1);
|
||||
__ shr(edx, 7);
|
||||
__ shr_cl(edx);
|
||||
|
@ -85,7 +85,73 @@ TEST(Run_WasmI64Shl) {
|
||||
}
|
||||
#endif
|
||||
// kExprI64ShrU:
|
||||
#if !V8_TARGET_ARCH_MIPS && !V8_TARGET_ARCH_X87 && !V8_TARGET_ARCH_ARM
|
||||
TEST(Run_WasmI64ShrU) {
|
||||
{
|
||||
WasmRunner<int64_t> r(MachineType::Int64(), MachineType::Int64());
|
||||
BUILD(r, WASM_I64_SHR(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)));
|
||||
FOR_UINT64_INPUTS(i) {
|
||||
for (int64_t j = 1; j < 64; j++) {
|
||||
CHECK_EQ(*i >> j, r.Call(*i, j));
|
||||
}
|
||||
}
|
||||
}
|
||||
{
|
||||
WasmRunner<int64_t> r(MachineType::Int64());
|
||||
BUILD(r, WASM_I64_SHR(WASM_GET_LOCAL(0), WASM_I64V_1(0)));
|
||||
FOR_UINT64_INPUTS(i) { CHECK_EQ(*i >> 0, r.Call(*i)); }
|
||||
}
|
||||
{
|
||||
WasmRunner<int64_t> r(MachineType::Int64());
|
||||
BUILD(r, WASM_I64_SHR(WASM_GET_LOCAL(0), WASM_I64V_1(32)));
|
||||
FOR_UINT64_INPUTS(i) { CHECK_EQ(*i >> 32, r.Call(*i)); }
|
||||
}
|
||||
{
|
||||
WasmRunner<int64_t> r(MachineType::Int64());
|
||||
BUILD(r, WASM_I64_SHR(WASM_GET_LOCAL(0), WASM_I64V_1(20)));
|
||||
FOR_UINT64_INPUTS(i) { CHECK_EQ(*i >> 20, r.Call(*i)); }
|
||||
}
|
||||
{
|
||||
WasmRunner<int64_t> r(MachineType::Int64());
|
||||
BUILD(r, WASM_I64_SHR(WASM_GET_LOCAL(0), WASM_I64V_1(40)));
|
||||
FOR_UINT64_INPUTS(i) { CHECK_EQ(*i >> 40, r.Call(*i)); }
|
||||
}
|
||||
}
|
||||
#endif
|
||||
// kExprI64ShrS:
|
||||
#if !V8_TARGET_ARCH_MIPS && !V8_TARGET_ARCH_X87 && !V8_TARGET_ARCH_ARM
|
||||
TEST(Run_WasmI64ShrS) {
|
||||
{
|
||||
WasmRunner<int64_t> r(MachineType::Int64(), MachineType::Int64());
|
||||
BUILD(r, WASM_I64_SAR(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)));
|
||||
FOR_INT64_INPUTS(i) {
|
||||
for (int64_t j = 1; j < 64; j++) {
|
||||
CHECK_EQ(*i >> j, r.Call(*i, j));
|
||||
}
|
||||
}
|
||||
}
|
||||
{
|
||||
WasmRunner<int64_t> r(MachineType::Int64());
|
||||
BUILD(r, WASM_I64_SAR(WASM_GET_LOCAL(0), WASM_I64V_1(0)));
|
||||
FOR_INT64_INPUTS(i) { CHECK_EQ(*i >> 0, r.Call(*i)); }
|
||||
}
|
||||
{
|
||||
WasmRunner<int64_t> r(MachineType::Int64());
|
||||
BUILD(r, WASM_I64_SAR(WASM_GET_LOCAL(0), WASM_I64V_1(32)));
|
||||
FOR_INT64_INPUTS(i) { CHECK_EQ(*i >> 32, r.Call(*i)); }
|
||||
}
|
||||
{
|
||||
WasmRunner<int64_t> r(MachineType::Int64());
|
||||
BUILD(r, WASM_I64_SAR(WASM_GET_LOCAL(0), WASM_I64V_1(20)));
|
||||
FOR_INT64_INPUTS(i) { CHECK_EQ(*i >> 20, r.Call(*i)); }
|
||||
}
|
||||
{
|
||||
WasmRunner<int64_t> r(MachineType::Int64());
|
||||
BUILD(r, WASM_I64_SAR(WASM_GET_LOCAL(0), WASM_I64V_1(40)));
|
||||
FOR_INT64_INPUTS(i) { CHECK_EQ(*i >> 40, r.Call(*i)); }
|
||||
}
|
||||
}
|
||||
#endif
|
||||
// kExprI64Eq:
|
||||
TEST(Run_WasmI64Eq) {
|
||||
WasmRunner<int32_t> r(MachineType::Int64(), MachineType::Int64());
|
||||
|
@ -350,7 +350,37 @@ TEST_F(Int64LoweringTest, Int64Shl) {
|
||||
start(), start()));
|
||||
}
|
||||
// kExprI64ShrU:
|
||||
TEST_F(Int64LoweringTest, Int64ShrU) {
|
||||
LowerGraph(graph()->NewNode(machine()->Word64Shr(), Int64Constant(value(0)),
|
||||
Int64Constant(value(1))),
|
||||
MachineRepresentation::kWord64);
|
||||
|
||||
Capture<Node*> shr;
|
||||
Matcher<Node*> shr_matcher = IsWord32PairShr(
|
||||
IsInt32Constant(low_word_value(0)), IsInt32Constant(high_word_value(0)),
|
||||
IsInt32Constant(low_word_value(1)));
|
||||
|
||||
EXPECT_THAT(graph()->end()->InputAt(1),
|
||||
IsReturn2(IsProjection(0, AllOf(CaptureEq(&shr), shr_matcher)),
|
||||
IsProjection(1, AllOf(CaptureEq(&shr), shr_matcher)),
|
||||
start(), start()));
|
||||
}
|
||||
// kExprI64ShrS:
|
||||
TEST_F(Int64LoweringTest, Int64ShrS) {
|
||||
LowerGraph(graph()->NewNode(machine()->Word64Sar(), Int64Constant(value(0)),
|
||||
Int64Constant(value(1))),
|
||||
MachineRepresentation::kWord64);
|
||||
|
||||
Capture<Node*> sar;
|
||||
Matcher<Node*> sar_matcher = IsWord32PairSar(
|
||||
IsInt32Constant(low_word_value(0)), IsInt32Constant(high_word_value(0)),
|
||||
IsInt32Constant(low_word_value(1)));
|
||||
|
||||
EXPECT_THAT(graph()->end()->InputAt(1),
|
||||
IsReturn2(IsProjection(0, AllOf(CaptureEq(&sar), sar_matcher)),
|
||||
IsProjection(1, AllOf(CaptureEq(&sar), sar_matcher)),
|
||||
start(), start()));
|
||||
}
|
||||
// kExprI64Eq:
|
||||
TEST_F(Int64LoweringTest, Int64Eq) {
|
||||
LowerGraph(graph()->NewNode(machine()->Word64Equal(), Int64Constant(value(0)),
|
||||
|
@ -2113,6 +2113,8 @@ Matcher<Node*> IsLoadFramePointer() {
|
||||
}
|
||||
|
||||
IS_TERNOP_MATCHER(Word32PairShl)
|
||||
IS_TERNOP_MATCHER(Word32PairShr)
|
||||
IS_TERNOP_MATCHER(Word32PairSar)
|
||||
|
||||
#define IS_BINOP_MATCHER(Name) \
|
||||
Matcher<Node*> Is##Name(const Matcher<Node*>& lhs_matcher, \
|
||||
|
@ -361,6 +361,13 @@ Matcher<Node*> IsLoadFramePointer();
|
||||
Matcher<Node*> IsWord32PairShl(const Matcher<Node*>& lhs_matcher,
|
||||
const Matcher<Node*>& mid_matcher,
|
||||
const Matcher<Node*>& rhs_matcher);
|
||||
Matcher<Node*> IsWord32PairShr(const Matcher<Node*>& lhs_matcher,
|
||||
const Matcher<Node*>& mid_matcher,
|
||||
const Matcher<Node*>& rhs_matcher);
|
||||
|
||||
Matcher<Node*> IsWord32PairSar(const Matcher<Node*>& lhs_matcher,
|
||||
const Matcher<Node*>& mid_matcher,
|
||||
const Matcher<Node*>& rhs_matcher);
|
||||
|
||||
} // namespace compiler
|
||||
} // namespace internal
|
||||
|
Loading…
Reference in New Issue
Block a user