diff mbox

more partial int mode precision patches

Message ID 201404142309.s3EN9tbZ010076@greed.delorie.com
State New
Headers show

Commit Message

DJ Delorie April 14, 2014, 11:09 p.m. UTC
More cases where a mode's precision should be used instead of its
storage size.  Ok?

gcc/
	* expmed.c (init_expmed_one_conv): Assume partial integers have a
	known precision, but still compensate for those that are
	whole-int-sized.
	* expr.c (convert_move): Allow for the case where the target has
	an explicit converter between the two given modes, before checking
	for the "expected" converters.
	* loop-iv.c (iv_number_of_iterations): Use the mode's precision,
	not bitsize.
	* optabs.c (expand_float): Check mode precisions, not storage
	sizes.
	* simplify-rtx.c (simplify_unary_operation_1): Check mode
	precisions, not storage sizes.
diff mbox

Patch

Index: optabs.c
===================================================================
--- optabs.c	(revision 209391)
+++ optabs.c	(working copy)
@@ -5162,13 +5162,13 @@  expand_float (rtx to, rtx from, int unsi
     {
       rtx libfunc;
       rtx insns;
       rtx value;
       convert_optab tab = unsignedp ? ufloat_optab : sfloat_optab;
 
-      if (GET_MODE_SIZE (GET_MODE (from)) < GET_MODE_SIZE (SImode))
+      if (GET_MODE_PRECISION (GET_MODE (from)) < GET_MODE_PRECISION (SImode))
 	from = convert_to_mode (SImode, from, unsignedp);
 
       libfunc = convert_optab_libfunc (tab, GET_MODE (to), GET_MODE (from));
       gcc_assert (libfunc);
 
       start_sequence ();
Index: expr.c
===================================================================
--- expr.c	(revision 209391)
+++ expr.c	(working copy)
@@ -420,12 +420,32 @@  convert_move (rtx to, rtx from, int unsi
 								       from)
 			  : gen_rtx_FLOAT_EXTEND (to_mode, from));
       return;
     }
 
   /* Handle pointer conversion.  */			/* SPEE 900220.  */
+  /* If the target has a converter from FROM_MODE to TO_MODE, use it.  */
+  {
+    convert_optab ctab;
+
+    if (GET_MODE_PRECISION (from_mode) > GET_MODE_PRECISION (to_mode))
+      ctab = trunc_optab;
+    else if (unsignedp)
+      ctab = zext_optab;
+    else
+      ctab = sext_optab;
+
+    if (convert_optab_handler (ctab, to_mode, from_mode)
+	!= CODE_FOR_nothing)
+      {
+	emit_unop_insn (convert_optab_handler (ctab, to_mode, from_mode),
+			to, from, UNKNOWN);
+	return;
+      }
+  }
+
   /* Targets are expected to provide conversion insns between PxImode and
      xImode for all MODE_PARTIAL_INT modes they use, but no others.  */
   if (GET_MODE_CLASS (to_mode) == MODE_PARTIAL_INT)
     {
       enum machine_mode full_mode
 	= smallest_mode_for_size (GET_MODE_BITSIZE (to_mode), MODE_INT);
Index: expmed.c
===================================================================
--- expmed.c	(revision 209391)
+++ expmed.c	(working copy)
@@ -103,19 +103,25 @@  static void
 init_expmed_one_conv (struct init_expmed_rtl *all, enum machine_mode to_mode,
 		      enum machine_mode from_mode, bool speed)
 {
   int to_size, from_size;
   rtx which;
 
-  /* We're given no information about the true size of a partial integer,
-     only the size of the "full" integer it requires for storage.  For
-     comparison purposes here, reduce the bit size by one in that case.  */
-  to_size = (GET_MODE_BITSIZE (to_mode)
-	     - (GET_MODE_CLASS (to_mode) == MODE_PARTIAL_INT));
-  from_size = (GET_MODE_BITSIZE (from_mode)
-	       - (GET_MODE_CLASS (from_mode) == MODE_PARTIAL_INT));
+  to_size = GET_MODE_PRECISION (to_mode);
+  from_size = GET_MODE_PRECISION (from_mode);
+
+  /* Most partial integers have a precision less than the "full"
+     integer it requires for storage.  In case one doesn't, for
+     comparison purposes here, reduce the bit size by one in that
+     case.  */
+  if (GET_MODE_CLASS (to_mode) == MODE_PARTIAL_INT
+      && exact_log2 (to_size) != -1)
+    to_mode --;
+  if (GET_MODE_CLASS (from_mode) == MODE_PARTIAL_INT
+      && exact_log2 (from_size) != -1)
+    from_mode --;
   
   /* Assume cost of zero-extend and sign-extend is the same.  */
   which = (to_size < from_size ? &all->trunc : &all->zext);
 
   PUT_MODE (&all->reg, from_mode);
   set_convert_cost (to_mode, from_mode, speed, set_src_cost (which, speed));
Index: simplify-rtx.c
===================================================================
--- simplify-rtx.c	(revision 209391)
+++ simplify-rtx.c	(working copy)
@@ -1344,14 +1344,14 @@  simplify_unary_operation_1 (enum rtx_cod
 	}
 
       /* (sign_extend:M (sign_extend:N <X>)) is (sign_extend:M <X>).
 	 (sign_extend:M (zero_extend:N <X>)) is (zero_extend:M <X>).  */
       if (GET_CODE (op) == SIGN_EXTEND || GET_CODE (op) == ZERO_EXTEND)
 	{
-	  gcc_assert (GET_MODE_BITSIZE (mode)
-		      > GET_MODE_BITSIZE (GET_MODE (op)));
+	  gcc_assert (GET_MODE_PRECISION (mode)
+		      > GET_MODE_PRECISION (GET_MODE (op)));
 	  return simplify_gen_unary (GET_CODE (op), mode, XEXP (op, 0),
 				     GET_MODE (XEXP (op, 0)));
 	}
 
       /* (sign_extend:M (ashiftrt:N (ashift <X> (const_int I)) (const_int I)))
 	 is (sign_extend:M (subreg:O <X>)) if there is mode with
Index: loop-iv.c
===================================================================
--- loop-iv.c	(revision 209391)
+++ loop-iv.c	(working copy)
@@ -2394,13 +2394,13 @@  iv_number_of_iterations (struct loop *lo
 
   if (!canonicalize_iv_subregs (&iv0, &iv1, cond, desc))
     goto fail;
 
   comp_mode = iv0.extend_mode;
   mode = iv0.mode;
-  size = GET_MODE_BITSIZE (mode);
+  size = GET_MODE_PRECISION (mode);
   get_mode_bounds (mode, (cond == LE || cond == LT), comp_mode, &mmin, &mmax);
   mode_mmin = lowpart_subreg (mode, mmin, comp_mode);
   mode_mmax = lowpart_subreg (mode, mmax, comp_mode);
 
   if (!CONST_INT_P (iv0.step) || !CONST_INT_P (iv1.step))
     goto fail;