diff options
author | ebotcazou <ebotcazou@138bc75d-0d04-0410-961f-82ee72b054a4> | 2012-09-14 13:28:44 +0000 |
---|---|---|
committer | ebotcazou <ebotcazou@138bc75d-0d04-0410-961f-82ee72b054a4> | 2012-09-14 13:28:44 +0000 |
commit | 2d0fd66d982886cf217f7127f2d906fed5df9374 (patch) | |
tree | 5c32661073d991fc5ce315762062115ab0af337c /gcc/expmed.c | |
parent | 9579a4b96330010a9a9b327eec8dfd4be1d3524d (diff) | |
download | gcc-2d0fd66d982886cf217f7127f2d906fed5df9374.tar.gz |
PR rtl-optimization/44194
* calls.c (expand_call): In the PARALLEL case, copy the return value
into pseudos instead of spilling it onto the stack.
* emit-rtl.c (adjust_address_1): Rename ADJUST into ADJUST_ADDRESS and
add new ADJUST_OBJECT parameter.
If ADJUST_OBJECT is set, drop the underlying object if it cannot be
proved that the adjusted memory access is still within its bounds.
(adjust_automodify_address_1): Adjust call to adjust_address_1.
(widen_memory_access): Likewise.
* expmed.c (store_bit_field_1): Call adjust_bitfield_address instead
of adjust_address. Do not drop the underlying object of a MEM.
(store_fixed_bit_field): Likewise.
(extract_bit_field_1): Likewise. Fix oversight in recursion.
(extract_fixed_bit_field): Likewise.
* expr.h (adjust_address_1): Adjust prototype.
(adjust_address): Adjust call to adjust_address_1.
(adjust_address_nv): Likewise.
(adjust_bitfield_address): New macro.
(adjust_bitfield_address_nv): Likewise.
* expr.c (expand_assignment): Handle a PARALLEL in more cases.
(store_expr): Likewise.
(store_field): Likewise.
* dse.c: Fix typos in the head comment.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@191302 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/expmed.c')
-rw-r--r-- | gcc/expmed.c | 56 |
1 files changed, 22 insertions, 34 deletions
diff --git a/gcc/expmed.c b/gcc/expmed.c index 24a15770a47..cde92463637 100644 --- a/gcc/expmed.c +++ b/gcc/expmed.c @@ -500,7 +500,7 @@ store_bit_field_1 (rtx str_rtx, unsigned HOST_WIDE_INT bitsize, && MEM_ALIGN (op0) % GET_MODE_BITSIZE (fieldmode) == 0)))) { if (MEM_P (op0)) - op0 = adjust_address (op0, fieldmode, offset); + op0 = adjust_bitfield_address (op0, fieldmode, offset); else if (GET_MODE (op0) != fieldmode) op0 = simplify_gen_subreg (fieldmode, op0, GET_MODE (op0), byte_offset); @@ -517,7 +517,7 @@ store_bit_field_1 (rtx str_rtx, unsigned HOST_WIDE_INT bitsize, if (imode != GET_MODE (op0)) { if (MEM_P (op0)) - op0 = adjust_address (op0, imode, 0); + op0 = adjust_bitfield_address (op0, imode, 0); else { gcc_assert (imode != BLKmode); @@ -526,16 +526,6 @@ store_bit_field_1 (rtx str_rtx, unsigned HOST_WIDE_INT bitsize, } } - /* We may be accessing data outside the field, which means - we can alias adjacent data. */ - /* ?? not always for C++0x memory model ?? */ - if (MEM_P (op0)) - { - op0 = shallow_copy_rtx (op0); - set_mem_alias_set (op0, 0); - set_mem_expr (op0, 0); - } - /* If OP0 is a register, BITPOS must count within a word. But as we have it, it counts within whatever size OP0 now has. On a bigendian machine, these are not the same, so convert. */ @@ -718,7 +708,7 @@ store_bit_field_1 (rtx str_rtx, unsigned HOST_WIDE_INT bitsize, /* Add OFFSET into OP0's address. */ if (MEM_P (xop0)) - xop0 = adjust_address (xop0, byte_mode, offset); + xop0 = adjust_bitfield_address (xop0, byte_mode, offset); /* If xop0 is a register, we need it in OP_MODE to make it acceptable to the format of insv. */ @@ -852,7 +842,7 @@ store_bit_field_1 (rtx str_rtx, unsigned HOST_WIDE_INT bitsize, unit = GET_MODE_BITSIZE (bestmode); xoffset = (bitnum / unit) * GET_MODE_SIZE (bestmode); xbitpos = bitnum % unit; - xop0 = adjust_address (op0, bestmode, xoffset); + xop0 = adjust_bitfield_address (op0, bestmode, xoffset); /* Fetch that unit, store the bitfield in it, then store the unit. */ @@ -1024,7 +1014,7 @@ store_fixed_bit_field (rtx op0, unsigned HOST_WIDE_INT offset, Then alter OP0 to refer to that word. */ bitpos += (offset % (total_bits / BITS_PER_UNIT)) * BITS_PER_UNIT; offset -= (offset % (total_bits / BITS_PER_UNIT)); - op0 = adjust_address (op0, mode, offset); + op0 = adjust_bitfield_address (op0, mode, offset); } mode = GET_MODE (op0); @@ -1388,7 +1378,7 @@ extract_bit_field_1 (rtx str_rtx, unsigned HOST_WIDE_INT bitsize, if (imode != GET_MODE (op0)) { if (MEM_P (op0)) - op0 = adjust_address (op0, imode, 0); + op0 = adjust_bitfield_address (op0, imode, 0); else if (imode != BLKmode) { op0 = gen_lowpart (imode, op0); @@ -1414,20 +1404,11 @@ extract_bit_field_1 (rtx str_rtx, unsigned HOST_WIDE_INT bitsize, rtx mem = assign_stack_temp (GET_MODE (op0), GET_MODE_SIZE (GET_MODE (op0))); emit_move_insn (mem, op0); - op0 = adjust_address (mem, BLKmode, 0); + op0 = adjust_bitfield_address (mem, BLKmode, 0); } } } - /* We may be accessing data outside the field, which means - we can alias adjacent data. */ - if (MEM_P (op0)) - { - op0 = shallow_copy_rtx (op0); - set_mem_alias_set (op0, 0); - set_mem_expr (op0, 0); - } - /* Extraction of a full-word or multi-word value from a structure in a register or aligned memory can be done with just a SUBREG. A subword value in the least significant part of a register @@ -1487,7 +1468,7 @@ extract_bit_field_1 (rtx str_rtx, unsigned HOST_WIDE_INT bitsize, && MEM_ALIGN (op0) % bitsize == 0))))) { if (MEM_P (op0)) - op0 = adjust_address (op0, mode1, offset); + op0 = adjust_bitfield_address (op0, mode1, offset); else if (mode1 != GET_MODE (op0)) { rtx sub = simplify_gen_subreg (mode1, op0, GET_MODE (op0), @@ -1513,6 +1494,7 @@ extract_bit_field_1 (rtx str_rtx, unsigned HOST_WIDE_INT bitsize, unsigned int nwords = (bitsize + (BITS_PER_WORD - 1)) / BITS_PER_WORD; unsigned int i; + rtx last; if (target == 0 || !REG_P (target) || !valid_multiword_target_p (target)) target = gen_reg_rtx (mode); @@ -1520,6 +1502,7 @@ extract_bit_field_1 (rtx str_rtx, unsigned HOST_WIDE_INT bitsize, /* Indicate for flow that the entire target reg is being set. */ emit_clobber (target); + last = get_last_insn (); for (i = 0; i < nwords; i++) { /* If I is 0, use the low-order word in both field and target; @@ -1536,12 +1519,17 @@ extract_bit_field_1 (rtx str_rtx, unsigned HOST_WIDE_INT bitsize, : (int) i * BITS_PER_WORD); rtx target_part = operand_subword (target, wordnum, 1, VOIDmode); rtx result_part - = extract_bit_field (op0, MIN (BITS_PER_WORD, - bitsize - i * BITS_PER_WORD), - bitnum + bit_offset, 1, false, target_part, mode, - word_mode); + = extract_bit_field_1 (op0, MIN (BITS_PER_WORD, + bitsize - i * BITS_PER_WORD), + bitnum + bit_offset, 1, false, target_part, + mode, word_mode, fallback_p); gcc_assert (target_part); + if (!result_part) + { + delete_insns_since (last); + return NULL; + } if (result_part != target_part) emit_move_insn (target_part, result_part); @@ -1629,7 +1617,7 @@ extract_bit_field_1 (rtx str_rtx, unsigned HOST_WIDE_INT bitsize, xop0 = gen_lowpart_SUBREG (ext_mode, xop0); if (MEM_P (xop0)) /* Get ref to first byte containing part of the field. */ - xop0 = adjust_address (xop0, byte_mode, xoffset); + xop0 = adjust_bitfield_address (xop0, byte_mode, xoffset); /* Now convert from counting within UNIT to counting in EXT_MODE. */ if (BYTES_BIG_ENDIAN && !MEM_P (xop0)) @@ -1725,7 +1713,7 @@ extract_bit_field_1 (rtx str_rtx, unsigned HOST_WIDE_INT bitsize, last = get_last_insn (); /* Fetch it to a register in that size. */ - xop0 = adjust_address (op0, bestmode, xoffset); + xop0 = adjust_bitfield_address (op0, bestmode, xoffset); xop0 = force_reg (bestmode, xop0); result = extract_bit_field_1 (xop0, bitsize, xbitpos, unsignedp, packedp, target, @@ -1906,7 +1894,7 @@ extract_fixed_bit_field (enum machine_mode tmode, rtx op0, offset -= (offset % (total_bits / BITS_PER_UNIT)); } - op0 = adjust_address (op0, mode, offset); + op0 = adjust_bitfield_address (op0, mode, offset); } mode = GET_MODE (op0); |