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] Get rid of awkward semantics for subtypes


Hi,

as explained in http://gcc.gnu.org/ml/gcc/2009-04/msg00323.html the attached 
patch gets rid of the awkward semantics implemented for subtypes (INTEGER_TYPE 
with a non-NULL TREE_TYPE).  It doesn't get rid of subtypes because they are 
needed for certain things but promotes them to first-class citizenship, so 
that it shouldn't be necessary to specifically check for them anymore in the 
middle-end, except for debugging information.  It's up to the front-end to 
make sure that range subtypes, e.g. built for arrays in all languages, don't 
leak into the code.

Tested on i586-suse-linux with the associated Gigi patch, OK for mainline?


2009-05-10  Eric Botcazou  <ebotcazou@adacore.com>

	* dbxout.c (dbxout_type): Be prepared to deal with subtypes.
	* dwarf2out.c (base_type_die): Likewise.
	(is_subrange_type): Delete.
	(subrange_type_die): Add LOW and HIGH parameters.  Use them for bounds.
	(modified_type_die): Call subrange_type_for_debug_p on subtypes.
	* fold-const.c (fold_truth_not_expr) <CONVERT_EXPR>: Do not strip
	it if the destination type is boolean.
	(build_range_check): Do not special-case subtypes.
	(fold_sign_changed_comparison): Likewise.
	(fold_unary): Likewise.
	* langhooks-def.h (LANG_HOOKS_GET_SUBRANGE_BOUNDS): Define.
	(LANG_HOOKS_FOR_TYPES_INITIALIZER): Add LANG_HOOKS_GET_SUBRANGE_BOUNDS.
	* langhooks.h (lang_hooks_for_types): Add get_subrange_bounds.
	* tree.h (subrange_type_for_debug_p): Declare.
	* tree.c (subrange_type_for_debug_p): New predicate based on the
	former is_subrange_type.
	* tree-chrec.c (avoid_arithmetics_in_type_p): Delete.
	(convert_affine_scev): Remove call to above function.
	(chrec_convert_aggressive): Likewise.
	* tree-ssa.c (useless_type_conversion_p_1): Do not specifically return
	false for conversions involving subtypes.
	* tree-vrp.c (vrp_val_max): Do not special-case subtypes.
	(vrp_val_min): Likewise.
	(needs_overflow_infinity): Likewise.
	(extract_range_from_unary_expr): Likewise.


-- 
Eric Botcazou
Index: tree-vrp.c
===================================================================
--- tree-vrp.c	(revision 147337)
+++ tree-vrp.c	(working copy)
@@ -121,7 +121,7 @@ DEF_VEC_ALLOC_O(switch_update, heap);
 static VEC (switch_update, heap) *to_update_switch_stmts;
 
 
-/* Return the maximum value for TYPEs base type.  */
+/* Return the maximum value for TYPE.  */
 
 static inline tree
 vrp_val_max (const_tree type)
@@ -129,14 +129,10 @@ vrp_val_max (const_tree type)
   if (!INTEGRAL_TYPE_P (type))
     return NULL_TREE;
 
-  /* For integer sub-types the values for the base type are relevant.  */
-  if (TREE_TYPE (type))
-    type = TREE_TYPE (type);
-
   return TYPE_MAX_VALUE (type);
 }
 
-/* Return the minimum value for TYPEs base type.  */
+/* Return the minimum value for TYPE.  */
 
 static inline tree
 vrp_val_min (const_tree type)
@@ -144,10 +140,6 @@ vrp_val_min (const_tree type)
   if (!INTEGRAL_TYPE_P (type))
     return NULL_TREE;
 
-  /* For integer sub-types the values for the base type are relevant.  */
-  if (TREE_TYPE (type))
-    type = TREE_TYPE (type);
-
   return TYPE_MIN_VALUE (type);
 }
 
