Patchwork RFC: PR rtl-optimization/44695: [4.6 Regression] ice in simplify_subreg, at simplify-rtx.c:5117

login
register
mail settings
Submitter H.J. Lu
Date June 29, 2010, 7:12 p.m.
Message ID <20100629191246.GA2770@intel.com>
Download mbox | patch
Permalink /patch/57300/
State New
Headers show

Comments

H.J. Lu - June 29, 2010, 7:12 p.m.
After revision 161329, x86 backend may generate:

(ior:HI (ashift:HI (zero_extend:HI (umod:QI (reg:HI 68)
                (reg:QI 61 [ D.2750 ])))
        (const_int 8 [0x8]))
    (zero_extend:HI (udiv:QI (reg:HI 68)
            (reg:QI 61 [ D.2750 ]))))

combine calls simplify_subreg and leads to

#2  0x00000000009ad621 in simplify_subreg (outermode=HImode, 
    op=0x7ffff7facd40, innermode=QImode, byte=0)
    at /space/rguenther/src/svn/trunk/gcc/simplify-rtx.c:5116
5116      gcc_assert (GET_MODE (op) == innermode
5117                  || GET_MODE (op) == VOIDmode);
(gdb) call debug_rtx (op)
(reg:HI 68)

This patch adds simplify_gen_subreg_for_combine to deal with invalid
combination of outermode, op and innermode generated by combine.  Any
comments?

Thanks.


H.J.
---
gcc/

2010-06-29  H.J. Lu  <hongjiu.lu@intel.com>

	PR rtl-optimization/44695
	* combine.c (simplify_gen_subreg_for_combine): New.
	(if_then_else_cond): Replace simplify_gen_subreg with
	simplify_gen_subreg_for_combine.

gcc/testsuite/

2010-06-29  H.J. Lu  <hongjiu.lu@intel.com>

	PR rtl-optimization/44695
	* gcc.dg/torture/pr44695.c: New.
Paolo Bonzini - June 30, 2010, 11:53 a.m.
On 06/29/2010 09:12 PM, H.J. Lu wrote:
> After revision 161329, x86 backend may generate:
>
> (ior:HI (ashift:HI (zero_extend:HI (umod:QI (reg:HI 68)
>                  (reg:QI 61 [ D.2750 ])))
>          (const_int 8 [0x8]))
>      (zero_extend:HI (udiv:QI (reg:HI 68)
>              (reg:QI 61 [ D.2750 ]))))
>
> combine calls simplify_subreg and leads to
>
> #2  0x00000000009ad621 in simplify_subreg (outermode=HImode,
>      op=0x7ffff7facd40, innermode=QImode, byte=0)
>      at /space/rguenther/src/svn/trunk/gcc/simplify-rtx.c:5116
> 5116      gcc_assert (GET_MODE (op) == innermode
> 5117                  || GET_MODE (op) == VOIDmode);
> (gdb) call debug_rtx (op)
> (reg:HI 68)
>
> This patch adds simplify_gen_subreg_for_combine to deal with invalid
> combination of outermode, op and innermode generated by combine.  Any
> comments?

I commented in the PR about the correct fix.  Sorry for not spotting it 
in the review (I had a doubt, but in the end I didn't look it up and 
left the final call to Uros...).

Paolo

Patch

diff --git a/gcc/combine.c b/gcc/combine.c
index d3305cb..0f1d315 100644
--- a/gcc/combine.c
+++ b/gcc/combine.c
@@ -423,6 +423,9 @@  static rtx simplify_shift_const_1 (enum rtx_code, enum machine_mode, rtx, int);
 static rtx simplify_shift_const (rtx, enum rtx_code, enum machine_mode, rtx,
 				 int);
 static int recog_for_combine (rtx *, rtx, rtx *);
+static rtx simplify_gen_subreg_for_combine (enum machine_mode, rtx,
+					    enum machine_mode,
+					    unsigned int);
 static rtx gen_lowpart_for_combine (enum machine_mode, rtx);
 static enum rtx_code simplify_comparison (enum rtx_code, rtx *, rtx *);
 static void update_table_tick (rtx);
@@ -7482,6 +7485,20 @@  canon_reg_for_combine (rtx x, rtx reg)
   return x;
 }
 
+/* Like simplify_gen_subreg but for use by combine.  Return NULL_RTX
+   if it is called with invalid combination of OUTERMODE, OP and
+   INNERMODE.  */
+
+static rtx
+simplify_gen_subreg_for_combine (enum machine_mode outermode, rtx op,
+				 enum machine_mode innermode,
+				 unsigned int byte)
+{
+  if (GET_MODE (op) != innermode && GET_MODE (op) != VOIDmode)
+    return NULL_RTX;
+  return simplify_gen_subreg (outermode, op, innermode, byte);
+}
+
 /* Return X converted to MODE.  If the value is already truncated to
    MODE we can just return a subreg even though in the general case we
    would need an explicit truncation.  */
@@ -8222,10 +8239,12 @@  if_then_else_cond (rtx x, rtx *ptrue, rtx *pfalse)
 	   && 0 != (cond0 = if_then_else_cond (SUBREG_REG (x),
 					       &true0, &false0)))
     {
-      true0 = simplify_gen_subreg (mode, true0,
-				   GET_MODE (SUBREG_REG (x)), SUBREG_BYTE (x));
-      false0 = simplify_gen_subreg (mode, false0,
-				    GET_MODE (SUBREG_REG (x)), SUBREG_BYTE (x));
+      true0 = simplify_gen_subreg_for_combine (mode, true0,
+					       GET_MODE (SUBREG_REG (x)),
+					       SUBREG_BYTE (x));
+      false0 = simplify_gen_subreg_for_combine (mode, false0,
+						GET_MODE (SUBREG_REG (x)),
+						SUBREG_BYTE (x));
       if (true0 && false0)
 	{
 	  *ptrue = true0;
--- /dev/null	2010-06-16 10:11:06.602750711 -0700
+++ gcc/gcc/testsuite/gcc.dg/torture/pr44695.c	2010-06-29 11:49:12.186942482 -0700
@@ -0,0 +1,15 @@ 
+/* { dg-do compile } */
+
+typedef unsigned char uint8_t;
+
+static uint8_t
+safe_div_func_uint8_t_u_u (uint8_t ui1, uint8_t ui2)
+{
+  return ui2 ? ui2 : (ui1 / ui2);
+}
+
+int
+int81 (int x)
+{
+  return safe_div_func_uint8_t_u_u (1, 8 & x);
+}