From 5b17692e0069fc49e5e3cac99a74e52cdf24a6bd Mon Sep 17 00:00:00 2001 From: Matthias Braun Date: Thu, 29 Jul 2010 09:27:59 +0000 Subject: [PATCH] use new double wide register requirements; implement calling convention for sparc 64bit floats [r27846] --- ir/be/bearch.h | 2 +- ir/be/scripts/generate_new_opcodes.pl | 9 +- ir/be/sparc/bearch_sparc.c | 4 +- ir/be/sparc/sparc_cconv.c | 2 +- ir/be/sparc/sparc_emitter.c | 19 +++- ir/be/sparc/sparc_emitter.h | 1 + ir/be/sparc/sparc_nodes_attr.h | 5 +- ir/be/sparc/sparc_spec.pl | 60 +++++++++--- ir/be/sparc/sparc_transform.c | 132 +++++++++++++++++++------- 9 files changed, 180 insertions(+), 54 deletions(-) diff --git a/ir/be/bearch.h b/ir/be/bearch.h index 462ab0898..7fb173a9f 100644 --- a/ir/be/bearch.h +++ b/ir/be/bearch.h @@ -85,7 +85,7 @@ typedef enum arch_register_req_type_t { /** The register must be unequal from some other at the node. */ arch_register_req_type_must_be_different = 1U << 3, /** The registernumber should be aligned (in case of multiregister values)*/ - arch_register_req_type_must_be_aligned = 1U << 4, + arch_register_req_type_aligned = 1U << 4, /** ignore while allocating registers */ arch_register_req_type_ignore = 1U << 5, /** the output produces a new value for the stack pointer diff --git a/ir/be/scripts/generate_new_opcodes.pl b/ir/be/scripts/generate_new_opcodes.pl index 9dc39488f..2a16256ee 100755 --- a/ir/be/scripts/generate_new_opcodes.pl +++ b/ir/be/scripts/generate_new_opcodes.pl @@ -1263,6 +1263,7 @@ sub generate_requirements { my $idx = shift; my $is_in = shift; my $class = ""; + my $width = 1; my $result; my @req_type_mask; @@ -1272,6 +1273,10 @@ sub generate_requirements { push(@req_type_mask, "arch_register_req_type_ignore"); } elsif ($f eq "S") { push(@req_type_mask, "arch_register_req_type_produces_sp"); + } elsif ($f eq "a") { + push(@req_type_mask, "arch_register_req_type_aligned"); + } elsif ($f eq "2" or $f eq "4" or $f eq "8") { + $width = int($f); } } } @@ -1300,7 +1305,7 @@ EOF NULL, /* limit bitset */ 0, /* same pos */ 0, /* different pos */ - 1 /* width */ + $width /* width */ }; EOF @@ -1336,7 +1341,7 @@ EOF ${limit_bitset}, ${same_pos}, /* same pos */ ${different_pos}, /* different pos */ - 1 /* width */ + $width /* width */ }; EOF diff --git a/ir/be/sparc/bearch_sparc.c b/ir/be/sparc/bearch_sparc.c index 5e2e1a93c..9067b9fdd 100644 --- a/ir/be/sparc/bearch_sparc.c +++ b/ir/be/sparc/bearch_sparc.c @@ -263,11 +263,13 @@ static void sparc_collect_frame_entity_nodes(ir_node *node, void *data) attr = get_sparc_load_store_attr_const(node); entity = attr->entity; mode = attr->load_store_mode; - align = get_mode_size_bytes(mode); if (entity != NULL) return; if (!attr->is_frame_entity) return; + if (arch_irn_get_flags(node) & sparc_arch_irn_flag_needs_64bit_spillslot) + mode = mode_Lu; + align = get_mode_size_bytes(mode); be_node_needs_frame_entity(env, node, mode, align); } diff --git a/ir/be/sparc/sparc_cconv.c b/ir/be/sparc/sparc_cconv.c index 4f83049d9..92c7297db 100644 --- a/ir/be/sparc/sparc_cconv.c +++ b/ir/be/sparc/sparc_cconv.c @@ -71,7 +71,6 @@ calling_convention_t *sparc_decide_calling_convention(ir_type *function_type, ir_mode *mode = get_type_mode(param_type); int bits = get_mode_size_bits(mode); reg_or_stackslot_t *param = ¶ms[i]; - param->type = param_type; if (regnum < n_param_regs) { const arch_register_t *reg = param_regs[regnum++]; @@ -79,6 +78,7 @@ calling_convention_t *sparc_decide_calling_convention(ir_type *function_type, reg = map_i_to_o_reg(reg); param->reg0 = reg; } else { + param->type = param_type; param->offset = stack_offset; /* increase offset 4 bytes so everything is aligned */ stack_offset += bits > 32 ? bits/8 : 4; diff --git a/ir/be/sparc/sparc_emitter.c b/ir/be/sparc/sparc_emitter.c index 4b751aef3..96e55f1d3 100644 --- a/ir/be/sparc/sparc_emitter.c +++ b/ir/be/sparc/sparc_emitter.c @@ -170,6 +170,21 @@ void sparc_emit_offset(const ir_node *node) } } +void sparc_emit_float_load_store_mode(const ir_node *node) +{ + const sparc_load_store_attr_t *attr = get_sparc_load_store_attr_const(node); + ir_mode *mode = attr->load_store_mode; + int bits = get_mode_size_bits(mode); + + assert(mode_is_float(mode)); + + switch (bits) { + case 32: return; + case 64: be_emit_char('d'); return; + case 128: be_emit_char('q'); return; + } + panic("invalid flaot load/store mode %+F", mode); +} /** * Emit load mode char @@ -186,7 +201,7 @@ void sparc_emit_load_mode(const ir_node *node) } else if (bits == 8) { be_emit_string(is_signed ? "sb" : "ub"); } else if (bits == 64) { - be_emit_string("d"); + be_emit_char('d'); } else { assert(bits == 32); } @@ -206,7 +221,7 @@ void sparc_emit_store_mode(const ir_node *node) } else if (bits == 8) { be_emit_string("b"); } else if (bits == 64) { - be_emit_string("d"); + be_emit_char('d'); } else { assert(bits == 32); } diff --git a/ir/be/sparc/sparc_emitter.h b/ir/be/sparc/sparc_emitter.h index ece24c268..ea3f4c116 100644 --- a/ir/be/sparc/sparc_emitter.h +++ b/ir/be/sparc/sparc_emitter.h @@ -42,6 +42,7 @@ void sparc_emit_dest_register(const ir_node *node, int pos); void sparc_emit_offset(const ir_node *node); void sparc_emit_load_mode(const ir_node *node); void sparc_emit_store_mode(const ir_node *node); +void sparc_emit_float_load_store_mode(const ir_node *node); void sparc_emit_mode_sign_prefix(const ir_node *node); void sparc_emit_fp_mode_suffix(const ir_node *node); void sparc_emit_fp_conv_source(const ir_node *node); diff --git a/ir/be/sparc/sparc_nodes_attr.h b/ir/be/sparc/sparc_nodes_attr.h index 8cb690f06..d8342da16 100644 --- a/ir/be/sparc/sparc_nodes_attr.h +++ b/ir/be/sparc/sparc_nodes_attr.h @@ -43,8 +43,9 @@ struct sparc_attr_t }; enum sparc_arch_irn_flags_t { - sparc_arch_irn_flag_modifies_flags = arch_irn_flags_backend << 0, - sparc_arch_irn_flag_modifies_fp_flags = arch_irn_flags_backend << 1, + sparc_arch_irn_flag_modifies_flags = arch_irn_flags_backend << 0, + sparc_arch_irn_flag_modifies_fp_flags = arch_irn_flags_backend << 1, + sparc_arch_irn_flag_needs_64bit_spillslot = arch_irn_flags_backend << 2, }; /** diff --git a/ir/be/sparc/sparc_spec.pl b/ir/be/sparc/sparc_spec.pl index af685815a..cde687736 100644 --- a/ir/be/sparc/sparc_spec.pl +++ b/ir/be/sparc/sparc_spec.pl @@ -6,7 +6,9 @@ $arch = "sparc"; $mode_gp = "mode_Iu"; $mode_flags = "mode_Bu"; $mode_fpflags = "mode_Bu"; -$mode_fp = "mode_D"; +$mode_fp = "mode_F"; +$mode_fp2 = "mode_D"; +$mode_fp4 = "mode_E"; # not correct, we need to register a new mode $normal = 0; # no special type $caller_save = 1; # caller save (register must be saved by the caller of a function) @@ -130,6 +132,7 @@ $state = 32; # register represents a state IM => "${arch}_emit_immediate(node);", LM => "${arch}_emit_load_mode(node);", SM => "${arch}_emit_store_mode(node);", + FLSM => "${arch}_emit_float_load_store_mode(node);", FPM => "${arch}_emit_fp_mode_suffix(node);", FCONVS => "${arch}_emit_fp_conv_source(node);", FCONVD => "${arch}_emit_fp_conv_destination(node);", @@ -211,6 +214,24 @@ my %binop_operand_constructors = ( }, ); +my %float_binop_constructors = ( + s => { + reg_req => { in => [ "fp", "fp" ], out => [ "fp" ] }, + ins => [ "left", "right" ], + mode => $mode_fp, + }, + d => { + reg_req => { in => [ "fp:a|2", "fp:a|2" ], out => [ "fp:a|2" ] }, + ins => [ "left", "right" ], + mode => $mode_fp2, + }, + q => { + reg_req => { in => [ "fp:a|4", "fp:a|4" ], out => [ "fp:a|4" ] }, + ins => [ "left", "right" ], + mode => $mode_fp4, + } +); + %nodes = ( Add => { @@ -233,9 +254,16 @@ Sub => { Ld => { op_flags => [ "labeled", "fragile" ], state => "exc_pinned", - ins => [ "ptr", "mem" ], + constructors => { + "" => { + reg_req => { in => [ "gp", "none" ], out => [ "gp", "none" ] }, + }, + d => { + reg_req => { in => [ "gp", "none" ], out => [ "gp:a|2", "none" ] }, + }, + }, outs => [ "res", "M" ], - reg_req => { in => [ "gp", "none" ], out => [ "gp", "none" ] }, + ins => [ "ptr", "mem" ], attr_type => "sparc_load_store_attr_t", attr => "ir_mode *ls_mode, ir_entity *entity, int entity_sign, long offset, bool is_frame_entity", emit => '. ld%LM [%S1%O], %D1' @@ -264,11 +292,18 @@ LoImm => { St => { op_flags => [ "labeled", "fragile" ], - mode => "mode_M", + mode => "mode_M", state => "exc_pinned", + constructors => { + "" => { + reg_req => { in => [ "gp", "gp", "none" ], out => [ "none" ] }, + }, + d => { + reg_req => { in => [ "gp", "gp:a|2", "none" ], out => [ "none" ] }, + }, + }, ins => [ "ptr", "val", "mem" ], outs => [ "M" ], - reg_req => { in => [ "gp", "gp", "none" ], out => [ "none" ] }, attr_type => "sparc_load_store_attr_t", attr => "ir_mode *ls_mode, ir_entity *entity, int entity_sign, long offset, bool is_frame_entity", emit => '. st%SM %S2, [%S1%O]' @@ -522,7 +557,7 @@ fadd => { emit => '. fadd%FPM %S1, %S2, %D1', attr_type => "sparc_fp_attr_t", attr => "ir_mode *fp_mode", - mode => $mode_fp, + constructors => \%float_binop_constructors, }, fsub => { @@ -531,7 +566,7 @@ fsub => { emit => '. fsub%FPM %S1, %S2, %D1', attr_type => "sparc_fp_attr_t", attr => "ir_mode *fp_mode", - mode => $mode_fp, + constructors => \%float_binop_constructors, }, fmul => { @@ -541,7 +576,7 @@ fmul => { emit =>'. fmul%FPM %S1, %S2, %D1', attr_type => "sparc_fp_attr_t", attr => "ir_mode *fp_mode", - mode => $mode_fp, + constructors => \%float_binop_constructors, }, fdiv => { @@ -551,6 +586,7 @@ fdiv => { attr_type => "sparc_fp_attr_t", attr => "ir_mode *fp_mode", outs => [ "res", "M" ], + constructors => \%float_binop_constructors, }, fneg => { @@ -568,13 +604,13 @@ fneg => { emit => '. fabs%FPM %S1, %D1', attr_type => "sparc_fp_attr_t", attr => "ir_mode *fp_mode", - mode => $mode_fp, + constructors => \%float_binop_constructors, }, fftof => { irn_flags => [ "rematerializable" ], reg_req => { in => [ "fp" ], out => [ "fp" ] }, - emit => '. f%FCONVS.to%FCONVD %S1, %D1', + emit => '. f%FCONVS%.to%FCONVD %S1, %D1', attr_type => "sparc_fp_conv_attr_t", attr => "ir_mode *src_mode, ir_mode *dest_mode", mode => $mode_fp, @@ -606,7 +642,7 @@ Ldf => { reg_req => { in => [ "gp", "none" ], out => [ "fp", "none" ] }, attr_type => "sparc_load_store_attr_t", attr => "ir_mode *ls_mode, ir_entity *entity, int entity_sign, long offset, bool is_frame_entity", - emit => '. ld [%S1%O], %D1' + emit => '. ld%FLSM [%S1%O], %D1' }, Stf => { @@ -617,7 +653,7 @@ Stf => { reg_req => { in => [ "gp", "fp", "none" ], out => [ "none" ] }, attr_type => "sparc_load_store_attr_t", attr => "ir_mode *ls_mode, ir_entity *entity, int entity_sign, long offset, bool is_frame_entity", - emit => '. st %S2, [%S1%O]', + emit => '. st%FLSM %S2, [%S1%O]', mode => 'mode_M', }, diff --git a/ir/be/sparc/sparc_transform.c b/ir/be/sparc/sparc_transform.c index dad12fc48..cb268473a 100644 --- a/ir/be/sparc/sparc_transform.c +++ b/ir/be/sparc/sparc_transform.c @@ -62,6 +62,8 @@ static const arch_register_t *fp_reg = &sparc_gp_regs[REG_FRAME_POINTER]; static calling_convention_t *cconv = NULL; static ir_mode *mode_gp; static ir_mode *mode_fp; +static ir_mode *mode_fp2; +//static ir_mode *mode_fp4; static pmap *node_to_stack; static ir_node *gen_SymConst(ir_node *node); @@ -208,8 +210,6 @@ static bool is_imm_encodeable(const ir_node *node) { long val; - //assert(mode_is_float_vector(get_irn_mode(node))); - if (!is_Const(node)) return false; @@ -254,7 +254,9 @@ static ir_node *gen_helper_binop(ir_node *node, match_flags_t flags, * helper function for FP binop operations */ static ir_node *gen_helper_binfpop(ir_node *node, ir_mode *mode, - new_binop_fp_func new_func) + new_binop_fp_func new_func_single, + new_binop_fp_func new_func_double, + new_binop_fp_func new_func_quad) { ir_node *block = be_transform_node(get_nodes_block(node)); ir_node *op1 = get_binop_left(node); @@ -262,8 +264,19 @@ static ir_node *gen_helper_binfpop(ir_node *node, ir_mode *mode, ir_node *op2 = get_binop_right(node); ir_node *new_op2 = be_transform_node(op2); dbg_info *dbgi = get_irn_dbg_info(node); - - return new_func(dbgi, block, new_op1, new_op2, mode); + unsigned bits = get_mode_size_bits(mode); + + switch (bits) { + case 32: + return new_func_single(dbgi, block, new_op1, new_op2, mode); + case 64: + return new_func_double(dbgi, block, new_op1, new_op2, mode); + case 128: + return new_func_quad(dbgi, block, new_op1, new_op2, mode); + default: + break; + } + panic("unsupported mode %+F for float op", mode); } /** @@ -277,7 +290,8 @@ static ir_node *gen_Add(ir_node *node) ir_mode *mode = get_irn_mode(node); if (mode_is_float(mode)) { - return gen_helper_binfpop(node, mode, new_bd_sparc_fadd); + return gen_helper_binfpop(node, mode, new_bd_sparc_fadd_s, + new_bd_sparc_fadd_d, new_bd_sparc_fadd_q); } return gen_helper_binop(node, MATCH_COMMUTATIVE, new_bd_sparc_Add_reg, new_bd_sparc_Add_imm); @@ -294,7 +308,8 @@ static ir_node *gen_Sub(ir_node *node) ir_mode *mode = get_irn_mode(node); if (mode_is_float(mode)) { - return gen_helper_binfpop(node, mode, new_bd_sparc_fsub); + return gen_helper_binfpop(node, mode, new_bd_sparc_fsub_s, + new_bd_sparc_fsub_d, new_bd_sparc_fsub_q); } return gen_helper_binop(node, MATCH_NONE, new_bd_sparc_Sub_reg, new_bd_sparc_Sub_imm); @@ -366,7 +381,8 @@ static ir_node *gen_Mul(ir_node *node) { ir_mode *mode = get_irn_mode(node); if (mode_is_float(mode)) { - return gen_helper_binfpop(node, mode, new_bd_sparc_fmul); + return gen_helper_binfpop(node, mode, new_bd_sparc_fmul_s, + new_bd_sparc_fmul_d, new_bd_sparc_fmul_q); } assert(mode_is_data(mode)); @@ -422,7 +438,8 @@ static ir_node *gen_Quot(ir_node *node) { ir_mode *mode = get_Quot_resmode(node); assert(mode_is_float(mode)); - return gen_helper_binfpop(node, mode, new_bd_sparc_fdiv); + return gen_helper_binfpop(node, mode, new_bd_sparc_fdiv_s, + new_bd_sparc_fdiv_d, new_bd_sparc_fdiv_q); } /** @@ -442,8 +459,10 @@ static ir_node *gen_Abs(ir_node *node) { ir_node *mov, *sra, *xor, *sub, *new_op; - if (mode_is_float(mode)) - panic("FP not supported yet"); + if (mode_is_float(mode)) { + return gen_helper_binfpop(node, mode, new_bd_sparc_fabs_s, + new_bd_sparc_fdiv_d, new_bd_sparc_fdiv_q); + } new_op = be_transform_node(op); @@ -1071,37 +1090,66 @@ static ir_node *gen_Return(ir_node *node) } static ir_node *bitcast_int_to_float(dbg_info *dbgi, ir_node *block, - ir_node *node) + ir_node *value0, ir_node *value1) { ir_graph *irg = current_ir_graph; - ir_node *stack = get_irg_frame(irg); + ir_node *sp = get_irg_frame(irg); ir_node *nomem = new_NoMem(); - ir_node *st = new_bd_sparc_St(dbgi, block, stack, node, nomem, mode_gp, + ir_node *st = new_bd_sparc_St(dbgi, block, sp, value0, nomem, mode_gp, NULL, 0, 0, true); + ir_mode *mode; ir_node *ldf; + ir_node *mem; set_irn_pinned(st, op_pin_state_floats); - ldf = new_bd_sparc_Ldf(dbgi, block, stack, st, mode_fp, NULL, 0, 0, true); + if (value1 != NULL) { + ir_node *st1 = new_bd_sparc_St(dbgi, block, sp, value1, nomem, mode_gp, + NULL, 0, 4, true); + ir_node *in[2] = { st, st1 }; + ir_node *sync = new_r_Sync(block, 2, in); + set_irn_pinned(st1, op_pin_state_floats); + mem = sync; + mode = mode_fp2; + } else { + mem = st; + mode = mode_fp; + } + + ldf = new_bd_sparc_Ldf(dbgi, block, sp, mem, mode, NULL, 0, 0, true); set_irn_pinned(ldf, op_pin_state_floats); - return new_Proj(ldf, mode_fp, pn_sparc_Ldf_res); + return new_Proj(ldf, mode, pn_sparc_Ldf_res); } -static ir_node *bitcast_float_to_int(dbg_info *dbgi, ir_node *block, - ir_node *node) +static void bitcast_float_to_int(dbg_info *dbgi, ir_node *block, + ir_node *node, ir_mode *float_mode, + ir_node **result) { ir_graph *irg = current_ir_graph; ir_node *stack = get_irg_frame(irg); ir_node *nomem = new_NoMem(); - ir_node *stf = new_bd_sparc_Stf(dbgi, block, stack, node, nomem, mode_fp, - NULL, 0, 0, true); + ir_node *stf = new_bd_sparc_Stf(dbgi, block, stack, node, nomem, + float_mode, NULL, 0, 0, true); + int bits = get_mode_size_bits(float_mode); ir_node *ld; set_irn_pinned(stf, op_pin_state_floats); ld = new_bd_sparc_Ld(dbgi, block, stack, stf, mode_gp, NULL, 0, 0, true); set_irn_pinned(ld, op_pin_state_floats); + result[0] = new_Proj(ld, mode_gp, pn_sparc_Ld_res); - return new_Proj(ld, mode_fp, pn_sparc_Ld_res); + if (bits == 64) { + ir_node *ld2 = new_bd_sparc_Ld(dbgi, block, stack, stf, mode_gp, + NULL, 0, 4, true); + set_irn_pinned(ld, op_pin_state_floats); + result[1] = new_Proj(ld2, mode_gp, pn_sparc_Ld_res); + + arch_irn_add_flags(ld, sparc_arch_irn_flag_needs_64bit_spillslot); + arch_irn_add_flags(ld2, sparc_arch_irn_flag_needs_64bit_spillslot); + } else { + assert(bits == 32); + result[1] = NULL; + } } static ir_node *gen_Call(ir_node *node) @@ -1161,37 +1209,40 @@ static ir_node *gen_Call(ir_node *node) for (p = 0; p < n_params; ++p) { ir_node *value = get_Call_param(node, p); ir_node *new_value = be_transform_node(value); - ir_node *new_value1 = NULL; const reg_or_stackslot_t *param = &cconv->parameters[p]; ir_type *param_type = get_method_param_type(type, p); ir_mode *mode = get_type_mode(param_type); + ir_node *new_values[2]; ir_node *str; if (mode_is_float(mode) && param->reg0 != NULL) { unsigned size_bits = get_mode_size_bits(mode); - assert(size_bits == 32); - new_value = bitcast_float_to_int(dbgi, new_block, new_value); + assert(size_bits <= 64); + bitcast_float_to_int(dbgi, new_block, new_value, mode, new_values); + } else { + new_values[0] = new_value; + new_values[1] = NULL; } /* put value into registers */ if (param->reg0 != NULL) { - in[in_arity] = new_value; + in[in_arity] = new_values[0]; in_req[in_arity] = param->reg0->single_req; ++in_arity; - if (new_value1 == NULL) + if (new_values[1] == NULL) continue; } if (param->reg1 != NULL) { - assert(new_value1 != NULL); - in[in_arity] = new_value1; + assert(new_values[1] != NULL); + in[in_arity] = new_values[1]; in_req[in_arity] = param->reg1->single_req; ++in_arity; continue; } /* we need a store if we're here */ - if (new_value1 != NULL) { - new_value = new_value1; + if (new_values[1] != NULL) { + new_value = new_values[1]; mode = mode_gp; } @@ -1471,8 +1522,21 @@ static ir_node *gen_Proj_Proj_Start(ir_node *node) ir_node *value = be_prolog_get_reg_value(abihelper, reg); if (mode_is_float(mode)) { + ir_node *value1 = NULL; + + if (param->reg1 != NULL) { + value1 = be_prolog_get_reg_value(abihelper, param->reg1); + } else if (param->entity != NULL) { + ir_node *fp = be_prolog_get_reg_value(abihelper, fp_reg); + ir_node *mem = be_prolog_get_memory(abihelper); + ir_node *ld = new_bd_sparc_Ld(NULL, new_block, fp, mem, + mode_gp, param->entity, + 0, 0, true); + value1 = new_Proj(ld, mode_gp, pn_sparc_Ld_res); + } + /* convert integer value to float */ - value = bitcast_int_to_float(NULL, new_block, value); + value = bitcast_int_to_float(NULL, new_block, value, value1); } return value; } else { @@ -1690,8 +1754,10 @@ void sparc_transform_graph(sparc_code_gen_t *cg) node_to_stack = pmap_create(); - mode_gp = mode_Iu; - mode_fp = mode_F; + mode_gp = mode_Iu; + mode_fp = mode_F; + mode_fp2 = mode_D; + //mode_fp4 = ? abihelper = be_abihelper_prepare(irg); be_collect_stacknodes(abihelper); -- 2.20.1