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]

Add few cases to operand_equal_p


Hi,
I am working on patch that makes operand_equal_p replace logic from
ipa-icf-gimple's compare_op via a valueizer hook.  Currently the patch however
cuts number of merges on firefox to half (apparently becuase it gives up on
some tree codes too early)
The patch bellow merges code from ipa-icf-gimple.c that is missing in
fold-const and is needed. 

Bootstrapped/regtested x86_64-linux, OK?

Honza

	* fold-const.c (operand_equal_p): Handle OBJ_TYPE_REF, CONSTRUCTOR
	and be more tolerant about FIELD_DECL.
	* tree.c (add_expr): Handle FIELD_DECL.
	(prototype_p, virtual_method_call_p, obj_type_ref_class): Constify.
	* tree.h (prototype_p, virtual_method_call_p, obj_type_ref_class):
	Constify.
Index: fold-const.c
===================================================================
--- fold-const.c	(revision 223500)
@@ -3037,6 +3058,40 @@ operand_equal_p (const_tree arg0, const_
 	case DOT_PROD_EXPR:
 	  return OP_SAME (0) && OP_SAME (1) && OP_SAME (2);
 
+ 	/* OBJ_TYPE_REF really is just a transparent wrapper around expression,
+ 	   but it holds additional type information for devirtualization that
+	   needs to be matched.  We may want to intoruce OEP flag if we want
+	   to compare the actual value only, or if we also care about effects
+	   of potentially merging the code.  This flag can bypass this check
+	   as well as the alias set matching in MEM_REF.  */
+	case OBJ_TYPE_REF:
+	  {
+	    if (!operand_equal_p (OBJ_TYPE_REF_EXPR (arg0),
+				  OBJ_TYPE_REF_EXPR (arg1), flags))
+	      return false;
+	    if (flag_devirtualize && virtual_method_call_p (arg0))
+	      {
+		if (tree_to_uhwi (OBJ_TYPE_REF_TOKEN (arg0))
+		    != tree_to_uhwi (OBJ_TYPE_REF_TOKEN (arg1)))
+		  return false;
+		if (!types_same_for_odr (obj_type_ref_class (arg0),
+					 obj_type_ref_class (arg1)))
+		  return false;
+		/* OBJ_TYPE_REF_OBJECT is used to track the instance of
+ 		   object THIS pointer points to.  Checking that both
+		   addresses equal is safe approximation of the fact
+		   that dynamic types are equal.
+		   Do not care about the other flags, because this expression
+		   does not attribute to actual value of OBJ_TYPE_REF  */
+		if (!operand_equal_p (OBJ_TYPE_REF_OBJECT (arg0),
+				      OBJ_TYPE_REF_OBJECT (arg1),
+				      OEP_ADDRESS_OF))
+		  return false;
+	      }
+
+	    return true;
+	  }
+
 	default:
 	  return 0;
 	}
@@ -3097,6 +3152,21 @@ operand_equal_p (const_tree arg0, const_
 	}
 
     case tcc_declaration:
