//===-- FIROps.cpp --------------------------------------------------------===//
//
// 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
//
//===----------------------------------------------------------------------===//
//
// Coding style: https://mlir.llvm.org/getting_started/DeveloperGuide/
//
//===----------------------------------------------------------------------===//

#include "flang/Optimizer/Dialect/FIROps.h"
#include "flang/Optimizer/Dialect/CUDAKernelOpInterface.h"
#include "flang/Optimizer/Dialect/FIRAttr.h"
#include "flang/Optimizer/Dialect/FIRBoxUtils.h"
#include "flang/Optimizer/Dialect/FIRDialect.h"
#include "flang/Optimizer/Dialect/FIROpsSupport.h"
#include "flang/Optimizer/Dialect/FIRType.h"
#include "flang/Optimizer/Dialect/Support/FIRContext.h"
#include "flang/Optimizer/Dialect/Support/KindMapping.h"
#include "flang/Optimizer/Support/Utils.h"
#include "mlir/Dialect/Func/IR/FuncOps.h"
#include "mlir/Dialect/OpenACC/OpenACC.h"
#include "mlir/Dialect/OpenACC/OpenACCUtils.h"
#include "mlir/Dialect/OpenMP/OpenMPDialect.h"
#include "mlir/IR/Attributes.h"
#include "mlir/IR/BuiltinAttributes.h"
#include "mlir/IR/BuiltinOps.h"
#include "mlir/IR/Diagnostics.h"
#include "mlir/IR/Matchers.h"
#include "mlir/IR/OpDefinition.h"
#include "mlir/IR/PatternMatch.h"
#include "mlir/IR/TypeRange.h"
#include "mlir/Interfaces/DataLayoutInterfaces.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/TypeSwitch.h"
#include "llvm/Support/CommandLine.h"

namespace {
#include "flang/Optimizer/Dialect/CanonicalizationPatterns.inc"
} // namespace

static llvm::cl::opt<bool> clUseStrictVolatileVerification(
    "strict-fir-volatile-verifier", llvm::cl::init(false),
    llvm::cl::desc(
        "use stricter verifier for FIR operations with volatile types"));

bool fir::useStrictVolatileVerification() {
  return clUseStrictVolatileVerification;
}

static void propagateAttributes(mlir::Operation *fromOp,
                                mlir::Operation *toOp) {
  if (!fromOp || !toOp)
    return;

  for (mlir::NamedAttribute attr : fromOp->getAttrs()) {
    if (attr.getName().getValue().starts_with(
            mlir::acc::OpenACCDialect::getDialectNamespace()))
      toOp->setAttr(attr.getName(), attr.getValue());
  }
}

/// Return true if a sequence type is of some incomplete size or a record type
/// is malformed or contains an incomplete sequence type. An incomplete sequence
/// type is one with more unknown extents in the type than have been provided
/// via `dynamicExtents`. Sequence types with an unknown rank are incomplete by
/// definition.
static bool verifyInType(mlir::Type inType,
                         llvm::SmallVectorImpl<llvm::StringRef> &visited,
                         unsigned dynamicExtents = 0) {
  if (auto st = mlir::dyn_cast<fir::SequenceType>(inType)) {
    auto shape = st.getShape();
    if (shape.size() == 0)
      return true;
    for (std::size_t i = 0, end = shape.size(); i < end; ++i) {
      if (shape[i] != fir::SequenceType::getUnknownExtent())
        continue;
      if (dynamicExtents-- == 0)
        return true;
    }
  } else if (auto rt = mlir::dyn_cast<fir::RecordType>(inType)) {
    // don't recurse if we're already visiting this one
    if (llvm::is_contained(visited, rt.getName()))
      return false;
    // keep track of record types currently being visited
    visited.push_back(rt.getName());
    for (auto &field : rt.getTypeList())
      if (verifyInType(field.second, visited))
        return true;
    visited.pop_back();
  }
  return false;
}

static bool verifyTypeParamCount(mlir::Type inType, unsigned numParams) {
  auto ty = fir::unwrapSequenceType(inType);
  if (numParams > 0) {
    if (auto recTy = mlir::dyn_cast<fir::RecordType>(ty))
      return numParams != recTy.getNumLenParams();
    if (auto chrTy = mlir::dyn_cast<fir::CharacterType>(ty))
      return !(numParams == 1 && chrTy.hasDynamicLen());
    return true;
  }
  if (auto chrTy = mlir::dyn_cast<fir::CharacterType>(ty))
    return !chrTy.hasConstantLen();
  return false;
}

/// Parser shared by Alloca and Allocmem
/// operation ::= %res = (`fir.alloca` | `fir.allocmem`) $in_type
///                      ( `(` $typeparams `)` )? ( `,` $shape )?
///                      attr-dict-without-keyword
template <typename FN>
static mlir::ParseResult parseAllocatableOp(FN wrapResultType,
                                            mlir::OpAsmParser &parser,
                                            mlir::OperationState &result) {
  mlir::Type intype;
  if (parser.parseType(intype))
    return mlir::failure();
  auto &builder = parser.getBuilder();
  result.addAttribute("in_type", mlir::TypeAttr::get(intype));
  llvm::SmallVector<mlir::OpAsmParser::UnresolvedOperand> operands;
  llvm::SmallVector<mlir::Type> typeVec;
  bool hasOperands = false;
  std::int32_t typeparamsSize = 0;
  if (!parser.parseOptionalLParen()) {
    // parse the LEN params of the derived type. (<params> : <types>)
    if (parser.parseOperandList(operands, mlir::OpAsmParser::Delimiter::None) ||
        parser.parseColonTypeList(typeVec) || parser.parseRParen())
      return mlir::failure();
    typeparamsSize = operands.size();
    hasOperands = true;
  }
  std::int32_t shapeSize = 0;
  if (!parser.parseOptionalComma()) {
    // parse size to scale by, vector of n dimensions of type index
    if (parser.parseOperandList(operands, mlir::OpAsmParser::Delimiter::None))
      return mlir::failure();
    shapeSize = operands.size() - typeparamsSize;
    auto idxTy = builder.getIndexType();
    for (std::int32_t i = typeparamsSize, end = operands.size(); i != end; ++i)
      typeVec.push_back(idxTy);
    hasOperands = true;
  }
  if (hasOperands &&
      parser.resolveOperands(operands, typeVec, parser.getNameLoc(),
                             result.operands))
    return mlir::failure();
  mlir::Type restype = wrapResultType(intype);
  if (!restype) {
    parser.emitError(parser.getNameLoc(), "invalid allocate type: ") << intype;
    return mlir::failure();
  }
  result.addAttribute("operandSegmentSizes", builder.getDenseI32ArrayAttr(
                                                 {typeparamsSize, shapeSize}));
  if (parser.parseOptionalAttrDict(result.attributes) ||
      parser.addTypeToList(restype, result.types))
    return mlir::failure();
  return mlir::success();
}

template <typename OP>
static void printAllocatableOp(mlir::OpAsmPrinter &p, OP &op) {
  p << ' ' << op.getInType();
  if (!op.getTypeparams().empty()) {
    p << '(' << op.getTypeparams() << " : " << op.getTypeparams().getTypes()
      << ')';
  }
  // print the shape of the allocation (if any); all must be index type
  for (auto sh : op.getShape()) {
    p << ", ";
    p.printOperand(sh);
  }
  p.printOptionalAttrDict(op->getAttrs(), {"in_type", "operandSegmentSizes"});
}

bool fir::mayBeAbsentBox(mlir::Value val) {
  assert(mlir::isa<fir::BaseBoxType>(val.getType()) && "expected box argument");
  while (val) {
    mlir::Operation *defOp = val.getDefiningOp();
    if (!defOp) {
      // TODO: we need a better way to identify definitely
      // present boxes to allow more speculation.
      // Maybe we should rely on [hl]fir.declare's inside
      // acc.compute_region or use more generic interface
      // (such as RegionBranchOpInterface) to map the block
      // arguments to the operands (though, the meaning
      // of operands/block-arguments of acc.compute_region
      // is tricky).
      if (mlir::Value accOperand = mlir::acc::getACCOperandForBlockArg(val)) {
        val = accOperand;
        continue;
      }

      return true;
    }

    if (auto varIface = mlir::dyn_cast<fir::FortranVariableOpInterface>(defOp))
      return varIface.isOptional();

    // Check for fir.embox and fir.rebox before checking for
    // FortranObjectViewOpInterface, which they support.
    // A box created by fir.embox/fir.rebox/fir.rebox_assumed_rank is only
    // potentially absent when the operation was explicitly tagged with the
    // `optional` attribute.
    if (auto reboxOp = mlir::dyn_cast<fir::ReboxOp>(defOp))
      return reboxOp.getOptional();
    if (auto emboxOp = mlir::dyn_cast<fir::EmboxOp>(defOp))
      return emboxOp.getOptional();
    if (auto reboxAROp = mlir::dyn_cast<fir::ReboxAssumedRankOp>(defOp))
      return reboxAROp.getOptional();
    if (mlir::isa<fir::LoadOp>(defOp))
      return false;

    if (mlir::isa<ACC_DATA_ENTRY_AND_INIT_OPS>(defOp)) {
      val = mlir::acc::getVar(defOp);
      continue;
    }

    if (auto viewIface =
            mlir::dyn_cast<fir::FortranObjectViewOpInterface>(defOp)) {
      val = viewIface.getViewSource(mlir::cast<mlir::OpResult>(val));
      continue;
    }
    break;
  }
  return true;
}

//===----------------------------------------------------------------------===//
// AllocaOp
//===----------------------------------------------------------------------===//

/// Create a legal memory reference as return type
static mlir::Type wrapAllocaResultType(mlir::Type intype) {
  // FIR semantics: memory references to memory references are disallowed
  if (mlir::isa<fir::ReferenceType>(intype))
    return {};
  return fir::ReferenceType::get(intype);
}

llvm::SmallVector<mlir::MemorySlot> fir::AllocaOp::getPromotableSlots() {
  // TODO: support promotion of dynamic allocas
  if (isDynamic())
    return {};

  return {mlir::MemorySlot{getResult(), getAllocatedType()}};
}

mlir::Value fir::AllocaOp::getDefaultValue(const mlir::MemorySlot &slot,
                                           mlir::OpBuilder &builder) {
  return fir::UndefOp::create(builder, getLoc(), slot.elemType);
}

void fir::AllocaOp::handleBlockArgument(const mlir::MemorySlot &slot,
                                        mlir::BlockArgument argument,
                                        mlir::OpBuilder &builder) {
  // When there is a fir.declare, fir.debug_value must be emitted at each value
  // change and at each beginning of a block where the reaching value is
  // propagated as a block argument.
  // TODO: in order to get proper inter-dialect mem2reg, the
  // PromotableOpInterface should be provided with a
  // requiresInsertedBlockArguments similar to requiresReplacedValues so that
  // fir::DeclareOp can be the one dictating that this needs to happen instead
  // of the allocation. There are other challenges to inter dialect mem2reg to
  // solve first, like having a common concept for going through converts and
  // no-ops like fir.declare (i.e., to replace the FIR specific
  // isSlotOrDeclaredSlot).
  for (mlir::Operation *user : getOperation()->getUsers())
    if (auto declareOp = mlir::dyn_cast<fir::DeclareOp>(user)) {
      // Inlined dummy scopes may not dominate block-argument debug values.
      if (declareOp.getDummyScope())
        continue;
      fir::DeclareValueOp::create(
          builder, declareOp.getLoc(), argument, declareOp.getDummyScope(),
          declareOp.getUniqNameAttr(), declareOp.getFortranAttrsAttr(),
          declareOp.getDataAttrAttr(), declareOp.getDummyArgNoAttr());
    }
}

std::optional<mlir::PromotableAllocationOpInterface>
fir::AllocaOp::handlePromotionComplete(const mlir::MemorySlot &slot,
                                       mlir::Value defaultValue,
                                       mlir::OpBuilder &builder) {
  if (defaultValue && defaultValue.use_empty()) {
    assert(mlir::isa<fir::UndefOp>(defaultValue.getDefiningOp()) &&
           "Expected undef op to be the default value");
    defaultValue.getDefiningOp()->erase();
  }
  this->erase();
  return std::nullopt;
}

mlir::Type fir::AllocaOp::getAllocatedType() {
  return mlir::cast<fir::ReferenceType>(getType()).getEleTy();
}

mlir::Type fir::AllocaOp::getRefTy(mlir::Type ty) {
  return fir::ReferenceType::get(ty);
}

void fir::AllocaOp::build(mlir::OpBuilder &builder,
                          mlir::OperationState &result, mlir::Type inType,
                          llvm::StringRef uniqName, mlir::ValueRange typeparams,
                          mlir::ValueRange shape,
                          llvm::ArrayRef<mlir::NamedAttribute> attributes) {
  auto nameAttr = builder.getStringAttr(uniqName);
  build(builder, result, wrapAllocaResultType(inType), inType, nameAttr, {},
        /*pinned=*/false, typeparams, shape);
  result.addAttributes(attributes);
}

void fir::AllocaOp::build(mlir::OpBuilder &builder,
                          mlir::OperationState &result, mlir::Type inType,
                          llvm::StringRef uniqName, bool pinned,
                          mlir::ValueRange typeparams, mlir::ValueRange shape,
                          llvm::ArrayRef<mlir::NamedAttribute> attributes) {
  auto nameAttr = builder.getStringAttr(uniqName);
  build(builder, result, wrapAllocaResultType(inType), inType, nameAttr, {},
        pinned, typeparams, shape);
  result.addAttributes(attributes);
}

void fir::AllocaOp::build(mlir::OpBuilder &builder,
                          mlir::OperationState &result, mlir::Type inType,
                          llvm::StringRef uniqName, llvm::StringRef bindcName,
                          mlir::ValueRange typeparams, mlir::ValueRange shape,
                          llvm::ArrayRef<mlir::NamedAttribute> attributes) {
  auto nameAttr =
      uniqName.empty() ? mlir::StringAttr{} : builder.getStringAttr(uniqName);
  auto bindcAttr =
      bindcName.empty() ? mlir::StringAttr{} : builder.getStringAttr(bindcName);
  build(builder, result, wrapAllocaResultType(inType), inType, nameAttr,
        bindcAttr, /*pinned=*/false, typeparams, shape);
  result.addAttributes(attributes);
}

void fir::AllocaOp::build(mlir::OpBuilder &builder,
                          mlir::OperationState &result, mlir::Type inType,
                          llvm::StringRef uniqName, llvm::StringRef bindcName,
                          bool pinned, mlir::ValueRange typeparams,
                          mlir::ValueRange shape,
                          llvm::ArrayRef<mlir::NamedAttribute> attributes) {
  auto nameAttr =
      uniqName.empty() ? mlir::StringAttr{} : builder.getStringAttr(uniqName);
  auto bindcAttr =
      bindcName.empty() ? mlir::StringAttr{} : builder.getStringAttr(bindcName);
  build(builder, result, wrapAllocaResultType(inType), inType, nameAttr,
        bindcAttr, pinned, typeparams, shape);
  result.addAttributes(attributes);
}

void fir::AllocaOp::build(mlir::OpBuilder &builder,
                          mlir::OperationState &result, mlir::Type inType,
                          mlir::ValueRange typeparams, mlir::ValueRange shape,
                          llvm::ArrayRef<mlir::NamedAttribute> attributes) {
  build(builder, result, wrapAllocaResultType(inType), inType, {}, {},
        /*pinned=*/false, typeparams, shape);
  result.addAttributes(attributes);
}

void fir::AllocaOp::build(mlir::OpBuilder &builder,
                          mlir::OperationState &result, mlir::Type inType,
                          bool pinned, mlir::ValueRange typeparams,
                          mlir::ValueRange shape,
                          llvm::ArrayRef<mlir::NamedAttribute> attributes) {
  build(builder, result, wrapAllocaResultType(inType), inType, {}, {}, pinned,
        typeparams, shape);
  result.addAttributes(attributes);
}

mlir::ParseResult fir::AllocaOp::parse(mlir::OpAsmParser &parser,
                                       mlir::OperationState &result) {
  return parseAllocatableOp(wrapAllocaResultType, parser, result);
}

void fir::AllocaOp::print(mlir::OpAsmPrinter &p) {
  printAllocatableOp(p, *this);
}

llvm::LogicalResult fir::AllocaOp::verify() {
  llvm::SmallVector<llvm::StringRef> visited;
  if (verifyInType(getInType(), visited, numShapeOperands()))
    return emitOpError("invalid type for allocation");
  if (verifyTypeParamCount(getInType(), numLenParams()))
    return emitOpError("LEN params do not correspond to type");
  mlir::Type outType = getType();
  if (!mlir::isa<fir::ReferenceType>(outType))
    return emitOpError("must be a !fir.ref type");
  return mlir::success();
}

bool fir::AllocaOp::ownsNestedAlloca(mlir::Operation *op) {
  return op->hasTrait<mlir::OpTrait::IsIsolatedFromAbove>() ||
         op->hasTrait<mlir::OpTrait::AutomaticAllocationScope>() ||
         mlir::isa<mlir::LoopLikeOpInterface>(*op);
}

mlir::Region *fir::AllocaOp::getOwnerRegion() {
  mlir::Operation *currentOp = getOperation();
  while (mlir::Operation *parentOp = currentOp->getParentOp()) {
    // If the operation was not registered, inquiries about its traits will be
    // incorrect and it is not possible to reason about the operation. This
    // should not happen in a normal Fortran compilation flow, but be foolproof.
    if (!parentOp->isRegistered())
      return nullptr;
    if (fir::AllocaOp::ownsNestedAlloca(parentOp))
      return currentOp->getParentRegion();
    currentOp = parentOp;
  }
  return nullptr;
}

//===----------------------------------------------------------------------===//
// AllocMemOp
//===----------------------------------------------------------------------===//

/// Create a legal heap reference as return type
static mlir::Type wrapAllocMemResultType(mlir::Type intype) {
  // Fortran semantics: C852 an entity cannot be both ALLOCATABLE and POINTER
  // 8.5.3 note 1 prohibits ALLOCATABLE procedures as well
  // FIR semantics: one may not allocate a memory reference value
  if (mlir::isa<fir::ReferenceType, fir::HeapType, fir::PointerType,
                mlir::FunctionType>(intype))
    return {};
  return fir::HeapType::get(intype);
}

mlir::Type fir::AllocMemOp::getAllocatedType() {
  return mlir::cast<fir::HeapType>(getType()).getEleTy();
}

mlir::Type fir::AllocMemOp::getRefTy(mlir::Type ty) {
  return fir::HeapType::get(ty);
}

void fir::AllocMemOp::build(mlir::OpBuilder &builder,
                            mlir::OperationState &result, mlir::Type inType,
                            llvm::StringRef uniqName,
                            mlir::ValueRange typeparams, mlir::ValueRange shape,
                            llvm::ArrayRef<mlir::NamedAttribute> attributes) {
  auto nameAttr = builder.getStringAttr(uniqName);
  build(builder, result, wrapAllocMemResultType(inType), inType, nameAttr, {},
        typeparams, shape, /*alignment=*/{});
  result.addAttributes(attributes);
}

void fir::AllocMemOp::build(mlir::OpBuilder &builder,
                            mlir::OperationState &result, mlir::Type inType,
                            llvm::StringRef uniqName, llvm::StringRef bindcName,
                            mlir::ValueRange typeparams, mlir::ValueRange shape,
                            llvm::ArrayRef<mlir::NamedAttribute> attributes) {
  auto nameAttr = builder.getStringAttr(uniqName);
  auto bindcAttr = builder.getStringAttr(bindcName);
  build(builder, result, wrapAllocMemResultType(inType), inType, nameAttr,
        bindcAttr, typeparams, shape, /*alignment=*/{});
  result.addAttributes(attributes);
}

void fir::AllocMemOp::build(mlir::OpBuilder &builder,
                            mlir::OperationState &result, mlir::Type inType,
                            mlir::ValueRange typeparams, mlir::ValueRange shape,
                            llvm::ArrayRef<mlir::NamedAttribute> attributes) {
  build(builder, result, wrapAllocMemResultType(inType), inType, {}, {},
        typeparams, shape, /*alignment=*/{});
  result.addAttributes(attributes);
}

mlir::ParseResult fir::AllocMemOp::parse(mlir::OpAsmParser &parser,
                                         mlir::OperationState &result) {
  return parseAllocatableOp(wrapAllocMemResultType, parser, result);
}

void fir::AllocMemOp::print(mlir::OpAsmPrinter &p) {
  printAllocatableOp(p, *this);
}

llvm::LogicalResult fir::AllocMemOp::verify() {
  llvm::SmallVector<llvm::StringRef> visited;
  if (verifyInType(getInType(), visited, numShapeOperands()))
    return emitOpError("invalid type for allocation");
  if (verifyTypeParamCount(getInType(), numLenParams()))
    return emitOpError("LEN params do not correspond to type");
  mlir::Type outType = getType();
  if (!mlir::dyn_cast<fir::HeapType>(outType))
    return emitOpError("must be a !fir.heap type");
  if (fir::isa_unknown_size_box(fir::dyn_cast_ptrEleTy(outType)))
    return emitOpError("cannot allocate !fir.box of unknown rank or type");
  if (std::optional<std::int64_t> alignment = getAlignment()) {
    if (*alignment <= 0 || (*alignment & (*alignment - 1)) != 0)
      return emitOpError("alignment must be a positive power of two");
  }
  return mlir::success();
}

//===----------------------------------------------------------------------===//
// ArrayCoorOp
//===----------------------------------------------------------------------===//

// CHARACTERs and derived types with LEN PARAMETERs are dependent types that
// require runtime values to fully define the type of an object.
static bool validTypeParams(mlir::Type dynTy, mlir::ValueRange typeParams,
                            bool allowParamsForBox = false) {
  dynTy = fir::unwrapAllRefAndSeqType(dynTy);
  if (mlir::isa<fir::BaseBoxType>(dynTy)) {
    // A box value will contain type parameter values itself.
    if (!allowParamsForBox)
      return typeParams.size() == 0;

    // A boxed value may have no length parameters, when the lengths
    // are assumed. If dynamic lengths are used, then proceed
    // to the verification below.
    if (typeParams.size() == 0)
      return true;

    dynTy = fir::getFortranElementType(dynTy);
  }
  // Derived type must have all type parameters satisfied.
  if (auto recTy = mlir::dyn_cast<fir::RecordType>(dynTy))
    return typeParams.size() == recTy.getNumLenParams();
  // Characters with non-constant LEN must have a type parameter value.
  if (auto charTy = mlir::dyn_cast<fir::CharacterType>(dynTy))
    if (charTy.hasDynamicLen())
      return typeParams.size() == 1;
  // Otherwise, any type parameters are invalid.
  return typeParams.size() == 0;
}

llvm::LogicalResult fir::ArrayCoorOp::verify() {
  auto eleTy = fir::dyn_cast_ptrOrBoxEleTy(getMemref().getType());
  auto arrTy = mlir::dyn_cast<fir::SequenceType>(eleTy);
  if (!arrTy)
    return emitOpError("must be a reference to an array");
  auto arrDim = arrTy.getDimension();

  if (auto shapeOp = getShape()) {
    auto shapeTy = shapeOp.getType();
    unsigned shapeTyRank = 0;
    if (auto s = mlir::dyn_cast<fir::ShapeType>(shapeTy)) {
      shapeTyRank = s.getRank();
    } else if (auto ss = mlir::dyn_cast<fir::ShapeShiftType>(shapeTy)) {
      shapeTyRank = ss.getRank();
    } else {
      auto s = mlir::cast<fir::ShiftType>(shapeTy);
      shapeTyRank = s.getRank();
      // TODO: it looks like PreCGRewrite and CodeGen can support
      // fir.shift with plain array reference, so we may consider
      // removing this check.
      if (!mlir::isa<fir::BaseBoxType>(getMemref().getType()))
        return emitOpError("shift can only be provided with fir.box memref");
    }
    if (arrDim && arrDim != shapeTyRank)
      return emitOpError("rank of dimension mismatched");
    // TODO: support slicing with changing the number of dimensions,
    // e.g. when array_coor represents an element access to array(:,1,:)
    // slice: the shape is 3D and the number of indices is 2 in this case.
    if (shapeTyRank != getIndices().size())
      return emitOpError("number of indices do not match dim rank");
  }

  if (auto sliceOp = getSlice()) {
    if (auto sl = mlir::dyn_cast_or_null<fir::SliceOp>(sliceOp.getDefiningOp()))
      if (!sl.getSubstr().empty())
        return emitOpError("array_coor cannot take a slice with substring");
    if (auto sliceTy = mlir::dyn_cast<fir::SliceType>(sliceOp.getType()))
      if (sliceTy.getRank() != arrDim)
        return emitOpError("rank of dimension in slice mismatched");
  }
  if (!validTypeParams(getMemref().getType(), getTypeparams()))
    return emitOpError("invalid type parameters");

  return mlir::success();
}

// Helper shared by array_coor canonicalization patterns. Returns true if
// folding `producers` into `consumer` would cross an ACC data-clause or CUDA
// kernel boundary that the lowering pipeline relies on:
//
//   - ACC: when `consumer` lives inside an ACC compute or data construct and
//     any producer's result is referenced by an ACC data-clause op, the
//     producer must remain (the data legalization pipeline expects it to be
//     the copyin var / kernel argument).
//   - CUF: every producer must share the same enclosing CUDA kernel as the
//     consumer; otherwise the kernel would end up capturing a host-side
//     descriptor directly, causing illegal device dereferences at runtime.
static bool arrayCoorFoldCrossesACCOrCUDABoundary(
    mlir::Operation *consumer, llvm::ArrayRef<mlir::Operation *> producers) {
  if (consumer->getParentOfType<ACC_COMPUTE_AND_DATA_CONSTRUCT_OPS>() &&
      llvm::any_of(producers, [](mlir::Operation *p) {
        return llvm::any_of(p->getUsers(), [](mlir::Operation *u) {
          return mlir::isa<ACC_DATA_ENTRY_OPS>(u);
        });
      }))
    return true;
  auto consumerKernel = consumer->getParentOfType<fir::CUDAKernelOpInterface>();
  for (mlir::Operation *p : producers)
    if (p->getParentOfType<fir::CUDAKernelOpInterface>() != consumerKernel)
      return true;
  return false;
}

