Hi!

The following testcase ICEs in cross to riscv64-linux.  The problem is
that we have a DImode integral constant (that doesn't fit into SImode),
which is pushed into a constant pool and later access just the first half of
it using a MEM.  When plus_constant is called on such a MEM, if the constant
has mode, we verify the mode, but if it doesn't, we don't and ICE later on
when we think the CONST_INT is a valid SImode constant.

Fixed thusly, tested with cross to riscv64-linux and bootstrapped/regtested
on x86_64-linux and i686-linux, ok for trunk?

2020-03-03  Jakub Jelinek  <ja...@redhat.com>

        PR rtl-optimization/94002
        * explow.c (plus_constant): Punt if cst has VOIDmode and
        get_pool_mode is different from mode.

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

--- gcc/explow.c.jj     2020-01-12 11:54:36.564411130 +0100
+++ gcc/explow.c        2020-03-02 22:09:19.544380020 +0100
@@ -128,6 +128,9 @@ plus_constant (machine_mode mode, rtx x,
              cst = gen_lowpart (mode, cst);
              gcc_assert (cst);
            }
+          else if (GET_MODE (cst) == VOIDmode
+                  && get_pool_mode (XEXP (x, 0)) != mode)
+           break;
          if (GET_MODE (cst) == VOIDmode || GET_MODE (cst) == mode)
            {
              tem = plus_constant (mode, cst, c);
--- gcc/testsuite/gcc.dg/pr94002.c.jj   2020-03-02 22:05:58.508338170 +0100
+++ gcc/testsuite/gcc.dg/pr94002.c      2020-03-02 22:05:32.864715503 +0100
@@ -0,0 +1,13 @@
+/* PR rtl-optimization/94002 */
+/* { dg-do compile } */
+/* { dg-options "-O1 -fno-tree-dce -fno-tree-reassoc" } */
+/* { dg-additional-options "-fPIC" { target fpic } } */
+
+unsigned a, b;
+
+void
+foo (void)
+{
+  __builtin_sub_overflow (b, 44852956282LL, &a);
+  a += ~b;
+}

        Jakub

Reply via email to