Coverage Report

Created: 2017-03-28 09:59

/Users/buildslave/jenkins/sharedspace/clang-stage2-coverage-R@2/llvm/tools/polly/lib/External/isl/isl_schedule_tree.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * Copyright 2013-2014 Ecole Normale Superieure
3
 * Copyright 2014      INRIA Rocquencourt
4
 * Copyright 2016      INRIA Paris
5
 *
6
 * Use of this software is governed by the MIT license
7
 *
8
 * Written by Sven Verdoolaege,
9
 * Ecole Normale Superieure, 45 rue d'Ulm, 75230 Paris, France
10
 * and Inria Paris - Rocquencourt, Domaine de Voluceau - Rocquencourt,
11
 * B.P. 105 - 78153 Le Chesnay, France
12
 * and Centre de Recherche Inria de Paris, 2 rue Simone Iff - Voie DQ12,
13
 * CS 42112, 75589 Paris Cedex 12, France
14
 */
15
16
#include <isl/map.h>
17
#include <isl_schedule_band.h>
18
#include <isl_schedule_private.h>
19
20
#undef EL
21
#define EL isl_schedule_tree
22
23
#include <isl_list_templ.h>
24
25
#undef BASE
26
#define BASE schedule_tree
27
28
#include <isl_list_templ.c>
29
30
/* Is "tree" the leaf of a schedule tree?
31
 */
32
int isl_schedule_tree_is_leaf(__isl_keep isl_schedule_tree *tree)
33
61.7k
{
34
61.7k
  return isl_schedule_tree_get_type(tree) == isl_schedule_node_leaf;
35
61.7k
}
36
37
/* Create a new schedule tree of type "type".
38
 * The caller is responsible for filling in the type specific fields and
39
 * the children.
40
 *
41
 * By default, the single node tree does not have any anchored nodes.
42
 * The caller is responsible for updating the anchored field if needed.
43
 */
44
static __isl_give isl_schedule_tree *isl_schedule_tree_alloc(isl_ctx *ctx,
45
  enum isl_schedule_node_type type)
46
24.5k
{
47
24.5k
  isl_schedule_tree *tree;
48
24.5k
49
24.5k
  if (type == isl_schedule_node_error)
50
0
    return NULL;
51
24.5k
52
24.5k
  
tree = 24.5k
isl_calloc_type24.5k
(ctx, isl_schedule_tree);
53
24.5k
  if (!tree)
54
0
    return NULL;
55
24.5k
56
24.5k
  tree->ref = 1;
57
24.5k
  tree->ctx = ctx;
58
24.5k
  isl_ctx_ref(ctx);
59
24.5k
  tree->type = type;
60
24.5k
  tree->anchored = 0;
61
24.5k
62
24.5k
  return tree;
63
24.5k
}
64
65
/* Return a fresh copy of "tree".
66
 */
67
__isl_take isl_schedule_tree *isl_schedule_tree_dup(
68
  __isl_keep isl_schedule_tree *tree)
69
13.7k
{
70
13.7k
  isl_ctx *ctx;
71
13.7k
  isl_schedule_tree *dup;
72
13.7k
73
13.7k
  if (!tree)
74
0
    return NULL;
75
13.7k
76
13.7k
  ctx = isl_schedule_tree_get_ctx(tree);
77
13.7k
  dup = isl_schedule_tree_alloc(ctx, tree->type);
78
13.7k
  if (!dup)
79
0
    return NULL;
80
13.7k
81
13.7k
  switch (tree->type) {
82
0
  case isl_schedule_node_error:
83
0
    isl_die(ctx, isl_error_internal,
84
0
      "allocation should have failed",
85
0
      return isl_schedule_tree_free(dup));
86
2.33k
  case isl_schedule_node_band:
87
2.33k
    dup->band = isl_schedule_band_copy(tree->band);
88
2.33k
    if (!dup->band)
89
0
      return isl_schedule_tree_free(dup);
90
2.33k
    break;
91
0
  case isl_schedule_node_context:
92
0
    dup->context = isl_set_copy(tree->context);
93
0
    if (!dup->context)
94
0
      return isl_schedule_tree_free(dup);
95
0
    break;
96
5.23k
  case isl_schedule_node_domain:
97
5.23k
    dup->domain = isl_union_set_copy(tree->domain);
98
5.23k
    if (!dup->domain)
99
0
      return isl_schedule_tree_free(dup);
100
5.23k
    break;
101
2
  case isl_schedule_node_expansion:
102
2
    dup->contraction =
103
2
      isl_union_pw_multi_aff_copy(tree->contraction);
104
2
    dup->expansion = isl_union_map_copy(tree->expansion);
105
2
    if (
!dup->contraction || 2
!dup->expansion2
)
106
0
      return isl_schedule_tree_free(dup);
107
2
    break;
108
45
  case isl_schedule_node_extension:
109
45
    dup->extension = isl_union_map_copy(tree->extension);
110
45
    if (!dup->extension)
111
0
      return isl_schedule_tree_free(dup);
112
45
    break;
113
3.21k
  case isl_schedule_node_filter:
114
3.21k
    dup->filter = isl_union_set_copy(tree->filter);
115
3.21k
    if (!dup->filter)
116
0
      return isl_schedule_tree_free(dup);
117
3.21k
    break;
118
0
  case isl_schedule_node_guard:
119
0
    dup->guard = isl_set_copy(tree->guard);
120
0
    if (!dup->guard)
121
0
      return isl_schedule_tree_free(dup);
122
0
    break;
123
898
  case isl_schedule_node_mark:
124
898
    dup->mark = isl_id_copy(tree->mark);
125
898
    if (!dup->mark)
126
0
      return isl_schedule_tree_free(dup);
127
898
    break;
128
2.01k
  case isl_schedule_node_leaf:
129
2.01k
  case isl_schedule_node_sequence:
130
2.01k
  case isl_schedule_node_set:
131
2.01k
    break;
132
13.7k
  }
133
13.7k
134
13.7k
  
if (13.7k
tree->children13.7k
)
{10.0k
135
10.0k
    dup->children = isl_schedule_tree_list_copy(tree->children);
136
10.0k
    if (!dup->children)
137
0
      return isl_schedule_tree_free(dup);
138
10.0k
  }
139
13.7k
  dup->anchored = tree->anchored;
140
13.7k
141
13.7k
  return dup;
142
13.7k
}
143
144
/* Return an isl_schedule_tree that is equal to "tree" and that has only
145
 * a single reference.
146
 */
147
__isl_give isl_schedule_tree *isl_schedule_tree_cow(
148
  __isl_take isl_schedule_tree *tree)
149
18.4k
{
150
18.4k
  if (!tree)
151
0
    return NULL;
152
18.4k
153
18.4k
  
if (18.4k
tree->ref == 118.4k
)
154
4.71k
    return tree;
155
13.7k
  tree->ref--;
156
13.7k
  return isl_schedule_tree_dup(tree);
157
18.4k
}
158
159
/* Return a new reference to "tree".
160
 */
161
__isl_give isl_schedule_tree *isl_schedule_tree_copy(
162
  __isl_keep isl_schedule_tree *tree)
163
410k
{
164
410k
  if (!tree)
165
0
    return NULL;
166
410k
167
410k
  tree->ref++;
168
410k
  return tree;
169
410k
}
170
171
/* Free "tree" and return NULL.
172
 */
173
__isl_null isl_schedule_tree *isl_schedule_tree_free(
174
  __isl_take isl_schedule_tree *tree)
175
420k
{
176
420k
  if (!tree)
177
2
    return NULL;
178
420k
  
if (420k
--tree->ref > 0420k
)
179
396k
    return NULL;
180
420k
181
24.5k
  switch (tree->type) {
182
3.85k
  case isl_schedule_node_band:
183
3.85k
    isl_schedule_band_free(tree->band);
184
3.85k
    break;
185
0
  case isl_schedule_node_context:
186
0
    isl_set_free(tree->context);
187
0
    break;
188
8.66k
  case isl_schedule_node_domain:
189
8.66k
    isl_union_set_free(tree->domain);
190
8.66k
    break;
191
5
  case isl_schedule_node_expansion:
192
5
    isl_union_pw_multi_aff_free(tree->contraction);
193
5
    isl_union_map_free(tree->expansion);
194
5
    break;
195
81
  case isl_schedule_node_extension:
196
81
    isl_union_map_free(tree->extension);
197
81
    break;
198
4.42k
  case isl_schedule_node_filter:
199
4.42k
    isl_union_set_free(tree->filter);
200
4.42k
    break;
201
0
  case isl_schedule_node_guard:
202
0
    isl_set_free(tree->guard);
203
0
    break;
204
1.02k
  case isl_schedule_node_mark:
205
1.02k
    isl_id_free(tree->mark);
206
1.02k
    break;
207
6.50k
  case isl_schedule_node_sequence:
208
6.50k
  case isl_schedule_node_set:
209
6.50k
  case isl_schedule_node_error:
210
6.50k
  case isl_schedule_node_leaf:
211
6.50k
    break;
212
24.5k
  }
213
24.5k
  isl_schedule_tree_list_free(tree->children);
214
24.5k
  isl_ctx_deref(tree->ctx);
215
24.5k
  free(tree);
216
24.5k
217
24.5k
  return NULL;
218
24.5k
}
219
220
/* Create and return a new leaf schedule tree.
221
 */
222
__isl_give isl_schedule_tree *isl_schedule_tree_leaf(isl_ctx *ctx)
223
3.74k
{
224
3.74k
  return isl_schedule_tree_alloc(ctx, isl_schedule_node_leaf);
225
3.74k
}
226
227
/* Create a new band schedule tree referring to "band"
228
 * with no children.
229
 */
230
__isl_give isl_schedule_tree *isl_schedule_tree_from_band(
231
  __isl_take isl_schedule_band *band)
232
1.51k
{
233
1.51k
  isl_ctx *ctx;
234
1.51k
  isl_schedule_tree *tree;
235
1.51k
236
1.51k
  if (!band)
237
0
    return NULL;
238
1.51k
239
1.51k
  ctx = isl_schedule_band_get_ctx(band);
240
1.51k
  tree = isl_schedule_tree_alloc(ctx, isl_schedule_node_band);
241
1.51k
  if (!tree)
242
0
    goto error;
243
1.51k
244
1.51k
  tree->band = band;
245
1.51k
  tree->anchored = isl_schedule_band_is_anchored(band);
246
1.51k
247
1.51k
  return tree;
248
0
error:
249
0
  isl_schedule_band_free(band);
250
0
  return NULL;
251
1.51k
}
252
253
/* Create a new context schedule tree with the given context and no children.
254
 * Since the context references the outer schedule dimension,
255
 * the tree is anchored.
256
 */
257
__isl_give isl_schedule_tree *isl_schedule_tree_from_context(
258
  __isl_take isl_set *context)
259
0
{
260
0
  isl_ctx *ctx;
261
0
  isl_schedule_tree *tree;
262
0
263
0
  if (!context)
264
0
    return NULL;
265
0
266
0
  ctx = isl_set_get_ctx(context);
267
0
  tree = isl_schedule_tree_alloc(ctx, isl_schedule_node_context);
268
0
  if (!tree)
269
0
    goto error;
270
0
271
0
  tree->context = context;
272
0
  tree->anchored = 1;
273
0
274
0
  return tree;
275
0
error:
276
0
  isl_set_free(context);
277
0
  return NULL;
278
0
}
279
280
/* Create a new domain schedule tree with the given domain and no children.
281
 */
282
__isl_give isl_schedule_tree *isl_schedule_tree_from_domain(
283
  __isl_take isl_union_set *domain)
284
3.43k
{
285
3.43k
  isl_ctx *ctx;
286
3.43k
  isl_schedule_tree *tree;
287
3.43k
288
3.43k
  if (!domain)
289
5
    return NULL;
290
3.43k
291
3.43k
  ctx = isl_union_set_get_ctx(domain);
292
3.43k
  tree = isl_schedule_tree_alloc(ctx, isl_schedule_node_domain);
293
3.43k
  if (!tree)
294
0
    goto error;
295
3.43k
296
3.43k
  tree->domain = domain;
297
3.43k
298
3.43k
  return tree;
299
0
error:
300
0
  isl_union_set_free(domain);
301
0
  return NULL;
302
3.43k
}
303
304
/* Create a new expansion schedule tree with the given contraction and
305
 * expansion and no children.
306
 */
307
__isl_give isl_schedule_tree *isl_schedule_tree_from_expansion(
308
  __isl_take isl_union_pw_multi_aff *contraction,
309
  __isl_take isl_union_map *expansion)
310
3
{
311
3
  isl_ctx *ctx;
312
3
  isl_schedule_tree *tree;
313
3
314
3
  if (
!contraction || 3
!expansion3
)
315
0
    goto error;
316
3
317
3
  ctx = isl_union_map_get_ctx(expansion);
318
3
  tree = isl_schedule_tree_alloc(ctx, isl_schedule_node_expansion);
319
3
  if (!tree)
320
0
    goto error;
321
3
322
3
  tree->contraction = contraction;
323
3
  tree->expansion = expansion;
324
3
325
3
  return tree;
326
0
error:
327
0
  isl_union_pw_multi_aff_free(contraction);
328
0
  isl_union_map_free(expansion);
329
0
  return NULL;
330
3
}
331
332
/* Create a new extension schedule tree with the given extension and
333
 * no children.
334
 * Since the domain of the extension refers to the outer schedule dimension,
335
 * the tree is anchored.
336
 */
337
__isl_give isl_schedule_tree *isl_schedule_tree_from_extension(
338
  __isl_take isl_union_map *extension)
339
36
{
340
36
  isl_ctx *ctx;
341
36
  isl_schedule_tree *tree;
342
36
343
36
  if (!extension)
344
0
    return NULL;
345
36
346
36
  ctx = isl_union_map_get_ctx(extension);
347
36
  tree = isl_schedule_tree_alloc(ctx, isl_schedule_node_extension);
348
36
  if (!tree)
349
0
    goto error;
350
36
351
36
  tree->extension = extension;
352
36
  tree->anchored = 1;
353
36
354
36
  return tree;
355
0
error:
356
0
  isl_union_map_free(extension);
357
0
  return NULL;
358
36
}
359
360
/* Create a new filter schedule tree with the given filter and no children.
361
 */
362
__isl_give isl_schedule_tree *isl_schedule_tree_from_filter(
363
  __isl_take isl_union_set *filter)
364
1.20k
{
365
1.20k
  isl_ctx *ctx;
366
1.20k
  isl_schedule_tree *tree;
367
1.20k
368
1.20k
  if (!filter)
369
0
    return NULL;
370
1.20k
371
1.20k
  ctx = isl_union_set_get_ctx(filter);
372
1.20k
  tree = isl_schedule_tree_alloc(ctx, isl_schedule_node_filter);
373
1.20k
  if (!tree)
374
0
    goto error;
375
1.20k
376
1.20k
  tree->filter = filter;
377
1.20k
378
1.20k
  return tree;
379
0
error:
380
0
  isl_union_set_free(filter);
381
0
  return NULL;
382
1.20k
}
383
384
/* Create a new guard schedule tree with the given guard and no children.
385
 * Since the guard references the outer schedule dimension,
386
 * the tree is anchored.
387
 */
388
__isl_give isl_schedule_tree *isl_schedule_tree_from_guard(
389
  __isl_take isl_set *guard)
390
0
{
391
0
  isl_ctx *ctx;
392
0
  isl_schedule_tree *tree;
393
0
394
0
  if (!guard)
395
0
    return NULL;
396
0
397
0
  ctx = isl_set_get_ctx(guard);
398
0
  tree = isl_schedule_tree_alloc(ctx, isl_schedule_node_guard);
399
0
  if (!tree)
400
0
    goto error;
401
0
402
0
  tree->guard = guard;
403
0
  tree->anchored = 1;
404
0
405
0
  return tree;
406
0
error:
407
0
  isl_set_free(guard);
408
0
  return NULL;
409
0
}
410
411
/* Create a new mark schedule tree with the given mark identifier and
412
 * no children.
413
 */
