aboutsummaryrefslogtreecommitdiffstats
path: root/toolchain-layer/recipes-devtools/gcc/gcc-4.6/linaro/gcc-4.6-linaro-r106817.patch
blob: d44f8cf1a5b6720c8973365f62ac0c7bcbb74ff0 (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
2011-10-01  Revital Eres  <revital.eres@linaro.org> 

	gcc/
	Backport from mainline -r179380 and -r179381

	* ddg.c (autoinc_var_is_used_p): New function.
	(create_ddg_dep_from_intra_loop_link,
	add_cross_iteration_register_deps): Call it.
	* ddg.h (autoinc_var_is_used_p): Declare.
	* modulo-sched.c (sms_schedule): Handle instructions with REG_INC.
	(generate_reg_moves): Call autoinc_var_is_used_p.  Skip
	instructions that do not set a register and verify no regmoves
	are created for !single_set instructions.

	gcc/testsuite/

	* gcc.dg/sms-10.c: New file

=== modified file 'gcc/ddg.c'
--- old/gcc/ddg.c	2011-07-31 11:29:10 +0000
+++ new/gcc/ddg.c	2011-10-02 06:56:53 +0000
@@ -145,6 +145,27 @@
   return rtx_mem_access_p (PATTERN (insn));
 }
 
+/* Return true if DEF_INSN contains address being auto-inc or auto-dec
+   which is used in USE_INSN.  Otherwise return false.  The result is
+   being used to decide whether to remove the edge between def_insn and
+   use_insn when -fmodulo-sched-allow-regmoves is set.  This function
+   doesn't need to consider the specific address register; no reg_moves
+   will be allowed for any life range defined by def_insn and used
+   by use_insn, if use_insn uses an address register auto-inc'ed by
+   def_insn.  */
+bool
+autoinc_var_is_used_p (rtx def_insn, rtx use_insn)
+{
+  rtx note;
+
+  for (note = REG_NOTES (def_insn); note; note = XEXP (note, 1))
+    if (REG_NOTE_KIND (note) == REG_INC
+	&& reg_referenced_p (XEXP (note, 0), PATTERN (use_insn)))
+      return true;
+
+  return false;
+}
+
 /* Computes the dependence parameters (latency, distance etc.), creates
    a ddg_edge and adds it to the given DDG.  */
 static void
@@ -173,10 +194,15 @@
      compensate for that by generating reg-moves based on the life-range
      analysis.  The anti-deps that will be deleted are the ones which
      have true-deps edges in the opposite direction (in other words
-     the kernel has only one def of the relevant register).  TODO:
-     support the removal of all anti-deps edges, i.e. including those
+     the kernel has only one def of the relevant register).
+     If the address that is being auto-inc or auto-dec in DEST_NODE
+     is used in SRC_NODE then do not remove the edge to make sure
+     reg-moves will not be created for this address.  
+     TODO: support the removal of all anti-deps edges, i.e. including those
      whose register has multiple defs in the loop.  */
-  if (flag_modulo_sched_allow_regmoves && (t == ANTI_DEP && dt == REG_DEP))
+  if (flag_modulo_sched_allow_regmoves 
+      && (t == ANTI_DEP && dt == REG_DEP)
+      && !autoinc_var_is_used_p (dest_node->insn, src_node->insn))
     {
       rtx set;
 
@@ -302,10 +328,14 @@
 	  gcc_assert (first_def_node);
 
          /* Always create the edge if the use node is a branch in
-            order to prevent the creation of reg-moves.  */
+            order to prevent the creation of reg-moves.  
+            If the address that is being auto-inc or auto-dec in LAST_DEF
+            is used in USE_INSN then do not remove the edge to make sure
+            reg-moves will not be created for that address.  */
           if (DF_REF_ID (last_def) != DF_REF_ID (first_def)
               || !flag_modulo_sched_allow_regmoves
-	      || JUMP_P (use_node->insn))
+	      || JUMP_P (use_node->insn)
+              || autoinc_var_is_used_p (DF_REF_INSN (last_def), use_insn))
             create_ddg_dep_no_link (g, use_node, first_def_node, ANTI_DEP,
                                     REG_DEP, 1);
 

