aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorEric Botcazou <ebotcazou@adacore.com>2010-09-15 22:48:00 +0000
committerEric Botcazou <ebotcazou@gcc.gnu.org>2010-09-15 22:48:00 +0000
commit9fa07b131e21a921ecc535f736882a5fb0698a9c (patch)
tree53bdda0670a317b7ee0c5d54eced29a316056e18 /gcc
parent06730c5d14d81a26842428dc85ff9e9849dba96f (diff)
downloadgcc-9fa07b131e21a921ecc535f736882a5fb0698a9c.zip
gcc-9fa07b131e21a921ecc535f736882a5fb0698a9c.tar.gz
gcc-9fa07b131e21a921ecc535f736882a5fb0698a9c.tar.bz2
re PR rtl-optimization/45593 (segfault with -Os)
PR rtl-optimization/45593 * reorg.c (relax_delay_slots): Use emit_copy_of_insn_after to re-emit insns that were in delay slots as stand-alone insns. From-SVN: r164318
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog6
-rw-r--r--gcc/reorg.c38
-rw-r--r--gcc/testsuite/ChangeLog4
-rw-r--r--gcc/testsuite/gcc.c-torture/compile/20100915-1.c82
4 files changed, 112 insertions, 18 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 178b31d..184894a 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,9 @@
+2010-09-15 Eric Botcazou <ebotcazou@adacore.com>
+
+ PR rtl-optimization/45593
+ * reorg.c (relax_delay_slots): Use emit_copy_of_insn_after to re-emit
+ insns that were in delay slots as stand-alone insns.
+
2010-09-15 Ian Lance Taylor <iant@google.com>
* incpath.c (remove_duplicates): If name is not a directory, issue
diff --git a/gcc/reorg.c b/gcc/reorg.c
index ec13bcc..7776fa2 100644
--- a/gcc/reorg.c
+++ b/gcc/reorg.c
@@ -3459,9 +3459,13 @@ relax_delay_slots (rtx first)
We do this by deleting the INSN containing the SEQUENCE, then
re-emitting the insns separately, and then deleting the RETURN.
This allows the count of the jump target to be properly
- decremented. */
+ decremented.
- /* Clear the from target bit, since these insns are no longer
+ Note that we need to change the INSN_UID of the re-emitted insns
+ since it is used to hash the insns for mark_target_live_regs and
+ the re-emitted insns will no longer be wrapped up in a SEQUENCE.
+
+ Clear the from target bit, since these insns are no longer
in delay slots. */
for (i = 0; i < XVECLEN (pat, 0); i++)
INSN_FROM_TARGET_P (XVECEXP (pat, 0, i)) = 0;
@@ -3469,13 +3473,10 @@ relax_delay_slots (rtx first)
trial = PREV_INSN (insn);
delete_related_insns (insn);
gcc_assert (GET_CODE (pat) == SEQUENCE);
- after = trial;
- for (i = 0; i < XVECLEN (pat, 0); i++)
- {
- rtx this_insn = XVECEXP (pat, 0, i);
- add_insn_after (this_insn, after, NULL);
- after = this_insn;
- }
+ add_insn_after (delay_insn, trial, NULL);
+ after = delay_insn;
+ for (i = 1; i < XVECLEN (pat, 0); i++)
+ after = emit_copy_of_insn_after (XVECEXP (pat, 0, i), after);
delete_scheduled_jump (delay_insn);
continue;
}
@@ -3580,9 +3581,13 @@ relax_delay_slots (rtx first)
We do this by deleting the INSN containing the SEQUENCE, then
re-emitting the insns separately, and then deleting the jump.
This allows the count of the jump target to be properly
- decremented. */
+ decremented.
- /* Clear the from target bit, since these insns are no longer
+ Note that we need to change the INSN_UID of the re-emitted insns
+ since it is used to hash the insns for mark_target_live_regs and
+ the re-emitted insns will no longer be wrapped up in a SEQUENCE.
+
+ Clear the from target bit, since these insns are no longer
in delay slots. */
for (i = 0; i < XVECLEN (pat, 0); i++)
INSN_FROM_TARGET_P (XVECEXP (pat, 0, i)) = 0;
@@ -3590,13 +3595,10 @@ relax_delay_slots (rtx first)
trial = PREV_INSN (insn);
delete_related_insns (insn);
gcc_assert (GET_CODE (pat) == SEQUENCE);
- after = trial;
- for (i = 0; i < XVECLEN (pat, 0); i++)
- {
- rtx this_insn = XVECEXP (pat, 0, i);
- add_insn_after (this_insn, after, NULL);
- after = this_insn;
- }
+ add_insn_after (delay_insn, trial, NULL);
+ after = delay_insn;
+ for (i = 1; i < XVECLEN (pat, 0); i++)
+ after = emit_copy_of_insn_after (XVECEXP (pat, 0, i), after);
delete_scheduled_jump (delay_insn);
continue;
}
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index d03b017..b1f8744 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,7 @@
+2010-09-15 Eric Botcazou <ebotcazou@adacore.com>
+
+ * gcc.c-torture/compile/20100915-1.c: New test.
+
2010-09-15 Martin Jambor <mjambor@suse.cz>
PR middle-end/45644
diff --git a/gcc/testsuite/gcc.c-torture/compile/20100915-1.c b/gcc/testsuite/gcc.c-torture/compile/20100915-1.c
new file mode 100644
index 0000000..04f6ab0
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/compile/20100915-1.c
@@ -0,0 +1,82 @@
+/* PR rtl-optimization/45593 */
+/* Testcase by Arnaud Lacombe <lacombar@gmail.com> */
+
+typedef unsigned int __u32;
+typedef __u32 __be32;
+static inline __attribute__((always_inline)) int __attribute__((__cold__)) printk(const char *s, ...) { return 0; }
+typedef struct journal_s journal_t;
+typedef struct journal_header_s
+{
+ __be32 h_magic;
+ __be32 h_blocktype;
+ __be32 h_sequence;
+} journal_header_t;
+typedef struct journal_superblock_s
+{
+ journal_header_t s_header;
+ __be32 s_blocksize;
+ __be32 s_maxlen;
+} journal_superblock_t;
+struct journal_s
+{
+ struct buffer_head *j_sb_buffer;
+ journal_superblock_t *j_superblock;
+ int j_format_version;
+ int j_blocksize;
+ unsigned int j_maxlen;
+};
+static void journal_fail_superblock (journal_t *journal)
+{
+ journal->j_sb_buffer = ((void *)0);
+}
+static int journal_get_superblock(journal_t *journal)
+{
+ struct buffer_head *bh;
+ journal_superblock_t *sb;
+ int err = -100;
+ bh = journal->j_sb_buffer;
+ if (!buffer_uptodate(bh)) {
+ if (!buffer_uptodate(bh)) {
+ printk ("JBD: IO error reading journal superblock\n");
+ goto out;
+ }
+ }
+ err = -101;
+ if (sb->s_header.h_magic != (( __be32)(__u32)(0)) ||
+ sb->s_blocksize != (( __be32)(__u32)(journal->j_blocksize))) {
+ printk("JBD: no valid journal superblock found\n");
+ goto out;
+ }
+ switch((( __u32)(__be32)(sb->s_header.h_blocktype))) {
+ case 0:
+ case 1:
+ break;
+ default:
+ goto out;
+ }
+ if ((( __u32)(__be32)(sb->s_maxlen)) < journal->j_maxlen)
+ journal->j_maxlen = (( __u32)(__be32)(sb->s_maxlen));
+ else if ((( __u32)(__be32)(sb->s_maxlen)) > journal->j_maxlen) {
+ printk ("JBD: journal file too short\n");
+ goto out;
+ }
+ return 0;
+out:
+ journal_fail_superblock(journal);
+ return err;
+}
+static int load_superblock(journal_t *journal)
+{
+ journal_get_superblock(journal);
+ return 0;
+}
+int jbd2_journal_update_format (journal_t *journal)
+{
+ journal_get_superblock(journal);
+ return 0;
+}
+int jbd2_journal_wipe(journal_t *journal, int write)
+{
+ load_superblock(journal);
+ return 0;
+}