- never use (broken) sequential load/store in abi
authorMatthias Braun <matze@braunis.de>
Tue, 25 Sep 2007 13:57:17 +0000 (13:57 +0000)
committerMatthias Braun <matze@braunis.de>
Tue, 25 Sep 2007 13:57:17 +0000 (13:57 +0000)
- more sophisticated address mode code selection, brings huge speedups in
  164.gzip

[r15918]

ir/be/ia32/bearch_ia32.c
ir/be/ia32/ia32_address_mode.c
ir/be/ia32/ia32_address_mode.h
ir/be/ia32/ia32_emitter.c
ir/be/ia32/ia32_transform.c
ir/be/ia32/ia32_transform.h

index 598a0fb..8be3441 100644 (file)
@@ -1774,11 +1774,9 @@ static void ia32_get_call_abi(const void *self, ir_type *method_type, be_abi_cal
        int       n, i, regnum;
        be_abi_call_flags_t call_flags = be_abi_call_get_flags(abi);
 
-       unsigned use_push = !IS_P6_ARCH(isa->opt_arch);
-
        /* set abi flags for calls */
        call_flags.bits.left_to_right         = 0;  /* always last arg first on stack */
-       call_flags.bits.store_args_sequential = use_push;
+       call_flags.bits.store_args_sequential = 0;
        /* call_flags.bits.try_omit_fp                 not changed: can handle both settings */
        call_flags.bits.fp_free               = 0;  /* the frame pointer is fixed in IA32 */
        call_flags.bits.call_has_imm          = 1;  /* IA32 calls can have immediate address */
index d18a2bc..3fa5a4f 100644 (file)
 #endif
 
 #include "ia32_address_mode.h"
+#include "ia32_transform.h"
 
 #include "irtypes.h"
 #include "irnode_t.h"
 #include "irprintf.h"
 #include "error.h"
 #include "iredges_t.h"
+#include "irgwalk.h"
 
 #include "../benode_t.h"
 
-#undef AGGRESSIVE_AM
+#define AGGRESSIVE_AM
 
 /* gas/ld don't support negative symconsts :-( */
 #undef SUPPORT_NEGATIVE_SYMCONSTS
 
-static int is_immediate_2(const ir_node *node, int *symconsts, int negate)
+static bitset_t *non_address_mode_nodes;
+
+static int do_is_immediate(const ir_node *node, int *symconsts, int negate)
 {
        ir_node *left;
        ir_node *right;
@@ -74,11 +78,14 @@ static int is_immediate_2(const ir_node *node, int *symconsts, int negate)
                return 1;
        case iro_Add:
        case iro_Sub:
+               if(bitset_is_set(non_address_mode_nodes, get_irn_idx(node)))
+                       return 0;
+
                left  = get_binop_left(node);
                right = get_binop_right(node);
-               if(!is_immediate_2(left, symconsts, negate))
+               if(!do_is_immediate(left, symconsts, negate))
                        return 0;
-               if(!is_immediate_2(right, symconsts, is_Sub(node) ? !negate : negate))
+               if(!do_is_immediate(right, symconsts, is_Sub(node) ? !negate : negate))
                        return 0;
 
                return 1;
@@ -89,13 +96,19 @@ static int is_immediate_2(const ir_node *node, int *symconsts, int negate)
        return 0;
 }
 
+static int is_immediate_simple(const ir_node *node)
+{
+       int symconsts = 0;
+       return do_is_immediate(node, &symconsts, 0);
+}
+
 static int is_immediate(ia32_address_t *addr, const ir_node *node, int negate)
 {
        int symconsts = 0;
        if(addr->symconst_ent != NULL)
                symconsts = 1;
 
-       return is_immediate_2(node, &symconsts, negate);
+       return do_is_immediate(node, &symconsts, negate);
 }
 
 static void eat_immediate(ia32_address_t *addr, ir_node *node, int negate)
@@ -107,10 +120,11 @@ static void eat_immediate(ia32_address_t *addr, ir_node *node, int negate)
        switch(get_irn_opcode(node)) {
        case iro_Const:
                tv = get_Const_tarval(node);
+               long val = get_tarval_long(tv);
                if(negate) {
-                       addr->offset -= get_tarval_long(tv);
+                       addr->offset -= val;
                } else {
-                       addr->offset += get_tarval_long(tv);
+                       addr->offset += val;
                }
                break;
        case iro_SymConst:
@@ -125,12 +139,14 @@ static void eat_immediate(ia32_address_t *addr, ir_node *node, int negate)
                addr->symconst_sign = negate;
                break;
        case iro_Add:
+               assert(!bitset_is_set(non_address_mode_nodes, get_irn_idx(node)));
                left  = get_Add_left(node);
                right = get_Add_right(node);
                eat_immediate(addr, left, negate);
                eat_immediate(addr, right, negate);
                break;
        case iro_Sub:
+               assert(!bitset_is_set(non_address_mode_nodes, get_irn_idx(node)));
                left  = get_Sub_left(node);
                right = get_Sub_right(node);
                eat_immediate(addr, left, negate);
@@ -141,19 +157,22 @@ static void eat_immediate(ia32_address_t *addr, ir_node *node, int negate)
        }
 }
 
