summaryrefslogtreecommitdiff
path: root/patches/gcc/6.2.0/871-xtensa-Fix-PR-target-78118.patch
blob: c6ae103a766935358f51a23dd631dda51b01fa49 (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
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
From bdda1689faf608ad7c83b5bd2e21a236b0047579 Mon Sep 17 00:00:00 2001
From: Max Filippov <jcmvbkbc@gmail.com>
Date: Wed, 26 Oct 2016 08:02:51 +0000
Subject: [PATCH] xtensa: Fix PR target/78118

It started failing after the following commit: 32e90dc6a0cda45 ("PR
rtl-optimization/61047").

The change that made xtensa backend go ICE looks completely unrelated,
and indeed, the issue is caused by the side effect of
compute_frame_size() function call hidden in the
INITIAL_ELIMINATION_OFFSET macro. This call updates the value of the
xtensa_current_frame_size static variable, used in "return" instruction
predicate. Prior to the change the value of xtensa_current_frame_size was
set to 0 after the end of epilogue generation, which enabled the "return"
instruction for the CALL0 ABI, but after the change the additional
INITIAL_ELIMINATION_OFFSET calls make xtensa_current_frame_size non-zero
and "return" pattern unavailable.

Get rid of the global xtensa_current_frame_size and
xtensa_callee_save_size variables by moving them into the
machine_function structure. Implement predicate for the "return" pattern
as a function. Don't communicate completion of epilogue generation
through zeroing of xtensa_current_frame_size, add explicit epilogue_done
variable to the machine_function structure. Don't update stack frame
layout after the completion of reload.

2016-10-26  Max Filippov  <jcmvbkbc@gmail.com>
gcc/
	* config/xtensa/xtensa-protos.h
	(xtensa_use_return_instruction_p): New prototype.
	* config/xtensa/xtensa.c (xtensa_current_frame_size,
	xtensa_callee_save_size): Remove.
	(struct machine_function): Add new fields: current_frame_size,
	callee_save_size, frame_laid_out and epilogue_done.
	(compute_frame_size, xtensa_expand_prologue,
	xtensa_expand_epilogue): Replace xtensa_callee_save_size with
	cfun->machine->callee_save_size and xtensa_current_frame_size
	with cfun->machine->current_frame_size.
	(compute_frame_size): Update cfun->machine->frame_laid_out and
	don't update frame layout after reload completion.
	(xtensa_expand_epilogue): Set cfun->machine->epilogue_done
	instead of zeroing xtensa_current_frame_size.
	(xtensa_use_return_instruction_p): New function.
	* config/xtensa/xtensa.h (xtensa_current_frame_size): Remove
	declaration.
	(INITIAL_ELIMINATION_OFFSET): Use return value of
	compute_frame_size instead of xtensa_current_frame_size value.
	* config/xtensa/xtensa.md ("return" pattern): Use new predicate
	function xtensa_use_return_instruction_p instead of inline code.

Signed-off-by: Max Filippov <jcmvbkbc@gmail.com>
---
 gcc/config/xtensa/xtensa-protos.h |  1 +
 gcc/config/xtensa/xtensa.c        | 82 ++++++++++++++++++++++++---------------
 gcc/config/xtensa/xtensa.h        |  6 +--
 gcc/config/xtensa/xtensa.md       |  2 +-
 4 files changed, 55 insertions(+), 36 deletions(-)

diff --git a/gcc/config/xtensa/xtensa-protos.h b/gcc/config/xtensa/xtensa-protos.h
index f2ca526..873557f 100644
--- a/gcc/config/xtensa/xtensa-protos.h
+++ b/gcc/config/xtensa/xtensa-protos.h
@@ -68,6 +68,7 @@ extern rtx xtensa_return_addr (int, rtx);
 extern void xtensa_setup_frame_addresses (void);
 extern int xtensa_dbx_register_number (int);
 extern long compute_frame_size (int);
+extern bool xtensa_use_return_instruction_p (void);
 extern void xtensa_expand_prologue (void);
 extern void xtensa_expand_epilogue (void);
 extern void order_regs_for_local_alloc (void);
diff --git a/gcc/config/xtensa/xtensa.c b/gcc/config/xtensa/xtensa.c
index 64d089b..e49f784 100644
--- a/gcc/config/xtensa/xtensa.c
+++ b/gcc/config/xtensa/xtensa.c
@@ -78,11 +78,6 @@ enum internal_test
    can support a given mode.  */
 char xtensa_hard_regno_mode_ok[(int) MAX_MACHINE_MODE][FIRST_PSEUDO_REGISTER];
 
-/* Current frame size calculated by compute_frame_size.  */
-unsigned xtensa_current_frame_size;
-/* Callee-save area size in the current frame calculated by compute_frame_size. */
-int xtensa_callee_save_size;
-
 /* Largest block move to handle in-line.  */
 #define LARGEST_MOVE_RATIO 15
 
@@ -94,6 +89,13 @@ struct GTY(()) machine_function
   bool vararg_a7;
   rtx vararg_a7_copy;
   rtx_insn *set_frame_ptr_insn;
+  /* Current frame size calculated by compute_frame_size.  */
+  unsigned current_frame_size;
+  /* Callee-save area size in the current frame calculated by
+     compute_frame_size.  */
+  int callee_save_size;
+  bool frame_laid_out;
+  bool epilogue_done;
 };
 
 /* Vector, indexed by hard register number, which contains 1 for a
@@ -2628,24 +2630,29 @@ compute_frame_size (int size)
 {
   int regno;
 
+  if (reload_completed && cfun->machine->frame_laid_out)
+    return cfun->machine->current_frame_size;
+
   /* Add space for the incoming static chain value.  */
   if (cfun->static_chain_decl != NULL)
     size += (1 * UNITS_PER_WORD);
 
-  xtensa_callee_save_size = 0;
+  cfun->machine->callee_save_size = 0;
   for (regno = 0; regno < FIRST_PSEUDO_REGISTER; ++regno)
     {
       if (xtensa_call_save_reg(regno))
-	xtensa_callee_save_size += UNITS_PER_WORD;
+	cfun->machine->callee_save_size += UNITS_PER_WORD;
     }
 
-  xtensa_current_frame_size =
+  cfun->machine->current_frame_size =
     XTENSA_STACK_ALIGN (size
-			+ xtensa_callee_save_size
+			+ cfun->machine->callee_save_size
 			+ crtl->outgoing_args_size
 			+ (WINDOW_SIZE * UNITS_PER_WORD));
-  xtensa_callee_save_size = XTENSA_STACK_ALIGN (xtensa_callee_save_size);
-  return xtensa_current_frame_size;
+  cfun->machine->callee_save_size =
+    XTENSA_STACK_ALIGN (cfun->machine->callee_save_size);
+  cfun->machine->frame_laid_out = true;
+  return cfun->machine->current_frame_size;
 }
 
 
