Commit 02972eaf by Richard Sandiford Committed by Richard Sandiford

re PR target/45074 (GCC Segmentation fault - negating global register variables)

gcc/
	PR target/45074
	* optabs.h (valid_multiword_target_p): Declare.
	* expmed.c (extract_bit_field_1): Check valid_multiword_target_p when
	doing multi-word operations.
	* optabs.c (expand_binop): Likewise.
	(expand_doubleword_bswap): Likewise.
	(expand_absneg_bit): Likewise.
	(expand_unop): Likewise.
	(expand_copysign_bit): Likewise.
	(multiword_target_p): New function.

gcc/testsuite/
	PR target/45074
	* gcc.target/mips/pr45074.c: New test.

From-SVN: r174541
parent 4d41c2d1
2011-06-01 Richard Sandiford <rdsandiford@googlemail.com> 2011-06-01 Richard Sandiford <rdsandiford@googlemail.com>
PR target/45074
* optabs.h (valid_multiword_target_p): Declare.
* expmed.c (extract_bit_field_1): Check valid_multiword_target_p when
doing multi-word operations.
* optabs.c (expand_binop): Likewise.
(expand_doubleword_bswap): Likewise.
(expand_absneg_bit): Likewise.
(expand_unop): Likewise.
(expand_copysign_bit): Likewise.
(multiword_target_p): New function.
2011-06-01 Richard Sandiford <rdsandiford@googlemail.com>
PR rtl-optimization/48830 PR rtl-optimization/48830
PR rtl-optimization/48808 PR rtl-optimization/48808
PR rtl-optimization/48792 PR rtl-optimization/48792
......
...@@ -1341,7 +1341,7 @@ extract_bit_field_1 (rtx str_rtx, unsigned HOST_WIDE_INT bitsize, ...@@ -1341,7 +1341,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 nwords = (bitsize + (BITS_PER_WORD - 1)) / BITS_PER_WORD;
unsigned int i; unsigned int i;
if (target == 0 || !REG_P (target)) if (target == 0 || !REG_P (target) || !valid_multiword_target_p (target))
target = gen_reg_rtx (mode); target = gen_reg_rtx (mode);
/* Indicate for flow that the entire target reg is being set. */ /* Indicate for flow that the entire target reg is being set. */
......
...@@ -1537,7 +1537,10 @@ expand_binop (enum machine_mode mode, optab binoptab, rtx op0, rtx op1, ...@@ -1537,7 +1537,10 @@ expand_binop (enum machine_mode mode, optab binoptab, rtx op0, rtx op1,
/* If TARGET is the same as one of the operands, the REG_EQUAL note /* If TARGET is the same as one of the operands, the REG_EQUAL note
won't be accurate, so use a new target. */ won't be accurate, so use a new target. */
if (target == 0 || target == op0 || target == op1) if (target == 0
|| target == op0
|| target == op1
|| !valid_multiword_target_p (target))
target = gen_reg_rtx (mode); target = gen_reg_rtx (mode);
start_sequence (); start_sequence ();
...@@ -1605,7 +1608,10 @@ expand_binop (enum machine_mode mode, optab binoptab, rtx op0, rtx op1, ...@@ -1605,7 +1608,10 @@ expand_binop (enum machine_mode mode, optab binoptab, rtx op0, rtx op1,
/* If TARGET is the same as one of the operands, the REG_EQUAL note /* If TARGET is the same as one of the operands, the REG_EQUAL note
won't be accurate, so use a new target. */ won't be accurate, so use a new target. */
if (target == 0 || target == op0 || target == op1) if (target == 0
|| target == op0
|| target == op1
|| !valid_multiword_target_p (target))
target = gen_reg_rtx (mode); target = gen_reg_rtx (mode);
start_sequence (); start_sequence ();
...@@ -1659,7 +1665,11 @@ expand_binop (enum machine_mode mode, optab binoptab, rtx op0, rtx op1, ...@@ -1659,7 +1665,11 @@ expand_binop (enum machine_mode mode, optab binoptab, rtx op0, rtx op1,
opportunities, and second because if target and op0 happen to be MEMs opportunities, and second because if target and op0 happen to be MEMs
designating the same location, we would risk clobbering it too early designating the same location, we would risk clobbering it too early
in the code sequence we generate below. */ in the code sequence we generate below. */
if (target == 0 || target == op0 || target == op1 || ! REG_P (target)) if (target == 0
|| target == op0
|| target == op1
|| !REG_P (target)
|| !valid_multiword_target_p (target))
target = gen_reg_rtx (mode); target = gen_reg_rtx (mode);
start_sequence (); start_sequence ();
...@@ -1779,7 +1789,7 @@ expand_binop (enum machine_mode mode, optab binoptab, rtx op0, rtx op1, ...@@ -1779,7 +1789,7 @@ expand_binop (enum machine_mode mode, optab binoptab, rtx op0, rtx op1,
xtarget = gen_reg_rtx (mode); xtarget = gen_reg_rtx (mode);
if (target == 0 || !REG_P (target)) if (target == 0 || !REG_P (target) || !valid_multiword_target_p (target))
target = xtarget; target = xtarget;
/* Indicate for flow that the entire target reg is being set. */ /* Indicate for flow that the entire target reg is being set. */
...@@ -2481,7 +2491,7 @@ expand_doubleword_bswap (enum machine_mode mode, rtx op, rtx target) ...@@ -2481,7 +2491,7 @@ expand_doubleword_bswap (enum machine_mode mode, rtx op, rtx target)
t0 = expand_unop (word_mode, bswap_optab, t0 = expand_unop (word_mode, bswap_optab,
operand_subword_force (op, 1, mode), NULL_RTX, true); operand_subword_force (op, 1, mode), NULL_RTX, true);
if (target == 0) if (target == 0 || !valid_multiword_target_p (target))
target = gen_reg_rtx (mode); target = gen_reg_rtx (mode);
if (REG_P (target)) if (REG_P (target))
emit_clobber (target); emit_clobber (target);
...@@ -2724,7 +2734,9 @@ expand_absneg_bit (enum rtx_code code, enum machine_mode mode, ...@@ -2724,7 +2734,9 @@ expand_absneg_bit (enum rtx_code code, enum machine_mode mode,
if (code == ABS) if (code == ABS)
mask = double_int_not (mask); mask = double_int_not (mask);
if (target == 0 || target == op0) if (target == 0
|| target == op0
|| (nwords > 1 && !valid_multiword_target_p (target)))
target = gen_reg_rtx (mode); target = gen_reg_rtx (mode);
if (nwords > 1) if (nwords > 1)
...@@ -2915,7 +2927,7 @@ expand_unop (enum machine_mode mode, optab unoptab, rtx op0, rtx target, ...@@ -2915,7 +2927,7 @@ expand_unop (enum machine_mode mode, optab unoptab, rtx op0, rtx target,
int i; int i;
rtx insns; rtx insns;
if (target == 0 || target == op0) if (target == 0 || target == op0 || !valid_multiword_target_p (target))
target = gen_reg_rtx (mode); target = gen_reg_rtx (mode);
start_sequence (); start_sequence ();
...@@ -3386,7 +3398,10 @@ expand_copysign_bit (enum machine_mode mode, rtx op0, rtx op1, rtx target, ...@@ -3386,7 +3398,10 @@ expand_copysign_bit (enum machine_mode mode, rtx op0, rtx op1, rtx target,
mask = double_int_setbit (double_int_zero, bitpos); mask = double_int_setbit (double_int_zero, bitpos);
if (target == 0 || target == op0 || target == op1) if (target == 0
|| target == op0
|| target == op1
|| (nwords > 1 && !valid_multiword_target_p (target)))
target = gen_reg_rtx (mode); target = gen_reg_rtx (mode);
if (nwords > 1) if (nwords > 1)
...@@ -7034,6 +7049,23 @@ insn_operand_matches (enum insn_code icode, unsigned int opno, rtx operand) ...@@ -7034,6 +7049,23 @@ insn_operand_matches (enum insn_code icode, unsigned int opno, rtx operand)
(operand, insn_data[(int) icode].operand[opno].mode))); (operand, insn_data[(int) icode].operand[opno].mode)));
} }
/* TARGET is a target of a multiword operation that we are going to
implement as a series of word-mode operations. Return true if
TARGET is suitable for this purpose. */
bool
valid_multiword_target_p (rtx target)
{
enum machine_mode mode;
int i;
mode = GET_MODE (target);
for (i = 0; i < GET_MODE_SIZE (mode); i += UNITS_PER_WORD)
if (!validate_subreg (word_mode, mode, target, i))
return false;
return true;
}
/* Like maybe_legitimize_operand, but do not change the code of the /* Like maybe_legitimize_operand, but do not change the code of the
current rtx value. */ current rtx value. */
......
...@@ -1059,6 +1059,8 @@ create_integer_operand (struct expand_operand *op, HOST_WIDE_INT intval) ...@@ -1059,6 +1059,8 @@ create_integer_operand (struct expand_operand *op, HOST_WIDE_INT intval)
create_expand_operand (op, EXPAND_INTEGER, GEN_INT (intval), VOIDmode, false); create_expand_operand (op, EXPAND_INTEGER, GEN_INT (intval), VOIDmode, false);
} }
extern bool valid_multiword_target_p (rtx);
extern bool maybe_legitimize_operands (enum insn_code icode, extern bool maybe_legitimize_operands (enum insn_code icode,
unsigned int opno, unsigned int nops, unsigned int opno, unsigned int nops,
struct expand_operand *ops); struct expand_operand *ops);
......
2011-06-01 Richard Sandiford <rdsandiford@googlemail.com>
PR target/45074
* gcc.target/mips/pr45074.c: New test.
2011-06-01 Eric Botcazou <ebotcazou@adacore.com> 2011-06-01 Eric Botcazou <ebotcazou@adacore.com>
Hans-Peter Nilsson <hp@axis.com> Hans-Peter Nilsson <hp@axis.com>
......
/* { dg-options "-mhard-float -mgp32 -O" } */
register double g __asm__("$f20");
NOMIPS16 void
test (double a)
{
g = -a;
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment