summaryrefslogtreecommitdiff
path: root/0135-Backport-SME-mode-switching-Fix-the-mode-passed-to-t.patch
diff options
context:
space:
mode:
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.patch136
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 &regs_live)
++new_seginfo (int prev_mode, int mode, rtx_insn *insn,
++ const HARD_REG_SET &regs_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
+