Coverage Report

Created: 2019-07-24 05:18

/Users/buildslave/jenkins/workspace/clang-stage2-coverage-R/llvm/tools/polly/lib/External/isl/isl_schedule_band.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * Copyright 2013-2014 Ecole Normale Superieure
3
 * Copyright 2014      INRIA Rocquencourt
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
 * and Inria Paris - Rocquencourt, Domaine de Voluceau - Rocquencourt,
10
 * B.P. 105 - 78153 Le Chesnay, France
11
 */
12
13
#include <string.h>
14
#include <isl/val.h>
15
#include <isl/space.h>
16
#include <isl/map.h>
17
#include <isl/schedule_node.h>
18
#include <isl_schedule_band.h>
19
#include <isl_schedule_private.h>
20
21
isl_ctx *isl_schedule_band_get_ctx(__isl_keep isl_schedule_band *band)
22
3.61k
{
23
3.61k
  return band ? isl_multi_union_pw_aff_get_ctx(band->mupa) : NULL;
24
3.61k
}
25
26
/* Return a new uninitialized isl_schedule_band.
27
 */
28
static __isl_give isl_schedule_band *isl_schedule_band_alloc(isl_ctx *ctx)
29
3.43k
{
30
3.43k
  isl_schedule_band *band;
31
3.43k
32
3.43k
  band = isl_calloc_type(ctx, isl_schedule_band);
33
3.43k
  if (!band)
34
0
    return NULL;
35
3.43k
36
3.43k
  band->ref = 1;
37
3.43k
38
3.43k
  return band;
39
3.43k
}
40
41
/* Return a new isl_schedule_band with partial schedule "mupa".
42
 * First replace "mupa" by its greatest integer part to ensure
43
 * that the schedule is always integral.
44
 * The band is not marked permutable, the dimensions are not
45
 * marked coincident and the AST build options are empty.
46
 * Since there are no build options, the node is not anchored.
47
 */
48
__isl_give isl_schedule_band *isl_schedule_band_from_multi_union_pw_aff(
49
  __isl_take isl_multi_union_pw_aff *mupa)
50
2.06k
{
51
2.06k
  isl_ctx *ctx;
52
2.06k
  isl_schedule_band *band;
53
2.06k
  isl_space *space;
54
2.06k
55
2.06k
  mupa = isl_multi_union_pw_aff_floor(mupa);
56
2.06k
  if (!mupa)
57
0
    return NULL;
58
2.06k
  ctx = isl_multi_union_pw_aff_get_ctx(mupa);
59
2.06k
  band = isl_schedule_band_alloc(ctx);
60
2.06k
  if (!band)
61
0
    goto error;
62
2.06k
63
2.06k
  band->n = isl_multi_union_pw_aff_dim(mupa, isl_dim_set);
64
2.06k
  band->coincident = isl_calloc_array(ctx, int, band->n);
65
2.06k
  band->mupa = mupa;
66
2.06k
  space = isl_space_params_alloc(ctx, 0);
67
2.06k
  band->ast_build_options = isl_union_set_empty(space);
68
2.06k
  band->anchored = 0;
69
2.06k
70
2.06k
  if ((band->n && !band->coincident) || !band->ast_build_options)
71
0
    return isl_schedule_band_free(band);
72
2.06k
73
2.06k
  return band;
74
0
error:
75
0
  isl_multi_union_pw_aff_free(mupa);
76
0
  return NULL;
77
2.06k
}
78
79
/* Create a duplicate of the given isl_schedule_band.
80
 */
81
__isl_give isl_schedule_band *isl_schedule_band_dup(
82
  __isl_keep isl_schedule_band *band)
83
1.37k
{
84
1.37k
  int i;
85
1.37k
  isl_ctx *ctx;
86
1.37k
  isl_schedule_band *dup;
87
1.37k
88
1.37k
  if (!band)
89
0
    return NULL;
90
1.37k
91
1.37k
  ctx = isl_schedule_band_get_ctx(band);
92
1.37k
  dup = isl_schedule_band_alloc(ctx);
93
1.37k
  if (!dup)
94
0
    return NULL;
95
1.37k
96
1.37k
  dup->n = band->n;
97
1.37k
  dup->coincident = isl_alloc_array(ctx, int, band->n);
98
1.37k
  if (band->n && !dup->coincident)
99
0
    return isl_schedule_band_free(dup);
100
1.37k
101
3.58k
  
for (i = 0; 1.37k
i < band->n;
++i2.21k
)
102
2.21k
    dup->coincident[i] = band->coincident[i];
103
1.37k
  dup->permutable = band->permutable;
104
1.37k
105
1.37k
  dup->mupa = isl_multi_union_pw_aff_copy(band->mupa);
106
1.37k
  dup->ast_build_options = isl_union_set_copy(band->ast_build_options);
107
1.37k
  if (!dup->mupa || !dup->ast_build_options)
108
0
    return isl_schedule_band_free(dup);
109
1.37k
110
1.37k
  if (band->loop_type) {
111
18
    dup->loop_type = isl_alloc_array(ctx,
112
18
              enum isl_ast_loop_type, band->n);
113
18
    if (band->n && !dup->loop_type)
114
0
      return isl_schedule_band_free(dup);
115
62
    
for (i = 0; 18
i < band->n;
++i44
)
116
44
      dup->loop_type[i] = band->loop_type[i];
117
18
  }
118
1.37k
  if (band->isolate_loop_type) {
119
0
    dup->isolate_loop_type = isl_alloc_array(ctx,
120
0
              enum isl_ast_loop_type, band->n);
121
0
    if (band->n && !dup->isolate_loop_type)
122
0
      return isl_schedule_band_free(dup);
123
0
    for (i = 0; i < band->n; ++i)
124
0
      dup->isolate_loop_type[i] = band->isolate_loop_type[i];
125
0
  }
126
1.37k
127
1.37k
  return dup;
128
1.37k
}
129
130
/* Return an isl_schedule_band that is equal to "band" and that has only
131
 * a single reference.
132
 */
133
__isl_give isl_schedule_band *isl_schedule_band_cow(
134
  __isl_take isl_schedule_band *band)
135
1.45k
{
136
1.45k
  if (!band)
137
0
    return NULL;
138
1.45k
139
1.45k
  if (band->ref == 1)
140
74
    return band;
141
1.37k
  band->ref--;
142
1.37k
  return isl_schedule_band_dup(band);
143
1.37k
}
144
145
/* Return a new reference to "band".
146
 */
147
__isl_give isl_schedule_band *isl_schedule_band_copy(
148
  __isl_keep isl_schedule_band *band)
