[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}
This commit is contained in:
parent
ee250655b4
commit
fab253109d
@ -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:
|
||||
|
Loading…
Reference in New Issue
Block a user