OSDN Git Service

Fix to expose more LIM when creating mem_ref
authordavidxl <davidxl@138bc75d-0d04-0410-961f-82ee72b054a4>
Wed, 28 Jul 2010 05:08:24 +0000 (05:08 +0000)
committerdavidxl <davidxl@138bc75d-0d04-0410-961f-82ee72b054a4>
Wed, 28 Jul 2010 05:08:24 +0000 (05:08 +0000)
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@162616 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/ChangeLog
gcc/tree-flow.h
gcc/tree-ssa-address.c
gcc/tree-ssa-loop-ivopts.c

index 438f2db..1d0b535 100644 (file)
@@ -1,3 +1,10 @@
+2010-07-27  Xinliang David Li <davidxl@google.com>
+       * tree-flow.h (create_mem_ref): Add one new parameter.
+       * tree-ssa-address.c (create_mem_ref): New parameter.
+       (addr_to_parts): Ditto.
+       (move_variant_to_index): New function.
+       * tree-ssa-loop-ivopts.c (rewrite_use_address): Pass new argument.
+
 2010-07-27  Bernd Schmidt  <bernds@codesourcery.com>
 
        * rtl.def (DEBUG_INSN, INSN, JUMP_INSN, CALL_INSN, NOTE): Swap operands
index 6209a84..abbf917 100644 (file)
@@ -832,8 +832,8 @@ struct mem_address
 };
 
 struct affine_tree_combination;
-tree create_mem_ref (gimple_stmt_iterator *, tree, tree,
-                    struct affine_tree_combination *, tree, bool);
+tree create_mem_ref (gimple_stmt_iterator *, tree,
+                    struct affine_tree_combination *, tree, tree, tree, bool);
 rtx addr_for_mem_ref (struct mem_address *, addr_space_t, bool);
 void get_address_description (tree, struct mem_address *);
 tree maybe_fold_tmr (tree);
index f49bf14..474a798 100644 (file)
@@ -470,6 +470,31 @@ move_pointer_to_base (struct mem_address *parts, aff_tree *addr)
   aff_combination_remove_elt (addr, i);
 }
 
+/* Moves the loop variant part V in linear address ADDR to be the index
+   of PARTS.  */
+
+static void
+move_variant_to_index (struct mem_address *parts, aff_tree *addr, tree v)
+{
+  unsigned i;
+  tree val = NULL_TREE;
+
+  gcc_assert (!parts->index);
+  for (i = 0; i < addr->n; i++)
+    {
+      val = addr->elts[i].val;
+      if (operand_equal_p (val, v, 0))
+       break;
+    }
+
+  if (i == addr->n)
+    return;
+
+  parts->index = fold_convert (sizetype, val);
+  parts->step = double_int_to_tree (sizetype, addr->elts[i].coef);
+  aff_combination_remove_elt (addr, i);
+}
+
 /* Adds ELT to PARTS.  */
 
 static void
@@ -573,7 +598,8 @@ most_expensive_mult_to_index (tree type, struct mem_address *parts,
 
 /* Splits address ADDR for a memory access of type TYPE into PARTS.
    If BASE_HINT is non-NULL, it specifies an SSA name to be used
-   preferentially as base of the reference.
+   preferentially as base of the reference, and IV_CAND is the selected
+   iv candidate used in ADDR.
 
    TODO -- be more clever about the distribution of the elements of ADDR
    to PARTS.  Some architectures do not support anything but single
@@ -583,8 +609,9 @@ most_expensive_mult_to_index (tree type, struct mem_address *parts,
    addressing modes is useless.  */
 
 static void
-addr_to_parts (tree type, aff_tree *addr, tree base_hint,
-              struct mem_address *parts, bool speed)
+addr_to_parts (tree type, aff_tree *addr, tree iv_cand,
+              tree base_hint, struct mem_address *parts,
+               bool speed)
 {
   tree part;
   unsigned i;
@@ -602,9 +629,17 @@ addr_to_parts (tree type, aff_tree *addr, tree base_hint,
   /* Try to find a symbol.  */
   move_fixed_address_to_symbol (parts, addr);
 
+  /* No need to do address parts reassociation if the number of parts
+     is <= 2 -- in that case, no loop invariant code motion can be
+     exposed.  */
+
+  if (!base_hint && (addr->n > 2))
+    move_variant_to_index (parts, addr, iv_cand);
+
   /* First move the most expensive feasible multiplication
      to index.  */
-  most_expensive_mult_to_index (type, parts, addr, speed);
+  if (!parts->index)
+    most_expensive_mult_to_index (type, parts, addr, speed);
 
   /* Try to find a base of the reference.  Since at the moment
      there is no reliable way how to distinguish between pointer and its
@@ -644,17 +679,19 @@ gimplify_mem_ref_parts (gimple_stmt_iterator *gsi, struct mem_address *parts)
 
 /* Creates and returns a TARGET_MEM_REF for address ADDR.  If necessary
    computations are emitted in front of GSI.  TYPE is the mode
-   of created memory reference.  */
+   of created memory reference. IV_CAND is the selected iv candidate in ADDR,
+   and BASE_HINT is non NULL if IV_CAND comes from a base address
+   object.  */
 
 tree
-create_mem_ref (gimple_stmt_iterator *gsi, tree type, tree alias_ptr_type,
-               aff_tree *addr, tree base_hint, bool speed)
+create_mem_ref (gimple_stmt_iterator *gsi, tree type, aff_tree *addr,
+               tree alias_ptr_type, tree iv_cand, tree base_hint, bool speed)
 {
   tree mem_ref, tmp;
   tree atype;
   struct mem_address parts;
 
-  addr_to_parts (type, addr, base_hint, &parts, speed);
+  addr_to_parts (type, addr, iv_cand, base_hint, &parts, speed);
   gimplify_mem_ref_parts (gsi, &parts);
   mem_ref = create_mem_ref_raw (type, alias_ptr_type, &parts);
   if (mem_ref)
index ae29988..478a019 100644 (file)
@@ -5745,7 +5745,7 @@ rewrite_use_address (struct ivopts_data *data,
   aff_tree aff;
   gimple_stmt_iterator bsi = gsi_for_stmt (use->stmt);
   tree base_hint = NULL_TREE;
-  tree ref;
+  tree ref, iv;
   bool ok;
 
   adjust_iv_update_pos (cand, use);
@@ -5767,9 +5767,10 @@ rewrite_use_address (struct ivopts_data *data,
   if (cand->iv->base_object)
     base_hint = var_at_stmt (data->current_loop, cand, use->stmt);
 
-  ref = create_mem_ref (&bsi, TREE_TYPE (*use->op_p),
+  iv = var_at_stmt (data->current_loop, cand, use->stmt);
+  ref = create_mem_ref (&bsi, TREE_TYPE (*use->op_p), &aff,
                        reference_alias_ptr_type (*use->op_p),
-                       &aff, base_hint, data->speed);
+                       iv, base_hint, data->speed);
   copy_ref_info (ref, *use->op_p);
   *use->op_p = ref;
 }