@@ -243,7 +243,6 @@ isl::schedule_node extendChild(
243
243
* then recursively add nodes corresponding to the descendants of "root".
244
244
*/
245
245
isl::schedule toIslSchedule (const ScheduleTree* root) {
246
- checkValidIslSchedule (root);
247
246
auto domain = root->elemAs <ScheduleTreeElemDomain>();
248
247
CHECK (domain) << " Root node should be domain node" << *root;
249
248
auto node = isl::schedule_node::from_domain (domain->domain_ );
@@ -289,235 +288,6 @@ bool validateSchedule(isl::schedule sc) {
289
288
return validateSchedule (fromIslSchedule (sc).get ());
290
289
}
291
290
292
- namespace {
293
-
294
- // Get the parametric space in which the relation contained by the given tree
295
- // are defined.
296
- isl::space definitionParamSpace (const ScheduleTree* node) {
297
- auto space = isl::space (node->ctx_ , 0 );
298
- switch (node->type_ ) {
299
- // mapping_filter is a filter for ISL
300
- // TODO: this switch is too ISL-ish and is not meant for subtyping
301
- // extensions. Replace by if (node->elemAsBase<T>(...))
302
- case detail::ScheduleTreeType::MappingFilter:
303
- case detail::ScheduleTreeType::Filter: {
304
- auto filterNode = node->elemAsBase <ScheduleTreeElemFilter>();
305
- space = filterNode->filter_ .get_space ().params ();
306
- break ;
307
- }
308
- case detail::ScheduleTreeType::Band: {
309
- auto bandNode = node->elemAs <ScheduleTreeElemBand>();
310
- space = bandNode->mupa_ .get_space ().params ();
311
- break ;
312
- }
313
- case detail::ScheduleTreeType::Extension: {
314
- auto extensionNode = node->elemAs <ScheduleTreeElemExtension>();
315
- space = extensionNode->extension_ .get_space ().params ();
316
- break ;
317
- }
318
- case detail::ScheduleTreeType::Domain: {
319
- auto domainElem = node->elemAs <ScheduleTreeElemDomain>();
320
- space = domainElem->domain_ .get_space ().params ();
321
- break ;
322
- }
323
- case detail::ScheduleTreeType::Context: {
324
- auto contextElem = node->elemAs <ScheduleTreeElemContext>();
325
- space = contextElem->context_ .get_space ().params ();
326
- break ;
327
- }
328
-
329
- // Other types of nodes do not have any potentially parametric expression.
330
- case detail::ScheduleTreeType::Any:
331
- case detail::ScheduleTreeType::None:
332
- case detail::ScheduleTreeType::Set:
333
- case detail::ScheduleTreeType::Sequence:
334
- case detail::ScheduleTreeType::ThreadSpecificMarker:
335
- break ;
336
- }
337
- return space;
338
- }
339
-
340
- bool refersToUndefinedParameters (
341
- const ScheduleTree* relativeRoot,
342
- const ScheduleTree* node) {
343
- using namespace polyhedral ::detail;
344
-
345
- // Assuming no parameters are introduced above root.
346
- if (node == relativeRoot) {
347
- return false ;
348
- }
349
-
350
- // Domain and context can introduce new parameters.
351
- if (node->elemAs <ScheduleTreeElemDomain>() ||
352
- node->elemAs <ScheduleTreeElemContext>()) {
353
- return false ;
354
- }
355
-
356
- // Collect all ancestors that are allowed to introduce new parameters, i.e.
357
- // domain and context nodes. Collect the parameters they introduce in a
358
- // space.
359
- auto paramSpace = isl::null<isl::space>();
360
- for (auto anc : node->ancestors (relativeRoot)) {
361
- auto contextNode = anc->elemAs <ScheduleTreeElemContext>();
362
- auto domainNode = anc->elemAs <ScheduleTreeElemDomain>();
363
- if (!contextNode && !domainNode) {
364
- continue ;
365
- }
366
-
367
- auto space = contextNode ? contextNode->context_ .get_space ()
368
- : domainNode->domain_ .get_space ();
369
- space = space.params ();
370
- paramSpace = paramSpace.get () ? paramSpace.align_params (space) : space;
371
- }
372
-
373
- CHECK (paramSpace.get ()) << " no parent context or domain node found" ;
374
- if (!paramSpace.get ()) {
375
- return true ;
376
- }
377
-
378
- // The space in which tree's relations are defined should not involve
379
- // parameters that were not present in its domain or context ancestors. If
380
- // the tree has no relations, it cannot refer to undefined parameters.
381
- auto space = definitionParamSpace (node);
382
- if (space.dim (isl::dim_type::param) == 0 ) {
383
- return false ;
384
- }
385
-
386
- // If space uses some parameters that are not available in paramSpace,
387
- // they will be introduced into paramSpace, making its dimension larger.
388
- auto definedParams = paramSpace.dim (isl::dim_type::param);
389
- paramSpace = paramSpace.align_params (space);
390
- return paramSpace.dim (isl::dim_type::param) > definedParams;
391
- }
392
-
393
- // Note that this uses union_set as "optional" where nullptr value means
394
- // there's no actual value, rather than an error.
395
- isl::union_set nodeDomain (const ScheduleTree* node) {
396
- if (auto domainElem = node->elemAs <ScheduleTreeElemDomain>()) {
397
- return domainElem->domain_ ;
398
- } else if (auto bandElem = node->elemAs <ScheduleTreeElemBand>()) {
399
- return bandElem->mupa_ .domain ();
400
- } else if (auto filterElem = node->elemAsBase <ScheduleTreeElemFilter>()) {
401
- return filterElem->filter_ ;
402
- } else if (auto extensionElem = node->elemAs <ScheduleTreeElemExtension>()) {
403
- // FIXME: these are the points that are _introduced_... they are inactive
404
- // until now...
405
- // does the extension have a domain?
406
- return extensionElem->extension_
407
- .range (); // FIXME: do we need to restrict its domain first?
408
- }
409
- return isl::null<isl::union_set>();
410
- }
411
- } // namespace
412
-
413
- void checkValidIslSchedule (const ScheduleTree* root_) {
414
- using namespace polyhedral ::detail;
415
-
416
- // 1. The root node is always of type domain or extension.
417
- auto domainRoot = root_->elemAs <ScheduleTreeElemDomain>();
418
- auto extensionRoot = root_->elemAs <ScheduleTreeElemDomain>();
419
- CHECK (domainRoot || extensionRoot)
420
- << " root must be a domain or an extension" << *root_;
421
-
422
- for (auto node : ScheduleTree::collect (root_)) {
423
- auto activeInstances = activeDomainPoints (root_, node);
424
- auto nodeDomainPoints = nodeDomain (node);
425
-
426
- // 2. Only set or sequence nodes are allowed to have multiple children and
427
- // these children must be filter nodes.
428
- auto nodeIsSet = node->elemAs <ScheduleTreeElemSet>() != nullptr ;
429
- auto nodeIsSequence = node->elemAs <ScheduleTreeElemSequence>() != nullptr ;
430
- auto nChildren = node->numChildren ();
431
-
432
- // 4. Nodes should not refer to inactive domain points.
433
- if (nodeDomainPoints.get ()) {
434
- if (!nodeDomainPoints.is_subset (activeInstances)) {
435
- LOG_IF (WARNING, tc::FLAGS_schedule_tree_verbose_validation)
436
- << " node refers to inactive domain points: active "
437
- << activeInstances << " found: " << nodeDomainPoints << " in\n "
438
- << *node;
439
- }
440
- }
441
-
442
- if (!nodeIsSet && !nodeIsSequence) {
443
- CHECK_LE (nChildren, 1u )
444
- << " only sequence or set nodes can have multiple children" << *node;
445
- } else {
446
- auto filters = isl::null<isl::union_set>();
447
- for (auto child : node->children ()) {
448
- auto filterElem = child->elemAsBase <ScheduleTreeElemFilter>();
449
- auto childIsFilter = filterElem != nullptr ;
450
- CHECK (childIsFilter)
451
- << " only filter nodes allowed as children of sequence or set node"
452
- << *child;
453
-
454
- filters = filters.get () ? filters.unite (filterElem->filter_ )
455
- : filterElem->filter_ ;
456
- }
457
- CHECK (filters.get ()) << " set/sequence node must have at least one child"
458
- << *node;
459
-
460
- // 5. The union of filters must cover all active domain points.
461
- CHECK (activeInstances.is_subset (filters))
462
- << " filters must cover all active domain points; active "
463
- << activeInstances << " filtered: " << filters << " in\n "
464
- << *node;
465
- }
466
-
467
- // 3. Nodes should not refer to parameters that are not declared in context
468
- // nodes above.
469
- bool usesUndefinedParams = refersToUndefinedParameters (root_, node);
470
- CHECK (!usesUndefinedParams)
471
- << " non-context node introduces new parameters" << *node;
472
-
473
- // 7. Band schedules should be total on all active domain points.
474
- // Only check if an actual domain is specified.
475
- // In particular, 0D bands do not necessarily specify a domain.
476
- if (auto bandElem = node->elemAs <ScheduleTreeElemBand>()) {
477
- auto scheduleDefinitionDomain = bandElem->mupa_ .domain ();
478
- if (!scheduleDefinitionDomain.is_params ()) {
479
- CHECK (activeInstances.is_subset (scheduleDefinitionDomain))
480
- << " schedule should be total on the active domain points: active"
481
- << activeInstances
482
- << " schedule defined over: " << scheduleDefinitionDomain << " in\n "
483
- << *node;
484
- }
485
- }
486
-
487
- // 8. Extension nodes should not introduce any elements that are already
488
- // active domain elements.
489
- // 10. Anchored nodes match the flattened space of the outer bands.
490
- if (auto extensionElem = node->elemAs <ScheduleTreeElemExtension>()) {
491
- auto introducedInstances =
492
- extensionElem->extension_
493
- .range (); // FIXME: restrict domain to the partial schedule??
494
- CHECK (introducedInstances.intersect (activeInstances).is_empty ())
495
- << " extension node should not introduce elements that are already "
496
- " active domain elements: active "
497
- << activeInstances << " introduced: " << introducedInstances
498
- << " in\n "
499
- << *node;
500
- // FIXME: we probably want to check dim_ids for an exact match
501
- auto depth = node->scheduleDepth (root_);
502
- auto extension = extensionElem->extension_ ;
503
- for (auto const & e : isl::UnionAsVector<isl::union_map>(extension)) {
504
- CHECK_EQ (depth, e.dim (isl::dim_type::in))
505
- << " the input dimensionality of the extension map should "
506
- " correspond to the schedule depth"
507
- << *node;
508
- }
509
- }
510
-
511
- // 10. Anchored nodes match the flattened space of the outer bands.
512
- if (auto contextElem = node->elemAs <ScheduleTreeElemContext>()) {
513
- auto depth = node->scheduleDepth (root_);
514
- CHECK_EQ (depth, contextElem->context_ .dim (isl::dim_type::set))
515
- << " the dimensionality of the context should correspond "
516
- " to the schedule depth"
517
- << *node;
518
- }
519
- }
520
- }
521
291
} // namespace detail
522
292
} // namespace polyhedral
523
293
} // namespace tc
0 commit comments