// Pull in fir.embox and fir.rebox into fir.array_coor when possible.
struct SimplifyArrayCoorOp : public mlir::OpRewritePattern<fir::ArrayCoorOp> {
  using mlir::OpRewritePattern<fir::ArrayCoorOp>::OpRewritePattern;
  llvm::LogicalResult
  matchAndRewrite(fir::ArrayCoorOp op,
                  mlir::PatternRewriter &rewriter) const override {
    mlir::Value memref = op.getMemref();

    // Look through fir.box_addr: if the array_coor's memref is a ref-typed
    // value produced by fir.box_addr, treat the underlying box as the
    // defining producer for the embox/rebox lookup below. This exposes a
    // sliced embox that is otherwise hidden by the box_addr indirection,
    // which is necessary for later lowering (FIRToMemRef) to see the
    // full-rank access pattern.
    mlir::Operation *defOp = memref.getDefiningOp();
    if (!mlir::isa<fir::BaseBoxType>(memref.getType())) {
      auto boxAddrOp = mlir::dyn_cast_or_null<fir::BoxAddrOp>(defOp);
      if (!boxAddrOp)
        return mlir::failure();
      // fir.box_addr may carry an explicit result type that does not match the
      // boxed value type (a merged cast). Only peel when types agree so we do
      // not reinterpret array_coor index semantics from the lied ref type.
      mlir::Type boxEleTy =
          fir::dyn_cast_ptrOrBoxEleTy(boxAddrOp.getVal().getType());
      mlir::Type refEleTy = fir::dyn_cast_ptrOrBoxEleTy(boxAddrOp.getType());
      if (boxEleTy && (!refEleTy || boxEleTy != refEleTy))
        return mlir::failure();
      defOp = boxAddrOp.getVal().getDefiningOp();
    }

    mlir::Value boxedMemref, boxedShape, boxedSlice;
    if (auto emboxOp = mlir::dyn_cast_or_null<fir::EmboxOp>(defOp)) {
      boxedMemref = emboxOp.getMemref();
      boxedShape = emboxOp.getShape();
      boxedSlice = emboxOp.getSlice();
      // If any of operands, that are not currently supported for migration
      // to ArrayCoorOp, is present, don't rewrite.
      if (!emboxOp.getTypeparams().empty() || emboxOp.getSourceBox() ||
          emboxOp.getAccessMap())
        return mlir::failure();
    } else if (auto reboxOp = mlir::dyn_cast_or_null<fir::ReboxOp>(defOp)) {
      // Skip when folding the rebox into the array_coor would cross an ACC
      // data-clause or CUDA kernel boundary that the lowering pipeline
      // relies on (data legalization expects the rebox to remain as the
      // copyin var / kernel argument; folding across a CUDA kernel boundary
      // would leave the kernel capturing a host-side descriptor directly).
      if (arrayCoorFoldCrossesACCOrCUDABoundary(op, {reboxOp}))
        return mlir::failure();
      boxedMemref = reboxOp.getBox();
      boxedShape = reboxOp.getShape();
      // Avoid pulling in rebox that performs reshaping.
      // There is no way to represent box reshaping with array_coor.
      if (boxedShape && !mlir::isa<fir::ShiftType>(boxedShape.getType()))
        return mlir::failure();
      boxedSlice = reboxOp.getSlice();
    } else {
      return mlir::failure();
    }

    bool boxedShapeIsShift =
        boxedShape && mlir::isa<fir::ShiftType>(boxedShape.getType());
    bool boxedShapeIsShape =
        boxedShape && mlir::isa<fir::ShapeType>(boxedShape.getType());
    bool boxedShapeIsShapeShift =
        boxedShape && mlir::isa<fir::ShapeShiftType>(boxedShape.getType());

    // Compute the rank of the original underlying memref and the rank of
    // the view the current array_coor operates on.
    unsigned origBoxRank;
    if (mlir::isa<fir::BaseBoxType>(boxedMemref.getType()))
      origBoxRank = fir::getBoxRank(boxedMemref.getType());
    else if (auto arrTy = mlir::dyn_cast<fir::SequenceType>(
                 fir::unwrapRefType(boxedMemref.getType())))
      origBoxRank = arrTy.getDimension();
    else
      return mlir::failure();

    unsigned opRank;
    if (mlir::isa<fir::BaseBoxType>(memref.getType()))
      opRank = fir::getBoxRank(memref.getType());
    else if (auto arrTy = mlir::dyn_cast<fir::SequenceType>(
                 fir::unwrapRefType(memref.getType())))
      opRank = arrTy.getDimension();
    else
      return mlir::failure();

    if (opRank > origBoxRank)
      return mlir::failure();

    // Slices with substring are not supported by array_coor.
    if (boxedSlice)
      if (auto sliceOp =
              mlir::dyn_cast_or_null<fir::SliceOp>(boxedSlice.getDefiningOp()))
        if (!sliceOp.getSubstr().empty())
          return mlir::failure();

    // Rank-reducing case: the underlying memref has more dimensions than the
    // array_coor view because boxedSlice contains scalar triples (whose upper
    // bound is fir.undefined). Rebuild the array_coor on the original memref
    // with origBoxRank indices, filling scalar dims from the slice's lower
    // bounds and the remaining range dims from the existing array_coor
    // indices.
    if (opRank < origBoxRank) {
      auto sliceOp = mlir::dyn_cast_or_null<fir::SliceOp>(
          boxedSlice ? boxedSlice.getDefiningOp() : nullptr);
      if (!sliceOp)
        return mlir::failure();
      // A component-path slice (substr handled above already) is not
      // representable in the new array_coor's indices.
      if (!sliceOp.getFields().empty())
        return mlir::failure();
      // Combining the array_coor's own slice with the boxedSlice when the
      // ranks differ is out of scope.
      if (op.getSlice())
        return mlir::failure();
      if (!boxedShape) {
        // fir.rebox with a rank-reducing slice often has no shape operand.
        // Synthesize fir.shape from box_dims extents. Do not synthesize
        // fir.shift: the descriptor produced by fir.rebox have default
        // lower bounds.
        if (!mlir::isa<fir::BaseBoxType>(boxedMemref.getType()))
          return mlir::failure();
        boxedShape = getShapeFromBoxDims(boxedMemref, origBoxRank, op.getLoc(),
                                         op, rewriter);
        if (!boxedShape)
          return mlir::failure();
      }
      // Avoid emitting a plain ref array_coor whose shape is a ShiftType:
      // the verifier rejects this (shift can only pair with fir.box memref).
      if (!mlir::isa<fir::BaseBoxType>(boxedMemref.getType()) &&
          mlir::isa<fir::ShiftType>(boxedShape.getType()))
        return mlir::failure();

      auto triples = sliceOp.getTriples();
      if (triples.size() != 3 * origBoxRank)
        return mlir::failure();

      IndicesVectorTy newIndices;
      newIndices.reserve(origBoxRank);
      llvm::SmallVector<mlir::Value> lowerBounds;
      if (auto shiftOp = mlir::dyn_cast_or_null<fir::ShiftOp>(
              boxedShape.getDefiningOp())) {
        for (mlir::Value lb : shiftOp.getOrigins())
          lowerBounds.push_back(lb);
      } else if (auto shapeShiftOp = mlir::dyn_cast_or_null<fir::ShapeShiftOp>(
                     boxedShape.getDefiningOp())) {
        for (mlir::Value lb : shapeShiftOp.getOrigins())
          lowerBounds.push_back(lb);
      }
      if (!lowerBounds.empty() && lowerBounds.size() != origBoxRank)
        return mlir::failure();

      mlir::Type idxTy = rewriter.getIndexType();
      mlir::Value one =
          mlir::arith::ConstantIndexOp::create(rewriter, op.getLoc(), 1);
      auto nsw = mlir::arith::IntegerOverflowFlags::nsw;
      auto opIndices = op.getIndices();
      unsigned opIdxPos = 0;
      for (unsigned i = 0; i < origBoxRank; ++i) {
        mlir::Value upper = triples[3 * i + 1];
        bool isScalar =
            mlir::isa_and_nonnull<fir::UndefOp>(upper.getDefiningOp());
        if (isScalar) {
          // fir.array_coor's indices are typed as AnyCoordinateType, so any
          // signless integer (or index) is accepted directly without an
          // explicit fir.convert to index.
          newIndices.push_back(triples[3 * i]);
        } else {
          if (opIdxPos >= opIndices.size())
            return mlir::failure();
          mlir::Value idx = opIndices[opIdxPos++];
          if (!lowerBounds.empty()) {
            mlir::Value lb = lowerBounds[i];
            auto constLb = fir::getIntIfConstant(lb);
            if (!(constLb && constLb->isOne())) {
              mlir::Location loc = op.getLoc();
              mlir::Value extLb =
                  fir::ConvertOp::create(rewriter, loc, idxTy, lb);
              mlir::Value extIdx =
                  fir::ConvertOp::create(rewriter, loc, idxTy, idx);
              mlir::Value add = mlir::arith::AddIOp::create(rewriter, loc,
                                                            extIdx, extLb, nsw);
              idx = mlir::arith::SubIOp::create(rewriter, loc, add, one, nsw);
            }
          }
          newIndices.push_back(idx);
        }
      }
      if (opIdxPos != opIndices.size())
        return mlir::failure();

      rewriter.replaceOpWithNewOp<fir::ArrayCoorOp>(
          op, op.getType(), boxedMemref, boxedShape, boxedSlice, newIndices,
          typeparamsForCanonicalizedMemref(boxedMemref, op.getTypeparams()));
      return mlir::success();
    }

    // Rank-preserving case from here on.
    assert(opRank == origBoxRank && "expected rank-preserving case");

    // If embox/rebox and array_coor have conflicting shapes or slices,
    // do nothing.
    if (op.getShape() && boxedShape && boxedShape != op.getShape())
      return mlir::failure();
    if (op.getSlice() && boxedSlice && boxedSlice != op.getSlice())
      return mlir::failure();

    std::optional<IndicesVectorTy> shiftedIndices;
    // The embox/rebox and array_coor either have compatible
    // shape/slice at this point or shape/slice is null
    // in one of them but not in the other.
    // The compatibility means they are equal or both null.
    if (!op.getShape()) {
      if (boxedShape) {
        if (op.getSlice()) {
          if (!boxedSlice) {
            if (boxedShapeIsShift) {
              // %0 = fir.rebox %arg(%shift)
              // %1 = fir.array_coor %0 [%slice] %idx
              // Both the slice indices and %idx are 1-based, so the rebox
              // may be pulled in as:
              // %1 = fir.array_coor %arg [%slice] %idx
              boxedShape = nullptr;
            } else if (boxedShapeIsShape) {
              // %0 = fir.embox %arg(%shape)
              // %1 = fir.array_coor %0 [%slice] %idx
              // Pull in as:
              // %1 = fir.array_coor %arg(%shape) [%slice] %idx
            } else if (boxedShapeIsShapeShift) {
              // %0 = fir.embox %arg(%shapeshift)
              // %1 = fir.array_coor %0 [%slice] %idx
              // Pull in as:
              // %shape = fir.shape <extents from the %shapeshift>
              // %1 = fir.array_coor %arg(%shape) [%slice] %idx
              boxedShape = getShapeFromShapeShift(boxedShape, rewriter);
              if (!boxedShape)
                return mlir::failure();
            } else {
              return mlir::failure();
            }
          } else {
            if (boxedShapeIsShift) {
              // %0 = fir.rebox %arg(%shift) [%slice]
              // %1 = fir.array_coor %0 [%slice] %idx
              // This FIR may only be valid if the shape specifies
              // that all lower bounds are 1s and the slice's start indices
              // and strides are all 1s.
              // We could pull in the rebox as:
              // %1 = fir.array_coor %arg [%slice] %idx
              // Do not do anything for the time being.
              return mlir::failure();
            } else if (boxedShapeIsShape) {
              // %0 = fir.embox %arg(%shape) [%slice]
              // %1 = fir.array_coor %0 [%slice] %idx
              // This FIR may only be valid if the slice's start indices
              // and strides are all 1s.
              // We could pull in the embox as:
              // %1 = fir.array_coor %arg(%shape) [%slice] %idx
              return mlir::failure();
            } else if (boxedShapeIsShapeShift) {
              // %0 = fir.embox %arg(%shapeshift) [%slice]
              // %1 = fir.array_coor %0 [%slice] %idx
              // This FIR may only be valid if the shape specifies
              // that all lower bounds are 1s and the slice's start indices
              // and strides are all 1s.
              // We could pull in the embox as:
              // %shape = fir.shape <extents from the %shapeshift>
              // %1 = fir.array_coor %arg(%shape) [%slice] %idx
              return mlir::failure();
            } else {
              return mlir::failure();
            }
          }
        } else { // !op.getSlice()
          if (!boxedSlice) {
            if (boxedShapeIsShift) {
              // %0 = fir.rebox %arg(%shift)
              // %1 = fir.array_coor %0 %idx
              // Pull in as:
              // %1 = fir.array_coor %arg %idx
              boxedShape = nullptr;
            } else if (boxedShapeIsShape) {
              // %0 = fir.embox %arg(%shape)
              // %1 = fir.array_coor %0 %idx
              // Pull in as:
              // %1 = fir.array_coor %arg(%shape) %idx
            } else if (boxedShapeIsShapeShift) {
              // %0 = fir.embox %arg(%shapeshift)
              // %1 = fir.array_coor %0 %idx
              // Pull in as:
              // %shape = fir.shape <extents from the %shapeshift>
              // %1 = fir.array_coor %arg(%shape) %idx
              boxedShape = getShapeFromShapeShift(boxedShape, rewriter);
              if (!boxedShape)
                return mlir::failure();
            } else {
              return mlir::failure();
            }
          } else {
            if (boxedShapeIsShift) {
              // %0 = fir.embox %arg(%shift) [%slice]
              // %1 = fir.array_coor %0 %idx
              // Pull in as:
              // %tmp = arith.addi %idx, %shift.origin
              // %idx_shifted = arith.subi %tmp, 1
              // %1 = fir.array_coor %arg(%shift) %[slice] %idx_shifted
              shiftedIndices =
                  getShiftedIndices(boxedShape, op.getIndices(), rewriter);
              if (!shiftedIndices)
                return mlir::failure();
            } else if (boxedShapeIsShape) {
              // %0 = fir.embox %arg(%shape) [%slice]
              // %1 = fir.array_coor %0 %idx
              // Pull in as:
              // %1 = fir.array_coor %arg(%shape) %[slice] %idx
            } else if (boxedShapeIsShapeShift) {
              // %0 = fir.embox %arg(%shapeshift) [%slice]
              // %1 = fir.array_coor %0 %idx
              // Pull in as:
              // %tmp = arith.addi %idx, %shapeshift.lb
              // %idx_shifted = arith.subi %tmp, 1
              // %1 = fir.array_coor %arg(%shapeshift) %[slice] %idx_shifted
              shiftedIndices =
                  getShiftedIndices(boxedShape, op.getIndices(), rewriter);
              if (!shiftedIndices)
                return mlir::failure();
            } else {
              return mlir::failure();
            }
          }
        }
      } else { // !boxedShape
        if (op.getSlice()) {
          if (!boxedSlice) {
            // %0 = fir.rebox %arg
            // %1 = fir.array_coor %0 [%slice] %idx
            // Pull in as:
            // %1 = fir.array_coor %arg [%slice] %idx
          } else {
            // %0 = fir.rebox %arg [%slice]
            // %1 = fir.array_coor %0 [%slice] %idx
            // This is a valid FIR iff the slice's lower bounds
            // and strides are all 1s.
            // Pull in as:
            // %1 = fir.array_coor %arg [%slice] %idx
          }
        } else { // !op.getSlice()
          if (!boxedSlice) {
            // %0 = fir.rebox %arg
            // %1 = fir.array_coor %0 %idx
            // Pull in as:
            // %1 = fir.array_coor %arg %idx
          } else {
            // %0 = fir.rebox %arg [%slice]
            // %1 = fir.array_coor %0 %idx
            // Pull in as:
            // %1 = fir.array_coor %arg [%slice] %idx
          }
        }
      }
    } else { // op.getShape()
      if (boxedShape) {
        // Check if pulling in non-default shape is correct.
        if (op.getSlice()) {
          if (!boxedSlice) {
            // %0 = fir.embox %arg(%shape)
            // %1 = fir.array_coor %0(%shape) [%slice] %idx
            // Pull in as:
            // %1 = fir.array_coor %arg(%shape) [%slice] %idx
          } else {
            // %0 = fir.embox %arg(%shape) [%slice]
            // %1 = fir.array_coor %0(%shape) [%slice] %idx
            // Pull in as:
            // %1 = fir.array_coor %arg(%shape) [%slice] %idx
          }
        } else { // !op.getSlice()
          if (!boxedSlice) {
            // %0 = fir.embox %arg(%shape)
            // %1 = fir.array_coor %0(%shape) %idx
            // Pull in as:
            // %1 = fir.array_coor %arg(%shape) %idx
          } else {
            // %0 = fir.embox %arg(%shape) [%slice]
            // %1 = fir.array_coor %0(%shape) %idx
            // Pull in as:
            // %1 = fir.array_coor %arg(%shape) [%slice] %idx
          }
        }
      } else { // !boxedShape
        if (op.getSlice()) {
          if (!boxedSlice) {
            // %0 = fir.rebox %arg
            // %1 = fir.array_coor %0(%shape) [%slice] %idx
            // Pull in as:
            // %1 = fir.array_coor %arg(%shape) [%slice] %idx
          } else {
            // %0 = fir.rebox %arg [%slice]
            // %1 = fir.array_coor %0(%shape) [%slice] %idx
            return mlir::failure();
          }
        } else { // !op.getSlice()
          if (!boxedSlice) {
            // %0 = fir.rebox %arg
            // %1 = fir.array_coor %0(%shape) %idx
            // Pull in as:
            // %1 = fir.array_coor %arg(%shape) %idx
          } else {
            // %0 = fir.rebox %arg [%slice]
            // %1 = fir.array_coor %0(%shape) %idx
            // Cannot pull in without adjusting the slice indices.
            return mlir::failure();
          }
        }
      }
    }

    // TODO: temporarily avoid producing array_coor with the shape shift
    // and plain array reference (it seems to be a limitation of
    // ArrayCoorOp verifier).
    if (!mlir::isa<fir::BaseBoxType>(boxedMemref.getType())) {
      if (boxedShape) {
        if (mlir::isa<fir::ShiftType>(boxedShape.getType()))
          return mlir::failure();
      } else if (op.getShape() &&
                 mlir::isa<fir::ShiftType>(op.getShape().getType())) {
        return mlir::failure();
      }
    }

    rewriter.modifyOpInPlace(op, [&]() {
      op.getMemrefMutable().assign(boxedMemref);
      if (boxedShape)
        op.getShapeMutable().assign(boxedShape);
      if (boxedSlice)
        op.getSliceMutable().assign(boxedSlice);
      if (shiftedIndices)
        op.getIndicesMutable().assign(*shiftedIndices);
      op.getTypeparamsMutable().assign(
          typeparamsForCanonicalizedMemref(boxedMemref, op.getTypeparams()));
    });
    return mlir::success();
  }

private:
  using IndicesVectorTy = std::vector<mlir::Value>;

  // array_coor on a fir.box carries length/type info in the descriptor;
  // explicit typeparams are only valid for plain ref memrefs.
  static mlir::ValueRange
  typeparamsForCanonicalizedMemref(mlir::Value memref,
                                   mlir::ValueRange typeparams) {
    if (mlir::isa<fir::BaseBoxType>(memref.getType()))
      return mlir::ValueRange{};
    return typeparams;
  }

  // Build fir.shape<rank> from fir.box_dims extents of box.
  static mlir::Value getShapeFromBoxDims(mlir::Value box, unsigned rank,
                                         mlir::Location loc,
                                         mlir::Operation *insertBefore,
                                         mlir::PatternRewriter &rewriter) {
    auto boxType = mlir::dyn_cast<fir::BaseBoxType>(box.getType());
    if (!boxType || boxType.isAssumedRank() || fir::getBoxRank(boxType) != rank)
      return nullptr;
    mlir::OpBuilder::InsertionGuard guard(rewriter);
    rewriter.setInsertionPoint(insertBefore);
    llvm::SmallVector<mlir::Value> extents;
    fir::genDimInfoFromBox(rewriter, loc, box, /*lbounds=*/nullptr, &extents,
                           /*strides=*/nullptr);
    return fir::ShapeOp::create(rewriter, loc, extents);
  }

  // If v is a shape_shift operation:
  //   fir.shape_shift %l1, %e1, %l2, %e2, ...
  // create:
  //   fir.shape %e1, %e2, ...
  static mlir::Value getShapeFromShapeShift(mlir::Value v,
                                            mlir::PatternRewriter &rewriter) {
    auto shapeShiftOp =
        mlir::dyn_cast_or_null<fir::ShapeShiftOp>(v.getDefiningOp());
    if (!shapeShiftOp)
      return nullptr;
    mlir::OpBuilder::InsertionGuard guard(rewriter);
    rewriter.setInsertionPoint(shapeShiftOp);
    return fir::ShapeOp::create(rewriter, shapeShiftOp.getLoc(),
                                shapeShiftOp.getExtents());
  }

  static std::optional<IndicesVectorTy>
  getShiftedIndices(mlir::Value v, mlir::ValueRange indices,
                    mlir::PatternRewriter &rewriter) {
    auto insertAdjustments = [&](mlir::Operation *op, mlir::ValueRange lbs) {
      // Compute the shifted indices using the extended type.
      // Note that this can probably result in less efficient
      // MLIR and further LLVM IR due to the extra conversions.
      mlir::OpBuilder::InsertPoint savedIP = rewriter.saveInsertionPoint();
      rewriter.setInsertionPoint(op);
      mlir::Location loc = op->getLoc();
      mlir::Type idxTy = rewriter.getIndexType();
      mlir::Value one = mlir::arith::ConstantOp::create(
          rewriter, loc, idxTy, rewriter.getIndexAttr(1));
      rewriter.restoreInsertionPoint(savedIP);
      auto nsw = mlir::arith::IntegerOverflowFlags::nsw;

      IndicesVectorTy shiftedIndices;
      for (auto [lb, idx] : llvm::zip(lbs, indices)) {
        mlir::Value extLb = fir::ConvertOp::create(rewriter, loc, idxTy, lb);
        mlir::Value extIdx = fir::ConvertOp::create(rewriter, loc, idxTy, idx);
        mlir::Value add =
            mlir::arith::AddIOp::create(rewriter, loc, extIdx, extLb, nsw);
        mlir::Value sub =
            mlir::arith::SubIOp::create(rewriter, loc, add, one, nsw);
        shiftedIndices.push_back(sub);
      }

      return shiftedIndices;
    };

    if (auto shiftOp =
            mlir::dyn_cast_or_null<fir::ShiftOp>(v.getDefiningOp())) {
      return insertAdjustments(shiftOp.getOperation(), shiftOp.getOrigins());
    } else if (auto shapeShiftOp = mlir::dyn_cast_or_null<fir::ShapeShiftOp>(
                   v.getDefiningOp())) {
      return insertAdjustments(shapeShiftOp.getOperation(),
                               shapeShiftOp.getOrigins());
    }

    return std::nullopt;
  }
};

// Pull a producer fir.array_coor (via a fir.convert that reinterprets a
// scalar element address as an M-D array ref) into the consumer fir.array_coor.
// Mirrors the slice-designator lowering pattern emitted by ConvertHLFIRtoFIR
// for Fortran array sections like `dx(1:3)` or `dx(1:3, 4)`.
//
// Pattern:
//   %outer = fir.array_coor %base(%base_shape) %ox_0, ..., %ox_{N-1}
//                : (BaseTy, ShapeTy, index, ...) -> !fir.ref<EleTy>
//   %view  = fir.convert %outer
//                : !fir.ref<EleTy> -> !fir.ref<!fir.array<...x EleTy>>  (M-D)
//   %inner = fir.array_coor %view(%inner_shape) %ix_0, ..., %ix_{M-1}
//                : (!fir.ref<!fir.array<...>>, !fir.shape<M>, index, ...)
//                -> !fir.ref<EleTy>
//
// In Fortran column-major storage, the M leading dimensions of the original
// array are exactly the dimensions of the contiguous sub-array; the trailing
// (N-M) outer indices stay fixed. So %inner is rewritten as:
//   %combined_i = arith.addi %ox_i, arith.subi(%ix_i, 1)        for i in 0..M-1
//   %inner = fir.array_coor %base(%base_shape)
//                %combined_0, ..., %combined_{M-1},
//                %ox_M, ..., %ox_{N-1}
//                : (BaseTy, ShapeTy, index, ...) -> !fir.ref<EleTy>
//
// Restrictions (kept minimal):
//   - No slice on outer or inner.
//   - Inner shape must be a plain fir.shape (default lb=1); shift/shape_shift
//     on the inner are not handled.
//   - Outer's result type must be a scalar ref (not an array ref).
//   - Convert source type must equal outer's result type.
//   - Convert result type's element type must equal outer's pointee.
//   - Inner rank M <= outer rank N.
//   - Neither op carries typeparams.
//   - Mirrors SimplifyArrayCoorOp's ACC/CUF guards.
struct MergeArrayCoorOnConvert
    : public mlir::OpRewritePattern<fir::ArrayCoorOp> {
  using mlir::OpRewritePattern<fir::ArrayCoorOp>::OpRewritePattern;
  llvm::LogicalResult
  matchAndRewrite(fir::ArrayCoorOp inner,
                  mlir::PatternRewriter &rewriter) const override {
    if (inner.getSlice() || !inner.getTypeparams().empty())
      return mlir::failure();

    auto innerShapeOp = mlir::dyn_cast_or_null<fir::ShapeOp>(
        inner.getShape() ? inner.getShape().getDefiningOp() : nullptr);
    if (!innerShapeOp)
      return mlir::failure();

    auto convertOp = inner.getMemref().getDefiningOp<fir::ConvertOp>();
    if (!convertOp)
      return mlir::failure();

    auto outer = convertOp.getValue().getDefiningOp<fir::ArrayCoorOp>();
    if (!outer)
      return mlir::failure();

    if (outer.getSlice() || !outer.getTypeparams().empty())
      return mlir::failure();

    mlir::Type outerResTy = outer.getType();
    mlir::Type outerEleTy = fir::dyn_cast_ptrEleTy(outerResTy);
    if (!outerEleTy || mlir::isa<fir::SequenceType>(outerEleTy))
      return mlir::failure();

    if (convertOp.getValue().getType() != outerResTy)
      return mlir::failure();

    mlir::Type convResTy = convertOp.getType();
    mlir::Type convResEleTy = fir::dyn_cast_ptrEleTy(convResTy);
    auto convResSeqTy = mlir::dyn_cast_or_null<fir::SequenceType>(convResEleTy);
    if (!convResSeqTy || convResSeqTy.getEleTy() != outerEleTy)
      return mlir::failure();

    unsigned innerRank = inner.getIndices().size();
    unsigned outerRank = outer.getIndices().size();
    if (innerRank == 0 || innerRank > outerRank)
      return mlir::failure();

    if (innerShapeOp.getExtents().size() != innerRank)
      return mlir::failure();

    // Skip when folding the convert+outer chain into the inner array_coor
    // would cross an ACC data-clause or CUDA kernel boundary.
    if (arrayCoorFoldCrossesACCOrCUDABoundary(inner, {convertOp, outer}))
      return mlir::failure();

    mlir::Location loc = inner.getLoc();
    mlir::Type idxTy = rewriter.getIndexType();
    mlir::Value one = mlir::arith::ConstantIndexOp::create(rewriter, loc, 1);
    auto nsw = mlir::arith::IntegerOverflowFlags::nsw;

    auto toIndex = [&](mlir::Value v) -> mlir::Value {
      if (v.getType() == idxTy)
        return v;
      return fir::ConvertOp::create(rewriter, loc, idxTy, v);
    };

    llvm::SmallVector<mlir::Value> combinedIndices;
    combinedIndices.reserve(outerRank);
    for (unsigned i = 0; i < innerRank; ++i) {
      mlir::Value outerIdx = toIndex(outer.getIndices()[i]);
      mlir::Value innerIdx = toIndex(inner.getIndices()[i]);
      mlir::Value innerMinusOne =
          mlir::arith::SubIOp::create(rewriter, loc, innerIdx, one, nsw);
      mlir::Value combined = mlir::arith::AddIOp::create(
          rewriter, loc, outerIdx, innerMinusOne, nsw);
      combinedIndices.push_back(combined);
    }
    for (unsigned i = innerRank; i < outerRank; ++i)
      combinedIndices.push_back(outer.getIndices()[i]);

    rewriter.replaceOpWithNewOp<fir::ArrayCoorOp>(
        inner, inner.getType(), outer.getMemref(), outer.getShape(),
        /*slice=*/mlir::Value{}, combinedIndices, outer.getTypeparams());
    return mlir::success();
  }
};

void fir::ArrayCoorOp::getCanonicalizationPatterns(
    mlir::RewritePatternSet &patterns, mlir::MLIRContext *context) {
  // TODO: !fir.shape<1> operand may be removed from array_coor always.
  patterns.add<SimplifyArrayCoorOp, MergeArrayCoorOnConvert>(context);
}

std::optional<std::int64_t> fir::ArrayCoorOp::getViewOffset(mlir::OpResult) {
  // TODO: we can try to compute the constant offset.
  return std::nullopt;
}

//===----------------------------------------------------------------------===//
// BoxAddrOp
//===----------------------------------------------------------------------===//

void fir::BoxAddrOp::build(mlir::OpBuilder &builder,
                           mlir::OperationState &result, mlir::Value val) {
  mlir::Type type =
      llvm::TypeSwitch<mlir::Type, mlir::Type>(val.getType())
          .Case([&](fir::BaseBoxType ty) -> mlir::Type {
            mlir::Type eleTy = ty.getEleTy();
            if (fir::isa_ref_type(eleTy))
              return eleTy;
            return fir::ReferenceType::get(eleTy);
          })
          .Case([&](fir::BoxCharType ty) -> mlir::Type {
            return fir::ReferenceType::get(ty.getEleTy());
          })
          .Case([&](fir::BoxProcType ty) { return ty.getEleTy(); })
          .Default([&](const auto &) { return mlir::Type{}; });
  assert(type && "bad val type");
  build(builder, result, type, val);
}

mlir::OpFoldResult fir::BoxAddrOp::fold(FoldAdaptor adaptor) {
  if (auto *v = getVal().getDefiningOp()) {
    if (auto box = mlir::dyn_cast<fir::EmboxOp>(v)) {
      // Fold only if not sliced
      if (!box.getSlice() && box.getMemref().getType() == getType()) {
        propagateAttributes(getOperation(), box.getMemref().getDefiningOp());
        return box.getMemref();
      }
    }
    // fir.create_box always describes the whole array (no slice), so the
    // base address is exactly its memref operand. The verifier guarantees the
    // result box preserves the memref storage kind, so the types match.
    if (auto box = mlir::dyn_cast<fir::CreateBoxOp>(v)) {
      if (box.getMemref().getType() == getType()) {
        propagateAttributes(getOperation(), box.getMemref().getDefiningOp());
        return box.getMemref();
      }
    }
    if (auto box = mlir::dyn_cast<fir::EmboxCharOp>(v))
      if (box.getMemref().getType() == getType())
        return box.getMemref();
  }
  return {};
}

std::optional<std::int64_t> fir::BoxAddrOp::getViewOffset(mlir::OpResult) {
  // fir.box_addr just returns the base address stored inside a box,
  // so the direct accesses through the base address and through the box
  // are not offsetted.
  return 0;
}

mlir::Speculation::Speculatability fir::BoxAddrOp::getSpeculatability() {
  // Do not speculate fir.box_addr with BoxProcType and BoxCharType
  // inputs.
  if (!mlir::isa<fir::BaseBoxType>(getVal().getType()))
    return mlir::Speculation::NotSpeculatable;
  return mayBeAbsentBox(getVal()) ? mlir::Speculation::NotSpeculatable
                                  : mlir::Speculation::Speculatable;
}

//===----------------------------------------------------------------------===//
// BoxCharLenOp
//===----------------------------------------------------------------------===//

mlir::OpFoldResult fir::BoxCharLenOp::fold(FoldAdaptor adaptor) {
  if (auto v = getVal().getDefiningOp()) {
    if (auto box = mlir::dyn_cast<fir::EmboxCharOp>(v))
      return box.getLen();
  }
  return {};
}

//===----------------------------------------------------------------------===//
// BoxEleSizeOp
//===----------------------------------------------------------------------===//

namespace {
/// Canonicalize fir.box_elesize when the element type is statically known.
struct FoldBoxEleSize : public mlir::OpRewritePattern<fir::BoxEleSizeOp> {
  using mlir::OpRewritePattern<fir::BoxEleSizeOp>::OpRewritePattern;

  mlir::LogicalResult
  matchAndRewrite(fir::BoxEleSizeOp op,
                  mlir::PatternRewriter &rewriter) const override {
    auto boxTy = mlir::cast<fir::BaseBoxType>(op.getVal().getType());

    // ClassType is polymorphic — the actual runtime type may differ, size
    // not statically known.
    if (mlir::isa<fir::ClassType>(boxTy))
      return mlir::failure();

    // unwrapInnerType peels through any ptr/heap/array wrapper inside the box
    // to reach the scalar element type.
    mlir::Type eleTy = boxTy.unwrapInnerType();

    // NoneType is the element type for TYPE(*) assumed-type boxes — no static
    // element type.
    if (mlir::isa<mlir::NoneType>(eleTy))
      return mlir::failure();

    // Bail out for types whose size is only known at runtime as a string whose
    // length is unknown or a record type with fields with a dynamic size
    if (fir::hasDynamicSize(eleTy))
      return mlir::failure();

    mlir::DataLayout dl = mlir::DataLayout::closest(op);
    fir::KindMapping kindMap = fir::getKindMapping(op.getOperation());

    auto sizeAndAlign =
        fir::getTypeSizeAndAlignment(op.getLoc(), eleTy, dl, kindMap);
    if (!sizeAndAlign)
      return mlir::failure();

    // The descriptor stores the byte stride between elements (not the raw
    // natural size), so we must round up to alignment just as
    // fir::computeElementDistance does.
    auto [size, alignment] = *sizeAndAlign;
    std::int64_t distance = llvm::alignTo(size, alignment);

    mlir::Type resultTy = op.getType();
    rewriter.replaceOpWithNewOp<mlir::arith::ConstantOp>(
        op, resultTy, rewriter.getIntegerAttr(resultTy, distance));
    return mlir::success();
  }
};
} // namespace

void fir::BoxEleSizeOp::getCanonicalizationPatterns(
    mlir::RewritePatternSet &results, mlir::MLIRContext *context) {
  results.insert<FoldBoxEleSize>(context);
}

//===----------------------------------------------------------------------===//
// BoxDimsOp
//===----------------------------------------------------------------------===//

namespace {
/// fir.box_dims of a descriptor built by fir.create_box with a statically known
/// dimension forwards the lower bound, extent, and byte stride operands that
/// built that dimension. These are plain SSA operands of the create_box, so
/// replacing the box_dims results with them is a value forwarding; the
/// create_box dominates the box_dims, so the operands are already available.
struct SimplifyBoxDimsFromCreateBox
    : public mlir::OpRewritePattern<fir::BoxDimsOp> {
  using mlir::OpRewritePattern<fir::BoxDimsOp>::OpRewritePattern;

  mlir::LogicalResult
  matchAndRewrite(fir::BoxDimsOp op,
                  mlir::PatternRewriter &rewriter) const override {
    auto createBox = op.getVal().getDefiningOp<fir::CreateBoxOp>();
    if (!createBox)
      return mlir::failure();

    std::optional<llvm::APInt> constantDim = fir::getIntIfConstant(op.getDim());
    std::optional<std::int64_t> dim =
        constantDim ? constantDim->trySExtValue() : std::nullopt;
    if (!dim || *dim < 0 || *dim >= createBox.getRank())
      return mlir::failure();

    // The create_box operands are AnyIntegerType and may differ from the
    // index-typed box_dims results, so convert them.
    mlir::Location loc = op.getLoc();
    rewriter.replaceOp(op,
                       {rewriter.createOrFold<fir::ConvertOp>(
                            loc, op.getType(0), createBox.getLbounds()[*dim]),
                        rewriter.createOrFold<fir::ConvertOp>(
                            loc, op.getType(1), createBox.getExtents()[*dim]),
                        rewriter.createOrFold<fir::ConvertOp>(
                            loc, op.getType(2), createBox.getStrides()[*dim])});
    return mlir::success();
  }
};
} // namespace

void fir::BoxDimsOp::getCanonicalizationPatterns(
    mlir::RewritePatternSet &results, mlir::MLIRContext *context) {
  results.insert<SimplifyBoxDimsFromCreateBox>(context);
}

/// Get the result types packed in a tuple tuple
mlir::Type fir::BoxDimsOp::getTupleType() {
  // note: triple, but 4 is nearest power of 2
  llvm::SmallVector<mlir::Type> triple{
      getResult(0).getType(), getResult(1).getType(), getResult(2).getType()};
  return mlir::TupleType::get(getContext(), triple);
}

mlir::Speculation::Speculatability fir::BoxDimsOp::getSpeculatability() {
  return mayBeAbsentBox(getVal()) ? mlir::Speculation::NotSpeculatable
                                  : mlir::Speculation::Speculatable;
}

//===----------------------------------------------------------------------===//
// BoxRankOp
//===----------------------------------------------------------------------===//

void fir::BoxRankOp::getEffects(
    llvm::SmallVectorImpl<
        mlir::SideEffects::EffectInstance<mlir::MemoryEffects::Effect>>
        &effects) {
  mlir::OpOperand &inputBox = getBoxMutable();
  if (fir::isBoxAddress(inputBox.get().getType()))
    effects.emplace_back(mlir::MemoryEffects::Read::get(), &inputBox,
                         mlir::SideEffects::DefaultResource::get());
}

//===----------------------------------------------------------------------===//
// CallOp
//===----------------------------------------------------------------------===//

mlir::FunctionType fir::CallOp::getFunctionType() {
  return mlir::FunctionType::get(getContext(), getOperandTypes(),
                                 getResultTypes());
}

void fir::CallOp::print(mlir::OpAsmPrinter &p) {
  bool isDirect = getCallee().has_value();
  p << ' ';
  if (isDirect)
    p << *getCallee();
  else
    p << getOperand(0);
  p << '(' << (*this)->getOperands().drop_front(isDirect ? 0 : 1) << ')';

  // Print `proc_attrs<...>`, if present.
  fir::FortranProcedureFlagsEnumAttr procAttrs = getProcedureAttrsAttr();
  if (procAttrs &&
      procAttrs.getValue() != fir::FortranProcedureFlagsEnum::none) {
    p << ' ' << fir::FortranProcedureFlagsEnumAttr::getMnemonic();
    p.printStrippedAttrOrType(procAttrs);
  }

  // Print 'fastmath<...>' (if it has non-default value) before
  // any other attributes.
  mlir::arith::FastMathFlagsAttr fmfAttr = getFastmathAttr();
  if (fmfAttr.getValue() != mlir::arith::FastMathFlags::none) {
    p << ' ' << mlir::arith::FastMathFlagsAttr::getMnemonic();
    p.printStrippedAttrOrType(fmfAttr);
  }

  p.printOptionalAttrDict((*this)->getAttrs(),
                          {fir::CallOp::getCalleeAttrNameStr(),
                           getFastmathAttrName(), getProcedureAttrsAttrName(),
                           getArgAttrsAttrName(), getResAttrsAttrName()});
  p << " : ";
  mlir::call_interface_impl::printFunctionSignature(
      p, getArgs().drop_front(isDirect ? 0 : 1).getTypes(), getArgAttrsAttr(),
      /*isVariadic=*/false, getResultTypes(), getResAttrsAttr());
}

mlir::ParseResult fir::CallOp::parse(mlir::OpAsmParser &parser,
                                     mlir::OperationState &result) {
  llvm::SmallVector<mlir::OpAsmParser::UnresolvedOperand> operands;
  if (parser.parseOperandList(operands))
    return mlir::failure();

  mlir::NamedAttrList attrs;
  mlir::SymbolRefAttr funcAttr;
  bool isDirect = operands.empty();
  if (isDirect)
    if (parser.parseAttribute(funcAttr, fir::CallOp::getCalleeAttrNameStr(),
                              attrs))
      return mlir::failure();

  if (parser.parseOperandList(operands, mlir::OpAsmParser::Delimiter::Paren))
    return mlir::failure();

  // Parse `proc_attrs<...>`, if present.
  fir::FortranProcedureFlagsEnumAttr procAttr;
  if (mlir::succeeded(parser.parseOptionalKeyword(
          fir::FortranProcedureFlagsEnumAttr::getMnemonic())))
    if (parser.parseCustomAttributeWithFallback(
            procAttr, mlir::Type{}, getProcedureAttrsAttrName(result.name),
            attrs))
      return mlir::failure();

  // Parse 'fastmath<...>', if present.
  mlir::arith::FastMathFlagsAttr fmfAttr;
  llvm::StringRef fmfAttrName = getFastmathAttrName(result.name);
  if (mlir::succeeded(parser.parseOptionalKeyword(fmfAttrName)))
    if (parser.parseCustomAttributeWithFallback(fmfAttr, mlir::Type{},
                                                fmfAttrName, attrs))
      return mlir::failure();

  if (parser.parseOptionalAttrDict(attrs) || parser.parseColon())
    return mlir::failure();
  llvm::SmallVector<mlir::Type> argTypes;
  llvm::SmallVector<mlir::Type> resTypes;
  llvm::SmallVector<mlir::DictionaryAttr> argAttrs;
  llvm::SmallVector<mlir::DictionaryAttr> resultAttrs;
  if (mlir::call_interface_impl::parseFunctionSignature(
          parser, argTypes, argAttrs, resTypes, resultAttrs))
    return parser.emitError(parser.getNameLoc(), "expected function type");
  mlir::FunctionType funcType =
      mlir::FunctionType::get(parser.getContext(), argTypes, resTypes);
  if (isDirect) {
    if (parser.resolveOperands(operands, funcType.getInputs(),
                               parser.getNameLoc(), result.operands))
      return mlir::failure();
  } else {
    auto funcArgs =
        llvm::ArrayRef<mlir::OpAsmParser::UnresolvedOperand>(operands)
            .drop_front();
    if (parser.resolveOperand(operands[0], funcType, result.operands) ||
        parser.resolveOperands(funcArgs, funcType.getInputs(),
                               parser.getNameLoc(), result.operands))
      return mlir::failure();
  }
  result.attributes = attrs;
  mlir::call_interface_impl::addArgAndResultAttrs(
      parser.getBuilder(), result, argAttrs, resultAttrs,
      getArgAttrsAttrName(result.name), getResAttrsAttrName(result.name));
  result.addTypes(funcType.getResults());
  return mlir::success();
}

void fir::CallOp::build(mlir::OpBuilder &builder, mlir::OperationState &result,
                        mlir::func::FuncOp callee, mlir::ValueRange operands) {
  result.addOperands(operands);
  result.addAttribute(getCalleeAttrNameStr(), mlir::SymbolRefAttr::get(callee));
  result.addTypes(callee.getFunctionType().getResults());
}

void fir::CallOp::build(mlir::OpBuilder &builder, mlir::OperationState &result,
                        mlir::SymbolRefAttr callee,
                        llvm::ArrayRef<mlir::Type> results,
                        mlir::ValueRange operands) {
  result.addOperands(operands);
  if (callee)
    result.addAttribute(getCalleeAttrNameStr(), callee);
  result.addTypes(results);
}

