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 "errors.h"
00027 #include "ggc.h"
00028 #include "tree.h"
00029 #include "basic-block.h"
00030 #include "diagnostic.h"
00031 #include "tree-flow.h"
00032 #include "tree-dump.h"
00033 #include "timevar.h"
00034 #include "cfgloop.h"
00035 #include "expr.h"
00036 #include "optabs.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 bool 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 void vect_enhance_data_refs_alignment (loop_vec_info);
00052 static bool vect_analyze_operations (loop_vec_info);
00053
00054
00055 static bool exist_non_indexing_operands_for_use_p (tree, tree);
00056 static void vect_mark_relevant (varray_type *, tree);
00057 static bool vect_stmt_relevant_p (tree, loop_vec_info);
00058 static tree vect_get_loop_niters (struct loop *, tree *);
00059 static bool vect_analyze_data_ref_dependence
00060 (struct data_reference *, struct data_reference *, loop_vec_info);
00061 static bool vect_compute_data_ref_alignment (struct data_reference *);
00062 static bool vect_analyze_data_ref_access (struct data_reference *);
00063 static struct data_reference * vect_analyze_pointer_ref_access
00064 (tree, tree, bool, tree, tree *, tree *);
00065 static bool vect_can_advance_ivs_p (loop_vec_info);
00066 static tree vect_get_ptr_offset (tree, tree, tree *);
00067 static bool vect_analyze_offset_expr (tree, struct loop *, tree, tree *,
00068 tree *, tree *);
00069 static bool vect_base_addr_differ_p (struct data_reference *,
00070 struct data_reference *drb, bool *);
00071 static tree vect_object_analysis (tree, tree, bool, tree,
00072 struct data_reference **, tree *, tree *,
00073 tree *, bool *, tree *);
00074 static tree vect_address_analysis (tree, tree, bool, tree,
00075 struct data_reference *, tree *, tree *,
00076 tree *, bool *);
00077
00078
00079
00080
00081
00082
00083 static tree
00084 vect_get_ptr_offset (tree ref ATTRIBUTE_UNUSED,
00085 tree vectype ATTRIBUTE_UNUSED,
00086 tree *offset ATTRIBUTE_UNUSED)
00087 {
00088
00089 return NULL_TREE;
00090 }
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125 static bool
00126 vect_analyze_offset_expr (tree expr,
00127 struct loop *loop,
00128 tree vectype_alignment,
00129 tree *initial_offset,
00130 tree *misalign,
00131 tree *step)
00132 {
00133 tree oprnd0;
00134 tree oprnd1;
00135 tree left_offset = ssize_int (0);
00136 tree right_offset = ssize_int (0);
00137 tree left_misalign = ssize_int (0);
00138 tree right_misalign = ssize_int (0);
00139 tree left_step = ssize_int (0);
00140 tree right_step = ssize_int (0);
00141 enum tree_code code;
00142 tree init, evolution;
00143
00144 *step = NULL_TREE;
00145 *misalign = NULL_TREE;
00146 *initial_offset = NULL_TREE;
00147
00148
00149 expr = vect_strip_conversion (expr);
00150 if (!expr)
00151 return false;
00152
00153
00154
00155 if (TREE_CODE (expr) == INTEGER_CST)
00156 {
00157 *initial_offset = fold_convert (ssizetype, expr);
00158 *misalign = fold_convert (ssizetype, expr);
00159 *step = ssize_int (0);
00160 return true;
00161 }
00162
00163
00164
00165 if (SSA_VAR_P (expr))
00166 {
00167 tree access_fn = analyze_scalar_evolution (loop, expr);
00168
00169 if (access_fn == chrec_dont_know)
00170
00171 return false;
00172
00173 init = initial_condition_in_loop_num (access_fn, loop->num);
00174 if (init == expr && !expr_invariant_in_loop_p (loop, init))
00175
00176
00177
00178
00179 return false;
00180
00181 evolution = evolution_part_in_loop_num (access_fn, loop->num);
00182 if (evolution && TREE_CODE (evolution) != INTEGER_CST)
00183
00184 return false;
00185
00186 if (TREE_CODE (init) == INTEGER_CST)
00187 *misalign = fold_convert (ssizetype, init);
00188 else
00189
00190 *misalign = NULL_TREE;
00191
00192 *initial_offset = fold_convert (ssizetype, init);
00193
00194 *step = evolution ? fold_convert (ssizetype, evolution) : ssize_int (0);
00195 return true;
00196 }
00197
00198
00199 if (!BINARY_CLASS_P (expr))
00200 {
00201
00202 if (vect_print_dump_info (REPORT_DETAILS, UNKNOWN_LOC))
00203 {
00204 fprintf (vect_dump, "Not binary expression ");
00205 print_generic_expr (vect_dump, expr, TDF_SLIM);
00206 }
00207 return false;
00208 }
00209 oprnd0 = TREE_OPERAND (expr, 0);
00210 oprnd1 = TREE_OPERAND (expr, 1);
00211
00212 if (!vect_analyze_offset_expr (oprnd0, loop, vectype_alignment, &left_offset,
00213 &left_misalign, &left_step)
00214 || !vect_analyze_offset_expr (oprnd1, loop, vectype_alignment,
00215 &right_offset, &right_misalign, &right_step))
00216 return false;
00217
00218
00219 code = TREE_CODE (expr);
00220 switch (code)
00221 {
00222 case MULT_EXPR:
00223 if (TREE_CODE (right_offset) != INTEGER_CST)
00224
00225
00226
00227 return false;
00228
00229
00230 left_offset = vect_strip_conversion (left_offset);
00231 if (!left_offset)
00232 return false;
00233
00234 if (SSA_VAR_P (left_offset))
00235 {
00236
00237
00238
00239 if (integer_zerop (size_binop (TRUNC_MOD_EXPR, right_offset,
00240 fold_convert (ssizetype, vectype_alignment))))
00241 *misalign = ssize_int (0);
00242 else
00243
00244
00245 *misalign = NULL_TREE;
00246 }
00247 else
00248 {
00249
00250 if (left_misalign)
00251
00252
00253 *misalign = size_binop (code, left_misalign, right_misalign);
00254 else
00255 *misalign = NULL_TREE;
00256 }
00257
00258
00259
00260 *step = size_binop (MULT_EXPR, left_step, right_offset);
00261 break;
00262
00263 case PLUS_EXPR:
00264 case MINUS_EXPR:
00265
00266 *step = size_binop (code, left_step, right_step);
00267
00268 if (left_misalign && right_misalign)
00269 *misalign = size_binop (code, left_misalign, right_misalign);
00270 else
00271 *misalign = NULL_TREE;
00272
00273 break;
00274
00275 default:
00276 gcc_unreachable ();
00277 }
00278
00279
00280 *initial_offset = fold_convert (ssizetype,
00281 fold (build2 (code, TREE_TYPE (left_offset),
00282 left_offset,
00283 right_offset)));
00284 return true;
00285 }
00286
00287
00288
00289
00290
00291
00292 static bool
00293 vect_analyze_operations (loop_vec_info loop_vinfo)
00294 {
00295 struct loop *loop = LOOP_VINFO_LOOP (loop_vinfo);
00296 basic_block *bbs = LOOP_VINFO_BBS (loop_vinfo);
00297 int nbbs = loop->num_nodes;
00298 block_stmt_iterator si;
00299 unsigned int vectorization_factor = 0;
00300 int i;
00301 bool ok;
00302 tree scalar_type;
00303
00304 if (vect_print_dump_info (REPORT_DETAILS, UNKNOWN_LOC))
00305 fprintf (vect_dump, "=== vect_analyze_operations ===");
00306
00307 for (i = 0; i < nbbs; i++)
00308 {
00309 basic_block bb = bbs[i];
00310
00311 for (si = bsi_start (bb); !bsi_end_p (si); bsi_next (&si))
00312 {
00313 tree stmt = bsi_stmt (si);
00314 unsigned int nunits;
00315 stmt_vec_info stmt_info = vinfo_for_stmt (stmt);
00316 tree vectype;
00317
00318 if (vect_print_dump_info (REPORT_DETAILS, UNKNOWN_LOC))
00319 {
00320 fprintf (vect_dump, "==> examining statement: ");
00321 print_generic_expr (vect_dump, stmt, TDF_SLIM);
00322 }
00323
00324 gcc_assert (stmt_info);
00325
00326
00327
00328
00329
00330
00331
00332
00333 if (!STMT_VINFO_RELEVANT_P (stmt_info))
00334 {
00335 if (vect_print_dump_info (REPORT_DETAILS, UNKNOWN_LOC))
00336 fprintf (vect_dump, "irrelevant.");
00337 continue;
00338 }
00339
00340 if (VECTOR_MODE_P (TYPE_MODE (TREE_TYPE (stmt))))
00341 {
00342 if (vect_print_dump_info (REPORT_UNVECTORIZED_LOOPS,
00343 LOOP_LOC (loop_vinfo)))
00344 {
00345 fprintf (vect_dump, "not vectorized: vector stmt in loop:");
00346 print_generic_expr (vect_dump, stmt, TDF_SLIM);
00347 }
00348 return false;
00349 }
00350
00351 if (STMT_VINFO_DATA_REF (stmt_info))
00352 scalar_type = TREE_TYPE (DR_REF (STMT_VINFO_DATA_REF (stmt_info)));
00353 else if (TREE_CODE (stmt) == MODIFY_EXPR)
00354 scalar_type = TREE_TYPE (TREE_OPERAND (stmt, 0));
00355 else
00356 scalar_type = TREE_TYPE (stmt);
00357
00358 if (vect_print_dump_info (REPORT_DETAILS, UNKNOWN_LOC))
00359 {
00360 fprintf (vect_dump, "get vectype for scalar type: ");
00361 print_generic_expr (vect_dump, scalar_type, TDF_SLIM);
00362 }
00363
00364 vectype = get_vectype_for_scalar_type (scalar_type);
00365 if (!vectype)
00366 {
00367 if (vect_print_dump_info (REPORT_UNVECTORIZED_LOOPS,
00368 LOOP_LOC (loop_vinfo)))
00369 {
00370 fprintf (vect_dump,
00371 "not vectorized: unsupported data-type ");
00372 print_generic_expr (vect_dump, scalar_type, TDF_SLIM);
00373 }
00374 return false;
00375 }
00376
00377 if (vect_print_dump_info (REPORT_DETAILS, UNKNOWN_LOC))
00378 {
00379 fprintf (vect_dump, "vectype: ");
00380 print_generic_expr (vect_dump, vectype, TDF_SLIM);
00381 }
00382 STMT_VINFO_VECTYPE (stmt_info) = vectype;
00383
00384 ok = (vectorizable_operation (stmt, NULL, NULL)
00385 || vectorizable_assignment (stmt, NULL, NULL)
00386 || vectorizable_load (stmt, NULL, NULL)
00387 || vectorizable_store (stmt, NULL, NULL));
00388
00389 if (!ok)
00390 {
00391 if (vect_print_dump_info (REPORT_UNVECTORIZED_LOOPS,
00392 LOOP_LOC (loop_vinfo)))
00393 {
00394 fprintf (vect_dump, "not vectorized: stmt not supported: ");
00395 print_generic_expr (vect_dump, stmt, TDF_SLIM);
00396 }
00397 return false;
00398 }
00399
00400 nunits = GET_MODE_NUNITS (TYPE_MODE (vectype));
00401 if (vect_print_dump_info (REPORT_DETAILS, UNKNOWN_LOC))
00402 fprintf (vect_dump, "nunits = %d", nunits);
00403
00404 if (vectorization_factor)
00405 {
00406
00407
00408 if (nunits != vectorization_factor)
00409 {
00410 if (vect_print_dump_info (REPORT_UNVECTORIZED_LOOPS,
00411 LOOP_LOC (loop_vinfo)))
00412 fprintf (vect_dump, "not vectorized: mixed data-types");
00413 return false;
00414 }
00415 }
00416 else
00417 vectorization_factor = nunits;
00418
00419 #ifdef ENABLE_CHECKING
00420 gcc_assert (GET_MODE_SIZE (TYPE_MODE (scalar_type))
00421 * vectorization_factor == UNITS_PER_SIMD_WORD);
00422 #endif
00423 }
00424 }
00425
00426
00427
00428 if (vectorization_factor <= 1)
00429 {
00430 if (vect_print_dump_info (REPORT_UNVECTORIZED_LOOPS,
00431 LOOP_LOC (loop_vinfo)))
00432 fprintf (vect_dump, "not vectorized: unsupported data-type");
00433 return false;
00434 }
00435 LOOP_VINFO_VECT_FACTOR (loop_vinfo) = vectorization_factor;
00436
00437 if (LOOP_VINFO_NITERS_KNOWN_P (loop_vinfo)
00438 && vect_print_dump_info (REPORT_DETAILS, UNKNOWN_LOC))
00439 fprintf (vect_dump,
00440 "vectorization_factor = %d, niters = " HOST_WIDE_INT_PRINT_DEC,
00441 vectorization_factor, LOOP_VINFO_INT_NITERS (loop_vinfo));
00442
00443 if (LOOP_VINFO_NITERS_KNOWN_P (loop_vinfo)
00444 && LOOP_VINFO_INT_NITERS (loop_vinfo) < vectorization_factor)
00445 {
00446 if (vect_print_dump_info (REPORT_UNVECTORIZED_LOOPS,
00447 LOOP_LOC (loop_vinfo)))
00448 fprintf (vect_dump, "not vectorized: iteration count too small.");
00449 return false;
00450 }
00451
00452 if (!LOOP_VINFO_NITERS_KNOWN_P (loop_vinfo)
00453 || LOOP_VINFO_INT_NITERS (loop_vinfo) % vectorization_factor != 0)
00454 {
00455 if (vect_print_dump_info (REPORT_DETAILS, LOOP_LOC (loop_vinfo)))
00456 fprintf (vect_dump, "epilog loop required.");
00457 if (!vect_can_advance_ivs_p (loop_vinfo))
00458 {
00459 if (vect_print_dump_info (REPORT_UNVECTORIZED_LOOPS,
00460 LOOP_LOC (loop_vinfo)))
00461 fprintf (vect_dump,
00462 "not vectorized: can't create epilog loop 1.");
00463 return false;
00464 }
00465 if (!slpeel_can_duplicate_loop_p (loop, loop->exit_edges[0]))
00466 {
00467 if (vect_print_dump_info (REPORT_UNVECTORIZED_LOOPS,
00468 LOOP_LOC (loop_vinfo)))
00469 fprintf (vect_dump,
00470 "not vectorized: can't create epilog loop 2.");
00471 return false;
00472 }
00473 }
00474
00475 return true;
00476 }
00477
00478
00479
00480
00481
00482
00483
00484 static bool
00485 exist_non_indexing_operands_for_use_p (tree use, tree stmt)
00486 {
00487 tree operand;
00488 stmt_vec_info stmt_info = vinfo_for_stmt (stmt);
00489
00490
00491
00492
00493 if (!STMT_VINFO_DATA_REF (stmt_info))
00494 return true;
00495
00496
00497
00498
00499
00500
00501
00502
00503
00504
00505
00506
00507
00508
00509 if (TREE_CODE (TREE_OPERAND (stmt, 0)) == SSA_NAME)
00510 return false;
00511
00512 operand = TREE_OPERAND (stmt, 1);
00513
00514 if (TREE_CODE (operand) != SSA_NAME)
00515 return false;
00516
00517 if (operand == use)
00518 return true;
00519
00520 return false;
00521 }
00522
00523
00524
00525
00526
00527
00528
00529
00530
00531
00532
00533
00534
00535
00536
00537
00538
00539
00540
00541
00542
00543
00544
00545
00546
00547
00548
00549
00550
00551
00552
00553
00554
00555
00556
00557
00558
00559
00560 static bool
00561 vect_analyze_scalar_cycles (loop_vec_info loop_vinfo)
00562 {
00563 tree phi;
00564 struct loop *loop = LOOP_VINFO_LOOP (loop_vinfo);
00565 basic_block bb = loop->header;
00566 tree dummy;
00567
00568 if (vect_print_dump_info (REPORT_DETAILS, UNKNOWN_LOC))
00569 fprintf (vect_dump, "=== vect_analyze_scalar_cycles ===");
00570
00571 for (phi = phi_nodes (bb); phi; phi = PHI_CHAIN (phi))
00572 {
00573 tree access_fn = NULL;
00574
00575 if (vect_print_dump_info (REPORT_DETAILS, UNKNOWN_LOC))
00576 {
00577 fprintf (vect_dump, "Analyze phi: ");
00578 print_generic_expr (vect_dump, phi, TDF_SLIM);
00579 }
00580
00581
00582
00583
00584 if (!is_gimple_reg (SSA_NAME_VAR (PHI_RESULT (phi))))
00585 {
00586 if (vect_print_dump_info (REPORT_DETAILS, UNKNOWN_LOC))
00587 fprintf (vect_dump, "virtual phi. skip.");
00588 continue;
00589 }
00590
00591
00592
00593
00594
00595
00596
00597
00598
00599
00600
00601
00602 access_fn =
00603
00604 analyze_scalar_evolution (loop, PHI_RESULT (phi));
00605
00606 if (!access_fn)
00607 {
00608 if (vect_print_dump_info (REPORT_UNVECTORIZED_LOOPS,
00609 LOOP_LOC (loop_vinfo)))
00610 fprintf (vect_dump, "not vectorized: unsupported scalar cycle.");
00611 return false;
00612 }
00613
00614 if (vect_print_dump_info (REPORT_DETAILS,
00615 LOOP_LOC (loop_vinfo)))
00616 {
00617 fprintf (vect_dump, "Access function of PHI: ");
00618 print_generic_expr (vect_dump, access_fn, TDF_SLIM);
00619 }
00620
00621 if (!vect_is_simple_iv_evolution (loop->num, access_fn, &dummy, &dummy))
00622 {
00623 if (vect_print_dump_info (REPORT_UNVECTORIZED_LOOPS,
00624 LOOP_LOC (loop_vinfo)))
00625 fprintf (vect_dump, "not vectorized: unsupported scalar cycle.");
00626 return false;
00627 }
00628 }
00629
00630 return true;
00631 }
00632
00633
00634
00635
00636
00637
00638
00639
00640
00641
00642
00643 static bool
00644 vect_base_addr_differ_p (struct data_reference *dra,
00645 struct data_reference *drb,
00646 bool *differ_p)
00647 {
00648 tree stmt_a = DR_STMT (dra);
00649 stmt_vec_info stmt_info_a = vinfo_for_stmt (stmt_a);
00650 tree stmt_b = DR_STMT (drb);
00651 stmt_vec_info stmt_info_b = vinfo_for_stmt (stmt_b);
00652 tree addr_a = STMT_VINFO_VECT_DR_BASE_ADDRESS (stmt_info_a);
00653 tree addr_b = STMT_VINFO_VECT_DR_BASE_ADDRESS (stmt_info_b);
00654 tree type_a = TREE_TYPE (addr_a);
00655 tree type_b = TREE_TYPE (addr_b);
00656 HOST_WIDE_INT alias_set_a, alias_set_b;
00657
00658 gcc_assert (POINTER_TYPE_P (type_a) && POINTER_TYPE_P (type_b));
00659
00660
00661 if (TREE_CODE (addr_a) == ADDR_EXPR && TREE_CODE (addr_b) == ADDR_EXPR)
00662 return array_base_name_differ_p (dra, drb, differ_p);
00663
00664 alias_set_a = (TREE_CODE (addr_a) == ADDR_EXPR) ?
00665 get_alias_set (TREE_OPERAND (addr_a, 0)) : get_alias_set (addr_a);
00666 alias_set_b = (TREE_CODE (addr_b) == ADDR_EXPR) ?
00667 get_alias_set (TREE_OPERAND (addr_b, 0)) : get_alias_set (addr_b);
00668
00669 if (!alias_sets_conflict_p (alias_set_a, alias_set_b))
00670 {
00671 *differ_p = true;
00672 return true;
00673 }
00674
00675
00676
00677
00678 else if ((TYPE_RESTRICT (type_a) && !DR_IS_READ (dra))
00679 || (TYPE_RESTRICT (type_b) && !DR_IS_READ (drb)))
00680 {
00681 *differ_p = true;
00682 return true;
00683 }
00684 return false;
00685 }
00686
00687
00688
00689
00690
00691
00692
00693 static bool
00694 vect_analyze_data_ref_dependence (struct data_reference *dra,
00695 struct data_reference *drb,
00696 loop_vec_info loop_vinfo)
00697 {
00698 bool differ_p;
00699 struct data_dependence_relation *ddr;
00700
00701 if (!vect_base_addr_differ_p (dra, drb, &differ_p))
00702 {
00703 if (vect_print_dump_info (REPORT_UNVECTORIZED_LOOPS,
00704 LOOP_LOC (loop_vinfo)))
00705 {
00706 fprintf (vect_dump,
00707 "not vectorized: can't determine dependence between: ");
00708 print_generic_expr (vect_dump, DR_REF (dra), TDF_SLIM);
00709 fprintf (vect_dump, " and ");
00710 print_generic_expr (vect_dump, DR_REF (drb), TDF_SLIM);
00711 }
00712 return true;
00713 }
00714
00715 if (differ_p)
00716 return false;
00717
00718 ddr = initialize_data_dependence_relation (dra, drb);
00719 compute_affine_dependence (ddr);
00720
00721 if (DDR_ARE_DEPENDENT (ddr) == chrec_known)
00722 return false;
00723
00724 if (vect_print_dump_info (REPORT_UNVECTORIZED_LOOPS,
00725 LOOP_LOC (loop_vinfo)))
00726 {
00727 fprintf (vect_dump,
00728 "not vectorized: possible dependence between data-refs ");
00729 print_generic_expr (vect_dump, DR_REF (dra), TDF_SLIM);
00730 fprintf (vect_dump, " and ");
00731 print_generic_expr (vect_dump, DR_REF (drb), TDF_SLIM);
00732 }
00733
00734 return true;
00735 }
00736
00737
00738
00739
00740
00741
00742
00743
00744
00745
00746 static bool
00747 vect_analyze_data_ref_dependences (loop_vec_info loop_vinfo)
00748 {
00749 unsigned int i, j;
00750 varray_type loop_write_refs = LOOP_VINFO_DATAREF_WRITES (loop_vinfo);
00751 varray_type loop_read_refs = LOOP_VINFO_DATAREF_READS (loop_vinfo);
00752
00753
00754
00755 if (vect_print_dump_info (REPORT_DETAILS, UNKNOWN_LOC))
00756 fprintf (vect_dump, "=== vect_analyze_dependences ===");
00757
00758 if (vect_print_dump_info (REPORT_DETAILS, UNKNOWN_LOC))
00759 fprintf (vect_dump, "compare all store-store pairs.");
00760
00761 for (i = 0; i < VARRAY_ACTIVE_SIZE (loop_write_refs); i++)
00762 {
00763 for (j = i + 1; j < VARRAY_ACTIVE_SIZE (loop_write_refs); j++)
00764 {
00765 struct data_reference *dra =
00766 VARRAY_GENERIC_PTR (loop_write_refs, i);
00767 struct data_reference *drb =
00768 VARRAY_GENERIC_PTR (loop_write_refs, j);
00769 if (vect_analyze_data_ref_dependence (dra, drb, loop_vinfo))
00770 return false;
00771 }
00772 }
00773
00774
00775
00776 if (vect_print_dump_info (REPORT_DETAILS, UNKNOWN_LOC))
00777 fprintf (vect_dump, "compare all load-store pairs.");
00778
00779 for (i = 0; i < VARRAY_ACTIVE_SIZE (loop_read_refs); i++)
00780 {
00781 for (j = 0; j < VARRAY_ACTIVE_SIZE (loop_write_refs); j++)
00782 {
00783 struct data_reference *dra = VARRAY_GENERIC_PTR (loop_read_refs, i);
00784 struct data_reference *drb =
00785 VARRAY_GENERIC_PTR (loop_write_refs, j);
00786 if (vect_analyze_data_ref_dependence (dra, drb, loop_vinfo))
00787 return false;
00788 }
00789 }
00790
00791 return true;
00792 }
00793
00794
00795
00796
00797
00798
00799
00800
00801
00802
00803
00804
00805
00806
00807 static bool
00808 vect_compute_data_ref_alignment (struct data_reference *dr)
00809 {
00810 tree stmt = DR_STMT (dr);
00811 stmt_vec_info stmt_info = vinfo_for_stmt (stmt);
00812 tree ref = DR_REF (dr);
00813 tree vectype;
00814 tree base, alignment;
00815 bool base_aligned_p;
00816 tree misalign;
00817
00818 if (vect_print_dump_info (REPORT_DETAILS, UNKNOWN_LOC))
00819 fprintf (vect_dump, "vect_compute_data_ref_alignment:");
00820
00821
00822 DR_MISALIGNMENT (dr) = -1;
00823
00824 misalign = STMT_VINFO_VECT_MISALIGNMENT (stmt_info);
00825 base_aligned_p = STMT_VINFO_VECT_BASE_ALIGNED_P (stmt_info);
00826 base = build_fold_indirect_ref (STMT_VINFO_VECT_DR_BASE_ADDRESS (stmt_info));
00827 vectype = STMT_VINFO_VECTYPE (stmt_info);
00828
00829 if (!misalign)
00830 {
00831 if (vect_print_dump_info (REPORT_DETAILS, UNKNOWN_LOC))
00832 {
00833 fprintf (vect_dump, "Unknown alignment for access: ");
00834 print_generic_expr (vect_dump, base, TDF_SLIM);
00835 }
00836 return true;
00837 }
00838
00839 if (!base_aligned_p)
00840 {
00841 if (!vect_can_force_dr_alignment_p (base, TYPE_ALIGN (vectype)))
00842 {
00843 if (vect_print_dump_info (REPORT_DETAILS, UNKNOWN_LOC))
00844 {
00845 fprintf (vect_dump, "can't force alignment of ref: ");
00846 print_generic_expr (vect_dump, ref, TDF_SLIM);
00847 }
00848 return true;
00849 }
00850
00851
00852
00853
00854 if (vect_print_dump_info (REPORT_DETAILS, UNKNOWN_LOC))
00855 fprintf (vect_dump, "force alignment");
00856 DECL_ALIGN (base) = TYPE_ALIGN (vectype);
00857 DECL_USER_ALIGN (base) = 1;
00858 }
00859
00860
00861 gcc_assert (base_aligned_p
00862 || (TREE_CODE (base) == VAR_DECL
00863 && DECL_ALIGN (base) >= TYPE_ALIGN (vectype)));
00864
00865
00866 alignment = ssize_int (TYPE_ALIGN (vectype)/BITS_PER_UNIT);
00867
00868
00869 misalign = size_binop (TRUNC_MOD_EXPR, misalign, alignment);
00870 if (tree_int_cst_sgn (misalign) < 0)
00871 {
00872
00873 if (vect_print_dump_info (REPORT_DETAILS, UNKNOWN_LOC))
00874 fprintf (vect_dump, "unexpected misalign value");
00875 return false;
00876 }
00877
00878 DR_MISALIGNMENT (dr) = tree_low_cst (misalign, 1);
00879
00880 if (vect_print_dump_info (REPORT_DETAILS, UNKNOWN_LOC))
00881 fprintf (vect_dump, "misalign = %d bytes", DR_MISALIGNMENT (dr));
00882
00883 return true;
00884 }
00885
00886
00887
00888
00889
00890
00891
00892
00893
00894
00895
00896 static bool
00897 vect_compute_data_refs_alignment (loop_vec_info loop_vinfo)
00898 {
00899 varray_type loop_write_datarefs = LOOP_VINFO_DATAREF_WRITES (loop_vinfo);
00900 varray_type loop_read_datarefs = LOOP_VINFO_DATAREF_READS (loop_vinfo);
00901 unsigned int i;
00902
00903 for (i = 0; i < VARRAY_ACTIVE_SIZE (loop_write_datarefs); i++)
00904 {
00905 struct data_reference *dr = VARRAY_GENERIC_PTR (loop_write_datarefs, i);
00906 if (!vect_compute_data_ref_alignment (dr))
00907 return false;
00908 }
00909
00910 for (i = 0; i < VARRAY_ACTIVE_SIZE (loop_read_datarefs); i++)
00911 {
00912 struct data_reference *dr = VARRAY_GENERIC_PTR (loop_read_datarefs, i);
00913 if (!vect_compute_data_ref_alignment (dr))
00914 return false;
00915 }
00916
00917 return true;
00918 }
00919
00920
00921
00922
00923
00924
00925
00926
00927
00928
00929
00930
00931 static void
00932 vect_enhance_data_refs_alignment (loop_vec_info loop_vinfo)
00933 {
00934 varray_type loop_read_datarefs = LOOP_VINFO_DATAREF_READS (loop_vinfo);
00935 varray_type loop_write_datarefs = LOOP_VINFO_DATAREF_WRITES (loop_vinfo);
00936 unsigned int i;
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
01006
01007
01008
01009
01010
01011
01012
01013
01014
01015
01016
01017
01018
01019
01020
01021
01022
01023
01024
01025
01026
01027
01028
01029
01030
01031
01032
01033
01034
01035
01036
01037 for (i = 0; i < VARRAY_ACTIVE_SIZE (loop_write_datarefs); i++)
01038 {
01039 struct data_reference *dr = VARRAY_GENERIC_PTR (loop_write_datarefs, i);
01040 if (!aligned_access_p (dr))
01041 {
01042 LOOP_VINFO_UNALIGNED_DR (loop_vinfo) = dr;
01043 LOOP_DO_PEELING_FOR_ALIGNMENT (loop_vinfo) = true;
01044 break;
01045 }
01046 }
01047
01048 if (!LOOP_VINFO_UNALIGNED_DR (loop_vinfo))
01049 {
01050 if (vect_print_dump_info (REPORT_DETAILS, LOOP_LOC (loop_vinfo)))
01051 fprintf (vect_dump, "Peeling for alignment will not be applied.");
01052 return;
01053 }
01054 else
01055 if (vect_print_dump_info (REPORT_DETAILS, LOOP_LOC (loop_vinfo)))
01056 fprintf (vect_dump, "Peeling for alignment will be applied.");
01057
01058
01059
01060
01061
01062
01063
01064
01065
01066
01067
01068
01069
01070
01071
01072
01073
01074 for (i = 0; i < VARRAY_ACTIVE_SIZE (loop_write_datarefs); i++)
01075 {
01076 struct data_reference *dr = VARRAY_GENERIC_PTR (loop_write_datarefs, i);
01077 if (dr == LOOP_VINFO_UNALIGNED_DR (loop_vinfo))
01078 {
01079 DR_MISALIGNMENT (dr) = 0;
01080 if (vect_print_dump_info (REPORT_ALIGNMENT, LOOP_LOC (loop_vinfo)))
01081 fprintf (vect_dump, "Alignment of access forced using peeling.");
01082 }
01083 else
01084 DR_MISALIGNMENT (dr) = -1;
01085 }
01086 for (i = 0; i < VARRAY_ACTIVE_SIZE (loop_read_datarefs); i++)
01087 {
01088 struct data_reference *dr = VARRAY_GENERIC_PTR (loop_read_datarefs, i);
01089 if (dr == LOOP_VINFO_UNALIGNED_DR (loop_vinfo))
01090 {
01091 DR_MISALIGNMENT (dr) = 0;
01092 if (vect_print_dump_info (REPORT_ALIGNMENT, LOOP_LOC (loop_vinfo)))
01093 fprintf (vect_dump, "Alignment of access forced using peeling.");
01094 }
01095 else
01096 DR_MISALIGNMENT (dr) = -1;
01097 }
01098 }
01099
01100
01101
01102
01103
01104
01105
01106
01107
01108 static bool
01109 vect_analyze_data_refs_alignment (loop_vec_info loop_vinfo)
01110 {
01111 varray_type loop_read_datarefs = LOOP_VINFO_DATAREF_READS (loop_vinfo);
01112 varray_type loop_write_datarefs = LOOP_VINFO_DATAREF_WRITES (loop_vinfo);
01113 enum dr_alignment_support supportable_dr_alignment;
01114 unsigned int i;
01115
01116 if (vect_print_dump_info (REPORT_DETAILS, UNKNOWN_LOC))
01117 fprintf (vect_dump, "=== vect_analyze_data_refs_alignment ===");
01118
01119
01120
01121
01122
01123 if (!vect_compute_data_refs_alignment (loop_vinfo))
01124 {
01125 if (vect_print_dump_info (REPORT_UNVECTORIZED_LOOPS,
01126 LOOP_LOC (loop_vinfo)))
01127 fprintf (vect_dump,
01128 "not vectorized: can't calculate alignment for data ref.");
01129 return false;
01130 }
01131
01132
01133
01134
01135
01136 vect_enhance_data_refs_alignment (loop_vinfo);
01137
01138
01139
01140
01141
01142 for (i = 0; i < VARRAY_ACTIVE_SIZE (loop_read_datarefs); i++)
01143 {
01144 struct data_reference *dr = VARRAY_GENERIC_PTR (loop_read_datarefs, i);
01145 supportable_dr_alignment = vect_supportable_dr_alignment (dr);
01146 if (!supportable_dr_alignment)
01147 {
01148 if (vect_print_dump_info (REPORT_UNVECTORIZED_LOOPS,
01149 LOOP_LOC (loop_vinfo)))
01150 fprintf (vect_dump, "not vectorized: unsupported unaligned load.");
01151 return false;
01152 }
01153 if (supportable_dr_alignment != dr_aligned
01154 && (vect_print_dump_info (REPORT_ALIGNMENT, LOOP_LOC (loop_vinfo))))
01155 fprintf (vect_dump, "Vectorizing an unaligned access.");
01156 }
01157 for (i = 0; i < VARRAY_ACTIVE_SIZE (loop_write_datarefs); i++)
01158 {
01159 struct data_reference *dr = VARRAY_GENERIC_PTR (loop_write_datarefs, i);
01160 supportable_dr_alignment = vect_supportable_dr_alignment (dr);
01161 if (!supportable_dr_alignment)
01162 {
01163 if (vect_print_dump_info (REPORT_UNVECTORIZED_LOOPS,
01164 LOOP_LOC (loop_vinfo)))
01165 fprintf (vect_dump, "not vectorized: unsupported unaligned store.");
01166 return false;
01167 }
01168 if (supportable_dr_alignment != dr_aligned
01169 && (vect_print_dump_info (REPORT_ALIGNMENT, LOOP_LOC (loop_vinfo))))
01170 fprintf (vect_dump, "Vectorizing an unaligned access.");
01171 }
01172
01173 return true;
01174 }
01175
01176
01177
01178
01179
01180
01181
01182 static bool
01183 vect_analyze_data_ref_access (struct data_reference *dr)
01184 {
01185 tree stmt = DR_STMT (dr);
01186 stmt_vec_info stmt_info = vinfo_for_stmt (stmt);
01187 tree step = STMT_VINFO_VECT_STEP (stmt_info);
01188 tree scalar_type = TREE_TYPE (DR_REF (dr));
01189
01190 if (!step || tree_int_cst_compare (step, TYPE_SIZE_UNIT (scalar_type)))
01191 {
01192 if (vect_print_dump_info (REPORT_DETAILS, UNKNOWN_LOC))
01193 fprintf (vect_dump, "not consecutive access");
01194 return false;
01195 }
01196 return true;
01197 }
01198
01199
01200
01201
01202
01203
01204
01205
01206
01207
01208
01209 static bool
01210 vect_analyze_data_ref_accesses (loop_vec_info loop_vinfo)
01211 {
01212 unsigned int i;
01213 varray_type loop_write_datarefs = LOOP_VINFO_DATAREF_WRITES (loop_vinfo);
01214 varray_type loop_read_datarefs = LOOP_VINFO_DATAREF_READS (loop_vinfo);
01215
01216 if (vect_print_dump_info (REPORT_DETAILS, UNKNOWN_LOC))
01217 fprintf (vect_dump, "=== vect_analyze_data_ref_accesses ===");
01218
01219 for (i = 0; i < VARRAY_ACTIVE_SIZE (loop_write_datarefs); i++)
01220 {
01221 struct data_reference *dr = VARRAY_GENERIC_PTR (loop_write_datarefs, i);
01222 bool ok = vect_analyze_data_ref_access (dr);
01223 if (!ok)
01224 {
01225 if (vect_print_dump_info (REPORT_UNVECTORIZED_LOOPS,
01226 LOOP_LOC (loop_vinfo)))
01227 fprintf (vect_dump, "not vectorized: complicated access pattern.");
01228 return false;
01229 }
01230 }
01231
01232 for (i = 0; i < VARRAY_ACTIVE_SIZE (loop_read_datarefs); i++)
01233 {
01234 struct data_reference *dr = VARRAY_GENERIC_PTR (loop_read_datarefs, i);
01235 bool ok = vect_analyze_data_ref_access (dr);
01236 if (!ok)
01237 {
01238 if (vect_print_dump_info (REPORT_UNVECTORIZED_LOOPS,
01239 LOOP_LOC (loop_vinfo)))
01240 fprintf (vect_dump, "not vectorized: complicated access pattern.");
01241 return false;
01242 }
01243 }
01244
01245 return true;
01246 }
01247
01248
01249
01250
01251
01252
01253
01254
01255
01256
01257
01258
01259
01260
01261
01262
01263 static struct data_reference *
01264 vect_analyze_pointer_ref_access (tree memref, tree stmt, bool is_read,
01265 tree access_fn, tree *ptr_init, tree *ptr_step)
01266 {
01267 stmt_vec_info stmt_info = vinfo_for_stmt (stmt);
01268 loop_vec_info loop_vinfo = STMT_VINFO_LOOP_VINFO (stmt_info);
01269 struct loop *loop = LOOP_VINFO_LOOP (loop_vinfo);
01270 tree step, init;
01271 tree reftype, innertype;
01272 tree indx_access_fn;
01273 int loopnum = loop->num;
01274 struct data_reference *dr;
01275
01276 if (!vect_is_simple_iv_evolution (loopnum, access_fn, &init, &step))
01277 {
01278 if (vect_print_dump_info (REPORT_UNVECTORIZED_LOOPS,
01279 LOOP_LOC (loop_vinfo)))
01280 fprintf (vect_dump, "not vectorized: pointer access is not simple.");
01281 return NULL;
01282 }
01283
01284 STRIP_NOPS (init);
01285
01286 if (!expr_invariant_in_loop_p (loop, init))
01287 {
01288 if (vect_print_dump_info (REPORT_UNVECTORIZED_LOOPS,
01289 LOOP_LOC (loop_vinfo)))
01290 fprintf (vect_dump,
01291 "not vectorized: initial condition is not loop invariant.");
01292 return NULL;
01293 }
01294
01295 if (TREE_CODE (step) != INTEGER_CST)
01296 {
01297 if (vect_print_dump_info (REPORT_UNVECTORIZED_LOOPS,
01298 LOOP_LOC (loop_vinfo)))
01299 fprintf (vect_dump,
01300 "not vectorized: non constant step for pointer access.");
01301 return NULL;
01302 }
01303
01304 reftype = TREE_TYPE (TREE_OPERAND (memref, 0));
01305 if (!POINTER_TYPE_P (reftype))
01306 {
01307 if (vect_print_dump_info (REPORT_UNVECTORIZED_LOOPS,
01308 LOOP_LOC (loop_vinfo)))
01309 fprintf (vect_dump, "not vectorized: unexpected pointer access form.");
01310 return NULL;
01311 }
01312
01313 if (!POINTER_TYPE_P (TREE_TYPE (init)))
01314 {
01315 if (vect_print_dump_info (REPORT_UNVECTORIZED_LOOPS,
01316 LOOP_LOC (loop_vinfo)))
01317 fprintf (vect_dump, "not vectorized: unexpected pointer access form.");
01318 return NULL;
01319 }
01320
01321 *ptr_step = fold_convert (ssizetype, step);
01322 innertype = TREE_TYPE (reftype);
01323
01324 if (!COMPLETE_TYPE_P (innertype))
01325 {
01326 if (vect_print_dump_info (REPORT_UNVECTORIZED_LOOPS,
01327 LOOP_LOC (loop_vinfo)))
01328 fprintf (vect_dump, "not vectorized: pointer to incomplete type.");
01329 return NULL;
01330 }
01331
01332 if (!integer_zerop (size_binop (TRUNC_MOD_EXPR, *ptr_step,
01333 fold_convert (ssizetype, TYPE_SIZE_UNIT (innertype)))))
01334 {
01335 if (vect_print_dump_info (REPORT_UNVECTORIZED_LOOPS,
01336 LOOP_LOC (loop_vinfo)))
01337 fprintf (vect_dump, "not vectorized: non consecutive access.");
01338 return NULL;
01339 }
01340
01341 indx_access_fn =
01342 build_polynomial_chrec (loopnum, integer_zero_node, integer_one_node);
01343 if (vect_print_dump_info (REPORT_DETAILS, UNKNOWN_LOC))
01344 {
01345 fprintf (vect_dump, "Access function of ptr indx: ");
01346 print_generic_expr (vect_dump, indx_access_fn, TDF_SLIM);
01347 }
01348 dr = init_data_ref (stmt, memref, NULL_TREE, indx_access_fn, is_read);
01349 *ptr_init = init;
01350 return dr;
01351 }
01352
01353
01354
01355
01356
01357
01358
01359
01360
01361
01362
01363
01364
01365
01366
01367
01368
01369
01370
01371
01372
01373
01374
01375
01376
01377
01378
01379 static tree
01380 vect_address_analysis (tree expr, tree stmt, bool is_read, tree vectype,
01381 struct data_reference *dr, tree *offset, tree *misalign,
01382 tree *step, bool *base_aligned)
01383 {
01384 tree oprnd0, oprnd1, base_address, offset_expr, base_addr0, base_addr1;
01385 tree address_offset = ssize_int (0), address_misalign = ssize_int (0);
01386 tree dummy;
01387
01388 switch (TREE_CODE (expr))
01389 {
01390 case PLUS_EXPR:
01391 case MINUS_EXPR:
01392
01393 oprnd0 = TREE_OPERAND (expr, 0);
01394 oprnd1 = TREE_OPERAND (expr, 1);
01395
01396 STRIP_NOPS (oprnd0);
01397 STRIP_NOPS (oprnd1);
01398
01399
01400
01401 base_addr0 = vect_address_analysis (oprnd0, stmt, is_read, vectype, dr,
01402 &address_offset, &address_misalign, step,
01403 base_aligned);
01404
01405 base_addr1 = vect_address_analysis (oprnd1, stmt, is_read, vectype, dr,
01406 &address_offset, &address_misalign, step,
01407 base_aligned);
01408
01409
01410
01411 if ((base_addr0 && base_addr1) || (!base_addr0 && !base_addr1))
01412 return NULL_TREE;
01413
01414
01415 oprnd0 = TREE_OPERAND (expr, 0);
01416 oprnd1 = TREE_OPERAND (expr, 1);
01417
01418 offset_expr = base_addr0 ?
01419 fold_convert (ssizetype, oprnd1) : fold_convert (ssizetype, oprnd0);
01420
01421
01422
01423
01424 if (TREE_CODE (offset_expr) == INTEGER_CST && address_misalign)
01425 *misalign = size_binop (TREE_CODE (expr), address_misalign,
01426 offset_expr);
01427 else
01428 *misalign = NULL_TREE;
01429
01430
01431
01432 *offset = size_binop (TREE_CODE (expr), address_offset, offset_expr);
01433 return base_addr0 ? base_addr0 : base_addr1;
01434
01435 case ADDR_EXPR:
01436 base_address = vect_object_analysis (TREE_OPERAND (expr, 0), stmt, is_read,
01437 vectype, &dr, offset, misalign, step,
01438 base_aligned, &dummy);
01439 return base_address;
01440
01441 case SSA_NAME:
01442 if (!POINTER_TYPE_P (TREE_TYPE (expr)))
01443 return NULL_TREE;
01444
01445 if (TYPE_ALIGN (TREE_TYPE (TREE_TYPE (expr))) < TYPE_ALIGN (vectype))
01446 {
01447 if (vect_get_ptr_offset (expr, vectype, misalign))
01448 *base_aligned = true;
01449 else
01450 *base_aligned = false;
01451 }
01452 else
01453 {
01454 *base_aligned = true;
01455 *misalign = ssize_int (0);
01456 }
01457 *offset = ssize_int (0);
01458 *step = ssize_int (0);
01459 return expr;
01460
01461 default:
01462 return NULL_TREE;
01463 }
01464 }
01465
01466
01467
01468
01469
01470
01471
01472
01473
01474
01475
01476
01477
01478
01479
01480
01481
01482
01483
01484
01485
01486
01487
01488
01489
01490
01491
01492
01493
01494
01495
01496
01497
01498
01499
01500
01501
01502
01503
01504
01505
01506
01507
01508
01509
01510
01511
01512
01513
01514
01515
01516
01517
01518
01519
01520
01521 static tree
01522 vect_object_analysis (tree memref, tree stmt, bool is_read,
01523 tree vectype, struct data_reference **dr,
01524 tree *offset, tree *misalign, tree *step,
01525 bool *base_aligned, tree *memtag)
01526 {
01527 tree base = NULL_TREE, base_address = NULL_TREE;
01528 tree object_offset = ssize_int (0), object_misalign = ssize_int (0);
01529 tree object_step = ssize_int (0), address_step = ssize_int (0);
01530 bool object_base_aligned = true, address_base_aligned = true;
01531 tree address_offset = ssize_int (0), address_misalign = ssize_int (0);
01532 HOST_WIDE_INT pbitsize, pbitpos;
01533 tree poffset, bit_pos_in_bytes;
01534 enum machine_mode pmode;
01535 int punsignedp, pvolatilep;
01536 tree ptr_step = ssize_int (0), ptr_init = NULL_TREE;
01537 stmt_vec_info stmt_info = vinfo_for_stmt (stmt);
01538 loop_vec_info loop_vinfo = STMT_VINFO_LOOP_VINFO (stmt_info);
01539 struct loop *loop = LOOP_VINFO_LOOP (loop_vinfo);
01540 struct data_reference *ptr_dr = NULL;
01541 tree access_fn, evolution_part, address_to_analyze;
01542
01543
01544
01545 if (handled_component_p (memref))
01546 {
01547
01548
01549 base = get_inner_reference (memref, &pbitsize, &pbitpos, &poffset,
01550 &pmode, &punsignedp, &pvolatilep, false);
01551 if (!base)
01552 return NULL_TREE;
01553
01554
01555 if (poffset
01556 && !vect_analyze_offset_expr (poffset, loop, TYPE_SIZE_UNIT (vectype),
01557 &object_offset, &object_misalign, &object_step))
01558 {
01559 if (vect_print_dump_info (REPORT_DETAILS, UNKNOWN_LOC))
01560 {
01561 fprintf (vect_dump, "failed to compute offset or step for ");
01562 print_generic_expr (vect_dump, memref, TDF_SLIM);
01563 }
01564 return NULL_TREE;
01565 }
01566
01567
01568
01569 bit_pos_in_bytes = ssize_int (pbitpos/BITS_PER_UNIT);
01570
01571 if (pbitpos%BITS_PER_UNIT)
01572 {
01573 if (vect_print_dump_info (REPORT_DETAILS, UNKNOWN_LOC))
01574 fprintf (vect_dump, "bit offset alignment.");
01575 return NULL_TREE;
01576 }
01577 object_offset = size_binop (PLUS_EXPR, bit_pos_in_bytes, object_offset);
01578 if (object_misalign)
01579 object_misalign = size_binop (PLUS_EXPR, object_misalign,
01580 bit_pos_in_bytes);
01581
01582
01583 if (!(*dr))
01584 {
01585 if (TREE_CODE (memref) == ARRAY_REF)
01586 *dr = analyze_array (stmt, memref, is_read);
01587 else
01588
01589 return NULL_TREE;
01590 }
01591 memref = base;
01592
01593 }
01594
01595
01596 if (DECL_P (memref))
01597 {
01598
01599 if (!(*dr))
01600 {
01601 if (vect_print_dump_info (REPORT_DETAILS, UNKNOWN_LOC))
01602 {
01603 fprintf (vect_dump, "unhandled decl ");
01604 print_generic_expr (vect_dump, memref, TDF_SLIM);
01605 }
01606 return NULL_TREE;
01607 }
01608
01609
01610 if (DECL_ALIGN (memref) >= TYPE_ALIGN (vectype))
01611 object_base_aligned = true;
01612 else
01613 object_base_aligned = false;
01614
01615
01616 if (!DR_BASE_NAME ((*dr)))
01617
01618
01619 DR_BASE_NAME ((*dr)) = memref;
01620
01621 base_address = build_fold_addr_expr (memref);
01622 *memtag = memref;
01623 }
01624
01625
01626 else if (TREE_CODE (memref) == INDIRECT_REF)
01627 {
01628
01629 access_fn = analyze_scalar_evolution (loop, TREE_OPERAND (memref, 0));
01630 if (!access_fn)
01631 {
01632 if (vect_print_dump_info (REPORT_UNVECTORIZED_LOOPS,
01633 LOOP_LOC (loop_vinfo)))
01634 fprintf (vect_dump, "not vectorized: complicated pointer access.");
01635 return NULL_TREE;
01636 }
01637 if (vect_print_dump_info (REPORT_DETAILS, UNKNOWN_LOC))
01638 {
01639 fprintf (vect_dump, "Access function of ptr: ");
01640 print_generic_expr (vect_dump, access_fn, TDF_SLIM);
01641 }
01642
01643
01644 evolution_part = evolution_part_in_loop_num (access_fn, loop->num);
01645 if (evolution_part)
01646 {
01647 ptr_dr = vect_analyze_pointer_ref_access (memref, stmt, is_read,
01648 access_fn, &ptr_init, &ptr_step);
01649 if (!(ptr_dr))
01650 return NULL_TREE;
01651
01652 object_step = size_binop (PLUS_EXPR, object_step, ptr_step);
01653 address_to_analyze = ptr_init;
01654 }
01655 else
01656 {
01657 if (!(*dr))
01658 {
01659 if (vect_print_dump_info (REPORT_UNVECTORIZED_LOOPS,
01660 LOOP_LOC (loop_vinfo)))
01661 fprintf (vect_dump, "not vectorized: ptr is loop invariant.");
01662 return NULL_TREE;
01663 }
01664
01665
01666
01667 address_to_analyze = initial_condition_in_loop_num (access_fn,
01668 loop->num);
01669 }
01670
01671
01672 *dr = (*dr) ? *dr : ptr_dr;
01673
01674
01675
01676 base_address = vect_address_analysis (address_to_analyze, stmt, is_read,
01677 vectype, *dr, &address_offset, &address_misalign,
01678 &address_step, &address_base_aligned);
01679 if (!base_address)
01680 return NULL_TREE;
01681
01682 switch (TREE_CODE (base_address))
01683 {
01684 case SSA_NAME:
01685 *memtag = get_var_ann (SSA_NAME_VAR (base_address))->type_mem_tag;
01686 if (!(*memtag) && TREE_CODE (TREE_OPERAND (memref, 0)) == SSA_NAME)
01687 *memtag = get_var_ann (
01688 SSA_NAME_VAR (TREE_OPERAND (memref, 0)))->type_mem_tag;
01689 break;
01690 case ADDR_EXPR:
01691 *memtag = TREE_OPERAND (base_address, 0);
01692 break;
01693 default:
01694 if (vect_print_dump_info (REPORT_UNVECTORIZED_LOOPS,
01695 LOOP_LOC (loop_vinfo)))
01696 {
01697 fprintf (vect_dump, "not vectorized: no memtag ref: ");
01698 print_generic_expr (vect_dump, memref, TDF_SLIM);
01699 }
01700 return NULL_TREE;
01701 }
01702 }
01703
01704 if (!base_address)
01705
01706 return NULL_TREE;
01707
01708
01709
01710 *offset = size_binop (PLUS_EXPR, object_offset, address_offset);
01711 if (object_misalign && address_misalign)
01712 *misalign = size_binop (PLUS_EXPR, object_misalign, address_misalign);
01713 else
01714 *misalign = NULL_TREE;
01715 *step = size_binop (PLUS_EXPR, object_step, address_step);
01716 *base_aligned = object_base_aligned && address_base_aligned;
01717
01718 if (vect_print_dump_info (REPORT_DETAILS, UNKNOWN_LOC))
01719 {
01720 fprintf (vect_dump, "Results of object analysis for: ");
01721 print_generic_expr (vect_dump, memref, TDF_SLIM);
01722 fprintf (vect_dump, "\n\tbase_address: ");
01723 print_generic_expr (vect_dump, base_address, TDF_SLIM);
01724 fprintf (vect_dump, "\n\toffset: ");
01725 print_generic_expr (vect_dump, *offset, TDF_SLIM);
01726 fprintf (vect_dump, "\n\tstep: ");
01727 print_generic_expr (vect_dump, *step, TDF_SLIM);
01728 fprintf (vect_dump, "\n\tbase aligned %d\n\tmisalign: ", *base_aligned);
01729 print_generic_expr (vect_dump, *misalign, TDF_SLIM);
01730 }
01731 return base_address;
01732 }
01733
01734
01735
01736
01737
01738
01739
01740
01741
01742
01743
01744
01745
01746
01747
01748
01749
01750
01751
01752
01753
01754
01755
01756
01757
01758
01759
01760 static bool
01761 vect_analyze_data_refs (loop_vec_info loop_vinfo)
01762 {
01763 struct loop *loop = LOOP_VINFO_LOOP (loop_vinfo);
01764 basic_block *bbs = LOOP_VINFO_BBS (loop_vinfo);
01765 int nbbs = loop->num_nodes;
01766 block_stmt_iterator si;
01767 int j;
01768 struct data_reference *dr;
01769
01770 if (vect_print_dump_info (REPORT_DETAILS, UNKNOWN_LOC))
01771 fprintf (vect_dump, "=== vect_analyze_data_refs ===");
01772
01773 for (j = 0; j < nbbs; j++)
01774 {
01775 basic_block bb = bbs[j];
01776 for (si = bsi_start (bb); !bsi_end_p (si); bsi_next (&si))
01777 {
01778 bool is_read = false;
01779 tree stmt = bsi_stmt (si);
01780 stmt_vec_info stmt_info = vinfo_for_stmt (stmt);
01781 v_may_def_optype v_may_defs = STMT_V_MAY_DEF_OPS (stmt);
01782 v_must_def_optype v_must_defs = STMT_V_MUST_DEF_OPS (stmt);
01783 vuse_optype vuses = STMT_VUSE_OPS (stmt);
01784 varray_type *datarefs = NULL;
01785 int nvuses, nv_may_defs, nv_must_defs;
01786 tree memref = NULL;
01787 tree scalar_type, vectype;
01788 tree base, offset, misalign, step, tag;
01789 bool base_aligned;
01790
01791
01792
01793
01794 if (!vuses && !v_may_defs && !v_must_defs)
01795 continue;
01796
01797 nvuses = NUM_VUSES (vuses);
01798 nv_may_defs = NUM_V_MAY_DEFS (v_may_defs);
01799 nv_must_defs = NUM_V_MUST_DEFS (v_must_defs);
01800
01801 if (nvuses && (nv_may_defs || nv_must_defs))
01802 {
01803 if (vect_print_dump_info (REPORT_DETAILS, UNKNOWN_LOC))
01804 {
01805 fprintf (vect_dump, "unexpected vdefs and vuses in stmt: ");
01806 print_generic_expr (vect_dump, stmt, TDF_SLIM);
01807 }
01808 return false;
01809 }
01810
01811 if (TREE_CODE (stmt) != MODIFY_EXPR)
01812 {
01813 if (vect_print_dump_info (REPORT_DETAILS, UNKNOWN_LOC))
01814 {
01815 fprintf (vect_dump, "unexpected vops in stmt: ");
01816 print_generic_expr (vect_dump, stmt, TDF_SLIM);
01817 }
01818 return false;
01819 }
01820
01821 if (vuses)
01822 {
01823 memref = TREE_OPERAND (stmt, 1);
01824 datarefs = &(LOOP_VINFO_DATAREF_READS (loop_vinfo));
01825 is_read = true;
01826 }
01827 else
01828 {
01829 memref = TREE_OPERAND (stmt, 0);
01830 datarefs = &(LOOP_VINFO_DATAREF_WRITES (loop_vinfo));
01831 is_read = false;
01832 }
01833
01834 scalar_type = TREE_TYPE (memref);
01835 vectype = get_vectype_for_scalar_type (scalar_type);
01836 if (!vectype)
01837 {
01838 if (vect_print_dump_info (REPORT_DETAILS, UNKNOWN_LOC))
01839 {
01840 fprintf (vect_dump, "no vectype for stmt: ");
01841 print_generic_expr (vect_dump, stmt, TDF_SLIM);
01842 fprintf (vect_dump, " scalar_type: ");
01843 print_generic_expr (vect_dump, scalar_type, TDF_DETAILS);
01844 }
01845
01846 return false;
01847 }
01848
01849
01850 dr = NULL;
01851 base = vect_object_analysis (memref, stmt, is_read, vectype, &dr,
01852 &offset, &misalign, &step,
01853 &base_aligned, &tag);
01854 if (!base)
01855 {
01856 if (vect_print_dump_info (REPORT_UNVECTORIZED_LOOPS,
01857 LOOP_LOC (loop_vinfo)))
01858 {
01859 fprintf (vect_dump, "not vectorized: unhandled data ref: ");
01860 print_generic_expr (vect_dump, stmt, TDF_SLIM);
01861 }
01862 return false;
01863 }
01864 STMT_VINFO_VECT_DR_BASE_ADDRESS (stmt_info) = base;
01865 STMT_VINFO_VECT_INIT_OFFSET (stmt_info) = offset;
01866 STMT_VINFO_VECT_STEP (stmt_info) = step;
01867 STMT_VINFO_VECT_MISALIGNMENT (stmt_info) = misalign;
01868 STMT_VINFO_VECT_BASE_ALIGNED_P (stmt_info) = base_aligned;
01869 STMT_VINFO_MEMTAG (stmt_info) = tag;
01870 STMT_VINFO_VECTYPE (stmt_info) = vectype;
01871 VARRAY_PUSH_GENERIC_PTR (*datarefs, dr);
01872 STMT_VINFO_DATA_REF (stmt_info) = dr;
01873 }
01874 }
01875
01876 return true;
01877 }
01878
01879
01880
01881
01882
01883
01884
01885
01886 static void
01887 vect_mark_relevant (varray_type *worklist, tree stmt)
01888 {
01889 stmt_vec_info stmt_info;
01890
01891 if (vect_print_dump_info (REPORT_DETAILS, UNKNOWN_LOC))
01892 fprintf (vect_dump, "mark relevant.");
01893
01894 if (TREE_CODE (stmt) == PHI_NODE)
01895 {
01896 VARRAY_PUSH_TREE (*worklist, stmt);
01897 return;
01898 }
01899
01900 stmt_info = vinfo_for_stmt (stmt);
01901
01902 if (!stmt_info)
01903 {
01904 if (vect_print_dump_info (REPORT_DETAILS, UNKNOWN_LOC))
01905 {
01906 fprintf (vect_dump, "mark relevant: no stmt info!!.");
01907 print_generic_expr (vect_dump, stmt, TDF_SLIM);
01908 }
01909 return;
01910 }
01911
01912 if (STMT_VINFO_RELEVANT_P (stmt_info))
01913 {
01914 if (vect_print_dump_info (REPORT_DETAILS, UNKNOWN_LOC))
01915 fprintf (vect_dump, "already marked relevant.");
01916 return;
01917 }
01918
01919 STMT_VINFO_RELEVANT_P (stmt_info) = 1;
01920 VARRAY_PUSH_TREE (*worklist, stmt);
01921 }
01922
01923
01924
01925
01926
01927
01928
01929
01930
01931
01932
01933
01934
01935
01936 static bool
01937 vect_stmt_relevant_p (tree stmt, loop_vec_info loop_vinfo)
01938 {
01939 v_may_def_optype v_may_defs;
01940 v_must_def_optype v_must_defs;
01941 struct loop *loop = LOOP_VINFO_LOOP (loop_vinfo);
01942 int i;
01943 dataflow_t df;
01944 int num_uses;
01945
01946
01947 if (is_ctrl_stmt (stmt) && (stmt != LOOP_VINFO_EXIT_COND (loop_vinfo)))
01948 return true;
01949
01950
01951 if (TREE_CODE (stmt) != PHI_NODE)
01952 {
01953 v_may_defs = STMT_V_MAY_DEF_OPS (stmt);
01954 v_must_defs = STMT_V_MUST_DEF_OPS (stmt);
01955 if (v_may_defs || v_must_defs)
01956 {
01957 if (vect_print_dump_info (REPORT_DETAILS, UNKNOWN_LOC))
01958 fprintf (vect_dump, "vec_stmt_relevant_p: stmt has vdefs.");
01959 return true;
01960 }
01961 }
01962
01963
01964 df = get_immediate_uses (stmt);
01965 num_uses = num_immediate_uses (df);
01966 for (i = 0; i < num_uses; i++)
01967 {
01968 tree use = immediate_use (df, i);
01969 basic_block bb = bb_for_stmt (use);
01970 if (!flow_bb_inside_loop_p (loop, bb))
01971 {
01972 if (vect_print_dump_info (REPORT_DETAILS, UNKNOWN_LOC))
01973 fprintf (vect_dump, "vec_stmt_relevant_p: used out of loop.");
01974 return true;
01975 }
01976 }
01977
01978 return false;
01979 }
01980
01981
01982
01983
01984
01985
01986
01987
01988
01989
01990
01991
01992
01993
01994
01995
01996
01997
01998 static bool
01999 vect_mark_stmts_to_be_vectorized (loop_vec_info loop_vinfo)
02000 {
02001 varray_type worklist;
02002 struct loop *loop = LOOP_VINFO_LOOP (loop_vinfo);
02003 basic_block *bbs = LOOP_VINFO_BBS (loop_vinfo);
02004 unsigned int nbbs = loop->num_nodes;
02005 block_stmt_iterator si;
02006 tree stmt;
02007 stmt_ann_t ann;
02008 unsigned int i;
02009 int j;
02010 use_optype use_ops;
02011 stmt_vec_info stmt_info;
02012 basic_block bb;
02013 tree phi;
02014
02015 if (vect_print_dump_info (REPORT_DETAILS, UNKNOWN_LOC))
02016 fprintf (vect_dump, "=== vect_mark_stmts_to_be_vectorized ===");
02017
02018 bb = loop->header;
02019 for (phi = phi_nodes (bb); phi; phi = PHI_CHAIN (phi))
02020 {
02021 if (vect_print_dump_info (REPORT_DETAILS, UNKNOWN_LOC))
02022 {
02023 fprintf (vect_dump, "init: phi relevant? ");
02024 print_generic_expr (vect_dump, phi, TDF_SLIM);
02025 }
02026
02027 if (vect_stmt_relevant_p (phi, loop_vinfo))
02028 {
02029 if (vect_print_dump_info (REPORT_UNVECTORIZED_LOOPS,
02030 LOOP_LOC (loop_vinfo)))
02031 fprintf (vect_dump, "unsupported reduction/induction.");
02032 return false;
02033 }
02034 }
02035
02036 VARRAY_TREE_INIT (worklist, 64, "work list");
02037
02038
02039
02040 for (i = 0; i < nbbs; i++)
02041 {
02042 bb = bbs[i];
02043 for (si = bsi_start (bb); !bsi_end_p (si); bsi_next (&si))
02044 {
02045 stmt = bsi_stmt (si);
02046
02047 if (vect_print_dump_info (REPORT_DETAILS, UNKNOWN_LOC))
02048 {
02049 fprintf (vect_dump, "init: stmt relevant? ");
02050 print_generic_expr (vect_dump, stmt, TDF_SLIM);
02051 }
02052
02053 stmt_info = vinfo_for_stmt (stmt);
02054 STMT_VINFO_RELEVANT_P (stmt_info) = 0;
02055
02056 if (vect_stmt_relevant_p (stmt, loop_vinfo))
02057 vect_mark_relevant (&worklist, stmt);
02058 }
02059 }
02060
02061
02062
02063
02064 while (VARRAY_ACTIVE_SIZE (worklist) > 0)
02065 {
02066 stmt = VARRAY_TOP_TREE (worklist);
02067 VARRAY_POP (worklist);
02068
02069 if (vect_print_dump_info (REPORT_DETAILS, UNKNOWN_LOC))
02070 {
02071 fprintf (vect_dump, "worklist: examine stmt: ");
02072 print_generic_expr (vect_dump, stmt, TDF_SLIM);
02073 }
02074
02075
02076
02077
02078
02079 if (TREE_CODE (stmt) == PHI_NODE)
02080 {
02081
02082 for (j = 0; j < PHI_NUM_ARGS (stmt); j++)
02083 {
02084 tree arg = PHI_ARG_DEF (stmt, j);
02085 tree def_stmt = NULL_TREE;
02086 basic_block bb;
02087 if (!vect_is_simple_use (arg, loop_vinfo, &def_stmt))
02088 {
02089 if (vect_print_dump_info (REPORT_UNVECTORIZED_LOOPS,
02090 LOOP_LOC (loop_vinfo)))
02091 fprintf (vect_dump, "not vectorized: unsupported use in stmt.");
02092 varray_clear (worklist);
02093 return false;
02094 }
02095 if (!def_stmt)
02096 continue;
02097
02098 if (vect_print_dump_info (REPORT_DETAILS, UNKNOWN_LOC))
02099 {
02100 fprintf (vect_dump, "worklist: def_stmt: ");
02101 print_generic_expr (vect_dump, def_stmt, TDF_SLIM);
02102 }
02103
02104 bb = bb_for_stmt (def_stmt);
02105 if (flow_bb_inside_loop_p (loop, bb))
02106 vect_mark_relevant (&worklist, def_stmt);
02107 }
02108 }
02109
02110 ann = stmt_ann (stmt);
02111 use_ops = USE_OPS (ann);
02112
02113 for (i = 0; i < NUM_USES (use_ops); i++)
02114 {
02115 tree use = USE_OP (use_ops, i);
02116
02117
02118
02119
02120 if (exist_non_indexing_operands_for_use_p (use, stmt))
02121 {
02122 tree def_stmt = NULL_TREE;
02123 basic_block bb;
02124 if (!vect_is_simple_use (use, loop_vinfo, &def_stmt))
02125 {
02126 if (vect_print_dump_info (REPORT_UNVECTORIZED_LOOPS,
02127 LOOP_LOC (loop_vinfo)))
02128 fprintf (vect_dump, "not vectorized: unsupported use in stmt.");
02129 varray_clear (worklist);
02130 return false;
02131 }
02132
02133 if (!def_stmt)
02134 continue;
02135
02136 if (vect_print_dump_info (REPORT_DETAILS, UNKNOWN_LOC))
02137 {
02138 fprintf (vect_dump, "worklist: examine use %d: ", i);
02139 print_generic_expr (vect_dump, use, TDF_SLIM);
02140 }
02141
02142 bb = bb_for_stmt (def_stmt);
02143 if (flow_bb_inside_loop_p (loop, bb))
02144 vect_mark_relevant (&worklist, def_stmt);
02145 }
02146 }
02147 }
02148
02149 varray_clear (worklist);
02150 return true;
02151 }
02152
02153
02154
02155
02156
02157
02158
02159
02160
02161
02162
02163 static bool
02164 vect_can_advance_ivs_p (loop_vec_info loop_vinfo)
02165 {
02166 struct loop *loop = LOOP_VINFO_LOOP (loop_vinfo);
02167 basic_block bb = loop->header;
02168 tree phi;
02169
02170
02171
02172 for (phi = phi_nodes (bb); phi; phi = PHI_CHAIN (phi))
02173 {
02174 tree access_fn = NULL;
02175 tree evolution_part;
02176
02177 if (vect_print_dump_info (REPORT_DETAILS, UNKNOWN_LOC))
02178 {
02179 fprintf (vect_dump, "Analyze phi: ");
02180 print_generic_expr (vect_dump, phi, TDF_SLIM);
02181 }
02182
02183
02184
02185
02186 if (!is_gimple_reg (SSA_NAME_VAR (PHI_RESULT (phi))))
02187 {
02188 if (vect_print_dump_info (REPORT_DETAILS, UNKNOWN_LOC))
02189 fprintf (vect_dump, "virtual phi. skip.");
02190 continue;
02191 }
02192
02193
02194
02195 access_fn = instantiate_parameters
02196 (loop, analyze_scalar_evolution (loop, PHI_RESULT (phi)));
02197
02198 if (!access_fn)
02199 {
02200 if (vect_print_dump_info (REPORT_DETAILS, UNKNOWN_LOC))
02201 fprintf (vect_dump, "No Access function.");
02202 return false;
02203 }
02204
02205 if (vect_print_dump_info (REPORT_DETAILS, UNKNOWN_LOC))
02206 {
02207 fprintf (vect_dump, "Access function of PHI: ");
02208 print_generic_expr (vect_dump, access_fn, TDF_SLIM);
02209 }
02210
02211 evolution_part = evolution_part_in_loop_num (access_fn, loop->num);
02212
02213 if (evolution_part == NULL_TREE)
02214 return false;
02215
02216
02217
02218
02219 if (tree_is_chrec (evolution_part))
02220 return false;
02221 }
02222
02223 return true;
02224 }
02225
02226
02227
02228
02229
02230
02231
02232
02233
02234 static tree
02235 vect_get_loop_niters (struct loop *loop, tree *number_of_iterations)
02236 {
02237 tree niters;
02238
02239 if (vect_print_dump_info (REPORT_DETAILS, UNKNOWN_LOC))
02240 fprintf (vect_dump, "=== get_loop_niters ===");
02241
02242 niters = number_of_iterations_in_loop (loop);
02243
02244 if (niters != NULL_TREE
02245 && niters != chrec_dont_know)
02246 {
02247 *number_of_iterations = niters;
02248
02249 if (vect_print_dump_info (REPORT_DETAILS, UNKNOWN_LOC))
02250 {
02251 fprintf (vect_dump, "==> get_loop_niters:" );
02252 print_generic_expr (vect_dump, *number_of_iterations, TDF_SLIM);
02253 }
02254 }
02255
02256 return get_loop_exit_condition (loop);
02257 }
02258
02259
02260
02261
02262
02263
02264
02265
02266
02267
02268
02269
02270 static loop_vec_info
02271 vect_analyze_loop_form (struct loop *loop)
02272 {
02273 loop_vec_info loop_vinfo;
02274 tree loop_cond;
02275 tree number_of_iterations = NULL;
02276 bool rescan = false;
02277 LOC loop_loc;
02278
02279 loop_loc = find_loop_location (loop);
02280
02281 if (vect_print_dump_info (REPORT_DETAILS, loop_loc))
02282 fprintf (vect_dump, "=== vect_analyze_loop_form ===");
02283
02284 if (loop->inner)
02285 {
02286 if (vect_print_dump_info (REPORT_OUTER_LOOPS, loop_loc))
02287 fprintf (vect_dump, "not vectorized: nested loop.");
02288 return NULL;
02289 }
02290
02291 if (!loop->single_exit
02292 || loop->num_nodes != 2
02293 || EDGE_COUNT (loop->header->preds) != 2
02294 || loop->num_entries != 1)
02295 {
02296 if (vect_print_dump_info (REPORT_BAD_FORM_LOOPS, loop_loc))
02297 {
02298 if (!loop->single_exit)
02299 fprintf (vect_dump, "not vectorized: multiple exits.");
02300 else if (loop->num_nodes != 2)
02301 fprintf (vect_dump, "not vectorized: too many BBs in loop.");
02302 else if (EDGE_COUNT (loop->header->preds) != 2)
02303 fprintf (vect_dump, "not vectorized: too many incoming edges.");
02304 else if (loop->num_entries != 1)
02305 fprintf (vect_dump, "not vectorized: too many entries.");
02306 }
02307
02308 return NULL;
02309 }
02310
02311
02312
02313
02314
02315 if (!empty_block_p (loop->latch))
02316 {
02317 if (vect_print_dump_info (REPORT_BAD_FORM_LOOPS, loop_loc))
02318 fprintf (vect_dump, "not vectorized: unexpectd loop form.");
02319 return NULL;
02320 }
02321
02322
02323 if (!loop->pre_header || EDGE_COUNT (loop->pre_header->succs) != 1)
02324 {
02325 edge e = loop_preheader_edge (loop);
02326 loop_split_edge_with (e, NULL);
02327 if (vect_print_dump_info (REPORT_DETAILS, loop_loc))
02328 fprintf (vect_dump, "split preheader edge.");
02329 rescan = true;
02330 }
02331
02332
02333 if (EDGE_COUNT (loop->single_exit->dest->preds) != 1)
02334 {
02335 edge e = loop->single_exit;
02336 if (!(e->flags & EDGE_ABNORMAL))
02337 {
02338 loop_split_edge_with (e, NULL);
02339 if (vect_print_dump_info (REPORT_DETAILS, loop_loc))
02340 fprintf (vect_dump, "split exit edge.");
02341 rescan = true;
02342 }
02343 else
02344 {
02345 if (vect_print_dump_info (REPORT_BAD_FORM_LOOPS, loop_loc))
02346 fprintf (vect_dump, "not vectorized: abnormal loop exit edge.");
02347 return NULL;
02348 }
02349 }
02350
02351 if (rescan)
02352 {
02353 flow_loop_scan (loop, LOOP_ALL);
02354
02355 loop->single_exit = loop->exit_edges[0];
02356 }
02357
02358 if (empty_block_p (loop->header))
02359 {
02360 if (vect_print_dump_info (REPORT_BAD_FORM_LOOPS, loop_loc))
02361 fprintf (vect_dump, "not vectorized: empty loop.");
02362 return NULL;
02363 }
02364
02365 loop_cond = vect_get_loop_niters (loop, &number_of_iterations);
02366 if (!loop_cond)
02367 {
02368 if (vect_print_dump_info (REPORT_BAD_FORM_LOOPS, loop_loc))
02369 fprintf (vect_dump, "not vectorized: complicated exit condition.");
02370 return NULL;
02371 }
02372
02373 if (!number_of_iterations)
02374 {
02375 if (vect_print_dump_info (REPORT_BAD_FORM_LOOPS, loop_loc))
02376 fprintf (vect_dump,
02377 "not vectorized: number of iterations cannot be computed.");
02378 return NULL;
02379 }
02380
02381 if (chrec_contains_undetermined (number_of_iterations))
02382 {
02383 if (vect_print_dump_info (REPORT_BAD_FORM_LOOPS, loop_loc))
02384 fprintf (vect_dump, "Infinite number of iterations.");
02385 return false;
02386 }
02387
02388 loop_vinfo = new_loop_vec_info (loop);
02389 LOOP_VINFO_NITERS (loop_vinfo) = number_of_iterations;
02390
02391 if (!LOOP_VINFO_NITERS_KNOWN_P (loop_vinfo))
02392 {
02393 if (vect_print_dump_info (REPORT_DETAILS, loop_loc))
02394 {
02395 fprintf (vect_dump, "Symbolic number of iterations is ");
02396 print_generic_expr (vect_dump, number_of_iterations, TDF_DETAILS);
02397 }
02398 }
02399 else
02400 if (LOOP_VINFO_INT_NITERS (loop_vinfo) == 0)
02401 {
02402 if (vect_print_dump_info (REPORT_UNVECTORIZED_LOOPS, loop_loc))
02403 fprintf (vect_dump, "not vectorized: number of iterations = 0.");
02404 return NULL;
02405 }
02406
02407 LOOP_VINFO_EXIT_COND (loop_vinfo) = loop_cond;
02408 LOOP_VINFO_LOC (loop_vinfo) = loop_loc;
02409
02410 return loop_vinfo;
02411 }
02412
02413
02414
02415
02416
02417
02418
02419 loop_vec_info
02420 vect_analyze_loop (struct loop *loop)
02421 {
02422 bool ok;
02423 loop_vec_info loop_vinfo;
02424
02425 if (vect_print_dump_info (REPORT_DETAILS, UNKNOWN_LOC))
02426 fprintf (vect_dump, "===== analyze_loop_nest =====");
02427
02428
02429
02430 loop_vinfo = vect_analyze_loop_form (loop);
02431 if (!loop_vinfo)
02432 {
02433 if (vect_print_dump_info (REPORT_DETAILS, UNKNOWN_LOC))
02434 fprintf (vect_dump, "bad loop form.");
02435 return NULL;
02436 }
02437
02438
02439
02440
02441
02442
02443
02444 ok = vect_analyze_data_refs (loop_vinfo);
02445 if (!ok)
02446 {
02447 if (vect_print_dump_info (REPORT_DETAILS, LOOP_LOC (loop_vinfo)))
02448 fprintf (vect_dump, "bad data references.");
02449 destroy_loop_vec_info (loop_vinfo);
02450 return NULL;
02451 }
02452
02453
02454
02455 ok = vect_mark_stmts_to_be_vectorized (loop_vinfo);
02456 if (!ok)
02457 {
02458 if (vect_print_dump_info (REPORT_DETAILS, LOOP_LOC (loop_vinfo)))
02459 fprintf (vect_dump, "unexpected pattern.");
02460 destroy_loop_vec_info (loop_vinfo);
02461 return NULL;
02462 }
02463
02464
02465
02466
02467 ok = vect_analyze_scalar_cycles (loop_vinfo);
02468 if (!ok)
02469 {
02470 if (vect_print_dump_info (REPORT_DETAILS, LOOP_LOC (loop_vinfo)))
02471 fprintf (vect_dump, "bad scalar cycle.");
02472 destroy_loop_vec_info (loop_vinfo);
02473 return NULL;
02474 }
02475
02476
02477
02478
02479 ok = vect_analyze_data_ref_dependences (loop_vinfo);
02480 if (!ok)
02481 {
02482 if (vect_print_dump_info (REPORT_DETAILS, LOOP_LOC (loop_vinfo)))
02483 fprintf (vect_dump, "bad data dependence.");
02484 destroy_loop_vec_info (loop_vinfo);
02485 return NULL;
02486 }
02487
02488
02489
02490
02491 ok = vect_analyze_data_ref_accesses (loop_vinfo);
02492 if (!ok)
02493 {
02494 if (vect_print_dump_info (REPORT_DETAILS, LOOP_LOC (loop_vinfo)))
02495 fprintf (vect_dump, "bad data access.");
02496 destroy_loop_vec_info (loop_vinfo);
02497 return NULL;
02498 }
02499
02500
02501
02502
02503 ok = vect_analyze_data_refs_alignment (loop_vinfo);
02504 if (!ok)
02505 {
02506 if (vect_print_dump_info (REPORT_DETAILS, LOOP_LOC (loop_vinfo)))
02507 fprintf (vect_dump, "bad data alignment.");
02508 destroy_loop_vec_info (loop_vinfo);
02509 return NULL;
02510 }
02511
02512
02513
02514
02515 ok = vect_analyze_operations (loop_vinfo);
02516 if (!ok)
02517 {
02518 if (vect_print_dump_info (REPORT_DETAILS, LOOP_LOC (loop_vinfo)))
02519 fprintf (vect_dump, "bad operation or unsupported loop bound.");
02520 destroy_loop_vec_info (loop_vinfo);
02521 return NULL;
02522 }
02523
02524 LOOP_VINFO_VECTORIZABLE_P (loop_vinfo) = 1;
02525
02526 return loop_vinfo;
02527 }