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] Fix up WIDEN_MULT_EXPR (PR middle-end/57251)


Hi!

On the following testcase, the widen multiplies etc. is introduced so late
that no forwprop or ccp follows it.  The WIDEN_MULT_EXPR tries hard not to
use widening multiply if both arguments are INTEGER_CSTs, but if they
are e.g. SSA_NAMEs that expand_normal into CONST_INT, we can still ICE.

The following patch attempts to handle those cases.  Bootstrapped/regtested
on x86_64-linux and i686-linux, ok for trunk/4.8?

2013-05-13  Jakub Jelinek  <jakub@redhat.com>

	PR middle-end/57251
	* expr.c (expand_expr_real_2) <case WIDEN_MULT_EXPR>: Handle
	the case when both op0 and op1 have VOIDmode.

	* gcc.dg/torture/pr57251.c: New test.

--- gcc/expr.c.jj	2013-05-07 10:27:07.000000000 +0200
+++ gcc/expr.c	2013-05-13 12:01:49.339087536 +0200
@@ -8390,6 +8390,15 @@ expand_expr_real_2 (sepops ops, rtx targ
 	      else
 		expand_operands (treeop0, treeop1, NULL_RTX, &op1, &op0,
 				 EXPAND_NORMAL);
+	      /* op0 and op1 might still be constant, despite the above
+		 != INTEGER_CST check.  Handle it.  */
+	      if (GET_MODE (op0) == VOIDmode && GET_MODE (op1) == VOIDmode)
+		{
+		  op0 = convert_modes (innermode, mode, op0, true);
+		  op1 = convert_modes (innermode, mode, op1, false);
+		  return REDUCE_BIT_FIELD (expand_mult (mode, op0, op1,
+							target, unsignedp));
+		}
 	      goto binop3;
 	    }
 	}
@@ -8412,6 +8421,19 @@ expand_expr_real_2 (sepops ops, rtx targ
 		{
 		  expand_operands (treeop0, treeop1, NULL_RTX, &op0, &op1,
 				   EXPAND_NORMAL);
+		  /* op0 and op1 might still be constant, despite the above
+		     != INTEGER_CST check.  Handle it.  */
+		  if (GET_MODE (op0) == VOIDmode && GET_MODE (op1) == VOIDmode)
+		    {
+		     widen_mult_const:
+		      op0 = convert_modes (innermode, mode, op0, zextend_p);
+		      op1
+			= convert_modes (innermode, mode, op1,
+					 TYPE_UNSIGNED (TREE_TYPE (treeop1)));
+		      return REDUCE_BIT_FIELD (expand_mult (mode, op0, op1,
+							    target,
+							    unsignedp));
+		    }
 		  temp = expand_widening_mult (mode, op0, op1, target,
 					       unsignedp, this_optab);
 		  return REDUCE_BIT_FIELD (temp);
@@ -8424,9 +8446,14 @@ expand_expr_real_2 (sepops ops, rtx targ
 		  op0 = expand_normal (treeop0);
 		  if (TREE_CODE (treeop1) == INTEGER_CST)
 		    op1 = convert_modes (innermode, mode,
-					 expand_normal (treeop1), unsignedp);
+					 expand_normal (treeop1),
+					 TYPE_UNSIGNED (TREE_TYPE (treeop1)));
 		  else
 		    op1 = expand_normal (treeop1);
+		  /* op0 and op1 might still be constant, despite the above
+		     != INTEGER_CST check.  Handle it.  */
+		  if (GET_MODE (op0) == VOIDmode && GET_MODE (op1) == VOIDmode)
+		    goto widen_mult_const;
 		  temp = expand_binop (mode, other_optab, op0, op1, target,
 				       unsignedp, OPTAB_LIB_WIDEN);
 		  hipart = gen_highpart (innermode, temp);
--- gcc/testsuite/gcc.dg/torture/pr57251.c.jj	2013-05-13 11:46:34.937151578 +0200
+++ gcc/testsuite/gcc.dg/torture/pr57251.c	2013-05-13 11:54:23.070414122 +0200
@@ -0,0 +1,12 @@
+/* PR middle-end/57251 */
+/* { dg-do compile } */
+/* { dg-options "-ftracer" } */
+
+short a, b;
+int
+f (void)
+{
+  long long i = 2;
+  a ? f () ? : 0 : b--;
+  b &= i *= a |= 0;
+}

	Jakub


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