Hi!

As can be seen on the following testcase, when expanding an extension
in EXPAND_INITIALIZER context, we emit wrong extension operation
(one depending on the signedness of the result type rather than
on the signedness of the argument type, so e.g. extension of
unsigned int to long long int is done using SIGN_EXTEND instead of
ZERO_EXTEND, and extension of int to unsigned long long int using
ZERO_EXTEND instead of SIGN_EXTEND.

Fixed thusly, bootstrapped/regtested on x86_64-linux and i686-linux,
ok for trunk?

2017-03-24  Jakub Jelinek  <ja...@redhat.com>

        PR c/80163
        * expr.c <CASE_CONVERT>: For EXPAND_INITIALIZER determine SIGN_EXTEND
        vs. ZERO_EXTEND based on signedness of treeop0's type rather than
        signedness of the result type.

        * gcc.dg/torture/pr80163.c: New test.

--- gcc/expr.c.jj       2017-03-07 09:04:04.000000000 +0100
+++ gcc/expr.c  2017-03-24 12:09:57.729854079 +0100
@@ -8333,7 +8333,8 @@ expand_expr_real_2 (sepops ops, rtx targ
        }
 
       else if (modifier == EXPAND_INITIALIZER)
-       op0 = gen_rtx_fmt_e (unsignedp ? ZERO_EXTEND : SIGN_EXTEND, mode, op0);
+       op0 = gen_rtx_fmt_e (TYPE_UNSIGNED (TREE_TYPE (treeop0))
+                            ? ZERO_EXTEND : SIGN_EXTEND, mode, op0);
 
       else if (target == 0)
        op0 = convert_to_mode (mode, op0,
--- gcc/testsuite/gcc.dg/torture/pr80163.c.jj   2017-03-24 12:19:21.363603066 
+0100
+++ gcc/testsuite/gcc.dg/torture/pr80163.c      2017-03-24 12:19:09.000000000 
+0100
@@ -0,0 +1,35 @@
+/* PR c/80163 */
+/* { dg-do compile { target int128 } } */
+
+volatile int v;
+
+__attribute__((noinline, noclone)) void
+bar (void)
+{
+  v++;
+  asm volatile ("" : : : "memory");
+}
+
+__attribute__((noinline, noclone)) __int128_t *
+foo (unsigned long **p)
+{
+a:
+  bar ();
+b:
+  bar ();
+  static __int128_t d = (unsigned long) &&a - (unsigned long) &&b;
+  static unsigned long e = (unsigned long) &&a - (unsigned long) &&b;
+  *p = &e;
+  return &d;
+}
+
+int
+main ()
+{
+  __int128_t *p;
+  unsigned long *q;
+  p = foo (&q);
+  if (*p != *q)
+    __builtin_abort ();
+  return 0;
+}

        Jakub

Reply via email to