@@ -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;
@@ -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);
+}
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.