[backport from gcc-4.8/trunk r191451, fixes regression from previous PR44194 patch ] From: Eric Botcazou Subject: Fix PR middle-end/54617 Date: Wed, 19 Sep 2012 00:38:15 +0200 List-Archive: In the recent patch for PR rtl-opt/44194 I left a case potentially ICEing because I managed to have it covered neither on x86-64 nor on SPARC 64-bit. This PR brings the missing coverage and it's from the gcc.c-torture/compile testsuite on PowerPC/Darwin 64-bit. Bootstrapped/regtested on x86-64/Linux, generated code manually inspected on PowerPC/Darwin 64-bit, applied on the mainline. gcc/ 2012-09-18 Eric Botcazou PR middle-end/54617 * expr.c (store_field): Handle a PARALLEL in more cases. --- gcc-4.7.2/gcc/expr.c.~1~ 2012-10-21 11:40:30.000000000 +0200 +++ gcc-4.7.2/gcc/expr.c 2012-10-21 11:40:44.000000000 +0200 @@ -6485,16 +6485,33 @@ store_field (rtx target, HOST_WIDE_INT b /* Handle calls that return values in multiple non-contiguous locations. The Irix 6 ABI has examples of this. */ - if (bitpos == 0 - && bitsize == GET_MODE_BITSIZE (mode) - && GET_CODE (temp) == PARALLEL) - emit_group_store (target, temp, TREE_TYPE (exp), - int_size_in_bytes (TREE_TYPE (exp))); - else - /* Store the value in the bitfield. */ - store_bit_field (target, bitsize, bitpos, - bitregion_start, bitregion_end, - mode, temp); + if (GET_CODE (temp) == PARALLEL) + { + rtx temp_target; + + /* We are not supposed to have a true bitfield in this case. */ + gcc_assert (bitsize == GET_MODE_BITSIZE (mode)); + + /* If we don't store at bit 0, we need an intermediate pseudo + since emit_group_store only stores at bit 0. */ + if (bitpos != 0) + temp_target = gen_reg_rtx (mode); + else + temp_target = target; + + emit_group_store (temp_target, temp, TREE_TYPE (exp), + int_size_in_bytes (TREE_TYPE (exp))); + + if (temp_target == target) + return const0_rtx; + + temp = temp_target; + } + + /* Store the value in the bitfield. */ + store_bit_field (target, bitsize, bitpos, + bitregion_start, bitregion_end, + mode, temp); return const0_rtx; }