Re: [PATCH] Make sure shift amount in RTL is not wider than shift mode (PR rtl-optimization/65321)

2015-03-09 Thread Jeff Law

On 03/09/15 15:23, Jakub Jelinek wrote:

Hi!

As mentioned in the PR, e.g. wide-int is very unhappy if the shift second
operand doesn't fit into the shift mode.
Generally, the backend shift patterns ensure that, but in debug insns
nothing enforces that.

This patch fixes that by making sure e.g. QImode shifts have always at
QImode shift amount, HImode shifts have QImode or HImode shift amount etc.

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

2015-03-09  Jakub Jelinek  

PR rtl-optimization/65321
* cfgexpand.c (expand_debug_expr): Ensure shift amount isn't wider
than shift mode.
* var-tracking.c (use_narrower_mode): Likewise.

* gcc.dg/pr65321.c: New test.

OK.

jeff



[PATCH] Make sure shift amount in RTL is not wider than shift mode (PR rtl-optimization/65321)

2015-03-09 Thread Jakub Jelinek
Hi!

As mentioned in the PR, e.g. wide-int is very unhappy if the shift second
operand doesn't fit into the shift mode.
Generally, the backend shift patterns ensure that, but in debug insns
nothing enforces that.

This patch fixes that by making sure e.g. QImode shifts have always at
QImode shift amount, HImode shifts have QImode or HImode shift amount etc.

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

2015-03-09  Jakub Jelinek  

PR rtl-optimization/65321
* cfgexpand.c (expand_debug_expr): Ensure shift amount isn't wider
than shift mode.
* var-tracking.c (use_narrower_mode): Likewise.

* gcc.dg/pr65321.c: New test.

--- gcc/cfgexpand.c.jj  2015-03-09 08:05:13.0 +0100
+++ gcc/cfgexpand.c 2015-03-09 09:15:38.139652882 +0100
@@ -3921,6 +3921,31 @@ expand_debug_expr (tree exp)
   op1 = expand_debug_expr (TREE_OPERAND (exp, 1));
   if (!op1)
return NULL_RTX;
+  switch (TREE_CODE (exp))
+   {
+   case LSHIFT_EXPR:
+   case RSHIFT_EXPR:
+   case LROTATE_EXPR:
+   case RROTATE_EXPR:
+   case WIDEN_LSHIFT_EXPR:
+ /* Ensure second operand isn't wider than the first one.  */
+ inner_mode = TYPE_MODE (TREE_TYPE (TREE_OPERAND (exp, 1)));
+ if (SCALAR_INT_MODE_P (inner_mode))
+   {
+ machine_mode opmode = mode;
+ if (VECTOR_MODE_P (mode))
+   opmode = GET_MODE_INNER (mode);
+ if (SCALAR_INT_MODE_P (opmode)
+ && (GET_MODE_PRECISION (opmode)
+ < GET_MODE_PRECISION (inner_mode)))
+   op1 = simplify_gen_subreg (opmode, op1, inner_mode,
+  subreg_lowpart_offset (opmode,
+ inner_mode));
+   }
+ break;
+   default:
+ break;
+   }
   /* Fall through.  */
 
 unary:
--- gcc/var-tracking.c.jj   2015-01-15 20:25:40.0 +0100
+++ gcc/var-tracking.c  2015-03-09 09:07:00.042127704 +0100
@@ -1011,7 +1011,13 @@ use_narrower_mode (rtx x, machine_mode m
   return simplify_gen_binary (GET_CODE (x), mode, op0, op1);
 case ASHIFT:
   op0 = use_narrower_mode (XEXP (x, 0), mode, wmode);
-  return simplify_gen_binary (ASHIFT, mode, op0, XEXP (x, 1));
+  op1 = XEXP (x, 1);
+  /* Ensure shift amount is not wider than mode.  */
+  if (GET_MODE (op1) == VOIDmode)
+   op1 = lowpart_subreg (mode, op1, wmode);
+  else if (GET_MODE_PRECISION (mode) < GET_MODE_PRECISION (GET_MODE (op1)))
+   op1 = lowpart_subreg (mode, op1, GET_MODE (op1));
+  return simplify_gen_binary (ASHIFT, mode, op0, op1);
 default:
   gcc_unreachable ();
 }
--- gcc/testsuite/gcc.dg/pr65321.c.jj   2015-03-09 09:10:32.110658776 +0100
+++ gcc/testsuite/gcc.dg/pr65321.c  2015-03-09 09:10:19.0 +0100
@@ -0,0 +1,31 @@
+/* PR rtl-optimization/65321 */
+/* { dg-do compile } */
+/* { dg-options "-O3 -g" } */
+
+int a, b, c, d, e;
+
+int
+foo (void)
+{
+  int h;
+  char i;
+  for (; c > 0;)
+{
+  for (d = 0; d < 2; d++)
+   {
+ i = 1 << d;
+ if (i - a)
+   {
+ e = b = 0;
+ for (; c; c--)
+   d = 127;
+   }
+   }
+  h = ~d;
+  if (h > c)
+   for (;;)
+ ;
+  return 0;
+}
+  return 0;
+}

Jakub