torch/csrc/jit/passes/loop_unrolling.cpp
// XXX: This function can only be called with a loop that is guaranteed to execute EXACTLY ONCE.
This function can only be called with a loop that is guaranteed to execute EXACTLY ONCE.
This function can only be called with a loop that is guaranteed to execute EXACTLY ONCE .
void inlineBody(Node *loop) {
  auto graph = loop->owningGraph();
  auto body = loop->blocks().at(0);
  WithInsertPoint insert_point_guard { loop };
  std::unordered_map<Value*, Value*> value_map;
  auto get_value = [&](Value *v) {
    auto it = value_map.find(v);
    if (it != value_map.end())
      return it->second;
    return v;
  };
  for (size_t i = 2; i < loop->inputs().size(); ++i) {
    value_map[body->inputs()[i - 1]] = loop->inputs()[i];
  }
  for (Node *orig : body->nodes()) {
    Node *clone = graph->insertNode(graph->createClone(orig, get_value));
    for (size_t i = 0; i < orig->outputs().size(); ++i) {
      value_map[orig->outputs()[i]] = clone->outputs()[i];
    }
  }
  for (size_t i = 0; i < loop->outputs().size(); ++i) {
    loop->outputs().at(i)->replaceAllUsesWith(get_value(body->outputs().at(i + 1)));
  }
  loop->destroy();
}
void inlineBody ( Node * loop ) { auto graph = loop -> owningGraph ( ) ; auto body = loop -> blocks ( ) . at ( 0 ) ; WithInsertPoint insert_point_guard { loop } ; std :: unordered_map < Value * , Value * > value_map ; auto get_value = [ & ] ( Value * v ) { auto it = value_map . find ( v ) ; if ( it != value_map . end ( ) ) return it -> second ; return v ; } ; for ( size_t i = 2 ; i < loop -> inputs ( ) . size ( ) ; ++ i ) { value_map [ body -> inputs ( ) [ i - 1 ] ] = loop -> inputs ( ) [ i ] ; } for ( Node * orig : body -> nodes ( ) ) { Node * clone = graph -> insertNode ( graph -> createClone ( orig , get_value ) ) ; for ( size_t i = 0 ; i < orig -> outputs ( ) . size ( ) ; ++ i ) { value_map [ orig -> outputs ( ) [ i ] ] = clone -> outputs ( ) [ i ] ; } } for ( size_t i = 0 ; i < loop -> outputs ( ) . size ( ) ; ++ i ) { loop -> outputs ( ) . at ( i ) -> replaceAllUsesWith ( get_value ( body -> outputs ( ) . at ( i + 1 ) ) ) ; } loop -> destroy ( ) ; }
XXX: This function can only be called with a loop that is guaranteed to execute EXACTLY ONCE.
XXX : This function can only be called with a loop that is guaranteed to execute EXACTLY ONCE .
// Loop node has extra (max_iters, initial_cond) inputs, // body has an extra (loop_counter) input. // XXX: it is extremely important to destroy the loop in here. DCE might not be able // to conclude that it's safe, because the loop might contain side effects.