Trying out a new style of JIT pattern matching.
This commit is contained in:
39
src/alloy/hir/block.cc
Normal file
39
src/alloy/hir/block.cc
Normal file
@@ -0,0 +1,39 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* Xenia : Xbox 360 Emulator Research Project *
|
||||
******************************************************************************
|
||||
* Copyright 2014 Ben Vanik. All rights reserved. *
|
||||
* Released under the BSD license - see LICENSE in the root for more details. *
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
#include <alloy/hir/block.h>
|
||||
|
||||
#include <alloy/hir/instr.h>
|
||||
|
||||
using namespace alloy;
|
||||
using namespace alloy::hir;
|
||||
|
||||
|
||||
void Block::AssertNoCycles() {
|
||||
Instr* hare = instr_head;
|
||||
Instr* tortoise = instr_head;
|
||||
if (!hare) {
|
||||
return;
|
||||
}
|
||||
while (hare = hare->next) {
|
||||
if (hare == tortoise) {
|
||||
// Cycle!
|
||||
XEASSERTALWAYS();
|
||||
}
|
||||
hare = hare->next;
|
||||
if (hare == tortoise) {
|
||||
// Cycle!
|
||||
XEASSERTALWAYS();
|
||||
}
|
||||
tortoise = tortoise->next;
|
||||
if (!hare || !tortoise) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -61,6 +61,8 @@ public:
|
||||
Instr* instr_tail;
|
||||
|
||||
uint16_t ordinal;
|
||||
|
||||
void AssertNoCycles();
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -92,7 +92,7 @@ void HIRBuilder::DumpValue(StringBuffer* str, Value* value) {
|
||||
case INT8_TYPE: str->Append("%X", value->constant.i8); break;
|
||||
case INT16_TYPE: str->Append("%X", value->constant.i16); break;
|
||||
case INT32_TYPE: str->Append("%X", value->constant.i32); break;
|
||||
case INT64_TYPE: str->Append("%X", value->constant.i64); break;
|
||||
case INT64_TYPE: str->Append("%llX", value->constant.i64); break;
|
||||
case FLOAT32_TYPE: str->Append("%F", value->constant.f32); break;
|
||||
case FLOAT64_TYPE: str->Append("%F", value->constant.f64); break;
|
||||
case VEC128_TYPE: str->Append("(%F,%F,%F,%F)",
|
||||
@@ -252,6 +252,29 @@ void HIRBuilder::Dump(StringBuffer* str) {
|
||||
}
|
||||
}
|
||||
|
||||
void HIRBuilder::AssertNoCycles() {
|
||||
Block* hare = block_head_;
|
||||
Block* tortoise = block_head_;
|
||||
if (!hare) {
|
||||
return;
|
||||
}
|
||||
while (hare = hare->next) {
|
||||
if (hare == tortoise) {
|
||||
// Cycle!
|
||||
XEASSERTALWAYS();
|
||||
}
|
||||
hare = hare->next;
|
||||
if (hare == tortoise) {
|
||||
// Cycle!
|
||||
XEASSERTALWAYS();
|
||||
}
|
||||
tortoise = tortoise->next;
|
||||
if (!hare || !tortoise) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Block* HIRBuilder::current_block() const {
|
||||
return current_block_;
|
||||
}
|
||||
@@ -1729,16 +1752,19 @@ Value* HIRBuilder::Extract(Value* value, Value* index,
|
||||
TypeName target_type) {
|
||||
// TODO(benvanik): could do some of this as constants.
|
||||
|
||||
Value* trunc_index = index->type != INT8_TYPE ?
|
||||
Truncate(index, INT8_TYPE) : index;
|
||||
|
||||
Instr* i = AppendInstr(
|
||||
OPCODE_EXTRACT_info, 0,
|
||||
AllocValue(target_type));
|
||||
i->set_src1(value);
|
||||
i->set_src2(ZeroExtend(index, INT64_TYPE));
|
||||
i->set_src2(trunc_index);
|
||||
i->src3.value = NULL;
|
||||
return i->dest;
|
||||
}
|
||||
|
||||
Value* HIRBuilder::Extract(Value* value, uint64_t index,
|
||||
Value* HIRBuilder::Extract(Value* value, uint8_t index,
|
||||
TypeName target_type) {
|
||||
return Extract(value, LoadConstant(index), target_type);
|
||||
}
|
||||
|
||||
@@ -35,6 +35,7 @@ public:
|
||||
virtual int Finalize();
|
||||
|
||||
void Dump(StringBuffer* str);
|
||||
void AssertNoCycles();
|
||||
|
||||
Arena* arena() const { return arena_; }
|
||||
|
||||
@@ -196,7 +197,7 @@ public:
|
||||
Value* Insert(Value* value, Value* index, Value* part);
|
||||
Value* Insert(Value* value, uint64_t index, Value* part);
|
||||
Value* Extract(Value* value, Value* index, TypeName target_type);
|
||||
Value* Extract(Value* value, uint64_t index, TypeName target_type);
|
||||
Value* Extract(Value* value, uint8_t index, TypeName target_type);
|
||||
// i8->i16/i32/... (i8|i8 / i8|i8|i8|i8 / ...)
|
||||
// i8/i16/i32 -> vec128
|
||||
Value* Splat(Value* value, TypeName target_type);
|
||||
|
||||
@@ -48,19 +48,6 @@ void Instr::set_src3(Value* value) {
|
||||
src3_use = value ? value->AddUse(block->arena, this) : NULL;
|
||||
}
|
||||
|
||||
bool Instr::Match(SignatureType dest_req,
|
||||
SignatureType src1_req,
|
||||
SignatureType src2_req,
|
||||
SignatureType src3_req) const {
|
||||
#define TO_SIG_TYPE(v) \
|
||||
(v ? (v->IsConstant() ? SignatureType((v->type + 1) | SIG_TYPE_C) : SignatureType(v->type + 1)) : SIG_TYPE_X)
|
||||
return
|
||||
((dest_req == SIG_TYPE_IGNORE) || (dest_req == TO_SIG_TYPE(dest))) &&
|
||||
((src1_req == SIG_TYPE_IGNORE) || (src1_req == TO_SIG_TYPE(src1.value))) &&
|
||||
((src2_req == SIG_TYPE_IGNORE) || (src2_req == TO_SIG_TYPE(src2.value))) &&
|
||||
((src3_req == SIG_TYPE_IGNORE) || (src3_req == TO_SIG_TYPE(src3.value)));
|
||||
}
|
||||
|
||||
void Instr::MoveBefore(Instr* other) {
|
||||
if (next == other) {
|
||||
return;
|
||||
|
||||
@@ -24,26 +24,6 @@ namespace hir {
|
||||
class Block;
|
||||
class Label;
|
||||
|
||||
enum SignatureType {
|
||||
SIG_TYPE_X = 0,
|
||||
SIG_TYPE_I8 = 1,
|
||||
SIG_TYPE_I16 = 2,
|
||||
SIG_TYPE_I32 = 3,
|
||||
SIG_TYPE_I64 = 4,
|
||||
SIG_TYPE_F32 = 5,
|
||||
SIG_TYPE_F64 = 6,
|
||||
SIG_TYPE_V128 = 7,
|
||||
SIG_TYPE_C = (1 << 3),
|
||||
SIG_TYPE_I8C = SIG_TYPE_C | SIG_TYPE_I8,
|
||||
SIG_TYPE_I16C = SIG_TYPE_C | SIG_TYPE_I16,
|
||||
SIG_TYPE_I32C = SIG_TYPE_C | SIG_TYPE_I32,
|
||||
SIG_TYPE_I64C = SIG_TYPE_C | SIG_TYPE_I64,
|
||||
SIG_TYPE_F32C = SIG_TYPE_C | SIG_TYPE_F32,
|
||||
SIG_TYPE_F64C = SIG_TYPE_C | SIG_TYPE_F64,
|
||||
SIG_TYPE_V128C = SIG_TYPE_C | SIG_TYPE_V128,
|
||||
SIG_TYPE_IGNORE = 0xFF,
|
||||
};
|
||||
|
||||
class Instr {
|
||||
public:
|
||||
Block* block;
|
||||
@@ -74,11 +54,6 @@ public:
|
||||
void set_src2(Value* value);
|
||||
void set_src3(Value* value);
|
||||
|
||||
bool Match(SignatureType dest = SIG_TYPE_X,
|
||||
SignatureType src1 = SIG_TYPE_X,
|
||||
SignatureType src2 = SIG_TYPE_X,
|
||||
SignatureType src3 = SIG_TYPE_X) const;
|
||||
|
||||
void MoveBefore(Instr* other);
|
||||
void Replace(const OpcodeInfo* opcode, uint16_t flags);
|
||||
void Remove();
|
||||
|
||||
@@ -11,590 +11,590 @@
|
||||
DEFINE_OPCODE(
|
||||
OPCODE_COMMENT,
|
||||
"comment",
|
||||
OPCODE_SIG_X,
|
||||
OPCODE_FLAG_IGNORE);
|
||||
OPCODE_SIG_X_O,
|
||||
OPCODE_FLAG_IGNORE)
|
||||
|
||||
DEFINE_OPCODE(
|
||||
OPCODE_NOP,
|
||||
"nop",
|
||||
OPCODE_SIG_X,
|
||||
OPCODE_FLAG_IGNORE);
|
||||
OPCODE_FLAG_IGNORE)
|
||||
|
||||
DEFINE_OPCODE(
|
||||
OPCODE_SOURCE_OFFSET,
|
||||
"source_offset",
|
||||
OPCODE_SIG_X_O,
|
||||
OPCODE_FLAG_IGNORE | OPCODE_FLAG_HIDE);
|
||||
OPCODE_FLAG_IGNORE | OPCODE_FLAG_HIDE)
|
||||
|
||||
DEFINE_OPCODE(
|
||||
OPCODE_DEBUG_BREAK,
|
||||
"debug_break",
|
||||
OPCODE_SIG_X,
|
||||
OPCODE_FLAG_VOLATILE);
|
||||
OPCODE_FLAG_VOLATILE)
|
||||
|
||||
DEFINE_OPCODE(
|
||||
OPCODE_DEBUG_BREAK_TRUE,
|
||||
"debug_break_true",
|
||||
OPCODE_SIG_X_V,
|
||||
OPCODE_FLAG_VOLATILE);
|
||||
OPCODE_FLAG_VOLATILE)
|
||||
|
||||
DEFINE_OPCODE(
|
||||
OPCODE_TRAP,
|
||||
"trap",
|
||||
OPCODE_SIG_X,
|
||||
OPCODE_FLAG_VOLATILE);
|
||||
OPCODE_FLAG_VOLATILE)
|
||||
|
||||
DEFINE_OPCODE(
|
||||
OPCODE_TRAP_TRUE,
|
||||
"trap_true",
|
||||
OPCODE_SIG_X_V,
|
||||
OPCODE_FLAG_VOLATILE);
|
||||
OPCODE_FLAG_VOLATILE)
|
||||
|
||||
DEFINE_OPCODE(
|
||||
OPCODE_CALL,
|
||||
"call",
|
||||
OPCODE_SIG_X_S,
|
||||
OPCODE_FLAG_BRANCH);
|
||||
OPCODE_FLAG_BRANCH)
|
||||
|
||||
DEFINE_OPCODE(
|
||||
OPCODE_CALL_TRUE,
|
||||
"call_true",
|
||||
OPCODE_SIG_X_V_S,
|
||||
OPCODE_FLAG_BRANCH);
|
||||
OPCODE_FLAG_BRANCH)
|
||||
|
||||
DEFINE_OPCODE(
|
||||
OPCODE_CALL_INDIRECT,
|
||||
"call_indirect",
|
||||
OPCODE_SIG_X_V,
|
||||
OPCODE_FLAG_BRANCH);
|
||||
OPCODE_FLAG_BRANCH)
|
||||
|
||||
DEFINE_OPCODE(
|
||||
OPCODE_CALL_INDIRECT_TRUE,
|
||||
"call_indirect_true",
|
||||
OPCODE_SIG_X_V_V,
|
||||
OPCODE_FLAG_BRANCH);
|
||||
OPCODE_FLAG_BRANCH)
|
||||
|
||||
DEFINE_OPCODE(
|
||||
OPCODE_CALL_EXTERN,
|
||||
"call_extern",
|
||||
OPCODE_SIG_X_S,
|
||||
OPCODE_FLAG_BRANCH);
|
||||
OPCODE_FLAG_BRANCH)
|
||||
|
||||
DEFINE_OPCODE(
|
||||
OPCODE_RETURN,
|
||||
"return",
|
||||
OPCODE_SIG_X,
|
||||
OPCODE_FLAG_BRANCH);
|
||||
OPCODE_FLAG_BRANCH)
|
||||
|
||||
DEFINE_OPCODE(
|
||||
OPCODE_RETURN_TRUE,
|
||||
"return_true",
|
||||
OPCODE_SIG_X_V,
|
||||
OPCODE_FLAG_BRANCH);
|
||||
OPCODE_FLAG_BRANCH)
|
||||
|
||||
DEFINE_OPCODE(
|
||||
OPCODE_SET_RETURN_ADDRESS,
|
||||
"set_return_address",
|
||||
OPCODE_SIG_X_V,
|
||||
0);
|
||||
0)
|
||||
|
||||
DEFINE_OPCODE(
|
||||
OPCODE_BRANCH,
|
||||
"branch",
|
||||
OPCODE_SIG_X_L,
|
||||
OPCODE_FLAG_BRANCH);
|
||||
OPCODE_FLAG_BRANCH)
|
||||
|
||||
DEFINE_OPCODE(
|
||||
OPCODE_BRANCH_TRUE,
|
||||
"branch_true",
|
||||
OPCODE_SIG_X_V_L,
|
||||
OPCODE_FLAG_BRANCH);
|
||||
OPCODE_FLAG_BRANCH)
|
||||
|
||||
DEFINE_OPCODE(
|
||||
OPCODE_BRANCH_FALSE,
|
||||
"branch_false",
|
||||
OPCODE_SIG_X_V_L,
|
||||
OPCODE_FLAG_BRANCH);
|
||||
OPCODE_FLAG_BRANCH)
|
||||
|
||||
DEFINE_OPCODE(
|
||||
OPCODE_ASSIGN,
|
||||
"assign",
|
||||
OPCODE_SIG_V_V,
|
||||
0);
|
||||
0)
|
||||
|
||||
DEFINE_OPCODE(
|
||||
OPCODE_CAST,
|
||||
"cast",
|
||||
OPCODE_SIG_V_V,
|
||||
0);
|
||||
0)
|
||||
|
||||
DEFINE_OPCODE(
|
||||
OPCODE_ZERO_EXTEND,
|
||||
"zero_extend",
|
||||
OPCODE_SIG_V_V,
|
||||
0);
|
||||
0)
|
||||
|
||||
DEFINE_OPCODE(
|
||||
OPCODE_SIGN_EXTEND,
|
||||
"sign_extend",
|
||||
OPCODE_SIG_V_V,
|
||||
0);
|
||||
0)
|
||||
|
||||
DEFINE_OPCODE(
|
||||
OPCODE_TRUNCATE,
|
||||
"truncate",
|
||||
OPCODE_SIG_V_V,
|
||||
0);
|
||||
0)
|
||||
|
||||
DEFINE_OPCODE(
|
||||
OPCODE_CONVERT,
|
||||
"convert",
|
||||
OPCODE_SIG_V_V,
|
||||
0);
|
||||
0)
|
||||
|
||||
DEFINE_OPCODE(
|
||||
OPCODE_ROUND,
|
||||
"round",
|
||||
OPCODE_SIG_V_V,
|
||||
0);
|
||||
0)
|
||||
|
||||
DEFINE_OPCODE(
|
||||
OPCODE_VECTOR_CONVERT_I2F,
|
||||
"vector_convert_i2f",
|
||||
OPCODE_SIG_V_V,
|
||||
0);
|
||||
0)
|
||||
|
||||
DEFINE_OPCODE(
|
||||
OPCODE_VECTOR_CONVERT_F2I,
|
||||
"vector_convert_f2i",
|
||||
OPCODE_SIG_V_V,
|
||||
0);
|
||||
0)
|
||||
|
||||
DEFINE_OPCODE(
|
||||
OPCODE_LOAD_VECTOR_SHL,
|
||||
"load_vector_shl",
|
||||
OPCODE_SIG_V_V,
|
||||
0);
|
||||
0)
|
||||
|
||||
DEFINE_OPCODE(
|
||||
OPCODE_LOAD_VECTOR_SHR,
|
||||
"load_vector_shr",
|
||||
OPCODE_SIG_V_V,
|
||||
0);
|
||||
0)
|
||||
|
||||
DEFINE_OPCODE(
|
||||
OPCODE_LOAD_CLOCK,
|
||||
"load_clock",
|
||||
OPCODE_SIG_V,
|
||||
0);
|
||||
0)
|
||||
|
||||
DEFINE_OPCODE(
|
||||
OPCODE_LOAD_LOCAL,
|
||||
"load_local",
|
||||
OPCODE_SIG_V_V,
|
||||
0);
|
||||
0)
|
||||
|
||||
DEFINE_OPCODE(
|
||||
OPCODE_STORE_LOCAL,
|
||||
"store_local",
|
||||
OPCODE_SIG_X_V_V,
|
||||
0);
|
||||
0)
|
||||
|
||||
DEFINE_OPCODE(
|
||||
OPCODE_LOAD_CONTEXT,
|
||||
"load_context",
|
||||
OPCODE_SIG_V_O,
|
||||
0);
|
||||
0)
|
||||
|
||||
DEFINE_OPCODE(
|
||||
OPCODE_STORE_CONTEXT,
|
||||
"store_context",
|
||||
OPCODE_SIG_X_O_V,
|
||||
0);
|
||||
0)
|
||||
|
||||
DEFINE_OPCODE(
|
||||
OPCODE_LOAD,
|
||||
"load",
|
||||
OPCODE_SIG_V_V,
|
||||
OPCODE_FLAG_MEMORY);
|
||||
OPCODE_FLAG_MEMORY)
|
||||
|
||||
DEFINE_OPCODE(
|
||||
OPCODE_STORE,
|
||||
"store",
|
||||
OPCODE_SIG_X_V_V,
|
||||
OPCODE_FLAG_MEMORY);
|
||||
OPCODE_FLAG_MEMORY)
|
||||
|
||||
DEFINE_OPCODE(
|
||||
OPCODE_PREFETCH,
|
||||
"prefetch",
|
||||
OPCODE_SIG_X_V_O,
|
||||
0);
|
||||
0)
|
||||
|
||||
DEFINE_OPCODE(
|
||||
OPCODE_MAX,
|
||||
"max",
|
||||
OPCODE_SIG_V_V_V,
|
||||
0);
|
||||
0)
|
||||
|
||||
DEFINE_OPCODE(
|
||||
OPCODE_MIN,
|
||||
"min",
|
||||
OPCODE_SIG_V_V_V,
|
||||
0);
|
||||
0)
|
||||
|
||||
DEFINE_OPCODE(
|
||||
OPCODE_SELECT,
|
||||
"select",
|
||||
OPCODE_SIG_V_V_V_V,
|
||||
0);
|
||||
0)
|
||||
|
||||
DEFINE_OPCODE(
|
||||
OPCODE_IS_TRUE,
|
||||
"is_true",
|
||||
OPCODE_SIG_V_V,
|
||||
0);
|
||||
0)
|
||||
|
||||
DEFINE_OPCODE(
|
||||
OPCODE_IS_FALSE,
|
||||
"is_false",
|
||||
OPCODE_SIG_V_V,
|
||||
0);
|
||||
0)
|
||||
|
||||
DEFINE_OPCODE(
|
||||
OPCODE_COMPARE_EQ,
|
||||
"compare_eq",
|
||||
OPCODE_SIG_V_V_V,
|
||||
OPCODE_FLAG_COMMUNATIVE);
|
||||
OPCODE_FLAG_COMMUNATIVE)
|
||||
DEFINE_OPCODE(
|
||||
OPCODE_COMPARE_NE,
|
||||
"compare_ne",
|
||||
OPCODE_SIG_V_V_V,
|
||||
OPCODE_FLAG_COMMUNATIVE);
|
||||
OPCODE_FLAG_COMMUNATIVE)
|
||||
DEFINE_OPCODE(
|
||||
OPCODE_COMPARE_SLT,
|
||||
"compare_slt",
|
||||
OPCODE_SIG_V_V_V,
|
||||
0);
|
||||
0)
|
||||
DEFINE_OPCODE(
|
||||
OPCODE_COMPARE_SLE,
|
||||
"compare_sle",
|
||||
OPCODE_SIG_V_V_V,
|
||||
0);
|
||||
0)
|
||||
DEFINE_OPCODE(
|
||||
OPCODE_COMPARE_SGT,
|
||||
"compare_sgt",
|
||||
OPCODE_SIG_V_V_V,
|
||||
0);
|
||||
0)
|
||||
DEFINE_OPCODE(
|
||||
OPCODE_COMPARE_SGE,
|
||||
"compare_sge",
|
||||
OPCODE_SIG_V_V_V,
|
||||
0);
|
||||
0)
|
||||
DEFINE_OPCODE(
|
||||
OPCODE_COMPARE_ULT,
|
||||
"compare_ult",
|
||||
OPCODE_SIG_V_V_V,
|
||||
0);
|
||||
0)
|
||||
DEFINE_OPCODE(
|
||||
OPCODE_COMPARE_ULE,
|
||||
"compare_ule",
|
||||
OPCODE_SIG_V_V_V,
|
||||
0);
|
||||
0)
|
||||
DEFINE_OPCODE(
|
||||
OPCODE_COMPARE_UGT,
|
||||
"compare_ugt",
|
||||
OPCODE_SIG_V_V_V,
|
||||
0);
|
||||
0)
|
||||
DEFINE_OPCODE(
|
||||
OPCODE_COMPARE_UGE,
|
||||
"compare_uge",
|
||||
OPCODE_SIG_V_V_V,
|
||||
0);
|
||||
0)
|
||||
|
||||
DEFINE_OPCODE(
|
||||
OPCODE_DID_CARRY,
|
||||
"did_carry",
|
||||
OPCODE_SIG_V_V,
|
||||
OPCODE_FLAG_PAIRED_PREV);
|
||||
OPCODE_FLAG_PAIRED_PREV)
|
||||
DEFINE_OPCODE(
|
||||
OPCODE_DID_OVERFLOW,
|
||||
"did_overflow",
|
||||
OPCODE_SIG_V_V,
|
||||
OPCODE_FLAG_PAIRED_PREV);
|
||||
OPCODE_FLAG_PAIRED_PREV)
|
||||
DEFINE_OPCODE(
|
||||
OPCODE_DID_SATURATE,
|
||||
"did_saturate",
|
||||
OPCODE_SIG_V_V,
|
||||
OPCODE_FLAG_PAIRED_PREV);
|
||||
OPCODE_FLAG_PAIRED_PREV)
|
||||
|
||||
DEFINE_OPCODE(
|
||||
OPCODE_VECTOR_COMPARE_EQ,
|
||||
"vector_compare_eq",
|
||||
OPCODE_SIG_V_V_V,
|
||||
OPCODE_FLAG_COMMUNATIVE);
|
||||
OPCODE_FLAG_COMMUNATIVE)
|
||||
DEFINE_OPCODE(
|
||||
OPCODE_VECTOR_COMPARE_SGT,
|
||||
"vector_compare_sgt",
|
||||
OPCODE_SIG_V_V_V,
|
||||
0);
|
||||
0)
|
||||
DEFINE_OPCODE(
|
||||
OPCODE_VECTOR_COMPARE_SGE,
|
||||
"vector_compare_sge",
|
||||
OPCODE_SIG_V_V_V,
|
||||
0);
|
||||
0)
|
||||
DEFINE_OPCODE(
|
||||
OPCODE_VECTOR_COMPARE_UGT,
|
||||
"vector_compare_ugt",
|
||||
OPCODE_SIG_V_V_V,
|
||||
0);
|
||||
0)
|
||||
DEFINE_OPCODE(
|
||||
OPCODE_VECTOR_COMPARE_UGE,
|
||||
"vector_compare_uge",
|
||||
OPCODE_SIG_V_V_V,
|
||||
0);
|
||||
0)
|
||||
|
||||
DEFINE_OPCODE(
|
||||
OPCODE_ADD,
|
||||
"add",
|
||||
OPCODE_SIG_V_V_V,
|
||||
OPCODE_FLAG_COMMUNATIVE);
|
||||
OPCODE_FLAG_COMMUNATIVE)
|
||||
|
||||
DEFINE_OPCODE(
|
||||
OPCODE_ADD_CARRY,
|
||||
"add_carry",
|
||||
OPCODE_SIG_V_V_V_V,
|
||||
0);
|
||||
0)
|
||||
|
||||
DEFINE_OPCODE(
|
||||
OPCODE_VECTOR_ADD,
|
||||
"vector_add",
|
||||
OPCODE_SIG_V_V_V,
|
||||
OPCODE_FLAG_COMMUNATIVE);
|
||||
OPCODE_FLAG_COMMUNATIVE)
|
||||
|
||||
DEFINE_OPCODE(
|
||||
OPCODE_SUB,
|
||||
"sub",
|
||||
OPCODE_SIG_V_V_V,
|
||||
0);
|
||||
0)
|
||||
|
||||
DEFINE_OPCODE(
|
||||
OPCODE_MUL,
|
||||
"mul",
|
||||
OPCODE_SIG_V_V_V,
|
||||
OPCODE_FLAG_COMMUNATIVE);
|
||||
OPCODE_FLAG_COMMUNATIVE)
|
||||
|
||||
DEFINE_OPCODE(
|
||||
OPCODE_MUL_HI,
|
||||
"mul_hi",
|
||||
OPCODE_SIG_V_V_V,
|
||||
OPCODE_FLAG_COMMUNATIVE);
|
||||
OPCODE_FLAG_COMMUNATIVE)
|
||||
|
||||
DEFINE_OPCODE(
|
||||
OPCODE_DIV,
|
||||
"div",
|
||||
OPCODE_SIG_V_V_V,
|
||||
0);
|
||||
0)
|
||||
|
||||
DEFINE_OPCODE(
|
||||
OPCODE_MUL_ADD,
|
||||
"mul_add",
|
||||
OPCODE_SIG_V_V_V_V,
|
||||
0);
|
||||
0)
|
||||
|
||||
DEFINE_OPCODE(
|
||||
OPCODE_MUL_SUB,
|
||||
"mul_sub",
|
||||
OPCODE_SIG_V_V_V_V,
|
||||
0);
|
||||
0)
|
||||
|
||||
DEFINE_OPCODE(
|
||||
OPCODE_NEG,
|
||||
"neg",
|
||||
OPCODE_SIG_V_V,
|
||||
0);
|
||||
0)
|
||||
|
||||
DEFINE_OPCODE(
|
||||
OPCODE_ABS,
|
||||
"abs",
|
||||
OPCODE_SIG_V_V,
|
||||
0);
|
||||
0)
|
||||
|
||||
DEFINE_OPCODE(
|
||||
OPCODE_SQRT,
|
||||
"sqrt",
|
||||
OPCODE_SIG_V_V,
|
||||
0);
|
||||
0)
|
||||
|
||||
DEFINE_OPCODE(
|
||||
OPCODE_RSQRT,
|
||||
"rsqrt",
|
||||
OPCODE_SIG_V_V,
|
||||
0);
|
||||
0)
|
||||
|
||||
DEFINE_OPCODE(
|
||||
OPCODE_POW2,
|
||||
"pow2",
|
||||
OPCODE_SIG_V_V,
|
||||
0);
|
||||
0)
|
||||
|
||||
DEFINE_OPCODE(
|
||||
OPCODE_LOG2,
|
||||
"log2",
|
||||
OPCODE_SIG_V_V,
|
||||
0);
|
||||
0)
|
||||
|
||||
DEFINE_OPCODE(
|
||||
OPCODE_DOT_PRODUCT_3,
|
||||
"dot_product_3",
|
||||
OPCODE_SIG_V_V_V,
|
||||
0);
|
||||
0)
|
||||
|
||||
DEFINE_OPCODE(
|
||||
OPCODE_DOT_PRODUCT_4,
|
||||
"dot_product_4",
|
||||
OPCODE_SIG_V_V_V,
|
||||
0);
|
||||
0)
|
||||
|
||||
DEFINE_OPCODE(
|
||||
OPCODE_AND,
|
||||
"and",
|
||||
OPCODE_SIG_V_V_V,
|
||||
OPCODE_FLAG_COMMUNATIVE);
|
||||
OPCODE_FLAG_COMMUNATIVE)
|
||||
|
||||
DEFINE_OPCODE(
|
||||
OPCODE_OR,
|
||||
"or",
|
||||
OPCODE_SIG_V_V_V,
|
||||
OPCODE_FLAG_COMMUNATIVE);
|
||||
OPCODE_FLAG_COMMUNATIVE)
|
||||
|
||||
DEFINE_OPCODE(
|
||||
OPCODE_XOR,
|
||||
"xor",
|
||||
OPCODE_SIG_V_V_V,
|
||||
OPCODE_FLAG_COMMUNATIVE);
|
||||
OPCODE_FLAG_COMMUNATIVE)
|
||||
|
||||
DEFINE_OPCODE(
|
||||
OPCODE_NOT,
|
||||
"not",
|
||||
OPCODE_SIG_V_V,
|
||||
0);
|
||||
0)
|
||||
|
||||
DEFINE_OPCODE(
|
||||
OPCODE_SHL,
|
||||
"shl",
|
||||
OPCODE_SIG_V_V_V,
|
||||
0);
|
||||
0)
|
||||
|
||||
DEFINE_OPCODE(
|
||||
OPCODE_VECTOR_SHL,
|
||||
"vector_shl",
|
||||
OPCODE_SIG_V_V_V,
|
||||
0);
|
||||
0)
|
||||
|
||||
DEFINE_OPCODE(
|
||||
OPCODE_SHR,
|
||||
"shr",
|
||||
OPCODE_SIG_V_V_V,
|
||||
0);
|
||||
0)
|
||||
|
||||
DEFINE_OPCODE(
|
||||
OPCODE_VECTOR_SHR,
|
||||
"vector_shr",
|
||||
OPCODE_SIG_V_V_V,
|
||||
0);
|
||||
0)
|
||||
|
||||
DEFINE_OPCODE(
|
||||
OPCODE_SHA,
|
||||
"sha",
|
||||
OPCODE_SIG_V_V_V,
|
||||
0);
|
||||
0)
|
||||
|
||||
DEFINE_OPCODE(
|
||||
OPCODE_VECTOR_SHA,
|
||||
"vector_sha",
|
||||
OPCODE_SIG_V_V_V,
|
||||
0);
|
||||
0)
|
||||
|
||||
DEFINE_OPCODE(
|
||||
OPCODE_ROTATE_LEFT,
|
||||
"rotate_left",
|
||||
OPCODE_SIG_V_V_V,
|
||||
0);
|
||||
0)
|
||||
|
||||
DEFINE_OPCODE(
|
||||
OPCODE_BYTE_SWAP,
|
||||
"byte_swap",
|
||||
OPCODE_SIG_V_V,
|
||||
0);
|
||||
0)
|
||||
|
||||
DEFINE_OPCODE(
|
||||
OPCODE_CNTLZ,
|
||||
"cntlz",
|
||||
OPCODE_SIG_V_V,
|
||||
0);
|
||||
0)
|
||||
|
||||
DEFINE_OPCODE(
|
||||
OPCODE_INSERT,
|
||||
"insert",
|
||||
OPCODE_SIG_V_V_V_V,
|
||||
0);
|
||||
0)
|
||||
|
||||
DEFINE_OPCODE(
|
||||
OPCODE_EXTRACT,
|
||||
"extract",
|
||||
OPCODE_SIG_V_V_V,
|
||||
0);
|
||||
0)
|
||||
|
||||
DEFINE_OPCODE(
|
||||
OPCODE_SPLAT,
|
||||
"splat",
|
||||
OPCODE_SIG_V_V,
|
||||
0);
|
||||
0)
|
||||
|
||||
DEFINE_OPCODE(
|
||||
OPCODE_PERMUTE,
|
||||
"permute",
|
||||
OPCODE_SIG_V_V_V_V,
|
||||
0);
|
||||
0)
|
||||
|
||||
DEFINE_OPCODE(
|
||||
OPCODE_SWIZZLE,
|
||||
"swizzle",
|
||||
OPCODE_SIG_V_V_O,
|
||||
0);
|
||||
0)
|
||||
|
||||
DEFINE_OPCODE(
|
||||
OPCODE_PACK,
|
||||
"pack",
|
||||
OPCODE_SIG_V_V,
|
||||
0);
|
||||
0)
|
||||
|
||||
DEFINE_OPCODE(
|
||||
OPCODE_UNPACK,
|
||||
"unpack",
|
||||
OPCODE_SIG_V_V,
|
||||
0);
|
||||
0)
|
||||
|
||||
DEFINE_OPCODE(
|
||||
OPCODE_COMPARE_EXCHANGE,
|
||||
"compare_exchange",
|
||||
OPCODE_SIG_V_V_V_V,
|
||||
OPCODE_FLAG_VOLATILE);
|
||||
OPCODE_FLAG_VOLATILE)
|
||||
|
||||
DEFINE_OPCODE(
|
||||
OPCODE_ATOMIC_EXCHANGE,
|
||||
"atomic_exchange",
|
||||
OPCODE_SIG_V_V_V,
|
||||
OPCODE_FLAG_VOLATILE);
|
||||
OPCODE_FLAG_VOLATILE)
|
||||
|
||||
DEFINE_OPCODE(
|
||||
OPCODE_ATOMIC_ADD,
|
||||
"atomic_add",
|
||||
OPCODE_SIG_V_V_V,
|
||||
0);
|
||||
0)
|
||||
|
||||
DEFINE_OPCODE(
|
||||
OPCODE_ATOMIC_SUB,
|
||||
"atomic_sub",
|
||||
OPCODE_SIG_V_V_V,
|
||||
0);
|
||||
0)
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
# Copyright 2013 Ben Vanik. All Rights Reserved.
|
||||
{
|
||||
'sources': [
|
||||
'block.cc',
|
||||
'block.h',
|
||||
'hir_builder.cc',
|
||||
'hir_builder.h',
|
||||
|
||||
@@ -560,6 +560,26 @@ void Value::ByteSwap() {
|
||||
}
|
||||
}
|
||||
|
||||
void Value::CountLeadingZeros(const ConstantValue& src) {
|
||||
switch (type) {
|
||||
case INT8_TYPE:
|
||||
constant.i8 = __lzcnt16(src.i8) - 8;
|
||||
break;
|
||||
case INT16_TYPE:
|
||||
constant.i8 = __lzcnt16(src.i16);
|
||||
break;
|
||||
case INT32_TYPE:
|
||||
constant.i8 = __lzcnt(src.i32);
|
||||
break;
|
||||
case INT64_TYPE:
|
||||
constant.i8 = __lzcnt64(src.i64);
|
||||
break;
|
||||
default:
|
||||
XEASSERTALWAYS();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
bool Value::Compare(Opcode opcode, Value* other) {
|
||||
// TODO(benvanik): big matrix.
|
||||
XEASSERTALWAYS();
|
||||
|
||||
@@ -68,6 +68,10 @@ enum ValueFlags {
|
||||
VALUE_IS_ALLOCATED = (1 << 2), // Used by backends. Do not set.
|
||||
};
|
||||
|
||||
struct RegAssignment {
|
||||
const backend::MachineInfo::RegisterSet* set;
|
||||
int32_t index;
|
||||
};
|
||||
|
||||
class Value {
|
||||
public:
|
||||
@@ -91,10 +95,7 @@ public:
|
||||
TypeName type;
|
||||
|
||||
uint32_t flags;
|
||||
struct {
|
||||
const backend::MachineInfo::RegisterSet* set;
|
||||
int32_t index;
|
||||
} reg;
|
||||
RegAssignment reg;
|
||||
ConstantValue constant;
|
||||
|
||||
Instr* def;
|
||||
@@ -392,6 +393,7 @@ public:
|
||||
void Shr(Value* other);
|
||||
void Sha(Value* other);
|
||||
void ByteSwap();
|
||||
void CountLeadingZeros(const ConstantValue& src);
|
||||
bool Compare(Opcode opcode, Value* other);
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user