149
3.50k
{
150
3.50k
  if (!band)
151
0
    return NULL;
152
3.50k
153
3.50k
  band->ref++;
154
3.50k
  return band;
155
3.50k
}
156
157
/* Free a reference to "band" and return NULL.
158
 */
159
__isl_null isl_schedule_band *isl_schedule_band_free(
160
  __isl_take isl_schedule_band *band)
161
5.53k
{
162
5.53k
  if (!band)
163
0
    return NULL;
164
5.53k
165
5.53k
  if (--band->ref > 0)
166
2.12k
    return NULL;
167
3.40k
168
3.40k
  isl_multi_union_pw_aff_free(band->mupa);
169
3.40k
  isl_union_set_free(band->ast_build_options);
170
3.40k
  free(band->loop_type);
171
3.40k
  free(band->isolate_loop_type);
172
3.40k
  free(band->coincident);
173
3.40k
  free(band);
174
3.40k
175
3.40k
  return NULL;
176
3.40k
}
177
178
/* Are "band1" and "band2" obviously equal?
179
 */
180
isl_bool isl_schedule_band_plain_is_equal(__isl_keep isl_schedule_band *band1,
181
  __isl_keep isl_schedule_band *band2)
182
0
{
183
0
  int i;
184
0
  isl_bool equal;
185
0
186
0
  if (!band1 || !band2)
187
0
    return isl_bool_error;
188
0
  if (band1 == band2)
189
0
    return isl_bool_true;
190
0
191
0
  if (band1->n != band2->n)
192
0
    return isl_bool_false;
193
0
  for (i = 0; i < band1->n; ++i)
194
0
    if (band1->coincident[i] != band2->coincident[i])
195
0
      return isl_bool_false;
196
0
  if (band1->permutable != band2->permutable)
197
0
    return isl_bool_false;
198
0
199
0
  equal = isl_multi_union_pw_aff_plain_is_equal(band1->mupa, band2->mupa);
200
0
  if (equal < 0 || !equal)
201
0
    return equal;
202
0
203
0
  if (!band1->loop_type != !band2->loop_type)
204
0
    return isl_bool_false;
205
0
  if (band1->loop_type)
206
0
    for (i = 0; i < band1->n; ++i)
207
0
      if (band1->loop_type[i] != band2->loop_type[i])
208
0
        return isl_bool_false;
209
0
210
0
  if (!band1->isolate_loop_type != !band2->isolate_loop_type)
211
0
    return isl_bool_false;
212
0
  if (band1->isolate_loop_type)
213
0
    for (i = 0; i < band1->n; ++i)
214
0
      if (band1->isolate_loop_type[i] !=
215
0
            band2->isolate_loop_type[i])
216
0
        return isl_bool_false;
217
0
218
0
  return isl_union_set_is_equal(band1->ast_build_options,
219
0
          band2->ast_build_options);
220
0
}
221
222
/* Return the number of scheduling dimensions in the band.
223
 */
224
int isl_schedule_band_n_member(__isl_keep isl_schedule_band *band)
225
79.0k
{
226
79.0k
  return band ? band->n : 
00
;
227
79.0k
}
228
229
/* Is the given scheduling dimension coincident within the band and
230
 * with respect to the coincidence constraints?
231
 */
232
isl_bool isl_schedule_band_member_get_coincident(
233
  __isl_keep isl_schedule_band *band, int pos)
234
1.53k
{
235
1.53k
  if (!band)
236
0
    return isl_bool_error;
237
1.53k
238
1.53k
  if (pos < 0 || pos >= band->n)
239
1.53k
    
isl_die0
(isl_schedule_band_get_ctx(band), isl_error_invalid,
240
1.53k
      "invalid member position", return isl_bool_error);
241
1.53k
242
1.53k
  return band->coincident[pos];
243
1.53k
}
244
245
/* Mark the given scheduling dimension as being coincident or not
246
 * according to "coincident".
247
 */
248
__isl_give isl_schedule_band *isl_schedule_band_member_set_coincident(
249
  __isl_take isl_schedule_band *band, int pos, int coincident)
250
227
{
251
227
  if (!band)
252
0
    return NULL;
253
227
  if (isl_schedule_band_member_get_coincident(band, pos) == coincident)
254
0
    return band;
255
227
  band = isl_schedule_band_cow(band);
256
227
  if (!band)
257
0
    return NULL;
258
227
259
227
  if (pos < 0 || pos >= band->n)
260
227
    
isl_die0
(isl_schedule_band_get_ctx(band), isl_error_invalid,
261
227
      "invalid member position",
262
227
      return isl_schedule_band_free(band));
263
227
264
227
  band->coincident[pos] = coincident;
265
227
266
227
  return band;
267
227
}
268
269
/* Is the schedule band mark permutable?
270
 */
271
isl_bool isl_schedule_band_get_permutable(__isl_keep isl_schedule_band *band)
272
928
{
273
928
  if (!band)
274
0
    return isl_bool_error;
275
928
  return band->permutable;
276
928
}
277
278
/* Mark the schedule band permutable or not according to "permutable"?
279
 */
280
__isl_give isl_schedule_band *isl_schedule_band_set_permutable(
281
  __isl_take isl_schedule_band *band, int permutable)
282
150
{
283
150
  if (!band)
284
0
    return NULL;
285
150
  if (band->permutable == permutable)
286
0
    return band;
287
150
  band = isl_schedule_band_cow(band);
288
150
  if (!band)
289
0
    return NULL;
290
150
291
150
  band->permutable = permutable;
292
150
293
150
  return band;
294
150
}
295
296
/* Is the band node "node" anchored?  That is, does it reference
297
 * the outer band nodes?
298
 */
299
int isl_schedule_band_is_anchored(__isl_keep isl_schedule_band *band)
300
5.33k
{
301
5.33k
  return band ? band->anchored : 
-10
;
302
5.33k
}
303
304
/* Return the schedule space of the band.
305
 */
306
__isl_give isl_space *isl_schedule_band_get_space(
307
  __isl_keep isl_schedule_band *band)
308
2.81k
{
309
2.81k
  if (!band)
310
0
    return NULL;
311
2.81k
  return isl_multi_union_pw_aff_get_space(band->mupa);
312
2.81k
}
313
314
/* Intersect the domain of the band schedule of "band" with "domain".
315
 */
316
__isl_give isl_schedule_band *isl_schedule_band_intersect_domain(
317
  __isl_take isl_schedule_band *band, __isl_take isl_union_set *domain)
