//===- ACCAtomicPatterns.cpp - ACC atomic to LLVM patterns ------*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// Lowers OpenACC atomic operations (read, write, update, capture) to LLVM
// dialect atomicrmw / cmpxchg sequences.
//
//===----------------------------------------------------------------------===//

#include "mlir/Conversion/OpenACCToLLVM/ACCToLLVM.h"

#include "mlir/Conversion/LLVMCommon/Pattern.h"
#include "mlir/Dialect/Arith/IR/Arith.h"
#include "mlir/Dialect/Complex/IR/Complex.h"
#include "mlir/Dialect/LLVMIR/LLVMDialect.h"
#include "mlir/Dialect/MemRef/IR/MemRef.h"
#include "mlir/Dialect/OpenACC/Analysis/OpenACCSupport.h"
#include "mlir/Dialect/OpenACC/OpenACC.h"
#include "mlir/Dialect/OpenACC/OpenACCUtilsType.h"
#include "mlir/IR/BuiltinOps.h"
#include "mlir/Interfaces/SideEffectInterfaces.h"
#include "llvm/ADT/TypeSwitch.h"
#include "llvm/Support/Debug.h"

#include <cstdint>
#include <optional>
#include <set>
#include <utility>

#define DEBUG_TYPE "acc-atomic-patterns"

using namespace mlir;
using namespace mlir::acc;

namespace {

constexpr uint64_t kBitsInByte = 8;

template <typename AtomicOpTy>
class ACCAtomicOpConversion : public ConvertOpToLLVMPattern<AtomicOpTy> {
  using typename ConvertOpToLLVMPattern<AtomicOpTy>::OpAdaptor;

public:
  ACCAtomicOpConversion(const LLVMTypeConverter &typeConverter,
                        OpenACCSupport &accSupport,
                        const ACCAtomicLoadAddressCallback &getLoadAddress)
      : ConvertOpToLLVMPattern<AtomicOpTy>(typeConverter),
        accSupport(accSupport), getLoadAddress(getLoadAddress) {}

  LogicalResult
  matchAndRewrite(AtomicOpTy op, OpAdaptor adaptor,
                  ConversionPatternRewriter &rewriter) const override;

private:
  OpenACCSupport &accSupport;
  ACCAtomicLoadAddressCallback getLoadAddress;

  size_t getComplexStructElementSizeInBits(Type ty) const {
    auto structType = dyn_cast<LLVM::LLVMStructType>(ty);
    if (!structType || structType.getBody().size() != 2 ||
        structType.getBody()[0] != structType.getBody()[1] ||
        !structType.getBody()[0].isIntOrFloat())
      return 0;
    size_t elementSizeInBits = structType.getBody()[0].getIntOrFloatBitWidth();
    if (elementSizeInBits == 0 || elementSizeInBits > 64)
      llvm_unreachable("unexpected complex type");
    return elementSizeInBits;
  }

  /// Serialize a complex value into an integer.
  Value serializeExpr(Value expr, ConversionPatternRewriter &rewriter) const {
    size_t elementSizeInBits =
        getComplexStructElementSizeInBits(expr.getType());
    if (!elementSizeInBits)
      return expr;

    Location loc = expr.getLoc();
    Value firstValue = LLVM::ExtractValueOp::create(rewriter, loc, expr, 0);
    Value secondValue = LLVM::ExtractValueOp::create(rewriter, loc, expr, 1);
    MLIRContext *context = rewriter.getContext();
    Type intCastTy = IntegerType::get(context, elementSizeInBits);
    Type intTy = IntegerType::get(context, elementSizeInBits * 2);
    firstValue = LLVM::BitcastOp::create(rewriter, loc, intCastTy, firstValue);
    secondValue =
        LLVM::BitcastOp::create(rewriter, loc, intCastTy, secondValue);
    firstValue = LLVM::ZExtOp::create(rewriter, loc, intTy, firstValue);
    secondValue = LLVM::ZExtOp::create(rewriter, loc, intTy, secondValue);
    Value shlVal =
        LLVM::ConstantOp::create(rewriter, loc, intTy, elementSizeInBits);
    Value result = LLVM::ShlOp::create(rewriter, loc, secondValue, shlVal);
    return LLVM::OrOp::create(rewriter, loc, result, firstValue);
  }

  /// Deserialize an integer into a complex value.
  Value deserializeExpr(Value expr, Type origTy,
                        ConversionPatternRewriter &rewriter) const {
    size_t elementSizeInBits = getComplexStructElementSizeInBits(origTy);
    if (!elementSizeInBits)
      return expr;

    auto intTy = dyn_cast<IntegerType>(expr.getType());
    if (!intTy || intTy.getWidth() != elementSizeInBits * 2)
      return expr;

    Location loc = expr.getLoc();
    MLIRContext *context = rewriter.getContext();
    Type elemTy = IntegerType::get(context, elementSizeInBits);
    Value low = LLVM::TruncOp::create(rewriter, loc, elemTy, expr);
    Value shiftAmount =
        LLVM::ConstantOp::create(rewriter, loc, intTy, elementSizeInBits);
    Value highFull = LLVM::LShrOp::create(rewriter, loc, expr, shiftAmount);
    Value high = LLVM::TruncOp::create(rewriter, loc, elemTy, highFull);
    Type origElemTy = cast<LLVM::LLVMStructType>(origTy).getBody()[0];
    if (origElemTy != elemTy) {
      low = LLVM::BitcastOp::create(rewriter, loc, origElemTy, low);
      high = LLVM::BitcastOp::create(rewriter, loc, origElemTy, high);
    }
    Value undefStruct = LLVM::UndefOp::create(rewriter, loc, origTy);
    Value structWithLow = LLVM::InsertValueOp::create(
        rewriter, loc, origTy, undefStruct, low, ArrayRef<int64_t>{0});
    return LLVM::InsertValueOp::create(rewriter, loc, origTy, structWithLow,
                                       high, ArrayRef<int64_t>{1});
  }

