aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorRichard Sandiford <rdsandiford@googlemail.com>2011-06-01 19:49:53 +0000
committerRichard Sandiford <rsandifo@gcc.gnu.org>2011-06-01 19:49:53 +0000
commit02972eafb03f823c9dcbe3ede3d1f96562afaa89 (patch)
tree512555575631369514775396520cedb9467f1074 /gcc
parent4d41c2d1ce6f01c53eb8941461b3047e8a6368f6 (diff)
downloadgcc-02972eafb03f823c9dcbe3ede3d1f96562afaa89.zip
gcc-02972eafb03f823c9dcbe3ede3d1f96562afaa89.tar.gz
gcc-02972eafb03f823c9dcbe3ede3d1f96562afaa89.tar.bz2
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
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog13
-rw-r--r--gcc/expmed.c2
-rw-r--r--gcc/optabs.c48
-rw-r--r--gcc/optabs.h2
-rw-r--r--gcc/testsuite/ChangeLog5
-rw-r--r--gcc/testsuite/gcc.target/mips/pr45074.c8
6 files changed, 69 insertions, 9 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 658174b..85b68a7 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,5 +1,18 @@
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/48808
PR rtl-optimization/48792
diff --git a/gcc/expmed.c b/gcc/expmed.c
index 5527c1e..314fac7 100644
--- a/gcc/expmed.c
+++ b/gcc/expmed.c
@@ -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 i;
- if (target == 0 || !REG_P (target))
+ if (target == 0 || !REG_P (target) || !valid_multiword_target_p (target))
target = gen_reg_rtx (mode);
/* Indicate for flow that the entire target reg is being set. */
diff --git a/gcc/optabs.c b/gcc/optabs.c
index 1473b0f..224fb11 100644
--- a/gcc/optabs.c
+++ b/gcc/optabs.c
@@ -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
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);
start_sequence ();
@@ -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
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);
start_sequence ();
@@ -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
designating the same location, we would risk clobbering it too early
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);
start_sequence ();
@@ -1779,7 +1789,7 @@ expand_binop (enum machine_mode mode, optab binoptab, rtx op0, rtx op1,
xtarget = gen_reg_rtx (mode);
- if (target == 0 || !REG_P (target))
+ if (target == 0 || !REG_P (target) || !valid_multiword_target_p (target))
target = xtarget;
/* 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)
t0 = expand_unop (word_mode, bswap_optab,
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);
if (REG_P (target))
emit_clobber (target);
@@ -2724,7 +2734,9 @@ expand_absneg_bit (enum rtx_code code, enum machine_mode mode,
if (code == ABS)
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);
if (nwords > 1)
@@ -2915,7 +2927,7 @@ expand_unop (enum machine_mode mode, optab unoptab, rtx op0, rtx target,
int i;
rtx insns;
- if (target == 0 || target == op0)
+ if (target == 0 || target == op0 || !valid_multiword_target_p (target))
target = gen_reg_rtx (mode);
start_sequence ();
@@ -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);
- 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);
if (nwords > 1)
@@ -7034,6 +7049,23 @@ insn_operand_matches (enum insn_code icode, unsigned int opno, rtx operand)
(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
current rtx value. */
diff --git a/gcc/optabs.h b/gcc/optabs.h
index db6e65e..62bc14e 100644
--- a/gcc/optabs.h
+++ b/gcc/optabs.h
@@ -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);
}
+extern bool valid_multiword_target_p (rtx);
+
extern bool maybe_legitimize_operands (enum insn_code icode,
unsigned int opno, unsigned int nops,
struct expand_operand *ops);
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 2195344..7e90e17 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,8 @@
+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>
Hans-Peter Nilsson <hp@axis.com>
diff --git a/gcc/testsuite/gcc.target/mips/pr45074.c b/gcc/testsuite/gcc.target/mips/pr45074.c
new file mode 100644
index 0000000..ba578c8
--- /dev/null
+++ b/gcc/testsuite/gcc.target/mips/pr45074.c
@@ -0,0 +1,8 @@
+/* { dg-options "-mhard-float -mgp32 -O" } */
+register double g __asm__("$f20");
+
+NOMIPS16 void
+test (double a)
+{
+ g = -a;
+}