318
2
{
319
2
  band = isl_schedule_band_cow(band);
320
2
  if (!band || !domain)
321
0
    goto error;
322
2
323
2
  band->mupa = isl_multi_union_pw_aff_intersect_domain(band->mupa,
324
2
                domain);
325
2
  if (!band->mupa)
326
0
    return isl_schedule_band_free(band);
327
2
328
2
  return band;
329
0
error:
330
0
  isl_schedule_band_free(band);
331
0
  isl_union_set_free(domain);
332
0
  return NULL;
333
2
}
334
335
/* Return the schedule of the band in isolation.
336
 */
337
__isl_give isl_multi_union_pw_aff *isl_schedule_band_get_partial_schedule(
338
  __isl_keep isl_schedule_band *band)
339
12.5k
{
340
12.5k
  return band ? isl_multi_union_pw_aff_copy(band->mupa) : NULL;
341
12.5k
}
342
343
/* Replace the schedule of "band" by "schedule".
344
 */
345
__isl_give isl_schedule_band *isl_schedule_band_set_partial_schedule(
346
  __isl_take isl_schedule_band *band,
347
  __isl_take isl_multi_union_pw_aff *schedule)
348
2
{
349
2
  band = isl_schedule_band_cow(band);
350
2
  if (!band || !schedule)
351
0
    goto error;
352
2
353
2
  isl_multi_union_pw_aff_free(band->mupa);
354
2
  band->mupa = schedule;
355
2
356
2
  return band;
357
0
error:
358
0
  isl_schedule_band_free(band);
359
0
  isl_multi_union_pw_aff_free(schedule);
360
0
  return NULL;
361
2
}
362
363
/* Return the loop AST generation type for the band member of "band"
364
 * at position "pos".
365
 */
366
enum isl_ast_loop_type isl_schedule_band_member_get_ast_loop_type(
367
  __isl_keep isl_schedule_band *band, int pos)
368
861
{
369
861
  if (!band)
370
0
    return isl_ast_loop_error;
371
861
372
861
  if (pos < 0 || pos >= band->n)
373
861
    
isl_die0
(isl_schedule_band_get_ctx(band), isl_error_invalid,
374
861
      "invalid member position", return isl_ast_loop_error);
375
861
376
861
  if (!band->loop_type)
377
738
    return isl_ast_loop_default;
378
123
379
123
  return band->loop_type[pos];
380
123
}
381
382
/* Set the loop AST generation type for the band member of "band"
383
 * at position "pos" to "type".
384
 */
385
__isl_give isl_schedule_band *isl_schedule_band_member_set_ast_loop_type(
386
  __isl_take isl_schedule_band *band, int pos,
387
  enum isl_ast_loop_type type)
388
0
{
389
0
  if (!band)
390
0
    return NULL;
391
0
  if (isl_schedule_band_member_get_ast_loop_type(band, pos) == type)
392
0
    return band;
393
0
394
0
  if (pos < 0 || pos >= band->n)
395
0
    isl_die(isl_schedule_band_get_ctx(band), isl_error_invalid,
396
0
      "invalid member position",
397
0
      return isl_schedule_band_free(band));
398
0
399
0
  band = isl_schedule_band_cow(band);
400
0
  if (!band)
401
0
    return isl_schedule_band_free(band);
402
0
403
0
  if (!band->loop_type) {
404
0
    isl_ctx *ctx;
405
0
406
0
    ctx = isl_schedule_band_get_ctx(band);
407
0
    band->loop_type = isl_calloc_array(ctx,
408
0
              enum isl_ast_loop_type, band->n);
409
0
    if (band->n && !band->loop_type)
410
0
      return isl_schedule_band_free(band);
411
0
  }
412
0
413
0
  band->loop_type[pos] = type;
414
0
415
0
  return band;
416
0
}
417
418
/* Return the loop AST generation type for the band member of "band"
419
 * at position "pos" for the part that has been isolated by the isolate option.
420
 */
421
enum isl_ast_loop_type isl_schedule_band_member_get_isolate_ast_loop_type(
422
  __isl_keep isl_schedule_band *band, int pos)
423
917
{
424
917
  if (!band)
425
0
    return isl_ast_loop_error;
426
917
427
917
  if (pos < 0 || pos >= band->n)
428
917
    
isl_die0
(isl_schedule_band_get_ctx(band), isl_error_invalid,
429
917
      "invalid member position", return isl_ast_loop_error);
430
917
431
917
  if (!band->isolate_loop_type)
432
50
    return isl_ast_loop_default;
433
867
434
867
  return band->isolate_loop_type[pos];
435
867
}
436
437
/* Set the loop AST generation type for the band member of "band"
438
 * at position "pos" to "type" for the part that has been isolated
439
 * by the isolate option.
440
 */
441
__isl_give isl_schedule_band *
442
isl_schedule_band_member_set_isolate_ast_loop_type(
443
  __isl_take isl_schedule_band *band, int pos,
444
  enum isl_ast_loop_type type)
445
0
{
446
0
  if (!band)
447
0
    return NULL;
448
0
  if (isl_schedule_band_member_get_isolate_ast_loop_type(band, pos) ==
449
0
                  type)
450
0
    return band;
451
0
452
0
  if (pos < 0 || pos >= band->n)
453
0
    isl_die(isl_schedule_band_get_ctx(band), isl_error_invalid,
454
0
      "invalid member position",
455
0
      return isl_schedule_band_free(band));
456
0
457
0
  band = isl_schedule_band_cow(band);
458
0
  if (!band)
459
0
    return isl_schedule_band_free(band);
460
0
461
0
  if (!band->isolate_loop_type) {
462
0
    isl_ctx *ctx;
463
0
464
0
    ctx = isl_schedule_band_get_ctx(band);
465
0
    band->isolate_loop_type = isl_calloc_array(ctx,
466
0
              enum isl_ast_loop_type, band->n);
467
0
    if (band->n && !band->isolate_loop_type)
468
0
      return isl_schedule_band_free(band);
469
0
  }
470
0
471
0
  band->isolate_loop_type[pos] = type;
472
0
473
0
  return band;
474
0
}
475
476
static const char *option_str[] = {
477
  [isl_ast_loop_atomic] = "atomic",
478
  [isl_ast_loop_unroll] = "unroll",
479
  [isl_ast_loop_separate] = "separate"
480
};
481
482
/* Given a parameter space "space", extend it to a set space
483
 *
484
 *  { type[x] }
485
 *
486
 * or
487
 *
488
 *  { [isolate[] -> type[x]] }
489
 *
490
 * depending on whether "isolate" is set.
491
 * These can be used to encode loop AST generation options of the given type.
492
 */