414
__isl_give isl_schedule_tree *isl_schedule_tree_from_mark(
415
  __isl_take isl_id *mark)
416
123
{
417
123
  isl_ctx *ctx;
418
123
  isl_schedule_tree *tree;
419
123
420
123
  if (!mark)
421
0
    return NULL;
422
123
423
123
  ctx = isl_id_get_ctx(mark);
424
123
  tree = isl_schedule_tree_alloc(ctx, isl_schedule_node_mark);
425
123
  if (!tree)
426
0
    goto error;
427
123
428
123
  tree->mark = mark;
429
123
430
123
  return tree;
431
0
error:
432
0
  isl_id_free(mark);
433
0
  return NULL;
434
123
}
435
436
/* Does "tree" have any node that depends on its position
437
 * in the complete schedule tree?
438
 */
439
isl_bool isl_schedule_tree_is_subtree_anchored(
440
  __isl_keep isl_schedule_tree *tree)
441
3.00k
{
442
3.00k
  return tree ? 
tree->anchored3.00k
:
isl_bool_error0
;
443
3.00k
}
444
445
/* Does the root node of "tree" depend on its position in the complete
446
 * schedule tree?
447
 * Band nodes may be anchored depending on the associated AST build options.
448
 * Context, extension and guard nodes are always anchored.
449
 */
450
int isl_schedule_tree_is_anchored(__isl_keep isl_schedule_tree *tree)
451
13.0k
{
452
13.0k
  if (!tree)
453
0
    return -1;
454
13.0k
455
13.0k
  switch (isl_schedule_tree_get_type(tree)) {
456
0
  case isl_schedule_node_error:
457
0
    return -1;
458
2.07k
  case isl_schedule_node_band:
459
2.07k
    return isl_schedule_band_is_anchored(tree->band);
460
63
  case isl_schedule_node_context:
461
63
  case isl_schedule_node_extension:
462
63
  case isl_schedule_node_guard:
463
63
    return 1;
464
10.8k
  case isl_schedule_node_domain:
465
10.8k
  case isl_schedule_node_expansion:
466
10.8k
  case isl_schedule_node_filter:
467
10.8k
  case isl_schedule_node_leaf:
468
10.8k
  case isl_schedule_node_mark:
469
10.8k
  case isl_schedule_node_sequence:
470
10.8k
  case isl_schedule_node_set:
471
10.8k
    return 0;
472
13.0k
  }
473
13.0k
474
0
  
isl_die0
(isl_schedule_tree_get_ctx(tree), isl_error_internal,0
475
0
    "unhandled case", return -1);
476
0
}
477
478
/* Update the anchored field of "tree" based on whether the root node
479
 * itself in anchored and the anchored fields of the children.
480
 *
481
 * This function should be called whenever the children of a tree node
482
 * are changed or the anchoredness of the tree root itself changes.
483
 */
484
__isl_give isl_schedule_tree *isl_schedule_tree_update_anchored(
485
  __isl_take isl_schedule_tree *tree)
486
12.8k
{
487
12.8k
  int i, n;
488
12.8k
  int anchored;
489
12.8k
490
12.8k
  if (!tree)
491
0
    return NULL;
492
12.8k
493
12.8k
  anchored = isl_schedule_tree_is_anchored(tree);
494
12.8k
  if (anchored < 0)
495
0
    return isl_schedule_tree_free(tree);
496
12.8k
497
12.8k
  n = isl_schedule_tree_list_n_schedule_tree(tree->children);
498
51.8k
  for (i = 0; 
!anchored && 51.8k
i < n50.7k
;
++i38.9k
)
{38.9k
499
38.9k
    isl_schedule_tree *child;
500
38.9k
501
38.9k
    child = isl_schedule_tree_get_child(tree, i);
502
38.9k
    if (!child)
503
0
      return isl_schedule_tree_free(tree);
504
38.9k
    anchored = child->anchored;
505
38.9k
    isl_schedule_tree_free(child);
506
38.9k
  }
507
12.8k
508
12.8k
  
if (12.8k
anchored == tree->anchored12.8k
)
509
12.6k
    return tree;
510
224
  tree = isl_schedule_tree_cow(tree);
511
224
  if (!tree)
512
0
    return NULL;
513
224
  tree->anchored = anchored;
514
224
  return tree;
515
224
}
516
517
/* Create a new tree of the given type (isl_schedule_node_sequence or
518
 * isl_schedule_node_set) with the given children.
519
 */
520
__isl_give isl_schedule_tree *isl_schedule_tree_from_children(
521
  enum isl_schedule_node_type type,
522
  __isl_take isl_schedule_tree_list *list)
523
744
{
524
744
  isl_ctx *ctx;
525
744
  isl_schedule_tree *tree;
526
744
527
744
  if (!list)
528
0
    return NULL;
529
744
530
744
  ctx = isl_schedule_tree_list_get_ctx(list);
531
744
  tree = isl_schedule_tree_alloc(ctx, type);
532
744
  if (!tree)
533
0
    goto error;
534
744
535
744
  tree->children = list;
536
744
  tree = isl_schedule_tree_update_anchored(tree);
537
744
538
744
  return tree;
539
0
error:
540
0
  isl_schedule_tree_list_free(list);
541
0
  return NULL;
542
744
}
543
544
/* Construct a tree with a root node of type "type" and as children
545
 * "tree1" and "tree2".
546
 * If the root of one (or both) of the input trees is itself of type "type",
547
 * then the tree is replaced by its children.
548
 */
549
__isl_give isl_schedule_tree *isl_schedule_tree_from_pair(
550
  enum isl_schedule_node_type type, __isl_take isl_schedule_tree *tree1,
551
  __isl_take isl_schedule_tree *tree2)
552
675
{
553
675
  isl_ctx *ctx;
554
675
  isl_schedule_tree_list *list;
555
675
556
675
  if (
!tree1 || 675
!tree2675
)
557
0
    goto error;
558
675
559
675
  ctx = isl_schedule_tree_get_ctx(tree1);
560
675
  if (
isl_schedule_tree_get_type(tree1) == type675
)
{294
561
294
    list = isl_schedule_tree_list_copy(tree1->children);
562
294
    isl_schedule_tree_free(tree1);
563
381
  } else {
564
381
    list = isl_schedule_tree_list_alloc(ctx, 2);
565
381
    list = isl_schedule_tree_list_add(list, tree1);
566
381
  }
567
675
  if (
isl_schedule_tree_get_type(tree2) == type675
)
{0
568
0
    isl_schedule_tree_list *children;
569
0
570
0
    children = isl_schedule_tree_list_copy(tree2->children);
571
0
    list = isl_schedule_tree_list_concat(list, children);
572
0
    isl_schedule_tree_free(tree2);
573
675
  } else {
574
675
    list = isl_schedule_tree_list_add(list, tree2);
575
675
  }
576
675
577
675
  return isl_schedule_tree_from_children(type, list);
578
0
error:
579
0
  isl_schedule_tree_free(tree1);
580
0
  isl_schedule_tree_free(tree2);
581
0
  return NULL;
582
675
}
583
584
/* Construct a tree with a sequence root node and as children
585
 * "tree1" and "tree2".
586
 * If the root of one (or both) of the input trees is itself a sequence,
587
 * then the tree is replaced by its children.
588
 */
589
__isl_give isl_schedule_tree *isl_schedule_tree_sequence_pair(
590
  __isl_take isl_schedule_tree *tree1,
591
  __isl_take isl_schedule_tree *tree2)
592
18
{
593
18
  return isl_schedule_tree_from_pair(isl_schedule_node_sequence,
594
18
            tree1, tree2);
595
18
}
596
597
/* Construct a tree with a set root node and as children
598
 * "tree1" and "tree2".
599
 * If the root of one (or both) of the input trees is itself a set,
600
 * then the tree is replaced by its children.
601
 */
602
__isl_give isl_schedule_tree *isl_schedule_tree_set_pair(
603
  __isl_take isl_schedule_tree *tree1,
604
  __isl_take isl_schedule_tree *tree2)
605
0
{
606
0
  return isl_schedule_tree_from_pair(isl_schedule_node_set, tree1, tree2);
607
0
}
608
609
/* Return the isl_ctx to which "tree" belongs.
610
 */
611
isl_ctx *isl_schedule_tree_get_ctx(__isl_keep isl_schedule_tree *tree)
612
79.0k
{
613
79.0k
  return tree ? tree->ctx : NULL;
614
79.0k
}
615
616
/* Return the type of the root of the tree or isl_schedule_node_error
617
 * on error.
618
 */
619
enum isl_schedule_node_type isl_schedule_tree_get_type(
620
  __isl_keep isl_schedule_tree *tree)
621
165k
{
622
165k
  return tree ? 
tree->type165k
:
isl_schedule_node_error0
;
623
165k
}
624
625
/* Are "tree1" and "tree2" obviously equal to each other?
626
 */
627
isl_bool isl_schedule_tree_plain_is_equal(__isl_keep isl_schedule_tree *tree1,
628
  __isl_keep isl_schedule_tree *tree2)
629
0
{
630
0
  isl_bool equal;
631
0
  int i, n;
632
0
633
0
  if (
!tree1 || 0
!tree20
)
634
0
    return isl_bool_error;
635
0
  
if (0
tree1 == tree20
)
636
0
    return isl_bool_true;
637
0
  
if (0
tree1->type != tree2->type0
)
638
0
    return isl_bool_false;
639
0
640
0
  switch (tree1->type) {
641
0
  case isl_schedule_node_band:
642
0
    equal = isl_schedule_band_plain_is_equal(tree1->band,
643
0
              tree2->band);
644
0
    break;
645
0
  case isl_schedule_node_context:
646
0
    equal = isl_set_is_equal(tree1->context, tree2->context);
647
0
    break;
648
0
  case isl_schedule_node_domain:
649
0
    equal = isl_union_set_is_equal(tree1->domain, tree2->domain);
650
0
    break;
651
0
  case isl_schedule_node_expansion:
652
0
    equal = isl_union_map_is_equal(tree1->expansion,
653
0
            tree2->expansion);
654
0
    if (
equal >= 0 && 0
equal0
)
655
0
      equal = isl_union_pw_multi_aff_plain_is_equal(
656
0
            tree1->contraction, tree2->contraction);
657
0
    break;
658
0
  case isl_schedule_node_extension:
659
0
    equal = isl_union_map_is_equal(tree1->extension,
660
0
            tree2->extension);
661
0
    break;
662
0
  case isl_schedule_node_filter:
663
0
    equal = isl_union_set_is_equal(tree1->filter, tree2->filter);
664
0
    break;
665
0
  case isl_schedule_node_guard:
666
0
    equal = isl_set_is_equal(tree1->guard, tree2->guard);
667
0
    break;
668
0
  case isl_schedule_node_mark:
669
0
    equal = tree1->mark == tree2->mark;
670
0
    break;
671
0
  case isl_schedule_node_leaf:
672
0
  case isl_schedule_node_sequence:
673
0
  case isl_schedule_node_set:
674
0
    equal = isl_bool_true;
675
0
    break;
676
0
  case isl_schedule_node_error:
677
0
    equal = isl_bool_error;
678
0
    break;
679
0
  }
680
0
681
0
  
if (0
equal < 0 || 0
!equal0
)
682
0
    return equal;
683
0
684
0
  n = isl_schedule_tree_n_children(tree1);
685
0
  if (n != isl_schedule_tree_n_children(tree2))
686
0
    return isl_bool_false;
687
0
  
for (i = 0; 0
i < n0
;
++i0
)
{0
688
0
    isl_schedule_tree *child1, *child2;
689
0
690
0
    child1 = isl_schedule_tree_get_child(tree1, i);
691
0
    child2 = isl_schedule_tree_get_child(tree2, i);
692
0
    equal = isl_schedule_tree_plain_is_equal(child1, child2);
693
0
    isl_schedule_tree_free(child1);
694
0
    isl_schedule_tree_free(child2);
695
0
696
0
    if (
equal < 0 || 0
!equal0
)
697
0
      return equal;
698
0
  }
699
0
700
0
  return isl_bool_true;
701
0
}
702
703
/* Does "tree" have any children, other than an implicit leaf.
704
 */
705
int isl_schedule_tree_has_children(__isl_keep isl_schedule_tree *tree)
706
29.3k
{
707
29.3k
  if (!tree)
708
0
    return -1;
709
29.3k
710
29.3k
  return tree->children != NULL;
711
29.3k
}
712
713
/* Return the number of children of "tree", excluding implicit leaves.
714
 */
715
int isl_schedule_tree_n_children(__isl_keep isl_schedule_tree *tree)
716
1.46k
{
717
1.46k
  if (!tree)
718
0
    return -1;
719
1.46k
720
1.46k
  return isl_schedule_tree_list_n_schedule_tree(tree->children);
721
1.46k
}
722
723
/* Return a copy of the (explicit) child at position "pos" of "tree".
724
 */
725
__isl_give isl_schedule_tree *isl_schedule_tree_get_child(
726
  __isl_keep isl_schedule_tree *tree, int pos)
727
57.9k
{
728
57.9k
  if (!tree)
729
0
    return NULL;
730
57.9k
  
if (57.9k
!tree->children57.9k
)
731
0
    isl_die(isl_schedule_tree_get_ctx(tree), isl_error_internal,
732
57.9k
      "schedule tree has no explicit children", return NULL);
733
57.9k
  return isl_schedule_tree_list_get_schedule_tree(tree->children, pos);
734
57.9k
}
735
736
/* Return a copy of the (explicit) child at position "pos" of "tree" and
737
 * free "tree".
738
 */
739
__isl_give isl_schedule_tree *isl_schedule_tree_child(
740
  __isl_take isl_schedule_tree *tree, int pos)
741
831
{
742
831
  isl_schedule_tree *child;
743
831
744
831
  child = isl_schedule_tree_get_child(tree, pos);
745
831
  isl_schedule_tree_free(tree);
746
831
  return child;
747
831
}
748
749
/* Remove all (explicit) children from "tree".
750
 */
751
__isl_give isl_schedule_tree *isl_schedule_tree_reset_children(
752
  __isl_take isl_schedule_tree *tree)
753
139
{
754
139
  tree = isl_schedule_tree_cow(tree);
755
139
  if (!tree)
756
0
    return NULL;
757
139
  tree->children = isl_schedule_tree_list_free(tree->children);
758
139
  return tree;
759
139
}
760
761
/* Remove the child at position "pos" from the children of "tree".
762
 * If there was only one child to begin with, then remove all children.
763
 */
764
__isl_give isl_schedule_tree *isl_schedule_tree_drop_child(
765
  __isl_take isl_schedule_tree *tree, int pos)
766
229
{
767
229
  int n;
768
229
769
229
  tree = isl_schedule_tree_cow(tree);
770
229
  if (!tree)
771
0
    return NULL;
772
229
773
229
  
if (229
!isl_schedule_tree_has_children(tree)229
)
774
0
    isl_die(isl_schedule_tree_get_ctx(tree), isl_error_invalid,
775
229
      "tree does not have any explicit children",
776
229
      return isl_schedule_tree_free(tree));
777
229
  n = isl_schedule_tree_list_n_schedule_tree(tree->children);
778
229
  if (
pos < 0 || 229
pos >= n229
)
779
0
    isl_die(isl_schedule_tree_get_ctx(tree), isl_error_invalid,
780
229
      "position out of bounds",
781
229
      return isl_schedule_tree_free(tree));
782
229
  
if (229
n == 1229
)
783
0
    return isl_schedule_tree_reset_children(tree);
784
229
785
229
  tree->children = isl_schedule_tree_list_drop(tree->children, pos, 1);
786
229
  if (!tree->children)
787
0
    return isl_schedule_tree_free(tree);
788
229
789
229
  return tree;
790
229
}
791
792
/* Replace the child at position "pos" of "tree" by "child".
793
 *
794
 * If the new child is a leaf, then it is not explicitly
795
 * recorded in the list of children.  Instead, the list of children
796
 * (which is assumed to have only one element) is removed.
797
 * Note that the children of set and sequence nodes are always
798
 * filters, so they cannot be replaced by empty trees.
799
 */
