[PATCH] Fixup fortran type_for_size langhook

Jakub Jelinek jakub@redhat.com
Fri Sep 23 16:27:00 GMT 2011


Hi!

I've noticed with the
2009-05-29  Eric Botcazou  <ebotcazou@adacore.com>
        
        * tree-ssa-loop-ivopts.c (strip_offset_1) <MULT_EXPR>: New case.
        (force_expr_to_var_cost) <NEGATE_EXPR>: Likewise.
        (ptr_difference_cost): Use affine combinations to compute it.
        (difference_cost): Likewise.
        (get_computation_cost_at): Compute more accurate cost for addresses
        if the ratio is a multiplier allowed in addresses.
        For non-addresses, consider that an additional offset or symbol is
        added only once.
patch backported to 4.4-RH branch an ICE on PowerPC, where difference_cost
calls signed_type_for, which for a BOOLEAN_TYPE returns NULL, but
difference_cost isn't prepared for it.  Can't reproduce it on 4.6 nor trunk,
but most probably just because some other optimizations made the problem
latent.  Looking at signed_type_for and the type_for_size langhook it uses
(yeah, I know, it isn't very much desirable to use langhooks in the
middle-end), the langhook is documented to return a signed resp. unsigned
type that can hold AT LEAST the requested bits and most frontends implement
it that way, with the exception of Fortran and Go.  And it seems lots of
places all around the middle-end assume that for not excessively large types
signed_type_for/unsigned_type_for will always succeed.
This patch fixes up the Fortran FE, so that even if there is no exact match
with a TYPE_PRECISION, if there is a wider type, the smallest of them will
be used.  The type_for_mode langhook on the other side must return a type
with the requested mode exactly, so if it uses gfc_type_for_size which now
can return wider type, it needs to check whether the returned type's
TYPE_MODE is the requested one.

Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?

2011-09-23  Jakub Jelinek  <jakub@redhat.com>

	* trans-types.c (gfc_type_for_size): Return wider type
	if no suitable narrower type has been found.
	(gfc_type_for_mode): Return NULL_TREE if gfc_type_for_size
	returned type doesn't have expected TYPE_MODE.

--- gcc/fortran/trans-types.c.jj	2011-09-05 12:28:53.000000000 +0200
+++ gcc/fortran/trans-types.c	2011-09-23 11:34:44.000000000 +0200
@@ -2791,18 +2791,29 @@ gfc_type_for_size (unsigned bits, int un
       if (bits == TYPE_PRECISION (intTI_type_node))
 	return intTI_type_node;
 #endif
+
+      if (bits <= TYPE_PRECISION (intQI_type_node))
+	return intQI_type_node;
+      if (bits <= TYPE_PRECISION (intHI_type_node))
+	return intHI_type_node;
+      if (bits <= TYPE_PRECISION (intSI_type_node))
+	return intSI_type_node;
+      if (bits <= TYPE_PRECISION (intDI_type_node))
+	return intDI_type_node;
+      if (bits <= TYPE_PRECISION (intTI_type_node))
+	return intTI_type_node;
     }
   else
     {
-      if (bits == TYPE_PRECISION (unsigned_intQI_type_node))
+      if (bits <= TYPE_PRECISION (unsigned_intQI_type_node))
         return unsigned_intQI_type_node;
-      if (bits == TYPE_PRECISION (unsigned_intHI_type_node))
+      if (bits <= TYPE_PRECISION (unsigned_intHI_type_node))
 	return unsigned_intHI_type_node;
-      if (bits == TYPE_PRECISION (unsigned_intSI_type_node))
+      if (bits <= TYPE_PRECISION (unsigned_intSI_type_node))
 	return unsigned_intSI_type_node;
-      if (bits == TYPE_PRECISION (unsigned_intDI_type_node))
+      if (bits <= TYPE_PRECISION (unsigned_intDI_type_node))
 	return unsigned_intDI_type_node;
-      if (bits == TYPE_PRECISION (unsigned_intTI_type_node))
+      if (bits <= TYPE_PRECISION (unsigned_intTI_type_node))
 	return unsigned_intTI_type_node;
     }
 
@@ -2823,7 +2834,10 @@ gfc_type_for_mode (enum machine_mode mod
   else if (GET_MODE_CLASS (mode) == MODE_COMPLEX_FLOAT)
     base = gfc_complex_types;
   else if (SCALAR_INT_MODE_P (mode))
-    return gfc_type_for_size (GET_MODE_PRECISION (mode), unsignedp);
+    {
+      tree type = gfc_type_for_size (GET_MODE_PRECISION (mode), unsignedp);
+      return type != NULL_TREE && mode == TYPE_MODE (type) ? type : NULL_TREE;
+    }
   else if (VECTOR_MODE_P (mode))
     {
       enum machine_mode inner_mode = GET_MODE_INNER (mode);

	Jakub



More information about the Gcc-patches mailing list