From: Matthias Braun Date: Mon, 9 Aug 2010 14:53:12 +0000 (+0000) Subject: sparc: redo and improve sparc immediate handling (low-part after sethi is now omitted... X-Git-Url: http://nsz.repo.hu/git/?a=commitdiff_plain;h=21762fc6e19ed2219563af9f13364a808e92641e;p=libfirm sparc: redo and improve sparc immediate handling (low-part after sethi is now omitted if it is 0) [r27918] --- diff --git a/ir/be/sparc/sparc_emitter.c b/ir/be/sparc/sparc_emitter.c index a5b25e932..bffd3e3c7 100644 --- a/ir/be/sparc/sparc_emitter.c +++ b/ir/be/sparc/sparc_emitter.c @@ -111,9 +111,15 @@ static const arch_register_t *get_out_reg(const ir_node *node, int pos) void sparc_emit_immediate(const ir_node *node) { - int const val = get_sparc_attr_const(node)->immediate_value; - assert(-4096 <= val && val < 4096); - be_emit_irprintf("%d", val); + int32_t value = get_sparc_attr_const(node)->immediate_value; + assert(-4096 <= value && value < 4096); + be_emit_irprintf("%d", value); +} + +void sparc_emit_high_immediate(const ir_node *node) +{ + uint32_t value = (uint32_t) get_sparc_attr_const(node)->immediate_value; + be_emit_irprintf("%%hi(0x%X)", value); } void sparc_emit_source_register(const ir_node *node, int pos) @@ -329,31 +335,6 @@ static void emit_sparc_Save(const ir_node *irn) be_emit_finish_line_gas(irn); } -/** - * emits code to load hi 22 bit of a constant - */ -static void emit_sparc_HiImm(const ir_node *irn) -{ - const sparc_attr_t *attr = get_sparc_attr_const(irn); - be_emit_cstring("\tsethi "); - be_emit_irprintf("%%hi(%d), ", attr->immediate_value); - sparc_emit_dest_register(irn, 0); - be_emit_finish_line_gas(irn); -} - -/** - * emits code to load lo 10bits of a constant - */ -static void emit_sparc_LoImm(const ir_node *irn) -{ - const sparc_attr_t *attr = get_sparc_attr_const(irn); - be_emit_cstring("\tor "); - sparc_emit_source_register(irn, 0); - be_emit_irprintf(", %%lo(%d), ", attr->immediate_value); - sparc_emit_dest_register(irn, 0); - be_emit_finish_line_gas(irn); -} - /** * emits code for mulh */ @@ -849,8 +830,6 @@ static void sparc_register_emitters(void) set_emitter(op_sparc_Call, emit_sparc_Call); set_emitter(op_sparc_fbfcc, emit_sparc_fbfcc); set_emitter(op_sparc_FrameAddr, emit_sparc_FrameAddr); - set_emitter(op_sparc_HiImm, emit_sparc_HiImm); - set_emitter(op_sparc_LoImm, emit_sparc_LoImm); set_emitter(op_sparc_Mulh, emit_sparc_Mulh); set_emitter(op_sparc_Save, emit_sparc_Save); set_emitter(op_sparc_SDiv, emit_sparc_SDiv); diff --git a/ir/be/sparc/sparc_emitter.h b/ir/be/sparc/sparc_emitter.h index ea3f4c116..4e12d8df8 100644 --- a/ir/be/sparc/sparc_emitter.h +++ b/ir/be/sparc/sparc_emitter.h @@ -35,6 +35,7 @@ #include "bearch_sparc_t.h" void sparc_emit_immediate(const ir_node *node); +void sparc_emit_high_immediate(const ir_node *node); void sparc_emit_mode(const ir_node *node); void sparc_emit_source_register(const ir_node *node, int pos); void sparc_emit_reg_or_imm(const ir_node *node, int pos); diff --git a/ir/be/sparc/sparc_new_nodes.c b/ir/be/sparc/sparc_new_nodes.c index 47ad2f939..772fa1bec 100644 --- a/ir/be/sparc/sparc_new_nodes.c +++ b/ir/be/sparc/sparc_new_nodes.c @@ -147,7 +147,7 @@ static void sparc_dump_node(FILE *F, ir_node *n, dump_reason_t reason) } } -static void sparc_set_attr_imm(ir_node *res, int immediate_value) +static void sparc_set_attr_imm(ir_node *res, int32_t immediate_value) { sparc_attr_t *attr = get_irn_generic_attr(res); attr->immediate_value = immediate_value; diff --git a/ir/be/sparc/sparc_nodes_attr.h b/ir/be/sparc/sparc_nodes_attr.h index d8342da16..ab028c843 100644 --- a/ir/be/sparc/sparc_nodes_attr.h +++ b/ir/be/sparc/sparc_nodes_attr.h @@ -26,6 +26,7 @@ #define FIRM_BE_SPARC_SPARC_NODES_ATTR_H #include "../bearch.h" +#include typedef struct sparc_attr_t sparc_attr_t; @@ -36,7 +37,7 @@ struct sparc_attr_t { except_attr exc; /**< the exception attribute. MUST be the first one. */ const arch_register_req_t **in_req; /**< register requirements for arguments */ - int immediate_value; /* immediate values */ + int32_t immediate_value; /* immediate values */ bool is_load_store; ir_entity *immediate_value_entity; /* hack for now */ diff --git a/ir/be/sparc/sparc_spec.pl b/ir/be/sparc/sparc_spec.pl index 61c76eb72..1a13450f1 100644 --- a/ir/be/sparc/sparc_spec.pl +++ b/ir/be/sparc/sparc_spec.pl @@ -130,6 +130,7 @@ $state = 32; # register represents a state D5 => "${arch}_emit_dest_register(node, 4);", D6 => "${arch}_emit_dest_register(node, 5);", IM => "${arch}_emit_immediate(node);", + HIM => "${arch}_emit_high_immediate(node);", LM => "${arch}_emit_load_mode(node);", SM => "${arch}_emit_store_mode(node);", FLSM => "${arch}_emit_float_load_store_mode(node);", @@ -179,7 +180,7 @@ $default_copy_attr = "sparc_copy_attr"; my %cmp_operand_constructors = ( imm => { - attr => "int immediate_value", + attr => "int32_t immediate_value", custominit => "sparc_set_attr_imm(res, immediate_value);", reg_req => { in => [ "gp" ], out => [ "flags" ] }, ins => [ "left" ], @@ -192,7 +193,7 @@ my %cmp_operand_constructors = ( my %unop_operand_constructors = ( imm => { - attr => "int immediate_value", + attr => "int32_t immediate_value", custominit => "sparc_set_attr_imm(res, immediate_value);", reg_req => { in => [], out => [ "gp" ] }, }, @@ -203,7 +204,7 @@ my %unop_operand_constructors = ( my %binop_operand_constructors = ( imm => { - attr => "int immediate_value", + attr => "int32_t immediate_value", custominit => "sparc_set_attr_imm(res, immediate_value);", reg_req => { in => [ "gp" ], out => [ "gp" ] }, ins => [ "left" ], @@ -286,25 +287,14 @@ Ld => { emit => '. ld%LM [%S1%O], %D1' }, -HiImm => { - irn_flags => [ "rematerializable" ], - state => "exc_pinned", - outs => [ "res" ], - mode => $mode_gp, - reg_req => { in => [], out => [ "gp" ] }, - attr => "int immediate_value", - custominit => "sparc_set_attr_imm(res, immediate_value);", -}, - -LoImm => { - irn_flags => [ "rematerializable" ], - state => "exc_pinned", - ins => [ "hireg" ], - outs => [ "res" ], - mode => $mode_gp, - reg_req => { in => [ "gp" ], out => [ "gp" ] }, - attr => "int immediate_value", +SetHi => { + irn_flags => [ "rematerializable" ], + outs => [ "res" ], + mode => $mode_gp, + reg_req => { in => [], out => [ "gp" ] }, + attr => "int32_t immediate_value", custominit => "sparc_set_attr_imm(res, immediate_value);", + emit => '. sethi %HIM, %D1' }, St => { @@ -326,14 +316,6 @@ St => { emit => '. st%SM %S2, [%S1%O]' }, -Mov => { - irn_flags => [ "rematerializable" ], - arity => "variable", - emit => '. mov %R1I, %D1', - mode => $mode_gp, - constructors => \%unop_operand_constructors, -}, - Save => { reg_req => { in => [ "sp", "none"], diff --git a/ir/be/sparc/sparc_transform.c b/ir/be/sparc/sparc_transform.c index 075f07bba..09230d973 100644 --- a/ir/be/sparc/sparc_transform.c +++ b/ir/be/sparc/sparc_transform.c @@ -33,6 +33,7 @@ #include "iredges.h" #include "ircons.h" #include "irprintf.h" +#include "iroptimize.h" #include "dbginfo.h" #include "iropt_t.h" #include "debug.h" @@ -151,50 +152,6 @@ static ir_node *gen_extension(dbg_info *dbgi, ir_node *block, ir_node *op, } } -/** - * Creates a possible DAG for a constant. - */ -static ir_node *create_const_graph_value(dbg_info *dbgi, ir_node *block, - long value) -{ - ir_node *result; - - /* we need to load hi & lo separately */ - if (value < -4096 || value > 4095) { - ir_node *hi = new_bd_sparc_HiImm(dbgi, block, (int) value); - result = new_bd_sparc_LoImm(dbgi, block, hi, value); - be_dep_on_frame(hi); - } else { - result = new_bd_sparc_Mov_imm(dbgi, block, (int) value); - be_dep_on_frame(result); - } - - return result; -} - -/** - * Create a DAG constructing a given Const. - * - * @param irn a Firm const - */ -static ir_node *create_const_graph(ir_node *irn, ir_node *block) -{ - tarval *tv = get_Const_tarval(irn); - ir_mode *mode = get_tarval_mode(tv); - dbg_info *dbgi = get_irn_dbg_info(irn); - long value; - - - if (mode_is_reference(mode)) { - /* SPARC V8 is 32bit, so we can safely convert a reference tarval into Iu */ - assert(get_mode_size_bits(mode) == get_mode_size_bits(mode_gp)); - tv = tarval_convert_to(tv, mode_gp); - } - - value = get_tarval_long(tv); - return create_const_graph_value(dbgi, block, value); -} - typedef enum { MATCH_NONE = 0, MATCH_COMMUTATIVE = 1 << 0, /**< commutative operation. */ @@ -202,7 +159,7 @@ typedef enum { typedef ir_node* (*new_binop_reg_func) (dbg_info *dbgi, ir_node *block, ir_node *op1, ir_node *op2); typedef ir_node* (*new_binop_fp_func) (dbg_info *dbgi, ir_node *block, ir_node *op1, ir_node *op2, ir_mode *mode); -typedef ir_node* (*new_binop_imm_func) (dbg_info *dbgi, ir_node *block, ir_node *op1, int simm13); +typedef ir_node* (*new_binop_imm_func) (dbg_info *dbgi, ir_node *block, ir_node *op1, int32_t immediate); typedef ir_node* (*new_unop_fp_func) (dbg_info *dbgi, ir_node *block, ir_node *op1, ir_mode *mode); /** @@ -211,14 +168,12 @@ typedef ir_node* (*new_unop_fp_func) (dbg_info *dbgi, ir_node *block, ir_node *o */ static bool is_imm_encodeable(const ir_node *node) { - long val; - + long value; if (!is_Const(node)) return false; - val = get_tarval_long(get_Const_tarval(node)); - - return -4096 <= val && val <= 4095; + value = get_tarval_long(get_Const_tarval(node)); + return -4096 <= value && value <= 4095; } /** @@ -710,19 +665,15 @@ static ir_entity *create_float_const_entity(tarval *tv) return entity; } -/** - * Transforms a Const node. - * - * @param node the ir Const node - * @return The transformed sparc node. - */ static ir_node *gen_Const(ir_node *node) { - ir_node *block = be_transform_node(get_nodes_block(node)); - ir_mode *mode = get_irn_mode(node); + ir_node *block = be_transform_node(get_nodes_block(node)); + ir_mode *mode = get_irn_mode(node); + dbg_info *dbgi = get_irn_dbg_info(node); + tarval *tv; + long value; if (mode_is_float(mode)) { - dbg_info *dbgi = get_irn_dbg_info(node); tarval *tv = get_Const_tarval(node); ir_entity *entity = create_float_const_entity(tv); ir_node *addr = make_addr(dbgi, entity); @@ -735,12 +686,21 @@ static ir_node *gen_Const(ir_node *node) return proj; } - /* use the 0 register instead of a 0-constant */ - if (is_Const_null(node)) { + tv = get_Const_tarval(node); + value = get_tarval_long(tv); + if (value == 0) { return get_g0(); + } else if (-4096 <= value && value <= 4095) { + return new_bd_sparc_Or_imm(dbgi, block, get_g0(), value); + } else { + ir_node *hi = new_bd_sparc_SetHi(dbgi, block, value); + be_dep_on_frame(hi); + if ((value & 0x3ff) != 0) { + return new_bd_sparc_Or_imm(dbgi, block, hi, value & 0x3ff); + } else { + return hi; + } } - - return create_const_graph(node, block); } static ir_mode *get_cmp_mode(ir_node *b_value) @@ -773,7 +733,7 @@ static ir_node *gen_Cond(ir_node *node) // switch/case jumps if (mode != mode_b) { - panic("SwitchJmp not supported yet"); + panic("SwitchJump not implemented yet"); } // regular if/else jumps @@ -965,10 +925,6 @@ static ir_node *gen_Conv(ir_node *node) static ir_node *gen_Unknown(ir_node *node) { - ir_node *block = get_nodes_block(node); - ir_node *new_block = be_transform_node(block); - dbg_info *dbgi = get_irn_dbg_info(node); - /* just produce a 0 */ ir_mode *mode = get_irn_mode(node); if (mode_is_float(mode)) { @@ -976,7 +932,7 @@ static ir_node *gen_Unknown(ir_node *node) be_dep_on_frame(node); return node; } else if (mode_needs_gp_reg(mode)) { - return create_const_graph_value(dbgi, new_block, 0); + return get_g0(); } panic("Unexpected Unknown mode"); @@ -1899,6 +1855,9 @@ void sparc_transform_graph(sparc_code_gen_t *cg) node_to_stack = NULL; be_add_missing_keeps(irg); + + /* do code placement, to optimize the position of constants */ + place_code(cg->irg); } void sparc_init_transform(void)