493
static __isl_give isl_space *loop_type_space(__isl_take isl_space *space,
494
  enum isl_ast_loop_type type, int isolate)
495
1.18k
{
496
1.18k
  const char *name;
497
1.18k
498
1.18k
  name = option_str[type];
499
1.18k
  space = isl_space_set_from_params(space);
500
1.18k
  space = isl_space_add_dims(space, isl_dim_set, 1);
501
1.18k
  space = isl_space_set_tuple_name(space, isl_dim_set, name);
502
1.18k
  if (!isolate)
503
888
    return space;
504
300
  space = isl_space_from_range(space);
505
300
  space = isl_space_set_tuple_name(space, isl_dim_in, "isolate");
506
300
  space = isl_space_wrap(space);
507
300
508
300
  return space;
509
300
}
510
511
/* Add encodings of the "n" loop AST generation options "type" to "options".
512
 * If "isolate" is set, then these options refer to the isolated part.
513
 *
514
 * In particular, for each sequence of consecutive identical types "t",
515
 * different from the default, add an option
516
 *
517
 *  { t[x] : first <= x <= last }
518
 *
519
 * or
520
 *
521
 *  { [isolate[] -> t[x]] : first <= x <= last }
522
 */
523
static __isl_give isl_union_set *add_loop_types(
524
  __isl_take isl_union_set *options, int n, enum isl_ast_loop_type *type,
525
  int isolate)
526
112
{
527
112
  int i;
528
112
529
112
  if (!type)
530
76
    return options;
531
36
  if (!options)
532
0
    return NULL;
533
36
534
72
  
for (i = 0; 36
i < n;
++i36
) {
535
36
    int first;
536
36
    isl_space *space;
537
36
    isl_set *option;
538
36
539
36
    if (type[i] == isl_ast_loop_default)
540
0
      continue;
541
36
542
36
    first = i;
543
108
    while (i + 1 < n && 
type[i + 1] == type[i]72
)
544
72
      ++i;
545
36
546
36
    space = isl_union_set_get_space(options);
547
36
    space = loop_type_space(space, type[i], isolate);
548
36
    option = isl_set_universe(space);
549
36
    option = isl_set_lower_bound_si(option, isl_dim_set, 0, first);
550
36
    option = isl_set_upper_bound_si(option, isl_dim_set, 0, i);
551
36
    options = isl_union_set_add_set(options, option);
552
36
  }
553
36
554
36
  return options;
555
36
}
556
557
/* Return the AST build options associated to "band".
558
 */
559
__isl_give isl_union_set *isl_schedule_band_get_ast_build_options(
560
  __isl_keep isl_schedule_band *band)
561
56
{
562
56
  isl_union_set *options;
563
56
564
56
  if (!band)
565
0
    return NULL;
566
56
567
56
  options = isl_union_set_copy(band->ast_build_options);
568
56
  options = add_loop_types(options, band->n, band->loop_type, 0);
569
56
  options = add_loop_types(options, band->n, band->isolate_loop_type, 1);
570
56
571
56
  return options;
572
56
}
573
574
/* Does "uset" contain any set that satisfies "is"?
575
 * "is" is assumed to set its integer argument to 1 if it is satisfied.
576
 */
577
static int has_any(__isl_keep isl_union_set *uset,
578
  isl_stat (*is)(__isl_take isl_set *set, void *user))
579
390
{
580
390
  int found = 0;
581
390
582
390
  if (isl_union_set_foreach_set(uset, is, &found) < 0 && 
!found170
)
583
0
    return -1;
584
390
585
390
  return found;
586
390
}
587
588
/* Does "set" live in a space of the form
589
 *
590
 *  isolate[[...] -> [...]]
591
 *
592
 * ?
593
 *
594
 * If so, set *found and abort the search.
595
 */
596
static isl_stat is_isolate(__isl_take isl_set *set, void *user)
597
107
{
598
107
  int *found = user;
599
107
600
107
  if (isl_set_has_tuple_name(set)) {
601
85
    const char *name;
602
85
    name = isl_set_get_tuple_name(set);
603
85
    if (isl_set_is_wrapping(set) && 
!strcmp(name, "isolate")65
)
604
65
      *found = 1;
605
85
  }
606
107
  isl_set_free(set);
607
107
608
107
  return *found ? 
isl_stat_error65
:
isl_stat_ok42
;
609
107
}
610
611
/* Does "options" include an option of the ofrm
612
 *
613
 *  isolate[[...] -> [...]]
614
 *
615
 * ?
616
 */
617
static int has_isolate_option(__isl_keep isl_union_set *options)
618
130
{
619
130
  return has_any(options, &is_isolate);
620
130
}
621
622
/* Does "set" encode a loop AST generation option?
623
 */
624
static isl_stat is_loop_type_option(__isl_take isl_set *set, void *user)
625
164
{
626
164
  int *found = user;
627
164
628
164
  if (isl_set_dim(set, isl_dim_set) == 1 &&
629
164
      
isl_set_has_tuple_name(set)103
) {
630
81
    const char *name;
631
81
    enum isl_ast_loop_type type;
632
81
    name = isl_set_get_tuple_name(set);
633
81
    for (type = isl_ast_loop_atomic;
634
169
        type <= isl_ast_loop_separate; 
++type88
) {
635
169
      if (strcmp(name, option_str[type]))
636
88
        continue;
637
81
      *found = 1;
638
81
      break;
639
81
    }
640
81
  }
641
164
  isl_set_free(set);
642
164
643
164
  return *found ? 
isl_stat_error81
:
isl_stat_ok83
;
644
164
}
645
646
/* Does "set" encode a loop AST generation option for the isolated part?
647
 * That is, is of the form
648
 *
649
 *  { [isolate[] -> t[x]] }
650
 *
651
 * with t equal to "atomic", "unroll" or "separate"?
652
 */
653
static isl_stat is_isolate_loop_type_option(__isl_take isl_set *set, void *user)
654
126
{
655
126
  int *found = user;
656
126
  const char *name;
657
126
  enum isl_ast_loop_type type;
658
126
  isl_map *map;
659
126
660
126
  if (!isl_set_is_wrapping(set)) {
661
59
    isl_set_free(set);
662
59
    return isl_stat_ok;
663
59
  }
664
67
  map = isl_set_unwrap(set);
665
67
  if (!isl_map_has_tuple_name(map, isl_dim_in) ||
666
67
      
!isl_map_has_tuple_name(map, isl_dim_out)24
) {
667
43
    isl_map_free(map);
668
43
    return isl_stat_ok;
669
43
  }
670
24
  name = isl_map_get_tuple_name(map, isl_dim_in);
671
24
  if (!strcmp(name, "isolate")) {
672
24
    name = isl_map_get_tuple_name(map, isl_dim_out);
673
24
    for (type = isl_ast_loop_atomic;
674
48
        type <= isl_ast_loop_separate; 
++type24
) {
675
48
      if (strcmp(name, option_str[type]))
676
24
        continue;
677
24
      *found = 1;
678
24
      break;
679
24
    }
680
24
  }
681
24
  isl_map_free(map);
682
24
683
24
  return *found ? isl_stat_error : 
isl_stat_ok0
;
684
24
}
685
686
/* Does "options" encode any loop AST generation options
687
 * for the isolated part?
688
 */
