diff options
author | Felix Fietkau <nbd@nbd.name> | 2018-02-25 20:25:20 +0100 |
---|---|---|
committer | Felix Fietkau <nbd@nbd.name> | 2018-02-26 19:13:55 +0100 |
commit | 25aaff9100065dba881be71b9dcab1e9cc8a7b5f (patch) | |
tree | 74dc31493b9079261f6ef6ded6791f258f75d331 | |
parent | 38dc678166c8dbdb1f6bdbfd3f070c92f3fe0e04 (diff) | |
download | upstream-25aaff9100065dba881be71b9dcab1e9cc8a7b5f.tar.gz upstream-25aaff9100065dba881be71b9dcab1e9cc8a7b5f.tar.bz2 upstream-25aaff9100065dba881be71b9dcab1e9cc8a7b5f.zip |
gcc: merge upstream fix for PR 83496 (fixes FS#814)
This bug was causing miscompiled code related to branch delay slots
Signed-off-by: Felix Fietkau <nbd@nbd.name>
-rw-r--r-- | toolchain/gcc/patches/7.3.0/100-PR-rtl-optimization-83496.patch | 136 |
1 files changed, 136 insertions, 0 deletions
diff --git a/toolchain/gcc/patches/7.3.0/100-PR-rtl-optimization-83496.patch b/toolchain/gcc/patches/7.3.0/100-PR-rtl-optimization-83496.patch new file mode 100644 index 0000000000..466a731c50 --- /dev/null +++ b/toolchain/gcc/patches/7.3.0/100-PR-rtl-optimization-83496.patch @@ -0,0 +1,136 @@ +From: ebotcazou <ebotcazou@138bc75d-0d04-0410-961f-82ee72b054a4> +Date: Mon, 26 Feb 2018 16:29:30 +0000 +Subject: [PATCH] PR rtl-optimization/83496 * reorg.c + (steal_delay_list_from_target): Change REDUNDANT array from booleans to + RTXes. Call fix_reg_dead_note on every non-null element. + (steal_delay_list_from_fallthrough): Call fix_reg_dead_note on a + redundant insn, if any. (relax_delay_slots): Likewise. + (update_reg_unused_notes): Rename REDUNDANT_INSN to OTHER_INSN. + +git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@257996 138bc75d-0d04-0410-961f-82ee72b054a4 +--- + create mode 120000 gcc/testsuite/gcc.c-torture/execute/20180226-1.c + +--- a/gcc/reorg.c ++++ b/gcc/reorg.c +@@ -1035,7 +1035,8 @@ check_annul_list_true_false (int annul_t + + static void + steal_delay_list_from_target (rtx_insn *insn, rtx condition, rtx_sequence *seq, +- vec<rtx_insn *> *delay_list, resources *sets, ++ vec<rtx_insn *> *delay_list, ++ struct resources *sets, + struct resources *needed, + struct resources *other_needed, + int slots_to_fill, int *pslots_filled, +@@ -1048,7 +1049,7 @@ steal_delay_list_from_target (rtx_insn * + int used_annul = 0; + int i; + struct resources cc_set; +- bool *redundant; ++ rtx_insn **redundant; + + /* We can't do anything if there are more delay slots in SEQ than we + can handle, or if we don't know that it will be a taken branch. +@@ -1087,7 +1088,7 @@ steal_delay_list_from_target (rtx_insn * + if (! targetm.can_follow_jump (insn, seq->insn (0))) + return; + +- redundant = XALLOCAVEC (bool, XVECLEN (seq, 0)); ++ redundant = XALLOCAVEC (rtx_insn *, XVECLEN (seq, 0)); + for (i = 1; i < seq->len (); i++) + { + rtx_insn *trial = seq->insn (i); +@@ -1151,7 +1152,10 @@ steal_delay_list_from_target (rtx_insn * + we therefore decided not to copy. */ + for (i = 1; i < seq->len (); i++) + if (redundant[i]) +- update_block (seq->insn (i), insn); ++ { ++ fix_reg_dead_note (redundant[i], insn); ++ update_block (seq->insn (i), insn); ++ } + + /* Show the place to which we will be branching. */ + *pnew_thread = first_active_target_insn (JUMP_LABEL (seq->insn (0))); +@@ -1198,6 +1202,7 @@ steal_delay_list_from_fallthrough (rtx_i + for (i = 1; i < seq->len (); i++) + { + rtx_insn *trial = seq->insn (i); ++ rtx_insn *prior_insn; + + /* If TRIAL sets CC0, stealing it will move it too far from the use + of CC0. */ +@@ -1209,8 +1214,9 @@ steal_delay_list_from_fallthrough (rtx_i + break; + + /* If this insn was already done, we don't need it. */ +- if (redundant_insn (trial, insn, *delay_list)) ++ if ((prior_insn = redundant_insn (trial, insn, *delay_list))) + { ++ fix_reg_dead_note (prior_insn, insn); + update_block (trial, insn); + delete_from_delay_slot (trial); + continue; +@@ -1790,15 +1796,14 @@ fix_reg_dead_note (rtx_insn *start_insn, + } + } + +-/* Delete any REG_UNUSED notes that exist on INSN but not on REDUNDANT_INSN. ++/* Delete any REG_UNUSED notes that exist on INSN but not on OTHER_INSN. + + This handles the case of udivmodXi4 instructions which optimize their +- output depending on whether any REG_UNUSED notes are present. +- we must make sure that INSN calculates as many results as REDUNDANT_INSN +- does. */ ++ output depending on whether any REG_UNUSED notes are present. We must ++ make sure that INSN calculates as many results as OTHER_INSN does. */ + + static void +-update_reg_unused_notes (rtx_insn *insn, rtx redundant_insn) ++update_reg_unused_notes (rtx_insn *insn, rtx other_insn) + { + rtx link, next; + +@@ -1810,8 +1815,7 @@ update_reg_unused_notes (rtx_insn *insn, + || !REG_P (XEXP (link, 0))) + continue; + +- if (! find_regno_note (redundant_insn, REG_UNUSED, +- REGNO (XEXP (link, 0)))) ++ if (!find_regno_note (other_insn, REG_UNUSED, REGNO (XEXP (link, 0)))) + remove_note (insn, link); + } + } +@@ -2324,9 +2328,8 @@ follow_jumps (rtx label, rtx_insn *jump, + taken and THREAD_IF_TRUE is set. This is used for the branch at the + end of a loop back up to the top. + +- OWN_THREAD and OWN_OPPOSITE_THREAD are true if we are the only user of the +- thread. I.e., it is the fallthrough code of our jump or the target of the +- jump when we are the only jump going there. ++ OWN_THREAD is true if we are the only user of the thread, i.e. it is ++ the target of the jump when we are the only jump going there. + + If OWN_THREAD is false, it must be the "true" thread of a jump. In that + case, we can only take insns from the head of the thread for our delay +@@ -3117,7 +3120,7 @@ relax_delay_slots (rtx_insn *first) + /* Look at every JUMP_INSN and see if we can improve it. */ + for (insn = first; insn; insn = next) + { +- rtx_insn *other; ++ rtx_insn *other, *prior_insn; + bool crossing; + + next = next_active_insn (insn); +@@ -3223,8 +3226,9 @@ relax_delay_slots (rtx_insn *first) + /* See if the first insn in the delay slot is redundant with some + previous insn. Remove it from the delay slot if so; then set up + to reprocess this insn. */ +- if (redundant_insn (pat->insn (1), delay_insn, vNULL)) ++ if ((prior_insn = redundant_insn (pat->insn (1), delay_insn, vNULL))) + { ++ fix_reg_dead_note (prior_insn, insn); + update_block (pat->insn (1), insn); + delete_from_delay_slot (pat->insn (1)); + next = prev_active_insn (next); |