summaryrefslogtreecommitdiff
path: root/0139-Backport-SME-mode-switching-Pass-set-of-live-registe.patch
blob: 037a4f781a524dfb95ab4afb31844ae7bbb6062d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
From a6964e11c7f624cdaed2c9608565a5968292b70f Mon Sep 17 00:00:00 2001
From: Richard Sandiford <richard.sandiford@arm.com>
Date: Sat, 11 Nov 2023 17:28:58 +0000
Subject: [PATCH 040/157] [Backport][SME] mode-switching: Pass set of live
 registers to the needed hook

Reference: https://gcc.gnu.org/git/?p=gcc.git;a=commit;h=29d3e1892ebec8abce784077d1f1a3e21d763218

The emit hook already takes the set of live hard registers as input.
This patch passes it to the needed hook too.  SME uses this to
optimise the mode choice based on whether state is live or dead.

The main caller already had access to the required info, but the
special handling of return values did not.

gcc/
	* target.def (mode_switching.needed): Add a regs_live parameter.
	* doc/tm.texi: Regenerate.
	* config/epiphany/epiphany-protos.h (epiphany_mode_needed): Update
	accordingly.
	* config/epiphany/epiphany.cc (epiphany_mode_needed): Likewise.
	* config/epiphany/mode-switch-use.cc (insert_uses): Likewise.
	* config/i386/i386.cc (ix86_mode_needed): Likewise.
	* config/riscv/riscv.cc (riscv_mode_needed): Likewise.
	* config/sh/sh.cc (sh_mode_needed): Likewise.
	* mode-switching.cc (optimize_mode_switching): Likewise.
	(create_pre_exit): Likewise, using the DF simulate functions
	to calculate the required information.
---
 gcc/config/epiphany/epiphany-protos.h  |  4 +++-
 gcc/config/epiphany/epiphany.cc        |  2 +-
 gcc/config/epiphany/mode-switch-use.cc |  2 +-
 gcc/config/i386/i386.cc                |  2 +-
 gcc/config/sh/sh.cc                    |  4 ++--
 gcc/doc/tm.texi                        |  5 +++--
 gcc/mode-switching.cc                  | 14 ++++++++++++--
 gcc/target.def                         |  5 +++--
 8 files changed, 26 insertions(+), 12 deletions(-)

diff --git a/gcc/config/epiphany/epiphany-protos.h b/gcc/config/epiphany/epiphany-protos.h
index 61b63234e..d463e5483 100644
--- a/gcc/config/epiphany/epiphany-protos.h
+++ b/gcc/config/epiphany/epiphany-protos.h
@@ -44,7 +44,9 @@ extern void emit_set_fp_mode (int entity, int mode, int prev_mode,
 #endif
 extern void epiphany_insert_mode_switch_use (rtx_insn *insn, int, int);
 extern void epiphany_expand_set_fp_mode (rtx *operands);
-extern int epiphany_mode_needed (int entity, rtx_insn *insn);
+#ifdef HARD_CONST
+extern int epiphany_mode_needed (int entity, rtx_insn *insn, HARD_REG_SET);
+#endif
 extern int epiphany_mode_after (int entity, int last_mode, rtx_insn *insn);
 extern bool epiphany_epilogue_uses (int regno);
 extern bool epiphany_optimize_mode_switching (int entity);
diff --git a/gcc/config/epiphany/epiphany.cc b/gcc/config/epiphany/epiphany.cc
index f8c049340..be0fbc68c 100644
--- a/gcc/config/epiphany/epiphany.cc
+++ b/gcc/config/epiphany/epiphany.cc
@@ -2400,7 +2400,7 @@ epiphany_mode_priority (int entity, int priority)
 }
 
 int
