[patch] Compare addresses in operand_equal_p correctly

Zdenek Dvorak rakdver@atrey.karlin.mff.cuni.cz
Thu Nov 9 23:37:00 GMT 2006


Hello,

operand_equal_p will claim that &a[i] != &a[i] most of the time, since
it will recursively ask whether a[i] == a[i], and fail because a[i] has
side effects.  This patch makes operand_equal_p remember whether we are
inside ADDR_EXPR, and ignore side effects of the (nonexistent) memory access
in this case.

Bootstrapped & regtested on i686.

Zdenek

	* tree.h (enum operand_equal_flag): Add OEP_IN_ADDRESS.
	* fold-const.c (operand_equal_p): Do not take side effects into account
	when OEP_IN_ADDRESS is passed in flags.

Index: tree.h
===================================================================
*** tree.h	(revision 118545)
--- tree.h	(working copy)
*************** extern int div_and_round_double (enum tr
*** 4251,4257 ****
  enum operand_equal_flag
  {
    OEP_ONLY_CONST = 1,
!   OEP_PURE_SAME = 2
  };
  
  extern int operand_equal_p (tree, tree, unsigned int);
--- 4257,4264 ----
  enum operand_equal_flag
  {
    OEP_ONLY_CONST = 1,
!   OEP_PURE_SAME = 2,
!   OEP_IN_ADDRESS = 4
  };
  
  extern int operand_equal_p (tree, tree, unsigned int);
Index: fold-const.c
===================================================================
*** fold-const.c	(revision 118545)
--- fold-const.c	(working copy)
*************** truth_value_p (enum tree_code code)
*** 2479,2485 ****
  
     If OEP_PURE_SAME is set, then pure functions with identical arguments
     are considered the same.  It is used when the caller has other ways
!    to ensure that global memory is unchanged in between.  */
  
  int
  operand_equal_p (tree arg0, tree arg1, unsigned int flags)
--- 2479,2488 ----
  
     If OEP_PURE_SAME is set, then pure functions with identical arguments
     are considered the same.  It is used when the caller has other ways
!    to ensure that global memory is unchanged in between.
! 
!    If OEP_IN_ADDRESS is set, then identical-looking memory references
!    are considered equal, even if they have side effects.  */
  
  int
  operand_equal_p (tree arg0, tree arg1, unsigned int flags)
*************** operand_equal_p (tree arg0, tree arg1, u
*** 2647,2654 ****
      case tcc_reference:
        /* If either of the pointer (or reference) expressions we are
  	 dereferencing contain a side effect, these cannot be equal.  */
!       if (TREE_SIDE_EFFECTS (arg0)
! 	  || TREE_SIDE_EFFECTS (arg1))
  	return 0;
  
        switch (TREE_CODE (arg0))
--- 2650,2663 ----
      case tcc_reference:
        /* If either of the pointer (or reference) expressions we are
  	 dereferencing contain a side effect, these cannot be equal.  */
!       if (!(flags & OEP_IN_ADDRESS)
! 	  && (TREE_SIDE_EFFECTS (arg0)
! 	      || TREE_SIDE_EFFECTS (arg1)))
! 	return 0;
! 
!       /* Types of structures must match.  */
!       if (AGGREGATE_TYPE_P (TREE_TYPE (arg0))
! 	  && TREE_TYPE (arg0) != TREE_TYPE (arg1))
  	return 0;
  
        switch (TREE_CODE (arg0))
*************** operand_equal_p (tree arg0, tree arg1, u
*** 2658,2682 ****
  	case MISALIGNED_INDIRECT_REF:
  	case REALPART_EXPR:
  	case IMAGPART_EXPR:
  	  return OP_SAME (0);
  
  	case ARRAY_REF:
  	case ARRAY_RANGE_REF:
  	  /* Operands 2 and 3 may be null.  */
! 	  return (OP_SAME (0)
! 		  && OP_SAME (1)
  		  && OP_SAME_WITH_NULL (2)
  		  && OP_SAME_WITH_NULL (3));
  
  	case COMPONENT_REF:
  	  /* Handle operand 2 the same as for ARRAY_REF.  Operand 0
  	     may be NULL when we're called to compare MEM_EXPRs.  */
! 	  return OP_SAME_WITH_NULL (0)
! 		 && OP_SAME (1)
! 		 && OP_SAME_WITH_NULL (2);
  
  	case BIT_FIELD_REF:
! 	  return OP_SAME (0) && OP_SAME (1) && OP_SAME (2);
  
  	default:
  	  return 0;
--- 2667,2701 ----
  	case MISALIGNED_INDIRECT_REF:
  	case REALPART_EXPR:
  	case IMAGPART_EXPR:
+ 	  flags &= ~OEP_IN_ADDRESS;
  	  return OP_SAME (0);
  
  	case ARRAY_REF:
  	case ARRAY_RANGE_REF:
  	  /* Operands 2 and 3 may be null.  */
! 	  if (!OP_SAME (0))
! 	    return false;
! 	  flags &= ~OEP_IN_ADDRESS;
! 	  return (OP_SAME (1)
  		  && OP_SAME_WITH_NULL (2)
  		  && OP_SAME_WITH_NULL (3));
  
  	case COMPONENT_REF:
  	  /* Handle operand 2 the same as for ARRAY_REF.  Operand 0
  	     may be NULL when we're called to compare MEM_EXPRs.  */
! 	  if (!OP_SAME_WITH_NULL (0))
! 	    return false;
! 
! 	  flags &= ~OEP_IN_ADDRESS;
! 	  return (OP_SAME (1)
! 		  && OP_SAME_WITH_NULL (2));
  
  	case BIT_FIELD_REF:
! 	  if (!OP_SAME (0))
! 	    return false;
! 
! 	  flags &= ~OEP_IN_ADDRESS;
! 	  return OP_SAME (1) && OP_SAME (2);
  
  	default:
  	  return 0;
*************** operand_equal_p (tree arg0, tree arg1, u
*** 2686,2691 ****
--- 2705,2713 ----
        switch (TREE_CODE (arg0))
  	{
  	case ADDR_EXPR:
+ 	  flags |= OEP_IN_ADDRESS;
+ 	  return OP_SAME (0);
+ 
  	case TRUTH_NOT_EXPR:
  	  return OP_SAME (0);
  
*************** operand_equal_p (tree arg0, tree arg1, u
*** 2745,2750 ****
--- 2767,2779 ----
  	}
  
      case tcc_declaration:
+       if (TREE_CODE (arg0) == FIELD_DECL)
+ 	return arg0 == arg1;
+ 
+       if ((flags & OEP_IN_ADDRESS) != 0
+ 	  && SSA_VAR_P (arg0))
+ 	return arg0 == arg1;
+ 
        /* Consider __builtin_sqrt equal to sqrt.  */
        return (TREE_CODE (arg0) == FUNCTION_DECL
  	      && DECL_BUILT_IN (arg0) && DECL_BUILT_IN (arg1)



More information about the Gcc-patches mailing list