689
static int has_isolate_loop_type_options(__isl_keep isl_union_set *options)
690
130
{
691
130
  return has_any(options, &is_isolate_loop_type_option);
692
130
}
693
694
/* Does "options" encode any loop AST generation options?
695
 */
696
static int has_loop_type_options(__isl_keep isl_union_set *options)
697
130
{
698
130
  return has_any(options, &is_loop_type_option);
699
130
}
700
701
/* Extract the loop AST generation type for the band member
702
 * at position "pos" from "options".
703
 * If "isolate" is set, then extract the loop types for the isolated part.
704
 */
705
static enum isl_ast_loop_type extract_loop_type(
706
  __isl_keep isl_union_set *options, int pos, int isolate)
707
279
{
708
279
  isl_ctx *ctx;
709
279
  enum isl_ast_loop_type type, res = isl_ast_loop_default;
710
279
711
279
  ctx = isl_union_set_get_ctx(options);
712
279
  for (type = isl_ast_loop_atomic;
713
1.11k
      type <= isl_ast_loop_separate; 
++type837
) {
714
837
    isl_space *space;
715
837
    isl_set *option;
716
837
    int empty;
717
837
718
837
    space = isl_union_set_get_space(options);
719
837
    space = loop_type_space(space, type, isolate);
720
837
    option = isl_union_set_extract_set(options, space);
721
837
    option = isl_set_fix_si(option, isl_dim_set, 0, pos);
722
837
    empty = isl_set_is_empty(option);
723
837
    isl_set_free(option);
724
837
725
837
    if (empty < 0)
726
0
      return isl_ast_loop_error;
727
837
    if (empty)
728
558
      continue;
729
279
    if (res != isl_ast_loop_default)
730
279
      
isl_die0
(ctx, isl_error_invalid,
731
279
        "conflicting loop type options",
732
279
        return isl_ast_loop_error);
733
279
    res = type;
734
279
  }
735
279
736
279
  return res;
737
279
}
738
739
/* Extract the loop AST generation types for the members of "band"
740
 * from "options" and store them in band->loop_type.
741
 * Return -1 on error.
742
 */
743
static int extract_loop_types(__isl_keep isl_schedule_band *band,
744
  __isl_keep isl_union_set *options)
745
81
{
746
81
  int i;
747
81
748
81
  if (!band->loop_type) {
749
68
    isl_ctx *ctx = isl_schedule_band_get_ctx(band);
750
68
    band->loop_type = isl_alloc_array(ctx,
751
68
              enum isl_ast_loop_type, band->n);
752
68
    if (band->n && !band->loop_type)
753
0
      return -1;
754
81
  }
755
288
  
for (i = 0; 81
i < band->n;
++i207
) {
756
207
    band->loop_type[i] = extract_loop_type(options, i, 0);
757
207
    if (band->loop_type[i] == isl_ast_loop_error)
758
0
      return -1;
759
207
  }
760
81
761
81
  return 0;
762
81
}
763
764
/* Extract the loop AST generation types for the members of "band"
765
 * from "options" for the isolated part and
766
 * store them in band->isolate_loop_type.
767
 * Return -1 on error.
768
 */
769
static int extract_isolate_loop_types(__isl_keep isl_schedule_band *band,
770
  __isl_keep isl_union_set *options)
771
24
{
772
24
  int i;
773
24
774
24
  if (!band->isolate_loop_type) {
775
24
    isl_ctx *ctx = isl_schedule_band_get_ctx(band);
776
24
    band->isolate_loop_type = isl_alloc_array(ctx,
777
24
              enum isl_ast_loop_type, band->n);
778
24
    if (band->n && !band->isolate_loop_type)
779
0
      return -1;
780
24
  }
781
96
  
for (i = 0; 24
i < band->n;
++i72
) {
782
72
    band->isolate_loop_type[i] = extract_loop_type(options, i, 1);
783
72
    if (band->isolate_loop_type[i] == isl_ast_loop_error)
784
0
      return -1;
785
72
  }
786
24
787
24
  return 0;
788
24
}
789
790
/* Construct universe sets of the spaces that encode loop AST generation
791
 * types (for the isolated part if "isolate" is set).  That is, construct
792
 *
793
 *  { atomic[x]; separate[x]; unroll[x] }
794
 *
795
 * or
796
 *
797
 *  { [isolate[] -> atomic[x]]; [isolate[] -> separate[x]];
798
 *    [isolate[] -> unroll[x]] }
799
 */
800
static __isl_give isl_union_set *loop_types(__isl_take isl_space *space,
801
  int isolate)
802
105
{
803
105
  enum isl_ast_loop_type type;
804
105
  isl_union_set *types;
805
105
806
105
  types = isl_union_set_empty(space);
807
105
  for (type = isl_ast_loop_atomic;
808
420
      type <= isl_ast_loop_separate; 
++type315
) {
809
315
    isl_set *set;
810
315
811
315
    space = isl_union_set_get_space(types);
812
315
    space = loop_type_space(space, type, isolate);
813
315
    set = isl_set_universe(space);
814
315
    types = isl_union_set_add_set(types, set);
815
315
  }
816
105
817
105
  return types;
818
105
}
819
820
/* Remove all elements from spaces that encode loop AST generation types
821
 * from "options".
822
 */
823
static __isl_give isl_union_set *clear_loop_types(
824
  __isl_take isl_union_set *options)
825
81
{
826
81
  isl_union_set *types;
827
81
828
81
  types = loop_types(isl_union_set_get_space(options), 0);
829
81
  options = isl_union_set_subtract(options, types);
830
81
831
81
  return options;
832
81
}
833
834
/* Remove all elements from spaces that encode loop AST generation types
835
 * for the isolated part from "options".
836
 */
837
static __isl_give isl_union_set *clear_isolate_loop_types(
838
  __isl_take isl_union_set *options)
