mirror of
https://github.com/danog/ir.git
synced 2024-11-26 20:34:53 +01:00
JMP optimization. Lift constant IJMP targets into jmp_table(s).
This commit is contained in:
parent
31ea3153f3
commit
fd653528e9
@ -3389,7 +3389,24 @@ static void ir_emit_switch(ir_ctx *ctx, uint32_t b, ir_ref def, ir_insn *insn)
|
||||
|.align 8
|
||||
|1:
|
||||
for (i = 0; i <= (max.i64 - min.i64); i++) {
|
||||
| .addr =>labels[i]
|
||||
int b = labels[i];
|
||||
ir_block *bb = &ctx->cfg_blocks[b];
|
||||
ir_insn *insn = &ctx->ir_base[bb->end];
|
||||
|
||||
if (insn->op == IR_IJMP && IR_IS_CONST_REF(insn->op2)) {
|
||||
ir_ref prev = ctx->prev_ref[bb->end];
|
||||
if (prev != bb->start && ctx->ir_base[prev].op == IR_SNAPSHOT) {
|
||||
prev = ctx->prev_ref[prev];
|
||||
}
|
||||
if (prev == bb->start) {
|
||||
void *addr = ir_jmp_addr(ctx, insn, &ctx->ir_base[insn->op2]);
|
||||
|
||||
| .addr &addr
|
||||
bb->flags |= IR_BB_SKIP;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
| .addr =>b
|
||||
}
|
||||
|.code
|
||||
ir_mem_free(labels);
|
||||
@ -4905,7 +4922,9 @@ void *ir_emit_code(ir_ctx *ctx, size_t *size_ptr)
|
||||
|
||||
for (b = 1, bb = ctx->cfg_blocks + b; b <= ctx->cfg_blocks_count; b++, bb++) {
|
||||
IR_ASSERT(!(bb->flags & IR_BB_UNREACHABLE));
|
||||
if (ctx->prev_ref[bb->end] == bb->start
|
||||
if (bb->flags & IR_BB_SKIP) {
|
||||
continue;
|
||||
} else if (ctx->prev_ref[bb->end] == bb->start
|
||||
&& bb->successors_count == 1
|
||||
&& (ctx->ir_base[bb->end].op == IR_END || ctx->ir_base[bb->end].op == IR_LOOP_END)
|
||||
&& !(bb->flags & (IR_BB_START|IR_BB_ENTRY|IR_BB_DESSA_MOVES))) {
|
||||
|
43
ir_disasm.c
43
ir_disasm.c
@ -397,8 +397,9 @@ int ir_disasm(const char *name,
|
||||
p = (uintptr_t*)((char*)start + jmp_table_offset);
|
||||
while (n > 0) {
|
||||
if (*p) {
|
||||
IR_ASSERT((uintptr_t)*p >= (uintptr_t)start && (uintptr_t)*p < (uintptr_t)orig_end);
|
||||
ir_hashtab_add(&labels, (uint32_t)((uintptr_t)*p - (uintptr_t)start), -1);
|
||||
if ((uintptr_t)*p >= (uintptr_t)start && (uintptr_t)*p < (uintptr_t)orig_end) {
|
||||
ir_hashtab_add(&labels, (uint32_t)((uintptr_t)*p - (uintptr_t)start), -1);
|
||||
}
|
||||
}
|
||||
p++;
|
||||
n -= sizeof(void*);
|
||||
@ -628,20 +629,38 @@ int ir_disasm(const char *name,
|
||||
}
|
||||
}
|
||||
if (*p) {
|
||||
IR_ASSERT((uintptr_t)*p >= (uintptr_t)start && (uintptr_t)*p < (uintptr_t)orig_end);
|
||||
entry = ir_hashtab_find(&labels, (uint32_t)(*p - (uintptr_t)start));
|
||||
IR_ASSERT(entry != (ir_ref)IR_INVALID_VAL);
|
||||
if (entry >= 0) {
|
||||
if (sizeof(void*) == 8) {
|
||||
fprintf(f, "\t.qword .ENTRY_%d\n", entry);
|
||||
if ((uintptr_t)*p >= (uintptr_t)start && (uintptr_t)*p < (uintptr_t)orig_end) {
|
||||
entry = ir_hashtab_find(&labels, (uint32_t)(*p - (uintptr_t)start));
|
||||
IR_ASSERT(entry != (ir_ref)IR_INVALID_VAL);
|
||||
if (entry >= 0) {
|
||||
if (sizeof(void*) == 8) {
|
||||
fprintf(f, "\t.qword .ENTRY_%d\n", entry);
|
||||
} else {
|
||||
fprintf(f, "\t.dword .ENTRY_%d\n", entry);
|
||||
}
|
||||
} else {
|
||||
fprintf(f, "\t.dword .ENTRY_%d\n", entry);
|
||||
if (sizeof(void*) == 8) {
|
||||
fprintf(f, "\t.qword .L%d\n", -entry);
|
||||
} else {
|
||||
fprintf(f, "\t.dword .L%d\n", -entry);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (sizeof(void*) == 8) {
|
||||
fprintf(f, "\t.qword .L%d\n", -entry);
|
||||
int64_t offset;
|
||||
const char *name = ir_disasm_find_symbol(*p, &offset);
|
||||
|
||||
if (name && offset == 0) {
|
||||
if (sizeof(void*) == 8) {
|
||||
fprintf(f, "\t.qword %s\n", name);
|
||||
} else {
|
||||
fprintf(f, "\t.dword %s\n", name);
|
||||
}
|
||||
} else {
|
||||
fprintf(f, "\t.dword .L%d\n", -entry);
|
||||
if (sizeof(void*) == 8) {
|
||||
fprintf(f, "\t.qword 0x%0llx\n", (long long)*p);
|
||||
} else {
|
||||
fprintf(f, "\t.dword 0x%0x\n", (int)*p);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
@ -805,6 +805,7 @@ struct _ir_use_list {
|
||||
#define IR_BB_IRREDUCIBLE_LOOP (1<<4)
|
||||
#define IR_BB_DESSA_MOVES (1<<5) /* translation out of SSA requires MOVEs */
|
||||
#define IR_BB_EMPTY (1<<6)
|
||||
#define IR_BB_SKIP (1<<7) /* skip during code generation */
|
||||
|
||||
struct _ir_block {
|
||||
uint32_t flags;
|
||||
|
23
ir_x86.dasc
23
ir_x86.dasc
@ -5674,7 +5674,24 @@ static void ir_emit_switch(ir_ctx *ctx, uint32_t b, ir_ref def, ir_insn *insn)
|
||||
|.align aword
|
||||
|1:
|
||||
for (i = 0; i <= (max.i64 - min.i64); i++) {
|
||||
| .aword =>labels[i]
|
||||
int b = labels[i];
|
||||
ir_block *bb = &ctx->cfg_blocks[b];
|
||||
ir_insn *insn = &ctx->ir_base[bb->end];
|
||||
|
||||
if (insn->op == IR_IJMP && IR_IS_CONST_REF(insn->op2)) {
|
||||
ir_ref prev = ctx->prev_ref[bb->end];
|
||||
if (prev != bb->start && ctx->ir_base[prev].op == IR_SNAPSHOT) {
|
||||
prev = ctx->prev_ref[prev];
|
||||
}
|
||||
if (prev == bb->start) {
|
||||
void *addr = ir_jmp_addr(ctx, insn, &ctx->ir_base[insn->op2]);
|
||||
|
||||
| .aword &addr
|
||||
bb->flags |= IR_BB_SKIP;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
| .aword =>b
|
||||
}
|
||||
|.code
|
||||
ir_mem_free(labels);
|
||||
@ -7761,7 +7778,9 @@ void *ir_emit_code(ir_ctx *ctx, size_t *size_ptr)
|
||||
|
||||
for (b = 1, bb = ctx->cfg_blocks + b; b <= ctx->cfg_blocks_count; b++, bb++) {
|
||||
IR_ASSERT(!(bb->flags & IR_BB_UNREACHABLE));
|
||||
if (ctx->prev_ref[bb->end] == bb->start
|
||||
if (bb->flags & IR_BB_SKIP) {
|
||||
continue;
|
||||
} else if (ctx->prev_ref[bb->end] == bb->start
|
||||
&& bb->successors_count == 1
|
||||
&& (ctx->ir_base[bb->end].op == IR_END || ctx->ir_base[bb->end].op == IR_LOOP_END)
|
||||
&& !(bb->flags & (IR_BB_START|IR_BB_ENTRY|IR_BB_DESSA_MOVES))) {
|
||||
|
Loading…
Reference in New Issue
Block a user