Hi!

The following testcase ICEs on powerpc-linux, because we merge
SImode constants 0x7fffffff and 1 into 0x80000000, which is not valid SImode
CONST_INT - -0x80000000 is.  Fixed by calling trunc_int_for_mode, and to
avoid UB in the compiler do the addition in unsigned type.

Bootstrapped/regtested on x86_64-linux and i686-linux and tested on the
testcase with powerpc64-linux cross with -m32, ok for trunk?

2018-03-16  Jakub Jelinek  <ja...@redhat.com>

        PR target/84899
        * postreload.c (reload_combine_recognize_pattern): Perform
        INTVAL addition in unsigned HOST_WIDE_INT type to avoid UB and
        truncate_int_for_mode the result for the destination's mode.

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

--- gcc/postreload.c.jj 2018-01-03 10:19:55.572534024 +0100
+++ gcc/postreload.c    2018-03-16 18:19:17.819417570 +0100
@@ -1157,11 +1157,13 @@ reload_combine_recognize_pattern (rtx_in
             value in PREV, the constant loading instruction.  */
          validate_change (prev, &SET_DEST (prev_set), index_reg, 1);
          if (reg_state[regno].offset != const0_rtx)
-           validate_change (prev,
-                            &SET_SRC (prev_set),
-                            GEN_INT (INTVAL (SET_SRC (prev_set))
-                                     + INTVAL (reg_state[regno].offset)),
-                            1);
+           {
+             HOST_WIDE_INT c
+               = trunc_int_for_mode (UINTVAL (SET_SRC (prev_set))
+                                     + UINTVAL (reg_state[regno].offset),
+                                     GET_MODE (index_reg));
+             validate_change (prev, &SET_SRC (prev_set), GEN_INT (c), 1);
+           }
 
          /* Now for every use of REG that we have recorded, replace REG
             with REG_SUM.  */
--- gcc/testsuite/gcc.dg/pr84899.c.jj   2018-03-16 18:22:39.243512333 +0100
+++ gcc/testsuite/gcc.dg/pr84899.c      2018-03-16 18:22:22.353504390 +0100
@@ -0,0 +1,12 @@
+/* PR target/84899 */
+/* { dg-do compile } */
+/* { dg-options "-O -funroll-all-loops -fno-move-loop-invariants" } */
+
+void
+foo (int x)
+{
+  int a = 1 / x, b = 0;
+
+  while ((a + b + 1) < x)
+    b = __INT_MAX__;
+}

        Jakub

Reply via email to