| 23 | namespace xla { |
| 24 | |
| 25 | StatusOr<std::vector<XlaOp>> WhileLoopHelper( |
| 26 | const WhileLoopHelperConditionFunction& condition_function, |
| 27 | const WhileLoopHelperBodyFunction& body_function, |
| 28 | absl::Span<const XlaOp> initial_values, absl::string_view name, |
| 29 | XlaBuilder* builder) { |
| 30 | int arity = initial_values.size(); |
| 31 | std::vector<Shape> var_shapes; |
| 32 | var_shapes.reserve(arity); |
| 33 | for (const XlaOp& input : initial_values) { |
| 34 | TF_ASSIGN_OR_RETURN(auto shape, builder->GetShape(input)); |
| 35 | var_shapes.push_back(std::move(shape)); |
| 36 | } |
| 37 | Shape tuple_shape = ShapeUtil::MakeTupleShape(var_shapes); |
| 38 | |
| 39 | // Unpacks a tuple into its component parts. |
| 40 | auto unpack_tuple = [](XlaOp tuple, int arity, XlaBuilder* builder) { |
| 41 | std::vector<XlaOp> elements(arity); |
| 42 | for (int i = 0; i < arity; ++i) { |
| 43 | elements[i] = GetTupleElement(tuple, i); |
| 44 | } |
| 45 | return elements; |
| 46 | }; |
| 47 | |
| 48 | // Build the condition. |
| 49 | std::unique_ptr<XlaBuilder> cond_builder = |
| 50 | builder->CreateSubBuilder(absl::StrCat(name, "_condition")); |
| 51 | { |
| 52 | auto parameter = Parameter(cond_builder.get(), 0, tuple_shape, "parameter"); |
| 53 | |
| 54 | TF_RETURN_IF_ERROR( |
| 55 | condition_function(unpack_tuple(parameter, arity, cond_builder.get()), |
| 56 | cond_builder.get()) |
| 57 | .status()); |
| 58 | } |
| 59 | TF_ASSIGN_OR_RETURN(auto cond, cond_builder->Build()); |
| 60 | |
| 61 | // Build the body. |
| 62 | std::unique_ptr<XlaBuilder> body_builder = |
| 63 | builder->CreateSubBuilder(absl::StrCat(name, "_body")); |
| 64 | { |
| 65 | auto parameter = Parameter(body_builder.get(), 0, tuple_shape, "parameter"); |
| 66 | |
| 67 | TF_ASSIGN_OR_RETURN( |
| 68 | auto result, |
| 69 | body_function(unpack_tuple(parameter, arity, body_builder.get()), |
| 70 | body_builder.get())); |
| 71 | |
| 72 | TF_RET_CHECK(result.size() == initial_values.size()); |
| 73 | Tuple(body_builder.get(), result); |
| 74 | } |
| 75 | TF_ASSIGN_OR_RETURN(auto body, body_builder->Build()); |
| 76 | |
| 77 | auto outputs = While(cond, body, Tuple(builder, initial_values)); |
| 78 | |
| 79 | return unpack_tuple(outputs, arity, builder); |
| 80 | } |
| 81 | |
| 82 | StatusOr<std::vector<XlaOp>> ForEachIndex( |
no test coverage detected