800
__isl_give isl_schedule_tree *isl_schedule_tree_replace_child(
801
  __isl_take isl_schedule_tree *tree, int pos,
802
  __isl_take isl_schedule_tree *child)
803
13.4k
{
804
13.4k
  tree = isl_schedule_tree_cow(tree);
805
13.4k
  if (
!tree || 13.4k
!child13.4k
)
806
0
    goto error;
807
13.4k
808
13.4k
  
if (13.4k
isl_schedule_tree_is_leaf(child)13.4k
)
{1.32k
809
1.32k
    isl_schedule_tree_free(child);
810
1.32k
    if (
!tree->children && 1.32k
pos == 01.19k
)
811
1.19k
      return tree;
812
132
    
if (132
isl_schedule_tree_n_children(tree) != 1132
)
813
0
      isl_die(isl_schedule_tree_get_ctx(tree),
814
132
        isl_error_internal,
815
132
        "can only replace single child by leaf",
816
132
        goto error);
817
132
    return isl_schedule_tree_reset_children(tree);
818
132
  }
819
13.4k
820
12.1k
  
if (12.1k
!tree->children && 12.1k
pos == 02.79k
)
821
2.79k
    tree->children =
822
2.79k
      isl_schedule_tree_list_from_schedule_tree(child);
823
12.1k
  else
824
9.31k
    tree->children = isl_schedule_tree_list_set_schedule_tree(
825
9.31k
        tree->children, pos, child);
826
12.1k
827
12.1k
  if (!tree->children)
828
0
    return isl_schedule_tree_free(tree);
829
12.1k
  tree = isl_schedule_tree_update_anchored(tree);
830
12.1k
831
12.1k
  return tree;
832
0
error:
833
0
  isl_schedule_tree_free(tree);
834
0
  isl_schedule_tree_free(child);
835
0
  return NULL;
836
12.1k
}
837
838
/* Replace the (explicit) children of "tree" by "children"?
839
 */
840
__isl_give isl_schedule_tree *isl_schedule_tree_set_children(
841
  __isl_take isl_schedule_tree *tree,
842
  __isl_take isl_schedule_tree_list *children)
843
7
{
844
7
  tree = isl_schedule_tree_cow(tree);
845
7
  if (
!tree || 7
!children7
)
846
0
    goto error;
847
7
  isl_schedule_tree_list_free(tree->children);
848
7
  tree->children = children;
849
7
  return tree;
850
0
error:
851
0
  isl_schedule_tree_free(tree);
852
0
  isl_schedule_tree_list_free(children);
853
0
  return NULL;
854
7
}
855
856
/* Create a new band schedule tree referring to "band"
857
 * with "tree" as single child.
858
 */
859
__isl_give isl_schedule_tree *isl_schedule_tree_insert_band(
860
  __isl_take isl_schedule_tree *tree, __isl_take isl_schedule_band *band)
861
1.51k
{
862
1.51k
  isl_schedule_tree *res;
863
1.51k
864
1.51k
  res = isl_schedule_tree_from_band(band);
865
1.51k
  return isl_schedule_tree_replace_child(res, 0, tree);
866
1.51k
}
867
868
/* Create a new context schedule tree with the given context and
869
 * with "tree" as single child.
870
 */
871
__isl_give isl_schedule_tree *isl_schedule_tree_insert_context(
872
  __isl_take isl_schedule_tree *tree, __isl_take isl_set *context)
873
0
{
874
0
  isl_schedule_tree *res;
875
0
876
0
  res = isl_schedule_tree_from_context(context);
877
0
  return isl_schedule_tree_replace_child(res, 0, tree);
878
0
}
879
880
/* Create a new domain schedule tree with the given domain and
881
 * with "tree" as single child.
882
 */
883
__isl_give isl_schedule_tree *isl_schedule_tree_insert_domain(
884
  __isl_take isl_schedule_tree *tree, __isl_take isl_union_set *domain)
885
657
{
886
657
  isl_schedule_tree *res;
887
657
888
657
  res = isl_schedule_tree_from_domain(domain);
889
657
  return isl_schedule_tree_replace_child(res, 0, tree);
890
657
}
891
892
/* Create a new expansion schedule tree with the given contraction and
893
 * expansion and with "tree" as single child.
894
 */
895
__isl_give isl_schedule_tree *isl_schedule_tree_insert_expansion(
896
  __isl_take isl_schedule_tree *tree,
897
  __isl_take isl_union_pw_multi_aff *contraction,
898
  __isl_take isl_union_map *expansion)
899
3
{
900
3
  isl_schedule_tree *res;
901
3
902
3
  res = isl_schedule_tree_from_expansion(contraction, expansion);
903
3
  return isl_schedule_tree_replace_child(res, 0, tree);
904
3
}
905
906
/* Create a new extension schedule tree with the given extension and
907
 * with "tree" as single child.
908
 */
909
__isl_give isl_schedule_tree *isl_schedule_tree_insert_extension(
910
  __isl_take isl_schedule_tree *tree, __isl_take isl_union_map *extension)
911
18
{
912
18
  isl_schedule_tree *res;
913
18
914
18
  res = isl_schedule_tree_from_extension(extension);
915
18
  return isl_schedule_tree_replace_child(res, 0, tree);
916
18
}
917
918
/* Create a new filter schedule tree with the given filter and single child.
919
 *
920
 * If the root of "tree" is itself a filter node, then the two
921
 * filter nodes are merged into one node.
922
 */
923
__isl_give isl_schedule_tree *isl_schedule_tree_insert_filter(
924
  __isl_take isl_schedule_tree *tree, __isl_take isl_union_set *filter)
925
1.87k
{
926
1.87k
  isl_schedule_tree *res;
927
1.87k
928
1.87k
  if (
isl_schedule_tree_get_type(tree) == isl_schedule_node_filter1.87k
)
{1.37k
929
1.37k
    isl_union_set *tree_filter;
930
1.37k
931
1.37k
    tree_filter = isl_schedule_tree_filter_get_filter(tree);
932
1.37k
    tree_filter = isl_union_set_intersect(tree_filter, filter);
933
1.37k
    tree = isl_schedule_tree_filter_set_filter(tree, tree_filter);
934
1.37k
    return tree;
935
1.37k
  }
936
1.87k
937
498
  res = isl_schedule_tree_from_filter(filter);
938
498
  return isl_schedule_tree_replace_child(res, 0, tree);
939
1.87k
}
940
941
/* Insert a filter node with filter set "filter"
942
 * in each of the children of "tree".
943
 */
944
__isl_give isl_schedule_tree *isl_schedule_tree_children_insert_filter(
945
  __isl_take isl_schedule_tree *tree, __isl_take isl_union_set *filter)
946
294
{
947
294
  int i, n;
948
294
949
294
  if (
!tree || 294
!filter294
)
950
0
    goto error;
951
294
952
294
  n = isl_schedule_tree_n_children(tree);
953
1.66k
  for (i = 0; 
i < n1.66k
;
++i1.37k
)
{1.37k
954
1.37k
    isl_schedule_tree *child;
955
1.37k
956
1.37k
    child = isl_schedule_tree_get_child(tree, i);
957
1.37k
    child = isl_schedule_tree_insert_filter(child,
958
1.37k
                isl_union_set_copy(filter));
959
1.37k
    tree = isl_schedule_tree_replace_child(tree, i, child);
960
1.37k
  }
961
294
962
294
  isl_union_set_free(filter);
963
294
  return tree;
964
0
error:
965
0
  isl_union_set_free(filter);
966
0
  isl_schedule_tree_free(tree);
967
0
  return NULL;
968
294
}
969
970
/* Create a new guard schedule tree with the given guard and
971
 * with "tree" as single child.
972
 */
973
__isl_give isl_schedule_tree *isl_schedule_tree_insert_guard(
974
  __isl_take isl_schedule_tree *tree, __isl_take isl_set *guard)
975
0
{
976
0
  isl_schedule_tree *res;
977
0
978
0
  res = isl_schedule_tree_from_guard(guard);
979
0
  return isl_schedule_tree_replace_child(res, 0, tree);
980
0
}
981
982
/* Create a new mark schedule tree with the given mark identifier and
983
 * single child.
984
 */
985
__isl_give isl_schedule_tree *isl_schedule_tree_insert_mark(
986
  __isl_take isl_schedule_tree *tree, __isl_take isl_id *mark)
987
123
{
988
123
  isl_schedule_tree *res;
989
123
990
123
  res = isl_schedule_tree_from_mark(mark);
991
123
  return isl_schedule_tree_replace_child(res, 0, tree);
992
123
}
993
994
/* Return the number of members in the band tree root.
995
 */
996
unsigned isl_schedule_tree_band_n_member(__isl_keep isl_schedule_tree *tree)
997
28.8k
{
998
28.8k
  if (!tree)
999
0
    return 0;
1000
28.8k
1001
28.8k
  
if (28.8k
tree->type != isl_schedule_node_band28.8k
)
1002
0
    isl_die(isl_schedule_tree_get_ctx(tree), isl_error_invalid,
1003
28.8k
      "not a band node", return 0);
1004
28.8k
1005
28.8k
  return isl_schedule_band_n_member(tree->band);
1006
28.8k
}
1007
1008
/* Is the band member at position "pos" of the band tree root
1009
 * marked coincident?
1010
 */
1011
isl_bool isl_schedule_tree_band_member_get_coincident(
1012
  __isl_keep isl_schedule_tree *tree, int pos)
1013
429
{
1014
429
  if (!tree)
1015
0
    return isl_bool_error;
1016
429
1017
429
  
if (429
tree->type != isl_schedule_node_band429
)
1018
0
    isl_die(isl_schedule_tree_get_ctx(tree), isl_error_invalid,
1019
429
      "not a band node", return isl_bool_error);
1020
429
1021
429
  return isl_schedule_band_member_get_coincident(tree->band, pos);
1022
429
}
1023
1024
/* Mark the given band member as being coincident or not
1025
 * according to "coincident".
1026
 */
1027
__isl_give isl_schedule_tree *isl_schedule_tree_band_member_set_coincident(
1028
  __isl_take isl_schedule_tree *tree, int pos, int coincident)
1029
158
{
1030
158
  if (!tree)
1031
0
    return NULL;
1032
158
  
if (158
tree->type != isl_schedule_node_band158
)
1033
0
    isl_die(isl_schedule_tree_get_ctx(tree), isl_error_invalid,
1034
158
      "not a band node", return isl_schedule_tree_free(tree));
1035
158
  
if (158
isl_schedule_tree_band_member_get_coincident(tree, pos) ==158
1036
158
                    coincident)
1037
0
    return tree;
1038
158
  tree = isl_schedule_tree_cow(tree);
1039
158
  if (!tree)
1040
0
    return NULL;
1041
158
1042
158
  tree->band = isl_schedule_band_member_set_coincident(tree->band, pos,
1043
158
              coincident);
1044
158
  if (!tree->band)
1045
0
    return isl_schedule_tree_free(tree);
1046
158
  return tree;
1047
158
}
1048
1049
/* Is the band tree root marked permutable?
1050
 */
1051
isl_bool isl_schedule_tree_band_get_permutable(
1052
  __isl_keep isl_schedule_tree *tree)
1053
418
{
1054
418
  if (!tree)
1055
0
    return isl_bool_error;
1056
418
1057
418
  
if (418
tree->type != isl_schedule_node_band418
)
1058
0
    isl_die(isl_schedule_tree_get_ctx(tree), isl_error_invalid,
1059
418
      "not a band node", return isl_bool_error);
1060
418
1061
418
  return isl_schedule_band_get_permutable(tree->band);
1062
418
}
1063
1064
/* Mark the band tree root permutable or not according to "permutable"?
1065
 */
1066
__isl_give isl_schedule_tree *isl_schedule_tree_band_set_permutable(
1067
  __isl_take isl_schedule_tree *tree, int permutable)
1068
125
{
1069
125
  if (!tree)
1070
0
    return NULL;
1071
125
  
if (125
tree->type != isl_schedule_node_band125
)
1072
0
    isl_die(isl_schedule_tree_get_ctx(tree), isl_error_invalid,
1073
125
      "not a band node", return isl_schedule_tree_free(tree));
1074
125
  
if (125
isl_schedule_tree_band_get_permutable(tree) == permutable125
)
1075
0
    return tree;
1076
125
  tree = isl_schedule_tree_cow(tree);
1077
125
  if (!tree)
1078
0
    return NULL;
1079
125
1080
125
  tree->band = isl_schedule_band_set_permutable(tree->band, permutable);
1081
125
  if (!tree->band)
1082
0
    return isl_schedule_tree_free(tree);
1083
125
  return tree;
1084
125
}
1085
1086
/* Return the schedule space of the band tree root.
1087
 */
1088
__isl_give isl_space *isl_schedule_tree_band_get_space(
1089
  __isl_keep isl_schedule_tree *tree)
1090
272
{
1091
272
  if (!tree)
1092
0
    return NULL;
1093
272
1094
272
  
if (272
tree->type != isl_schedule_node_band272
)
1095
0
    isl_die(isl_schedule_tree_get_ctx(tree), isl_error_invalid,
1096
272
      "not a band node", return NULL);
1097
272
1098
272
  return isl_schedule_band_get_space(tree->band);
1099
272
}
1100
1101
/* Intersect the domain of the band schedule of the band tree root
1102
 * with "domain".
1103
 */
1104
__isl_give isl_schedule_tree *isl_schedule_tree_band_intersect_domain(
1105
  __isl_take isl_schedule_tree *tree, __isl_take isl_union_set *domain)
1106
2
{
1107
2
  if (
!tree || 2
!domain2
)
1108
0
    goto error;
1109
2
1110
2
  
if (2
tree->type != isl_schedule_node_band2
)
1111
0
    isl_die(isl_schedule_tree_get_ctx(tree), isl_error_invalid,
1112
2
      "not a band node", goto error);
1113
2
1114
2
  tree->band = isl_schedule_band_intersect_domain(tree->band, domain);
1115
2
  if (!tree->band)
1116
0
    return isl_schedule_tree_free(tree);
1117
2
1118
2
  return tree;
1119
0
error:
1120
0
  isl_schedule_tree_free(tree);
1121
0
  isl_union_set_free(domain);
1122
0
  return NULL;
1123
2
}
1124
1125
/* Return the schedule of the band tree root in isolation.
1126
 */
1127
__isl_give isl_multi_union_pw_aff *isl_schedule_tree_band_get_partial_schedule(
1128
  __isl_keep isl_schedule_tree *tree)
1129
3.47k
{
1130
3.47k
  if (!tree)
1131
0
    return NULL;
1132
3.47k
1133
3.47k
  
if (3.47k
tree->type != isl_schedule_node_band3.47k
)
1134
0
    isl_die(isl_schedule_tree_get_ctx(tree), isl_error_invalid,
1135
3.47k
      "not a band node", return NULL);
1136
3.47k
1137
3.47k
  return isl_schedule_band_get_partial_schedule(tree->band);
1138
3.47k
}
1139
1140
/* Replace the schedule of the band tree root by "schedule".
1141
 */
1142
__isl_give isl_schedule_tree *isl_schedule_tree_band_set_partial_schedule(
1143
  __isl_take isl_schedule_tree *tree,
1144
  __isl_take isl_multi_union_pw_aff *schedule)
