Repository: llvm/llvm-project
File: mlir/lib/Dialect/LLVMIR/Transforms/InlinerInterfaceImpl.cpp (C++)

Code before:
      return false;
    }
    if (funcOp.getPassthrough()) {
      // TODO: Used attributes should not be passthrough.
      if (llvm::any_of(*funcOp.getPassthrough(), [&](Attribute attr) {
            auto stringAttr = dyn_cast<StringAttr>(attr);
            if (!stringAttr)
              return false;
            if (disallowedFunctionAttrs.contains(stringAttr)) {
              LDBG() << "Cannot inline " << funcOp.getSymName()
                     << ": found disallowed function attribute " << stringAttr;
              return true;
            }
            return false;
          }))
        return false;
    }
    // Refuse to inline if any block in the callee ends with an op that does
    // not have the terminator trait. The MLIR verifier conservatively accepts
    // unregistered ops as potential terminators, but the LLVM inliner's
    // handleTerminator relies on the terminator being a recognized LLVM op
    // (e.g. llvm.return). Inlining a callee with an unrecognized terminator
    // would crash.
    for (Block &block : funcOp.getBody()) {
      if (!block.empty() && !block.back().hasTrait<OpTrait::IsTerminator>()) {
        LDBG() << "Cannot inline " << funcOp.getSymName()
               << ": block ends with non-terminator op";
        return false;
      }
    }
    return true;
  }

  bool isLegalToInline(Region *, Region *, bool, IRMapping &) const final {
    return true;
  }

  bool isLegalToInline(Operation *op, Region *, bool, IRMapping &) const final {
    // The inliner cannot handle variadic function arguments and blocktag
    // operations prevent inlining since they the blockaddress operations
    // reference them via the callee symbol.
    return !(isa<LLVM::VaStartOp>(op) || isa<LLVM::BlockTagOp>(op));
  }

  /// Handle the given inlined return by replacing it with a branch. This
  /// overload is called when the inlined region has more than one block.
  void handleTerminator(Operation *op, Block *newDest) const final {
    // Only return needs to be handled here.
    auto returnOp = dyn_cast<LLVM::ReturnOp>(op);
    if (!returnOp)
      return;

Review comment (suggestion):
Is it enough to check for `IsTerminator`? Based on the comment, it sounds like it must be an LLVM op.


Code after:
      return false;
    }
    if (funcOp.getPassthrough()) {
      // TODO: Used attributes should not be passthrough.
      if (llvm::any_of(*funcOp.getPassthrough(), [&](Attribute attr) {
            auto stringAttr = dyn_cast<StringAttr>(attr);
            if (!stringAttr)
              return false;
            if (disallowedFunctionAttrs.contains(stringAttr)) {
              LDBG() << "Cannot inline " << funcOp.getSymName()
                     << ": found disallowed function attribute " << stringAttr;
              return true;
            }
            return false;
          }))
        return false;
    }
    // Refuse to inline if any block in the callee ends with an op that does
    // not have the terminator trait. The MLIR verifier conservatively accepts
    // unregistered ops as potential terminators (via mightHaveTrait), but
    // handleTerminator uses cast<LLVM::ReturnOp> in the single-block path and
    // would crash on such ops. Registered terminators from other dialects
    // (e.g. cf.br) are safe: the multi-block path uses dyn_cast and skips
    // non-llvm.return ops gracefully.
    for (Block &block : funcOp.getBody()) {
      if (!block.empty() && !block.back().hasTrait<OpTrait::IsTerminator>()) {
        LDBG() << "Cannot inline " << funcOp.getSymName()
               << ": block ends with non-terminator op";
        return false;
      }
    }
    return true;
  }

  bool isLegalToInline(Region *, Region *, bool, IRMapping &) const final {
    return true;
  }

  bool isLegalToInline(Operation *op, Region *, bool, IRMapping &) const final {
    // The inliner cannot handle variadic function arguments and blocktag
    // operations prevent inlining since they the blockaddress operations
    // reference them via the callee symbol.
    return !(isa<LLVM::VaStartOp>(op) || isa<LLVM::BlockTagOp>(op));
  }

  /// Handle the given inlined return by replacing it with a branch. This
  /// overload is called when the inlined region has more than one block.
  void handleTerminator(Operation *op, Block *newDest) const final {
    // Only return needs to be handled here.
    auto returnOp = dyn_cast<LLVM::ReturnOp>(op);
    if (!returnOp)