chromium/v8/src/compiler/turboshaft/uniform-reducer-adapter.h

// Copyright 2022 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef V8_COMPILER_TURBOSHAFT_UNIFORM_REDUCER_ADAPTER_H_
#define V8_COMPILER_TURBOSHAFT_UNIFORM_REDUCER_ADAPTER_H_

#include "src/compiler/turboshaft/operations.h"

namespace v8::internal::compiler::turboshaft {

// UniformReducerAdapter allows to handle all operations uniformly during a
// reduction by wiring all ReduceInputGraphXyz and ReduceXyz calls through
// a single ReduceInputGraphOperation and ReduceOperation, respectively.
//
// This is how to use the adapter with your reducer MyReducer, which can then
// be used in a ReducerStack like any other reducer):
//
// template <typename Next>
// class MyReducer : public UniformReducerAdapter<MyReducer, Next> {
//  public:
//   TURBOSHAFT_REDUCER_BOILERPLATE()
//   using Adapter = UniformReducerAdapter<MyReducer, Next>;
//
//   OpIndex ReduceInputGraphConstant(OpIndex ig_index, const ConstantOp& op) {
//     /* Handle ConstantOps separately */
//     /* ... */
//
//     /* Call Adapter::ReduceInputGraphConstant(index, op) to also run */
//     /* through the generic handling in ReduceInputGraphOperation */
//     return Next::ReduceInputGraphConstant(index, op);
//   }
//
//   template <typename Op, typename Continuation>
//   OpIndex ReduceInputGraphOperation(OpIndex ig_index, const Op& op) {
//     /* Handle all (other) operations uniformly */
//     /* ... */
//
//     /* Forward to next reducer using the Continuation object */
//     return Continuation{this}.ReduceInputGraph(ig_index, op);
//   }
//
//   OpIndex ReduceConstant(ConstantOp::Kind kind, ConstantOp::Storage st) {
//     /* Handle Constants separately */
//     /* ... */
//
//     /* Call Adapter::ReduceConstant(kind, st) to also run through the */
//     /* generic handling in ReduceOperation */
//     return Next::ReduceConstant(kind, st);
//   }
//
//   template <Opcode opcode, typename Continuation, typename... Args>
//   OpIndex ReduceOperation(Args... args) {
//     /* Handle all (other) operations uniformly */
//     /* ... */
//
//     /* Forward to next reducer using the Continuation object */
//     return Continuation{this}.Reduce(args...);
//   }
//
//  private:
//   /* ... */
// };
//
// NOTICE: Inside the ReduceXyz and ReduceInputGraphXyz callbacks of MyReducer,
// you need to make a choice:
//
//   A) Call Next::ReduceXyz (or Next::ReduceInputGraphXyz) to forward to the
//      next reducer in the stack. Then the uniform ReduceOperation (and
//      ReduceInputGraphOperation) of the current reducer is not visited for
//      OperationXyz.
//   B) Call Adapter::ReduceXyz (or Adapter::ReduceInputGraphXyz) to forward to
//      the uniform ReduceOperation (and ReduceInputGraphOperation) such that
//      OperationXyz is also processed by those (in addition to the special
//      handling in ReduceXyz and ReduceInputGraphXyz).
//
// For the above MyReducer, consider this CopyingPhase<R1, MyReducer, R2>.
// Then the ReduceInputGraph (RIG) and Reduce (R) implementations are visited as
// follows for Operations OpA and OpB (and all other operations that are not
// ConstantOp), when all reducers just forward to Next. For ConstantOp, the
// reduction is equivalent to any "normal" reducer that does not use a
// UniformReducerAdapter.
//
//
// InputGraph OpA                     OpB     ____________________________
//             |                       |     |  ___                       |
//             |                       |     | |   |                      |
//             v                       v     | |   v                      v
// R1        RIGOpA                  RIGOpB  | |  ROpA                   ROpB
//             |     __          __    |     | |   |    ___        ___    |
//             |    |  |        |  |   |     | |   |   |   |      |   |   |
//             |    |  v        v  |   |     | |   |   |   v      v   |   |
// MyReducer   |    | RIGOperation |   |     | |   |   |  ROperation  |   |
//             v    |      v       |   |     | |   v   |      v       |   v
// (Adapter) RIGOpA | Continuation | RIGOpB  | |  ROpA | Continuation |  ROpB
//             |____|  |        |  |___|     | |   |___|  |        |  |___|
//                     |        |            | |          |        |
//              _______|        |______      | |    ______|        |______
//             |                       |     | |   |                      |
//             |                       |     | |   |                      |
//             v                       v     | |   v                      v
// R2        RIGOpA                  RIGOpB  | |  ROpA                   ROpB
//             |                       |_____| |   |                      |
//             |_______________________________|   |                      |
//                                                 v                      v
// OutputGraph                                    OpA                    OpB
//
//
template <template <typename> typename Reducer, typename Next>
class UniformReducerAdapter : public Next {};

}  // namespace v8::internal::compiler::turboshaft

#endif  // V8_COMPILER_TURBOSHAFT_UNIFORM_REDUCER_ADAPTER_H_