1145
2
{
1146
2
  tree = isl_schedule_tree_cow(tree);
1147
2
  if (
!tree || 2
!schedule2
)
1148
0
    goto error;
1149
2
1150
2
  
if (2
tree->type != isl_schedule_node_band2
)
1151
0
    isl_die(isl_schedule_tree_get_ctx(tree), isl_error_invalid,
1152
2
      "not a band node", return NULL);
1153
2
  tree->band = isl_schedule_band_set_partial_schedule(tree->band,
1154
2
                schedule);
1155
2
1156
2
  return tree;
1157
0
error:
1158
0
  isl_schedule_tree_free(tree);
1159
0
  isl_multi_union_pw_aff_free(schedule);
1160
0
  return NULL;
1161
2
}
1162
1163
/* Return the loop AST generation type for the band member
1164
 * of the band tree root at position "pos".
1165
 */
1166
enum isl_ast_loop_type isl_schedule_tree_band_member_get_ast_loop_type(
1167
  __isl_keep isl_schedule_tree *tree, int pos)
1168
694
{
1169
694
  if (!tree)
1170
0
    return isl_ast_loop_error;
1171
694
1172
694
  
if (694
tree->type != isl_schedule_node_band694
)
1173
0
    isl_die(isl_schedule_tree_get_ctx(tree), isl_error_invalid,
1174
694
      "not a band node", return isl_ast_loop_error);
1175
694
1176
694
  return isl_schedule_band_member_get_ast_loop_type(tree->band, pos);
1177
694
}
1178
1179
/* Set the loop AST generation type for the band member of the band tree root
1180
 * at position "pos" to "type".
1181
 */
1182
__isl_give isl_schedule_tree *isl_schedule_tree_band_member_set_ast_loop_type(
1183
  __isl_take isl_schedule_tree *tree, int pos,
1184
  enum isl_ast_loop_type type)
1185
0
{
1186
0
  tree = isl_schedule_tree_cow(tree);
1187
0
  if (!tree)
1188
0
    return NULL;
1189
0
1190
0
  
if (0
tree->type != isl_schedule_node_band0
)
1191
0
    isl_die(isl_schedule_tree_get_ctx(tree), isl_error_invalid,
1192
0
      "not a band node", return isl_schedule_tree_free(tree));
1193
0
1194
0
  tree->band = isl_schedule_band_member_set_ast_loop_type(tree->band,
1195
0
                pos, type);
1196
0
  if (!tree->band)
1197
0
    return isl_schedule_tree_free(tree);
1198
0
1199
0
  return tree;
1200
0
}
1201
1202
/* Return the loop AST generation type for the band member
1203
 * of the band tree root at position "pos" for the isolated part.
1204
 */
1205
enum isl_ast_loop_type isl_schedule_tree_band_member_get_isolate_ast_loop_type(
1206
  __isl_keep isl_schedule_tree *tree, int pos)
1207
566
{
1208
566
  if (!tree)
1209
0
    return isl_ast_loop_error;
1210
566
1211
566
  
if (566
tree->type != isl_schedule_node_band566
)
1212
0
    isl_die(isl_schedule_tree_get_ctx(tree), isl_error_invalid,
1213
566
      "not a band node", return isl_ast_loop_error);
1214
566
1215
566
  return isl_schedule_band_member_get_isolate_ast_loop_type(tree->band,
1216
566
                  pos);
1217
566
}
1218
1219
/* Set the loop AST generation type for the band member of the band tree root
1220
 * at position "pos" for the isolated part to "type".
1221
 */
1222
__isl_give isl_schedule_tree *
1223
isl_schedule_tree_band_member_set_isolate_ast_loop_type(
1224
  __isl_take isl_schedule_tree *tree, int pos,
1225
  enum isl_ast_loop_type type)
1226
0
{
1227
0
  tree = isl_schedule_tree_cow(tree);
1228
0
  if (!tree)
1229
0
    return NULL;
1230
0
1231
0
  
if (0
tree->type != isl_schedule_node_band0
)
1232
0
    isl_die(isl_schedule_tree_get_ctx(tree), isl_error_invalid,
1233
0
      "not a band node", return isl_schedule_tree_free(tree));
1234
0
1235
0
  tree->band = isl_schedule_band_member_set_isolate_ast_loop_type(
1236
0
              tree->band, pos, type);
1237
0
  if (!tree->band)
1238
0
    return isl_schedule_tree_free(tree);
1239
0
1240
0
  return tree;
1241
0
}
1242
1243
/* Return the AST build options associated to the band tree root.
1244
 */
1245
__isl_give isl_union_set *isl_schedule_tree_band_get_ast_build_options(
1246
  __isl_keep isl_schedule_tree *tree)
1247
0
{
1248
0
  if (!tree)
1249
0
    return NULL;
1250
0
1251
0
  
if (0
tree->type != isl_schedule_node_band0
)
1252
0
    isl_die(isl_schedule_tree_get_ctx(tree), isl_error_invalid,
1253
0
      "not a band node", return NULL);
1254
0
1255
0
  return isl_schedule_band_get_ast_build_options(tree->band);
1256
0
}
1257
1258
/* Replace the AST build options associated to band tree root by "options".
1259
 * Updated the anchored field if the anchoredness of the root node itself
1260
 * changes.
1261
 */
1262
__isl_give isl_schedule_tree *isl_schedule_tree_band_set_ast_build_options(
1263
  __isl_take isl_schedule_tree *tree, __isl_take isl_union_set *options)
1264
60
{
1265
60
  int was_anchored;
1266
60
1267
60
  tree = isl_schedule_tree_cow(tree);
1268
60
  if (
!tree || 60
!options60
)
1269
0
    goto error;
1270
60
1271
60
  
if (60
tree->type != isl_schedule_node_band60
)
1272
0
    isl_die(isl_schedule_tree_get_ctx(tree), isl_error_invalid,
1273
60
      "not a band node", goto error);
1274
60
1275
60
  was_anchored = isl_schedule_tree_is_anchored(tree);
1276
60
  tree->band = isl_schedule_band_set_ast_build_options(tree->band,
1277
60
                options);
1278
60
  if (!tree->band)
1279
0
    return isl_schedule_tree_free(tree);
1280
60
  
if (60
isl_schedule_tree_is_anchored(tree) != was_anchored60
)
1281
33
    tree = isl_schedule_tree_update_anchored(tree);
1282
60
1283
60
  return tree;
1284
0
error:
1285
0
  isl_schedule_tree_free(tree);
1286
0
  isl_union_set_free(options);
1287
0
  return NULL;
1288
60
}
1289
1290
/* Return the "isolate" option associated to the band tree root of "tree",
1291
 * which is assumed to appear at schedule depth "depth".
1292
 */
1293
__isl_give isl_set *isl_schedule_tree_band_get_ast_isolate_option(
1294
  __isl_keep isl_schedule_tree *tree, int depth)
1295
1.30k
{
1296
1.30k
  if (!tree)
1297
0
    return NULL;
1298
1.30k
1299
1.30k
  
if (1.30k
tree->type != isl_schedule_node_band1.30k
)
1300
0
    isl_die(isl_schedule_tree_get_ctx(tree), isl_error_invalid,
1301
1.30k
      "not a band node", return NULL);
1302
1.30k
1303
1.30k
  return isl_schedule_band_get_ast_isolate_option(tree->band, depth);
1304
1.30k
}
1305
1306
/* Return the context of the context tree root.
1307
 */
1308
__isl_give isl_set *isl_schedule_tree_context_get_context(
1309
  __isl_keep isl_schedule_tree *tree)
1310
0
{
1311
0
  if (!tree)
1312
0
    return NULL;
1313
0
1314
0
  
if (0
tree->type != isl_schedule_node_context0
)
1315
0
    isl_die(isl_schedule_tree_get_ctx(tree), isl_error_invalid,
1316
0
      "not a context node", return NULL);
1317
0
1318
0
  return isl_set_copy(tree->context);
1319
0
}
1320
1321
/* Return the domain of the domain tree root.
1322
 */
1323
__isl_give isl_union_set *isl_schedule_tree_domain_get_domain(
1324
  __isl_keep isl_schedule_tree *tree)
1325
9.54k
{
1326
9.54k
  if (!tree)
1327
0
    return NULL;
1328
9.54k
1329
9.54k
  
if (9.54k
tree->type != isl_schedule_node_domain9.54k
)
1330
0
    isl_die(isl_schedule_tree_get_ctx(tree), isl_error_invalid,
1331
9.54k
      "not a domain node", return NULL);
1332
9.54k
1333
9.54k
  return isl_union_set_copy(tree->domain);
1334
9.54k
}
1335
1336
/* Replace the domain of domain tree root "tree" by "domain".
1337
 */
1338
__isl_give isl_schedule_tree *isl_schedule_tree_domain_set_domain(
1339
  __isl_take isl_schedule_tree *tree, __isl_take isl_union_set *domain)
1340
1.06k
{
1341
1.06k
  tree = isl_schedule_tree_cow(tree);
1342
1.06k
  if (
!tree || 1.06k
!domain1.06k
)
1343
0
    goto error;
1344
1.06k
1345
1.06k
  
if (1.06k
tree->type != isl_schedule_node_domain1.06k
)
1346
0
    isl_die(isl_schedule_tree_get_ctx(tree), isl_error_invalid,
1347
1.06k
      "not a domain node", goto error);
1348
1.06k
1349
1.06k
  isl_union_set_free(tree->domain);
1350
1.06k
  tree->domain = domain;
1351
1.06k
1352
1.06k
  return tree;
1353
0
error:
1354
0
  isl_schedule_tree_free(tree);
1355
0
  isl_union_set_free(domain);
1356
0
  return NULL;
1357
1.06k
}
1358
1359
/* Return the contraction of the expansion tree root.
1360
 */
1361
__isl_give isl_union_pw_multi_aff *isl_schedule_tree_expansion_get_contraction(
1362
  __isl_keep isl_schedule_tree *tree)
1363
8
{
1364
8
  if (!tree)
1365
0
    return NULL;
1366
8
1367
8
  
if (8
tree->type != isl_schedule_node_expansion8
)
1368
0
    isl_die(isl_schedule_tree_get_ctx(tree), isl_error_invalid,
1369
8
      "not an expansion node", return NULL);
1370
8
1371
8
  return isl_union_pw_multi_aff_copy(tree->contraction);
1372
8
}
1373
1374
/* Return the expansion of the expansion tree root.
1375
 */
1376
__isl_give isl_union_map *isl_schedule_tree_expansion_get_expansion(
1377
  __isl_keep isl_schedule_tree *tree)
1378
13
{
1379
13
  if (!tree)
1380
0
    return NULL;
1381
13
1382
13
  
if (13
tree->type != isl_schedule_node_expansion13
)
1383
0
    isl_die(isl_schedule_tree_get_ctx(tree), isl_error_invalid,
1384
13
      "not an expansion node", return NULL);
1385
13
1386
13
  return isl_union_map_copy(tree->expansion);
1387
13
}
1388
1389
/* Replace the contraction and the expansion of the expansion tree root "tree"
1390
 * by "contraction" and "expansion".
1391
 */
1392
__isl_give isl_schedule_tree *
1393
isl_schedule_tree_expansion_set_contraction_and_expansion(
1394
  __isl_take isl_schedule_tree *tree,
1395
  __isl_take isl_union_pw_multi_aff *contraction,
1396
  __isl_take isl_union_map *expansion)
1397
1
{
1398
1
  tree = isl_schedule_tree_cow(tree);
1399
1
  if (
!tree || 1
!contraction1
||
!expansion1
)
1400
0
    goto error;
1401
1
1402
1
  
if (1
tree->type != isl_schedule_node_expansion1
)
1403
0
    isl_die(isl_schedule_tree_get_ctx(tree), isl_error_invalid,
1404
1
      "not an expansion node", return NULL);
1405
1
1406
1
  isl_union_pw_multi_aff_free(tree->contraction);
1407
1
  tree->contraction = contraction;
1408
1
  isl_union_map_free(tree->expansion);
1409
1
  tree->expansion = expansion;
1410
1
1411
1
  return tree;
1412
0
error:
1413
0
  isl_schedule_tree_free(tree);
1414
0
  isl_union_pw_multi_aff_free(contraction);
1415
0
  isl_union_map_free(expansion);
1416
0
  return NULL;
1417
1
}
1418
1419
/* Return the extension of the extension tree root.
1420
 */
1421
__isl_give isl_union_map *isl_schedule_tree_extension_get_extension(
1422
  __isl_take isl_schedule_tree *tree)
1423
52
{
1424
52
  if (!tree)
1425
0
    return NULL;
1426
52
1427
52
  
if (52
tree->type != isl_schedule_node_extension52
)
1428
0
    isl_die(isl_schedule_tree_get_ctx(tree), isl_error_invalid,
1429
52
      "not an extension node", return NULL);
1430
52
1431
52
  return isl_union_map_copy(tree->extension);
1432
52
}
1433
1434
/* Replace the extension of extension tree root "tree" by "extension".
1435
 */
1436
__isl_give isl_schedule_tree *isl_schedule_tree_extension_set_extension(
1437
  __isl_take isl_schedule_tree *tree, __isl_take isl_union_map *extension)
1438
0
{
1439
0
  tree = isl_schedule_tree_cow(tree);
1440
0
  if (
!tree || 0
!extension0
)
1441
0
    goto error;
1442
0
1443
0
  
if (0
tree->type != isl_schedule_node_extension0
)
1444
0
    isl_die(isl_schedule_tree_get_ctx(tree), isl_error_invalid,
1445
0
      "not an extension node", return NULL);
1446
0
  isl_union_map_free(tree->extension);
1447
0
  tree->extension = extension;
1448
0
1449
0
  return tree;
1450
0
error:
1451
0
  isl_schedule_tree_free(tree);
1452
0
  isl_union_map_free(extension);
1453
0
  return NULL;
1454
0
}
1455
1456
/* Return the filter of the filter tree root.
1457
 */
1458
__isl_give isl_union_set *isl_schedule_tree_filter_get_filter(
1459
  __isl_keep isl_schedule_tree *tree)
1460
12.5k
{
1461
12.5k
  if (!tree)
1462
0
    return NULL;
1463
12.5k
1464
12.5k
  
if (12.5k
tree->type != isl_schedule_node_filter12.5k
)
1465
0
    isl_die(isl_schedule_tree_get_ctx(tree), isl_error_invalid,
1466
12.5k
      "not a filter node", return NULL);
1467
12.5k
1468
12.5k
  return isl_union_set_copy(tree->filter);
1469
12.5k
}
1470
1471
/* Replace the filter of the filter tree root by "filter".
1472
 */
1473
__isl_give isl_schedule_tree *isl_schedule_tree_filter_set_filter(
1474
  __isl_take isl_schedule_tree *tree, __isl_take isl_union_set *filter)
1475
2.17k
{
1476
2.17k
  tree = isl_schedule_tree_cow(tree);
1477
2.17k
  if (
!tree || 2.17k
!filter2.17k
)
1478
0
    goto error;
1479
2.17k
1480
2.17k
  
if (2.17k
tree->type != isl_schedule_node_filter2.17k
)
1481
0
    isl_die(isl_schedule_tree_get_ctx(tree), isl_error_invalid,
1482
2.17k
      "not a filter node", return NULL);
1483
2.17k
1484
2.17k
  isl_union_set_free(tree->filter);
1485
2.17k
  tree->filter = filter;
1486
2.17k
1487
2.17k
  return tree;
1488
0
error:
1489
0
  isl_schedule_tree_free(tree);
1490
0
  isl_union_set_free(filter);
1491
0
  return NULL;
1492
2.17k
}
1493
1494
/* Return the guard of the guard tree root.
1495
 */