void fir::CallOp::setCalleeFromCallable(mlir::CallInterfaceCallable callee) {
  if (auto symbolRef = llvm::dyn_cast<mlir::SymbolRefAttr>(callee)) {
    // Handling a direct call.
    bool wasIndirect = llvm::isa<mlir::Value>(getCallableForCallee());
    (*this)->setAttr(getCalleeAttrName(), symbolRef);
    // If it was indirect before, the operand list and associated attributes
    // needs to be fixed up.
    if (wasIndirect) {
      assert(getNumOperands() > 0 && "indirect call must have callee operand");
      (*this)->eraseOperand(0);
      // Fix arg_attrs to remove the first (callee) operand if needed.
      if (auto argAttrs = getArgAttrsAttr()) {
        // Since we already removed the first operand, check that number
        // of attributes is one more than number of operands.
        assert(argAttrs.size() == getNumOperands() + 1 &&
               "arg_attrs must be one-per-operand");
        llvm::SmallVector<mlir::Attribute> newAttrs(argAttrs.begin() + 1,
                                                    argAttrs.end());
        if (newAttrs.empty())
          (*this)->removeAttr(getArgAttrsAttrName());
        else
          (*this)->setAttr(getArgAttrsAttrName(),
                           mlir::ArrayAttr::get(getContext(), newAttrs));
      }
    }
    return;
  }
  // The provided callee makes this an indirect call now.
  bool wasIndirect = llvm::isa<mlir::Value>(getCallableForCallee());
  (*this)->removeAttr(getCalleeAttrNameStr());
  mlir::Value calleeVal = llvm::cast<mlir::Value>(callee);
  if (wasIndirect) {
    setOperand(0, calleeVal);
  } else {
    (*this)->insertOperands(0, calleeVal);
    // Make arg_attrs consistent in size with operands by adding an empty dict
    // for the callee.
    if (auto argAttrs = getArgAttrsAttr()) {
      assert(argAttrs.size() == getNumOperands() - 1 &&
             "arg_attrs must be one-per-operand");
      llvm::SmallVector<mlir::Attribute> newAttrs;
      newAttrs.reserve(1 + argAttrs.size());
      newAttrs.push_back(mlir::DictionaryAttr::get(getContext(), {}));
      newAttrs.append(argAttrs.begin(), argAttrs.end());
      (*this)->setAttr(getArgAttrsAttrName(),
                       mlir::ArrayAttr::get(getContext(), newAttrs));
    }
  }
}

//===----------------------------------------------------------------------===//
// CharConvertOp
//===----------------------------------------------------------------------===//

llvm::LogicalResult fir::CharConvertOp::verify() {
  auto unwrap = [&](mlir::Type t) {
    t = fir::unwrapSequenceType(fir::dyn_cast_ptrEleTy(t));
    return mlir::dyn_cast<fir::CharacterType>(t);
  };
  auto inTy = unwrap(getFrom().getType());
  auto outTy = unwrap(getTo().getType());
  if (!(inTy && outTy))
    return emitOpError("not a reference to a character");
  if (inTy.getFKind() == outTy.getFKind())
    return emitOpError("buffers must have different KIND values");
  return mlir::success();
}

//===----------------------------------------------------------------------===//
// CmpOp
//===----------------------------------------------------------------------===//

template <typename OPTY>
static void printCmpOp(mlir::OpAsmPrinter &p, OPTY op) {
  p << ' ';
  auto predSym = mlir::arith::symbolizeCmpFPredicate(
      op->template getAttrOfType<mlir::IntegerAttr>(
            OPTY::getPredicateAttrName())
          .getInt());
  assert(predSym.has_value() && "invalid symbol value for predicate");
  p << '"' << mlir::arith::stringifyCmpFPredicate(predSym.value()) << '"'
    << ", ";
  p.printOperand(op.getLhs());
  p << ", ";
  p.printOperand(op.getRhs());
  p.printOptionalAttrDict(op->getAttrs(),
                          /*elidedAttrs=*/{OPTY::getPredicateAttrName()});
  p << " : " << op.getLhs().getType();
}

template <typename OPTY>
static mlir::ParseResult parseCmpOp(mlir::OpAsmParser &parser,
                                    mlir::OperationState &result) {
  llvm::SmallVector<mlir::OpAsmParser::UnresolvedOperand> ops;
  mlir::NamedAttrList attrs;
  mlir::Attribute predicateNameAttr;
  mlir::Type type;
  if (parser.parseAttribute(predicateNameAttr, OPTY::getPredicateAttrName(),
                            attrs) ||
      parser.parseComma() || parser.parseOperandList(ops, 2) ||
      parser.parseOptionalAttrDict(attrs) || parser.parseColonType(type) ||
      parser.resolveOperands(ops, type, result.operands))
    return mlir::failure();

  if (!mlir::isa<mlir::StringAttr>(predicateNameAttr))
    return parser.emitError(parser.getNameLoc(),
                            "expected string comparison predicate attribute");

  // Rewrite string attribute to an enum value.
  llvm::StringRef predicateName =
      mlir::cast<mlir::StringAttr>(predicateNameAttr).getValue();
  auto predicate = fir::CmpcOp::getPredicateByName(predicateName);
  auto builder = parser.getBuilder();
  mlir::Type i1Type = builder.getI1Type();
  attrs.set(OPTY::getPredicateAttrName(),
            builder.getI64IntegerAttr(static_cast<std::int64_t>(predicate)));
  result.attributes = attrs;
  result.addTypes({i1Type});
  return mlir::success();
}

//===----------------------------------------------------------------------===//
// BitcastOp
//===----------------------------------------------------------------------===//

static bool isBitcastCompatibleType(mlir::Type ty) {
  return mlir::isa<mlir::IntegerType, mlir::FloatType, fir::LogicalType>(ty) ||
         (mlir::isa<fir::CharacterType>(ty) &&
          mlir::cast<fir::CharacterType>(ty).getLen() ==
              fir::CharacterType::singleton());
}

static std::optional<unsigned> getBitcastBitSize(mlir::Type ty) {
  if (auto intTy = mlir::dyn_cast<mlir::IntegerType>(ty))
    return intTy.getWidth();
  if (auto floatTy = mlir::dyn_cast<mlir::FloatType>(ty))
    return floatTy.getWidth();
  // Bit size of fir.logical and fir.char depends on the kind map which is not
  // available in the verifier without an expensive lookup.
  return std::nullopt;
}

llvm::LogicalResult fir::BitcastOp::verify() {
  mlir::Type inType = getValue().getType();
  mlir::Type outType = getType();
  if (!isBitcastCompatibleType(inType))
    return emitOpError("input type is not bitcast compatible: ") << inType;
  if (!isBitcastCompatibleType(outType))
    return emitOpError("output type is not bitcast compatible: ") << outType;
  auto inBits = getBitcastBitSize(inType);
  auto outBits = getBitcastBitSize(outType);
  if (inBits && outBits && *inBits != *outBits)
    return emitOpError("bit size mismatch: input has ")
           << *inBits << " bits but output has " << *outBits << " bits";
  return mlir::success();
}

mlir::OpFoldResult fir::BitcastOp::fold(FoldAdaptor adaptor) {
  if (getValue().getType() == getType())
    return getValue();
  if (auto inner = getValue().getDefiningOp<fir::BitcastOp>()) {
    if (inner.getValue().getType() == getType())
      return inner.getValue();
    getValueMutable().assign(inner.getValue());
    return getResult();
  }
  return {};
}

//===----------------------------------------------------------------------===//
// CmpcOp
//===----------------------------------------------------------------------===//

void fir::buildCmpCOp(mlir::OpBuilder &builder, mlir::OperationState &result,
                      mlir::arith::CmpFPredicate predicate, mlir::Value lhs,
                      mlir::Value rhs) {
  result.addOperands({lhs, rhs});
  result.types.push_back(builder.getI1Type());
  result.addAttribute(
      fir::CmpcOp::getPredicateAttrName(),
      builder.getI64IntegerAttr(static_cast<std::int64_t>(predicate)));
}

mlir::arith::CmpFPredicate
fir::CmpcOp::getPredicateByName(llvm::StringRef name) {
  auto pred = mlir::arith::symbolizeCmpFPredicate(name);
  assert(pred.has_value() && "invalid predicate name");
  return pred.value();
}

void fir::CmpcOp::print(mlir::OpAsmPrinter &p) { printCmpOp(p, *this); }

mlir::ParseResult fir::CmpcOp::parse(mlir::OpAsmParser &parser,
                                     mlir::OperationState &result) {
  return parseCmpOp<fir::CmpcOp>(parser, result);
}

//===----------------------------------------------------------------------===//
// VolatileCastOp
//===----------------------------------------------------------------------===//

static bool typesMatchExceptForVolatility(mlir::Type fromType,
                                          mlir::Type toType) {
  // If we can change only the volatility and get identical types, then we
  // match.
  if (fir::updateTypeWithVolatility(fromType, fir::isa_volatile_type(toType)) ==
      toType)
    return true;

  // Otherwise, recurse on the element types if the base classes are the same.
  const bool match =
      llvm::TypeSwitch<mlir::Type, bool>(fromType)
          .Case<fir::BoxType, fir::ReferenceType, fir::ClassType>(
              [&](auto type) {
                using TYPE = decltype(type);
                // If we are not the same base class, then we don't match.
                auto castedToType = mlir::dyn_cast<TYPE>(toType);
                if (!castedToType)
                  return false;
                // If we are the same base class, we match if the element types
                // match.
                return typesMatchExceptForVolatility(type.getEleTy(),
                                                     castedToType.getEleTy());
              })
          .Default([](mlir::Type) { return false; });

  return match;
}

llvm::LogicalResult fir::VolatileCastOp::verify() {
  mlir::Type fromType = getValue().getType();
  mlir::Type toType = getType();
  if (!typesMatchExceptForVolatility(fromType, toType))
    return emitOpError("types must be identical except for volatility ")
           << fromType << " / " << toType;
  return mlir::success();
}

mlir::OpFoldResult fir::VolatileCastOp::fold(FoldAdaptor adaptor) {
  if (getValue().getType() == getType())
    return getValue();
  return {};
}

//===----------------------------------------------------------------------===//
// ConvertOp
//===----------------------------------------------------------------------===//

void fir::ConvertOp::getCanonicalizationPatterns(
    mlir::RewritePatternSet &results, mlir::MLIRContext *context) {
  results.insert<ConvertConvertOptPattern, ConvertAscendingIndexOptPattern,
                 ConvertDescendingIndexOptPattern, RedundantConvertOptPattern,
                 CombineConvertOptPattern, CombineConvertTruncOptPattern,
                 ForwardConstantConvertPattern, ChainedPointerConvertsPattern>(
      context);
}

static bool isI1(mlir::Type ty) {
  if (auto intTy = mlir::dyn_cast<mlir::IntegerType>(ty))
    return intTy.getWidth() == 1;
  return false;
}

mlir::OpFoldResult fir::ConvertOp::fold(FoldAdaptor adaptor) {
  if (getValue().getType() == getType())
    return getValue();
  if (matchPattern(getValue(), mlir::m_Op<fir::ConvertOp>())) {
    auto inner = mlir::cast<fir::ConvertOp>(getValue().getDefiningOp());
    // (convert (convert 'a : logical -> i1) : i1 -> logical) ==> forward 'a
    if (auto toTy = mlir::dyn_cast<fir::LogicalType>(getType()))
      if (auto fromTy =
              mlir::dyn_cast<fir::LogicalType>(inner.getValue().getType()))
        if (mlir::isa<mlir::IntegerType>(inner.getType()) && (toTy == fromTy))
          return inner.getValue();
    // (convert (convert 'a : i1 -> logical) : logical -> i1) ==> forward 'a
    if (auto toTy = mlir::dyn_cast<mlir::IntegerType>(getType()))
      if (auto fromTy =
              mlir::dyn_cast<mlir::IntegerType>(inner.getValue().getType()))
        if (mlir::isa<fir::LogicalType>(inner.getType()) && (toTy == fromTy) &&
            (fromTy.getWidth() == 1))
          return inner.getValue();
  }
  // (convert (bitcast 'cst : int -> logical) : logical -> i1) ==> `'cst != 0`
  if (isI1(getType()) &&
      matchPattern(getValue(), mlir::m_Op<fir::BitcastOp>())) {
    auto bitcast = mlir::cast<fir::BitcastOp>(getValue().getDefiningOp());
    if (auto cst = fir::getIntIfConstant(bitcast.getValue()))
      return mlir::IntegerAttr::get(getType(), cst->isZero() ? 0 : 1);
  }
  return {};
}

//===----------------------------------------------------------------------===//
// Logical binary operations fold helpers
//===----------------------------------------------------------------------===//

/// If \p value is a fir.convert of an arith.constant i1, return the i1 value.
static std::optional<bool> getLogicalConstant(mlir::Value value) {
  mlir::Value maybeConvertInput = value;
  if (auto convertOp = value.getDefiningOp<fir::ConvertOp>())
    maybeConvertInput = convertOp.getValue();
  if (auto cst = fir::getIntIfConstant(maybeConvertInput))
    return !cst->isZero();
  return std::nullopt;
}

/// Try to fold a logical binary operation where both operands are constants.
/// For integer result types, return an IntegerAttr directly (materialized by
/// the dialect's materializeConstant hook).  For fir.logical result types we
/// cannot create new operations in a folder, so return one of the existing
/// constant operands if its truth value matches the intended result.
static mlir::OpFoldResult
foldLogicalBinaryWithConstants(bool result, mlir::Type resTy, bool lhsCst,
                               mlir::Value lhs, bool rhsCst, mlir::Value rhs) {
  if (auto intTy = mlir::dyn_cast<mlir::IntegerType>(resTy))
    return mlir::IntegerAttr::get(intTy, result ? 1 : 0);
  if (lhsCst == result)
    return lhs;
  if (rhsCst == result)
    return rhs;
  return {};
}

mlir::OpFoldResult fir::LogicalAndOp::fold(FoldAdaptor adaptor) {
  auto lhsCst = getLogicalConstant(getLhs());
  auto rhsCst = getLogicalConstant(getRhs());
  if (lhsCst && rhsCst)
    return foldLogicalBinaryWithConstants(*lhsCst && *rhsCst, getType(),
                                          *lhsCst, getLhs(), *rhsCst, getRhs());
  // logical_and(x, true) -> x
  if (rhsCst && *rhsCst)
    return getLhs();
  if (lhsCst && *lhsCst)
    return getRhs();
  return {};
}

mlir::OpFoldResult fir::LogicalOrOp::fold(FoldAdaptor adaptor) {
  auto lhsCst = getLogicalConstant(getLhs());
  auto rhsCst = getLogicalConstant(getRhs());
  if (lhsCst && rhsCst)
    return foldLogicalBinaryWithConstants(*lhsCst || *rhsCst, getType(),
                                          *lhsCst, getLhs(), *rhsCst, getRhs());
  // logical_or(x, false) -> x
  if (rhsCst && !*rhsCst)
    return getLhs();
  if (lhsCst && !*lhsCst)
    return getRhs();
  return {};
}

mlir::OpFoldResult fir::EqvOp::fold(FoldAdaptor adaptor) {
  auto lhsCst = getLogicalConstant(getLhs());
  auto rhsCst = getLogicalConstant(getRhs());
  if (lhsCst && rhsCst)
    return foldLogicalBinaryWithConstants(*lhsCst == *rhsCst, getType(),
                                          *lhsCst, getLhs(), *rhsCst, getRhs());
  // eqv(x, true) -> x
  if (rhsCst && *rhsCst)
    return getLhs();
  if (lhsCst && *lhsCst)
    return getRhs();
  return {};
}

mlir::OpFoldResult fir::NeqvOp::fold(FoldAdaptor adaptor) {
  auto lhsCst = getLogicalConstant(getLhs());
  auto rhsCst = getLogicalConstant(getRhs());
  if (lhsCst && rhsCst)
    return foldLogicalBinaryWithConstants(*lhsCst != *rhsCst, getType(),
                                          *lhsCst, getLhs(), *rhsCst, getRhs());
  // neqv(x, false) -> x
  if (rhsCst && !*rhsCst)
    return getLhs();
  if (lhsCst && !*lhsCst)
    return getRhs();
  return {};
}

bool fir::ConvertOp::isInteger(mlir::Type ty) {
  return mlir::isa<mlir::IntegerType, mlir::IndexType, fir::IntegerType>(ty);
}

bool fir::ConvertOp::isIntegerCompatible(mlir::Type ty) {
  return isInteger(ty) || mlir::isa<fir::LogicalType>(ty);
}

bool fir::ConvertOp::isFloatCompatible(mlir::Type ty) {
  return mlir::isa<mlir::FloatType>(ty);
}

bool fir::ConvertOp::isPointerCompatible(mlir::Type ty) {
  return mlir::isa<fir::ReferenceType, fir::PointerType, fir::HeapType,
                   fir::LLVMPointerType, mlir::MemRefType, mlir::FunctionType,
                   fir::TypeDescType, mlir::LLVM::LLVMPointerType>(ty);
}

static std::optional<mlir::Type> getVectorElementType(mlir::Type ty) {
  mlir::Type elemTy;
  if (mlir::isa<fir::VectorType>(ty))
    elemTy = mlir::dyn_cast<fir::VectorType>(ty).getElementType();
  else if (mlir::isa<mlir::VectorType>(ty))
    elemTy = mlir::dyn_cast<mlir::VectorType>(ty).getElementType();
  else
    return std::nullopt;

  // e.g. fir.vector<4:ui32> => mlir.vector<4xi32>
  // e.g. mlir.vector<4xui32> => mlir.vector<4xi32>
  if (elemTy.isUnsignedInteger()) {
    elemTy = mlir::IntegerType::get(
        ty.getContext(), mlir::dyn_cast<mlir::IntegerType>(elemTy).getWidth());
  }
  return elemTy;
}

static std::optional<uint64_t> getVectorLen(mlir::Type ty) {
  if (mlir::isa<fir::VectorType>(ty))
    return mlir::dyn_cast<fir::VectorType>(ty).getLen();
  else if (mlir::isa<mlir::VectorType>(ty)) {
    // fir.vector only supports 1-D vector
    if (!(mlir::dyn_cast<mlir::VectorType>(ty).isScalable()))
      return mlir::dyn_cast<mlir::VectorType>(ty).getShape()[0];
  }

  return std::nullopt;
}

bool fir::ConvertOp::areVectorsCompatible(mlir::Type inTy, mlir::Type outTy) {
  if (!(mlir::isa<fir::VectorType>(inTy) &&
        mlir::isa<mlir::VectorType>(outTy)) &&
      !(mlir::isa<mlir::VectorType>(inTy) && mlir::isa<fir::VectorType>(outTy)))
    return false;

  // Only support integer, unsigned and real vector
  // Both vectors must have the same element type
  std::optional<mlir::Type> inElemTy = getVectorElementType(inTy);
  std::optional<mlir::Type> outElemTy = getVectorElementType(outTy);
  if (!inElemTy.has_value() || !outElemTy.has_value() ||
      inElemTy.value() != outElemTy.value())
    return false;

  // Both vectors must have the same number of elements
  std::optional<uint64_t> inLen = getVectorLen(inTy);
  std::optional<uint64_t> outLen = getVectorLen(outTy);
  if (!inLen.has_value() || !outLen.has_value() ||
      inLen.value() != outLen.value())
    return false;

  return true;
}

static bool areRecordsCompatible(mlir::Type inTy, mlir::Type outTy) {
  // Both records must have the same field types.
  // Trust frontend semantics for in-depth checks, such as if both records
  // have the BIND(C) attribute.
  auto inRecTy = mlir::dyn_cast<fir::RecordType>(inTy);
  auto outRecTy = mlir::dyn_cast<fir::RecordType>(outTy);
  return inRecTy && outRecTy && inRecTy.getTypeList() == outRecTy.getTypeList();
}

bool fir::ConvertOp::canBeConverted(mlir::Type inType, mlir::Type outType) {
  if (inType == outType)
    return true;
  return (isPointerCompatible(inType) && isPointerCompatible(outType)) ||
         (isIntegerCompatible(inType) && isIntegerCompatible(outType)) ||
         (isInteger(inType) && isFloatCompatible(outType)) ||
         (isFloatCompatible(inType) && isInteger(outType)) ||
         (isFloatCompatible(inType) && isFloatCompatible(outType)) ||
         (isInteger(inType) && isPointerCompatible(outType)) ||
         (isPointerCompatible(inType) && isInteger(outType)) ||
         (mlir::isa<fir::BoxType>(inType) &&
          mlir::isa<fir::BoxType>(outType)) ||
         (mlir::isa<fir::BoxProcType>(inType) &&
          mlir::isa<fir::BoxProcType>(outType)) ||
         (fir::isa_complex(inType) && fir::isa_complex(outType)) ||
         (fir::isBoxedRecordType(inType) && fir::isPolymorphicType(outType)) ||
         (fir::isPolymorphicType(inType) && fir::isPolymorphicType(outType)) ||
         (fir::isPolymorphicType(inType) && mlir::isa<BoxType>(outType)) ||
         areVectorsCompatible(inType, outType) ||
         areRecordsCompatible(inType, outType);
}

// In general, ptrtoint-like conversions are allowed to lose volatility
// information because they are either:
//
// 1. passing an entity to an external function and there's nothing we can do
//    about volatility after that happens, or
// 2. for code generation, at which point we represent volatility with
//    attributes on the LLVM instructions and intrinsics.
//
// For all other cases, volatility ought to match exactly.
static mlir::LogicalResult verifyVolatility(mlir::Type inType,
                                            mlir::Type outType) {
  const bool toLLVMPointer = mlir::isa<mlir::LLVM::LLVMPointerType>(outType);
  const bool toInteger = fir::isa_integer(outType);

  // When converting references to classes or allocatables into boxes for
  // runtime arguments, we cast away all the volatility information and pass a
  // box<none>. This is allowed.
  const bool isBoxNoneLike = [&]() {
    if (fir::isBoxNone(outType))
      return true;
    if (auto referenceType = mlir::dyn_cast<fir::ReferenceType>(outType)) {
      if (fir::isBoxNone(referenceType.getElementType())) {
        return true;
      }
    }
    return false;
  }();

  const bool isPtrToIntLike = toLLVMPointer || toInteger || isBoxNoneLike;
  if (isPtrToIntLike) {
    return mlir::success();
  }

  // In all other cases, we need to check for an exact volatility match.
  return mlir::success(fir::isa_volatile_type(inType) ==
                       fir::isa_volatile_type(outType));
}

llvm::LogicalResult fir::ConvertOp::verify() {
  mlir::Type inType = getValue().getType();
  mlir::Type outType = getType();
  if (fir::useStrictVolatileVerification()) {
    if (failed(verifyVolatility(inType, outType))) {
      return emitOpError("this conversion does not preserve volatility: ")
             << inType << " / " << outType;
    }
  }
  if (canBeConverted(inType, outType))
    return mlir::success();
  return emitOpError("invalid type conversion")
         << getValue().getType() << " / " << getType();
}

mlir::Speculation::Speculatability fir::ConvertOp::getSpeculatability() {
  // fir.convert is speculatable, in general. The only concern may be
  // converting from or/and to floating point types, which may trigger
  // some FP exceptions. Disallow speculating such converts for the time being.
  // Also disallow speculation for converts to/from non-FIR types, except
  // for some builtin types.
  auto canSpeculateType = [](mlir::Type ty) {
    if (fir::isa_fir_type(ty) || fir::isa_integer(ty) ||
        mlir::isa<mlir::MemRefType>(ty))
      return true;
    return false;
  };
  return (canSpeculateType(getValue().getType()) && canSpeculateType(getType()))
             ? mlir::Speculation::Speculatable
             : mlir::Speculation::NotSpeculatable;
}

//===----------------------------------------------------------------------===//
// CoordinateOp
//===----------------------------------------------------------------------===//

void fir::CoordinateOp::build(mlir::OpBuilder &builder,
                              mlir::OperationState &result,
                              mlir::Type resultType, mlir::Value ref,
                              mlir::ValueRange coor) {
  llvm::SmallVector<int32_t> fieldIndices;
  llvm::SmallVector<mlir::Value> dynamicIndices;
  bool anyField = false;
  for (mlir::Value index : coor) {
    if (auto field = index.getDefiningOp<fir::FieldIndexOp>()) {
      auto recTy = mlir::cast<fir::RecordType>(field.getOnType());
      fieldIndices.push_back(recTy.getFieldIndex(field.getFieldId()));
      anyField = true;
    } else {
      fieldIndices.push_back(fir::CoordinateOp::kDynamicIndex);
      dynamicIndices.push_back(index);
    }
  }
  auto typeAttr = mlir::TypeAttr::get(ref.getType());
  if (anyField) {
    build(builder, result, resultType, ref, dynamicIndices, typeAttr,
          builder.getDenseI32ArrayAttr(fieldIndices));
  } else {
    build(builder, result, resultType, ref, dynamicIndices, typeAttr, nullptr);
  }
}

void fir::CoordinateOp::build(mlir::OpBuilder &builder,
                              mlir::OperationState &result,
                              mlir::Type resultType, mlir::Value ref,
                              llvm::ArrayRef<fir::IntOrValue> coor) {
  llvm::SmallVector<int32_t> fieldIndices;
  llvm::SmallVector<mlir::Value> dynamicIndices;
  bool anyField = false;
  for (fir::IntOrValue index : coor) {
    llvm::TypeSwitch<fir::IntOrValue>(index)
        .Case([&](mlir::IntegerAttr intAttr) {
          fieldIndices.push_back(intAttr.getInt());
          anyField = true;
        })
        .Case([&](mlir::Value value) {
          dynamicIndices.push_back(value);
          fieldIndices.push_back(fir::CoordinateOp::kDynamicIndex);
        });
  }
  auto typeAttr = mlir::TypeAttr::get(ref.getType());
  if (anyField) {
    build(builder, result, resultType, ref, dynamicIndices, typeAttr,
          builder.getDenseI32ArrayAttr(fieldIndices));
  } else {
    build(builder, result, resultType, ref, dynamicIndices, typeAttr, nullptr);
  }
}

void fir::CoordinateOp::print(mlir::OpAsmPrinter &p) {
  p << ' ' << getRef();
  if (!getFieldIndicesAttr()) {
    p << ", " << getCoor();
  } else {
    mlir::Type eleTy = fir::getFortranElementType(getRef().getType());
    for (auto index : getIndices()) {
      p << ", ";
      llvm::TypeSwitch<fir::IntOrValue>(index)
          .Case([&](mlir::IntegerAttr intAttr) {
            if (auto recordType = llvm::dyn_cast<fir::RecordType>(eleTy)) {
              int fieldId = intAttr.getInt();
              if (fieldId < static_cast<int>(recordType.getNumFields())) {
                auto nameAndType = recordType.getTypeList()[fieldId];
                p << std::get<std::string>(nameAndType);
                eleTy = fir::getFortranElementType(
                    std::get<mlir::Type>(nameAndType));
                return;
              }
            }
            // Invalid index, still print it so that invalid IR can be
            // investigated.
            p << intAttr;
          })
          .Case([&](mlir::Value value) { p << value; });
    }
  }
  p.printOptionalAttrDict(
      (*this)->getAttrs(),
      /*elideAttrs=*/{getBaseTypeAttrName(), getFieldIndicesAttrName()});
  p << " : ";
  p.printFunctionalType(getOperandTypes(), (*this)->getResultTypes());
}

mlir::ParseResult fir::CoordinateOp::parse(mlir::OpAsmParser &parser,
                                           mlir::OperationState &result) {
  mlir::OpAsmParser::UnresolvedOperand memref;
  if (parser.parseOperand(memref) || parser.parseComma())
    return mlir::failure();
  llvm::SmallVector<mlir::OpAsmParser::UnresolvedOperand> coorOperands;
  llvm::SmallVector<std::pair<llvm::StringRef, int>> fieldNames;
  llvm::SmallVector<int32_t> fieldIndices;
  while (true) {
    llvm::StringRef fieldName;
    if (mlir::succeeded(parser.parseOptionalKeyword(&fieldName))) {
      fieldNames.push_back({fieldName, static_cast<int>(fieldIndices.size())});
      // Actual value will be computed later when base type has been parsed.
      fieldIndices.push_back(0);
    } else {
      mlir::OpAsmParser::UnresolvedOperand index;
      if (parser.parseOperand(index))
        return mlir::failure();
      fieldIndices.push_back(fir::CoordinateOp::kDynamicIndex);
      coorOperands.push_back(index);
    }
    if (mlir::failed(parser.parseOptionalComma()))
      break;
  }
  llvm::SmallVector<mlir::OpAsmParser::UnresolvedOperand> allOperands;
  allOperands.push_back(memref);
  allOperands.append(coorOperands.begin(), coorOperands.end());
  mlir::FunctionType funcTy;
  auto loc = parser.getCurrentLocation();
  if (parser.parseOptionalAttrDict(result.attributes) ||
      parser.parseColonType(funcTy) ||
      parser.resolveOperands(allOperands, funcTy.getInputs(), loc,
                             result.operands) ||
      parser.addTypesToList(funcTy.getResults(), result.types))
    return mlir::failure();
  result.addAttribute(getBaseTypeAttrName(result.name),
                      mlir::TypeAttr::get(funcTy.getInput(0)));
  if (!fieldNames.empty()) {
    mlir::Type eleTy = fir::getFortranElementType(funcTy.getInput(0));
    for (auto [fieldName, operandPosition] : fieldNames) {
      auto recTy = llvm::dyn_cast<fir::RecordType>(eleTy);
      if (!recTy)
        return parser.emitError(
            loc, "base must be a derived type when field name appears");
      unsigned fieldNum = recTy.getFieldIndex(fieldName);
      if (fieldNum > recTy.getNumFields())
        return parser.emitError(loc)
               << "field '" << fieldName
               << "' is not a component or subcomponent of the base type";
      fieldIndices[operandPosition] = fieldNum;
      eleTy = fir::getFortranElementType(
          std::get<mlir::Type>(recTy.getTypeList()[fieldNum]));
    }
    result.addAttribute(getFieldIndicesAttrName(result.name),
                        parser.getBuilder().getDenseI32ArrayAttr(fieldIndices));
  }
  return mlir::success();
}

llvm::LogicalResult fir::CoordinateOp::verify() {
  const mlir::Type refTy = getRef().getType();
  if (fir::isa_ref_type(refTy)) {
    auto eleTy = fir::dyn_cast_ptrEleTy(refTy);
    if (auto arrTy = mlir::dyn_cast<fir::SequenceType>(eleTy)) {
      if (arrTy.hasUnknownShape())
        return emitOpError("cannot find coordinate in unknown shape");
      if (arrTy.getConstantRows() < arrTy.getDimension() - 1)
        return emitOpError("cannot find coordinate with unknown extents");
    }
    if (!(fir::isa_aggregate(eleTy) || fir::isa_complex(eleTy) ||
          fir::isa_char_string(eleTy)))
      return emitOpError("cannot apply to this element type");
  }
  auto eleTy = fir::dyn_cast_ptrOrBoxEleTy(refTy);
  unsigned dimension = 0;
  const unsigned numCoors = getCoor().size();
  for (auto coorOperand : llvm::enumerate(getCoor())) {
    auto co = coorOperand.value();
    if (dimension == 0 && mlir::isa<fir::SequenceType>(eleTy)) {
      dimension = mlir::cast<fir::SequenceType>(eleTy).getDimension();
      if (dimension == 0)
        return emitOpError("cannot apply to array of unknown rank");
    }
    if (auto *defOp = co.getDefiningOp()) {
      if (auto index = mlir::dyn_cast<fir::LenParamIndexOp>(defOp)) {
        // Recovering a LEN type parameter only makes sense from a boxed
        // value. For a bare reference, the LEN type parameters must be
        // passed as additional arguments to `index`.
        if (mlir::isa<fir::BoxType>(refTy)) {
          if (coorOperand.index() != numCoors - 1)
            return emitOpError("len_param_index must be last argument");
          if (getNumOperands() != 2)
            return emitOpError("too many operands for len_param_index case");
        }
        if (eleTy != index.getOnType())
          return emitOpError(
              "len_param_index type not compatible with reference type");
        return mlir::success();
      } else if (auto index = mlir::dyn_cast<fir::FieldIndexOp>(defOp)) {
        if (eleTy != index.getOnType())
          return emitOpError(
              "field_index type not compatible with reference type");
        if (auto recTy = mlir::dyn_cast<fir::RecordType>(eleTy)) {
          eleTy = recTy.getType(index.getFieldName());
          continue;
        }
        return emitOpError("field_index not applied to !fir.type");
      }
    }
    if (dimension) {
      if (--dimension == 0)
        eleTy = mlir::cast<fir::SequenceType>(eleTy).getElementType();
    } else {
      if (auto t = mlir::dyn_cast<mlir::TupleType>(eleTy)) {
        // FIXME: Generally, we don't know which field of the tuple is being
        // referred to unless the operand is a constant. Just assume everything
        // is good in the tuple case for now.
        return mlir::success();
      } else if (auto t = mlir::dyn_cast<fir::RecordType>(eleTy)) {
        // FIXME: This is the same as the tuple case.
        return mlir::success();
      } else if (auto t = mlir::dyn_cast<mlir::ComplexType>(eleTy)) {
        eleTy = t.getElementType();
      } else if (auto t = mlir::dyn_cast<fir::CharacterType>(eleTy)) {
        if (t.getLen() == fir::CharacterType::singleton())
          return emitOpError("cannot apply to character singleton");
        eleTy = fir::CharacterType::getSingleton(t.getContext(), t.getFKind());
        if (fir::unwrapRefType(getType()) != eleTy)
          return emitOpError("character type mismatch");
      } else {
        return emitOpError("invalid parameters (too many)");
      }
    }
  }
  return mlir::success();
}

fir::CoordinateIndicesAdaptor fir::CoordinateOp::getIndices() {
  return CoordinateIndicesAdaptor(getFieldIndicesAttr(), getCoor());
}

std::optional<std::int64_t> fir::CoordinateOp::getViewOffset(mlir::OpResult) {
  // TODO: we can try to compute the constant offset.
  return std::nullopt;
}

mlir::Speculation::Speculatability fir::CoordinateOp::getSpeculatability() {
  const mlir::Type refTy = getRef().getType();
  if (fir::isa_ref_type(refTy))
    return mlir::Speculation::Speculatable;

  return mayBeAbsentBox(getRef()) ? mlir::Speculation::NotSpeculatable
                                  : mlir::Speculation::Speculatable;
}

//===----------------------------------------------------------------------===//
// DispatchOp
//===----------------------------------------------------------------------===//

llvm::LogicalResult fir::DispatchOp::verify() {
  // Check that pass_arg_pos is in range of actual operands. pass_arg_pos is
  // unsigned so check for less than zero is not needed.
  if (getPassArgPos() && *getPassArgPos() > (getArgOperands().size() - 1))
    return emitOpError(
        "pass_arg_pos must be smaller than the number of operands");

  // Operand pointed by pass_arg_pos must have polymorphic type.
  if (getPassArgPos() &&
      !fir::isPolymorphicType(getArgOperands()[*getPassArgPos()].getType()))
    return emitOpError("pass_arg_pos must be a polymorphic operand");
  return mlir::success();
}

mlir::FunctionType fir::DispatchOp::getFunctionType() {
  return mlir::FunctionType::get(getContext(), getOperandTypes(),
                                 getResultTypes());
}

//===----------------------------------------------------------------------===//
// TypeInfoOp
//===----------------------------------------------------------------------===//

void fir::TypeInfoOp::build(mlir::OpBuilder &builder,
                            mlir::OperationState &result, fir::RecordType type,
                            fir::RecordType parentType,
                            llvm::ArrayRef<mlir::NamedAttribute> attrs) {
  result.addRegion();
  result.addRegion();
  result.addAttribute(mlir::SymbolTable::getSymbolAttrName(),
                      builder.getStringAttr(type.getName()));
  result.addAttribute(getTypeAttrName(result.name), mlir::TypeAttr::get(type));
  if (parentType)
    result.addAttribute(getParentTypeAttrName(result.name),
                        mlir::TypeAttr::get(parentType));
  result.addAttributes(attrs);
}

