mirror of
https://github.com/php/php-src.git
synced 2026-03-24 00:02:20 +01:00
Update IR
IR commit: 65586bd4cf9cd2d3b41492f52823c5083cea77e4
This commit is contained in:
@@ -75,7 +75,7 @@ const char *ir_op_name[IR_LAST_OP] = {
|
||||
#endif
|
||||
};
|
||||
|
||||
static void ir_print_escaped_str(const char *s, size_t len, FILE *f)
|
||||
void ir_print_escaped_str(const char *s, size_t len, FILE *f)
|
||||
{
|
||||
char ch;
|
||||
|
||||
@@ -95,10 +95,14 @@ static void ir_print_escaped_str(const char *s, size_t len, FILE *f)
|
||||
case '\v': fputs("\\v", f); break;
|
||||
case '\?': fputs("\\?", f); break;
|
||||
default:
|
||||
#ifdef __aarch64__
|
||||
if (ch < 32) {
|
||||
#else
|
||||
if (ch >= 0 && ch < 32) {
|
||||
#endif
|
||||
fprintf(f, "\\%c%c%c",
|
||||
'0' + ((ch >> 3) % 8),
|
||||
'0' + ((ch >> 6) % 8),
|
||||
'0' + ((ch >> 3) % 8),
|
||||
'0' + (ch % 8));
|
||||
break;
|
||||
} else {
|
||||
@@ -1784,48 +1788,64 @@ static ir_alias ir_check_aliasing(ir_ctx *ctx, ir_ref addr1, ir_ref addr2)
|
||||
static ir_alias ir_check_partial_aliasing(const ir_ctx *ctx, ir_ref addr1, ir_ref addr2, ir_type type1, ir_type type2)
|
||||
{
|
||||
ir_insn *insn1, *insn2;
|
||||
ir_ref base1, base2, off1, off2;
|
||||
|
||||
/* this must be already check */
|
||||
IR_ASSERT(addr1 != addr2);
|
||||
|
||||
insn1 = &ctx->ir_base[addr1];
|
||||
insn2 = &ctx->ir_base[addr2];
|
||||
if (insn1->op == IR_ADD && IR_IS_CONST_REF(insn1->op2)) {
|
||||
if (insn1->op1 == addr2) {
|
||||
uintptr_t offset1 = ctx->ir_base[insn1->op2].val.addr;
|
||||
uintptr_t size2 = ir_type_size[type2];
|
||||
if (insn1->op != IR_ADD) {
|
||||
base1 = addr1;
|
||||
off1 = IR_UNUSED;
|
||||
} else if (ctx->ir_base[insn1->op2].op == IR_SYM) {
|
||||
base1 = insn1->op2;
|
||||
off1 = insn1->op1;
|
||||
} else {
|
||||
base1 = insn1->op1;
|
||||
off1 = insn1->op2;
|
||||
}
|
||||
if (insn2->op != IR_ADD) {
|
||||
base2 = addr2;
|
||||
off2 = IR_UNUSED;
|
||||
} else if (ctx->ir_base[insn2->op2].op == IR_SYM) {
|
||||
base2 = insn2->op2;
|
||||
off2 = insn2->op1;
|
||||
} else {
|
||||
base2 = insn2->op1;
|
||||
off2 = insn2->op2;
|
||||
}
|
||||
if (base1 == base2) {
|
||||
uintptr_t offset1, offset2;
|
||||
|
||||
return (offset1 < size2) ? IR_MUST_ALIAS : IR_NO_ALIAS;
|
||||
} else if (insn2->op == IR_ADD && IR_IS_CONST_REF(insn1->op2) && insn1->op1 == insn2->op1) {
|
||||
if (insn1->op2 == insn2->op2) {
|
||||
return IR_MUST_ALIAS;
|
||||
} else if (IR_IS_CONST_REF(insn1->op2) && IR_IS_CONST_REF(insn2->op2)) {
|
||||
uintptr_t offset1 = ctx->ir_base[insn1->op2].val.addr;
|
||||
uintptr_t offset2 = ctx->ir_base[insn2->op2].val.addr;
|
||||
|
||||
if (offset1 == offset2) {
|
||||
return IR_MUST_ALIAS;
|
||||
} else if (type1 == type2) {
|
||||
return IR_NO_ALIAS;
|
||||
} else {
|
||||
/* check for partail intersection */
|
||||
uintptr_t size1 = ir_type_size[type1];
|
||||
uintptr_t size2 = ir_type_size[type2];
|
||||
|
||||
if (offset1 > offset2) {
|
||||
return offset1 < offset2 + size2 ? IR_MUST_ALIAS : IR_NO_ALIAS;
|
||||
} else {
|
||||
return offset2 < offset1 + size1 ? IR_MUST_ALIAS : IR_NO_ALIAS;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!off1) {
|
||||
offset1 = 0;
|
||||
} else if (IR_IS_CONST_REF(off1) && !IR_IS_SYM_CONST(ctx->ir_base[off1].op)) {
|
||||
offset1 = ctx->ir_base[off1].val.addr;
|
||||
} else {
|
||||
return IR_MAY_ALIAS;
|
||||
}
|
||||
} else if (insn2->op == IR_ADD && IR_IS_CONST_REF(insn2->op2)) {
|
||||
if (insn2->op1 == addr1) {
|
||||
uintptr_t offset2 = ctx->ir_base[insn2->op2].val.addr;
|
||||
uintptr_t size1 = ir_type_size[type1];
|
||||
|
||||
return (offset2 < size1) ? IR_MUST_ALIAS : IR_NO_ALIAS;
|
||||
if (!off2) {
|
||||
offset2 = 0;
|
||||
} else if (IR_IS_CONST_REF(off2) && !IR_IS_SYM_CONST(ctx->ir_base[off2].op)) {
|
||||
offset2 = ctx->ir_base[off2].val.addr;
|
||||
} else {
|
||||
return IR_MAY_ALIAS;
|
||||
}
|
||||
if (offset1 == offset2) {
|
||||
return IR_MUST_ALIAS;
|
||||
} else if (offset1 < offset2) {
|
||||
return offset1 + ir_type_size[type1] <= offset2 ? IR_NO_ALIAS : IR_MUST_ALIAS;
|
||||
} else {
|
||||
return offset2 + ir_type_size[type2] <= offset1 ? IR_NO_ALIAS : IR_MUST_ALIAS;
|
||||
}
|
||||
} else {
|
||||
insn1 = &ctx->ir_base[base1];
|
||||
insn2 = &ctx->ir_base[base2];
|
||||
if ((insn1->op == IR_ALLOCA && (insn2->op == IR_ALLOCA || insn2->op == IR_SYM || insn2->op == IR_PARAM))
|
||||
|| (insn1->op == IR_SYM && (insn2->op == IR_ALLOCA || insn2->op == IR_SYM))
|
||||
|| (insn1->op == IR_PARAM && insn2->op == IR_ALLOCA)) {
|
||||
return IR_NO_ALIAS;
|
||||
}
|
||||
}
|
||||
return IR_MAY_ALIAS;
|
||||
|
||||
@@ -513,6 +513,9 @@ void ir_strtab_free(ir_strtab *strtab);
|
||||
#define IR_EXTERN (1<<5)
|
||||
#define IR_CONST (1<<6)
|
||||
|
||||
#define IR_INITIALIZED (1<<7) /* sym data flag: constant or an initialized variable */
|
||||
#define IR_CONST_STRING (1<<8) /* sym data flag: constant string */
|
||||
|
||||
#define IR_SKIP_PROLOGUE (1<<8) /* Don't generate function prologue. */
|
||||
#define IR_USE_FRAME_POINTER (1<<9)
|
||||
#define IR_PREALLOCATED_STACK (1<<10)
|
||||
@@ -825,11 +828,12 @@ struct _ir_loader {
|
||||
uint32_t flags, ir_type ret_type, uint32_t params_count, const uint8_t *param_types);
|
||||
bool (*forward_func_dcl) (ir_loader *loader, const char *name,
|
||||
uint32_t flags, ir_type ret_type, uint32_t params_count, const uint8_t *param_types);
|
||||
bool (*sym_dcl) (ir_loader *loader, const char *name, uint32_t flags, size_t size, bool has_data);
|
||||
bool (*sym_dcl) (ir_loader *loader, const char *name, uint32_t flags, size_t size);
|
||||
bool (*sym_data) (ir_loader *loader, ir_type type, uint32_t count, const void *data);
|
||||
bool (*sym_data_str) (ir_loader *loader, const char *str, size_t len);
|
||||
bool (*sym_data_pad) (ir_loader *loader, size_t offset);
|
||||
bool (*sym_data_ref) (ir_loader *loader, ir_op op, const char *ref, uintptr_t offset);
|
||||
bool (*sym_data_end) (ir_loader *loader);
|
||||
bool (*sym_data_end) (ir_loader *loader, uint32_t flags);
|
||||
bool (*func_init) (ir_loader *loader, ir_ctx *ctx, const char *name);
|
||||
bool (*func_process) (ir_loader *loader, ir_ctx *ctx, const char *name);
|
||||
void*(*resolve_sym_name) (ir_loader *loader, const char *name, bool add_thunk);
|
||||
@@ -867,12 +871,12 @@ void ir_dump_codegen(const ir_ctx *ctx, FILE *f);
|
||||
/* IR to C conversion (implementation in ir_emit_c.c) */
|
||||
int ir_emit_c(ir_ctx *ctx, const char *name, FILE *f);
|
||||
void ir_emit_c_func_decl(const char *name, uint32_t flags, ir_type ret_type, uint32_t params_count, const uint8_t *param_types, FILE *f);
|
||||
void ir_emit_c_sym_decl(const char *name, uint32_t flags, bool has_data, FILE *f);
|
||||
void ir_emit_c_sym_decl(const char *name, uint32_t flags, FILE *f);
|
||||
|
||||
/* IR to LLVM conversion (implementation in ir_emit_llvm.c) */
|
||||
int ir_emit_llvm(ir_ctx *ctx, const char *name, FILE *f);
|
||||
void ir_emit_llvm_func_decl(const char *name, uint32_t flags, ir_type ret_type, uint32_t params_count, const uint8_t *param_types, FILE *f);
|
||||
void ir_emit_llvm_sym_decl(const char *name, uint32_t flags, bool has_data, FILE *f);
|
||||
void ir_emit_llvm_sym_decl(const char *name, uint32_t flags, FILE *f);
|
||||
|
||||
/* IR verification API (implementation in ir_check.c) */
|
||||
bool ir_check(const ir_ctx *ctx);
|
||||
|
||||
@@ -1057,7 +1057,7 @@ binop_fp:
|
||||
return insn->op;
|
||||
case IR_VA_START:
|
||||
ctx->flags2 |= IR_HAS_VA_START;
|
||||
if (ctx->ir_base[insn->op2].op == IR_ALLOCA) {
|
||||
if ((ctx->ir_base[insn->op2].op == IR_ALLOCA) || (ctx->ir_base[insn->op2].op == IR_VADDR)) {
|
||||
ir_use_list *use_list = &ctx->use_lists[insn->op2];
|
||||
ir_ref *p, n = use_list->count;
|
||||
for (p = &ctx->use_edges[use_list->refs]; n > 0; p++, n--) {
|
||||
@@ -1092,7 +1092,7 @@ binop_fp:
|
||||
|
||||
for (p = &ctx->use_edges[use_list->refs]; n > 0; p++, n--) {
|
||||
if (ctx->ir_base[*p].op != IR_VA_END) {
|
||||
return IR_VADDR;
|
||||
return IR_STATIC_ALLOCA;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3802,7 +3802,7 @@ static ir_mem ir_fuse_addr(ir_ctx *ctx, ir_ref root, ir_ref ref)
|
||||
return IR_MEM_BO(reg, ctx->ir_base[addr_insn->op2].val.i32);
|
||||
}
|
||||
} else {
|
||||
IR_ASSERT(addr_insn->op == IR_ALLOCA);
|
||||
IR_ASSERT(addr_insn->op == IR_ALLOCA || addr_insn->op == IR_VADDR);
|
||||
reg = (ctx->flags & IR_USE_FRAME_POINTER) ? IR_REG_FRAME_POINTER : IR_REG_STACK_POINTER;
|
||||
offset = IR_SPILL_POS_TO_OFFSET(ctx->ir_base[ref].op3);
|
||||
return IR_MEM_BO(reg, offset);
|
||||
|
||||
@@ -178,14 +178,10 @@ bool ir_check(const ir_ctx *ctx)
|
||||
/* boolean not */
|
||||
break;
|
||||
}
|
||||
if (sizeof(void*) == 8) {
|
||||
if (insn->type == IR_ADDR && (use_insn->type == IR_U64 || use_insn->type == IR_I64)) {
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
if (insn->type == IR_ADDR && (use_insn->type == IR_U32 || use_insn->type == IR_I32)) {
|
||||
break;
|
||||
}
|
||||
if (insn->type == IR_ADDR && (use_insn->type == IR_UINTPTR_T || use_insn->type == IR_INTPTR_T)) {
|
||||
break;
|
||||
} else if (use_insn->type == IR_ADDR && (insn->type == IR_UINTPTR_T || insn->type == IR_INTPTR_T)) {
|
||||
break;
|
||||
}
|
||||
fprintf(stderr, "ir_base[%d].ops[%d] (%d) type is incompatible with result type (%d != %d)\n",
|
||||
i, j, use, use_insn->type, insn->type);
|
||||
|
||||
@@ -2501,10 +2501,230 @@ IR_FOLD(ADD(ADD, C_I64))
|
||||
IR_FOLD_NEXT;
|
||||
}
|
||||
|
||||
IR_FOLD(ADD(SUB, C_U8))
|
||||
IR_FOLD(ADD(SUB, C_U16))
|
||||
IR_FOLD(ADD(SUB, C_U32))
|
||||
IR_FOLD(ADD(SUB, C_U64))
|
||||
IR_FOLD(ADD(SUB, C_ADDR))
|
||||
{
|
||||
if (IR_IS_CONST_REF(op1_insn->op2) && !IR_IS_SYM_CONST(ctx->ir_base[op1_insn->op2].op)) {
|
||||
/* (x - c1) + c2 => x + (c2 - c1) */
|
||||
val.u64 = op2_insn->val.u64 - ctx->ir_base[op1_insn->op2].val.u64;
|
||||
op1 = op1_insn->op1;
|
||||
op2 = ir_const(ctx, val, IR_OPT_TYPE(opt));
|
||||
IR_FOLD_RESTART;
|
||||
} else if (IR_IS_CONST_REF(op1_insn->op1) && !IR_IS_SYM_CONST(ctx->ir_base[op1_insn->op1].op)) {
|
||||
/* (c1 - x) + c2 => (c1 + c2) - x */
|
||||
val.u64 = ctx->ir_base[op1_insn->op1].val.u64 + op2_insn->val.u64;
|
||||
opt++; /* ADD -> SUB */
|
||||
op1 = ir_const(ctx, val, IR_OPT_TYPE(opt));
|
||||
op2 = op1_insn->op2;
|
||||
IR_FOLD_RESTART;
|
||||
}
|
||||
IR_FOLD_NEXT;
|
||||
}
|
||||
|
||||
IR_FOLD(ADD(SUB, C_I8))
|
||||
IR_FOLD(ADD(SUB, C_I16))
|
||||
IR_FOLD(ADD(SUB, C_I32))
|
||||
IR_FOLD(ADD(SUB, C_I64))
|
||||
{
|
||||
if (IR_IS_CONST_REF(op1_insn->op2) && !IR_IS_SYM_CONST(ctx->ir_base[op1_insn->op2].op)) {
|
||||
/* (x - c1) + c2 => x + (c2 - c1) */
|
||||
val.i64 = op2_insn->val.i64 - ctx->ir_base[op1_insn->op2].val.i64;
|
||||
if (val.i64 < 0 && val.i64 - 1 < 0) {
|
||||
val.i64 = -val.i64;
|
||||
opt++; /* ADD -> SUB */
|
||||
}
|
||||
op1 = op1_insn->op1;
|
||||
op2 = ir_const(ctx, val, IR_OPT_TYPE(opt));
|
||||
IR_FOLD_RESTART;
|
||||
} else if (IR_IS_CONST_REF(op1_insn->op1) && !IR_IS_SYM_CONST(ctx->ir_base[op1_insn->op1].op)) {
|
||||
/* (c1 - x) + c2 => (c1 + c2) - x */
|
||||
val.i64 = ctx->ir_base[op1_insn->op1].val.i64 + op2_insn->val.i64;
|
||||
opt++; /* ADD -> SUB */
|
||||
op1 = ir_const(ctx, val, IR_OPT_TYPE(opt));
|
||||
op2 = op1_insn->op2;
|
||||
IR_FOLD_RESTART;
|
||||
}
|
||||
IR_FOLD_NEXT;
|
||||
}
|
||||
|
||||
IR_FOLD(SUB(ADD, C_U8))
|
||||
IR_FOLD(SUB(ADD, C_U16))
|
||||
IR_FOLD(SUB(ADD, C_U32))
|
||||
IR_FOLD(SUB(ADD, C_U64))
|
||||
IR_FOLD(SUB(ADD, C_ADDR))
|
||||
{
|
||||
if (IR_IS_CONST_REF(op1_insn->op2) && !IR_IS_SYM_CONST(ctx->ir_base[op1_insn->op2].op)) {
|
||||
/* (x + c1) - c2 => x + (c1 - c2) */
|
||||
val.u64 = ctx->ir_base[op1_insn->op2].val.u64 - op2_insn->val.u64;
|
||||
opt--; /* SUB -> ADD */
|
||||
op1 = op1_insn->op1;
|
||||
op2 = ir_const(ctx, val, IR_OPT_TYPE(opt));
|
||||
IR_FOLD_RESTART;
|
||||
}
|
||||
IR_FOLD_NEXT;
|
||||
}
|
||||
|
||||
IR_FOLD(SUB(ADD, C_I8))
|
||||
IR_FOLD(SUB(ADD, C_I16))
|
||||
IR_FOLD(SUB(ADD, C_I32))
|
||||
IR_FOLD(SUB(ADD, C_I64))
|
||||
{
|
||||
if (IR_IS_CONST_REF(op1_insn->op2) && !IR_IS_SYM_CONST(ctx->ir_base[op1_insn->op2].op)) {
|
||||
/* (x + c1) - c2 => x + (c1 - c2) */
|
||||
val.i64 = ctx->ir_base[op1_insn->op2].val.i64 - op2_insn->val.i64;
|
||||
if (val.i64 < 0 && val.i64 - 1 < 0) {
|
||||
val.i64 = -val.i64;
|
||||
} else {
|
||||
opt--; /* SUB -> ADD */
|
||||
}
|
||||
op1 = op1_insn->op1;
|
||||
op2 = ir_const(ctx, val, IR_OPT_TYPE(opt));
|
||||
IR_FOLD_RESTART;
|
||||
}
|
||||
IR_FOLD_NEXT;
|
||||
}
|
||||
|
||||
IR_FOLD(SUB(C_U8, ADD))
|
||||
IR_FOLD(SUB(C_U16, ADD))
|
||||
IR_FOLD(SUB(C_U32, ADD))
|
||||
IR_FOLD(SUB(C_U64, ADD))
|
||||
IR_FOLD(SUB(C_ADDR, ADD))
|
||||
{
|
||||
if (IR_IS_CONST_REF(op2_insn->op2) && !IR_IS_SYM_CONST(ctx->ir_base[op2_insn->op2].op)) {
|
||||
/* c1 - (x + c2) => (c1 - c2) - x */
|
||||
val.u64 = op1_insn->val.u64 - ctx->ir_base[op2_insn->op2].val.u64;
|
||||
op1 = ir_const(ctx, val, IR_OPT_TYPE(opt));
|
||||
op2 = op2_insn->op1;
|
||||
IR_FOLD_RESTART;
|
||||
}
|
||||
IR_FOLD_NEXT;
|
||||
}
|
||||
|
||||
IR_FOLD(SUB(C_I8, ADD))
|
||||
IR_FOLD(SUB(C_I16, ADD))
|
||||
IR_FOLD(SUB(C_I32, ADD))
|
||||
IR_FOLD(SUB(C_I64, ADD))
|
||||
{
|
||||
if (IR_IS_CONST_REF(op2_insn->op2) && !IR_IS_SYM_CONST(ctx->ir_base[op2_insn->op2].op)) {
|
||||
/* c1 - (x + c2) => (c1 - c2) - x */
|
||||
val.i64 = op1_insn->val.i64 - ctx->ir_base[op2_insn->op2].val.i64;
|
||||
op1 = ir_const(ctx, val, IR_OPT_TYPE(opt));
|
||||
op2 = op2_insn->op1;
|
||||
IR_FOLD_RESTART;
|
||||
}
|
||||
IR_FOLD_NEXT;
|
||||
}
|
||||
|
||||
IR_FOLD(SUB(SUB, C_U8))
|
||||
IR_FOLD(SUB(SUB, C_U16))
|
||||
IR_FOLD(SUB(SUB, C_U32))
|
||||
IR_FOLD(SUB(SUB, C_U64))
|
||||
IR_FOLD(SUB(SUB, C_ADDR))
|
||||
{
|
||||
if (IR_IS_CONST_REF(op1_insn->op2) && !IR_IS_SYM_CONST(ctx->ir_base[op1_insn->op2].op)) {
|
||||
/* (x - c1) - c2 => x - (c1 + c2) */
|
||||
val.u64 = ctx->ir_base[op1_insn->op2].val.u64 + op2_insn->val.u64;
|
||||
if (val.i64 < 0 && val.i64 - 1 < 0) {
|
||||
val.i64 = -val.i64;
|
||||
opt--; /* SUB -> ADD */
|
||||
}
|
||||
op1 = op1_insn->op1;
|
||||
op2 = ir_const(ctx, val, IR_OPT_TYPE(opt));
|
||||
IR_FOLD_RESTART;
|
||||
} else if (IR_IS_CONST_REF(op1_insn->op1) && !IR_IS_SYM_CONST(ctx->ir_base[op1_insn->op1].op)) {
|
||||
/* (c1 - x) - c2 => (c1 - c2) - x */
|
||||
val.u64 = ctx->ir_base[op1_insn->op1].val.u64 - op2_insn->val.u64;
|
||||
op1 = ir_const(ctx, val, IR_OPT_TYPE(opt));
|
||||
op2 = op1_insn->op2;
|
||||
IR_FOLD_RESTART;
|
||||
}
|
||||
IR_FOLD_NEXT;
|
||||
}
|
||||
|
||||
IR_FOLD(SUB(SUB, C_I8))
|
||||
IR_FOLD(SUB(SUB, C_I16))
|
||||
IR_FOLD(SUB(SUB, C_I32))
|
||||
IR_FOLD(SUB(SUB, C_I64))
|
||||
{
|
||||
if (IR_IS_CONST_REF(op1_insn->op2) && !IR_IS_SYM_CONST(ctx->ir_base[op1_insn->op2].op)) {
|
||||
/* (x - c1) - c2 => x - (c1 + c2) */
|
||||
val.i64 = ctx->ir_base[op1_insn->op2].val.i64 + op2_insn->val.i64;
|
||||
if (val.i64 < 0 && val.i64 - 1 < 0) {
|
||||
val.i64 = -val.i64;
|
||||
opt--; /* SUB -> ADD */
|
||||
}
|
||||
op1 = op1_insn->op1;
|
||||
op2 = ir_const(ctx, val, IR_OPT_TYPE(opt));
|
||||
IR_FOLD_RESTART;
|
||||
} else if (IR_IS_CONST_REF(op1_insn->op1) && !IR_IS_SYM_CONST(ctx->ir_base[op1_insn->op1].op)) {
|
||||
/* (c1 - x) - c2 => (c1 - c2) - x */
|
||||
val.i64 = ctx->ir_base[op1_insn->op1].val.i64 - op2_insn->val.i64;
|
||||
op1 = ir_const(ctx, val, IR_OPT_TYPE(opt));
|
||||
op2 = op1_insn->op2;
|
||||
IR_FOLD_RESTART;
|
||||
}
|
||||
IR_FOLD_NEXT;
|
||||
}
|
||||
|
||||
IR_FOLD(SUB(C_U8, SUB))
|
||||
IR_FOLD(SUB(C_U16, SUB))
|
||||
IR_FOLD(SUB(C_U32, SUB))
|
||||
IR_FOLD(SUB(C_U64, SUB))
|
||||
IR_FOLD(SUB(C_ADDR, SUB))
|
||||
{
|
||||
if (IR_IS_CONST_REF(op2_insn->op2) && !IR_IS_SYM_CONST(ctx->ir_base[op2_insn->op2].op)) {
|
||||
/* c1 - (x - c2) => (c1 + c2) - x */
|
||||
val.u64 = op1_insn->val.u64 + ctx->ir_base[op2_insn->op2].val.u64;
|
||||
op1 = ir_const(ctx, val, IR_OPT_TYPE(opt));
|
||||
op2 = op2_insn->op1;
|
||||
IR_FOLD_RESTART;
|
||||
} else if (IR_IS_CONST_REF(op2_insn->op1) && !IR_IS_SYM_CONST(ctx->ir_base[op2_insn->op1].op)) {
|
||||
/* c1 - (c2 - x) => x + (c1 - c2) */
|
||||
val.u64 = op1_insn->val.u64 - ctx->ir_base[op2_insn->op1].val.u64;
|
||||
if (val.i64 < 0 && val.i64 - 1 < 0) {
|
||||
val.i64 = -val.i64;
|
||||
opt++; /* ADD -> SUB */
|
||||
}
|
||||
op1 = op2_insn->op2;
|
||||
op2 = ir_const(ctx, val, IR_OPT_TYPE(opt));
|
||||
IR_FOLD_RESTART;
|
||||
}
|
||||
IR_FOLD_NEXT;
|
||||
}
|
||||
|
||||
IR_FOLD(SUB(C_I8, SUB))
|
||||
IR_FOLD(SUB(C_I16, SUB))
|
||||
IR_FOLD(SUB(C_I32, SUB))
|
||||
IR_FOLD(SUB(C_I64, SUB))
|
||||
{
|
||||
if (IR_IS_CONST_REF(op2_insn->op2) && !IR_IS_SYM_CONST(ctx->ir_base[op2_insn->op2].op)) {
|
||||
/* c1 - (x - c2) => (c1 + c2) - x */
|
||||
val.i64 = op1_insn->val.i64 + ctx->ir_base[op2_insn->op2].val.i64;
|
||||
op1 = ir_const(ctx, val, IR_OPT_TYPE(opt));
|
||||
op2 = op2_insn->op1;
|
||||
IR_FOLD_RESTART;
|
||||
} else if (IR_IS_CONST_REF(op2_insn->op1) && !IR_IS_SYM_CONST(ctx->ir_base[op2_insn->op1].op)) {
|
||||
/* c1 - (c2 - x) => x + (c1 - c2) */
|
||||
val.i64 = op1_insn->val.i64 - ctx->ir_base[op2_insn->op1].val.i64;
|
||||
if (val.i64 < 0 && val.i64 - 1 < 0) {
|
||||
val.i64 = -val.i64;
|
||||
opt++; /* ADD -> SUB */
|
||||
}
|
||||
op1 = op2_insn->op2;
|
||||
op2 = ir_const(ctx, val, IR_OPT_TYPE(opt));
|
||||
IR_FOLD_RESTART;
|
||||
}
|
||||
IR_FOLD_NEXT;
|
||||
}
|
||||
|
||||
IR_FOLD(MUL(MUL, C_U8))
|
||||
IR_FOLD(MUL(MUL, C_U16))
|
||||
IR_FOLD(MUL(MUL, C_U32))
|
||||
IR_FOLD(MUL(MUL, C_U64))
|
||||
IR_FOLD(MUL(MUL, C_ADDR))
|
||||
{
|
||||
if (IR_IS_CONST_REF(op1_insn->op2) && !IR_IS_SYM_CONST(ctx->ir_base[op1_insn->op2].op)) {
|
||||
/* (x * c1) * c2 => x * (c1 * c2) */
|
||||
@@ -2520,7 +2740,6 @@ IR_FOLD(MUL(MUL, C_I8))
|
||||
IR_FOLD(MUL(MUL, C_I16))
|
||||
IR_FOLD(MUL(MUL, C_I32))
|
||||
IR_FOLD(MUL(MUL, C_I64))
|
||||
IR_FOLD(MUL(MUL, C_ADDR))
|
||||
{
|
||||
if (IR_IS_CONST_REF(op1_insn->op2) && !IR_IS_SYM_CONST(ctx->ir_base[op1_insn->op2].op)) {
|
||||
/* (x * c1) * c2 => x * (c1 * c2) */
|
||||
|
||||
@@ -855,6 +855,8 @@ extern const uint8_t ir_type_size[IR_LAST_TYPE];
|
||||
extern const uint32_t ir_op_flags[IR_LAST_OP];
|
||||
extern const char *ir_op_name[IR_LAST_OP];
|
||||
|
||||
void ir_print_escaped_str(const char *s, size_t len, FILE *f);
|
||||
|
||||
#define IR_IS_CONST_OP(op) ((op) > IR_NOP && (op) <= IR_C_FLOAT)
|
||||
#define IR_IS_FOLDABLE_OP(op) ((op) <= IR_LAST_FOLDABLE_OP)
|
||||
#define IR_IS_SYM_CONST(op) ((op) == IR_STR || (op) == IR_SYM || (op) == IR_FUNC)
|
||||
|
||||
@@ -722,8 +722,10 @@ int ir_compute_live_ranges(ir_ctx *ctx)
|
||||
|| (ctx->rules[ref] & IR_RULE_MASK) == IR_ALLOCA)
|
||||
&& ctx->use_lists[ref].count > 0) {
|
||||
insn = &ctx->ir_base[ref];
|
||||
insn->op3 = ctx->vars;
|
||||
ctx->vars = ref;
|
||||
if (insn->op != IR_VADDR) {
|
||||
insn->op3 = ctx->vars;
|
||||
ctx->vars = ref;
|
||||
}
|
||||
}
|
||||
continue;
|
||||
}
|
||||
@@ -1338,8 +1340,10 @@ int ir_compute_live_ranges(ir_ctx *ctx)
|
||||
|| (ctx->rules[ref] & IR_RULE_MASK) == IR_ALLOCA)
|
||||
&& ctx->use_lists[ref].count > 0) {
|
||||
insn = &ctx->ir_base[ref];
|
||||
insn->op3 = ctx->vars;
|
||||
ctx->vars = ref;
|
||||
if (insn->op != IR_VADDR) {
|
||||
insn->op3 = ctx->vars;
|
||||
ctx->vars = ref;
|
||||
}
|
||||
}
|
||||
continue;
|
||||
}
|
||||
@@ -3507,13 +3511,27 @@ static int ir_linear_scan(ir_ctx *ctx)
|
||||
data.handled = NULL;
|
||||
|
||||
while (vars) {
|
||||
ir_insn *insn = &ctx->ir_base[vars];
|
||||
ir_ref var = vars;
|
||||
ir_insn *insn = &ctx->ir_base[var];
|
||||
|
||||
IR_ASSERT(insn->op == IR_VAR || insn->op == IR_ALLOCA);
|
||||
vars = insn->op3; /* list next */
|
||||
|
||||
if (insn->op == IR_VAR) {
|
||||
insn->op3 = ir_allocate_spill_slot(ctx, insn->type, &data);
|
||||
ir_ref slot = ir_allocate_spill_slot(ctx, insn->type, &data);;
|
||||
ir_use_list *use_list;
|
||||
ir_ref n, *p;
|
||||
|
||||
insn->op3 = slot;
|
||||
use_list = &ctx->use_lists[var];
|
||||
n = use_list->count;
|
||||
p = &ctx->use_edges[use_list->refs];
|
||||
for (; n > 0; p++, n--) {
|
||||
insn = &ctx->ir_base[*p];
|
||||
if (insn->op == IR_VADDR) {
|
||||
insn->op3 = slot;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
ir_insn *val = &ctx->ir_base[insn->op2];
|
||||
|
||||
@@ -4060,7 +4078,8 @@ static void assign_regs(ir_ctx *ctx)
|
||||
if (IR_IS_CONST_REF(ops[ival->tmp_op_num])) {
|
||||
/* constant rematerialization */
|
||||
reg |= IR_REG_SPILL_LOAD;
|
||||
} else if (ctx->ir_base[ops[ival->tmp_op_num]].op == IR_ALLOCA) {
|
||||
} else if (ctx->ir_base[ops[ival->tmp_op_num]].op == IR_ALLOCA
|
||||
|| ctx->ir_base[ops[ival->tmp_op_num]].op == IR_VADDR) {
|
||||
/* local address rematerialization */
|
||||
reg |= IR_REG_SPILL_LOAD;
|
||||
}
|
||||
|
||||
@@ -2810,7 +2810,7 @@ store_int:
|
||||
|
||||
for (p = &ctx->use_edges[use_list->refs]; n > 0; p++, n--) {
|
||||
if (ctx->ir_base[*p].op != IR_VA_END) {
|
||||
return IR_VADDR;
|
||||
return IR_STATIC_ALLOCA;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user