return rshift_node;
}
-/**
- * returns true if it is assured, that the upper bits of a node are "clean"
- * which means for a 16 or 8 bit value, that the upper bits in the register
- * are 0 for unsigned and a copy of the last significant bit for signed
- * numbers.
- */
-static bool upper_bits_clean(ir_node *node, ir_mode *mode)
-{
- switch ((ir_opcode)get_irn_opcode(node)) {
- case iro_And:
- if (!mode_is_signed(mode)) {
- return upper_bits_clean(get_And_left(node), mode)
- || upper_bits_clean(get_And_right(node), mode);
- }
- /* FALLTHROUGH */
- case iro_Or:
- case iro_Eor:
- return upper_bits_clean(get_binop_left(node), mode)
- && upper_bits_clean(get_binop_right(node), mode);
-
- case iro_Shr:
- if (mode_is_signed(mode)) {
- return false; /* TODO */
- } else {
- ir_node *right = get_Shr_right(node);
- if (is_Const(right)) {
- ir_tarval *tv = get_Const_tarval(right);
- long val = get_tarval_long(tv);
- if (val >= 32 - (long)get_mode_size_bits(mode))
- return true;
- }
- return upper_bits_clean(get_Shr_left(node), mode);
- }
-
- case iro_Shrs:
- return upper_bits_clean(get_Shrs_left(node), mode);
-
- case iro_Const: {
- ir_tarval *tv = get_Const_tarval(node);
- long val = get_tarval_long(tv);
- if (mode_is_signed(mode)) {
- long shifted = val >> (get_mode_size_bits(mode)-1);
- return shifted == 0 || shifted == -1;
- } else {
- unsigned long shifted = (unsigned long)val;
- shifted >>= get_mode_size_bits(mode)-1;
- shifted >>= 1;
- return shifted == 0;
- }
- }
-
- case iro_Conv: {
- ir_mode *dest_mode = get_irn_mode(node);
- ir_node *op = get_Conv_op(node);
- ir_mode *src_mode = get_irn_mode(op);
- unsigned src_bits = get_mode_size_bits(src_mode);
- unsigned dest_bits = get_mode_size_bits(dest_mode);
- /* downconvs are a nop */
- if (src_bits <= dest_bits)
- return upper_bits_clean(op, mode);
- if (dest_bits <= get_mode_size_bits(mode)
- && mode_is_signed(dest_mode) == mode_is_signed(mode))
- return true;
- return false;
- }
-
- case iro_Proj: {
- ir_node *pred = get_Proj_pred(node);
- switch (get_irn_opcode(pred)) {
- case iro_Load: {
- ir_mode *load_mode = get_Load_mode(pred);
- unsigned load_bits = get_mode_size_bits(load_mode);
- unsigned bits = get_mode_size_bits(mode);
- if (load_bits > bits)
- return false;
- if (mode_is_signed(mode) != mode_is_signed(load_mode))
- return false;
- return true;
- }
- default:
- break;
- }
- }
- default:
- break;
- }
- return false;
-}
-
/**
* Extend a value to 32 bit signed/unsigned depending on its mode.
*
static bool needs_extension(ir_node *op)
{
ir_mode *mode = get_irn_mode(op);
- if (get_mode_size_bits(mode) >= get_mode_size_bits(mode_gp))
+ unsigned gp_bits = get_mode_size_bits(mode_gp);
+ if (get_mode_size_bits(mode) >= gp_bits)
return false;
- return !upper_bits_clean(op, mode);
+ return !be_upper_bits_clean(op, mode);
}
/**
}
-static ir_node *get_g0(ir_graph *irg)
+static ir_node *get_reg(ir_graph *const irg, reg_info_t *const reg)
{
- if (start_g0.irn == NULL) {
+ if (!reg->irn) {
/* this is already the transformed start node */
ir_node *const start = get_irg_start(irg);
assert(is_sparc_Start(start));
- start_g0.irn = new_r_Proj(start, mode_gp, start_g0.offset);
+ arch_register_class_t const *const cls = arch_get_irn_register_req_out(start, reg->offset)->cls;
+ reg->irn = new_r_Proj(start, cls ? cls->mode : mode_M, reg->offset);
}
- return start_g0.irn;
+ return reg->irn;
+}
+
+static ir_node *get_g0(ir_graph *irg)
+{
+ return get_reg(irg, &start_g0);
}
static ir_node *get_g7(ir_graph *irg)
{
- if (start_g7.irn == NULL) {
- ir_node *start = get_irg_start(irg);
- assert(is_sparc_Start(start));
- start_g7.irn = new_r_Proj(start, mode_gp, start_g7.offset);
- }
- return start_g7.irn;
+ return get_reg(irg, &start_g7);
}
static ir_node *make_tls_offset(dbg_info *dbgi, ir_node *block,
return create_itof(dbgi, block, new_op, dst_mode);
}
} else { /* complete in gp registers */
- int min_bits;
- ir_mode *min_mode;
-
- if (src_bits == dst_bits || dst_mode == mode_b) {
+ if (src_bits >= dst_bits || dst_mode == mode_b) {
/* kill unnecessary conv */
return be_transform_node(op);
}
- if (src_bits < dst_bits) {
- min_bits = src_bits;
- min_mode = src_mode;
- } else {
- min_bits = dst_bits;
- min_mode = dst_mode;
- }
-
- if (upper_bits_clean(op, min_mode)) {
+ if (be_upper_bits_clean(op, src_mode)) {
return be_transform_node(op);
}
new_op = be_transform_node(op);
- if (mode_is_signed(min_mode)) {
- return gen_sign_extension(dbgi, block, new_op, min_bits);
+ if (mode_is_signed(src_mode)) {
+ return gen_sign_extension(dbgi, block, new_op, src_bits);
} else {
- return gen_zero_extension(dbgi, block, new_op, min_bits);
+ return gen_zero_extension(dbgi, block, new_op, src_bits);
}
}
}
panic("Unexpected Unknown mode");
}
+static void make_start_out(reg_info_t *const info, struct obstack *const obst, ir_node *const start, size_t const offset, arch_register_t const *const reg, arch_register_req_type_t const flags)
+{
+ info->offset = offset;
+ info->irn = NULL;
+ arch_register_req_t const *const req = be_create_reg_req(obst, reg, arch_register_req_type_ignore | flags);
+ arch_set_irn_register_req_out(start, offset, req);
+ arch_set_irn_register_out(start, offset, reg);
+}
+
/**
* transform the start node to the prolog code
*/
ir_node *new_block = be_transform_node(block);
dbg_info *dbgi = get_irn_dbg_info(node);
struct obstack *obst = be_get_be_obst(irg);
- const arch_register_req_t *req;
size_t n_outs;
ir_node *start;
size_t i;
- size_t o;
/* start building list of start constraints */
- assert(obstack_object_size(obst) == 0);
/* calculate number of outputs */
n_outs = 4; /* memory, g0, g7, sp */
start = new_bd_sparc_Start(dbgi, new_block, n_outs);
- o = 0;
+ size_t o = 0;
/* first output is memory */
start_mem.offset = o;
+ start_mem.irn = NULL;
arch_set_irn_register_req_out(start, o, arch_no_register_req);
++o;
/* the zero register */
- start_g0.offset = o;
- req = be_create_reg_req(obst, &sparc_registers[REG_G0],
- arch_register_req_type_ignore);
- arch_set_irn_register_req_out(start, o, req);
- arch_set_irn_register_out(start, o, &sparc_registers[REG_G0]);
- ++o;
+ make_start_out(&start_g0, obst, start, o++, &sparc_registers[REG_G0], arch_register_req_type_none);
/* g7 is used for TLS data */
- start_g7.offset = o;
- req = be_create_reg_req(obst, &sparc_registers[REG_G7],
- arch_register_req_type_ignore);
- arch_set_irn_register_req_out(start, o, req);
- arch_set_irn_register_out(start, o, &sparc_registers[REG_G7]);
- ++o;
+ make_start_out(&start_g7, obst, start, o++, &sparc_registers[REG_G7], arch_register_req_type_none);
/* we need an output for the stackpointer */
- start_sp.offset = o;
- req = be_create_reg_req(obst, sp_reg,
- arch_register_req_type_produces_sp | arch_register_req_type_ignore);
- arch_set_irn_register_req_out(start, o, req);
- arch_set_irn_register_out(start, o, sp_reg);
- ++o;
+ make_start_out(&start_sp, obst, start, o++, sp_reg, arch_register_req_type_produces_sp);
if (!current_cconv->omit_fp) {
- start_fp.offset = o;
- req = be_create_reg_req(obst, fp_reg, arch_register_req_type_ignore);
- arch_set_irn_register_req_out(start, o, req);
- arch_set_irn_register_out(start, o, fp_reg);
- ++o;
+ make_start_out(&start_fp, obst, start, o++, fp_reg, arch_register_req_type_none);
}
/* function parameters in registers */
static ir_node *get_initial_sp(ir_graph *irg)
{
- if (start_sp.irn == NULL) {
- ir_node *start = get_irg_start(irg);
- start_sp.irn = new_r_Proj(start, mode_gp, start_sp.offset);
- }
- return start_sp.irn;
+ return get_reg(irg, &start_sp);
}
static ir_node *get_initial_fp(ir_graph *irg)
{
- if (start_fp.irn == NULL) {
- ir_node *start = get_irg_start(irg);
- start_fp.irn = new_r_Proj(start, mode_gp, start_fp.offset);
- }
- return start_fp.irn;
+ return get_reg(irg, &start_fp);
}
static ir_node *get_initial_mem(ir_graph *irg)
{
- if (start_mem.irn == NULL) {
- ir_node *start = get_irg_start(irg);
- start_mem.irn = new_r_Proj(start, mode_M, start_mem.offset);
- }
- return start_mem.irn;
+ return get_reg(irg, &start_mem);
}
static ir_node *get_stack_pointer_for(ir_node *node)
}
assert(result_info->req1 == NULL);
}
+ const unsigned *allocatable_regs = be_birg_from_irg(irg)->allocatable_regs;
for (i = 0; i < N_SPARC_REGISTERS; ++i) {
const arch_register_t *reg;
if (!rbitset_is_set(cconv->caller_saves, i))
continue;
reg = &sparc_registers[i];
- arch_set_irn_register_req_out(res, o++, reg->single_req);
+ arch_set_irn_register_req_out(res, o, reg->single_req);
+ if (!rbitset_is_set(allocatable_regs, reg->global_index))
+ arch_set_irn_register_out(res, o, reg);
+ ++o;
}
assert(o == out_arity);
}
}
-/**
- * Transform some Phi nodes
- */
static ir_node *gen_Phi(ir_node *node)
{
+ ir_mode *mode = get_irn_mode(node);
const arch_register_req_t *req;
- ir_node *block = be_transform_node(get_nodes_block(node));
- ir_graph *irg = current_ir_graph;
- dbg_info *dbgi = get_irn_dbg_info(node);
- ir_mode *mode = get_irn_mode(node);
- ir_node *phi;
-
if (mode_needs_gp_reg(mode)) {
/* we shouldn't have any 64bit stuff around anymore */
assert(get_mode_size_bits(mode) <= 32);
req = arch_no_register_req;
}
- /* phi nodes allow loops, so we use the old arguments for now
- * and fix this later */
- phi = new_ir_node(dbgi, irg, block, op_Phi, mode, get_irn_arity(node), get_irn_in(node) + 1);
- copy_node_attr(irg, node, phi);
- be_duplicate_deps(node, phi);
- arch_set_irn_register_req_out(phi, 0, req);
- be_enqueue_preds(node);
- return phi;
+ return be_transform_phi(node, req);
}
/**
panic("Unsupported Proj from Store");
}
-/**
- * Transform the Projs from a Cmp.
- */
-static ir_node *gen_Proj_Cmp(ir_node *node)
-{
- (void) node;
- panic("not implemented");
-}
-
/**
* transform Projs from a Div
*/
return gen_Proj_Load(node);
case iro_Call:
return gen_Proj_Call(node);
- case iro_Cmp:
- return gen_Proj_Cmp(node);
case iro_Switch:
case iro_Cond:
return be_duplicate_node(node);
mode_flags = sparc_reg_classes[CLASS_sparc_flags_class].mode;
assert(sparc_reg_classes[CLASS_sparc_fpflags_class].mode == mode_flags);
- start_mem.irn = NULL;
- start_g0.irn = NULL;
- start_g7.irn = NULL;
- start_sp.irn = NULL;
- start_fp.irn = NULL;
- frame_base = NULL;
+ frame_base = NULL;
stackorder = be_collect_stacknodes(irg);
current_cconv