diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 3c3f735a878..d63fe3905cc 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,12 @@ +2004-12-09 Richard Sandiford + + * simplify-rtx.c (simplify_subreg): In the CONCAT case, check whether + the request subreg is entirely contained in the requested component. + (simplify_gen_subreg): Return null for CONCATs that are rejected + by simplify_subreg. + * expmed.c (store_bit_field): Create a temporary when changing the + value to an integer mode. + 2004-12-09 David Edelsohn * real.c (ibm_extended): Correct comment. diff --git a/gcc/expmed.c b/gcc/expmed.c index 47fc2d2bd47..10a95b3862a 100644 --- a/gcc/expmed.c +++ b/gcc/expmed.c @@ -591,16 +591,18 @@ store_bit_field (rtx str_rtx, unsigned HOST_WIDE_INT bitsize, offset = 0; } - /* If VALUE is a floating-point mode, access it as an integer of the - corresponding size. This can occur on a machine with 64 bit registers - that uses SFmode for float. This can also occur for unaligned float - structure fields. */ + /* If VALUE has a floating-point or complex mode, access it as an + integer of the corresponding size. This can occur on a machine + with 64 bit registers that uses SFmode for float. It can also + occur for unaligned float or complex fields. */ orig_value = value; - if (GET_MODE_CLASS (GET_MODE (value)) != MODE_INT + if (GET_MODE (value) != VOIDmode + && GET_MODE_CLASS (GET_MODE (value)) != MODE_INT && GET_MODE_CLASS (GET_MODE (value)) != MODE_PARTIAL_INT) - value = gen_lowpart ((GET_MODE (value) == VOIDmode - ? word_mode : int_mode_for_mode (GET_MODE (value))), - value); + { + value = gen_reg_rtx (int_mode_for_mode (GET_MODE (value))); + emit_move_insn (gen_lowpart (GET_MODE (orig_value), value), orig_value); + } /* Now OFFSET is nonzero only if OP0 is memory and is therefore always measured in bytes. */ diff --git a/gcc/simplify-rtx.c b/gcc/simplify-rtx.c index 580782d600f..2ac56612f8c 100644 --- a/gcc/simplify-rtx.c +++ b/gcc/simplify-rtx.c @@ -3722,17 +3722,20 @@ simplify_subreg (enum machine_mode outermode, rtx op, of real and imaginary part. */ if (GET_CODE (op) == CONCAT) { - int is_realpart = byte < (unsigned int) GET_MODE_UNIT_SIZE (innermode); - rtx part = is_realpart ? XEXP (op, 0) : XEXP (op, 1); - unsigned int final_offset; - rtx res; + unsigned int inner_size, final_offset; + rtx part, res; + + inner_size = GET_MODE_UNIT_SIZE (innermode); + part = byte < inner_size ? XEXP (op, 0) : XEXP (op, 1); + final_offset = byte % inner_size; + if (final_offset + GET_MODE_SIZE (outermode) > inner_size) + return NULL_RTX; - final_offset = byte % (GET_MODE_UNIT_SIZE (innermode)); res = simplify_subreg (outermode, part, GET_MODE (part), final_offset); if (res) return res; if (validate_subreg (outermode, GET_MODE (part), part, final_offset)) - return gen_rtx_SUBREG (outermode, part, final_offset); + return gen_rtx_SUBREG (outermode, part, final_offset); return NULL_RTX; } @@ -3786,7 +3789,9 @@ simplify_gen_subreg (enum machine_mode outermode, rtx op, if (newx) return newx; - if (GET_CODE (op) == SUBREG || GET_MODE (op) == VOIDmode) + if (GET_CODE (op) == SUBREG + || GET_CODE (op) == CONCAT + || GET_MODE (op) == VOIDmode) return NULL_RTX; if (validate_subreg (outermode, innermode, op, byte))