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