  uint64_t getAtomicSizeInBytes(Type originalTy, Type convertedTy,
                                ModuleOp module) const {
    std::optional<TypeSizeAndAlignment> sizeAndAlignment =
        acc::getTypeSizeAndAlignment(originalTy, module, &accSupport);
    if (!sizeAndAlignment)
      sizeAndAlignment =
          acc::getTypeSizeAndAlignment(convertedTy, module, &accSupport);
    assert(sizeAndAlignment && "atomic type size is not computable");
    return sizeAndAlignment->first.getFixedValue();
  }

  Type getAtomicType(Type originalTy, Type convertedTy, ModuleOp module) const {
    if (convertedTy.isIntOrFloat())
      return convertedTy;
    return IntegerType::get(
        convertedTy.getContext(),
        getAtomicSizeInBytes(originalTy, convertedTy, module) * kBitsInByte);
  }

  Type getReferencedElementType(Value ref, ModuleOp module = nullptr) const {
    auto ptr = dyn_cast<PointerLikeType>(ref.getType());
    if (!ptr)
      llvm_unreachable("unexpected type");
    Type elementTy = ptr.getElementType();
    Type convertedTy = this->getTypeConverter()->convertType(elementTy);
    if (module)
      return getAtomicType(elementTy, convertedTy, module);
    return convertedTy;
  }

  /// Memrefs are converted to descriptors rather than bare pointers, so the
  /// element pointer must be recomputed from the descriptor.
  Value getAtomicPointer(Value originalRef, Value convertedPtr, Location loc,
                         ConversionPatternRewriter &rewriter) const {
    auto memrefTy = dyn_cast<MemRefType>(originalRef.getType());
    if (!memrefTy)
      return convertedPtr;

    // Extract aligned base pointer (index 1) and offset (index 2).
    Value alignedPtr =
        LLVM::ExtractValueOp::create(rewriter, loc, convertedPtr, 1);
    Value offset = LLVM::ExtractValueOp::create(rewriter, loc, convertedPtr, 2);
    Type elemPtrType = LLVM::LLVMPointerType::get(rewriter.getContext());
    return LLVM::GEPOp::create(
        rewriter, loc, elemPtrType,
        this->getTypeConverter()->convertType(memrefTy.getElementType()),
        alignedPtr, offset);
  }

  Block *constructCmpxchgLoop(Value ptr, Type type, Value expr,
                              ConversionPatternRewriter &rewriter) const;

  /// Emit a single atomicrmw for a `x = x <binop> expr` capture, or fail so
  /// the caller falls back to the cmpxchg loop.
  LogicalResult
  tryEmitCaptureAtomicRMW(AtomicCaptureOp capture, AtomicUpdateOp update,
                          AtomicReadOp read,
                          ConversionPatternRewriter &rewriter) const;