-static ir_node *eat_immediates(ia32_address_t *addr, ir_node *node)
+static ir_node *eat_immediates(ia32_address_t *addr, ir_node *node, int force)
 {
+       if(!force && bitset_is_set(non_address_mode_nodes, get_irn_idx(node)))
+               return node;
+
        if(is_Add(node)) {
                ir_node *left  = get_Add_left(node);
                ir_node *right = get_Add_right(node);
 
                if(is_immediate(addr, left, 0)) {
                        eat_immediate(addr, left, 0);
-                       return eat_immediates(addr, right);
+                       return eat_immediates(addr, right, 0);
                }
                if(is_immediate(addr, right, 0)) {
                        eat_immediate(addr, right, 0);
-                       return eat_immediates(addr, left);
+                       return eat_immediates(addr, left, 0);
                }
        } else if(is_Sub(node)) {
                ir_node *left  = get_Sub_left(node);
@@ -161,7 +180,7 @@ static ir_node *eat_immediates(ia32_address_t *addr, ir_node *node)
 
                if(is_immediate(addr, right, 1)) {
                        eat_immediate(addr, right, 1);
-                       return eat_immediates(addr, left);
+                       return eat_immediates(addr, left, 0);
                }
        }
 
@@ -190,6 +209,8 @@ static int eat_shl(ia32_address_t *addr, ir_node *node)
        if(val == 0) {
                ir_fprintf(stderr, "Optimisation warning: unoptimized Shl(,0) found\n");
        }
+       if(bitset_is_set(non_address_mode_nodes, get_irn_idx(node)))
+               return 0;
 
 #ifndef AGGRESSIVE_AM
        if(get_irn_n_edges(node) > 1)
@@ -197,7 +218,7 @@ static int eat_shl(ia32_address_t *addr, ir_node *node)
 #endif
 
        addr->scale = val;
-       addr->index = eat_immediates(addr, get_Shl_left(node));
+       addr->index = eat_immediates(addr, get_Shl_left(node), 0);
        return 1;
 }
 
@@ -218,7 +239,12 @@ void ia32_create_address_mode(ia32_address_t *addr, ir_node *node, int force)
        }
 #endif
 
-       eat_imms = eat_immediates(addr, node);
+       if(!force && bitset_is_set(non_address_mode_nodes, get_irn_idx(node))) {
+               addr->base = node;
+               return;
+       }
+
+       eat_imms = eat_immediates(addr, node, force);
        if(eat_imms != node) {
                res  = 1;
                node = eat_imms;
@@ -228,6 +254,10 @@ void ia32_create_address_mode(ia32_address_t *addr, ir_node *node, int force)
                        return;
                }
 #endif
+               if(bitset_is_set(non_address_mode_nodes, get_irn_idx(node))) {
+                       addr->base = node;
+                       return;
+               }
        }
 
        /* starting point Add, Sub or Shl, FrameAddr */
