Alien-LibJIT
view release on metacpan or search on metacpan
libjit/jit/jit-reg-alloc.c view on Meta::CPAN
index = regs->dest_input_index;
}
else
{
index = 2;
}
desc2 = ®s->descs[index];
}
else
{
desc2 = desc;
}
if(regs->flip_args)
{
if(regs->x87_arith && index == 1
&& desc2->value->in_register && !desc2->copy)
{
desc->reg = desc2->value->reg;
}
else
{
desc->reg = (gen->reg_stack_top
- regs->loaded_stack_count
+ index - 1);
}
}
else
{
if(regs->x87_arith && index == 2
&& desc2->value->in_register && !desc2->copy)
{
desc->reg = desc2->value->reg;
}
else
{
desc->reg = (gen->reg_stack_top
- regs->loaded_stack_count
+ regs->wanted_stack_count
- index);
}
}
}
#ifdef JIT_REG_DEBUG
printf("reg = %d\n", desc->reg);
if(desc->reg < JIT_REG_STACK_START || desc->reg > JIT_REG_STACK_END)
{
printf("*** Invalid stack register! ***\n");
abort();
}
#endif
}
#endif
/*
* Associate a temporary with register.
*/
static void
bind_temporary(jit_gencode_t gen, int reg, int other_reg)
{
#ifdef JIT_REG_DEBUG
printf("bind_temporary(reg = %d, other_reg = %d)\n", reg, other_reg);
#endif
gen->contents[reg].num_values = 0;
gen->contents[reg].age = 0;
gen->contents[reg].used_for_temp = 1;
gen->contents[reg].is_long_end = 0;
gen->contents[reg].is_long_start = 0;
if(other_reg >= 0)
{
gen->contents[other_reg].num_values = 0;
gen->contents[other_reg].age = 0;
gen->contents[other_reg].used_for_temp = 1;
gen->contents[other_reg].is_long_end = 0;
gen->contents[other_reg].is_long_start = 0;
}
}
/*
* Associate value with register.
*/
static void
bind_value(jit_gencode_t gen, jit_value_t value, int reg, int other_reg, int still_in_frame)
{
#ifdef JIT_REG_DEBUG
printf("bind_value(value = ");
jit_dump_value(stdout, jit_value_get_function(value), value, 0);
printf(", reg = %d, other_reg = %d, still_in_frame = %d)\n",
reg, other_reg, still_in_frame);
#endif
if(value->has_global_register && value->global_reg == reg)
{
value->in_register = 0;
value->in_global_register = 1;
return;
}
if(value->is_constant)
{
still_in_frame = 0;
}
#ifdef JIT_REG_DEBUG
if(gen->contents[reg].num_values == JIT_MAX_REG_VALUES)
{
printf("*** Too many values for one register! ***\n");
abort();
}
#endif
gen->contents[reg].values[gen->contents[reg].num_values] = value;
++(gen->contents[reg].num_values);
gen->contents[reg].age = gen->current_age;
gen->contents[reg].used_for_temp = 0;
gen->contents[reg].is_long_end = 0;
if(other_reg == -1)
{
gen->contents[reg].is_long_start = 0;
}
else
{
gen->contents[reg].is_long_start = 1;
gen->contents[other_reg].num_values = 0;
gen->contents[other_reg].age = gen->current_age;
gen->contents[other_reg].used_for_temp = 0;
gen->contents[other_reg].is_long_start = 0;
gen->contents[other_reg].is_long_end = 1;
}
++(gen->current_age);
/* Adjust the value to reflect that it is in "reg", and maybe the frame */
value->in_register = 1;
if(value->has_global_register)
{
value->in_global_register = still_in_frame;
}
else
{
value->in_frame = still_in_frame;
}
value->reg = reg;
}
/*
* Disassociate value with register.
*/
static void
unbind_value(jit_gencode_t gen, jit_value_t value, int reg, int other_reg)
{
int index;
#ifdef JIT_REG_DEBUG
printf("unbind_value(value = ");
jit_dump_value(stdout, jit_value_get_function(value), value, 0);
printf(", reg = %d, other_reg = %d)\n", reg, other_reg);
#endif
if(!value->in_register || value->reg != reg)
{
return;
}
value->in_register = 0;
value->reg = -1;
for(index = gen->contents[reg].num_values - 1; index >= 0; --index)
{
if(gen->contents[reg].values[index] == value)
{
--(gen->contents[reg].num_values);
for(; index < gen->contents[reg].num_values; index++)
{
gen->contents[reg].values[index] = gen->contents[reg].values[index + 1];
}
break;
}
}
if(gen->contents[reg].num_values == 0 && other_reg >= 0)
{
gen->contents[reg].is_long_start = 0;
gen->contents[other_reg].is_long_end = 0;
}
}
/*
* Swap the contents of a register and the top of the register stack. If
* the register is not a stack register then the function has no effect.
*/
#ifdef JIT_REG_STACK
static void
exch_stack_top(jit_gencode_t gen, int reg, int pop)
{
int top, index;
int num_values, used_for_temp, age;
jit_value_t value1, value2;
#ifdef JIT_REG_DEBUG
printf("exch_stack_top(reg = %d, pop = %d)\n", reg, pop);
#endif
if(!IS_STACK_REG(reg))
{
return;
}
/* Find the top of the stack. */
top = gen->reg_stack_top - 1;
if(pop)
{
/* Generate move/pop-top instruction. */
_jit_gen_move_top(gen, reg);
libjit/jit/jit-reg-alloc.c view on Meta::CPAN
_jit_gen_exch_top(gen, reg);
}
/* Update information about the contents of the registers. */
for(index = 0;
index < gen->contents[reg].num_values || index < gen->contents[top].num_values;
index++)
{
value1 = (index < gen->contents[top].num_values
? gen->contents[top].values[index] : 0);
value2 = (index < gen->contents[reg].num_values
? gen->contents[reg].values[index] : 0);
if(value1)
{
value1->reg = reg;
}
gen->contents[reg].values[index] = value1;
if(pop)
{
if(value2)
{
value2->in_register = 0;
value2->reg = -1;
}
gen->contents[top].values[index] = 0;
}
else
{
if(value2)
{
value2->reg = top;
}
gen->contents[top].values[index] = value2;
}
}
if(pop)
{
num_values = 0;
used_for_temp = 0;
age = 0;
}
else
{
num_values = gen->contents[reg].num_values;
used_for_temp = gen->contents[reg].used_for_temp;
age = gen->contents[reg].age;
}
gen->contents[reg].num_values = gen->contents[top].num_values;
gen->contents[reg].used_for_temp = gen->contents[top].used_for_temp;
gen->contents[reg].age = gen->contents[top].age;
gen->contents[top].num_values = num_values;
gen->contents[top].used_for_temp = used_for_temp;
gen->contents[top].age = age;
}
#endif
/*
* Drop value from the register and optionally bind a temporary value in place of it.
*/
static void
free_value(jit_gencode_t gen, jit_value_t value, int reg, int other_reg, int temp)
{
#ifdef JIT_REG_DEBUG
printf("free_value(value = ");
jit_dump_value(stdout, jit_value_get_function(value), value, 0);
printf(", reg = %d, other_reg = %d, temp = %d)\n", reg, other_reg, temp);
#endif
/* Never free global registers. */
if(value->has_global_register && value->global_reg == reg)
{
return;
}
if(gen->contents[reg].num_values == 1)
{
if(temp)
{
unbind_value(gen, value, reg, other_reg);
bind_temporary(gen, reg, other_reg);
return;
}
#ifdef JIT_REG_STACK
if(IS_STACK_REG(reg))
{
/* Free stack register. */
exch_stack_top(gen, reg, 1);
return;
}
#endif
}
unbind_value(gen, value, reg, other_reg);
}
/*
* Save the value from the register into its frame position and optionally free it.
* If the value is already in the frame or is a constant then it is not saved but
* the free option still applies to them.
*/
static void
save_value(jit_gencode_t gen, jit_value_t value, int reg, int other_reg, int free)
{
#ifdef JIT_REG_DEBUG
printf("save_value(value = ");
jit_dump_value(stdout, jit_value_get_function(value), value, 0);
printf(", reg = %d, other_reg = %d, free=%d)\n", reg, other_reg, free);
#endif
/* First take care of values that reside in global registers. */
if(value->has_global_register)
{
/* Never free global registers. */
if(value->global_reg == reg)
{
return;
}
if(!value->in_global_register)
{
_jit_gen_spill_reg(gen, reg, other_reg, value);
value->in_global_register = 1;
}
if(free)
{
unbind_value(gen, value, reg, other_reg);
}
return;
}
/* Take care of constants and values that are already in frame. */
if(value->is_constant || value->in_frame)
{
if(free)
{
free_value(gen, value, reg, other_reg, 0);
}
return;
}
/* Now really save the value into the frame. */
#ifdef JIT_REG_STACK
if(IS_STACK_REG(reg))
{
int top;
/* Find the top of the stack. */
top = gen->reg_stack_top - 1;
/* Move the value on the stack top if it is not already there. */
if(top != reg)
{
exch_stack_top(gen, reg, 0);
}
if(free)
{
if(gen->contents[top].num_values == 1)
{
_jit_gen_spill_top(gen, top, value, 1);
--(gen->reg_stack_top);
}
else
{
_jit_gen_spill_top(gen, top, value, 0);
}
unbind_value(gen, value, top, 0);
}
else
{
_jit_gen_spill_top(gen, top, value, 0);
}
}
else
#endif
{
_jit_gen_spill_reg(gen, reg, other_reg, value);
if(free)
{
unbind_value(gen, value, reg, other_reg);
}
}
value->in_frame = 1;
}
/*
* Spill a specific register.
*/
static void
spill_register(jit_gencode_t gen, int reg)
{
int other_reg, index;
jit_value_t value;
#ifdef JIT_REG_DEBUG
printf("spill_register(reg = %d)\n", reg);
#endif
/* Find the other register in a long pair */
if(gen->contents[reg].is_long_start)
{
other_reg = jit_reg_other_reg(reg);
}
else if(gen->contents[reg].is_long_end)
{
other_reg = reg;
reg = get_long_pair_start(reg);
}
else
{
other_reg = -1;
}
for(index = gen->contents[reg].num_values - 1; index >= 0; --index)
{
value = gen->contents[reg].values[index];
save_value(gen, value, reg, other_reg, 1);
}
}
/*
* Spill a register clobbered by the instruction.
*/
static void
spill_clobbered_register(jit_gencode_t gen, _jit_regs_t *regs, int reg)
{
int other_reg, index, usage;
jit_value_t value;
#ifdef JIT_REG_DEBUG
printf("spill_clobbered_register(reg = %d)\n", reg);
#endif
#ifdef JIT_REG_STACK
/* For a stack register spill it in two passes. First drop values that
reqiure neither spilling nor a generation of the free instruction.
Then lazily exchange the register with the top and spill or free it
as necessary. This approach might save a exch/free instructions in
certain cases. */
if(IS_STACK_REG(reg))
{
for(index = gen->contents[reg].num_values - 1; index >= 0; --index)
{
if(gen->contents[reg].num_values == 1)
{
break;
}
value = gen->contents[reg].values[index];
usage = value_usage(regs, value);
if((usage & VALUE_INPUT) != 0)
{
continue;
}
if((usage & VALUE_DEAD) != 0 || value->in_frame)
{
unbind_value(gen, value, reg, -1);
}
}
for(index = gen->contents[reg].num_values - 1; index >= 0; --index)
{
int top;
value = gen->contents[reg].values[index];
usage = value_usage(regs, value);
if((usage & VALUE_INPUT) != 0)
{
if((usage & VALUE_DEAD) != 0 || value->in_frame)
{
continue;
}
top = gen->reg_stack_top - 1;
if(reg != top)
{
exch_stack_top(gen, reg, 0);
reg = top;
}
save_value(gen, value, reg, -1, 0);
}
else
{
top = gen->reg_stack_top - 1;
if(reg != top)
{
exch_stack_top(gen, reg, 0);
reg = top;
}
if((usage & VALUE_DEAD) != 0 || value->in_frame)
{
free_value(gen, value, reg, -1, 0);
}
else
{
save_value(gen, value, reg, -1, 1);
}
}
}
}
else
#endif
{
/* Find the other register in a long pair */
if(gen->contents[reg].is_long_start)
{
other_reg = jit_reg_other_reg(reg);
}
else if(gen->contents[reg].is_long_end)
{
other_reg = reg;
reg = get_long_pair_start(reg);
}
else
{
other_reg = -1;
libjit/jit/jit-reg-alloc.c view on Meta::CPAN
}
reg = desc->value->reg;
if(gen->contents[reg].is_long_start)
{
other_reg = jit_reg_other_reg(reg);
}
else
{
other_reg = -1;
}
free_value(gen, desc->value, reg, other_reg, 0);
}
static void
load_input_value(jit_gencode_t gen, _jit_regs_t *regs, int index)
{
_jit_regdesc_t *desc;
#ifdef JIT_REG_DEBUG
printf("load_input_value(%d)\n", index);
#endif
desc = ®s->descs[index];
if(!desc->value || desc->duplicate)
{
return;
}
if(desc->value->has_global_register)
{
if(desc->value->in_global_register && desc->value->global_reg == desc->reg)
{
return;
}
if(desc->value->in_register && desc->value->reg == desc->reg)
{
update_age(gen, desc);
return;
}
_jit_gen_load_value(gen, desc->reg, desc->other_reg, desc->value);
}
else if(desc->value->in_register)
{
if(desc->value->reg == desc->reg)
{
update_age(gen, desc);
if(IS_STACK_REG(desc->reg))
{
desc->stack_reg = desc->reg;
}
return;
}
#ifdef JIT_REG_STACK
if(IS_STACK_REG(desc->reg))
{
_jit_gen_load_value(gen, gen->reg_stack_top, -1, desc->value);
desc->stack_reg = gen->reg_stack_top++;
bind_temporary(gen, desc->stack_reg, -1);
}
else
#endif
{
_jit_gen_load_value(gen, desc->reg, desc->other_reg, desc->value);
bind_temporary(gen, desc->reg, desc->other_reg);
}
}
else
{
#ifdef JIT_REG_STACK
if(IS_STACK_REG(desc->reg))
{
_jit_gen_load_value(gen, gen->reg_stack_top, -1, desc->value);
desc->stack_reg = gen->reg_stack_top++;
bind_value(gen, desc->value, desc->stack_reg, -1, 1);
}
else
#endif
{
_jit_gen_load_value(gen, desc->reg, desc->other_reg, desc->value);
bind_value(gen, desc->value, desc->reg, desc->other_reg, 1);
}
}
}
#ifdef JIT_REG_STACK
static void
move_input_value(jit_gencode_t gen, _jit_regs_t *regs, int index)
{
_jit_regdesc_t *desc;
int src_reg, dst_reg;
#ifdef JIT_REG_DEBUG
printf("move_input_value(%d)\n", index);
#endif
desc = ®s->descs[index];
if(!desc->value || desc->duplicate || !desc->value->in_register)
{
return;
}
if(!IS_STACK_REG(desc->value->reg))
{
return;
}
if(desc->copy)
{
src_reg = desc->stack_reg;
if(src_reg < 0)
{
return;
}
}
else
{
src_reg = desc->value->reg;
}
if(desc->reg < gen->reg_stack_top)
{
dst_reg = desc->reg;
}
else
{
dst_reg = gen->reg_stack_top - 1;
}
if(src_reg != dst_reg)
{
if(src_reg != (gen->reg_stack_top - 1))
{
exch_stack_top(gen, src_reg, 0);
}
if(dst_reg != (gen->reg_stack_top - 1))
{
exch_stack_top(gen, dst_reg, 0);
}
}
}
#endif
#ifdef JIT_REG_STACK
static void
pop_input_value(jit_gencode_t gen, _jit_regs_t *regs, int index)
{
_jit_regdesc_t *desc;
#ifdef JIT_REG_DEBUG
printf("pop_input_value(%d)\n", index);
#endif
desc = ®s->descs[index];
if(!desc->value || desc->duplicate)
{
return;
}
if(IS_STACK_REG(desc->reg))
{
if(desc->copy)
{
gen->contents[desc->reg].used_for_temp = 0;
}
else
{
unbind_value(gen, desc->value, desc->reg, 0);
}
--(gen->reg_stack_top);
}
}
#endif
static void
commit_input_value(jit_gencode_t gen, _jit_regs_t *regs, int index, int killed)
{
_jit_regdesc_t *desc;
int reg, other_reg;
#ifdef JIT_REG_DEBUG
printf("commit_input_value(%d)\n", index);
#endif
desc = ®s->descs[index];
if(!desc->value || desc->duplicate)
{
return;
}
#ifdef JIT_REG_STACK
if(!IS_STACK_REG(desc->reg))
{
killed = 0;
}
#endif
if(desc->copy)
{
#ifdef JIT_REG_STACK
if(killed)
{
killed = 0;
}
else
#endif
{
gen->contents[desc->reg].used_for_temp = 0;
if(desc->other_reg >= 0)
{
gen->contents[desc->other_reg].used_for_temp = 0;
}
}
}
#ifdef JIT_REG_STACK
if(!killed && desc->kill && desc->value->in_register)
#else
if(desc->kill && desc->value->in_register)
#endif
{
reg = desc->value->reg;
if(gen->contents[reg].is_long_start)
{
other_reg = jit_reg_other_reg(reg);
}
else
{
other_reg = -1;
}
free_value(gen, desc->value, reg, other_reg, 0);
}
#ifdef JIT_REG_DEBUG
printf("value = ");
jit_dump_value(stdout, jit_value_get_function(desc->value), desc->value, 0);
printf("\n");
printf("value->in_register = %d\n", desc->value->in_register);
printf("value->reg = %d\n", desc->value->reg);
printf("value->in_global_register = %d\n", desc->value->in_global_register);
printf("value->global_reg = %d\n", desc->value->global_reg);
printf("value->in_frame = %d\n", desc->value->in_frame);
#endif
}
static void
commit_output_value(jit_gencode_t gen, _jit_regs_t *regs, int push_stack_top)
{
_jit_regdesc_t *desc;
#ifdef JIT_REG_DEBUG
printf("commit_output_value()\n");
#endif
desc = ®s->descs[0];
if(!desc->value)
{
return;
}
#ifdef JIT_REG_STACK
if(IS_STACK_REG(desc->reg) && push_stack_top)
{
++(gen->reg_stack_top);
}
#endif
bind_value(gen, desc->value, desc->reg, desc->other_reg, 0);
if(!desc->used)
{
if(desc->live)
{
save_value(gen, desc->value, desc->reg, desc->other_reg, 1);
}
else
{
free_value(gen, desc->value, desc->reg, desc->other_reg, 0);
}
}
else if(desc->kill)
{
save_value(gen, desc->value, desc->reg, desc->other_reg, 1);
}
#ifdef JIT_REG_DEBUG
printf("value = ");
jit_dump_value(stdout, jit_value_get_function(desc->value), desc->value, 0);
printf("\n");
printf("value->in_register = %d\n", desc->value->in_register);
printf("value->reg = %d\n", desc->value->reg);
printf("value->in_global_register = %d\n", desc->value->in_global_register);
printf("value->global_reg = %d\n", desc->value->global_reg);
printf("value->in_frame = %d\n", desc->value->in_frame);
#endif
}
/*@
* @deftypefun void _jit_regs_lookup (char *name)
* Get the pseudo register by its name.
* @end deftypefun
@*/
int
_jit_regs_lookup(char *name)
{
int reg;
if(name)
{
for(reg = 0; reg < JIT_NUM_REGS; reg++)
{
if(strcmp(jit_reg_name(reg), name) == 0)
{
return reg;
}
}
}
return -1;
}
/*@
* @deftypefun void _jit_regs_alloc_global (jit_gencode_t gen, jit_function_t func)
* Perform global register allocation on the values in @code{func}.
* This is called during function compilation just after variable
* liveness has been computed.
* @end deftypefun
@*/
void _jit_regs_alloc_global(jit_gencode_t gen, jit_function_t func)
{
libjit/jit/jit-reg-alloc.c view on Meta::CPAN
/* If this is a stack register, then we need to find the
register that contains the top-most stack position,
because we must spill stack registers from top down.
As we spill each one, something else will become the top */
#ifdef JIT_REG_STACK
if(IS_STACK_REG(reg))
{
if(gen->reg_stack_top > JIT_REG_STACK_START)
{
spill_register(gen, gen->reg_stack_top - 1);
}
}
else
#endif
{
spill_register(gen, reg);
}
}
#ifdef JIT_REG_DEBUG
printf("leave _jit_regs_spill_all\n\n");
#endif
}
/*@
* @deftypefun void _jit_regs_set_incoming (jit_gencode_t gen, int reg, jit_value_t value)
* Set pseudo register @code{reg} to record that it currently holds the
* contents of @code{value}. The register must not contain any other
* live value at this point.
* @end deftypefun
@*/
void
_jit_regs_set_incoming(jit_gencode_t gen, int reg, jit_value_t value)
{
int other_reg;
/* Find the other register in a register pair */
other_reg = jit_reg_get_pair(value->type, reg);
/* avd: It's too late to spill here, if there was any
value it is already cloberred by the incoming value.
So for correct code generation the register must be
free by now (spilled at some earlier point). */
#if 0
/* Eject any values that are currently in the register */
spill_register(gen, reg);
if(other_reg >= 0)
{
spill_register(gen, other_reg);
}
#endif
/* Record that the value is in "reg", but not in the frame */
#ifdef JIT_REG_STACK
if(IS_STACK_REG(reg))
{
++(gen->reg_stack_top);
}
#endif
bind_value(gen, value, reg, other_reg, 0);
}
/*@
* @deftypefun void _jit_regs_set_outgoing (jit_gencode_t gen, int reg, jit_value_t value)
* Load the contents of @code{value} into pseudo register @code{reg},
* spilling out the current contents. This is used to set up outgoing
* parameters for a function call.
* @end deftypefun
@*/
void
_jit_regs_set_outgoing(jit_gencode_t gen, int reg, jit_value_t value)
{
int other_reg;
#ifdef JIT_BACKEND_X86
jit_type_t type;
other_reg = -1;
type = jit_type_normalize(value->type);
if(type)
{
/* We might need to put float values in register pairs under x86 */
if(type->kind == JIT_TYPE_LONG || type->kind == JIT_TYPE_ULONG ||
type->kind == JIT_TYPE_FLOAT64 || type->kind == JIT_TYPE_NFLOAT)
{
/* Long values in outgoing registers must be in ECX:EDX,
not in the ordinary register pairing of ECX:EBX */
other_reg = 2;
/* Force the value out of whatever register it is already in */
_jit_regs_force_out(gen, value, 0);
}
}
#else
other_reg = jit_reg_get_pair(value->type, reg);
#endif
if(value->in_register && value->reg == reg)
{
/* The value is already in the register, but we may need to spill
if the frame copy is not up to date with the register */
if(!(value->in_global_register || value->in_frame))
{
save_value(gen, value, reg, other_reg, 0);
}
/* The value is no longer "really" in the register. A copy is
left behind, but the value itself reverts to the frame copy
as we are about to kill the registers in a function call */
free_value(gen, value, reg, other_reg, 1);
}
else
{
/* Reload the value into the specified register */
spill_register(gen, reg);
if(other_reg >= 0)
{
spill_register(gen, other_reg);
}
libjit/jit/jit-reg-alloc.c view on Meta::CPAN
return 0;
}
suitable_reg = -1;
suitable_other_reg = -1;
suitable_cost = COST_TOO_MUCH;
suitable_age = -1;
for(reg = 0; reg < JIT_NUM_REGS; reg++)
{
if((jit_reg_flags(reg) & type) == 0)
{
continue;
}
if(jit_reg_is_used(gen->inhibit, reg))
{
continue;
}
if(jit_reg_is_used(gen->permanent, reg))
{
continue;
}
other_reg = jit_reg_get_pair(value->type, reg);
if(other_reg >= 0)
{
if(jit_reg_is_used(gen->inhibit, other_reg))
{
continue;
}
if(jit_reg_is_used(gen->permanent, other_reg))
{
continue;
}
}
spill_cost = compute_spill_cost(gen, 0, reg, other_reg);
if(spill_cost < suitable_cost
|| (spill_cost == suitable_cost
&& spill_cost > 0 && gen->contents[reg].age < suitable_age))
{
suitable_reg = reg;
suitable_other_reg = other_reg;
suitable_cost = spill_cost;
suitable_age = gen->contents[reg].age;
}
}
if(suitable_reg >= 0)
{
spill_register(gen, suitable_reg);
if(suitable_other_reg >= 0)
{
spill_register(gen, suitable_other_reg);
}
_jit_gen_load_value(gen, suitable_reg, suitable_other_reg, value);
if(!destroy && !used_again)
{
bind_value(gen, value, suitable_reg, suitable_other_reg, 1);
}
else
{
bind_temporary(gen, suitable_reg, suitable_other_reg);
}
}
return suitable_reg;
}
void
_jit_regs_init(jit_gencode_t gen, _jit_regs_t *regs, int flags)
{
int index;
jit_memset(regs, 0, sizeof(_jit_regs_t));
regs->ternary = (flags & _JIT_REGS_TERNARY) != 0;
regs->branch = (flags & _JIT_REGS_BRANCH) != 0;
regs->copy = (flags & _JIT_REGS_COPY) != 0;
regs->commutative = (flags & _JIT_REGS_COMMUTATIVE) != 0;
regs->free_dest = (flags & _JIT_REGS_FREE_DEST) != 0;
#ifdef JIT_REG_STACK
regs->on_stack = (flags & _JIT_REGS_STACK) != 0;
regs->x87_arith = (flags & _JIT_REGS_X87_ARITH) != 0;
regs->reversible = (flags & _JIT_REGS_REVERSIBLE) != 0;
regs->no_pop = (regs->on_stack & regs->copy) != 0;
#endif
for(index = 0; index < _JIT_REGS_VALUE_MAX; index++)
{
regs->descs[index].reg = -1;
regs->descs[index].other_reg = -1;
regs->descs[index].stack_reg = -1;
}
for(index = 0; index < _JIT_REGS_SCRATCH_MAX; index++)
{
regs->scratch[index].reg = -1;
}
regs->clobber = jit_regused_init;
regs->assigned = gen->inhibit;
}
void
_jit_regs_init_dest(_jit_regs_t *regs, jit_insn_t insn, int flags, _jit_regclass_t *regclass)
{
if((insn->flags & JIT_INSN_DEST_OTHER_FLAGS) == 0)
{
set_regdesc_value(regs, 0, insn->dest, flags, regclass,
(insn->flags & JIT_INSN_DEST_LIVE) != 0,
(insn->flags & JIT_INSN_DEST_NEXT_USE) != 0);
}
}
void
_jit_regs_init_value1(_jit_regs_t *regs, jit_insn_t insn, int flags, _jit_regclass_t *regclass)
{
if((insn->flags & JIT_INSN_VALUE1_OTHER_FLAGS) == 0)
{
set_regdesc_value(regs, 1, insn->value1, flags, regclass,
(insn->flags & JIT_INSN_VALUE1_LIVE) != 0,
(insn->flags & JIT_INSN_VALUE1_NEXT_USE) != 0);
}
libjit/jit/jit-reg-alloc.c view on Meta::CPAN
{
pop_input_value(gen, regs, 0);
pop_input_value(gen, regs, 1);
pop_input_value(gen, regs, 2);
}
#endif
commit_input_value(gen, regs, 0, 1);
commit_input_value(gen, regs, 1, 1);
commit_input_value(gen, regs, 2, 1);
}
else if(!regs->descs[0].value)
{
#ifdef JIT_REG_STACK
if(regs->wanted_stack_count > 0)
{
pop_input_value(gen, regs, 1);
pop_input_value(gen, regs, 2);
}
#endif
commit_input_value(gen, regs, 1, 1);
commit_input_value(gen, regs, 2, 1);
}
#ifdef JIT_REG_STACK
else if(regs->wanted_stack_count > 0)
{
int pop1, pop2;
struct _jit_value temp;
int reg1, reg2;
pop1 = pop2 = 0;
if(!regs->no_pop)
{
if(regs->x87_arith)
{
if(regs->flip_args)
{
pop_input_value(gen, regs, 2);
pop2 = 1;
}
else
{
pop_input_value(gen, regs, 1);
pop1 = 1;
}
}
else
{
pop_input_value(gen, regs, 1);
pop_input_value(gen, regs, 2);
pop1 = pop2 = 1;
}
}
if(IS_STACK_REG(regs->descs[0].reg))
{
temp = *regs->descs[0].value;
if(!regs->x87_arith && !regs->copy)
{
++(gen->reg_stack_top);
}
bind_value(gen, &temp, regs->descs[0].reg, -1, 0);
}
reg1 = ((regs->descs[1].value && regs->descs[1].value->in_register)
? regs->descs[1].value->reg : -1);
reg2 = ((regs->descs[2].value && regs->descs[2].value->in_register)
? regs->descs[2].value->reg : -1);
if(reg1 > reg2)
{
commit_input_value(gen, regs, 1, pop1);
commit_input_value(gen, regs, 2, pop2);
}
else
{
commit_input_value(gen, regs, 2, pop2);
commit_input_value(gen, regs, 1, pop1);
}
if(IS_STACK_REG(regs->descs[0].reg))
{
reg1 = temp.reg;
free_value(gen, &temp, reg1, -1, 1);
regs->descs[0].reg = reg1;
regs->descs[0].other_reg = -1;
}
commit_output_value(gen, regs, 0);
}
#endif
else
{
commit_input_value(gen, regs, 2, 0);
commit_input_value(gen, regs, 1, 0);
commit_output_value(gen, regs, 1);
}
/* Load clobbered global registers. */
for(reg = JIT_NUM_REGS - 1; reg >= 0; reg--)
{
if(jit_reg_is_used(regs->clobber, reg) && jit_reg_is_used(gen->permanent, reg))
{
#ifdef IS_REGISTER_OCCUPIED
if(!regs->ternary
&& regs->descs[0].value
&& regs->descs[0].value->has_global_register
&& regs->descs[0].value->global_reg == reg)
{
continue;
}
#endif
_jit_gen_load_global(gen, reg, 0);
}
}
#ifdef JIT_REG_DEBUG
dump_regs(gen, "leave _jit_regs_commit");
#endif
}
void
_jit_regs_begin(jit_gencode_t gen, _jit_regs_t *regs, int space)
{
( run in 0.565 second using v1.01-cache-2.11-cpan-2398b32b56e )