diff options
Diffstat (limited to '0135-Backport-SME-mode-switching-Fix-the-mode-passed-to-t.patch')
-rw-r--r-- | 0135-Backport-SME-mode-switching-Fix-the-mode-passed-to-t.patch | 136 |
1 files changed, 136 insertions, 0 deletions
diff --git a/0135-Backport-SME-mode-switching-Fix-the-mode-passed-to-t.patch b/0135-Backport-SME-mode-switching-Fix-the-mode-passed-to-t.patch new file mode 100644 index 0000000..c1b4036 --- /dev/null +++ b/0135-Backport-SME-mode-switching-Fix-the-mode-passed-to-t.patch @@ -0,0 +1,136 @@ +From 194700063ed04b56d84912f7ace1b8370af6c696 Mon Sep 17 00:00:00 2001 +From: Richard Sandiford <richard.sandiford@arm.com> +Date: Sat, 11 Nov 2023 17:28:56 +0000 +Subject: [PATCH 036/157] [Backport][SME] mode-switching: Fix the mode passed + to the emit hook + +Reference: https://gcc.gnu.org/git/?p=gcc.git;a=commit;h=5afd208beaef50bcc43b556d4c41d41656b06436 + +optimize_mode_switching passes an entity's current mode (if known) +to the emit hook. However, the mode that it passed ignored the +effect of the after hook. Instead, the mode for the first emit +call in a block was taken from the incoming mode, whereas the +mode for each subsequent emit call was taken from the result +of the previous call. + +The previous pass through the insns already calculated the +correct mode, so this patch records it in the seginfo structure. +(There was a 32-bit hole on 64-bit hosts, so this doesn't increase +the size of the structure for them.) + +gcc/ + * mode-switching.cc (seginfo): Add a prev_mode field. + (new_seginfo): Take and initialize the prev_mode. + (optimize_mode_switching): Update calls accordingly. + Use the recorded modes during the emit phase, rather than + computing one on the fly. +--- + gcc/mode-switching.cc | 30 +++++++++++++++++------------- + 1 file changed, 17 insertions(+), 13 deletions(-) + +diff --git a/gcc/mode-switching.cc b/gcc/mode-switching.cc +index 6a13951c9..584cd4f67 100644 +--- a/gcc/mode-switching.cc ++++ b/gcc/mode-switching.cc +@@ -68,6 +68,7 @@ along with GCC; see the file COPYING3. If not see + NEXT is the next insn in the same basic block. */ + struct seginfo + { ++ int prev_mode; + int mode; + rtx_insn *insn_ptr; + struct seginfo *next; +@@ -140,20 +141,22 @@ commit_mode_sets (struct edge_list *edge_list, int e, struct bb_info *info) + return need_commit; + } + +-/* Allocate a new BBINFO structure, initialized with the MODE, INSN, +- and REGS_LIVE parameters. ++/* Allocate a new BBINFO structure, initialized with the PREV_MODE, MODE, ++ INSN, and REGS_LIVE parameters. + INSN may not be a NOTE_INSN_BASIC_BLOCK, unless it is an empty + basic block; that allows us later to insert instructions in a FIFO-like + manner. */ + + static struct seginfo * +-new_seginfo (int mode, rtx_insn *insn, const HARD_REG_SET ®s_live) ++new_seginfo (int prev_mode, int mode, rtx_insn *insn, ++ const HARD_REG_SET ®s_live) + { + struct seginfo *ptr; + + gcc_assert (!NOTE_INSN_BASIC_BLOCK_P (insn) + || insn == BB_END (NOTE_BASIC_BLOCK (insn))); + ptr = XNEW (struct seginfo); ++ ptr->prev_mode = prev_mode; + ptr->mode = mode; + ptr->insn_ptr = insn; + ptr->next = NULL; +@@ -589,7 +592,7 @@ optimize_mode_switching (void) + gcc_assert (NOTE_INSN_BASIC_BLOCK_P (ins_pos)); + if (ins_pos != BB_END (bb)) + ins_pos = NEXT_INSN (ins_pos); +- ptr = new_seginfo (no_mode, ins_pos, live_now); ++ ptr = new_seginfo (no_mode, no_mode, ins_pos, live_now); + add_seginfo (&tail_ptr, ptr); + for (i = 0; i < no_mode; i++) + clear_mode_bit (transp[bb->index], j, i); +@@ -605,12 +608,12 @@ optimize_mode_switching (void) + + if (mode != no_mode && mode != last_mode) + { +- any_set_required = true; +- last_mode = mode; +- ptr = new_seginfo (mode, insn, live_now); ++ ptr = new_seginfo (last_mode, mode, insn, live_now); + add_seginfo (&tail_ptr, ptr); + for (i = 0; i < no_mode; i++) + clear_mode_bit (transp[bb->index], j, i); ++ any_set_required = true; ++ last_mode = mode; + } + + if (targetm.mode_switching.after) +@@ -636,7 +639,7 @@ optimize_mode_switching (void) + mark the block as nontransparent. */ + if (!any_set_required) + { +- ptr = new_seginfo (no_mode, BB_END (bb), live_now); ++ ptr = new_seginfo (last_mode, no_mode, BB_END (bb), live_now); + add_seginfo (&tail_ptr, ptr); + if (last_mode != no_mode) + for (i = 0; i < no_mode; i++) +@@ -777,9 +780,9 @@ optimize_mode_switching (void) + FOR_EACH_BB_FN (bb, cfun) + { + struct seginfo *ptr, *next; +- int cur_mode = bb_info[j][bb->index].mode_in; ++ struct seginfo *first = bb_info[j][bb->index].seginfo; + +- for (ptr = bb_info[j][bb->index].seginfo; ptr; ptr = next) ++ for (ptr = first; ptr; ptr = next) + { + next = ptr->next; + if (ptr->mode != no_mode) +@@ -789,14 +792,15 @@ optimize_mode_switching (void) + rtl_profile_for_bb (bb); + start_sequence (); + ++ int cur_mode = (ptr == first && ptr->prev_mode == no_mode ++ ? bb_info[j][bb->index].mode_in ++ : ptr->prev_mode); ++ + targetm.mode_switching.emit (entity_map[j], ptr->mode, + cur_mode, ptr->regs_live); + mode_set = get_insns (); + end_sequence (); + +- /* modes kill each other inside a basic block. */ +- cur_mode = ptr->mode; +- + /* Insert MODE_SET only if it is nonempty. */ + if (mode_set != NULL_RTX) + { +-- +2.33.0 + |