Coverage Report

Created: 2017-06-23 12:40

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