@@ -188,11 +180,7 @@ vrp_val_is_min (const_tree val)
 static inline bool
 needs_overflow_infinity (const_tree type)
 {
-  return (INTEGRAL_TYPE_P (type)
-	  && !TYPE_OVERFLOW_WRAPS (type)
-	  /* Integer sub-types never overflow as they are never
-	     operands of arithmetic operators.  */
-	  && !(TREE_TYPE (type) && TREE_TYPE (type) != type));
+  return INTEGRAL_TYPE_P (type) && !TYPE_OVERFLOW_WRAPS (type);
 }
 
 /* Return whether TYPE can support our overflow infinity
@@ -2702,13 +2690,6 @@ extract_range_from_unary_expr (value_ran
       tree inner_type = TREE_TYPE (op0);
       tree outer_type = type;
 
-      /* Always use base-types here.  This is important for the
-	 correct signedness.  */
-      if (TREE_TYPE (inner_type))
-	inner_type = TREE_TYPE (inner_type);
-      if (TREE_TYPE (outer_type))
-	outer_type = TREE_TYPE (outer_type);
-
       /* If VR0 is varying and we increase the type precision, assume
 	 a full range for the following transformation.  */
       if (vr0.type == VR_VARYING
Index: tree.c
===================================================================
--- tree.c	(revision 147337)
+++ tree.c	(working copy)
@@ -5715,6 +5715,57 @@ build_range_type (tree type, tree lowval
     return itype;
 }
 
+/* Return true if the debug information for TYPE, a subtype, should be emitted
+   as a subrange type.  If so, set LOWVAL to the low bound and HIGHVAL to the
+   high bound, respectively.  Sometimes doing so unnecessarily obfuscates the
+   debug info and doesn't reflect the source code.  */
+
+bool
+subrange_type_for_debug_p (const_tree type, tree *lowval, tree *highval)
+{
+  tree base_type = TREE_TYPE (type), low, high;
+
+  /* Subrange types have a base type which is an integral type.  */
+  if (!INTEGRAL_TYPE_P (base_type))
+    return false;
+
+  /* Get the real bounds of the subtype.  */
+  if (lang_hooks.types.get_subrange_bounds)
+    lang_hooks.types.get_subrange_bounds (type, &low, &high);
+  else
+    {
+      low = TYPE_MIN_VALUE (type);
+      high = TYPE_MAX_VALUE (type);
+    }
+
+  /* If the type and its base type have the same representation and the same
+     name, then the type is not a subrange but a copy of the base type.  */
+  if ((TREE_CODE (base_type) == INTEGER_TYPE
+       || TREE_CODE (base_type) == BOOLEAN_TYPE)
+      && int_size_in_bytes (type) == int_size_in_bytes (base_type)
+      && tree_int_cst_equal (low, TYPE_MIN_VALUE (base_type))
+      && tree_int_cst_equal (high, TYPE_MAX_VALUE (base_type)))
+    {
+      tree type_name = TYPE_NAME (type);
+      tree base_type_name = TYPE_NAME (base_type);
+
+      if (type_name && TREE_CODE (type_name) == TYPE_DECL)
+	type_name = DECL_NAME (type_name);
+
+      if (base_type_name && TREE_CODE (base_type_name) == TYPE_DECL)
+	base_type_name = DECL_NAME (base_type_name);
+
+      if (type_name == base_type_name)
+	return false;
+    }
+
+  if (lowval)
+    *lowval = low;
+  if (highval)
+    *highval = high;
+  return true;
+}
+
 /* Just like build_index_type, but takes lowval and highval instead
    of just highval (maxval).  */
 
Index: tree.h
===================================================================
--- tree.h	(revision 147337)
+++ tree.h	(working copy)
@@ -4860,6 +4860,7 @@ extern void build_common_tree_nodes_2 (i
 extern void build_common_builtin_nodes (void);
 extern tree build_nonstandard_integer_type (unsigned HOST_WIDE_INT, int);
 extern tree build_range_type (tree, tree, tree);
+extern bool subrange_type_for_debug_p (const_tree, tree *, tree *);
 extern HOST_WIDE_INT int_cst_value (const_tree);
 
 extern bool fields_compatible_p (const_tree, const_tree);
Index: fold-const.c
===================================================================
--- fold-const.c	(revision 147337)
+++ fold-const.c	(working copy)
@@ -3742,6 +3742,7 @@ fold_truth_not_expr (tree arg)
       return invert_truthvalue (TREE_OPERAND (arg, 0));
 
     case NOP_EXPR:
+    case CONVERT_EXPR:
       if (TREE_CODE (TREE_TYPE (arg)) == BOOLEAN_TYPE)
 	{
 	  t = build1 (TRUTH_NOT_EXPR, type, arg);
@@ -3750,7 +3751,6 @@ fold_truth_not_expr (tree arg)
 
       /* ... fall through ...  */
 
-    case CONVERT_EXPR:
     case FLOAT_EXPR:
       t = build1 (TREE_CODE (arg), type,
 		  invert_truthvalue (TREE_OPERAND (arg, 0)));
@@ -4694,7 +4694,6 @@ static tree
 build_range_check (tree type, tree exp, int in_p, tree low, tree high)
 {
   tree etype = TREE_TYPE (exp), value;
-  enum tree_code code;
 
 #ifdef HAVE_canonicalize_funcptr_for_compare
   /* Disable this optimization for function pointer expressions
@@ -4777,35 +4776,14 @@ build_range_check (tree type, tree exp, 
     }
 
   /* Optimize (c>=low) && (c<=high) into (c-low>=0) && (c-low<=high-low).
-     This requires wrap-around arithmetics for the type of the expression.  */
-  code = TREE_CODE (etype);
-  switch (code)
-    {
-    case INTEGER_TYPE:
-    case ENUMERAL_TYPE:
-    case BOOLEAN_TYPE:
-      /* There is no requirement that LOW be within the range of ETYPE
-	 if the latter is a subtype.  It must, however, be within the base
-	 type of ETYPE.  So be sure we do the subtraction in that type.  */
-      if (code == INTEGER_TYPE && TREE_TYPE (etype))
-	{
-	  etype = TREE_TYPE (etype);
-	  /* But not in an enumeral or boolean type though.  */
-	  code = TREE_CODE (etype);
-	}
+     This requires wrap-around arithmetics for the type of the expression.
+     First make sure that arithmetics in this type is valid, then make sure
+     that it wraps around.  */
+  if (TREE_CODE (etype) == ENUMERAL_TYPE || TREE_CODE (etype) == BOOLEAN_TYPE)
+    etype = lang_hooks.types.type_for_size (TYPE_PRECISION (etype),
+					    TYPE_UNSIGNED (etype));
 
-      if (code != INTEGER_TYPE)
-	etype = lang_hooks.types.type_for_size (TYPE_PRECISION (etype),
-						TYPE_UNSIGNED (etype));
-      break;
-
-    default:
-      break;
-    }
-
-  /* If we don't have wrap-around arithmetics upfront, try to force it.  */
-  if (TREE_CODE (etype) == INTEGER_TYPE
-      && !TYPE_OVERFLOW_WRAPS (etype))
+  if (TREE_CODE (etype) == INTEGER_TYPE && !TYPE_OVERFLOW_WRAPS (etype))
     {
       tree utype, minv, maxv;
 
@@ -7229,11 +7207,6 @@ fold_sign_changed_comparison (enum tree_
   if (TYPE_PRECISION (inner_type) != TYPE_PRECISION (outer_type))
     return NULL_TREE;
 
-  /* If the conversion is from an integral subtype to its basetype
-     leave it alone.  */
-  if (TREE_TYPE (inner_type) == outer_type)
-    return NULL_TREE;
-
   if (TREE_CODE (arg1) != INTEGER_CST
       && !(CONVERT_EXPR_P (arg1)
 	   && TREE_TYPE (TREE_OPERAND (arg1, 0)) == inner_type))
@@ -8291,9 +8264,7 @@ fold_unary (enum tree_code code, tree ty
 	 transformation effectively doesn't preserve non-maximal ranges.  */
       if (TREE_CODE (type) == INTEGER_TYPE
 	  && TREE_CODE (op0) == BIT_AND_EXPR
-	  && TREE_CODE (TREE_OPERAND (op0, 1)) == INTEGER_CST
-	  /* Not if the conversion is to the sub-type.  */
-	  && TREE_TYPE (type) != TREE_TYPE (op0))
+	  && TREE_CODE (TREE_OPERAND (op0, 1)) == INTEGER_CST)
 	{
 	  tree and = op0;
 	  tree and0 = TREE_OPERAND (and, 0), and1 = TREE_OPERAND (and, 1);
@@ -8410,11 +8381,7 @@ fold_unary (enum tree_code code, tree ty
 	   || POINTER_TYPE_P (type))
 	  && (INTEGRAL_TYPE_P (TREE_TYPE (op0))
 	      || POINTER_TYPE_P (TREE_TYPE (op0)))
-	  && TYPE_PRECISION (type) == TYPE_PRECISION (TREE_TYPE (op0))
-	  /* Do not muck with VIEW_CONVERT_EXPRs that convert from
-	     a sub-type to its base type as generated by the Ada FE.  */
-	  && !(INTEGRAL_TYPE_P (TREE_TYPE (op0))
-	       && TREE_TYPE (TREE_TYPE (op0))))
+	  && TYPE_PRECISION (type) == TYPE_PRECISION (TREE_TYPE (op0)))
 	return fold_convert (type, op0);
 
       /* Strip inner integral conversions that do not change the precision.  */
Index: tree-chrec.c
===================================================================
--- tree-chrec.c	(revision 147337)
+++ tree-chrec.c	(working copy)
@@ -1100,21 +1100,6 @@ nb_vars_in_chrec (tree chrec)
     }
 }
 
-/* Returns true if TYPE is a type in that we cannot directly perform
-   arithmetics, even though it is a scalar type.  */
-
-static bool
-avoid_arithmetics_in_type_p (const_tree type)
-{
-  /* Ada frontend uses subtypes -- an arithmetic cannot be directly performed
-     in the subtype, but a base type must be used, and the result then can
-     be casted to the subtype.  */
-  if (TREE_CODE (type) == INTEGER_TYPE && TREE_TYPE (type) != NULL_TREE)
-    return true;
-
-  return false;
-}
-
 static tree chrec_convert_1 (tree, tree, gimple, bool);
 
 /* Converts BASE and STEP of affine scev to TYPE.  LOOP is the loop whose iv
@@ -1136,10 +1121,6 @@ convert_affine_scev (struct loop *loop, 
   tree new_base, new_step;
   tree step_type = POINTER_TYPE_P (type) ? sizetype : type;
 
-  /* If we cannot perform arithmetic in TYPE, avoid creating an scev.  */
-  if (avoid_arithmetics_in_type_p (type))
-    return false;
-
   /* In general,
      (TYPE) (BASE + STEP * i) = (TYPE) BASE + (TYPE -- sign extend) STEP * i,
      but we must check some assumptions.
@@ -1342,10 +1323,6 @@ chrec_convert_aggressive (tree type, tre
   if (TYPE_PRECISION (type) > TYPE_PRECISION (inner_type))
     return NULL_TREE;
 
-  /* If we cannot perform arithmetic in TYPE, avoid creating an scev.  */
-  if (avoid_arithmetics_in_type_p (type))
-    return NULL_TREE;
-
   rtype = POINTER_TYPE_P (type) ? sizetype : type;
 
   left = CHREC_LEFT (chrec);
Index: dbxout.c
===================================================================
--- dbxout.c	(revision 147337)
+++ dbxout.c	(working copy)
@@ -1676,6 +1676,13 @@ dbxout_type (tree type, int full)
       vector_type = true;
     }
 
+  /* If this is a subtype that should not be emitted as a subrange type,
+     use the base type.  */
+  if (TREE_CODE (type) == INTEGER_TYPE
+      && TREE_TYPE (type) != NULL_TREE
+      && !subrange_type_for_debug_p (type, NULL, NULL))
+    type = TREE_TYPE (type);
+
   /* If there was an input error and we don't really have a type,
      avoid crashing and write something that is at least valid
      by assuming `int'.  */
Index: dwarf2out.c
===================================================================
--- dwarf2out.c	(revision 147337)
+++ dwarf2out.c	(working copy)
@@ -5095,8 +5095,7 @@ static void output_line_info (void);
 static void output_file_names (void);
 static dw_die_ref base_type_die (tree);
 static int is_base_type (tree);
-static bool is_subrange_type (const_tree);
-static dw_die_ref subrange_type_die (tree, dw_die_ref);
+static dw_die_ref subrange_type_die (tree, tree, tree, dw_die_ref);
 static dw_die_ref modified_type_die (tree, int, int, dw_die_ref);
 static int type_is_enum (const_tree);
 static unsigned int dbx_reg_number (const_rtx);
@@ -9273,6 +9272,11 @@ base_type_die (tree type)
   if (TREE_CODE (type) == ERROR_MARK || TREE_CODE (type) == VOID_TYPE)
     return 0;
 
+  /* If this is a subtype that should not be emitted as a subrange type,
+     use the base type.  See subrange_type_for_debug_p.  */
+  if (TREE_CODE (type) == INTEGER_TYPE && TREE_TYPE (type) != NULL_TREE)
+    type = TREE_TYPE (type);
+
   switch (TREE_CODE (type))
     {
     case INTEGER_TYPE:
@@ -9392,67 +9396,11 @@ simple_type_size_in_bits (const_tree typ
     return TYPE_ALIGN (type);
 }
 
-/* Return true if the debug information for the given type should be
-   emitted as a subrange type.  */
-
-static inline bool
-is_subrange_type (const_tree type)
-{
-  tree subtype = TREE_TYPE (type);
-
-  /* Subrange types are identified by the fact that they are integer
-     types, and that they have a subtype which is either an integer type
-     or an enumeral type.  */
-
-  if (TREE_CODE (type) != INTEGER_TYPE
-      || subtype == NULL_TREE)
-    return false;
-
-  if (TREE_CODE (subtype) != INTEGER_TYPE
-      && TREE_CODE (subtype) != ENUMERAL_TYPE
-      && TREE_CODE (subtype) != BOOLEAN_TYPE)
-    return false;
-
-  if (TREE_CODE (type) == TREE_CODE (subtype)
-      && int_size_in_bytes (type) == int_size_in_bytes (subtype)
-      && TYPE_MIN_VALUE (type) != NULL
-      && TYPE_MIN_VALUE (subtype) != NULL
-      && tree_int_cst_equal (TYPE_MIN_VALUE (type), TYPE_MIN_VALUE (subtype))
-      && TYPE_MAX_VALUE (type) != NULL
-      && TYPE_MAX_VALUE (subtype) != NULL
-      && tree_int_cst_equal (TYPE_MAX_VALUE (type), TYPE_MAX_VALUE (subtype)))
-    {
-      /* The type and its subtype have the same representation.  If in
-	 addition the two types also have the same name, then the given
-	 type is not a subrange type, but rather a plain base type.  */
-      /* FIXME: brobecker/2004-03-22:
-	 Sizetype INTEGER_CSTs nodes are canonicalized.  It should
-	 therefore be sufficient to check the TYPE_SIZE node pointers
-	 rather than checking the actual size.  Unfortunately, we have
-	 found some cases, such as in the Ada "integer" type, where
-	 this is not the case.  Until this problem is solved, we need to
-	 keep checking the actual size.  */
-      tree type_name = TYPE_NAME (type);
-      tree subtype_name = TYPE_NAME (subtype);
-
-      if (type_name != NULL && TREE_CODE (type_name) == TYPE_DECL)
-	type_name = DECL_NAME (type_name);
-
-      if (subtype_name != NULL && TREE_CODE (subtype_name) == TYPE_DECL)
-	subtype_name = DECL_NAME (subtype_name);
-
-      if (type_name == subtype_name)
-	return false;
-    }
-
-  return true;
-}
-
 /*  Given a pointer to a tree node for a subrange type, return a pointer
     to a DIE that describes the given type.  */
 
 static dw_die_ref
-subrange_type_die (tree type, dw_die_ref context_die)
+subrange_type_die (tree type, tree low, tree high, dw_die_ref context_die)
 {
   dw_die_ref subrange_die;
   const HOST_WIDE_INT size_in_bytes = int_size_in_bytes (type);
@@ -9469,12 +9417,10 @@ subrange_type_die (tree type, dw_die_ref
       add_AT_unsigned (subrange_die, DW_AT_byte_size, size_in_bytes);
     }
 
-  if (TYPE_MIN_VALUE (type) != NULL)
-    add_bound_info (subrange_die, DW_AT_lower_bound,
-		    TYPE_MIN_VALUE (type));
-  if (TYPE_MAX_VALUE (type) != NULL)
-    add_bound_info (subrange_die, DW_AT_upper_bound,
-		    TYPE_MAX_VALUE (type));
+  if (low)
+    add_bound_info (subrange_die, DW_AT_lower_bound, low);
+  if (high)
+    add_bound_info (subrange_die, DW_AT_upper_bound, high);
 
   return subrange_die;
 }
@@ -9491,7 +9437,7 @@ modified_type_die (tree type, int is_con
   dw_die_ref sub_die = NULL;
   tree item_type = NULL;
   tree qualified_type;
-  tree name;
+  tree name, low, high;
 
   if (code == ERROR_MARK)
     return NULL;
@@ -9561,9 +9507,11 @@ modified_type_die (tree type, int is_con
 		       simple_type_size_in_bits (type) / BITS_PER_UNIT);
       item_type = TREE_TYPE (type);
     }
-  else if (is_subrange_type (type))
+  else if (code == INTEGER_TYPE
+	   && TREE_TYPE (type) != NULL_TREE
+	   && subrange_type_for_debug_p (type, &low, &high))
     {
-      mod_type_die = subrange_type_die (type, context_die);
+      mod_type_die = subrange_type_die (type, low, high, context_die);
       item_type = TREE_TYPE (type);
     }
   else if (is_base_type (type))
Index: langhooks.h
===================================================================
--- langhooks.h	(revision 147337)
+++ langhooks.h	(working copy)
@@ -130,6 +130,9 @@ struct lang_hooks_for_types
      for the debugger about the array bounds, strides, etc.  */
   bool (*get_array_descr_info) (const_tree, struct array_descr_info *);
 
+  /* Fill in information for the debugger about the bounds of TYPE.  */
+  void (*get_subrange_bounds) (const_tree, tree *, tree *);
+
   /* If we requested a pointer to a vector, build up the pointers that
      we stripped off while looking for the inner type.  Similarly for
      return values from functions.  The argument TYPE is the top of the
Index: tree-ssa.c
===================================================================
--- tree-ssa.c	(revision 147337)
+++ tree-ssa.c	(working copy)
@@ -923,19 +923,9 @@ useless_type_conversion_p_1 (tree outer_
 	  || TYPE_PRECISION (inner_type) != TYPE_PRECISION (outer_type))
 	return false;
 
-      /* Conversions from a non-base to a base type are not useless.
-	 This way we preserve the invariant to do arithmetic in
-	 base types only.  */
-      if (TREE_TYPE (inner_type)
-	  && TREE_TYPE (inner_type) != inner_type
-	  && (TREE_TYPE (outer_type) == outer_type
-	      || TREE_TYPE (outer_type) == NULL_TREE))
-	return false;
-
       /* We don't need to preserve changes in the types minimum or
 	 maximum value in general as these do not generate code
 	 unless the types precisions are different.  */
-
       return true;
     }
 
Index: langhooks-def.h
===================================================================
--- langhooks-def.h	(revision 147337)
+++ langhooks-def.h	(working copy)
@@ -161,6 +161,7 @@ extern tree lhd_make_node (enum tree_cod
   lhd_omp_firstprivatize_type_sizes
 #define LANG_HOOKS_TYPE_HASH_EQ		NULL
 #define LANG_HOOKS_GET_ARRAY_DESCR_INFO	NULL
+#define LANG_HOOKS_GET_SUBRANGE_BOUNDS	NULL
 #define LANG_HOOKS_RECONSTRUCT_COMPLEX_TYPE reconstruct_complex_type
 #define LANG_HOOKS_HASH_TYPES		true
 
@@ -177,6 +178,7 @@ extern tree lhd_make_node (enum tree_cod
   LANG_HOOKS_OMP_FIRSTPRIVATIZE_TYPE_SIZES, \
   LANG_HOOKS_TYPE_HASH_EQ, \
   LANG_HOOKS_GET_ARRAY_DESCR_INFO, \
+  LANG_HOOKS_GET_SUBRANGE_BOUNDS, \
   LANG_HOOKS_RECONSTRUCT_COMPLEX_TYPE, \
   LANG_HOOKS_HASH_TYPES \
 }

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