839
24
{
840
24
  isl_union_set *types;
841
24
842
24
  types = loop_types(isl_union_set_get_space(options), 1);
843
24
  options = isl_union_set_subtract(options, types);
844
24
845
24
  return options;
846
24
}
847
848
/* Replace the AST build options associated to "band" by "options".
849
 * If there are any loop AST generation type options, then they
850
 * are extracted and stored in band->loop_type.  Otherwise,
851
 * band->loop_type is removed to indicate that the default applies
852
 * to all members.  Similarly for the loop AST generation type options
853
 * for the isolated part, which are stored in band->isolate_loop_type.
854
 * The remaining options are stored in band->ast_build_options.
855
 *
856
 * Set anchored if the options include an isolate option since the
857
 * domain of the wrapped map references the outer band node schedules.
858
 */
859
__isl_give isl_schedule_band *isl_schedule_band_set_ast_build_options(
860
  __isl_take isl_schedule_band *band, __isl_take isl_union_set *options)
861
130
{
862
130
  int has_isolate, has_loop_type, has_isolate_loop_type;
863
130
864
130
  band = isl_schedule_band_cow(band);
865
130
  if (!band || !options)
866
0
    goto error;
867
130
  has_isolate = has_isolate_option(options);
868
130
  if (has_isolate < 0)
869
0
    goto error;
870
130
  has_loop_type = has_loop_type_options(options);
871
130
  if (has_loop_type < 0)
872
0
    goto error;
873
130
  has_isolate_loop_type = has_isolate_loop_type_options(options);
874
130
  if (has_isolate_loop_type < 0)
875
0
    goto error;
876
130
877
130
  if (!has_loop_type) {
878
49
    free(band->loop_type);
879
49
    band->loop_type = NULL;
880
81
  } else {
881
81
    if (extract_loop_types(band, options) < 0)
882
0
      goto error;
883
81
    options = clear_loop_types(options);
884
81
    if (!options)
885
0
      goto error;
886
130
  }
887
130
888
130
  if (!has_isolate_loop_type) {
889
106
    free(band->isolate_loop_type);
890
106
    band->isolate_loop_type = NULL;
891
106
  } else {
892
24
    if (extract_isolate_loop_types(band, options) < 0)
893
0
      goto error;
894
24
    options = clear_isolate_loop_types(options);
895
24
    if (!options)
896
0
      goto error;
897
130
  }
898
130
899
130
  isl_union_set_free(band->ast_build_options);
900
130
  band->ast_build_options = options;
901
130
  band->anchored = has_isolate;
902
130
903
130
  return band;
904
0
error:
905
0
  isl_schedule_band_free(band);
906
0
  isl_union_set_free(options);
907
0
  return NULL;
908
130
}
909
910
/* Return the "isolate" option associated to "band", assuming
911
 * it at appears at schedule depth "depth".
912
 *
913
 * The isolate option is of the form
914
 *
915
 *  isolate[[flattened outer bands] -> band]
916
 */
917
__isl_give isl_set *isl_schedule_band_get_ast_isolate_option(
918
  __isl_keep isl_schedule_band *band, int depth)
919
2.49k
{
920
2.49k
  isl_space *space;
921
2.49k
  isl_set *isolate;
922
2.49k
923
2.49k
  if (!band)
924
0
    return NULL;
925
2.49k
926
2.49k
  space = isl_schedule_band_get_space(band);
927
2.49k
  space = isl_space_from_range(space);
928
2.49k
  space = isl_space_add_dims(space, isl_dim_in, depth);
929
2.49k
  space = isl_space_wrap(space);
930
2.49k
  space = isl_space_set_tuple_name(space, isl_dim_set, "isolate");
931
2.49k
932
2.49k
  isolate = isl_union_set_extract_set(band->ast_build_options, space);
933
2.49k
934
2.49k
  return isolate;
935
2.49k
}
936
937
/* Replace the option "drop" in the AST build options by "add".
938
 * That is, remove "drop" and add "add".
939
 */
940
__isl_give isl_schedule_band *isl_schedule_band_replace_ast_build_option(
941
  __isl_take isl_schedule_band *band, __isl_take isl_set *drop,
942
  __isl_take isl_set *add)
943
72
{
944
72
  isl_union_set *options;
945
72
946
72
  band = isl_schedule_band_cow(band);
947
72
  if (!band)
948
0
    goto error;
949
72
950
72
  options = band->ast_build_options;
951
72
  options = isl_union_set_subtract(options, isl_union_set_from_set(drop));
952
72
  options = isl_union_set_union(options, isl_union_set_from_set(add));
953
72
  band->ast_build_options = options;
954
72
955
72
  if (!band->ast_build_options)
956
0
    return isl_schedule_band_free(band);
957
72
958
72
  return band;
959
0
error:
960
0
  isl_schedule_band_free(band);
961
0
  isl_set_free(drop);
962
0
  isl_set_free(add);
963
0
  return NULL;
964
72
}
965
966
/* Multiply the partial schedule of "band" with the factors in "mv".
967
 * Replace the result by its greatest integer part to ensure
968
 * that the schedule is always integral.
969
 */
970
__isl_give isl_schedule_band *isl_schedule_band_scale(
971
  __isl_take isl_schedule_band *band, __isl_take isl_multi_val *mv)
972
0
{
973
0
  band = isl_schedule_band_cow(band);
974
0
  if (!band || !mv)
975
0
    goto error;
976
0
  band->mupa = isl_multi_union_pw_aff_scale_multi_val(band->mupa, mv);
977
0
  band->mupa = isl_multi_union_pw_aff_floor(band->mupa);
978
0
  if (!band->mupa)
979
0
    return isl_schedule_band_free(band);
980
0
  return band;
981
0
error:
982
0
  isl_schedule_band_free(band);
983
0
  isl_multi_val_free(mv);
984
0
  return NULL;
985
0
}
986
987
/* Divide the partial schedule of "band" by the factors in "mv".
988
 * Replace the result by its greatest integer part to ensure
989
 * that the schedule is always integral.
990
 */
991
__isl_give isl_schedule_band *isl_schedule_band_scale_down(
992
  __isl_take isl_schedule_band *band, __isl_take isl_multi_val *mv)
993
0
{
994
0
  band = isl_schedule_band_cow(band);
995
0
  if (!band || !mv)
996
0
    goto error;
997
0
  band->mupa = isl_multi_union_pw_aff_scale_down_multi_val(band->mupa,
998
0
                mv);
999
0
  band->mupa = isl_multi_union_pw_aff_floor(band->mupa);
1000
0
  if (!band->mupa)
1001
0
    return isl_schedule_band_free(band);
1002
0
  return band;
1003
0
error:
1004
0
  isl_schedule_band_free(band);
1005
0
  isl_multi_val_free(mv);
1006
0
  return NULL;
1007
0
}
1008
1009
/* Reduce the partial schedule of "band" modulo the factors in "mv".
1010
 */