llvm::LogicalResult fir::TypeInfoOp::verify() {
  if (!getDispatchTable().empty())
    for (auto &op : getDispatchTable().front().without_terminator())
      if (!mlir::isa<fir::DTEntryOp>(op))
        return op.emitOpError("dispatch table must contain dt_entry");

  if (!mlir::isa<fir::RecordType>(getType()))
    return emitOpError("type must be a fir.type");

  if (getParentType() && !mlir::isa<fir::RecordType>(*getParentType()))
    return emitOpError("parent_type must be a fir.type");
  return mlir::success();
}

//===----------------------------------------------------------------------===//
// EmboxOp
//===----------------------------------------------------------------------===//

// Conversions from reference types to box types must preserve volatility.
static llvm::LogicalResult
verifyEmboxOpVolatilityInvariants(mlir::Type memrefType,
                                  mlir::Type resultType) {

  if (!fir::useStrictVolatileVerification())
    return mlir::success();

  mlir::Type boxElementType =
      llvm::TypeSwitch<mlir::Type, mlir::Type>(resultType)
          .Case<fir::BoxType, fir::ClassType>(
              [&](auto type) { return type.getEleTy(); })
          .Default([&](mlir::Type type) { return type; });

  // If the embox is simply wrapping a non-volatile type into a volatile box,
  // we're not losing any volatility information.
  if (boxElementType == memrefType) {
    return mlir::success();
  }

  // Otherwise, the volatility of the input and result must match.
  const bool volatilityMatches =
      fir::isa_volatile_type(memrefType) == fir::isa_volatile_type(resultType);

  return mlir::success(volatilityMatches);
}

llvm::LogicalResult fir::EmboxOp::verify() {
  auto eleTy = fir::dyn_cast_ptrEleTy(getMemref().getType());
  bool isArray = false;
  if (auto seqTy = mlir::dyn_cast<fir::SequenceType>(eleTy)) {
    eleTy = seqTy.getEleTy();
    isArray = true;
  }
  if (hasLenParams()) {
    auto lenPs = numLenParams();
    if (auto rt = mlir::dyn_cast<fir::RecordType>(eleTy)) {
      if (lenPs != rt.getNumLenParams())
        return emitOpError("number of LEN params does not correspond"
                           " to the !fir.type type");
    } else if (auto strTy = mlir::dyn_cast<fir::CharacterType>(eleTy)) {
      if (strTy.getLen() != fir::CharacterType::unknownLen())
        return emitOpError("CHARACTER already has static LEN");
    } else {
      return emitOpError("LEN parameters require CHARACTER or derived type");
    }
    for (auto lp : getTypeparams())
      if (!fir::isa_integer(lp.getType()))
        return emitOpError("LEN parameters must be integral type");
  }
  if (getShape() && !isArray)
    return emitOpError("shape must not be provided for a scalar");
  if (getSlice() && !isArray)
    return emitOpError("slice must not be provided for a scalar");
  if (getSourceBox() && !mlir::isa<fir::ClassType>(getResult().getType()))
    return emitOpError("source_box must be used with fir.class result type");
  if (failed(verifyEmboxOpVolatilityInvariants(getMemref().getType(),
                                               getResult().getType())))
    return emitOpError(
               "cannot convert between volatile and non-volatile types:")
           << " " << getMemref().getType() << " " << getResult().getType();
  return mlir::success();
}

/// Returns true if \p extent matches the extent of the \p box's
/// dimension \p dim.
static bool isBoxExtent(mlir::Value box, std::int64_t dim, mlir::Value extent) {
  if (auto op = extent.getDefiningOp<fir::BoxDimsOp>())
    if (op.getVal() == box && op.getExtent() == extent)
      if (auto dimOperand = fir::getIntIfConstant(op.getDim()))
        return *dimOperand == dim;
  return false;
}

/// Returns true if \p lb matches the lower bound of the \p box's
/// dimension \p dim. If \p mayHaveNonDefaultLowerBounds is false,
/// then \p lb may be an integer constant 1.
static bool isBoxLb(mlir::Value box, std::int64_t dim, mlir::Value lb,
                    bool mayHaveNonDefaultLowerBounds = true) {
  if (auto op = lb.getDefiningOp<fir::BoxDimsOp>()) {
    if (op.getVal() == box && op.getLowerBound() == lb)
      if (auto dimOperand = fir::getIntIfConstant(op.getDim()))
        return *dimOperand == dim;
  } else if (!mayHaveNonDefaultLowerBounds) {
    if (auto constantLb = fir::getIntIfConstant(lb))
      return constantLb->isOne();
  }
  return false;
}

/// Returns true if \p ub matches the upper bound of the \p box's
/// dimension \p dim. If \p mayHaveNonDefaultLowerBounds is false,
/// then the dimension's lower bound may be an integer constant 1.
/// Note that the upper bound is usually a result of computation
/// involving the lower bound and the extent, and the function
/// tries its best to recognize the computation pattern.
/// The conservative result 'false' does not necessarily mean
/// that \p ub is not an actual upper bound value.
static bool isBoxUb(mlir::Value box, std::int64_t dim, mlir::Value ub,
                    bool mayHaveNonDefaultLowerBounds = true) {
  if (auto sub1 = ub.getDefiningOp<mlir::arith::SubIOp>()) {
    auto one = fir::getIntIfConstant(sub1.getOperand(1));
    if (!one || !one->isOne())
      return false;
    if (auto add = sub1.getOperand(0).getDefiningOp<mlir::arith::AddIOp>())
      if ((isBoxLb(box, dim, add.getOperand(0)) &&
           isBoxExtent(box, dim, add.getOperand(1))) ||
          (isBoxLb(box, dim, add.getOperand(1)) &&
           isBoxExtent(box, dim, add.getOperand(0))))
        return true;
  } else if (!mayHaveNonDefaultLowerBounds) {
    return isBoxExtent(box, dim, ub);
  }
  return false;
}

/// Checks if the given \p sliceOp specifies a contiguous
/// array slice. If \p checkWhole is true, then the check
/// is done for all dimensions, otherwise, only for the innermost
/// dimension.
/// The simplest way to prove that this is an contiguous slice
/// is to check whether the slice stride(s) is 1.
/// For more complex cases, extra information must be provided
/// by the caller:
///   * \p origBox - if not null, then the source array is represented
///     with this !fir.box value. The box is used to recognize
///     the full dimension slices, which are specified by the triplets
///     computed from the dimensions' lower bounds and extents.
///   * \p mayHaveNonDefaultLowerBounds may be set to false to indicate
///     that the source entity has default lower bounds, so the full
///     dimension slices computations may use 1 for the lower bound.
static bool isContiguousArraySlice(fir::SliceOp sliceOp, bool checkWhole = true,
                                   mlir::Value origBox = nullptr,
                                   bool mayHaveNonDefaultLowerBounds = true) {
  if (sliceOp.getFields().empty() && sliceOp.getSubstr().empty()) {
    // TODO: generalize code for the triples analysis with
    // hlfir::designatePreservesContinuity, especially when
    // recognition of the whole dimension slices is added.
    auto triples = sliceOp.getTriples();
    assert((triples.size() % 3) == 0 && "invalid triples size");

    // A slice with step=1 in the innermost dimension preserves
    // the continuity of the array in the innermost dimension.
    // If checkWhole is false, then check only the innermost slice triples.
    std::size_t checkUpTo = checkWhole ? triples.size() : 3;
    checkUpTo = std::min(checkUpTo, triples.size());
    for (std::size_t i = 0; i < checkUpTo; i += 3) {
      if (triples[i] != triples[i + 1]) {
        // This is a section of the dimension. Only allow it
        // to be the first triple, if the source of the slice
        // is a boxed array. If it is a raw pointer, then
        // the result will still be contiguous, as long as
        // the strides are all ones.
        // When origBox is not null, we must prove that the triple
        // covers the whole dimension and the stride is one,
        // before claiming contiguity for this dimension.
        if (i != 0 && origBox) {
          std::int64_t dim = i / 3;
          if (!isBoxLb(origBox, dim, triples[i],
                       mayHaveNonDefaultLowerBounds) ||
              !isBoxUb(origBox, dim, triples[i + 1],
                       mayHaveNonDefaultLowerBounds))
            return false;
        }
        auto constantStep = fir::getIntIfConstant(triples[i + 2]);
        if (!constantStep || !constantStep->isOne())
          return false;
      }
    }
    return true;
  }
  return false;
}

bool fir::isContiguousEmbox(fir::EmboxOp embox, bool checkWhole) {
  auto sliceArg = embox.getSlice();
  if (!sliceArg)
    return true;

  if (auto sliceOp =
          mlir::dyn_cast_or_null<fir::SliceOp>(sliceArg.getDefiningOp()))
    return isContiguousArraySlice(sliceOp, checkWhole);

  return false;
}

std::optional<std::int64_t> fir::EmboxOp::getViewOffset(mlir::OpResult) {
  // The address offset is zero, unless there is a slice.
  // TODO: we can handle slices that leave the base address untouched.
  if (!getSlice())
    return 0;
  return std::nullopt;
}

mlir::Speculation::Speculatability fir::EmboxOp::getSpeculatability() {
  // The operation is always safe to evaluate if it has the "optional"
  // attribute, otherwise it is not safe to evaluate if the input may
  // be absent.
  if (getOptional())
    return mlir::Speculation::Speculatable;
  return (getSourceBox() && mayBeAbsentBox(getSourceBox()))
             ? mlir::Speculation::NotSpeculatable
             : mlir::Speculation::Speculatable;
}

//===----------------------------------------------------------------------===//
// CreateBoxOp
//===----------------------------------------------------------------------===//

unsigned fir::CreateBoxOp::getRank() {
  auto boxTy = mlir::cast<fir::BaseBoxType>(getResult().getType());
  if (auto seqTy = mlir::dyn_cast<fir::SequenceType>(
          fir::unwrapRefType(boxTy.getEleTy())))
    return seqTy.getDimension();
  return 0;
}

llvm::LogicalResult fir::CreateBoxOp::verify() {
  auto memEleTy = fir::dyn_cast_ptrEleTy(getMemref().getType());
  auto seqTy = mlir::dyn_cast_or_null<fir::SequenceType>(memEleTy);
  if (!seqTy)
    return emitOpError("memref must be a reference to an array");

  auto boxTy = mlir::cast<fir::BaseBoxType>(getResult().getType());
  auto boxSeqTy =
      mlir::dyn_cast<fir::SequenceType>(fir::unwrapRefType(boxTy.getEleTy()));
  if (!boxSeqTy)
    return emitOpError("result box must describe an array");

  // The result box must preserve the memref's storage kind so that the
  // descriptor's CFI attribute field is set correctly and the value matches a
  // box loaded from the corresponding !fir.ref<!fir.box<...>>:
  //   !fir.heap<...> -> !fir.box<!fir.heap<...>> (allocatable)
  //   !fir.ptr<...>  -> !fir.box<!fir.ptr<...>>  (pointer)
  //   !fir.ref<...>  -> !fir.box<...>            (plain)
  mlir::Type memrefTy = getMemref().getType();
  mlir::Type boxEleTy = boxTy.getEleTy();
  if (mlir::isa<fir::HeapType>(memrefTy) !=
          mlir::isa<fir::HeapType>(boxEleTy) ||
      mlir::isa<fir::PointerType>(memrefTy) !=
          mlir::isa<fir::PointerType>(boxEleTy))
    return emitOpError(
        "result box element storage kind must match the memref storage kind");

  unsigned rank = boxSeqTy.getDimension();
  if (seqTy.getDimension() != rank)
    return emitOpError("memref rank does not match result box rank");
  if (getLbounds().size() != rank || getExtents().size() != rank ||
      getStrides().size() != rank)
    return emitOpError("expected ")
           << rank << " values for each of lbounds, extents, and strides";

  mlir::Type eleTy = boxSeqTy.getEleTy();
  if (fir::isPolymorphicType(boxTy))
    return emitOpError("result box element type must not be polymorphic");
  if (fir::characterWithDynamicLen(eleTy) ||
      fir::isRecordWithTypeParameters(eleTy))
    return emitOpError("result box element type must be statically sized");
  if (failed(verifyEmboxOpVolatilityInvariants(getMemref().getType(),
                                               getResult().getType())))
    return emitOpError(
               "cannot convert between volatile and non-volatile types:")
           << " " << getMemref().getType() << " " << getResult().getType();
  return mlir::success();
}

std::optional<std::int64_t> fir::CreateBoxOp::getViewOffset(mlir::OpResult) {
  // The base pointer is the view source and the descriptor addresses relative
  // to it, so the view offset onto the source is zero.
  return 0;
}

//===----------------------------------------------------------------------===//
// EmboxCharOp
//===----------------------------------------------------------------------===//

llvm::LogicalResult fir::EmboxCharOp::verify() {
  auto eleTy = fir::dyn_cast_ptrEleTy(getMemref().getType());
  if (!mlir::dyn_cast_or_null<fir::CharacterType>(eleTy))
    return mlir::failure();
  return mlir::success();
}

//===----------------------------------------------------------------------===//
// EmboxProcOp
//===----------------------------------------------------------------------===//

llvm::LogicalResult fir::EmboxProcOp::verify() {
  // host bindings (optional) must be a reference to a tuple
  if (auto h = getHost()) {
    if (auto r = mlir::dyn_cast<fir::ReferenceType>(h.getType()))
      if (mlir::isa<mlir::TupleType>(r.getEleTy()))
        return mlir::success();
    return mlir::failure();
  }
  return mlir::success();
}

//===----------------------------------------------------------------------===//
// TypeDescOp
//===----------------------------------------------------------------------===//

void fir::TypeDescOp::build(mlir::OpBuilder &, mlir::OperationState &result,
                            mlir::TypeAttr inty) {
  result.addAttribute("in_type", inty);
  result.addTypes(TypeDescType::get(inty.getValue()));
}

mlir::ParseResult fir::TypeDescOp::parse(mlir::OpAsmParser &parser,
                                         mlir::OperationState &result) {
  mlir::Type intype;
  if (parser.parseType(intype))
    return mlir::failure();
  result.addAttribute("in_type", mlir::TypeAttr::get(intype));
  mlir::Type restype = fir::TypeDescType::get(intype);
  if (parser.addTypeToList(restype, result.types))
    return mlir::failure();
  return mlir::success();
}

void fir::TypeDescOp::print(mlir::OpAsmPrinter &p) {
  p << ' ' << getOperation()->getAttr("in_type");
  p.printOptionalAttrDict(getOperation()->getAttrs(), {"in_type"});
}

llvm::LogicalResult fir::TypeDescOp::verify() {
  mlir::Type resultTy = getType();
  if (auto tdesc = mlir::dyn_cast<fir::TypeDescType>(resultTy)) {
    if (tdesc.getOfTy() != getInType())
      return emitOpError("wrapped type mismatched");
    return mlir::success();
  }
  return emitOpError("must be !fir.tdesc type");
}

//===----------------------------------------------------------------------===//
// GlobalOp
//===----------------------------------------------------------------------===//

mlir::Type fir::GlobalOp::resultType() {
  return wrapAllocaResultType(getType());
}

mlir::ParseResult fir::GlobalOp::parse(mlir::OpAsmParser &parser,
                                       mlir::OperationState &result) {
  // Parse the optional linkage
  llvm::StringRef linkage;
  auto &builder = parser.getBuilder();
  if (mlir::succeeded(parser.parseOptionalKeyword(&linkage))) {
    if (fir::GlobalOp::verifyValidLinkage(linkage))
      return mlir::failure();
    mlir::StringAttr linkAttr = builder.getStringAttr(linkage);
    result.addAttribute(fir::GlobalOp::getLinkNameAttrName(result.name),
                        linkAttr);
  }

  // Parse the name as a symbol reference attribute.
  mlir::SymbolRefAttr nameAttr;
  if (parser.parseAttribute(nameAttr,
                            fir::GlobalOp::getSymrefAttrName(result.name),
                            result.attributes))
    return mlir::failure();
  result.addAttribute(mlir::SymbolTable::getSymbolAttrName(),
                      nameAttr.getRootReference());

  bool simpleInitializer = false;
  if (mlir::succeeded(parser.parseOptionalLParen())) {
    mlir::Attribute attr;
    if (parser.parseAttribute(attr, getInitValAttrName(result.name),
                              result.attributes) ||
        parser.parseRParen())
      return mlir::failure();
    simpleInitializer = true;
  }

  if (parser.parseOptionalAttrDict(result.attributes))
    return mlir::failure();

  if (succeeded(
          parser.parseOptionalKeyword(getConstantAttrName(result.name)))) {
    // if "constant" keyword then mark this as a constant, not a variable
    result.addAttribute(getConstantAttrName(result.name),
                        builder.getUnitAttr());
  }

  if (succeeded(parser.parseOptionalKeyword(getTargetAttrName(result.name))))
    result.addAttribute(getTargetAttrName(result.name), builder.getUnitAttr());

  mlir::Type globalType;
  if (parser.parseColonType(globalType))
    return mlir::failure();

  result.addAttribute(fir::GlobalOp::getTypeAttrName(result.name),
                      mlir::TypeAttr::get(globalType));

  if (simpleInitializer) {
    result.addRegion();
  } else {
    // Parse the optional initializer body.
    auto parseResult =
        parser.parseOptionalRegion(*result.addRegion(), /*arguments=*/{});
    if (parseResult.has_value() && mlir::failed(*parseResult))
      return mlir::failure();
  }
  return mlir::success();
}

void fir::GlobalOp::print(mlir::OpAsmPrinter &p) {
  if (getLinkName())
    p << ' ' << *getLinkName();
  p << ' ';
  p.printAttributeWithoutType(getSymrefAttr());
  if (auto val = getValueOrNull())
    p << '(' << val << ')';
  // Print all other attributes that are not pretty printed here.
  p.printOptionalAttrDict((*this)->getAttrs(), /*elideAttrs=*/{
                              getSymNameAttrName(), getSymrefAttrName(),
                              getTypeAttrName(), getConstantAttrName(),
                              getTargetAttrName(), getLinkNameAttrName(),
                              getInitValAttrName()});
  if (getOperation()->getAttr(getConstantAttrName()))
    p << " " << getConstantAttrName().strref();
  if (getOperation()->getAttr(getTargetAttrName()))
    p << " " << getTargetAttrName().strref();
  p << " : ";
  p.printType(getType());
  if (hasInitializationBody()) {
    p << ' ';
    p.printRegion(getOperation()->getRegion(0),
                  /*printEntryBlockArgs=*/false,
                  /*printBlockTerminators=*/true);
  }
}

void fir::GlobalOp::appendInitialValue(mlir::Operation *op) {
  getBlock().getOperations().push_back(op);
}

void fir::GlobalOp::build(mlir::OpBuilder &builder,
                          mlir::OperationState &result, llvm::StringRef name,
                          bool isConstant, bool isTarget, mlir::Type type,
                          mlir::Attribute initialVal, mlir::StringAttr linkage,
                          llvm::ArrayRef<mlir::NamedAttribute> attrs) {
  result.addRegion();
  result.addAttribute(getTypeAttrName(result.name), mlir::TypeAttr::get(type));
  result.addAttribute(mlir::SymbolTable::getSymbolAttrName(),
                      builder.getStringAttr(name));
  result.addAttribute(getSymrefAttrName(result.name),
                      mlir::SymbolRefAttr::get(builder.getContext(), name));
  if (isConstant)
    result.addAttribute(getConstantAttrName(result.name),
                        builder.getUnitAttr());
  if (isTarget)
    result.addAttribute(getTargetAttrName(result.name), builder.getUnitAttr());
  if (initialVal)
    result.addAttribute(getInitValAttrName(result.name), initialVal);
  if (linkage)
    result.addAttribute(getLinkNameAttrName(result.name), linkage);
  result.attributes.append(attrs.begin(), attrs.end());
}

void fir::GlobalOp::build(mlir::OpBuilder &builder,
                          mlir::OperationState &result, llvm::StringRef name,
                          mlir::Type type, mlir::Attribute initialVal,
                          mlir::StringAttr linkage,
                          llvm::ArrayRef<mlir::NamedAttribute> attrs) {
  build(builder, result, name, /*isConstant=*/false, /*isTarget=*/false, type,
        {}, linkage, attrs);
}

void fir::GlobalOp::build(mlir::OpBuilder &builder,
                          mlir::OperationState &result, llvm::StringRef name,
                          bool isConstant, bool isTarget, mlir::Type type,
                          mlir::StringAttr linkage,
                          llvm::ArrayRef<mlir::NamedAttribute> attrs) {
  build(builder, result, name, isConstant, isTarget, type, {}, linkage, attrs);
}

void fir::GlobalOp::build(mlir::OpBuilder &builder,
                          mlir::OperationState &result, llvm::StringRef name,
                          mlir::Type type, mlir::StringAttr linkage,
                          llvm::ArrayRef<mlir::NamedAttribute> attrs) {
  build(builder, result, name, /*isConstant=*/false, /*isTarget=*/false, type,
        {}, linkage, attrs);
}

void fir::GlobalOp::build(mlir::OpBuilder &builder,
                          mlir::OperationState &result, llvm::StringRef name,
                          bool isConstant, bool isTarget, mlir::Type type,
                          llvm::ArrayRef<mlir::NamedAttribute> attrs) {
  build(builder, result, name, isConstant, isTarget, type, mlir::StringAttr{},
        attrs);
}

void fir::GlobalOp::build(mlir::OpBuilder &builder,
                          mlir::OperationState &result, llvm::StringRef name,
                          mlir::Type type,
                          llvm::ArrayRef<mlir::NamedAttribute> attrs) {
  build(builder, result, name, /*isConstant=*/false, /*isTarget=*/false, type,
        attrs);
}

mlir::ParseResult fir::GlobalOp::verifyValidLinkage(llvm::StringRef linkage) {
  // Supporting only a subset of the LLVM linkage types for now
  static const char *validNames[] = {"common", "internal", "linkonce",
                                     "linkonce_odr", "weak"};
  return mlir::success(llvm::is_contained(validNames, linkage));
}

//===----------------------------------------------------------------------===//
// GlobalLenOp
//===----------------------------------------------------------------------===//

mlir::ParseResult fir::GlobalLenOp::parse(mlir::OpAsmParser &parser,
                                          mlir::OperationState &result) {
  llvm::StringRef fieldName;
  if (failed(parser.parseOptionalKeyword(&fieldName))) {
    mlir::StringAttr fieldAttr;
    if (parser.parseAttribute(fieldAttr,
                              fir::GlobalLenOp::getLenParamAttrName(),
                              result.attributes))
      return mlir::failure();
  } else {
    result.addAttribute(fir::GlobalLenOp::getLenParamAttrName(),
                        parser.getBuilder().getStringAttr(fieldName));
  }
  mlir::IntegerAttr constant;
  if (parser.parseComma() ||
      parser.parseAttribute(constant, fir::GlobalLenOp::getIntAttrName(),
                            result.attributes))
    return mlir::failure();
  return mlir::success();
}

void fir::GlobalLenOp::print(mlir::OpAsmPrinter &p) {
  p << ' ' << getOperation()->getAttr(fir::GlobalLenOp::getLenParamAttrName())
    << ", " << getOperation()->getAttr(fir::GlobalLenOp::getIntAttrName());
}

//===----------------------------------------------------------------------===//
// FieldIndexOp
//===----------------------------------------------------------------------===//

template <typename TY>
mlir::ParseResult parseFieldLikeOp(mlir::OpAsmParser &parser,
                                   mlir::OperationState &result) {
  llvm::StringRef fieldName;
  auto &builder = parser.getBuilder();
  mlir::Type recty;
  if (parser.parseOptionalKeyword(&fieldName) || parser.parseComma() ||
      parser.parseType(recty))
    return mlir::failure();
  result.addAttribute(fir::FieldIndexOp::getFieldAttrName(),
                      builder.getStringAttr(fieldName));
  if (!mlir::dyn_cast<fir::RecordType>(recty))
    return mlir::failure();
  result.addAttribute(fir::FieldIndexOp::getTypeAttrName(),
                      mlir::TypeAttr::get(recty));
  if (!parser.parseOptionalLParen()) {
    llvm::SmallVector<mlir::OpAsmParser::UnresolvedOperand> operands;
    llvm::SmallVector<mlir::Type> types;
    auto loc = parser.getNameLoc();
    if (parser.parseOperandList(operands, mlir::OpAsmParser::Delimiter::None) ||
        parser.parseColonTypeList(types) || parser.parseRParen() ||
        parser.resolveOperands(operands, types, loc, result.operands))
      return mlir::failure();
  }
  mlir::Type fieldType = TY::get(builder.getContext());
  if (parser.addTypeToList(fieldType, result.types))
    return mlir::failure();
  return mlir::success();
}

mlir::ParseResult fir::FieldIndexOp::parse(mlir::OpAsmParser &parser,
                                           mlir::OperationState &result) {
  return parseFieldLikeOp<fir::FieldType>(parser, result);
}

template <typename OP>
void printFieldLikeOp(mlir::OpAsmPrinter &p, OP &op) {
  p << ' '
    << op.getOperation()
           ->template getAttrOfType<mlir::StringAttr>(
               fir::FieldIndexOp::getFieldAttrName())
           .getValue()
    << ", " << op.getOperation()->getAttr(fir::FieldIndexOp::getTypeAttrName());
  if (op.getNumOperands()) {
    p << '(';
    p.printOperands(op.getTypeparams());
    auto sep = ") : ";
    for (auto op : op.getTypeparams()) {
      p << sep;
      if (op)
        p.printType(op.getType());
      else
        p << "()";
      sep = ", ";
    }
  }
}

void fir::FieldIndexOp::print(mlir::OpAsmPrinter &p) {
  printFieldLikeOp(p, *this);
}

void fir::FieldIndexOp::build(mlir::OpBuilder &builder,
                              mlir::OperationState &result,
                              llvm::StringRef fieldName, mlir::Type recTy,
                              mlir::ValueRange operands) {
  result.addAttribute(getFieldAttrName(), builder.getStringAttr(fieldName));
  result.addAttribute(getTypeAttrName(), mlir::TypeAttr::get(recTy));
  result.addOperands(operands);
}

llvm::SmallVector<mlir::Attribute> fir::FieldIndexOp::getAttributes() {
  llvm::SmallVector<mlir::Attribute> attrs;
  attrs.push_back(getFieldIdAttr());
  attrs.push_back(getOnTypeAttr());
  return attrs;
}

//===----------------------------------------------------------------------===//
// InsertOnRangeOp
//===----------------------------------------------------------------------===//

static mlir::ParseResult
parseCustomRangeSubscript(mlir::OpAsmParser &parser,
                          mlir::DenseIntElementsAttr &coord) {
  llvm::SmallVector<std::int64_t> lbounds;
  llvm::SmallVector<std::int64_t> ubounds;
  if (parser.parseKeyword("from") ||
      parser.parseCommaSeparatedList(
          mlir::AsmParser::Delimiter::Paren,
          [&] { return parser.parseInteger(lbounds.emplace_back(0)); }) ||
      parser.parseKeyword("to") ||
      parser.parseCommaSeparatedList(mlir::AsmParser::Delimiter::Paren, [&] {
        return parser.parseInteger(ubounds.emplace_back(0));
      }))
    return mlir::failure();
  llvm::SmallVector<std::int64_t> zippedBounds;
  for (auto zip : llvm::zip(lbounds, ubounds)) {
    zippedBounds.push_back(std::get<0>(zip));
    zippedBounds.push_back(std::get<1>(zip));
  }
  coord = mlir::Builder(parser.getContext()).getIndexTensorAttr(zippedBounds);
  return mlir::success();
}

static void printCustomRangeSubscript(mlir::OpAsmPrinter &printer,
                                      fir::InsertOnRangeOp op,
                                      mlir::DenseIntElementsAttr coord) {
  printer << "from (";
  auto enumerate = llvm::enumerate(coord.getValues<std::int64_t>());
  // Even entries are the lower bounds.
  llvm::interleaveComma(
      make_filter_range(
          enumerate,
          [](auto indexed_value) { return indexed_value.index() % 2 == 0; }),
      printer, [&](auto indexed_value) { printer << indexed_value.value(); });
  printer << ") to (";
  // Odd entries are the upper bounds.
  llvm::interleaveComma(
      make_filter_range(
          enumerate,
          [](auto indexed_value) { return indexed_value.index() % 2 != 0; }),
      printer, [&](auto indexed_value) { printer << indexed_value.value(); });
  printer << ")";
}

/// Range bounds must be nonnegative, and the range must not be empty.
llvm::LogicalResult fir::InsertOnRangeOp::verify() {
  if (fir::hasDynamicSize(getSeq().getType()))
    return emitOpError("must have constant shape and size");
  mlir::DenseIntElementsAttr coorAttr = getCoor();
  if (coorAttr.size() < 2 || coorAttr.size() % 2 != 0)
    return emitOpError("has uneven number of values in ranges");
  bool rangeIsKnownToBeNonempty = false;
  for (auto i = coorAttr.getValues<std::int64_t>().end(),
            b = coorAttr.getValues<std::int64_t>().begin();
       i != b;) {
    int64_t ub = (*--i);
    int64_t lb = (*--i);
    if (lb < 0 || ub < 0)
      return emitOpError("negative range bound");
    if (rangeIsKnownToBeNonempty)
      continue;
    if (lb > ub)
      return emitOpError("empty range");
    rangeIsKnownToBeNonempty = lb < ub;
  }
  return mlir::success();
}

bool fir::InsertOnRangeOp::isFullRange() {
  auto extents = getType().getShape();
  mlir::DenseIntElementsAttr indexes = getCoor();
  if (indexes.size() / 2 != static_cast<int64_t>(extents.size()))
    return false;
  auto cur_index = indexes.value_begin<int64_t>();
  for (unsigned i = 0; i < indexes.size(); i += 2) {
    if (*(cur_index++) != 0)
      return false;
    if (*(cur_index++) != extents[i / 2] - 1)
      return false;
  }
  return true;
}

//===----------------------------------------------------------------------===//
// InsertValueOp
//===----------------------------------------------------------------------===//

static bool checkIsIntegerConstant(mlir::Attribute attr, std::int64_t conVal) {
  if (auto iattr = mlir::dyn_cast<mlir::IntegerAttr>(attr))
    return iattr.getInt() == conVal;
  return false;
}

static bool isZero(mlir::Attribute a) { return checkIsIntegerConstant(a, 0); }
static bool isOne(mlir::Attribute a) { return checkIsIntegerConstant(a, 1); }

// Undo some complex patterns created in the front-end and turn them back into
// complex ops.
template <typename FltOp, typename CpxOp>
struct UndoComplexPattern : public mlir::RewritePattern {
  UndoComplexPattern(mlir::MLIRContext *ctx)
      : mlir::RewritePattern("fir.insert_value", 2, ctx) {}

  llvm::LogicalResult
  matchAndRewrite(mlir::Operation *op,
                  mlir::PatternRewriter &rewriter) const override {
    auto insval = mlir::dyn_cast_or_null<fir::InsertValueOp>(op);
    if (!insval || !mlir::isa<mlir::ComplexType>(insval.getType()))
      return mlir::failure();
    auto insval2 = mlir::dyn_cast_or_null<fir::InsertValueOp>(
        insval.getAdt().getDefiningOp());
    if (!insval2)
      return mlir::failure();
    auto binf = mlir::dyn_cast_or_null<FltOp>(insval.getVal().getDefiningOp());
    auto binf2 =
        mlir::dyn_cast_or_null<FltOp>(insval2.getVal().getDefiningOp());
    if (!binf || !binf2 || insval.getCoor().size() != 1 ||
        !isOne(insval.getCoor()[0]) || insval2.getCoor().size() != 1 ||
        !isZero(insval2.getCoor()[0]))
      return mlir::failure();
    auto eai = mlir::dyn_cast_or_null<fir::ExtractValueOp>(
        binf.getLhs().getDefiningOp());
    auto ebi = mlir::dyn_cast_or_null<fir::ExtractValueOp>(
        binf.getRhs().getDefiningOp());
    auto ear = mlir::dyn_cast_or_null<fir::ExtractValueOp>(
        binf2.getLhs().getDefiningOp());
    auto ebr = mlir::dyn_cast_or_null<fir::ExtractValueOp>(
        binf2.getRhs().getDefiningOp());
    if (!eai || !ebi || !ear || !ebr || ear.getAdt() != eai.getAdt() ||
        ebr.getAdt() != ebi.getAdt() || eai.getCoor().size() != 1 ||
        !isOne(eai.getCoor()[0]) || ebi.getCoor().size() != 1 ||
        !isOne(ebi.getCoor()[0]) || ear.getCoor().size() != 1 ||
        !isZero(ear.getCoor()[0]) || ebr.getCoor().size() != 1 ||
        !isZero(ebr.getCoor()[0]))
      return mlir::failure();
    rewriter.replaceOpWithNewOp<CpxOp>(op, ear.getAdt(), ebr.getAdt());
    return mlir::success();
  }
};

void fir::InsertValueOp::getCanonicalizationPatterns(
    mlir::RewritePatternSet &results, mlir::MLIRContext *context) {
  results.insert<UndoComplexPattern<mlir::arith::AddFOp, fir::AddcOp>,
                 UndoComplexPattern<mlir::arith::SubFOp, fir::SubcOp>>(context);
}

//===----------------------------------------------------------------------===//
// IterWhileOp
//===----------------------------------------------------------------------===//

void fir::IterWhileOp::build(mlir::OpBuilder &builder,
                             mlir::OperationState &result, mlir::Value lb,
                             mlir::Value ub, mlir::Value step,
                             mlir::Value iterate, bool finalCountValue,
                             mlir::ValueRange iterArgs,
                             llvm::ArrayRef<mlir::NamedAttribute> attributes) {
  result.addOperands({lb, ub, step, iterate});
  if (finalCountValue) {
    result.addTypes(builder.getIndexType());
    result.addAttribute(getFinalValueAttrNameStr(), builder.getUnitAttr());
  }
  result.addTypes(iterate.getType());
  result.addOperands(iterArgs);
  for (auto v : iterArgs)
    result.addTypes(v.getType());
  mlir::Region *bodyRegion = result.addRegion();
  bodyRegion->push_back(new mlir::Block{});
  bodyRegion->front().addArgument(builder.getIndexType(), result.location);
  bodyRegion->front().addArgument(iterate.getType(), result.location);
  bodyRegion->front().addArguments(
      iterArgs.getTypes(),
      llvm::SmallVector<mlir::Location>(iterArgs.size(), result.location));
  result.addAttributes(attributes);
}

