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] Fix PR39999, oscillating compute_antic


This fixes PR39999 - PRE doesn't like the non-symmetry with
useless type conversions, so it oscillates with two identical
expressions that only differ in their non-compatible but
trivially convertible in one direction types.

The following patch fixes the issue by using gimple_expr_type properly
and by fixing that (well, at least partly, for the interesting cases)
to return the expression type and not the type the expression type
was trivially converted to.

Bootstrapped and tested on x86_64-unknown-linux-gnu on the 4.4 branch,
on trunk this breaks Ada (and thus waits for the subtype removal).

I will apply this to the 4.4 branch in a few days.

Richard.

2009-05-08  Richard Guenther  <rguenther@suse.de>

	PR tree-optimization/39999
	* gimple.h (gimple_expr_type): Use the expression type looking
	through useless conversions.
	* tree-ssa-sccvn.c (vn_nary_op_lookup_stmt): Use gimple_expr_type.
	(vn_nary_op_insert_stmt): Likewise.
	(simplify_binary_expression): Likewise.

	* gcc.c-torture/compile/pr39999.c: New testcase.

Index: gcc/gimple.h
===================================================================
*** gcc/gimple.h.orig	2009-05-08 12:10:44.000000000 +0200
--- gcc/gimple.h	2009-05-08 12:12:48.000000000 +0200
*************** gimple_modified_p (const_gimple g)
*** 1360,1394 ****
    return (gimple_has_ops (g)) ? (bool) g->gsbase.modified : false;
  }
  
- /* Return the type of the main expression computed by STMT.  Return
-    void_type_node if the statement computes nothing.  */
- 
- static inline tree
- gimple_expr_type (const_gimple stmt)
- {
-   enum gimple_code code = gimple_code (stmt);
- 
-   if (code == GIMPLE_ASSIGN || code == GIMPLE_CALL)
-     {
-       tree type = TREE_TYPE (gimple_get_lhs (stmt));
-       /* Integral sub-types are never the type of the expression,
-          but they still can be the type of the result as the base
- 	 type (in which expressions are computed) is trivially
- 	 convertible to one of its sub-types.  So always return
- 	 the base type here.  */
-       if (INTEGRAL_TYPE_P (type)
- 	  && TREE_TYPE (type)
- 	  /* But only if they are trivially convertible.  */
- 	  && useless_type_conversion_p (type, TREE_TYPE (type)))
- 	type = TREE_TYPE (type);
-       return type;
-     }
-   else if (code == GIMPLE_COND)
-     return boolean_type_node;
-   else
-     return void_type_node;
- }
- 
  
  /* Return the tree code for the expression computed by STMT.  This is
     only valid for GIMPLE_COND, GIMPLE_CALL and GIMPLE_ASSIGN.  For
--- 1360,1365 ----
*************** gimple_predict_set_outcome (gimple gs, e
*** 4242,4247 ****
--- 4213,4267 ----
  }
  
  
+ /* Return the type of the main expression computed by STMT.  Return
+    void_type_node if the statement computes nothing.  */
+ 
+ static inline tree
+ gimple_expr_type (const_gimple stmt)
+ {
+   enum gimple_code code = gimple_code (stmt);
+ 
+   if (code == GIMPLE_ASSIGN || code == GIMPLE_CALL)
+     {
+       tree type;
+       /* In general we want to pass out a type that can be substituted
+          for both the RHS and the LHS types if there is a possibly
+ 	 useless conversion involved.  That means returning the
+ 	 original RHS type as far as we can reconstruct it.  */
+       if (code == GIMPLE_CALL)
+ 	type = gimple_call_return_type (stmt);
+       else
+ 	switch (gimple_assign_rhs_code (stmt))
+ 	  {
+ 	  case POINTER_PLUS_EXPR:
+ 	    type = TREE_TYPE (gimple_assign_rhs1 (stmt));
+ 	    break;
+ 
+ 	  default:
+ 	    /* As fallback use the type of the LHS.  */
+ 	    type = TREE_TYPE (gimple_get_lhs (stmt));
+ 	    break;
+ 	  }
+ 
+       /* Integral sub-types are never the type of the expression,
+          but they still can be the type of the result as the base
+ 	 type (in which expressions are computed) is trivially
+ 	 convertible to one of its sub-types.  So always return
+ 	 the base type here.  */
+       if (INTEGRAL_TYPE_P (type)
+ 	  && TREE_TYPE (type)
+ 	  /* But only if they are trivially convertible.  */
+ 	  && useless_type_conversion_p (type, TREE_TYPE (type)))
+ 	type = TREE_TYPE (type);
+       return type;
+     }
+   else if (code == GIMPLE_COND)
+     return boolean_type_node;
+   else
+     return void_type_node;
+ }
+ 
+ 
  /* Return a new iterator pointing to GIMPLE_SEQ's first statement.  */
  
  static inline gimple_stmt_iterator
