Fixing constant compare.
This commit is contained in:
@@ -1196,7 +1196,8 @@ Value* HIRBuilder::CompareXX(const OpcodeInfo& opcode, Value* value1,
|
||||
Value* value2) {
|
||||
ASSERT_TYPES_EQUAL(value1, value2);
|
||||
if (value1->IsConstant() && value2->IsConstant()) {
|
||||
return LoadConstant(value1->Compare(opcode.num, value2) ? 1 : 0);
|
||||
return LoadConstant(value1->Compare(opcode.num, value2) ? int8_t(1)
|
||||
: int8_t(0));
|
||||
}
|
||||
|
||||
Instr* i = AppendInstr(opcode, 0, AllocValue(INT8_TYPE));
|
||||
|
||||
@@ -244,7 +244,7 @@ bool Value::Add(Value* other) {
|
||||
}
|
||||
|
||||
bool Value::Sub(Value* other) {
|
||||
#define SUB_DID_CARRY(a, b) (b == 0 || a > (~(0-b)))
|
||||
#define SUB_DID_CARRY(a, b) (b == 0 || a > (~(0 - b)))
|
||||
assert_true(type == other->type);
|
||||
bool did_carry = false;
|
||||
switch (type) {
|
||||
@@ -313,9 +313,12 @@ void Value::MulHi(Value* other, bool is_unsigned) {
|
||||
switch (type) {
|
||||
case INT32_TYPE:
|
||||
if (is_unsigned) {
|
||||
constant.i32 = (int32_t)(((uint64_t)((uint32_t)constant.i32) * (uint32_t)other->constant.i32) >> 32);
|
||||
constant.i32 = (int32_t)(((uint64_t)((uint32_t)constant.i32) *
|
||||
(uint32_t)other->constant.i32) >>
|
||||
32);
|
||||
} else {
|
||||
constant.i32 = (int32_t)(((int64_t)constant.i32 * (int64_t)other->constant.i32) >> 32);
|
||||
constant.i32 = (int32_t)(
|
||||
((int64_t)constant.i32 * (int64_t)other->constant.i32) >> 32);
|
||||
}
|
||||
break;
|
||||
case INT64_TYPE:
|
||||
@@ -670,9 +673,132 @@ void Value::CountLeadingZeros(const Value* other) {
|
||||
}
|
||||
|
||||
bool Value::Compare(Opcode opcode, Value* other) {
|
||||
// TODO(benvanik): big matrix.
|
||||
assert_always();
|
||||
return false;
|
||||
assert_true(type == other->type);
|
||||
switch (other->type) {
|
||||
case INT8_TYPE:
|
||||
return CompareInt8(opcode, this, other);
|
||||
case INT16_TYPE:
|
||||
return CompareInt16(opcode, this, other);
|
||||
case INT32_TYPE:
|
||||
return CompareInt32(opcode, this, other);
|
||||
case INT64_TYPE:
|
||||
return CompareInt64(opcode, this, other);
|
||||
default:
|
||||
assert_unhandled_case(type);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool Value::CompareInt8(Opcode opcode, Value* a, Value* b) {
|
||||
switch (opcode) {
|
||||
case OPCODE_COMPARE_EQ:
|
||||
return a->constant.i8 == b->constant.i8;
|
||||
case OPCODE_COMPARE_NE:
|
||||
return a->constant.i8 != b->constant.i8;
|
||||
case OPCODE_COMPARE_SLT:
|
||||
return a->constant.i8 < b->constant.i8;
|
||||
case OPCODE_COMPARE_SLE:
|
||||
return a->constant.i8 <= b->constant.i8;
|
||||
case OPCODE_COMPARE_SGT:
|
||||
return a->constant.i8 > b->constant.i8;
|
||||
case OPCODE_COMPARE_SGE:
|
||||
return a->constant.i8 >= b->constant.i8;
|
||||
case OPCODE_COMPARE_ULT:
|
||||
return uint8_t(a->constant.i8) < uint8_t(b->constant.i8);
|
||||
case OPCODE_COMPARE_ULE:
|
||||
return uint8_t(a->constant.i8) <= uint8_t(b->constant.i8);
|
||||
case OPCODE_COMPARE_UGT:
|
||||
return uint8_t(a->constant.i8) > uint8_t(b->constant.i8);
|
||||
case OPCODE_COMPARE_UGE:
|
||||
return uint8_t(a->constant.i8) >= uint8_t(b->constant.i8);
|
||||
default:
|
||||
assert_unhandled_case(opcode);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool Value::CompareInt16(Opcode opcode, Value* a, Value* b) {
|
||||
switch (opcode) {
|
||||
case OPCODE_COMPARE_EQ:
|
||||
return a->constant.i16 == b->constant.i16;
|
||||
case OPCODE_COMPARE_NE:
|
||||
return a->constant.i16 != b->constant.i16;
|
||||
case OPCODE_COMPARE_SLT:
|
||||
return a->constant.i16 < b->constant.i16;
|
||||
case OPCODE_COMPARE_SLE:
|
||||
return a->constant.i16 <= b->constant.i16;
|
||||
case OPCODE_COMPARE_SGT:
|
||||
return a->constant.i16 > b->constant.i16;
|
||||
case OPCODE_COMPARE_SGE:
|
||||
return a->constant.i16 >= b->constant.i16;
|
||||
case OPCODE_COMPARE_ULT:
|
||||
return uint16_t(a->constant.i16) < uint16_t(b->constant.i16);
|
||||
case OPCODE_COMPARE_ULE:
|
||||
return uint16_t(a->constant.i16) <= uint16_t(b->constant.i16);
|
||||
case OPCODE_COMPARE_UGT:
|
||||
return uint16_t(a->constant.i16) > uint16_t(b->constant.i16);
|
||||
case OPCODE_COMPARE_UGE:
|
||||
return uint16_t(a->constant.i16) >= uint16_t(b->constant.i16);
|
||||
default:
|
||||
assert_unhandled_case(opcode);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool Value::CompareInt32(Opcode opcode, Value* a, Value* b) {
|
||||
switch (opcode) {
|
||||
case OPCODE_COMPARE_EQ:
|
||||
return a->constant.i32 == b->constant.i32;
|
||||
case OPCODE_COMPARE_NE:
|
||||
return a->constant.i32 != b->constant.i32;
|
||||
case OPCODE_COMPARE_SLT:
|
||||
return a->constant.i32 < b->constant.i32;
|
||||
case OPCODE_COMPARE_SLE:
|
||||
return a->constant.i32 <= b->constant.i32;
|
||||
case OPCODE_COMPARE_SGT:
|
||||
return a->constant.i32 > b->constant.i32;
|
||||
case OPCODE_COMPARE_SGE:
|
||||
return a->constant.i32 >= b->constant.i32;
|
||||
case OPCODE_COMPARE_ULT:
|
||||
return uint32_t(a->constant.i32) < uint32_t(b->constant.i32);
|
||||
case OPCODE_COMPARE_ULE:
|
||||
return uint32_t(a->constant.i32) <= uint32_t(b->constant.i32);
|
||||
case OPCODE_COMPARE_UGT:
|
||||
return uint32_t(a->constant.i32) > uint32_t(b->constant.i32);
|
||||
case OPCODE_COMPARE_UGE:
|
||||
return uint32_t(a->constant.i32) >= uint32_t(b->constant.i32);
|
||||
default:
|
||||
assert_unhandled_case(opcode);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool Value::CompareInt64(Opcode opcode, Value* a, Value* b) {
|
||||
switch (opcode) {
|
||||
case OPCODE_COMPARE_EQ:
|
||||
return a->constant.i64 == b->constant.i64;
|
||||
case OPCODE_COMPARE_NE:
|
||||
return a->constant.i64 != b->constant.i64;
|
||||
case OPCODE_COMPARE_SLT:
|
||||
return a->constant.i64 < b->constant.i64;
|
||||
case OPCODE_COMPARE_SLE:
|
||||
return a->constant.i64 <= b->constant.i64;
|
||||
case OPCODE_COMPARE_SGT:
|
||||
return a->constant.i64 > b->constant.i64;
|
||||
case OPCODE_COMPARE_SGE:
|
||||
return a->constant.i64 >= b->constant.i64;
|
||||
case OPCODE_COMPARE_ULT:
|
||||
return uint64_t(a->constant.i64) < uint64_t(b->constant.i64);
|
||||
case OPCODE_COMPARE_ULE:
|
||||
return uint64_t(a->constant.i64) <= uint64_t(b->constant.i64);
|
||||
case OPCODE_COMPARE_UGT:
|
||||
return uint64_t(a->constant.i64) > uint64_t(b->constant.i64);
|
||||
case OPCODE_COMPARE_UGE:
|
||||
return uint64_t(a->constant.i64) >= uint64_t(b->constant.i64);
|
||||
default:
|
||||
assert_unhandled_case(opcode);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace hir
|
||||
|
||||
@@ -403,6 +403,12 @@ class Value {
|
||||
void ByteSwap();
|
||||
void CountLeadingZeros(const Value* other);
|
||||
bool Compare(Opcode opcode, Value* other);
|
||||
|
||||
private:
|
||||
static bool CompareInt8(Opcode opcode, Value* a, Value* b);
|
||||
static bool CompareInt16(Opcode opcode, Value* a, Value* b);
|
||||
static bool CompareInt32(Opcode opcode, Value* a, Value* b);
|
||||
static bool CompareInt64(Opcode opcode, Value* a, Value* b);
|
||||
};
|
||||
|
||||
} // namespace hir
|
||||
|
||||
Reference in New Issue
Block a user