@@ -2696,6 +2703,7 @@ xtensa_expand_prologue (void)
     {
       int regno;
       HOST_WIDE_INT offset = 0;
+      int callee_save_size = cfun->machine->callee_save_size;
 
       /* -128 is a limit of single addi instruction. */
       if (total_size > 0 && total_size <= 128)
@@ -2709,7 +2717,7 @@ xtensa_expand_prologue (void)
 	  add_reg_note (insn, REG_FRAME_RELATED_EXPR, note_rtx);
 	  offset = total_size - UNITS_PER_WORD;
 	}
-      else if (xtensa_callee_save_size)
+      else if (callee_save_size)
 	{
 	  /* 1020 is maximal s32i offset, if the frame is bigger than that
 	   * we move sp to the end of callee-saved save area, save and then
@@ -2717,13 +2725,13 @@ xtensa_expand_prologue (void)
 	  if (total_size > 1024)
 	    {
 	      insn = emit_insn (gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx,
-					    GEN_INT (-xtensa_callee_save_size)));
+					    GEN_INT (-callee_save_size)));
 	      RTX_FRAME_RELATED_P (insn) = 1;
 	      note_rtx = gen_rtx_SET (stack_pointer_rtx,
 				      plus_constant (Pmode, stack_pointer_rtx,
-						     -xtensa_callee_save_size));
+						     -callee_save_size));
 	      add_reg_note (insn, REG_FRAME_RELATED_EXPR, note_rtx);
-	      offset = xtensa_callee_save_size - UNITS_PER_WORD;
+	      offset = callee_save_size - UNITS_PER_WORD;
 	    }
 	  else
 	    {
@@ -2759,13 +2767,13 @@ xtensa_expand_prologue (void)
 	{
 	  rtx tmp_reg = gen_rtx_REG (Pmode, A9_REG);
 	  emit_move_insn (tmp_reg, GEN_INT (total_size -
-					    xtensa_callee_save_size));
+					    callee_save_size));
 	  insn = emit_insn (gen_subsi3 (stack_pointer_rtx,
 					stack_pointer_rtx, tmp_reg));
 	  RTX_FRAME_RELATED_P (insn) = 1;
 	  note_rtx = gen_rtx_SET (stack_pointer_rtx,
 				  plus_constant (Pmode, stack_pointer_rtx,
-						 xtensa_callee_save_size -
+						 callee_save_size -
 						 total_size));
 	  add_reg_note (insn, REG_FRAME_RELATED_EXPR, note_rtx);
 	}
@@ -2833,21 +2841,21 @@ xtensa_expand_epilogue (void)
       int regno;
       HOST_WIDE_INT offset;
 
-      if (xtensa_current_frame_size > (frame_pointer_needed ? 127 : 1024))
+      if (cfun->machine->current_frame_size > (frame_pointer_needed ? 127 : 1024))
 	{
 	  rtx tmp_reg = gen_rtx_REG (Pmode, A9_REG);
-	  emit_move_insn (tmp_reg, GEN_INT (xtensa_current_frame_size -
-					    xtensa_callee_save_size));
+	  emit_move_insn (tmp_reg, GEN_INT (cfun->machine->current_frame_size -
+					    cfun->machine->callee_save_size));
 	  emit_insn (gen_addsi3 (stack_pointer_rtx, frame_pointer_needed ?
 				 hard_frame_pointer_rtx : stack_pointer_rtx,
 				 tmp_reg));
-	  offset = xtensa_callee_save_size - UNITS_PER_WORD;
+	  offset = cfun->machine->callee_save_size - UNITS_PER_WORD;
 	}
       else
 	{
 	  if (frame_pointer_needed)
 	    emit_move_insn (stack_pointer_rtx, hard_frame_pointer_rtx);
-	  offset = xtensa_current_frame_size - UNITS_PER_WORD;
+	  offset = cfun->machine->current_frame_size - UNITS_PER_WORD;
 	}
 
       /* Prevent reordering of saved a0 update and loading it back from
@@ -2867,16 +2875,16 @@ xtensa_expand_epilogue (void)
 	    }
 	}
 
-      if (xtensa_current_frame_size > 0)
+      if (cfun->machine->current_frame_size > 0)
 	{
 	  if (frame_pointer_needed || /* always reachable with addi */
-	      xtensa_current_frame_size > 1024 ||
-	      xtensa_current_frame_size <= 127)
+	      cfun->machine->current_frame_size > 1024 ||
+	      cfun->machine->current_frame_size <= 127)
 	    {
-	      if (xtensa_current_frame_size <= 127)
-		offset = xtensa_current_frame_size;
+	      if (cfun->machine->current_frame_size <= 127)
+		offset = cfun->machine->current_frame_size;
 	      else
-		offset = xtensa_callee_save_size;
+		offset = cfun->machine->callee_save_size;
 
 	      emit_insn (gen_addsi3 (stack_pointer_rtx,
 				     stack_pointer_rtx,
@@ -2885,7 +2893,8 @@ xtensa_expand_epilogue (void)
 	  else
 	    {
 	      rtx tmp_reg = gen_rtx_REG (Pmode, A9_REG);
-	      emit_move_insn (tmp_reg, GEN_INT (xtensa_current_frame_size));
+	      emit_move_insn (tmp_reg,
+			      GEN_INT (cfun->machine->current_frame_size));
 	      emit_insn (gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx,
 				     tmp_reg));
 	    }
@@ -2896,11 +2905,22 @@ xtensa_expand_epilogue (void)
 				  stack_pointer_rtx,
 				  EH_RETURN_STACKADJ_RTX));
     }
