mirror of
https://github.com/danog/ir.git
synced 2024-12-02 09:38:29 +01:00
Split ir_ctx->flags into public and private (ir_ctx->flags2)
This commit is contained in:
parent
688f876928
commit
68068c4f58
10
ir.c
10
ir.c
@ -782,7 +782,7 @@ restart:
|
|||||||
} while (1);
|
} while (1);
|
||||||
|
|
||||||
ir_fold_restart:
|
ir_fold_restart:
|
||||||
if (!(ctx->flags & IR_OPT_IN_SCCP)) {
|
if (!(ctx->flags2 & IR_OPT_IN_SCCP)) {
|
||||||
op1_insn = ctx->ir_base + op1;
|
op1_insn = ctx->ir_base + op1;
|
||||||
op2_insn = ctx->ir_base + op2;
|
op2_insn = ctx->ir_base + op2;
|
||||||
op3_insn = ctx->ir_base + op3;
|
op3_insn = ctx->ir_base + op3;
|
||||||
@ -795,7 +795,7 @@ ir_fold_restart:
|
|||||||
return IR_FOLD_DO_RESTART;
|
return IR_FOLD_DO_RESTART;
|
||||||
}
|
}
|
||||||
ir_fold_cse:
|
ir_fold_cse:
|
||||||
if (!(ctx->flags & IR_OPT_IN_SCCP)) {
|
if (!(ctx->flags2 & IR_OPT_IN_SCCP)) {
|
||||||
/* Local CSE */
|
/* Local CSE */
|
||||||
ref = _ir_fold_cse(ctx, opt, op1, op2, op3);
|
ref = _ir_fold_cse(ctx, opt, op1, op2, op3);
|
||||||
if (ref) {
|
if (ref) {
|
||||||
@ -819,7 +819,7 @@ ir_fold_cse:
|
|||||||
return ref;
|
return ref;
|
||||||
}
|
}
|
||||||
ir_fold_emit:
|
ir_fold_emit:
|
||||||
if (!(ctx->flags & IR_OPT_IN_SCCP)) {
|
if (!(ctx->flags2 & IR_OPT_IN_SCCP)) {
|
||||||
return ir_emit(ctx, opt, op1, op2, op3);
|
return ir_emit(ctx, opt, op1, op2, op3);
|
||||||
} else {
|
} else {
|
||||||
ctx->fold_insn.optx = opt;
|
ctx->fold_insn.optx = opt;
|
||||||
@ -829,14 +829,14 @@ ir_fold_emit:
|
|||||||
return IR_FOLD_DO_EMIT;
|
return IR_FOLD_DO_EMIT;
|
||||||
}
|
}
|
||||||
ir_fold_copy:
|
ir_fold_copy:
|
||||||
if (!(ctx->flags & IR_OPT_IN_SCCP)) {
|
if (!(ctx->flags2 & IR_OPT_IN_SCCP)) {
|
||||||
return ref;
|
return ref;
|
||||||
} else {
|
} else {
|
||||||
ctx->fold_insn.op1 = ref;
|
ctx->fold_insn.op1 = ref;
|
||||||
return IR_FOLD_DO_COPY;
|
return IR_FOLD_DO_COPY;
|
||||||
}
|
}
|
||||||
ir_fold_const:
|
ir_fold_const:
|
||||||
if (!(ctx->flags & IR_OPT_IN_SCCP)) {
|
if (!(ctx->flags2 & IR_OPT_IN_SCCP)) {
|
||||||
return ir_const(ctx, val, IR_OPT_TYPE(opt));
|
return ir_const(ctx, val, IR_OPT_TYPE(opt));
|
||||||
} else {
|
} else {
|
||||||
ctx->fold_insn.type = IR_OPT_TYPE(opt);
|
ctx->fold_insn.type = IR_OPT_TYPE(opt);
|
||||||
|
31
ir.h
31
ir.h
@ -496,38 +496,18 @@ void ir_strtab_free(ir_strtab *strtab);
|
|||||||
#define IR_SKIP_PROLOGUE (1<<6) /* Don't generate function prologue. */
|
#define IR_SKIP_PROLOGUE (1<<6) /* Don't generate function prologue. */
|
||||||
#define IR_USE_FRAME_POINTER (1<<7)
|
#define IR_USE_FRAME_POINTER (1<<7)
|
||||||
#define IR_PREALLOCATED_STACK (1<<8)
|
#define IR_PREALLOCATED_STACK (1<<8)
|
||||||
#define IR_HAS_ALLOCA (1<<9)
|
#define IR_NO_STACK_COMBINE (1<<9)
|
||||||
#define IR_HAS_CALLS (1<<10)
|
#define IR_START_BR_TARGET (1<<10)
|
||||||
#define IR_NO_STACK_COMBINE (1<<11)
|
#define IR_ENTRY_BR_TARGET (1<<11)
|
||||||
#define IR_START_BR_TARGET (1<<12)
|
#define IR_GEN_ENDBR (1<<12)
|
||||||
#define IR_ENTRY_BR_TARGET (1<<13)
|
#define IR_MERGE_EMPTY_ENTRIES (1<<13)
|
||||||
#define IR_GEN_ENDBR (1<<14)
|
|
||||||
#define IR_MERGE_EMPTY_ENTRIES (1<<15)
|
|
||||||
|
|
||||||
#define IR_CFG_HAS_LOOPS (1<<16)
|
|
||||||
#define IR_IRREDUCIBLE_CFG (1<<17)
|
|
||||||
|
|
||||||
#define IR_OPT_FOLDING (1<<18)
|
#define IR_OPT_FOLDING (1<<18)
|
||||||
#define IR_OPT_CFG (1<<19) /* merge BBs, by remove END->BEGIN nodes during CFG construction */
|
#define IR_OPT_CFG (1<<19) /* merge BBs, by remove END->BEGIN nodes during CFG construction */
|
||||||
#define IR_OPT_CODEGEN (1<<20)
|
#define IR_OPT_CODEGEN (1<<20)
|
||||||
#define IR_OPT_IN_SCCP (1<<21)
|
|
||||||
#define IR_LINEAR (1<<22)
|
|
||||||
#define IR_GEN_NATIVE (1<<23)
|
#define IR_GEN_NATIVE (1<<23)
|
||||||
#define IR_GEN_CODE (1<<24) /* C or LLVM */
|
#define IR_GEN_CODE (1<<24) /* C or LLVM */
|
||||||
|
|
||||||
/* Temporary: SCCP -> CFG */
|
|
||||||
#define IR_SCCP_DONE (1<<25)
|
|
||||||
|
|
||||||
/* Temporary: Dominators -> Loops */
|
|
||||||
#define IR_NO_LOOPS (1<<25)
|
|
||||||
|
|
||||||
/* Temporary: Live Ranges */
|
|
||||||
#define IR_LR_HAVE_DESSA_MOVES (1<<25)
|
|
||||||
|
|
||||||
/* Temporary: Register Allocator */
|
|
||||||
#define IR_RA_HAVE_SPLITS (1<<25)
|
|
||||||
#define IR_RA_HAVE_SPILLS (1<<26)
|
|
||||||
|
|
||||||
/* debug related */
|
/* debug related */
|
||||||
#ifdef IR_DEBUG
|
#ifdef IR_DEBUG
|
||||||
# define IR_DEBUG_SCCP (1<<27)
|
# define IR_DEBUG_SCCP (1<<27)
|
||||||
@ -560,6 +540,7 @@ struct _ir_ctx {
|
|||||||
ir_ref consts_count; /* number of constants stored in constants buffer */
|
ir_ref consts_count; /* number of constants stored in constants buffer */
|
||||||
ir_ref consts_limit; /* size of allocated constants buffer (it's extended when overflow) */
|
ir_ref consts_limit; /* size of allocated constants buffer (it's extended when overflow) */
|
||||||
uint32_t flags; /* IR context flags (see IR_* defines above) */
|
uint32_t flags; /* IR context flags (see IR_* defines above) */
|
||||||
|
uint32_t flags2; /* IR context provate flags (see IR_* defines in ir_private.h) */
|
||||||
ir_type ret_type; /* Function return type */
|
ir_type ret_type; /* Function return type */
|
||||||
uint32_t mflags; /* CPU specific flags (see IR_X86_... macros below) */
|
uint32_t mflags; /* CPU specific flags (see IR_X86_... macros below) */
|
||||||
int32_t status; /* non-zero error code (see IR_ERROR_... macros), app may use negative codes */
|
int32_t status; /* non-zero error code (see IR_ERROR_... macros), app may use negative codes */
|
||||||
|
@ -752,7 +752,7 @@ binop_fp:
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case IR_CALL:
|
case IR_CALL:
|
||||||
ctx->flags |= IR_HAS_CALLS;
|
ctx->flags2 |= IR_HAS_CALLS;
|
||||||
return IR_CALL;
|
return IR_CALL;
|
||||||
case IR_VAR:
|
case IR_VAR:
|
||||||
return IR_SKIPPED | IR_VAR;
|
return IR_SKIPPED | IR_VAR;
|
||||||
@ -760,7 +760,8 @@ binop_fp:
|
|||||||
return ctx->use_lists[ref].count > 0 ? IR_PARAM : IR_SKIPPED | IR_PARAM;
|
return ctx->use_lists[ref].count > 0 ? IR_PARAM : IR_SKIPPED | IR_PARAM;
|
||||||
case IR_ALLOCA:
|
case IR_ALLOCA:
|
||||||
if (ctx->flags & IR_FUNCTION) {
|
if (ctx->flags & IR_FUNCTION) {
|
||||||
ctx->flags |= IR_USE_FRAME_POINTER | IR_HAS_ALLOCA;
|
ctx->flags |= IR_USE_FRAME_POINTER;
|
||||||
|
ctx->flags2 |= IR_HAS_ALLOCA;
|
||||||
}
|
}
|
||||||
return IR_ALLOCA;
|
return IR_ALLOCA;
|
||||||
case IR_LOAD:
|
case IR_LOAD:
|
||||||
@ -1361,7 +1362,7 @@ static void ir_emit_epilogue(ir_ctx *ctx)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (ctx->flags & IR_USE_FRAME_POINTER) {
|
if (ctx->flags & IR_USE_FRAME_POINTER) {
|
||||||
if (ctx->call_stack_size || (ctx->flags & IR_HAS_ALLOCA)) {
|
if (ctx->call_stack_size || (ctx->flags2 & IR_HAS_ALLOCA)) {
|
||||||
| mov sp, x29
|
| mov sp, x29
|
||||||
}
|
}
|
||||||
| ldp x29, x30, [sp], # (ctx->stack_frame_size+16)
|
| ldp x29, x30, [sp], # (ctx->stack_frame_size+16)
|
||||||
@ -3448,7 +3449,7 @@ static void ir_emit_alloca(ir_ctx *ctx, ir_ref def, ir_insn *insn)
|
|||||||
IR_ASSERT(IR_IS_TYPE_INT(val->type));
|
IR_ASSERT(IR_IS_TYPE_INT(val->type));
|
||||||
IR_ASSERT(IR_IS_TYPE_UNSIGNED(val->type) || val->val.i64 > 0);
|
IR_ASSERT(IR_IS_TYPE_UNSIGNED(val->type) || val->val.i64 > 0);
|
||||||
|
|
||||||
if (ctx->flags & IR_HAS_CALLS) {
|
if (ctx->flags2 & IR_HAS_CALLS) {
|
||||||
/* Stack must be 16 byte aligned */
|
/* Stack must be 16 byte aligned */
|
||||||
size = IR_ALIGNED_SIZE(size, 16);
|
size = IR_ALIGNED_SIZE(size, 16);
|
||||||
} else {
|
} else {
|
||||||
@ -3459,7 +3460,7 @@ static void ir_emit_alloca(ir_ctx *ctx, ir_ref def, ir_insn *insn)
|
|||||||
ctx->call_stack_size += size;
|
ctx->call_stack_size += size;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
int32_t alignment = (ctx->flags & IR_HAS_CALLS) ? 16 : 8;
|
int32_t alignment = (ctx->flags2 & IR_HAS_CALLS) ? 16 : 8;
|
||||||
ir_reg op2_reg = ctx->regs[def][2];
|
ir_reg op2_reg = ctx->regs[def][2];
|
||||||
ir_type type = ctx->ir_base[insn->op2].type;
|
ir_type type = ctx->ir_base[insn->op2].type;
|
||||||
|
|
||||||
@ -3496,7 +3497,7 @@ static void ir_emit_afree(ir_ctx *ctx, ir_ref def, ir_insn *insn)
|
|||||||
IR_ASSERT(IR_IS_TYPE_INT(val->type));
|
IR_ASSERT(IR_IS_TYPE_INT(val->type));
|
||||||
IR_ASSERT(IR_IS_TYPE_UNSIGNED(val->type) || val->val.i64 > 0);
|
IR_ASSERT(IR_IS_TYPE_UNSIGNED(val->type) || val->val.i64 > 0);
|
||||||
|
|
||||||
if (ctx->flags & IR_HAS_CALLS) {
|
if (ctx->flags2 & IR_HAS_CALLS) {
|
||||||
/* Stack must be 16 byte aligned */
|
/* Stack must be 16 byte aligned */
|
||||||
size = IR_ALIGNED_SIZE(size, 16);
|
size = IR_ALIGNED_SIZE(size, 16);
|
||||||
} else {
|
} else {
|
||||||
@ -3507,7 +3508,7 @@ static void ir_emit_afree(ir_ctx *ctx, ir_ref def, ir_insn *insn)
|
|||||||
ctx->call_stack_size -= size;
|
ctx->call_stack_size -= size;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// int32_t alignment = (ctx->flags & IR_HAS_CALLS) ? 16 : 8;
|
// int32_t alignment = (ctx->flags2 & IR_HAS_CALLS) ? 16 : 8;
|
||||||
ir_reg op2_reg = ctx->regs[def][2];
|
ir_reg op2_reg = ctx->regs[def][2];
|
||||||
ir_type type = ctx->ir_base[insn->op2].type;
|
ir_type type = ctx->ir_base[insn->op2].type;
|
||||||
|
|
||||||
@ -3540,6 +3541,18 @@ static void ir_emit_frame_addr(ir_ctx *ctx, ir_ref def)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void ir_emit_va_start(ir_ctx *ctx, ir_ref def, ir_insn *insn)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ir_emit_va_copy(ir_ctx *ctx, ir_ref def, ir_insn *insn)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ir_emit_va_arg(ir_ctx *ctx, ir_ref def, ir_insn *insn)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
static void ir_emit_switch(ir_ctx *ctx, uint32_t b, ir_ref def, ir_insn *insn)
|
static void ir_emit_switch(ir_ctx *ctx, uint32_t b, ir_ref def, ir_insn *insn)
|
||||||
{
|
{
|
||||||
ir_backend_data *data = ctx->data;
|
ir_backend_data *data = ctx->data;
|
||||||
@ -4979,12 +4992,12 @@ void ir_fix_stack_frame(ir_ctx *ctx)
|
|||||||
ctx->stack_frame_alignment = 0;
|
ctx->stack_frame_alignment = 0;
|
||||||
ctx->call_stack_size = 0;
|
ctx->call_stack_size = 0;
|
||||||
|
|
||||||
if ((ctx->flags & IR_HAS_CALLS) && !(ctx->flags & IR_FUNCTION)) {
|
if ((ctx->flags2 & IR_HAS_CALLS) && !(ctx->flags & IR_FUNCTION)) {
|
||||||
while (IR_ALIGNED_SIZE(ctx->stack_frame_size, 16) != ctx->stack_frame_size) {
|
while (IR_ALIGNED_SIZE(ctx->stack_frame_size, 16) != ctx->stack_frame_size) {
|
||||||
ctx->stack_frame_size += sizeof(void*);
|
ctx->stack_frame_size += sizeof(void*);
|
||||||
ctx->stack_frame_alignment += sizeof(void*);
|
ctx->stack_frame_alignment += sizeof(void*);
|
||||||
}
|
}
|
||||||
} else if (ctx->flags & IR_HAS_CALLS) {
|
} else if (ctx->flags2 & IR_HAS_CALLS) {
|
||||||
ctx->flags |= IR_USE_FRAME_POINTER;
|
ctx->flags |= IR_USE_FRAME_POINTER;
|
||||||
/* Stack must be 16 byte aligned */
|
/* Stack must be 16 byte aligned */
|
||||||
if (!(ctx->flags & IR_FUNCTION)) {
|
if (!(ctx->flags & IR_FUNCTION)) {
|
||||||
@ -5111,6 +5124,7 @@ void *ir_emit_code(ir_ctx *ctx, size_t *size_ptr)
|
|||||||
case IR_PI:
|
case IR_PI:
|
||||||
case IR_PHI:
|
case IR_PHI:
|
||||||
case IR_SNAPSHOT:
|
case IR_SNAPSHOT:
|
||||||
|
case IR_VA_END:
|
||||||
break;
|
break;
|
||||||
case IR_MUL_PWR2:
|
case IR_MUL_PWR2:
|
||||||
case IR_DIV_PWR2:
|
case IR_DIV_PWR2:
|
||||||
@ -5278,6 +5292,15 @@ void *ir_emit_code(ir_ctx *ctx, size_t *size_ptr)
|
|||||||
case IR_ALLOCA:
|
case IR_ALLOCA:
|
||||||
ir_emit_alloca(ctx, i, insn);
|
ir_emit_alloca(ctx, i, insn);
|
||||||
break;
|
break;
|
||||||
|
case IR_VA_START:
|
||||||
|
ir_emit_va_start(ctx, i, insn);
|
||||||
|
break;
|
||||||
|
case IR_VA_COPY:
|
||||||
|
ir_emit_va_copy(ctx, i, insn);
|
||||||
|
break;
|
||||||
|
case IR_VA_ARG:
|
||||||
|
ir_emit_va_arg(ctx, i, insn);
|
||||||
|
break;
|
||||||
case IR_AFREE:
|
case IR_AFREE:
|
||||||
ir_emit_afree(ctx, i, insn);
|
ir_emit_afree(ctx, i, insn);
|
||||||
break;
|
break;
|
||||||
|
20
ir_cfg.c
20
ir_cfg.c
@ -231,7 +231,7 @@ next_successor:
|
|||||||
bb = blocks + 1;
|
bb = blocks + 1;
|
||||||
count = 0;
|
count = 0;
|
||||||
/* SCCP already removed UNREACHABKE blocks, otherwise all blocks are marked as UNREACHABLE first */
|
/* SCCP already removed UNREACHABKE blocks, otherwise all blocks are marked as UNREACHABLE first */
|
||||||
bb_init_falgs = (ctx->flags & IR_SCCP_DONE) ? 0 : IR_BB_UNREACHABLE;
|
bb_init_falgs = (ctx->flags2 & IR_SCCP_DONE) ? 0 : IR_BB_UNREACHABLE;
|
||||||
IR_BITSET_FOREACH(bb_starts, len, start) {
|
IR_BITSET_FOREACH(bb_starts, len, start) {
|
||||||
end = _blocks[start];
|
end = _blocks[start];
|
||||||
_blocks[start] = b;
|
_blocks[start] = b;
|
||||||
@ -313,7 +313,7 @@ next_successor:
|
|||||||
ctx->cfg_edges = edges;
|
ctx->cfg_edges = edges;
|
||||||
ctx->cfg_map = _blocks;
|
ctx->cfg_map = _blocks;
|
||||||
|
|
||||||
if (!(ctx->flags & IR_SCCP_DONE)) {
|
if (!(ctx->flags2 & IR_SCCP_DONE)) {
|
||||||
uint32_t reachable_count = 0;
|
uint32_t reachable_count = 0;
|
||||||
|
|
||||||
/* Mark reachable blocks */
|
/* Mark reachable blocks */
|
||||||
@ -600,7 +600,7 @@ int ir_build_dominators_tree(ir_ctx *ctx)
|
|||||||
uint32_t *edges;
|
uint32_t *edges;
|
||||||
bool changed;
|
bool changed;
|
||||||
|
|
||||||
ctx->flags &= ~IR_NO_LOOPS;
|
ctx->flags2 &= ~IR_NO_LOOPS;
|
||||||
|
|
||||||
postnum = 1;
|
postnum = 1;
|
||||||
compute_postnum(ctx, &postnum, 1);
|
compute_postnum(ctx, &postnum, 1);
|
||||||
@ -706,7 +706,7 @@ int ir_build_dominators_tree(ir_ctx *ctx)
|
|||||||
ir_block *blocks, *bb;
|
ir_block *blocks, *bb;
|
||||||
uint32_t *edges;
|
uint32_t *edges;
|
||||||
|
|
||||||
ctx->flags |= IR_NO_LOOPS;
|
ctx->flags2 |= IR_NO_LOOPS;
|
||||||
|
|
||||||
/* Find immediate dominators */
|
/* Find immediate dominators */
|
||||||
blocks = ctx->cfg_blocks;
|
blocks = ctx->cfg_blocks;
|
||||||
@ -726,7 +726,7 @@ int ir_build_dominators_tree(ir_ctx *ctx)
|
|||||||
|
|
||||||
if (UNEXPECTED(idom > b)) {
|
if (UNEXPECTED(idom > b)) {
|
||||||
/* In rare cases, LOOP_BEGIN.op1 may be a back-edge. Skip back-edges. */
|
/* In rare cases, LOOP_BEGIN.op1 may be a back-edge. Skip back-edges. */
|
||||||
ctx->flags &= ~IR_NO_LOOPS;
|
ctx->flags2 &= ~IR_NO_LOOPS;
|
||||||
while (1) {
|
while (1) {
|
||||||
k--;
|
k--;
|
||||||
p++;
|
p++;
|
||||||
@ -753,7 +753,7 @@ int ir_build_dominators_tree(ir_ctx *ctx)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
ctx->flags &= ~IR_NO_LOOPS;
|
ctx->flags2 &= ~IR_NO_LOOPS;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
bb->idom = idom;
|
bb->idom = idom;
|
||||||
@ -805,7 +805,7 @@ int ir_find_loops(ir_ctx *ctx)
|
|||||||
uint32_t *edges = ctx->cfg_edges;
|
uint32_t *edges = ctx->cfg_edges;
|
||||||
ir_worklist work;
|
ir_worklist work;
|
||||||
|
|
||||||
if (ctx->flags & IR_NO_LOOPS) {
|
if (ctx->flags2 & IR_NO_LOOPS) {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -908,13 +908,13 @@ next:
|
|||||||
if (UNEXPECTED(irreducible)) {
|
if (UNEXPECTED(irreducible)) {
|
||||||
// TODO: Support for irreducible loops ???
|
// TODO: Support for irreducible loops ???
|
||||||
bb->flags |= IR_BB_IRREDUCIBLE_LOOP;
|
bb->flags |= IR_BB_IRREDUCIBLE_LOOP;
|
||||||
ctx->flags |= IR_IRREDUCIBLE_CFG;
|
ctx->flags2 |= IR_IRREDUCIBLE_CFG;
|
||||||
while (ir_worklist_len(&work)) {
|
while (ir_worklist_len(&work)) {
|
||||||
ir_worklist_pop(&work);
|
ir_worklist_pop(&work);
|
||||||
}
|
}
|
||||||
} else if (ir_worklist_len(&work)) {
|
} else if (ir_worklist_len(&work)) {
|
||||||
bb->flags |= IR_BB_LOOP_HEADER;
|
bb->flags |= IR_BB_LOOP_HEADER;
|
||||||
ctx->flags |= IR_CFG_HAS_LOOPS;
|
ctx->flags2 |= IR_CFG_HAS_LOOPS;
|
||||||
bb->loop_depth = 1;
|
bb->loop_depth = 1;
|
||||||
while (ir_worklist_len(&work)) {
|
while (ir_worklist_len(&work)) {
|
||||||
j = ir_worklist_pop(&work);
|
j = ir_worklist_pop(&work);
|
||||||
@ -942,7 +942,7 @@ next:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ctx->flags & IR_CFG_HAS_LOOPS) {
|
if (ctx->flags2 & IR_CFG_HAS_LOOPS) {
|
||||||
for (n = 1; n < count; n++) {
|
for (n = 1; n < count; n++) {
|
||||||
i = sorted_blocks[n];
|
i = sorted_blocks[n];
|
||||||
ir_block *bb = &blocks[i];
|
ir_block *bb = &blocks[i];
|
||||||
|
@ -127,7 +127,7 @@ bool ir_check(const ir_ctx *ctx)
|
|||||||
}
|
}
|
||||||
if (use >= i
|
if (use >= i
|
||||||
&& !(insn->op == IR_PHI
|
&& !(insn->op == IR_PHI
|
||||||
&& (!(ctx->flags & IR_LINEAR) || ctx->ir_base[insn->op1].op == IR_LOOP_BEGIN))) {
|
&& (!(ctx->flags2 & IR_LINEAR) || ctx->ir_base[insn->op1].op == IR_LOOP_BEGIN))) {
|
||||||
fprintf(stderr, "ir_base[%d].ops[%d] invalid forward reference (%d)\n", i, j, use);
|
fprintf(stderr, "ir_base[%d].ops[%d] invalid forward reference (%d)\n", i, j, use);
|
||||||
ok = 0;
|
ok = 0;
|
||||||
}
|
}
|
||||||
@ -194,7 +194,7 @@ bool ir_check(const ir_ctx *ctx)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if ((ctx->flags & IR_LINEAR)
|
if ((ctx->flags2 & IR_LINEAR)
|
||||||
&& ctx->cfg_map
|
&& ctx->cfg_map
|
||||||
&& insn->op != IR_PHI
|
&& insn->op != IR_PHI
|
||||||
&& !ir_check_domination(ctx, use, i)) {
|
&& !ir_check_domination(ctx, use, i)) {
|
||||||
|
5
ir_gcm.c
5
ir_gcm.c
@ -682,7 +682,7 @@ restart:
|
|||||||
ir_mem_free(_next);
|
ir_mem_free(_next);
|
||||||
|
|
||||||
ctx->prev_ref = _prev;
|
ctx->prev_ref = _prev;
|
||||||
ctx->flags |= IR_LINEAR;
|
ctx->flags2 |= IR_LINEAR;
|
||||||
ir_truncate(ctx);
|
ir_truncate(ctx);
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
@ -694,6 +694,7 @@ restart:
|
|||||||
|
|
||||||
ir_init(&new_ctx, ctx->flags, consts_count, insns_count);
|
ir_init(&new_ctx, ctx->flags, consts_count, insns_count);
|
||||||
new_ctx.insns_count = insns_count;
|
new_ctx.insns_count = insns_count;
|
||||||
|
new_ctx.flags2 = ctx->flags2;
|
||||||
new_ctx.ret_type = ctx->ret_type;
|
new_ctx.ret_type = ctx->ret_type;
|
||||||
new_ctx.mflags = ctx->mflags;
|
new_ctx.mflags = ctx->mflags;
|
||||||
new_ctx.spill_base = ctx->spill_base;
|
new_ctx.spill_base = ctx->spill_base;
|
||||||
@ -867,7 +868,7 @@ restart:
|
|||||||
IR_ASSERT(new_ctx.consts_count == new_ctx.consts_limit);
|
IR_ASSERT(new_ctx.consts_count == new_ctx.consts_limit);
|
||||||
IR_ASSERT(new_ctx.insns_count == new_ctx.insns_limit);
|
IR_ASSERT(new_ctx.insns_count == new_ctx.insns_limit);
|
||||||
memcpy(ctx, &new_ctx, sizeof(ir_ctx));
|
memcpy(ctx, &new_ctx, sizeof(ir_ctx));
|
||||||
ctx->flags |= IR_LINEAR;
|
ctx->flags2 |= IR_LINEAR;
|
||||||
|
|
||||||
ir_mem_free(_next);
|
ir_mem_free(_next);
|
||||||
|
|
||||||
|
21
ir_private.h
21
ir_private.h
@ -876,6 +876,27 @@ IR_ALWAYS_INLINE uint32_t ir_insn_len(const ir_insn *insn)
|
|||||||
return ir_insn_inputs_to_len(insn->inputs_count);
|
return ir_insn_inputs_to_len(insn->inputs_count);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*** IR Context Private Flags (ir_ctx->flags2) ***/
|
||||||
|
#define IR_CFG_HAS_LOOPS (1<<0)
|
||||||
|
#define IR_IRREDUCIBLE_CFG (1<<1)
|
||||||
|
#define IR_HAS_ALLOCA (1<<2)
|
||||||
|
#define IR_HAS_CALLS (1<<3)
|
||||||
|
#define IR_OPT_IN_SCCP (1<<4)
|
||||||
|
#define IR_LINEAR (1<<5)
|
||||||
|
|
||||||
|
/* Temporary: SCCP -> CFG */
|
||||||
|
#define IR_SCCP_DONE (1<<25)
|
||||||
|
|
||||||
|
/* Temporary: Dominators -> Loops */
|
||||||
|
#define IR_NO_LOOPS (1<<25)
|
||||||
|
|
||||||
|
/* Temporary: Live Ranges */
|
||||||
|
#define IR_LR_HAVE_DESSA_MOVES (1<<25)
|
||||||
|
|
||||||
|
/* Temporary: Register Allocator */
|
||||||
|
#define IR_RA_HAVE_SPLITS (1<<25)
|
||||||
|
#define IR_RA_HAVE_SPILLS (1<<26)
|
||||||
|
|
||||||
/*** IR Binding ***/
|
/*** IR Binding ***/
|
||||||
IR_ALWAYS_INLINE ir_ref ir_binding_find(const ir_ctx *ctx, ir_ref ref)
|
IR_ALWAYS_INLINE ir_ref ir_binding_find(const ir_ctx *ctx, ir_ref ref)
|
||||||
{
|
{
|
||||||
|
24
ir_ra.c
24
ir_ra.c
@ -593,7 +593,7 @@ int ir_compute_live_ranges(ir_ctx *ctx)
|
|||||||
ir_bitqueue queue;
|
ir_bitqueue queue;
|
||||||
ir_live_interval *ival;
|
ir_live_interval *ival;
|
||||||
|
|
||||||
if (!(ctx->flags & IR_LINEAR) || !ctx->vregs) {
|
if (!(ctx->flags2 & IR_LINEAR) || !ctx->vregs) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -606,7 +606,7 @@ int ir_compute_live_ranges(ir_ctx *ctx)
|
|||||||
ctx->vars = IR_UNUSED;
|
ctx->vars = IR_UNUSED;
|
||||||
|
|
||||||
/* Compute Live Ranges */
|
/* Compute Live Ranges */
|
||||||
ctx->flags &= ~IR_LR_HAVE_DESSA_MOVES;
|
ctx->flags2 &= ~IR_LR_HAVE_DESSA_MOVES;
|
||||||
len = ir_bitset_len(ctx->vregs_count + 1);
|
len = ir_bitset_len(ctx->vregs_count + 1);
|
||||||
bb_live = ir_mem_malloc((ctx->cfg_blocks_count + 1) * len * sizeof(ir_bitset_base_t));
|
bb_live = ir_mem_malloc((ctx->cfg_blocks_count + 1) * len * sizeof(ir_bitset_base_t));
|
||||||
|
|
||||||
@ -1243,7 +1243,7 @@ int ir_compute_live_ranges(ir_ctx *ctx)
|
|||||||
ir_list live_lists;
|
ir_list live_lists;
|
||||||
ir_live_interval *ival;
|
ir_live_interval *ival;
|
||||||
|
|
||||||
if (!(ctx->flags & IR_LINEAR) || !ctx->vregs) {
|
if (!(ctx->flags2 & IR_LINEAR) || !ctx->vregs) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1256,7 +1256,7 @@ int ir_compute_live_ranges(ir_ctx *ctx)
|
|||||||
ctx->vars = IR_UNUSED;
|
ctx->vars = IR_UNUSED;
|
||||||
|
|
||||||
/* Compute Live Ranges */
|
/* Compute Live Ranges */
|
||||||
ctx->flags &= ~IR_LR_HAVE_DESSA_MOVES;
|
ctx->flags2 &= ~IR_LR_HAVE_DESSA_MOVES;
|
||||||
|
|
||||||
/* vregs + tmp + fixed + SRATCH + ALL */
|
/* vregs + tmp + fixed + SRATCH + ALL */
|
||||||
ctx->live_intervals = ir_mem_calloc(ctx->vregs_count + 1 + IR_REG_NUM + 2, sizeof(ir_live_interval*));
|
ctx->live_intervals = ir_mem_calloc(ctx->vregs_count + 1 + IR_REG_NUM + 2, sizeof(ir_live_interval*));
|
||||||
@ -1645,7 +1645,7 @@ static void ir_add_phi_move(ir_ctx *ctx, uint32_t b, ir_ref from, ir_ref to)
|
|||||||
if (IR_IS_CONST_REF(from) || ctx->vregs[from] != ctx->vregs[to]) {
|
if (IR_IS_CONST_REF(from) || ctx->vregs[from] != ctx->vregs[to]) {
|
||||||
ctx->cfg_blocks[b].flags &= ~IR_BB_EMPTY;
|
ctx->cfg_blocks[b].flags &= ~IR_BB_EMPTY;
|
||||||
ctx->cfg_blocks[b].flags |= IR_BB_DESSA_MOVES;
|
ctx->cfg_blocks[b].flags |= IR_BB_DESSA_MOVES;
|
||||||
ctx->flags |= IR_LR_HAVE_DESSA_MOVES;
|
ctx->flags2 |= IR_LR_HAVE_DESSA_MOVES;
|
||||||
#if 0
|
#if 0
|
||||||
fprintf(stderr, "BB%d: MOV %d -> %d\n", b, from, to);
|
fprintf(stderr, "BB%d: MOV %d -> %d\n", b, from, to);
|
||||||
#endif
|
#endif
|
||||||
@ -1980,7 +1980,7 @@ int ir_compute_dessa_moves(ir_ctx *ctx)
|
|||||||
int pred = ctx->cfg_edges[bb->predecessors + (j-2)];
|
int pred = ctx->cfg_edges[bb->predecessors + (j-2)];
|
||||||
ctx->cfg_blocks[pred].flags &= ~IR_BB_EMPTY;
|
ctx->cfg_blocks[pred].flags &= ~IR_BB_EMPTY;
|
||||||
ctx->cfg_blocks[pred].flags |= IR_BB_DESSA_MOVES;
|
ctx->cfg_blocks[pred].flags |= IR_BB_DESSA_MOVES;
|
||||||
ctx->flags |= IR_LR_HAVE_DESSA_MOVES;
|
ctx->flags2 |= IR_LR_HAVE_DESSA_MOVES;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2295,7 +2295,7 @@ static ir_live_interval *ir_split_interval_at(ir_ctx *ctx, ir_live_interval *iva
|
|||||||
|
|
||||||
IR_LOG_LSRA_SPLIT(ival, pos);
|
IR_LOG_LSRA_SPLIT(ival, pos);
|
||||||
IR_ASSERT(pos > ival->range.start);
|
IR_ASSERT(pos > ival->range.start);
|
||||||
ctx->flags |= IR_RA_HAVE_SPLITS;
|
ctx->flags2 |= IR_RA_HAVE_SPLITS;
|
||||||
|
|
||||||
p = &ival->range;
|
p = &ival->range;
|
||||||
prev = NULL;
|
prev = NULL;
|
||||||
@ -2883,7 +2883,7 @@ static ir_reg ir_allocate_blocked_reg(ir_ctx *ctx, ir_live_interval *ival, ir_li
|
|||||||
if (!use_pos) {
|
if (!use_pos) {
|
||||||
/* spill */
|
/* spill */
|
||||||
IR_LOG_LSRA(" ---- Spill", ival, " (no use pos that must be in reg)");
|
IR_LOG_LSRA(" ---- Spill", ival, " (no use pos that must be in reg)");
|
||||||
ctx->flags |= IR_RA_HAVE_SPILLS;
|
ctx->flags2 |= IR_RA_HAVE_SPILLS;
|
||||||
return IR_REG_NONE;
|
return IR_REG_NONE;
|
||||||
}
|
}
|
||||||
next_use_pos = use_pos->pos;
|
next_use_pos = use_pos->pos;
|
||||||
@ -3333,7 +3333,7 @@ static int ir_linear_scan(ir_ctx *ctx)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ctx->flags & IR_LR_HAVE_DESSA_MOVES) {
|
if (ctx->flags2 & IR_LR_HAVE_DESSA_MOVES) {
|
||||||
/* Add fixed intervals for temporary registers used for DESSA moves */
|
/* Add fixed intervals for temporary registers used for DESSA moves */
|
||||||
for (b = 1, bb = &ctx->cfg_blocks[1]; b <= ctx->cfg_blocks_count; b++, bb++) {
|
for (b = 1, bb = &ctx->cfg_blocks[1]; b <= ctx->cfg_blocks_count; b++, bb++) {
|
||||||
IR_ASSERT(!(bb->flags & IR_BB_UNREACHABLE));
|
IR_ASSERT(!(bb->flags & IR_BB_UNREACHABLE));
|
||||||
@ -3385,7 +3385,7 @@ static int ir_linear_scan(ir_ctx *ctx)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx->flags &= ~(IR_RA_HAVE_SPLITS|IR_RA_HAVE_SPILLS);
|
ctx->flags2 &= ~(IR_RA_HAVE_SPLITS|IR_RA_HAVE_SPILLS);
|
||||||
|
|
||||||
#ifdef IR_DEBUG
|
#ifdef IR_DEBUG
|
||||||
if (ctx->flags & IR_DEBUG_RA) {
|
if (ctx->flags & IR_DEBUG_RA) {
|
||||||
@ -3499,7 +3499,7 @@ static int ir_linear_scan(ir_ctx *ctx)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (ctx->flags & (IR_RA_HAVE_SPLITS|IR_RA_HAVE_SPILLS)) {
|
if (ctx->flags2 & (IR_RA_HAVE_SPLITS|IR_RA_HAVE_SPILLS)) {
|
||||||
|
|
||||||
if (ctx->binding) {
|
if (ctx->binding) {
|
||||||
ir_assign_bound_spill_slots(ctx);
|
ir_assign_bound_spill_slots(ctx);
|
||||||
@ -3674,7 +3674,7 @@ static void assign_regs(ir_ctx *ctx)
|
|||||||
memset(ctx->regs, IR_REG_NONE, sizeof(ir_regs) * ctx->insns_count);
|
memset(ctx->regs, IR_REG_NONE, sizeof(ir_regs) * ctx->insns_count);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(ctx->flags & (IR_RA_HAVE_SPLITS|IR_RA_HAVE_SPILLS))) {
|
if (!(ctx->flags2 & (IR_RA_HAVE_SPLITS|IR_RA_HAVE_SPILLS))) {
|
||||||
for (i = 1; i <= ctx->vregs_count; i++) {
|
for (i = 1; i <= ctx->vregs_count; i++) {
|
||||||
ival = ctx->live_intervals[i];
|
ival = ctx->live_intervals[i];
|
||||||
if (ival) {
|
if (ival) {
|
||||||
|
@ -545,7 +545,7 @@ int ir_sccp(ir_ctx *ctx)
|
|||||||
ir_bitqueue worklist;
|
ir_bitqueue worklist;
|
||||||
ir_insn *_values = ir_mem_calloc(ctx->insns_count, sizeof(ir_insn));
|
ir_insn *_values = ir_mem_calloc(ctx->insns_count, sizeof(ir_insn));
|
||||||
|
|
||||||
ctx->flags |= IR_OPT_IN_SCCP;
|
ctx->flags2 |= IR_OPT_IN_SCCP;
|
||||||
|
|
||||||
/* A bit modified SCCP algorithm of M. N. Wegman and F. K. Zadeck */
|
/* A bit modified SCCP algorithm of M. N. Wegman and F. K. Zadeck */
|
||||||
ir_bitqueue_init(&worklist, ctx->insns_count);
|
ir_bitqueue_init(&worklist, ctx->insns_count);
|
||||||
@ -878,8 +878,8 @@ int ir_sccp(ir_ctx *ctx)
|
|||||||
ir_mem_free(_values);
|
ir_mem_free(_values);
|
||||||
ir_bitqueue_free(&worklist);
|
ir_bitqueue_free(&worklist);
|
||||||
|
|
||||||
ctx->flags &= ~IR_OPT_IN_SCCP;
|
ctx->flags2 &= ~IR_OPT_IN_SCCP;
|
||||||
ctx->flags |= IR_SCCP_DONE;
|
ctx->flags2 |= IR_SCCP_DONE;
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
17
ir_x86.dasc
17
ir_x86.dasc
@ -1423,7 +1423,7 @@ binop_fp:
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case IR_CALL:
|
case IR_CALL:
|
||||||
ctx->flags |= IR_HAS_CALLS;
|
ctx->flags2 |= IR_HAS_CALLS;
|
||||||
IR_FALLTHROUGH;
|
IR_FALLTHROUGH;
|
||||||
case IR_TAILCALL:
|
case IR_TAILCALL:
|
||||||
if (ir_in_same_block(ctx, insn->op2)) {
|
if (ir_in_same_block(ctx, insn->op2)) {
|
||||||
@ -1435,9 +1435,10 @@ binop_fp:
|
|||||||
case IR_PARAM:
|
case IR_PARAM:
|
||||||
return ctx->use_lists[ref].count > 0 ? IR_PARAM : IR_SKIPPED | IR_PARAM;
|
return ctx->use_lists[ref].count > 0 ? IR_PARAM : IR_SKIPPED | IR_PARAM;
|
||||||
case IR_ALLOCA:
|
case IR_ALLOCA:
|
||||||
/* alloca() may be use only in functions */
|
/* alloca() may be used only in functions */
|
||||||
if (ctx->flags & IR_FUNCTION) {
|
if (ctx->flags & IR_FUNCTION) {
|
||||||
ctx->flags |= IR_USE_FRAME_POINTER | IR_HAS_ALLOCA;
|
ctx->flags |= IR_USE_FRAME_POINTER;
|
||||||
|
ctx->flags2 |= IR_HAS_ALLOCA;
|
||||||
}
|
}
|
||||||
return IR_ALLOCA;
|
return IR_ALLOCA;
|
||||||
case IR_VSTORE:
|
case IR_VSTORE:
|
||||||
@ -6144,7 +6145,7 @@ static void ir_emit_alloca(ir_ctx *ctx, ir_ref def, ir_insn *insn)
|
|||||||
IR_ASSERT(IR_IS_TYPE_UNSIGNED(val->type) || val->val.i64 > 0);
|
IR_ASSERT(IR_IS_TYPE_UNSIGNED(val->type) || val->val.i64 > 0);
|
||||||
IR_ASSERT(IR_IS_SIGNED_32BIT(val->val.i64));
|
IR_ASSERT(IR_IS_SIGNED_32BIT(val->val.i64));
|
||||||
|
|
||||||
if (ctx->flags & IR_HAS_CALLS) {
|
if (ctx->flags2 & IR_HAS_CALLS) {
|
||||||
/* Stack must be 16 byte aligned */
|
/* Stack must be 16 byte aligned */
|
||||||
size = IR_ALIGNED_SIZE(size, 16);
|
size = IR_ALIGNED_SIZE(size, 16);
|
||||||
} else {
|
} else {
|
||||||
@ -6155,7 +6156,7 @@ static void ir_emit_alloca(ir_ctx *ctx, ir_ref def, ir_insn *insn)
|
|||||||
ctx->call_stack_size += size;
|
ctx->call_stack_size += size;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
int32_t alignment = (ctx->flags & IR_HAS_CALLS) ? 16 : 8;
|
int32_t alignment = (ctx->flags2 & IR_HAS_CALLS) ? 16 : 8;
|
||||||
ir_reg op2_reg = ctx->regs[def][2];
|
ir_reg op2_reg = ctx->regs[def][2];
|
||||||
ir_type type = ctx->ir_base[insn->op2].type;
|
ir_type type = ctx->ir_base[insn->op2].type;
|
||||||
|
|
||||||
@ -6201,7 +6202,7 @@ static void ir_emit_afree(ir_ctx *ctx, ir_ref def, ir_insn *insn)
|
|||||||
IR_ASSERT(IR_IS_TYPE_UNSIGNED(val->type) || val->val.i64 > 0);
|
IR_ASSERT(IR_IS_TYPE_UNSIGNED(val->type) || val->val.i64 > 0);
|
||||||
IR_ASSERT(IR_IS_SIGNED_32BIT(val->val.i64));
|
IR_ASSERT(IR_IS_SIGNED_32BIT(val->val.i64));
|
||||||
|
|
||||||
if (ctx->flags & IR_HAS_CALLS) {
|
if (ctx->flags2 & IR_HAS_CALLS) {
|
||||||
/* Stack must be 16 byte aligned */
|
/* Stack must be 16 byte aligned */
|
||||||
size = IR_ALIGNED_SIZE(size, 16);
|
size = IR_ALIGNED_SIZE(size, 16);
|
||||||
} else {
|
} else {
|
||||||
@ -6212,7 +6213,7 @@ static void ir_emit_afree(ir_ctx *ctx, ir_ref def, ir_insn *insn)
|
|||||||
ctx->call_stack_size -= size;
|
ctx->call_stack_size -= size;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// int32_t alignment = (ctx->flags & IR_HAS_CALLS) ? 16 : 8;
|
// int32_t alignment = (ctx->flags2 & IR_HAS_CALLS) ? 16 : 8;
|
||||||
ir_reg op2_reg = ctx->regs[def][2];
|
ir_reg op2_reg = ctx->regs[def][2];
|
||||||
ir_type type = ctx->ir_base[insn->op2].type;
|
ir_type type = ctx->ir_base[insn->op2].type;
|
||||||
|
|
||||||
@ -8509,7 +8510,7 @@ void ir_fix_stack_frame(ir_ctx *ctx)
|
|||||||
ctx->stack_frame_alignment = 0;
|
ctx->stack_frame_alignment = 0;
|
||||||
ctx->call_stack_size = 0;
|
ctx->call_stack_size = 0;
|
||||||
|
|
||||||
if (ctx->flags & IR_HAS_CALLS) {
|
if (ctx->flags2 & IR_HAS_CALLS) {
|
||||||
/* Stack must be 16 byte aligned */
|
/* Stack must be 16 byte aligned */
|
||||||
if (!(ctx->flags & IR_FUNCTION)) {
|
if (!(ctx->flags & IR_FUNCTION)) {
|
||||||
while (IR_ALIGNED_SIZE(ctx->stack_frame_size, 16) != ctx->stack_frame_size) {
|
while (IR_ALIGNED_SIZE(ctx->stack_frame_size, 16) != ctx->stack_frame_size) {
|
||||||
|
Loading…
Reference in New Issue
Block a user