diff options
author | Jakub Jelinek <jakub@redhat.com> | 2017-03-27 23:00:35 +0200 |
---|---|---|
committer | Jakub Jelinek <jakub@gcc.gnu.org> | 2017-03-27 23:00:35 +0200 |
commit | aade772d8a2eeda4ea22f0ca648ebdf44d8d8c15 (patch) | |
tree | 580908125ff2f800b4a09a1179d95a53ebb8aa20 /gcc/cfgcleanup.c | |
parent | e298b56acbe3e2534767462937d5674978979683 (diff) |
re PR target/80102 (ICE in maybe_record_trace_start, at dwarf2cfi.c:2330)
PR target/80102
* reg-notes.def (REG_CFA_NOTE): Define. Use it for CFA related
notes.
* cfgcleanup.c (reg_note_cfa_p): New array.
(insns_have_identical_cfa_notes): New function.
(old_insns_match_p): Don't cross-jump in between /f
and non-/f instructions. If both i1 and i2 are frame related,
verify all CFA notes, their order and content.
* g++.dg/opt/pr80102.C: New test.
From-SVN: r246511
Diffstat (limited to 'gcc/cfgcleanup.c')
-rw-r--r-- | gcc/cfgcleanup.c | 52 |
1 files changed, 52 insertions, 0 deletions
diff --git a/gcc/cfgcleanup.c b/gcc/cfgcleanup.c index 9663b68fb32..d55b0ceb832 100644 --- a/gcc/cfgcleanup.c +++ b/gcc/cfgcleanup.c @@ -1111,6 +1111,48 @@ merge_dir (enum replace_direction a, enum replace_direction b) return dir_none; } +/* Array of flags indexed by reg note kind, true if the given + reg note is CFA related. */ +static const bool reg_note_cfa_p[] = { +#undef REG_CFA_NOTE +#define DEF_REG_NOTE(NAME) false, +#define REG_CFA_NOTE(NAME) true, +#include "reg-notes.def" +#undef REG_CFA_NOTE +#undef DEF_REG_NOTE + false +}; + +/* Return true if I1 and I2 have identical CFA notes (the same order + and equivalent content). */ + +static bool +insns_have_identical_cfa_notes (rtx_insn *i1, rtx_insn *i2) +{ + rtx n1, n2; + for (n1 = REG_NOTES (i1), n2 = REG_NOTES (i2); ; + n1 = XEXP (n1, 1), n2 = XEXP (n2, 1)) + { + /* Skip over reg notes not related to CFI information. */ + while (n1 && !reg_note_cfa_p[REG_NOTE_KIND (n1)]) + n1 = XEXP (n1, 1); + while (n2 && !reg_note_cfa_p[REG_NOTE_KIND (n2)]) + n2 = XEXP (n2, 1); + if (n1 == NULL_RTX && n2 == NULL_RTX) + return true; + if (n1 == NULL_RTX || n2 == NULL_RTX) + return false; + if (XEXP (n1, 0) == XEXP (n2, 0)) + ; + else if (XEXP (n1, 0) == NULL_RTX || XEXP (n2, 0) == NULL_RTX) + return false; + else if (!(reload_completed + ? rtx_renumbered_equal_p (XEXP (n1, 0), XEXP (n2, 0)) + : rtx_equal_p (XEXP (n1, 0), XEXP (n2, 0)))) + return false; + } +} + /* Examine I1 and I2 and return: - dir_forward if I1 can be replaced by I2, or - dir_backward if I2 can be replaced by I1, or @@ -1149,6 +1191,11 @@ old_insns_match_p (int mode ATTRIBUTE_UNUSED, rtx_insn *i1, rtx_insn *i2) else if (p1 || p2) return dir_none; + /* Do not allow cross-jumping between frame related insns and other + insns. */ + if (RTX_FRAME_RELATED_P (i1) != RTX_FRAME_RELATED_P (i2)) + return dir_none; + p1 = PATTERN (i1); p2 = PATTERN (i2); @@ -1207,6 +1254,11 @@ old_insns_match_p (int mode ATTRIBUTE_UNUSED, rtx_insn *i1, rtx_insn *i2) } } + /* If both i1 and i2 are frame related, verify all the CFA notes + in the same order and with the same content. */ + if (RTX_FRAME_RELATED_P (i1) && !insns_have_identical_cfa_notes (i1, i2)) + return dir_none; + #ifdef STACK_REGS /* If cross_jump_death_matters is not 0, the insn's mode indicates whether or not the insn contains any stack-like |