1496
__isl_give isl_set *isl_schedule_tree_guard_get_guard(
1497
  __isl_take isl_schedule_tree *tree)
1498
0
{
1499
0
  if (!tree)
1500
0
    return NULL;
1501
0
1502
0
  
if (0
tree->type != isl_schedule_node_guard0
)
1503
0
    isl_die(isl_schedule_tree_get_ctx(tree), isl_error_invalid,
1504
0
      "not a guard node", return NULL);
1505
0
1506
0
  return isl_set_copy(tree->guard);
1507
0
}
1508
1509
/* Return the mark identifier of the mark tree root "tree".
1510
 */
1511
__isl_give isl_id *isl_schedule_tree_mark_get_id(
1512
  __isl_keep isl_schedule_tree *tree)
1513
112
{
1514
112
  if (!tree)
1515
0
    return NULL;
1516
112
1517
112
  
if (112
tree->type != isl_schedule_node_mark112
)
1518
0
    isl_die(isl_schedule_tree_get_ctx(tree), isl_error_invalid,
1519
112
      "not a mark node", return NULL);
1520
112
1521
112
  return isl_id_copy(tree->mark);
1522
112
}
1523
1524
/* Set dim to the range dimension of "map" and abort the search.
1525
 */
1526
static isl_stat set_range_dim(__isl_take isl_map *map, void *user)
1527
3.28k
{
1528
3.28k
  int *dim = user;
1529
3.28k
1530
3.28k
  *dim = isl_map_dim(map, isl_dim_out);
1531
3.28k
  isl_map_free(map);
1532
3.28k
1533
3.28k
  return isl_stat_error;
1534
3.28k
}
1535
1536
/* Return the dimension of the range of "umap".
1537
 * "umap" is assumed not to be empty and
1538
 * all maps inside "umap" are assumed to have the same range.
1539
 *
1540
 * We extract the range dimension from the first map in "umap".
1541
 */
1542
static int range_dim(__isl_keep isl_union_map *umap)
1543
3.28k
{
1544
3.28k
  int dim = -1;
1545
3.28k
1546
3.28k
  if (!umap)
1547
0
    return -1;
1548
3.28k
  
if (3.28k
isl_union_map_n_map(umap) == 03.28k
)
1549
0
    isl_die(isl_union_map_get_ctx(umap), isl_error_internal,
1550
3.28k
      "unexpected empty input", return -1);
1551
3.28k
1552
3.28k
  isl_union_map_foreach_map(umap, &set_range_dim, &dim);
1553
3.28k
1554
3.28k
  return dim;
1555
3.28k
}
1556
1557
/* Append an "extra" number of zeros to the range of "umap" and
1558
 * return the result.
1559
 */
1560
static __isl_give isl_union_map *append_range(__isl_take isl_union_map *umap,
1561
  int extra)
1562
973
{
1563
973
  isl_union_set *dom;
1564
973
  isl_space *space;
1565
973
  isl_multi_val *mv;
1566
973
  isl_union_pw_multi_aff *suffix;
1567
973
  isl_union_map *universe;
1568
973
  isl_union_map *suffix_umap;
1569
973
1570
973
  universe = isl_union_map_universe(isl_union_map_copy(umap));
1571
973
  dom = isl_union_map_domain(universe);
1572
973
  space = isl_union_set_get_space(dom);
1573
973
  space = isl_space_set_from_params(space);
1574
973
  space = isl_space_add_dims(space, isl_dim_set, extra);
1575
973
  mv = isl_multi_val_zero(space);
1576
973
1577
973
  suffix = isl_union_pw_multi_aff_multi_val_on_domain(dom, mv);
1578
973
  suffix_umap = isl_union_map_from_union_pw_multi_aff(suffix);
1579
973
  umap = isl_union_map_flat_range_product(umap, suffix_umap);
1580
973
1581
973
  return umap;
1582
973
}
1583
1584
/* Should we skip the root of "tree" while looking for the first
1585
 * descendant with schedule information?
1586
 * That is, is it impossible to derive any information about
1587
 * the iteration domain from this node?
1588
 *
1589
 * We do not want to skip leaf or error nodes because there is
1590
 * no point in looking any deeper from these nodes.
1591
 * We can only extract partial iteration domain information
1592
 * from an extension node, but extension nodes are not supported
1593
 * by the caller and it will error out on them.
1594
 */
1595
static int domain_less(__isl_keep isl_schedule_tree *tree)
1596
1.01k
{
1597
1.01k
  enum isl_schedule_node_type type;
1598
1.01k
1599
1.01k
  type = isl_schedule_tree_get_type(tree);
1600
1.01k
  switch (type) {
1601
722
  case isl_schedule_node_band:
1602
722
    return isl_schedule_tree_band_n_member(tree) == 0;
1603
12
  case isl_schedule_node_context:
1604
12
  case isl_schedule_node_guard:
1605
12
  case isl_schedule_node_mark:
1606
12
    return 1;
1607
281
  case isl_schedule_node_leaf:
1608
281
  case isl_schedule_node_error:
1609
281
  case isl_schedule_node_domain:
1610
281
  case isl_schedule_node_expansion:
1611
281
  case isl_schedule_node_extension:
1612
281
  case isl_schedule_node_filter:
1613
281
  case isl_schedule_node_set:
1614
281
  case isl_schedule_node_sequence:
1615
281
    return 0;
1616
1.01k
  }
1617
1.01k
1618
0
  
isl_die0
(isl_schedule_tree_get_ctx(tree), isl_error_internal,0
1619
0
    "unhandled case", return 0);
1620
0
}
1621
1622
/* Move down to the first descendant of "tree" that contains any schedule
1623
 * information or return "leaf" if there is no such descendant.
1624
 */
1625
__isl_give isl_schedule_tree *isl_schedule_tree_first_schedule_descendant(
1626
  __isl_take isl_schedule_tree *tree, __isl_keep isl_schedule_tree *leaf)
1627
1.00k
{
1628
1.01k
  while (
domain_less(tree)1.01k
)
{12
1629
12
    if (
!isl_schedule_tree_has_children(tree)12
)
{0
1630
0
      isl_schedule_tree_free(tree);
1631
0
      return isl_schedule_tree_copy(leaf);
1632
0
    }
1633
12
    tree = isl_schedule_tree_child(tree, 0);
1634
12
  }
1635
1.00k
1636
1.00k
  return tree;
1637
1.00k
}
1638
1639
static __isl_give isl_union_map *subtree_schedule_extend(
1640
  __isl_keep isl_schedule_tree *tree, __isl_take isl_union_map *outer);
1641
1642
/* Extend the schedule map "outer" with the subtree schedule
1643
 * of the (single) child of "tree", if any.
1644
 *
1645
 * If "tree" does not have any descendants (apart from those that
1646
 * do not carry any schedule information), then we simply return "outer".
1647
 * Otherwise, we extend the schedule map "outer" with the subtree schedule
1648
 * of the single child.
1649
 */
1650
static __isl_give isl_union_map *subtree_schedule_extend_child(
1651
  __isl_keep isl_schedule_tree *tree, __isl_take isl_union_map *outer)
1652
5.56k
{
1653
5.56k
  isl_schedule_tree *child;
1654
5.56k
  isl_union_map *res;
1655
5.56k
1656
5.56k
  if (!tree)
1657
0
    return isl_union_map_free(outer);
1658
5.56k
  
if (5.56k
!isl_schedule_tree_has_children(tree)5.56k
)
1659
3.61k
    return outer;
1660
1.95k
  child = isl_schedule_tree_get_child(tree, 0);
1661
1.95k
  if (!child)
1662
0
    return isl_union_map_free(outer);
1663
1.95k
  res = subtree_schedule_extend(child, outer);
1664
1.95k
  isl_schedule_tree_free(child);
1665
1.95k
  return res;
1666
1.95k
}
1667
1668
/* Extract the parameter space from one of the children of "tree",
1669
 * which are assumed to be filters.
1670
 */
1671
static __isl_give isl_space *extract_space_from_filter_child(
1672
  __isl_keep isl_schedule_tree *tree)
1673
915
{
1674
915
  isl_space *space;
1675
915
  isl_union_set *dom;
1676
915
  isl_schedule_tree *child;
1677
915
1678
915
  child = isl_schedule_tree_list_get_schedule_tree(tree->children, 0);
1679
915
  dom = isl_schedule_tree_filter_get_filter(child);
1680
915
  space = isl_union_set_get_space(dom);
1681
915
  isl_union_set_free(dom);
1682
915
  isl_schedule_tree_free(child);
1683
915
1684
915
  return space;
1685
915
}
1686
1687
/* Extend the schedule map "outer" with the subtree schedule
1688
 * of a set or sequence node.
1689
 *
1690
 * The schedule for the set or sequence node itself is composed of
1691
 * pieces of the form
1692
 *
1693
 *  filter -> []
1694
 *
1695
 * or
1696
 *
1697
 *  filter -> [index]
1698
 *
1699
 * The first form is used if there is only a single child or
1700
 * if the current node is a set node and the schedule_separate_components
1701
 * option is not set.
1702
 *
1703
 * Each of the pieces above is extended with the subtree schedule of
1704
 * the child of the corresponding filter, if any, padded with zeros
1705
 * to ensure that all pieces have the same range dimension.
1706
 */
1707
static __isl_give isl_union_map *subtree_schedule_extend_from_children(
1708
  __isl_keep isl_schedule_tree *tree, __isl_take isl_union_map *outer)
1709
654
{
1710
654
  int i, n;
1711
654
  int dim;
1712
654
  int separate;
1713
654
  isl_ctx *ctx;
1714
654
  isl_val *v = NULL;
1715
654
  isl_multi_val *mv;
1716
654
  isl_space *space;
1717
654
  isl_union_map *umap;
1718
654
1719
654
  if (!tree)
1720
0
    return NULL;
1721
654
1722
654
  ctx = isl_schedule_tree_get_ctx(tree);
1723
654
  if (!tree->children)
1724
0
    isl_die(isl_schedule_tree_get_ctx(tree), isl_error_internal,
1725
654
      "missing children", return NULL);
1726
654
  n = isl_schedule_tree_list_n_schedule_tree(tree->children);
1727
654
  if (n == 0)
1728
0
    isl_die(isl_schedule_tree_get_ctx(tree), isl_error_internal,
1729
654
      "missing children", return NULL);
1730
654
1731
654
  
separate = n > 1 && 654
(tree->type == isl_schedule_node_sequence ||654
1732
6
          isl_options_get_schedule_separate_components(ctx));
1733
654
1734
654
  space = extract_space_from_filter_child(tree);
1735
654
1736
654
  umap = isl_union_map_empty(isl_space_copy(space));
1737
654
  space = isl_space_set_from_params(space);
1738
654
  if (
separate654
)
{654
1739
654
    space = isl_space_add_dims(space, isl_dim_set, 1);
1740
654
    v = isl_val_zero(ctx);
1741
654
  }
1742
654
  mv = isl_multi_val_zero(space);
1743
654
1744
654
  dim = isl_multi_val_dim(mv, isl_dim_set);
1745
3.93k
  for (i = 0; 
i < n3.93k
;
++i3.28k
)
{3.28k
1746
3.28k
    isl_union_pw_multi_aff *upma;
1747
3.28k
    isl_union_map *umap_i;
1748
3.28k
    isl_union_set *dom;
1749
3.28k
    isl_schedule_tree *child;
1750
3.28k
    int dim_i;
1751
3.28k
    int empty;
1752
3.28k
1753
3.28k
    child = isl_schedule_tree_list_get_schedule_tree(
1754
3.28k
              tree->children, i);
1755
3.28k
    dom = isl_schedule_tree_filter_get_filter(child);
1756
3.28k
1757
3.28k
    if (
separate3.28k
)
{3.28k
1758
3.28k
      mv = isl_multi_val_set_val(mv, 0, isl_val_copy(v));
1759
3.28k
      v = isl_val_add_ui(v, 1);
1760
3.28k
    }
1761
3.28k
    upma = isl_union_pw_multi_aff_multi_val_on_domain(dom,
1762
3.28k
              isl_multi_val_copy(mv));
1763
3.28k
    umap_i = isl_union_map_from_union_pw_multi_aff(upma);
1764
3.28k
    umap_i = isl_union_map_flat_range_product(
1765
3.28k
              isl_union_map_copy(outer), umap_i);
1766
3.28k
    umap_i = subtree_schedule_extend_child(child, umap_i);
1767
3.28k
    isl_schedule_tree_free(child);
1768
3.28k
1769
3.28k
    empty = isl_union_map_is_empty(umap_i);
1770
3.28k
    if (empty < 0)
1771
0
      umap_i = isl_union_map_free(umap_i);
1772
3.28k
    else 
if (3.28k
empty3.28k
)
{0
1773
0
      isl_union_map_free(umap_i);
1774
0
      continue;
1775
0
    }
1776
3.28k
1777
3.28k
    dim_i = range_dim(umap_i);
1778
3.28k
    if (
dim_i < 03.28k
)
{0
1779
0
      umap = isl_union_map_free(umap);
1780
3.28k
    } else 
if (3.28k
dim < dim_i3.28k
)
{735
1781
735
      umap = append_range(umap, dim_i - dim);
1782
735
      dim = dim_i;
1783
2.55k
    } else 
if (2.55k
dim_i < dim2.55k
)
{238
1784
238
      umap_i = append_range(umap_i, dim - dim_i);
1785
238
    }
1786
3.28k
    umap = isl_union_map_union(umap, umap_i);
1787
3.28k
  }
1788
654
1789
654
  isl_val_free(v);
1790
654
  isl_multi_val_free(mv);
1791
654
  isl_union_map_free(outer);
1792
654
1793
654
  return umap;
1794
654
}
1795
1796
/* Extend the schedule map "outer" with the subtree schedule of "tree".
1797
 *
1798
 * If the root of the tree is a set or a sequence, then we extend
1799
 * the schedule map in subtree_schedule_extend_from_children.
1800
 * Otherwise, we extend the schedule map with the partial schedule
1801
 * corresponding to the root of the tree and then continue with
1802
 * the single child of this root.
1803
 * In the special case of an expansion, the schedule map is "extended"
1804
 * by applying the expansion to the domain of the schedule map.
1805
 */
1806
static __isl_give isl_union_map *subtree_schedule_extend(
1807
  __isl_keep isl_schedule_tree *tree, __isl_take isl_union_map *outer)