  Value genUpdateCmpxchgLoop(AtomicUpdateOp update,
                             ConversionPatternRewriter &rewriter) const;
};

template <>
LogicalResult ACCAtomicOpConversion<AtomicReadOp>::matchAndRewrite(
    AtomicReadOp read, OpAdaptor adaptor,
    ConversionPatternRewriter &rewriter) const {
  Location loc = read.getLoc();
  Value xRef = read.getX();
  Value xPtr = getAtomicPointer(xRef, adaptor.getX(), loc, rewriter);
  ModuleOp mod = read->getParentOfType<ModuleOp>();
  Type xType = getReferencedElementType(xRef, mod);

  auto ordering = LLVM::AtomicOrdering::monotonic;
  Value storeVal;
  if (xType.isSignlessInteger()) {
    Value zero = LLVM::ConstantOp::create(rewriter, loc, xType, 0);
    storeVal = LLVM::AtomicRMWOp::create(rewriter, loc, LLVM::AtomicBinOp::_or,
                                         xPtr, zero, ordering);
  } else {
    unsigned bitWidth = xType.getIntOrFloatBitWidth();
    Type intType = IntegerType::get(rewriter.getContext(), bitWidth);
    Value zero = LLVM::ConstantOp::create(rewriter, loc, intType, 0);
    Value intVal = LLVM::AtomicRMWOp::create(
        rewriter, loc, LLVM::AtomicBinOp::_or, xPtr, zero, ordering);
    storeVal = LLVM::BitcastOp::create(rewriter, loc, xType, intVal);
  }

  Value vRef = read.getV();
  Value vPtr = getAtomicPointer(vRef, adaptor.getV(), loc, rewriter);
  Type vType = getReferencedElementType(vRef, mod);

  if (xType != vType) {
    // Convert `x` if the types do not match.
    auto vPtrType = cast<PointerLikeType>(vRef.getType());
    storeVal = vPtrType.genCast(rewriter, loc, storeVal, vType);
    if (!storeVal) {
      return rewriter.notifyMatchFailure(
          read, "failed to convert the loaded value to the destination type");
    }
  }
  auto storeOp = LLVM::StoreOp::create(rewriter, loc, storeVal, vPtr);
  rewriter.replaceOp(read, storeOp);
  return success();
}

template <>
LogicalResult ACCAtomicOpConversion<AtomicWriteOp>::matchAndRewrite(
    AtomicWriteOp write, OpAdaptor adaptor,
    ConversionPatternRewriter &rewriter) const {
  Location loc = write.getLoc();
  Value expr = serializeExpr(adaptor.getExpr(), rewriter);
  Value xRef = write.getX();
  Value xPtr = getAtomicPointer(xRef, adaptor.getX(), loc, rewriter);
  ModuleOp mod = write->getParentOfType<ModuleOp>();
  Type xType = getReferencedElementType(xRef, mod);

  auto ordering = LLVM::AtomicOrdering::monotonic;
  if (!xType.isSignlessInteger()) {
    unsigned bitWidth = xType.getIntOrFloatBitWidth();
    Type intType = IntegerType::get(rewriter.getContext(), bitWidth);
    expr = LLVM::BitcastOp::create(rewriter, loc, intType, expr);
  }
  LLVM::AtomicRMWOp::create(rewriter, loc, LLVM::AtomicBinOp::xchg, xPtr, expr,
                            ordering);
  rewriter.eraseOp(write);
  return success();
}

// Generate a cmpxchg loop based on the GenericAtomicRMWOpLowering algorithm.
template <typename AtomicOpTy>
Block *ACCAtomicOpConversion<AtomicOpTy>::constructCmpxchgLoop(
    Value ptr, Type type, Value expr,
    ConversionPatternRewriter &rewriter) const {
  // Split the block into initial, loop, and ending parts.
  Location loc = rewriter.getInsertionPoint()->getLoc();
  Block *initBlock = rewriter.getInsertionBlock();
  Block *loopBlock =
      rewriter.splitBlock(initBlock, rewriter.getInsertionPoint());
  loopBlock->addArgument(type, loc);
  Block *endBlock =
      rewriter.splitBlock(loopBlock, rewriter.getInsertionPoint());

  // Compute the loaded value and branch to the loop block.
  rewriter.setInsertionPointToEnd(initBlock);
  Value init = LLVM::LoadOp::create(rewriter, loc, type, ptr);
  LLVM::BrOp::create(rewriter, loc, init, loopBlock);

  // Prepare the body of the loop block.
  rewriter.setInsertionPointToStart(loopBlock);

  Value loopArgument = loopBlock->getArgument(0);
  Value result = serializeExpr(rewriter.getRemappedValue(expr), rewriter);
  ModuleOp mod = initBlock->getParent()->getParentOfType<ModuleOp>();
  Type convertedExprType =
      this->getTypeConverter()->convertType(expr.getType());
  Type exprType = getAtomicType(expr.getType(), convertedExprType, mod);

  // Cast to an integer type.
  if (!exprType.isSignlessInteger()) {
    Type tmpType = IntegerType::get(
        rewriter.getContext(),
        getAtomicSizeInBytes(expr.getType(), convertedExprType, mod) *
            kBitsInByte);
    result = LLVM::BitcastOp::create(rewriter, loc, tmpType, result);
    loopArgument =
        LLVM::BitcastOp::create(rewriter, loc, tmpType, loopArgument);
  }

  // Prepare the epilog of the loop block.
  // Append the cmpxchg op to the end of the loop block.
  auto successOrdering = LLVM::AtomicOrdering::acq_rel;
  auto failureOrdering = LLVM::AtomicOrdering::monotonic;
  auto cmpxchg =
      LLVM::AtomicCmpXchgOp::create(rewriter, loc, ptr, loopArgument, result,
                                    successOrdering, failureOrdering);
  // Extract the %new_loaded and %ok values from the pair.
  Value newLoaded = LLVM::ExtractValueOp::create(rewriter, loc, cmpxchg, 0);
  Value ok = LLVM::ExtractValueOp::create(rewriter, loc, cmpxchg, 1);

  // Cast back to the original type.
  if (!exprType.isSignlessInteger())
    newLoaded = LLVM::BitcastOp::create(rewriter, loc, exprType, newLoaded);

  // Conditionally branch to the end or back to the loop depending on %ok.
  LLVM::CondBrOp::create(rewriter, loc, ok, endBlock, ArrayRef<Value>(),
                         loopBlock, newLoaded);

  return loopBlock;
}

static Value skipUnrealizedConversionOp(Value v) {
  if (auto convOp =
          dyn_cast_or_null<UnrealizedConversionCastOp>(v.getDefiningOp()))
    return skipUnrealizedConversionOp(convOp.getOperand(0));
  return v;
}

/// Obtain the foremost value of addr to indicate the origin of the storage.
static Value getBaseStorage(Value addr, ConversionPatternRewriter &rewriter) {
  Operation *op = skipUnrealizedConversionOp(addr).getDefiningOp();
  if (auto gepOp = dyn_cast_or_null<LLVM::GEPOp>(op)) {
    addr = gepOp.getBase();
    op = addr.getDefiningOp();
  }
  if (auto extractOp = dyn_cast_or_null<LLVM::ExtractValueOp>(op)) {
    // addr is in a struct. Get the inserted value corresponding to the
    // extraction.
    ArrayRef extractingPosition = extractOp.getPosition();
    Value container = skipUnrealizedConversionOp(extractOp.getContainer());
    Value remappedContainer = rewriter.getRemappedValue(container);
    op = remappedContainer ? remappedContainer.getDefiningOp() : nullptr;
    bool inserted = false;
    while (auto insertValueOp = dyn_cast_or_null<LLVM::InsertValueOp>(op)) {
      ArrayRef insertingPosition = insertValueOp.getPosition();
      if (insertingPosition == extractingPosition) {
        addr = insertValueOp.getValue();
        inserted = true;
        break;
      }
      op = insertValueOp.getContainer().getDefiningOp();
    }
    // The aggregate holding addr is not built by insertions, so the value it
    // is converted from identifies the storage.
    if (!inserted)
      addr = container;
  }
  // op might be alloca already, or addr might be an argument.
  return skipUnrealizedConversionOp(addr);
}

/// Include flow dependency (v -> expr) in the generated loop of
/// `{ atomic.read, atomic.write/update }`.
static void moveDependency(Value vRef, Value vPtr, Value expr,
                           Value loopArgument, Operation &loopHead,
                           ConversionPatternRewriter &rewriter,
                           const ACCAtomicLoadAddressCallback &getLoadAddress) {
  Value vStorage = getBaseStorage(vPtr, rewriter);
  // A dependency may be reached before it is itself converted, in which case
  // its address is still expressed in terms of `vRef`.
  Value vStorageRef = skipUnrealizedConversionOp(vRef);
  LLVM_DEBUG({
    llvm::dbgs() << "[acc-atomic] moveDependency\n";
    llvm::dbgs() << "  vPtr        = " << vPtr << "\n";
    llvm::dbgs() << "  vStorage    = " << vStorage << "\n";
    llvm::dbgs() << "  vStorageRef = " << vStorageRef << "\n";
    llvm::dbgs() << "  expr        = " << expr << "\n";
  });
  llvm::DenseMap<Value, Value> remappedToOriginal;
  std::set<std::pair<Operation *, std::set<Operation *>>> worklist;
  std::set<Operation *> included;
  Value mappedExpr = rewriter.getRemappedValue(expr);
  remappedToOriginal[mappedExpr] = expr;
  if (Operation *exprDef = mappedExpr.getDefiningOp())
    worklist.insert(std::pair{exprDef, std::set<Operation *>{}});

  while (!worklist.empty()) {
    auto [dep, post] = worklist.extract(worklist.begin()).value();
    if (!dep)
      continue;
    LLVM_DEBUG(llvm::dbgs() << "  visit dep   = " << *dep << "\n");
    if (vPtr.getDefiningOp() &&
        !vPtr.getDefiningOp()->getParentOp()->isAncestor(dep)) {
      // Outside the parental region. No load found in this flow.
      LLVM_DEBUG(llvm::dbgs() << "    -> skipped: not in parental region\n");
      continue;
    }

    Value addr;
    if (auto load = dyn_cast<LLVM::LoadOp>(dep)) {
      addr = load.getAddr();
    } else if (auto load = dyn_cast<memref::LoadOp>(dep)) {
      addr = load.getMemref();
    } else if (getLoadAddress) {
      addr = getLoadAddress(dep);
    }
    if (addr) {
      Value baseStorage = getBaseStorage(addr, rewriter);
      LLVM_DEBUG({
        llvm::dbgs() << "    addr        = " << addr << "\n";
        llvm::dbgs() << "    baseStorage = " << baseStorage << "\n";
        llvm::dbgs() << "    remapped    = "
                     << rewriter.getRemappedValue(baseStorage) << "\n";
        llvm::dbgs() << "    matchRef=" << (baseStorage == vStorageRef)
                     << " matchConv="
                     << (rewriter.getRemappedValue(baseStorage) == vStorage)
                     << "\n";
      });
      if (baseStorage == vStorageRef ||
          rewriter.getRemappedValue(baseStorage) == vStorage) {
        // Found the load of `v`. Include this flow in dependency.
        Value load = dep->getResult(0);
        auto replaceUses = [&](Operation *op) {
          rewriter.modifyOpInPlace(op, [&] {
            op->replaceUsesOfWith(remappedToOriginal[load], loopArgument);
          });
        };
        for (Operation *p : post)
          replaceUses(p);
        replaceUses(&loopHead);
        included.insert(post.begin(), post.end());
      }
      continue;
    }
    post.insert(dep);
    for (Value operand : dep->getOperands()) {
      Value mappedOperand = rewriter.getRemappedValue(operand);
      if (auto *d = mappedOperand.getDefiningOp()) {
        if (dep == d) {
          if (auto *op = operand.getDefiningOp()) {
            remappedToOriginal[op->getResult(0)] = operand;
            worklist.insert(std::pair{op, post});
          }
        } else {
          remappedToOriginal[mappedOperand] = operand;
          worklist.insert(std::pair{d, post});
        }
      }
    }
  }

  // Include dependency.
  SmallVector<Operation *> includedInOrder;
  vPtr.getParentRegion()->walk([&](Operation *op) {
    if (included.find(op) != included.end())
      includedInOrder.push_back(op);
  });
  for (Operation *d : includedInOrder)
    d->moveBefore(&loopHead);
}

/// Generate a cmpxchg loop for update and return a stored value.
template <typename AtomicOpTy>
Value ACCAtomicOpConversion<AtomicOpTy>::genUpdateCmpxchgLoop(
    AtomicUpdateOp update, ConversionPatternRewriter &rewriter) const {
  Location loc = update.getLoc();
  Value xRef = update.getX();
  Value xPtr =
      getAtomicPointer(xRef, rewriter.getRemappedValue(xRef), loc, rewriter);
  ModuleOp mod = update->getParentOfType<ModuleOp>();
  Type xType = getReferencedElementType(xRef, mod);
  Type xTypeOrig = getReferencedElementType(xRef);

  Block &updateBlock = update.getRegion().front();
  Value updateArgument = updateBlock.getArgument(0);
  Operation *terminator = updateBlock.getTerminator();
  Value expr = terminator->getOperand(0);

  Block *loopBlock = constructCmpxchgLoop(xPtr, xType, expr, rewriter);
  Value loopArgument = loopBlock->getArgument(0);
  Operation &loopHead = loopBlock->front();

  rewriter.setInsertionPointToStart(loopBlock);
  loopArgument = deserializeExpr(loopArgument, xTypeOrig, rewriter);

  // Move in and out flow dependency (x -> expr). Some computation might be
  // outside atomic regions.
  moveDependency(xRef, xPtr, expr, loopArgument, loopHead, rewriter,
                 getLoadAddress);
  // Move out the residue.
  rewriter.replaceAllUsesWith(cast<BlockArgument>(updateArgument),
                              {loopArgument});

  updateBlock.walk([&](Operation *op) {
    if (!op->hasTrait<OpTrait::IsTerminator>())
      rewriter.moveOpBefore(op, &loopHead);
  });

  if (auto cmpxchg = dyn_cast<LLVM::AtomicCmpXchgOp>(loopHead))
    return cmpxchg.getVal();
  if (auto bitcast = dyn_cast<LLVM::BitcastOp>(loopHead))
    // Handling a non-integer type.
    return bitcast.getArg();
  if (auto extract = dyn_cast<LLVM::ExtractValueOp>(loopHead))
    // Handling a complex type.
    return extract.getContainer();
  llvm_unreachable("invalid cmpxchg loop");
}

static std::optional<LLVM::AtomicBinOp> getAtomicBinOp(Operation *op,
                                                       bool updateIsLhs) {
  return TypeSwitch<Operation *, std::optional<LLVM::AtomicBinOp>>(op)
      .Case<arith::AddFOp>([](auto) { return LLVM::AtomicBinOp::fadd; })
      .Case<arith::AddIOp>([](auto) { return LLVM::AtomicBinOp::add; })
      .Case<arith::SubFOp>(
          [updateIsLhs](auto) -> std::optional<LLVM::AtomicBinOp> {
            // atomicrmw fsub is always `*ptr = *ptr - val`.
            if (!updateIsLhs)
              return std::nullopt;
            return LLVM::AtomicBinOp::fsub;
          })
      .Case<arith::SubIOp>(
          [updateIsLhs](auto) -> std::optional<LLVM::AtomicBinOp> {
            // atomicrmw sub is always `*ptr = *ptr - val`.
            if (!updateIsLhs)
              return std::nullopt;
            return LLVM::AtomicBinOp::sub;
          })
      .Case<arith::AndIOp>([](auto) { return LLVM::AtomicBinOp::_and; })
      .Case<arith::OrIOp>([](auto) { return LLVM::AtomicBinOp::_or; })
      .Case<arith::XOrIOp>([](auto) { return LLVM::AtomicBinOp::_xor; })
      .Case<arith::MaxSIOp>([](auto) { return LLVM::AtomicBinOp::max; })
      .Case<arith::MinSIOp>([](auto) { return LLVM::AtomicBinOp::min; })
      .Case<arith::MaxUIOp>([](auto) { return LLVM::AtomicBinOp::umax; })
      .Case<arith::MinUIOp>([](auto) { return LLVM::AtomicBinOp::umin; })
      .Case<arith::MaximumFOp>([](auto) { return LLVM::AtomicBinOp::fmaximum; })
      .Case<arith::MinimumFOp>([](auto) { return LLVM::AtomicBinOp::fminimum; })
      .Case<arith::MaxNumFOp>(
          [](auto) { return LLVM::AtomicBinOp::fmaximumnum; })
      .Case<arith::MinNumFOp>(
          [](auto) { return LLVM::AtomicBinOp::fminimumnum; })
      .Default([](Operation *) { return std::nullopt; });
}

/// Match an update region computing `x = x <binop> expr`, and return the
/// atomicrmw kind with the binary operation. Shared by the update and capture
/// conversions so the same region cannot take atomicrmw in one and the cmpxchg
/// loop in the other.
static std::optional<std::pair<LLVM::AtomicBinOp, Operation *>>
matchAtomicBinOpUpdate(AtomicUpdateOp update) {
  Block &block = update.getRegion().front();
  Value arg = block.getArgument(0);
  Operation *yield = block.getTerminator();
  if (!yield || yield->getNumOperands() != 1)
    return std::nullopt;
  Operation *binOp = yield->getOperand(0).getDefiningOp();
  if (!binOp || binOp->getBlock() != &block || binOp->getNumOperands() != 2 ||
      binOp->getNumResults() != 1)
    return std::nullopt;
  // The updated value has to feed the binop and nothing else.
  if (!arg.hasOneUse() || arg.use_begin()->getOwner() != binOp)
    return std::nullopt;
  bool updateIsLhs = binOp->getOperand(0) == arg;
  std::optional<LLVM::AtomicBinOp> kind = getAtomicBinOp(binOp, updateIsLhs);
  if (!kind)
    return std::nullopt;
  return std::make_pair(*kind, binOp);
}

/// Generate llvm.atomicrmw or an llvm.cmpxchg loop.
template <>
LogicalResult ACCAtomicOpConversion<AtomicUpdateOp>::matchAndRewrite(
    AtomicUpdateOp update, OpAdaptor adaptor,
    ConversionPatternRewriter &rewriter) const {
  Block &updateBlock = update.getRegion().front();
  Value updateArgument = updateBlock.getArgument(0);

  // Collect operations that depend on the update argument.
  std::set<Operation *> dependents;
  SmallVector<Value> worklist;
  worklist.push_back(updateArgument);
  while (!worklist.empty()) {
    Value value = worklist.back();
    worklist.pop_back();
    for (OpOperand &use : value.getUses()) {
      Operation *useOp = use.getOwner();
      dependents.insert(useOp);
      if (useOp->getNumResults() == 1)
        worklist.push_back(useOp->getResult(0));
    }
  }

  // Move independent operations out of the update block.
  SmallVector<Operation *> independent;
  for (Operation &op : updateBlock.getOperations()) {
    if (dependents.find(&op) == dependents.end()) {
      if (op.hasTrait<OpTrait::IsTerminator>())
        llvm_unreachable("invalid update operation");
      independent.push_back(&op);
    }
  }
  for (Operation *op : independent)
    rewriter.moveOpBefore(op, update);

  // Map arith op to atomicrmw kind.
  //
  // In the current version of LLVM, these are the equivalences for float
  // min/max across the different instructions intrinsics and operations -
  // confusingly they have slightly different and not very descriptive names.
  //
  // | MLIR       | atomicrmw inst | llvm intrinsic    |
  // |------------+----------------+-------------------|
  // | -          | fmax           | llvm.maxnum.*     |
  // | MaximumFOp | fmaximum       | llvm.maximum.*    |
  // | MaxNumFOp  | fmaximumnum    | llvm.maximumnum.* |
  //
  // Sources:
  // https://llvm.org/docs/LangRef.html#id236
  // https://llvm.org/docs/LangRef.html#floating-point-min-max-intrinsics-comparison
  // https://mlir.llvm.org/docs/Dialects/ArithOps/#arithmaximumf-arithmaximumfop
  // https://mlir.llvm.org/docs/Dialects/ArithOps/#arithmaxnumf-arithmaxnumfop

  // Select the kind and the val of atomicrmw.
  std::optional<Value> val = std::nullopt;
  std::optional<LLVM::AtomicBinOp> kind = std::nullopt;

  if (auto matched = matchAtomicBinOpUpdate(update)) {
    Operation *binOp = matched->second;
    bool updateIsLhs = binOp->getOperand(0) == updateArgument;
    kind = matched->first;
    val = binOp->getOperand(updateIsLhs ? 1 : 0);
  }

  // Per-component atomicrmw info for complex type decomposition.
  // Decomposed complex ops (complex.re/im + arith binop + complex.create)
  // produce per-component binary ops that each need a separate atomicrmw.
  struct ComponentAtomic {
    LLVM::AtomicBinOp kind;
    Value val;
    int32_t fieldIdx;
  };
  SmallVector<ComponentAtomic, 2> componentAtomics;

  if (!val || !kind) {
    Type convertedArgTy =
        this->getTypeConverter()->convertType(updateArgument.getType());
    if (auto structTy = dyn_cast<LLVM::LLVMStructType>(convertedArgTy)) {
      if (structTy.getBody().size() == 2 &&
          structTy.getBody()[0] == structTy.getBody()[1] &&
          structTy.getBody()[0].isIntOrFloat() &&
          structTy.getBody()[0].getIntOrFloatBitWidth() > 32) {
        for (Operation &op : updateBlock.getOperations()) {
          if (op.hasTrait<OpTrait::IsTerminator>() || op.getNumOperands() < 2)
            continue;
          int32_t fieldIdx = -1;
          Value externalVal = nullptr;
          bool updateIsLhs = false;
          for (unsigned i = 0; i < 2; ++i) {
            Value operand = op.getOperand(i);
            if (auto reOp = operand.getDefiningOp<complex::ReOp>()) {
              if (reOp.getOperand() == updateArgument) {
                fieldIdx = 0;
                externalVal = op.getOperand(1 - i);
                updateIsLhs = i == 0;
              }
            } else if (auto imOp = operand.getDefiningOp<complex::ImOp>()) {
              if (imOp.getOperand() == updateArgument) {
                fieldIdx = 1;
                externalVal = op.getOperand(1 - i);
                updateIsLhs = i == 0;
              }
            }
          }
          if (fieldIdx < 0)
            continue;
          auto componentKind = getAtomicBinOp(&op, updateIsLhs);
          if (!componentKind)
            continue;
          componentAtomics.push_back({*componentKind, externalVal, fieldIdx});
        }
      }
    }
  }

  Location loc = update.getLoc();
  Value xPtr = getAtomicPointer(update.getX(), adaptor.getX(), loc, rewriter);

  // Require distinct real/imag lanes; duplicate fieldIdx values must fall back
  // to cmpxchg rather than emitting two atomicrmw ops on the same component.
  bool hasDistinctComplexLanes = false;
  if (componentAtomics.size() == 2) {
    unsigned lanes = 0;
    for (const ComponentAtomic &ca : componentAtomics) {
      if (ca.fieldIdx == 0 || ca.fieldIdx == 1)
        lanes |= 1u << ca.fieldIdx;
    }
    hasDistinctComplexLanes = lanes == 0b11;
  }

  if (val && kind) {
    auto ordering = LLVM::AtomicOrdering::monotonic;
    LLVM::AtomicRMWOp::create(rewriter, loc, *kind, xPtr,
                              rewriter.getRemappedValue(*val), ordering);
  } else if (hasDistinctComplexLanes) {
    auto structTy = cast<LLVM::LLVMStructType>(
        this->getTypeConverter()->convertType(updateArgument.getType()));
    Type ptrType = LLVM::LLVMPointerType::get(rewriter.getContext());
    auto ordering = LLVM::AtomicOrdering::monotonic;
    for (ComponentAtomic &ca : componentAtomics) {
      Value elemPtr =
          LLVM::GEPOp::create(rewriter, loc, ptrType, structTy, xPtr,
                              ArrayRef<LLVM::GEPArg>{0, ca.fieldIdx});
      LLVM::AtomicRMWOp::create(rewriter, loc, ca.kind, elemPtr,
                                rewriter.getRemappedValue(ca.val), ordering);
    }
  } else {
    // Fallback to the llvm.cmpxchg loop generation.
    genUpdateCmpxchgLoop(update, rewriter);
  }
  rewriter.eraseOp(update);
  return success();
}

/// The cmpxchg loop re-points reads of `v`/`x` inside `expr` at the atomically
/// loaded value (see moveDependency). An atomicrmw cannot do that, so any
/// `expr` that loads from memory keeps the loop: the load may be the captured
/// value itself, and the address is not reliably comparable here.
static bool exprReadsMemory(Value expr) {
  SmallVector<Value> worklist{expr};
  llvm::DenseSet<Operation *> seen;
  while (!worklist.empty()) {
    Operation *def = worklist.pop_back_val().getDefiningOp();
    if (!def || !seen.insert(def).second)
      continue;
    if (!isMemoryEffectFree(def))
      return true;
    worklist.append(def->getOperands().begin(), def->getOperands().end());
  }
  return false;
}

/// Emit a single atomicrmw for a `x = x <binop> expr` capture.
template <typename AtomicOpTy>
LogicalResult ACCAtomicOpConversion<AtomicOpTy>::tryEmitCaptureAtomicRMW(
    AtomicCaptureOp capture, AtomicUpdateOp update, AtomicReadOp read,
    ConversionPatternRewriter &rewriter) const {
  if (read.getX() != update.getX())
    return failure();
  auto matched = matchAtomicBinOpUpdate(update);
  if (!matched)
    return failure();
  auto [kind, binOp] = *matched;

  Value arg = update.getRegion().front().getArgument(0);
  bool updateIsLhs = binOp->getOperand(0) == arg;
  Value expr = binOp->getOperand(updateIsLhs ? 1 : 0);

  // Keep serialized and aggregate types on the cmpxchg path.
  Type argTy = arg.getType();
  if (!argTy.isIntOrFloat() ||
      this->getTypeConverter()->convertType(argTy) != argTy)
    return failure();
  // The operand must already be available, and must not be the captured value.
  Operation *exprDef = expr.getDefiningOp();
  if (exprDef && exprDef->getBlock() == &update.getRegion().front())
    return failure();
  if (exprReadsMemory(expr))
    return failure();

  Location loc = capture.getLoc();
  Value xRef = update.getX();
  Value vRef = read.getV();
  Value xPtr =
      getAtomicPointer(xRef, rewriter.getRemappedValue(xRef), loc, rewriter);
  Value vPtr =
      getAtomicPointer(vRef, rewriter.getRemappedValue(vRef), loc, rewriter);

  rewriter.setInsertionPoint(capture);
  auto rmw = LLVM::AtomicRMWOp::create(rewriter, loc, kind, xPtr,
                                       rewriter.getRemappedValue(expr),
                                       LLVM::AtomicOrdering::monotonic);
  // atomicrmw yields the old value; `{update, read}` captures the new one.
  Value captured = rmw.getRes();
  if (capture.getFirstOp() == update.getOperation()) {
    rewriter.moveOpAfter(binOp, rmw);
    binOp->replaceUsesOfWith(arg, captured);
    captured = binOp->getResult(0);
  }
  rewriter.replaceOpWithNewOp<LLVM::StoreOp>(capture, captured, vPtr);
  return success();
}

/// Generate an llvm.cmpxchg loop.
template <>
LogicalResult ACCAtomicOpConversion<AtomicCaptureOp>::matchAndRewrite(
    AtomicCaptureOp capture, OpAdaptor /*adaptor*/,
    ConversionPatternRewriter &rewriter) const {
  Operation *firstOp = capture.getFirstOp();
  Operation *secondOp = capture.getSecondOp();
  Value vPtr = nullptr;
  Value storeVal = nullptr;

  // A single `x = x <binop> expr` capture becomes one atomicrmw. The cmpxchg
  // loop below serializes retries and collapses under contention.
  if (AtomicUpdateOp update = capture.getAtomicUpdateOp())
    if (AtomicReadOp read = capture.getAtomicReadOp())
      if (succeeded(tryEmitCaptureAtomicRMW(capture, update, read, rewriter)))
        return success();

  if (auto firstReadStmt = dyn_cast<AtomicReadOp>(firstOp)) {
    Location loc = capture.getLoc();
    Value xRef = firstReadStmt.getX();
    Value xPtr =
        getAtomicPointer(xRef, rewriter.getRemappedValue(xRef), loc, rewriter);
    ModuleOp mod = capture->getParentOfType<ModuleOp>();
    Type xType = getReferencedElementType(xRef, mod);
    Type xTypeOrig = getReferencedElementType(xRef);
    Value vRef = firstReadStmt.getV();
    vPtr =
        getAtomicPointer(vRef, rewriter.getRemappedValue(vRef), loc, rewriter);

    Value expr = nullptr;
    if (auto secondWriteStmt = dyn_cast<AtomicWriteOp>(secondOp)) {
      // 1. `{ atomic.read, atomic.write }` pattern
      expr = secondWriteStmt.getExpr();
    } else if (auto secondUpdateStmt = dyn_cast<AtomicUpdateOp>(secondOp)) {
      // 2. `{ atomic.read, atomic.update }` pattern
      Block &updateBlock = secondUpdateStmt.getRegion().front();
      Operation *terminator = updateBlock.getTerminator();
      expr = terminator->getOperand(0);
    }

    Block *loopBlock = constructCmpxchgLoop(xPtr, xType, expr, rewriter);
    Value loopArgument = loopBlock->getArgument(0);
    Operation &loopHead = loopBlock->front();
    auto condBr = cast<LLVM::CondBrOp>(loopBlock->back());
    storeVal = condBr.getFalseDestOperands()[0];

    rewriter.setInsertionPointToStart(loopBlock);
    loopArgument = deserializeExpr(loopArgument, xTypeOrig, rewriter);

    // Include flow dependency (v -> expr).
    if (auto secondUpdateStmt = dyn_cast<AtomicUpdateOp>(secondOp)) {
      Block &updateBlock = secondUpdateStmt.getRegion().front();
      Value updateArgument = updateBlock.getArgument(0);
      updateArgument.replaceAllUsesWith(loopArgument);
      updateBlock.walk([&](Operation *op) {
        if (!op->hasTrait<OpTrait::IsTerminator>())
          rewriter.moveOpBefore(op, &loopHead);
      });
    }
    moveDependency(vRef, vPtr, expr, loopArgument, loopHead, rewriter,
                   getLoadAddress);
  } else if (auto firstUpdateStmt = dyn_cast<AtomicUpdateOp>(firstOp)) {
    if (auto secondReadStmt = dyn_cast<AtomicReadOp>(secondOp)) {
      // 3. `{ atomic.update, atomic.read }` pattern
      storeVal = genUpdateCmpxchgLoop(firstUpdateStmt, rewriter);

      Value vRef = secondReadStmt.getV();
      vPtr = getAtomicPointer(vRef, rewriter.getRemappedValue(vRef),
                              capture.getLoc(), rewriter);
    }
  }
  // Generate `v = x`.
  rewriter.setInsertionPoint(capture);
  rewriter.replaceOpWithNewOp<LLVM::StoreOp>(capture, storeVal, vPtr);
  return success();
}

} // namespace

namespace mlir {

void configureACCAtomicConversionLegality(ConversionTarget &target) {
  target.addIllegalOp<AtomicReadOp, AtomicWriteOp, AtomicUpdateOp,
                      AtomicCaptureOp>();
}

void populateACCAtomicPatterns(const LLVMTypeConverter &converter,
                               RewritePatternSet &patterns,
                               acc::OpenACCSupport &accSupport,
                               ACCAtomicLoadAddressCallback getLoadAddress) {
  patterns.add<ACCAtomicOpConversion<AtomicReadOp>,
               ACCAtomicOpConversion<AtomicWriteOp>,
               ACCAtomicOpConversion<AtomicUpdateOp>,
               ACCAtomicOpConversion<AtomicCaptureOp>>(converter, accSupport,
                                                       getLoadAddress);
}

} // namespace mlir