mlir::ParseResult fir::IterWhileOp::parse(mlir::OpAsmParser &parser,
                                          mlir::OperationState &result) {
  auto &builder = parser.getBuilder();
  mlir::OpAsmParser::Argument inductionVariable, iterateVar;
  mlir::OpAsmParser::UnresolvedOperand lb, ub, step, iterateInput;
  if (parser.parseLParen() || parser.parseArgument(inductionVariable) ||
      parser.parseEqual())
    return mlir::failure();

  // Parse loop bounds.
  auto indexType = builder.getIndexType();
  auto i1Type = builder.getIntegerType(1);
  if (parser.parseOperand(lb) ||
      parser.resolveOperand(lb, indexType, result.operands) ||
      parser.parseKeyword("to") || parser.parseOperand(ub) ||
      parser.resolveOperand(ub, indexType, result.operands) ||
      parser.parseKeyword("step") || parser.parseOperand(step) ||
      parser.parseRParen() ||
      parser.resolveOperand(step, indexType, result.operands) ||
      parser.parseKeyword("and") || parser.parseLParen() ||
      parser.parseArgument(iterateVar) || parser.parseEqual() ||
      parser.parseOperand(iterateInput) || parser.parseRParen() ||
      parser.resolveOperand(iterateInput, i1Type, result.operands))
    return mlir::failure();

  // Parse the initial iteration arguments.
  auto prependCount = false;

  // Induction variable.
  llvm::SmallVector<mlir::OpAsmParser::Argument> regionArgs;
  regionArgs.push_back(inductionVariable);
  regionArgs.push_back(iterateVar);

  if (succeeded(parser.parseOptionalKeyword("iter_args"))) {
    llvm::SmallVector<mlir::OpAsmParser::UnresolvedOperand> operands;
    llvm::SmallVector<mlir::Type> regionTypes;
    // Parse assignment list and results type list.
    if (parser.parseAssignmentList(regionArgs, operands) ||
        parser.parseArrowTypeList(regionTypes))
      return mlir::failure();
    if (regionTypes.size() == operands.size() + 2)
      prependCount = true;
    llvm::ArrayRef<mlir::Type> resTypes = regionTypes;
    resTypes = prependCount ? resTypes.drop_front(2) : resTypes;
    // Resolve input operands.
    for (auto operandType : llvm::zip(operands, resTypes))
      if (parser.resolveOperand(std::get<0>(operandType),
                                std::get<1>(operandType), result.operands))
        return mlir::failure();
    if (prependCount) {
      result.addTypes(regionTypes);
    } else {
      result.addTypes(i1Type);
      result.addTypes(resTypes);
    }
  } else if (succeeded(parser.parseOptionalArrow())) {
    llvm::SmallVector<mlir::Type> typeList;
    if (parser.parseLParen() || parser.parseTypeList(typeList) ||
        parser.parseRParen())
      return mlir::failure();
    // Type list must be "(index, i1)".
    if (typeList.size() != 2 || !mlir::isa<mlir::IndexType>(typeList[0]) ||
        !typeList[1].isSignlessInteger(1))
      return mlir::failure();
    result.addTypes(typeList);
    prependCount = true;
  } else {
    result.addTypes(i1Type);
  }

  if (parser.parseOptionalAttrDictWithKeyword(result.attributes))
    return mlir::failure();

  llvm::SmallVector<mlir::Type> argTypes;
  // Induction variable (hidden)
  if (prependCount)
    result.addAttribute(IterWhileOp::getFinalValueAttrNameStr(),
                        builder.getUnitAttr());
  else
    argTypes.push_back(indexType);
  // Loop carried variables (including iterate)
  argTypes.append(result.types.begin(), result.types.end());
  // Parse the body region.
  auto *body = result.addRegion();
  if (regionArgs.size() != argTypes.size())
    return parser.emitError(
        parser.getNameLoc(),
        "mismatch in number of loop-carried values and defined values");

  for (size_t i = 0, e = regionArgs.size(); i != e; ++i)
    regionArgs[i].type = argTypes[i];

  if (parser.parseRegion(*body, regionArgs))
    return mlir::failure();

  fir::IterWhileOp::ensureTerminator(*body, builder, result.location);
  return mlir::success();
}

llvm::LogicalResult fir::IterWhileOp::verify() {
  // Check that the body defines as single block argument for the induction
  // variable.
  auto *body = getBody();
  if (!body->getArgument(1).getType().isInteger(1))
    return emitOpError(
        "expected body second argument to be an index argument for "
        "the induction variable");
  if (!body->getArgument(0).getType().isIndex())
    return emitOpError(
        "expected body first argument to be an index argument for "
        "the induction variable");

  auto opNumResults = getNumResults();
  if (getFinalValue()) {
    // Result type must be "(index, i1, ...)".
    if (!mlir::isa<mlir::IndexType>(getResult(0).getType()))
      return emitOpError("result #0 expected to be index");
    if (!getResult(1).getType().isSignlessInteger(1))
      return emitOpError("result #1 expected to be i1");
    opNumResults--;
  } else {
    // iterate_while always returns the early exit induction value.
    // Result type must be "(i1, ...)"
    if (!getResult(0).getType().isSignlessInteger(1))
      return emitOpError("result #0 expected to be i1");
  }
  if (opNumResults == 0)
    return mlir::failure();
  if (getNumIterOperands() != opNumResults)
    return emitOpError(
        "mismatch in number of loop-carried values and defined values");
  if (getNumRegionIterArgs() != opNumResults)
    return emitOpError(
        "mismatch in number of basic block args and defined values");
  auto iterOperands = getIterOperands();
  auto iterArgs = getRegionIterArgs();
  auto opResults = getFinalValue() ? getResults().drop_front() : getResults();
  unsigned i = 0u;
  for (auto e : llvm::zip(iterOperands, iterArgs, opResults)) {
    if (std::get<0>(e).getType() != std::get<2>(e).getType())
      return emitOpError() << "types mismatch between " << i
                           << "th iter operand and defined value";
    if (std::get<1>(e).getType() != std::get<2>(e).getType())
      return emitOpError() << "types mismatch between " << i
                           << "th iter region arg and defined value";

    i++;
  }
  return mlir::success();
}

void fir::IterWhileOp::print(mlir::OpAsmPrinter &p) {
  p << " (" << getInductionVar() << " = " << getLowerBound() << " to "
    << getUpperBound() << " step " << getStep() << ") and (";
  assert(hasIterOperands());
  auto regionArgs = getRegionIterArgs();
  auto operands = getIterOperands();
  p << regionArgs.front() << " = " << *operands.begin() << ")";
  if (regionArgs.size() > 1) {
    p << " iter_args(";
    llvm::interleaveComma(
        llvm::zip(regionArgs.drop_front(), operands.drop_front()), p,
        [&](auto it) { p << std::get<0>(it) << " = " << std::get<1>(it); });
    p << ") -> (";
    llvm::interleaveComma(
        llvm::drop_begin(getResultTypes(), getFinalValue() ? 0 : 1), p);
    p << ")";
  } else if (getFinalValue()) {
    p << " -> (" << getResultTypes() << ')';
  }
  p.printOptionalAttrDictWithKeyword((*this)->getAttrs(),
                                     {getFinalValueAttrNameStr()});
  p << ' ';
  p.printRegion(getRegion(), /*printEntryBlockArgs=*/false,
                /*printBlockTerminators=*/true);
}

llvm::SmallVector<mlir::Region *> fir::IterWhileOp::getLoopRegions() {
  return {&getRegion()};
}

mlir::BlockArgument fir::IterWhileOp::iterArgToBlockArg(mlir::Value iterArg) {
  for (auto i : llvm::enumerate(getInitArgs()))
    if (iterArg == i.value())
      return getRegion().front().getArgument(i.index() + 1);
  return {};
}

void fir::IterWhileOp::resultToSourceOps(
    llvm::SmallVectorImpl<mlir::Value> &results, unsigned resultNum) {
  auto oper = getFinalValue() ? resultNum + 1 : resultNum;
  auto *term = getRegion().front().getTerminator();
  if (oper < term->getNumOperands())
    results.push_back(term->getOperand(oper));
}

mlir::Value fir::IterWhileOp::blockArgToSourceOp(unsigned blockArgNum) {
  if (blockArgNum > 0 && blockArgNum <= getInitArgs().size())
    return getInitArgs()[blockArgNum - 1];
  return {};
}

std::optional<llvm::MutableArrayRef<mlir::OpOperand>>
fir::IterWhileOp::getYieldedValuesMutable() {
  auto *term = getRegion().front().getTerminator();
  return getFinalValue() ? term->getOpOperands().drop_front()
                         : term->getOpOperands();
}

//===----------------------------------------------------------------------===//
// LenParamIndexOp
//===----------------------------------------------------------------------===//

mlir::ParseResult fir::LenParamIndexOp::parse(mlir::OpAsmParser &parser,
                                              mlir::OperationState &result) {
  return parseFieldLikeOp<fir::LenType>(parser, result);
}

void fir::LenParamIndexOp::print(mlir::OpAsmPrinter &p) {
  printFieldLikeOp(p, *this);
}

void fir::LenParamIndexOp::build(mlir::OpBuilder &builder,
                                 mlir::OperationState &result,
                                 llvm::StringRef fieldName, mlir::Type recTy,
                                 mlir::ValueRange operands) {
  result.addAttribute(getFieldAttrName(), builder.getStringAttr(fieldName));
  result.addAttribute(getTypeAttrName(), mlir::TypeAttr::get(recTy));
  result.addOperands(operands);
}

llvm::SmallVector<mlir::Attribute> fir::LenParamIndexOp::getAttributes() {
  llvm::SmallVector<mlir::Attribute> attrs;
  attrs.push_back(getFieldIdAttr());
  attrs.push_back(getOnTypeAttr());
  return attrs;
}

//===----------------------------------------------------------------------===//
// LoadOp
//===----------------------------------------------------------------------===//

static bool isSlotOrDeclaredSlot(mlir::Value val,
                                 const mlir::MemorySlot &slot) {
  if (val == slot.ptr)
    return true;
  if (auto declareOp = val.getDefiningOp<fir::DeclareOp>())
    return declareOp.getMemref() == slot.ptr;
  return false;
}

bool fir::LoadOp::loadsFrom(const mlir::MemorySlot &slot) {
  return isSlotOrDeclaredSlot(getMemref(), slot);
}

bool fir::LoadOp::storesTo(const mlir::MemorySlot &slot) { return false; }

mlir::Value fir::LoadOp::getStored(const mlir::MemorySlot &slot,
                                   mlir::OpBuilder &builder,
                                   mlir::Value reachingDef,
                                   const mlir::DataLayout &dataLayout) {
  return mlir::Value();
}

bool fir::LoadOp::canUsesBeRemoved(
    const mlir::MemorySlot &slot,
    const SmallPtrSetImpl<mlir::OpOperand *> &blockingUses,
    mlir::SmallVectorImpl<mlir::OpOperand *> &newBlockingUses,
    const mlir::DataLayout &dataLayout) {
  if (blockingUses.size() != 1)
    return false;
  mlir::Value blockingUse = (*blockingUses.begin())->get();
  return isSlotOrDeclaredSlot(blockingUse, slot) && getMemref() == blockingUse;
}

mlir::DeletionKind fir::LoadOp::removeBlockingUses(
    const mlir::MemorySlot &slot,
    const SmallPtrSetImpl<mlir::OpOperand *> &blockingUses,
    mlir::OpBuilder &builder, mlir::Value reachingDefinition,
    const mlir::DataLayout &dataLayout) {
  getResult().replaceAllUsesWith(reachingDefinition);
  return mlir::DeletionKind::Delete;
}

void fir::LoadOp::build(mlir::OpBuilder &builder, mlir::OperationState &result,
                        mlir::Value refVal) {
  if (!refVal) {
    mlir::emitError(result.location, "LoadOp has null argument");
    return;
  }
  auto eleTy = fir::dyn_cast_ptrEleTy(refVal.getType());
  if (!eleTy) {
    mlir::emitError(result.location, "not a memory reference type");
    return;
  }
  build(builder, result, eleTy, refVal);
}

void fir::LoadOp::build(mlir::OpBuilder &builder, mlir::OperationState &result,
                        mlir::Type resTy, mlir::Value refVal) {

  if (!refVal) {
    mlir::emitError(result.location, "LoadOp has null argument");
    return;
  }
  result.addOperands(refVal);
  result.addTypes(resTy);
}

mlir::ParseResult fir::LoadOp::getElementOf(mlir::Type &ele, mlir::Type ref) {
  if ((ele = fir::dyn_cast_ptrEleTy(ref)))
    return mlir::success();
  return mlir::failure();
}

mlir::ParseResult fir::LoadOp::parse(mlir::OpAsmParser &parser,
                                     mlir::OperationState &result) {
  mlir::Type type;
  mlir::OpAsmParser::UnresolvedOperand oper;
  if (parser.parseOperand(oper) ||
      parser.parseOptionalAttrDict(result.attributes) ||
      parser.parseColonType(type) ||
      parser.resolveOperand(oper, type, result.operands))
    return mlir::failure();
  mlir::Type eleTy;
  if (fir::LoadOp::getElementOf(eleTy, type) ||
      parser.addTypeToList(eleTy, result.types))
    return mlir::failure();
  return mlir::success();
}

void fir::LoadOp::print(mlir::OpAsmPrinter &p) {
  p << ' ';
  p.printOperand(getMemref());
  p.printOptionalAttrDict(getOperation()->getAttrs(), {});
  p << " : " << getMemref().getType();
}

void fir::LoadOp::getEffects(
    llvm::SmallVectorImpl<
        mlir::SideEffects::EffectInstance<mlir::MemoryEffects::Effect>>
        &effects) {
  effects.emplace_back(mlir::MemoryEffects::Read::get(), &getMemrefMutable(),
                       mlir::SideEffects::DefaultResource::get());
  addVolatileMemoryEffects({getMemref().getType()}, effects);
}

//===----------------------------------------------------------------------===//
// DoLoopOp
//===----------------------------------------------------------------------===//

void fir::DoLoopOp::build(mlir::OpBuilder &builder,
                          mlir::OperationState &result, mlir::Value lb,
                          mlir::Value ub, mlir::Value step, bool unordered,
                          bool finalCountValue, mlir::ValueRange iterArgs,
                          mlir::ValueRange reduceOperands,
                          llvm::ArrayRef<mlir::Attribute> reduceAttrs,
                          llvm::ArrayRef<mlir::NamedAttribute> attributes) {
  result.addOperands({lb, ub, step});
  result.addOperands(reduceOperands);
  result.addOperands(iterArgs);
  result.addAttribute(getOperandSegmentSizeAttr(),
                      builder.getDenseI32ArrayAttr(
                          {1, 1, 1, static_cast<int32_t>(reduceOperands.size()),
                           static_cast<int32_t>(iterArgs.size())}));
  if (finalCountValue) {
    result.addTypes(lb.getType());
    result.addAttribute(getFinalValueAttrName(result.name),
                        builder.getUnitAttr());
  }
  for (auto v : iterArgs)
    result.addTypes(v.getType());
  mlir::Region *bodyRegion = result.addRegion();
  bodyRegion->push_back(new mlir::Block{});
  if (iterArgs.empty() && !finalCountValue)
    fir::DoLoopOp::ensureTerminator(*bodyRegion, builder, result.location);
  bodyRegion->front().addArgument(lb.getType(), result.location);
  bodyRegion->front().addArguments(
      iterArgs.getTypes(),
      llvm::SmallVector<mlir::Location>(iterArgs.size(), result.location));
  if (unordered)
    result.addAttribute(getUnorderedAttrName(result.name),
                        builder.getUnitAttr());
  if (!reduceAttrs.empty())
    result.addAttribute(getReduceAttrsAttrName(result.name),
                        builder.getArrayAttr(reduceAttrs));
  result.addAttributes(attributes);
}

mlir::ParseResult fir::DoLoopOp::parse(mlir::OpAsmParser &parser,
                                       mlir::OperationState &result) {
  auto &builder = parser.getBuilder();
  mlir::OpAsmParser::Argument inductionVariable;
  mlir::OpAsmParser::UnresolvedOperand lb, ub, step;
  // Parse the induction variable followed by '='.
  if (parser.parseArgument(inductionVariable) || parser.parseEqual())
    return mlir::failure();

  // Parse loop bounds.
  if (parser.parseOperand(lb) || parser.parseKeyword("to") ||
      parser.parseOperand(ub) || parser.parseKeyword("step") ||
      parser.parseOperand(step))
    return mlir::failure();

  if (mlir::succeeded(parser.parseOptionalKeyword("unordered")))
    result.addAttribute("unordered", builder.getUnitAttr());

  // Parse the reduction arguments.
  llvm::SmallVector<mlir::OpAsmParser::UnresolvedOperand> reduceOperands;
  llvm::SmallVector<mlir::Type> reduceArgTypes;
  if (succeeded(parser.parseOptionalKeyword("reduce"))) {
    // Parse reduction attributes and variables.
    llvm::SmallVector<ReduceAttr> attributes;
    if (failed(parser.parseCommaSeparatedList(
            mlir::AsmParser::Delimiter::Paren, [&]() {
              if (parser.parseAttribute(attributes.emplace_back()) ||
                  parser.parseArrow() ||
                  parser.parseOperand(reduceOperands.emplace_back()) ||
                  parser.parseColonType(reduceArgTypes.emplace_back()))
                return mlir::failure();
              return mlir::success();
            })))
      return mlir::failure();
    // Resolve input operands.
    for (auto operand_type : llvm::zip(reduceOperands, reduceArgTypes))
      if (parser.resolveOperand(std::get<0>(operand_type),
                                std::get<1>(operand_type), result.operands))
        return mlir::failure();
    llvm::SmallVector<mlir::Attribute> arrayAttr(attributes.begin(),
                                                 attributes.end());
    result.addAttribute(getReduceAttrsAttrName(result.name),
                        builder.getArrayAttr(arrayAttr));
  }

  // Parse the optional initial iteration arguments.
  llvm::SmallVector<mlir::OpAsmParser::Argument> regionArgs;
  llvm::SmallVector<mlir::OpAsmParser::UnresolvedOperand> iterOperands;
  llvm::SmallVector<mlir::Type> argTypes;
  bool prependCount = false;
  regionArgs.push_back(inductionVariable);

  if (succeeded(parser.parseOptionalKeyword("iter_args"))) {
    // Parse assignment list and results type list.
    if (parser.parseAssignmentList(regionArgs, iterOperands) ||
        parser.parseArrowTypeList(result.types))
      return mlir::failure();
    if (result.types.size() == iterOperands.size() + 1)
      prependCount = true;
    // Resolve input operands.
    llvm::ArrayRef<mlir::Type> resTypes = result.types;
    for (auto operand_type : llvm::zip(
             iterOperands, prependCount ? resTypes.drop_front() : resTypes))
      if (parser.resolveOperand(std::get<0>(operand_type),
                                std::get<1>(operand_type), result.operands))
        return mlir::failure();
  } else if (succeeded(parser.parseOptionalArrow())) {
    mlir::Type finalValueType;
    if (parser.parseType(finalValueType))
      return mlir::failure();
    result.types.push_back(finalValueType);
    prependCount = true;
  }

  // Set the operandSegmentSizes attribute
  result.addAttribute(getOperandSegmentSizeAttr(),
                      builder.getDenseI32ArrayAttr(
                          {1, 1, 1, static_cast<int32_t>(reduceOperands.size()),
                           static_cast<int32_t>(iterOperands.size())}));

  mlir::Type controlType = builder.getIndexType();
  if (succeeded(parser.parseOptionalColon()) && parser.parseType(controlType))
    return mlir::failure();

  llvm::SmallVector<mlir::Value> controlOperands;
  if (parser.resolveOperand(lb, controlType, controlOperands) ||
      parser.resolveOperand(ub, controlType, controlOperands) ||
      parser.resolveOperand(step, controlType, controlOperands))
    return mlir::failure();
  result.operands.insert(result.operands.begin(), controlOperands.begin(),
                         controlOperands.end());

  if (parser.parseOptionalAttrDictWithKeyword(result.attributes))
    return mlir::failure();

  // Induction variable.
  if (prependCount)
    result.addAttribute(DoLoopOp::getFinalValueAttrName(result.name),
                        builder.getUnitAttr());
  argTypes.push_back(controlType);
  // Loop carried variables
  mlir::TypeRange iterArgTypes = result.types;
  if (prependCount)
    iterArgTypes = iterArgTypes.drop_front();
  argTypes.append(iterArgTypes.begin(), iterArgTypes.end());
  // Parse the body region.
  auto *body = result.addRegion();
  if (regionArgs.size() != argTypes.size())
    return parser.emitError(
        parser.getNameLoc(),
        "mismatch in number of loop-carried values and defined values");
  for (size_t i = 0, e = regionArgs.size(); i != e; ++i)
    regionArgs[i].type = argTypes[i];

  if (parser.parseRegion(*body, regionArgs))
    return mlir::failure();

  DoLoopOp::ensureTerminator(*body, builder, result.location);

  return mlir::success();
}

fir::DoLoopOp fir::getForInductionVarOwner(mlir::Value val) {
  auto ivArg = mlir::dyn_cast<mlir::BlockArgument>(val);
  if (!ivArg)
    return {};
  assert(ivArg.getOwner() && "unlinked block argument");
  auto *containingInst = ivArg.getOwner()->getParentOp();
  return mlir::dyn_cast_or_null<fir::DoLoopOp>(containingInst);
}

// Lifted from loop.loop
llvm::LogicalResult fir::DoLoopOp::verify() {
  // Check that the body defines as single block argument for the induction
  // variable.
  auto *body = getBody();
  if (body->getArgument(0).getType() != getLowerBound().getType())
    return emitOpError("expected induction variable to have the same type as "
                       "the loop control");

  auto opNumResults = getNumResults();
  if (opNumResults == 0)
    return mlir::success();

  if (getFinalValue()) {
    if (getUnordered())
      return emitOpError("unordered loop has no final value");
    if (getResult(0).getType() != getLowerBound().getType())
      return emitOpError("expected final value to have the same type as the "
                         "loop control");
    opNumResults--;
  }
  if (getNumIterOperands() != opNumResults)
    return emitOpError(
        "mismatch in number of loop-carried values and defined values");
  if (getNumRegionIterArgs() != opNumResults)
    return emitOpError(
        "mismatch in number of basic block args and defined values");
  auto iterOperands = getIterOperands();
  auto iterArgs = getRegionIterArgs();
  auto opResults = getFinalValue() ? getResults().drop_front() : getResults();
  unsigned i = 0u;
  for (auto e : llvm::zip(iterOperands, iterArgs, opResults)) {
    if (std::get<0>(e).getType() != std::get<2>(e).getType())
      return emitOpError() << "types mismatch between " << i
                           << "th iter operand and defined value";
    if (std::get<1>(e).getType() != std::get<2>(e).getType())
      return emitOpError() << "types mismatch between " << i
                           << "th iter region arg and defined value";

    i++;
  }
  auto reduceAttrs = getReduceAttrsAttr();
  if (getNumReduceOperands() != (reduceAttrs ? reduceAttrs.size() : 0))
    return emitOpError(
        "mismatch in number of reduction variables and reduction attributes");
  return mlir::success();
}

void fir::DoLoopOp::print(mlir::OpAsmPrinter &p) {
  bool printBlockTerminators = false;
  p << ' ' << getInductionVar() << " = " << getLowerBound() << " to "
    << getUpperBound() << " step " << getStep();
  if (getUnordered())
    p << " unordered";
  if (hasReduceOperands()) {
    p << " reduce(";
    auto attrs = getReduceAttrsAttr();
    auto operands = getReduceOperands();
    llvm::interleaveComma(llvm::zip(attrs, operands), p, [&](auto it) {
      p << std::get<0>(it) << " -> " << std::get<1>(it) << " : "
        << std::get<1>(it).getType();
    });
    p << ')';
    printBlockTerminators = true;
  }
  if (hasIterOperands()) {
    p << " iter_args(";
    auto regionArgs = getRegionIterArgs();
    auto operands = getIterOperands();
    llvm::interleaveComma(llvm::zip(regionArgs, operands), p, [&](auto it) {
      p << std::get<0>(it) << " = " << std::get<1>(it);
    });
    p << ") -> (" << getResultTypes() << ')';
    printBlockTerminators = true;
  } else if (getFinalValue()) {
    p << " -> " << getResultTypes();
    printBlockTerminators = true;
  }
  if (!getInductionVar().getType().isIndex())
    p << " : " << getInductionVar().getType();
  p.printOptionalAttrDictWithKeyword(
      (*this)->getAttrs(),
      {"unordered", "finalValue", "reduceAttrs", "operandSegmentSizes"});
  p << ' ';
  p.printRegion(getRegion(), /*printEntryBlockArgs=*/false,
                printBlockTerminators);
}

llvm::SmallVector<mlir::Region *> fir::DoLoopOp::getLoopRegions() {
  return {&getRegion()};
}

/// Translate a value passed as an iter_arg to the corresponding block
/// argument in the body of the loop.
mlir::BlockArgument fir::DoLoopOp::iterArgToBlockArg(mlir::Value iterArg) {
  for (auto i : llvm::enumerate(getInitArgs()))
    if (iterArg == i.value())
      return getRegion().front().getArgument(i.index() + 1);
  return {};
}

/// Translate the result vector (by index number) to the corresponding value
/// to the `fir.result` Op.
void fir::DoLoopOp::resultToSourceOps(
    llvm::SmallVectorImpl<mlir::Value> &results, unsigned resultNum) {
  auto oper = getFinalValue() ? resultNum + 1 : resultNum;
  auto *term = getRegion().front().getTerminator();
  if (oper < term->getNumOperands())
    results.push_back(term->getOperand(oper));
}

/// Translate the block argument (by index number) to the corresponding value
/// passed as an iter_arg to the parent DoLoopOp.
mlir::Value fir::DoLoopOp::blockArgToSourceOp(unsigned blockArgNum) {
  if (blockArgNum > 0 && blockArgNum <= getInitArgs().size())
    return getInitArgs()[blockArgNum - 1];
  return {};
}

std::optional<llvm::MutableArrayRef<mlir::OpOperand>>
fir::DoLoopOp::getYieldedValuesMutable() {
  auto *term = getRegion().front().getTerminator();
  return getFinalValue() ? term->getOpOperands().drop_front()
                         : term->getOpOperands();
}

void fir::DoLoopOp::getSuccessorRegions(
    mlir::RegionBranchPoint point,
    llvm::SmallVectorImpl<mlir::RegionSuccessor> &regions) {
  // Entry (parent → body): loop executes ≥1 iterations, or is skipped (0-trip).
  // Loop-back (body → body): another iteration follows.
  regions.push_back(mlir::RegionSuccessor(&getRegion()));
  // Exit (body → parent): last iteration completes.
  regions.push_back(mlir::RegionSuccessor(getOperation()));
}

// Note: when finalValue is set, result[0] tracks the IV's final value.
mlir::OperandRange
fir::DoLoopOp::getEntrySuccessorOperands(mlir::RegionSuccessor successor) {
  // Initial iter-arg values, forwarded into the body or (zero-trip) directly
  // to the parent's iter results.
  return getInitArgs();
}

mlir::ValueRange
fir::DoLoopOp::getSuccessorInputs(mlir::RegionSuccessor successor) {
  // Returns the receiving slots for values flowing into `successor`.
  //
  // For a loop with finalValue and one iter arg:
  //   %r:2 = fir.do_loop ... iter_args(%acc = %init) -> (index, i32)
  //
  //   body successor  → receiving slots = [%acc]      (regionIterArgs)
  //   parent successor → receiving slots = [%r#1]     (results, drop %r#0)
  //
  // %r#0 (finalValue IV) is excluded: it has no symmetric iter-arg slot in
  // the body, so it cannot participate in the 4-edge count check.
  if (successor.isOperation())
    return getResults().drop_front(getFinalValue() ? 1 : 0);
  return getRegionIterArgs();
}

mlir::MutableOperandRange
fir::ResultOp::getMutableSuccessorOperands(mlir::RegionSuccessor successor) {
  // called on fir.result to determine
  // which of the operands is sending to the specific successor
  //
  // Without finalValue (N iter args, N results):
  //   fir.result %a0, %a1 : T0, T1   → send all N ops to body/%acc or results
  //
  // With finalValue (N iter args, N+1 results):
  //   fir.result %iv_next, %a0 : index, T0
  //              ops[0]: IV final value — only meaningful on the last exit,
  //                      has no iter-arg slot in the body; excluded here.
  //              ops[1..]: iter-carried values — sent on both loop-back and
  //              exit.
  //
  // For fir.if / fir.iter_while the parent cast fails; all ops are returned.
  if (auto doLoop =
          mlir::dyn_cast<fir::DoLoopOp>(getOperation()->getParentOp()))
    if (doLoop.getFinalValue() && getNumOperands() > 0)
      return mlir::MutableOperandRange(getOperation(), /*start=*/1,
                                       getNumOperands() - 1);
  return mlir::MutableOperandRange(getOperation());
}

//===----------------------------------------------------------------------===//
// DTEntryOp
//===----------------------------------------------------------------------===//

mlir::ParseResult fir::DTEntryOp::parse(mlir::OpAsmParser &parser,
                                        mlir::OperationState &result) {
  llvm::StringRef methodName;
  // allow `methodName` or `"methodName"`
  if (failed(parser.parseOptionalKeyword(&methodName))) {
    mlir::StringAttr methodAttr;
    if (parser.parseAttribute(methodAttr, getMethodAttrName(result.name),
                              result.attributes))
      return mlir::failure();
  } else {
    result.addAttribute(getMethodAttrName(result.name),
                        parser.getBuilder().getStringAttr(methodName));
  }
  mlir::SymbolRefAttr calleeAttr;
  if (parser.parseComma() ||
      parser.parseAttribute(calleeAttr, fir::DTEntryOp::getProcAttrNameStr(),
                            result.attributes))
    return mlir::failure();

  // Optional "deferred" keyword.
  if (succeeded(parser.parseOptionalKeyword("deferred"))) {
    result.addAttribute(fir::DTEntryOp::getDeferredAttrNameStr(),
                        parser.getBuilder().getUnitAttr());
  }
  return mlir::success();
}

void fir::DTEntryOp::print(mlir::OpAsmPrinter &p) {
  p << ' ' << getMethodAttr() << ", " << getProcAttr();
  if ((*this)->getAttr(fir::DTEntryOp::getDeferredAttrNameStr()))
    p << " deferred";
}

//===----------------------------------------------------------------------===//
// ReboxOp
//===----------------------------------------------------------------------===//

/// Get the scalar type related to a fir.box type.
/// Example: return f32 for !fir.box<!fir.heap<!fir.array<?x?xf32>>.
static mlir::Type getBoxScalarEleTy(mlir::Type boxTy) {
  auto eleTy = fir::dyn_cast_ptrOrBoxEleTy(boxTy);
  if (auto seqTy = mlir::dyn_cast<fir::SequenceType>(eleTy))
    return seqTy.getEleTy();
  return eleTy;
}

/// Test if \p t1 and \p t2 are compatible character types (if they can
/// represent the same type at runtime).
static bool areCompatibleCharacterTypes(mlir::Type t1, mlir::Type t2) {
  auto c1 = mlir::dyn_cast<fir::CharacterType>(t1);
  auto c2 = mlir::dyn_cast<fir::CharacterType>(t2);
  if (!c1 || !c2)
    return false;
  if (c1.hasDynamicLen() || c2.hasDynamicLen())
    return true;
  return c1.getLen() == c2.getLen();
}

llvm::LogicalResult fir::ReboxOp::verify() {
  auto inputBoxTy = getBox().getType();
  if (fir::isa_unknown_size_box(inputBoxTy))
    return emitOpError("box operand must not have unknown rank or type");
  auto outBoxTy = getType();
  if (fir::isa_unknown_size_box(outBoxTy))
    return emitOpError("result type must not have unknown rank or type");
  auto inputRank = fir::getBoxRank(inputBoxTy);
  auto inputEleTy = getBoxScalarEleTy(inputBoxTy);
  auto outRank = fir::getBoxRank(outBoxTy);
  auto outEleTy = getBoxScalarEleTy(outBoxTy);

  if (auto sliceVal = getSlice()) {
    // Slicing case
    if (mlir::cast<fir::SliceType>(sliceVal.getType()).getRank() != inputRank)
      return emitOpError("slice operand rank must match box operand rank");
    if (auto shapeVal = getShape()) {
      if (auto shiftTy = mlir::dyn_cast<fir::ShiftType>(shapeVal.getType())) {
        if (shiftTy.getRank() != inputRank)
          return emitOpError("shape operand and input box ranks must match "
                             "when there is a slice");
      } else {
        return emitOpError("shape operand must absent or be a fir.shift "
                           "when there is a slice");
      }
    }
    if (auto sliceOp = sliceVal.getDefiningOp()) {
      auto slicedRank = mlir::cast<fir::SliceOp>(sliceOp).getOutRank();
      if (slicedRank != outRank)
        return emitOpError("result type rank and rank after applying slice "
                           "operand must match");
    }
  } else {
    // Reshaping case
    unsigned shapeRank = inputRank;
    if (auto shapeVal = getShape()) {
      auto ty = shapeVal.getType();
      if (auto shapeTy = mlir::dyn_cast<fir::ShapeType>(ty)) {
        shapeRank = shapeTy.getRank();
      } else if (auto shapeShiftTy = mlir::dyn_cast<fir::ShapeShiftType>(ty)) {
        shapeRank = shapeShiftTy.getRank();
      } else {
        auto shiftTy = mlir::cast<fir::ShiftType>(ty);
        shapeRank = shiftTy.getRank();
        if (shapeRank != inputRank)
          return emitOpError("shape operand and input box ranks must match "
                             "when the shape is a fir.shift");
      }
    }
    if (shapeRank != outRank)
      return emitOpError("result type and shape operand ranks must match");
  }

  if (inputEleTy != outEleTy) {
    // TODO: check that outBoxTy is a parent type of inputBoxTy for derived
    // types.
    // Character input and output types with constant length may be different if
    // there is a substring in the slice, otherwise, they must match. If any of
    // the types is a character with dynamic length, the other type can be any
    // character type.
    const bool typeCanMismatch =
        mlir::isa<fir::RecordType>(inputEleTy) ||
        mlir::isa<mlir::NoneType>(outEleTy) ||
        (mlir::isa<mlir::NoneType>(inputEleTy) &&
         mlir::isa<fir::RecordType>(outEleTy)) ||
        (getSlice() && mlir::isa<fir::CharacterType>(inputEleTy)) ||
        (getSlice() && fir::isa_complex(inputEleTy) &&
         mlir::isa<mlir::FloatType>(outEleTy)) ||
        areCompatibleCharacterTypes(inputEleTy, outEleTy);
    if (!typeCanMismatch)
      return emitOpError(
          "op input and output element types must match for intrinsic types");
  }
  return mlir::success();
}

std::optional<std::int64_t> fir::ReboxOp::getViewOffset(mlir::OpResult) {
  // The address offset is zero, unless there is a slice.
  // TODO: we can handle slices that leave the base address untouched.
  if (!getSlice())
    return 0;
  return std::nullopt;
}

mlir::Speculation::Speculatability fir::ReboxOp::getSpeculatability() {
  // The operation is always safe to evaluate if it has the "optional"
  // attribute, otherwise it is not safe to evaluate if the input may
  // be absent.
  if (getOptional())
    return mlir::Speculation::Speculatable;
  return mayBeAbsentBox(getBox()) ? mlir::Speculation::NotSpeculatable
                                  : mlir::Speculation::Speculatable;
}

//===----------------------------------------------------------------------===//
// ReboxAssumedRankOp
//===----------------------------------------------------------------------===//

static bool areCompatibleAssumedRankElementType(mlir::Type inputEleTy,
                                                mlir::Type outEleTy) {
  if (inputEleTy == outEleTy)
    return true;
  // Output is unlimited polymorphic -> output dynamic type is the same as input
  // type.
  if (mlir::isa<mlir::NoneType>(outEleTy))
    return true;
  // Output/Input are derived types. Assuming input extends output type, output
  // dynamic type is the output static type, unless output is polymorphic.
  if (mlir::isa<fir::RecordType>(inputEleTy) &&
      mlir::isa<fir::RecordType>(outEleTy))
    return true;
  if (areCompatibleCharacterTypes(inputEleTy, outEleTy))
    return true;
  return false;
}