-epiphany_mode_needed (int entity, rtx_insn *insn)
+epiphany_mode_needed (int entity, rtx_insn *insn, HARD_REG_SET)
 {
   enum attr_fp_mode mode;
 
diff --git a/gcc/config/epiphany/mode-switch-use.cc b/gcc/config/epiphany/mode-switch-use.cc
index 887550a33..cacb1ce5a 100644
--- a/gcc/config/epiphany/mode-switch-use.cc
+++ b/gcc/config/epiphany/mode-switch-use.cc
@@ -58,7 +58,7 @@ insert_uses (void)
 	{
 	  if (!INSN_P (insn))
 	    continue;
-	  mode = epiphany_mode_needed (e, insn);
+	  mode = epiphany_mode_needed (e, insn, {});
 	  if (mode == no_mode)
 	    continue;
 	  if (target_insert_mode_switch_use)
diff --git a/gcc/config/i386/i386.cc b/gcc/config/i386/i386.cc
index 60f3296b0..4d591d217 100644
--- a/gcc/config/i386/i386.cc
+++ b/gcc/config/i386/i386.cc
@@ -14522,7 +14522,7 @@ ix86_i387_mode_needed (int entity, rtx_insn *insn)
    prior to the execution of insn.  */
 
 static int
-ix86_mode_needed (int entity, rtx_insn *insn)
+ix86_mode_needed (int entity, rtx_insn *insn, HARD_REG_SET)
 {
   switch (entity)
     {
diff --git a/gcc/config/sh/sh.cc b/gcc/config/sh/sh.cc
index 03e1c04ec..85e83e12e 100644
--- a/gcc/config/sh/sh.cc
+++ b/gcc/config/sh/sh.cc
@@ -195,7 +195,7 @@ static int calc_live_regs (HARD_REG_SET *);
 static HOST_WIDE_INT rounded_frame_size (int);
 static bool sh_frame_pointer_required (void);
 static void sh_emit_mode_set (int, int, int, HARD_REG_SET);
-static int sh_mode_needed (int, rtx_insn *);
+static int sh_mode_needed (int, rtx_insn *, HARD_REG_SET);
 static int sh_mode_after (int, int, rtx_insn *);
 static int sh_mode_entry (int);
 static int sh_mode_exit (int);
@@ -12529,7 +12529,7 @@ sh_emit_mode_set (int entity ATTRIBUTE_UNUSED, int mode,
 }
 
 static int
-sh_mode_needed (int entity ATTRIBUTE_UNUSED, rtx_insn *insn)
+sh_mode_needed (int entity ATTRIBUTE_UNUSED, rtx_insn *insn, HARD_REG_SET)
 {
   return recog_memoized (insn) >= 0  ? get_attr_fp_mode (insn) : FP_MODE_NONE;
 }
diff --git a/gcc/doc/tm.texi b/gcc/doc/tm.texi
index 4788b3f7a..d8ac6c4d6 100644
--- a/gcc/doc/tm.texi
+++ b/gcc/doc/tm.texi
@@ -10280,12 +10280,13 @@ known.  Sets of a lower numbered entity will be emitted before
 sets of a higher numbered entity to a mode of the same or lower priority.
 @end deftypefn
 
-@deftypefn {Target Hook} int TARGET_MODE_NEEDED (int @var{entity}, rtx_insn *@var{insn})
+@deftypefn {Target Hook} int TARGET_MODE_NEEDED (int @var{entity}, rtx_insn *@var{insn}, HARD_REG_SET @var{regs_live})
 @var{entity} is an integer specifying a mode-switched entity.
 If @code{OPTIMIZE_MODE_SWITCHING} is defined, you must define this hook
 to return the mode that @var{entity} must be switched into prior to the
 execution of @var{insn}, or the number of modes if @var{insn} has no
-such requirement.
+such requirement.  @var{regs_live} contains the set of hard registers
+that are live before @var{insn}.
 @end deftypefn
 
 @deftypefn {Target Hook} int TARGET_MODE_AFTER (int @var{entity}, int @var{mode}, rtx_insn *@var{insn})
diff --git a/gcc/mode-switching.cc b/gcc/mode-switching.cc
index 9a6ba6cca..6bbda5058 100644
--- a/gcc/mode-switching.cc
+++ b/gcc/mode-switching.cc
@@ -254,6 +254,9 @@ create_pre_exit (int n_entities, int *entity_map, const int *num_modes)
 	    && GET_CODE (PATTERN (last_insn)) == USE
 	    && GET_CODE ((ret_reg = XEXP (PATTERN (last_insn), 0))) == REG)
 	  {
+	    auto_bitmap live;
+	    df_simulate_initialize_backwards (src_bb, live);
+
 	    int ret_start = REGNO (ret_reg);
 	    int nregs = REG_NREGS (ret_reg);
 	    int ret_end = ret_start + nregs;
@@ -262,6 +265,8 @@ create_pre_exit (int n_entities, int *entity_map, const int *num_modes)
 	    bool forced_late_switch = false;
 	    rtx_insn *before_return_copy;
 
+	    df_simulate_one_insn_backwards (src_bb, last_insn, live);
+
 	    do
 	      {
 		rtx_insn *return_copy = PREV_INSN (last_insn);
@@ -269,6 +274,8 @@ create_pre_exit (int n_entities, int *entity_map, const int *num_modes)
 		int copy_start, copy_num;
 		int j;
 
+		df_simulate_one_insn_backwards (src_bb, return_copy, live);
+
 		if (NONDEBUG_INSN_P (return_copy))
 		  {
 		    /* When using SJLJ exceptions, the call to the
@@ -368,11 +375,14 @@ create_pre_exit (int n_entities, int *entity_map, const int *num_modes)
 		       the case for floating point on SH4 - then it might
 		       be set by an arithmetic operation that needs a
 		       different mode than the exit block.  */
+		    HARD_REG_SET hard_regs_live;
+		    REG_SET_TO_HARD_REG_SET (hard_regs_live, live);
 		    for (j = n_entities - 1; j >= 0; j--)
 		      {
 			int e = entity_map[j];
 			int mode =
-			  targetm.mode_switching.needed (e, return_copy);
+			  targetm.mode_switching.needed (e, return_copy,
+							 hard_regs_live);
 
 			if (mode != num_modes[e]
 			    && mode != targetm.mode_switching.exit (e))
@@ -609,7 +619,7 @@ optimize_mode_switching (void)
 	    {
 	      if (INSN_P (insn))
 		{
-		  int mode = targetm.mode_switching.needed (e, insn);
+		  int mode = targetm.mode_switching.needed (e, insn, live_now);
 		  rtx link;
 
 		  if (mode != no_mode && mode != last_mode)
diff --git a/gcc/target.def b/gcc/target.def
index bbb482de6..06a52bdaf 100644
--- a/gcc/target.def
+++ b/gcc/target.def
@@ -7003,8 +7003,9 @@ DEFHOOK
 If @code{OPTIMIZE_MODE_SWITCHING} is defined, you must define this hook\n\
 to return the mode that @var{entity} must be switched into prior to the\n\
 execution of @var{insn}, or the number of modes if @var{insn} has no\n\
-such requirement.",
- int, (int entity, rtx_insn *insn), NULL)
+such requirement.  @var{regs_live} contains the set of hard registers\n\
+that are live before @var{insn}.",
+ int, (int entity, rtx_insn *insn, HARD_REG_SET regs_live), NULL)
 
 DEFHOOK
 (after,
-- 
2.33.0