1808
2.93k
{
1809
2.93k
  isl_multi_union_pw_aff *mupa;
1810
2.93k
  isl_union_map *umap;
1811
2.93k
  isl_union_set *domain;
1812
2.93k
1813
2.93k
  if (!tree)
1814
0
    return NULL;
1815
2.93k
1816
2.93k
  switch (tree->type) {
1817
0
  case isl_schedule_node_error:
1818
0
    return isl_union_map_free(outer);
1819
0
  case isl_schedule_node_extension:
1820
0
    isl_die(isl_schedule_tree_get_ctx(tree), isl_error_invalid,
1821
0
      "cannot construct subtree schedule of tree "
1822
0
      "with extension nodes",
1823
0
      return isl_union_map_free(outer));
1824
58
  case isl_schedule_node_context:
1825
58
  case isl_schedule_node_guard:
1826
58
  case isl_schedule_node_mark:
1827
58
    return subtree_schedule_extend_child(tree, outer);
1828
2.22k
  case isl_schedule_node_band:
1829
2.22k
    if (isl_schedule_tree_band_n_member(tree) == 0)
1830
0
      return subtree_schedule_extend_child(tree, outer);
1831
2.22k
    mupa = isl_schedule_band_get_partial_schedule(tree->band);
1832
2.22k
    umap = isl_union_map_from_multi_union_pw_aff(mupa);
1833
2.22k
    outer = isl_union_map_flat_range_product(outer, umap);
1834
2.22k
    umap = subtree_schedule_extend_child(tree, outer);
1835
2.22k
    break;
1836
0
  case isl_schedule_node_domain:
1837
0
    domain = isl_schedule_tree_domain_get_domain(tree);
1838
0
    umap = isl_union_map_from_domain(domain);
1839
0
    outer = isl_union_map_flat_range_product(outer, umap);
1840
0
    umap = subtree_schedule_extend_child(tree, outer);
1841
0
    break;
1842
2
  case isl_schedule_node_expansion:
1843
2
    umap = isl_schedule_tree_expansion_get_expansion(tree);
1844
2
    outer = isl_union_map_apply_domain(outer, umap);
1845
2
    umap = subtree_schedule_extend_child(tree, outer);
1846
2
    break;
1847
0
  case isl_schedule_node_filter:
1848
0
    domain = isl_schedule_tree_filter_get_filter(tree);
1849
0
    umap = isl_union_map_from_domain(domain);
1850
0
    outer = isl_union_map_flat_range_product(outer, umap);
1851
0
    umap = subtree_schedule_extend_child(tree, outer);
1852
0
    break;
1853
0
  case isl_schedule_node_leaf:
1854
0
    isl_die(isl_schedule_tree_get_ctx(tree), isl_error_internal,
1855
0
      "leaf node should be handled by caller", return NULL);
1856
654
  case isl_schedule_node_set:
1857
654
  case isl_schedule_node_sequence:
1858
654
    umap = subtree_schedule_extend_from_children(tree, outer);
1859
654
    break;
1860
2.93k
  }
1861
2.93k
1862
2.87k
  return umap;
1863
2.93k
}
1864
1865
static __isl_give isl_union_set *initial_domain(
1866
  __isl_keep isl_schedule_tree *tree);
1867
1868
/* Extract a universe domain from the children of the tree root "tree",
1869
 * which is a set or sequence, meaning that its children are filters.
1870
 * In particular, return the union of the universes of the filters.
1871
 */
1872
static __isl_give isl_union_set *initial_domain_from_children(
1873
  __isl_keep isl_schedule_tree *tree)
1874
261
{
1875
261
  int i, n;
1876
261
  isl_space *space;
1877
261
  isl_union_set *domain;
1878
261
1879
261
  if (!tree->children)
1880
0
    isl_die(isl_schedule_tree_get_ctx(tree), isl_error_internal,
1881
261
      "missing children", return NULL);
1882
261
  n = isl_schedule_tree_list_n_schedule_tree(tree->children);
1883
261
  if (n == 0)
1884
0
    isl_die(isl_schedule_tree_get_ctx(tree), isl_error_internal,
1885
261
      "missing children", return NULL);
1886
261
1887
261
  space = extract_space_from_filter_child(tree);
1888
261
  domain = isl_union_set_empty(space);
1889
261
1890
2.12k
  for (i = 0; 
i < n2.12k
;
++i1.86k
)
{1.86k
1891
1.86k
    isl_schedule_tree *child;
1892
1.86k
    isl_union_set *domain_i;
1893
1.86k
1894
1.86k
    child = isl_schedule_tree_get_child(tree, i);
1895
1.86k
    domain_i = initial_domain(child);
1896
1.86k
    domain = isl_union_set_union(domain, domain_i);
1897
1.86k
    isl_schedule_tree_free(child);
1898
1.86k
  }
1899
261
1900
261
  return domain;
1901
261
}
1902
1903
/* Extract a universe domain from the tree root "tree".
1904
 * The caller is responsible for making sure that this node
1905
 * would not be skipped by isl_schedule_tree_first_schedule_descendant
1906
 * and that it is not a leaf node.
1907
 */
1908
static __isl_give isl_union_set *initial_domain(
1909
  __isl_keep isl_schedule_tree *tree)
1910
2.84k
{
1911
2.84k
  isl_multi_union_pw_aff *mupa;
1912
2.84k
  isl_union_set *domain;
1913
2.84k
  isl_union_map *exp;
1914
2.84k
1915
2.84k
  if (!tree)
1916
0
    return NULL;
1917
2.84k
1918
2.84k
  switch (tree->type) {
1919
0
  case isl_schedule_node_error:
1920
0
    return NULL;
1921
0
  case isl_schedule_node_context:
1922
0
    isl_die(isl_schedule_tree_get_ctx(tree), isl_error_internal,
1923
0
      "context node should be handled by caller",
1924
0
      return NULL);
1925
0
  case isl_schedule_node_guard:
1926
0
    isl_die(isl_schedule_tree_get_ctx(tree), isl_error_internal,
1927
0
      "guard node should be handled by caller",
1928
0
      return NULL);
1929
0
  case isl_schedule_node_mark:
1930
0
    isl_die(isl_schedule_tree_get_ctx(tree), isl_error_internal,
1931
0
      "mark node should be handled by caller",
1932
0
      return NULL);
1933
0
  case isl_schedule_node_extension:
1934
0
    isl_die(isl_schedule_tree_get_ctx(tree), isl_error_invalid,
1935
0
      "cannot construct subtree schedule of tree "
1936
0
      "with extension nodes", return NULL);
1937
722
  case isl_schedule_node_band:
1938
722
    if (isl_schedule_tree_band_n_member(tree) == 0)
1939
0
      isl_die(isl_schedule_tree_get_ctx(tree),
1940
722
        isl_error_internal,
1941
722
        "0D band should be handled by caller",
1942
722
        return NULL);
1943
722
    mupa = isl_schedule_band_get_partial_schedule(tree->band);
1944
722
    domain = isl_multi_union_pw_aff_domain(mupa);
1945
722
    domain = isl_union_set_universe(domain);
1946
722
    break;
1947
0
  case isl_schedule_node_domain:
1948
0
    domain = isl_schedule_tree_domain_get_domain(tree);
1949
0
    domain = isl_union_set_universe(domain);
1950
0
    break;
1951
0
  case isl_schedule_node_expansion:
1952
0
    exp = isl_schedule_tree_expansion_get_expansion(tree);
1953
0
    exp = isl_union_map_universe(exp);
1954
0
    domain = isl_union_map_domain(exp);
1955
0
    break;
1956
1.86k
  case isl_schedule_node_filter:
1957
1.86k
    domain = isl_schedule_tree_filter_get_filter(tree);
1958
1.86k
    domain = isl_union_set_universe(domain);
1959
1.86k
    break;
1960
0
  case isl_schedule_node_leaf:
1961
0
    isl_die(isl_schedule_tree_get_ctx(tree), isl_error_internal,
1962
0
      "leaf node should be handled by caller", return NULL);
1963
261
  case isl_schedule_node_set:
1964
261
  case isl_schedule_node_sequence:
1965
261
    domain = initial_domain_from_children(tree);
1966
261
    break;
1967
2.84k
  }
1968
2.84k
1969
2.84k
  return domain;
1970
2.84k
}
1971
1972
/* Return the subtree schedule of a node that contains some schedule
1973
 * information, i.e., a node that would not be skipped by
1974
 * isl_schedule_tree_first_schedule_descendant and that is not a leaf.
1975
 *
1976
 * If the tree contains any expansions, then the returned subtree
1977
 * schedule is formulated in terms of the expanded domains.
1978
 * The tree is not allowed to contain any extension nodes.
1979
 *
1980
 * We start with an initial zero-dimensional subtree schedule based
1981
 * on the domain information in the root node and then extend it
1982
 * based on the schedule information in the root node and its descendants.
1983
 */
1984
__isl_give isl_union_map *isl_schedule_tree_get_subtree_schedule_union_map(
1985
  __isl_keep isl_schedule_tree *tree)
1986
983
{
1987
983
  isl_union_set *domain;
1988
983
  isl_union_map *umap;
1989
983
1990
983
  domain = initial_domain(tree);
1991
983
  umap = isl_union_map_from_domain(domain);
1992
983
  return subtree_schedule_extend(tree, umap);
1993
983
}
1994
1995
/* Multiply the partial schedule of the band root node of "tree"
1996
 * with the factors in "mv".
1997
 */
1998
__isl_give isl_schedule_tree *isl_schedule_tree_band_scale(
1999
  __isl_take isl_schedule_tree *tree, __isl_take isl_multi_val *mv)
2000
0
{
2001
0
  if (
!tree || 0
!mv0
)
2002
0
    goto error;
2003
0
  
if (0
tree->type != isl_schedule_node_band0
)
2004
0
    isl_die(isl_schedule_tree_get_ctx(tree), isl_error_invalid,
2005
0
      "not a band node", goto error);
2006
0
2007
0
  tree = isl_schedule_tree_cow(tree);
2008
0
  if (!tree)
2009
0
    goto error;
2010
0
2011
0
  tree->band = isl_schedule_band_scale(tree->band, mv);
2012
0
  if (!tree->band)
2013
0
    return isl_schedule_tree_free(tree);
2014
0
2015
0
  return tree;
2016
0
error:
2017
0
  isl_schedule_tree_free(tree);
2018
0
  isl_multi_val_free(mv);
2019
0
  return NULL;
2020
0
}
2021
2022
/* Divide the partial schedule of the band root node of "tree"
2023
 * by the factors in "mv".
2024
 */
2025
__isl_give isl_schedule_tree *isl_schedule_tree_band_scale_down(
2026
  __isl_take isl_schedule_tree *tree, __isl_take isl_multi_val *mv)
2027
0
{
2028
0
  if (
!tree || 0
!mv0
)
2029
0
    goto error;
2030
0
  
if (0
tree->type != isl_schedule_node_band0
)
2031
0
    isl_die(isl_schedule_tree_get_ctx(tree), isl_error_invalid,
2032
0
      "not a band node", goto error);
2033
0
2034
0
  tree = isl_schedule_tree_cow(tree);
2035
0
  if (!tree)
2036
0
    goto error;
2037
0
2038
0
  tree->band = isl_schedule_band_scale_down(tree->band, mv);
2039
0
  if (!tree->band)
2040
0
    return isl_schedule_tree_free(tree);
2041
0
2042
0
  return tree;
2043
0
error:
2044
0
  isl_schedule_tree_free(tree);
2045
0
  isl_multi_val_free(mv);
2046
0
  return NULL;
2047
0
}
2048
2049
/* Reduce the partial schedule of the band root node of "tree"
2050
 * modulo the factors in "mv".
2051
 */
2052
__isl_give isl_schedule_tree *isl_schedule_tree_band_mod(
2053
  __isl_take isl_schedule_tree *tree, __isl_take isl_multi_val *mv)
2054
0
{
2055
0
  if (
!tree || 0
!mv0
)
2056
0
    goto error;
2057
0
  
if (0
tree->type != isl_schedule_node_band0
)
2058
0
    isl_die(isl_schedule_tree_get_ctx(tree), isl_error_invalid,
2059
0
      "not a band node", goto error);
2060
0
2061
0
  tree = isl_schedule_tree_cow(tree);
2062
0
  if (!tree)
2063
0
    goto error;
2064
0
2065
0
  tree->band = isl_schedule_band_mod(tree->band, mv);
2066
0
  if (!tree->band)
2067
0
    return isl_schedule_tree_free(tree);
2068
0
2069
0
  return tree;
2070
0
error:
2071
0
  isl_schedule_tree_free(tree);
2072
0
  isl_multi_val_free(mv);
2073
0
  return NULL;
2074
0
}
2075
2076
/* Shift the partial schedule of the band root node of "tree" by "shift".
2077
 */
2078
__isl_give isl_schedule_tree *isl_schedule_tree_band_shift(
2079
  __isl_take isl_schedule_tree *tree,
2080
  __isl_take isl_multi_union_pw_aff *shift)
2081
0
{
2082
0
  if (
!tree || 0
!shift0
)
2083
0
    goto error;
2084
0
  
if (0
tree->type != isl_schedule_node_band0
)
2085
0
    isl_die(isl_schedule_tree_get_ctx(tree), isl_error_invalid,
2086
0
      "not a band node", goto error);
2087
0
2088
0
  tree = isl_schedule_tree_cow(tree);
2089
0
  if (!tree)
2090
0
    goto error;
2091
0
2092
0
  tree->band = isl_schedule_band_shift(tree->band, shift);
2093
0
  if (!tree->band)
2094
0
    return isl_schedule_tree_free(tree);
2095
0
2096
0
  return tree;
2097
0
error:
2098
0
  isl_schedule_tree_free(tree);
2099
0
  isl_multi_union_pw_aff_free(shift);
2100
0
  return NULL;
2101
0
}
2102
2103
/* Given two trees with sequence roots, replace the child at position
2104
 * "pos" of "tree" with the children of "child".
2105
 */
2106
__isl_give isl_schedule_tree *isl_schedule_tree_sequence_splice(
2107
  __isl_take isl_schedule_tree *tree, int pos,
2108
  __isl_take isl_schedule_tree *child)
2109
0
{
2110
0
  int n;
2111
0
  isl_schedule_tree_list *list1, *list2;
2112
0
2113
0
  tree = isl_schedule_tree_cow(tree);
2114
0
  if (
!tree || 0
!child0
)
2115
0
    goto error;
2116
0
  
if (0
isl_schedule_tree_get_type(tree) != isl_schedule_node_sequence0
)
2117
0
    isl_die(isl_schedule_tree_get_ctx(tree), isl_error_invalid,
2118
0
      "not a sequence node", goto error);
2119
0
  n = isl_schedule_tree_n_children(tree);
2120
0
  if (
pos < 0 || 0
pos >= n0
)
2121
0
    isl_die(isl_schedule_tree_get_ctx(tree), isl_error_invalid,
2122
0
      "position out of bounds", goto error);
2123
0
  
if (0
isl_schedule_tree_get_type(child) != isl_schedule_node_sequence0
)
2124
0
    isl_die(isl_schedule_tree_get_ctx(tree), isl_error_invalid,
2125
0
      "not a sequence node", goto error);
2126
0
2127
0
  list1 = isl_schedule_tree_list_copy(tree->children);
2128
0
  list1 = isl_schedule_tree_list_drop(list1, pos, n - pos);
2129
0
  list2 = isl_schedule_tree_list_copy(tree->children);
2130
0
  list2 = isl_schedule_tree_list_drop(list2, 0, pos + 1);
2131
0
  list1 = isl_schedule_tree_list_concat(list1,
2132
0
        isl_schedule_tree_list_copy(child->children));
2133
0
  list1 = isl_schedule_tree_list_concat(list1, list2);
2134
0
2135
0
  isl_schedule_tree_free(tree);
2136
0
  isl_schedule_tree_free(child);
2137
0
  return isl_schedule_tree_from_children(isl_schedule_node_sequence,
2138
0
            list1);
2139
0
error:
2140
0
  isl_schedule_tree_free(tree);
2141
0
  isl_schedule_tree_free(child);
2142
0
  return NULL;
2143
0
}
2144
2145
/* Tile the band root node of "tree" with tile sizes "sizes".
2146
 *
2147
 * We duplicate the band node, change the schedule of one of them
2148
 * to the tile schedule and the other to the point schedule and then
2149
 * attach the point band as a child to the tile band.
2150
 */
2151
__isl_give isl_schedule_tree *isl_schedule_tree_band_tile(
2152
  __isl_take isl_schedule_tree *tree, __isl_take isl_multi_val *sizes)