llvm::LogicalResult fir::ReboxAssumedRankOp::verify() {
  mlir::Type inputType = getBox().getType();
  if (!mlir::isa<fir::BaseBoxType>(inputType) && !fir::isBoxAddress(inputType))
    return emitOpError("input must be a box or box address");
  mlir::Type inputEleTy =
      mlir::cast<fir::BaseBoxType>(fir::unwrapRefType(inputType))
          .unwrapInnerType();
  mlir::Type outEleTy =
      mlir::cast<fir::BaseBoxType>(getType()).unwrapInnerType();
  if (!areCompatibleAssumedRankElementType(inputEleTy, outEleTy))
    return emitOpError("input and output element types are incompatible");
  return mlir::success();
}

void fir::ReboxAssumedRankOp::getEffects(
    llvm::SmallVectorImpl<
        mlir::SideEffects::EffectInstance<mlir::MemoryEffects::Effect>>
        &effects) {
  mlir::OpOperand &inputBox = getBoxMutable();
  if (fir::isBoxAddress(inputBox.get().getType()))
    effects.emplace_back(mlir::MemoryEffects::Read::get(), &inputBox,
                         mlir::SideEffects::DefaultResource::get());
}

//===----------------------------------------------------------------------===//
// ResultOp
//===----------------------------------------------------------------------===//

llvm::LogicalResult fir::ResultOp::verify() {
  auto *parentOp = (*this)->getParentOp();
  auto results = parentOp->getResults();
  auto operands = (*this)->getOperands();

  if (parentOp->getNumResults() != getNumOperands())
    return emitOpError() << "parent of result must have same arity";
  for (auto e : llvm::zip(results, operands))
    if (std::get<0>(e).getType() != std::get<1>(e).getType())
      return emitOpError() << "types mismatch between result op and its parent";
  return mlir::success();
}

//===----------------------------------------------------------------------===//
// SaveResultOp
//===----------------------------------------------------------------------===//

llvm::LogicalResult fir::SaveResultOp::verify() {
  auto resultType = getValue().getType();
  if (resultType != fir::dyn_cast_ptrEleTy(getMemref().getType()))
    return emitOpError("value type must match memory reference type");
  if (fir::isa_unknown_size_box(resultType))
    return emitOpError("cannot save !fir.box of unknown rank or type");

  if (mlir::isa<fir::BoxType>(resultType)) {
    if (getShape() || !getTypeparams().empty())
      return emitOpError(
          "must not have shape or length operands if the value is a fir.box");
    return mlir::success();
  }

  // fir.record or fir.array case.
  unsigned shapeTyRank = 0;
  if (auto shapeVal = getShape()) {
    auto shapeTy = shapeVal.getType();
    if (auto s = mlir::dyn_cast<fir::ShapeType>(shapeTy))
      shapeTyRank = s.getRank();
    else
      shapeTyRank = mlir::cast<fir::ShapeShiftType>(shapeTy).getRank();
  }

  auto eleTy = resultType;
  if (auto seqTy = mlir::dyn_cast<fir::SequenceType>(resultType)) {
    if (seqTy.getDimension() != shapeTyRank)
      return emitOpError(
          "shape operand must be provided and have the value rank "
          "when the value is a fir.array");
    eleTy = seqTy.getEleTy();
  } else {
    if (shapeTyRank != 0)
      return emitOpError(
          "shape operand should only be provided if the value is a fir.array");
  }

  if (auto recTy = mlir::dyn_cast<fir::RecordType>(eleTy)) {
    if (recTy.getNumLenParams() != getTypeparams().size())
      return emitOpError(
          "length parameters number must match with the value type "
          "length parameters");
  } else if (auto charTy = mlir::dyn_cast<fir::CharacterType>(eleTy)) {
    if (getTypeparams().size() > 1)
      return emitOpError(
          "no more than one length parameter must be provided for "
          "character value");
  } else {
    if (!getTypeparams().empty())
      return emitOpError(
          "length parameters must not be provided for this value type");
  }

  return mlir::success();
}

//===----------------------------------------------------------------------===//
// IntegralSwitchTerminator
//===----------------------------------------------------------------------===//
static constexpr llvm::StringRef getCompareOffsetAttr() {
  return "compare_operand_offsets";
}

static constexpr llvm::StringRef getTargetOffsetAttr() {
  return "target_operand_offsets";
}

template <typename OpT>
static llvm::LogicalResult verifyIntegralSwitchTerminator(OpT op) {
  if (!mlir::isa<mlir::IntegerType, mlir::IndexType, fir::IntegerType>(
          op.getSelector().getType()))
    return op.emitOpError("must be an integer");
  auto cases =
      op->template getAttrOfType<mlir::ArrayAttr>(op.getCasesAttr()).getValue();
  auto count = op.getNumDest();
  if (count == 0)
    return op.emitOpError("must have at least one successor");
  if (op.getNumConditions() != count)
    return op.emitOpError("number of cases and targets don't match");
  if (op.targetOffsetSize() != count)
    return op.emitOpError("incorrect number of successor operand groups");
  for (decltype(count) i = 0; i != count; ++i) {
    if (!mlir::isa<mlir::IntegerAttr, mlir::UnitAttr>(cases[i]))
      return op.emitOpError("invalid case alternative");
  }
  return mlir::success();
}

static mlir::ParseResult parseIntegralSwitchTerminator(
    mlir::OpAsmParser &parser, mlir::OperationState &result,
    llvm::StringRef casesAttr, llvm::StringRef operandSegmentAttr) {
  mlir::OpAsmParser::UnresolvedOperand selector;
  mlir::Type type;
  if (fir::parseSelector(parser, result, selector, type))
    return mlir::failure();

  llvm::SmallVector<mlir::Attribute> ivalues;
  llvm::SmallVector<mlir::Block *> dests;
  llvm::SmallVector<llvm::SmallVector<mlir::Value>> destArgs;
  while (true) {
    mlir::Attribute ivalue; // Integer or Unit
    mlir::Block *dest;
    llvm::SmallVector<mlir::Value> destArg;
    mlir::NamedAttrList temp;
    if (parser.parseAttribute(ivalue, "i", temp) || parser.parseComma() ||
        parser.parseSuccessorAndUseList(dest, destArg))
      return mlir::failure();
    ivalues.push_back(ivalue);
    dests.push_back(dest);
    destArgs.push_back(destArg);
    if (!parser.parseOptionalRSquare())
      break;
    if (parser.parseComma())
      return mlir::failure();
  }
  auto &bld = parser.getBuilder();
  result.addAttribute(casesAttr, bld.getArrayAttr(ivalues));
  llvm::SmallVector<int32_t> argOffs;
  int32_t sumArgs = 0;
  const auto count = dests.size();
  for (std::remove_const_t<decltype(count)> i = 0; i != count; ++i) {
    result.addSuccessors(dests[i]);
    result.addOperands(destArgs[i]);
    auto argSize = destArgs[i].size();
    argOffs.push_back(argSize);
    sumArgs += argSize;
  }
  result.addAttribute(operandSegmentAttr,
                      bld.getDenseI32ArrayAttr({1, 0, sumArgs}));
  result.addAttribute(getTargetOffsetAttr(), bld.getDenseI32ArrayAttr(argOffs));
  return mlir::success();
}

template <typename OpT>
static void printIntegralSwitchTerminator(OpT op, mlir::OpAsmPrinter &p) {
  p << ' ';
  p.printOperand(op.getSelector());
  p << " : " << op.getSelector().getType() << " [";
  auto cases =
      op->template getAttrOfType<mlir::ArrayAttr>(op.getCasesAttr()).getValue();
  auto count = op.getNumConditions();
  for (decltype(count) i = 0; i != count; ++i) {
    if (i)
      p << ", ";
    auto &attr = cases[i];
    if (auto intAttr = mlir::dyn_cast_or_null<mlir::IntegerAttr>(attr))
      p << intAttr.getValue();
    else
      p.printAttribute(attr);
    p << ", ";
    op.printSuccessorAtIndex(p, i);
  }
  p << ']';
  p.printOptionalAttrDict(
      op->getAttrs(), {op.getCasesAttr(), getCompareOffsetAttr(),
                       getTargetOffsetAttr(), op.getOperandSegmentSizeAttr()});
}

//===----------------------------------------------------------------------===//
// SelectOp
//===----------------------------------------------------------------------===//

llvm::LogicalResult fir::SelectOp::verify() {
  return verifyIntegralSwitchTerminator(*this);
}

mlir::ParseResult fir::SelectOp::parse(mlir::OpAsmParser &parser,
                                       mlir::OperationState &result) {
  return parseIntegralSwitchTerminator(parser, result, getCasesAttr(),
                                       getOperandSegmentSizeAttr());
}

void fir::SelectOp::print(mlir::OpAsmPrinter &p) {
  printIntegralSwitchTerminator(*this, p);
}

template <typename A, typename... AdditionalArgs>
static A getSubOperands(unsigned pos, A allArgs, mlir::DenseI32ArrayAttr ranges,
                        AdditionalArgs &&...additionalArgs) {
  unsigned start = 0;
  for (unsigned i = 0; i < pos; ++i)
    start += ranges[i];
  return allArgs.slice(start, ranges[pos],
                       std::forward<AdditionalArgs>(additionalArgs)...);
}

static mlir::MutableOperandRange
getMutableSuccessorOperands(unsigned pos, mlir::MutableOperandRange operands,
                            llvm::StringRef offsetAttr) {
  mlir::Operation *owner = operands.getOwner();
  mlir::NamedAttribute targetOffsetAttr =
      *owner->getAttrDictionary().getNamed(offsetAttr);
  return getSubOperands(
      pos, operands,
      mlir::cast<mlir::DenseI32ArrayAttr>(targetOffsetAttr.getValue()),
      mlir::MutableOperandRange::OperandSegment(pos, targetOffsetAttr));
}

std::optional<mlir::OperandRange> fir::SelectOp::getCompareOperands(unsigned) {
  return {};
}

std::optional<llvm::ArrayRef<mlir::Value>>
fir::SelectOp::getCompareOperands(llvm::ArrayRef<mlir::Value>, unsigned) {
  return {};
}

mlir::SuccessorOperands fir::SelectOp::getSuccessorOperands(unsigned oper) {
  return mlir::SuccessorOperands(::getMutableSuccessorOperands(
      oper, getTargetArgsMutable(), getTargetOffsetAttr()));
}

std::optional<llvm::ArrayRef<mlir::Value>>
fir::SelectOp::getSuccessorOperands(llvm::ArrayRef<mlir::Value> operands,
                                    unsigned oper) {
  auto a =
      (*this)->getAttrOfType<mlir::DenseI32ArrayAttr>(getTargetOffsetAttr());
  auto segments = (*this)->getAttrOfType<mlir::DenseI32ArrayAttr>(
      getOperandSegmentSizeAttr());
  return {getSubOperands(oper, getSubOperands(2, operands, segments), a)};
}

std::optional<mlir::ValueRange>
fir::SelectOp::getSuccessorOperands(mlir::ValueRange operands, unsigned oper) {
  auto a =
      (*this)->getAttrOfType<mlir::DenseI32ArrayAttr>(getTargetOffsetAttr());
  auto segments = (*this)->getAttrOfType<mlir::DenseI32ArrayAttr>(
      getOperandSegmentSizeAttr());
  return {getSubOperands(oper, getSubOperands(2, operands, segments), a)};
}

unsigned fir::SelectOp::targetOffsetSize() {
  return (*this)
      ->getAttrOfType<mlir::DenseI32ArrayAttr>(getTargetOffsetAttr())
      .size();
}

//===----------------------------------------------------------------------===//
// SelectCaseOp
//===----------------------------------------------------------------------===//

std::optional<mlir::OperandRange>
fir::SelectCaseOp::getCompareOperands(unsigned cond) {
  auto a =
      (*this)->getAttrOfType<mlir::DenseI32ArrayAttr>(getCompareOffsetAttr());
  return {getSubOperands(cond, getCompareArgs(), a)};
}

std::optional<llvm::ArrayRef<mlir::Value>>
fir::SelectCaseOp::getCompareOperands(llvm::ArrayRef<mlir::Value> operands,
                                      unsigned cond) {
  auto a =
      (*this)->getAttrOfType<mlir::DenseI32ArrayAttr>(getCompareOffsetAttr());
  auto segments = (*this)->getAttrOfType<mlir::DenseI32ArrayAttr>(
      getOperandSegmentSizeAttr());
  return {getSubOperands(cond, getSubOperands(1, operands, segments), a)};
}

std::optional<mlir::ValueRange>
fir::SelectCaseOp::getCompareOperands(mlir::ValueRange operands,
                                      unsigned cond) {
  auto a =
      (*this)->getAttrOfType<mlir::DenseI32ArrayAttr>(getCompareOffsetAttr());
  auto segments = (*this)->getAttrOfType<mlir::DenseI32ArrayAttr>(
      getOperandSegmentSizeAttr());
  return {getSubOperands(cond, getSubOperands(1, operands, segments), a)};
}

mlir::SuccessorOperands fir::SelectCaseOp::getSuccessorOperands(unsigned oper) {
  return mlir::SuccessorOperands(::getMutableSuccessorOperands(
      oper, getTargetArgsMutable(), getTargetOffsetAttr()));
}

std::optional<llvm::ArrayRef<mlir::Value>>
fir::SelectCaseOp::getSuccessorOperands(llvm::ArrayRef<mlir::Value> operands,
                                        unsigned oper) {
  auto a =
      (*this)->getAttrOfType<mlir::DenseI32ArrayAttr>(getTargetOffsetAttr());
  auto segments = (*this)->getAttrOfType<mlir::DenseI32ArrayAttr>(
      getOperandSegmentSizeAttr());
  return {getSubOperands(oper, getSubOperands(2, operands, segments), a)};
}

std::optional<mlir::ValueRange>
fir::SelectCaseOp::getSuccessorOperands(mlir::ValueRange operands,
                                        unsigned oper) {
  auto a =
      (*this)->getAttrOfType<mlir::DenseI32ArrayAttr>(getTargetOffsetAttr());
  auto segments = (*this)->getAttrOfType<mlir::DenseI32ArrayAttr>(
      getOperandSegmentSizeAttr());
  return {getSubOperands(oper, getSubOperands(2, operands, segments), a)};
}

// parser for fir.select_case Op
mlir::ParseResult fir::SelectCaseOp::parse(mlir::OpAsmParser &parser,
                                           mlir::OperationState &result) {
  mlir::OpAsmParser::UnresolvedOperand selector;
  mlir::Type type;
  if (fir::parseSelector(parser, result, selector, type))
    return mlir::failure();

  llvm::SmallVector<mlir::Attribute> attrs;
  llvm::SmallVector<mlir::OpAsmParser::UnresolvedOperand> opers;
  llvm::SmallVector<mlir::Block *> dests;
  llvm::SmallVector<llvm::SmallVector<mlir::Value>> destArgs;
  llvm::SmallVector<std::int32_t> argOffs;
  std::int32_t offSize = 0;
  while (true) {
    mlir::Attribute attr;
    mlir::Block *dest;
    llvm::SmallVector<mlir::Value> destArg;
    mlir::NamedAttrList temp;
    if (parser.parseAttribute(attr, "a", temp) || isValidCaseAttr(attr) ||
        parser.parseComma())
      return mlir::failure();
    attrs.push_back(attr);
    if (mlir::dyn_cast_or_null<mlir::UnitAttr>(attr)) {
      argOffs.push_back(0);
    } else if (mlir::dyn_cast_or_null<fir::ClosedIntervalAttr>(attr)) {
      mlir::OpAsmParser::UnresolvedOperand oper1;
      mlir::OpAsmParser::UnresolvedOperand oper2;
      if (parser.parseOperand(oper1) || parser.parseComma() ||
          parser.parseOperand(oper2) || parser.parseComma())
        return mlir::failure();
      opers.push_back(oper1);
      opers.push_back(oper2);
      argOffs.push_back(2);
      offSize += 2;
    } else {
      mlir::OpAsmParser::UnresolvedOperand oper;
      if (parser.parseOperand(oper) || parser.parseComma())
        return mlir::failure();
      opers.push_back(oper);
      argOffs.push_back(1);
      ++offSize;
    }
    if (parser.parseSuccessorAndUseList(dest, destArg))
      return mlir::failure();
    dests.push_back(dest);
    destArgs.push_back(destArg);
    if (mlir::succeeded(parser.parseOptionalRSquare()))
      break;
    if (parser.parseComma())
      return mlir::failure();
  }
  result.addAttribute(fir::SelectCaseOp::getCasesAttr(),
                      parser.getBuilder().getArrayAttr(attrs));
  if (parser.resolveOperands(opers, type, result.operands))
    return mlir::failure();
  llvm::SmallVector<int32_t> targOffs;
  int32_t toffSize = 0;
  const auto count = dests.size();
  for (std::remove_const_t<decltype(count)> i = 0; i != count; ++i) {
    result.addSuccessors(dests[i]);
    result.addOperands(destArgs[i]);
    auto argSize = destArgs[i].size();
    targOffs.push_back(argSize);
    toffSize += argSize;
  }
  auto &bld = parser.getBuilder();
  result.addAttribute(fir::SelectCaseOp::getOperandSegmentSizeAttr(),
                      bld.getDenseI32ArrayAttr({1, offSize, toffSize}));
  result.addAttribute(getCompareOffsetAttr(),
                      bld.getDenseI32ArrayAttr(argOffs));
  result.addAttribute(getTargetOffsetAttr(),
                      bld.getDenseI32ArrayAttr(targOffs));
  return mlir::success();
}

void fir::SelectCaseOp::print(mlir::OpAsmPrinter &p) {
  p << ' ';
  p.printOperand(getSelector());
  p << " : " << getSelector().getType() << " [";
  auto cases =
      getOperation()->getAttrOfType<mlir::ArrayAttr>(getCasesAttr()).getValue();
  auto count = getNumConditions();
  for (decltype(count) i = 0; i != count; ++i) {
    if (i)
      p << ", ";
    p << cases[i] << ", ";
    if (!mlir::isa<mlir::UnitAttr>(cases[i])) {
      auto caseArgs = *getCompareOperands(i);
      p.printOperand(*caseArgs.begin());
      p << ", ";
      if (mlir::isa<fir::ClosedIntervalAttr>(cases[i])) {
        p.printOperand(*(++caseArgs.begin()));
        p << ", ";
      }
    }
    printSuccessorAtIndex(p, i);
  }
  p << ']';
  p.printOptionalAttrDict(getOperation()->getAttrs(),
                          {getCasesAttr(), getCompareOffsetAttr(),
                           getTargetOffsetAttr(), getOperandSegmentSizeAttr()});
}

unsigned fir::SelectCaseOp::compareOffsetSize() {
  return (*this)
      ->getAttrOfType<mlir::DenseI32ArrayAttr>(getCompareOffsetAttr())
      .size();
}

unsigned fir::SelectCaseOp::targetOffsetSize() {
  return (*this)
      ->getAttrOfType<mlir::DenseI32ArrayAttr>(getTargetOffsetAttr())
      .size();
}

void fir::SelectCaseOp::build(mlir::OpBuilder &builder,
                              mlir::OperationState &result,
                              mlir::Value selector,
                              llvm::ArrayRef<mlir::Attribute> compareAttrs,
                              llvm::ArrayRef<mlir::ValueRange> cmpOperands,
                              llvm::ArrayRef<mlir::Block *> destinations,
                              llvm::ArrayRef<mlir::ValueRange> destOperands,
                              llvm::ArrayRef<mlir::NamedAttribute> attributes) {
  result.addOperands(selector);
  result.addAttribute(getCasesAttr(), builder.getArrayAttr(compareAttrs));
  llvm::SmallVector<int32_t> operOffs;
  int32_t operSize = 0;
  for (auto attr : compareAttrs) {
    if (mlir::isa<fir::ClosedIntervalAttr>(attr)) {
      operOffs.push_back(2);
      operSize += 2;
    } else if (mlir::isa<mlir::UnitAttr>(attr)) {
      operOffs.push_back(0);
    } else {
      operOffs.push_back(1);
      ++operSize;
    }
  }
  for (auto ops : cmpOperands)
    result.addOperands(ops);
  result.addAttribute(getCompareOffsetAttr(),
                      builder.getDenseI32ArrayAttr(operOffs));
  const auto count = destinations.size();
  for (auto d : destinations)
    result.addSuccessors(d);
  const auto opCount = destOperands.size();
  llvm::SmallVector<std::int32_t> argOffs;
  std::int32_t sumArgs = 0;
  for (std::remove_const_t<decltype(count)> i = 0; i != count; ++i) {
    if (i < opCount) {
      result.addOperands(destOperands[i]);
      const auto argSz = destOperands[i].size();
      argOffs.push_back(argSz);
      sumArgs += argSz;
    } else {
      argOffs.push_back(0);
    }
  }
  result.addAttribute(getOperandSegmentSizeAttr(),
                      builder.getDenseI32ArrayAttr({1, operSize, sumArgs}));
  result.addAttribute(getTargetOffsetAttr(),
                      builder.getDenseI32ArrayAttr(argOffs));
  result.addAttributes(attributes);
}

/// This builder has a slightly simplified interface in that the list of
/// operands need not be partitioned by the builder. Instead the operands are
/// partitioned here, before being passed to the default builder. This
/// partitioning is unchecked, so can go awry on bad input.
void fir::SelectCaseOp::build(mlir::OpBuilder &builder,
                              mlir::OperationState &result,
                              mlir::Value selector,
                              llvm::ArrayRef<mlir::Attribute> compareAttrs,
                              llvm::ArrayRef<mlir::Value> cmpOpList,
                              llvm::ArrayRef<mlir::Block *> destinations,
                              llvm::ArrayRef<mlir::ValueRange> destOperands,
                              llvm::ArrayRef<mlir::NamedAttribute> attributes) {
  llvm::SmallVector<mlir::ValueRange> cmpOpers;
  auto iter = cmpOpList.begin();
  for (auto &attr : compareAttrs) {
    if (mlir::isa<fir::ClosedIntervalAttr>(attr)) {
      cmpOpers.push_back(mlir::ValueRange({iter, iter + 2}));
      iter += 2;
    } else if (mlir::isa<mlir::UnitAttr>(attr)) {
      cmpOpers.push_back(mlir::ValueRange{});
    } else {
      cmpOpers.push_back(mlir::ValueRange({iter, iter + 1}));
      ++iter;
    }
  }
  build(builder, result, selector, compareAttrs, cmpOpers, destinations,
        destOperands, attributes);
}

llvm::LogicalResult fir::SelectCaseOp::verify() {
  if (!mlir::isa<mlir::IntegerType, mlir::IndexType, fir::IntegerType,
                 fir::LogicalType, fir::CharacterType>(getSelector().getType()))
    return emitOpError("must be an integer, character, or logical");
  auto cases =
      getOperation()->getAttrOfType<mlir::ArrayAttr>(getCasesAttr()).getValue();
  auto count = getNumDest();
  if (count == 0)
    return emitOpError("must have at least one successor");
  if (getNumConditions() != count)
    return emitOpError("number of conditions and successors don't match");
  if (compareOffsetSize() != count)
    return emitOpError("incorrect number of compare operand groups");
  if (targetOffsetSize() != count)
    return emitOpError("incorrect number of successor operand groups");
  for (decltype(count) i = 0; i != count; ++i) {
    auto &attr = cases[i];
    if (!(mlir::isa<fir::PointIntervalAttr>(attr) ||
          mlir::isa<fir::LowerBoundAttr>(attr) ||
          mlir::isa<fir::UpperBoundAttr>(attr) ||
          mlir::isa<fir::ClosedIntervalAttr>(attr) ||
          mlir::isa<mlir::UnitAttr>(attr)))
      return emitOpError("incorrect select case attribute type");
  }
  return mlir::success();
}

//===----------------------------------------------------------------------===//
// SelectRankOp
//===----------------------------------------------------------------------===//

llvm::LogicalResult fir::SelectRankOp::verify() {
  return verifyIntegralSwitchTerminator(*this);
}

mlir::ParseResult fir::SelectRankOp::parse(mlir::OpAsmParser &parser,
                                           mlir::OperationState &result) {
  return parseIntegralSwitchTerminator(parser, result, getCasesAttr(),
                                       getOperandSegmentSizeAttr());
}

void fir::SelectRankOp::print(mlir::OpAsmPrinter &p) {
  printIntegralSwitchTerminator(*this, p);
}

std::optional<mlir::OperandRange>
fir::SelectRankOp::getCompareOperands(unsigned) {
  return {};
}

std::optional<llvm::ArrayRef<mlir::Value>>
fir::SelectRankOp::getCompareOperands(llvm::ArrayRef<mlir::Value>, unsigned) {
  return {};
}

mlir::SuccessorOperands fir::SelectRankOp::getSuccessorOperands(unsigned oper) {
  return mlir::SuccessorOperands(::getMutableSuccessorOperands(
      oper, getTargetArgsMutable(), getTargetOffsetAttr()));
}

std::optional<llvm::ArrayRef<mlir::Value>>
fir::SelectRankOp::getSuccessorOperands(llvm::ArrayRef<mlir::Value> operands,
                                        unsigned oper) {
  auto a =
      (*this)->getAttrOfType<mlir::DenseI32ArrayAttr>(getTargetOffsetAttr());
  auto segments = (*this)->getAttrOfType<mlir::DenseI32ArrayAttr>(
      getOperandSegmentSizeAttr());
  return {getSubOperands(oper, getSubOperands(2, operands, segments), a)};
}

std::optional<mlir::ValueRange>
fir::SelectRankOp::getSuccessorOperands(mlir::ValueRange operands,
                                        unsigned oper) {
  auto a =
      (*this)->getAttrOfType<mlir::DenseI32ArrayAttr>(getTargetOffsetAttr());
  auto segments = (*this)->getAttrOfType<mlir::DenseI32ArrayAttr>(
      getOperandSegmentSizeAttr());
  return {getSubOperands(oper, getSubOperands(2, operands, segments), a)};
}

unsigned fir::SelectRankOp::targetOffsetSize() {
  return (*this)
      ->getAttrOfType<mlir::DenseI32ArrayAttr>(getTargetOffsetAttr())
      .size();
}

//===----------------------------------------------------------------------===//
// SelectTypeOp
//===----------------------------------------------------------------------===//

std::optional<mlir::OperandRange>
fir::SelectTypeOp::getCompareOperands(unsigned) {
  return {};
}

std::optional<llvm::ArrayRef<mlir::Value>>
fir::SelectTypeOp::getCompareOperands(llvm::ArrayRef<mlir::Value>, unsigned) {
  return {};
}

mlir::SuccessorOperands fir::SelectTypeOp::getSuccessorOperands(unsigned oper) {
  return mlir::SuccessorOperands(::getMutableSuccessorOperands(
      oper, getTargetArgsMutable(), getTargetOffsetAttr()));
}

std::optional<llvm::ArrayRef<mlir::Value>>
fir::SelectTypeOp::getSuccessorOperands(llvm::ArrayRef<mlir::Value> operands,
                                        unsigned oper) {
  auto a =
      (*this)->getAttrOfType<mlir::DenseI32ArrayAttr>(getTargetOffsetAttr());
  auto segments = (*this)->getAttrOfType<mlir::DenseI32ArrayAttr>(
      getOperandSegmentSizeAttr());
  return {getSubOperands(oper, getSubOperands(2, operands, segments), a)};
}

std::optional<mlir::ValueRange>
fir::SelectTypeOp::getSuccessorOperands(mlir::ValueRange operands,
                                        unsigned oper) {
  auto a =
      (*this)->getAttrOfType<mlir::DenseI32ArrayAttr>(getTargetOffsetAttr());
  auto segments = (*this)->getAttrOfType<mlir::DenseI32ArrayAttr>(
      getOperandSegmentSizeAttr());
  return {getSubOperands(oper, getSubOperands(2, operands, segments), a)};
}

mlir::ParseResult fir::SelectTypeOp::parse(mlir::OpAsmParser &parser,
                                           mlir::OperationState &result) {
  mlir::OpAsmParser::UnresolvedOperand selector;
  mlir::Type type;
  if (fir::parseSelector(parser, result, selector, type))
    return mlir::failure();

  llvm::SmallVector<mlir::Attribute> attrs;
  llvm::SmallVector<mlir::Block *> dests;
  llvm::SmallVector<llvm::SmallVector<mlir::Value>> destArgs;
  while (true) {
    mlir::Attribute attr;
    mlir::Block *dest;
    llvm::SmallVector<mlir::Value> destArg;
    mlir::NamedAttrList temp;
    if (parser.parseAttribute(attr, "a", temp) || parser.parseComma() ||
        parser.parseSuccessorAndUseList(dest, destArg))
      return mlir::failure();
    attrs.push_back(attr);
    dests.push_back(dest);
    destArgs.push_back(destArg);
    if (mlir::succeeded(parser.parseOptionalRSquare()))
      break;
    if (parser.parseComma())
      return mlir::failure();
  }
  auto &bld = parser.getBuilder();
  result.addAttribute(fir::SelectTypeOp::getCasesAttr(),
                      bld.getArrayAttr(attrs));
  llvm::SmallVector<int32_t> argOffs;
  int32_t offSize = 0;
  const auto count = dests.size();
  for (std::remove_const_t<decltype(count)> i = 0; i != count; ++i) {
    result.addSuccessors(dests[i]);
    result.addOperands(destArgs[i]);
    auto argSize = destArgs[i].size();
    argOffs.push_back(argSize);
    offSize += argSize;
  }
  result.addAttribute(fir::SelectTypeOp::getOperandSegmentSizeAttr(),
                      bld.getDenseI32ArrayAttr({1, 0, offSize}));
  result.addAttribute(getTargetOffsetAttr(), bld.getDenseI32ArrayAttr(argOffs));
  return mlir::success();
}

unsigned fir::SelectTypeOp::targetOffsetSize() {
  return (*this)
      ->getAttrOfType<mlir::DenseI32ArrayAttr>(getTargetOffsetAttr())
      .size();
}

void fir::SelectTypeOp::print(mlir::OpAsmPrinter &p) {
  p << ' ';
  p.printOperand(getSelector());
  p << " : " << getSelector().getType() << " [";
  auto cases =
      getOperation()->getAttrOfType<mlir::ArrayAttr>(getCasesAttr()).getValue();
  auto count = getNumConditions();
  for (decltype(count) i = 0; i != count; ++i) {
    if (i)
      p << ", ";
    p << cases[i] << ", ";
    printSuccessorAtIndex(p, i);
  }
  p << ']';
  p.printOptionalAttrDict(getOperation()->getAttrs(),
                          {getCasesAttr(), getCompareOffsetAttr(),
                           getTargetOffsetAttr(),
                           fir::SelectTypeOp::getOperandSegmentSizeAttr()});
}

llvm::LogicalResult fir::SelectTypeOp::verify() {
  if (!mlir::isa<fir::BaseBoxType>(getSelector().getType()))
    return emitOpError("must be a fir.class or fir.box type");
  if (auto boxType = mlir::dyn_cast<fir::BoxType>(getSelector().getType()))
    if (!mlir::isa<mlir::NoneType>(boxType.getEleTy()))
      return emitOpError("selector must be polymorphic");
  auto typeGuardAttr = getCases();
  for (unsigned idx = 0; idx < typeGuardAttr.size(); ++idx)
    if (mlir::isa<mlir::UnitAttr>(typeGuardAttr[idx]) &&
        idx != typeGuardAttr.size() - 1)
      return emitOpError("default must be the last attribute");
  auto count = getNumDest();
  if (count == 0)
    return emitOpError("must have at least one successor");
  if (getNumConditions() != count)
    return emitOpError("number of conditions and successors don't match");
  if (targetOffsetSize() != count)
    return emitOpError("incorrect number of successor operand groups");
  for (unsigned i = 0; i != count; ++i) {
    if (!mlir::isa<fir::ExactTypeAttr, fir::SubclassAttr, mlir::UnitAttr>(
            typeGuardAttr[i]))
      return emitOpError("invalid type-case alternative");
  }
  return mlir::success();
}

void fir::SelectTypeOp::build(mlir::OpBuilder &builder,
                              mlir::OperationState &result,
                              mlir::Value selector,
                              llvm::ArrayRef<mlir::Attribute> typeOperands,
                              llvm::ArrayRef<mlir::Block *> destinations,
                              llvm::ArrayRef<mlir::ValueRange> destOperands,
                              llvm::ArrayRef<mlir::NamedAttribute> attributes) {
  result.addOperands(selector);
  result.addAttribute(getCasesAttr(), builder.getArrayAttr(typeOperands));
  const auto count = destinations.size();
  for (mlir::Block *dest : destinations)
    result.addSuccessors(dest);
  const auto opCount = destOperands.size();
  llvm::SmallVector<int32_t> argOffs;
  int32_t sumArgs = 0;
  for (std::remove_const_t<decltype(count)> i = 0; i != count; ++i) {
    if (i < opCount) {
      result.addOperands(destOperands[i]);
      const auto argSz = destOperands[i].size();
      argOffs.push_back(argSz);
      sumArgs += argSz;
    } else {
      argOffs.push_back(0);
    }
  }
  result.addAttribute(getOperandSegmentSizeAttr(),
                      builder.getDenseI32ArrayAttr({1, 0, sumArgs}));
  result.addAttribute(getTargetOffsetAttr(),
                      builder.getDenseI32ArrayAttr(argOffs));
  result.addAttributes(attributes);
}

//===----------------------------------------------------------------------===//
// ShapeOp
//===----------------------------------------------------------------------===//

llvm::LogicalResult fir::ShapeOp::verify() {
  auto size = getExtents().size();
  auto shapeTy = mlir::dyn_cast<fir::ShapeType>(getType());
  assert(shapeTy && "must be a shape type");
  if (shapeTy.getRank() != size)
    return emitOpError("shape type rank mismatch");
  return mlir::success();
}

void fir::ShapeOp::build(mlir::OpBuilder &builder, mlir::OperationState &result,
                         mlir::ValueRange extents) {
  auto type = fir::ShapeType::get(builder.getContext(), extents.size());
  build(builder, result, type, extents);
}

//===----------------------------------------------------------------------===//
// ShapeExtentsOp
//===----------------------------------------------------------------------===//

namespace {
struct FoldShapeExtentsOfShape
    : public mlir::OpRewritePattern<fir::ShapeExtentsOp> {
  using OpRewritePattern::OpRewritePattern;

  mlir::LogicalResult
  matchAndRewrite(fir::ShapeExtentsOp op,
                  mlir::PatternRewriter &rewriter) const override {
    mlir::Value shape = op.getShape();
    mlir::ValueRange extents;
    if (auto shapeOp = shape.getDefiningOp<fir::ShapeOp>())
      extents = shapeOp.getExtents();
    else if (auto ssOp = shape.getDefiningOp<fir::ShapeShiftOp>())
      extents = ssOp.getExtents();
    else
      return mlir::failure();
    llvm::SmallVector<mlir::Value> results;
    for (auto [extent, resultType] : llvm::zip(extents, op.getResultTypes())) {
      if (extent.getType() == resultType) {
        results.push_back(extent);
      } else if (fir::ConvertOp::canBeConverted(extent.getType(), resultType)) {
        results.push_back(
            fir::ConvertOp::create(rewriter, op.getLoc(), resultType, extent));
      } else {
        return mlir::failure();
      }
    }
    rewriter.replaceOp(op, results);
    return mlir::success();
  }
};
} // namespace