@@ -255,14 +285,16 @@ void ia32_create_address_mode(ia32_address_t *addr, ir_node *node, int force)
                } else if(is_Shl(right) && eat_shl(addr, right)) {
                        right = NULL;
                }
-               if(left != NULL && be_is_FrameAddr(left)) {
+               if(left != NULL && be_is_FrameAddr(left)
+                               && !bitset_is_set(non_address_mode_nodes, get_irn_idx(left))) {
                        assert(addr->base == NULL);
                        assert(addr->frame_entity == NULL);
                        addr->base         = be_get_FrameAddr_frame(left);
                        addr->use_frame    = 1;
                        addr->frame_entity = be_get_FrameAddr_entity(left);
                        left               = NULL;
-               } else if(right != NULL && be_is_FrameAddr(right)) {
+               } else if(right != NULL && be_is_FrameAddr(right)
+                               && !bitset_is_set(non_address_mode_nodes, get_irn_idx(right))) {
                        assert(addr->base == NULL);
                        assert(addr->frame_entity == NULL);
                        addr->base         = be_get_FrameAddr_frame(right);
@@ -295,37 +327,66 @@ void ia32_create_address_mode(ia32_address_t *addr, ir_node *node, int force)
 }
 
 
-typedef struct mark_evn_t mark_evn_t;
-struct mark_evn_t {
-       bitset_t *non_address_nodes;
-};
 
-
-static void mark_non_address_nodes(mark_evn_t *env, ir_node *node)
+static void mark_non_address_nodes(ir_node *node, void *env)
 {
-       bitset_set(env->non_address_nodes, get_irn_idx(node));
-
-       if(is_Load(node)) {
-               ir_node *ptr = get_Load_ptr(node);
-               ir_node *mem = get_Load_mem(node);
-
-               mark_non_address_nodes(env, mem);
-               (void) ptr;
-       } else if(is_Store(node)) {
-               ir_node *val = get_Store_value(node);
-               ir_node *ptr = get_Store_ptr(node);
-               ir_node *mem = get_Store_mem(node);
-
-               mark_non_address_nodes(env, val);
-               mark_non_address_nodes(env, mem);
-               (void) ptr;
-       } else {
-               int i;
-               int arity = get_irn_arity(node);
+       int i, arity;
+       ir_node *ptr;
+       ir_node *mem;
+       ir_node *val;
+       ir_node *left;
+       ir_node *right;
+       (void) env;
+
+       switch(get_irn_opcode(node)) {
+       case iro_Load:
+               ptr = get_Load_ptr(node);
+               mem = get_Load_mem(node);
+
+               bitset_set(non_address_mode_nodes, get_irn_idx(mem));
+               break;
+
+       case iro_Store:
+               val = get_Store_value(node);
+               ptr = get_Store_ptr(node);
+               mem = get_Store_mem(node);
+
+               bitset_set(non_address_mode_nodes, get_irn_idx(val));
+               bitset_set(non_address_mode_nodes, get_irn_idx(mem));
+               break;
+
+       case iro_Add:
+               left  = get_Add_left(node);
+               right = get_Add_right(node);
+               /* if we can do source address mode then we will never fold the add
+                * into address mode */
+               if(is_immediate_simple(right) ||
+                        (!use_source_address_mode(get_nodes_block(node), left, right)
+                    && !use_source_address_mode(get_nodes_block(node), right, left))) {
+                   break;
+               }
+               bitset_set(non_address_mode_nodes, get_irn_idx(node));
+               /* fallthrough */
+
+       default:
+               arity = get_irn_arity(node);
 
                for(i = 0; i < arity; ++i) {
                        ir_node *in = get_irn_n(node, i);
-                       mark_non_address_nodes(env, in);
+                       bitset_set(non_address_mode_nodes, get_irn_idx(in));
                }
+               break;
        }
 }
+
+void calculate_non_address_mode_nodes(ir_graph *irg)
+{
+       non_address_mode_nodes = bitset_malloc(get_irg_last_idx(irg));
+
+       irg_walk_graph(irg, NULL, mark_non_address_nodes, NULL);
+}
+
+void free_non_address_mode_nodes(void)
+{
+       bitset_free(non_address_mode_nodes);
+}
index fba3c0c..2f19db0 100644 (file)
@@ -44,4 +44,8 @@ struct ia32_address_t {
 
 void ia32_create_address_mode(ia32_address_t *addr, ir_node *node, int force);
 
+void calculate_non_address_mode_nodes(ir_graph *irg);
+
+void free_non_address_mode_nodes(void);
+
 #endif
index 7c356ec..7881584 100644 (file)
@@ -1313,9 +1313,11 @@ void emit_ia32_Immediate(ia32_emit_env_t *env, const ir_node *node)
                be_emit_ident(env, id);
        }
        if(attr->symconst == NULL || attr->offset != 0) {
-               if(attr->symconst != NULL)
-                       be_emit_char(env, '+');
-               be_emit_irprintf(env->emit, "0x%X", attr->offset);
+               if(attr->symconst != NULL) {
+                       be_emit_irprintf(env->emit, "%+d", attr->offset);
+               } else {
+                       be_emit_irprintf(env->emit, "0x%X", attr->offset);
+               }
        }
 }
 
index 8144253..6585e73 100644 (file)
@@ -447,8 +447,7 @@ const char *ia32_get_old_node_name(ia32_code_gen_t *cg, ir_node *irn) {
 }
 #endif /* NDEBUG */
 
-static int use_source_address_mode(ir_node *block, ir_node *node,
-                                   ir_node *other)
+int use_source_address_mode(ir_node *block, ir_node *node, ir_node *other)
 {
        ir_mode *mode;
        ir_node *load;
@@ -1620,8 +1619,8 @@ static ir_node *gen_Load(ir_node *node) {
 
                /* create a conv node with address mode for smaller modes */
                if(get_mode_size_bits(mode) < 32) {
-                       new_op = new_rd_ia32_Conv_I2I(dbgi, irg, block, base, index, new_mem,
-                                                     noreg, mode);
+                       new_op = new_rd_ia32_Conv_I2I(dbgi, irg, block, base, index,
+                                                     new_mem, noreg, mode);
                } else {
                        new_op = new_rd_ia32_Load(dbgi, irg, block, base, index, new_mem);
                }
@@ -2561,7 +2560,7 @@ static ir_node *create_I2I_Conv(ir_mode *src_mode, ir_mode *tgt_mode,
                new_op     = noreg;
                am.op_type = ia32_AddrModeS;
        } else {
-               new_op = be_transform_node(op);
+               new_op     = be_transform_node(op);
                am.op_type = ia32_Normal;
        }
        if(addr->base == NULL)
@@ -4654,14 +4653,18 @@ void ia32_add_missing_keeps(ia32_code_gen_t *cg)
 
 /* do the transformation */
 void ia32_transform_graph(ia32_code_gen_t *cg) {
+       ir_graph *irg = cg->irg;
+
        register_transformers();
        env_cg       = cg;
        initial_fpcw = NULL;
 
-       heights      = heights_new(cg->irg);
+       heights      = heights_new(irg);
+       calculate_non_address_mode_nodes(irg);
 
        be_transform_graph(cg->birg, ia32_pretransform_node, cg);
 
+       free_non_address_mode_nodes();
        heights_free(heights);
        heights = NULL;
 }
index fda2b41..c3512d8 100644 (file)
@@ -61,4 +61,12 @@ ir_entity *ia32_gen_fp_known_const(ia32_known_const_t kct);
 
 void ia32_add_missing_keeps(ia32_code_gen_t *cg);
 
+/**
+ * return true if the node is a Proj(Load) and could be used in source address
+ * mode for another node. Will return only true if the @p other node is not
+ * dependent on the memory of the Load (for binary operations use the other
+ * input here, for unary operations use NULL).
+ */
+int use_source_address_mode(ir_node *block, ir_node *node, ir_node *other);
+
 #endif /* FIRM_BE_IA32_IA32_TRANSFORM_H */