1 /* Conversion of SESE regions to Polyhedra. 2 Copyright (C) 2009-2017 Free Software Foundation, Inc. 3 Contributed by Sebastian Pop <sebastian.pop@amd.com>. 4 5 This file is part of GCC. 6 7 GCC is free software; you can redistribute it and/or modify 8 it under the terms of the GNU General Public License as published by 9 the Free Software Foundation; either version 3, or (at your option) 10 any later version. 11 12 GCC is distributed in the hope that it will be useful, 13 but WITHOUT ANY WARRANTY; without even the implied warranty of 14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 GNU General Public License for more details. 16 17 You should have received a copy of the GNU General Public License 18 along with GCC; see the file COPYING3. If not see 19 <http://www.gnu.org/licenses/>. */ 20 21 #define USES_ISL 22 23 #include "config.h" 24 25 #ifdef HAVE_isl 26 27 #include "system.h" 28 #include "coretypes.h" 29 #include "backend.h" 30 #include "cfghooks.h" 31 #include "tree.h" 32 #include "gimple.h" 33 #include "ssa.h" 34 #include "params.h" 35 #include "fold-const.h" 36 #include "gimple-iterator.h" 37 #include "gimplify.h" 38 #include "gimplify-me.h" 39 #include "tree-cfg.h" 40 #include "tree-ssa-loop-manip.h" 41 #include "tree-ssa-loop-niter.h" 42 #include "tree-ssa-loop.h" 43 #include "tree-into-ssa.h" 44 #include "tree-pass.h" 45 #include "cfgloop.h" 46 #include "tree-data-ref.h" 47 #include "tree-scalar-evolution.h" 48 #include "domwalk.h" 49 #include "tree-ssa-propagate.h" 50 51 #include <isl/constraint.h> 52 #include <isl/set.h> 53 #include <isl/map.h> 54 #include <isl/union_map.h> 55 #include <isl/constraint.h> 56 #include <isl/aff.h> 57 #include <isl/val.h> 58 59 #include "graphite.h" 60 61 /* Assigns to RES the value of the INTEGER_CST T. */ 62 63 static inline void 64 tree_int_to_gmp (tree t, mpz_t res) 65 { 66 wi::to_mpz (t, res, TYPE_SIGN (TREE_TYPE (t))); 67 } 68 69 /* Return an isl identifier for the polyhedral basic block PBB. */ 70 71 static isl_id * 72 isl_id_for_pbb (scop_p s, poly_bb_p pbb) 73 { 74 char name[14]; 75 snprintf (name, sizeof (name), "S_%d", pbb_index (pbb)); 76 return isl_id_alloc (s->isl_context, name, pbb); 77 } 78 79 static isl_pw_aff *extract_affine (scop_p, tree, __isl_take isl_space *space); 80 81 /* Extract an affine expression from the chain of recurrence E. */ 82 83 static isl_pw_aff * 84 extract_affine_chrec (scop_p s, tree e, __isl_take isl_space *space) 85 { 86 isl_pw_aff *lhs = extract_affine (s, CHREC_LEFT (e), isl_space_copy (space)); 87 isl_pw_aff *rhs = extract_affine (s, CHREC_RIGHT (e), isl_space_copy (space)); 88 isl_local_space *ls = isl_local_space_from_space (space); 89 unsigned pos = sese_loop_depth (s->scop_info->region, get_chrec_loop (e)) - 1; 90 isl_aff *loop = isl_aff_set_coefficient_si 91 (isl_aff_zero_on_domain (ls), isl_dim_in, pos, 1); 92 isl_pw_aff *l = isl_pw_aff_from_aff (loop); 93 94 /* Before multiplying, make sure that the result is affine. */ 95 gcc_assert (isl_pw_aff_is_cst (rhs) 96 || isl_pw_aff_is_cst (l)); 97 98 return isl_pw_aff_add (lhs, isl_pw_aff_mul (rhs, l)); 99 } 100 101 /* Extract an affine expression from the mult_expr E. */ 102 103 static isl_pw_aff * 104 extract_affine_mul (scop_p s, tree e, __isl_take isl_space *space) 105 { 106 isl_pw_aff *lhs = extract_affine (s, TREE_OPERAND (e, 0), 107 isl_space_copy (space)); 108 isl_pw_aff *rhs = extract_affine (s, TREE_OPERAND (e, 1), space); 109 110 if (!isl_pw_aff_is_cst (lhs) 111 && !isl_pw_aff_is_cst (rhs)) 112 { 113 isl_pw_aff_free (lhs); 114 isl_pw_aff_free (rhs); 115 return NULL; 116 } 117 118 return isl_pw_aff_mul (lhs, rhs); 119 } 120 121 /* Return an isl identifier from the name of the ssa_name E. */ 122 123 static isl_id * 124 isl_id_for_ssa_name (scop_p s, tree e) 125 { 126 char name1[14]; 127 snprintf (name1, sizeof (name1), "P_%d", SSA_NAME_VERSION (e)); 128 return isl_id_alloc (s->isl_context, name1, e); 129 } 130 131 /* Return an isl identifier for the data reference DR. Data references and 132 scalar references get the same isl_id. They need to be comparable and are 133 distinguished through the first dimension, which contains the alias set or 134 SSA_NAME_VERSION number. */ 135 136 static isl_id * 137 isl_id_for_dr (scop_p s) 138 { 139 return isl_id_alloc (s->isl_context, "", 0); 140 } 141 142 /* Extract an affine expression from the ssa_name E. */ 143 144 static isl_pw_aff * 145 extract_affine_name (scop_p s, tree e, __isl_take isl_space *space) 146 { 147 isl_id *id = isl_id_for_ssa_name (s, e); 148 int dimension = isl_space_find_dim_by_id (space, isl_dim_param, id); 149 isl_id_free (id); 150 isl_set *dom = isl_set_universe (isl_space_copy (space)); 151 isl_aff *aff = isl_aff_zero_on_domain (isl_local_space_from_space (space)); 152 aff = isl_aff_add_coefficient_si (aff, isl_dim_param, dimension, 1); 153 return isl_pw_aff_alloc (dom, aff); 154 } 155 156 /* Convert WI to a isl_val with CTX. */ 157 158 static __isl_give isl_val * 159 isl_val_int_from_wi (isl_ctx *ctx, const widest_int &wi) 160 { 161 if (wi::neg_p (wi, SIGNED)) 162 { 163 widest_int mwi = -wi; 164 return isl_val_neg (isl_val_int_from_chunks (ctx, mwi.get_len (), 165 sizeof (HOST_WIDE_INT), 166 mwi.get_val ())); 167 } 168 return isl_val_int_from_chunks (ctx, wi.get_len (), sizeof (HOST_WIDE_INT), 169 wi.get_val ()); 170 } 171 172 /* Extract an affine expression from the gmp constant G. */ 173 174 static isl_pw_aff * 175 extract_affine_wi (const widest_int &g, __isl_take isl_space *space) 176 { 177 isl_local_space *ls = isl_local_space_from_space (isl_space_copy (space)); 178 isl_aff *aff = isl_aff_zero_on_domain (ls); 179 isl_set *dom = isl_set_universe (space); 180 isl_ctx *ct = isl_aff_get_ctx (aff); 181 isl_val *v = isl_val_int_from_wi (ct, g); 182 aff = isl_aff_add_constant_val (aff, v); 183 184 return isl_pw_aff_alloc (dom, aff); 185 } 186 187 /* Extract an affine expression from the integer_cst E. */ 188 189 static isl_pw_aff * 190 extract_affine_int (tree e, __isl_take isl_space *space) 191 { 192 isl_pw_aff *res = extract_affine_wi (wi::to_widest (e), space); 193 return res; 194 } 195 196 /* Compute pwaff mod 2^width. */ 197 198 static isl_pw_aff * 199 wrap (isl_pw_aff *pwaff, unsigned width) 200 { 201 isl_val *mod; 202 203 mod = isl_val_int_from_ui (isl_pw_aff_get_ctx (pwaff), width); 204 mod = isl_val_2exp (mod); 205 pwaff = isl_pw_aff_mod_val (pwaff, mod); 206 207 return pwaff; 208 } 209 210 /* When parameter NAME is in REGION, returns its index in SESE_PARAMS. 211 Otherwise returns -1. */ 212 213 static inline int 214 parameter_index_in_region_1 (tree name, sese_info_p region) 215 { 216 int i; 217 tree p; 218 219 gcc_assert (TREE_CODE (name) == SSA_NAME); 220 221 FOR_EACH_VEC_ELT (region->params, i, p) 222 if (p == name) 223 return i; 224 225 return -1; 226 } 227 228 /* Extract an affine expression from the tree E in the scop S. */ 229 230 static isl_pw_aff * 231 extract_affine (scop_p s, tree e, __isl_take isl_space *space) 232 { 233 isl_pw_aff *lhs, *rhs, *res; 234 235 if (e == chrec_dont_know) { 236 isl_space_free (space); 237 return NULL; 238 } 239 240 switch (TREE_CODE (e)) 241 { 242 case POLYNOMIAL_CHREC: 243 res = extract_affine_chrec (s, e, space); 244 break; 245 246 case MULT_EXPR: 247 res = extract_affine_mul (s, e, space); 248 break; 249 250 case PLUS_EXPR: 251 case POINTER_PLUS_EXPR: 252 lhs = extract_affine (s, TREE_OPERAND (e, 0), isl_space_copy (space)); 253 rhs = extract_affine (s, TREE_OPERAND (e, 1), space); 254 res = isl_pw_aff_add (lhs, rhs); 255 break; 256 257 case MINUS_EXPR: 258 lhs = extract_affine (s, TREE_OPERAND (e, 0), isl_space_copy (space)); 259 rhs = extract_affine (s, TREE_OPERAND (e, 1), space); 260 res = isl_pw_aff_sub (lhs, rhs); 261 break; 262 263 case NEGATE_EXPR: 264 case BIT_NOT_EXPR: 265 lhs = extract_affine (s, TREE_OPERAND (e, 0), isl_space_copy (space)); 266 rhs = extract_affine (s, integer_minus_one_node, space); 267 res = isl_pw_aff_mul (lhs, rhs); 268 break; 269 270 case SSA_NAME: 271 gcc_assert (-1 != parameter_index_in_region_1 (e, s->scop_info) 272 || defined_in_sese_p (e, s->scop_info->region)); 273 res = extract_affine_name (s, e, space); 274 break; 275 276 case INTEGER_CST: 277 res = extract_affine_int (e, space); 278 /* No need to wrap a single integer. */ 279 return res; 280 281 CASE_CONVERT: 282 case NON_LVALUE_EXPR: 283 res = extract_affine (s, TREE_OPERAND (e, 0), space); 284 break; 285 286 default: 287 gcc_unreachable (); 288 break; 289 } 290 291 tree type = TREE_TYPE (e); 292 if (TYPE_UNSIGNED (type)) 293 res = wrap (res, TYPE_PRECISION (type)); 294 295 return res; 296 } 297 298 /* Returns a linear expression for tree T evaluated in PBB. */ 299 300 static isl_pw_aff * 301 create_pw_aff_from_tree (poly_bb_p pbb, loop_p loop, tree t) 302 { 303 scop_p scop = PBB_SCOP (pbb); 304 305 t = scalar_evolution_in_region (scop->scop_info->region, loop, t); 306 307 gcc_assert (!chrec_contains_undetermined (t)); 308 gcc_assert (!automatically_generated_chrec_p (t)); 309 310 return extract_affine (scop, t, isl_set_get_space (pbb->domain)); 311 } 312 313 /* Add conditional statement STMT to pbb. CODE is used as the comparison 314 operator. This allows us to invert the condition or to handle 315 inequalities. */ 316 317 static void 318 add_condition_to_pbb (poly_bb_p pbb, gcond *stmt, enum tree_code code) 319 { 320 loop_p loop = gimple_bb (stmt)->loop_father; 321 isl_pw_aff *lhs = create_pw_aff_from_tree (pbb, loop, gimple_cond_lhs (stmt)); 322 isl_pw_aff *rhs = create_pw_aff_from_tree (pbb, loop, gimple_cond_rhs (stmt)); 323 324 isl_set *cond; 325 switch (code) 326 { 327 case LT_EXPR: 328 cond = isl_pw_aff_lt_set (lhs, rhs); 329 break; 330 331 case GT_EXPR: 332 cond = isl_pw_aff_gt_set (lhs, rhs); 333 break; 334 335 case LE_EXPR: 336 cond = isl_pw_aff_le_set (lhs, rhs); 337 break; 338 339 case GE_EXPR: 340 cond = isl_pw_aff_ge_set (lhs, rhs); 341 break; 342 343 case EQ_EXPR: 344 cond = isl_pw_aff_eq_set (lhs, rhs); 345 break; 346 347 case NE_EXPR: 348 cond = isl_pw_aff_ne_set (lhs, rhs); 349 break; 350 351 default: 352 gcc_unreachable (); 353 } 354 355 cond = isl_set_coalesce (cond); 356 cond = isl_set_set_tuple_id (cond, isl_set_get_tuple_id (pbb->domain)); 357 pbb->domain = isl_set_coalesce (isl_set_intersect (pbb->domain, cond)); 358 } 359 360 /* Add conditions to the domain of PBB. */ 361 362 static void 363 add_conditions_to_domain (poly_bb_p pbb) 364 { 365 unsigned int i; 366 gimple *stmt; 367 gimple_poly_bb_p gbb = PBB_BLACK_BOX (pbb); 368 369 if (GBB_CONDITIONS (gbb).is_empty ()) 370 return; 371 372 FOR_EACH_VEC_ELT (GBB_CONDITIONS (gbb), i, stmt) 373 switch (gimple_code (stmt)) 374 { 375 case GIMPLE_COND: 376 { 377 /* Don't constrain on anything else than INTEGER_TYPE. */ 378 if (TREE_CODE (TREE_TYPE (gimple_cond_lhs (stmt))) != INTEGER_TYPE) 379 break; 380 381 gcond *cond_stmt = as_a <gcond *> (stmt); 382 enum tree_code code = gimple_cond_code (cond_stmt); 383 384 /* The conditions for ELSE-branches are inverted. */ 385 if (!GBB_CONDITION_CASES (gbb)[i]) 386 code = invert_tree_comparison (code, false); 387 388 add_condition_to_pbb (pbb, cond_stmt, code); 389 break; 390 } 391 392 default: 393 gcc_unreachable (); 394 break; 395 } 396 } 397 398 /* Add constraints on the possible values of parameter P from the type 399 of P. */ 400 401 static void 402 add_param_constraints (scop_p scop, graphite_dim_t p) 403 { 404 tree parameter = scop->scop_info->params[p]; 405 tree type = TREE_TYPE (parameter); 406 tree lb = NULL_TREE; 407 tree ub = NULL_TREE; 408 409 if (POINTER_TYPE_P (type) || !TYPE_MIN_VALUE (type)) 410 lb = lower_bound_in_type (type, type); 411 else 412 lb = TYPE_MIN_VALUE (type); 413 414 if (POINTER_TYPE_P (type) || !TYPE_MAX_VALUE (type)) 415 ub = upper_bound_in_type (type, type); 416 else 417 ub = TYPE_MAX_VALUE (type); 418 419 if (lb) 420 { 421 isl_space *space = isl_set_get_space (scop->param_context); 422 isl_constraint *c; 423 isl_val *v; 424 425 c = isl_inequality_alloc (isl_local_space_from_space (space)); 426 v = isl_val_int_from_wi (scop->isl_context, wi::to_widest (lb)); 427 v = isl_val_neg (v); 428 c = isl_constraint_set_constant_val (c, v); 429 c = isl_constraint_set_coefficient_si (c, isl_dim_param, p, 1); 430 431 scop->param_context = isl_set_coalesce 432 (isl_set_add_constraint (scop->param_context, c)); 433 } 434 435 if (ub) 436 { 437 isl_space *space = isl_set_get_space (scop->param_context); 438 isl_constraint *c; 439 isl_val *v; 440 441 c = isl_inequality_alloc (isl_local_space_from_space (space)); 442 443 v = isl_val_int_from_wi (scop->isl_context, wi::to_widest (ub)); 444 c = isl_constraint_set_constant_val (c, v); 445 c = isl_constraint_set_coefficient_si (c, isl_dim_param, p, -1); 446 447 scop->param_context = isl_set_coalesce 448 (isl_set_add_constraint (scop->param_context, c)); 449 } 450 } 451 452 /* Add a constrain to the ACCESSES polyhedron for the alias set of 453 data reference DR. ACCESSP_NB_DIMS is the dimension of the 454 ACCESSES polyhedron, DOM_NB_DIMS is the dimension of the iteration 455 domain. */ 456 457 static isl_map * 458 pdr_add_alias_set (isl_map *acc, dr_info &dri) 459 { 460 isl_constraint *c = isl_equality_alloc 461 (isl_local_space_from_space (isl_map_get_space (acc))); 462 /* Positive numbers for all alias sets. */ 463 c = isl_constraint_set_constant_si (c, -dri.alias_set); 464 c = isl_constraint_set_coefficient_si (c, isl_dim_out, 0, 1); 465 466 return isl_map_add_constraint (acc, c); 467 } 468 469 /* Add a constrain to the ACCESSES polyhedron for the alias set of 470 data reference DR. ACCESSP_NB_DIMS is the dimension of the 471 ACCESSES polyhedron, DOM_NB_DIMS is the dimension of the iteration 472 domain. */ 473 474 static isl_map * 475 add_scalar_version_numbers (isl_map *acc, tree var) 476 { 477 isl_constraint *c = isl_equality_alloc 478 (isl_local_space_from_space (isl_map_get_space (acc))); 479 int max_arrays = PARAM_VALUE (PARAM_GRAPHITE_MAX_ARRAYS_PER_SCOP); 480 /* Each scalar variables has a unique alias set number starting from 481 max_arrays. */ 482 c = isl_constraint_set_constant_si (c, -max_arrays - SSA_NAME_VERSION (var)); 483 c = isl_constraint_set_coefficient_si (c, isl_dim_out, 0, 1); 484 485 return isl_map_add_constraint (acc, c); 486 } 487 488 /* Assign the affine expression INDEX to the output dimension POS of 489 MAP and return the result. */ 490 491 static isl_map * 492 set_index (isl_map *map, int pos, isl_pw_aff *index) 493 { 494 isl_map *index_map; 495 int len = isl_map_dim (map, isl_dim_out); 496 isl_id *id; 497 498 index_map = isl_map_from_pw_aff (index); 499 index_map = isl_map_insert_dims (index_map, isl_dim_out, 0, pos); 500 index_map = isl_map_add_dims (index_map, isl_dim_out, len - pos - 1); 501 502 id = isl_map_get_tuple_id (map, isl_dim_out); 503 index_map = isl_map_set_tuple_id (index_map, isl_dim_out, id); 504 id = isl_map_get_tuple_id (map, isl_dim_in); 505 index_map = isl_map_set_tuple_id (index_map, isl_dim_in, id); 506 507 return isl_map_intersect (map, index_map); 508 } 509 510 /* Add to ACCESSES polyhedron equalities defining the access functions 511 to the memory. ACCESSP_NB_DIMS is the dimension of the ACCESSES 512 polyhedron, DOM_NB_DIMS is the dimension of the iteration domain. 513 PBB is the poly_bb_p that contains the data reference DR. */ 514 515 static isl_map * 516 pdr_add_memory_accesses (isl_map *acc, dr_info &dri) 517 { 518 data_reference_p dr = dri.dr; 519 poly_bb_p pbb = dri.pbb; 520 int i, nb_subscripts = DR_NUM_DIMENSIONS (dr); 521 scop_p scop = PBB_SCOP (pbb); 522 523 for (i = 0; i < nb_subscripts; i++) 524 { 525 isl_pw_aff *aff; 526 tree afn = DR_ACCESS_FN (dr, i); 527 528 aff = extract_affine (scop, afn, 529 isl_space_domain (isl_map_get_space (acc))); 530 acc = set_index (acc, nb_subscripts - i , aff); 531 } 532 533 return isl_map_coalesce (acc); 534 } 535 536 /* Return true when the LOW and HIGH bounds of an array reference REF are valid 537 to extract constraints on accessed elements of the array. Returning false is 538 the conservative answer. */ 539 540 static bool 541 bounds_are_valid (tree ref, tree low, tree high) 542 { 543 if (!high) 544 return false; 545 546 if (!tree_fits_shwi_p (low) 547 || !tree_fits_shwi_p (high)) 548 return false; 549 550 /* 1-element arrays at end of structures may extend over 551 their declared size. */ 552 if (array_at_struct_end_p (ref) 553 && operand_equal_p (low, high, 0)) 554 return false; 555 556 /* Fortran has some arrays where high bound is -1 and low is 0. */ 557 if (integer_onep (fold_build2 (LT_EXPR, boolean_type_node, high, low))) 558 return false; 559 560 return true; 561 } 562 563 /* Add constrains representing the size of the accessed data to the 564 ACCESSES polyhedron. ACCESSP_NB_DIMS is the dimension of the 565 ACCESSES polyhedron, DOM_NB_DIMS is the dimension of the iteration 566 domain. */ 567 568 static isl_set * 569 pdr_add_data_dimensions (isl_set *subscript_sizes, scop_p scop, 570 data_reference_p dr) 571 { 572 tree ref = DR_REF (dr); 573 574 int nb_subscripts = DR_NUM_DIMENSIONS (dr); 575 for (int i = nb_subscripts - 1; i >= 0; i--, ref = TREE_OPERAND (ref, 0)) 576 { 577 if (TREE_CODE (ref) != ARRAY_REF) 578 return subscript_sizes; 579 580 tree low = array_ref_low_bound (ref); 581 tree high = array_ref_up_bound (ref); 582 583 if (!bounds_are_valid (ref, low, high)) 584 continue; 585 586 isl_space *space = isl_set_get_space (subscript_sizes); 587 isl_pw_aff *lb = extract_affine_int (low, isl_space_copy (space)); 588 isl_pw_aff *ub = extract_affine_int (high, isl_space_copy (space)); 589 590 /* high >= 0 */ 591 isl_set *valid = isl_pw_aff_nonneg_set (isl_pw_aff_copy (ub)); 592 valid = isl_set_project_out (valid, isl_dim_set, 0, 593 isl_set_dim (valid, isl_dim_set)); 594 scop->param_context = isl_set_coalesce 595 (isl_set_intersect (scop->param_context, valid)); 596 597 isl_aff *aff 598 = isl_aff_zero_on_domain (isl_local_space_from_space (space)); 599 aff = isl_aff_add_coefficient_si (aff, isl_dim_in, i + 1, 1); 600 isl_set *univ 601 = isl_set_universe (isl_space_domain (isl_aff_get_space (aff))); 602 isl_pw_aff *index = isl_pw_aff_alloc (univ, aff); 603 604 isl_id *id = isl_set_get_tuple_id (subscript_sizes); 605 lb = isl_pw_aff_set_tuple_id (lb, isl_dim_in, isl_id_copy (id)); 606 ub = isl_pw_aff_set_tuple_id (ub, isl_dim_in, id); 607 608 /* low <= sub_i <= high */ 609 isl_set *lbs = isl_pw_aff_ge_set (isl_pw_aff_copy (index), lb); 610 isl_set *ubs = isl_pw_aff_le_set (index, ub); 611 subscript_sizes = isl_set_intersect (subscript_sizes, lbs); 612 subscript_sizes = isl_set_intersect (subscript_sizes, ubs); 613 } 614 615 return isl_set_coalesce (subscript_sizes); 616 } 617 618 /* Build data accesses for DRI. */ 619 620 static void 621 build_poly_dr (dr_info &dri) 622 { 623 isl_map *acc; 624 isl_set *subscript_sizes; 625 poly_bb_p pbb = dri.pbb; 626 data_reference_p dr = dri.dr; 627 scop_p scop = PBB_SCOP (pbb); 628 isl_id *id = isl_id_for_dr (scop); 629 630 { 631 isl_space *dc = isl_set_get_space (pbb->domain); 632 int nb_out = 1 + DR_NUM_DIMENSIONS (dr); 633 isl_space *space = isl_space_add_dims (isl_space_from_domain (dc), 634 isl_dim_out, nb_out); 635 636 acc = isl_map_universe (space); 637 acc = isl_map_set_tuple_id (acc, isl_dim_out, isl_id_copy (id)); 638 } 639 640 acc = pdr_add_alias_set (acc, dri); 641 acc = pdr_add_memory_accesses (acc, dri); 642 643 { 644 int nb = 1 + DR_NUM_DIMENSIONS (dr); 645 isl_space *space = isl_space_set_alloc (scop->isl_context, 0, nb); 646 647 space = isl_space_set_tuple_id (space, isl_dim_set, id); 648 subscript_sizes = isl_set_nat_universe (space); 649 subscript_sizes = isl_set_fix_si (subscript_sizes, isl_dim_set, 0, 650 dri.alias_set); 651 subscript_sizes = pdr_add_data_dimensions (subscript_sizes, scop, dr); 652 } 653 654 new_poly_dr (pbb, DR_STMT (dr), DR_IS_READ (dr) ? PDR_READ : PDR_WRITE, 655 acc, subscript_sizes); 656 } 657 658 static void 659 build_poly_sr_1 (poly_bb_p pbb, gimple *stmt, tree var, enum poly_dr_type kind, 660 isl_map *acc, isl_set *subscript_sizes) 661 { 662 int max_arrays = PARAM_VALUE (PARAM_GRAPHITE_MAX_ARRAYS_PER_SCOP); 663 /* Each scalar variables has a unique alias set number starting from 664 max_arrays. */ 665 subscript_sizes = isl_set_fix_si (subscript_sizes, isl_dim_set, 0, 666 max_arrays + SSA_NAME_VERSION (var)); 667 668 new_poly_dr (pbb, stmt, kind, add_scalar_version_numbers (acc, var), 669 subscript_sizes); 670 } 671 672 /* Record all cross basic block scalar variables in PBB. */ 673 674 static void 675 build_poly_sr (poly_bb_p pbb) 676 { 677 scop_p scop = PBB_SCOP (pbb); 678 gimple_poly_bb_p gbb = PBB_BLACK_BOX (pbb); 679 vec<scalar_use> &reads = gbb->read_scalar_refs; 680 vec<tree> &writes = gbb->write_scalar_refs; 681 682 isl_space *dc = isl_set_get_space (pbb->domain); 683 int nb_out = 1; 684 isl_space *space = isl_space_add_dims (isl_space_from_domain (dc), 685 isl_dim_out, nb_out); 686 isl_id *id = isl_id_for_dr (scop); 687 space = isl_space_set_tuple_id (space, isl_dim_set, isl_id_copy (id)); 688 isl_map *acc = isl_map_universe (isl_space_copy (space)); 689 acc = isl_map_set_tuple_id (acc, isl_dim_out, id); 690 isl_set *subscript_sizes = isl_set_nat_universe (space); 691 692 int i; 693 tree var; 694 FOR_EACH_VEC_ELT (writes, i, var) 695 build_poly_sr_1 (pbb, SSA_NAME_DEF_STMT (var), var, PDR_WRITE, 696 isl_map_copy (acc), isl_set_copy (subscript_sizes)); 697 698 scalar_use *use; 699 FOR_EACH_VEC_ELT (reads, i, use) 700 build_poly_sr_1 (pbb, use->first, use->second, PDR_READ, isl_map_copy (acc), 701 isl_set_copy (subscript_sizes)); 702 703 isl_map_free (acc); 704 isl_set_free (subscript_sizes); 705 } 706 707 /* Build data references in SCOP. */ 708 709 static void 710 build_scop_drs (scop_p scop) 711 { 712 int i; 713 dr_info *dri; 714 FOR_EACH_VEC_ELT (scop->drs, i, dri) 715 build_poly_dr (*dri); 716 717 poly_bb_p pbb; 718 FOR_EACH_VEC_ELT (scop->pbbs, i, pbb) 719 build_poly_sr (pbb); 720 } 721 722 /* Add to the iteration DOMAIN one extra dimension for LOOP->num. */ 723 724 static isl_set * 725 add_iter_domain_dimension (__isl_take isl_set *domain, loop_p loop, scop_p scop) 726 { 727 int loop_index = isl_set_dim (domain, isl_dim_set); 728 domain = isl_set_add_dims (domain, isl_dim_set, 1); 729 char name[50]; 730 snprintf (name, sizeof(name), "i%d", loop->num); 731 isl_id *label = isl_id_alloc (scop->isl_context, name, NULL); 732 return isl_set_set_dim_id (domain, isl_dim_set, loop_index, label); 733 } 734 735 /* Add constraints to DOMAIN for each loop from LOOP up to CONTEXT. */ 736 737 static isl_set * 738 add_loop_constraints (scop_p scop, __isl_take isl_set *domain, loop_p loop, 739 loop_p context) 740 { 741 if (loop == context) 742 return domain; 743 const sese_l ®ion = scop->scop_info->region; 744 if (!loop_in_sese_p (loop, region)) 745 return domain; 746 747 /* Recursion all the way up to the context loop. */ 748 domain = add_loop_constraints (scop, domain, loop_outer (loop), context); 749 750 /* Then, build constraints over the loop in post-order: outer to inner. */ 751 752 int loop_index = isl_set_dim (domain, isl_dim_set); 753 if (dump_file) 754 fprintf (dump_file, "[sese-to-poly] adding one extra dimension to the " 755 "domain for loop_%d.\n", loop->num); 756 domain = add_iter_domain_dimension (domain, loop, scop); 757 isl_space *space = isl_set_get_space (domain); 758 759 /* 0 <= loop_i */ 760 isl_local_space *ls = isl_local_space_from_space (isl_space_copy (space)); 761 isl_constraint *c = isl_inequality_alloc (ls); 762 c = isl_constraint_set_coefficient_si (c, isl_dim_set, loop_index, 1); 763 if (dump_file) 764 { 765 fprintf (dump_file, "[sese-to-poly] adding constraint to the domain: "); 766 print_isl_constraint (dump_file, c); 767 } 768 domain = isl_set_add_constraint (domain, c); 769 770 tree nb_iters = number_of_latch_executions (loop); 771 if (TREE_CODE (nb_iters) == INTEGER_CST) 772 { 773 /* loop_i <= cst_nb_iters */ 774 isl_local_space *ls = isl_local_space_from_space (space); 775 isl_constraint *c = isl_inequality_alloc (ls); 776 c = isl_constraint_set_coefficient_si (c, isl_dim_set, loop_index, -1); 777 isl_val *v 778 = isl_val_int_from_wi (scop->isl_context, wi::to_widest (nb_iters)); 779 c = isl_constraint_set_constant_val (c, v); 780 return isl_set_add_constraint (domain, c); 781 } 782 /* loop_i <= expr_nb_iters */ 783 gcc_assert (!chrec_contains_undetermined (nb_iters)); 784 nb_iters = scalar_evolution_in_region (region, loop, nb_iters); 785 gcc_assert (!chrec_contains_undetermined (nb_iters)); 786 787 isl_pw_aff *aff_nb_iters = extract_affine (scop, nb_iters, 788 isl_space_copy (space)); 789 isl_set *valid = isl_pw_aff_nonneg_set (isl_pw_aff_copy (aff_nb_iters)); 790 valid = isl_set_project_out (valid, isl_dim_set, 0, 791 isl_set_dim (valid, isl_dim_set)); 792 793 if (valid) 794 scop->param_context = isl_set_intersect (scop->param_context, valid); 795 796 ls = isl_local_space_from_space (isl_space_copy (space)); 797 isl_aff *loop_i = isl_aff_set_coefficient_si (isl_aff_zero_on_domain (ls), 798 isl_dim_in, loop_index, 1); 799 isl_set *le = isl_pw_aff_le_set (isl_pw_aff_from_aff (loop_i), 800 isl_pw_aff_copy (aff_nb_iters)); 801 if (dump_file) 802 { 803 fprintf (dump_file, "[sese-to-poly] adding constraint to the domain: "); 804 print_isl_set (dump_file, le); 805 } 806 domain = isl_set_intersect (domain, le); 807 808 widest_int nit; 809 if (!max_stmt_executions (loop, &nit)) 810 { 811 isl_pw_aff_free (aff_nb_iters); 812 isl_space_free (space); 813 return domain; 814 } 815 816 /* NIT is an upper bound to NB_ITERS: "NIT >= NB_ITERS", although we 817 do not know whether the loop executes at least once. */ 818 --nit; 819 820 isl_pw_aff *approx = extract_affine_wi (nit, isl_space_copy (space)); 821 isl_set *x = isl_pw_aff_ge_set (approx, aff_nb_iters); 822 x = isl_set_project_out (x, isl_dim_set, 0, 823 isl_set_dim (x, isl_dim_set)); 824 scop->param_context = isl_set_intersect (scop->param_context, x); 825 826 ls = isl_local_space_from_space (space); 827 c = isl_inequality_alloc (ls); 828 c = isl_constraint_set_coefficient_si (c, isl_dim_set, loop_index, -1); 829 isl_val *v = isl_val_int_from_wi (scop->isl_context, nit); 830 c = isl_constraint_set_constant_val (c, v); 831 832 if (dump_file) 833 { 834 fprintf (dump_file, "[sese-to-poly] adding constraint to the domain: "); 835 print_isl_constraint (dump_file, c); 836 } 837 838 return isl_set_add_constraint (domain, c); 839 } 840 841 /* Builds the original iteration domains for each pbb in the SCOP. */ 842 843 static int 844 build_iteration_domains (scop_p scop, __isl_keep isl_set *context, 845 int index, loop_p context_loop) 846 { 847 loop_p current = pbb_loop (scop->pbbs[index]); 848 isl_set *domain = isl_set_copy (context); 849 domain = add_loop_constraints (scop, domain, current, context_loop); 850 const sese_l ®ion = scop->scop_info->region; 851 852 int i; 853 poly_bb_p pbb; 854 FOR_EACH_VEC_ELT_FROM (scop->pbbs, i, pbb, index) 855 { 856 loop_p loop = pbb_loop (pbb); 857 if (current == loop) 858 { 859 pbb->iterators = isl_set_copy (domain); 860 pbb->domain = isl_set_copy (domain); 861 pbb->domain = isl_set_set_tuple_id (pbb->domain, 862 isl_id_for_pbb (scop, pbb)); 863 add_conditions_to_domain (pbb); 864 865 if (dump_file) 866 { 867 fprintf (dump_file, "[sese-to-poly] set pbb_%d->domain: ", 868 pbb_index (pbb)); 869 print_isl_set (dump_file, domain); 870 } 871 continue; 872 } 873 874 while (loop_in_sese_p (loop, region) 875 && current != loop) 876 loop = loop_outer (loop); 877 878 if (current != loop) 879 { 880 /* A statement in a different loop nest than CURRENT loop. */ 881 isl_set_free (domain); 882 return i; 883 } 884 885 /* A statement nested in the CURRENT loop. */ 886 i = build_iteration_domains (scop, domain, i, current); 887 i--; 888 } 889 890 isl_set_free (domain); 891 return i; 892 } 893 894 /* Assign dimension for each parameter in SCOP and add constraints for the 895 parameters. */ 896 897 static void 898 build_scop_context (scop_p scop) 899 { 900 sese_info_p region = scop->scop_info; 901 unsigned nbp = sese_nb_params (region); 902 isl_space *space = isl_space_set_alloc (scop->isl_context, nbp, 0); 903 904 unsigned i; 905 tree e; 906 FOR_EACH_VEC_ELT (region->params, i, e) 907 space = isl_space_set_dim_id (space, isl_dim_param, i, 908 isl_id_for_ssa_name (scop, e)); 909 910 scop->param_context = isl_set_universe (space); 911 912 graphite_dim_t p; 913 for (p = 0; p < nbp; p++) 914 add_param_constraints (scop, p); 915 } 916 917 /* Return true when loop A is nested in loop B. */ 918 919 static bool 920 nested_in (loop_p a, loop_p b) 921 { 922 return b == find_common_loop (a, b); 923 } 924 925 /* Return the loop at a specific SCOP->pbbs[*INDEX]. */ 926 static loop_p 927 loop_at (scop_p scop, int *index) 928 { 929 return pbb_loop (scop->pbbs[*index]); 930 } 931 932 /* Return the index of any pbb belonging to loop or a subloop of A. */ 933 934 static int 935 index_outermost_in_loop (loop_p a, scop_p scop) 936 { 937 int i, outermost = -1; 938 int last_depth = -1; 939 poly_bb_p pbb; 940 FOR_EACH_VEC_ELT (scop->pbbs, i, pbb) 941 if (nested_in (pbb_loop (pbb), a) 942 && (last_depth == -1 943 || last_depth > (int) loop_depth (pbb_loop (pbb)))) 944 { 945 outermost = i; 946 last_depth = loop_depth (pbb_loop (pbb)); 947 } 948 return outermost; 949 } 950 951 /* Return the index of any pbb belonging to loop or a subloop of A. */ 952 953 static int 954 index_pbb_in_loop (loop_p a, scop_p scop) 955 { 956 int i; 957 poly_bb_p pbb; 958 FOR_EACH_VEC_ELT (scop->pbbs, i, pbb) 959 if (pbb_loop (pbb) == a) 960 return i; 961 return -1; 962 } 963 964 static poly_bb_p 965 outermost_pbb_in (loop_p loop, scop_p scop) 966 { 967 int x = index_pbb_in_loop (loop, scop); 968 if (x == -1) 969 x = index_outermost_in_loop (loop, scop); 970 return scop->pbbs[x]; 971 } 972 973 static isl_schedule * 974 add_in_sequence (__isl_take isl_schedule *a, __isl_take isl_schedule *b) 975 { 976 gcc_assert (a || b); 977 978 if (!a) 979 return b; 980 981 if (!b) 982 return a; 983 984 return isl_schedule_sequence (a, b); 985 } 986 987 struct map_to_dimension_data { 988 int n; 989 isl_union_pw_multi_aff *res; 990 }; 991 992 /* Create a function that maps the elements of SET to its N-th dimension and add 993 it to USER->res. */ 994 995 static isl_stat 996 add_outer_projection (__isl_take isl_set *set, void *user) 997 { 998 struct map_to_dimension_data *data = (struct map_to_dimension_data *) user; 999 int dim = isl_set_dim (set, isl_dim_set); 1000 isl_space *space = isl_set_get_space (set); 1001 1002 gcc_assert (dim >= data->n); 1003 isl_pw_multi_aff *pma 1004 = isl_pw_multi_aff_project_out_map (space, isl_dim_set, data->n, 1005 dim - data->n); 1006 data->res = isl_union_pw_multi_aff_add_pw_multi_aff (data->res, pma); 1007 1008 isl_set_free (set); 1009 return isl_stat_ok; 1010 } 1011 1012 /* Return SET in which all inner dimensions above N are removed. */ 1013 1014 static isl_multi_union_pw_aff * 1015 outer_projection_mupa (__isl_take isl_union_set *set, int n) 1016 { 1017 gcc_assert (n >= 0); 1018 gcc_assert (set); 1019 gcc_assert (!isl_union_set_is_empty (set)); 1020 1021 isl_space *space = isl_union_set_get_space (set); 1022 isl_union_pw_multi_aff *pwaff = isl_union_pw_multi_aff_empty (space); 1023 1024 struct map_to_dimension_data data = {n, pwaff}; 1025 1026 if (isl_union_set_foreach_set (set, &add_outer_projection, &data) < 0) 1027 data.res = isl_union_pw_multi_aff_free (data.res); 1028 1029 isl_union_set_free (set); 1030 return isl_multi_union_pw_aff_from_union_pw_multi_aff (data.res); 1031 } 1032 1033 /* Embed SCHEDULE in the constraints of the LOOP domain. */ 1034 1035 static isl_schedule * 1036 add_loop_schedule (__isl_take isl_schedule *schedule, loop_p loop, 1037 scop_p scop) 1038 { 1039 poly_bb_p pbb = outermost_pbb_in (loop, scop); 1040 isl_set *iterators = pbb->iterators; 1041 1042 int empty = isl_set_is_empty (iterators); 1043 if (empty < 0 || empty) 1044 return empty < 0 ? isl_schedule_free (schedule) : schedule; 1045 1046 isl_space *space = isl_set_get_space (iterators); 1047 int loop_index = isl_space_dim (space, isl_dim_set) - 1; 1048 1049 loop_p ploop = pbb_loop (pbb); 1050 while (loop != ploop) 1051 { 1052 --loop_index; 1053 ploop = loop_outer (ploop); 1054 } 1055 1056 isl_local_space *ls = isl_local_space_from_space (space); 1057 isl_aff *aff = isl_aff_var_on_domain (ls, isl_dim_set, loop_index); 1058 isl_multi_aff *prefix = isl_multi_aff_from_aff (aff); 1059 char name[50]; 1060 snprintf (name, sizeof(name), "L_%d", loop->num); 1061 isl_id *label = isl_id_alloc (isl_schedule_get_ctx (schedule), 1062 name, NULL); 1063 prefix = isl_multi_aff_set_tuple_id (prefix, isl_dim_out, label); 1064 1065 int n = isl_multi_aff_dim (prefix, isl_dim_in); 1066 isl_union_set *domain = isl_schedule_get_domain (schedule); 1067 isl_multi_union_pw_aff *mupa = outer_projection_mupa (domain, n); 1068 mupa = isl_multi_union_pw_aff_apply_multi_aff (mupa, prefix); 1069 return isl_schedule_insert_partial_schedule (schedule, mupa); 1070 } 1071 1072 /* Build schedule for the pbb at INDEX. */ 1073 1074 static isl_schedule * 1075 build_schedule_pbb (scop_p scop, int *index) 1076 { 1077 poly_bb_p pbb = scop->pbbs[*index]; 1078 ++*index; 1079 isl_set *domain = isl_set_copy (pbb->domain); 1080 isl_union_set *ud = isl_union_set_from_set (domain); 1081 return isl_schedule_from_domain (ud); 1082 } 1083 1084 static isl_schedule *build_schedule_loop_nest (scop_p, int *, loop_p); 1085 1086 /* Build the schedule of the loop containing the SCOP pbb at INDEX. */ 1087 1088 static isl_schedule * 1089 build_schedule_loop (scop_p scop, int *index) 1090 { 1091 int max = scop->pbbs.length (); 1092 gcc_assert (*index < max); 1093 loop_p loop = loop_at (scop, index); 1094 1095 isl_schedule *s = NULL; 1096 while (nested_in (loop_at (scop, index), loop)) 1097 { 1098 if (loop == loop_at (scop, index)) 1099 s = add_in_sequence (s, build_schedule_pbb (scop, index)); 1100 else 1101 s = add_in_sequence (s, build_schedule_loop_nest (scop, index, loop)); 1102 1103 if (*index == max) 1104 break; 1105 } 1106 1107 return add_loop_schedule (s, loop, scop); 1108 } 1109 1110 /* S is the schedule of the loop LOOP. Embed the schedule S in all outer loops. 1111 When CONTEXT_LOOP is null, embed the schedule in all loops contained in the 1112 SCOP surrounding LOOP. When CONTEXT_LOOP is non null, only embed S in the 1113 maximal loop nest contained within CONTEXT_LOOP. */ 1114 1115 static isl_schedule * 1116 embed_in_surrounding_loops (__isl_take isl_schedule *s, scop_p scop, 1117 loop_p loop, int *index, loop_p context_loop) 1118 { 1119 loop_p outer = loop_outer (loop); 1120 sese_l region = scop->scop_info->region; 1121 if (context_loop == outer 1122 || !loop_in_sese_p (outer, region)) 1123 return s; 1124 1125 int max = scop->pbbs.length (); 1126 if (*index == max 1127 || (context_loop && !nested_in (loop_at (scop, index), context_loop)) 1128 || (!context_loop 1129 && !loop_in_sese_p (find_common_loop (outer, loop_at (scop, index)), 1130 region))) 1131 return embed_in_surrounding_loops (add_loop_schedule (s, outer, scop), 1132 scop, outer, index, context_loop); 1133 1134 bool a_pbb; 1135 while ((a_pbb = (outer == loop_at (scop, index))) 1136 || nested_in (loop_at (scop, index), outer)) 1137 { 1138 if (a_pbb) 1139 s = add_in_sequence (s, build_schedule_pbb (scop, index)); 1140 else 1141 s = add_in_sequence (s, build_schedule_loop (scop, index)); 1142 1143 if (*index == max) 1144 break; 1145 } 1146 1147 /* We reached the end of the OUTER loop: embed S in OUTER. */ 1148 return embed_in_surrounding_loops (add_loop_schedule (s, outer, scop), scop, 1149 outer, index, context_loop); 1150 } 1151 1152 /* Build schedule for the full loop nest containing the pbb at INDEX. When 1153 CONTEXT_LOOP is null, build the schedule of all loops contained in the SCOP 1154 surrounding the pbb. When CONTEXT_LOOP is non null, only build the maximal loop 1155 nest contained within CONTEXT_LOOP. */ 1156 1157 static isl_schedule * 1158 build_schedule_loop_nest (scop_p scop, int *index, loop_p context_loop) 1159 { 1160 gcc_assert (*index != (int) scop->pbbs.length ()); 1161 1162 loop_p loop = loop_at (scop, index); 1163 isl_schedule *s = build_schedule_loop (scop, index); 1164 return embed_in_surrounding_loops (s, scop, loop, index, context_loop); 1165 } 1166 1167 /* Build the schedule of the SCOP. */ 1168 1169 static bool 1170 build_original_schedule (scop_p scop) 1171 { 1172 int i = 0; 1173 int n = scop->pbbs.length (); 1174 while (i < n) 1175 { 1176 poly_bb_p pbb = scop->pbbs[i]; 1177 isl_schedule *s = NULL; 1178 if (!loop_in_sese_p (pbb_loop (pbb), scop->scop_info->region)) 1179 s = build_schedule_pbb (scop, &i); 1180 else 1181 s = build_schedule_loop_nest (scop, &i, NULL); 1182 1183 scop->original_schedule = add_in_sequence (scop->original_schedule, s); 1184 } 1185 1186 if (dump_file) 1187 { 1188 fprintf (dump_file, "[sese-to-poly] original schedule:\n"); 1189 print_isl_schedule (dump_file, scop->original_schedule); 1190 } 1191 if (!scop->original_schedule) 1192 return false; 1193 return true; 1194 } 1195 1196 /* Builds the polyhedral representation for a SESE region. */ 1197 1198 bool 1199 build_poly_scop (scop_p scop) 1200 { 1201 build_scop_context (scop); 1202 1203 unsigned i = 0; 1204 unsigned n = scop->pbbs.length (); 1205 while (i < n) 1206 i = build_iteration_domains (scop, scop->param_context, i, NULL); 1207 1208 build_scop_drs (scop); 1209 build_original_schedule (scop); 1210 return true; 1211 } 1212 #endif /* HAVE_isl */ 1213