00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028 #include "config.h"
00029 #include "system.h"
00030 #include "obstack.h"
00031 #include "hashtab.h"
00032 #include "rtl.h"
00033 #include "hard-reg-set.h"
00034 #include "basic-block.h"
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064 struct conflict_graph_arc_def
00065 {
00066
00067
00068
00069 struct conflict_graph_arc_def *smaller_next;
00070
00071
00072
00073
00074 struct conflict_graph_arc_def *larger_next;
00075
00076
00077 int smaller;
00078
00079
00080 int larger;
00081 };
00082
00083 typedef struct conflict_graph_arc_def *conflict_graph_arc;
00084 typedef const struct conflict_graph_arc_def *const_conflict_graph_arc;
00085
00086
00087
00088
00089 struct conflict_graph_def
00090 {
00091
00092 htab_t arc_hash_table;
00093
00094
00095 int num_regs;
00096
00097
00098
00099
00100 conflict_graph_arc *neighbor_heads;
00101
00102
00103 struct obstack arc_obstack;
00104 };
00105
00106
00107
00108 #define INITIAL_ARC_CAPACITY 64
00109
00110
00111
00112
00113 #define CONFLICT_HASH_FN(R1, R2) ((R2) * ((R2) - 1) / 2 + (R1))
00114
00115 static hashval_t arc_hash PARAMS ((const void *));
00116 static int arc_eq PARAMS ((const void *, const void *));
00117 static int print_conflict PARAMS ((int, int, void *));
00118 static void mark_reg PARAMS ((rtx, rtx, void *));
00119
00120
00121
00122
00123 static hashval_t
00124 arc_hash (arcp)
00125 const void *arcp;
00126 {
00127 const_conflict_graph_arc arc = (const_conflict_graph_arc) arcp;
00128
00129 return CONFLICT_HASH_FN (arc->smaller, arc->larger);
00130 }
00131
00132
00133
00134
00135 static int
00136 arc_eq (arcp1, arcp2)
00137 const void *arcp1;
00138 const void *arcp2;
00139 {
00140 const_conflict_graph_arc arc1 = (const_conflict_graph_arc) arcp1;
00141 const_conflict_graph_arc arc2 = (const_conflict_graph_arc) arcp2;
00142
00143 return arc1->smaller == arc2->smaller && arc1->larger == arc2->larger;
00144 }
00145
00146
00147
00148
00149 conflict_graph
00150 conflict_graph_new (num_regs)
00151 int num_regs;
00152 {
00153 conflict_graph graph
00154 = (conflict_graph) xmalloc (sizeof (struct conflict_graph_def));
00155 graph->num_regs = num_regs;
00156
00157
00158
00159 graph->arc_hash_table
00160 = htab_create (INITIAL_ARC_CAPACITY, &arc_hash, &arc_eq, NULL);
00161
00162
00163 obstack_init (&graph->arc_obstack);
00164
00165
00166 graph->neighbor_heads
00167 = (conflict_graph_arc *) xmalloc (num_regs * sizeof (conflict_graph_arc));
00168
00169 memset (graph->neighbor_heads, 0, num_regs * sizeof (conflict_graph_arc));
00170 return graph;
00171 }
00172
00173
00174
00175 void
00176 conflict_graph_delete (graph)
00177 conflict_graph graph;
00178 {
00179 obstack_free (&graph->arc_obstack, NULL);
00180 htab_delete (graph->arc_hash_table);
00181 free (graph->neighbor_heads);
00182 free (graph);
00183 }
00184
00185
00186
00187
00188
00189 int
00190 conflict_graph_add (graph, reg1, reg2)
00191 conflict_graph graph;
00192 int reg1;
00193 int reg2;
00194 {
00195 int smaller = MIN (reg1, reg2);
00196 int larger = MAX (reg1, reg2);
00197 struct conflict_graph_arc_def dummy;
00198 conflict_graph_arc arc;
00199 void **slot;
00200
00201
00202 if (reg1 == reg2)
00203 abort ();
00204
00205 dummy.smaller = smaller;
00206 dummy.larger = larger;
00207 slot = htab_find_slot (graph->arc_hash_table, (void *) &dummy, INSERT);
00208
00209
00210 if (*slot != NULL)
00211 return 0;
00212
00213
00214 arc
00215 = (conflict_graph_arc)
00216 obstack_alloc (&graph->arc_obstack,
00217 sizeof (struct conflict_graph_arc_def));
00218
00219
00220 arc->smaller = smaller;
00221 arc->larger = larger;
00222
00223
00224 arc->smaller_next = graph->neighbor_heads[smaller];
00225 graph->neighbor_heads[smaller] = arc;
00226 arc->larger_next = graph->neighbor_heads[larger];
00227 graph->neighbor_heads[larger] = arc;
00228
00229
00230 *slot = (void *) arc;
00231
00232 return 1;
00233 }
00234
00235
00236
00237
00238 int
00239 conflict_graph_conflict_p (graph, reg1, reg2)
00240 conflict_graph graph;
00241 int reg1;
00242 int reg2;
00243 {
00244
00245 struct conflict_graph_arc_def arc;
00246 arc.smaller = MIN (reg1, reg2);
00247 arc.larger = MAX (reg1, reg2);
00248
00249 return htab_find (graph->arc_hash_table, (void *) &arc) != NULL;
00250 }
00251
00252
00253
00254
00255 void
00256 conflict_graph_enum (graph, reg, enum_fn, extra)
00257 conflict_graph graph;
00258 int reg;
00259 conflict_graph_enum_fn enum_fn;
00260 void *extra;
00261 {
00262 conflict_graph_arc arc = graph->neighbor_heads[reg];
00263 while (arc != NULL)
00264 {
00265
00266 if ((*enum_fn) (arc->smaller, arc->larger, extra))
00267
00268 break;
00269
00270
00271
00272 if (reg < arc->larger)
00273 arc = arc->smaller_next;
00274 else
00275 arc = arc->larger_next;
00276 }
00277 }
00278
00279
00280
00281
00282 void
00283 conflict_graph_merge_regs (graph, target, src)
00284 conflict_graph graph;
00285 int target;
00286 int src;
00287 {
00288 conflict_graph_arc arc = graph->neighbor_heads[src];
00289
00290 if (target == src)
00291 return;
00292
00293 while (arc != NULL)
00294 {
00295 int other = arc->smaller;
00296
00297 if (other == src)
00298 other = arc->larger;
00299
00300 conflict_graph_add (graph, target, other);
00301
00302
00303
00304 if (src < arc->larger)
00305 arc = arc->smaller_next;
00306 else
00307 arc = arc->larger_next;
00308 }
00309 }
00310
00311
00312
00313
00314 struct print_context
00315 {
00316
00317 FILE *fp;
00318
00319
00320 int reg;
00321
00322
00323 int started;
00324 };
00325
00326
00327
00328 static int
00329 print_conflict (reg1, reg2, contextp)
00330 int reg1;
00331 int reg2;
00332 void *contextp;
00333 {
00334 struct print_context *context = (struct print_context *) contextp;
00335 int reg;
00336
00337
00338
00339 if (! context->started)
00340 {
00341 fprintf (context->fp, " %d:", context->reg);
00342 context->started = 1;
00343 }
00344
00345
00346
00347 if (reg1 == context->reg)
00348 reg = reg2;
00349 else if (reg2 == context->reg)
00350 reg = reg1;
00351 else
00352 abort ();
00353
00354
00355 fprintf (context->fp, " %d", reg);
00356
00357
00358 return 0;
00359 }
00360
00361
00362
00363 void
00364 conflict_graph_print (graph, fp)
00365 conflict_graph graph;
00366 FILE *fp;
00367 {
00368 int reg;
00369 struct print_context context;
00370
00371 context.fp = fp;
00372 fprintf (fp, "Conflicts:\n");
00373
00374
00375 for (reg = 0; reg < graph->num_regs; ++reg)
00376 {
00377 context.reg = reg;
00378 context.started = 0;
00379
00380
00381
00382
00383
00384 conflict_graph_enum (graph, reg, &print_conflict, &context);
00385
00386
00387 if (context.started)
00388 fputc ('\n', fp);
00389 }
00390 }
00391
00392
00393
00394 static void
00395 mark_reg (reg, setter, data)
00396 rtx reg;
00397 rtx setter ATTRIBUTE_UNUSED;
00398 void *data;
00399 {
00400 regset set = (regset) data;
00401
00402 if (GET_CODE (reg) == SUBREG)
00403 reg = SUBREG_REG (reg);
00404
00405
00406 if (GET_CODE (reg) != REG)
00407 return;
00408
00409 SET_REGNO_REG_SET (set, REGNO (reg));
00410 }
00411
00412
00413
00414
00415
00416
00417
00418
00419
00420
00421
00422
00423
00424
00425
00426
00427
00428
00429
00430
00431
00432
00433
00434
00435
00436
00437
00438
00439
00440
00441 conflict_graph
00442 conflict_graph_compute (regs, p)
00443 regset regs;
00444 partition p;
00445 {
00446 conflict_graph graph = conflict_graph_new (max_reg_num ());
00447 regset_head live_head;
00448 regset live = &live_head;
00449 regset_head born_head;
00450 regset born = &born_head;
00451 basic_block bb;
00452
00453 INIT_REG_SET (live);
00454 INIT_REG_SET (born);
00455
00456 FOR_EACH_BB_REVERSE (bb)
00457 {
00458 rtx insn;
00459 rtx head;
00460
00461
00462
00463 COPY_REG_SET (live, bb->global_live_at_end);
00464 AND_REG_SET (live, regs);
00465
00466
00467 head = bb->head;
00468 insn = bb->end;
00469 for (insn = bb->end; insn != head; insn = PREV_INSN (insn))
00470 {
00471 int born_reg;
00472 int live_reg;
00473 rtx link;
00474
00475
00476 if (INSN_P (insn))
00477 {
00478
00479
00480
00481 CLEAR_REG_SET (born);
00482 note_stores (PATTERN (insn), mark_reg, born);
00483 AND_REG_SET (born, regs);
00484
00485
00486 AND_COMPL_REG_SET (live, born);
00487
00488
00489
00490 EXECUTE_IF_SET_IN_REG_SET
00491 (born, FIRST_PSEUDO_REGISTER, born_reg,
00492 {
00493 EXECUTE_IF_SET_IN_REG_SET
00494 (live, FIRST_PSEUDO_REGISTER, live_reg,
00495 {
00496
00497
00498 int b = partition_find (p, born_reg);
00499 int l = partition_find (p, live_reg);
00500
00501 if (b != l)
00502 conflict_graph_add (graph, b, l);
00503 });
00504 });
00505
00506
00507
00508
00509
00510 for (link = REG_NOTES (insn); link; link = XEXP (link, 1))
00511 if (REG_NOTE_KIND (link) == REG_DEAD)
00512 {
00513 unsigned int regno = REGNO (XEXP (link, 0));
00514
00515 if (REGNO_REG_SET_P (regs, regno))
00516 SET_REGNO_REG_SET (live, regno);
00517 }
00518 }
00519 }
00520 }
00521
00522 FREE_REG_SET (live);
00523 FREE_REG_SET (born);
00524
00525 return graph;
00526 }