Patchwork Fix ICE on VCE expansion (PR rtl-optimization/45728)

login
register
mail settings
Submitter Jakub Jelinek
Date Sept. 20, 2010, 10:36 a.m.
Message ID <20100920103652.GK1269@tyan-ft48-01.lab.bos.redhat.com>
Download mbox | patch
Permalink /patch/65197/
State New
Headers show

Comments

Jakub Jelinek - Sept. 20, 2010, 10:36 a.m.
Hi!

On this testcase, the operand of VCE is expanded as symbol_ref:DI,
and mode is DFmode.  Neither of them is BLKmode and they are even the same
size, so expand_expr_real_1 uses gen_lowpart on them.
Unfortunately, gen_lowpart_general doesn't handle all possible cases, in
particular it calls gen_lowpart_common to attempt to handle a bunch of
common cases, and if that fails, assumes that the operand is REG/MEM/SUBREG,
but nothing else.
The following patch fixes it by forcing it to REG if gen_lowpart wouldn't
be able to handle it.  As gen_lowpart_common can handle a bunch of cases
even when op0 isn't REG/SUBREG/MEM (e.g. ZERO_EXTEND/SIGN_EXTEND/CONCAT and
various constants, but not all of cases for them), calling force_reg
immediately could pessimize the code.

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

2010-09-20  Jakub Jelinek  <jakub@redhat.com>

	PR rtl-optimization/45728
	* expr.c (expand_expr_real_1): If op0 isn't REG or MEM, try
	gen_lowpart_common first and if that fails, force_reg first
	before calling gen_lowpart.

	* gcc.c-torture/compile/pr45728.c: New test.


	Jakub
Richard Henderson - Sept. 20, 2010, 7:18 p.m.
On 09/20/2010 03:36 AM, Jakub Jelinek wrote:
> 	PR rtl-optimization/45728
> 	* expr.c (expand_expr_real_1): If op0 isn't REG or MEM, try
> 	gen_lowpart_common first and if that fails, force_reg first
> 	before calling gen_lowpart.

ok.


r~

Patch

--- gcc/expr.c.jj	2010-09-17 14:11:11.000000000 +0200
+++ gcc/expr.c	2010-09-20 09:12:38.000000000 +0200
@@ -9381,7 +9381,15 @@  expand_expr_real_1 (tree exp, rtx target
 	{
 	  if (GET_CODE (op0) == SUBREG)
 	    op0 = force_reg (GET_MODE (op0), op0);
-	  op0 = gen_lowpart (mode, op0);
+	  temp = gen_lowpart_common (mode, op0);
+	  if (temp)
+	    op0 = temp;
+	  else
+	    {
+	      if (!REG_P (op0) && !MEM_P (op0))
+		op0 = force_reg (GET_MODE (op0), op0);
+	      op0 = gen_lowpart (mode, op0);
+	    }
 	}
       /* If both types are integral, convert from one mode to the other.  */
       else if (INTEGRAL_TYPE_P (type) && INTEGRAL_TYPE_P (TREE_TYPE (treeop0)))
--- gcc/testsuite/gcc.c-torture/compile/pr45728.c.jj	2010-09-20 09:20:38.000000000 +0200
+++ gcc/testsuite/gcc.c-torture/compile/pr45728.c	2010-09-20 09:20:09.000000000 +0200
@@ -0,0 +1,17 @@ 
+/* PR rtl-optimization/45728 */
+
+union U
+{
+  int *m;
+  double d;
+};
+
+int i;
+union U u;
+
+int
+foo (void)
+{
+  union U v = { &i };
+  return u.d == v.d;
+}