1011
__isl_give isl_schedule_band *isl_schedule_band_mod(
1012
  __isl_take isl_schedule_band *band, __isl_take isl_multi_val *mv)
1013
0
{
1014
0
  band = isl_schedule_band_cow(band);
1015
0
  if (!band || !mv)
1016
0
    goto error;
1017
0
  band->mupa = isl_multi_union_pw_aff_mod_multi_val(band->mupa, mv);
1018
0
  if (!band->mupa)
1019
0
    return isl_schedule_band_free(band);
1020
0
  return band;
1021
0
error:
1022
0
  isl_schedule_band_free(band);
1023
0
  isl_multi_val_free(mv);
1024
0
  return NULL;
1025
0
}
1026
1027
/* Shift the partial schedule of "band" by "shift" after checking
1028
 * that the domain of the partial schedule would not be affected
1029
 * by this shift.
1030
 */
1031
__isl_give isl_schedule_band *isl_schedule_band_shift(
1032
  __isl_take isl_schedule_band *band,
1033
  __isl_take isl_multi_union_pw_aff *shift)
1034
0
{
1035
0
  isl_union_set *dom1, *dom2;
1036
0
  isl_bool subset;
1037
0
1038
0
  band = isl_schedule_band_cow(band);
1039
0
  if (!band || !shift)
1040
0
    goto error;
1041
0
  dom1 = isl_multi_union_pw_aff_domain(
1042
0
        isl_multi_union_pw_aff_copy(band->mupa));
1043
0
  dom2 = isl_multi_union_pw_aff_domain(
1044
0
        isl_multi_union_pw_aff_copy(shift));
1045
0
  subset = isl_union_set_is_subset(dom1, dom2);
1046
0
  isl_union_set_free(dom1);
1047
0
  isl_union_set_free(dom2);
1048
0
  if (subset < 0)
1049
0
    goto error;
1050
0
  if (!subset)
1051
0
    isl_die(isl_schedule_band_get_ctx(band), isl_error_invalid,
1052
0
      "domain of shift needs to include domain of "
1053
0
      "partial schedule", goto error);
1054
0
  band->mupa = isl_multi_union_pw_aff_add(band->mupa, shift);
1055
0
  if (!band->mupa)
1056
0
    return isl_schedule_band_free(band);
1057
0
  return band;
1058
0
error:
1059
0
  isl_schedule_band_free(band);
1060
0
  isl_multi_union_pw_aff_free(shift);
1061
0
  return NULL;
1062
0
}
1063
1064
/* Given the schedule of a band, construct the corresponding
1065
 * schedule for the tile loops based on the given tile sizes
1066
 * and return the result.
1067
 *
1068
 * If the scale tile loops options is set, then the tile loops
1069
 * are scaled by the tile sizes.
1070
 *
1071
 * That is replace each schedule dimension "i" by either
1072
 * "floor(i/s)" or "s * floor(i/s)".
1073
 */
1074
static isl_multi_union_pw_aff *isl_multi_union_pw_aff_tile(
1075
  __isl_take isl_multi_union_pw_aff *sched,
1076
  __isl_take isl_multi_val *sizes)
1077
80
{
1078
80
  isl_ctx *ctx;
1079
80
  int i, n;
1080
80
  isl_val *v;
1081
80
  int scale;
1082
80
1083
80
  ctx = isl_multi_val_get_ctx(sizes);
1084
80
  scale = isl_options_get_tile_scale_tile_loops(ctx);
1085
80
1086
80
  n = isl_multi_union_pw_aff_dim(sched, isl_dim_set);
1087
256
  for (i = 0; i < n; 
++i176
) {
1088
176
    isl_union_pw_aff *upa;
1089
176
1090
176
    upa = isl_multi_union_pw_aff_get_union_pw_aff(sched, i);
1091
176
    v = isl_multi_val_get_val(sizes, i);
1092
176
1093
176
    upa = isl_union_pw_aff_scale_down_val(upa, isl_val_copy(v));
1094
176
    upa = isl_union_pw_aff_floor(upa);
1095
176
    if (scale)
1096
4
      upa = isl_union_pw_aff_scale_val(upa, isl_val_copy(v));
1097
176
    isl_val_free(v);
1098
176
1099
176
    sched = isl_multi_union_pw_aff_set_union_pw_aff(sched, i, upa);
1100
176
  }
1101
80
1102
80
  isl_multi_val_free(sizes);
1103
80
  return sched;
1104
80
}
1105
1106
/* Replace "band" by a band corresponding to the tile loops of a tiling
1107
 * with the given tile sizes.
1108
 */
1109
__isl_give isl_schedule_band *isl_schedule_band_tile(
1110
  __isl_take isl_schedule_band *band, __isl_take isl_multi_val *sizes)
1111
80
{
1112
80
  band = isl_schedule_band_cow(band);
1113
80
  if (!band || !sizes)
1114
0
    goto error;
1115
80
  band->mupa = isl_multi_union_pw_aff_tile(band->mupa, sizes);
1116
80
  if (!band->mupa)
1117
0
    return isl_schedule_band_free(band);
1118
80
  return band;
1119
0
error:
1120
0
  isl_schedule_band_free(band);
1121
0
  isl_multi_val_free(sizes);
1122
0
  return NULL;
1123
80
}
1124
1125
/* Replace "band" by a band corresponding to the point loops of a tiling
1126
 * with the given tile sizes.
1127
 * "tile" is the corresponding tile loop band.
1128
 *
1129
 * If the shift point loops option is set, then the point loops
1130
 * are shifted to start at zero.  That is, each schedule dimension "i"
1131
 * is replaced by "i - s * floor(i/s)".
1132
 * The expression "floor(i/s)" (or "s * floor(i/s)") is extracted from
1133
 * the tile band.
1134
 *
1135
 * Otherwise, the band is left untouched.
1136
 */
1137
__isl_give isl_schedule_band *isl_schedule_band_point(
1138
  __isl_take isl_schedule_band *band, __isl_keep isl_schedule_band *tile,
1139
  __isl_take isl_multi_val *sizes)
