// Copyright 2020 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

// clang-format off

// NOLINTNEXTLINE
// RUN: test-dot-prod -runtime-support=$(dirname %s)/runtime-support.so 2>&1 | IreeFileCheck %s

// clang-format on

#include "experimental/ModelBuilder/MemRefUtils.h"
#include "experimental/ModelBuilder/ModelBuilder.h"
#include "experimental/ModelBuilder/ModelRunner.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/InitLLVM.h"

using namespace mlir;                    // NOLINT
using namespace mlir::edsc;              // NOLINT
using namespace mlir::edsc::intrinsics;  // NOLINT

static llvm::cl::opt<std::string> runtimeSupport(
    "runtime-support", llvm::cl::desc("Runtime support library filename"),
    llvm::cl::value_desc("filename"), llvm::cl::init("-"));

void DotProdOnVectors() {
  constexpr unsigned N = 4;

  ModelBuilder modelBuilder;
  // Build a func "dot_prod".
  constexpr StringLiteral funcName = "dot-prod";
  auto f32 = modelBuilder.f32;
  auto vectorType = modelBuilder.getVectorType(N, f32);
  auto refType = modelBuilder.getMemRefType(1, vectorType);

  auto func = modelBuilder.makeFunction(funcName, {}, {refType, refType});

  SmallVector<AffineMap, 3> accesses;
  accesses.push_back(modelBuilder.getDimIdentityMap());
  accesses.push_back(accesses[0]);
  accesses.push_back(AffineMap::get(1, 0, modelBuilder.getContext()));

  SmallVector<Attribute, 1> iterator_types;
  iterator_types.push_back(modelBuilder.getStringAttr("reduction"));

  OpBuilder b(&func.getBody());
  ScopedContext scope(b, func.getLoc());
  Value A = func.getArgument(0), B = func.getArgument(1);
  Value idx_0 = std_constant_index(0);
  Value A_val = std_load(A, idx_0);
  Value B_val = std_load(B, idx_0);
  Value flt_0 = std_constant_float(APFloat(0.0f), f32);
  Value res_val = (vector_contract(A_val, B_val, flt_0,
                                   modelBuilder.getAffineMapArrayAttr(accesses),
                                   modelBuilder.getArrayAttr(iterator_types)));

  (vector_print(A_val));
  (vector_print(B_val));
  (vector_print(res_val));

  std_ret();

  // Compile the function, pass in runtime support library
  //    to the execution engine for vector.print.
  ModelRunner runner(modelBuilder.getModuleRef());
  runner.compile(CompilationOptions(), runtimeSupport);

  // initialize data by interoperating with the MLIR ABI by codegen.
  auto inputInit1 = [](unsigned idx, Vector1D<N, float> *ptr) {
    for (unsigned i = 0; i < N; ++i) ptr[idx][i] = 3.0 * i;
  };
  auto inputInit2 = [](unsigned idx, Vector1D<N, float> *ptr) {
    for (unsigned i = 0; i < N; ++i) ptr[idx][i] = 2.0 * i;
  };

  auto _A = makeInitializedStridedMemRefDescriptor<Vector1D<N, float>, 1>(
      {N}, inputInit1);
  auto _B = makeInitializedStridedMemRefDescriptor<Vector1D<N, float>, 1>(
      {N}, inputInit2);

  // Call the funcOp
  // CHECK: ( 0, 3, 6, 9 )
  // CHECK: ( 0, 2, 4, 6 )
  // CHECK: 84
  auto err = runner.invoke(funcName, _A, _B);

  if (err) llvm_unreachable("Error running function.");
}

int main(int argc, char **argv) {
  llvm::InitLLVM y(argc, argv);
  llvm::cl::ParseCommandLineOptions(argc, argv, "TestDotProd\n");
  DotProdOnVectors();
}
