00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include "config.h"
00023 #include "system.h"
00024 #include "coretypes.h"
00025 #include "tm.h"
00026 #include "ggc.h"
00027 #include "tree.h"
00028 #include "basic-block.h"
00029 #include "diagnostic.h"
00030 #include "tree-flow.h"
00031 #include "tree-dump.h"
00032 #include "timevar.h"
00033 #include "cfgloop.h"
00034 #include "expr.h"
00035 #include "optabs.h"
00036 #include "params.h"
00037 #include "tree-chrec.h"
00038 #include "tree-data-ref.h"
00039 #include "tree-scalar-evolution.h"
00040 #include "tree-vectorizer.h"
00041
00042
00043 static loop_vec_info vect_analyze_loop_form (struct loop *);
00044 static bool vect_analyze_data_refs (loop_vec_info);
00045 static bool vect_mark_stmts_to_be_vectorized (loop_vec_info);
00046 static void vect_analyze_scalar_cycles (loop_vec_info);
00047 static bool vect_analyze_data_ref_accesses (loop_vec_info);
00048 static bool vect_analyze_data_ref_dependences (loop_vec_info);
00049 static bool vect_analyze_data_refs_alignment (loop_vec_info);
00050 static bool vect_compute_data_refs_alignment (loop_vec_info);
00051 static bool vect_enhance_data_refs_alignment (loop_vec_info);
00052 static bool vect_analyze_operations (loop_vec_info);
00053 static bool vect_determine_vectorization_factor (loop_vec_info);
00054
00055
00056 static bool exist_non_indexing_operands_for_use_p (tree, tree);
00057 static void vect_mark_relevant (VEC(tree,heap) **, tree, bool, bool);
00058 static bool vect_stmt_relevant_p (tree, loop_vec_info, bool *, bool *);
00059 static tree vect_get_loop_niters (struct loop *, tree *);
00060 static bool vect_analyze_data_ref_dependence
00061 (struct data_dependence_relation *, loop_vec_info);
00062 static bool vect_compute_data_ref_alignment (struct data_reference *);
00063 static bool vect_analyze_data_ref_access (struct data_reference *);
00064 static bool vect_can_advance_ivs_p (loop_vec_info);
00065 static void vect_update_misalignment_for_peel
00066 (struct data_reference *, struct data_reference *, int npeel);
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094 static bool
00095 vect_determine_vectorization_factor (loop_vec_info loop_vinfo)
00096 {
00097 struct loop *loop = LOOP_VINFO_LOOP (loop_vinfo);
00098 basic_block *bbs = LOOP_VINFO_BBS (loop_vinfo);
00099 int nbbs = loop->num_nodes;
00100 block_stmt_iterator si;
00101 unsigned int vectorization_factor = 0;
00102 int i;
00103 tree scalar_type;
00104
00105 if (vect_print_dump_info (REPORT_DETAILS))
00106 fprintf (vect_dump, "=== vect_determine_vectorization_factor ===");
00107
00108 for (i = 0; i < nbbs; i++)
00109 {
00110 basic_block bb = bbs[i];
00111
00112 for (si = bsi_start (bb); !bsi_end_p (si); bsi_next (&si))
00113 {
00114 tree stmt = bsi_stmt (si);
00115 unsigned int nunits;
00116 stmt_vec_info stmt_info = vinfo_for_stmt (stmt);
00117 tree vectype;
00118
00119 if (vect_print_dump_info (REPORT_DETAILS))
00120 {
00121 fprintf (vect_dump, "==> examining statement: ");
00122 print_generic_expr (vect_dump, stmt, TDF_SLIM);
00123 }
00124
00125 gcc_assert (stmt_info);
00126
00127 if (!STMT_VINFO_RELEVANT_P (stmt_info)
00128 && !STMT_VINFO_LIVE_P (stmt_info))
00129 {
00130 if (vect_print_dump_info (REPORT_DETAILS))
00131 fprintf (vect_dump, "skip.");
00132 continue;
00133 }
00134
00135 if (VECTOR_MODE_P (TYPE_MODE (TREE_TYPE (stmt))))
00136 {
00137 if (vect_print_dump_info (REPORT_UNVECTORIZED_LOOPS))
00138 {
00139 fprintf (vect_dump, "not vectorized: vector stmt in loop:");
00140 print_generic_expr (vect_dump, stmt, TDF_SLIM);
00141 }
00142 return false;
00143 }
00144
00145 if (STMT_VINFO_VECTYPE (stmt_info))
00146 {
00147 vectype = STMT_VINFO_VECTYPE (stmt_info);
00148 scalar_type = TREE_TYPE (vectype);
00149 }
00150 else
00151 {
00152 if (STMT_VINFO_DATA_REF (stmt_info))
00153 scalar_type =
00154 TREE_TYPE (DR_REF (STMT_VINFO_DATA_REF (stmt_info)));
00155 else if (TREE_CODE (stmt) == MODIFY_EXPR)
00156 scalar_type = TREE_TYPE (TREE_OPERAND (stmt, 0));
00157 else
00158 scalar_type = TREE_TYPE (stmt);
00159
00160 if (vect_print_dump_info (REPORT_DETAILS))
00161 {
00162 fprintf (vect_dump, "get vectype for scalar type: ");
00163 print_generic_expr (vect_dump, scalar_type, TDF_SLIM);
00164 }
00165
00166 vectype = get_vectype_for_scalar_type (scalar_type);
00167 if (!vectype)
00168 {
00169 if (vect_print_dump_info (REPORT_UNVECTORIZED_LOOPS))
00170 {
00171 fprintf (vect_dump,
00172 "not vectorized: unsupported data-type ");
00173 print_generic_expr (vect_dump, scalar_type, TDF_SLIM);
00174 }
00175 return false;
00176 }
00177 STMT_VINFO_VECTYPE (stmt_info) = vectype;
00178 }
00179
00180 if (vect_print_dump_info (REPORT_DETAILS))
00181 {
00182 fprintf (vect_dump, "vectype: ");
00183 print_generic_expr (vect_dump, vectype, TDF_SLIM);
00184 }
00185
00186 nunits = TYPE_VECTOR_SUBPARTS (vectype);
00187 if (vect_print_dump_info (REPORT_DETAILS))
00188 fprintf (vect_dump, "nunits = %d", nunits);
00189
00190 if (vectorization_factor)
00191 {
00192
00193
00194 if (nunits != vectorization_factor)
00195 {
00196 if (vect_print_dump_info (REPORT_UNVECTORIZED_LOOPS))
00197 fprintf (vect_dump, "not vectorized: mixed data-types");
00198 return false;
00199 }
00200 }
00201 else
00202 vectorization_factor = nunits;
00203
00204 gcc_assert (GET_MODE_SIZE (TYPE_MODE (scalar_type))
00205 * vectorization_factor == UNITS_PER_SIMD_WORD);
00206 }
00207 }
00208
00209
00210
00211 if (vectorization_factor <= 1)
00212 {
00213 if (vect_print_dump_info (REPORT_UNVECTORIZED_LOOPS))
00214 fprintf (vect_dump, "not vectorized: unsupported data-type");
00215 return false;
00216 }
00217 LOOP_VINFO_VECT_FACTOR (loop_vinfo) = vectorization_factor;
00218
00219 return true;
00220 }
00221
00222
00223
00224
00225
00226
00227 static bool
00228 vect_analyze_operations (loop_vec_info loop_vinfo)
00229 {
00230 struct loop *loop = LOOP_VINFO_LOOP (loop_vinfo);
00231 basic_block *bbs = LOOP_VINFO_BBS (loop_vinfo);
00232 int nbbs = loop->num_nodes;
00233 block_stmt_iterator si;
00234 unsigned int vectorization_factor = 0;
00235 int i;
00236 bool ok;
00237 tree phi;
00238 stmt_vec_info stmt_info;
00239 bool need_to_vectorize = false;
00240
00241 if (vect_print_dump_info (REPORT_DETAILS))
00242 fprintf (vect_dump, "=== vect_analyze_operations ===");
00243
00244 gcc_assert (LOOP_VINFO_VECT_FACTOR (loop_vinfo));
00245 vectorization_factor = LOOP_VINFO_VECT_FACTOR (loop_vinfo);
00246
00247 for (i = 0; i < nbbs; i++)
00248 {
00249 basic_block bb = bbs[i];
00250
00251 for (phi = phi_nodes (bb); phi; phi = PHI_CHAIN (phi))
00252 {
00253 stmt_info = vinfo_for_stmt (phi);
00254 if (vect_print_dump_info (REPORT_DETAILS))
00255 {
00256 fprintf (vect_dump, "examining phi: ");
00257 print_generic_expr (vect_dump, phi, TDF_SLIM);
00258 }
00259
00260 gcc_assert (stmt_info);
00261
00262 if (STMT_VINFO_LIVE_P (stmt_info))
00263 {
00264
00265 if (vect_print_dump_info (REPORT_UNVECTORIZED_LOOPS))
00266 fprintf (vect_dump, "not vectorized: value used after loop.");
00267 return false;
00268 }
00269
00270 if (STMT_VINFO_RELEVANT_P (stmt_info))
00271 {
00272
00273
00274 if (vect_print_dump_info (REPORT_UNVECTORIZED_LOOPS))
00275 fprintf (vect_dump, "not vectorized: unsupported pattern.");
00276 return false;
00277 }
00278 }
00279
00280 for (si = bsi_start (bb); !bsi_end_p (si); bsi_next (&si))
00281 {
00282 tree stmt = bsi_stmt (si);
00283 stmt_vec_info stmt_info = vinfo_for_stmt (stmt);
00284
00285 if (vect_print_dump_info (REPORT_DETAILS))
00286 {
00287 fprintf (vect_dump, "==> examining statement: ");
00288 print_generic_expr (vect_dump, stmt, TDF_SLIM);
00289 }
00290
00291 gcc_assert (stmt_info);
00292
00293
00294
00295
00296
00297
00298
00299
00300 if (!STMT_VINFO_RELEVANT_P (stmt_info)
00301 && !STMT_VINFO_LIVE_P (stmt_info))
00302 {
00303 if (vect_print_dump_info (REPORT_DETAILS))
00304 fprintf (vect_dump, "irrelevant.");
00305 continue;
00306 }
00307
00308 if (STMT_VINFO_RELEVANT_P (stmt_info))
00309 {
00310 gcc_assert (!VECTOR_MODE_P (TYPE_MODE (TREE_TYPE (stmt))));
00311 gcc_assert (STMT_VINFO_VECTYPE (stmt_info));
00312
00313 ok = (vectorizable_operation (stmt, NULL, NULL)
00314 || vectorizable_assignment (stmt, NULL, NULL)
00315 || vectorizable_load (stmt, NULL, NULL)
00316 || vectorizable_store (stmt, NULL, NULL)
00317 || vectorizable_condition (stmt, NULL, NULL));
00318
00319 if (!ok)
00320 {
00321 if (vect_print_dump_info (REPORT_UNVECTORIZED_LOOPS))
00322 {
00323 fprintf (vect_dump,
00324 "not vectorized: relevant stmt not supported: ");
00325 print_generic_expr (vect_dump, stmt, TDF_SLIM);
00326 }
00327 return false;
00328 }
00329 need_to_vectorize = true;
00330 }
00331
00332 if (STMT_VINFO_LIVE_P (stmt_info))
00333 {
00334 ok = vectorizable_reduction (stmt, NULL, NULL);
00335
00336 if (ok)
00337 need_to_vectorize = true;
00338 else
00339 ok = vectorizable_live_operation (stmt, NULL, NULL);
00340
00341 if (!ok)
00342 {
00343 if (vect_print_dump_info (REPORT_UNVECTORIZED_LOOPS))
00344 {
00345 fprintf (vect_dump,
00346 "not vectorized: live stmt not supported: ");
00347 print_generic_expr (vect_dump, stmt, TDF_SLIM);
00348 }
00349 return false;
00350 }
00351 }
00352 }
00353 }
00354
00355
00356
00357
00358
00359
00360
00361
00362 if (!need_to_vectorize)
00363 {
00364 if (vect_print_dump_info (REPORT_DETAILS))
00365 fprintf (vect_dump,
00366 "All the computation can be taken out of the loop.");
00367 if (vect_print_dump_info (REPORT_UNVECTORIZED_LOOPS))
00368 fprintf (vect_dump,
00369 "not vectorized: redundant loop. no profit to vectorize.");
00370 return false;
00371 }
00372
00373 if (LOOP_VINFO_NITERS_KNOWN_P (loop_vinfo)
00374 && vect_print_dump_info (REPORT_DETAILS))
00375 fprintf (vect_dump,
00376 "vectorization_factor = %d, niters = " HOST_WIDE_INT_PRINT_DEC,
00377 vectorization_factor, LOOP_VINFO_INT_NITERS (loop_vinfo));
00378
00379 if (LOOP_VINFO_NITERS_KNOWN_P (loop_vinfo)
00380 && LOOP_VINFO_INT_NITERS (loop_vinfo) < vectorization_factor)
00381 {
00382 if (vect_print_dump_info (REPORT_UNVECTORIZED_LOOPS))
00383 fprintf (vect_dump, "not vectorized: iteration count too small.");
00384 return false;
00385 }
00386
00387 if (!LOOP_VINFO_NITERS_KNOWN_P (loop_vinfo)
00388 || LOOP_VINFO_INT_NITERS (loop_vinfo) % vectorization_factor != 0
00389 || LOOP_PEELING_FOR_ALIGNMENT (loop_vinfo))
00390 {
00391 if (vect_print_dump_info (REPORT_DETAILS))
00392 fprintf (vect_dump, "epilog loop required.");
00393 if (!vect_can_advance_ivs_p (loop_vinfo))
00394 {
00395 if (vect_print_dump_info (REPORT_UNVECTORIZED_LOOPS))
00396 fprintf (vect_dump,
00397 "not vectorized: can't create epilog loop 1.");
00398 return false;
00399 }
00400 if (!slpeel_can_duplicate_loop_p (loop, loop->single_exit))
00401 {
00402 if (vect_print_dump_info (REPORT_UNVECTORIZED_LOOPS))
00403 fprintf (vect_dump,
00404 "not vectorized: can't create epilog loop 2.");
00405 return false;
00406 }
00407 }
00408
00409 return true;
00410 }
00411
00412
00413
00414
00415
00416
00417
00418 static bool
00419 exist_non_indexing_operands_for_use_p (tree use, tree stmt)
00420 {
00421 tree operand;
00422 stmt_vec_info stmt_info = vinfo_for_stmt (stmt);
00423
00424
00425
00426
00427 if (!STMT_VINFO_DATA_REF (stmt_info))
00428 return true;
00429
00430
00431
00432
00433
00434
00435
00436
00437
00438
00439
00440
00441
00442
00443 if (TREE_CODE (TREE_OPERAND (stmt, 0)) == SSA_NAME)
00444 return false;
00445
00446 operand = TREE_OPERAND (stmt, 1);
00447
00448 if (TREE_CODE (operand) != SSA_NAME)
00449 return false;
00450
00451 if (operand == use)
00452 return true;
00453
00454 return false;
00455 }
00456
00457
00458
00459
00460
00461
00462
00463
00464
00465
00466
00467
00468
00469
00470
00471
00472
00473
00474
00475
00476
00477
00478
00479
00480
00481
00482
00483
00484
00485
00486
00487
00488
00489
00490
00491
00492
00493
00494
00495
00496
00497 static void
00498 vect_analyze_scalar_cycles (loop_vec_info loop_vinfo)
00499 {
00500 tree phi;
00501 struct loop *loop = LOOP_VINFO_LOOP (loop_vinfo);
00502 basic_block bb = loop->header;
00503 tree dummy;
00504
00505 if (vect_print_dump_info (REPORT_DETAILS))
00506 fprintf (vect_dump, "=== vect_analyze_scalar_cycles ===");
00507
00508 for (phi = phi_nodes (bb); phi; phi = PHI_CHAIN (phi))
00509 {
00510 tree access_fn = NULL;
00511 tree def = PHI_RESULT (phi);
00512 stmt_vec_info stmt_vinfo = vinfo_for_stmt (phi);
00513 tree reduc_stmt;
00514
00515 if (vect_print_dump_info (REPORT_DETAILS))
00516 {
00517 fprintf (vect_dump, "Analyze phi: ");
00518 print_generic_expr (vect_dump, phi, TDF_SLIM);
00519 }
00520
00521
00522
00523
00524 if (!is_gimple_reg (SSA_NAME_VAR (def)))
00525 {
00526 if (vect_print_dump_info (REPORT_DETAILS))
00527 fprintf (vect_dump, "virtual phi. skip.");
00528 continue;
00529 }
00530
00531 STMT_VINFO_DEF_TYPE (stmt_vinfo) = vect_unknown_def_type;
00532
00533
00534
00535 access_fn = analyze_scalar_evolution (loop, def);
00536
00537 if (!access_fn)
00538 continue;
00539
00540 if (vect_print_dump_info (REPORT_DETAILS))
00541 {
00542 fprintf (vect_dump, "Access function of PHI: ");
00543 print_generic_expr (vect_dump, access_fn, TDF_SLIM);
00544 }
00545
00546 if (vect_is_simple_iv_evolution (loop->num, access_fn, &dummy, &dummy))
00547 {
00548 if (vect_print_dump_info (REPORT_DETAILS))
00549 fprintf (vect_dump, "Detected induction.");
00550 STMT_VINFO_DEF_TYPE (stmt_vinfo) = vect_induction_def;
00551 continue;
00552 }
00553
00554
00555
00556 reduc_stmt = vect_is_simple_reduction (loop, phi);
00557 if (reduc_stmt)
00558 {
00559 if (vect_print_dump_info (REPORT_DETAILS))
00560 fprintf (vect_dump, "Detected reduction.");
00561 STMT_VINFO_DEF_TYPE (stmt_vinfo) = vect_reduction_def;
00562 STMT_VINFO_DEF_TYPE (vinfo_for_stmt (reduc_stmt)) =
00563 vect_reduction_def;
00564 }
00565 else
00566 if (vect_print_dump_info (REPORT_DETAILS))
00567 fprintf (vect_dump, "Unknown def-use cycle pattern.");
00568
00569 }
00570
00571 return;
00572 }
00573
00574
00575
00576
00577
00578
00579
00580 static bool
00581 vect_analyze_data_ref_dependence (struct data_dependence_relation *ddr,
00582 loop_vec_info loop_vinfo)
00583 {
00584 unsigned int i;
00585 struct loop *loop = LOOP_VINFO_LOOP (loop_vinfo);
00586 int vectorization_factor = LOOP_VINFO_VECT_FACTOR (loop_vinfo);
00587 struct data_reference *dra = DDR_A (ddr);
00588 struct data_reference *drb = DDR_B (ddr);
00589 stmt_vec_info stmtinfo_a = vinfo_for_stmt (DR_STMT (dra));
00590 stmt_vec_info stmtinfo_b = vinfo_for_stmt (DR_STMT (drb));
00591 lambda_vector dist_v;
00592 unsigned int loop_depth;
00593
00594 if (DDR_ARE_DEPENDENT (ddr) == chrec_known)
00595 return false;
00596
00597 if (DDR_ARE_DEPENDENT (ddr) == chrec_dont_know)
00598 {
00599 if (vect_print_dump_info (REPORT_UNVECTORIZED_LOOPS))
00600 {
00601 fprintf (vect_dump,
00602 "not vectorized: can't determine dependence between ");
00603 print_generic_expr (vect_dump, DR_REF (dra), TDF_SLIM);
00604 fprintf (vect_dump, " and ");
00605 print_generic_expr (vect_dump, DR_REF (drb), TDF_SLIM);
00606 }
00607 return true;
00608 }
00609
00610 if (DDR_NUM_DIST_VECTS (ddr) == 0)
00611 {
00612 if (vect_print_dump_info (REPORT_UNVECTORIZED_LOOPS))
00613 {
00614 fprintf (vect_dump, "not vectorized: bad dist vector for ");
00615 print_generic_expr (vect_dump, DR_REF (dra), TDF_SLIM);
00616 fprintf (vect_dump, " and ");
00617 print_generic_expr (vect_dump, DR_REF (drb), TDF_SLIM);
00618 }
00619 return true;
00620 }
00621
00622 loop_depth = index_in_loop_nest (loop->num, DDR_LOOP_NEST (ddr));
00623 for (i = 0; VEC_iterate (lambda_vector, DDR_DIST_VECTS (ddr), i, dist_v); i++)
00624 {
00625 int dist = dist_v[loop_depth];
00626
00627 if (vect_print_dump_info (REPORT_DR_DETAILS))
00628 fprintf (vect_dump, "dependence distance = %d.", dist);
00629
00630
00631 if (dist % vectorization_factor == 0)
00632 {
00633
00634 VEC_safe_push (dr_p, heap, STMT_VINFO_SAME_ALIGN_REFS (stmtinfo_a), drb);
00635 VEC_safe_push (dr_p, heap, STMT_VINFO_SAME_ALIGN_REFS (stmtinfo_b), dra);
00636 if (vect_print_dump_info (REPORT_ALIGNMENT))
00637 fprintf (vect_dump, "accesses have the same alignment.");
00638 if (vect_print_dump_info (REPORT_DR_DETAILS))
00639 {
00640 fprintf (vect_dump, "dependence distance modulo vf == 0 between ");
00641 print_generic_expr (vect_dump, DR_REF (dra), TDF_SLIM);
00642 fprintf (vect_dump, " and ");
00643 print_generic_expr (vect_dump, DR_REF (drb), TDF_SLIM);
00644 }
00645 continue;
00646 }
00647
00648 if (abs (dist) >= vectorization_factor)
00649 {
00650
00651
00652 if (vect_print_dump_info (REPORT_DR_DETAILS))
00653 fprintf (vect_dump, "dependence distance >= VF.");
00654 continue;
00655 }
00656
00657 if (vect_print_dump_info (REPORT_UNVECTORIZED_LOOPS))
00658 {
00659 fprintf (vect_dump,
00660 "not vectorized: possible dependence between data-refs ");
00661 print_generic_expr (vect_dump, DR_REF (dra), TDF_SLIM);
00662 fprintf (vect_dump, " and ");
00663 print_generic_expr (vect_dump, DR_REF (drb), TDF_SLIM);
00664 }
00665
00666 return true;
00667 }
00668
00669 return false;
00670 }
00671
00672
00673
00674
00675
00676
00677
00678 static bool
00679 vect_analyze_data_ref_dependences (loop_vec_info loop_vinfo)
00680 {
00681 unsigned int i;
00682 VEC (ddr_p, heap) *ddrs = LOOP_VINFO_DDRS (loop_vinfo);
00683 struct data_dependence_relation *ddr;
00684
00685 if (vect_print_dump_info (REPORT_DETAILS))
00686 fprintf (vect_dump, "=== vect_analyze_dependences ===");
00687
00688 for (i = 0; VEC_iterate (ddr_p, ddrs, i, ddr); i++)
00689 if (vect_analyze_data_ref_dependence (ddr, loop_vinfo))
00690 return false;
00691
00692 return true;
00693 }
00694
00695
00696
00697
00698
00699
00700
00701
00702
00703
00704
00705
00706
00707
00708 static bool
00709 vect_compute_data_ref_alignment (struct data_reference *dr)
00710 {
00711 tree stmt = DR_STMT (dr);
00712 stmt_vec_info stmt_info = vinfo_for_stmt (stmt);
00713 tree ref = DR_REF (dr);
00714 tree vectype;
00715 tree base, base_addr;
00716 bool base_aligned;
00717 tree misalign;
00718 tree aligned_to, alignment;
00719
00720 if (vect_print_dump_info (REPORT_DETAILS))
00721 fprintf (vect_dump, "vect_compute_data_ref_alignment:");
00722
00723
00724 DR_MISALIGNMENT (dr) = -1;
00725
00726 misalign = DR_OFFSET_MISALIGNMENT (dr);
00727 aligned_to = DR_ALIGNED_TO (dr);
00728 base_addr = DR_BASE_ADDRESS (dr);
00729 base = build_fold_indirect_ref (base_addr);
00730 vectype = STMT_VINFO_VECTYPE (stmt_info);
00731 alignment = ssize_int (TYPE_ALIGN (vectype)/BITS_PER_UNIT);
00732
00733 if ((aligned_to && tree_int_cst_compare (aligned_to, alignment) < 0)
00734 || !misalign)
00735 {
00736 if (vect_print_dump_info (REPORT_DETAILS))
00737 {
00738 fprintf (vect_dump, "Unknown alignment for access: ");
00739 print_generic_expr (vect_dump, base, TDF_SLIM);
00740 }
00741 return true;
00742 }
00743
00744 if ((DECL_P (base)
00745 && tree_int_cst_compare (ssize_int (DECL_ALIGN_UNIT (base)),
00746 alignment) >= 0)
00747 || (TREE_CODE (base_addr) == SSA_NAME
00748 && tree_int_cst_compare (ssize_int (TYPE_ALIGN_UNIT (TREE_TYPE (
00749 TREE_TYPE (base_addr)))),
00750 alignment) >= 0))
00751 base_aligned = true;
00752 else
00753 base_aligned = false;
00754
00755 if (!base_aligned)
00756 {
00757
00758
00759 if (!vect_can_force_dr_alignment_p (base, TYPE_ALIGN (vectype))
00760 || (TREE_STATIC (base) && flag_section_anchors))
00761 {
00762 if (vect_print_dump_info (REPORT_DETAILS))
00763 {
00764 fprintf (vect_dump, "can't force alignment of ref: ");
00765 print_generic_expr (vect_dump, ref, TDF_SLIM);
00766 }
00767 return true;
00768 }
00769
00770
00771
00772
00773 if (vect_print_dump_info (REPORT_DETAILS))
00774 fprintf (vect_dump, "force alignment");
00775 DECL_ALIGN (base) = TYPE_ALIGN (vectype);
00776 DECL_USER_ALIGN (base) = 1;
00777 }
00778
00779
00780 gcc_assert (base_aligned
00781 || (TREE_CODE (base) == VAR_DECL
00782 && DECL_ALIGN (base) >= TYPE_ALIGN (vectype)));
00783
00784
00785 misalign = size_binop (TRUNC_MOD_EXPR, misalign, alignment);
00786
00787 if (!host_integerp (misalign, 1))
00788 {
00789
00790 if (vect_print_dump_info (REPORT_DETAILS))
00791 fprintf (vect_dump, "unexpected misalign value");
00792 return false;
00793 }
00794
00795 DR_MISALIGNMENT (dr) = TREE_INT_CST_LOW (misalign);
00796
00797 if (vect_print_dump_info (REPORT_DETAILS))
00798 {
00799 fprintf (vect_dump, "misalign = %d bytes of ref ", DR_MISALIGNMENT (dr));
00800 print_generic_expr (vect_dump, ref, TDF_SLIM);
00801 }
00802
00803 return true;
00804 }
00805
00806
00807
00808
00809
00810
00811
00812 static bool
00813 vect_compute_data_refs_alignment (loop_vec_info loop_vinfo)
00814 {
00815 VEC (data_reference_p, heap) *datarefs = LOOP_VINFO_DATAREFS (loop_vinfo);
00816 struct data_reference *dr;
00817 unsigned int i;
00818
00819 for (i = 0; VEC_iterate (data_reference_p, datarefs, i, dr); i++)
00820 if (!vect_compute_data_ref_alignment (dr))
00821 return false;
00822
00823 return true;
00824 }
00825
00826
00827
00828
00829
00830
00831
00832
00833
00834
00835 static void
00836 vect_update_misalignment_for_peel (struct data_reference *dr,
00837 struct data_reference *dr_peel, int npeel)
00838 {
00839 unsigned int i;
00840 int drsize;
00841 VEC(dr_p,heap) *same_align_drs;
00842 struct data_reference *current_dr;
00843
00844 if (known_alignment_for_access_p (dr)
00845 && DR_MISALIGNMENT (dr) == DR_MISALIGNMENT (dr_peel))
00846 {
00847 DR_MISALIGNMENT (dr) = 0;
00848 return;
00849 }
00850
00851
00852
00853 same_align_drs
00854 = STMT_VINFO_SAME_ALIGN_REFS (vinfo_for_stmt (DR_STMT (dr_peel)));
00855 for (i = 0; VEC_iterate (dr_p, same_align_drs, i, current_dr); i++)
00856 {
00857 if (current_dr != dr)
00858 continue;
00859 gcc_assert (DR_MISALIGNMENT (dr) == DR_MISALIGNMENT (dr_peel));
00860 DR_MISALIGNMENT (dr) = 0;
00861 return;
00862 }
00863
00864 if (known_alignment_for_access_p (dr)
00865 && known_alignment_for_access_p (dr_peel))
00866 {
00867 drsize = GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (DR_REF (dr))));
00868 DR_MISALIGNMENT (dr) += npeel * drsize;
00869 DR_MISALIGNMENT (dr) %= UNITS_PER_SIMD_WORD;
00870 return;
00871 }
00872
00873 DR_MISALIGNMENT (dr) = -1;
00874 }
00875
00876
00877
00878
00879
00880
00881
00882 static bool
00883 vect_verify_datarefs_alignment (loop_vec_info loop_vinfo)
00884 {
00885 VEC (data_reference_p, heap) *datarefs = LOOP_VINFO_DATAREFS (loop_vinfo);
00886 struct data_reference *dr;
00887 enum dr_alignment_support supportable_dr_alignment;
00888 unsigned int i;
00889
00890 for (i = 0; VEC_iterate (data_reference_p, datarefs, i, dr); i++)
00891 {
00892 supportable_dr_alignment = vect_supportable_dr_alignment (dr);
00893 if (!supportable_dr_alignment)
00894 {
00895 if (vect_print_dump_info (REPORT_UNVECTORIZED_LOOPS))
00896 {
00897 if (DR_IS_READ (dr))
00898 fprintf (vect_dump,
00899 "not vectorized: unsupported unaligned load.");
00900 else
00901 fprintf (vect_dump,
00902 "not vectorized: unsupported unaligned store.");
00903 }
00904 return false;
00905 }
00906 if (supportable_dr_alignment != dr_aligned
00907 && vect_print_dump_info (REPORT_ALIGNMENT))
00908 fprintf (vect_dump, "Vectorizing an unaligned access.");
00909 }
00910 return true;
00911 }
00912
00913
00914
00915
00916
00917
00918
00919
00920
00921
00922
00923
00924
00925
00926
00927
00928
00929
00930
00931
00932
00933
00934
00935
00936
00937
00938
00939
00940
00941
00942
00943
00944
00945
00946
00947
00948
00949
00950
00951
00952
00953
00954
00955
00956
00957
00958
00959
00960
00961
00962
00963
00964
00965
00966
00967
00968
00969
00970
00971
00972
00973
00974
00975
00976
00977
00978
00979
00980
00981
00982
00983
00984
00985
00986
00987
00988
00989
00990
00991
00992
00993
00994
00995
00996
00997
00998
00999
01000
01001
01002
01003
01004
01005 static bool
01006 vect_enhance_data_refs_alignment (loop_vec_info loop_vinfo)
01007 {
01008 VEC (data_reference_p, heap) *datarefs = LOOP_VINFO_DATAREFS (loop_vinfo);
01009 enum dr_alignment_support supportable_dr_alignment;
01010 struct data_reference *dr0 = NULL;
01011 struct data_reference *dr;
01012 unsigned int i;
01013 bool do_peeling = false;
01014 bool do_versioning = false;
01015 bool stat;
01016
01017
01018
01019
01020
01021
01022
01023
01024
01025
01026
01027
01028
01029
01030
01031
01032
01033
01034
01035
01036
01037
01038
01039
01040
01041
01042
01043
01044
01045
01046
01047
01048
01049
01050
01051
01052
01053
01054
01055
01056 for (i = 0; VEC_iterate (data_reference_p, datarefs, i, dr); i++)
01057 if (!DR_IS_READ (dr) && !aligned_access_p (dr))
01058 {
01059 dr0 = dr;
01060 do_peeling = true;
01061 break;
01062 }
01063
01064
01065
01066 if (!vect_can_advance_ivs_p (loop_vinfo))
01067 do_peeling = false;
01068
01069 if (do_peeling)
01070 {
01071 int mis;
01072 int npeel = 0;
01073
01074 if (known_alignment_for_access_p (dr0))
01075 {
01076
01077
01078
01079
01080 mis = DR_MISALIGNMENT (dr0);
01081 mis /= GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (DR_REF (dr0))));
01082 npeel = LOOP_VINFO_VECT_FACTOR (loop_vinfo) - mis;
01083 }
01084
01085
01086 for (i = 0; VEC_iterate (data_reference_p, datarefs, i, dr); i++)
01087 {
01088 int save_misalignment;
01089
01090 if (dr == dr0)
01091 continue;
01092
01093 save_misalignment = DR_MISALIGNMENT (dr);
01094 vect_update_misalignment_for_peel (dr, dr0, npeel);
01095 supportable_dr_alignment = vect_supportable_dr_alignment (dr);
01096 DR_MISALIGNMENT (dr) = save_misalignment;
01097
01098 if (!supportable_dr_alignment)
01099 {
01100 do_peeling = false;
01101 break;
01102 }
01103 }
01104
01105 if (do_peeling)
01106 {
01107
01108
01109
01110
01111
01112
01113
01114 for (i = 0; VEC_iterate (data_reference_p, datarefs, i, dr); i++)
01115 if (dr != dr0)
01116 vect_update_misalignment_for_peel (dr, dr0, npeel);
01117
01118 LOOP_VINFO_UNALIGNED_DR (loop_vinfo) = dr0;
01119 LOOP_PEELING_FOR_ALIGNMENT (loop_vinfo) = DR_MISALIGNMENT (dr0);
01120 DR_MISALIGNMENT (dr0) = 0;
01121 if (vect_print_dump_info (REPORT_ALIGNMENT))
01122 fprintf (vect_dump, "Alignment of access forced using peeling.");
01123
01124 if (vect_print_dump_info (REPORT_DETAILS))
01125 fprintf (vect_dump, "Peeling for alignment will be applied.");
01126
01127 stat = vect_verify_datarefs_alignment (loop_vinfo);
01128 gcc_assert (stat);
01129 return stat;
01130 }
01131 }
01132
01133
01134
01135
01136
01137
01138
01139
01140
01141
01142
01143
01144 do_versioning = flag_tree_vect_loop_version && (!optimize_size);
01145
01146 if (do_versioning)
01147 {
01148 for (i = 0; VEC_iterate (data_reference_p, datarefs, i, dr); i++)
01149 {
01150 if (aligned_access_p (dr))
01151 continue;
01152
01153 supportable_dr_alignment = vect_supportable_dr_alignment (dr);
01154
01155 if (!supportable_dr_alignment)
01156 {
01157 tree stmt;
01158 int mask;
01159 tree vectype;
01160
01161 if (known_alignment_for_access_p (dr)
01162 || VEC_length (tree,
01163 LOOP_VINFO_MAY_MISALIGN_STMTS (loop_vinfo))
01164 >= (unsigned) PARAM_VALUE (PARAM_VECT_MAX_VERSION_CHECKS))
01165 {
01166 do_versioning = false;
01167 break;
01168 }
01169
01170 stmt = DR_STMT (dr);
01171 vectype = STMT_VINFO_VECTYPE (vinfo_for_stmt (stmt));
01172 gcc_assert (vectype);
01173
01174
01175
01176
01177
01178 mask = GET_MODE_SIZE (TYPE_MODE (vectype)) - 1;
01179
01180
01181
01182
01183
01184
01185 gcc_assert (!LOOP_VINFO_PTR_MASK (loop_vinfo)
01186 || LOOP_VINFO_PTR_MASK (loop_vinfo) == mask);
01187 LOOP_VINFO_PTR_MASK (loop_vinfo) = mask;
01188 VEC_safe_push (tree, heap,
01189 LOOP_VINFO_MAY_MISALIGN_STMTS (loop_vinfo),
01190 DR_STMT (dr));
01191 }
01192 }
01193
01194
01195 if (VEC_length (tree, LOOP_VINFO_MAY_MISALIGN_STMTS (loop_vinfo)) == 0)
01196 do_versioning = false;
01197 else if (!do_versioning)
01198 VEC_truncate (tree, LOOP_VINFO_MAY_MISALIGN_STMTS (loop_vinfo), 0);
01199 }
01200
01201 if (do_versioning)
01202 {
01203 VEC(tree,heap) *may_misalign_stmts
01204 = LOOP_VINFO_MAY_MISALIGN_STMTS (loop_vinfo);
01205 tree stmt;
01206
01207
01208
01209
01210 for (i = 0; VEC_iterate (tree, may_misalign_stmts, i, stmt); i++)
01211 {
01212 stmt_vec_info stmt_info = vinfo_for_stmt (stmt);
01213 dr = STMT_VINFO_DATA_REF (stmt_info);
01214 DR_MISALIGNMENT (dr) = 0;
01215 if (vect_print_dump_info (REPORT_ALIGNMENT))
01216 fprintf (vect_dump, "Alignment of access forced using versioning.");
01217 }
01218
01219 if (vect_print_dump_info (REPORT_DETAILS))
01220 fprintf (vect_dump, "Versioning for alignment will be applied.");
01221
01222
01223 gcc_assert (! (do_peeling && do_versioning));
01224
01225 stat = vect_verify_datarefs_alignment (loop_vinfo);
01226 gcc_assert (stat);
01227 return stat;
01228 }
01229
01230
01231 gcc_assert (! (do_peeling || do_versioning));
01232
01233 stat = vect_verify_datarefs_alignment (loop_vinfo);
01234 return stat;
01235 }
01236
01237
01238
01239
01240
01241
01242
01243 static bool
01244 vect_analyze_data_refs_alignment (loop_vec_info loop_vinfo)
01245 {
01246 if (vect_print_dump_info (REPORT_DETAILS))
01247 fprintf (vect_dump, "=== vect_analyze_data_refs_alignment ===");
01248
01249 if (!vect_compute_data_refs_alignment (loop_vinfo))
01250 {
01251 if (vect_print_dump_info (REPORT_UNVECTORIZED_LOOPS))
01252 fprintf (vect_dump,
01253 "not vectorized: can't calculate alignment for data ref.");
01254 return false;
01255 }
01256
01257 return true;
01258 }
01259
01260
01261
01262
01263
01264
01265
01266 static bool
01267 vect_analyze_data_ref_access (struct data_reference *dr)
01268 {
01269 tree step = DR_STEP (dr);
01270 tree scalar_type = TREE_TYPE (DR_REF (dr));
01271
01272 if (!step || tree_int_cst_compare (step, TYPE_SIZE_UNIT (scalar_type)))
01273 {
01274 if (vect_print_dump_info (REPORT_DETAILS))
01275 fprintf (vect_dump, "not consecutive access");
01276 return false;
01277 }
01278 return true;
01279 }
01280
01281
01282
01283
01284
01285
01286
01287
01288
01289
01290
01291 static bool
01292 vect_analyze_data_ref_accesses (loop_vec_info loop_vinfo)
01293 {
01294 unsigned int i;
01295 VEC (data_reference_p, heap) *datarefs = LOOP_VINFO_DATAREFS (loop_vinfo);
01296 struct data_reference *dr;
01297
01298 if (vect_print_dump_info (REPORT_DETAILS))
01299 fprintf (vect_dump, "=== vect_analyze_data_ref_accesses ===");
01300
01301 for (i = 0; VEC_iterate (data_reference_p, datarefs, i, dr); i++)
01302 if (!vect_analyze_data_ref_access (dr))
01303 {
01304 if (vect_print_dump_info (REPORT_UNVECTORIZED_LOOPS))
01305 fprintf (vect_dump, "not vectorized: complicated access pattern.");
01306 return false;
01307 }
01308
01309 return true;
01310 }
01311
01312
01313
01314
01315
01316
01317
01318
01319
01320
01321
01322
01323
01324
01325
01326
01327 static bool
01328 vect_analyze_data_refs (loop_vec_info loop_vinfo)
01329 {
01330 struct loop *loop = LOOP_VINFO_LOOP (loop_vinfo);
01331 unsigned int i;
01332 VEC (data_reference_p, heap) *datarefs;
01333 struct data_reference *dr;
01334 tree scalar_type;
01335
01336 if (vect_print_dump_info (REPORT_DETAILS))
01337 fprintf (vect_dump, "=== vect_analyze_data_refs ===");
01338
01339 compute_data_dependences_for_loop (loop, false,
01340 &LOOP_VINFO_DATAREFS (loop_vinfo),
01341 &LOOP_VINFO_DDRS (loop_vinfo));
01342
01343
01344
01345 datarefs = LOOP_VINFO_DATAREFS (loop_vinfo);
01346
01347 for (i = 0; VEC_iterate (data_reference_p, datarefs, i, dr); i++)
01348 {
01349 tree stmt;
01350 stmt_vec_info stmt_info;
01351
01352 if (!dr || !DR_REF (dr))
01353 {
01354 if (vect_print_dump_info (REPORT_UNVECTORIZED_LOOPS))
01355 fprintf (vect_dump, "not vectorized: unhandled data-ref ");
01356 return false;
01357 }
01358
01359
01360 stmt = DR_STMT (dr);
01361 stmt_info = vinfo_for_stmt (stmt);
01362
01363 if (STMT_VINFO_DATA_REF (stmt_info))
01364 {
01365 if (vect_print_dump_info (REPORT_UNVECTORIZED_LOOPS))
01366 {
01367 fprintf (vect_dump,
01368 "not vectorized: more than one data ref in stmt: ");
01369 print_generic_expr (vect_dump, stmt, TDF_SLIM);
01370 }
01371 return false;
01372 }
01373 STMT_VINFO_DATA_REF (stmt_info) = dr;
01374
01375
01376 if (!DR_BASE_ADDRESS (dr) || !DR_OFFSET (dr) || !DR_INIT (dr)
01377 || !DR_STEP (dr))
01378 {
01379 if (vect_print_dump_info (REPORT_UNVECTORIZED_LOOPS))
01380 {
01381 fprintf (vect_dump, "not vectorized: data ref analysis failed ");
01382 print_generic_expr (vect_dump, stmt, TDF_SLIM);
01383 }
01384 return false;
01385 }
01386 if (!DR_MEMTAG (dr))
01387 {
01388 if (vect_print_dump_info (REPORT_UNVECTORIZED_LOOPS))
01389 {
01390 fprintf (vect_dump, "not vectorized: no memory tag for ");
01391 print_generic_expr (vect_dump, DR_REF (dr), TDF_SLIM);
01392 }
01393 return false;
01394 }
01395
01396
01397 scalar_type = TREE_TYPE (DR_REF (dr));
01398 STMT_VINFO_VECTYPE (stmt_info) =
01399 get_vectype_for_scalar_type (scalar_type);
01400 if (!STMT_VINFO_VECTYPE (stmt_info))
01401 {
01402 if (vect_print_dump_info (REPORT_UNVECTORIZED_LOOPS))
01403 {
01404 fprintf (vect_dump,
01405 "not vectorized: no vectype for stmt: ");
01406 print_generic_expr (vect_dump, stmt, TDF_SLIM);
01407 fprintf (vect_dump, " scalar_type: ");
01408 print_generic_expr (vect_dump, scalar_type, TDF_DETAILS);
01409 }
01410 return false;
01411 }
01412 }
01413
01414 return true;
01415 }
01416
01417
01418
01419
01420
01421
01422
01423
01424 static void
01425 vect_mark_relevant (VEC(tree,heap) **worklist, tree stmt,
01426 bool relevant_p, bool live_p)
01427 {
01428 stmt_vec_info stmt_info = vinfo_for_stmt (stmt);
01429 bool save_relevant_p = STMT_VINFO_RELEVANT_P (stmt_info);
01430 bool save_live_p = STMT_VINFO_LIVE_P (stmt_info);
01431
01432 if (vect_print_dump_info (REPORT_DETAILS))
01433 fprintf (vect_dump, "mark relevant %d, live %d.",relevant_p, live_p);
01434
01435 if (STMT_VINFO_IN_PATTERN_P (stmt_info))
01436 {
01437 tree pattern_stmt;
01438
01439
01440
01441
01442
01443 if (vect_print_dump_info (REPORT_DETAILS))
01444 fprintf (vect_dump, "last stmt in pattern. don't mark relevant/live.");
01445 pattern_stmt = STMT_VINFO_RELATED_STMT (stmt_info);
01446 stmt_info = vinfo_for_stmt (pattern_stmt);
01447 gcc_assert (STMT_VINFO_RELATED_STMT (stmt_info) == stmt);
01448 save_relevant_p = STMT_VINFO_RELEVANT_P (stmt_info);
01449 save_live_p = STMT_VINFO_LIVE_P (stmt_info);
01450 stmt = pattern_stmt;
01451 }
01452
01453 STMT_VINFO_LIVE_P (stmt_info) |= live_p;
01454 STMT_VINFO_RELEVANT_P (stmt_info) |= relevant_p;
01455
01456 if (TREE_CODE (stmt) == PHI_NODE)
01457
01458
01459 return;
01460
01461 if (STMT_VINFO_RELEVANT_P (stmt_info) == save_relevant_p
01462 && STMT_VINFO_LIVE_P (stmt_info) == save_live_p)
01463 {
01464 if (vect_print_dump_info (REPORT_DETAILS))
01465 fprintf (vect_dump, "already marked relevant/live.");
01466 return;
01467 }
01468
01469 VEC_safe_push (tree, heap, *worklist, stmt);
01470 }
01471
01472
01473
01474
01475
01476
01477
01478
01479
01480
01481
01482
01483
01484
01485 static bool
01486 vect_stmt_relevant_p (tree stmt, loop_vec_info loop_vinfo,
01487 bool *relevant_p, bool *live_p)
01488 {
01489 struct loop *loop = LOOP_VINFO_LOOP (loop_vinfo);
01490 ssa_op_iter op_iter;
01491 imm_use_iterator imm_iter;
01492 use_operand_p use_p;
01493 def_operand_p def_p;
01494
01495 *relevant_p = false;
01496 *live_p = false;
01497
01498
01499 if (is_ctrl_stmt (stmt) && (stmt != LOOP_VINFO_EXIT_COND (loop_vinfo)))
01500 *relevant_p = true;
01501
01502
01503 if (TREE_CODE (stmt) != PHI_NODE)
01504 if (!ZERO_SSA_OPERANDS (stmt, SSA_OP_VIRTUAL_DEFS))
01505 {
01506 if (vect_print_dump_info (REPORT_DETAILS))
01507 fprintf (vect_dump, "vec_stmt_relevant_p: stmt has vdefs.");
01508 *relevant_p = true;
01509 }
01510
01511
01512 FOR_EACH_PHI_OR_STMT_DEF (def_p, stmt, op_iter, SSA_OP_DEF)
01513 {
01514 FOR_EACH_IMM_USE_FAST (use_p, imm_iter, DEF_FROM_PTR (def_p))
01515 {
01516 basic_block bb = bb_for_stmt (USE_STMT (use_p));
01517 if (!flow_bb_inside_loop_p (loop, bb))
01518 {
01519 if (vect_print_dump_info (REPORT_DETAILS))
01520 fprintf (vect_dump, "vec_stmt_relevant_p: used out of loop.");
01521
01522
01523
01524 gcc_assert (TREE_CODE (USE_STMT (use_p)) == PHI_NODE);
01525 gcc_assert (bb == loop->single_exit->dest);
01526
01527 *live_p = true;
01528 }
01529 }
01530 }
01531
01532 return (*live_p || *relevant_p);
01533 }
01534
01535
01536
01537
01538
01539
01540
01541
01542
01543
01544
01545
01546
01547
01548
01549
01550
01551
01552 static bool
01553 vect_mark_stmts_to_be_vectorized (loop_vec_info loop_vinfo)
01554 {
01555 VEC(tree,heap) *worklist;
01556 struct loop *loop = LOOP_VINFO_LOOP (loop_vinfo);
01557 basic_block *bbs = LOOP_VINFO_BBS (loop_vinfo);
01558 unsigned int nbbs = loop->num_nodes;
01559 block_stmt_iterator si;
01560 tree stmt, use;
01561 stmt_ann_t ann;
01562 ssa_op_iter iter;
01563 unsigned int i;
01564 stmt_vec_info stmt_vinfo;
01565 basic_block bb;
01566 tree phi;
01567 bool relevant_p, live_p;
01568 tree def, def_stmt;
01569 enum vect_def_type dt;
01570
01571 if (vect_print_dump_info (REPORT_DETAILS))
01572 fprintf (vect_dump, "=== vect_mark_stmts_to_be_vectorized ===");
01573
01574 worklist = VEC_alloc (tree, heap, 64);
01575
01576
01577
01578 bb = loop->header;
01579 for (phi = phi_nodes (bb); phi; phi = PHI_CHAIN (phi))
01580 {
01581 if (vect_print_dump_info (REPORT_DETAILS))
01582 {
01583 fprintf (vect_dump, "init: phi relevant? ");
01584 print_generic_expr (vect_dump, phi, TDF_SLIM);
01585 }
01586
01587 if (vect_stmt_relevant_p (phi, loop_vinfo, &relevant_p, &live_p))
01588 vect_mark_relevant (&worklist, phi, relevant_p, live_p);
01589 }
01590
01591 for (i = 0; i < nbbs; i++)
01592 {
01593 bb = bbs[i];
01594 for (si = bsi_start (bb); !bsi_end_p (si); bsi_next (&si))
01595 {
01596 stmt = bsi_stmt (si);
01597
01598 if (vect_print_dump_info (REPORT_DETAILS))
01599 {
01600 fprintf (vect_dump, "init: stmt relevant? ");
01601 print_generic_expr (vect_dump, stmt, TDF_SLIM);
01602 }
01603
01604 if (vect_stmt_relevant_p (stmt, loop_vinfo, &relevant_p, &live_p))
01605 vect_mark_relevant (&worklist, stmt, relevant_p, live_p);
01606 }
01607 }
01608
01609
01610
01611
01612 while (VEC_length (tree, worklist) > 0)
01613 {
01614 stmt = VEC_pop (tree, worklist);
01615
01616 if (vect_print_dump_info (REPORT_DETAILS))
01617 {
01618 fprintf (vect_dump, "worklist: examine stmt: ");
01619 print_generic_expr (vect_dump, stmt, TDF_SLIM);
01620 }
01621
01622
01623
01624
01625
01626
01627
01628 gcc_assert (TREE_CODE (stmt) != PHI_NODE);
01629
01630 ann = stmt_ann (stmt);
01631 stmt_vinfo = vinfo_for_stmt (stmt);
01632
01633 relevant_p = STMT_VINFO_RELEVANT_P (stmt_vinfo);
01634 live_p = STMT_VINFO_LIVE_P (stmt_vinfo);
01635
01636
01637
01638
01639
01640
01641
01642
01643
01644
01645
01646
01647
01648
01649
01650
01651
01652
01653
01654
01655
01656
01657
01658
01659
01660
01661
01662
01663
01664
01665
01666
01667
01668
01669
01670 if (STMT_VINFO_DEF_TYPE (stmt_vinfo) == vect_reduction_def)
01671 {
01672 gcc_assert (!relevant_p && live_p);
01673 relevant_p = true;
01674 live_p = false;
01675 }
01676
01677 FOR_EACH_SSA_TREE_OPERAND (use, stmt, iter, SSA_OP_USE)
01678 {
01679
01680
01681
01682
01683 if (!exist_non_indexing_operands_for_use_p (use, stmt))
01684 continue;
01685
01686 if (!vect_is_simple_use (use, loop_vinfo, &def_stmt, &def, &dt))
01687 {
01688 if (vect_print_dump_info (REPORT_UNVECTORIZED_LOOPS))
01689 fprintf (vect_dump, "not vectorized: unsupported use in stmt.");
01690 VEC_free (tree, heap, worklist);
01691 return false;
01692 }
01693
01694 if (!def_stmt || IS_EMPTY_STMT (def_stmt))
01695 continue;
01696
01697 if (vect_print_dump_info (REPORT_DETAILS))
01698 {
01699 fprintf (vect_dump, "worklist: examine use %d: ", i);
01700 print_generic_expr (vect_dump, use, TDF_SLIM);
01701 }
01702
01703 bb = bb_for_stmt (def_stmt);
01704 if (!flow_bb_inside_loop_p (loop, bb))
01705 continue;
01706
01707
01708
01709 if (STMT_VINFO_DEF_TYPE (stmt_vinfo) == vect_reduction_def
01710 && TREE_CODE (def_stmt) == PHI_NODE)
01711 continue;
01712
01713 vect_mark_relevant (&worklist, def_stmt, relevant_p, live_p);
01714 }
01715 }
01716
01717 VEC_free (tree, heap, worklist);
01718 return true;
01719 }
01720
01721
01722
01723
01724
01725
01726
01727
01728
01729
01730
01731 static bool
01732 vect_can_advance_ivs_p (loop_vec_info loop_vinfo)
01733 {
01734 struct loop *loop = LOOP_VINFO_LOOP (loop_vinfo);
01735 basic_block bb = loop->header;
01736 tree phi;
01737
01738
01739
01740 if (vect_print_dump_info (REPORT_DETAILS))
01741 fprintf (vect_dump, "=== vect_can_advance_ivs_p ===");
01742
01743 for (phi = phi_nodes (bb); phi; phi = PHI_CHAIN (phi))
01744 {
01745 tree access_fn = NULL;
01746 tree evolution_part;
01747
01748 if (vect_print_dump_info (REPORT_DETAILS))
01749 {
01750 fprintf (vect_dump, "Analyze phi: ");
01751 print_generic_expr (vect_dump, phi, TDF_SLIM);
01752 }
01753
01754
01755
01756
01757 if (!is_gimple_reg (SSA_NAME_VAR (PHI_RESULT (phi))))
01758 {
01759 if (vect_print_dump_info (REPORT_DETAILS))
01760 fprintf (vect_dump, "virtual phi. skip.");
01761 continue;
01762 }
01763
01764
01765
01766 if (STMT_VINFO_DEF_TYPE (vinfo_for_stmt (phi)) == vect_reduction_def)
01767 {
01768 if (vect_print_dump_info (REPORT_DETAILS))
01769 fprintf (vect_dump, "reduc phi. skip.");
01770 continue;
01771 }
01772
01773
01774
01775 access_fn = instantiate_parameters
01776 (loop, analyze_scalar_evolution (loop, PHI_RESULT (phi)));
01777
01778 if (!access_fn)
01779 {
01780 if (vect_print_dump_info (REPORT_DETAILS))
01781 fprintf (vect_dump, "No Access function.");
01782 return false;
01783 }
01784
01785 if (vect_print_dump_info (REPORT_DETAILS))
01786 {
01787 fprintf (vect_dump, "Access function of PHI: ");
01788 print_generic_expr (vect_dump, access_fn, TDF_SLIM);
01789 }
01790
01791 evolution_part = evolution_part_in_loop_num (access_fn, loop->num);
01792
01793 if (evolution_part == NULL_TREE)
01794 {
01795 if (vect_print_dump_info (REPORT_DETAILS))
01796 fprintf (vect_dump, "No evolution.");
01797 return false;
01798 }
01799
01800
01801
01802
01803 if (tree_is_chrec (evolution_part))
01804 return false;
01805 }
01806
01807 return true;
01808 }
01809
01810
01811
01812
01813
01814
01815
01816
01817
01818 static tree
01819 vect_get_loop_niters (struct loop *loop, tree *number_of_iterations)
01820 {
01821 tree niters;
01822
01823 if (vect_print_dump_info (REPORT_DETAILS))
01824 fprintf (vect_dump, "=== get_loop_niters ===");
01825
01826 niters = number_of_iterations_in_loop (loop);
01827
01828 if (niters != NULL_TREE
01829 && niters != chrec_dont_know)
01830 {
01831 *number_of_iterations = niters;
01832
01833 if (vect_print_dump_info (REPORT_DETAILS))
01834 {
01835 fprintf (vect_dump, "==> get_loop_niters:" );
01836 print_generic_expr (vect_dump, *number_of_iterations, TDF_SLIM);
01837 }
01838 }
01839
01840 return get_loop_exit_condition (loop);
01841 }
01842
01843
01844
01845
01846
01847
01848
01849
01850
01851
01852
01853
01854 static loop_vec_info
01855 vect_analyze_loop_form (struct loop *loop)
01856 {
01857 loop_vec_info loop_vinfo;
01858 tree loop_cond;
01859 tree number_of_iterations = NULL;
01860
01861 if (vect_print_dump_info (REPORT_DETAILS))
01862 fprintf (vect_dump, "=== vect_analyze_loop_form ===");
01863
01864 if (loop->inner)
01865 {
01866 if (vect_print_dump_info (REPORT_OUTER_LOOPS))
01867 fprintf (vect_dump, "not vectorized: nested loop.");
01868 return NULL;
01869 }
01870
01871 if (!loop->single_exit
01872 || loop->num_nodes != 2
01873 || EDGE_COUNT (loop->header->preds) != 2)
01874 {
01875 if (vect_print_dump_info (REPORT_BAD_FORM_LOOPS))
01876 {
01877 if (!loop->single_exit)
01878 fprintf (vect_dump, "not vectorized: multiple exits.");
01879 else if (loop->num_nodes != 2)
01880 fprintf (vect_dump, "not vectorized: too many BBs in loop.");
01881 else if (EDGE_COUNT (loop->header->preds) != 2)
01882 fprintf (vect_dump, "not vectorized: too many incoming edges.");
01883 }
01884
01885 return NULL;
01886 }
01887
01888
01889
01890
01891
01892 if (!empty_block_p (loop->latch)
01893 || phi_nodes (loop->latch))
01894 {
01895 if (vect_print_dump_info (REPORT_BAD_FORM_LOOPS))
01896 fprintf (vect_dump, "not vectorized: unexpected loop form.");
01897 return NULL;
01898 }
01899
01900
01901 if (!single_pred_p (loop->single_exit->dest))
01902 {
01903 edge e = loop->single_exit;
01904 if (!(e->flags & EDGE_ABNORMAL))
01905 {
01906 split_loop_exit_edge (e);
01907 if (vect_print_dump_info (REPORT_DETAILS))
01908 fprintf (vect_dump, "split exit edge.");
01909 }
01910 else
01911 {
01912 if (vect_print_dump_info (REPORT_BAD_FORM_LOOPS))
01913 fprintf (vect_dump, "not vectorized: abnormal loop exit edge.");
01914 return NULL;
01915 }
01916 }
01917
01918 if (empty_block_p (loop->header))
01919 {
01920 if (vect_print_dump_info (REPORT_BAD_FORM_LOOPS))
01921 fprintf (vect_dump, "not vectorized: empty loop.");
01922 return NULL;
01923 }
01924
01925 loop_cond = vect_get_loop_niters (loop, &number_of_iterations);
01926 if (!loop_cond)
01927 {
01928 if (vect_print_dump_info (REPORT_BAD_FORM_LOOPS))
01929 fprintf (vect_dump, "not vectorized: complicated exit condition.");
01930 return NULL;
01931 }
01932
01933 if (!number_of_iterations)
01934 {
01935 if (vect_print_dump_info (REPORT_BAD_FORM_LOOPS))
01936 fprintf (vect_dump,
01937 "not vectorized: number of iterations cannot be computed.");
01938 return NULL;
01939 }
01940
01941 if (chrec_contains_undetermined (number_of_iterations))
01942 {
01943 if (vect_print_dump_info (REPORT_BAD_FORM_LOOPS))
01944 fprintf (vect_dump, "Infinite number of iterations.");
01945 return false;
01946 }
01947
01948 loop_vinfo = new_loop_vec_info (loop);
01949 LOOP_VINFO_NITERS (loop_vinfo) = number_of_iterations;
01950
01951 if (!LOOP_VINFO_NITERS_KNOWN_P (loop_vinfo))
01952 {
01953 if (vect_print_dump_info (REPORT_DETAILS))
01954 {
01955 fprintf (vect_dump, "Symbolic number of iterations is ");
01956 print_generic_expr (vect_dump, number_of_iterations, TDF_DETAILS);
01957 }
01958 }
01959 else
01960 if (LOOP_VINFO_INT_NITERS (loop_vinfo) == 0)
01961 {
01962 if (vect_print_dump_info (REPORT_UNVECTORIZED_LOOPS))
01963 fprintf (vect_dump, "not vectorized: number of iterations = 0.");
01964 return NULL;
01965 }
01966
01967 LOOP_VINFO_EXIT_COND (loop_vinfo) = loop_cond;
01968
01969 return loop_vinfo;
01970 }
01971
01972
01973
01974
01975
01976
01977
01978 loop_vec_info
01979 vect_analyze_loop (struct loop *loop)
01980 {
01981 bool ok;
01982 loop_vec_info loop_vinfo;
01983
01984 if (vect_print_dump_info (REPORT_DETAILS))
01985 fprintf (vect_dump, "===== analyze_loop_nest =====");
01986
01987
01988
01989 loop_vinfo = vect_analyze_loop_form (loop);
01990 if (!loop_vinfo)
01991 {
01992 if (vect_print_dump_info (REPORT_DETAILS))
01993 fprintf (vect_dump, "bad loop form.");
01994 return NULL;
01995 }
01996
01997
01998
01999
02000
02001
02002
02003 ok = vect_analyze_data_refs (loop_vinfo);
02004 if (!ok)
02005 {
02006 if (vect_print_dump_info (REPORT_DETAILS))
02007 fprintf (vect_dump, "bad data references.");
02008 destroy_loop_vec_info (loop_vinfo);
02009 return NULL;
02010 }
02011
02012
02013
02014
02015 vect_analyze_scalar_cycles (loop_vinfo);
02016
02017 vect_pattern_recog (loop_vinfo);
02018
02019
02020
02021 ok = vect_mark_stmts_to_be_vectorized (loop_vinfo);
02022 if (!ok)
02023 {
02024 if (vect_print_dump_info (REPORT_DETAILS))
02025 fprintf (vect_dump, "unexpected pattern.");
02026 destroy_loop_vec_info (loop_vinfo);
02027 return NULL;
02028 }
02029
02030
02031
02032
02033 ok = vect_analyze_data_refs_alignment (loop_vinfo);
02034 if (!ok)
02035 {
02036 if (vect_print_dump_info (REPORT_DETAILS))
02037 fprintf (vect_dump, "bad data alignment.");
02038 destroy_loop_vec_info (loop_vinfo);
02039 return NULL;
02040 }
02041
02042 ok = vect_determine_vectorization_factor (loop_vinfo);
02043 if (!ok)
02044 {
02045 if (vect_print_dump_info (REPORT_DETAILS))
02046 fprintf (vect_dump, "can't determine vectorization factor.");
02047 destroy_loop_vec_info (loop_vinfo);
02048 return NULL;
02049 }
02050
02051
02052
02053
02054 ok = vect_analyze_data_ref_dependences (loop_vinfo);
02055 if (!ok)
02056 {
02057 if (vect_print_dump_info (REPORT_DETAILS))
02058 fprintf (vect_dump, "bad data dependence.");
02059 destroy_loop_vec_info (loop_vinfo);
02060 return NULL;
02061 }
02062
02063
02064
02065
02066 ok = vect_analyze_data_ref_accesses (loop_vinfo);
02067 if (!ok)
02068 {
02069 if (vect_print_dump_info (REPORT_DETAILS))
02070 fprintf (vect_dump, "bad data access.");
02071 destroy_loop_vec_info (loop_vinfo);
02072 return NULL;
02073 }
02074
02075
02076
02077
02078 ok = vect_enhance_data_refs_alignment (loop_vinfo);
02079 if (!ok)
02080 {
02081 if (vect_print_dump_info (REPORT_DETAILS))
02082 fprintf (vect_dump, "bad data alignment.");
02083 destroy_loop_vec_info (loop_vinfo);
02084 return NULL;
02085 }
02086
02087
02088
02089
02090 ok = vect_analyze_operations (loop_vinfo);
02091 if (!ok)
02092 {
02093 if (vect_print_dump_info (REPORT_DETAILS))
02094 fprintf (vect_dump, "bad operation or unsupported loop bound.");
02095 destroy_loop_vec_info (loop_vinfo);
02096 return NULL;
02097 }
02098
02099 LOOP_VINFO_VECTORIZABLE_P (loop_vinfo) = 1;
02100
02101 return loop_vinfo;
02102 }