=== modified file 'gcc/ddg.h'
--- old/gcc/ddg.h	2009-11-25 10:55:54 +0000
+++ new/gcc/ddg.h	2011-10-02 06:56:53 +0000
@@ -186,4 +186,6 @@
 int find_nodes_on_paths (sbitmap result, ddg_ptr, sbitmap from, sbitmap to);
 int longest_simple_path (ddg_ptr, int from, int to, sbitmap via);
 
+bool autoinc_var_is_used_p (rtx, rtx);
+
 #endif /* GCC_DDG_H */

=== modified file 'gcc/modulo-sched.c'
--- old/gcc/modulo-sched.c	2011-09-14 11:06:06 +0000
+++ new/gcc/modulo-sched.c	2011-10-02 06:56:53 +0000
@@ -477,7 +477,12 @@
       sbitmap *uses_of_defs;
       rtx last_reg_move;
       rtx prev_reg, old_reg;
-
+      rtx set = single_set (u->insn);
+      
+      /* Skip instructions that do not set a register.  */
+      if ((set && !REG_P (SET_DEST (set))))
+        continue;
+ 
       /* Compute the number of reg_moves needed for u, by looking at life
 	 ranges started at u (excluding self-loops).  */
       for (e = u->out; e; e = e->next_out)
@@ -494,6 +499,20 @@
 		&& SCHED_COLUMN (e->dest) < SCHED_COLUMN (e->src))
 	      nreg_moves4e--;
 
+            if (nreg_moves4e >= 1)
+	      {
+		/* !single_set instructions are not supported yet and
+		   thus we do not except to encounter them in the loop
+		   except from the doloop part.  For the latter case
+		   we assume no regmoves are generated as the doloop
+		   instructions are tied to the branch with an edge.  */
+		gcc_assert (set);
+		/* If the instruction contains auto-inc register then
+		   validate that the regmov is being generated for the
+		   target regsiter rather then the inc'ed register.	*/
+		gcc_assert (!autoinc_var_is_used_p (u->insn, e->dest->insn));
+	      }
+	    
 	    nreg_moves = MAX (nreg_moves, nreg_moves4e);
 	  }
 
@@ -1266,12 +1285,10 @@
 	continue;
       }
 
-      /* Don't handle BBs with calls or barriers or auto-increment insns 
-	 (to avoid creating invalid reg-moves for the auto-increment insns),
+      /* Don't handle BBs with calls or barriers
 	 or !single_set with the exception of instructions that include
 	 count_reg---these instructions are part of the control part
 	 that do-loop recognizes.
-         ??? Should handle auto-increment insns.
          ??? Should handle insns defining subregs.  */
      for (insn = head; insn != NEXT_INSN (tail); insn = NEXT_INSN (insn))
       {
@@ -1282,7 +1299,6 @@
             || (NONDEBUG_INSN_P (insn) && !JUMP_P (insn)
                 && !single_set (insn) && GET_CODE (PATTERN (insn)) != USE
                 && !reg_mentioned_p (count_reg, insn))
-            || (FIND_REG_INC_NOTE (insn, NULL_RTX) != 0)
             || (INSN_P (insn) && (set = single_set (insn))
                 && GET_CODE (SET_DEST (set)) == SUBREG))
         break;
@@ -1296,8 +1312,6 @@
 		fprintf (dump_file, "SMS loop-with-call\n");
 	      else if (BARRIER_P (insn))
 		fprintf (dump_file, "SMS loop-with-barrier\n");
-              else if (FIND_REG_INC_NOTE (insn, NULL_RTX) != 0)
-                fprintf (dump_file, "SMS reg inc\n");
               else if ((NONDEBUG_INSN_P (insn) && !JUMP_P (insn)
                 && !single_set (insn) && GET_CODE (PATTERN (insn)) != USE))
                 fprintf (dump_file, "SMS loop-with-not-single-set\n");

