sparc: redo and improve sparc immediate handling (low-part after sethi is now omitted...
authorMatthias Braun <matze@braunis.de>
Mon, 9 Aug 2010 14:53:12 +0000 (14:53 +0000)
committerMatthias Braun <matze@braunis.de>
Mon, 9 Aug 2010 14:53:12 +0000 (14:53 +0000)
[r27918]

ir/be/sparc/sparc_emitter.c
ir/be/sparc/sparc_emitter.h
ir/be/sparc/sparc_new_nodes.c
ir/be/sparc/sparc_nodes_attr.h
ir/be/sparc/sparc_spec.pl
ir/be/sparc/sparc_transform.c

index a5b25e9..bffd3e3 100644 (file)
@@ -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);
index ea3f4c1..4e12d8d 100644 (file)
@@ -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);
index 47ad2f9..772fa1b 100644 (file)
@@ -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;
index d8342da..ab028c8 100644 (file)
@@ -26,6 +26,7 @@
 #define FIRM_BE_SPARC_SPARC_NODES_ATTR_H
 
 #include "../bearch.h"
+#include <stdint.h>
 
 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 */
index 61c76eb..1a13450 100644 (file)
@@ -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"],
index 075f07b..09230d9 100644 (file)
@@ -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)