1 /* 2 * Copyright 2012 Ecole Normale Superieure 3 * Copyright 2015-2016 Sven Verdoolaege 4 * 5 * Use of this software is governed by the MIT license 6 * 7 * Written by Sven Verdoolaege, 8 * Ecole Normale Superieure, 45 rue d'Ulm, 75230 Paris, France 9 */ 10 11 #include <isl_schedule_constraints.h> 12 #include <isl/schedule.h> 13 #include <isl/space.h> 14 #include <isl/set.h> 15 #include <isl/map.h> 16 #include <isl/union_set.h> 17 #include <isl/union_map.h> 18 #include <isl/stream.h> 19 20 /* The constraints that need to be satisfied by a schedule on "domain". 21 * 22 * "context" specifies extra constraints on the parameters. 23 * 24 * "validity" constraints map domain elements i to domain elements 25 * that should be scheduled after i. (Hard constraint) 26 * "proximity" constraints map domain elements i to domains elements 27 * that should be scheduled as early as possible after i (or before i). 28 * (Soft constraint) 29 * 30 * "condition" and "conditional_validity" constraints map possibly "tagged" 31 * domain elements i -> s to "tagged" domain elements j -> t. 32 * The elements of the "conditional_validity" constraints, but without the 33 * tags (i.e., the elements i -> j) are treated as validity constraints, 34 * except that during the construction of a tilable band, 35 * the elements of the "conditional_validity" constraints may be violated 36 * provided that all adjacent elements of the "condition" constraints 37 * are local within the band. 38 * A dependence is local within a band if domain and range are mapped 39 * to the same schedule point by the band. 40 */ 41 struct isl_schedule_constraints { 42 isl_union_set *domain; 43 isl_set *context; 44 45 isl_union_map *constraint[isl_edge_last + 1]; 46 }; 47 48 __isl_give isl_schedule_constraints *isl_schedule_constraints_copy( 49 __isl_keep isl_schedule_constraints *sc) 50 { 51 isl_ctx *ctx; 52 isl_schedule_constraints *sc_copy; 53 enum isl_edge_type i; 54 55 ctx = isl_union_set_get_ctx(sc->domain); 56 sc_copy = isl_calloc_type(ctx, struct isl_schedule_constraints); 57 if (!sc_copy) 58 return NULL; 59 60 sc_copy->domain = isl_union_set_copy(sc->domain); 61 sc_copy->context = isl_set_copy(sc->context); 62 if (!sc_copy->domain || !sc_copy->context) 63 return isl_schedule_constraints_free(sc_copy); 64 65 for (i = isl_edge_first; i <= isl_edge_last; ++i) { 66 sc_copy->constraint[i] = isl_union_map_copy(sc->constraint[i]); 67 if (!sc_copy->constraint[i]) 68 return isl_schedule_constraints_free(sc_copy); 69 } 70 71 return sc_copy; 72 } 73 74 /* Construct an empty (invalid) isl_schedule_constraints object. 75 * The caller is responsible for setting the domain and initializing 76 * all the other fields, e.g., by calling isl_schedule_constraints_init. 77 */ 78 static __isl_give isl_schedule_constraints *isl_schedule_constraints_alloc( 79 isl_ctx *ctx) 80 { 81 return isl_calloc_type(ctx, struct isl_schedule_constraints); 82 } 83 84 /* Initialize all the fields of "sc", except domain, which is assumed 85 * to have been set by the caller. 86 */ 87 static __isl_give isl_schedule_constraints *isl_schedule_constraints_init( 88 __isl_take isl_schedule_constraints *sc) 89 { 90 isl_space *space; 91 isl_union_map *empty; 92 enum isl_edge_type i; 93 94 if (!sc) 95 return NULL; 96 if (!sc->domain) 97 return isl_schedule_constraints_free(sc); 98 space = isl_union_set_get_space(sc->domain); 99 if (!sc->context) 100 sc->context = isl_set_universe(isl_space_copy(space)); 101 empty = isl_union_map_empty(space); 102 for (i = isl_edge_first; i <= isl_edge_last; ++i) { 103 if (sc->constraint[i]) 104 continue; 105 sc->constraint[i] = isl_union_map_copy(empty); 106 if (!sc->constraint[i]) 107 sc->domain = isl_union_set_free(sc->domain); 108 } 109 isl_union_map_free(empty); 110 111 if (!sc->domain || !sc->context) 112 return isl_schedule_constraints_free(sc); 113 114 return sc; 115 } 116 117 /* Construct an isl_schedule_constraints object for computing a schedule 118 * on "domain". The initial object does not impose any constraints. 119 */ 120 __isl_give isl_schedule_constraints *isl_schedule_constraints_on_domain( 121 __isl_take isl_union_set *domain) 122 { 123 isl_ctx *ctx; 124 isl_schedule_constraints *sc; 125 126 if (!domain) 127 return NULL; 128 129 ctx = isl_union_set_get_ctx(domain); 130 sc = isl_schedule_constraints_alloc(ctx); 131 if (!sc) 132 goto error; 133 134 sc->domain = domain; 135 return isl_schedule_constraints_init(sc); 136 error: 137 isl_union_set_free(domain); 138 return NULL; 139 } 140 141 /* Replace the domain of "sc" by "domain". 142 */ 143 static __isl_give isl_schedule_constraints *isl_schedule_constraints_set_domain( 144 __isl_take isl_schedule_constraints *sc, 145 __isl_take isl_union_set *domain) 146 { 147 if (!sc || !domain) 148 goto error; 149 150 isl_union_set_free(sc->domain); 151 sc->domain = domain; 152 153 return sc; 154 error: 155 isl_schedule_constraints_free(sc); 156 isl_union_set_free(domain); 157 return NULL; 158 } 159 160 /* Replace the context of "sc" by "context". 161 */ 162 __isl_give isl_schedule_constraints *isl_schedule_constraints_set_context( 163 __isl_take isl_schedule_constraints *sc, __isl_take isl_set *context) 164 { 165 if (!sc || !context) 166 goto error; 167 168 isl_set_free(sc->context); 169 sc->context = context; 170 171 return sc; 172 error: 173 isl_schedule_constraints_free(sc); 174 isl_set_free(context); 175 return NULL; 176 } 177 178 /* Replace the constraints of type "type" in "sc" by "c". 179 * 180 * First detect any equality constraints that may be implicit in "c" 181 * in order to try and improve the accuracy of the input (and therefore 182 * also the output) of the isl_set_coefficients calls 183 * that are eventually performed on (some of) these constraints. 184 */ 185 static __isl_give isl_schedule_constraints *isl_schedule_constraints_set( 186 __isl_take isl_schedule_constraints *sc, enum isl_edge_type type, 187 __isl_take isl_union_map *c) 188 { 189 c = isl_union_map_detect_equalities(c); 190 if (!sc || !c) 191 goto error; 192 193 isl_union_map_free(sc->constraint[type]); 194 sc->constraint[type] = c; 195 196 return sc; 197 error: 198 isl_schedule_constraints_free(sc); 199 isl_union_map_free(c); 200 return NULL; 201 } 202 203 /* Replace the validity constraints of "sc" by "validity". 204 */ 205 __isl_give isl_schedule_constraints *isl_schedule_constraints_set_validity( 206 __isl_take isl_schedule_constraints *sc, 207 __isl_take isl_union_map *validity) 208 { 209 return isl_schedule_constraints_set(sc, isl_edge_validity, validity); 210 } 211 212 /* Replace the coincidence constraints of "sc" by "coincidence". 213 */ 214 __isl_give isl_schedule_constraints *isl_schedule_constraints_set_coincidence( 215 __isl_take isl_schedule_constraints *sc, 216 __isl_take isl_union_map *coincidence) 217 { 218 return isl_schedule_constraints_set(sc, isl_edge_coincidence, 219 coincidence); 220 } 221 222 /* Replace the proximity constraints of "sc" by "proximity". 223 */ 224 __isl_give isl_schedule_constraints *isl_schedule_constraints_set_proximity( 225 __isl_take isl_schedule_constraints *sc, 226 __isl_take isl_union_map *proximity) 227 { 228 return isl_schedule_constraints_set(sc, isl_edge_proximity, proximity); 229 } 230 231 /* Replace the conditional validity constraints of "sc" by "condition" 232 * and "validity". 233 */ 234 __isl_give isl_schedule_constraints * 235 isl_schedule_constraints_set_conditional_validity( 236 __isl_take isl_schedule_constraints *sc, 237 __isl_take isl_union_map *condition, 238 __isl_take isl_union_map *validity) 239 { 240 sc = isl_schedule_constraints_set(sc, isl_edge_condition, condition); 241 sc = isl_schedule_constraints_set(sc, isl_edge_conditional_validity, 242 validity); 243 return sc; 244 } 245 246 __isl_null isl_schedule_constraints *isl_schedule_constraints_free( 247 __isl_take isl_schedule_constraints *sc) 248 { 249 enum isl_edge_type i; 250 251 if (!sc) 252 return NULL; 253 254 isl_union_set_free(sc->domain); 255 isl_set_free(sc->context); 256 for (i = isl_edge_first; i <= isl_edge_last; ++i) 257 isl_union_map_free(sc->constraint[i]); 258 259 free(sc); 260 261 return NULL; 262 } 263 264 isl_ctx *isl_schedule_constraints_get_ctx( 265 __isl_keep isl_schedule_constraints *sc) 266 { 267 return sc ? isl_union_set_get_ctx(sc->domain) : NULL; 268 } 269 270 /* Return the domain of "sc". 271 */ 272 __isl_give isl_union_set *isl_schedule_constraints_get_domain( 273 __isl_keep isl_schedule_constraints *sc) 274 { 275 if (!sc) 276 return NULL; 277 278 return isl_union_set_copy(sc->domain); 279 } 280 281 /* Return the context of "sc". 282 */ 283 __isl_give isl_set *isl_schedule_constraints_get_context( 284 __isl_keep isl_schedule_constraints *sc) 285 { 286 if (!sc) 287 return NULL; 288 289 return isl_set_copy(sc->context); 290 } 291 292 /* Return the constraints of type "type" in "sc". 293 */ 294 __isl_give isl_union_map *isl_schedule_constraints_get( 295 __isl_keep isl_schedule_constraints *sc, enum isl_edge_type type) 296 { 297 if (!sc) 298 return NULL; 299 300 return isl_union_map_copy(sc->constraint[type]); 301 } 302 303 /* Return the validity constraints of "sc". 304 */ 305 __isl_give isl_union_map *isl_schedule_constraints_get_validity( 306 __isl_keep isl_schedule_constraints *sc) 307 { 308 return isl_schedule_constraints_get(sc, isl_edge_validity); 309 } 310 311 /* Return the coincidence constraints of "sc". 312 */ 313 __isl_give isl_union_map *isl_schedule_constraints_get_coincidence( 314 __isl_keep isl_schedule_constraints *sc) 315 { 316 return isl_schedule_constraints_get(sc, isl_edge_coincidence); 317 } 318 319 /* Return the proximity constraints of "sc". 320 */ 321 __isl_give isl_union_map *isl_schedule_constraints_get_proximity( 322 __isl_keep isl_schedule_constraints *sc) 323 { 324 return isl_schedule_constraints_get(sc, isl_edge_proximity); 325 } 326 327 /* Return the conditional validity constraints of "sc". 328 */ 329 __isl_give isl_union_map *isl_schedule_constraints_get_conditional_validity( 330 __isl_keep isl_schedule_constraints *sc) 331 { 332 return isl_schedule_constraints_get(sc, isl_edge_conditional_validity); 333 } 334 335 /* Return the conditions for the conditional validity constraints of "sc". 336 */ 337 __isl_give isl_union_map * 338 isl_schedule_constraints_get_conditional_validity_condition( 339 __isl_keep isl_schedule_constraints *sc) 340 { 341 return isl_schedule_constraints_get(sc, isl_edge_condition); 342 } 343 344 /* Add "c" to the constraints of type "type" in "sc". 345 */ 346 __isl_give isl_schedule_constraints *isl_schedule_constraints_add( 347 __isl_take isl_schedule_constraints *sc, enum isl_edge_type type, 348 __isl_take isl_union_map *c) 349 { 350 if (!sc || !c) 351 goto error; 352 353 c = isl_union_map_union(sc->constraint[type], c); 354 sc->constraint[type] = c; 355 if (!c) 356 return isl_schedule_constraints_free(sc); 357 358 return sc; 359 error: 360 isl_schedule_constraints_free(sc); 361 isl_union_map_free(c); 362 return NULL; 363 } 364 365 /* Can a schedule constraint of type "type" be tagged? 366 */ 367 static int may_be_tagged(enum isl_edge_type type) 368 { 369 if (type == isl_edge_condition || type == isl_edge_conditional_validity) 370 return 1; 371 return 0; 372 } 373 374 /* Apply "umap" to the domains of the wrapped relations 375 * inside the domain and range of "c". 376 * 377 * That is, for each map of the form 378 * 379 * [D -> S] -> [E -> T] 380 * 381 * in "c", apply "umap" to D and E. 382 * 383 * D is exposed by currying the relation to 384 * 385 * D -> [S -> [E -> T]] 386 * 387 * E is exposed by doing the same to the inverse of "c". 388 */ 389 static __isl_give isl_union_map *apply_factor_domain( 390 __isl_take isl_union_map *c, __isl_keep isl_union_map *umap) 391 { 392 c = isl_union_map_curry(c); 393 c = isl_union_map_apply_domain(c, isl_union_map_copy(umap)); 394 c = isl_union_map_uncurry(c); 395 396 c = isl_union_map_reverse(c); 397 c = isl_union_map_curry(c); 398 c = isl_union_map_apply_domain(c, isl_union_map_copy(umap)); 399 c = isl_union_map_uncurry(c); 400 c = isl_union_map_reverse(c); 401 402 return c; 403 } 404 405 /* Apply "umap" to domain and range of "c". 406 * If "tag" is set, then "c" may contain tags and then "umap" 407 * needs to be applied to the domains of the wrapped relations 408 * inside the domain and range of "c". 409 */ 410 static __isl_give isl_union_map *apply(__isl_take isl_union_map *c, 411 __isl_keep isl_union_map *umap, int tag) 412 { 413 isl_union_map *t; 414 415 if (tag) 416 t = isl_union_map_copy(c); 417 c = isl_union_map_apply_domain(c, isl_union_map_copy(umap)); 418 c = isl_union_map_apply_range(c, isl_union_map_copy(umap)); 419 if (!tag) 420 return c; 421 t = apply_factor_domain(t, umap); 422 c = isl_union_map_union(c, t); 423 return c; 424 } 425 426 /* Apply "umap" to the domain of the schedule constraints "sc". 427 * 428 * The two sides of the various schedule constraints are adjusted 429 * accordingly. 430 */ 431 __isl_give isl_schedule_constraints *isl_schedule_constraints_apply( 432 __isl_take isl_schedule_constraints *sc, 433 __isl_take isl_union_map *umap) 434 { 435 enum isl_edge_type i; 436 437 if (!sc || !umap) 438 goto error; 439 440 for (i = isl_edge_first; i <= isl_edge_last; ++i) { 441 int tag = may_be_tagged(i); 442 443 sc->constraint[i] = apply(sc->constraint[i], umap, tag); 444 if (!sc->constraint[i]) 445 goto error; 446 } 447 sc->domain = isl_union_set_apply(sc->domain, umap); 448 if (!sc->domain) 449 return isl_schedule_constraints_free(sc); 450 451 return sc; 452 error: 453 isl_schedule_constraints_free(sc); 454 isl_union_map_free(umap); 455 return NULL; 456 } 457 458 /* An enumeration of the various keys that may appear in a YAML mapping 459 * of an isl_schedule_constraints object. 460 * The keys for the edge types are assumed to have the same values 461 * as the edge types in isl_edge_type. 462 */ 463 enum isl_sc_key { 464 isl_sc_key_error = -1, 465 isl_sc_key_validity = isl_edge_validity, 466 isl_sc_key_coincidence = isl_edge_coincidence, 467 isl_sc_key_condition = isl_edge_condition, 468 isl_sc_key_conditional_validity = isl_edge_conditional_validity, 469 isl_sc_key_proximity = isl_edge_proximity, 470 isl_sc_key_domain, 471 isl_sc_key_context, 472 isl_sc_key_end 473 }; 474 475 /* Textual representations of the YAML keys for an isl_schedule_constraints 476 * object. 477 */ 478 static char *key_str[] = { 479 [isl_sc_key_validity] = "validity", 480 [isl_sc_key_coincidence] = "coincidence", 481 [isl_sc_key_condition] = "condition", 482 [isl_sc_key_conditional_validity] = "conditional_validity", 483 [isl_sc_key_proximity] = "proximity", 484 [isl_sc_key_domain] = "domain", 485 [isl_sc_key_context] = "context", 486 }; 487 488 #undef BASE 489 #define BASE set 490 #include "print_yaml_field_templ.c" 491 492 #undef BASE 493 #define BASE union_set 494 #include "print_yaml_field_templ.c" 495 496 #undef BASE 497 #define BASE union_map 498 #include "print_yaml_field_templ.c" 499 500 /* Print a key, value pair for the edge of type "type" in "sc" to "p". 501 * 502 * If the edge relation is empty, then it is not printed since 503 * an empty relation is the default value. 504 */ 505 static __isl_give isl_printer *print_constraint(__isl_take isl_printer *p, 506 __isl_keep isl_schedule_constraints *sc, enum isl_edge_type type) 507 { 508 isl_bool empty; 509 510 empty = isl_union_map_plain_is_empty(sc->constraint[type]); 511 if (empty < 0) 512 return isl_printer_free(p); 513 if (empty) 514 return p; 515 516 p = print_yaml_field_union_map(p, key_str[type], sc->constraint[type]); 517 518 return p; 519 } 520 521 /* Print "sc" to "p" 522 * 523 * In particular, print the isl_schedule_constraints object as a YAML document. 524 * Fields with values that are (obviously) equal to their default values 525 * are not printed. 526 */ 527 __isl_give isl_printer *isl_printer_print_schedule_constraints( 528 __isl_take isl_printer *p, __isl_keep isl_schedule_constraints *sc) 529 { 530 isl_bool universe; 531 532 if (!sc) 533 return isl_printer_free(p); 534 535 p = isl_printer_yaml_start_mapping(p); 536 p = print_yaml_field_union_set(p, key_str[isl_sc_key_domain], 537 sc->domain); 538 universe = isl_set_plain_is_universe(sc->context); 539 if (universe < 0) 540 return isl_printer_free(p); 541 if (!universe) 542 p = print_yaml_field_set(p, key_str[isl_sc_key_context], 543 sc->context); 544 p = print_constraint(p, sc, isl_edge_validity); 545 p = print_constraint(p, sc, isl_edge_proximity); 546 p = print_constraint(p, sc, isl_edge_coincidence); 547 p = print_constraint(p, sc, isl_edge_condition); 548 p = print_constraint(p, sc, isl_edge_conditional_validity); 549 p = isl_printer_yaml_end_mapping(p); 550 551 return p; 552 } 553 554 #undef BASE 555 #define BASE schedule_constraints 556 #include <print_templ_yaml.c> 557 558 #undef KEY 559 #define KEY enum isl_sc_key 560 #undef KEY_ERROR 561 #define KEY_ERROR isl_sc_key_error 562 #undef KEY_END 563 #define KEY_END isl_sc_key_end 564 #undef KEY_STR 565 #define KEY_STR key_str 566 #undef KEY_EXTRACT 567 #define KEY_EXTRACT extract_key 568 #undef KEY_GET 569 #define KEY_GET get_key 570 #include "extract_key.c" 571 572 #undef BASE 573 #define BASE set 574 #include "read_in_string_templ.c" 575 576 #undef BASE 577 #define BASE union_set 578 #include "read_in_string_templ.c" 579 580 #undef BASE 581 #define BASE union_map 582 #include "read_in_string_templ.c" 583 584 /* Read an isl_schedule_constraints object from "s". 585 * 586 * Start off with an empty (invalid) isl_schedule_constraints object and 587 * then fill up the fields based on the input. 588 * The input needs to contain at least a description of the domain. 589 * The other fields are set to defaults by isl_schedule_constraints_init 590 * if they are not specified in the input. 591 */ 592 __isl_give isl_schedule_constraints *isl_stream_read_schedule_constraints( 593 isl_stream *s) 594 { 595 isl_ctx *ctx; 596 isl_schedule_constraints *sc; 597 isl_bool more; 598 int domain_set = 0; 599 600 if (isl_stream_yaml_read_start_mapping(s) < 0) 601 return NULL; 602 603 ctx = isl_stream_get_ctx(s); 604 sc = isl_schedule_constraints_alloc(ctx); 605 while ((more = isl_stream_yaml_next(s)) == isl_bool_true) { 606 enum isl_sc_key key; 607 enum isl_edge_type type; 608 isl_set *context; 609 isl_union_set *domain; 610 isl_union_map *constraints; 611 612 key = get_key(s); 613 if (isl_stream_yaml_next(s) < 0) 614 return isl_schedule_constraints_free(sc); 615 switch (key) { 616 case isl_sc_key_end: 617 case isl_sc_key_error: 618 return isl_schedule_constraints_free(sc); 619 case isl_sc_key_domain: 620 domain_set = 1; 621 domain = read_union_set(s); 622 sc = isl_schedule_constraints_set_domain(sc, domain); 623 if (!sc) 624 return NULL; 625 break; 626 case isl_sc_key_context: 627 context = read_set(s); 628 sc = isl_schedule_constraints_set_context(sc, context); 629 if (!sc) 630 return NULL; 631 break; 632 case isl_sc_key_validity: 633 case isl_sc_key_coincidence: 634 case isl_sc_key_condition: 635 case isl_sc_key_conditional_validity: 636 case isl_sc_key_proximity: 637 type = (enum isl_edge_type) key; 638 constraints = read_union_map(s); 639 sc = isl_schedule_constraints_set(sc, type, 640 constraints); 641 if (!sc) 642 return NULL; 643 break; 644 } 645 } 646 if (more < 0) 647 return isl_schedule_constraints_free(sc); 648 649 if (isl_stream_yaml_read_end_mapping(s) < 0) 650 return isl_schedule_constraints_free(sc); 651 652 if (!domain_set) { 653 isl_stream_error(s, NULL, "no domain specified"); 654 return isl_schedule_constraints_free(sc); 655 } 656 657 return isl_schedule_constraints_init(sc); 658 } 659 660 /* Read an isl_schedule_constraints object from the file "input". 661 */ 662 __isl_give isl_schedule_constraints *isl_schedule_constraints_read_from_file( 663 isl_ctx *ctx, FILE *input) 664 { 665 struct isl_stream *s; 666 isl_schedule_constraints *sc; 667 668 s = isl_stream_new_file(ctx, input); 669 if (!s) 670 return NULL; 671 sc = isl_stream_read_schedule_constraints(s); 672 isl_stream_free(s); 673 674 return sc; 675 } 676 677 #undef TYPE_BASE 678 #define TYPE_BASE schedule_constraints 679 #include "isl_read_from_str_templ.c" 680 681 /* Align the parameters of the fields of "sc". 682 */ 683 __isl_give isl_schedule_constraints * 684 isl_schedule_constraints_align_params(__isl_take isl_schedule_constraints *sc) 685 { 686 isl_space *space; 687 enum isl_edge_type i; 688 689 if (!sc) 690 return NULL; 691 692 space = isl_union_set_get_space(sc->domain); 693 space = isl_space_align_params(space, isl_set_get_space(sc->context)); 694 for (i = isl_edge_first; i <= isl_edge_last; ++i) 695 space = isl_space_align_params(space, 696 isl_union_map_get_space(sc->constraint[i])); 697 698 for (i = isl_edge_first; i <= isl_edge_last; ++i) { 699 sc->constraint[i] = isl_union_map_align_params( 700 sc->constraint[i], isl_space_copy(space)); 701 if (!sc->constraint[i]) 702 space = isl_space_free(space); 703 } 704 sc->context = isl_set_align_params(sc->context, isl_space_copy(space)); 705 sc->domain = isl_union_set_align_params(sc->domain, space); 706 if (!sc->context || !sc->domain) 707 return isl_schedule_constraints_free(sc); 708 709 return sc; 710 } 711 712 /* Add the number of basic maps in "map" to *n. 713 */ 714 static isl_stat add_n_basic_map(__isl_take isl_map *map, void *user) 715 { 716 int *n = user; 717 isl_size n_basic_map; 718 719 n_basic_map = isl_map_n_basic_map(map); 720 *n += n_basic_map; 721 isl_map_free(map); 722 723 return n_basic_map < 0 ? isl_stat_error : isl_stat_ok; 724 } 725 726 /* Return the total number of isl_basic_maps in the constraints of "sc". 727 * Return -1 on error. 728 */ 729 int isl_schedule_constraints_n_basic_map( 730 __isl_keep isl_schedule_constraints *sc) 731 { 732 enum isl_edge_type i; 733 int n = 0; 734 735 if (!sc) 736 return -1; 737 for (i = isl_edge_first; i <= isl_edge_last; ++i) 738 if (isl_union_map_foreach_map(sc->constraint[i], 739 &add_n_basic_map, &n) < 0) 740 return -1; 741 742 return n; 743 } 744 745 /* Return the total number of isl_maps in the constraints of "sc". 746 */ 747 isl_size isl_schedule_constraints_n_map(__isl_keep isl_schedule_constraints *sc) 748 { 749 enum isl_edge_type i; 750 int n = 0; 751 752 for (i = isl_edge_first; i <= isl_edge_last; ++i) { 753 isl_size n_i; 754 755 n_i = isl_union_map_n_map(sc->constraint[i]); 756 if (n_i < 0) 757 return isl_size_error; 758 n += n_i; 759 } 760 761 return n; 762 } 763