aboutsummaryrefslogtreecommitdiff
path: root/gcc/expr.c
diff options
context:
space:
mode:
authorEric Botcazou <ebotcazou@adacore.com>2012-09-18 22:42:18 +0000
committerEric Botcazou <ebotcazou@gcc.gnu.org>2012-09-18 22:42:18 +0000
commit63d94e58b194a2f1a2022bfa03569ce51fd007f5 (patch)
treec5455487e4e74681465fd8b3190660245814f0f0 /gcc/expr.c
parent4f60e9d38fc40fc923451b9c0f03dcee86e6e4da (diff)
downloadgcc-63d94e58b194a2f1a2022bfa03569ce51fd007f5.zip
gcc-63d94e58b194a2f1a2022bfa03569ce51fd007f5.tar.gz
gcc-63d94e58b194a2f1a2022bfa03569ce51fd007f5.tar.bz2
re PR middle-end/54617 (ICE on gcc.c-torture/compile/pr42025-2.c with -m64 and -O1)
PR middle-end/54617 * expr.c (store_field): Handle a PARALLEL in more cases. From-SVN: r191451
Diffstat (limited to 'gcc/expr.c')
-rw-r--r--gcc/expr.c37
1 files changed, 27 insertions, 10 deletions
diff --git a/gcc/expr.c b/gcc/expr.c
index c53f1a8..36f4dd7 100644
--- a/gcc/expr.c
+++ b/gcc/expr.c
@@ -6452,16 +6452,33 @@ store_field (rtx target, HOST_WIDE_INT bitsize, HOST_WIDE_INT bitpos,
/* 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;
}