summaryrefslogtreecommitdiff
path: root/gcc/cfgcleanup.c
diff options
context:
space:
mode:
authorJakub Jelinek <jakub@redhat.com>2017-03-27 23:00:35 +0200
committerJakub Jelinek <jakub@gcc.gnu.org>2017-03-27 23:00:35 +0200
commitaade772d8a2eeda4ea22f0ca648ebdf44d8d8c15 (patch)
tree580908125ff2f800b4a09a1179d95a53ebb8aa20 /gcc/cfgcleanup.c
parente298b56acbe3e2534767462937d5674978979683 (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.c52
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