1 /* Conversion of SESE regions to Polyhedra. 2 Copyright (C) 2009-2019 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 /* Return an isl identifier for the polyhedral basic block PBB. */ 62 63 static isl_id * 64 isl_id_for_pbb (scop_p s, poly_bb_p pbb) 65 { 66 char name[14]; 67 snprintf (name, sizeof (name), "S_%d", pbb_index (pbb)); 68 return isl_id_alloc (s->isl_context, name, pbb); 69 } 70 71 static isl_pw_aff *extract_affine (scop_p, tree, __isl_take isl_space *space); 72 73 /* Extract an affine expression from the chain of recurrence E. */ 74 75 static isl_pw_aff * 76 extract_affine_chrec (scop_p s, tree e, __isl_take isl_space *space) 77 { 78 isl_pw_aff *lhs = extract_affine (s, CHREC_LEFT (e), isl_space_copy (space)); 79 isl_pw_aff *rhs = extract_affine (s, CHREC_RIGHT (e), isl_space_copy (space)); 80 isl_local_space *ls = isl_local_space_from_space (space); 81 unsigned pos = sese_loop_depth (s->scop_info->region, get_chrec_loop (e)) - 1; 82 isl_aff *loop = isl_aff_set_coefficient_si 83 (isl_aff_zero_on_domain (ls), isl_dim_in, pos, 1); 84 isl_pw_aff *l = isl_pw_aff_from_aff (loop); 85 86 /* Before multiplying, make sure that the result is affine. */ 87 gcc_assert (isl_pw_aff_is_cst (rhs) 88 || isl_pw_aff_is_cst (l)); 89 90 return isl_pw_aff_add (lhs, isl_pw_aff_mul (rhs, l)); 91 } 92 93 /* Extract an affine expression from the mult_expr E. */ 94 95 static isl_pw_aff * 96 extract_affine_mul (scop_p s, tree e, __isl_take isl_space *space) 97 { 98 isl_pw_aff *lhs = extract_affine (s, TREE_OPERAND (e, 0), 99 isl_space_copy (space)); 100 isl_pw_aff *rhs = extract_affine (s, TREE_OPERAND (e, 1), space); 101 102 if (!isl_pw_aff_is_cst (lhs) 103 && !isl_pw_aff_is_cst (rhs)) 104 { 105 isl_pw_aff_free (lhs); 106 isl_pw_aff_free (rhs); 107 return NULL; 108 } 109 110 return isl_pw_aff_mul (lhs, rhs); 111 } 112 113 /* Return an isl identifier from the name of the ssa_name E. */ 114 115 static isl_id * 116 isl_id_for_ssa_name (scop_p s, tree e) 117 { 118 char name1[14]; 119 snprintf (name1, sizeof (name1), "P_%d", SSA_NAME_VERSION (e)); 120 return isl_id_alloc (s->isl_context, name1, e); 121 } 122 123 /* Return an isl identifier for the data reference DR. Data references and 124 scalar references get the same isl_id. They need to be comparable and are 125 distinguished through the first dimension, which contains the alias set or 126 SSA_NAME_VERSION number. */ 127 128 static isl_id * 129 isl_id_for_dr (scop_p s) 130 { 131 return isl_id_alloc (s->isl_context, "", 0); 132 } 133 134 /* Extract an affine expression from the ssa_name E. */ 135 136 static isl_pw_aff * 137 extract_affine_name (int dimension, __isl_take isl_space *space) 138 { 139 isl_set *dom = isl_set_universe (isl_space_copy (space)); 140 isl_aff *aff = isl_aff_zero_on_domain (isl_local_space_from_space (space)); 141 aff = isl_aff_add_coefficient_si (aff, isl_dim_param, dimension, 1); 142 return isl_pw_aff_alloc (dom, aff); 143 } 144 145 /* Convert WI to a isl_val with CTX. */ 146 147 static __isl_give isl_val * 148 isl_val_int_from_wi (isl_ctx *ctx, const widest_int &wi) 149 { 150 if (wi::neg_p (wi, SIGNED)) 151 { 152 widest_int mwi = -wi; 153 return isl_val_neg (isl_val_int_from_chunks (ctx, mwi.get_len (), 154 sizeof (HOST_WIDE_INT), 155 mwi.get_val ())); 156 } 157 return isl_val_int_from_chunks (ctx, wi.get_len (), sizeof (HOST_WIDE_INT), 158 wi.get_val ()); 159 } 160 161 /* Extract an affine expression from the gmp constant G. */ 162 163 static isl_pw_aff * 164 extract_affine_wi (const widest_int &g, __isl_take isl_space *space) 165 { 166 isl_local_space *ls = isl_local_space_from_space (isl_space_copy (space)); 167 isl_aff *aff = isl_aff_zero_on_domain (ls); 168 isl_set *dom = isl_set_universe (space); 169 isl_ctx *ct = isl_aff_get_ctx (aff); 170 isl_val *v = isl_val_int_from_wi (ct, g); 171 aff = isl_aff_add_constant_val (aff, v); 172 173 return isl_pw_aff_alloc (dom, aff); 174 } 175 176 /* Extract an affine expression from the integer_cst E. */ 177 178 static isl_pw_aff * 179 extract_affine_int (tree e, __isl_take isl_space *space) 180 { 181 isl_pw_aff *res = extract_affine_wi (wi::to_widest (e), space); 182 return res; 183 } 184 185 /* Compute pwaff mod 2^width. */ 186 187 static isl_pw_aff * 188 wrap (isl_pw_aff *pwaff, unsigned width) 189 { 190 isl_val *mod; 191 192 mod = isl_val_int_from_ui (isl_pw_aff_get_ctx (pwaff), width); 193 mod = isl_val_2exp (mod); 194 pwaff = isl_pw_aff_mod_val (pwaff, mod); 195 196 return pwaff; 197 } 198 199 /* When parameter NAME is in REGION, returns its index in SESE_PARAMS. 200 Otherwise returns -1. */ 201 202 static inline int 203 parameter_index_in_region (tree name, sese_info_p region) 204 { 205 int i; 206 tree p; 207 FOR_EACH_VEC_ELT (region->params, i, p) 208 if (p == name) 209 return i; 210 return -1; 211 } 212 213 /* Extract an affine expression from the tree E in the scop S. */ 214 215 static isl_pw_aff * 216 extract_affine (scop_p s, tree e, __isl_take isl_space *space) 217 { 218 isl_pw_aff *lhs, *rhs, *res; 219 220 if (e == chrec_dont_know) { 221 isl_space_free (space); 222 return NULL; 223 } 224 225 tree type = TREE_TYPE (e); 226 switch (TREE_CODE (e)) 227 { 228 case POLYNOMIAL_CHREC: 229 res = extract_affine_chrec (s, e, space); 230 break; 231 232 case MULT_EXPR: 233 res = extract_affine_mul (s, e, space); 234 break; 235 236 case POINTER_PLUS_EXPR: 237 { 238 lhs = extract_affine (s, TREE_OPERAND (e, 0), isl_space_copy (space)); 239 /* The RHS of a pointer-plus expression is to be interpreted 240 as signed value. Try to look through a sign-changing conversion 241 first. */ 242 tree tem = TREE_OPERAND (e, 1); 243 STRIP_NOPS (tem); 244 rhs = extract_affine (s, tem, space); 245 if (TYPE_UNSIGNED (TREE_TYPE (tem))) 246 rhs = wrap (rhs, TYPE_PRECISION (type) - 1); 247 res = isl_pw_aff_add (lhs, rhs); 248 break; 249 } 250 251 case 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 BIT_NOT_EXPR: 264 lhs = extract_affine (s, integer_minus_one_node, isl_space_copy (space)); 265 rhs = extract_affine (s, TREE_OPERAND (e, 0), space); 266 res = isl_pw_aff_sub (lhs, rhs); 267 /* We need to always wrap the result of a bitwise operation. */ 268 return wrap (res, TYPE_PRECISION (type) - (TYPE_UNSIGNED (type) ? 0 : 1)); 269 270 case NEGATE_EXPR: 271 lhs = extract_affine (s, TREE_OPERAND (e, 0), isl_space_copy (space)); 272 rhs = extract_affine (s, integer_minus_one_node, space); 273 res = isl_pw_aff_mul (lhs, rhs); 274 break; 275 276 case SSA_NAME: 277 { 278 gcc_assert (! defined_in_sese_p (e, s->scop_info->region)); 279 int dim = parameter_index_in_region (e, s->scop_info); 280 gcc_assert (dim != -1); 281 /* No need to wrap a parameter. */ 282 return extract_affine_name (dim, space); 283 } 284 285 case INTEGER_CST: 286 res = extract_affine_int (e, space); 287 /* No need to wrap a single integer. */ 288 return res; 289 290 CASE_CONVERT: 291 { 292 tree itype = TREE_TYPE (TREE_OPERAND (e, 0)); 293 res = extract_affine (s, TREE_OPERAND (e, 0), space); 294 /* Signed values, even if overflow is undefined, get modulo-reduced. 295 But only if not all values of the old type fit in the new. */ 296 if (! TYPE_UNSIGNED (type) 297 && ((TYPE_UNSIGNED (itype) 298 && TYPE_PRECISION (type) <= TYPE_PRECISION (itype)) 299 || TYPE_PRECISION (type) < TYPE_PRECISION (itype))) 300 res = wrap (res, TYPE_PRECISION (type) - 1); 301 else if (TYPE_UNSIGNED (type) 302 && (!TYPE_UNSIGNED (itype) 303 || TYPE_PRECISION (type) < TYPE_PRECISION (itype))) 304 res = wrap (res, TYPE_PRECISION (type)); 305 return res; 306 } 307 308 case NON_LVALUE_EXPR: 309 res = extract_affine (s, TREE_OPERAND (e, 0), space); 310 break; 311 312 default: 313 gcc_unreachable (); 314 break; 315 } 316 317 /* For all wrapping arithmetic wrap the result. */ 318 if (TYPE_OVERFLOW_WRAPS (type)) 319 res = wrap (res, TYPE_PRECISION (type)); 320 321 return res; 322 } 323 324 /* Returns a linear expression for tree T evaluated in PBB. */ 325 326 static isl_pw_aff * 327 create_pw_aff_from_tree (poly_bb_p pbb, loop_p loop, tree t) 328 { 329 scop_p scop = PBB_SCOP (pbb); 330 331 t = cached_scalar_evolution_in_region (scop->scop_info->region, loop, t); 332 333 gcc_assert (!chrec_contains_undetermined (t)); 334 gcc_assert (!automatically_generated_chrec_p (t)); 335 336 return extract_affine (scop, t, isl_set_get_space (pbb->domain)); 337 } 338 339 /* Add conditional statement STMT to pbb. CODE is used as the comparison 340 operator. This allows us to invert the condition or to handle 341 inequalities. */ 342 343 static void 344 add_condition_to_pbb (poly_bb_p pbb, gcond *stmt, enum tree_code code) 345 { 346 loop_p loop = gimple_bb (stmt)->loop_father; 347 isl_pw_aff *lhs = create_pw_aff_from_tree (pbb, loop, gimple_cond_lhs (stmt)); 348 isl_pw_aff *rhs = create_pw_aff_from_tree (pbb, loop, gimple_cond_rhs (stmt)); 349 350 isl_set *cond; 351 switch (code) 352 { 353 case LT_EXPR: 354 cond = isl_pw_aff_lt_set (lhs, rhs); 355 break; 356 357 case GT_EXPR: 358 cond = isl_pw_aff_gt_set (lhs, rhs); 359 break; 360 361 case LE_EXPR: 362 cond = isl_pw_aff_le_set (lhs, rhs); 363 break; 364 365 case GE_EXPR: 366 cond = isl_pw_aff_ge_set (lhs, rhs); 367 break; 368 369 case EQ_EXPR: 370 cond = isl_pw_aff_eq_set (lhs, rhs); 371 break; 372 373 case NE_EXPR: 374 cond = isl_pw_aff_ne_set (lhs, rhs); 375 break; 376 377 default: 378 gcc_unreachable (); 379 } 380 381 cond = isl_set_coalesce (cond); 382 cond = isl_set_set_tuple_id (cond, isl_set_get_tuple_id (pbb->domain)); 383 pbb->domain = isl_set_coalesce (isl_set_intersect (pbb->domain, cond)); 384 } 385 386 /* Add conditions to the domain of PBB. */ 387 388 static void 389 add_conditions_to_domain (poly_bb_p pbb) 390 { 391 unsigned int i; 392 gimple *stmt; 393 gimple_poly_bb_p gbb = PBB_BLACK_BOX (pbb); 394 395 if (GBB_CONDITIONS (gbb).is_empty ()) 396 return; 397 398 FOR_EACH_VEC_ELT (GBB_CONDITIONS (gbb), i, stmt) 399 switch (gimple_code (stmt)) 400 { 401 case GIMPLE_COND: 402 { 403 /* Don't constrain on anything else than INTEGER_TYPE. */ 404 if (TREE_CODE (TREE_TYPE (gimple_cond_lhs (stmt))) != INTEGER_TYPE) 405 break; 406 407 gcond *cond_stmt = as_a <gcond *> (stmt); 408 enum tree_code code = gimple_cond_code (cond_stmt); 409 410 /* The conditions for ELSE-branches are inverted. */ 411 if (!GBB_CONDITION_CASES (gbb)[i]) 412 code = invert_tree_comparison (code, false); 413 414 add_condition_to_pbb (pbb, cond_stmt, code); 415 break; 416 } 417 418 default: 419 gcc_unreachable (); 420 break; 421 } 422 } 423 424 /* Add constraints on the possible values of parameter P from the type 425 of P. */ 426 427 static void 428 add_param_constraints (scop_p scop, graphite_dim_t p, tree parameter) 429 { 430 tree type = TREE_TYPE (parameter); 431 wide_int min, max; 432 433 gcc_assert (INTEGRAL_TYPE_P (type) || POINTER_TYPE_P (type)); 434 435 if (INTEGRAL_TYPE_P (type) 436 && get_range_info (parameter, &min, &max) == VR_RANGE) 437 ; 438 else 439 { 440 min = wi::min_value (TYPE_PRECISION (type), TYPE_SIGN (type)); 441 max = wi::max_value (TYPE_PRECISION (type), TYPE_SIGN (type)); 442 } 443 444 isl_space *space = isl_set_get_space (scop->param_context); 445 isl_constraint *c = isl_inequality_alloc (isl_local_space_from_space (space)); 446 isl_val *v = isl_val_int_from_wi (scop->isl_context, 447 widest_int::from (min, TYPE_SIGN (type))); 448 v = isl_val_neg (v); 449 c = isl_constraint_set_constant_val (c, v); 450 c = isl_constraint_set_coefficient_si (c, isl_dim_param, p, 1); 451 scop->param_context = isl_set_coalesce 452 (isl_set_add_constraint (scop->param_context, c)); 453 454 space = isl_set_get_space (scop->param_context); 455 c = isl_inequality_alloc (isl_local_space_from_space (space)); 456 v = isl_val_int_from_wi (scop->isl_context, 457 widest_int::from (max, TYPE_SIGN (type))); 458 c = isl_constraint_set_constant_val (c, v); 459 c = isl_constraint_set_coefficient_si (c, isl_dim_param, p, -1); 460 scop->param_context = isl_set_coalesce 461 (isl_set_add_constraint (scop->param_context, c)); 462 } 463 464 /* Add a constrain to the ACCESSES polyhedron for the alias set of 465 data reference DR. ACCESSP_NB_DIMS is the dimension of the 466 ACCESSES polyhedron, DOM_NB_DIMS is the dimension of the iteration 467 domain. */ 468 469 static isl_map * 470 pdr_add_alias_set (isl_map *acc, dr_info &dri) 471 { 472 isl_constraint *c = isl_equality_alloc 473 (isl_local_space_from_space (isl_map_get_space (acc))); 474 /* Positive numbers for all alias sets. */ 475 c = isl_constraint_set_constant_si (c, -dri.alias_set); 476 c = isl_constraint_set_coefficient_si (c, isl_dim_out, 0, 1); 477 478 return isl_map_add_constraint (acc, c); 479 } 480 481 /* Assign the affine expression INDEX to the output dimension POS of 482 MAP and return the result. */ 483 484 static isl_map * 485 set_index (isl_map *map, int pos, isl_pw_aff *index) 486 { 487 isl_map *index_map; 488 int len = isl_map_dim (map, isl_dim_out); 489 isl_id *id; 490 491 index_map = isl_map_from_pw_aff (index); 492 index_map = isl_map_insert_dims (index_map, isl_dim_out, 0, pos); 493 index_map = isl_map_add_dims (index_map, isl_dim_out, len - pos - 1); 494 495 id = isl_map_get_tuple_id (map, isl_dim_out); 496 index_map = isl_map_set_tuple_id (index_map, isl_dim_out, id); 497 id = isl_map_get_tuple_id (map, isl_dim_in); 498 index_map = isl_map_set_tuple_id (index_map, isl_dim_in, id); 499 500 return isl_map_intersect (map, index_map); 501 } 502 503 /* Add to ACCESSES polyhedron equalities defining the access functions 504 to the memory. ACCESSP_NB_DIMS is the dimension of the ACCESSES 505 polyhedron, DOM_NB_DIMS is the dimension of the iteration domain. 506 PBB is the poly_bb_p that contains the data reference DR. */ 507 508 static isl_map * 509 pdr_add_memory_accesses (isl_map *acc, dr_info &dri) 510 { 511 data_reference_p dr = dri.dr; 512 poly_bb_p pbb = dri.pbb; 513 int i, nb_subscripts = DR_NUM_DIMENSIONS (dr); 514 scop_p scop = PBB_SCOP (pbb); 515 516 for (i = 0; i < nb_subscripts; i++) 517 { 518 isl_pw_aff *aff; 519 tree afn = DR_ACCESS_FN (dr, i); 520 521 aff = extract_affine (scop, afn, 522 isl_space_domain (isl_map_get_space (acc))); 523 acc = set_index (acc, nb_subscripts - i , aff); 524 } 525 526 return isl_map_coalesce (acc); 527 } 528 529 /* Return true when the LOW and HIGH bounds of an array reference REF are valid 530 to extract constraints on accessed elements of the array. Returning false is 531 the conservative answer. */ 532 533 static bool 534 bounds_are_valid (tree ref, tree low, tree high) 535 { 536 if (!high) 537 return false; 538 539 if (!tree_fits_shwi_p (low) 540 || !tree_fits_shwi_p (high)) 541 return false; 542 543 /* 1-element arrays at end of structures may extend over 544 their declared size. */ 545 if (array_at_struct_end_p (ref) 546 && operand_equal_p (low, high, 0)) 547 return false; 548 549 /* Fortran has some arrays where high bound is -1 and low is 0. */ 550 if (integer_onep (fold_build2 (LT_EXPR, boolean_type_node, high, low))) 551 return false; 552 553 return true; 554 } 555 556 /* Add constrains representing the size of the accessed data to the 557 ACCESSES polyhedron. ACCESSP_NB_DIMS is the dimension of the 558 ACCESSES polyhedron, DOM_NB_DIMS is the dimension of the iteration 559 domain. */ 560 561 static isl_set * 562 pdr_add_data_dimensions (isl_set *subscript_sizes, scop_p scop, 563 data_reference_p dr) 564 { 565 tree ref = DR_REF (dr); 566 567 int nb_subscripts = DR_NUM_DIMENSIONS (dr); 568 for (int i = nb_subscripts - 1; i >= 0; i--, ref = TREE_OPERAND (ref, 0)) 569 { 570 if (TREE_CODE (ref) != ARRAY_REF) 571 return subscript_sizes; 572 573 tree low = array_ref_low_bound (ref); 574 tree high = array_ref_up_bound (ref); 575 576 if (!bounds_are_valid (ref, low, high)) 577 continue; 578 579 isl_space *space = isl_set_get_space (subscript_sizes); 580 isl_pw_aff *lb = extract_affine_int (low, isl_space_copy (space)); 581 isl_pw_aff *ub = extract_affine_int (high, isl_space_copy (space)); 582 583 /* high >= 0 */ 584 isl_set *valid = isl_pw_aff_nonneg_set (isl_pw_aff_copy (ub)); 585 valid = isl_set_project_out (valid, isl_dim_set, 0, 586 isl_set_dim (valid, isl_dim_set)); 587 scop->param_context = isl_set_coalesce 588 (isl_set_intersect (scop->param_context, valid)); 589 590 isl_aff *aff 591 = isl_aff_zero_on_domain (isl_local_space_from_space (space)); 592 aff = isl_aff_add_coefficient_si (aff, isl_dim_in, i + 1, 1); 593 isl_set *univ 594 = isl_set_universe (isl_space_domain (isl_aff_get_space (aff))); 595 isl_pw_aff *index = isl_pw_aff_alloc (univ, aff); 596 597 isl_id *id = isl_set_get_tuple_id (subscript_sizes); 598 lb = isl_pw_aff_set_tuple_id (lb, isl_dim_in, isl_id_copy (id)); 599 ub = isl_pw_aff_set_tuple_id (ub, isl_dim_in, id); 600 601 /* low <= sub_i <= high */ 602 isl_set *lbs = isl_pw_aff_ge_set (isl_pw_aff_copy (index), lb); 603 isl_set *ubs = isl_pw_aff_le_set (index, ub); 604 subscript_sizes = isl_set_intersect (subscript_sizes, lbs); 605 subscript_sizes = isl_set_intersect (subscript_sizes, ubs); 606 } 607 608 return isl_set_coalesce (subscript_sizes); 609 } 610 611 /* Build data accesses for DRI. */ 612 613 static void 614 build_poly_dr (dr_info &dri) 615 { 616 isl_map *acc; 617 isl_set *subscript_sizes; 618 poly_bb_p pbb = dri.pbb; 619 data_reference_p dr = dri.dr; 620 scop_p scop = PBB_SCOP (pbb); 621 isl_id *id = isl_id_for_dr (scop); 622 623 { 624 isl_space *dc = isl_set_get_space (pbb->domain); 625 int nb_out = 1 + DR_NUM_DIMENSIONS (dr); 626 isl_space *space = isl_space_add_dims (isl_space_from_domain (dc), 627 isl_dim_out, nb_out); 628 629 acc = isl_map_universe (space); 630 acc = isl_map_set_tuple_id (acc, isl_dim_out, isl_id_copy (id)); 631 } 632 633 acc = pdr_add_alias_set (acc, dri); 634 acc = pdr_add_memory_accesses (acc, dri); 635 636 { 637 int nb = 1 + DR_NUM_DIMENSIONS (dr); 638 isl_space *space = isl_space_set_alloc (scop->isl_context, 0, nb); 639 640 space = isl_space_set_tuple_id (space, isl_dim_set, id); 641 subscript_sizes = isl_set_nat_universe (space); 642 subscript_sizes = isl_set_fix_si (subscript_sizes, isl_dim_set, 0, 643 dri.alias_set); 644 subscript_sizes = pdr_add_data_dimensions (subscript_sizes, scop, dr); 645 } 646 647 new_poly_dr (pbb, DR_STMT (dr), DR_IS_READ (dr) ? PDR_READ : PDR_WRITE, 648 acc, subscript_sizes); 649 } 650 651 static void 652 build_poly_sr_1 (poly_bb_p pbb, gimple *stmt, tree var, enum poly_dr_type kind, 653 isl_map *acc, isl_set *subscript_sizes) 654 { 655 scop_p scop = PBB_SCOP (pbb); 656 /* Each scalar variables has a unique alias set number starting from 657 the maximum alias set assigned to a dr. */ 658 int alias_set = scop->max_alias_set + SSA_NAME_VERSION (var); 659 subscript_sizes = isl_set_fix_si (subscript_sizes, isl_dim_set, 0, 660 alias_set); 661 662 /* Add a constrain to the ACCESSES polyhedron for the alias set of 663 data reference DR. */ 664 isl_constraint *c 665 = isl_equality_alloc (isl_local_space_from_space (isl_map_get_space (acc))); 666 c = isl_constraint_set_constant_si (c, -alias_set); 667 c = isl_constraint_set_coefficient_si (c, isl_dim_out, 0, 1); 668 669 new_poly_dr (pbb, stmt, kind, isl_map_add_constraint (acc, c), 670 subscript_sizes); 671 } 672 673 /* Record all cross basic block scalar variables in PBB. */ 674 675 static void 676 build_poly_sr (poly_bb_p pbb) 677 { 678 scop_p scop = PBB_SCOP (pbb); 679 gimple_poly_bb_p gbb = PBB_BLACK_BOX (pbb); 680 vec<scalar_use> &reads = gbb->read_scalar_refs; 681 vec<tree> &writes = gbb->write_scalar_refs; 682 683 isl_space *dc = isl_set_get_space (pbb->domain); 684 int nb_out = 1; 685 isl_space *space = isl_space_add_dims (isl_space_from_domain (dc), 686 isl_dim_out, nb_out); 687 isl_id *id = isl_id_for_dr (scop); 688 space = isl_space_set_tuple_id (space, isl_dim_set, isl_id_copy (id)); 689 isl_map *acc = isl_map_universe (isl_space_copy (space)); 690 acc = isl_map_set_tuple_id (acc, isl_dim_out, id); 691 isl_set *subscript_sizes = isl_set_nat_universe (space); 692 693 int i; 694 tree var; 695 FOR_EACH_VEC_ELT (writes, i, var) 696 build_poly_sr_1 (pbb, SSA_NAME_DEF_STMT (var), var, PDR_WRITE, 697 isl_map_copy (acc), isl_set_copy (subscript_sizes)); 698 699 scalar_use *use; 700 FOR_EACH_VEC_ELT (reads, i, use) 701 build_poly_sr_1 (pbb, use->first, use->second, PDR_READ, isl_map_copy (acc), 702 isl_set_copy (subscript_sizes)); 703 704 isl_map_free (acc); 705 isl_set_free (subscript_sizes); 706 } 707 708 /* Build data references in SCOP. */ 709 710 static void 711 build_scop_drs (scop_p scop) 712 { 713 int i; 714 dr_info *dri; 715 FOR_EACH_VEC_ELT (scop->drs, i, dri) 716 build_poly_dr (*dri); 717 718 poly_bb_p pbb; 719 FOR_EACH_VEC_ELT (scop->pbbs, i, pbb) 720 build_poly_sr (pbb); 721 } 722 723 /* Add to the iteration DOMAIN one extra dimension for LOOP->num. */ 724 725 static isl_set * 726 add_iter_domain_dimension (__isl_take isl_set *domain, loop_p loop, scop_p scop) 727 { 728 int loop_index = isl_set_dim (domain, isl_dim_set); 729 domain = isl_set_add_dims (domain, isl_dim_set, 1); 730 char name[50]; 731 snprintf (name, sizeof(name), "i%d", loop->num); 732 isl_id *label = isl_id_alloc (scop->isl_context, name, NULL); 733 return isl_set_set_dim_id (domain, isl_dim_set, loop_index, label); 734 } 735 736 /* Add constraints to DOMAIN for each loop from LOOP up to CONTEXT. */ 737 738 static isl_set * 739 add_loop_constraints (scop_p scop, __isl_take isl_set *domain, loop_p loop, 740 loop_p context) 741 { 742 if (loop == context) 743 return domain; 744 const sese_l ®ion = scop->scop_info->region; 745 if (!loop_in_sese_p (loop, region)) 746 return domain; 747 748 /* Recursion all the way up to the context loop. */ 749 domain = add_loop_constraints (scop, domain, loop_outer (loop), context); 750 751 /* Then, build constraints over the loop in post-order: outer to inner. */ 752 753 int loop_index = isl_set_dim (domain, isl_dim_set); 754 if (dump_file) 755 fprintf (dump_file, "[sese-to-poly] adding one extra dimension to the " 756 "domain for loop_%d.\n", loop->num); 757 domain = add_iter_domain_dimension (domain, loop, scop); 758 isl_space *space = isl_set_get_space (domain); 759 760 /* 0 <= loop_i */ 761 isl_local_space *ls = isl_local_space_from_space (isl_space_copy (space)); 762 isl_constraint *c = isl_inequality_alloc (ls); 763 c = isl_constraint_set_coefficient_si (c, isl_dim_set, loop_index, 1); 764 if (dump_file) 765 { 766 fprintf (dump_file, "[sese-to-poly] adding constraint to the domain: "); 767 print_isl_constraint (dump_file, c); 768 } 769 domain = isl_set_add_constraint (domain, c); 770 771 tree nb_iters = number_of_latch_executions (loop); 772 if (TREE_CODE (nb_iters) == INTEGER_CST) 773 { 774 /* loop_i <= cst_nb_iters */ 775 isl_local_space *ls = isl_local_space_from_space (space); 776 isl_constraint *c = isl_inequality_alloc (ls); 777 c = isl_constraint_set_coefficient_si (c, isl_dim_set, loop_index, -1); 778 isl_val *v 779 = isl_val_int_from_wi (scop->isl_context, wi::to_widest (nb_iters)); 780 c = isl_constraint_set_constant_val (c, v); 781 return isl_set_add_constraint (domain, c); 782 } 783 /* loop_i <= expr_nb_iters */ 784 gcc_assert (!chrec_contains_undetermined (nb_iters)); 785 nb_iters = cached_scalar_evolution_in_region (region, loop, nb_iters); 786 gcc_assert (!chrec_contains_undetermined (nb_iters)); 787 788 isl_pw_aff *aff_nb_iters = extract_affine (scop, nb_iters, 789 isl_space_copy (space)); 790 isl_set *valid = isl_pw_aff_nonneg_set (isl_pw_aff_copy (aff_nb_iters)); 791 valid = isl_set_project_out (valid, isl_dim_set, 0, 792 isl_set_dim (valid, isl_dim_set)); 793 794 if (valid) 795 scop->param_context = isl_set_intersect (scop->param_context, valid); 796 797 ls = isl_local_space_from_space (isl_space_copy (space)); 798 isl_aff *loop_i = isl_aff_set_coefficient_si (isl_aff_zero_on_domain (ls), 799 isl_dim_in, loop_index, 1); 800 isl_set *le = isl_pw_aff_le_set (isl_pw_aff_from_aff (loop_i), 801 isl_pw_aff_copy (aff_nb_iters)); 802 if (dump_file) 803 { 804 fprintf (dump_file, "[sese-to-poly] adding constraint to the domain: "); 805 print_isl_set (dump_file, le); 806 } 807 domain = isl_set_intersect (domain, le); 808 809 widest_int nit; 810 if (!max_stmt_executions (loop, &nit)) 811 { 812 isl_pw_aff_free (aff_nb_iters); 813 isl_space_free (space); 814 return domain; 815 } 816 817 /* NIT is an upper bound to NB_ITERS: "NIT >= NB_ITERS", although we 818 do not know whether the loop executes at least once. */ 819 --nit; 820 821 isl_pw_aff *approx = extract_affine_wi (nit, isl_space_copy (space)); 822 isl_set *x = isl_pw_aff_ge_set (approx, aff_nb_iters); 823 x = isl_set_project_out (x, isl_dim_set, 0, 824 isl_set_dim (x, isl_dim_set)); 825 scop->param_context = isl_set_intersect (scop->param_context, x); 826 827 ls = isl_local_space_from_space (space); 828 c = isl_inequality_alloc (ls); 829 c = isl_constraint_set_coefficient_si (c, isl_dim_set, loop_index, -1); 830 isl_val *v = isl_val_int_from_wi (scop->isl_context, nit); 831 c = isl_constraint_set_constant_val (c, v); 832 833 if (dump_file) 834 { 835 fprintf (dump_file, "[sese-to-poly] adding constraint to the domain: "); 836 print_isl_constraint (dump_file, c); 837 } 838 839 return isl_set_add_constraint (domain, c); 840 } 841 842 /* Builds the original iteration domains for each pbb in the SCOP. */ 843 844 static int 845 build_iteration_domains (scop_p scop, __isl_keep isl_set *context, 846 int index, loop_p context_loop) 847 { 848 loop_p current = pbb_loop (scop->pbbs[index]); 849 isl_set *domain = isl_set_copy (context); 850 domain = add_loop_constraints (scop, domain, current, context_loop); 851 const sese_l ®ion = scop->scop_info->region; 852 853 int i; 854 poly_bb_p pbb; 855 FOR_EACH_VEC_ELT_FROM (scop->pbbs, i, pbb, index) 856 { 857 loop_p loop = pbb_loop (pbb); 858 if (current == loop) 859 { 860 pbb->iterators = isl_set_copy (domain); 861 pbb->domain = isl_set_copy (domain); 862 pbb->domain = isl_set_set_tuple_id (pbb->domain, 863 isl_id_for_pbb (scop, pbb)); 864 add_conditions_to_domain (pbb); 865 866 if (dump_file) 867 { 868 fprintf (dump_file, "[sese-to-poly] set pbb_%d->domain: ", 869 pbb_index (pbb)); 870 print_isl_set (dump_file, domain); 871 } 872 continue; 873 } 874 875 while (loop_in_sese_p (loop, region) 876 && current != loop) 877 loop = loop_outer (loop); 878 879 if (current != loop) 880 { 881 /* A statement in a different loop nest than CURRENT loop. */ 882 isl_set_free (domain); 883 return i; 884 } 885 886 /* A statement nested in the CURRENT loop. */ 887 i = build_iteration_domains (scop, domain, i, current); 888 i--; 889 } 890 891 isl_set_free (domain); 892 return i; 893 } 894 895 /* Assign dimension for each parameter in SCOP and add constraints for the 896 parameters. */ 897 898 static void 899 build_scop_context (scop_p scop) 900 { 901 sese_info_p region = scop->scop_info; 902 unsigned nbp = sese_nb_params (region); 903 isl_space *space = isl_space_set_alloc (scop->isl_context, nbp, 0); 904 905 unsigned i; 906 tree e; 907 FOR_EACH_VEC_ELT (region->params, i, e) 908 space = isl_space_set_dim_id (space, isl_dim_param, i, 909 isl_id_for_ssa_name (scop, e)); 910 911 scop->param_context = isl_set_universe (space); 912 913 FOR_EACH_VEC_ELT (region->params, i, e) 914 add_param_constraints (scop, i, e); 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_union_set *domain = isl_schedule_get_domain (schedule); 1047 /* We cannot apply an empty domain to pbbs in this loop so return early. */ 1048 if (isl_union_set_is_empty (domain)) 1049 { 1050 isl_union_set_free (domain); 1051 return schedule; 1052 } 1053 1054 isl_space *space = isl_set_get_space (iterators); 1055 int loop_index = isl_space_dim (space, isl_dim_set) - 1; 1056 1057 loop_p ploop = pbb_loop (pbb); 1058 while (loop != ploop) 1059 { 1060 --loop_index; 1061 ploop = loop_outer (ploop); 1062 } 1063 1064 isl_local_space *ls = isl_local_space_from_space (space); 1065 isl_aff *aff = isl_aff_var_on_domain (ls, isl_dim_set, loop_index); 1066 isl_multi_aff *prefix = isl_multi_aff_from_aff (aff); 1067 char name[50]; 1068 snprintf (name, sizeof(name), "L_%d", loop->num); 1069 isl_id *label = isl_id_alloc (isl_schedule_get_ctx (schedule), 1070 name, NULL); 1071 prefix = isl_multi_aff_set_tuple_id (prefix, isl_dim_out, label); 1072 1073 int n = isl_multi_aff_dim (prefix, isl_dim_in); 1074 isl_multi_union_pw_aff *mupa = outer_projection_mupa (domain, n); 1075 mupa = isl_multi_union_pw_aff_apply_multi_aff (mupa, prefix); 1076 return isl_schedule_insert_partial_schedule (schedule, mupa); 1077 } 1078 1079 /* Build schedule for the pbb at INDEX. */ 1080 1081 static isl_schedule * 1082 build_schedule_pbb (scop_p scop, int *index) 1083 { 1084 poly_bb_p pbb = scop->pbbs[*index]; 1085 ++*index; 1086 isl_set *domain = isl_set_copy (pbb->domain); 1087 isl_union_set *ud = isl_union_set_from_set (domain); 1088 return isl_schedule_from_domain (ud); 1089 } 1090 1091 static isl_schedule *build_schedule_loop_nest (scop_p, int *, loop_p); 1092 1093 /* Build the schedule of the loop containing the SCOP pbb at INDEX. */ 1094 1095 static isl_schedule * 1096 build_schedule_loop (scop_p scop, int *index) 1097 { 1098 int max = scop->pbbs.length (); 1099 gcc_assert (*index < max); 1100 loop_p loop = loop_at (scop, index); 1101 1102 isl_schedule *s = NULL; 1103 while (nested_in (loop_at (scop, index), loop)) 1104 { 1105 if (loop == loop_at (scop, index)) 1106 s = add_in_sequence (s, build_schedule_pbb (scop, index)); 1107 else 1108 s = add_in_sequence (s, build_schedule_loop_nest (scop, index, loop)); 1109 1110 if (*index == max) 1111 break; 1112 } 1113 1114 return add_loop_schedule (s, loop, scop); 1115 } 1116 1117 /* S is the schedule of the loop LOOP. Embed the schedule S in all outer loops. 1118 When CONTEXT_LOOP is null, embed the schedule in all loops contained in the 1119 SCOP surrounding LOOP. When CONTEXT_LOOP is non null, only embed S in the 1120 maximal loop nest contained within CONTEXT_LOOP. */ 1121 1122 static isl_schedule * 1123 embed_in_surrounding_loops (__isl_take isl_schedule *s, scop_p scop, 1124 loop_p loop, int *index, loop_p context_loop) 1125 { 1126 loop_p outer = loop_outer (loop); 1127 sese_l region = scop->scop_info->region; 1128 if (context_loop == outer 1129 || !loop_in_sese_p (outer, region)) 1130 return s; 1131 1132 int max = scop->pbbs.length (); 1133 if (*index == max 1134 || (context_loop && !nested_in (loop_at (scop, index), context_loop)) 1135 || (!context_loop 1136 && !loop_in_sese_p (find_common_loop (outer, loop_at (scop, index)), 1137 region))) 1138 return embed_in_surrounding_loops (add_loop_schedule (s, outer, scop), 1139 scop, outer, index, context_loop); 1140 1141 bool a_pbb; 1142 while ((a_pbb = (outer == loop_at (scop, index))) 1143 || nested_in (loop_at (scop, index), outer)) 1144 { 1145 if (a_pbb) 1146 s = add_in_sequence (s, build_schedule_pbb (scop, index)); 1147 else 1148 s = add_in_sequence (s, build_schedule_loop (scop, index)); 1149 1150 if (*index == max) 1151 break; 1152 } 1153 1154 /* We reached the end of the OUTER loop: embed S in OUTER. */ 1155 return embed_in_surrounding_loops (add_loop_schedule (s, outer, scop), scop, 1156 outer, index, context_loop); 1157 } 1158 1159 /* Build schedule for the full loop nest containing the pbb at INDEX. When 1160 CONTEXT_LOOP is null, build the schedule of all loops contained in the SCOP 1161 surrounding the pbb. When CONTEXT_LOOP is non null, only build the maximal loop 1162 nest contained within CONTEXT_LOOP. */ 1163 1164 static isl_schedule * 1165 build_schedule_loop_nest (scop_p scop, int *index, loop_p context_loop) 1166 { 1167 gcc_assert (*index != (int) scop->pbbs.length ()); 1168 1169 loop_p loop = loop_at (scop, index); 1170 isl_schedule *s = build_schedule_loop (scop, index); 1171 return embed_in_surrounding_loops (s, scop, loop, index, context_loop); 1172 } 1173 1174 /* Build the schedule of the SCOP. */ 1175 1176 static void 1177 build_original_schedule (scop_p scop) 1178 { 1179 int i = 0; 1180 int n = scop->pbbs.length (); 1181 while (i < n) 1182 { 1183 poly_bb_p pbb = scop->pbbs[i]; 1184 isl_schedule *s = NULL; 1185 if (!loop_in_sese_p (pbb_loop (pbb), scop->scop_info->region)) 1186 s = build_schedule_pbb (scop, &i); 1187 else 1188 s = build_schedule_loop_nest (scop, &i, NULL); 1189 1190 scop->original_schedule = add_in_sequence (scop->original_schedule, s); 1191 } 1192 1193 if (dump_file) 1194 { 1195 fprintf (dump_file, "[sese-to-poly] original schedule:\n"); 1196 print_isl_schedule (dump_file, scop->original_schedule); 1197 } 1198 } 1199 1200 /* Builds the polyhedral representation for a SESE region. */ 1201 1202 bool 1203 build_poly_scop (scop_p scop) 1204 { 1205 int old_err = isl_options_get_on_error (scop->isl_context); 1206 isl_options_set_on_error (scop->isl_context, ISL_ON_ERROR_CONTINUE); 1207 1208 build_scop_context (scop); 1209 1210 unsigned i = 0; 1211 unsigned n = scop->pbbs.length (); 1212 while (i < n) 1213 i = build_iteration_domains (scop, scop->param_context, i, NULL); 1214 1215 build_scop_drs (scop); 1216 build_original_schedule (scop); 1217 1218 enum isl_error err = isl_ctx_last_error (scop->isl_context); 1219 isl_ctx_reset_error (scop->isl_context); 1220 isl_options_set_on_error (scop->isl_context, old_err); 1221 if (err != isl_error_none 1222 && dump_enabled_p ()) 1223 dump_printf (MSG_MISSED_OPTIMIZATION, 1224 "ISL error while building poly scop\n"); 1225 1226 return err == isl_error_none; 1227 } 1228 #endif /* HAVE_isl */ 1229