Commit c0eee179 authored by Z Nguyen-Huu's avatar Z Nguyen-Huu Committed by Commit Bot

Add bit left-rotation machine operator

ROL will be optional operator as arm, arm64 only have ROR.

The reason for this CL is inefficient Wasm codegen for 64-bit
left-rotation.

Bug: v8:10216
Change-Id: I0cd13e4b6de5276a0d0b80eac5ed9c2e52ba1f96
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2157648
Commit-Queue: Z Nguyen-Huu <duongn@microsoft.com>
Reviewed-by: 's avatarTobias Tebbi <tebbi@chromium.org>
Reviewed-by: 's avatarAndreas Haas <ahaas@chromium.org>
Reviewed-by: 's avatarClemens Backes <clemensb@chromium.org>
Cr-Commit-Position: refs/heads/master@{#67518}
parent 41fbbd12
...@@ -1091,6 +1091,25 @@ void Assembler::rcr(Register dst, uint8_t imm8) { ...@@ -1091,6 +1091,25 @@ void Assembler::rcr(Register dst, uint8_t imm8) {
} }
} }
void Assembler::rol(Operand dst, uint8_t imm8) {
EnsureSpace ensure_space(this);
DCHECK(is_uint5(imm8)); // illegal shift count
if (imm8 == 1) {
EMIT(0xD1);
emit_operand(eax, dst);
} else {
EMIT(0xC1);
emit_operand(eax, dst);
EMIT(imm8);
}
}
void Assembler::rol_cl(Operand dst) {
EnsureSpace ensure_space(this);
EMIT(0xD3);
emit_operand(eax, dst);
}
void Assembler::ror(Operand dst, uint8_t imm8) { void Assembler::ror(Operand dst, uint8_t imm8) {
EnsureSpace ensure_space(this); EnsureSpace ensure_space(this);
DCHECK(is_uint5(imm8)); // illegal shift count DCHECK(is_uint5(imm8)); // illegal shift count
......
...@@ -635,6 +635,11 @@ class V8_EXPORT_PRIVATE Assembler : public AssemblerBase { ...@@ -635,6 +635,11 @@ class V8_EXPORT_PRIVATE Assembler : public AssemblerBase {
void rcl(Register dst, uint8_t imm8); void rcl(Register dst, uint8_t imm8);
void rcr(Register dst, uint8_t imm8); void rcr(Register dst, uint8_t imm8);
void rol(Register dst, uint8_t imm8) { rol(Operand(dst), imm8); }
void rol(Operand dst, uint8_t imm8);
void rol_cl(Register dst) { rol_cl(Operand(dst)); }
void rol_cl(Operand dst);
void ror(Register dst, uint8_t imm8) { ror(Operand(dst), imm8); } void ror(Register dst, uint8_t imm8) { ror(Operand(dst), imm8); }
void ror(Operand dst, uint8_t imm8); void ror(Operand dst, uint8_t imm8);
void ror_cl(Register dst) { ror_cl(Operand(dst)); } void ror_cl(Register dst) { ror_cl(Operand(dst)); }
......
...@@ -1233,6 +1233,8 @@ void InstructionSelector::VisitWord32PairSar(Node* node) { ...@@ -1233,6 +1233,8 @@ void InstructionSelector::VisitWord32PairSar(Node* node) {
VisitWord32PairShift(this, kArmAsrPair, node); VisitWord32PairShift(this, kArmAsrPair, node);
} }
void InstructionSelector::VisitWord32Rol(Node* node) { UNREACHABLE(); }
void InstructionSelector::VisitWord32Ror(Node* node) { void InstructionSelector::VisitWord32Ror(Node* node) {
VisitShift(this, node, TryMatchROR); VisitShift(this, node, TryMatchROR);
} }
......
...@@ -1301,6 +1301,10 @@ void InstructionSelector::VisitWord64Sar(Node* node) { ...@@ -1301,6 +1301,10 @@ void InstructionSelector::VisitWord64Sar(Node* node) {
VisitRRO(this, kArm64Asr, node, kShift64Imm); VisitRRO(this, kArm64Asr, node, kShift64Imm);
} }
void InstructionSelector::VisitWord32Rol(Node* node) { UNREACHABLE(); }
void InstructionSelector::VisitWord64Rol(Node* node) { UNREACHABLE(); }
void InstructionSelector::VisitWord32Ror(Node* node) { void InstructionSelector::VisitWord32Ror(Node* node) {
VisitRRO(this, kArm64Ror32, node, kShift32Imm); VisitRRO(this, kArm64Ror32, node, kShift32Imm);
} }
......
...@@ -1235,6 +1235,13 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction( ...@@ -1235,6 +1235,13 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction(
__ SarPair_cl(i.InputRegister(1), i.InputRegister(0)); __ SarPair_cl(i.InputRegister(1), i.InputRegister(0));
} }
break; break;
case kIA32Rol:
if (HasImmediateInput(instr, 1)) {
__ rol(i.OutputOperand(), i.InputInt5(1));
} else {
__ rol_cl(i.OutputOperand());
}
break;
case kIA32Ror: case kIA32Ror:
if (HasImmediateInput(instr, 1)) { if (HasImmediateInput(instr, 1)) {
__ ror(i.OutputOperand(), i.InputInt5(1)); __ ror(i.OutputOperand(), i.InputInt5(1));
......
...@@ -39,6 +39,7 @@ namespace compiler { ...@@ -39,6 +39,7 @@ namespace compiler {
V(IA32ShlPair) \ V(IA32ShlPair) \
V(IA32ShrPair) \ V(IA32ShrPair) \
V(IA32SarPair) \ V(IA32SarPair) \
V(IA32Rol) \
V(IA32Ror) \ V(IA32Ror) \
V(IA32Lzcnt) \ V(IA32Lzcnt) \
V(IA32Tzcnt) \ V(IA32Tzcnt) \
......
...@@ -38,6 +38,7 @@ int InstructionScheduler::GetTargetInstructionFlags( ...@@ -38,6 +38,7 @@ int InstructionScheduler::GetTargetInstructionFlags(
case kIA32ShlPair: case kIA32ShlPair:
case kIA32ShrPair: case kIA32ShrPair:
case kIA32SarPair: case kIA32SarPair:
case kIA32Rol:
case kIA32Ror: case kIA32Ror:
case kIA32Lzcnt: case kIA32Lzcnt:
case kIA32Tzcnt: case kIA32Tzcnt:
......
...@@ -895,6 +895,10 @@ void InstructionSelector::VisitWord32PairSar(Node* node) { ...@@ -895,6 +895,10 @@ void InstructionSelector::VisitWord32PairSar(Node* node) {
VisitWord32PairShift(this, kIA32SarPair, node); VisitWord32PairShift(this, kIA32SarPair, node);
} }
void InstructionSelector::VisitWord32Rol(Node* node) {
VisitShift(this, node, kIA32Rol);
}
void InstructionSelector::VisitWord32Ror(Node* node) { void InstructionSelector::VisitWord32Ror(Node* node) {
VisitShift(this, node, kIA32Ror); VisitShift(this, node, kIA32Ror);
} }
...@@ -2811,7 +2815,7 @@ MachineOperatorBuilder::Flags ...@@ -2811,7 +2815,7 @@ MachineOperatorBuilder::Flags
InstructionSelector::SupportedMachineOperatorFlags() { InstructionSelector::SupportedMachineOperatorFlags() {
MachineOperatorBuilder::Flags flags = MachineOperatorBuilder::Flags flags =
MachineOperatorBuilder::kWord32ShiftIsSafe | MachineOperatorBuilder::kWord32ShiftIsSafe |
MachineOperatorBuilder::kWord32Ctz; MachineOperatorBuilder::kWord32Ctz | MachineOperatorBuilder::kWord32Rol;
if (CpuFeatures::IsSupported(POPCNT)) { if (CpuFeatures::IsSupported(POPCNT)) {
flags |= MachineOperatorBuilder::kWord32Popcnt; flags |= MachineOperatorBuilder::kWord32Popcnt;
} }
......
...@@ -1417,6 +1417,8 @@ void InstructionSelector::VisitNode(Node* node) { ...@@ -1417,6 +1417,8 @@ void InstructionSelector::VisitNode(Node* node) {
return MarkAsWord32(node), VisitWord32Shr(node); return MarkAsWord32(node), VisitWord32Shr(node);
case IrOpcode::kWord32Sar: case IrOpcode::kWord32Sar:
return MarkAsWord32(node), VisitWord32Sar(node); return MarkAsWord32(node), VisitWord32Sar(node);
case IrOpcode::kWord32Rol:
return MarkAsWord32(node), VisitWord32Rol(node);
case IrOpcode::kWord32Ror: case IrOpcode::kWord32Ror:
return MarkAsWord32(node), VisitWord32Ror(node); return MarkAsWord32(node), VisitWord32Ror(node);
case IrOpcode::kWord32Equal: case IrOpcode::kWord32Equal:
...@@ -1447,6 +1449,8 @@ void InstructionSelector::VisitNode(Node* node) { ...@@ -1447,6 +1449,8 @@ void InstructionSelector::VisitNode(Node* node) {
return MarkAsWord64(node), VisitWord64Shr(node); return MarkAsWord64(node), VisitWord64Shr(node);
case IrOpcode::kWord64Sar: case IrOpcode::kWord64Sar:
return MarkAsWord64(node), VisitWord64Sar(node); return MarkAsWord64(node), VisitWord64Sar(node);
case IrOpcode::kWord64Rol:
return MarkAsWord64(node), VisitWord64Rol(node);
case IrOpcode::kWord64Ror: case IrOpcode::kWord64Ror:
return MarkAsWord64(node), VisitWord64Ror(node); return MarkAsWord64(node), VisitWord64Ror(node);
case IrOpcode::kWord64Clz: case IrOpcode::kWord64Clz:
...@@ -2387,6 +2391,8 @@ void InstructionSelector::VisitWord64Shr(Node* node) { UNIMPLEMENTED(); } ...@@ -2387,6 +2391,8 @@ void InstructionSelector::VisitWord64Shr(Node* node) { UNIMPLEMENTED(); }
void InstructionSelector::VisitWord64Sar(Node* node) { UNIMPLEMENTED(); } void InstructionSelector::VisitWord64Sar(Node* node) { UNIMPLEMENTED(); }
void InstructionSelector::VisitWord64Rol(Node* node) { UNIMPLEMENTED(); }
void InstructionSelector::VisitWord64Ror(Node* node) { UNIMPLEMENTED(); } void InstructionSelector::VisitWord64Ror(Node* node) { UNIMPLEMENTED(); }
void InstructionSelector::VisitWord64Clz(Node* node) { UNIMPLEMENTED(); } void InstructionSelector::VisitWord64Clz(Node* node) { UNIMPLEMENTED(); }
......
...@@ -1292,6 +1292,12 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction( ...@@ -1292,6 +1292,12 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction(
case kX64Sar: case kX64Sar:
ASSEMBLE_SHIFT(sarq, 6); ASSEMBLE_SHIFT(sarq, 6);
break; break;
case kX64Rol32:
ASSEMBLE_SHIFT(roll, 5);
break;
case kX64Rol:
ASSEMBLE_SHIFT(rolq, 6);
break;
case kX64Ror32: case kX64Ror32:
ASSEMBLE_SHIFT(rorl, 5); ASSEMBLE_SHIFT(rorl, 5);
break; break;
......
...@@ -48,6 +48,8 @@ namespace compiler { ...@@ -48,6 +48,8 @@ namespace compiler {
V(X64Shr32) \ V(X64Shr32) \
V(X64Sar) \ V(X64Sar) \
V(X64Sar32) \ V(X64Sar32) \
V(X64Rol) \
V(X64Rol32) \
V(X64Ror) \ V(X64Ror) \
V(X64Ror32) \ V(X64Ror32) \
V(X64Lzcnt) \ V(X64Lzcnt) \
......
...@@ -45,6 +45,8 @@ int InstructionScheduler::GetTargetInstructionFlags( ...@@ -45,6 +45,8 @@ int InstructionScheduler::GetTargetInstructionFlags(
case kX64Shr32: case kX64Shr32:
case kX64Sar: case kX64Sar:
case kX64Sar32: case kX64Sar32:
case kX64Rol:
case kX64Rol32:
case kX64Ror: case kX64Ror:
case kX64Ror32: case kX64Ror32:
case kX64Lzcnt: case kX64Lzcnt:
......
...@@ -911,6 +911,14 @@ void InstructionSelector::VisitWord64Sar(Node* node) { ...@@ -911,6 +911,14 @@ void InstructionSelector::VisitWord64Sar(Node* node) {
VisitWord64Shift(this, node, kX64Sar); VisitWord64Shift(this, node, kX64Sar);
} }
void InstructionSelector::VisitWord32Rol(Node* node) {
VisitWord32Shift(this, node, kX64Rol32);
}
void InstructionSelector::VisitWord64Rol(Node* node) {
VisitWord64Shift(this, node, kX64Rol);
}
void InstructionSelector::VisitWord32Ror(Node* node) { void InstructionSelector::VisitWord32Ror(Node* node) {
VisitWord32Shift(this, node, kX64Ror32); VisitWord32Shift(this, node, kX64Ror32);
} }
...@@ -1290,6 +1298,7 @@ bool ZeroExtendsWord32ToWord64(Node* node) { ...@@ -1290,6 +1298,7 @@ bool ZeroExtendsWord32ToWord64(Node* node) {
case IrOpcode::kWord32Shl: case IrOpcode::kWord32Shl:
case IrOpcode::kWord32Shr: case IrOpcode::kWord32Shr:
case IrOpcode::kWord32Sar: case IrOpcode::kWord32Sar:
case IrOpcode::kWord32Rol:
case IrOpcode::kWord32Ror: case IrOpcode::kWord32Ror:
case IrOpcode::kWord32Equal: case IrOpcode::kWord32Equal:
case IrOpcode::kInt32Add: case IrOpcode::kInt32Add:
...@@ -3376,7 +3385,8 @@ MachineOperatorBuilder::Flags ...@@ -3376,7 +3385,8 @@ MachineOperatorBuilder::Flags
InstructionSelector::SupportedMachineOperatorFlags() { InstructionSelector::SupportedMachineOperatorFlags() {
MachineOperatorBuilder::Flags flags = MachineOperatorBuilder::Flags flags =
MachineOperatorBuilder::kWord32ShiftIsSafe | MachineOperatorBuilder::kWord32ShiftIsSafe |
MachineOperatorBuilder::kWord32Ctz | MachineOperatorBuilder::kWord64Ctz; MachineOperatorBuilder::kWord32Ctz | MachineOperatorBuilder::kWord64Ctz |
MachineOperatorBuilder::kWord32Rol | MachineOperatorBuilder::kWord64Rol;
if (CpuFeatures::IsSupported(POPCNT)) { if (CpuFeatures::IsSupported(POPCNT)) {
flags |= MachineOperatorBuilder::kWord32Popcnt | flags |= MachineOperatorBuilder::kWord32Popcnt |
MachineOperatorBuilder::kWord64Popcnt; MachineOperatorBuilder::kWord64Popcnt;
......
...@@ -670,6 +670,9 @@ void Int64Lowering::LowerNode(Node* node) { ...@@ -670,6 +670,9 @@ void Int64Lowering::LowerNode(Node* node) {
ReplaceNode(node, low_node, high_node); ReplaceNode(node, low_node, high_node);
break; break;
} }
case IrOpcode::kWord64Rol:
DCHECK(machine()->Word32Rol().IsSupported());
V8_FALLTHROUGH;
case IrOpcode::kWord64Ror: { case IrOpcode::kWord64Ror: {
DCHECK_EQ(2, node->InputCount()); DCHECK_EQ(2, node->InputCount());
Node* input = node->InputAt(0); Node* input = node->InputAt(0);
...@@ -702,14 +705,19 @@ void Int64Lowering::LowerNode(Node* node) { ...@@ -702,14 +705,19 @@ void Int64Lowering::LowerNode(Node* node) {
Node* inv_shift = graph()->NewNode( Node* inv_shift = graph()->NewNode(
common()->Int32Constant(32 - masked_shift_value)); common()->Int32Constant(32 - masked_shift_value));
Node* low_node = graph()->NewNode( auto* op1 = machine()->Word32Shr();
machine()->Word32Or(), auto* op2 = machine()->Word32Shl();
graph()->NewNode(machine()->Word32Shr(), low_input, masked_shift), bool is_ror = node->opcode() == IrOpcode::kWord64Ror;
graph()->NewNode(machine()->Word32Shl(), high_input, inv_shift)); if (!is_ror) std::swap(op1, op2);
Node* high_node = graph()->NewNode(
machine()->Word32Or(), graph()->NewNode(machine()->Word32Shr(), Node* low_node =
high_input, masked_shift), graph()->NewNode(machine()->Word32Or(),
graph()->NewNode(machine()->Word32Shl(), low_input, inv_shift)); graph()->NewNode(op1, low_input, masked_shift),
graph()->NewNode(op2, high_input, inv_shift));
Node* high_node =
graph()->NewNode(machine()->Word32Or(),
graph()->NewNode(op1, high_input, masked_shift),
graph()->NewNode(op2, low_input, inv_shift));
ReplaceNode(node, low_node, high_node); ReplaceNode(node, low_node, high_node);
} }
} else { } else {
...@@ -720,15 +728,19 @@ void Int64Lowering::LowerNode(Node* node) { ...@@ -720,15 +728,19 @@ void Int64Lowering::LowerNode(Node* node) {
graph()->NewNode(common()->Int32Constant(0x1F))); graph()->NewNode(common()->Int32Constant(0x1F)));
} }
// By creating this bit-mask with SAR and SHL we do not have to deal bool is_ror = node->opcode() == IrOpcode::kWord64Ror;
// with shift == 0 as a special case. Node* inv_mask =
Node* inv_mask = graph()->NewNode( is_ror ? graph()->NewNode(
machine()->Word32Shl(), machine()->Word32Xor(),
graph()->NewNode(machine()->Word32Sar(), graph()->NewNode(
graph()->NewNode(common()->Int32Constant( machine()->Word32Shr(),
std::numeric_limits<int32_t>::min())), graph()->NewNode(common()->Int32Constant(-1)),
safe_shift), safe_shift),
graph()->NewNode(common()->Int32Constant(1))); graph()->NewNode(common()->Int32Constant(-1)))
: graph()->NewNode(
machine()->Word32Shl(),
graph()->NewNode(common()->Int32Constant(-1)),
safe_shift);
Node* bit_mask = Node* bit_mask =
graph()->NewNode(machine()->Word32Xor(), inv_mask, graph()->NewNode(machine()->Word32Xor(), inv_mask,
...@@ -759,21 +771,24 @@ void Int64Lowering::LowerNode(Node* node) { ...@@ -759,21 +771,24 @@ void Int64Lowering::LowerNode(Node* node) {
lt32.Phi(MachineRepresentation::kWord32, GetReplacementHigh(input), lt32.Phi(MachineRepresentation::kWord32, GetReplacementHigh(input),
GetReplacementLow(input)); GetReplacementLow(input));
Node* rotate_low = const Operator* oper =
graph()->NewNode(machine()->Word32Ror(), input_low, safe_shift); is_ror ? machine()->Word32Ror() : machine()->Word32Rol().op();
Node* rotate_high =
graph()->NewNode(machine()->Word32Ror(), input_high, safe_shift); Node* rotate_low = graph()->NewNode(oper, input_low, safe_shift);
Node* rotate_high = graph()->NewNode(oper, input_high, safe_shift);
auto* mask1 = bit_mask;
auto* mask2 = inv_mask;
if (!is_ror) std::swap(mask1, mask2);
Node* low_node = graph()->NewNode( Node* low_node = graph()->NewNode(
machine()->Word32Or(), machine()->Word32Or(),
graph()->NewNode(machine()->Word32And(), rotate_low, bit_mask), graph()->NewNode(machine()->Word32And(), rotate_low, mask1),
graph()->NewNode(machine()->Word32And(), rotate_high, inv_mask)); graph()->NewNode(machine()->Word32And(), rotate_high, mask2));
Node* high_node = graph()->NewNode( Node* high_node = graph()->NewNode(
machine()->Word32Or(), machine()->Word32Or(),
graph()->NewNode(machine()->Word32And(), rotate_high, bit_mask), graph()->NewNode(machine()->Word32And(), rotate_high, mask1),
graph()->NewNode(machine()->Word32And(), rotate_low, inv_mask)); graph()->NewNode(machine()->Word32And(), rotate_low, mask2));
ReplaceNode(node, low_node, high_node); ReplaceNode(node, low_node, high_node);
} }
break; break;
......
...@@ -487,6 +487,8 @@ ShiftKind ShiftKindOf(Operator const* op) { ...@@ -487,6 +487,8 @@ ShiftKind ShiftKindOf(Operator const* op) {
#define PURE_OPTIONAL_OP_LIST(V) \ #define PURE_OPTIONAL_OP_LIST(V) \
V(Word32Ctz, Operator::kNoProperties, 1, 0, 1) \ V(Word32Ctz, Operator::kNoProperties, 1, 0, 1) \
V(Word64Ctz, Operator::kNoProperties, 1, 0, 1) \ V(Word64Ctz, Operator::kNoProperties, 1, 0, 1) \
V(Word32Rol, Operator::kNoProperties, 2, 0, 1) \
V(Word64Rol, Operator::kNoProperties, 2, 0, 1) \
V(Word32ReverseBits, Operator::kNoProperties, 1, 0, 1) \ V(Word32ReverseBits, Operator::kNoProperties, 1, 0, 1) \
V(Word64ReverseBits, Operator::kNoProperties, 1, 0, 1) \ V(Word64ReverseBits, Operator::kNoProperties, 1, 0, 1) \
V(Int32AbsWithOverflow, Operator::kNoProperties, 1, 0, 2) \ V(Int32AbsWithOverflow, Operator::kNoProperties, 1, 0, 2) \
......
...@@ -220,13 +220,15 @@ class V8_EXPORT_PRIVATE MachineOperatorBuilder final ...@@ -220,13 +220,15 @@ class V8_EXPORT_PRIVATE MachineOperatorBuilder final
kWord64ReverseBits = 1u << 17, kWord64ReverseBits = 1u << 17,
kInt32AbsWithOverflow = 1u << 20, kInt32AbsWithOverflow = 1u << 20,
kInt64AbsWithOverflow = 1u << 21, kInt64AbsWithOverflow = 1u << 21,
kAllOptionalOps = kFloat32RoundDown | kFloat64RoundDown | kFloat32RoundUp | kWord32Rol = 1u << 22,
kFloat64RoundUp | kFloat32RoundTruncate | kWord64Rol = 1u << 23,
kFloat64RoundTruncate | kFloat64RoundTiesAway | kAllOptionalOps =
kFloat32RoundTiesEven | kFloat64RoundTiesEven | kFloat32RoundDown | kFloat64RoundDown | kFloat32RoundUp |
kWord32Ctz | kWord64Ctz | kWord32Popcnt | kWord64Popcnt | kFloat64RoundUp | kFloat32RoundTruncate | kFloat64RoundTruncate |
kWord32ReverseBits | kWord64ReverseBits | kFloat64RoundTiesAway | kFloat32RoundTiesEven | kFloat64RoundTiesEven |
kInt32AbsWithOverflow | kInt64AbsWithOverflow kWord32Ctz | kWord64Ctz | kWord32Popcnt | kWord64Popcnt |
kWord32ReverseBits | kWord64ReverseBits | kInt32AbsWithOverflow |
kInt64AbsWithOverflow | kWord32Rol | kWord64Rol
}; };
using Flags = base::Flags<Flag, unsigned>; using Flags = base::Flags<Flag, unsigned>;
...@@ -308,6 +310,7 @@ class V8_EXPORT_PRIVATE MachineOperatorBuilder final ...@@ -308,6 +310,7 @@ class V8_EXPORT_PRIVATE MachineOperatorBuilder final
const Operator* Word32SarShiftOutZeros() { const Operator* Word32SarShiftOutZeros() {
return Word32Sar(ShiftKind::kShiftOutZeros); return Word32Sar(ShiftKind::kShiftOutZeros);
} }
const OptionalOperator Word32Rol();
const Operator* Word32Ror(); const Operator* Word32Ror();
const Operator* Word32Equal(); const Operator* Word32Equal();
const Operator* Word32Clz(); const Operator* Word32Clz();
...@@ -337,6 +340,7 @@ class V8_EXPORT_PRIVATE MachineOperatorBuilder final ...@@ -337,6 +340,7 @@ class V8_EXPORT_PRIVATE MachineOperatorBuilder final
const Operator* Word64SarShiftOutZeros() { const Operator* Word64SarShiftOutZeros() {
return Word64Sar(ShiftKind::kShiftOutZeros); return Word64Sar(ShiftKind::kShiftOutZeros);
} }
const OptionalOperator Word64Rol();
const Operator* Word64Ror(); const Operator* Word64Ror();
const Operator* Word64Clz(); const Operator* Word64Clz();
const OptionalOperator Word64Ctz(); const OptionalOperator Word64Ctz();
......
...@@ -532,6 +532,7 @@ ...@@ -532,6 +532,7 @@
V(Word32Shl) \ V(Word32Shl) \
V(Word32Shr) \ V(Word32Shr) \
V(Word32Sar) \ V(Word32Sar) \
V(Word32Rol) \
V(Word32Ror) \ V(Word32Ror) \
V(Int32Add) \ V(Int32Add) \
V(Int32AddWithOverflow) \ V(Int32AddWithOverflow) \
...@@ -553,6 +554,7 @@ ...@@ -553,6 +554,7 @@
V(Word64Shl) \ V(Word64Shl) \
V(Word64Shr) \ V(Word64Shr) \
V(Word64Sar) \ V(Word64Sar) \
V(Word64Rol) \
V(Word64Ror) \ V(Word64Ror) \
V(Int64Add) \ V(Int64Add) \
V(Int64AddWithOverflow) \ V(Int64AddWithOverflow) \
......
...@@ -1623,6 +1623,7 @@ void Verifier::Visitor::Check(Node* node, const AllNodes& all) { ...@@ -1623,6 +1623,7 @@ void Verifier::Visitor::Check(Node* node, const AllNodes& all) {
case IrOpcode::kWord32Shl: case IrOpcode::kWord32Shl:
case IrOpcode::kWord32Shr: case IrOpcode::kWord32Shr:
case IrOpcode::kWord32Sar: case IrOpcode::kWord32Sar:
case IrOpcode::kWord32Rol:
case IrOpcode::kWord32Ror: case IrOpcode::kWord32Ror:
case IrOpcode::kWord32Equal: case IrOpcode::kWord32Equal:
case IrOpcode::kWord32Clz: case IrOpcode::kWord32Clz:
...@@ -1637,6 +1638,7 @@ void Verifier::Visitor::Check(Node* node, const AllNodes& all) { ...@@ -1637,6 +1638,7 @@ void Verifier::Visitor::Check(Node* node, const AllNodes& all) {
case IrOpcode::kWord64Shl: case IrOpcode::kWord64Shl:
case IrOpcode::kWord64Shr: case IrOpcode::kWord64Shr:
case IrOpcode::kWord64Sar: case IrOpcode::kWord64Sar:
case IrOpcode::kWord64Rol:
case IrOpcode::kWord64Ror: case IrOpcode::kWord64Ror:
case IrOpcode::kWord64Clz: case IrOpcode::kWord64Clz:
case IrOpcode::kWord64Popcnt: case IrOpcode::kWord64Popcnt:
......
...@@ -432,7 +432,11 @@ Node* WasmGraphBuilder::Binop(wasm::WasmOpcode opcode, Node* left, Node* right, ...@@ -432,7 +432,11 @@ Node* WasmGraphBuilder::Binop(wasm::WasmOpcode opcode, Node* left, Node* right,
right = MaskShiftCount32(right); right = MaskShiftCount32(right);
break; break;
case wasm::kExprI32Rol: case wasm::kExprI32Rol:
right = MaskShiftCount32(right); if (m->Word32Rol().IsSupported()) {
op = m->Word32Rol().op();
right = MaskShiftCount32(right);
break;
}
return BuildI32Rol(left, right); return BuildI32Rol(left, right);
case wasm::kExprI32Eq: case wasm::kExprI32Eq:
op = m->Word32Equal(); op = m->Word32Equal();
...@@ -543,6 +547,14 @@ Node* WasmGraphBuilder::Binop(wasm::WasmOpcode opcode, Node* left, Node* right, ...@@ -543,6 +547,14 @@ Node* WasmGraphBuilder::Binop(wasm::WasmOpcode opcode, Node* left, Node* right,
right = MaskShiftCount64(right); right = MaskShiftCount64(right);
break; break;
case wasm::kExprI64Rol: case wasm::kExprI64Rol:
if (m->Word64Rol().IsSupported()) {
op = m->Word64Rol().op();
right = MaskShiftCount64(right);
break;
} else if (m->Word32Rol().IsSupported()) {
op = m->Word64Rol().placeholder();
break;
}
return BuildI64Rol(left, right); return BuildI64Rol(left, right);
case wasm::kExprF32CopySign: case wasm::kExprF32CopySign:
return BuildF32CopySign(left, right); return BuildF32CopySign(left, right);
......
...@@ -816,10 +816,8 @@ TEST_F(Int64LoweringTest, I64Ror) { ...@@ -816,10 +816,8 @@ TEST_F(Int64LoweringTest, I64Ror) {
Matcher<Node*> shift_matcher = Matcher<Node*> shift_matcher =
IsWord32And(IsParameter(0), IsInt32Constant(0x1F)); IsWord32And(IsParameter(0), IsInt32Constant(0x1F));
Matcher<Node*> bit_mask_matcher = IsWord32Shl( Matcher<Node*> bit_mask_matcher = IsWord32Xor(
IsWord32Sar(IsInt32Constant(std::numeric_limits<int32_t>::min()), IsWord32Shr(IsInt32Constant(-1), shift_matcher), IsInt32Constant(-1));
shift_matcher),
IsInt32Constant(1));
Matcher<Node*> inv_mask_matcher = Matcher<Node*> inv_mask_matcher =
IsWord32Xor(bit_mask_matcher, IsInt32Constant(-1)); IsWord32Xor(bit_mask_matcher, IsInt32Constant(-1));
......
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