Index: gcc/tree-ssa-sccvn.c
===================================================================
*** gcc/tree-ssa-sccvn.c.orig	2009-04-27 12:25:04.000000000 +0200
--- gcc/tree-ssa-sccvn.c	2009-05-08 12:12:48.000000000 +0200
*************** vn_nary_op_lookup_stmt (gimple stmt, vn_
*** 1232,1238 ****
      *vnresult = NULL;
    vno1.opcode = gimple_assign_rhs_code (stmt);
    vno1.length = gimple_num_ops (stmt) - 1;
!   vno1.type = TREE_TYPE (gimple_assign_lhs (stmt));
    for (i = 0; i < vno1.length; ++i)
      vno1.op[i] = gimple_op (stmt, i + 1);
    if (vno1.opcode == REALPART_EXPR
--- 1232,1238 ----
      *vnresult = NULL;
    vno1.opcode = gimple_assign_rhs_code (stmt);
    vno1.length = gimple_num_ops (stmt) - 1;
!   vno1.type = gimple_expr_type (stmt);
    for (i = 0; i < vno1.length; ++i)
      vno1.op[i] = gimple_op (stmt, i + 1);
    if (vno1.opcode == REALPART_EXPR
*************** vn_nary_op_insert_stmt (gimple stmt, tre
*** 1340,1346 ****
    vno1->value_id = VN_INFO (result)->value_id;
    vno1->opcode = gimple_assign_rhs_code (stmt);
    vno1->length = length;
!   vno1->type = TREE_TYPE (gimple_assign_lhs (stmt));
    for (i = 0; i < vno1->length; ++i)
      vno1->op[i] = gimple_op (stmt, i + 1);
    if (vno1->opcode == REALPART_EXPR
--- 1340,1346 ----
    vno1->value_id = VN_INFO (result)->value_id;
    vno1->opcode = gimple_assign_rhs_code (stmt);
    vno1->length = length;
!   vno1->type = gimple_expr_type (stmt);
    for (i = 0; i < vno1->length; ++i)
      vno1->op[i] = gimple_op (stmt, i + 1);
    if (vno1->opcode == REALPART_EXPR
*************** simplify_binary_expression (gimple stmt)
*** 2065,2071 ****
    fold_defer_overflow_warnings ();
  
    result = fold_binary (gimple_assign_rhs_code (stmt),
! 		        TREE_TYPE (gimple_get_lhs (stmt)), op0, op1);
    if (result)
      STRIP_USELESS_TYPE_CONVERSION (result);
  
--- 2065,2071 ----
    fold_defer_overflow_warnings ();
  
    result = fold_binary (gimple_assign_rhs_code (stmt),
! 		        gimple_expr_type (stmt), op0, op1);
    if (result)
      STRIP_USELESS_TYPE_CONVERSION (result);
  
Index: gcc/testsuite/gcc.c-torture/compile/pr39999.c
===================================================================
*** /dev/null	1970-01-01 00:00:00.000000000 +0000
--- gcc/testsuite/gcc.c-torture/compile/pr39999.c	2009-05-08 12:12:48.000000000 +0200
***************
*** 0 ****
--- 1,18 ----
+ void foo(void *);
+ void
+ MMAPGCD (int *A1, int *A2)
+ {
+   int *t;
+ 
+   do
+     {
+       t = A1;
+       A1 = A2;
+       A2 = t;
+     }
+   while (A2[-1]);
+ 
+   foo (A1-1);
+   foo (A2-1);
+ }
+ 


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