llvm::LogicalResult fir::ShapeExtentsOp::verify() {
  mlir::Type ty = getShape().getType();
  unsigned rank;
  if (auto shapeTy = mlir::dyn_cast<fir::ShapeType>(ty))
    rank = shapeTy.getRank();
  else if (auto ssTy = mlir::dyn_cast<fir::ShapeShiftType>(ty))
    rank = ssTy.getRank();
  else
    return emitOpError("operand must be !fir.shape or !fir.shapeshift");
  if (getNumResults() != rank)
    return emitOpError("number of results must match shape rank");
  return mlir::success();
}

void fir::ShapeExtentsOp::build(mlir::OpBuilder &builder,
                                mlir::OperationState &result,
                                mlir::Value shape) {
  mlir::Type ty = shape.getType();
  unsigned rank;
  if (auto shapeTy = mlir::dyn_cast<fir::ShapeType>(ty))
    rank = shapeTy.getRank();
  else
    rank = mlir::cast<fir::ShapeShiftType>(ty).getRank();
  mlir::Type indexTy = builder.getIndexType();
  llvm::SmallVector<mlir::Type> resultTypes(rank, indexTy);
  result.addTypes(resultTypes);
  result.addOperands(shape);
}

void fir::ShapeExtentsOp::getCanonicalizationPatterns(
    mlir::RewritePatternSet &patterns, mlir::MLIRContext *context) {
  patterns.add<FoldShapeExtentsOfShape>(context);
}

//===----------------------------------------------------------------------===//
// ShapeShiftOp
//===----------------------------------------------------------------------===//

llvm::LogicalResult fir::ShapeShiftOp::verify() {
  auto size = getPairs().size();
  if (size < 2 || size > 16 * 2)
    return emitOpError("incorrect number of args");
  if (size % 2 != 0)
    return emitOpError("requires a multiple of 2 args");
  auto shapeTy = mlir::dyn_cast<fir::ShapeShiftType>(getType());
  assert(shapeTy && "must be a shape shift type");
  if (shapeTy.getRank() * 2 != size)
    return emitOpError("shape type rank mismatch");
  return mlir::success();
}

//===----------------------------------------------------------------------===//
// ShiftOp
//===----------------------------------------------------------------------===//

llvm::LogicalResult fir::ShiftOp::verify() {
  auto size = getOrigins().size();
  auto shiftTy = mlir::dyn_cast<fir::ShiftType>(getType());
  assert(shiftTy && "must be a shift type");
  if (shiftTy.getRank() != size)
    return emitOpError("shift type rank mismatch");
  return mlir::success();
}

//===----------------------------------------------------------------------===//
// SliceOp
//===----------------------------------------------------------------------===//

void fir::SliceOp::build(mlir::OpBuilder &builder, mlir::OperationState &result,
                         mlir::ValueRange trips, mlir::ValueRange path,
                         mlir::ValueRange substr) {
  const auto rank = trips.size() / 3;
  auto sliceTy = fir::SliceType::get(builder.getContext(), rank);
  build(builder, result, sliceTy, trips, path, substr);
}

/// Return the output rank of a slice op. The output rank must be between 1 and
/// the rank of the array being sliced (inclusive).
unsigned fir::SliceOp::getOutputRank(mlir::ValueRange triples) {
  unsigned rank = 0;
  if (!triples.empty()) {
    for (unsigned i = 1, end = triples.size(); i < end; i += 3) {
      auto *op = triples[i].getDefiningOp();
      if (!mlir::isa_and_nonnull<fir::UndefOp>(op))
        ++rank;
    }
    assert(rank > 0);
  }
  return rank;
}

llvm::LogicalResult fir::SliceOp::verify() {
  auto size = getTriples().size();
  if (size < 3 || size > 16 * 3)
    return emitOpError("incorrect number of args for triple");
  if (size % 3 != 0)
    return emitOpError("requires a multiple of 3 args");
  auto sliceTy = mlir::dyn_cast<fir::SliceType>(getType());
  assert(sliceTy && "must be a slice type");
  if (sliceTy.getRank() * 3 != size)
    return emitOpError("slice type rank mismatch");
  return mlir::success();
}

//===----------------------------------------------------------------------===//
// StoreOp
//===----------------------------------------------------------------------===//

bool fir::StoreOp::loadsFrom(const mlir::MemorySlot &slot) { return false; }

bool fir::StoreOp::storesTo(const mlir::MemorySlot &slot) {
  return isSlotOrDeclaredSlot(getMemref(), slot);
}

mlir::Value fir::StoreOp::getStored(const mlir::MemorySlot &slot,
                                    mlir::OpBuilder &builder,
                                    mlir::Value reachingDef,
                                    const mlir::DataLayout &dataLayout) {
  return getValue();
}

bool fir::StoreOp::canUsesBeRemoved(
    const mlir::MemorySlot &slot,
    const SmallPtrSetImpl<mlir::OpOperand *> &blockingUses,
    mlir::SmallVectorImpl<mlir::OpOperand *> &newBlockingUses,
    const mlir::DataLayout &dataLayout) {
  if (blockingUses.size() != 1)
    return false;
  mlir::Value blockingUse = (*blockingUses.begin())->get();
  return isSlotOrDeclaredSlot(blockingUse, slot) &&
         getMemref() == blockingUse && getValue() != blockingUse;
}

mlir::DeletionKind fir::StoreOp::removeBlockingUses(
    const mlir::MemorySlot &slot,
    const SmallPtrSetImpl<mlir::OpOperand *> &blockingUses,
    mlir::OpBuilder &builder, mlir::Value reachingDefinition,
    const mlir::DataLayout &dataLayout) {
  return mlir::DeletionKind::Delete;
}

mlir::Type fir::StoreOp::elementType(mlir::Type refType) {
  return fir::dyn_cast_ptrEleTy(refType);
}

mlir::ParseResult fir::StoreOp::parse(mlir::OpAsmParser &parser,
                                      mlir::OperationState &result) {
  mlir::Type type;
  mlir::OpAsmParser::UnresolvedOperand oper;
  mlir::OpAsmParser::UnresolvedOperand store;
  if (parser.parseOperand(oper) || parser.parseKeyword("to") ||
      parser.parseOperand(store) ||
      parser.parseOptionalAttrDict(result.attributes) ||
      parser.parseColonType(type) ||
      parser.resolveOperand(oper, fir::StoreOp::elementType(type),
                            result.operands) ||
      parser.resolveOperand(store, type, result.operands))
    return mlir::failure();
  return mlir::success();
}

void fir::StoreOp::print(mlir::OpAsmPrinter &p) {
  p << ' ';
  p.printOperand(getValue());
  p << " to ";
  p.printOperand(getMemref());
  p.printOptionalAttrDict(getOperation()->getAttrs(), {});
  p << " : " << getMemref().getType();
}

llvm::LogicalResult fir::StoreOp::verify() {
  if (getValue().getType() != fir::dyn_cast_ptrEleTy(getMemref().getType()))
    return emitOpError("store value type must match memory reference type");
  return mlir::success();
}

void fir::StoreOp::build(mlir::OpBuilder &builder, mlir::OperationState &result,
                         mlir::Value value, mlir::Value memref) {
  build(builder, result, value, memref, {}, {}, {});
}

void fir::StoreOp::getEffects(
    llvm::SmallVectorImpl<
        mlir::SideEffects::EffectInstance<mlir::MemoryEffects::Effect>>
        &effects) {
  effects.emplace_back(mlir::MemoryEffects::Write::get(), &getMemrefMutable(),
                       mlir::SideEffects::DefaultResource::get());
  addVolatileMemoryEffects({getMemref().getType()}, effects);
}

//===----------------------------------------------------------------------===//
// PrefetchOp
//===----------------------------------------------------------------------===//

mlir::ParseResult fir::PrefetchOp::parse(mlir::OpAsmParser &parser,
                                         mlir::OperationState &result) {
  mlir::OpAsmParser::UnresolvedOperand memref;
  if (parser.parseOperand(memref))
    return mlir::failure();

  if (mlir::succeeded(parser.parseLBrace())) {
    llvm::StringRef kw;
    if (parser.parseKeyword(&kw))
      return mlir::failure();

    if (kw == "read")
      result.addAttribute("rw", parser.getBuilder().getBoolAttr(false));
    else if (kw == "write")
      result.addAttribute("rw", parser.getBuilder().getUnitAttr());
    else
      return parser.emitError(parser.getCurrentLocation(),
                              "Expected either read or write keyword");

    if (parser.parseComma())
      return mlir::failure();

    if (parser.parseKeyword(&kw))
      return mlir::failure();
    if (kw == "instruction") {
      result.addAttribute("cacheType", parser.getBuilder().getBoolAttr(false));
    } else if (kw == "data") {
      result.addAttribute("cacheType", parser.getBuilder().getUnitAttr());
    } else
      return parser.emitError(parser.getCurrentLocation(),
                              "Expected either intruction or data keyword");

    if (parser.parseComma())
      return mlir::failure();

    if (mlir::succeeded(parser.parseKeyword("localityHint"))) {
      if (parser.parseEqual())
        return mlir::failure();
      mlir::Attribute intAttr;
      if (parser.parseAttribute(intAttr))
        return mlir::failure();
      result.addAttribute("localityHint", intAttr);
    }
    if (parser.parseRBrace())
      return mlir::failure();
  }
  mlir::Type type;
  if (parser.parseColonType(type))
    return mlir::failure();

  if (parser.resolveOperand(memref, type, result.operands))
    return mlir::failure();
  return mlir::success();
}

void fir::PrefetchOp::print(mlir::OpAsmPrinter &p) {
  p << " ";
  p.printOperand(getMemref());
  p << " {";
  if (getRw())
    p << "write";
  else
    p << "read";
  p << ", ";
  if (getCacheType())
    p << "data";
  else
    p << "instruction";
  p << ", localityHint = ";
  p << getLocalityHint();
  p << " : " << getLocalityHintAttr().getType();
  p << "} : " << getMemref().getType();
}

//===----------------------------------------------------------------------===//
// CopyOp
//===----------------------------------------------------------------------===//

void fir::CopyOp::build(mlir::OpBuilder &builder, mlir::OperationState &result,
                        mlir::Value source, mlir::Value destination,
                        bool noOverlap) {
  mlir::UnitAttr noOverlapAttr =
      noOverlap ? builder.getUnitAttr() : mlir::UnitAttr{};
  build(builder, result, source, destination, noOverlapAttr);
}

llvm::LogicalResult fir::CopyOp::verify() {
  mlir::Type sourceType = fir::unwrapRefType(getSource().getType());
  mlir::Type destinationType = fir::unwrapRefType(getDestination().getType());
  if (sourceType != destinationType)
    return emitOpError("source and destination must have the same value type");
  return mlir::success();
}

void fir::CopyOp::getEffects(
    llvm::SmallVectorImpl<
        mlir::SideEffects::EffectInstance<mlir::MemoryEffects::Effect>>
        &effects) {
  effects.emplace_back(mlir::MemoryEffects::Read::get(), &getSourceMutable(),
                       mlir::SideEffects::DefaultResource::get());
  effects.emplace_back(mlir::MemoryEffects::Write::get(),
                       &getDestinationMutable(),
                       mlir::SideEffects::DefaultResource::get());
  addVolatileMemoryEffects({getDestination().getType(), getSource().getType()},
                           effects);
}

//===----------------------------------------------------------------------===//
// StringLitOp
//===----------------------------------------------------------------------===//

inline fir::CharacterType::KindTy stringLitOpGetKind(fir::StringLitOp op) {
  auto eleTy = mlir::cast<fir::SequenceType>(op.getType()).getElementType();
  return mlir::cast<fir::CharacterType>(eleTy).getFKind();
}

bool fir::StringLitOp::isWideValue() { return stringLitOpGetKind(*this) != 1; }

static mlir::NamedAttribute
mkNamedIntegerAttr(mlir::OpBuilder &builder, llvm::StringRef name, int64_t v) {
  assert(v > 0);
  return builder.getNamedAttr(
      name, builder.getIntegerAttr(builder.getIntegerType(64), v));
}

void fir::StringLitOp::build(mlir::OpBuilder &builder,
                             mlir::OperationState &result,
                             fir::CharacterType inType, llvm::StringRef val,
                             std::optional<int64_t> len) {
  auto valAttr = builder.getNamedAttr(value(), builder.getStringAttr(val));
  int64_t length = len ? *len : inType.getLen();
  auto lenAttr = mkNamedIntegerAttr(builder, size(), length);
  result.addAttributes({valAttr, lenAttr});
  result.addTypes(inType);
}

template <typename C>
static mlir::ArrayAttr convertToArrayAttr(mlir::OpBuilder &builder,
                                          llvm::ArrayRef<C> xlist) {
  llvm::SmallVector<mlir::Attribute> attrs;
  auto ty = builder.getIntegerType(8 * sizeof(C));
  for (auto ch : xlist)
    attrs.push_back(builder.getIntegerAttr(ty, ch));
  return builder.getArrayAttr(attrs);
}

void fir::StringLitOp::build(mlir::OpBuilder &builder,
                             mlir::OperationState &result,
                             fir::CharacterType inType,
                             llvm::ArrayRef<char> vlist,
                             std::optional<std::int64_t> len) {
  auto valAttr =
      builder.getNamedAttr(xlist(), convertToArrayAttr(builder, vlist));
  std::int64_t length = len ? *len : inType.getLen();
  auto lenAttr = mkNamedIntegerAttr(builder, size(), length);
  result.addAttributes({valAttr, lenAttr});
  result.addTypes(inType);
}

void fir::StringLitOp::build(mlir::OpBuilder &builder,
                             mlir::OperationState &result,
                             fir::CharacterType inType,
                             llvm::ArrayRef<char16_t> vlist,
                             std::optional<std::int64_t> len) {
  auto valAttr =
      builder.getNamedAttr(xlist(), convertToArrayAttr(builder, vlist));
  std::int64_t length = len ? *len : inType.getLen();
  auto lenAttr = mkNamedIntegerAttr(builder, size(), length);
  result.addAttributes({valAttr, lenAttr});
  result.addTypes(inType);
}

void fir::StringLitOp::build(mlir::OpBuilder &builder,
                             mlir::OperationState &result,
                             fir::CharacterType inType,
                             llvm::ArrayRef<char32_t> vlist,
                             std::optional<std::int64_t> len) {
  auto valAttr =
      builder.getNamedAttr(xlist(), convertToArrayAttr(builder, vlist));
  std::int64_t length = len ? *len : inType.getLen();
  auto lenAttr = mkNamedIntegerAttr(builder, size(), length);
  result.addAttributes({valAttr, lenAttr});
  result.addTypes(inType);
}

mlir::ParseResult fir::StringLitOp::parse(mlir::OpAsmParser &parser,
                                          mlir::OperationState &result) {
  auto &builder = parser.getBuilder();
  mlir::Attribute val;
  mlir::NamedAttrList attrs;
  llvm::SMLoc trailingTypeLoc;
  if (parser.parseAttribute(val, "fake", attrs))
    return mlir::failure();
  if (auto v = mlir::dyn_cast<mlir::StringAttr>(val))
    result.attributes.push_back(
        builder.getNamedAttr(fir::StringLitOp::value(), v));
  else if (auto v = mlir::dyn_cast<mlir::DenseElementsAttr>(val))
    result.attributes.push_back(
        builder.getNamedAttr(fir::StringLitOp::xlist(), v));
  else if (auto v = mlir::dyn_cast<mlir::ArrayAttr>(val))
    result.attributes.push_back(
        builder.getNamedAttr(fir::StringLitOp::xlist(), v));
  else
    return parser.emitError(parser.getCurrentLocation(),
                            "found an invalid constant");
  mlir::IntegerAttr sz;
  mlir::Type type;
  if (parser.parseLParen() ||
      parser.parseAttribute(sz, fir::StringLitOp::size(), result.attributes) ||
      parser.parseRParen() || parser.getCurrentLocation(&trailingTypeLoc) ||
      parser.parseColonType(type))
    return mlir::failure();
  auto charTy = mlir::dyn_cast<fir::CharacterType>(type);
  if (!charTy)
    return parser.emitError(trailingTypeLoc, "must have character type");
  type = fir::CharacterType::get(builder.getContext(), charTy.getFKind(),
                                 sz.getInt());
  if (!type || parser.addTypesToList(type, result.types))
    return mlir::failure();
  return mlir::success();
}

void fir::StringLitOp::print(mlir::OpAsmPrinter &p) {
  p << ' ' << getValue() << '(';
  p << mlir::cast<mlir::IntegerAttr>(getSize()).getValue() << ") : ";
  p.printType(getType());
}

llvm::LogicalResult fir::StringLitOp::verify() {
  if (mlir::cast<mlir::IntegerAttr>(getSize()).getValue().isNegative())
    return emitOpError("size must be non-negative");
  if (auto xl = getOperation()->getAttr(fir::StringLitOp::xlist())) {
    if (auto xList = mlir::dyn_cast<mlir::ArrayAttr>(xl)) {
      for (auto a : xList)
        if (!mlir::isa<mlir::IntegerAttr>(a))
          return emitOpError("values in initializer must be integers");
    } else if (mlir::isa<mlir::DenseElementsAttr>(xl)) {
      // do nothing
    } else {
      return emitOpError("has unexpected attribute");
    }
  }
  return mlir::success();
}

//===----------------------------------------------------------------------===//
// UnboxProcOp
//===----------------------------------------------------------------------===//

llvm::LogicalResult fir::UnboxProcOp::verify() {
  if (auto eleTy = fir::dyn_cast_ptrEleTy(getRefTuple().getType()))
    if (mlir::isa<mlir::TupleType>(eleTy))
      return mlir::success();
  return emitOpError("second output argument has bad type");
}

//===----------------------------------------------------------------------===//
// IfOp
//===----------------------------------------------------------------------===//

void fir::IfOp::build(mlir::OpBuilder &builder, mlir::OperationState &result,
                      mlir::Value cond, bool withElseRegion) {
  build(builder, result, {}, cond, withElseRegion);
}

void fir::IfOp::build(mlir::OpBuilder &builder, mlir::OperationState &result,
                      mlir::TypeRange resultTypes, mlir::Value cond,
                      bool withElseRegion) {
  result.addOperands(cond);
  result.addTypes(resultTypes);

  mlir::Region *thenRegion = result.addRegion();
  thenRegion->push_back(new mlir::Block());
  if (resultTypes.empty())
    IfOp::ensureTerminator(*thenRegion, builder, result.location);

  mlir::Region *elseRegion = result.addRegion();
  if (withElseRegion) {
    elseRegion->push_back(new mlir::Block());
    if (resultTypes.empty())
      IfOp::ensureTerminator(*elseRegion, builder, result.location);
  }
}

// These 3 functions copied from scf.if implementation.

/// Given the region at `index`, or the parent operation if `index` is None,
/// return the successor regions. These are the regions that may be selected
/// during the flow of control.
void fir::IfOp::getSuccessorRegions(
    mlir::RegionBranchPoint point,
    llvm::SmallVectorImpl<mlir::RegionSuccessor> &regions) {
  // The `then` and the `else` region branch back to the parent operation.
  if (!point.isParent()) {
    regions.push_back(mlir::RegionSuccessor(getOperation()));
    return;
  }

  // Don't consider the else region if it is empty.
  regions.push_back(mlir::RegionSuccessor(&getThenRegion()));

  // Don't consider the else region if it is empty.
  mlir::Region *elseRegion = &this->getElseRegion();
  if (elseRegion->empty())
    regions.push_back(mlir::RegionSuccessor(getOperation()));
  else
    regions.push_back(mlir::RegionSuccessor(elseRegion));
}

mlir::ValueRange
fir::IfOp::getSuccessorInputs(mlir::RegionSuccessor successor) {
  if (successor.isOperation())
    return getOperation()->getResults();
  return mlir::ValueRange();
}

void fir::IfOp::getEntrySuccessorRegions(
    llvm::ArrayRef<mlir::Attribute> operands,
    llvm::SmallVectorImpl<mlir::RegionSuccessor> &regions) {
  FoldAdaptor adaptor(operands);
  auto boolAttr =
      mlir::dyn_cast_or_null<mlir::BoolAttr>(adaptor.getCondition());
  if (!boolAttr || boolAttr.getValue())
    regions.emplace_back(&getThenRegion());

  // If the else region is empty, execution continues after the parent op.
  if (!boolAttr || !boolAttr.getValue()) {
    if (!getElseRegion().empty())
      regions.emplace_back(&getElseRegion());
    else
      regions.push_back(mlir::RegionSuccessor(getOperation()));
  }
}

void fir::IfOp::getRegionInvocationBounds(
    llvm::ArrayRef<mlir::Attribute> operands,
    llvm::SmallVectorImpl<mlir::InvocationBounds> &invocationBounds) {
  if (auto cond = mlir::dyn_cast_or_null<mlir::BoolAttr>(operands[0])) {
    // If the condition is known, then one region is known to be executed once
    // and the other zero times.
    invocationBounds.emplace_back(0, cond.getValue() ? 1 : 0);
    invocationBounds.emplace_back(0, cond.getValue() ? 0 : 1);
  } else {
    // Non-constant condition. Each region may be executed 0 or 1 times.
    invocationBounds.assign(2, {0, 1});
  }
}

mlir::ParseResult fir::IfOp::parse(mlir::OpAsmParser &parser,
                                   mlir::OperationState &result) {
  result.regions.reserve(2);
  mlir::Region *thenRegion = result.addRegion();
  mlir::Region *elseRegion = result.addRegion();

  auto &builder = parser.getBuilder();
  mlir::OpAsmParser::UnresolvedOperand cond;
  mlir::Type i1Type = builder.getIntegerType(1);
  if (parser.parseOperand(cond) ||
      parser.resolveOperand(cond, i1Type, result.operands))
    return mlir::failure();

  if (mlir::succeeded(
          parser.parseOptionalKeyword(getWeightsAttrAssemblyName()))) {
    if (parser.parseLParen())
      return mlir::failure();
    mlir::DenseI32ArrayAttr weights;
    if (parser.parseCustomAttributeWithFallback(weights, mlir::Type{}))
      return mlir::failure();
    if (weights)
      result.addAttribute(getRegionWeightsAttrName(result.name), weights);
    if (parser.parseRParen())
      return mlir::failure();
  }

  if (parser.parseOptionalArrowTypeList(result.types))
    return mlir::failure();

  if (parser.parseRegion(*thenRegion, {}, {}))
    return mlir::failure();
  fir::IfOp::ensureTerminator(*thenRegion, parser.getBuilder(),
                              result.location);

  if (mlir::succeeded(parser.parseOptionalKeyword("else"))) {
    if (parser.parseRegion(*elseRegion, {}, {}))
      return mlir::failure();
    fir::IfOp::ensureTerminator(*elseRegion, parser.getBuilder(),
                                result.location);
  }

  // Parse the optional attribute list.
  if (parser.parseOptionalAttrDict(result.attributes))
    return mlir::failure();
  return mlir::success();
}

llvm::LogicalResult fir::IfOp::verify() {
  if (getNumResults() != 0 && getElseRegion().empty())
    return emitOpError("must have an else block if defining values");

  return mlir::success();
}

void fir::IfOp::print(mlir::OpAsmPrinter &p) {
  bool printBlockTerminators = false;
  p << ' ' << getCondition();
  if (auto weights = getRegionWeightsAttr()) {
    p << ' ' << getWeightsAttrAssemblyName() << '(';
    p.printStrippedAttrOrType(weights);
    p << ')';
  }
  if (!getResults().empty()) {
    p << " -> (" << getResultTypes() << ')';
    printBlockTerminators = true;
  }
  p << ' ';
  p.printRegion(getThenRegion(), /*printEntryBlockArgs=*/false,
                printBlockTerminators);

  // Print the 'else' regions if it exists and has a block.
  auto &otherReg = getElseRegion();
  if (!otherReg.empty()) {
    p << " else ";
    p.printRegion(otherReg, /*printEntryBlockArgs=*/false,
                  printBlockTerminators);
  }
  p.printOptionalAttrDict((*this)->getAttrs(),
                          /*elideAttrs=*/{getRegionWeightsAttrName()});
}

void fir::IfOp::resultToSourceOps(llvm::SmallVectorImpl<mlir::Value> &results,
                                  unsigned resultNum) {
  auto *term = getThenRegion().front().getTerminator();
  if (resultNum < term->getNumOperands())
    results.push_back(term->getOperand(resultNum));
  term = getElseRegion().front().getTerminator();
  if (resultNum < term->getNumOperands())
    results.push_back(term->getOperand(resultNum));
}

// Fold away a fir.if that only forwards an optional argument or returns
// fir.absent when it is not present:
//
//   %present = fir.is_present %var : (T) -> i1
//   %r = fir.if %present -> (T) {
//     fir.result %var : T
//   } else {
//     %absent = fir.absent T
//     fir.result %absent : T
//   }
//
// The result is always %var: optional arguments already encode presence.
struct FoldPresentAbsentIfOp : public mlir::OpRewritePattern<fir::IfOp> {
  using mlir::OpRewritePattern<fir::IfOp>::OpRewritePattern;

  mlir::LogicalResult
  matchAndRewrite(fir::IfOp ifOp,
                  mlir::PatternRewriter &rewriter) const override {
    if (ifOp.getNumResults() != 1)
      return mlir::failure();

    auto isPresentOp = ifOp.getCondition().getDefiningOp<fir::IsPresentOp>();
    if (!isPresentOp)
      return mlir::failure();

    mlir::Value optionalVal = isPresentOp.getVal();
    mlir::Type resultType = ifOp.getResult(0).getType();
    if (optionalVal.getType() != resultType)
      return mlir::failure();

    mlir::Block &thenBlock = ifOp.getThenRegion().front();
    if (thenBlock.getOperations().size() != 1)
      return mlir::failure();
    auto thenResult = mlir::dyn_cast<fir::ResultOp>(thenBlock.getTerminator());
    if (!thenResult || thenResult.getNumOperands() != 1 ||
        thenResult.getOperand(0) != optionalVal)
      return mlir::failure();

    if (ifOp.getElseRegion().empty())
      return mlir::failure();
    mlir::Block &elseBlock = ifOp.getElseRegion().front();
    if (elseBlock.getOperations().size() > 2)
      return mlir::failure();
    auto elseResult = mlir::dyn_cast<fir::ResultOp>(elseBlock.getTerminator());
    if (!elseResult || elseResult.getNumOperands() != 1)
      return mlir::failure();
    auto absentOp = elseResult.getOperand(0).getDefiningOp<fir::AbsentOp>();
    if (!absentOp)
      return mlir::failure();
    if (elseBlock.getOperations().size() == 2 &&
        absentOp.getOperation() != &elseBlock.front())
      return mlir::failure();

    rewriter.replaceOp(ifOp, optionalVal);
    return mlir::success();
  }
};

void fir::IfOp::getCanonicalizationPatterns(mlir::RewritePatternSet &patterns,
                                            mlir::MLIRContext *context) {
  patterns.add<FoldPresentAbsentIfOp>(context);
}

//===----------------------------------------------------------------------===//
// BoxOffsetOp
//===----------------------------------------------------------------------===//

llvm::LogicalResult fir::BoxOffsetOp::verify() {
  auto boxType = mlir::dyn_cast_or_null<fir::BaseBoxType>(
      fir::dyn_cast_ptrEleTy(getBoxRef().getType()));
  mlir::Type boxCharType;
  if (!boxType) {
    boxCharType = mlir::dyn_cast_or_null<fir::BoxCharType>(
        fir::dyn_cast_ptrEleTy(getBoxRef().getType()));
    if (!boxCharType)
      return emitOpError("box_ref operand must have !fir.ref<!fir.box<T>> or "
                         "!fir.ref<!fir.boxchar<k>> type");
    if (getField() == fir::BoxFieldAttr::derived_type)
      return emitOpError("cannot address derived_type field of a fir.boxchar");
  }
  if (getField() != fir::BoxFieldAttr::base_addr &&
      getField() != fir::BoxFieldAttr::derived_type)
    return emitOpError("cannot address provided field");
  if (getField() == fir::BoxFieldAttr::derived_type) {
    if (!fir::boxHasAddendum(boxType))
      return emitOpError("can only address derived_type field of derived type "
                         "or unlimited polymorphic fir.box");
  }
  return mlir::success();
}

void fir::BoxOffsetOp::build(mlir::OpBuilder &builder,
                             mlir::OperationState &result, mlir::Value boxRef,
                             fir::BoxFieldAttr field) {
  mlir::Type valueType =
      fir::unwrapPassByRefType(fir::unwrapRefType(boxRef.getType()));
  mlir::Type resultType = valueType;
  if (field == fir::BoxFieldAttr::base_addr)
    resultType = fir::LLVMPointerType::get(fir::ReferenceType::get(valueType));
  else if (field == fir::BoxFieldAttr::derived_type)
    resultType = fir::LLVMPointerType::get(
        fir::TypeDescType::get(fir::unwrapSequenceType(valueType)));
  build(builder, result, {resultType}, boxRef, field);
}

//===----------------------------------------------------------------------===//

mlir::ParseResult fir::isValidCaseAttr(mlir::Attribute attr) {
  if (mlir::isa<mlir::UnitAttr, fir::ClosedIntervalAttr, fir::PointIntervalAttr,
                fir::LowerBoundAttr, fir::UpperBoundAttr>(attr))
    return mlir::success();
  return mlir::failure();
}

unsigned fir::getCaseArgumentOffset(llvm::ArrayRef<mlir::Attribute> cases,
                                    unsigned dest) {
  unsigned o = 0;
  for (unsigned i = 0; i < dest; ++i) {
    auto &attr = cases[i];
    if (!mlir::dyn_cast_or_null<mlir::UnitAttr>(attr)) {
      ++o;
      if (mlir::dyn_cast_or_null<fir::ClosedIntervalAttr>(attr))
        ++o;
    }
  }
  return o;
}

mlir::ParseResult
fir::parseSelector(mlir::OpAsmParser &parser, mlir::OperationState &result,
                   mlir::OpAsmParser::UnresolvedOperand &selector,
                   mlir::Type &type) {
  if (parser.parseOperand(selector) || parser.parseColonType(type) ||
      parser.resolveOperand(selector, type, result.operands) ||
      parser.parseLSquare())
    return mlir::failure();
  return mlir::success();
}

mlir::func::FuncOp fir::createFuncOp(mlir::Location loc, mlir::ModuleOp module,
                                     llvm::StringRef name,
                                     mlir::FunctionType type,
                                     llvm::ArrayRef<mlir::NamedAttribute> attrs,
                                     const mlir::SymbolTable *symbolTable) {
  if (symbolTable)
    if (auto f = symbolTable->lookup<mlir::func::FuncOp>(name)) {
#ifdef EXPENSIVE_CHECKS
      assert(f == module.lookupSymbol<mlir::func::FuncOp>(name) &&
             "symbolTable and module out of sync");
#endif
      return f;
    }
  if (auto f = module.lookupSymbol<mlir::func::FuncOp>(name))
    return f;
  mlir::OpBuilder modBuilder(module.getBodyRegion());
  modBuilder.setInsertionPointToEnd(module.getBody());
  auto result = mlir::func::FuncOp::create(modBuilder, loc, name, type, attrs);
  result.setVisibility(mlir::SymbolTable::Visibility::Private);
  return result;
}

fir::GlobalOp fir::createGlobalOp(mlir::Location loc, mlir::ModuleOp module,
                                  llvm::StringRef name, mlir::Type type,
                                  llvm::ArrayRef<mlir::NamedAttribute> attrs,
                                  const mlir::SymbolTable *symbolTable) {
  if (symbolTable)
    if (auto g = symbolTable->lookup<fir::GlobalOp>(name)) {
#ifdef EXPENSIVE_CHECKS
      assert(g == module.lookupSymbol<fir::GlobalOp>(name) &&
             "symbolTable and module out of sync");
#endif
      return g;
    }
  if (auto g = module.lookupSymbol<fir::GlobalOp>(name))
    return g;
  mlir::OpBuilder modBuilder(module.getBodyRegion());
  auto result = fir::GlobalOp::create(modBuilder, loc, name, type, attrs);
  result.setVisibility(mlir::SymbolTable::Visibility::Private);
  return result;
}

bool fir::hasHostAssociationArgument(mlir::func::FuncOp func) {
  if (auto allArgAttrs = func.getAllArgAttrs())
    for (auto attr : allArgAttrs)
      if (auto dict = mlir::dyn_cast_or_null<mlir::DictionaryAttr>(attr))
        if (dict.get(fir::getHostAssocAttrName()))
          return true;
  return false;
}

// Test if value's definition has the specified set of
// attributeNames. The value's definition is one of the operations
// that are able to carry the Fortran variable attributes, e.g.
// fir.alloca or fir.allocmem. Function arguments may also represent
// value definitions and carry relevant attributes.
//
// If it is not possible to reach the limited set of definition
// entities from the given value, then the function will return
// std::nullopt. Otherwise, the definition is known and the return
// value is computed as:
//   * if checkAny is true, then the function will return true
//     iff any of the attributeNames attributes is set on the definition.
//   * if checkAny is false, then the function will return true
//     iff all of the attributeNames attributes are set on the definition.
static std::optional<bool>
valueCheckFirAttributes(mlir::Value value,
                        llvm::ArrayRef<llvm::StringRef> attributeNames,
                        bool checkAny) {
  auto testAttributeSets = [&](llvm::ArrayRef<mlir::NamedAttribute> setAttrs,
                               llvm::ArrayRef<llvm::StringRef> checkAttrs) {
    if (checkAny) {
      // Return true iff any of checkAttrs attributes is present
      // in setAttrs set.
      for (llvm::StringRef checkAttrName : checkAttrs)
        if (llvm::any_of(setAttrs, [&](mlir::NamedAttribute setAttr) {
              return setAttr.getName() == checkAttrName;
            }))
          return true;

      return false;
    }

    // Return true iff all attributes from checkAttrs are present
    // in setAttrs set.
    for (mlir::StringRef checkAttrName : checkAttrs)
      if (llvm::none_of(setAttrs, [&](mlir::NamedAttribute setAttr) {
            return setAttr.getName() == checkAttrName;
          }))
        return false;

    return true;
  };
  // If this is a fir.box that was loaded, the fir attributes will be on the
  // related fir.ref<fir.box> creation.
  if (mlir::isa<fir::BoxType>(value.getType()))
    if (auto definingOp = value.getDefiningOp())
      if (auto loadOp = mlir::dyn_cast<fir::LoadOp>(definingOp))
        value = loadOp.getMemref();
  // If this is a function argument, look in the argument attributes.
  if (auto blockArg = mlir::dyn_cast<mlir::BlockArgument>(value)) {
    if (blockArg.getOwner() && blockArg.getOwner()->isEntryBlock())
      if (auto funcOp = mlir::dyn_cast<mlir::func::FuncOp>(
              blockArg.getOwner()->getParentOp()))
        return testAttributeSets(
            mlir::cast<mlir::FunctionOpInterface>(*funcOp).getArgAttrs(
                blockArg.getArgNumber()),
            attributeNames);

    // If it is not a function argument, the attributes are unknown.
    return std::nullopt;
  }

  if (auto definingOp = value.getDefiningOp()) {
    // If this is an allocated value, look at the allocation attributes.
    if (mlir::isa<fir::AllocMemOp>(definingOp) ||
        mlir::isa<fir::AllocaOp>(definingOp))
      return testAttributeSets(definingOp->getAttrs(), attributeNames);
    // If this is an imported global, look at AddrOfOp and GlobalOp attributes.
    // Both operations are looked at because use/host associated variable (the
    // AddrOfOp) can have ASYNCHRONOUS/VOLATILE attributes even if the ultimate
    // entity (the globalOp) does not have them.
    if (auto addressOfOp = mlir::dyn_cast<fir::AddrOfOp>(definingOp)) {
      if (testAttributeSets(addressOfOp->getAttrs(), attributeNames))
        return true;
      if (auto module = definingOp->getParentOfType<mlir::ModuleOp>())
        if (auto globalOp =
                module.lookupSymbol<fir::GlobalOp>(addressOfOp.getSymbol()))
          return testAttributeSets(globalOp->getAttrs(), attributeNames);
    }
  }
  // TODO: Construct associated entities attributes. Decide where the fir
  // attributes must be placed/looked for in this case.
  return std::nullopt;
}