+      /* At LTO time the FIELD_DECL may exist in multiple copies.
+ 	 We only care about offsets and bit offsets for operands.  */
+      if (TREE_CODE (arg0) == FIELD_DECL)
+	{
+	  tree offset1 = DECL_FIELD_OFFSET (arg0);
+	  tree offset2 = DECL_FIELD_OFFSET (arg1);
+
+	  tree bit_offset1 = DECL_FIELD_BIT_OFFSET (arg0);
+	  tree bit_offset2 = DECL_FIELD_BIT_OFFSET (arg1);
+
+	  flags &= ~(OEP_CONSTANT_ADDRESS_OF|OEP_ADDRESS_OF);
+
+	  return operand_equal_p (offset1, offset2, flags)
+		 && operand_equal_p (bit_offset1, bit_offset2, flags);
+	}
       /* Consider __builtin_sqrt equal to sqrt.  */
       return (TREE_CODE (arg0) == FUNCTION_DECL
 	      && DECL_BUILT_IN (arg0) && DECL_BUILT_IN (arg1)
@@ -3104,12 +3174,50 @@ operand_equal_p (const_tree arg0, const_
 	      && DECL_FUNCTION_CODE (arg0) == DECL_FUNCTION_CODE (arg1));
 
     default:
+      /* In GIMPLE empty constructors are allowed in initializers of
+ 	 vector types.  */
+      if (TREE_CODE (arg0) == CONSTRUCTOR)
+	{
+	  unsigned length1 = vec_safe_length (CONSTRUCTOR_ELTS (arg0));
+	  unsigned length2 = vec_safe_length (CONSTRUCTOR_ELTS (arg1));
+
+	  if (length1 != length2)
+	    return false;
+
+	  flags &= ~(OEP_CONSTANT_ADDRESS_OF|OEP_ADDRESS_OF);
+
+	  for (unsigned i = 0; i < length1; i++)
+	    if (!operand_equal_p (CONSTRUCTOR_ELT (arg0, i)->value,
+				  CONSTRUCTOR_ELT (arg1, i)->value, flags))
+	      return false;
+
+	  return true;
+	}
       return 0;
     }
 
 #undef OP_SAME
 #undef OP_SAME_WITH_NULL
 }
Index: tree.c
===================================================================
--- tree.c	(revision 223500)
+++ tree.c	(working copy)
@@ -7647,6 +7647,12 @@ add_expr (const_tree t, inchash::hash &h
 	  }
 	return;
       }
+    case FIELD_DECL:
+      /* At LTO time the FIELD_DECL may exist in multiple copies.
+	 We only care about offsets and bit offsets for operands.  */
+      inchash::add_expr (DECL_FIELD_OFFSET (t), hstate);
+      inchash::add_expr (DECL_FIELD_BIT_OFFSET (t), hstate);
+      return;
     case FUNCTION_DECL:
       /* When referring to a built-in FUNCTION_DECL, use the __builtin__ form.
 	 Otherwise nodes that compare equal according to operand_equal_p might
@@ -11579,7 +11585,7 @@ stdarg_p (const_tree fntype)
 /* Return true if TYPE has a prototype.  */
 
 bool
-prototype_p (tree fntype)
+prototype_p (const_tree fntype)
 {
   tree t;
 
@@ -12005,7 +12011,7 @@ lhd_gcc_personality (void)
    can't apply.) */
 
 bool
-virtual_method_call_p (tree target)
+virtual_method_call_p (const_tree target)
 {
   if (TREE_CODE (target) != OBJ_TYPE_REF)
     return false;
@@ -12026,7 +12032,7 @@ virtual_method_call_p (tree target)
 /* REF is OBJ_TYPE_REF, return the class the ref corresponds to.  */
 
 tree
-obj_type_ref_class (tree ref)
+obj_type_ref_class (const_tree ref)
 {
   gcc_checking_assert (TREE_CODE (ref) == OBJ_TYPE_REF);
   ref = TREE_TYPE (ref);
Index: tree.h
===================================================================
--- tree.h	(revision 223500)
+++ tree.h	(working copy)
@@ -4375,7 +4375,7 @@ extern int operand_equal_for_phi_arg_p (
 extern tree create_artificial_label (location_t);
 extern const char *get_name (tree);
 extern bool stdarg_p (const_tree);
-extern bool prototype_p (tree);
+extern bool prototype_p (const_tree);
 extern bool is_typedef_decl (tree x);
 extern bool typedef_variant_p (tree);
 extern bool auto_var_in_fn_p (const_tree, const_tree);
@@ -4544,8 +4544,8 @@ extern location_t *block_nonartificial_l
 extern location_t tree_nonartificial_location (tree);
 extern tree block_ultimate_origin (const_tree);
 extern tree get_binfo_at_offset (tree, HOST_WIDE_INT, tree);
-extern bool virtual_method_call_p (tree);
-extern tree obj_type_ref_class (tree ref);
+extern bool virtual_method_call_p (const_tree);
+extern tree obj_type_ref_class (const_tree ref);
 extern bool types_same_for_odr (const_tree type1, const_tree type2,
 				bool strict=false);
 extern bool contains_bitfld_component_ref_p (const_tree);


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