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.
2012-09-18 Eric Botcazou <ebotca...@adacore.com>
PR middle-end/54617
* expr.c (store_field): Handle a PARALLEL in more cases.
--
Eric Botcazou
Index: expr.c
===================================================================
--- expr.c (revision 191365)
+++ expr.c (working copy)
@@ -6452,16 +6452,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;
}