src/backends/cuda/cuda.cpp
// full access to memory + idx + optional vector idx
full access to memory + idx + optional vector idx
full access to memory + idx + optional vector idx
std::string gen_access(const LoopTree &lt, const Allocation &alloc,
                       LoopTree::TreeRef use, const UnrollMap &unroll,
                       int external_idx = -1) {
  std::stringstream ss;
  std::vector<LoopTree::Loop> parent_chain;
  auto parent = lt.parent(use);
  while (parent != -1) {
    parent_chain.emplace_back(lt.node(parent).loop);
    parent = lt.parent(parent);
  }
  std::reverse(parent_chain.begin(), parent_chain.end());
  auto order = parent_chain; 
  auto idx_vec = gen_idx_vector(lt, alloc, use);
  bool unrolled_vectorize = true;
  for (const auto &p : idx_vec) {
    unrolled_vectorize &= (p.second % 4 == 0);
    auto loop = order[p.first];
    std::pair<IR::VarRef, int> key = {loop.var, loop.var_depth};
    if (!unroll.count(key)) {
      break;
    }
  }
  bool vectorize = false;
  bool flatten = true; 
  if (alloc.size % 4 == 0) {
    if (unrolled_vectorize) {
      vectorize = true;
      flatten = false;
    } else {
      flatten = true;
    }
  }
  if (flatten) {
    ss << "((float*)";
  }
  if (external_idx > -1) { 
    ss << "ext_" << external_idx;
  } else {
    ss << "mem_" << alloc.idx;
  }
  if (flatten) {
    ss << ")";
  }
  bool innermost = true;
  std::string extra = "";
  ss << "[";
  for (const auto &p : idx_vec) {
    auto loop = order.at(p.first);
    auto size = p.second;
    if (!innermost && vectorize) {
      ASSERT(size % 4 == 0);
    }
    std::pair<IR::VarRef, int> key = {loop.var, loop.var_depth};
    if (unroll.count(key)) {
      ss << unroll.at(key) * size / (vectorize ? 4 : 1);
      if (innermost && vectorize) {
        extra = "." + (std::vector<std::string>(
                          {"x", "y", "z", "w"})[unroll.at(key) % 4]);
      }
    } else {
      auto s = (size / (vectorize ? 4 : 1));
      ss << lt.ir.var(loop.var).name() << "_" << loop.var_depth << " * " << s;
    }
    ss << " + ";
    if (innermost) {
      innermost = false;
    }
  }
  ss << "0"; 
  ss << "]" << extra;
  return ss.str();
}
std :: string gen_access ( const LoopTree & lt , const Allocation & alloc , LoopTree :: TreeRef use , const UnrollMap & unroll , int external_idx = -1 ) { std :: stringstream ss ; std :: vector < LoopTree :: Loop > parent_chain ; auto parent = lt . parent ( use ) ; while ( parent != -1 ) { parent_chain . emplace_back ( lt . node ( parent ) . loop ) ; parent = lt . parent ( parent ) ; } std :: reverse ( parent_chain . begin ( ) , parent_chain . end ( ) ) ; auto order = parent_chain ; auto idx_vec = gen_idx_vector ( lt , alloc , use ) ; bool unrolled_vectorize = true ; for ( const auto & p : idx_vec ) { unrolled_vectorize &= ( p . second % 4 == 0 ) ; auto loop = order [ p . first ] ; std :: pair < IR :: VarRef , int > key = { loop . var , loop . var_depth } ; if ( ! unroll . count ( key ) ) { break ; } } bool vectorize = false ; bool flatten = true ; if ( alloc . size % 4 == 0 ) { if ( unrolled_vectorize ) { vectorize = true ; flatten = false ; } else { flatten = true ; } } if ( flatten ) { ss << " " ; } if ( external_idx > -1 ) { ss << " " << external_idx ; } else { ss << " " << alloc . idx ; } if ( flatten ) { ss << " " ; } bool innermost = true ; std :: string extra = " " ; ss << " " ; for ( const auto & p : idx_vec ) { auto loop = order . at ( p . first ) ; auto size = p . second ; if ( ! innermost && vectorize ) { ASSERT ( size % 4 == 0 ) ; } std :: pair < IR :: VarRef , int > key = { loop . var , loop . var_depth } ; if ( unroll . count ( key ) ) { ss << unroll . at ( key ) * size / ( vectorize ? 4 : 1 ) ; if ( innermost && vectorize ) { extra = " " + ( std :: vector < std :: string > ( { " " , " " , " " , " " } ) [ unroll . at ( key ) % 4 ] ) ; } } else { auto s = ( size / ( vectorize ? 4 : 1 ) ) ; ss << lt . ir . var ( loop . var ) . name ( ) << " " << loop . var_depth << " " << s ; } ss << " " ; if ( innermost ) { innermost = false ; } } ss << " " ; ss << " " << extra ; return ss . str ( ) ; }
full access to memory + idx + optional vector idx
full access to memory + idx + optional vector idx
// lt.loop_order(lt.node(use).node); // can we map innermost dims to vector index? // this becomes false if non-innermost sizes cannot be vectorized (TODO relax) // cast from float4 to float // we can index directly into the vector // memory name // for reads/writes to real memory // memory index // keeps the expression well formed