1140
80
{
1141
80
  isl_ctx *ctx;
1142
80
  isl_multi_union_pw_aff *scaled;
1143
80
1144
80
  if (!band || !sizes)
1145
0
    goto error;
1146
80
1147
80
  ctx = isl_schedule_band_get_ctx(band);
1148
80
  if (!isl_options_get_tile_shift_point_loops(ctx)) {
1149
2
    isl_multi_val_free(sizes);
1150
2
    return band;
1151
2
  }
1152
78
  band = isl_schedule_band_cow(band);
1153
78
  if (!band)
1154
0
    goto error;
1155
78
1156
78
  scaled = isl_schedule_band_get_partial_schedule(tile);
1157
78
  if (!isl_options_get_tile_scale_tile_loops(ctx))
1158
77
    scaled = isl_multi_union_pw_aff_scale_multi_val(scaled, sizes);
1159
1
  else
1160
1
    isl_multi_val_free(sizes);
1161
78
  band->mupa = isl_multi_union_pw_aff_sub(band->mupa, scaled);
1162
78
  if (!band->mupa)
1163
0
    return isl_schedule_band_free(band);
1164
78
  return band;
1165
0
error:
1166
0
  isl_schedule_band_free(band);
1167
0
  isl_multi_val_free(sizes);
1168
0
  return NULL;
1169
78
}
1170
1171
/* Drop the "n" dimensions starting at "pos" from "band".
1172
 *
1173
 * We apply the transformation even if "n" is zero to ensure consistent
1174
 * behavior with respect to changes in the schedule space.
1175
 *
1176
 * The caller is responsible for updating the isolate option.
1177
 */
1178
__isl_give isl_schedule_band *isl_schedule_band_drop(
1179
  __isl_take isl_schedule_band *band, int pos, int n)
1180
72
{
1181
72
  int i;
1182
72
1183
72
  if (pos < 0 || n < 0 || pos + n > band->n)
1184
72
    
isl_die0
(isl_schedule_band_get_ctx(band), isl_error_internal,
1185
72
      "range out of bounds",
1186
72
      return isl_schedule_band_free(band));
1187
72
1188
72
  band = isl_schedule_band_cow(band);
1189
72
  if (!band)
1190
0
    return NULL;
1191
72
1192
72
  band->mupa = isl_multi_union_pw_aff_drop_dims(band->mupa,
1193
72
              isl_dim_set, pos, n);
1194
72
  if (!band->mupa)
1195
0
    return isl_schedule_band_free(band);
1196
72
1197
115
  
for (i = pos + n; 72
i < band->n;
++i43
)
1198
43
    band->coincident[i - n] = band->coincident[i];
1199
72
  if (band->loop_type)
1200
3
    
for (i = pos + n; 2
i < band->n;
++i1
)
1201
1
      band->loop_type[i - n] = band->loop_type[i];
1202
72
  if (band->isolate_loop_type)
1203
0
    for (i = pos + n; i < band->n; ++i)
1204
0
      band->isolate_loop_type[i - n] =
1205
0
                band->isolate_loop_type[i];
1206
72
1207
72
  band->n -= n;
1208
72
1209
72
  return band;
1210
72
}
1211
1212
/* Reset the user pointer on all identifiers of parameters and tuples
1213
 * in "band".
1214
 */
1215
__isl_give isl_schedule_band *isl_schedule_band_reset_user(
1216
  __isl_take isl_schedule_band *band)
1217
0
{
1218
0
  band = isl_schedule_band_cow(band);
1219
0
  if (!band)
1220
0
    return NULL;
1221
0
1222
0
  band->mupa = isl_multi_union_pw_aff_reset_user(band->mupa);
1223
0
  band->ast_build_options =
1224
0
    isl_union_set_reset_user(band->ast_build_options);
1225
0
  if (!band->mupa || !band->ast_build_options)
1226
0
    return isl_schedule_band_free(band);
1227
0
1228
0
  return band;
1229
0
}
1230
1231
/* Align the parameters of "band" to those of "space".
1232
 */
1233
__isl_give isl_schedule_band *isl_schedule_band_align_params(
1234
  __isl_take isl_schedule_band *band, __isl_take isl_space *space)
1235
0
{
1236
0
  band = isl_schedule_band_cow(band);
1237
0
  if (!band || !space)
1238
0
    goto error;
1239
0
1240
0
  band->mupa = isl_multi_union_pw_aff_align_params(band->mupa,
1241
0
            isl_space_copy(space));
1242
0
  band->ast_build_options =
1243
0
    isl_union_set_align_params(band->ast_build_options, space);
1244
0
  if (!band->mupa || !band->ast_build_options)
1245
0
    return isl_schedule_band_free(band);
1246
0
1247
0
  return band;
1248
0
error:
1249
0
  isl_space_free(space);
1250
0
  isl_schedule_band_free(band);
1251
0
  return NULL;
1252
0
}
1253
1254
/* Compute the pullback of "band" by the function represented by "upma".
1255
 * In other words, plug in "upma" in the iteration domains of "band".
1256
 */
1257
__isl_give isl_schedule_band *isl_schedule_band_pullback_union_pw_multi_aff(
1258
  __isl_take isl_schedule_band *band,
1259
  __isl_take isl_union_pw_multi_aff *upma)
1260
322
{
1261
322
  band = isl_schedule_band_cow(band);
1262
322
  if (!band || !upma)
1263
0
    goto error;
1264
322
1265
322
  band->mupa =
1266
322
    isl_multi_union_pw_aff_pullback_union_pw_multi_aff(band->mupa,
1267
322
                  upma);
1268
322
  if (!band->mupa)
1269
0
    return isl_schedule_band_free(band);
1270
322
1271
322
  return band;
1272
0
error:
1273
0
  isl_union_pw_multi_aff_free(upma);
1274
0
  isl_schedule_band_free(band);
1275
0
  return NULL;
1276
322
}
1277
1278
/* Compute the gist of "band" with respect to "context".
1279
 * In particular, compute the gist of the associated partial schedule.
1280
 */
1281
__isl_give isl_schedule_band *isl_schedule_band_gist(
1282
  __isl_take isl_schedule_band *band, __isl_take isl_union_set *context)
1283
315
{
1284
315
  if (!band || !context)
1285
0
    goto error;
1286
315
  if (band->n == 0) {
1287
0
    isl_union_set_free(context);
1288
0
    return band;
1289
0
  }
1290
315
  band = isl_schedule_band_cow(band);
1291
315
  if (!band)
1292
0
    goto error;
1293
315
  band->mupa = isl_multi_union_pw_aff_gist(band->mupa, context);
1294
315
  if (!band->mupa)
1295
0
    return isl_schedule_band_free(band);
1296
315
  return band;
1297
0
error:
1298
0
  isl_union_set_free(context);
1299
0
  isl_schedule_band_free(band);
1300
0
  return NULL;
1301
315
}