2153
68
{
2154
68
  isl_schedule_tree *child = NULL;
2155
68
2156
68
  if (
!tree || 68
!sizes68
)
2157
0
    goto error;
2158
68
  
if (68
tree->type != isl_schedule_node_band68
)
2159
0
    isl_die(isl_schedule_tree_get_ctx(tree), isl_error_invalid,
2160
68
      "not a band node", goto error);
2161
68
2162
68
  child = isl_schedule_tree_copy(tree);
2163
68
  tree = isl_schedule_tree_cow(tree);
2164
68
  child = isl_schedule_tree_cow(child);
2165
68
  if (
!tree || 68
!child68
)
2166
0
    goto error;
2167
68
2168
68
  tree->band = isl_schedule_band_tile(tree->band,
2169
68
              isl_multi_val_copy(sizes));
2170
68
  if (!tree->band)
2171
0
    goto error;
2172
68
  child->band = isl_schedule_band_point(child->band, tree->band, sizes);
2173
68
  if (!child->band)
2174
0
    child = isl_schedule_tree_free(child);
2175
68
2176
68
  tree = isl_schedule_tree_replace_child(tree, 0, child);
2177
68
2178
68
  return tree;
2179
0
error:
2180
0
  isl_schedule_tree_free(child);
2181
0
  isl_schedule_tree_free(tree);
2182
0
  isl_multi_val_free(sizes);
2183
0
  return NULL;
2184
68
}
2185
2186
/* Given an isolate AST generation option "isolate" for a band of size pos + n,
2187
 * return the corresponding option for a band covering the first "pos"
2188
 * members.
2189
 *
2190
 * The input isolate option is of the form
2191
 *
2192
 *  isolate[[flattened outer bands] -> [pos; n]]
2193
 *
2194
 * The output isolate option is of the form
2195
 *
2196
 *  isolate[[flattened outer bands] -> [pos]]
2197
 */
2198
static __isl_give isl_set *isolate_initial(__isl_keep isl_set *isolate,
2199
  int pos, int n)
2200
30
{
2201
30
  isl_id *id;
2202
30
  isl_map *map;
2203
30
2204
30
  isolate = isl_set_copy(isolate);
2205
30
  id = isl_set_get_tuple_id(isolate);
2206
30
  map = isl_set_unwrap(isolate);
2207
30
  map = isl_map_project_out(map, isl_dim_out, pos, n);
2208
30
  isolate = isl_map_wrap(map);
2209
30
  isolate = isl_set_set_tuple_id(isolate, id);
2210
30
2211
30
  return isolate;
2212
30
}
2213
2214
/* Given an isolate AST generation option "isolate" for a band of size pos + n,
2215
 * return the corresponding option for a band covering the final "n"
2216
 * members within a band covering the first "pos" members.
2217
 *
2218
 * The input isolate option is of the form
2219
 *
2220
 *  isolate[[flattened outer bands] -> [pos; n]]
2221
 *
2222
 * The output isolate option is of the form
2223
 *
2224
 *  isolate[[flattened outer bands; pos] -> [n]]
2225
 *
2226
 *
2227
 * The range is first split into
2228
 *
2229
 *  isolate[[flattened outer bands] -> [[pos] -> [n]]]
2230
 *
2231
 * and then the first pos members are moved to the domain
2232
 *
2233
 *  isolate[[[flattened outer bands] -> [pos]] -> [n]]
2234
 *
2235
 * after which the domain is flattened to obtain the desired output.
2236
 */
2237
static __isl_give isl_set *isolate_final(__isl_keep isl_set *isolate,
2238
  int pos, int n)
2239
30
{
2240
30
  isl_id *id;
2241
30
  isl_space *space;
2242
30
  isl_multi_aff *ma1, *ma2;
2243
30
  isl_map *map;
2244
30
2245
30
  isolate = isl_set_copy(isolate);
2246
30
  id = isl_set_get_tuple_id(isolate);
2247
30
  map = isl_set_unwrap(isolate);
2248
30
  space = isl_space_range(isl_map_get_space(map));
2249
30
  ma1 = isl_multi_aff_project_out_map(isl_space_copy(space),
2250
30
               isl_dim_set, pos, n);
2251
30
  ma2 = isl_multi_aff_project_out_map(space, isl_dim_set, 0, pos);
2252
30
  ma1 = isl_multi_aff_range_product(ma1, ma2);
2253
30
  map = isl_map_apply_range(map, isl_map_from_multi_aff(ma1));
2254
30
  map = isl_map_uncurry(map);
2255
30
  map = isl_map_flatten_domain(map);
2256
30
  isolate = isl_map_wrap(map);
2257
30
  isolate = isl_set_set_tuple_id(isolate, id);
2258
30
2259
30
  return isolate;
2260
30
}
2261
2262
/* Split the band root node of "tree" into two nested band nodes,
2263
 * one with the first "pos" dimensions and
2264
 * one with the remaining dimensions.
2265
 * The tree is itself positioned at schedule depth "depth".
2266
 *
2267
 * The loop AST generation type options and the isolate option
2268
 * are split over the the two band nodes.
2269
 */
2270
__isl_give isl_schedule_tree *isl_schedule_tree_band_split(
2271
  __isl_take isl_schedule_tree *tree, int pos, int depth)
2272
30
{
2273
30
  int n;
2274
30
  isl_set *isolate, *tree_isolate, *child_isolate;
2275
30
  isl_schedule_tree *child;
2276
30
2277
30
  if (!tree)
2278
0
    return NULL;
2279
30
  
if (30
tree->type != isl_schedule_node_band30
)
2280
0
    isl_die(isl_schedule_tree_get_ctx(tree), isl_error_invalid,
2281
30
      "not a band node", return isl_schedule_tree_free(tree));
2282
30
2283
30
  n = isl_schedule_tree_band_n_member(tree);
2284
30
  if (
pos < 0 || 30
pos > n30
)
2285
0
    isl_die(isl_schedule_tree_get_ctx(tree), isl_error_invalid,
2286
30
      "position out of bounds",
2287
30
      return isl_schedule_tree_free(tree));
2288
30
2289
30
  child = isl_schedule_tree_copy(tree);
2290
30
  tree = isl_schedule_tree_cow(tree);
2291
30
  child = isl_schedule_tree_cow(child);
2292
30
  if (
!tree || 30
!child30
)
2293
0
    goto error;
2294
30
2295
30
  isolate = isl_schedule_tree_band_get_ast_isolate_option(tree, depth);
2296
30
  tree_isolate = isolate_initial(isolate, pos, n - pos);
2297
30
  child_isolate = isolate_final(isolate, pos, n - pos);
2298
30
  child->band = isl_schedule_band_drop(child->band, 0, pos);
2299
30
  child->band = isl_schedule_band_replace_ast_build_option(child->band,
2300
30
          isl_set_copy(isolate), child_isolate);
2301
30
  tree->band = isl_schedule_band_drop(tree->band, pos, n - pos);
2302
30
  tree->band = isl_schedule_band_replace_ast_build_option(tree->band,
2303
30
          isl_set_copy(isolate), tree_isolate);
2304
30
  isl_set_free(isolate);
2305
30
  if (
!child->band || 30
!tree->band30
)
2306
0
    goto error;
2307
30
2308
30
  tree = isl_schedule_tree_replace_child(tree, 0, child);
2309
30
2310
30
  return tree;
2311
0
error:
2312
0
  isl_schedule_tree_free(child);
2313
0
  isl_schedule_tree_free(tree);
2314
0
  return NULL;
2315
30
}
2316
2317
/* Attach "tree2" at each of the leaves of "tree1".
2318
 *
2319
 * If "tree1" does not have any explicit children, then make "tree2"
2320
 * its single child.  Otherwise, attach "tree2" to the leaves of
2321
 * each of the children of "tree1".
2322
 */
2323
__isl_give isl_schedule_tree *isl_schedule_tree_append_to_leaves(
2324
  __isl_take isl_schedule_tree *tree1,
2325
  __isl_take isl_schedule_tree *tree2)
2326
7
{
2327
7
  int i, n;
2328
7
2329
7
  if (
!tree1 || 7
!tree27
)
2330
0
    goto error;
2331
7
  n = isl_schedule_tree_n_children(tree1);
2332
7
  if (
n == 07
)
{7
2333
7
    isl_schedule_tree_list *list;
2334
7
    list = isl_schedule_tree_list_from_schedule_tree(tree2);
2335
7
    tree1 = isl_schedule_tree_set_children(tree1, list);
2336
7
    return tree1;
2337
7
  }
2338
0
  
for (i = 0; 0
i < n0
;
++i0
)
{0
2339
0
    isl_schedule_tree *child;
2340
0
2341
0
    child = isl_schedule_tree_get_child(tree1, i);
2342
0
    child = isl_schedule_tree_append_to_leaves(child,
2343
0
          isl_schedule_tree_copy(tree2));
2344
0
    tree1 = isl_schedule_tree_replace_child(tree1, i, child);
2345
0
  }
2346
0
2347
0
  isl_schedule_tree_free(tree2);
2348
0
  return tree1;
2349
0
error:
2350
0
  isl_schedule_tree_free(tree1);
2351
0
  isl_schedule_tree_free(tree2);
2352
0
  return NULL;
2353
7
}
2354
2355
/* Reset the user pointer on all identifiers of parameters and tuples
2356
 * in the root of "tree".
2357
 */
2358
__isl_give isl_schedule_tree *isl_schedule_tree_reset_user(
2359
  __isl_take isl_schedule_tree *tree)
2360
0
{
2361
0
  if (isl_schedule_tree_is_leaf(tree))
2362
0
    return tree;
2363
0
2364
0
  tree = isl_schedule_tree_cow(tree);
2365
0
  if (!tree)
2366
0
    return NULL;
2367
0
2368
0
  switch (tree->type) {
2369
0
  case isl_schedule_node_error:
2370
0
    return isl_schedule_tree_free(tree);
2371
0
  case isl_schedule_node_band:
2372
0
    tree->band = isl_schedule_band_reset_user(tree->band);
2373
0
    if (!tree->band)
2374
0
      return isl_schedule_tree_free(tree);
2375
0
    break;
2376
0
  case isl_schedule_node_context:
2377
0
    tree->context = isl_set_reset_user(tree->context);
2378
0
    if (!tree->context)
2379
0
      return isl_schedule_tree_free(tree);
2380
0
    break;
2381
0
  case isl_schedule_node_domain:
2382
0
    tree->domain = isl_union_set_reset_user(tree->domain);
2383
0
    if (!tree->domain)
2384
0
      return isl_schedule_tree_free(tree);
2385
0
    break;
2386
0
  case isl_schedule_node_expansion:
2387
0
    tree->contraction =
2388
0
      isl_union_pw_multi_aff_reset_user(tree->contraction);
2389
0
    tree->expansion = isl_union_map_reset_user(tree->expansion);
2390
0
    if (
!tree->contraction || 0
!tree->expansion0
)
2391
0
      return isl_schedule_tree_free(tree);
2392
0
    break;
2393
0
  case isl_schedule_node_extension:
2394
0
    tree->extension = isl_union_map_reset_user(tree->extension);
2395
0
    if (!tree->extension)
2396
0
      return isl_schedule_tree_free(tree);
2397
0
    break;
2398
0
  case isl_schedule_node_filter:
2399
0
    tree->filter = isl_union_set_reset_user(tree->filter);
2400
0
    if (!tree->filter)
2401
0
      return isl_schedule_tree_free(tree);
2402
0
    break;
2403
0
  case isl_schedule_node_guard:
2404
0
    tree->guard = isl_set_reset_user(tree->guard);
2405
0
    if (!tree->guard)
2406
0
      return isl_schedule_tree_free(tree);
2407
0
    break;
2408
0
  case isl_schedule_node_leaf:
2409
0
  case isl_schedule_node_mark:
2410
0
  case isl_schedule_node_sequence:
2411
0
  case isl_schedule_node_set:
2412
0
    break;
2413
0
  }
2414
0
2415
0
  return tree;
2416
0
}
2417
2418
/* Align the parameters of the root of "tree" to those of "space".
2419
 */
2420
__isl_give isl_schedule_tree *isl_schedule_tree_align_params(
2421
  __isl_take isl_schedule_tree *tree, __isl_take isl_space *space)
2422
0
{
2423
0
  if (!space)
2424
0
    goto error;
2425
0
2426
0
  
if (0
isl_schedule_tree_is_leaf(tree)0
)
{0
2427
0
    isl_space_free(space);
2428
0
    return tree;
2429
0
  }
2430
0
2431
0
  tree = isl_schedule_tree_cow(tree);
2432
0
  if (!tree)
2433
0
    goto error;
2434
0
2435
0
  switch (tree->type) {
2436
0
  case isl_schedule_node_error:
2437
0
    goto error;
2438
0
  case isl_schedule_node_band:
2439
0
    tree->band = isl_schedule_band_align_params(tree->band, space);
2440
0
    if (!tree->band)
2441
0
      return isl_schedule_tree_free(tree);
2442
0
    break;
2443
0
  case isl_schedule_node_context:
2444
0
    tree->context = isl_set_align_params(tree->context, space);
2445
0
    if (!tree->context)
2446
0
      return isl_schedule_tree_free(tree);
2447
0
    break;
2448
0
  case isl_schedule_node_domain:
2449
0
    tree->domain = isl_union_set_align_params(tree->domain, space);
2450
0
    if (!tree->domain)
2451
0
      return isl_schedule_tree_free(tree);
2452
0
    break;
2453
0
  case isl_schedule_node_expansion:
2454
0
    tree->contraction =
2455
0
      isl_union_pw_multi_aff_align_params(tree->contraction,
2456
0
              isl_space_copy(space));
2457
0
    tree->expansion = isl_union_map_align_params(tree->expansion,
2458
0
                space);
2459
0
    if (
!tree->contraction || 0
!tree->expansion0
)
2460
0
      return isl_schedule_tree_free(tree);
2461
0
    break;
2462
0
  case isl_schedule_node_extension:
2463
0
    tree->extension = isl_union_map_align_params(tree->extension,
2464
0
                space);
2465
0
    if (!tree->extension)
2466
0
      return isl_schedule_tree_free(tree);
2467
0
    break;
2468
0
  case isl_schedule_node_filter:
2469
0
    tree->filter = isl_union_set_align_params(tree->filter, space);
2470
0
    if (!tree->filter)
2471
0
      return isl_schedule_tree_free(tree);
2472
0
    break;
2473
0
  case isl_schedule_node_guard:
2474
0
    tree->guard = isl_set_align_params(tree->guard, space);
2475
0
    if (!tree->guard)
2476
0
      return isl_schedule_tree_free(tree);
2477
0
    break;
2478
0
  case isl_schedule_node_leaf:
2479
0
  case isl_schedule_node_mark:
2480
0
  case isl_schedule_node_sequence:
2481
0
  case isl_schedule_node_set:
2482
0
    isl_space_free(space);
2483
0
    break;
2484
0
  }
2485
0
2486
0
  return tree;
2487
0
error:
2488
0
  isl_space_free(space);
2489
0
  isl_schedule_tree_free(tree);
2490
0
  return NULL;
2491
0
}
2492
2493
/* Does "tree" involve the iteration domain?
2494
 * That is, does it need to be modified
2495
 * by isl_schedule_tree_pullback_union_pw_multi_aff?
2496
 */
2497
static int involves_iteration_domain(__isl_keep isl_schedule_tree *tree)
2498
700
{
2499
700
  if (!tree)
2500
0
    return -1;
2501
700
2502
700
  switch (tree->type) {
2503
0
  case isl_schedule_node_error:
2504
0
    return -1;
2505
467
  case isl_schedule_node_band:
2506
467
  case isl_schedule_node_domain:
2507
467
  case isl_schedule_node_expansion:
2508
467
  case isl_schedule_node_extension:
2509
467
  case isl_schedule_node_filter:
2510
467
    return 1;
2511
233
  case isl_schedule_node_context:
2512
233
  case isl_schedule_node_leaf:
2513
233
  case isl_schedule_node_guard:
2514
233
  case isl_schedule_node_mark:
2515
233
  case isl_schedule_node_sequence:
2516
233
  case isl_schedule_node_set:
2517
233
    return 0;
2518
700
  }
2519
700
2520
0
  
isl_die0
(isl_schedule_tree_get_ctx(tree), isl_error_internal,0
2521
0
    "unhandled case", return -1);
2522
0
}
2523
2524
/* Compute the pullback of the root node of "tree" by the function
2525
 * represented by "upma".
2526
 * In other words, plug in "upma" in the iteration domains of
2527
 * the root node of "tree".
2528
 * We currently do not handle expansion nodes.
2529
 *
2530
 * We first check if the root node involves any iteration domains.
2531
 * If so, we handle the specific cases.
2532
 */
