This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[patch] for PR 17591


Hello,

this patch fixes handling of varying component offsets in ivopts and
invariant motion, thus fixing the bootstrap problem and several of the
testsuite failures in this PR.

Also handling of ALIGN_INDIRECT_REF and MISALIGNED_INDIRECT_REF in
ivopts is wrong.  Until I can come up with a better solution, this
patch avoids (miss)optimizing them completely.

Older patch for ada bootstrap problem
(http://gcc.gnu.org/ml/gcc-patches/2004-09/msg01863.html) is included
in order to make testing possible.

Bootstrapped & regtested on i686.

Zdenek

	PR bootstrap/17591
	* tree-ssa-loop-im.c (for_each_index): Call callback for component_refs
	with varying offset.
	* tree-ssa-loop-ivopts.c (abnormal_ssa_name_p): New function.
	(idx_contains_abnormal_ssa_name_p): Scan step and lower bound for
	ARRAY_REFS.
	(expr_invariant_in_loop_p): New function.
	(idx_find_step): Handle step and lower bound for ARRAY_REFs.  Handle
	component_ref_field_offset for COMPONENT_REFs.  Do not allow
	ALIGN_INDIRECT_REFs and MISALIGNED_INDIRECT_REFs.
	(add_address_candidates): Do not handle ALIGN_INDIRECT_REFs and
	MISALIGNED_INDIRECT_REFs.
	(idx_remove_ssa_names): Handle step and lower bound for ARRAY_REFs.
	(rewrite_address_base): Do not handle ALIGN_INDIRECT_REFs and
	MISALIGNED_INDIRECT_REFs.

Index: tree-ssa-loop-im.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/tree-ssa-loop-im.c,v
retrieving revision 2.14
diff -c -3 -p -r2.14 tree-ssa-loop-im.c
*** tree-ssa-loop-im.c	23 Sep 2004 14:34:19 -0000	2.14
--- tree-ssa-loop-im.c	24 Sep 2004 13:47:13 -0000
*************** get_stmt_uid (tree stmt)
*** 128,134 ****
  bool
  for_each_index (tree *addr_p, bool (*cbck) (tree, tree *, void *), void *data)
  {
!   tree *nxt;
  
    for (; ; addr_p = nxt)
      {
--- 128,134 ----
  bool
  for_each_index (tree *addr_p, bool (*cbck) (tree, tree *, void *), void *data)
  {
!   tree *nxt, *idx;
  
    for (; ; addr_p = nxt)
      {
*************** for_each_index (tree *addr_p, bool (*cbc
*** 144,150 ****
  	  return cbck (*addr_p, nxt, data);
  
  	case BIT_FIELD_REF:
- 	case COMPONENT_REF:
  	case VIEW_CONVERT_EXPR:
  	case ARRAY_RANGE_REF:
  	case REALPART_EXPR:
--- 144,149 ----
*************** for_each_index (tree *addr_p, bool (*cbc
*** 152,157 ****
--- 151,167 ----
  	  nxt = &TREE_OPERAND (*addr_p, 0);
  	  break;
  
+ 	case COMPONENT_REF:
+ 	  /* If the component has varying offset, it behaves like index
+ 	     as well.  */
+ 	  idx = &TREE_OPERAND (*addr_p, 2);
+ 	  if (*idx
+ 	      && !cbck (*addr_p, idx, data))
+ 	    return false;
+ 
+ 	  nxt = &TREE_OPERAND (*addr_p, 0);
+ 	  break;
+ 
  	case ARRAY_REF:
  	  nxt = &TREE_OPERAND (*addr_p, 0);
  	  if (!cbck (*addr_p, &TREE_OPERAND (*addr_p, 1), data))
Index: tree-ssa-loop-ivopts.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/tree-ssa-loop-ivopts.c,v
retrieving revision 2.12
diff -c -3 -p -r2.12 tree-ssa-loop-ivopts.c
*** tree-ssa-loop-ivopts.c	23 Sep 2004 14:34:19 -0000	2.12
--- tree-ssa-loop-ivopts.c	24 Sep 2004 13:47:14 -0000
*************** determine_biv_step (tree phi)
*** 701,717 ****
    return step;
  }
  
! /* Returns false if INDEX is a ssa name that occurs in an
     abnormal phi node.  Callback for for_each_index.  */
  
  static bool
! idx_contains_abnormal_ssa_name_p (tree base ATTRIBUTE_UNUSED, tree *index,
  				  void *data ATTRIBUTE_UNUSED)
  {
!   if (TREE_CODE (*index) != SSA_NAME)
!     return true;
  
!   return SSA_NAME_OCCURS_IN_ABNORMAL_PHI (*index) == 0;
  }
  
  /* Returns true if EXPR contains a ssa name that occurs in an
--- 701,736 ----
    return step;
  }
  
! /* Returns true if EXP is a ssa name that occurs in an abnormal phi node.  */
! 
! static bool
! abnormal_ssa_name_p (tree exp)
! {
!   if (!exp)
!     return false;
! 
!   if (TREE_CODE (exp) != SSA_NAME)
!     return false;
! 
!   return SSA_NAME_OCCURS_IN_ABNORMAL_PHI (exp) != 0;
! }
! 
! /* Returns false if BASE or INDEX contains a ssa name that occurs in an
     abnormal phi node.  Callback for for_each_index.  */
  
  static bool
! idx_contains_abnormal_ssa_name_p (tree base, tree *index,
  				  void *data ATTRIBUTE_UNUSED)
  {
!   if (TREE_CODE (base) == ARRAY_REF)
!     {
!       if (abnormal_ssa_name_p (TREE_OPERAND (base, 2)))
! 	return false;
!       if (abnormal_ssa_name_p (TREE_OPERAND (base, 3)))
! 	return false;
!     }
  
!   return !abnormal_ssa_name_p (*index);
  }
  
  /* Returns true if EXPR contains a ssa name that occurs in an
*************** find_interesting_uses_cond (struct ivopt
*** 1146,1151 ****
--- 1165,1203 ----
    record_use (data, cond_p, civ, stmt, USE_COMPARE);
  }
  
+ /* Returns true if expression EXPR is obviously invariant in LOOP,
+    i.e. if all its operands are defined outside of the LOOP.  */
+ 
+ static bool
+ expr_invariant_in_loop_p (struct loop *loop, tree expr)
+ {
+   basic_block def_bb;
+   unsigned i, len;
+ 
+   if (is_gimple_min_invariant (expr))
+     return true;
+ 
+   if (TREE_CODE (expr) == SSA_NAME)
+     {
+       def_bb = bb_for_stmt (SSA_NAME_DEF_STMT (expr));
+       if (def_bb
+ 	  && flow_bb_inside_loop_p (loop, def_bb))
+ 	return false;
+ 
+       return true;
+     }
+ 
+   if (!EXPR_P (expr))
+     return false;
+ 
+   len = first_rtl_op (TREE_CODE (expr));
+   for (i = 0; i < len; i++)
+     if (!expr_invariant_in_loop_p (loop, TREE_OPERAND (expr, i)))
+       return false;
+ 
+   return true;
+ }
+ 
  /* Cumulates the steps of indices into DATA and replaces their values with the
     initial ones.  Returns false when the value of the index cannot be determined.
     Callback for for_each_index.  */
*************** idx_find_step (tree base, tree *idx, voi
*** 1162,1171 ****
  {
    struct ifs_ivopts_data *dta = data;
    struct iv *iv;
!   tree step, type, iv_type, iv_step, lbound;
!   basic_block def_bb;
    struct loop *loop = dta->ivopts_data->current_loop;
!   
    if (TREE_CODE (*idx) != SSA_NAME)
      return true;
  
--- 1214,1248 ----
  {
    struct ifs_ivopts_data *dta = data;
    struct iv *iv;
!   tree step, type, iv_type, iv_step, lbound, off;
    struct loop *loop = dta->ivopts_data->current_loop;
! 
!   if (TREE_CODE (base) == MISALIGNED_INDIRECT_REF
!       || TREE_CODE (base) == ALIGN_INDIRECT_REF)
!     return false;
! 
!   /* If base is a component ref, require that the offset of the reference
!      is invariant.  */
!   if (TREE_CODE (base) == COMPONENT_REF)
!     {
!       off = component_ref_field_offset (base);
!       return expr_invariant_in_loop_p (loop, off);
!     }
! 
!   /* If base is array, first check whether we will be able to move the
!      reference out of the loop (in order to take its address in strength
!      reduction).  In order for this to work we need both lower bound
!      and step to be loop invariants.  */
!   if (TREE_CODE (base) == ARRAY_REF)
!     {
!       step = array_ref_element_size (base);
!       lbound = array_ref_low_bound (base);
! 
!       if (!expr_invariant_in_loop_p (loop, step)
! 	  || !expr_invariant_in_loop_p (loop, lbound))
! 	return false;
!     }
! 
    if (TREE_CODE (*idx) != SSA_NAME)
      return true;
  
*************** idx_find_step (tree base, tree *idx, voi
*** 1183,1209 ****
    if (TREE_CODE (base) == ARRAY_REF)
      {
        step = array_ref_element_size (base);
-       lbound = array_ref_low_bound (base);
  
        /* We only handle addresses whose step is an integer constant.  */
        if (TREE_CODE (step) != INTEGER_CST)
  	return false;
- 
-       /* We need the lower bound to be invariant in loop, since otherwise
- 	 we are unable to initialize a new induction variable created
- 	 in strength reduction -- we need to take the address of the
- 	 reference in front of the loop.  */
-       if (is_gimple_min_invariant (lbound))
- 	; /* Nothing to do.  */
-       else if (TREE_CODE (lbound) != SSA_NAME)
- 	return false;
-       else
- 	{
- 	  def_bb = bb_for_stmt (SSA_NAME_DEF_STMT (lbound));
- 	  if (def_bb
- 	      && flow_bb_inside_loop_p (loop, def_bb))
- 	    return false;
- 	}
      }
    else
      /* The step for pointer arithmetics already is 1 byte.  */
--- 1260,1269 ----
*************** find_interesting_uses_address (struct iv
*** 1269,1277 ****
        || zero_p (step))
      goto fail;
  
!   if (TREE_CODE (base) == INDIRECT_REF
!       || TREE_CODE (base) == ALIGN_INDIRECT_REF
!       || TREE_CODE (base) == MISALIGNED_INDIRECT_REF)
      base = TREE_OPERAND (base, 0);
    else
      base = build_addr (base);
--- 1329,1338 ----
        || zero_p (step))
      goto fail;
  
!   gcc_assert (TREE_CODE (base) != ALIGN_INDIRECT_REF);
!   gcc_assert (TREE_CODE (base) != MISALIGNED_INDIRECT_REF);
! 
!   if (TREE_CODE (base) == INDIRECT_REF)
      base = TREE_OPERAND (base, 0);
    else
      base = build_addr (base);
*************** add_address_candidates (struct ivopts_da
*** 1701,1709 ****
  
        if (base != TREE_OPERAND (iv->base, 0))
  	{ 
! 	  if (TREE_CODE (base) == INDIRECT_REF
! 	      || TREE_CODE (base) == ALIGN_INDIRECT_REF
! 	      || TREE_CODE (base) == MISALIGNED_INDIRECT_REF)
  	    base = TREE_OPERAND (base, 0);
  	  else
  	    base = build_addr (base);
--- 1762,1771 ----
  
        if (base != TREE_OPERAND (iv->base, 0))
  	{ 
! 	  gcc_assert (TREE_CODE (base) != ALIGN_INDIRECT_REF);
! 	  gcc_assert (TREE_CODE (base) != MISALIGNED_INDIRECT_REF);
! 
! 	  if (TREE_CODE (base) == INDIRECT_REF)
  	    base = TREE_OPERAND (base, 0);
  	  else
  	    base = build_addr (base);
*************** rewrite_use_nonlinear_expr (struct ivopt
*** 3805,3815 ****
     for_each_index.  */
  
  static bool
! idx_remove_ssa_names (tree base ATTRIBUTE_UNUSED, tree *idx,
  		      void *data ATTRIBUTE_UNUSED)
  {
    if (TREE_CODE (*idx) == SSA_NAME)
      *idx = SSA_NAME_VAR (*idx);
    return true;
  }
  
--- 3867,3892 ----
     for_each_index.  */
  
  static bool
! idx_remove_ssa_names (tree base, tree *idx,
  		      void *data ATTRIBUTE_UNUSED)
  {
+   tree *op;
+ 
    if (TREE_CODE (*idx) == SSA_NAME)
      *idx = SSA_NAME_VAR (*idx);
+ 
+   if (TREE_CODE (base) == ARRAY_REF)
+     {
+       op = &TREE_OPERAND (base, 2);
+       if (*op
+ 	  && TREE_CODE (*op) == SSA_NAME)
+ 	*op = SSA_NAME_VAR (*op);
+       op = &TREE_OPERAND (base, 3);
+       if (*op
+ 	  && TREE_CODE (*op) == SSA_NAME)
+ 	*op = SSA_NAME_VAR (*op);
+     }
+ 
    return true;
  }
  
*************** rewrite_address_base (block_stmt_iterato
*** 3837,3845 ****
  
    if (!var || TREE_CODE (with) != SSA_NAME)
      goto do_rewrite;
!   if (TREE_CODE (var) == INDIRECT_REF
!       || TREE_CODE (var) == ALIGN_INDIRECT_REF
!       || TREE_CODE (var) == MISALIGNED_INDIRECT_REF)
      var = TREE_OPERAND (var, 0);
    if (TREE_CODE (var) == SSA_NAME)
      {
--- 3914,3923 ----
  
    if (!var || TREE_CODE (with) != SSA_NAME)
      goto do_rewrite;
! 
!   gcc_assert (TREE_CODE (var) != ALIGN_INDIRECT_REF);
!   gcc_assert (TREE_CODE (var) != MISALIGNED_INDIRECT_REF);
!   if (TREE_CODE (var) == INDIRECT_REF)
      var = TREE_OPERAND (var, 0);
    if (TREE_CODE (var) == SSA_NAME)
      {
*************** rewrite_address_base (block_stmt_iterato
*** 3876,3894 ****
  do_rewrite:
  
    orig = NULL_TREE;
!   if (TREE_CODE (*op) == INDIRECT_REF
!       || TREE_CODE (*op) == ALIGN_INDIRECT_REF
!       || TREE_CODE (*op) == MISALIGNED_INDIRECT_REF)
      orig = REF_ORIGINAL (*op);
    if (!orig)
      orig = unshare_and_remove_ssa_names (*op);
  
!   if (TREE_CODE (bvar) == ALIGN_INDIRECT_REF)
!     *op = build1 (ALIGN_INDIRECT_REF, TREE_TYPE (*op), with);
!   else if (TREE_CODE (bvar) == MISALIGNED_INDIRECT_REF)
!     *op = build2 (MISALIGNED_INDIRECT_REF, TREE_TYPE (*op), with, TREE_OPERAND (*op, 1));
!   else
!     *op = build1 (INDIRECT_REF, TREE_TYPE (*op), with);
  
    /* Record the original reference, for purposes of alias analysis.  */
    REF_ORIGINAL (*op) = orig;
--- 3954,3968 ----
  do_rewrite:
  
    orig = NULL_TREE;
!   gcc_assert (TREE_CODE (*op) != ALIGN_INDIRECT_REF);
!   gcc_assert (TREE_CODE (*op) != MISALIGNED_INDIRECT_REF);
! 
!   if (TREE_CODE (*op) == INDIRECT_REF)
      orig = REF_ORIGINAL (*op);
    if (!orig)
      orig = unshare_and_remove_ssa_names (*op);
  
!   *op = build1 (INDIRECT_REF, TREE_TYPE (*op), with);
  
    /* Record the original reference, for purposes of alias analysis.  */
    REF_ORIGINAL (*op) = orig;


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]