OPCODE_IS_NAN

This commit is contained in:
Dr. Chat 2016-07-11 20:44:12 -05:00
parent fb87b7a3c3
commit 18ff97e6b6
6 changed files with 48 additions and 0 deletions

View File

@ -2909,6 +2909,24 @@ struct IS_FALSE_V128
EMITTER_OPCODE_TABLE(OPCODE_IS_FALSE, IS_FALSE_I8, IS_FALSE_I16, IS_FALSE_I32, EMITTER_OPCODE_TABLE(OPCODE_IS_FALSE, IS_FALSE_I8, IS_FALSE_I16, IS_FALSE_I32,
IS_FALSE_I64, IS_FALSE_F32, IS_FALSE_F64, IS_FALSE_V128); IS_FALSE_I64, IS_FALSE_F32, IS_FALSE_F64, IS_FALSE_V128);
// ============================================================================
// OPCODE_IS_NAN
// ============================================================================
struct IS_NAN_F32 : Sequence<IS_NAN_F32, I<OPCODE_IS_NAN, I8Op, F32Op>> {
static void Emit(X64Emitter& e, const EmitArgType& i) {
e.vucomiss(i.src1, i.src1);
e.setp(i.dest);
}
};
struct IS_NAN_F64 : Sequence<IS_NAN_F64, I<OPCODE_IS_NAN, I8Op, F64Op>> {
static void Emit(X64Emitter& e, const EmitArgType& i) {
e.vucomisd(i.src1, i.src1);
e.setp(i.dest);
}
};
EMITTER_OPCODE_TABLE(OPCODE_IS_NAN, IS_NAN_F32, IS_NAN_F64);
// ============================================================================ // ============================================================================
// OPCODE_COMPARE_EQ // OPCODE_COMPARE_EQ
// ============================================================================ // ============================================================================
@ -7566,6 +7584,7 @@ void RegisterSequences() {
Register_OPCODE_SELECT(); Register_OPCODE_SELECT();
Register_OPCODE_IS_TRUE(); Register_OPCODE_IS_TRUE();
Register_OPCODE_IS_FALSE(); Register_OPCODE_IS_FALSE();
Register_OPCODE_IS_NAN();
Register_OPCODE_COMPARE_EQ(); Register_OPCODE_COMPARE_EQ();
Register_OPCODE_COMPARE_NE(); Register_OPCODE_COMPARE_NE();
Register_OPCODE_COMPARE_SLT(); Register_OPCODE_COMPARE_SLT();

View File

@ -300,6 +300,20 @@ bool ConstantPropagationPass::Run(HIRBuilder* builder) {
i->Remove(); i->Remove();
} }
break; break;
case OPCODE_IS_NAN:
if (i->src1.value->IsConstant()) {
if (i->src1.value->type == FLOAT32_TYPE &&
isnan(i->src1.value->constant.f32)) {
v->set_constant(uint8_t(1));
} else if (i->src1.value->type == FLOAT64_TYPE &&
isnan(i->src1.value->constant.f64)) {
v->set_constant(uint8_t(1));
} else {
v->set_constant(uint8_t(0));
}
i->Remove();
}
break;
// TODO(benvanik): compares // TODO(benvanik): compares
case OPCODE_COMPARE_EQ: case OPCODE_COMPARE_EQ:

View File

@ -1362,6 +1362,13 @@ Value* HIRBuilder::IsFalse(Value* value) {
return i->dest; return i->dest;
} }
Value* HIRBuilder::IsNan(Value* value) {
Instr* i = AppendInstr(OPCODE_IS_NAN_info, 0, AllocValue(INT8_TYPE));
i->set_src1(value);
i->src2.value = i->src3.value = NULL;
return i->dest;
}
Value* HIRBuilder::CompareXX(const OpcodeInfo& opcode, Value* value1, Value* HIRBuilder::CompareXX(const OpcodeInfo& opcode, Value* value1,
Value* value2) { Value* value2) {
ASSERT_TYPES_EQUAL(value1, value2); ASSERT_TYPES_EQUAL(value1, value2);

View File

@ -162,6 +162,7 @@ class HIRBuilder {
Value* Select(Value* cond, Value* value1, Value* value2); Value* Select(Value* cond, Value* value1, Value* value2);
Value* IsTrue(Value* value); Value* IsTrue(Value* value);
Value* IsFalse(Value* value); Value* IsFalse(Value* value);
Value* IsNan(Value* value);
Value* CompareEQ(Value* value1, Value* value2); Value* CompareEQ(Value* value1, Value* value2);
Value* CompareNE(Value* value1, Value* value2); Value* CompareNE(Value* value1, Value* value2);
Value* CompareSLT(Value* value1, Value* value2); Value* CompareSLT(Value* value1, Value* value2);

View File

@ -164,6 +164,7 @@ enum Opcode {
OPCODE_SELECT, OPCODE_SELECT,
OPCODE_IS_TRUE, OPCODE_IS_TRUE,
OPCODE_IS_FALSE, OPCODE_IS_FALSE,
OPCODE_IS_NAN,
OPCODE_COMPARE_EQ, OPCODE_COMPARE_EQ,
OPCODE_COMPARE_NE, OPCODE_COMPARE_NE,
OPCODE_COMPARE_SLT, OPCODE_COMPARE_SLT,

View File

@ -303,6 +303,12 @@ DEFINE_OPCODE(
OPCODE_SIG_V_V, OPCODE_SIG_V_V,
0) 0)
DEFINE_OPCODE(
OPCODE_IS_NAN,
"is_nan",
OPCODE_SIG_V_V,
0)
DEFINE_OPCODE( DEFINE_OPCODE(
OPCODE_COMPARE_EQ, OPCODE_COMPARE_EQ,
"compare_eq", "compare_eq",