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
00029
00030
00031
00032
00033
00034
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
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078 #include "config.h"
00079 #include "system.h"
00080 #include "coretypes.h"
00081 #include "tm.h"
00082 #include "ggc.h"
00083 #include "tree.h"
00084
00085
00086 #include "rtl.h"
00087 #include "basic-block.h"
00088 #include "diagnostic.h"
00089 #include "tree-flow.h"
00090 #include "tree-dump.h"
00091 #include "timevar.h"
00092 #include "cfgloop.h"
00093 #include "tree-chrec.h"
00094 #include "tree-data-ref.h"
00095 #include "tree-scalar-evolution.h"
00096 #include "tree-pass.h"
00097
00098 static struct datadep_stats
00099 {
00100 int num_dependence_tests;
00101 int num_dependence_dependent;
00102 int num_dependence_independent;
00103 int num_dependence_undetermined;
00104
00105 int num_subscript_tests;
00106 int num_subscript_undetermined;
00107 int num_same_subscript_function;
00108
00109 int num_ziv;
00110 int num_ziv_independent;
00111 int num_ziv_dependent;
00112 int num_ziv_unimplemented;
00113
00114 int num_siv;
00115 int num_siv_independent;
00116 int num_siv_dependent;
00117 int num_siv_unimplemented;
00118
00119 int num_miv;
00120 int num_miv_independent;
00121 int num_miv_dependent;
00122 int num_miv_unimplemented;
00123 } dependence_stats;
00124
00125 static tree object_analysis (tree, tree, bool, struct data_reference **,
00126 tree *, tree *, tree *, tree *, tree *,
00127 struct ptr_info_def **, subvar_t *);
00128 static struct data_reference * init_data_ref (tree, tree, tree, tree, bool,
00129 tree, tree, tree, tree, tree,
00130 struct ptr_info_def *,
00131 enum data_ref_type);
00132 static bool subscript_dependence_tester_1 (struct data_dependence_relation *,
00133 struct data_reference *,
00134 struct data_reference *);
00135
00136
00137
00138
00139 static bool
00140 ptr_decl_may_alias_p (tree ptr, tree decl,
00141 struct data_reference *ptr_dr,
00142 bool *aliased)
00143 {
00144 tree tag = NULL_TREE;
00145 struct ptr_info_def *pi = DR_PTR_INFO (ptr_dr);
00146
00147 gcc_assert (TREE_CODE (ptr) == SSA_NAME && DECL_P (decl));
00148
00149 if (pi)
00150 tag = pi->name_mem_tag;
00151 if (!tag)
00152 tag = get_var_ann (SSA_NAME_VAR (ptr))->symbol_mem_tag;
00153 if (!tag)
00154 tag = DR_MEMTAG (ptr_dr);
00155 if (!tag)
00156 return false;
00157
00158 *aliased = is_aliased_with (tag, decl);
00159 return true;
00160 }
00161
00162
00163
00164
00165
00166 static bool
00167 ptr_ptr_may_alias_p (tree ptr_a, tree ptr_b,
00168 struct data_reference *dra,
00169 struct data_reference *drb,
00170 bool *aliased)
00171 {
00172 tree tag_a = NULL_TREE, tag_b = NULL_TREE;
00173 struct ptr_info_def *pi_a = DR_PTR_INFO (dra);
00174 struct ptr_info_def *pi_b = DR_PTR_INFO (drb);
00175
00176 if (pi_a && pi_a->name_mem_tag && pi_b && pi_b->name_mem_tag)
00177 {
00178 tag_a = pi_a->name_mem_tag;
00179 tag_b = pi_b->name_mem_tag;
00180 }
00181 else
00182 {
00183 tag_a = get_var_ann (SSA_NAME_VAR (ptr_a))->symbol_mem_tag;
00184 if (!tag_a)
00185 tag_a = DR_MEMTAG (dra);
00186 if (!tag_a)
00187 return false;
00188
00189 tag_b = get_var_ann (SSA_NAME_VAR (ptr_b))->symbol_mem_tag;
00190 if (!tag_b)
00191 tag_b = DR_MEMTAG (drb);
00192 if (!tag_b)
00193 return false;
00194 }
00195
00196 if (tag_a == tag_b)
00197 *aliased = true;
00198 else
00199 *aliased = may_aliases_intersect (tag_a, tag_b);
00200
00201 return true;
00202 }
00203
00204
00205
00206
00207
00208 static bool
00209 may_alias_p (tree base_a, tree base_b,
00210 struct data_reference *dra,
00211 struct data_reference *drb,
00212 bool *aliased)
00213 {
00214 if (TREE_CODE (base_a) == ADDR_EXPR || TREE_CODE (base_b) == ADDR_EXPR)
00215 {
00216 if (TREE_CODE (base_a) == ADDR_EXPR && TREE_CODE (base_b) == ADDR_EXPR)
00217 {
00218 *aliased = (TREE_OPERAND (base_a, 0) == TREE_OPERAND (base_b, 0));
00219 return true;
00220 }
00221 if (TREE_CODE (base_a) == ADDR_EXPR)
00222 return ptr_decl_may_alias_p (base_b, TREE_OPERAND (base_a, 0), drb,
00223 aliased);
00224 else
00225 return ptr_decl_may_alias_p (base_a, TREE_OPERAND (base_b, 0), dra,
00226 aliased);
00227 }
00228
00229 return ptr_ptr_may_alias_p (base_a, base_b, dra, drb, aliased);
00230 }
00231
00232
00233
00234
00235 static bool
00236 record_ptr_differ_p (struct data_reference *dra,
00237 struct data_reference *drb)
00238 {
00239 bool aliased;
00240 tree base_a = DR_BASE_OBJECT (dra);
00241 tree base_b = DR_BASE_OBJECT (drb);
00242
00243 if (TREE_CODE (base_b) != COMPONENT_REF)
00244 return false;
00245
00246
00247
00248
00249 while (TREE_CODE (base_b) == COMPONENT_REF)
00250 base_b = TREE_OPERAND (base_b, 0);
00251
00252
00253 if (TREE_CODE (base_a) == INDIRECT_REF
00254 && ((TREE_CODE (base_b) == VAR_DECL
00255 && (ptr_decl_may_alias_p (TREE_OPERAND (base_a, 0), base_b, dra,
00256 &aliased)
00257 && !aliased))
00258 || (TREE_CODE (base_b) == INDIRECT_REF
00259 && (ptr_ptr_may_alias_p (TREE_OPERAND (base_a, 0),
00260 TREE_OPERAND (base_b, 0), dra, drb,
00261 &aliased)
00262 && !aliased))))
00263 return true;
00264 else
00265 return false;
00266 }
00267
00268
00269
00270 static bool
00271 record_record_differ_p (struct data_reference *dra,
00272 struct data_reference *drb)
00273 {
00274 bool aliased;
00275 tree base_a = DR_BASE_OBJECT (dra);
00276 tree base_b = DR_BASE_OBJECT (drb);
00277
00278 if (TREE_CODE (base_b) != COMPONENT_REF
00279 || TREE_CODE (base_a) != COMPONENT_REF)
00280 return false;
00281
00282
00283
00284
00285 while (TREE_CODE (base_b) == COMPONENT_REF)
00286 base_b = TREE_OPERAND (base_b, 0);
00287 while (TREE_CODE (base_a) == COMPONENT_REF)
00288 base_a = TREE_OPERAND (base_a, 0);
00289
00290 if (TREE_CODE (base_a) == INDIRECT_REF
00291 && TREE_CODE (base_b) == INDIRECT_REF
00292 && ptr_ptr_may_alias_p (TREE_OPERAND (base_a, 0),
00293 TREE_OPERAND (base_b, 0),
00294 dra, drb, &aliased)
00295 && !aliased)
00296 return true;
00297 else
00298 return false;
00299 }
00300
00301
00302
00303 static bool
00304 record_array_differ_p (struct data_reference *dra,
00305 struct data_reference *drb)
00306 {
00307 bool aliased;
00308 tree base_a = DR_BASE_OBJECT (dra);
00309 tree base_b = DR_BASE_OBJECT (drb);
00310
00311 if (TREE_CODE (base_b) != COMPONENT_REF)
00312 return false;
00313
00314
00315
00316
00317 while (TREE_CODE (base_b) == COMPONENT_REF)
00318 base_b = TREE_OPERAND (base_b, 0);
00319
00320
00321
00322
00323 if (TREE_CODE (base_a) == VAR_DECL
00324 && (TREE_CODE (base_b) == VAR_DECL
00325 || (TREE_CODE (base_b) == INDIRECT_REF
00326 && (ptr_decl_may_alias_p (TREE_OPERAND (base_b, 0), base_a, drb,
00327 &aliased)
00328 && !aliased))))
00329 return true;
00330 else
00331 return false;
00332 }
00333
00334
00335
00336
00337 static bool
00338 array_ptr_differ_p (tree base_a, tree base_b,
00339 struct data_reference *drb)
00340 {
00341 bool aliased;
00342
00343
00344
00345 if (TREE_CODE (base_a) == VAR_DECL && TREE_CODE (base_b) == INDIRECT_REF
00346 && (ptr_decl_may_alias_p (TREE_OPERAND (base_b, 0), base_a, drb, &aliased)
00347 && !aliased))
00348 return true;
00349 else
00350 return false;
00351 }
00352
00353
00354
00355
00356
00357
00358
00359
00360
00361 static bool
00362 base_object_differ_p (struct data_reference *a,
00363 struct data_reference *b,
00364 bool *differ_p)
00365 {
00366 tree base_a = DR_BASE_OBJECT (a);
00367 tree base_b = DR_BASE_OBJECT (b);
00368 bool aliased;
00369
00370 if (!base_a || !base_b)
00371 return false;
00372
00373
00374
00375 if (base_a == base_b)
00376 {
00377 *differ_p = false;
00378 return true;
00379 }
00380
00381
00382
00383 if (TREE_CODE (base_a) == INDIRECT_REF && TREE_CODE (base_b) == INDIRECT_REF
00384 && TREE_OPERAND (base_a, 0) == TREE_OPERAND (base_b, 0))
00385 {
00386 *differ_p = false;
00387 return true;
00388 }
00389
00390
00391 if (TREE_CODE (base_a) == COMPONENT_REF && TREE_CODE (base_b) == COMPONENT_REF
00392 && TREE_OPERAND (base_a, 0) == TREE_OPERAND (base_b, 0)
00393 && TREE_OPERAND (base_a, 1) == TREE_OPERAND (base_b, 1))
00394 {
00395 *differ_p = false;
00396 return true;
00397 }
00398
00399
00400
00401
00402
00403
00404
00405
00406
00407 if (TREE_CODE (base_a) == VAR_DECL && TREE_CODE (base_b) == VAR_DECL)
00408 {
00409 *differ_p = true;
00410 return true;
00411 }
00412
00413
00414
00415 if (array_ptr_differ_p (base_a, base_b, b)
00416 || array_ptr_differ_p (base_b, base_a, a))
00417 {
00418 *differ_p = true;
00419 return true;
00420 }
00421
00422
00423
00424 if (TREE_CODE (base_a) == INDIRECT_REF && TREE_CODE (base_b) == INDIRECT_REF
00425 && (may_alias_p (TREE_OPERAND (base_a, 0), TREE_OPERAND (base_b, 0), a, b,
00426 &aliased)
00427 && !aliased))
00428 {
00429 *differ_p = true;
00430 return true;
00431 }
00432
00433
00434
00435 if (TREE_CODE (base_a) == COMPONENT_REF && TREE_CODE (base_b) == COMPONENT_REF
00436 && ((TREE_CODE (TREE_OPERAND (base_a, 0)) == VAR_DECL
00437 && TREE_CODE (TREE_OPERAND (base_b, 0)) == VAR_DECL
00438 && TREE_OPERAND (base_a, 0) != TREE_OPERAND (base_b, 0))
00439 || (TREE_CODE (TREE_TYPE (TREE_OPERAND (base_a, 0))) == RECORD_TYPE
00440 && TREE_CODE (TREE_TYPE (TREE_OPERAND (base_b, 0))) == RECORD_TYPE
00441 && TREE_OPERAND (base_a, 1) != TREE_OPERAND (base_b, 1))))
00442 {
00443 *differ_p = true;
00444 return true;
00445 }
00446
00447
00448
00449 if (record_ptr_differ_p (a, b) || record_ptr_differ_p (b, a))
00450 {
00451 *differ_p = true;
00452 return true;
00453 }
00454
00455
00456
00457
00458 if (record_array_differ_p (a, b) || record_array_differ_p (b, a))
00459 {
00460 *differ_p = true;
00461 return true;
00462 }
00463
00464
00465 if (record_record_differ_p (a, b))
00466 {
00467 *differ_p = true;
00468 return true;
00469 }
00470
00471 return false;
00472 }
00473
00474
00475
00476
00477
00478
00479
00480
00481
00482
00483
00484
00485
00486
00487
00488
00489
00490 static bool
00491 base_addr_differ_p (struct data_reference *dra,
00492 struct data_reference *drb,
00493 bool *differ_p)
00494 {
00495 tree addr_a = DR_BASE_ADDRESS (dra);
00496 tree addr_b = DR_BASE_ADDRESS (drb);
00497 tree type_a, type_b;
00498 bool aliased;
00499
00500 if (!addr_a || !addr_b)
00501 return false;
00502
00503 type_a = TREE_TYPE (addr_a);
00504 type_b = TREE_TYPE (addr_b);
00505
00506 gcc_assert (POINTER_TYPE_P (type_a) && POINTER_TYPE_P (type_b));
00507
00508
00509
00510 if (DR_TYPE (dra) == ARRAY_REF_TYPE && DR_TYPE (drb) == ARRAY_REF_TYPE)
00511 return base_object_differ_p (dra, drb, differ_p);
00512
00513
00514
00515
00516
00517
00518
00519 if (DR_TYPE (dra) == POINTER_REF_TYPE && DR_TYPE (drb) == POINTER_REF_TYPE
00520 && (addr_a == addr_b
00521 || (TREE_CODE (addr_a) == ADDR_EXPR && TREE_CODE (addr_b) == ADDR_EXPR
00522 && TREE_OPERAND (addr_a, 0) == TREE_OPERAND (addr_b, 0))))
00523 {
00524
00525 tree offset_a = DR_OFFSET (dra);
00526 tree offset_b = DR_OFFSET (drb);
00527
00528 STRIP_NOPS (offset_a);
00529 STRIP_NOPS (offset_b);
00530
00531
00532
00533 if (offset_a == offset_b
00534 || (TREE_CODE (offset_a) == MULT_EXPR
00535 && TREE_CODE (offset_b) == MULT_EXPR
00536 && TREE_OPERAND (offset_a, 0) == TREE_OPERAND (offset_b, 0)
00537 && TREE_OPERAND (offset_a, 1) == TREE_OPERAND (offset_b, 1)))
00538 {
00539 *differ_p = false;
00540 return true;
00541 }
00542 }
00543
00544
00545
00546
00547
00548 if (may_alias_p (addr_a, addr_b, dra, drb, &aliased) && !aliased)
00549 {
00550 *differ_p = true;
00551 return true;
00552 }
00553
00554
00555
00556
00557 else if ((TYPE_RESTRICT (type_a) && !DR_IS_READ (dra))
00558 || (TYPE_RESTRICT (type_b) && !DR_IS_READ (drb)))
00559 {
00560 *differ_p = true;
00561 return true;
00562 }
00563 return false;
00564 }
00565
00566
00567
00568 static inline bool
00569 tree_fold_divides_p (tree a,
00570 tree b)
00571 {
00572
00573 return tree_int_cst_equal (a, tree_fold_gcd (a, b));
00574 }
00575
00576
00577
00578 static inline bool
00579 int_divides_p (int a, int b)
00580 {
00581 return ((b % a) == 0);
00582 }
00583
00584
00585
00586
00587
00588 void
00589 dump_data_references (FILE *file, VEC (data_reference_p, heap) *datarefs)
00590 {
00591 unsigned int i;
00592 struct data_reference *dr;
00593
00594 for (i = 0; VEC_iterate (data_reference_p, datarefs, i, dr); i++)
00595 dump_data_reference (file, dr);
00596 }
00597
00598
00599
00600 void
00601 dump_data_dependence_relations (FILE *file,
00602 VEC (ddr_p, heap) *ddrs)
00603 {
00604 unsigned int i;
00605 struct data_dependence_relation *ddr;
00606
00607 for (i = 0; VEC_iterate (ddr_p, ddrs, i, ddr); i++)
00608 dump_data_dependence_relation (file, ddr);
00609 }
00610
00611
00612
00613 void
00614 dump_data_reference (FILE *outf,
00615 struct data_reference *dr)
00616 {
00617 unsigned int i;
00618
00619 fprintf (outf, "(Data Ref: \n stmt: ");
00620 print_generic_stmt (outf, DR_STMT (dr), 0);
00621 fprintf (outf, " ref: ");
00622 print_generic_stmt (outf, DR_REF (dr), 0);
00623 fprintf (outf, " base_object: ");
00624 print_generic_stmt (outf, DR_BASE_OBJECT (dr), 0);
00625
00626 for (i = 0; i < DR_NUM_DIMENSIONS (dr); i++)
00627 {
00628 fprintf (outf, " Access function %d: ", i);
00629 print_generic_stmt (outf, DR_ACCESS_FN (dr, i), 0);
00630 }
00631 fprintf (outf, ")\n");
00632 }
00633
00634
00635
00636 void
00637 dump_subscript (FILE *outf, struct subscript *subscript)
00638 {
00639 tree chrec = SUB_CONFLICTS_IN_A (subscript);
00640
00641 fprintf (outf, "\n (subscript \n");
00642 fprintf (outf, " iterations_that_access_an_element_twice_in_A: ");
00643 print_generic_stmt (outf, chrec, 0);
00644 if (chrec == chrec_known)
00645 fprintf (outf, " (no dependence)\n");
00646 else if (chrec_contains_undetermined (chrec))
00647 fprintf (outf, " (don't know)\n");
00648 else
00649 {
00650 tree last_iteration = SUB_LAST_CONFLICT (subscript);
00651 fprintf (outf, " last_conflict: ");
00652 print_generic_stmt (outf, last_iteration, 0);
00653 }
00654
00655 chrec = SUB_CONFLICTS_IN_B (subscript);
00656 fprintf (outf, " iterations_that_access_an_element_twice_in_B: ");
00657 print_generic_stmt (outf, chrec, 0);
00658 if (chrec == chrec_known)
00659 fprintf (outf, " (no dependence)\n");
00660 else if (chrec_contains_undetermined (chrec))
00661 fprintf (outf, " (don't know)\n");
00662 else
00663 {
00664 tree last_iteration = SUB_LAST_CONFLICT (subscript);
00665 fprintf (outf, " last_conflict: ");
00666 print_generic_stmt (outf, last_iteration, 0);
00667 }
00668
00669 fprintf (outf, " (Subscript distance: ");
00670 print_generic_stmt (outf, SUB_DISTANCE (subscript), 0);
00671 fprintf (outf, " )\n");
00672 fprintf (outf, " )\n");
00673 }
00674
00675
00676
00677 void
00678 print_direction_vector (FILE *outf,
00679 lambda_vector dirv,
00680 int length)
00681 {
00682 int eq;
00683
00684 for (eq = 0; eq < length; eq++)
00685 {
00686 enum data_dependence_direction dir = dirv[eq];
00687
00688 switch (dir)
00689 {
00690 case dir_positive:
00691 fprintf (outf, " +");
00692 break;
00693 case dir_negative:
00694 fprintf (outf, " -");
00695 break;
00696 case dir_equal:
00697 fprintf (outf, " =");
00698 break;
00699 case dir_positive_or_equal:
00700 fprintf (outf, " +=");
00701 break;
00702 case dir_positive_or_negative:
00703 fprintf (outf, " +-");
00704 break;
00705 case dir_negative_or_equal:
00706 fprintf (outf, " -=");
00707 break;
00708 case dir_star:
00709 fprintf (outf, " *");
00710 break;
00711 default:
00712 fprintf (outf, "indep");
00713 break;
00714 }
00715 }
00716 fprintf (outf, "\n");
00717 }
00718
00719
00720
00721 void
00722 print_dir_vectors (FILE *outf, VEC (lambda_vector, heap) *dir_vects,
00723 int length)
00724 {
00725 unsigned j;
00726 lambda_vector v;
00727
00728 for (j = 0; VEC_iterate (lambda_vector, dir_vects, j, v); j++)
00729 print_direction_vector (outf, v, length);
00730 }
00731
00732
00733
00734 void
00735 print_dist_vectors (FILE *outf, VEC (lambda_vector, heap) *dist_vects,
00736 int length)
00737 {
00738 unsigned j;
00739 lambda_vector v;
00740
00741 for (j = 0; VEC_iterate (lambda_vector, dist_vects, j, v); j++)
00742 print_lambda_vector (outf, v, length);
00743 }
00744
00745
00746
00747 void
00748 debug_data_dependence_relation (struct data_dependence_relation *ddr)
00749 {
00750 dump_data_dependence_relation (stderr, ddr);
00751 }
00752
00753
00754
00755 void
00756 dump_data_dependence_relation (FILE *outf,
00757 struct data_dependence_relation *ddr)
00758 {
00759 struct data_reference *dra, *drb;
00760
00761 dra = DDR_A (ddr);
00762 drb = DDR_B (ddr);
00763 fprintf (outf, "(Data Dep: \n");
00764 if (DDR_ARE_DEPENDENT (ddr) == chrec_dont_know)
00765 fprintf (outf, " (don't know)\n");
00766
00767 else if (DDR_ARE_DEPENDENT (ddr) == chrec_known)
00768 fprintf (outf, " (no dependence)\n");
00769
00770 else if (DDR_ARE_DEPENDENT (ddr) == NULL_TREE)
00771 {
00772 unsigned int i;
00773 struct loop *loopi;
00774
00775 for (i = 0; i < DDR_NUM_SUBSCRIPTS (ddr); i++)
00776 {
00777 fprintf (outf, " access_fn_A: ");
00778 print_generic_stmt (outf, DR_ACCESS_FN (dra, i), 0);
00779 fprintf (outf, " access_fn_B: ");
00780 print_generic_stmt (outf, DR_ACCESS_FN (drb, i), 0);
00781 dump_subscript (outf, DDR_SUBSCRIPT (ddr, i));
00782 }
00783
00784 fprintf (outf, " loop nest: (");
00785 for (i = 0; VEC_iterate (loop_p, DDR_LOOP_NEST (ddr), i, loopi); i++)
00786 fprintf (outf, "%d ", loopi->num);
00787 fprintf (outf, ")\n");
00788
00789 for (i = 0; i < DDR_NUM_DIST_VECTS (ddr); i++)
00790 {
00791 fprintf (outf, " distance_vector: ");
00792 print_lambda_vector (outf, DDR_DIST_VECT (ddr, i),
00793 DDR_NB_LOOPS (ddr));
00794 }
00795
00796 for (i = 0; i < DDR_NUM_DIR_VECTS (ddr); i++)
00797 {
00798 fprintf (outf, " direction_vector: ");
00799 print_direction_vector (outf, DDR_DIR_VECT (ddr, i),
00800 DDR_NB_LOOPS (ddr));
00801 }
00802 }
00803
00804 fprintf (outf, ")\n");
00805 }
00806
00807
00808
00809 void
00810 dump_data_dependence_direction (FILE *file,
00811 enum data_dependence_direction dir)
00812 {
00813 switch (dir)
00814 {
00815 case dir_positive:
00816 fprintf (file, "+");
00817 break;
00818
00819 case dir_negative:
00820 fprintf (file, "-");
00821 break;
00822
00823 case dir_equal:
00824 fprintf (file, "=");
00825 break;
00826
00827 case dir_positive_or_negative:
00828 fprintf (file, "+-");
00829 break;
00830
00831 case dir_positive_or_equal:
00832 fprintf (file, "+=");
00833 break;
00834
00835 case dir_negative_or_equal:
00836 fprintf (file, "-=");
00837 break;
00838
00839 case dir_star:
00840 fprintf (file, "*");
00841 break;
00842
00843 default:
00844 break;
00845 }
00846 }
00847
00848
00849
00850
00851
00852
00853 void
00854 dump_dist_dir_vectors (FILE *file, VEC (ddr_p, heap) *ddrs)
00855 {
00856 unsigned int i, j;
00857 struct data_dependence_relation *ddr;
00858 lambda_vector v;
00859
00860 for (i = 0; VEC_iterate (ddr_p, ddrs, i, ddr); i++)
00861 if (DDR_ARE_DEPENDENT (ddr) == NULL_TREE && DDR_AFFINE_P (ddr))
00862 {
00863 for (j = 0; VEC_iterate (lambda_vector, DDR_DIST_VECTS (ddr), j, v); j++)
00864 {
00865 fprintf (file, "DISTANCE_V (");
00866 print_lambda_vector (file, v, DDR_NB_LOOPS (ddr));
00867 fprintf (file, ")\n");
00868 }
00869
00870 for (j = 0; VEC_iterate (lambda_vector, DDR_DIR_VECTS (ddr), j, v); j++)
00871 {
00872 fprintf (file, "DIRECTION_V (");
00873 print_direction_vector (file, v, DDR_NB_LOOPS (ddr));
00874 fprintf (file, ")\n");
00875 }
00876 }
00877
00878 fprintf (file, "\n\n");
00879 }
00880
00881
00882
00883 void
00884 dump_ddrs (FILE *file, VEC (ddr_p, heap) *ddrs)
00885 {
00886 unsigned int i;
00887 struct data_dependence_relation *ddr;
00888
00889 for (i = 0; VEC_iterate (ddr_p, ddrs, i, ddr); i++)
00890 dump_data_dependence_relation (file, ddr);
00891
00892 fprintf (file, "\n\n");
00893 }
00894
00895
00896
00897
00898
00899
00900 static void
00901 estimate_niter_from_size_of_data (struct loop *loop,
00902 tree opnd0,
00903 tree access_fn,
00904 tree stmt)
00905 {
00906 tree estimation = NULL_TREE;
00907 tree array_size, data_size, element_size;
00908 tree init, step;
00909
00910 init = initial_condition (access_fn);
00911 step = evolution_part_in_loop_num (access_fn, loop->num);
00912
00913 array_size = TYPE_SIZE (TREE_TYPE (opnd0));
00914 element_size = TYPE_SIZE (TREE_TYPE (TREE_TYPE (opnd0)));
00915 if (array_size == NULL_TREE
00916 || TREE_CODE (array_size) != INTEGER_CST
00917 || TREE_CODE (element_size) != INTEGER_CST)
00918 return;
00919
00920 data_size = fold_build2 (EXACT_DIV_EXPR, integer_type_node,
00921 array_size, element_size);
00922
00923 if (init != NULL_TREE
00924 && step != NULL_TREE
00925 && TREE_CODE (init) == INTEGER_CST
00926 && TREE_CODE (step) == INTEGER_CST)
00927 {
00928 tree i_plus_s = fold_build2 (PLUS_EXPR, integer_type_node, init, step);
00929 tree sign = fold_binary (GT_EXPR, boolean_type_node, i_plus_s, init);
00930
00931 if (sign == boolean_true_node)
00932 estimation = fold_build2 (CEIL_DIV_EXPR, integer_type_node,
00933 fold_build2 (MINUS_EXPR, integer_type_node,
00934 data_size, init), step);
00935
00936
00937
00938
00939 else if (sign == boolean_false_node)
00940 estimation =
00941 fold_build2 (PLUS_EXPR, integer_type_node,
00942 fold_build2 (CEIL_DIV_EXPR, integer_type_node,
00943 init,
00944 fold_build2 (MINUS_EXPR, unsigned_type_node,
00945 integer_zero_node, step)),
00946 integer_one_node);
00947
00948 if (estimation)
00949 record_estimate (loop, estimation, boolean_true_node, stmt);
00950 }
00951 }
00952
00953
00954
00955
00956
00957
00958
00959
00960
00961 static tree
00962 analyze_array_indexes (struct loop *loop,
00963 VEC(tree,heap) **access_fns,
00964 tree ref, tree stmt,
00965 bool estimate_only)
00966 {
00967 tree opnd0, opnd1;
00968 tree access_fn;
00969
00970 opnd0 = TREE_OPERAND (ref, 0);
00971 opnd1 = TREE_OPERAND (ref, 1);
00972
00973
00974
00975
00976
00977 access_fn = instantiate_parameters
00978 (loop, analyze_scalar_evolution (loop, opnd1));
00979
00980 if (estimate_only
00981 && chrec_contains_undetermined (loop->estimated_nb_iterations))
00982 estimate_niter_from_size_of_data (loop, opnd0, access_fn, stmt);
00983
00984 if (!estimate_only)
00985 VEC_safe_push (tree, heap, *access_fns, access_fn);
00986
00987
00988 if (TREE_CODE (opnd0) == ARRAY_REF)
00989 return analyze_array_indexes (loop, access_fns, opnd0, stmt, estimate_only);
00990
00991
00992 else
00993 return opnd0;
00994 }
00995
00996
00997
00998
00999 void
01000 estimate_iters_using_array (tree stmt, tree ref)
01001 {
01002 analyze_array_indexes (loop_containing_stmt (stmt), NULL, ref, stmt,
01003 true);
01004 }
01005
01006
01007
01008
01009
01010
01011 struct data_reference *
01012 analyze_array (tree stmt, tree ref, bool is_read)
01013 {
01014 struct data_reference *res;
01015 VEC(tree,heap) *acc_fns;
01016
01017 if (dump_file && (dump_flags & TDF_DETAILS))
01018 {
01019 fprintf (dump_file, "(analyze_array \n");
01020 fprintf (dump_file, " (ref = ");
01021 print_generic_stmt (dump_file, ref, 0);
01022 fprintf (dump_file, ")\n");
01023 }
01024
01025 res = XNEW (struct data_reference);
01026
01027 DR_STMT (res) = stmt;
01028 DR_REF (res) = ref;
01029 acc_fns = VEC_alloc (tree, heap, 3);
01030 DR_BASE_OBJECT (res) = analyze_array_indexes
01031 (loop_containing_stmt (stmt), &acc_fns, ref, stmt, false);
01032 DR_TYPE (res) = ARRAY_REF_TYPE;
01033 DR_SET_ACCESS_FNS (res, acc_fns);
01034 DR_IS_READ (res) = is_read;
01035 DR_BASE_ADDRESS (res) = NULL_TREE;
01036 DR_OFFSET (res) = NULL_TREE;
01037 DR_INIT (res) = NULL_TREE;
01038 DR_STEP (res) = NULL_TREE;
01039 DR_OFFSET_MISALIGNMENT (res) = NULL_TREE;
01040 DR_MEMTAG (res) = NULL_TREE;
01041 DR_PTR_INFO (res) = NULL;
01042
01043 if (dump_file && (dump_flags & TDF_DETAILS))
01044 fprintf (dump_file, ")\n");
01045
01046 return res;
01047 }
01048
01049
01050
01051
01052
01053
01054
01055 static struct data_reference *
01056 analyze_indirect_ref (tree stmt, tree ref, bool is_read)
01057 {
01058 struct loop *loop = loop_containing_stmt (stmt);
01059 tree ptr_ref = TREE_OPERAND (ref, 0);
01060 tree access_fn = analyze_scalar_evolution (loop, ptr_ref);
01061 tree init = initial_condition_in_loop_num (access_fn, loop->num);
01062 tree base_address = NULL_TREE, evolution, step = NULL_TREE;
01063 struct ptr_info_def *ptr_info = NULL;
01064
01065 if (TREE_CODE (ptr_ref) == SSA_NAME)
01066 ptr_info = SSA_NAME_PTR_INFO (ptr_ref);
01067
01068 STRIP_NOPS (init);
01069 if (access_fn == chrec_dont_know || !init || init == chrec_dont_know)
01070 {
01071 if (dump_file && (dump_flags & TDF_DETAILS))
01072 {
01073 fprintf (dump_file, "\nBad access function of ptr: ");
01074 print_generic_expr (dump_file, ref, TDF_SLIM);
01075 fprintf (dump_file, "\n");
01076 }
01077 return NULL;
01078 }
01079
01080 if (dump_file && (dump_flags & TDF_DETAILS))
01081 {
01082 fprintf (dump_file, "\nAccess function of ptr: ");
01083 print_generic_expr (dump_file, access_fn, TDF_SLIM);
01084 fprintf (dump_file, "\n");
01085 }
01086
01087 if (!expr_invariant_in_loop_p (loop, init))
01088 {
01089 if (dump_file && (dump_flags & TDF_DETAILS))
01090 fprintf (dump_file, "\ninitial condition is not loop invariant.\n");
01091 }
01092 else
01093 {
01094 base_address = init;
01095 evolution = evolution_part_in_loop_num (access_fn, loop->num);
01096 if (evolution != chrec_dont_know)
01097 {
01098 if (!evolution)
01099 step = ssize_int (0);
01100 else
01101 {
01102 if (TREE_CODE (evolution) == INTEGER_CST)
01103 step = fold_convert (ssizetype, evolution);
01104 else
01105 if (dump_file && (dump_flags & TDF_DETAILS))
01106 fprintf (dump_file, "\nnon constant step for ptr access.\n");
01107 }
01108 }
01109 else
01110 if (dump_file && (dump_flags & TDF_DETAILS))
01111 fprintf (dump_file, "\nunknown evolution of ptr.\n");
01112 }
01113 return init_data_ref (stmt, ref, NULL_TREE, access_fn, is_read, base_address,
01114 NULL_TREE, step, NULL_TREE, NULL_TREE,
01115 ptr_info, POINTER_REF_TYPE);
01116 }
01117
01118
01119
01120
01121 struct data_reference *
01122 init_data_ref (tree stmt,
01123 tree ref,
01124 tree base,
01125 tree access_fn,
01126 bool is_read,
01127 tree base_address,
01128 tree init_offset,
01129 tree step,
01130 tree misalign,
01131 tree memtag,
01132 struct ptr_info_def *ptr_info,
01133 enum data_ref_type type)
01134 {
01135 struct data_reference *res;
01136 VEC(tree,heap) *acc_fns;
01137
01138 if (dump_file && (dump_flags & TDF_DETAILS))
01139 {
01140 fprintf (dump_file, "(init_data_ref \n");
01141 fprintf (dump_file, " (ref = ");
01142 print_generic_stmt (dump_file, ref, 0);
01143 fprintf (dump_file, ")\n");
01144 }
01145
01146 res = XNEW (struct data_reference);
01147
01148 DR_STMT (res) = stmt;
01149 DR_REF (res) = ref;
01150 DR_BASE_OBJECT (res) = base;
01151 DR_TYPE (res) = type;
01152 acc_fns = VEC_alloc (tree, heap, 3);
01153 DR_SET_ACCESS_FNS (res, acc_fns);
01154 VEC_quick_push (tree, DR_ACCESS_FNS (res), access_fn);
01155 DR_IS_READ (res) = is_read;
01156 DR_BASE_ADDRESS (res) = base_address;
01157 DR_OFFSET (res) = init_offset;
01158 DR_INIT (res) = NULL_TREE;
01159 DR_STEP (res) = step;
01160 DR_OFFSET_MISALIGNMENT (res) = misalign;
01161 DR_MEMTAG (res) = memtag;
01162 DR_PTR_INFO (res) = ptr_info;
01163
01164 if (dump_file && (dump_flags & TDF_DETAILS))
01165 fprintf (dump_file, ")\n");
01166
01167 return res;
01168 }
01169
01170
01171
01172
01173
01174 static tree
01175 strip_conversion (tree expr)
01176 {
01177 tree to, ti, oprnd0;
01178
01179 while (TREE_CODE (expr) == NOP_EXPR || TREE_CODE (expr) == CONVERT_EXPR)
01180 {
01181 to = TREE_TYPE (expr);
01182 oprnd0 = TREE_OPERAND (expr, 0);
01183 ti = TREE_TYPE (oprnd0);
01184
01185 if (!INTEGRAL_TYPE_P (to) || !INTEGRAL_TYPE_P (ti))
01186 return NULL_TREE;
01187 if (GET_MODE_SIZE (TYPE_MODE (to)) < GET_MODE_SIZE (TYPE_MODE (ti)))
01188 return NULL_TREE;
01189
01190 expr = oprnd0;
01191 }
01192 return expr;
01193 }
01194
01195
01196
01197
01198
01199
01200
01201
01202
01203
01204
01205
01206
01207
01208
01209
01210
01211
01212
01213
01214
01215
01216
01217
01218
01219
01220
01221
01222
01223
01224
01225
01226
01227 static bool
01228 analyze_offset_expr (tree expr,
01229 struct loop *loop,
01230 tree *initial_offset,
01231 tree *misalign,
01232 tree *aligned_to,
01233 tree *step)
01234 {
01235 tree oprnd0;
01236 tree oprnd1;
01237 tree left_offset = ssize_int (0);
01238 tree right_offset = ssize_int (0);
01239 tree left_misalign = ssize_int (0);
01240 tree right_misalign = ssize_int (0);
01241 tree left_step = ssize_int (0);
01242 tree right_step = ssize_int (0);
01243 enum tree_code code;
01244 tree init, evolution;
01245 tree left_aligned_to = NULL_TREE, right_aligned_to = NULL_TREE;
01246
01247 *step = NULL_TREE;
01248 *misalign = NULL_TREE;
01249 *aligned_to = NULL_TREE;
01250 *initial_offset = NULL_TREE;
01251
01252
01253 expr = strip_conversion (expr);
01254 if (!expr)
01255 return false;
01256
01257
01258
01259 if (TREE_CODE (expr) == INTEGER_CST)
01260 {
01261 *initial_offset = fold_convert (ssizetype, expr);
01262 *misalign = fold_convert (ssizetype, expr);
01263 *step = ssize_int (0);
01264 return true;
01265 }
01266
01267
01268
01269 if (SSA_VAR_P (expr))
01270 {
01271 tree access_fn = analyze_scalar_evolution (loop, expr);
01272
01273 if (access_fn == chrec_dont_know)
01274
01275 return false;
01276
01277 init = initial_condition_in_loop_num (access_fn, loop->num);
01278 if (!expr_invariant_in_loop_p (loop, init))
01279
01280
01281
01282
01283 return false;
01284
01285 evolution = evolution_part_in_loop_num (access_fn, loop->num);
01286 if (evolution && TREE_CODE (evolution) != INTEGER_CST)
01287
01288 return false;
01289
01290 if (TREE_CODE (init) == INTEGER_CST)
01291 *misalign = fold_convert (ssizetype, init);
01292 else
01293
01294 *misalign = NULL_TREE;
01295
01296 *initial_offset = fold_convert (ssizetype, init);
01297
01298 *step = evolution ? fold_convert (ssizetype, evolution) : ssize_int (0);
01299 return true;
01300 }
01301
01302
01303 if (!BINARY_CLASS_P (expr))
01304 {
01305
01306 if (dump_file && (dump_flags & TDF_DETAILS))
01307 {
01308 fprintf (dump_file, "\nNot binary expression ");
01309 print_generic_expr (dump_file, expr, TDF_SLIM);
01310 fprintf (dump_file, "\n");
01311 }
01312 return false;
01313 }
01314 oprnd0 = TREE_OPERAND (expr, 0);
01315 oprnd1 = TREE_OPERAND (expr, 1);
01316
01317 if (!analyze_offset_expr (oprnd0, loop, &left_offset, &left_misalign,
01318 &left_aligned_to, &left_step)
01319 || !analyze_offset_expr (oprnd1, loop, &right_offset, &right_misalign,
01320 &right_aligned_to, &right_step))
01321 return false;
01322
01323
01324 code = TREE_CODE (expr);
01325 switch (code)
01326 {
01327 case MULT_EXPR:
01328 if (TREE_CODE (right_offset) != INTEGER_CST)
01329
01330
01331
01332 return false;
01333
01334
01335 left_offset = strip_conversion (left_offset);
01336 if (!left_offset)
01337 return false;
01338
01339 if (SSA_VAR_P (left_offset))
01340 {
01341
01342
01343
01344
01345
01346 *misalign = NULL_TREE;
01347 *aligned_to = ssize_int (highest_pow2_factor (right_offset));
01348 }
01349 else
01350 {
01351
01352 if (left_misalign)
01353 {
01354
01355
01356 *misalign = size_binop (code, left_misalign, right_misalign);
01357 if (left_aligned_to && right_aligned_to)
01358 *aligned_to = size_binop (MIN_EXPR, left_aligned_to,
01359 right_aligned_to);
01360 else
01361 *aligned_to = left_aligned_to ?
01362 left_aligned_to : right_aligned_to;
01363 }
01364 else
01365 *misalign = NULL_TREE;
01366 }
01367
01368
01369
01370 *step = size_binop (MULT_EXPR, left_step, right_offset);
01371 break;
01372
01373 case PLUS_EXPR:
01374 case MINUS_EXPR:
01375
01376 *step = size_binop (code, left_step, right_step);
01377
01378
01379 if ((!left_misalign && !left_aligned_to)
01380 || (!right_misalign && !right_aligned_to))
01381 {
01382 *misalign = NULL_TREE;
01383 *aligned_to = NULL_TREE;
01384 break;
01385 }
01386
01387 if (left_misalign && right_misalign)
01388 *misalign = size_binop (code, left_misalign, right_misalign);
01389 else
01390 *misalign = left_misalign ? left_misalign : right_misalign;
01391
01392 if (left_aligned_to && right_aligned_to)
01393 *aligned_to = size_binop (MIN_EXPR, left_aligned_to, right_aligned_to);
01394 else
01395 *aligned_to = left_aligned_to ? left_aligned_to : right_aligned_to;
01396
01397 break;
01398
01399 default:
01400 gcc_unreachable ();
01401 }
01402
01403
01404 *initial_offset = fold_convert (ssizetype,
01405 fold_build2 (code, TREE_TYPE (left_offset),
01406 left_offset,
01407 right_offset));
01408 return true;
01409 }
01410
01411
01412
01413
01414
01415
01416
01417
01418
01419
01420
01421
01422
01423
01424
01425
01426
01427
01428
01429
01430
01431
01432
01433
01434
01435 static tree
01436 address_analysis (tree expr, tree stmt, bool is_read, struct data_reference *dr,
01437 tree *offset, tree *misalign, tree *aligned_to, tree *step)
01438 {
01439 tree oprnd0, oprnd1, base_address, offset_expr, base_addr0, base_addr1;
01440 tree address_offset = ssize_int (0), address_misalign = ssize_int (0);
01441 tree dummy, address_aligned_to = NULL_TREE;
01442 struct ptr_info_def *dummy1;
01443 subvar_t dummy2;
01444
01445 switch (TREE_CODE (expr))
01446 {
01447 case PLUS_EXPR:
01448 case MINUS_EXPR:
01449
01450 oprnd0 = TREE_OPERAND (expr, 0);
01451 oprnd1 = TREE_OPERAND (expr, 1);
01452
01453 STRIP_NOPS (oprnd0);
01454 STRIP_NOPS (oprnd1);
01455
01456
01457
01458 base_addr0 = address_analysis (oprnd0, stmt, is_read, dr, &address_offset,
01459 &address_misalign, &address_aligned_to,
01460 step);
01461
01462 base_addr1 = address_analysis (oprnd1, stmt, is_read, dr, &address_offset,
01463 &address_misalign, &address_aligned_to,
01464 step);
01465
01466
01467
01468 if ((base_addr0 && base_addr1) || (!base_addr0 && !base_addr1))
01469 {
01470 if (dump_file && (dump_flags & TDF_DETAILS))
01471 {
01472 fprintf (dump_file,
01473 "\neither more than one address or no addresses in expr ");
01474 print_generic_expr (dump_file, expr, TDF_SLIM);
01475 fprintf (dump_file, "\n");
01476 }
01477 return NULL_TREE;
01478 }
01479
01480
01481 oprnd0 = TREE_OPERAND (expr, 0);
01482 oprnd1 = TREE_OPERAND (expr, 1);
01483
01484 offset_expr = base_addr0 ?
01485 fold_convert (ssizetype, oprnd1) : fold_convert (ssizetype, oprnd0);
01486
01487
01488
01489
01490 if (TREE_CODE (offset_expr) == INTEGER_CST && address_misalign)
01491 {
01492 *misalign = size_binop (TREE_CODE (expr), address_misalign,
01493 offset_expr);
01494 *aligned_to = address_aligned_to;
01495 }
01496 else
01497 {
01498 *misalign = NULL_TREE;
01499 *aligned_to = NULL_TREE;
01500 }
01501
01502
01503
01504 *offset = size_binop (TREE_CODE (expr), address_offset, offset_expr);
01505 return base_addr0 ? base_addr0 : base_addr1;
01506
01507 case ADDR_EXPR:
01508 base_address = object_analysis (TREE_OPERAND (expr, 0), stmt, is_read,
01509 &dr, offset, misalign, aligned_to, step,
01510 &dummy, &dummy1, &dummy2);
01511 return base_address;
01512
01513 case SSA_NAME:
01514 if (!POINTER_TYPE_P (TREE_TYPE (expr)))
01515 {
01516 if (dump_file && (dump_flags & TDF_DETAILS))
01517 {
01518 fprintf (dump_file, "\nnot pointer SSA_NAME ");
01519 print_generic_expr (dump_file, expr, TDF_SLIM);
01520 fprintf (dump_file, "\n");
01521 }
01522 return NULL_TREE;
01523 }
01524 *aligned_to = ssize_int (TYPE_ALIGN_UNIT (TREE_TYPE (TREE_TYPE (expr))));
01525 *misalign = ssize_int (0);
01526 *offset = ssize_int (0);
01527 *step = ssize_int (0);
01528 return expr;
01529
01530 default:
01531 return NULL_TREE;
01532 }
01533 }
01534
01535
01536
01537
01538
01539
01540
01541
01542
01543
01544
01545
01546
01547
01548
01549
01550
01551
01552
01553
01554
01555
01556
01557
01558
01559
01560
01561
01562
01563
01564
01565
01566
01567
01568
01569
01570
01571
01572
01573
01574
01575
01576
01577
01578
01579
01580
01581
01582
01583
01584
01585
01586
01587
01588
01589
01590
01591
01592
01593
01594 static tree
01595 object_analysis (tree memref, tree stmt, bool is_read,
01596 struct data_reference **dr, tree *offset, tree *misalign,
01597 tree *aligned_to, tree *step, tree *memtag,
01598 struct ptr_info_def **ptr_info, subvar_t *subvars)
01599 {
01600 tree base = NULL_TREE, base_address = NULL_TREE;
01601 tree object_offset = ssize_int (0), object_misalign = ssize_int (0);
01602 tree object_step = ssize_int (0), address_step = ssize_int (0);
01603 tree address_offset = ssize_int (0), address_misalign = ssize_int (0);
01604 HOST_WIDE_INT pbitsize, pbitpos;
01605 tree poffset, bit_pos_in_bytes;
01606 enum machine_mode pmode;
01607 int punsignedp, pvolatilep;
01608 tree ptr_step = ssize_int (0), ptr_init = NULL_TREE;
01609 struct loop *loop = loop_containing_stmt (stmt);
01610 struct data_reference *ptr_dr = NULL;
01611 tree object_aligned_to = NULL_TREE, address_aligned_to = NULL_TREE;
01612 tree comp_ref = NULL_TREE;
01613
01614 *ptr_info = NULL;
01615
01616
01617
01618 if (handled_component_p (memref))
01619 {
01620
01621 if (!(*dr))
01622 {
01623 if (TREE_CODE (memref) == ARRAY_REF)
01624 *dr = analyze_array (stmt, memref, is_read);
01625 else if (TREE_CODE (memref) == COMPONENT_REF)
01626 comp_ref = memref;
01627 else
01628 {
01629 if (dump_file && (dump_flags & TDF_DETAILS))
01630 {
01631 fprintf (dump_file, "\ndata-ref of unsupported type ");
01632 print_generic_expr (dump_file, memref, TDF_SLIM);
01633 fprintf (dump_file, "\n");
01634 }
01635 return NULL_TREE;
01636 }
01637 }
01638
01639
01640
01641 base = get_inner_reference (memref, &pbitsize, &pbitpos, &poffset,
01642 &pmode, &punsignedp, &pvolatilep, false);
01643 if (!base)
01644 {
01645 if (dump_file && (dump_flags & TDF_DETAILS))
01646 {
01647 fprintf (dump_file, "\nfailed to get inner ref for ");
01648 print_generic_expr (dump_file, memref, TDF_SLIM);
01649 fprintf (dump_file, "\n");
01650 }
01651 return NULL_TREE;
01652 }
01653
01654
01655 if (poffset
01656 && !analyze_offset_expr (poffset, loop, &object_offset,
01657 &object_misalign, &object_aligned_to,
01658 &object_step))
01659 {
01660 if (dump_file && (dump_flags & TDF_DETAILS))
01661 {
01662 fprintf (dump_file, "\nfailed to compute offset or step for ");
01663 print_generic_expr (dump_file, memref, TDF_SLIM);
01664 fprintf (dump_file, "\n");
01665 }
01666 return NULL_TREE;
01667 }
01668
01669
01670
01671 bit_pos_in_bytes = ssize_int (pbitpos/BITS_PER_UNIT);
01672
01673 if (pbitpos%BITS_PER_UNIT)
01674 {
01675 if (dump_file && (dump_flags & TDF_DETAILS))
01676 fprintf (dump_file, "\nbit offset alignment.\n");
01677 return NULL_TREE;
01678 }
01679 object_offset = size_binop (PLUS_EXPR, bit_pos_in_bytes, object_offset);
01680 if (object_misalign)
01681 object_misalign = size_binop (PLUS_EXPR, object_misalign,
01682 bit_pos_in_bytes);
01683
01684 memref = base;
01685
01686 }
01687
01688
01689 if (DECL_P (memref))
01690 {
01691
01692
01693 if (!(*dr))
01694 {
01695 if (comp_ref && TREE_CODE (TREE_OPERAND (comp_ref, 0)) == ARRAY_REF)
01696 {
01697 *dr = analyze_array (stmt, TREE_OPERAND (comp_ref, 0), is_read);
01698 if (DR_NUM_DIMENSIONS (*dr) != 1)
01699 {
01700 if (dump_file && (dump_flags & TDF_DETAILS))
01701 {
01702 fprintf (dump_file, "\n multidimensional component ref ");
01703 print_generic_expr (dump_file, comp_ref, TDF_SLIM);
01704 fprintf (dump_file, "\n");
01705 }
01706 return NULL_TREE;
01707 }
01708 }
01709 else
01710 {
01711 if (dump_file && (dump_flags & TDF_DETAILS))
01712 {
01713 fprintf (dump_file, "\nunhandled decl ");
01714 print_generic_expr (dump_file, memref, TDF_SLIM);
01715 fprintf (dump_file, "\n");
01716 }
01717 return NULL_TREE;
01718 }
01719 }
01720
01721
01722
01723
01724
01725
01726
01727
01728
01729
01730
01731
01732 if (SSA_VAR_P (memref) && var_can_have_subvars (memref))
01733 *subvars = get_subvars_for_var (memref);
01734 base_address = build_fold_addr_expr (memref);
01735
01736 *memtag = memref;
01737 }
01738
01739
01740 else if (TREE_CODE (memref) == INDIRECT_REF)
01741 {
01742 tree ptr_ref = TREE_OPERAND (memref, 0);
01743 if (TREE_CODE (ptr_ref) == SSA_NAME)
01744 *ptr_info = SSA_NAME_PTR_INFO (ptr_ref);
01745
01746
01747 ptr_dr = analyze_indirect_ref (stmt, memref, is_read);
01748 if (!ptr_dr)
01749 {
01750 if (dump_file && (dump_flags & TDF_DETAILS))
01751 {
01752 fprintf (dump_file, "\nfailed to create dr for ");
01753 print_generic_expr (dump_file, memref, TDF_SLIM);
01754 fprintf (dump_file, "\n");
01755 }
01756 return NULL_TREE;
01757 }
01758
01759
01760 ptr_step = DR_STEP (ptr_dr);
01761 ptr_init = DR_BASE_ADDRESS (ptr_dr);
01762 if (!ptr_init || !ptr_step || !POINTER_TYPE_P (TREE_TYPE (ptr_init)))
01763 {
01764 *dr = (*dr) ? *dr : ptr_dr;
01765 if (dump_file && (dump_flags & TDF_DETAILS))
01766 {
01767 fprintf (dump_file, "\nbad pointer access ");
01768 print_generic_expr (dump_file, memref, TDF_SLIM);
01769 fprintf (dump_file, "\n");
01770 }
01771 return NULL_TREE;
01772 }
01773
01774 if (integer_zerop (ptr_step) && !(*dr))
01775 {
01776 if (dump_file && (dump_flags & TDF_DETAILS))
01777 fprintf (dump_file, "\nptr is loop invariant.\n");
01778 *dr = ptr_dr;
01779 return NULL_TREE;
01780
01781
01782
01783
01784 }
01785 object_step = size_binop (PLUS_EXPR, object_step, ptr_step);
01786
01787
01788 if (!*dr)
01789 *dr = ptr_dr;
01790
01791
01792
01793 base_address = address_analysis (ptr_init, stmt, is_read, *dr,
01794 &address_offset, &address_misalign,
01795 &address_aligned_to, &address_step);
01796 if (!base_address)
01797 {
01798 if (dump_file && (dump_flags & TDF_DETAILS))
01799 {
01800 fprintf (dump_file, "\nfailed to analyze address ");
01801 print_generic_expr (dump_file, ptr_init, TDF_SLIM);
01802 fprintf (dump_file, "\n");
01803 }
01804 return NULL_TREE;
01805 }
01806
01807
01808 switch (TREE_CODE (base_address))
01809 {
01810 case SSA_NAME:
01811 *memtag = get_var_ann (SSA_NAME_VAR (base_address))->symbol_mem_tag;
01812 if (!(*memtag) && TREE_CODE (TREE_OPERAND (memref, 0)) == SSA_NAME)
01813 *memtag = get_var_ann (
01814 SSA_NAME_VAR (TREE_OPERAND (memref, 0)))->symbol_mem_tag;
01815 break;
01816 case ADDR_EXPR:
01817 *memtag = TREE_OPERAND (base_address, 0);
01818 break;
01819 default:
01820 if (dump_file && (dump_flags & TDF_DETAILS))
01821 {
01822 fprintf (dump_file, "\nno memtag for ");
01823 print_generic_expr (dump_file, memref, TDF_SLIM);
01824 fprintf (dump_file, "\n");
01825 }
01826 *memtag = NULL_TREE;
01827 break;
01828 }
01829 }
01830
01831 if (!base_address)
01832 {
01833
01834 if (dump_file && (dump_flags & TDF_DETAILS))
01835 {
01836 fprintf (dump_file, "\ndata-ref of unsupported type ");
01837 print_generic_expr (dump_file, memref, TDF_SLIM);
01838 fprintf (dump_file, "\n");
01839 }
01840 return NULL_TREE;
01841 }
01842
01843 if (comp_ref)
01844 DR_REF (*dr) = comp_ref;
01845
01846 if (SSA_VAR_P (*memtag) && var_can_have_subvars (*memtag))
01847 *subvars = get_subvars_for_var (*memtag);
01848
01849
01850
01851 *offset = size_binop (PLUS_EXPR, object_offset, address_offset);
01852
01853 if ((!object_misalign && !object_aligned_to)
01854 || (!address_misalign && !address_aligned_to))
01855 {
01856 *misalign = NULL_TREE;
01857 *aligned_to = NULL_TREE;
01858 }
01859 else
01860 {
01861 if (object_misalign && address_misalign)
01862 *misalign = size_binop (PLUS_EXPR, object_misalign, address_misalign);
01863 else
01864 *misalign = object_misalign ? object_misalign : address_misalign;
01865 if (object_aligned_to && address_aligned_to)
01866 *aligned_to = size_binop (MIN_EXPR, object_aligned_to,
01867 address_aligned_to);
01868 else
01869 *aligned_to = object_aligned_to ?
01870 object_aligned_to : address_aligned_to;
01871 }
01872 *step = size_binop (PLUS_EXPR, object_step, address_step);
01873
01874 return base_address;
01875 }
01876
01877
01878
01879
01880
01881
01882 static bool
01883 analyze_offset (tree offset, tree *invariant, tree *constant)
01884 {
01885 tree op0, op1, constant_0, constant_1, invariant_0, invariant_1;
01886 enum tree_code code = TREE_CODE (offset);
01887
01888 *invariant = NULL_TREE;
01889 *constant = NULL_TREE;
01890
01891
01892 if (code != PLUS_EXPR && code != MINUS_EXPR)
01893 {
01894 if (TREE_CODE (offset) == INTEGER_CST)
01895 *constant = offset;
01896 else
01897 *invariant = offset;
01898 return true;
01899 }
01900
01901 op0 = TREE_OPERAND (offset, 0);
01902 op1 = TREE_OPERAND (offset, 1);
01903
01904
01905 if (!analyze_offset (op0, &invariant_0, &constant_0)
01906 || !analyze_offset (op1, &invariant_1, &constant_1))
01907 return false;
01908
01909
01910
01911 if (constant_0 && constant_1)
01912 return false;
01913 *constant = constant_0 ? constant_0 : constant_1;
01914 if (code == MINUS_EXPR && constant_1)
01915 *constant = fold_build1 (NEGATE_EXPR, TREE_TYPE (*constant), *constant);
01916
01917 if (invariant_0 && invariant_1)
01918 *invariant =
01919 fold_build2 (code, TREE_TYPE (invariant_0), invariant_0, invariant_1);
01920 else
01921 {
01922 *invariant = invariant_0 ? invariant_0 : invariant_1;
01923 if (code == MINUS_EXPR && invariant_1)
01924 *invariant =
01925 fold_build1 (NEGATE_EXPR, TREE_TYPE (*invariant), *invariant);
01926 }
01927 return true;
01928 }
01929
01930
01931
01932 static void
01933 free_data_ref (data_reference_p dr)
01934 {
01935 DR_FREE_ACCESS_FNS (dr);
01936 free (dr);
01937 }
01938
01939
01940
01941
01942
01943
01944
01945
01946
01947
01948
01949
01950
01951
01952
01953
01954 static struct data_reference *
01955 create_data_ref (tree memref, tree stmt, bool is_read)
01956 {
01957 struct data_reference *dr = NULL;
01958 tree base_address, offset, step, misalign, memtag;
01959 struct loop *loop = loop_containing_stmt (stmt);
01960 tree invariant = NULL_TREE, constant = NULL_TREE;
01961 tree type_size, init_cond;
01962 struct ptr_info_def *ptr_info;
01963 subvar_t subvars = NULL;
01964 tree aligned_to, type = NULL_TREE, orig_offset;
01965
01966 if (!memref)
01967 return NULL;
01968
01969 base_address = object_analysis (memref, stmt, is_read, &dr, &offset,
01970 &misalign, &aligned_to, &step, &memtag,
01971 &ptr_info, &subvars);
01972 if (!dr || !base_address)
01973 {
01974 if (dump_file && (dump_flags & TDF_DETAILS))
01975 {
01976 fprintf (dump_file, "\ncreate_data_ref: failed to create a dr for ");
01977 print_generic_expr (dump_file, memref, TDF_SLIM);
01978 fprintf (dump_file, "\n");
01979 }
01980 return NULL;
01981 }
01982
01983 DR_BASE_ADDRESS (dr) = base_address;
01984 DR_OFFSET (dr) = offset;
01985 DR_INIT (dr) = ssize_int (0);
01986 DR_STEP (dr) = step;
01987 DR_OFFSET_MISALIGNMENT (dr) = misalign;
01988 DR_ALIGNED_TO (dr) = aligned_to;
01989 DR_MEMTAG (dr) = memtag;
01990 DR_PTR_INFO (dr) = ptr_info;
01991 DR_SUBVARS (dr) = subvars;
01992
01993 type_size = fold_convert (ssizetype, TYPE_SIZE_UNIT (TREE_TYPE (DR_REF (dr))));
01994
01995
01996
01997 orig_offset = offset;
01998 STRIP_NOPS (offset);
01999 if (offset != orig_offset)
02000 type = TREE_TYPE (orig_offset);
02001 if (!analyze_offset (offset, &invariant, &constant))
02002 {
02003 if (dump_file && (dump_flags & TDF_DETAILS))
02004 {
02005 fprintf (dump_file, "\ncreate_data_ref: failed to analyze dr's");
02006 fprintf (dump_file, " offset for ");
02007 print_generic_expr (dump_file, memref, TDF_SLIM);
02008 fprintf (dump_file, "\n");
02009 }
02010 return NULL;
02011 }
02012 if (type && invariant)
02013 invariant = fold_convert (type, invariant);
02014
02015
02016
02017 if (constant)
02018 {
02019 DR_INIT (dr) = fold_convert (ssizetype, constant);
02020 init_cond = fold_build2 (TRUNC_DIV_EXPR, TREE_TYPE (constant),
02021 constant, type_size);
02022 }
02023 else
02024 DR_INIT (dr) = init_cond = ssize_int (0);
02025
02026 if (invariant)
02027 DR_OFFSET (dr) = invariant;
02028 else
02029 DR_OFFSET (dr) = ssize_int (0);
02030
02031
02032
02033
02034
02035
02036
02037
02038
02039
02040 if (!DR_BASE_OBJECT (dr)
02041 || (TREE_CODE (memref) == COMPONENT_REF && DR_NUM_DIMENSIONS (dr) == 1))
02042 {
02043 tree access_fn;
02044 tree new_step;
02045
02046
02047 access_fn = DR_ACCESS_FN (dr, 0);
02048 if (automatically_generated_chrec_p (access_fn))
02049 {
02050 free_data_ref (dr);
02051 return NULL;
02052 }
02053
02054 new_step = size_binop (TRUNC_DIV_EXPR,
02055 fold_convert (ssizetype, step), type_size);
02056
02057 init_cond = chrec_convert (chrec_type (access_fn), init_cond, stmt);
02058 new_step = chrec_convert (chrec_type (access_fn), new_step, stmt);
02059 if (automatically_generated_chrec_p (init_cond)
02060 || automatically_generated_chrec_p (new_step))
02061 {
02062 free_data_ref (dr);
02063 return NULL;
02064 }
02065 access_fn = chrec_replace_initial_condition (access_fn, init_cond);
02066 access_fn = reset_evolution_in_loop (loop->num, access_fn, new_step);
02067
02068 VEC_replace (tree, DR_ACCESS_FNS (dr), 0, access_fn);
02069 }
02070
02071 if (dump_file && (dump_flags & TDF_DETAILS))
02072 {
02073 struct ptr_info_def *pi = DR_PTR_INFO (dr);
02074
02075 fprintf (dump_file, "\nCreated dr for ");
02076 print_generic_expr (dump_file, memref, TDF_SLIM);
02077 fprintf (dump_file, "\n\tbase_address: ");
02078 print_generic_expr (dump_file, DR_BASE_ADDRESS (dr), TDF_SLIM);
02079 fprintf (dump_file, "\n\toffset from base address: ");
02080 print_generic_expr (dump_file, DR_OFFSET (dr), TDF_SLIM);
02081 fprintf (dump_file, "\n\tconstant offset from base address: ");
02082 print_generic_expr (dump_file, DR_INIT (dr), TDF_SLIM);
02083 fprintf (dump_file, "\n\tbase_object: ");
02084 print_generic_expr (dump_file, DR_BASE_OBJECT (dr), TDF_SLIM);
02085 fprintf (dump_file, "\n\tstep: ");
02086 print_generic_expr (dump_file, DR_STEP (dr), TDF_SLIM);
02087 fprintf (dump_file, "B\n\tmisalignment from base: ");
02088 print_generic_expr (dump_file, DR_OFFSET_MISALIGNMENT (dr), TDF_SLIM);
02089 if (DR_OFFSET_MISALIGNMENT (dr))
02090 fprintf (dump_file, "B");
02091 if (DR_ALIGNED_TO (dr))
02092 {
02093 fprintf (dump_file, "\n\taligned to: ");
02094 print_generic_expr (dump_file, DR_ALIGNED_TO (dr), TDF_SLIM);
02095 }
02096 fprintf (dump_file, "\n\tmemtag: ");
02097 print_generic_expr (dump_file, DR_MEMTAG (dr), TDF_SLIM);
02098 fprintf (dump_file, "\n");
02099 if (pi && pi->name_mem_tag)
02100 {
02101 fprintf (dump_file, "\n\tnametag: ");
02102 print_generic_expr (dump_file, pi->name_mem_tag, TDF_SLIM);
02103 fprintf (dump_file, "\n");
02104 }
02105 }
02106 return dr;
02107 }
02108
02109
02110
02111
02112
02113 static bool
02114 all_chrecs_equal_p (tree chrec)
02115 {
02116 int j;
02117
02118 for (j = 0; j < TREE_VEC_LENGTH (chrec) - 1; j++)
02119 if (!eq_evolutions_p (TREE_VEC_ELT (chrec, j),
02120 TREE_VEC_ELT (chrec, j + 1)))
02121 return false;
02122
02123 return true;
02124 }
02125
02126
02127
02128
02129 static void
02130 compute_subscript_distance (struct data_dependence_relation *ddr)
02131 {
02132 if (DDR_ARE_DEPENDENT (ddr) == NULL_TREE)
02133 {
02134 unsigned int i;
02135
02136 for (i = 0; i < DDR_NUM_SUBSCRIPTS (ddr); i++)
02137 {
02138 tree conflicts_a, conflicts_b, difference;
02139 struct subscript *subscript;
02140
02141 subscript = DDR_SUBSCRIPT (ddr, i);
02142 conflicts_a = SUB_CONFLICTS_IN_A (subscript);
02143 conflicts_b = SUB_CONFLICTS_IN_B (subscript);
02144
02145 if (TREE_CODE (conflicts_a) == TREE_VEC)
02146 {
02147 if (!all_chrecs_equal_p (conflicts_a))
02148 {
02149 SUB_DISTANCE (subscript) = chrec_dont_know;
02150 return;
02151 }
02152 else
02153 conflicts_a = TREE_VEC_ELT (conflicts_a, 0);
02154 }
02155
02156 if (TREE_CODE (conflicts_b) == TREE_VEC)
02157 {
02158 if (!all_chrecs_equal_p (conflicts_b))
02159 {
02160 SUB_DISTANCE (subscript) = chrec_dont_know;
02161 return;
02162 }
02163 else
02164 conflicts_b = TREE_VEC_ELT (conflicts_b, 0);
02165 }
02166
02167 conflicts_b = chrec_convert (integer_type_node, conflicts_b,
02168 NULL_TREE);
02169 conflicts_a = chrec_convert (integer_type_node, conflicts_a,
02170 NULL_TREE);
02171 difference = chrec_fold_minus
02172 (integer_type_node, conflicts_b, conflicts_a);
02173
02174 if (evolution_function_is_constant_p (difference))
02175 SUB_DISTANCE (subscript) = difference;
02176
02177 else
02178 SUB_DISTANCE (subscript) = chrec_dont_know;
02179 }
02180 }
02181 }
02182
02183
02184
02185
02186
02187 static struct data_dependence_relation *
02188 initialize_data_dependence_relation (struct data_reference *a,
02189 struct data_reference *b,
02190 VEC (loop_p, heap) *loop_nest)
02191 {
02192 struct data_dependence_relation *res;
02193 bool differ_p, known_dependence;
02194 unsigned int i;
02195
02196 res = XNEW (struct data_dependence_relation);
02197 DDR_A (res) = a;
02198 DDR_B (res) = b;
02199 DDR_LOOP_NEST (res) = NULL;
02200
02201 if (a == NULL || b == NULL)
02202 {
02203 DDR_ARE_DEPENDENT (res) = chrec_dont_know;
02204 return res;
02205 }
02206
02207
02208
02209 if (DR_BASE_OBJECT (a) && DR_BASE_OBJECT (b)
02210 && DR_NUM_DIMENSIONS (a) != DR_NUM_DIMENSIONS (b))
02211 {
02212 DDR_ARE_DEPENDENT (res) = chrec_known;
02213 return res;
02214 }
02215
02216 if (DR_BASE_ADDRESS (a) && DR_BASE_ADDRESS (b))
02217 known_dependence = base_addr_differ_p (a, b, &differ_p);
02218 else
02219 known_dependence = base_object_differ_p (a, b, &differ_p);
02220
02221 if (!known_dependence)
02222 {
02223
02224
02225 DDR_ARE_DEPENDENT (res) = chrec_dont_know;
02226 return res;
02227 }
02228
02229 if (differ_p)
02230 {
02231 DDR_ARE_DEPENDENT (res) = chrec_known;
02232 return res;
02233 }
02234
02235 DDR_AFFINE_P (res) = true;
02236 DDR_ARE_DEPENDENT (res) = NULL_TREE;
02237 DDR_SUBSCRIPTS (res) = VEC_alloc (subscript_p, heap, DR_NUM_DIMENSIONS (a));
02238 DDR_LOOP_NEST (res) = loop_nest;
02239 DDR_DIR_VECTS (res) = NULL;
02240 DDR_DIST_VECTS (res) = NULL;
02241
02242 for (i = 0; i < DR_NUM_DIMENSIONS (a); i++)
02243 {
02244 struct subscript *subscript;
02245
02246 subscript = XNEW (struct subscript);
02247 SUB_CONFLICTS_IN_A (subscript) = chrec_dont_know;
02248 SUB_CONFLICTS_IN_B (subscript) = chrec_dont_know;
02249 SUB_LAST_CONFLICT (subscript) = chrec_dont_know;
02250 SUB_DISTANCE (subscript) = chrec_dont_know;
02251 VEC_safe_push (subscript_p, heap, DDR_SUBSCRIPTS (res), subscript);
02252 }
02253
02254 return res;
02255 }
02256
02257
02258
02259
02260 static inline void
02261 finalize_ddr_dependent (struct data_dependence_relation *ddr,
02262 tree chrec)
02263 {
02264 if (dump_file && (dump_flags & TDF_DETAILS))
02265 {
02266 fprintf (dump_file, "(dependence classified: ");
02267 print_generic_expr (dump_file, chrec, 0);
02268 fprintf (dump_file, ")\n");
02269 }
02270
02271 DDR_ARE_DEPENDENT (ddr) = chrec;
02272 VEC_free (subscript_p, heap, DDR_SUBSCRIPTS (ddr));
02273 }
02274
02275
02276
02277
02278 static inline void
02279 non_affine_dependence_relation (struct data_dependence_relation *ddr)
02280 {
02281 if (dump_file && (dump_flags & TDF_DETAILS))
02282 fprintf (dump_file, "(Dependence relation cannot be represented by distance vector.) \n");
02283
02284 DDR_AFFINE_P (ddr) = false;
02285 }
02286
02287
02288
02289
02290
02291
02292
02293
02294 static inline bool
02295 ziv_subscript_p (tree chrec_a,
02296 tree chrec_b)
02297 {
02298 return (evolution_function_is_constant_p (chrec_a)
02299 && evolution_function_is_constant_p (chrec_b));
02300 }
02301
02302
02303
02304
02305 static bool
02306 siv_subscript_p (tree chrec_a,
02307 tree chrec_b)
02308 {
02309 if ((evolution_function_is_constant_p (chrec_a)
02310 && evolution_function_is_univariate_p (chrec_b))
02311 || (evolution_function_is_constant_p (chrec_b)
02312 && evolution_function_is_univariate_p (chrec_a)))
02313 return true;
02314
02315 if (evolution_function_is_univariate_p (chrec_a)
02316 && evolution_function_is_univariate_p (chrec_b))
02317 {
02318 switch (TREE_CODE (chrec_a))
02319 {
02320 case POLYNOMIAL_CHREC:
02321 switch (TREE_CODE (chrec_b))
02322 {
02323 case POLYNOMIAL_CHREC:
02324 if (CHREC_VARIABLE (chrec_a) != CHREC_VARIABLE (chrec_b))
02325 return false;
02326
02327 default:
02328 return true;
02329 }
02330
02331 default:
02332 return true;
02333 }
02334 }
02335
02336 return false;
02337 }
02338
02339
02340
02341
02342
02343
02344
02345
02346 static void
02347 analyze_ziv_subscript (tree chrec_a,
02348 tree chrec_b,
02349 tree *overlaps_a,
02350 tree *overlaps_b,
02351 tree *last_conflicts)
02352 {
02353 tree difference;
02354 dependence_stats.num_ziv++;
02355
02356 if (dump_file && (dump_flags & TDF_DETAILS))
02357 fprintf (dump_file, "(analyze_ziv_subscript \n");
02358
02359 chrec_a = chrec_convert (integer_type_node, chrec_a, NULL_TREE);
02360 chrec_b = chrec_convert (integer_type_node, chrec_b, NULL_TREE);
02361 difference = chrec_fold_minus (integer_type_node, chrec_a, chrec_b);
02362
02363 switch (TREE_CODE (difference))
02364 {
02365 case INTEGER_CST:
02366 if (integer_zerop (difference))
02367 {
02368
02369
02370 *overlaps_a = integer_zero_node;
02371 *overlaps_b = integer_zero_node;
02372 *last_conflicts = chrec_dont_know;
02373 dependence_stats.num_ziv_dependent++;
02374 }
02375 else
02376 {
02377
02378 *overlaps_a = chrec_known;
02379 *overlaps_b = chrec_known;
02380 *last_conflicts = integer_zero_node;
02381 dependence_stats.num_ziv_independent++;
02382 }
02383 break;
02384
02385 default:
02386
02387
02388 if (dump_file && (dump_flags & TDF_DETAILS))
02389 fprintf (dump_file, "ziv test failed: difference is non-integer.\n");
02390
02391 *overlaps_a = chrec_dont_know;
02392 *overlaps_b = chrec_dont_know;
02393 *last_conflicts = chrec_dont_know;
02394 dependence_stats.num_ziv_unimplemented++;
02395 break;
02396 }
02397
02398 if (dump_file && (dump_flags & TDF_DETAILS))
02399 fprintf (dump_file, ")\n");
02400 }
02401
02402
02403
02404
02405
02406 static tree
02407 get_number_of_iters_for_loop (int loopnum)
02408 {
02409 tree numiter = number_of_iterations_in_loop (current_loops->parray[loopnum]);
02410
02411 if (TREE_CODE (numiter) != INTEGER_CST)
02412 numiter = current_loops->parray[loopnum]->estimated_nb_iterations;
02413 if (chrec_contains_undetermined (numiter))
02414 return NULL_TREE;
02415 return numiter;
02416 }
02417
02418
02419
02420
02421
02422
02423
02424
02425
02426 static void
02427 analyze_siv_subscript_cst_affine (tree chrec_a,
02428 tree chrec_b,
02429 tree *overlaps_a,
02430 tree *overlaps_b,
02431 tree *last_conflicts)
02432 {
02433 bool value0, value1, value2;
02434 tree difference;
02435
02436 chrec_a = chrec_convert (integer_type_node, chrec_a, NULL_TREE);
02437 chrec_b = chrec_convert (integer_type_node, chrec_b, NULL_TREE);
02438 difference = chrec_fold_minus
02439 (integer_type_node, initial_condition (chrec_b), chrec_a);
02440
02441 if (!chrec_is_positive (initial_condition (difference), &value0))
02442 {
02443 if (dump_file && (dump_flags & TDF_DETAILS))
02444 fprintf (dump_file, "siv test failed: chrec is not positive.\n");
02445
02446 dependence_stats.num_siv_unimplemented++;
02447 *overlaps_a = chrec_dont_know;
02448 *overlaps_b = chrec_dont_know;
02449 *last_conflicts = chrec_dont_know;
02450 return;
02451 }
02452 else
02453 {
02454 if (value0 == false)
02455 {
02456 if (!chrec_is_positive (CHREC_RIGHT (chrec_b), &value1))
02457 {
02458 if (dump_file && (dump_flags & TDF_DETAILS))
02459 fprintf (dump_file, "siv test failed: chrec not positive.\n");
02460
02461 *overlaps_a = chrec_dont_know;
02462 *overlaps_b = chrec_dont_know;
02463 *last_conflicts = chrec_dont_know;
02464 dependence_stats.num_siv_unimplemented++;
02465 return;
02466 }
02467 else
02468 {
02469 if (value1 == true)
02470 {
02471
02472
02473
02474
02475
02476 if (tree_fold_divides_p (CHREC_RIGHT (chrec_b), difference))
02477 {
02478 tree numiter;
02479 int loopnum = CHREC_VARIABLE (chrec_b);
02480
02481 *overlaps_a = integer_zero_node;
02482 *overlaps_b = fold_build2 (EXACT_DIV_EXPR, integer_type_node,
02483 fold_build1 (ABS_EXPR,
02484 integer_type_node,
02485 difference),
02486 CHREC_RIGHT (chrec_b));
02487 *last_conflicts = integer_one_node;
02488
02489
02490
02491
02492 numiter = get_number_of_iters_for_loop (loopnum);
02493
02494 if (numiter != NULL_TREE
02495 && TREE_CODE (*overlaps_b) == INTEGER_CST
02496 && tree_int_cst_lt (numiter, *overlaps_b))
02497 {
02498 *overlaps_a = chrec_known;
02499 *overlaps_b = chrec_known;
02500 *last_conflicts = integer_zero_node;
02501 dependence_stats.num_siv_independent++;
02502 return;
02503 }
02504 dependence_stats.num_siv_dependent++;
02505 return;
02506 }
02507
02508
02509
02510 else
02511 {
02512 *overlaps_a = chrec_known;
02513 *overlaps_b = chrec_known;
02514 *last_conflicts = integer_zero_node;
02515 dependence_stats.num_siv_independent++;
02516 return;
02517 }
02518 }
02519
02520 else
02521 {
02522
02523
02524
02525
02526
02527 *overlaps_a = chrec_known;
02528 *overlaps_b = chrec_known;
02529 *last_conflicts = integer_zero_node;
02530 dependence_stats.num_siv_independent++;
02531 return;
02532 }
02533 }
02534 }
02535 else
02536 {
02537 if (!chrec_is_positive (CHREC_RIGHT (chrec_b), &value2))
02538 {
02539 if (dump_file && (dump_flags & TDF_DETAILS))
02540 fprintf (dump_file, "siv test failed: chrec not positive.\n");
02541
02542 *overlaps_a = chrec_dont_know;
02543 *overlaps_b = chrec_dont_know;
02544 *last_conflicts = chrec_dont_know;
02545 dependence_stats.num_siv_unimplemented++;
02546 return;
02547 }
02548 else
02549 {
02550 if (value2 == false)
02551 {
02552
02553
02554
02555
02556 if (tree_fold_divides_p (CHREC_RIGHT (chrec_b), difference))
02557 {
02558 tree numiter;
02559 int loopnum = CHREC_VARIABLE (chrec_b);
02560
02561 *overlaps_a = integer_zero_node;
02562 *overlaps_b = fold_build2 (EXACT_DIV_EXPR,
02563 integer_type_node, difference,
02564 CHREC_RIGHT (chrec_b));
02565 *last_conflicts = integer_one_node;
02566
02567
02568
02569 numiter = get_number_of_iters_for_loop (loopnum);
02570
02571 if (numiter != NULL_TREE
02572 && TREE_CODE (*overlaps_b) == INTEGER_CST
02573 && tree_int_cst_lt (numiter, *overlaps_b))
02574 {
02575 *overlaps_a = chrec_known;
02576 *overlaps_b = chrec_known;
02577 *last_conflicts = integer_zero_node;
02578 dependence_stats.num_siv_independent++;
02579 return;
02580 }
02581 dependence_stats.num_siv_dependent++;
02582 return;
02583 }
02584
02585
02586
02587 else
02588 {
02589 *overlaps_a = chrec_known;
02590 *overlaps_b = chrec_known;
02591 *last_conflicts = integer_zero_node;
02592 dependence_stats.num_siv_independent++;
02593 return;
02594 }
02595 }
02596 else
02597 {
02598
02599
02600
02601
02602
02603 *overlaps_a = chrec_known;
02604 *overlaps_b = chrec_known;
02605 *last_conflicts = integer_zero_node;
02606 dependence_stats.num_siv_independent++;
02607 return;
02608 }
02609 }
02610 }
02611 }
02612 }
02613
02614
02615
02616
02617 static int
02618 initialize_matrix_A (lambda_matrix A, tree chrec, unsigned index, int mult)
02619 {
02620 gcc_assert (chrec);
02621
02622 if (TREE_CODE (chrec) != POLYNOMIAL_CHREC)
02623 return int_cst_value (chrec);
02624
02625 A[index][0] = mult * int_cst_value (CHREC_RIGHT (chrec));
02626 return initialize_matrix_A (A, CHREC_LEFT (chrec), index + 1, mult);
02627 }
02628
02629 #define FLOOR_DIV(x,y) ((x) / (y))
02630
02631
02632
02633
02634
02635
02636
02637
02638 static void
02639 compute_overlap_steps_for_affine_univar (int niter, int step_a, int step_b,
02640 tree *overlaps_a, tree *overlaps_b,
02641 tree *last_conflicts, int dim)
02642 {
02643 if (((step_a > 0 && step_b > 0)
02644 || (step_a < 0 && step_b < 0)))
02645 {
02646 int step_overlaps_a, step_overlaps_b;
02647 int gcd_steps_a_b, last_conflict, tau2;
02648
02649 gcd_steps_a_b = gcd (step_a, step_b);
02650 step_overlaps_a = step_b / gcd_steps_a_b;
02651 step_overlaps_b = step_a / gcd_steps_a_b;
02652
02653 tau2 = FLOOR_DIV (niter, step_overlaps_a);
02654 tau2 = MIN (tau2, FLOOR_DIV (niter, step_overlaps_b));
02655 last_conflict = tau2;
02656
02657 *overlaps_a = build_polynomial_chrec
02658 (dim, integer_zero_node,
02659 build_int_cst (NULL_TREE, step_overlaps_a));
02660 *overlaps_b = build_polynomial_chrec
02661 (dim, integer_zero_node,
02662 build_int_cst (NULL_TREE, step_overlaps_b));
02663 *last_conflicts = build_int_cst (NULL_TREE, last_conflict);
02664 }
02665
02666 else
02667 {
02668 *overlaps_a = integer_zero_node;
02669 *overlaps_b = integer_zero_node;
02670 *last_conflicts = integer_zero_node;
02671 }
02672 }
02673
02674
02675
02676
02677
02678
02679
02680
02681
02682
02683
02684
02685
02686
02687
02688
02689
02690 static void
02691 compute_overlap_steps_for_affine_1_2 (tree chrec_a, tree chrec_b,
02692 tree *overlaps_a, tree *overlaps_b,
02693 tree *last_conflicts)
02694 {
02695 bool xz_p, yz_p, xyz_p;
02696 int step_x, step_y, step_z;
02697 int niter_x, niter_y, niter_z, niter;
02698 tree numiter_x, numiter_y, numiter_z;
02699 tree overlaps_a_xz, overlaps_b_xz, last_conflicts_xz;
02700 tree overlaps_a_yz, overlaps_b_yz, last_conflicts_yz;
02701 tree overlaps_a_xyz, overlaps_b_xyz, last_conflicts_xyz;
02702
02703 step_x = int_cst_value (CHREC_RIGHT (CHREC_LEFT (chrec_a)));
02704 step_y = int_cst_value (CHREC_RIGHT (chrec_a));
02705 step_z = int_cst_value (CHREC_RIGHT (chrec_b));
02706
02707 numiter_x = get_number_of_iters_for_loop (CHREC_VARIABLE (CHREC_LEFT (chrec_a)));
02708 numiter_y = get_number_of_iters_for_loop (CHREC_VARIABLE (chrec_a));
02709 numiter_z = get_number_of_iters_for_loop (CHREC_VARIABLE (chrec_b));
02710
02711 if (numiter_x == NULL_TREE || numiter_y == NULL_TREE
02712 || numiter_z == NULL_TREE)
02713 {
02714 if (dump_file && (dump_flags & TDF_DETAILS))
02715 fprintf (dump_file, "overlap steps test failed: no iteration counts.\n");
02716
02717 *overlaps_a = chrec_dont_know;
02718 *overlaps_b = chrec_dont_know;
02719 *last_conflicts = chrec_dont_know;
02720 return;
02721 }
02722
02723 niter_x = int_cst_value (numiter_x);
02724 niter_y = int_cst_value (numiter_y);
02725 niter_z = int_cst_value (numiter_z);
02726
02727 niter = MIN (niter_x, niter_z);
02728 compute_overlap_steps_for_affine_univar (niter, step_x, step_z,
02729 &overlaps_a_xz,
02730 &overlaps_b_xz,
02731 &last_conflicts_xz, 1);
02732 niter = MIN (niter_y, niter_z);
02733 compute_overlap_steps_for_affine_univar (niter, step_y, step_z,
02734 &overlaps_a_yz,
02735 &overlaps_b_yz,
02736 &last_conflicts_yz, 2);
02737 niter = MIN (niter_x, niter_z);
02738 niter = MIN (niter_y, niter);
02739 compute_overlap_steps_for_affine_univar (niter, step_x + step_y, step_z,
02740 &overlaps_a_xyz,
02741 &overlaps_b_xyz,
02742 &last_conflicts_xyz, 3);
02743
02744 xz_p = !integer_zerop (last_conflicts_xz);
02745 yz_p = !integer_zerop (last_conflicts_yz);
02746 xyz_p = !integer_zerop (last_conflicts_xyz);
02747
02748 if (xz_p || yz_p || xyz_p)
02749 {
02750 *overlaps_a = make_tree_vec (2);
02751 TREE_VEC_ELT (*overlaps_a, 0) = integer_zero_node;
02752 TREE_VEC_ELT (*overlaps_a, 1) = integer_zero_node;
02753 *overlaps_b = integer_zero_node;
02754 if (xz_p)
02755 {
02756 tree t0 = chrec_convert (integer_type_node,
02757 TREE_VEC_ELT (*overlaps_a, 0), NULL_TREE);
02758 tree t1 = chrec_convert (integer_type_node, overlaps_a_xz,
02759 NULL_TREE);
02760 tree t2 = chrec_convert (integer_type_node, *overlaps_b,
02761 NULL_TREE);
02762 tree t3 = chrec_convert (integer_type_node, overlaps_b_xz,
02763 NULL_TREE);
02764
02765 TREE_VEC_ELT (*overlaps_a, 0) = chrec_fold_plus (integer_type_node,
02766 t0, t1);
02767 *overlaps_b = chrec_fold_plus (integer_type_node, t2, t3);
02768 *last_conflicts = last_conflicts_xz;
02769 }
02770 if (yz_p)
02771 {
02772 tree t0 = chrec_convert (integer_type_node,
02773 TREE_VEC_ELT (*overlaps_a, 1), NULL_TREE);
02774 tree t1 = chrec_convert (integer_type_node, overlaps_a_yz, NULL_TREE);
02775 tree t2 = chrec_convert (integer_type_node, *overlaps_b, NULL_TREE);
02776 tree t3 = chrec_convert (integer_type_node, overlaps_b_yz, NULL_TREE);
02777
02778 TREE_VEC_ELT (*overlaps_a, 1) = chrec_fold_plus (integer_type_node,
02779 t0, t1);
02780 *overlaps_b = chrec_fold_plus (integer_type_node, t2, t3);
02781 *last_conflicts = last_conflicts_yz;
02782 }
02783 if (xyz_p)
02784 {
02785 tree t0 = chrec_convert (integer_type_node,
02786 TREE_VEC_ELT (*overlaps_a, 0), NULL_TREE);
02787 tree t1 = chrec_convert (integer_type_node, overlaps_a_xyz,
02788 NULL_TREE);
02789 tree t2 = chrec_convert (integer_type_node,
02790 TREE_VEC_ELT (*overlaps_a, 1), NULL_TREE);
02791 tree t3 = chrec_convert (integer_type_node, overlaps_a_xyz,
02792 NULL_TREE);
02793 tree t4 = chrec_convert (integer_type_node, *overlaps_b, NULL_TREE);
02794 tree t5 = chrec_convert (integer_type_node, overlaps_b_xyz,
02795 NULL_TREE);
02796
02797 TREE_VEC_ELT (*overlaps_a, 0) = chrec_fold_plus (integer_type_node,
02798 t0, t1);
02799 TREE_VEC_ELT (*overlaps_a, 1) = chrec_fold_plus (integer_type_node,
02800 t2, t3);
02801 *overlaps_b = chrec_fold_plus (integer_type_node, t4, t5);
02802 *last_conflicts = last_conflicts_xyz;
02803 }
02804 }
02805 else
02806 {
02807 *overlaps_a = integer_zero_node;
02808 *overlaps_b = integer_zero_node;
02809 *last_conflicts = integer_zero_node;
02810 }
02811 }
02812
02813
02814
02815
02816
02817
02818 static void
02819 analyze_subscript_affine_affine (tree chrec_a,
02820 tree chrec_b,
02821 tree *overlaps_a,
02822 tree *overlaps_b,
02823 tree *last_conflicts)
02824 {
02825 unsigned nb_vars_a, nb_vars_b, dim;
02826 int init_a, init_b, gamma, gcd_alpha_beta;
02827 int tau1, tau2;
02828 lambda_matrix A, U, S;
02829
02830 if (eq_evolutions_p (chrec_a, chrec_b))
02831 {
02832
02833
02834 *overlaps_a = integer_zero_node;
02835 *overlaps_b = integer_zero_node;
02836 *last_conflicts = chrec_dont_know;
02837 return;
02838 }
02839 if (dump_file && (dump_flags & TDF_DETAILS))
02840 fprintf (dump_file, "(analyze_subscript_affine_affine \n");
02841
02842
02843
02844
02845
02846
02847
02848
02849
02850
02851
02852
02853 nb_vars_a = nb_vars_in_chrec (chrec_a);
02854 nb_vars_b = nb_vars_in_chrec (chrec_b);
02855
02856 dim = nb_vars_a + nb_vars_b;
02857 U = lambda_matrix_new (dim, dim);
02858 A = lambda_matrix_new (dim, 1);
02859 S = lambda_matrix_new (dim, 1);
02860
02861 init_a = initialize_matrix_A (A, chrec_a, 0, 1);
02862 init_b = initialize_matrix_A (A, chrec_b, nb_vars_a, -1);
02863 gamma = init_b - init_a;
02864
02865
02866
02867
02868
02869
02870
02871
02872
02873 if (gamma == 0)
02874 {
02875 if (nb_vars_a == 1 && nb_vars_b == 1)
02876 {
02877 int step_a, step_b;
02878 int niter, niter_a, niter_b;
02879 tree numiter_a, numiter_b;
02880
02881 numiter_a = get_number_of_iters_for_loop (CHREC_VARIABLE (chrec_a));
02882 numiter_b = get_number_of_iters_for_loop (CHREC_VARIABLE (chrec_b));
02883 if (numiter_a == NULL_TREE || numiter_b == NULL_TREE)
02884 {
02885 if (dump_file && (dump_flags & TDF_DETAILS))
02886 fprintf (dump_file, "affine-affine test failed: missing iteration counts.\n");
02887 *overlaps_a = chrec_dont_know;
02888 *overlaps_b = chrec_dont_know;
02889 *last_conflicts = chrec_dont_know;
02890 goto end_analyze_subs_aa;
02891 }
02892
02893 niter_a = int_cst_value (numiter_a);
02894 niter_b = int_cst_value (numiter_b);
02895 niter = MIN (niter_a, niter_b);
02896
02897 step_a = int_cst_value (CHREC_RIGHT (chrec_a));
02898 step_b = int_cst_value (CHREC_RIGHT (chrec_b));
02899
02900 compute_overlap_steps_for_affine_univar (niter, step_a, step_b,
02901 overlaps_a, overlaps_b,
02902 last_conflicts, 1);
02903 }
02904
02905 else if (nb_vars_a == 2 && nb_vars_b == 1)
02906 compute_overlap_steps_for_affine_1_2
02907 (chrec_a, chrec_b, overlaps_a, overlaps_b, last_conflicts);
02908
02909 else if (nb_vars_a == 1 && nb_vars_b == 2)
02910 compute_overlap_steps_for_affine_1_2
02911 (chrec_b, chrec_a, overlaps_b, overlaps_a, last_conflicts);
02912
02913 else
02914 {
02915 if (dump_file && (dump_flags & TDF_DETAILS))
02916 fprintf (dump_file, "affine-affine test failed: too many variables.\n");
02917 *overlaps_a = chrec_dont_know;
02918 *overlaps_b = chrec_dont_know;
02919 *last_conflicts = chrec_dont_know;
02920 }
02921 goto end_analyze_subs_aa;
02922 }
02923
02924
02925 lambda_matrix_right_hermite (A, dim, 1, S, U);
02926
02927 if (S[0][0] < 0)
02928 {
02929 S[0][0] *= -1;
02930 lambda_matrix_row_negate (U, dim, 0);
02931 }
02932 gcd_alpha_beta = S[0][0];
02933
02934
02935
02936
02937 if (gcd_alpha_beta == 0)
02938 {
02939 *overlaps_a = chrec_dont_know;
02940 *overlaps_b = chrec_dont_know;
02941 *last_conflicts = chrec_dont_know;
02942 goto end_analyze_subs_aa;
02943 }
02944
02945
02946 if (!int_divides_p (gcd_alpha_beta, gamma))
02947 {
02948
02949
02950 *overlaps_a = chrec_known;
02951 *overlaps_b = chrec_known;
02952 *last_conflicts = integer_zero_node;
02953 }
02954
02955
02956 else if (nb_vars_a == 1 && nb_vars_b == 1)
02957 {
02958
02959 if (((A[0][0] > 0 && -A[1][0] > 0)
02960 || (A[0][0] < 0 && -A[1][0] < 0)))
02961 {
02962
02963
02964
02965
02966
02967
02968
02969
02970
02971
02972
02973
02974
02975
02976
02977
02978
02979 int i0, j0, i1, j1;
02980
02981
02982
02983
02984 int x0, y0;
02985 int niter, niter_a, niter_b;
02986 tree numiter_a, numiter_b;
02987
02988 numiter_a = get_number_of_iters_for_loop (CHREC_VARIABLE (chrec_a));
02989 numiter_b = get_number_of_iters_for_loop (CHREC_VARIABLE (chrec_b));
02990
02991 if (numiter_a == NULL_TREE || numiter_b == NULL_TREE)
02992 {
02993 if (dump_file && (dump_flags & TDF_DETAILS))
02994 fprintf (dump_file, "affine-affine test failed: missing iteration counts.\n");
02995 *overlaps_a = chrec_dont_know;
02996 *overlaps_b = chrec_dont_know;
02997 *last_conflicts = chrec_dont_know;
02998 goto end_analyze_subs_aa;
02999 }
03000
03001 niter_a = int_cst_value (numiter_a);
03002 niter_b = int_cst_value (numiter_b);
03003 niter = MIN (niter_a, niter_b);
03004
03005 i0 = U[0][0] * gamma / gcd_alpha_beta;
03006 j0 = U[0][1] * gamma / gcd_alpha_beta;
03007 i1 = U[1][0];
03008 j1 = U[1][1];
03009
03010 if ((i1 == 0 && i0 < 0)
03011 || (j1 == 0 && j0 < 0))
03012 {
03013
03014
03015
03016
03017 *overlaps_a = chrec_known;
03018 *overlaps_b = chrec_known;
03019 *last_conflicts = integer_zero_node;
03020 }
03021
03022 else
03023 {
03024 if (i1 > 0)
03025 {
03026 tau1 = CEIL (-i0, i1);
03027 tau2 = FLOOR_DIV (niter - i0, i1);
03028
03029 if (j1 > 0)
03030 {
03031 int last_conflict, min_multiple;
03032 tau1 = MAX (tau1, CEIL (-j0, j1));
03033 tau2 = MIN (tau2, FLOOR_DIV (niter - j0, j1));
03034
03035 x0 = i1 * tau1 + i0;
03036 y0 = j1 * tau1 + j0;
03037
03038
03039
03040
03041
03042 min_multiple = MIN (x0 / i1, y0 / j1);
03043 x0 -= i1 * min_multiple;
03044 y0 -= j1 * min_multiple;
03045
03046 tau1 = (x0 - i0)/i1;
03047 last_conflict = tau2 - tau1;
03048
03049
03050
03051 if (x0 > niter || y0 > niter)
03052 {
03053 *overlaps_a = chrec_known;
03054 *overlaps_b = chrec_known;
03055 *last_conflicts = integer_zero_node;
03056 }
03057 else
03058 {
03059 *overlaps_a = build_polynomial_chrec
03060 (1,
03061 build_int_cst (NULL_TREE, x0),
03062 build_int_cst (NULL_TREE, i1));
03063 *overlaps_b = build_polynomial_chrec
03064 (1,
03065 build_int_cst (NULL_TREE, y0),
03066 build_int_cst (NULL_TREE, j1));
03067 *last_conflicts = build_int_cst (NULL_TREE, last_conflict);
03068 }
03069 }
03070 else
03071 {
03072
03073
03074 if (dump_file && (dump_flags & TDF_DETAILS))
03075 fprintf (dump_file, "affine-affine test failed: unimplemented.\n");
03076 *overlaps_a = chrec_dont_know;
03077 *overlaps_b = chrec_dont_know;
03078 *last_conflicts = chrec_dont_know;
03079 }
03080 }
03081
03082 else
03083 {
03084
03085
03086 if (dump_file && (dump_flags & TDF_DETAILS))
03087 fprintf (dump_file, "affine-affine test failed: unimplemented.\n");
03088 *overlaps_a = chrec_dont_know;
03089 *overlaps_b = chrec_dont_know;
03090 *last_conflicts = chrec_dont_know;
03091 }
03092 }
03093 }
03094 else
03095 {
03096 if (dump_file && (dump_flags & TDF_DETAILS))
03097 fprintf (dump_file, "affine-affine test failed: unimplemented.\n");
03098 *overlaps_a = chrec_dont_know;
03099 *overlaps_b = chrec_dont_know;
03100 *last_conflicts = chrec_dont_know;
03101 }
03102 }
03103
03104 else
03105 {
03106 if (dump_file && (dump_flags & TDF_DETAILS))
03107 fprintf (dump_file, "affine-affine test failed: unimplemented.\n");
03108 *overlaps_a = chrec_dont_know;
03109 *overlaps_b = chrec_dont_know;
03110 *last_conflicts = chrec_dont_know;
03111 }
03112
03113 end_analyze_subs_aa:
03114 if (dump_file && (dump_flags & TDF_DETAILS))
03115 {
03116 fprintf (dump_file, " (overlaps_a = ");
03117 print_generic_expr (dump_file, *overlaps_a, 0);
03118 fprintf (dump_file, ")\n (overlaps_b = ");
03119 print_generic_expr (dump_file, *overlaps_b, 0);
03120 fprintf (dump_file, ")\n");
03121 fprintf (dump_file, ")\n");
03122 }
03123 }
03124
03125
03126
03127
03128
03129
03130
03131
03132
03133
03134
03135
03136
03137
03138
03139 static bool
03140 can_use_analyze_subscript_affine_affine (tree *chrec_a, tree *chrec_b)
03141 {
03142 tree diff, type, left_a, left_b, right_b;
03143
03144 if (chrec_contains_symbols (CHREC_RIGHT (*chrec_a))
03145 || chrec_contains_symbols (CHREC_RIGHT (*chrec_b)))
03146
03147 return false;
03148
03149 type = chrec_type (*chrec_a);
03150 left_a = CHREC_LEFT (*chrec_a);
03151 left_b = chrec_convert (type, CHREC_LEFT (*chrec_b), NULL_TREE);
03152 diff = chrec_fold_minus (type, left_a, left_b);
03153
03154 if (!evolution_function_is_constant_p (diff))
03155 return false;
03156
03157 if (dump_file && (dump_flags & TDF_DETAILS))
03158 fprintf (dump_file, "can_use_subscript_aff_aff_for_symbolic \n");
03159
03160 *chrec_a = build_polynomial_chrec (CHREC_VARIABLE (*chrec_a),
03161 diff, CHREC_RIGHT (*chrec_a));
03162 right_b = chrec_convert (type, CHREC_RIGHT (*chrec_b), NULL_TREE);
03163 *chrec_b = build_polynomial_chrec (CHREC_VARIABLE (*chrec_b),
03164 build_int_cst (type, 0),
03165 right_b);
03166 return true;
03167 }
03168
03169
03170
03171
03172
03173
03174
03175
03176 static void
03177 analyze_siv_subscript (tree chrec_a,
03178 tree chrec_b,
03179 tree *overlaps_a,
03180 tree *overlaps_b,
03181 tree *last_conflicts)
03182 {
03183 dependence_stats.num_siv++;
03184
03185 if (dump_file && (dump_flags & TDF_DETAILS))
03186 fprintf (dump_file, "(analyze_siv_subscript \n");
03187
03188 if (evolution_function_is_constant_p (chrec_a)
03189 && evolution_function_is_affine_p (chrec_b))
03190 analyze_siv_subscript_cst_affine (chrec_a, chrec_b,
03191 overlaps_a, overlaps_b, last_conflicts);
03192
03193 else if (evolution_function_is_affine_p (chrec_a)
03194 && evolution_function_is_constant_p (chrec_b))
03195 analyze_siv_subscript_cst_affine (chrec_b, chrec_a,
03196 overlaps_b, overlaps_a, last_conflicts);
03197
03198 else if (evolution_function_is_affine_p (chrec_a)
03199 && evolution_function_is_affine_p (chrec_b))
03200 {
03201 if (!chrec_contains_symbols (chrec_a)
03202 && !chrec_contains_symbols (chrec_b))
03203 {
03204 analyze_subscript_affine_affine (chrec_a, chrec_b,
03205 overlaps_a, overlaps_b,
03206 last_conflicts);
03207
03208 if (*overlaps_a == chrec_dont_know
03209 || *overlaps_b == chrec_dont_know)
03210 dependence_stats.num_siv_unimplemented++;
03211 else if (*overlaps_a == chrec_known
03212 || *overlaps_b == chrec_known)
03213 dependence_stats.num_siv_independent++;
03214 else
03215 dependence_stats.num_siv_dependent++;
03216 }
03217 else if (can_use_analyze_subscript_affine_affine (&chrec_a,
03218 &chrec_b))
03219 {
03220 analyze_subscript_affine_affine (chrec_a, chrec_b,
03221 overlaps_a, overlaps_b,
03222 last_conflicts);
03223
03224
03225 *last_conflicts = chrec_dont_know;
03226
03227 if (*overlaps_a == chrec_dont_know
03228 || *overlaps_b == chrec_dont_know)
03229 dependence_stats.num_siv_unimplemented++;
03230 else if (*overlaps_a == chrec_known
03231 || *overlaps_b == chrec_known)
03232 dependence_stats.num_siv_independent++;
03233 else
03234 dependence_stats.num_siv_dependent++;
03235 }
03236 else
03237 goto siv_subscript_dontknow;
03238 }
03239
03240 else
03241 {
03242 siv_subscript_dontknow:;
03243 if (dump_file && (dump_flags & TDF_DETAILS))
03244 fprintf (dump_file, "siv test failed: unimplemented.\n");
03245 *overlaps_a = chrec_dont_know;
03246 *overlaps_b = chrec_dont_know;
03247 *last_conflicts = chrec_dont_know;
03248 dependence_stats.num_siv_unimplemented++;
03249 }
03250
03251 if (dump_file && (dump_flags & TDF_DETAILS))
03252 fprintf (dump_file, ")\n");
03253 }
03254
03255
03256
03257
03258
03259
03260 static bool
03261 chrec_steps_divide_constant_p (tree chrec,
03262 tree cst,
03263 bool *res)
03264 {
03265 switch (TREE_CODE (chrec))
03266 {
03267 case POLYNOMIAL_CHREC:
03268 if (evolution_function_is_constant_p (CHREC_RIGHT (chrec)))
03269 {
03270 if (tree_fold_divides_p (CHREC_RIGHT (chrec), cst))
03271
03272 return chrec_steps_divide_constant_p (CHREC_LEFT (chrec), cst, res);
03273
03274 *res = false;
03275 return true;
03276 }
03277 else
03278
03279 return false;
03280
03281 default:
03282
03283 return true;
03284 }
03285 }
03286
03287
03288
03289
03290
03291
03292
03293
03294 static void
03295 analyze_miv_subscript (tree chrec_a,
03296 tree chrec_b,
03297 tree *overlaps_a,
03298 tree *overlaps_b,
03299 tree *last_conflicts)
03300 {
03301
03302
03303
03304
03305
03306
03307
03308
03309 bool divide_p = true;
03310 tree difference;
03311 dependence_stats.num_miv++;
03312 if (dump_file && (dump_flags & TDF_DETAILS))
03313 fprintf (dump_file, "(analyze_miv_subscript \n");
03314
03315 chrec_a = chrec_convert (integer_type_node, chrec_a, NULL_TREE);
03316 chrec_b = chrec_convert (integer_type_node, chrec_b, NULL_TREE);
03317 difference = chrec_fold_minus (integer_type_node, chrec_a, chrec_b);
03318
03319 if (eq_evolutions_p (chrec_a, chrec_b))
03320 {
03321
03322
03323 *overlaps_a = integer_zero_node;
03324 *overlaps_b = integer_zero_node;
03325 *last_conflicts = get_number_of_iters_for_loop (CHREC_VARIABLE (chrec_a));
03326 dependence_stats.num_miv_dependent++;
03327 }
03328
03329 else if (evolution_function_is_constant_p (difference)
03330
03331
03332 && chrec_steps_divide_constant_p (chrec_a, difference, ÷_p)
03333 && !divide_p)
03334 {
03335
03336
03337
03338
03339
03340 *overlaps_a = chrec_known;
03341 *overlaps_b = chrec_known;
03342 *last_conflicts = integer_zero_node;
03343 dependence_stats.num_miv_independent++;
03344 }
03345
03346 else if (evolution_function_is_affine_multivariate_p (chrec_a)
03347 && !chrec_contains_symbols (chrec_a)
03348 && evolution_function_is_affine_multivariate_p (chrec_b)
03349 && !chrec_contains_symbols (chrec_b))
03350 {
03351
03352
03353
03354
03355
03356
03357
03358
03359
03360
03361
03362
03363
03364
03365 analyze_subscript_affine_affine (chrec_a, chrec_b,
03366 overlaps_a, overlaps_b, last_conflicts);
03367
03368 if (*overlaps_a == chrec_dont_know
03369 || *overlaps_b == chrec_dont_know)
03370 dependence_stats.num_miv_unimplemented++;
03371 else if (*overlaps_a == chrec_known
03372 || *overlaps_b == chrec_known)
03373 dependence_stats.num_miv_independent++;
03374 else
03375 dependence_stats.num_miv_dependent++;
03376 }
03377
03378 else
03379 {
03380
03381 if (dump_file && (dump_flags & TDF_DETAILS))
03382 fprintf (dump_file, "analyze_miv_subscript test failed: unimplemented.\n");
03383
03384 *overlaps_a = chrec_dont_know;
03385 *overlaps_b = chrec_dont_know;
03386 *last_conflicts = chrec_dont_know;
03387 dependence_stats.num_miv_unimplemented++;
03388 }
03389
03390 if (dump_file && (dump_flags & TDF_DETAILS))
03391 fprintf (dump_file, ")\n");
03392 }
03393
03394
03395
03396
03397
03398
03399
03400
03401
03402
03403
03404 static void
03405 analyze_overlapping_iterations (tree chrec_a,
03406 tree chrec_b,
03407 tree *overlap_iterations_a,
03408 tree *overlap_iterations_b,
03409 tree *last_conflicts)
03410 {
03411 dependence_stats.num_subscript_tests++;
03412
03413 if (dump_file && (dump_flags & TDF_DETAILS))
03414 {
03415 fprintf (dump_file, "(analyze_overlapping_iterations \n");
03416 fprintf (dump_file, " (chrec_a = ");
03417 print_generic_expr (dump_file, chrec_a, 0);
03418 fprintf (dump_file, ")\n (chrec_b = ");
03419 print_generic_expr (dump_file, chrec_b, 0);
03420 fprintf (dump_file, ")\n");
03421 }
03422
03423 if (chrec_a == NULL_TREE
03424 || chrec_b == NULL_TREE
03425 || chrec_contains_undetermined (chrec_a)
03426 || chrec_contains_undetermined (chrec_b))
03427 {
03428 dependence_stats.num_subscript_undetermined++;
03429
03430 *overlap_iterations_a = chrec_dont_know;
03431 *overlap_iterations_b = chrec_dont_know;
03432 }
03433
03434
03435
03436 else if (eq_evolutions_p (chrec_a, chrec_b)
03437 && evolution_function_is_affine_multivariate_p (chrec_a))
03438 {
03439 dependence_stats.num_same_subscript_function++;
03440 *overlap_iterations_a = integer_zero_node;
03441 *overlap_iterations_b = integer_zero_node;
03442 *last_conflicts = chrec_dont_know;
03443 }
03444
03445
03446
03447 else if ((chrec_contains_symbols (chrec_a)
03448 || chrec_contains_symbols (chrec_b))
03449 && (!evolution_function_is_affine_multivariate_p (chrec_a)
03450 || !evolution_function_is_affine_multivariate_p (chrec_b)))
03451 {
03452 dependence_stats.num_subscript_undetermined++;
03453 *overlap_iterations_a = chrec_dont_know;
03454 *overlap_iterations_b = chrec_dont_know;
03455 }
03456
03457 else if (ziv_subscript_p (chrec_a, chrec_b))
03458 analyze_ziv_subscript (chrec_a, chrec_b,
03459 overlap_iterations_a, overlap_iterations_b,
03460 last_conflicts);
03461
03462 else if (siv_subscript_p (chrec_a, chrec_b))
03463 analyze_siv_subscript (chrec_a, chrec_b,
03464 overlap_iterations_a, overlap_iterations_b,
03465 last_conflicts);
03466
03467 else
03468 analyze_miv_subscript (chrec_a, chrec_b,
03469 overlap_iterations_a, overlap_iterations_b,
03470 last_conflicts);
03471
03472 if (dump_file && (dump_flags & TDF_DETAILS))
03473 {
03474 fprintf (dump_file, " (overlap_iterations_a = ");
03475 print_generic_expr (dump_file, *overlap_iterations_a, 0);
03476 fprintf (dump_file, ")\n (overlap_iterations_b = ");
03477 print_generic_expr (dump_file, *overlap_iterations_b, 0);
03478 fprintf (dump_file, ")\n");
03479 fprintf (dump_file, ")\n");
03480 }
03481 }
03482
03483
03484
03485 static void
03486 save_dist_v (struct data_dependence_relation *ddr, lambda_vector dist_v)
03487 {
03488 unsigned i;
03489 lambda_vector v;
03490
03491 for (i = 0; VEC_iterate (lambda_vector, DDR_DIST_VECTS (ddr), i, v); i++)
03492 if (lambda_vector_equal (v, dist_v, DDR_NB_LOOPS (ddr)))
03493 return;
03494
03495 VEC_safe_push (lambda_vector, heap, DDR_DIST_VECTS (ddr), dist_v);
03496 }
03497
03498
03499
03500 static void
03501 save_dir_v (struct data_dependence_relation *ddr, lambda_vector dir_v)
03502 {
03503 unsigned i;
03504 lambda_vector v;
03505
03506 for (i = 0; VEC_iterate (lambda_vector, DDR_DIR_VECTS (ddr), i, v); i++)
03507 if (lambda_vector_equal (v, dir_v, DDR_NB_LOOPS (ddr)))
03508 return;
03509
03510 VEC_safe_push (lambda_vector, heap, DDR_DIR_VECTS (ddr), dir_v);
03511 }
03512
03513
03514
03515
03516
03517
03518
03519
03520
03521
03522
03523
03524
03525
03526
03527 static void
03528 add_outer_distances (struct data_dependence_relation *ddr,
03529 lambda_vector dist_v, int index)
03530 {
03531
03532
03533 while (--index >= 0)
03534 {
03535 lambda_vector save_v = lambda_vector_new (DDR_NB_LOOPS (ddr));
03536 lambda_vector_copy (dist_v, save_v, DDR_NB_LOOPS (ddr));
03537 save_v[index] = 1;
03538 save_dist_v (ddr, save_v);
03539 }
03540 }
03541
03542
03543
03544
03545
03546
03547 static bool
03548 build_classic_dist_vector_1 (struct data_dependence_relation *ddr,
03549 struct data_reference *ddr_a,
03550 struct data_reference *ddr_b,
03551 lambda_vector dist_v, bool *init_b,
03552 int *index_carry)
03553 {
03554 unsigned i;
03555 lambda_vector init_v = lambda_vector_new (DDR_NB_LOOPS (ddr));
03556
03557 for (i = 0; i < DDR_NUM_SUBSCRIPTS (ddr); i++)
03558 {
03559 tree access_fn_a, access_fn_b;
03560 struct subscript *subscript = DDR_SUBSCRIPT (ddr, i);
03561
03562 if (chrec_contains_undetermined (SUB_DISTANCE (subscript)))
03563 {
03564 non_affine_dependence_relation (ddr);
03565 return false;
03566 }
03567
03568 access_fn_a = DR_ACCESS_FN (ddr_a, i);
03569 access_fn_b = DR_ACCESS_FN (ddr_b, i);
03570
03571 if (TREE_CODE (access_fn_a) == POLYNOMIAL_CHREC
03572 && TREE_CODE (access_fn_b) == POLYNOMIAL_CHREC)
03573 {
03574 int dist, index;
03575 int index_a = index_in_loop_nest (CHREC_VARIABLE (access_fn_a),
03576 DDR_LOOP_NEST (ddr));
03577 int index_b = index_in_loop_nest (CHREC_VARIABLE (access_fn_b),
03578 DDR_LOOP_NEST (ddr));
03579
03580
03581
03582
03583
03584
03585
03586
03587
03588 index = index_a < index_b ? index_a : index_b;
03589 *index_carry = MIN (index, *index_carry);
03590
03591 if (chrec_contains_undetermined (SUB_DISTANCE (subscript)))
03592 {
03593 non_affine_dependence_relation (ddr);
03594 return false;
03595 }
03596
03597 dist = int_cst_value (SUB_DISTANCE (subscript));
03598
03599
03600
03601
03602
03603
03604
03605
03606
03607
03608
03609 if (init_v[index] != 0 && dist_v[index] != dist)
03610 {
03611 finalize_ddr_dependent (ddr, chrec_known);
03612 return false;
03613 }
03614
03615 dist_v[index] = dist;
03616 init_v[index] = 1;
03617 *init_b = true;
03618 }
03619 else
03620 {
03621
03622
03623
03624 non_affine_dependence_relation (ddr);
03625 return false;
03626 }
03627 }
03628
03629 return true;
03630 }
03631
03632
03633
03634
03635 static bool
03636 same_access_functions (struct data_dependence_relation *ddr)
03637 {
03638 unsigned i;
03639
03640 for (i = 0; i < DDR_NUM_SUBSCRIPTS (ddr); i++)
03641 if (!eq_evolutions_p (DR_ACCESS_FN (DDR_A (ddr), i),
03642 DR_ACCESS_FN (DDR_B (ddr), i)))
03643 return false;
03644
03645 return true;
03646 }
03647
03648
03649
03650
03651 static void
03652 add_multivariate_self_dist (struct data_dependence_relation *ddr, tree c_2)
03653 {
03654 int x_1, x_2;
03655 tree c_1 = CHREC_LEFT (c_2);
03656 tree c_0 = CHREC_LEFT (c_1);
03657 lambda_vector dist_v;
03658
03659
03660 if (TREE_CODE (c_0) != INTEGER_CST)
03661 {
03662 DDR_ARE_DEPENDENT (ddr) = chrec_dont_know;
03663 return;
03664 }
03665
03666 x_2 = index_in_loop_nest (CHREC_VARIABLE (c_2), DDR_LOOP_NEST (ddr));
03667 x_1 = index_in_loop_nest (CHREC_VARIABLE (c_1), DDR_LOOP_NEST (ddr));
03668
03669
03670 dist_v = lambda_vector_new (DDR_NB_LOOPS (ddr));
03671 dist_v[x_1] = int_cst_value (CHREC_RIGHT (c_2));
03672 dist_v[x_2] = -int_cst_value (CHREC_RIGHT (c_1));
03673 save_dist_v (ddr, dist_v);
03674
03675 add_outer_distances (ddr, dist_v, x_1);
03676 }
03677
03678
03679
03680
03681 static void
03682 add_other_self_distances (struct data_dependence_relation *ddr)
03683 {
03684 lambda_vector dist_v;
03685 unsigned i;
03686 int index_carry = DDR_NB_LOOPS (ddr);
03687
03688 for (i = 0; i < DDR_NUM_SUBSCRIPTS (ddr); i++)
03689 {
03690 tree access_fun = DR_ACCESS_FN (DDR_A (ddr), i);
03691
03692 if (TREE_CODE (access_fun) == POLYNOMIAL_CHREC)
03693 {
03694 if (!evolution_function_is_univariate_p (access_fun))
03695 {
03696 if (DDR_NUM_SUBSCRIPTS (ddr) != 1)
03697 {
03698 DDR_ARE_DEPENDENT (ddr) = chrec_dont_know;
03699 return;
03700 }
03701
03702 add_multivariate_self_dist (ddr, DR_ACCESS_FN (DDR_A (ddr), 0));
03703 return;
03704 }
03705
03706 index_carry = MIN (index_carry,
03707 index_in_loop_nest (CHREC_VARIABLE (access_fun),
03708 DDR_LOOP_NEST (ddr)));
03709 }
03710 }
03711
03712 dist_v = lambda_vector_new (DDR_NB_LOOPS (ddr));
03713 add_outer_distances (ddr, dist_v, index_carry);
03714 }
03715
03716
03717
03718
03719
03720 static bool
03721 build_classic_dist_vector (struct data_dependence_relation *ddr)
03722 {
03723 bool init_b = false;
03724 int index_carry = DDR_NB_LOOPS (ddr);
03725 lambda_vector dist_v;
03726
03727 if (DDR_ARE_DEPENDENT (ddr) != NULL_TREE)
03728 return true;
03729
03730 if (same_access_functions (ddr))
03731 {
03732
03733 dist_v = lambda_vector_new (DDR_NB_LOOPS (ddr));
03734 save_dist_v (ddr, dist_v);
03735
03736 if (DDR_NB_LOOPS (ddr) > 1)
03737 add_other_self_distances (ddr);
03738
03739 return true;
03740 }
03741
03742 dist_v = lambda_vector_new (DDR_NB_LOOPS (ddr));
03743 if (!build_classic_dist_vector_1 (ddr, DDR_A (ddr), DDR_B (ddr),
03744 dist_v, &init_b, &index_carry))
03745 return false;
03746
03747
03748 if (init_b)
03749 {
03750
03751
03752
03753
03754
03755
03756
03757
03758
03759
03760
03761
03762
03763
03764
03765
03766
03767
03768
03769
03770
03771
03772
03773
03774 if (!lambda_vector_lexico_pos (dist_v, DDR_NB_LOOPS (ddr)))
03775 {
03776 lambda_vector save_v = lambda_vector_new (DDR_NB_LOOPS (ddr));
03777 subscript_dependence_tester_1 (ddr, DDR_B (ddr), DDR_A (ddr));
03778 compute_subscript_distance (ddr);
03779 build_classic_dist_vector_1 (ddr, DDR_B (ddr), DDR_A (ddr),
03780 save_v, &init_b, &index_carry);
03781 save_dist_v (ddr, save_v);
03782
03783
03784
03785
03786
03787
03788
03789
03790
03791
03792
03793
03794
03795
03796
03797
03798
03799 if (DDR_NB_LOOPS (ddr) > 1)
03800 {
03801 add_outer_distances (ddr, save_v, index_carry);
03802 add_outer_distances (ddr, dist_v, index_carry);
03803 }
03804 }
03805 else
03806 {
03807 lambda_vector save_v = lambda_vector_new (DDR_NB_LOOPS (ddr));
03808 lambda_vector_copy (dist_v, save_v, DDR_NB_LOOPS (ddr));
03809 save_dist_v (ddr, save_v);
03810
03811 if (DDR_NB_LOOPS (ddr) > 1)
03812 {
03813 lambda_vector opposite_v = lambda_vector_new (DDR_NB_LOOPS (ddr));
03814
03815 subscript_dependence_tester_1 (ddr, DDR_B (ddr), DDR_A (ddr));
03816 compute_subscript_distance (ddr);
03817 build_classic_dist_vector_1 (ddr, DDR_B (ddr), DDR_A (ddr),
03818 opposite_v, &init_b, &index_carry);
03819
03820 add_outer_distances (ddr, dist_v, index_carry);
03821 add_outer_distances (ddr, opposite_v, index_carry);
03822 }
03823 }
03824 }
03825 else
03826 {
03827
03828
03829
03830
03831
03832
03833
03834 add_outer_distances (ddr, dist_v,
03835 lambda_vector_first_nz (dist_v,
03836 DDR_NB_LOOPS (ddr), 0));
03837 }
03838
03839 if (dump_file && (dump_flags & TDF_DETAILS))
03840 {
03841 unsigned i;
03842
03843 fprintf (dump_file, "(build_classic_dist_vector\n");
03844 for (i = 0; i < DDR_NUM_DIST_VECTS (ddr); i++)
03845 {
03846 fprintf (dump_file, " dist_vector = (");
03847 print_lambda_vector (dump_file, DDR_DIST_VECT (ddr, i),
03848 DDR_NB_LOOPS (ddr));
03849 fprintf (dump_file, " )\n");
03850 }
03851 fprintf (dump_file, ")\n");
03852 }
03853
03854 return true;
03855 }
03856
03857
03858
03859
03860
03861 static inline enum data_dependence_direction
03862 dir_from_dist (int dist)
03863 {
03864 if (dist > 0)
03865 return dir_positive;
03866 else if (dist < 0)
03867 return dir_negative;
03868 else
03869 return dir_equal;
03870 }
03871
03872
03873
03874
03875 static void
03876 build_classic_dir_vector (struct data_dependence_relation *ddr)
03877 {
03878 unsigned i, j;
03879 lambda_vector dist_v;
03880
03881 for (i = 0; VEC_iterate (lambda_vector, DDR_DIST_VECTS (ddr), i, dist_v); i++)
03882 {
03883 lambda_vector dir_v = lambda_vector_new (DDR_NB_LOOPS (ddr));
03884
03885 for (j = 0; j < DDR_NB_LOOPS (ddr); j++)
03886 dir_v[j] = dir_from_dist (dist_v[j]);
03887
03888 save_dir_v (ddr, dir_v);
03889 }
03890 }
03891
03892
03893
03894
03895 static bool
03896 subscript_dependence_tester_1 (struct data_dependence_relation *ddr,
03897 struct data_reference *dra,
03898 struct data_reference *drb)
03899 {
03900 unsigned int i;
03901 tree last_conflicts;
03902 struct subscript *subscript;
03903
03904 for (i = 0; VEC_iterate (subscript_p, DDR_SUBSCRIPTS (ddr), i, subscript);
03905 i++)
03906 {
03907 tree overlaps_a, overlaps_b;
03908
03909 analyze_overlapping_iterations (DR_ACCESS_FN (dra, i),
03910 DR_ACCESS_FN (drb, i),
03911 &overlaps_a, &overlaps_b,
03912 &last_conflicts);
03913
03914 if (chrec_contains_undetermined (overlaps_a)
03915 || chrec_contains_undetermined (overlaps_b))
03916 {
03917 finalize_ddr_dependent (ddr, chrec_dont_know);
03918 dependence_stats.num_dependence_undetermined++;
03919 return false;
03920 }
03921
03922 else if (overlaps_a == chrec_known
03923 || overlaps_b == chrec_known)
03924 {
03925 finalize_ddr_dependent (ddr, chrec_known);
03926 dependence_stats.num_dependence_independent++;
03927 return false;
03928 }
03929
03930 else
03931 {
03932 SUB_CONFLICTS_IN_A (subscript) = overlaps_a;
03933 SUB_CONFLICTS_IN_B (subscript) = overlaps_b;
03934 SUB_LAST_CONFLICT (subscript) = last_conflicts;
03935 }
03936 }
03937
03938 return true;
03939 }
03940
03941
03942
03943 static void
03944 subscript_dependence_tester (struct data_dependence_relation *ddr)
03945 {
03946
03947 if (dump_file && (dump_flags & TDF_DETAILS))
03948 fprintf (dump_file, "(subscript_dependence_tester \n");
03949
03950 if (subscript_dependence_tester_1 (ddr, DDR_A (ddr), DDR_B (ddr)))
03951 dependence_stats.num_dependence_dependent++;
03952
03953 compute_subscript_distance (ddr);
03954 if (build_classic_dist_vector (ddr))
03955 build_classic_dir_vector (ddr);
03956
03957 if (dump_file && (dump_flags & TDF_DETAILS))
03958 fprintf (dump_file, ")\n");
03959 }
03960
03961
03962
03963
03964 static bool
03965 access_functions_are_affine_or_constant_p (struct data_reference *a)
03966 {
03967 unsigned int i;
03968 VEC(tree,heap) **fns = DR_ACCESS_FNS_ADDR (a);
03969 tree t;
03970
03971 for (i = 0; VEC_iterate (tree, *fns, i, t); i++)
03972 if (!evolution_function_is_constant_p (t)
03973 && !evolution_function_is_affine_multivariate_p (t))
03974 return false;
03975
03976 return true;
03977 }
03978
03979
03980
03981
03982
03983
03984
03985
03986
03987
03988 static void
03989 compute_affine_dependence (struct data_dependence_relation *ddr)
03990 {
03991 struct data_reference *dra = DDR_A (ddr);
03992 struct data_reference *drb = DDR_B (ddr);
03993
03994 if (dump_file && (dump_flags & TDF_DETAILS))
03995 {
03996 fprintf (dump_file, "(compute_affine_dependence\n");
03997 fprintf (dump_file, " (stmt_a = \n");
03998 print_generic_expr (dump_file, DR_STMT (dra), 0);
03999 fprintf (dump_file, ")\n (stmt_b = \n");
04000 print_generic_expr (dump_file, DR_STMT (drb), 0);
04001 fprintf (dump_file, ")\n");
04002 }
04003
04004
04005 if (DDR_ARE_DEPENDENT (ddr) == NULL_TREE)
04006 {
04007 dependence_stats.num_dependence_tests++;
04008
04009 if (access_functions_are_affine_or_constant_p (dra)
04010 && access_functions_are_affine_or_constant_p (drb))
04011 subscript_dependence_tester (ddr);
04012
04013
04014
04015
04016 else
04017 {
04018 dependence_stats.num_dependence_undetermined++;
04019
04020 if (dump_file && (dump_flags & TDF_DETAILS))
04021 {
04022 fprintf (dump_file, "Data ref a:\n");
04023 dump_data_reference (dump_file, dra);
04024 fprintf (dump_file, "Data ref b:\n");
04025 dump_data_reference (dump_file, drb);
04026 fprintf (dump_file, "affine dependence test not usable: access function not affine or constant.\n");
04027 }
04028 finalize_ddr_dependent (ddr, chrec_dont_know);
04029 }
04030 }
04031
04032 if (dump_file && (dump_flags & TDF_DETAILS))
04033 fprintf (dump_file, ")\n");
04034 }
04035
04036
04037
04038
04039 static void
04040 compute_self_dependence (struct data_dependence_relation *ddr)
04041 {
04042 unsigned int i;
04043 struct subscript *subscript;
04044
04045 for (i = 0; VEC_iterate (subscript_p, DDR_SUBSCRIPTS (ddr), i, subscript);
04046 i++)
04047 {
04048
04049 SUB_CONFLICTS_IN_A (subscript) = integer_zero_node;
04050 SUB_CONFLICTS_IN_B (subscript) = integer_zero_node;
04051 SUB_LAST_CONFLICT (subscript) = chrec_dont_know;
04052 }
04053
04054
04055 save_dist_v (ddr, lambda_vector_new (DDR_NB_LOOPS (ddr)));
04056 save_dir_v (ddr, lambda_vector_new (DDR_NB_LOOPS (ddr)));
04057 }
04058
04059
04060
04061
04062
04063
04064 static void
04065 compute_all_dependences (VEC (data_reference_p, heap) *datarefs,
04066 VEC (ddr_p, heap) **dependence_relations,
04067 VEC (loop_p, heap) *loop_nest,
04068 bool compute_self_and_rr)
04069 {
04070 struct data_dependence_relation *ddr;
04071 struct data_reference *a, *b;
04072 unsigned int i, j;
04073
04074 for (i = 0; VEC_iterate (data_reference_p, datarefs, i, a); i++)
04075 for (j = i + 1; VEC_iterate (data_reference_p, datarefs, j, b); j++)
04076 if (!DR_IS_READ (a) || !DR_IS_READ (b) || compute_self_and_rr)
04077 {
04078 ddr = initialize_data_dependence_relation (a, b, loop_nest);
04079 VEC_safe_push (ddr_p, heap, *dependence_relations, ddr);
04080 compute_affine_dependence (ddr);
04081 }
04082
04083 if (compute_self_and_rr)
04084 for (i = 0; VEC_iterate (data_reference_p, datarefs, i, a); i++)
04085 {
04086 ddr = initialize_data_dependence_relation (a, a, loop_nest);
04087 VEC_safe_push (ddr_p, heap, *dependence_relations, ddr);
04088 compute_self_dependence (ddr);
04089 }
04090 }
04091
04092
04093
04094
04095
04096
04097
04098
04099 tree
04100 find_data_references_in_loop (struct loop *loop,
04101 VEC (data_reference_p, heap) **datarefs)
04102 {
04103 basic_block bb, *bbs;
04104 unsigned int i;
04105 block_stmt_iterator bsi;
04106 struct data_reference *dr;
04107
04108 bbs = get_loop_body (loop);
04109
04110 for (i = 0; i < loop->num_nodes; i++)
04111 {
04112 bb = bbs[i];
04113
04114 for (bsi = bsi_start (bb); !bsi_end_p (bsi); bsi_next (&bsi))
04115 {
04116 tree stmt = bsi_stmt (bsi);
04117
04118
04119
04120
04121 if ((TREE_CODE (stmt) == CALL_EXPR
04122 && !(call_expr_flags (stmt) & (ECF_CONST | ECF_PURE)))
04123 || (TREE_CODE (stmt) == ASM_EXPR
04124 && ASM_VOLATILE_P (stmt)))
04125 goto insert_dont_know_node;
04126
04127 if (ZERO_SSA_OPERANDS (stmt, SSA_OP_ALL_VIRTUALS))
04128 continue;
04129
04130 switch (TREE_CODE (stmt))
04131 {
04132 case MODIFY_EXPR:
04133 {
04134 bool one_inserted = false;
04135 tree opnd0 = TREE_OPERAND (stmt, 0);
04136 tree opnd1 = TREE_OPERAND (stmt, 1);
04137
04138 if (TREE_CODE (opnd0) == ARRAY_REF
04139 || TREE_CODE (opnd0) == INDIRECT_REF
04140 || TREE_CODE (opnd0) == COMPONENT_REF)
04141 {
04142 dr = create_data_ref (opnd0, stmt, false);
04143 if (dr)
04144 {
04145 VEC_safe_push (data_reference_p, heap, *datarefs, dr);
04146 one_inserted = true;
04147 }
04148 }
04149
04150 if (TREE_CODE (opnd1) == ARRAY_REF
04151 || TREE_CODE (opnd1) == INDIRECT_REF
04152 || TREE_CODE (opnd1) == COMPONENT_REF)
04153 {
04154 dr = create_data_ref (opnd1, stmt, true);
04155 if (dr)
04156 {
04157 VEC_safe_push (data_reference_p, heap, *datarefs, dr);
04158 one_inserted = true;
04159 }
04160 }
04161
04162 if (!one_inserted)
04163 goto insert_dont_know_node;
04164
04165 break;
04166 }
04167
04168 case CALL_EXPR:
04169 {
04170 tree args;
04171 bool one_inserted = false;
04172
04173 for (args = TREE_OPERAND (stmt, 1); args;
04174 args = TREE_CHAIN (args))
04175 if (TREE_CODE (TREE_VALUE (args)) == ARRAY_REF
04176 || TREE_CODE (TREE_VALUE (args)) == INDIRECT_REF
04177 || TREE_CODE (TREE_VALUE (args)) == COMPONENT_REF)
04178 {
04179 dr = create_data_ref (TREE_VALUE (args), stmt, true);
04180 if (dr)
04181 {
04182 VEC_safe_push (data_reference_p, heap, *datarefs, dr);
04183 one_inserted = true;
04184 }
04185 }
04186
04187 if (!one_inserted)
04188 goto insert_dont_know_node;
04189
04190 break;
04191 }
04192
04193 default:
04194 {
04195 struct data_reference *res;
04196
04197 insert_dont_know_node:;
04198 res = XNEW (struct data_reference);
04199 DR_STMT (res) = NULL_TREE;
04200 DR_REF (res) = NULL_TREE;
04201 DR_BASE_OBJECT (res) = NULL;
04202 DR_TYPE (res) = ARRAY_REF_TYPE;
04203 DR_SET_ACCESS_FNS (res, NULL);
04204 DR_BASE_OBJECT (res) = NULL;
04205 DR_IS_READ (res) = false;
04206 DR_BASE_ADDRESS (res) = NULL_TREE;
04207 DR_OFFSET (res) = NULL_TREE;
04208 DR_INIT (res) = NULL_TREE;
04209 DR_STEP (res) = NULL_TREE;
04210 DR_OFFSET_MISALIGNMENT (res) = NULL_TREE;
04211 DR_MEMTAG (res) = NULL_TREE;
04212 DR_PTR_INFO (res) = NULL;
04213 VEC_safe_push (data_reference_p, heap, *datarefs, res);
04214
04215 free (bbs);
04216 return chrec_dont_know;
04217 }
04218 }
04219
04220
04221 if (!ZERO_SSA_OPERANDS (stmt, SSA_OP_VIRTUAL_DEFS))
04222 loop->parallel_p = false;
04223 }
04224 }
04225
04226 free (bbs);
04227
04228 return NULL_TREE;
04229 }
04230
04231
04232
04233 static bool
04234 find_loop_nest_1 (struct loop *loop, VEC (loop_p, heap) **loop_nest)
04235 {
04236
04237
04238
04239
04240
04241
04242
04243
04244
04245
04246
04247
04248
04249
04250 if (loop->next)
04251 return false;
04252
04253 VEC_safe_push (loop_p, heap, *loop_nest, loop);
04254 if (loop->inner)
04255 return find_loop_nest_1 (loop->inner, loop_nest);
04256 return true;
04257 }
04258
04259
04260
04261
04262
04263
04264 static bool
04265 find_loop_nest (struct loop *loop, VEC (loop_p, heap) **loop_nest)
04266 {
04267 VEC_safe_push (loop_p, heap, *loop_nest, loop);
04268 if (loop->inner)
04269 return find_loop_nest_1 (loop->inner, loop_nest);
04270 return true;
04271 }
04272
04273
04274
04275
04276
04277
04278
04279 void
04280 compute_data_dependences_for_loop (struct loop *loop,
04281 bool compute_self_and_read_read_dependences,
04282 VEC (data_reference_p, heap) **datarefs,
04283 VEC (ddr_p, heap) **dependence_relations)
04284 {
04285 struct loop *loop_nest = loop;
04286 VEC (loop_p, heap) *vloops = VEC_alloc (loop_p, heap, 3);
04287
04288 memset (&dependence_stats, 0, sizeof (dependence_stats));
04289
04290
04291
04292
04293 if (!loop_nest
04294 || !find_loop_nest (loop_nest, &vloops)
04295 || find_data_references_in_loop (loop, datarefs) == chrec_dont_know)
04296 {
04297 struct data_dependence_relation *ddr;
04298
04299
04300
04301 ddr = initialize_data_dependence_relation (NULL, NULL, vloops);
04302 VEC_safe_push (ddr_p, heap, *dependence_relations, ddr);
04303 }
04304 else
04305 compute_all_dependences (*datarefs, dependence_relations, vloops,
04306 compute_self_and_read_read_dependences);
04307
04308 if (dump_file && (dump_flags & TDF_STATS))
04309 {
04310 fprintf (dump_file, "Dependence tester statistics:\n");
04311
04312 fprintf (dump_file, "Number of dependence tests: %d\n",
04313 dependence_stats.num_dependence_tests);
04314 fprintf (dump_file, "Number of dependence tests classified dependent: %d\n",
04315 dependence_stats.num_dependence_dependent);
04316 fprintf (dump_file, "Number of dependence tests classified independent: %d\n",
04317 dependence_stats.num_dependence_independent);
04318 fprintf (dump_file, "Number of undetermined dependence tests: %d\n",
04319 dependence_stats.num_dependence_undetermined);
04320
04321 fprintf (dump_file, "Number of subscript tests: %d\n",
04322 dependence_stats.num_subscript_tests);
04323 fprintf (dump_file, "Number of undetermined subscript tests: %d\n",
04324 dependence_stats.num_subscript_undetermined);
04325 fprintf (dump_file, "Number of same subscript function: %d\n",
04326 dependence_stats.num_same_subscript_function);
04327
04328 fprintf (dump_file, "Number of ziv tests: %d\n",
04329 dependence_stats.num_ziv);
04330 fprintf (dump_file, "Number of ziv tests returning dependent: %d\n",
04331 dependence_stats.num_ziv_dependent);
04332 fprintf (dump_file, "Number of ziv tests returning independent: %d\n",
04333 dependence_stats.num_ziv_independent);
04334 fprintf (dump_file, "Number of ziv tests unimplemented: %d\n",
04335 dependence_stats.num_ziv_unimplemented);
04336
04337 fprintf (dump_file, "Number of siv tests: %d\n",
04338 dependence_stats.num_siv);
04339 fprintf (dump_file, "Number of siv tests returning dependent: %d\n",
04340 dependence_stats.num_siv_dependent);
04341 fprintf (dump_file, "Number of siv tests returning independent: %d\n",
04342 dependence_stats.num_siv_independent);
04343 fprintf (dump_file, "Number of siv tests unimplemented: %d\n",
04344 dependence_stats.num_siv_unimplemented);
04345
04346 fprintf (dump_file, "Number of miv tests: %d\n",
04347 dependence_stats.num_miv);
04348 fprintf (dump_file, "Number of miv tests returning dependent: %d\n",
04349 dependence_stats.num_miv_dependent);
04350 fprintf (dump_file, "Number of miv tests returning independent: %d\n",
04351 dependence_stats.num_miv_independent);
04352 fprintf (dump_file, "Number of miv tests unimplemented: %d\n",
04353 dependence_stats.num_miv_unimplemented);
04354 }
04355 }
04356
04357
04358
04359
04360
04361
04362
04363
04364
04365
04366
04367
04368
04369
04370
04371
04372
04373
04374
04375
04376
04377
04378 #if 0
04379 static void
04380 analyze_all_data_dependences (struct loops *loops)
04381 {
04382 unsigned int i;
04383 int nb_data_refs = 10;
04384 VEC (data_reference_p, heap) *datarefs =
04385 VEC_alloc (data_reference_p, heap, nb_data_refs);
04386 VEC (ddr_p, heap) *dependence_relations =
04387 VEC_alloc (ddr_p, heap, nb_data_refs * nb_data_refs);
04388
04389
04390 compute_data_dependences_for_loop (loops->parray[0], false,
04391 &datarefs, &dependence_relations);
04392
04393 if (dump_file)
04394 {
04395 dump_data_dependence_relations (dump_file, dependence_relations);
04396 fprintf (dump_file, "\n\n");
04397
04398 if (dump_flags & TDF_DETAILS)
04399 dump_dist_dir_vectors (dump_file, dependence_relations);
04400
04401 if (dump_flags & TDF_STATS)
04402 {
04403 unsigned nb_top_relations = 0;
04404 unsigned nb_bot_relations = 0;
04405 unsigned nb_basename_differ = 0;
04406 unsigned nb_chrec_relations = 0;
04407 struct data_dependence_relation *ddr;
04408
04409 for (i = 0; VEC_iterate (ddr_p, dependence_relations, i, ddr); i++)
04410 {
04411 if (chrec_contains_undetermined (DDR_ARE_DEPENDENT (ddr)))
04412 nb_top_relations++;
04413
04414 else if (DDR_ARE_DEPENDENT (ddr) == chrec_known)
04415 {
04416 struct data_reference *a = DDR_A (ddr);
04417 struct data_reference *b = DDR_B (ddr);
04418 bool differ_p;
04419
04420 if ((DR_BASE_OBJECT (a) && DR_BASE_OBJECT (b)
04421 && DR_NUM_DIMENSIONS (a) != DR_NUM_DIMENSIONS (b))
04422 || (base_object_differ_p (a, b, &differ_p)
04423 && differ_p))
04424 nb_basename_differ++;
04425 else
04426 nb_bot_relations++;
04427 }
04428
04429 else
04430 nb_chrec_relations++;
04431 }
04432
04433 gather_stats_on_scev_database ();
04434 }
04435 }
04436
04437 free_dependence_relations (dependence_relations);
04438 free_data_refs (datarefs);
04439 }
04440 #endif
04441
04442
04443
04444 void
04445 free_dependence_relation (struct data_dependence_relation *ddr)
04446 {
04447 if (ddr == NULL)
04448 return;
04449
04450 if (DDR_ARE_DEPENDENT (ddr) == NULL_TREE && DDR_SUBSCRIPTS (ddr))
04451 VEC_free (subscript_p, heap, DDR_SUBSCRIPTS (ddr));
04452
04453 free (ddr);
04454 }
04455
04456
04457
04458
04459 void
04460 free_dependence_relations (VEC (ddr_p, heap) *dependence_relations)
04461 {
04462 unsigned int i;
04463 struct data_dependence_relation *ddr;
04464 VEC (loop_p, heap) *loop_nest = NULL;
04465
04466 for (i = 0; VEC_iterate (ddr_p, dependence_relations, i, ddr); i++)
04467 {
04468 if (ddr == NULL)
04469 continue;
04470 if (loop_nest == NULL)
04471 loop_nest = DDR_LOOP_NEST (ddr);
04472 else
04473 gcc_assert (DDR_LOOP_NEST (ddr) == NULL
04474 || DDR_LOOP_NEST (ddr) == loop_nest);
04475 free_dependence_relation (ddr);
04476 }
04477
04478 if (loop_nest)
04479 VEC_free (loop_p, heap, loop_nest);
04480 VEC_free (ddr_p, heap, dependence_relations);
04481 }
04482
04483
04484
04485 void
04486 free_data_refs (VEC (data_reference_p, heap) *datarefs)
04487 {
04488 unsigned int i;
04489 struct data_reference *dr;
04490
04491 for (i = 0; VEC_iterate (data_reference_p, datarefs, i, dr); i++)
04492 free_data_ref (dr);
04493 VEC_free (data_reference_p, heap, datarefs);
04494 }
04495