Hi! The following testcase is miscompiled on i686-linux, because make_extraction is asked to make an extraction of 33 bits from DImode MEM at position 0 and happily returns ZERO_EXTRACT with SImode (even when SImode can hold only 32 bits), the caller (make_field_assignment) then on this testcase because of that throws away the |= 0x100000000ULL.
Fixed thusly, bootstrapped/regtested on {x86_64,i686,powerpc64{,le}}-linux, preapproved by Segher on IRC, committed to trunk and 8.x branch. I've also gathered statistics and the only time during those bootstraps and (except for still pending (second) powerpc64-linux regtest) regtests the only time this patch made any difference was on this newly added testcase on i686-linux. 2019-02-14 Jakub Jelinek <ja...@redhat.com> PR rtl-optimization/89354 * combine.c (make_extraction): Punt if extraction_mode is narrower than len bits. * gcc.dg/pr89354.c: New test. --- gcc/combine.c.jj 2019-02-05 16:38:28.000000000 +0100 +++ gcc/combine.c 2019-02-14 16:45:41.445096523 +0100 @@ -7830,6 +7830,10 @@ make_extraction (machine_mode mode, rtx && partial_subreg_p (extraction_mode, mode)) extraction_mode = mode; + /* Punt if len is too large for extraction_mode. */ + if (maybe_gt (len, GET_MODE_PRECISION (extraction_mode))) + return NULL_RTX; + if (!MEM_P (inner)) wanted_inner_mode = wanted_inner_reg_mode; else --- gcc/testsuite/gcc.dg/pr89354.c.jj 2019-02-14 17:02:26.013552853 +0100 +++ gcc/testsuite/gcc.dg/pr89354.c 2019-02-14 17:01:44.431237813 +0100 @@ -0,0 +1,22 @@ +/* PR rtl-optimization/89354 */ +/* { dg-do run } */ +/* { dg-options "-O2" } */ +/* { dg-additional-options "-msse2" { target sse2_runtime } } */ + +static unsigned long long q = 0; + +__attribute__((noipa)) static void +foo (void) +{ + q = (q & ~0x1ffffffffULL) | 0x100000000ULL; +} + +int +main () +{ + __asm volatile ("" : "+m" (q)); + foo (); + if (q != 0x100000000ULL) + __builtin_abort (); + return 0; +} Jakub