=== added file 'gcc/testsuite/gcc.dg/sms-10.c'
--- old/gcc/testsuite/gcc.dg/sms-10.c	1970-01-01 00:00:00 +0000
+++ new/gcc/testsuite/gcc.dg/sms-10.c	2011-10-02 06:56:53 +0000
@@ -0,0 +1,118 @@
+ /* { dg-do run } */
+ /* { dg-options "-O2 -fmodulo-sched -fmodulo-sched-allow-regmoves -fdump-rtl-sms" } */
+
+
+typedef __SIZE_TYPE__ size_t;
+extern void *malloc (size_t);
+extern void free (void *);
+extern void abort (void);
+
+struct regstat_n_sets_and_refs_t
+{
+  int sets;
+  int refs;
+};
+
+struct regstat_n_sets_and_refs_t *regstat_n_sets_and_refs;
+
+struct df_reg_info
+{
+  unsigned int n_refs;
+};
+
+struct df_d
+{
+  struct df_reg_info **def_regs;
+  struct df_reg_info **use_regs;
+};
+struct df_d *df;
+
+static inline int
+REG_N_SETS (int regno)
+{
+  return regstat_n_sets_and_refs[regno].sets;
+}
+
+__attribute__ ((noinline))
+     int max_reg_num (void)
+{
+  return 100;
+}
+
+__attribute__ ((noinline))
+     void regstat_init_n_sets_and_refs (void)
+{
+  unsigned int i;
+  unsigned int max_regno = max_reg_num ();
+
+  for (i = 0; i < max_regno; i++)
+    {
+      (regstat_n_sets_and_refs[i].sets = (df->def_regs[(i)]->n_refs));
+      (regstat_n_sets_and_refs[i].refs =
+       (df->use_regs[(i)]->n_refs) + REG_N_SETS (i));
+    }
+}
+
+int a_sets[100] =
+  { 0, 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
+};
+
+int a_refs[100] =
+  { 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38,
+  40, 42, 44, 46, 48, 50, 52, 54, 56, 58, 60, 62, 64, 66, 68, 70, 72, 74, 76,
+  78, 80, 82,
+  84, 86, 88, 90, 92, 94, 96, 98, 100, 102, 104, 106, 108, 110, 112, 114, 116,
+  118, 120,
+  122, 124, 126, 128, 130, 132, 134, 136, 138, 140, 142, 144, 146, 148, 150,
+  152, 154, 156,
+  158, 160, 162, 164, 166, 168, 170, 172, 174, 176, 178, 180, 182, 184, 186,
+  188, 190, 192,
+  194, 196, 198
+};
+
+int
+main ()
+{
+  struct df_reg_info *b[100], *c[100];
+  struct df_d df1;
+  size_t s = sizeof (struct df_reg_info);
+  struct regstat_n_sets_and_refs_t a[100];
+
+  df = &df1;
+  regstat_n_sets_and_refs = a;
+  int i;
+
+  for (i = 0; i < 100; i++)
+    {
+      b[i] = (struct df_reg_info *) malloc (s);
+      b[i]->n_refs = i;
+      c[i] = (struct df_reg_info *) malloc (s);
+      c[i]->n_refs = i;
+    }
+
+  df1.def_regs = b;
+  df1.use_regs = c;
+  regstat_init_n_sets_and_refs ();
+
+  for (i = 0; i < 100; i++)
+    if ((a[i].sets != a_sets[i]) || (a[i].refs != a_refs[i]))
+      abort ();
+
+  for (i = 0; i < 100; i++)
+    {
+      free (b[i]);
+      free (c[i]);
+    }
+
+  return 0;
+}
+
+/* { dg-final { scan-rtl-dump-times "SMS succeeded" 1 "sms" { target powerpc*-*-* } } } */
+/* { dg-final { cleanup-rtl-dump "sms" } } */