-  xtensa_current_frame_size = 0;
-  xtensa_callee_save_size = 0;
+  cfun->machine->epilogue_done = true;
   emit_jump_insn (gen_return ());
 }
 
+bool
+xtensa_use_return_instruction_p (void)
+{
+  if (!reload_completed)
+    return false;
+  if (TARGET_WINDOWED_ABI)
+    return true;
+  if (compute_frame_size (get_frame_size ()) == 0)
+    return true;
+  return cfun->machine->epilogue_done;
+}
+
 void
 xtensa_set_return_address (rtx address, rtx scratch)
 {
diff --git a/gcc/config/xtensa/xtensa.h b/gcc/config/xtensa/xtensa.h
index 82e9900..58eb1b2 100644
--- a/gcc/config/xtensa/xtensa.h
+++ b/gcc/config/xtensa/xtensa.h
@@ -23,8 +23,6 @@ along with GCC; see the file COPYING3.  If not see
 
 /* External variables defined in xtensa.c.  */
 
-extern unsigned xtensa_current_frame_size;
-
 /* Macros used in the machine description to select various Xtensa
    configuration options.  */
 #ifndef XCHAL_HAVE_MUL32_HIGH
@@ -477,14 +475,14 @@ enum reg_class
 /* Specify the initial difference between the specified pair of registers.  */
 #define INITIAL_ELIMINATION_OFFSET(FROM, TO, OFFSET)			\
   do {									\
-    compute_frame_size (get_frame_size ());				\
+    long frame_size = compute_frame_size (get_frame_size ());		\
     switch (FROM)							\
       {									\
       case FRAME_POINTER_REGNUM:					\
         (OFFSET) = 0;							\
 	break;								\
       case ARG_POINTER_REGNUM:						\
-        (OFFSET) = xtensa_current_frame_size;				\
+        (OFFSET) = frame_size;						\
 	break;								\
       default:								\
 	gcc_unreachable ();						\
diff --git a/gcc/config/xtensa/xtensa.md b/gcc/config/xtensa/xtensa.md
index db54a12..fcdb6c8 100644
--- a/gcc/config/xtensa/xtensa.md
+++ b/gcc/config/xtensa/xtensa.md
@@ -1663,7 +1663,7 @@
 (define_insn "return"
   [(return)
    (use (reg:SI A0_REG))]
-  "(TARGET_WINDOWED_ABI || !xtensa_current_frame_size) && reload_completed"
+  "xtensa_use_return_instruction_p ()"
 {
   return TARGET_WINDOWED_ABI ?
       (TARGET_DENSITY ? "retw.n" : "retw") :
-- 
2.1.4