tc/core/polyhedral/cuda/memory_promotion_heuristic.cc
/*
 * Check if the given "group" can be promoted to registers for the given active
 * domain points under full "schedule" where "nThreads" consecutive dimensions
 * are mapped to threads (the innermost of them being mapped to thread x) and
 * the depth of this mapping can be obtained from threadIdxXScheduleDepthState.
 *
 * In parciular, the group's footprint must contain only one element and the
 * same tensor element should never be accessed by two different threads.
 */


In parciular, the group's footprint must contain only one element and the
same tensor element should never be accessed by two different threads.
In parciular the group ' s footprint must contain only one element and the same tensor element should never be accessed by two different threads .
bool isPromotableToRegisterBelowThreads(
    const ThreadIdxXScheduleDepthState& threadIdxXScheduleDepthState,
    const TensorReferenceGroup& group,
    isl::union_map schedule,
    size_t nThreads,
    isl::union_set activePoints) {
  auto originalAccesses = group.originalAccesses();
  auto sizes = group.approximationSizes();
  auto nElements =
      std::accumulate(sizes.begin(), sizes.end(), 1, std::multiplies<size_t>());
  if (nElements != 1) {
    return false;
  }
  auto depth = 1 +
      computeThreadIdxXScheduleDepth(
                   threadIdxXScheduleDepthState,
                   originalAccesses.domain().intersect(activePoints));
  auto scheduledAccesses = originalAccesses.apply_domain(schedule);
  for (auto sa : isl::UnionAsVector<isl::union_map>(scheduledAccesses)) {
    sa = sa.project_out(
        isl::dim_type::in, depth, sa.dim(isl::dim_type::in) - depth);
    sa = fixOuterInputDimsAsParameters(sa, depth - nThreads);
    if (!sa.is_injective()) {
      return false;
    }
  }
  return true;
}
bool isPromotableToRegisterBelowThreads ( const ThreadIdxXScheduleDepthState & threadIdxXScheduleDepthState , const TensorReferenceGroup & group , isl :: union_map schedule , size_t nThreads , isl :: union_set activePoints ) { auto originalAccesses = group . originalAccesses ( ) ; auto sizes = group . approximationSizes ( ) ; auto nElements = std :: accumulate ( sizes . begin ( ) , sizes . end ( ) , 1 , std :: multiplies < size_t > ( ) ) ; if ( nElements != 1 ) { return false ; } auto depth = 1 + computeThreadIdxXScheduleDepth ( threadIdxXScheduleDepthState , originalAccesses . domain ( ) . intersect ( activePoints ) ) ; auto scheduledAccesses = originalAccesses . apply_domain ( schedule ) ; for ( auto sa : isl :: UnionAsVector < isl :: union_map > ( scheduledAccesses ) ) { sa = sa . project_out ( isl :: dim_type :: in , depth , sa . dim ( isl :: dim_type :: in ) - depth ) ; sa = fixOuterInputDimsAsParameters ( sa , depth - nThreads ) ; if ( ! sa . is_injective ( ) ) { return false ; } } return true ; }
Check if the given "group" can be promoted to registers for the given active
 domain points under full "schedule" where "nThreads" consecutive dimensions
 are mapped to threads (the innermost of them being mapped to thread x) and
 the depth of this mapping can be obtained from threadIdxXScheduleDepthState.
Check if the given " group " can be promoted to registers for the given active domain points under full " schedule " where " nThreads " consecutive dimensions are mapped to threads ( the innermost of them being mapped to thread x ) and the depth of this mapping can be obtained from threadIdxXScheduleDepthState .
// Return early if more than one element needs to be stored in registers. // TODO: support arrays in registers if they are only accessed with constant // subscripts, e.g. if the inner loops are fully unrolled. // Since this function is only supposed to be called on groups seen _below_ // thread mapping, all refs in the group must all have the same thread-x // depth. // Scheduled accesses contain maps from schedule dimensions to tensor // subscripts.  Compute the relation that between the schedule dimensions // mapped to threads and tensor subscripts by first removing dimensions // following the one mapped to thread x (last one assuming inverse mapping // order), then by equating all dimensions not mapped to threads to // parameters.  Promotion to registers is only allowed if the resulting // relation is injective, i.e. the same tensor element is never accessed by // more than one thread.  Note that our current check is overly conservative // because different values of schedule dimension may get mapped to the same // thread, in which case the could access the same tensor element.