2533
__isl_give isl_schedule_tree *isl_schedule_tree_pullback_union_pw_multi_aff(
2534
  __isl_take isl_schedule_tree *tree,
2535
  __isl_take isl_union_pw_multi_aff *upma)
2536
700
{
2537
700
  int involves;
2538
700
2539
700
  if (
!tree || 700
!upma700
)
2540
0
    goto error;
2541
700
2542
700
  involves = involves_iteration_domain(tree);
2543
700
  if (involves < 0)
2544
0
    goto error;
2545
700
  
if (700
!involves700
)
{233
2546
233
    isl_union_pw_multi_aff_free(upma);
2547
233
    return tree;
2548
233
  }
2549
700
2550
467
  tree = isl_schedule_tree_cow(tree);
2551
467
  if (!tree)
2552
0
    goto error;
2553
467
2554
467
  
if (467
tree->type == isl_schedule_node_band467
)
{234
2555
234
    tree->band = isl_schedule_band_pullback_union_pw_multi_aff(
2556
234
                  tree->band, upma);
2557
234
    if (!tree->band)
2558
0
      return isl_schedule_tree_free(tree);
2559
233
  } else 
if (233
tree->type == isl_schedule_node_domain233
)
{108
2560
108
    tree->domain =
2561
108
      isl_union_set_preimage_union_pw_multi_aff(tree->domain,
2562
108
                  upma);
2563
108
    if (!tree->domain)
2564
0
      return isl_schedule_tree_free(tree);
2565
125
  } else 
if (125
tree->type == isl_schedule_node_expansion125
)
{0
2566
0
    isl_die(isl_schedule_tree_get_ctx(tree), isl_error_unsupported,
2567
0
      "cannot pullback expansion node", goto error);
2568
125
  } else 
if (125
tree->type == isl_schedule_node_extension125
)
{0
2569
0
    tree->extension =
2570
0
      isl_union_map_preimage_range_union_pw_multi_aff(
2571
0
          tree->extension, upma);
2572
0
    if (!tree->extension)
2573
0
      return isl_schedule_tree_free(tree);
2574
125
  } else 
if (125
tree->type == isl_schedule_node_filter125
)
{125
2575
125
    tree->filter =
2576
125
      isl_union_set_preimage_union_pw_multi_aff(tree->filter,
2577
125
                  upma);
2578
125
    if (!tree->filter)
2579
0
      return isl_schedule_tree_free(tree);
2580
125
  }
2581
467
2582
467
  return tree;
2583
0
error:
2584
0
  isl_union_pw_multi_aff_free(upma);
2585
0
  isl_schedule_tree_free(tree);
2586
0
  return NULL;
2587
467
}
2588
2589
/* Compute the gist of the band tree root with respect to "context".
2590
 */
2591
__isl_give isl_schedule_tree *isl_schedule_tree_band_gist(
2592
  __isl_take isl_schedule_tree *tree, __isl_take isl_union_set *context)
2593
177
{
2594
177
  if (!tree)
2595
0
    return NULL;
2596
177
  
if (177
tree->type != isl_schedule_node_band177
)
2597
0
    isl_die(isl_schedule_tree_get_ctx(tree), isl_error_invalid,
2598
177
      "not a band node", goto error);
2599
177
  tree = isl_schedule_tree_cow(tree);
2600
177
  if (!tree)
2601
0
    goto error;
2602
177
2603
177
  tree->band = isl_schedule_band_gist(tree->band, context);
2604
177
  if (!tree->band)
2605
0
    return isl_schedule_tree_free(tree);
2606
177
  return tree;
2607
0
error:
2608
0
  isl_union_set_free(context);
2609
0
  isl_schedule_tree_free(tree);
2610
0
  return NULL;
2611
177
}
2612
2613
/* Are any members in "band" marked coincident?
2614
 */
2615
static int any_coincident(__isl_keep isl_schedule_band *band)
2616
0
{
2617
0
  int i, n;
2618
0
2619
0
  n = isl_schedule_band_n_member(band);
2620
0
  for (i = 0; 
i < n0
;
++i0
)
2621
0
    
if (0
isl_schedule_band_member_get_coincident(band, i)0
)
2622
0
      return 1;
2623
0
2624
0
  return 0;
2625
0
}
2626
2627
/* Print the band node "band" to "p".
2628
 *
2629
 * The permutable and coincident properties are only printed if they
2630
 * are different from the defaults.
2631
 * The coincident property is always printed in YAML flow style.
2632
 */
2633
static __isl_give isl_printer *print_tree_band(__isl_take isl_printer *p,
2634
  __isl_keep isl_schedule_band *band)
2635
0
{
2636
0
  isl_union_set *options;
2637
0
  int empty;
2638
0
2639
0
  p = isl_printer_print_str(p, "schedule");
2640
0
  p = isl_printer_yaml_next(p);
2641
0
  p = isl_printer_print_str(p, "\"");
2642
0
  p = isl_printer_print_multi_union_pw_aff(p, band->mupa);
2643
0
  p = isl_printer_print_str(p, "\"");
2644
0
  if (
isl_schedule_band_get_permutable(band)0
)
{0
2645
0
    p = isl_printer_yaml_next(p);
2646
0
    p = isl_printer_print_str(p, "permutable");
2647
0
    p = isl_printer_yaml_next(p);
2648
0
    p = isl_printer_print_int(p, 1);
2649
0
  }
2650
0
  if (
any_coincident(band)0
)
{0
2651
0
    int i, n;
2652
0
    int style;
2653
0
2654
0
    p = isl_printer_yaml_next(p);
2655
0
    p = isl_printer_print_str(p, "coincident");
2656
0
    p = isl_printer_yaml_next(p);
2657
0
    style = isl_printer_get_yaml_style(p);
2658
0
    p = isl_printer_set_yaml_style(p, ISL_YAML_STYLE_FLOW);
2659
0
    p = isl_printer_yaml_start_sequence(p);
2660
0
    n = isl_schedule_band_n_member(band);
2661
0
    for (i = 0; 
i < n0
;
++i0
)
{0
2662
0
      p = isl_printer_print_int(p,
2663
0
          isl_schedule_band_member_get_coincident(band, i));
2664
0
      p = isl_printer_yaml_next(p);
2665
0
    }
2666
0
    p = isl_printer_yaml_end_sequence(p);
2667
0
    p = isl_printer_set_yaml_style(p, style);
2668
0
  }
2669
0
  options = isl_schedule_band_get_ast_build_options(band);
2670
0
  empty = isl_union_set_is_empty(options);
2671
0
  if (empty < 0)
2672
0
    p = isl_printer_free(p);
2673
0
  if (
!empty0
)
{0
2674
0
    p = isl_printer_yaml_next(p);
2675
0
    p = isl_printer_print_str(p, "options");
2676
0
    p = isl_printer_yaml_next(p);
2677
0
    p = isl_printer_print_str(p, "\"");
2678
0
    p = isl_printer_print_union_set(p, options);
2679
0
    p = isl_printer_print_str(p, "\"");
2680
0
  }
2681
0
  isl_union_set_free(options);
2682
0
2683
0
  return p;
2684
0
}
2685
2686
/* Print "tree" to "p".
2687
 *
2688
 * If "n_ancestor" is non-negative, then "child_pos" contains the child
2689
 * positions of a descendant of the current node that should be marked
2690
 * (by the comment "YOU ARE HERE").  In particular, if "n_ancestor"
2691
 * is zero, then the current node should be marked.
2692
 * The marking is only printed in YAML block format.
2693
 *
2694
 * Implicit leaf nodes are not printed, except if they correspond
2695
 * to the node that should be marked.
2696
 */
2697
__isl_give isl_printer *isl_printer_print_schedule_tree_mark(
2698
  __isl_take isl_printer *p, __isl_keep isl_schedule_tree *tree,
2699
  int n_ancestor, int *child_pos)
2700
0
{
2701
0
  int i, n;
2702
0
  int sequence = 0;
2703
0
  int block;
2704
0
2705
0
  block = isl_printer_get_yaml_style(p) == ISL_YAML_STYLE_BLOCK;
2706
0
2707
0
  p = isl_printer_yaml_start_mapping(p);
2708
0
  if (
n_ancestor == 0 && 0
block0
)
{0
2709
0
    p = isl_printer_print_str(p, "# YOU ARE HERE");
2710
0
    p = isl_printer_end_line(p);
2711
0
    p = isl_printer_start_line(p);
2712
0
  }
2713
0
  switch (tree->type) {
2714
0
  case isl_schedule_node_error:
2715
0
    p = isl_printer_print_str(p, "ERROR");
2716
0
    break;
2717
0
  case isl_schedule_node_leaf:
2718
0
    p = isl_printer_print_str(p, "leaf");
2719
0
    break;
2720
0
  case isl_schedule_node_sequence:
2721
0
    p = isl_printer_print_str(p, "sequence");
2722
0
    sequence = 1;
2723
0
    break;
2724
0
  case isl_schedule_node_set:
2725
0
    p = isl_printer_print_str(p, "set");
2726
0
    sequence = 1;
2727
0
    break;
2728
0
  case isl_schedule_node_context:
2729
0
    p = isl_printer_print_str(p, "context");
2730
0
    p = isl_printer_yaml_next(p);
2731
0
    p = isl_printer_print_str(p, "\"");
2732
0
    p = isl_printer_print_set(p, tree->context);
2733
0
    p = isl_printer_print_str(p, "\"");
2734
0
    break;
2735
0
  case isl_schedule_node_domain:
2736
0
    p = isl_printer_print_str(p, "domain");
2737
0
    p = isl_printer_yaml_next(p);
2738
0
    p = isl_printer_print_str(p, "\"");
2739
0
    p = isl_printer_print_union_set(p, tree->domain);
2740
0
    p = isl_printer_print_str(p, "\"");
2741
0
    break;
2742
0
  case isl_schedule_node_expansion:
2743
0
    p = isl_printer_print_str(p, "contraction");
2744
0
    p = isl_printer_yaml_next(p);
2745
0
    p = isl_printer_print_str(p, "\"");
2746
0
    p = isl_printer_print_union_pw_multi_aff(p, tree->contraction);
2747
0
    p = isl_printer_print_str(p, "\"");
2748
0
    p = isl_printer_yaml_next(p);
2749
0
    p = isl_printer_print_str(p, "expansion");
2750
0
    p = isl_printer_yaml_next(p);
2751
0
    p = isl_printer_print_str(p, "\"");
2752
0
    p = isl_printer_print_union_map(p, tree->expansion);
2753
0
    p = isl_printer_print_str(p, "\"");
2754
0
    break;
2755
0
  case isl_schedule_node_extension:
2756
0
    p = isl_printer_print_str(p, "extension");
2757
0
    p = isl_printer_yaml_next(p);
2758
0
    p = isl_printer_print_str(p, "\"");
2759
0
    p = isl_printer_print_union_map(p, tree->extension);
2760
0
    p = isl_printer_print_str(p, "\"");
2761
0
    break;
2762
0
  case isl_schedule_node_filter:
2763
0
    p = isl_printer_print_str(p, "filter");
2764
0
    p = isl_printer_yaml_next(p);
2765
0
    p = isl_printer_print_str(p, "\"");
2766
0
    p = isl_printer_print_union_set(p, tree->filter);
2767
0
    p = isl_printer_print_str(p, "\"");
2768
0
    break;
2769
0
  case isl_schedule_node_guard:
2770
0
    p = isl_printer_print_str(p, "guard");
2771
0
    p = isl_printer_yaml_next(p);
2772
0
    p = isl_printer_print_str(p, "\"");
2773
0
    p = isl_printer_print_set(p, tree->guard);
2774
0
    p = isl_printer_print_str(p, "\"");
2775
0
    break;
2776
0
  case isl_schedule_node_mark:
2777
0
    p = isl_printer_print_str(p, "mark");
2778
0
    p = isl_printer_yaml_next(p);
2779
0
    p = isl_printer_print_str(p, "\"");
2780
0
    p = isl_printer_print_str(p, isl_id_get_name(tree->mark));
2781
0
    p = isl_printer_print_str(p, "\"");
2782
0
    break;
2783
0
  case isl_schedule_node_band:
2784
0
    p = print_tree_band(p, tree->band);
2785
0
    break;
2786
0
  }
2787
0
  p = isl_printer_yaml_next(p);
2788
0
2789
0
  if (
!tree->children0
)
{0
2790
0
    if (
n_ancestor > 0 && 0
block0
)
{0
2791
0
      isl_schedule_tree *leaf;
2792
0
2793
0
      p = isl_printer_print_str(p, "child");
2794
0
      p = isl_printer_yaml_next(p);
2795
0
      leaf = isl_schedule_tree_leaf(isl_printer_get_ctx(p));
2796
0
      p = isl_printer_print_schedule_tree_mark(p,
2797
0
          leaf, 0, NULL);
2798
0
      isl_schedule_tree_free(leaf);
2799
0
      p = isl_printer_yaml_next(p);
2800
0
    }
2801
0
    return isl_printer_yaml_end_mapping(p);
2802
0
  }
2803
0
2804
0
  
if (0
sequence0
)
{0
2805
0
    p = isl_printer_yaml_start_sequence(p);
2806
0
  } else {
2807
0
    p = isl_printer_print_str(p, "child");
2808
0
    p = isl_printer_yaml_next(p);
2809
0
  }
2810
0
2811
0
  n = isl_schedule_tree_list_n_schedule_tree(tree->children);
2812
0
  for (i = 0; 
i < n0
;
++i0
)
{0
2813
0
    isl_schedule_tree *t;
2814
0
2815
0
    t = isl_schedule_tree_get_child(tree, i);
2816
0
    if (
n_ancestor > 0 && 0
child_pos[0] == i0
)
2817
0
      p = isl_printer_print_schedule_tree_mark(p, t,
2818
0
            n_ancestor - 1, child_pos + 1);
2819
0
    else
2820
0
      p = isl_printer_print_schedule_tree_mark(p, t,
2821
0
            -1, NULL);
2822
0
    isl_schedule_tree_free(t);
2823
0
2824
0
    p = isl_printer_yaml_next(p);
2825
0
  }
2826
0
2827
0
  if (sequence)
2828
0
    p = isl_printer_yaml_end_sequence(p);
2829
0
  p = isl_printer_yaml_end_mapping(p);
2830
0
2831
0
  return p;
2832
0
}
2833
2834
/* Print "tree" to "p".
2835
 */
2836
__isl_give isl_printer *isl_printer_print_schedule_tree(
2837
  __isl_take isl_printer *p, __isl_keep isl_schedule_tree *tree)
2838
0
{
2839
0
  return isl_printer_print_schedule_tree_mark(p, tree, -1, NULL);
2840
0
}
2841
2842
void isl_schedule_tree_dump(__isl_keep isl_schedule_tree *tree)
2843
0
{
2844
0
  isl_ctx *ctx;
2845
0
  isl_printer *printer;
2846
0
2847
0
  if (!tree)
2848
0
    return;
2849
0
2850
0
  ctx = isl_schedule_tree_get_ctx(tree);
2851
0
  printer = isl_printer_to_file(ctx, stderr);
2852
0
  printer = isl_printer_set_yaml_style(printer, ISL_YAML_STYLE_BLOCK);
2853
0
  printer = isl_printer_print_schedule_tree(printer, tree);
2854
0
2855
0
  isl_printer_free(printer);
2856
0
}