bool fir::valueMayHaveFirAttributes(
    mlir::Value value, llvm::ArrayRef<llvm::StringRef> attributeNames) {
  std::optional<bool> mayHaveAttr =
      valueCheckFirAttributes(value, attributeNames, /*checkAny=*/true);
  return mayHaveAttr.value_or(true);
}

bool fir::valueHasFirAttribute(mlir::Value value,
                               llvm::StringRef attributeName) {
  std::optional<bool> mayHaveAttr =
      valueCheckFirAttributes(value, {attributeName}, /*checkAny=*/false);
  return mayHaveAttr.value_or(false);
}

bool fir::anyFuncArgsHaveAttr(mlir::func::FuncOp func, llvm::StringRef attr) {
  for (unsigned i = 0, end = func.getNumArguments(); i < end; ++i)
    if (func.getArgAttr(i, attr))
      return true;
  return false;
}

std::optional<llvm::APInt> fir::getIntIfConstant(mlir::Value value) {
  if (auto *definingOp = value.getDefiningOp()) {
    if (auto cst = mlir::dyn_cast<mlir::arith::ConstantOp>(definingOp))
      if (auto intAttr = mlir::dyn_cast<mlir::IntegerAttr>(cst.getValue()))
        return intAttr.getValue();
    if (auto llConstOp = mlir::dyn_cast<mlir::LLVM::ConstantOp>(definingOp))
      if (auto attr = mlir::dyn_cast<mlir::IntegerAttr>(llConstOp.getValue()))
        return attr.getValue();
  }
  return {};
}

bool fir::isDummyArgument(mlir::Value v) {
  auto blockArg{mlir::dyn_cast<mlir::BlockArgument>(v)};
  if (!blockArg) {
    auto defOp = v.getDefiningOp();
    if (defOp) {
      if (auto declareOp = mlir::dyn_cast<fir::DeclareOp>(defOp))
        if (declareOp.getDummyScope())
          return true;
    }
    return false;
  }

  auto *owner{blockArg.getOwner()};
  return owner->isEntryBlock() &&
         mlir::isa<mlir::FunctionOpInterface>(owner->getParentOp());
}

mlir::Type fir::applyPathToType(mlir::Type eleTy, mlir::ValueRange path) {
  for (auto i = path.begin(), end = path.end(); eleTy && i < end;) {
    eleTy = llvm::TypeSwitch<mlir::Type, mlir::Type>(eleTy)
                .Case([&](fir::RecordType ty) {
                  if (auto *op = (*i++).getDefiningOp()) {
                    if (auto off = mlir::dyn_cast<fir::FieldIndexOp>(op))
                      return ty.getType(off.getFieldName());
                    if (auto off = mlir::dyn_cast<mlir::arith::ConstantOp>(op))
                      return ty.getType(fir::toInt(off));
                  }
                  return mlir::Type{};
                })
                .Case([&](fir::SequenceType ty) {
                  bool valid = true;
                  const auto rank = ty.getDimension();
                  for (std::remove_const_t<decltype(rank)> ii = 0;
                       valid && ii < rank; ++ii)
                    valid = i < end && fir::isa_integer((*i++).getType());
                  return valid ? ty.getEleTy() : mlir::Type{};
                })
                .Case([&](mlir::TupleType ty) {
                  if (auto *op = (*i++).getDefiningOp())
                    if (auto off = mlir::dyn_cast<mlir::arith::ConstantOp>(op))
                      return ty.getType(fir::toInt(off));
                  return mlir::Type{};
                })
                .Case([&](mlir::ComplexType ty) {
                  if (fir::isa_integer((*i++).getType()))
                    return ty.getElementType();
                  return mlir::Type{};
                })
                .Default([&](const auto &) { return mlir::Type{}; });
  }
  return eleTy;
}

bool fir::reboxPreservesContinuity(fir::ReboxOp rebox,
                                   bool mayHaveNonDefaultLowerBounds,
                                   bool checkWhole) {
  // If slicing is not involved, then the rebox does not affect
  // the continuity of the array.
  auto sliceArg = rebox.getSlice();
  if (!sliceArg)
    return true;

  if (auto sliceOp =
          mlir::dyn_cast_or_null<fir::SliceOp>(sliceArg.getDefiningOp()))
    return isContiguousArraySlice(sliceOp, checkWhole, rebox.getBox(),
                                  mayHaveNonDefaultLowerBounds);

  return false;
}

std::optional<int64_t> fir::getAllocaByteSize(fir::AllocaOp alloca,
                                              const mlir::DataLayout &dl,
                                              const fir::KindMapping &kindMap) {
  mlir::Type type = alloca.getInType();
  // TODO: should use the constant operands when all info is not available in
  // the type.
  if (!alloca.isDynamic())
    if (auto sizeAndAlignment =
            getTypeSizeAndAlignment(alloca.getLoc(), type, dl, kindMap))
      return sizeAndAlignment->first;
  return std::nullopt;
}

//===----------------------------------------------------------------------===//
// DeclareValueOp
//===----------------------------------------------------------------------===//

static bool isLegalTypeForValueDeclare(mlir::Type type) {
  return mlir::isa<mlir::IntegerType, mlir::FloatType, mlir::ComplexType,
                   fir::LogicalType>(type);
}

llvm::LogicalResult fir::DeclareValueOp::verify() {
  if (!isLegalTypeForValueDeclare(getValue().getType()))
    return emitOpError(
        "value must be a simple scalar (integer, real, complex, or logical)");
  return mlir::success();
}

//===----------------------------------------------------------------------===//
// DeclareOp
//===----------------------------------------------------------------------===//

llvm::LogicalResult fir::DeclareOp::verify() {
  auto fortranVar =
      mlir::cast<fir::FortranVariableOpInterface>(this->getOperation());
  return fortranVar.verifyDeclareLikeOpImpl(getMemref());
}

bool fir::DeclareOp::canUsesBeRemoved(
    const mlir::SmallPtrSetImpl<mlir::OpOperand *> &blockingUses,
    mlir::SmallVectorImpl<mlir::OpOperand *> &newBlockingUses,
    const mlir::DataLayout &dataLayout) {
  if (!isLegalTypeForValueDeclare(fir::unwrapRefType(getType())))
    return false;
  // MLIR's mem2reg computes defining blocks only from direct users of
  // the slot pointer. Stores through fir.declare are not direct users,
  // so they are not registered as defining blocks. This causes missing
  // phi nodes at join points (e.g., loop headers). Restrict promotion
  // to the single-block case where no phi nodes are needed.
  mlir::Block *declBlock = getOperation()->getBlock();
  for (mlir::OpOperand &use : getResult().getUses()) {
    if (use.getOwner()->getBlock() != declBlock)
      return false;
    newBlockingUses.push_back(&use);
  }
  return true;
}

mlir::DeletionKind fir::DeclareOp::removeBlockingUses(
    const mlir::SmallPtrSetImpl<mlir::OpOperand *> &blockingUses,
    mlir::OpBuilder &builder) {
  return mlir::DeletionKind::Delete;
}

bool fir::DeclareOp::requiresReplacedValues() { return true; }

void fir::DeclareOp::visitReplacedValues(
    llvm::ArrayRef<std::pair<mlir::Operation *, mlir::Value>> definitions,
    mlir::OpBuilder &builder) {
  for (auto [op, value] : definitions) {
    // Do not emit DeclareValue when we have a dummy scope as this can
    // potentially result in us generating it where the DummyScope does not
    // dominate it. This can happen after inlining.
    if (getDummyScope())
      continue;
    builder.setInsertionPointAfter(op);
    fir::DeclareValueOp::create(builder, getLoc(), value, nullptr,
                                getUniqNameAttr(), getFortranAttrsAttr(),
                                getDataAttrAttr(), getDummyArgNoAttr());
  }
}

//===----------------------------------------------------------------------===//
// PackArrayOp
//===----------------------------------------------------------------------===//

llvm::LogicalResult fir::PackArrayOp::verify() {
  mlir::Type arrayType = getArray().getType();
  if (!validTypeParams(arrayType, getTypeparams(), /*allowParamsForBox=*/true))
    return emitOpError("invalid type parameters");

  if (getInnermost() && fir::getBoxRank(arrayType) == 1)
    return emitOpError(
        "'innermost' is invalid for 1D arrays, use 'whole' instead");
  return mlir::success();
}

void fir::PackArrayOp::getEffects(
    llvm::SmallVectorImpl<
        mlir::SideEffects::EffectInstance<mlir::MemoryEffects::Effect>>
        &effects) {
  if (getStack())
    effects.emplace_back(
        mlir::MemoryEffects::Allocate::get(),
        mlir::SideEffects::AutomaticAllocationScopeResource::get());
  else
    effects.emplace_back(mlir::MemoryEffects::Allocate::get(),
                         mlir::SideEffects::DefaultResource::get());

  if (!getNoCopy())
    effects.emplace_back(mlir::MemoryEffects::Read::get(),
                         mlir::SideEffects::DefaultResource::get());
}

static mlir::ParseResult
parsePackArrayConstraints(mlir::OpAsmParser &parser, mlir::IntegerAttr &maxSize,
                          mlir::IntegerAttr &maxElementSize,
                          mlir::IntegerAttr &minStride) {
  mlir::OperationName opName = mlir::OperationName(
      fir::PackArrayOp::getOperationName(), parser.getContext());
  struct {
    llvm::StringRef name;
    mlir::IntegerAttr &ref;
  } attributes[] = {
      {fir::PackArrayOp::getMaxSizeAttrName(opName), maxSize},
      {fir::PackArrayOp::getMaxElementSizeAttrName(opName), maxElementSize},
      {fir::PackArrayOp::getMinStrideAttrName(opName), minStride}};

  mlir::NamedAttrList parsedAttrs;
  if (succeeded(parser.parseOptionalAttrDict(parsedAttrs))) {
    for (auto parsedAttr : parsedAttrs) {
      for (auto opAttr : attributes) {
        if (parsedAttr.getName() == opAttr.name)
          opAttr.ref = mlir::cast<mlir::IntegerAttr>(parsedAttr.getValue());
      }
    }
    return mlir::success();
  }
  return mlir::failure();
}

static void printPackArrayConstraints(mlir::OpAsmPrinter &p,
                                      fir::PackArrayOp &op,
                                      const mlir::IntegerAttr &maxSize,
                                      const mlir::IntegerAttr &maxElementSize,
                                      const mlir::IntegerAttr &minStride) {
  llvm::SmallVector<mlir::NamedAttribute> attributes;
  if (maxSize)
    attributes.emplace_back(op.getMaxSizeAttrName(), maxSize);
  if (maxElementSize)
    attributes.emplace_back(op.getMaxElementSizeAttrName(), maxElementSize);
  if (minStride)
    attributes.emplace_back(op.getMinStrideAttrName(), minStride);

  p.printOptionalAttrDict(attributes);
}

//===----------------------------------------------------------------------===//
// UnpackArrayOp
//===----------------------------------------------------------------------===//

llvm::LogicalResult fir::UnpackArrayOp::verify() {
  if (auto packOp = getTemp().getDefiningOp<fir::PackArrayOp>())
    if (getStack() != packOp.getStack())
      return emitOpError() << "the pack operation uses different memory for "
                              "the temporary (stack vs heap): "
                           << *packOp.getOperation() << "\n";
  return mlir::success();
}

void fir::UnpackArrayOp::getEffects(
    llvm::SmallVectorImpl<
        mlir::SideEffects::EffectInstance<mlir::MemoryEffects::Effect>>
        &effects) {
  if (getStack())
    effects.emplace_back(
        mlir::MemoryEffects::Free::get(),
        mlir::SideEffects::AutomaticAllocationScopeResource::get());
  else
    effects.emplace_back(mlir::MemoryEffects::Free::get(),
                         mlir::SideEffects::DefaultResource::get());

  if (!getNoCopy())
    effects.emplace_back(mlir::MemoryEffects::Write::get(),
                         mlir::SideEffects::DefaultResource::get());
}

//===----------------------------------------------------------------------===//
// IsContiguousBoxOp
//===----------------------------------------------------------------------===//

namespace {
struct SimplifyIsContiguousBoxOp
    : public mlir::OpRewritePattern<fir::IsContiguousBoxOp> {
  using mlir::OpRewritePattern<fir::IsContiguousBoxOp>::OpRewritePattern;
  mlir::LogicalResult
  matchAndRewrite(fir::IsContiguousBoxOp op,
                  mlir::PatternRewriter &rewriter) const override;
};
} // namespace

mlir::LogicalResult SimplifyIsContiguousBoxOp::matchAndRewrite(
    fir::IsContiguousBoxOp op, mlir::PatternRewriter &rewriter) const {
  auto boxType = mlir::cast<fir::BaseBoxType>(op.getBox().getType());
  // Nothing to do for assumed-rank arrays and !fir.box<none>.
  if (boxType.isAssumedRank() || fir::isBoxNone(boxType))
    return mlir::failure();

  if (fir::getBoxRank(boxType) == 0) {
    // Scalars are always contiguous.
    mlir::Type i1Type = rewriter.getI1Type();
    rewriter.replaceOpWithNewOp<mlir::arith::ConstantOp>(
        op, i1Type, rewriter.getIntegerAttr(i1Type, 1));
    return mlir::success();
  }

  // TODO: support more patterns, e.g. a result of fir.embox without
  // the slice is contiguous. We can add fir::isSimplyContiguous(box)
  // that walks def-use to figure it out.
  return mlir::failure();
}

void fir::IsContiguousBoxOp::getCanonicalizationPatterns(
    mlir::RewritePatternSet &patterns, mlir::MLIRContext *context) {
  patterns.add<SimplifyIsContiguousBoxOp>(context);
}

//===----------------------------------------------------------------------===//
// BoxTotalElementsOp
//===----------------------------------------------------------------------===//

namespace {
struct SimplifyBoxTotalElementsOp
    : public mlir::OpRewritePattern<fir::BoxTotalElementsOp> {
  using mlir::OpRewritePattern<fir::BoxTotalElementsOp>::OpRewritePattern;
  mlir::LogicalResult
  matchAndRewrite(fir::BoxTotalElementsOp op,
                  mlir::PatternRewriter &rewriter) const override;
};
} // namespace

mlir::LogicalResult SimplifyBoxTotalElementsOp::matchAndRewrite(
    fir::BoxTotalElementsOp op, mlir::PatternRewriter &rewriter) const {
  auto boxType = mlir::cast<fir::BaseBoxType>(op.getBox().getType());
  // Nothing to do for assumed-rank arrays and !fir.box<none>.
  if (boxType.isAssumedRank() || fir::isBoxNone(boxType))
    return mlir::failure();

  if (fir::getBoxRank(boxType) == 0) {
    // Scalar: 1 element.
    rewriter.replaceOpWithNewOp<mlir::arith::ConstantOp>(
        op, op.getType(), rewriter.getIntegerAttr(op.getType(), 1));
    return mlir::success();
  }

  // TODO: support more cases, e.g. !fir.box<!fir.array<10xi32>>.
  return mlir::failure();
}

void fir::BoxTotalElementsOp::getCanonicalizationPatterns(
    mlir::RewritePatternSet &patterns, mlir::MLIRContext *context) {
  patterns.add<SimplifyBoxTotalElementsOp>(context);
}

//===----------------------------------------------------------------------===//
// IsAssumedSizeExtentOp and AssumedSizeExtentOp
//===----------------------------------------------------------------------===//

namespace {
struct FoldIsAssumedSizeExtentOnCtor
    : public mlir::OpRewritePattern<fir::IsAssumedSizeExtentOp> {
  using mlir::OpRewritePattern<fir::IsAssumedSizeExtentOp>::OpRewritePattern;
  mlir::LogicalResult
  matchAndRewrite(fir::IsAssumedSizeExtentOp op,
                  mlir::PatternRewriter &rewriter) const override {
    if (llvm::isa_and_nonnull<fir::AssumedSizeExtentOp>(
            op.getVal().getDefiningOp())) {
      mlir::Type i1 = rewriter.getI1Type();
      rewriter.replaceOpWithNewOp<mlir::arith::ConstantOp>(
          op, i1, rewriter.getIntegerAttr(i1, 1));
      return mlir::success();
    }
    return mlir::failure();
  }
};
} // namespace

void fir::IsAssumedSizeExtentOp::getCanonicalizationPatterns(
    mlir::RewritePatternSet &patterns, mlir::MLIRContext *context) {
  patterns.add<FoldIsAssumedSizeExtentOnCtor>(context);
}

//===----------------------------------------------------------------------===//
// LocalitySpecifierOp
//===----------------------------------------------------------------------===//

// TODO This is a copy of omp::PrivateClauseOp::verifiyRegions(). Once we find a
// solution to merge both ops into one this duplication will not be needed. See:
// https://discourse.llvm.org/t/dialect-for-data-locality-sharing-specifiers-clauses-in-openmp-openacc-and-do-concurrent/86108.
llvm::LogicalResult fir::LocalitySpecifierOp::verifyRegions() {
  mlir::Type argType = getArgType();
  auto verifyTerminator = [&](mlir::Operation *terminator,
                              bool yieldsValue) -> llvm::LogicalResult {
    if (!terminator->getBlock()->getSuccessors().empty())
      return llvm::success();

    if (!llvm::isa<fir::YieldOp>(terminator))
      return mlir::emitError(terminator->getLoc())
             << "expected exit block terminator to be an `fir.yield` op.";

    YieldOp yieldOp = llvm::cast<YieldOp>(terminator);
    mlir::TypeRange yieldedTypes = yieldOp.getResults().getTypes();

    if (!yieldsValue) {
      if (yieldedTypes.empty())
        return llvm::success();

      return mlir::emitError(terminator->getLoc())
             << "Did not expect any values to be yielded.";
    }

    if (yieldedTypes.size() == 1 && yieldedTypes.front() == argType)
      return llvm::success();

    auto error = mlir::emitError(yieldOp.getLoc())
                 << "Invalid yielded value. Expected type: " << argType
                 << ", got: ";

    if (yieldedTypes.empty())
      error << "None";
    else
      error << yieldedTypes;

    return error;
  };

  auto verifyRegion = [&](mlir::Region &region, unsigned expectedNumArgs,
                          llvm::StringRef regionName,
                          bool yieldsValue) -> llvm::LogicalResult {
    assert(!region.empty());

    if (region.getNumArguments() != expectedNumArgs)
      return mlir::emitError(region.getLoc())
             << "`" << regionName << "`: "
             << "expected " << expectedNumArgs
             << " region arguments, got: " << region.getNumArguments();

    for (mlir::Block &block : region) {
      // MLIR will verify the absence of the terminator for us.
      if (!block.mightHaveTerminator())
        continue;

      if (failed(verifyTerminator(block.getTerminator(), yieldsValue)))
        return llvm::failure();
    }

    return llvm::success();
  };

  // Ensure all of the region arguments have the same type
  for (mlir::Region *region : getRegions())
    for (mlir::Type ty : region->getArgumentTypes())
      if (ty != argType)
        return emitError() << "Region argument type mismatch: got " << ty
                           << " expected " << argType << ".";

  mlir::Region &initRegion = getInitRegion();
  if (!initRegion.empty() &&
      failed(verifyRegion(getInitRegion(), /*expectedNumArgs=*/2, "init",
                          /*yieldsValue=*/true)))
    return llvm::failure();

  LocalitySpecifierType dsType = getLocalitySpecifierType();

  if (dsType == LocalitySpecifierType::Local && !getCopyRegion().empty())
    return emitError("`local` specifiers do not require a `copy` region.");

  if (dsType == LocalitySpecifierType::LocalInit && getCopyRegion().empty())
    return emitError(
        "`local_init` specifiers require at least a `copy` region.");

  if (dsType == LocalitySpecifierType::LocalInit &&
      failed(verifyRegion(getCopyRegion(), /*expectedNumArgs=*/2, "copy",
                          /*yieldsValue=*/true)))
    return llvm::failure();

  if (!getDeallocRegion().empty() &&
      failed(verifyRegion(getDeallocRegion(), /*expectedNumArgs=*/1, "dealloc",
                          /*yieldsValue=*/false)))
    return llvm::failure();

  return llvm::success();
}

// TODO This is a copy of omp::DeclareReductionOp::verifiyRegions(). Once we
// find a solution to merge both ops into one this duplication will not be
// needed.
mlir::LogicalResult fir::DeclareReductionOp::verifyRegions() {
  if (!getAllocRegion().empty()) {
    for (YieldOp yieldOp : getAllocRegion().getOps<YieldOp>()) {
      if (yieldOp.getResults().size() != 1 ||
          yieldOp.getResults().getTypes()[0] != getType())
        return emitOpError() << "expects alloc region to yield a value "
                                "of the reduction type";
    }
  }

  if (getInitializerRegion().empty())
    return emitOpError() << "expects non-empty initializer region";
  mlir::Block &initializerEntryBlock = getInitializerRegion().front();

  if (initializerEntryBlock.getNumArguments() == 1) {
    if (!getAllocRegion().empty())
      return emitOpError() << "expects two arguments to the initializer region "
                              "when an allocation region is used";
  } else if (initializerEntryBlock.getNumArguments() == 2) {
    if (getAllocRegion().empty())
      return emitOpError() << "expects one argument to the initializer region "
                              "when no allocation region is used";
  } else {
    return emitOpError()
           << "expects one or two arguments to the initializer region";
  }

  for (mlir::Value arg : initializerEntryBlock.getArguments())
    if (arg.getType() != getType())
      return emitOpError() << "expects initializer region argument to match "
                              "the reduction type";

  for (YieldOp yieldOp : getInitializerRegion().getOps<YieldOp>()) {
    if (yieldOp.getResults().size() != 1 ||
        yieldOp.getResults().getTypes()[0] != getType())
      return emitOpError() << "expects initializer region to yield a value "
                              "of the reduction type";
  }

  if (getReductionRegion().empty())
    return emitOpError() << "expects non-empty reduction region";
  mlir::Block &reductionEntryBlock = getReductionRegion().front();
  if (reductionEntryBlock.getNumArguments() != 2 ||
      reductionEntryBlock.getArgumentTypes()[0] !=
          reductionEntryBlock.getArgumentTypes()[1] ||
      reductionEntryBlock.getArgumentTypes()[0] != getType())
    return emitOpError() << "expects reduction region with two arguments of "
                            "the reduction type";
  for (YieldOp yieldOp : getReductionRegion().getOps<YieldOp>()) {
    if (yieldOp.getResults().size() != 1 ||
        yieldOp.getResults().getTypes()[0] != getType())
      return emitOpError() << "expects reduction region to yield a value "
                              "of the reduction type";
  }

  if (!getAtomicReductionRegion().empty()) {
    mlir::Block &atomicReductionEntryBlock = getAtomicReductionRegion().front();
    if (atomicReductionEntryBlock.getNumArguments() != 2 ||
        atomicReductionEntryBlock.getArgumentTypes()[0] !=
            atomicReductionEntryBlock.getArgumentTypes()[1])
      return emitOpError() << "expects atomic reduction region with two "
                              "arguments of the same type";
  }

  if (getCleanupRegion().empty())
    return mlir::success();
  mlir::Block &cleanupEntryBlock = getCleanupRegion().front();
  if (cleanupEntryBlock.getNumArguments() != 1 ||
      cleanupEntryBlock.getArgument(0).getType() != getType())
    return emitOpError() << "expects cleanup region with one argument "
                            "of the reduction type";

  return mlir::success();
}

//===----------------------------------------------------------------------===//
// DoConcurrentOp
//===----------------------------------------------------------------------===//

llvm::LogicalResult fir::DoConcurrentOp::verify() {
  mlir::Block *body = getBody();

  if (body->empty())
    return emitOpError("body cannot be empty");

  if (!body->mightHaveTerminator() ||
      !mlir::isa<fir::DoConcurrentLoopOp>(body->getTerminator()))
    return emitOpError("must be terminated by 'fir.do_concurrent.loop'");

  return mlir::success();
}

//===----------------------------------------------------------------------===//
// DoConcurrentLoopOp
//===----------------------------------------------------------------------===//

static mlir::ParseResult parseSpecifierList(
    mlir::OpAsmParser &parser, mlir::OperationState &result,
    llvm::StringRef specifierKeyword, llvm::StringRef symsAttrName,
    llvm::SmallVectorImpl<mlir::OpAsmParser::Argument> &regionArgs,
    llvm::SmallVectorImpl<mlir::Type> &regionArgTypes,
    int32_t &numSpecifierOperands, bool isReduce = false) {
  auto &builder = parser.getBuilder();
  llvm::SmallVector<mlir::OpAsmParser::UnresolvedOperand> specifierOperands;

  if (failed(parser.parseOptionalKeyword(specifierKeyword)))
    return mlir::success();

  std::size_t oldArgTypesSize = regionArgTypes.size();
  if (failed(parser.parseLParen()))
    return mlir::failure();

  llvm::SmallVector<bool> isByRefVec;
  llvm::SmallVector<mlir::SymbolRefAttr> spceifierSymbolVec;
  llvm::SmallVector<fir::ReduceAttr> attributes;

  if (failed(parser.parseCommaSeparatedList([&]() {
        if (isReduce)
          isByRefVec.push_back(
              parser.parseOptionalKeyword("byref").succeeded());

        if (failed(parser.parseAttribute(spceifierSymbolVec.emplace_back())))
          return mlir::failure();

        if (isReduce &&
            failed(parser.parseAttribute(attributes.emplace_back())))
          return mlir::failure();

        if (parser.parseOperand(specifierOperands.emplace_back()) ||
            parser.parseArrow() ||
            parser.parseArgument(regionArgs.emplace_back()))
          return mlir::failure();

        return mlir::success();
      })))
    return mlir::failure();

  if (failed(parser.parseColon()))
    return mlir::failure();

  if (failed(parser.parseCommaSeparatedList([&]() {
        if (failed(parser.parseType(regionArgTypes.emplace_back())))
          return mlir::failure();

        return mlir::success();
      })))
    return mlir::failure();

  if (regionArgs.size() != regionArgTypes.size())
    return parser.emitError(parser.getNameLoc(), "mismatch in number of " +
                                                     specifierKeyword.str() +
                                                     " arg and types");

  if (failed(parser.parseRParen()))
    return mlir::failure();

  for (auto operandType :
       llvm::zip_equal(specifierOperands,
                       llvm::drop_begin(regionArgTypes, oldArgTypesSize)))
    if (parser.resolveOperand(std::get<0>(operandType),
                              std::get<1>(operandType), result.operands))
      return mlir::failure();

  if (isReduce)
    result.addAttribute(
        fir::DoConcurrentLoopOp::getReduceByrefAttrName(result.name),
        isByRefVec.empty()
            ? nullptr
            : mlir::DenseBoolArrayAttr::get(builder.getContext(), isByRefVec));

  llvm::SmallVector<mlir::Attribute> symbolAttrs(spceifierSymbolVec.begin(),
                                                 spceifierSymbolVec.end());
  result.addAttribute(symsAttrName, builder.getArrayAttr(symbolAttrs));

  if (isReduce) {
    llvm::SmallVector<mlir::Attribute> arrayAttr(attributes.begin(),
                                                 attributes.end());
    result.addAttribute(
        fir::DoConcurrentLoopOp::getReduceAttrsAttrName(result.name),
        builder.getArrayAttr(arrayAttr));
  }

  numSpecifierOperands = specifierOperands.size();

  return mlir::success();
}

mlir::ParseResult fir::DoConcurrentLoopOp::parse(mlir::OpAsmParser &parser,
                                                 mlir::OperationState &result) {
  auto &builder = parser.getBuilder();
  // Parse an opening `(` followed by induction variables followed by `)`
  llvm::SmallVector<mlir::OpAsmParser::Argument, 4> regionArgs;

  if (parser.parseArgumentList(regionArgs, mlir::OpAsmParser::Delimiter::Paren))
    return mlir::failure();

  llvm::SmallVector<mlir::Type> argTypes(regionArgs.size(),
                                         builder.getIndexType());

  // Parse loop bounds.
  llvm::SmallVector<mlir::OpAsmParser::UnresolvedOperand, 4> lower;
  if (parser.parseEqual() ||
      parser.parseOperandList(lower, regionArgs.size(),
                              mlir::OpAsmParser::Delimiter::Paren) ||
      parser.resolveOperands(lower, builder.getIndexType(), result.operands))
    return mlir::failure();

  llvm::SmallVector<mlir::OpAsmParser::UnresolvedOperand, 4> upper;
  if (parser.parseKeyword("to") ||
      parser.parseOperandList(upper, regionArgs.size(),
                              mlir::OpAsmParser::Delimiter::Paren) ||
      parser.resolveOperands(upper, builder.getIndexType(), result.operands))
    return mlir::failure();

  // Parse step values.
  llvm::SmallVector<mlir::OpAsmParser::UnresolvedOperand, 4> steps;
  if (parser.parseKeyword("step") ||
      parser.parseOperandList(steps, regionArgs.size(),
                              mlir::OpAsmParser::Delimiter::Paren) ||
      parser.resolveOperands(steps, builder.getIndexType(), result.operands))
    return mlir::failure();

  int32_t numLocalOperands = 0;
  if (failed(parseSpecifierList(parser, result, "local",
                                getLocalSymsAttrName(result.name), regionArgs,
                                argTypes, numLocalOperands)))
    return mlir::failure();

  int32_t numReduceOperands = 0;
  if (failed(parseSpecifierList(
          parser, result, "reduce", getReduceSymsAttrName(result.name),
          regionArgs, argTypes, numReduceOperands, /*isReduce=*/true)))
    return mlir::failure();

  // Set `operandSegmentSizes` attribute.
  result.addAttribute(
      DoConcurrentLoopOp::getOperandSegmentSizeAttr(),
      builder.getDenseI32ArrayAttr({static_cast<int32_t>(lower.size()),
                                    static_cast<int32_t>(upper.size()),
                                    static_cast<int32_t>(steps.size()),
                                    static_cast<int32_t>(numLocalOperands),
                                    static_cast<int32_t>(numReduceOperands)}));

  // Now parse the body.
  for (auto [arg, type] : llvm::zip_equal(regionArgs, argTypes))
    arg.type = type;

  mlir::Region *body = result.addRegion();
  if (parser.parseRegion(*body, regionArgs))
    return mlir::failure();

  // Parse attributes.
  if (parser.parseOptionalAttrDict(result.attributes))
    return mlir::failure();

  return mlir::success();
}

void fir::DoConcurrentLoopOp::print(mlir::OpAsmPrinter &p) {
  p << " (" << getBody()->getArguments().slice(0, getNumInductionVars())
    << ") = (" << getLowerBound() << ") to (" << getUpperBound() << ") step ("
    << getStep() << ")";

  if (!getLocalVars().empty()) {
    p << " local(";
    llvm::interleaveComma(llvm::zip_equal(getLocalSymsAttr(), getLocalVars(),
                                          getRegionLocalArgs()),
                          p, [&](auto it) {
                            p << std::get<0>(it) << " " << std::get<1>(it)
                              << " -> " << std::get<2>(it);
                          });
    p << " : ";
    llvm::interleaveComma(getLocalVars(), p,
                          [&](auto it) { p << it.getType(); });
    p << ")";
  }

  if (!getReduceVars().empty()) {
    p << " reduce(";
    llvm::interleaveComma(
        llvm::zip_equal(getReduceByrefAttr().asArrayRef(), getReduceSymsAttr(),
                        getReduceAttrsAttr(), getReduceVars(),
                        getRegionReduceArgs()),
        p, [&](auto it) {
          if (std::get<0>(it))
            p << "byref ";

          p << std::get<1>(it) << " " << std::get<2>(it) << " "
            << std::get<3>(it) << " -> " << std::get<4>(it);
        });
    p << " : ";
    llvm::interleaveComma(getReduceVars(), p,
                          [&](auto it) { p << it.getType(); });
    p << ")";
  }

  p << ' ';
  p.printRegion(getRegion(), /*printEntryBlockArgs=*/false);
  p.printOptionalAttrDict(
      (*this)->getAttrs(),
      /*elidedAttrs=*/{DoConcurrentLoopOp::getOperandSegmentSizeAttr(),
                       DoConcurrentLoopOp::getLocalSymsAttrName(),
                       DoConcurrentLoopOp::getReduceSymsAttrName(),
                       DoConcurrentLoopOp::getReduceAttrsAttrName(),
                       DoConcurrentLoopOp::getReduceByrefAttrName()});
}

llvm::SmallVector<mlir::Region *> fir::DoConcurrentLoopOp::getLoopRegions() {
  return {&getRegion()};
}

llvm::LogicalResult fir::DoConcurrentLoopOp::verify() {
  mlir::Operation::operand_range lbValues = getLowerBound();
  mlir::Operation::operand_range ubValues = getUpperBound();
  mlir::Operation::operand_range stepValues = getStep();
  mlir::Operation::operand_range localVars = getLocalVars();
  mlir::Operation::operand_range reduceVars = getReduceVars();

  if (lbValues.empty())
    return emitOpError(
        "needs at least one tuple element for lowerBound, upperBound and step");

  if (lbValues.size() != ubValues.size() ||
      ubValues.size() != stepValues.size())
    return emitOpError("different number of tuple elements for lowerBound, "
                       "upperBound or step");

  // Check that the body defines the same number of block arguments as the
  // number of tuple elements in step.
  mlir::Block *body = getBody();
  unsigned numIndVarArgs =
      body->getNumArguments() - localVars.size() - reduceVars.size();

  if (numIndVarArgs != stepValues.size())
    return emitOpError() << "expects the same number of induction variables: "
                         << body->getNumArguments()
                         << " as bound and step values: " << stepValues.size();
  for (auto arg : body->getArguments().slice(0, numIndVarArgs))
    if (!arg.getType().isIndex())
      return emitOpError(
          "expects arguments for the induction variable to be of index type");

  auto reduceAttrs = getReduceAttrsAttr();
  if (getNumReduceOperands() != (reduceAttrs ? reduceAttrs.size() : 0))
    return emitOpError(
        "mismatch in number of reduction variables and reduction attributes");

  return mlir::success();
}

std::optional<llvm::SmallVector<mlir::Value>>
fir::DoConcurrentLoopOp::getLoopInductionVars() {
  return llvm::SmallVector<mlir::Value>{
      getBody()->getArguments().slice(0, getLowerBound().size())};
}

//===----------------------------------------------------------------------===//
// FIROpsDialect
//===----------------------------------------------------------------------===//

void fir::FIROpsDialect::registerOpExternalInterfaces() {
  // Attach default declare target interfaces to operations which can be marked
  // as declare target.
  fir::GlobalOp::attachInterface<
      mlir::omp::DeclareTargetDefaultModel<fir::GlobalOp>>(*getContext());
}

// Tablegen operators

#define GET_OP_CLASSES
#include "flang/Optimizer/Dialect/FIROps.cpp.inc"
