Commit fab25310 authored by ahaas's avatar ahaas Committed by Commit bot

[wasm] I added comparison operators to the Int64Lowering.

Comparison operators are lowered using to a lexicographic ordering, e.g.
(a,b) <= (c,d) <<>> (a < c) | (a == c) & (b <= d).

R=titzer@chromium.org

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

Cr-Commit-Position: refs/heads/master@{#34287}
parent ee250655
......@@ -313,13 +313,26 @@ void Int64Lowering::LowerNode(Node* node) {
}
// kExprI64Ne:
// kExprI64LtS:
// kExprI64LeS:
// kExprI64LtU:
// kExprI64LeU:
// kExprI64GtS:
// kExprI64GeS:
// kExprI64GtU:
// kExprI64GeU:
case IrOpcode::kInt64LessThan: {
LowerComparison(node, machine()->Int32LessThan(),
machine()->Uint32LessThan());
break;
}
case IrOpcode::kInt64LessThanOrEqual: {
LowerComparison(node, machine()->Int32LessThan(),
machine()->Uint32LessThanOrEqual());
break;
}
case IrOpcode::kUint64LessThan: {
LowerComparison(node, machine()->Uint32LessThan(),
machine()->Uint32LessThan());
break;
}
case IrOpcode::kUint64LessThanOrEqual: {
LowerComparison(node, machine()->Uint32LessThan(),
machine()->Uint32LessThanOrEqual());
break;
}
// kExprI64SConvertI32:
// kExprI64UConvertI32:
......@@ -343,6 +356,25 @@ void Int64Lowering::LowerNode(Node* node) {
}
}
void Int64Lowering::LowerComparison(Node* node, const Operator* high_word_op,
const Operator* low_word_op) {
DCHECK(node->InputCount() == 2);
Node* left = node->InputAt(0);
Node* right = node->InputAt(1);
Node* replacement = graph()->NewNode(
machine()->Word32Or(),
graph()->NewNode(high_word_op, GetReplacementHigh(left),
GetReplacementHigh(right)),
graph()->NewNode(
machine()->Word32And(),
graph()->NewNode(machine()->Word32Equal(), GetReplacementHigh(left),
GetReplacementHigh(right)),
graph()->NewNode(low_word_op, GetReplacementLow(left),
GetReplacementLow(right))));
ReplaceNode(node, replacement, nullptr);
}
bool Int64Lowering::DefaultLowering(Node* node) {
bool something_changed = false;
for (int i = NodeProperties::PastValueIndex(node) - 1; i >= 0; i--) {
......
......@@ -39,6 +39,8 @@ class Int64Lowering {
void LowerNode(Node* node);
bool DefaultLowering(Node* node);
void LowerComparison(Node* node, const Operator* signed_op,
const Operator* unsigned_op);
void ReplaceNode(Node* old, Node* new_low, Node* new_high);
bool HasReplacementLow(Node* node);
......
......@@ -514,13 +514,34 @@ Node* WasmGraphBuilder::Binop(wasm::WasmOpcode opcode, Node* left,
case wasm::kExprI64Ne:
return Invert(Binop(wasm::kExprI64Eq, left, right));
// kExprI64LtS:
// kExprI64LeS:
// kExprI64LtU:
// kExprI64LeU:
// kExprI64GtS:
// kExprI64GeS:
// kExprI64GtU:
// kExprI64GeU:
case wasm::kExprI64LtS:
op = m->Int64LessThan();
break;
case wasm::kExprI64LeS:
op = m->Int64LessThanOrEqual();
break;
case wasm::kExprI64LtU:
op = m->Uint64LessThan();
break;
case wasm::kExprI64LeU:
op = m->Uint64LessThanOrEqual();
break;
case wasm::kExprI64GtS:
op = m->Int64LessThan();
std::swap(left, right);
break;
case wasm::kExprI64GeS:
op = m->Int64LessThanOrEqual();
std::swap(left, right);
break;
case wasm::kExprI64GtU:
op = m->Uint64LessThan();
std::swap(left, right);
break;
case wasm::kExprI64GeU:
op = m->Uint64LessThanOrEqual();
std::swap(left, right);
break;
// kExprI32ConvertI64:
// kExprI64SConvertI32:
......@@ -600,34 +621,6 @@ Node* WasmGraphBuilder::Binop(wasm::WasmOpcode opcode, Node* left,
case wasm::kExprI64ShrS:
op = m->Word64Sar();
break;
case wasm::kExprI64LtS:
op = m->Int64LessThan();
break;
case wasm::kExprI64LeS:
op = m->Int64LessThanOrEqual();
break;
case wasm::kExprI64LtU:
op = m->Uint64LessThan();
break;
case wasm::kExprI64LeU:
op = m->Uint64LessThanOrEqual();
break;
case wasm::kExprI64GtS:
op = m->Int64LessThan();
std::swap(left, right);
break;
case wasm::kExprI64GeS:
op = m->Int64LessThanOrEqual();
std::swap(left, right);
break;
case wasm::kExprI64GtU:
op = m->Uint64LessThan();
std::swap(left, right);
break;
case wasm::kExprI64GeU:
op = m->Uint64LessThanOrEqual();
std::swap(left, right);
break;
#endif
case wasm::kExprF32CopySign:
......
......@@ -70,14 +70,64 @@ TEST(Run_WasmI64Ne) {
}
}
// kExprI64LtS:
// kExprI64LeS:
// kExprI64LtU:
// kExprI64LeU:
// kExprI64GtS:
// kExprI64GeS:
// kExprI64GtU:
// kExprI64GeU:
TEST(Run_WasmI64LtS) {
WasmRunner<int32_t> r(MachineType::Int64(), MachineType::Int64());
BUILD(r, WASM_I64_LTS(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)));
FOR_INT64_INPUTS(i) {
FOR_INT64_INPUTS(j) { CHECK_EQ(*i < *j ? 1 : 0, r.Call(*i, *j)); }
}
}
TEST(Run_WasmI64LeS) {
WasmRunner<int32_t> r(MachineType::Int64(), MachineType::Int64());
BUILD(r, WASM_I64_LES(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)));
FOR_INT64_INPUTS(i) {
FOR_INT64_INPUTS(j) { CHECK_EQ(*i <= *j ? 1 : 0, r.Call(*i, *j)); }
}
}
TEST(Run_WasmI64LtU) {
WasmRunner<int32_t> r(MachineType::Int64(), MachineType::Int64());
BUILD(r, WASM_I64_LTU(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)));
FOR_UINT64_INPUTS(i) {
FOR_UINT64_INPUTS(j) { CHECK_EQ(*i < *j ? 1 : 0, r.Call(*i, *j)); }
}
}
TEST(Run_WasmI64LeU) {
WasmRunner<int32_t> r(MachineType::Int64(), MachineType::Int64());
BUILD(r, WASM_I64_LEU(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)));
FOR_UINT64_INPUTS(i) {
FOR_UINT64_INPUTS(j) { CHECK_EQ(*i <= *j ? 1 : 0, r.Call(*i, *j)); }
}
}
TEST(Run_WasmI64GtS) {
WasmRunner<int32_t> r(MachineType::Int64(), MachineType::Int64());
BUILD(r, WASM_I64_GTS(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)));
FOR_INT64_INPUTS(i) {
FOR_INT64_INPUTS(j) { CHECK_EQ(*i > *j ? 1 : 0, r.Call(*i, *j)); }
}
}
TEST(Run_WasmI64GeS) {
WasmRunner<int32_t> r(MachineType::Int64(), MachineType::Int64());
BUILD(r, WASM_I64_GES(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)));
FOR_INT64_INPUTS(i) {
FOR_INT64_INPUTS(j) { CHECK_EQ(*i >= *j ? 1 : 0, r.Call(*i, *j)); }
}
}
TEST(Run_WasmI64GtU) {
WasmRunner<int32_t> r(MachineType::Int64(), MachineType::Int64());
BUILD(r, WASM_I64_GTU(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)));
FOR_UINT64_INPUTS(i) {
FOR_UINT64_INPUTS(j) { CHECK_EQ(*i > *j ? 1 : 0, r.Call(*i, *j)); }
}
}
TEST(Run_WasmI64GeU) {
WasmRunner<int32_t> r(MachineType::Int64(), MachineType::Int64());
BUILD(r, WASM_I64_GEU(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)));
FOR_UINT64_INPUTS(i) {
FOR_UINT64_INPUTS(j) { CHECK_EQ(*i >= *j ? 1 : 0, r.Call(*i, *j)); }
}
}
// kExprI32ConvertI64:
TEST(Run_WasmI32ConvertI64) {
FOR_INT64_INPUTS(i) {
......
......@@ -86,6 +86,28 @@ class Int64LoweringTest : public GraphTest {
return static_cast<int32_t>(value_[i] >> 32);
}
void TestComparison(
const Operator* op,
Matcher<Node*> (*high_word_matcher)(const Matcher<Node*>& lhs_matcher,
const Matcher<Node*>& rhs_matcher),
Matcher<Node*> (*low_word_matcher)(const Matcher<Node*>& lhs_matcher,
const Matcher<Node*>& rhs_matcher)) {
LowerGraph(
graph()->NewNode(op, Int64Constant(value(0)), Int64Constant(value(1))),
MachineRepresentation::kWord32);
EXPECT_THAT(
graph()->end()->InputAt(1),
IsReturn(IsWord32Or(
high_word_matcher(IsInt32Constant(high_word_value(0)),
IsInt32Constant(high_word_value(1))),
IsWord32And(
IsWord32Equal(IsInt32Constant(high_word_value(0)),
IsInt32Constant(high_word_value(1))),
low_word_matcher(IsInt32Constant(low_word_value(0)),
IsInt32Constant(low_word_value(1))))),
start(), start()));
}
private:
MachineOperatorBuilder machine_;
int64_t value_[3];
......@@ -356,13 +378,28 @@ TEST_F(Int64LoweringTest, Int64Eq) {
// kExprI64Ne:
// kExprI64LtS:
TEST_F(Int64LoweringTest, Int64LtS) {
if (4 != kPointerSize) return;
TestComparison(machine()->Int64LessThan(), IsInt32LessThan, IsUint32LessThan);
}
// kExprI64LeS:
TEST_F(Int64LoweringTest, Int64LeS) {
if (4 != kPointerSize) return;
TestComparison(machine()->Int64LessThanOrEqual(), IsInt32LessThan,
IsUint32LessThanOrEqual);
}
// kExprI64LtU:
TEST_F(Int64LoweringTest, Int64LtU) {
if (4 != kPointerSize) return;
TestComparison(machine()->Uint64LessThan(), IsUint32LessThan,
IsUint32LessThan);
}
// kExprI64LeU:
// kExprI64GtS:
// kExprI64GeS:
// kExprI64GtU:
// kExprI64GeU:
TEST_F(Int64LoweringTest, Int64LeU) {
if (4 != kPointerSize) return;
TestComparison(machine()->Uint64LessThanOrEqual(), IsUint32LessThan,
IsUint32LessThanOrEqual);
}
// kExprI32ConvertI64:
// kExprI64SConvertI32:
......
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