
# Autogenerated by mlir-tblgen; don't manually edit.

from ._ods_common import _cext as _ods_cext
from ._ods_common import (
    equally_sized_accessor as _ods_equally_sized_accessor,
    get_default_loc_context as _ods_get_default_loc_context,
    get_op_results_or_values as _get_op_results_or_values,
    segmented_accessor as _ods_segmented_accessor,
)
_ods_ir = _ods_cext.ir
_ods_cext.globals.register_traceback_file_exclusion(__file__)

import builtins
from typing import Any as _Any, Sequence as _Sequence, Union as _Union, Optional as _Optional
import sys as _sys
if _sys.version_info >= (3, 12):
  from collections.abc import Buffer as _Buffer  # pytype: disable=not-supported-yet
else:
  try:
    from typing_extensions import Buffer as _Buffer
  except ImportError:
    _Buffer = _Any


from ._transform_ops_gen import _Dialect

@_ods_cext.register_operation(_Dialect)
class ApplyDataLayoutPropagationPatternsOp(_ods_ir.OpView):
  r"""
  Collection of patterns to bubble up or down data layout ops across other
  operations.
  """

  OPERATION_NAME = "transform.apply_patterns.linalg.data_layout_propagation"

  _ODS_REGIONS = (0, True)

  def __init__(self, *, poison_padding: _Optional[_Union[bool, _ods_ir.BoolAttr]] = None, loc: _Optional[_ods_ir.Location] = None, ip: _Optional[_ods_ir.InsertionPoint] = None):
    operands = []
    attributes = {}
    regions = None
    _ods_context = _ods_get_default_loc_context(loc)
    if poison_padding is not None: attributes["poison_padding"] = (poison_padding if (
        isinstance(poison_padding, _ods_ir.Attribute) or
        not _ods_ir.AttrBuilder.contains('BoolAttr')) else
          _ods_ir.AttrBuilder.get('BoolAttr')(poison_padding, context=_ods_context))
    results = []
    _ods_successors = None
    super().__init__(self.OPERATION_NAME, self._ODS_REGIONS, self._ODS_OPERAND_SEGMENTS, self._ODS_RESULT_SEGMENTS, attributes=attributes, results=results, operands=operands, successors=_ods_successors, regions=regions, loc=loc, ip=ip)

  @builtins.property
  def poison_padding(self) -> _ods_ir.BoolAttr:
    return self.operation.attributes["poison_padding"]

  @poison_padding.setter
  def poison_padding(self, value: _ods_ir.BoolAttr):
    if value is None:
      raise ValueError("'None' not allowed as value for mandatory attributes")
    self.operation.attributes["poison_padding"] = value

@_ods_cext.register_op_adaptor(ApplyDataLayoutPropagationPatternsOp)
class ApplyDataLayoutPropagationPatternsOpAdaptor(_ods_ir.OpAdaptor):
  OPERATION_NAME = "transform.apply_patterns.linalg.data_layout_propagation"

  @builtins.property
  def poison_padding(self) -> _ods_ir.BoolAttr:
    return self.attributes["poison_padding"]

def apply_patterns_linalg_data_layout_propagation(*, poison_padding: _Optional[_Union[bool, _ods_ir.BoolAttr]] = None, loc: _Optional[_ods_ir.Location] = None, ip: _Optional[_ods_ir.InsertionPoint] = None) -> ApplyDataLayoutPropagationPatternsOp:
  return ApplyDataLayoutPropagationPatternsOp(poison_padding=poison_padding, loc=loc, ip=ip)

@_ods_cext.register_operation(_Dialect)
class ApplyDecomposeTensorPackUnpackPatternsOp(_ods_ir.OpView):
  r"""
  Collect patterns to decompose linalg.pack and linalg.unpack into e.g.
  tensor::PadOp, linalg::transposeOp Ops. Requires all outer dims to be unit.
  """

  OPERATION_NAME = "transform.apply_patterns.linalg.decompose_pack_unpack"

  _ODS_REGIONS = (0, True)

  def __init__(self, *, loc: _Optional[_ods_ir.Location] = None, ip: _Optional[_ods_ir.InsertionPoint] = None):
    operands = []
    attributes = {}
    regions = None
    _ods_context = _ods_get_default_loc_context(loc)
    results = []
    _ods_successors = None
    super().__init__(self.OPERATION_NAME, self._ODS_REGIONS, self._ODS_OPERAND_SEGMENTS, self._ODS_RESULT_SEGMENTS, attributes=attributes, results=results, operands=operands, successors=_ods_successors, regions=regions, loc=loc, ip=ip)

@_ods_cext.register_op_adaptor(ApplyDecomposeTensorPackUnpackPatternsOp)
class ApplyDecomposeTensorPackUnpackPatternsOpAdaptor(_ods_ir.OpAdaptor):
  OPERATION_NAME = "transform.apply_patterns.linalg.decompose_pack_unpack"

def apply_patterns_linalg_decompose_pack_unpack(*, loc: _Optional[_ods_ir.Location] = None, ip: _Optional[_ods_ir.InsertionPoint] = None) -> ApplyDecomposeTensorPackUnpackPatternsOp:
  return ApplyDecomposeTensorPackUnpackPatternsOp(loc=loc, ip=ip)

@_ods_cext.register_operation(_Dialect)
class ApplyDecomposeTensorPadPatternsOp(_ods_ir.OpView):
  r"""
  Collect patterns to decompose tensor.pad into e.g. tensor::EmptyOp,
  linalg::FillOp and tensor::InsertSliceOp.
  """

  OPERATION_NAME = "transform.apply_patterns.linalg.decompose_pad"

  _ODS_REGIONS = (0, True)

  def __init__(self, *, loc: _Optional[_ods_ir.Location] = None, ip: _Optional[_ods_ir.InsertionPoint] = None):
    operands = []
    attributes = {}
    regions = None
    _ods_context = _ods_get_default_loc_context(loc)
    results = []
    _ods_successors = None
    super().__init__(self.OPERATION_NAME, self._ODS_REGIONS, self._ODS_OPERAND_SEGMENTS, self._ODS_RESULT_SEGMENTS, attributes=attributes, results=results, operands=operands, successors=_ods_successors, regions=regions, loc=loc, ip=ip)

@_ods_cext.register_op_adaptor(ApplyDecomposeTensorPadPatternsOp)
class ApplyDecomposeTensorPadPatternsOpAdaptor(_ods_ir.OpAdaptor):
  OPERATION_NAME = "transform.apply_patterns.linalg.decompose_pad"

def apply_patterns_linalg_decompose_pad(*, loc: _Optional[_ods_ir.Location] = None, ip: _Optional[_ods_ir.InsertionPoint] = None) -> ApplyDecomposeTensorPadPatternsOp:
  return ApplyDecomposeTensorPadPatternsOp(loc=loc, ip=ip)

@_ods_cext.register_operation(_Dialect)
class ApplyEraseUnnecessaryInputsPatternsOp(_ods_ir.OpView):
  r"""
  Collects patterns that promote inputs to outputs and remove unused inputs of
  `linalg.generic` ops.
  """

  OPERATION_NAME = "transform.apply_patterns.linalg.erase_unnecessary_inputs"

  _ODS_REGIONS = (0, True)

  def __init__(self, *, loc: _Optional[_ods_ir.Location] = None, ip: _Optional[_ods_ir.InsertionPoint] = None):
    operands = []
    attributes = {}
    regions = None
    _ods_context = _ods_get_default_loc_context(loc)
    results = []
    _ods_successors = None
    super().__init__(self.OPERATION_NAME, self._ODS_REGIONS, self._ODS_OPERAND_SEGMENTS, self._ODS_RESULT_SEGMENTS, attributes=attributes, results=results, operands=operands, successors=_ods_successors, regions=regions, loc=loc, ip=ip)

@_ods_cext.register_op_adaptor(ApplyEraseUnnecessaryInputsPatternsOp)
class ApplyEraseUnnecessaryInputsPatternsOpAdaptor(_ods_ir.OpAdaptor):
  OPERATION_NAME = "transform.apply_patterns.linalg.erase_unnecessary_inputs"

def apply_patterns_linalg_erase_unnecessary_inputs(*, loc: _Optional[_ods_ir.Location] = None, ip: _Optional[_ods_ir.InsertionPoint] = None) -> ApplyEraseUnnecessaryInputsPatternsOp:
  return ApplyEraseUnnecessaryInputsPatternsOp(loc=loc, ip=ip)

@_ods_cext.register_operation(_Dialect)
class ApplyExtractSliceSinkingPatternsOp(_ods_ir.OpView):
  r"""
  Patterns to sink extract slice across other operations.
  """

  OPERATION_NAME = "transform.apply_patterns.linalg.extract_slice_sinking"

  _ODS_REGIONS = (0, True)

  def __init__(self, *, loc: _Optional[_ods_ir.Location] = None, ip: _Optional[_ods_ir.InsertionPoint] = None):
    operands = []
    attributes = {}
    regions = None
    _ods_context = _ods_get_default_loc_context(loc)
    results = []
    _ods_successors = None
    super().__init__(self.OPERATION_NAME, self._ODS_REGIONS, self._ODS_OPERAND_SEGMENTS, self._ODS_RESULT_SEGMENTS, attributes=attributes, results=results, operands=operands, successors=_ods_successors, regions=regions, loc=loc, ip=ip)

@_ods_cext.register_op_adaptor(ApplyExtractSliceSinkingPatternsOp)
class ApplyExtractSliceSinkingPatternsOpAdaptor(_ods_ir.OpAdaptor):
  OPERATION_NAME = "transform.apply_patterns.linalg.extract_slice_sinking"

def apply_patterns_linalg_extract_slice_sinking(*, loc: _Optional[_ods_ir.Location] = None, ip: _Optional[_ods_ir.InsertionPoint] = None) -> ApplyExtractSliceSinkingPatternsOp:
  return ApplyExtractSliceSinkingPatternsOp(loc=loc, ip=ip)

@_ods_cext.register_operation(_Dialect)
class ApplyFoldAddIntoDestPatternsOp(_ods_ir.OpView):
  r"""
  Collects patterns to replace linalg.add when destination passing suffices
  for achieving the sum.
  """

  OPERATION_NAME = "transform.apply_patterns.linalg.fold_add_into_dest"

  _ODS_REGIONS = (0, True)

  def __init__(self, *, loc: _Optional[_ods_ir.Location] = None, ip: _Optional[_ods_ir.InsertionPoint] = None):
    operands = []
    attributes = {}
    regions = None
    _ods_context = _ods_get_default_loc_context(loc)
    results = []
    _ods_successors = None
    super().__init__(self.OPERATION_NAME, self._ODS_REGIONS, self._ODS_OPERAND_SEGMENTS, self._ODS_RESULT_SEGMENTS, attributes=attributes, results=results, operands=operands, successors=_ods_successors, regions=regions, loc=loc, ip=ip)

@_ods_cext.register_op_adaptor(ApplyFoldAddIntoDestPatternsOp)
class ApplyFoldAddIntoDestPatternsOpAdaptor(_ods_ir.OpAdaptor):
  OPERATION_NAME = "transform.apply_patterns.linalg.fold_add_into_dest"

def apply_patterns_linalg_fold_add_into_dest(*, loc: _Optional[_ods_ir.Location] = None, ip: _Optional[_ods_ir.InsertionPoint] = None) -> ApplyFoldAddIntoDestPatternsOp:
  return ApplyFoldAddIntoDestPatternsOp(loc=loc, ip=ip)

@_ods_cext.register_operation(_Dialect)
class ApplyFoldIntoPackAndUnpackPatternsOp(_ods_ir.OpView):
  r"""
  Indicates that operations like tensor.pad and tensor.extract_slice should
  be folded into linalg.pack and linalg.unpack operations, respectively.
  """

  OPERATION_NAME = "transform.apply_patterns.tensor.fold_into_pack_and_unpack"

  _ODS_REGIONS = (0, True)

  def __init__(self, *, loc: _Optional[_ods_ir.Location] = None, ip: _Optional[_ods_ir.InsertionPoint] = None):
    operands = []
    attributes = {}
    regions = None
    _ods_context = _ods_get_default_loc_context(loc)
    results = []
    _ods_successors = None
    super().__init__(self.OPERATION_NAME, self._ODS_REGIONS, self._ODS_OPERAND_SEGMENTS, self._ODS_RESULT_SEGMENTS, attributes=attributes, results=results, operands=operands, successors=_ods_successors, regions=regions, loc=loc, ip=ip)

@_ods_cext.register_op_adaptor(ApplyFoldIntoPackAndUnpackPatternsOp)
class ApplyFoldIntoPackAndUnpackPatternsOpAdaptor(_ods_ir.OpAdaptor):
  OPERATION_NAME = "transform.apply_patterns.tensor.fold_into_pack_and_unpack"

def apply_patterns_tensor_fold_into_pack_and_unpack(*, loc: _Optional[_ods_ir.Location] = None, ip: _Optional[_ods_ir.InsertionPoint] = None) -> ApplyFoldIntoPackAndUnpackPatternsOp:
  return ApplyFoldIntoPackAndUnpackPatternsOp(loc=loc, ip=ip)

@_ods_cext.register_operation(_Dialect)
class ApplyFoldPackUnpackIntoEmptyPatternsOp(_ods_ir.OpView):
  r"""
  // TODO:
  """

  OPERATION_NAME = "transform.apply_patterns.linalg.fold_pack_unpack_into_empty"

  _ODS_REGIONS = (0, True)

  def __init__(self, *, fold_single_use_only: _Optional[_Union[bool, _ods_ir.BoolAttr]] = None, loc: _Optional[_ods_ir.Location] = None, ip: _Optional[_ods_ir.InsertionPoint] = None):
    operands = []
    attributes = {}
    regions = None
    _ods_context = _ods_get_default_loc_context(loc)
    if fold_single_use_only is not None: attributes["fold_single_use_only"] = (fold_single_use_only if (
        isinstance(fold_single_use_only, _ods_ir.Attribute) or
        not _ods_ir.AttrBuilder.contains('BoolAttr')) else
          _ods_ir.AttrBuilder.get('BoolAttr')(fold_single_use_only, context=_ods_context))
    results = []
    _ods_successors = None
    super().__init__(self.OPERATION_NAME, self._ODS_REGIONS, self._ODS_OPERAND_SEGMENTS, self._ODS_RESULT_SEGMENTS, attributes=attributes, results=results, operands=operands, successors=_ods_successors, regions=regions, loc=loc, ip=ip)

  @builtins.property
  def fold_single_use_only(self) -> _ods_ir.BoolAttr:
    return self.operation.attributes["fold_single_use_only"]

  @fold_single_use_only.setter
  def fold_single_use_only(self, value: _ods_ir.BoolAttr):
    if value is None:
      raise ValueError("'None' not allowed as value for mandatory attributes")
    self.operation.attributes["fold_single_use_only"] = value

@_ods_cext.register_op_adaptor(ApplyFoldPackUnpackIntoEmptyPatternsOp)
class ApplyFoldPackUnpackIntoEmptyPatternsOpAdaptor(_ods_ir.OpAdaptor):
  OPERATION_NAME = "transform.apply_patterns.linalg.fold_pack_unpack_into_empty"

  @builtins.property
  def fold_single_use_only(self) -> _ods_ir.BoolAttr:
    return self.attributes["fold_single_use_only"]

def apply_patterns_linalg_fold_pack_unpack_into_empty(*, fold_single_use_only: _Optional[_Union[bool, _ods_ir.BoolAttr]] = None, loc: _Optional[_ods_ir.Location] = None, ip: _Optional[_ods_ir.InsertionPoint] = None) -> ApplyFoldPackUnpackIntoEmptyPatternsOp:
  return ApplyFoldPackUnpackIntoEmptyPatternsOp(fold_single_use_only=fold_single_use_only, loc=loc, ip=ip)

@_ods_cext.register_operation(_Dialect)
class ApplyFoldUnitExtentDimsViaReshapesPatternsOp(_ods_ir.OpView):
  r"""
  Collects patterns to fold unit-extent dimensions in operands/results of
  linalg ops on tensors via reassociative reshape ops.
  """

  OPERATION_NAME = "transform.apply_patterns.linalg.fold_unit_extent_dims_via_reshapes"

  _ODS_REGIONS = (0, True)

  def __init__(self, *, loc: _Optional[_ods_ir.Location] = None, ip: _Optional[_ods_ir.InsertionPoint] = None):
    operands = []
    attributes = {}
    regions = None
    _ods_context = _ods_get_default_loc_context(loc)
    results = []
    _ods_successors = None
    super().__init__(self.OPERATION_NAME, self._ODS_REGIONS, self._ODS_OPERAND_SEGMENTS, self._ODS_RESULT_SEGMENTS, attributes=attributes, results=results, operands=operands, successors=_ods_successors, regions=regions, loc=loc, ip=ip)

@_ods_cext.register_op_adaptor(ApplyFoldUnitExtentDimsViaReshapesPatternsOp)
class ApplyFoldUnitExtentDimsViaReshapesPatternsOpAdaptor(_ods_ir.OpAdaptor):
  OPERATION_NAME = "transform.apply_patterns.linalg.fold_unit_extent_dims_via_reshapes"

def apply_patterns_linalg_fold_unit_extent_dims_via_reshapes(*, loc: _Optional[_ods_ir.Location] = None, ip: _Optional[_ods_ir.InsertionPoint] = None) -> ApplyFoldUnitExtentDimsViaReshapesPatternsOp:
  return ApplyFoldUnitExtentDimsViaReshapesPatternsOp(loc=loc, ip=ip)

@_ods_cext.register_operation(_Dialect)
class ApplyFoldUnitExtentDimsViaSlicesPatternsOp(_ods_ir.OpView):
  r"""
  Collects patterns to fold unit-extent dimensions in operands/results of
  linalg ops on tensors via rank-reducing slices.
  """

  OPERATION_NAME = "transform.apply_patterns.linalg.fold_unit_extent_dims_via_slices"

  _ODS_REGIONS = (0, True)

  def __init__(self, *, loc: _Optional[_ods_ir.Location] = None, ip: _Optional[_ods_ir.InsertionPoint] = None):
    operands = []
    attributes = {}
    regions = None
    _ods_context = _ods_get_default_loc_context(loc)
    results = []
    _ods_successors = None
    super().__init__(self.OPERATION_NAME, self._ODS_REGIONS, self._ODS_OPERAND_SEGMENTS, self._ODS_RESULT_SEGMENTS, attributes=attributes, results=results, operands=operands, successors=_ods_successors, regions=regions, loc=loc, ip=ip)

@_ods_cext.register_op_adaptor(ApplyFoldUnitExtentDimsViaSlicesPatternsOp)
class ApplyFoldUnitExtentDimsViaSlicesPatternsOpAdaptor(_ods_ir.OpAdaptor):
  OPERATION_NAME = "transform.apply_patterns.linalg.fold_unit_extent_dims_via_slices"

def apply_patterns_linalg_fold_unit_extent_dims_via_slices(*, loc: _Optional[_ods_ir.Location] = None, ip: _Optional[_ods_ir.InsertionPoint] = None) -> ApplyFoldUnitExtentDimsViaSlicesPatternsOp:
  return ApplyFoldUnitExtentDimsViaSlicesPatternsOp(loc=loc, ip=ip)

@_ods_cext.register_operation(_Dialect)
class ApplyPadVectorizationPatternsOp(_ods_ir.OpView):
  r"""
  Apply patterns that vectorize tensor.pad.
  
  These patterns rewrite tensor.pad Ops using vector.transfer_read and
  vector.transfer_write operations. This is done either by:
    1. Folding tensor.pad with an existing vector.transfer_read /
    vector.transfer_write Op (generated prior to running these patterns). 
    2. Rewriting it (when matched together with q tensor.insert_slice
    consumer Op) as a vector.transfer_read + vector.transfer_write pair.
  
  In both cases, these patterns look at producers and consumers for the
  matched tensor.pad Op to find opportunities for vectorization.
  """

  OPERATION_NAME = "transform.apply_patterns.linalg.pad_vectorization"

  _ODS_REGIONS = (0, True)

  def __init__(self, *, loc: _Optional[_ods_ir.Location] = None, ip: _Optional[_ods_ir.InsertionPoint] = None):
    operands = []
    attributes = {}
    regions = None
    _ods_context = _ods_get_default_loc_context(loc)
    results = []
    _ods_successors = None
    super().__init__(self.OPERATION_NAME, self._ODS_REGIONS, self._ODS_OPERAND_SEGMENTS, self._ODS_RESULT_SEGMENTS, attributes=attributes, results=results, operands=operands, successors=_ods_successors, regions=regions, loc=loc, ip=ip)

@_ods_cext.register_op_adaptor(ApplyPadVectorizationPatternsOp)
class ApplyPadVectorizationPatternsOpAdaptor(_ods_ir.OpAdaptor):
  OPERATION_NAME = "transform.apply_patterns.linalg.pad_vectorization"

def apply_patterns_linalg_pad_vectorization(*, loc: _Optional[_ods_ir.Location] = None, ip: _Optional[_ods_ir.InsertionPoint] = None) -> ApplyPadVectorizationPatternsOp:
  return ApplyPadVectorizationPatternsOp(loc=loc, ip=ip)

@_ods_cext.register_operation(_Dialect)
class ApplyTilingCanonicalizationPatternsOp(_ods_ir.OpView):
  r"""
  Collects canonicalization patterns relevant to apply after tiling patterns.
  """

  OPERATION_NAME = "transform.apply_patterns.linalg.tiling_canonicalization"

  _ODS_REGIONS = (0, True)

  def __init__(self, *, loc: _Optional[_ods_ir.Location] = None, ip: _Optional[_ods_ir.InsertionPoint] = None):
    operands = []
    attributes = {}
    regions = None
    _ods_context = _ods_get_default_loc_context(loc)
    results = []
    _ods_successors = None
    super().__init__(self.OPERATION_NAME, self._ODS_REGIONS, self._ODS_OPERAND_SEGMENTS, self._ODS_RESULT_SEGMENTS, attributes=attributes, results=results, operands=operands, successors=_ods_successors, regions=regions, loc=loc, ip=ip)

@_ods_cext.register_op_adaptor(ApplyTilingCanonicalizationPatternsOp)
class ApplyTilingCanonicalizationPatternsOpAdaptor(_ods_ir.OpAdaptor):
  OPERATION_NAME = "transform.apply_patterns.linalg.tiling_canonicalization"

def apply_patterns_linalg_tiling_canonicalization(*, loc: _Optional[_ods_ir.Location] = None, ip: _Optional[_ods_ir.InsertionPoint] = None) -> ApplyTilingCanonicalizationPatternsOp:
  return ApplyTilingCanonicalizationPatternsOp(loc=loc, ip=ip)

@_ods_cext.register_operation(_Dialect)
class BufferizeToAllocationOp(_ods_ir.OpView):
  r"""
  This transform bufferizes the targeted operation and materializes the
  result in a new allocation. It replaces all original uses of the target
  result with the newly allocated buffer, wrapped in a
  `bufferization.to_tensor` op. It returns a handle to the newly allocated
  buffer. Furthermore, it returns a handle that is mapped to all newly created
  ops.
  
  Only bufferizable ops are that bufferize to a memory write or have an
  aliasing OpOperand (and do not themselves bufferize to an allocation) are
  supported. They are bufferized using their BufferizableOpInterface
  implementation. E.g.:
  
  ```
  %0 = tensor.insert %f into %dest[%pos] : tensor<10xf32>
  ```
  
  Is bufferized to:
  
  ```
  %alloc = memref.alloc() : memref<10xf32>
  bufferization.materialize_in_destination %dest in %alloc
  memref.store %f, %alloc[%pos] : memref<10xf32>
  %0 = bufferization.to_tensor %alloc restrict writable : memref<10xf32>
  ```
  
  Selected ops that bufferize to an allocation (or need special handling) are
  also supported:
  - `tensor.pad` is lowered to an allocation, followed by a `linalg.fill` and
    and a buffer copy (all on memrefs).
  - `vector.mask` is bufferized together with its region. The allocation is
    placed in front of the `vector.mask` op.
  
  An optional memory space attribute can be specified for the materialized
  buffer allocation.
  
  If a memory copy is needed, a "bufferization.materialize_in_destination" is
  used when possible. This is an op with tensor semantics that will bufferize
  to a memory copy later. Which concrete op will be used for the memory copy
  is up to the bufferization framework. Alternatively, a custom memcpy op can
  be specified via `memcpy_op`. Currently supported are "memref.copy" and
  "linalg.copy". In that case, the source of each memcpy must not have a
  custom memory space. Furthermore, because the future buffer layout unknown
  for a given tensor, a fully dynamic layout is assumed for best
  compatibility. Users should use "bufferization.materialize_in_destination"
  when possible.
  
  "memref.alloc" is used for new buffer allocations. The buffer is deallocated
  at the end of the block if the "emit_dealloc" attribute is present. If this
  attribute is not present, the allocated memory will be leaked. However,
  running the `-buffer-deallocation-pipeline` after all bufferization is done
  will properly insert the corresponding deallocation(s). Custom allocation
  ops can be specified via `alloc_op`. Currently supported are "memref.alloc"
  and "memref.alloca". In case of a "memref.alloca", the buffer is not
  deallocated.
  
  If `bufferize_destination_only` is set, only the destination operands of the
  op are bufferized to a new memory allocation, but not the op itself.
  
  #### Return modes
  
  This operation consumes the `target` handle and produces the
  `allocated_buffer` and `new_ops` handles. It always succeeds.
  """

  OPERATION_NAME = "transform.structured.bufferize_to_allocation"

  _ODS_REGIONS = (0, True)

  def __init__(self, target: _ods_ir.Value, *, memory_space: _Optional[_Union[_Any, _ods_ir.Attribute]] = None, memcpy_op: _Optional[_Union[str, _ods_ir.StringAttr]] = None, alloc_op: _Optional[_Union[str, _ods_ir.StringAttr]] = None, bufferize_destination_only: _Optional[bool] = None, emit_dealloc: _Optional[bool] = None, results: _Optional[_Sequence[_ods_ir.Type]] = None, loc: _Optional[_ods_ir.Location] = None, ip: _Optional[_ods_ir.InsertionPoint] = None):
    operands = []
    attributes = {}
    regions = None
    operands.append(target)
    _ods_context = _ods_get_default_loc_context(loc)
    if memory_space is not None: attributes["memory_space"] = (memory_space if (
        isinstance(memory_space, _ods_ir.Attribute) or
        not _ods_ir.AttrBuilder.contains('AnyAttr')) else
          _ods_ir.AttrBuilder.get('AnyAttr')(memory_space, context=_ods_context))
    if memcpy_op is not None: attributes["memcpy_op"] = (memcpy_op if (
        isinstance(memcpy_op, _ods_ir.Attribute) or
        not _ods_ir.AttrBuilder.contains('StrAttr')) else
          _ods_ir.AttrBuilder.get('StrAttr')(memcpy_op, context=_ods_context))
    if alloc_op is not None: attributes["alloc_op"] = (alloc_op if (
        isinstance(alloc_op, _ods_ir.Attribute) or
        not _ods_ir.AttrBuilder.contains('StrAttr')) else
          _ods_ir.AttrBuilder.get('StrAttr')(alloc_op, context=_ods_context))
    if bool(bufferize_destination_only): attributes["bufferize_destination_only"] = _ods_ir.UnitAttr.get(
      _ods_get_default_loc_context(loc))
    if bool(emit_dealloc): attributes["emit_dealloc"] = _ods_ir.UnitAttr.get(
      _ods_get_default_loc_context(loc))
    _ods_successors = None
    super().__init__(self.OPERATION_NAME, self._ODS_REGIONS, self._ODS_OPERAND_SEGMENTS, self._ODS_RESULT_SEGMENTS, attributes=attributes, results=results, operands=operands, successors=_ods_successors, regions=regions, loc=loc, ip=ip)

  @builtins.property
  def target(self) -> _ods_ir.Value:
    return self.operation.operands[0]

  @builtins.property
  def memory_space(self) -> _Optional[_ods_ir.Attribute]:
    if "memory_space" not in self.operation.attributes:
      return None
    return self.operation.attributes["memory_space"]

  @memory_space.setter
  def memory_space(self, value: _Optional[_ods_ir.Attribute]):
    if value is not None:
      self.operation.attributes["memory_space"] = value
    elif "memory_space" in self.operation.attributes:
      del self.operation.attributes["memory_space"]

  @memory_space.deleter
  def memory_space(self):
    del self.operation.attributes["memory_space"]

  @builtins.property
  def memcpy_op(self) -> _ods_ir.StringAttr:
    return self.operation.attributes["memcpy_op"]

  @memcpy_op.setter
  def memcpy_op(self, value: _ods_ir.StringAttr):
    if value is None:
      raise ValueError("'None' not allowed as value for mandatory attributes")
    self.operation.attributes["memcpy_op"] = value

  @builtins.property
  def alloc_op(self) -> _ods_ir.StringAttr:
    return self.operation.attributes["alloc_op"]

  @alloc_op.setter
  def alloc_op(self, value: _ods_ir.StringAttr):
    if value is None:
      raise ValueError("'None' not allowed as value for mandatory attributes")
    self.operation.attributes["alloc_op"] = value

  @builtins.property
  def bufferize_destination_only(self) -> bool:
    return "bufferize_destination_only" in self.operation.attributes

  @bufferize_destination_only.setter
  def bufferize_destination_only(self, value):
    if bool(value):
      self.operation.attributes["bufferize_destination_only"] = _ods_ir.UnitAttr.get()
    elif "bufferize_destination_only" in self.operation.attributes:
      del self.operation.attributes["bufferize_destination_only"]

  @bufferize_destination_only.deleter
  def bufferize_destination_only(self):
    del self.operation.attributes["bufferize_destination_only"]

  @builtins.property
  def emit_dealloc(self) -> bool:
    return "emit_dealloc" in self.operation.attributes

  @emit_dealloc.setter
  def emit_dealloc(self, value):
    if bool(value):
      self.operation.attributes["emit_dealloc"] = _ods_ir.UnitAttr.get()
    elif "emit_dealloc" in self.operation.attributes:
      del self.operation.attributes["emit_dealloc"]

  @emit_dealloc.deleter
  def emit_dealloc(self):
    del self.operation.attributes["emit_dealloc"]

  @builtins.property
  def allocated_buffer(self) -> _ods_ir.OpResult:
    return self.operation.results[0]

  @builtins.property
  def new_ops(self) -> _ods_ir.OpResult:
    return self.operation.results[1]

@_ods_cext.register_op_adaptor(BufferizeToAllocationOp)
class BufferizeToAllocationOpAdaptor(_ods_ir.OpAdaptor):
  OPERATION_NAME = "transform.structured.bufferize_to_allocation"

  @builtins.property
  def target(self) -> _ods_ir.Value:
    return self.operands[0]

  @builtins.property
  def memory_space(self) -> _Optional[_ods_ir.Attribute]:
    if "memory_space" not in self.attributes:
      return None
    return self.attributes["memory_space"]

  @builtins.property
  def memcpy_op(self) -> _ods_ir.StringAttr:
    return self.attributes["memcpy_op"]

  @builtins.property
  def alloc_op(self) -> _ods_ir.StringAttr:
    return self.attributes["alloc_op"]

  @builtins.property
  def bufferize_destination_only(self) -> bool:
    return "bufferize_destination_only" in self.attributes

  @builtins.property
  def emit_dealloc(self) -> bool:
    return "emit_dealloc" in self.attributes

def structured_bufferize_to_allocation(target: _ods_ir.Value, *, memory_space: _Optional[_Union[_Any, _ods_ir.Attribute]] = None, memcpy_op: _Optional[_Union[str, _ods_ir.StringAttr]] = None, alloc_op: _Optional[_Union[str, _ods_ir.StringAttr]] = None, bufferize_destination_only: _Optional[bool] = None, emit_dealloc: _Optional[bool] = None, results: _Optional[_Sequence[_ods_ir.Type]] = None, loc: _Optional[_ods_ir.Location] = None, ip: _Optional[_ods_ir.InsertionPoint] = None) -> _ods_ir.OpResultList:
  return BufferizeToAllocationOp(target=target, memory_space=memory_space, memcpy_op=memcpy_op, alloc_op=alloc_op, bufferize_destination_only=bufferize_destination_only, emit_dealloc=emit_dealloc, results=results, loc=loc, ip=ip).results

@_ods_cext.register_operation(_Dialect)
class ContinuousTileSizesOp(_ods_ir.OpView):
  r"""
  This transform emits the IR computing the list of (1) exponentially
  diminishing tile sizes that are powers of 2; and (2) the corresponding
  chunk-sizes the target op should be split into along the given dimension.
  
  For example, for `target_size` 9, and `dimension` 0 for the following
  linalg op as target
  
  ```
    %0 = linalg.matmul  ins(%arg0, %arg1: tensor<25x34xf32>, tensor<34x25xf32>)
                    outs(%arg2: tensor<25x25xf32>)
  ```
  
  the first result `tile_sizes` will be a list of diminishing tile sizes
  9, 4, 2, 1; and the second result will be a list of chunk sizes
  18, 4, 2, 1 that the corresponding dimension should be split into.
  
  After the target op has been split along the given dimension (for example
  using multiway split), each chunk can be tiled with the corresponding tile
  size in the `tile_sizes` list generated as a result of this op.
  
  Specifying the output type as !transform.param<i64> will cause `tile_sizes`
  and `chunk_sizes` to be computed statically and not dynamically.
  """

  OPERATION_NAME = "transform.structured.continuous_tile_sizes"

  _ODS_REGIONS = (0, True)

  def __init__(self, tile_sizes: _ods_ir.Type, chunk_sizes: _ods_ir.Type, target: _ods_ir.Value, dimension: _Union[int, _ods_ir.IntegerAttr], target_size: _Union[int, _ods_ir.IntegerAttr], *, loc: _Optional[_ods_ir.Location] = None, ip: _Optional[_ods_ir.InsertionPoint] = None):
    operands = []
    attributes = {}
    regions = None
    operands.append(target)
    _ods_context = _ods_get_default_loc_context(loc)
    attributes["dimension"] = (dimension if (
    isinstance(dimension, _ods_ir.Attribute) or
    not _ods_ir.AttrBuilder.contains('I64Attr')) else
      _ods_ir.AttrBuilder.get('I64Attr')(dimension, context=_ods_context))
    attributes["target_size"] = (target_size if (
    isinstance(target_size, _ods_ir.Attribute) or
    not _ods_ir.AttrBuilder.contains('I64Attr')) else
      _ods_ir.AttrBuilder.get('I64Attr')(target_size, context=_ods_context))
    results = []
    results.append(tile_sizes)
    results.append(chunk_sizes)
    _ods_successors = None
    super().__init__(self.OPERATION_NAME, self._ODS_REGIONS, self._ODS_OPERAND_SEGMENTS, self._ODS_RESULT_SEGMENTS, attributes=attributes, results=results, operands=operands, successors=_ods_successors, regions=regions, loc=loc, ip=ip)

  @builtins.property
  def target(self) -> _ods_ir.Value:
    return self.operation.operands[0]

  @builtins.property
  def dimension(self) -> _ods_ir.IntegerAttr:
    return self.operation.attributes["dimension"]

  @dimension.setter
  def dimension(self, value: _ods_ir.IntegerAttr):
    if value is None:
      raise ValueError("'None' not allowed as value for mandatory attributes")
    self.operation.attributes["dimension"] = value

  @builtins.property
  def target_size(self) -> _ods_ir.IntegerAttr:
    return self.operation.attributes["target_size"]

  @target_size.setter
  def target_size(self, value: _ods_ir.IntegerAttr):
    if value is None:
      raise ValueError("'None' not allowed as value for mandatory attributes")
    self.operation.attributes["target_size"] = value

  @builtins.property
  def tile_sizes(self) -> _ods_ir.OpResult:
    return self.operation.results[0]

  @builtins.property
  def chunk_sizes(self) -> _ods_ir.OpResult:
    return self.operation.results[1]

@_ods_cext.register_op_adaptor(ContinuousTileSizesOp)
class ContinuousTileSizesOpAdaptor(_ods_ir.OpAdaptor):
  OPERATION_NAME = "transform.structured.continuous_tile_sizes"

  @builtins.property
  def target(self) -> _ods_ir.Value:
    return self.operands[0]

  @builtins.property
  def dimension(self) -> _ods_ir.IntegerAttr:
    return self.attributes["dimension"]

  @builtins.property
  def target_size(self) -> _ods_ir.IntegerAttr:
    return self.attributes["target_size"]

def structured_continuous_tile_sizes(tile_sizes: _ods_ir.Type, chunk_sizes: _ods_ir.Type, target: _ods_ir.Value, dimension: _Union[int, _ods_ir.IntegerAttr], target_size: _Union[int, _ods_ir.IntegerAttr], *, loc: _Optional[_ods_ir.Location] = None, ip: _Optional[_ods_ir.InsertionPoint] = None) -> _ods_ir.OpResultList:
  return ContinuousTileSizesOp(tile_sizes=tile_sizes, chunk_sizes=chunk_sizes, target=target, dimension=dimension, target_size=target_size, loc=loc, ip=ip).results

@_ods_cext.register_operation(_Dialect)
class ConvertConv2DToImg2ColOp(_ods_ir.OpView):
  r"""
  Convert linalg.conv_2d_xxx into linalg.generic (for img2col packing)
  and linalg.matmul.
  
  A convolution operation can be written as a matrix-matrix multiplication by
  unfolding the cross-correlation between input and filter and explicitly copy
  overlapped sliding window inputs.
  
  Consider 2D input X with single channel input and output and 2x2 filter W:
  ```
  [x(0, 0)  , x(0, 1)  , ...,   x(0, n)  ]
  [x(1, 0)  , x(1, 1)  , ...,   x(1, n)  ]
  [.        ,  .       ,.   ,      .     ]            [w(0, 0), w(0, 1)]
  [.        ,  .       , .  ,      .     ]    (conv)  [w(1, 0), w(1, 1)]
  [.        ,  .       ,   .,      .     ]
  [x(n-1, 0), x(n-1, 1), ..., x(n-1, n-1)]
  ```
  
  The packed input data (img2col) is a matrix with |rows| = output spatial
  size, |columns| = filter spatial size. To compute the output Y(i, j) we need
  to calculate the dot product between filter window at input X(x, y)) and the
  filter which will look like the following where r.h.s is the img2col matrix
  and l.h.s is the flattned filter:
  ```
  [x(0,0), x(0,1), x(1,0), x(1,1)]
  [x(0,1), x(1,1), x(0,2), x(1,2)] (matmul) [w(0,0), w(0,1), w(1,0), w(1,1)]
  [x(0,1), x(1,1), x(0,2), x(1,2)]
  [   .  ,    .  ,    .  ,    .  ]
  ```
  
  In general for 2D case with (N, H, W, C) input and (Kh, Kw, C, D) filter
  and output (N, Ho, Wo, D) the convolution is the following matrix-matrix
  multiplication (Ho x Wo, Kh x Kw x C) * (Kh x Kw x C, D) for each input in
  the N input. For the case where N > 1 its a batched matrxi-matrix
  multplication.
  
  Returns two handles:
  - One on the operation that produces the img2col tensor.
  - One on the final operation of the sequence that replaces the original
    convolution.
  
  #### Return modes:
  
  Returns a definite failure if target is not isolated from above.
  Returns a silenceable failure if the pattern application failed.
  """

  OPERATION_NAME = "transform.structured.convert_conv2d_to_img2col"

  _ODS_REGIONS = (0, True)

  def __init__(self, img2col_tensor: _ods_ir.Type, transformed: _ods_ir.Type, target: _ods_ir.Value, *, loc: _Optional[_ods_ir.Location] = None, ip: _Optional[_ods_ir.InsertionPoint] = None):
    operands = []
    attributes = {}
    regions = None
    operands.append(target)
    _ods_context = _ods_get_default_loc_context(loc)
    results = []
    results.append(img2col_tensor)
    results.append(transformed)
    _ods_successors = None
    super().__init__(self.OPERATION_NAME, self._ODS_REGIONS, self._ODS_OPERAND_SEGMENTS, self._ODS_RESULT_SEGMENTS, attributes=attributes, results=results, operands=operands, successors=_ods_successors, regions=regions, loc=loc, ip=ip)

  @builtins.property
  def target(self) -> _ods_ir.Value:
    return self.operation.operands[0]

  @builtins.property
  def img2col_tensor(self) -> _ods_ir.OpResult:
    return self.operation.results[0]

  @builtins.property
  def transformed(self) -> _ods_ir.OpResult:
    return self.operation.results[1]

@_ods_cext.register_op_adaptor(ConvertConv2DToImg2ColOp)
class ConvertConv2DToImg2ColOpAdaptor(_ods_ir.OpAdaptor):
  OPERATION_NAME = "transform.structured.convert_conv2d_to_img2col"

  @builtins.property
  def target(self) -> _ods_ir.Value:
    return self.operands[0]

def structured_convert_conv2d_to_img2col(img2col_tensor: _ods_ir.Type, transformed: _ods_ir.Type, target: _ods_ir.Value, *, loc: _Optional[_ods_ir.Location] = None, ip: _Optional[_ods_ir.InsertionPoint] = None) -> _ods_ir.OpResultList:
  return ConvertConv2DToImg2ColOp(img2col_tensor=img2col_tensor, transformed=transformed, target=target, loc=loc, ip=ip).results

@_ods_cext.register_operation(_Dialect)
class ConvertToLoopsOp(_ods_ir.OpView):
  r"""
  For operations that implement the `TilingInterface`, and implement
  the `generateScalarImplementation` method, lowers the operation to
  loops. The return handle points to all generated loops.
  Fails if the payload ops cannot be lowered to loops.
  """

  OPERATION_NAME = "transform.structured.convert_to_loops"

  _ODS_REGIONS = (0, True)

  def __init__(self, result: _ods_ir.Type, target: _ods_ir.Value, *, loc: _Optional[_ods_ir.Location] = None, ip: _Optional[_ods_ir.InsertionPoint] = None):
    operands = []
    attributes = {}
    regions = None
    operands.append(target)
    _ods_context = _ods_get_default_loc_context(loc)
    results = []
    results.append(result)
    _ods_successors = None
    super().__init__(self.OPERATION_NAME, self._ODS_REGIONS, self._ODS_OPERAND_SEGMENTS, self._ODS_RESULT_SEGMENTS, attributes=attributes, results=results, operands=operands, successors=_ods_successors, regions=regions, loc=loc, ip=ip)

  @builtins.property
  def target(self) -> _ods_ir.Value:
    return self.operation.operands[0]

  @builtins.property
  def result(self) -> _ods_ir.OpResult:
    return self.operation.results[0]

@_ods_cext.register_op_adaptor(ConvertToLoopsOp)
class ConvertToLoopsOpAdaptor(_ods_ir.OpAdaptor):
  OPERATION_NAME = "transform.structured.convert_to_loops"

  @builtins.property
  def target(self) -> _ods_ir.Value:
    return self.operands[0]

def structured_convert_to_loops(result: _ods_ir.Type, target: _ods_ir.Value, *, loc: _Optional[_ods_ir.Location] = None, ip: _Optional[_ods_ir.InsertionPoint] = None) -> _ods_ir.OpResult:
  return ConvertToLoopsOp(result=result, target=target, loc=loc, ip=ip).result

@_ods_cext.register_operation(_Dialect)
class DecomposeInterfaceOp(_ods_ir.OpView):
  r"""
  Decomposes target operations into sequences of simpler ops.
  
  #### Return modes
  
  This operation ignores ops that do not implement the AggregatedOpInterface
  and drops them in the return. If any such op is encountered, the transform
  emits a silenceable failure.
  
  If all the operations referred to by the `target` handle decompose
  properly, the transform succeeds. Otherwise the transform produces a
  silenceable failure.
  The return handle points to a subset of successfully produced operations.
  For each target, the handle contains one value per its result. That is,
  the handle contains at most as many ops as the targets had results.
  The handle can be empty.
  """

  OPERATION_NAME = "transform.structured.decompose_interface"

  _ODS_REGIONS = (0, True)

  def __init__(self, transformed: _ods_ir.Type, target: _ods_ir.Value, *, loc: _Optional[_ods_ir.Location] = None, ip: _Optional[_ods_ir.InsertionPoint] = None):
    operands = []
    attributes = {}
    regions = None
    operands.append(target)
    _ods_context = _ods_get_default_loc_context(loc)
    results = []
    results.append(transformed)
    _ods_successors = None
    super().__init__(self.OPERATION_NAME, self._ODS_REGIONS, self._ODS_OPERAND_SEGMENTS, self._ODS_RESULT_SEGMENTS, attributes=attributes, results=results, operands=operands, successors=_ods_successors, regions=regions, loc=loc, ip=ip)

  @builtins.property
  def target(self) -> _ods_ir.Value:
    return self.operation.operands[0]

  @builtins.property
  def transformed(self) -> _ods_ir.OpResult:
    return self.operation.results[0]

@_ods_cext.register_op_adaptor(DecomposeInterfaceOp)
class DecomposeInterfaceOpAdaptor(_ods_ir.OpAdaptor):
  OPERATION_NAME = "transform.structured.decompose_interface"

  @builtins.property
  def target(self) -> _ods_ir.Value:
    return self.operands[0]

def structured_decompose_interface(transformed: _ods_ir.Type, target: _ods_ir.Value, *, loc: _Optional[_ods_ir.Location] = None, ip: _Optional[_ods_ir.InsertionPoint] = None) -> _ods_ir.OpResult:
  return DecomposeInterfaceOp(transformed=transformed, target=target, loc=loc, ip=ip).result

@_ods_cext.register_operation(_Dialect)
class DecomposeOp(_ods_ir.OpView):
  r"""
  Decomposes higher-dimensional convolution ops into lower-dimensional
  equivalents when possible. This operates on both named ops and equivalent
  `linalg.generic` ops that have convolution-like structure (as determined
  by `inferConvolutionDims`).
  
  The transformation always attempts to specialize the result back to a named
  op when possible.
  
  #### Return modes
  
  This operation ignores non-Linalg ops and drops them in the return.
  If all the operations referred to by the `target` handle decompose
  properly, the transform succeeds. Otherwise the transform produces a
  silenceable failure. The return handle points to only the subset of
  successfully produced computational operations, which can be empty.
  """

  OPERATION_NAME = "transform.structured.decompose"

  _ODS_REGIONS = (0, True)

  def __init__(self, transformed: _ods_ir.Type, target: _ods_ir.Value, *, loc: _Optional[_ods_ir.Location] = None, ip: _Optional[_ods_ir.InsertionPoint] = None):
    operands = []
    attributes = {}
    regions = None
    operands.append(target)
    _ods_context = _ods_get_default_loc_context(loc)
    results = []
    results.append(transformed)
    _ods_successors = None
    super().__init__(self.OPERATION_NAME, self._ODS_REGIONS, self._ODS_OPERAND_SEGMENTS, self._ODS_RESULT_SEGMENTS, attributes=attributes, results=results, operands=operands, successors=_ods_successors, regions=regions, loc=loc, ip=ip)

  @builtins.property
  def target(self) -> _ods_ir.Value:
    return self.operation.operands[0]

  @builtins.property
  def transformed(self) -> _ods_ir.OpResult:
    return self.operation.results[0]

@_ods_cext.register_op_adaptor(DecomposeOp)
class DecomposeOpAdaptor(_ods_ir.OpAdaptor):
  OPERATION_NAME = "transform.structured.decompose"

  @builtins.property
  def target(self) -> _ods_ir.Value:
    return self.operands[0]

def structured_decompose(transformed: _ods_ir.Type, target: _ods_ir.Value, *, loc: _Optional[_ods_ir.Location] = None, ip: _Optional[_ods_ir.InsertionPoint] = None) -> _ods_ir.OpResult:
  return DecomposeOp(transformed=transformed, target=target, loc=loc, ip=ip).result

@_ods_cext.register_operation(_Dialect)
class DecomposeWinogradOp(_ods_ir.OpView):
  r"""
  Decompose winograd operations. It will convert filter, input and output
  transform operations into a combination of scf, tensor, and linalg
  equivalent operations. Before applying this transform operations, users
  need to tile winograd transform operations into supported sizes.
  
  #### Return modes:
  
  This operation fails if `target` is unsupported. Otherwise, the operation
  succeeds and returns a handle of the sequence that replaces the original
  operations.
  """

  OPERATION_NAME = "transform.structured.decompose_winograd_op"

  _ODS_REGIONS = (0, True)

  def __init__(self, transformed: _ods_ir.Type, target: _ods_ir.Value, *, loc: _Optional[_ods_ir.Location] = None, ip: _Optional[_ods_ir.InsertionPoint] = None):
    operands = []
    attributes = {}
    regions = None
    operands.append(target)
    _ods_context = _ods_get_default_loc_context(loc)
    results = []
    results.append(transformed)
    _ods_successors = None
    super().__init__(self.OPERATION_NAME, self._ODS_REGIONS, self._ODS_OPERAND_SEGMENTS, self._ODS_RESULT_SEGMENTS, attributes=attributes, results=results, operands=operands, successors=_ods_successors, regions=regions, loc=loc, ip=ip)

  @builtins.property
  def target(self) -> _ods_ir.Value:
    return self.operation.operands[0]

  @builtins.property
  def transformed(self) -> _ods_ir.OpResult:
    return self.operation.results[0]

@_ods_cext.register_op_adaptor(DecomposeWinogradOp)
class DecomposeWinogradOpAdaptor(_ods_ir.OpAdaptor):
  OPERATION_NAME = "transform.structured.decompose_winograd_op"

  @builtins.property
  def target(self) -> _ods_ir.Value:
    return self.operands[0]

def structured_decompose_winograd_op(transformed: _ods_ir.Type, target: _ods_ir.Value, *, loc: _Optional[_ods_ir.Location] = None, ip: _Optional[_ods_ir.InsertionPoint] = None) -> _ods_ir.OpResult:
  return DecomposeWinogradOp(transformed=transformed, target=target, loc=loc, ip=ip).result

@_ods_cext.register_operation(_Dialect)
class EliminateLinalgOpAnchoredEmptyTensorsOp(_ods_ir.OpView):
  r"""
  Try to eliminate all `tensor.empty` op uses that are anchored on a LinalgOp
  within the targeted op.
  
  This op is similar to `bufferization.eliminate_empty_tensors`, but specific
  to LinalgOps.
  
  `tensor.empty` ops cannot be bufferized. They can either be converted to
  `bufferization.alloc_tensor` or replaced with another tensor (via this
  transform). `tensor.empty` does not specify the contents of the returned
  tensor so their results can be replaced with arbitrary tensor values as long
  as the dimensions match.
  
  This transform looks for `tensor.empty` ops where the SSA use-def chain of
  the result ends in a supported LinalgOp (always following the aliasing
  OpOperand/OpResult chain). The following LinalgOps are supported:
  - Only parallel iterator types.
  - The use-def chain ends in an input operand of the LinalgOp.
  - The LinalgOp has an unused output operand with the same shape and
    indexing map.
  
  Example:
  
  ```
  %0 = tensor.empty()
  %1 = linalg.matmul ins(...) outs(%0)
  %2 = linalg.generic ins(%1) outs(%dest) {
    ^bb0(%in: f32, %out: f32):
    // out not used
  }
  ```
  
  Is rewritten with:
  ```
  %0 = tensor.empty()
  %1 = linalg.matmul ins(...) outs(%dest)
  %2 = linalg.generic ins(%0) outs(%1) {
    ^bb0(%in: f32, %out: f32):
    // Use %out instead of %in
  }
  ```
  
  After this transformation, the "ins" operand has no uses inside the body of
  the LinalgOp and can be folded away with existing cleanup patterns.
  Afterwards, the tensor::EmptyOp can also fold away, so that the example can
  bufferize without an allocation (in the absence of other conflicts).
  
  #### Return modes
  
  This transform reads the target handle and modifies the payload. It does
  not produce any handle.
  """

  OPERATION_NAME = "transform.structured.eliminate_empty_tensors"

  _ODS_REGIONS = (0, True)

  def __init__(self, target: _ods_ir.Value, *, loc: _Optional[_ods_ir.Location] = None, ip: _Optional[_ods_ir.InsertionPoint] = None):
    operands = []
    attributes = {}
    regions = None
    operands.append(target)
    _ods_context = _ods_get_default_loc_context(loc)
    results = []
    _ods_successors = None
    super().__init__(self.OPERATION_NAME, self._ODS_REGIONS, self._ODS_OPERAND_SEGMENTS, self._ODS_RESULT_SEGMENTS, attributes=attributes, results=results, operands=operands, successors=_ods_successors, regions=regions, loc=loc, ip=ip)

  @builtins.property
  def target(self) -> _ods_ir.Value:
    return self.operation.operands[0]

@_ods_cext.register_op_adaptor(EliminateLinalgOpAnchoredEmptyTensorsOp)
class EliminateLinalgOpAnchoredEmptyTensorsOpAdaptor(_ods_ir.OpAdaptor):
  OPERATION_NAME = "transform.structured.eliminate_empty_tensors"

  @builtins.property
  def target(self) -> _ods_ir.Value:
    return self.operands[0]

def structured_eliminate_empty_tensors(target: _ods_ir.Value, *, loc: _Optional[_ods_ir.Location] = None, ip: _Optional[_ods_ir.InsertionPoint] = None) -> EliminateLinalgOpAnchoredEmptyTensorsOp:
  return EliminateLinalgOpAnchoredEmptyTensorsOp(target=target, loc=loc, ip=ip)

@_ods_cext.register_operation(_Dialect)
class FlattenElementwiseLinalgOp(_ods_ir.OpView):
  r"""
  Flattens the iteration space and (applicable) operands of elementwise
  linalg ops to a single dimension.
  
  Returns one handle:
  - Flattened linalg operation.
  
  #### Return modes:
  
  Returns a definite failure if target is not isolated from above.
  Returns a silenceable failure if the pattern application failed.
  """

  OPERATION_NAME = "transform.structured.flatten_elementwise"

  _ODS_REGIONS = (0, True)

  def __init__(self, transformed: _ods_ir.Type, target: _ods_ir.Value, *, loc: _Optional[_ods_ir.Location] = None, ip: _Optional[_ods_ir.InsertionPoint] = None):
    operands = []
    attributes = {}
    regions = None
    operands.append(target)
    _ods_context = _ods_get_default_loc_context(loc)
    results = []
    results.append(transformed)
    _ods_successors = None
    super().__init__(self.OPERATION_NAME, self._ODS_REGIONS, self._ODS_OPERAND_SEGMENTS, self._ODS_RESULT_SEGMENTS, attributes=attributes, results=results, operands=operands, successors=_ods_successors, regions=regions, loc=loc, ip=ip)

  @builtins.property
  def target(self) -> _ods_ir.Value:
    return self.operation.operands[0]

  @builtins.property
  def transformed(self) -> _ods_ir.OpResult:
    return self.operation.results[0]

@_ods_cext.register_op_adaptor(FlattenElementwiseLinalgOp)
class FlattenElementwiseLinalgOpAdaptor(_ods_ir.OpAdaptor):
  OPERATION_NAME = "transform.structured.flatten_elementwise"

  @builtins.property
  def target(self) -> _ods_ir.Value:
    return self.operands[0]

def structured_flatten_elementwise(transformed: _ods_ir.Type, target: _ods_ir.Value, *, loc: _Optional[_ods_ir.Location] = None, ip: _Optional[_ods_ir.InsertionPoint] = None) -> _ods_ir.OpResult:
  return FlattenElementwiseLinalgOp(transformed=transformed, target=target, loc=loc, ip=ip).result

@_ods_cext.register_operation(_Dialect)
class FuseIntoContainingOp(_ods_ir.OpView):
  r"""
  Fuses the `producer_op` into the `containing_op`.
  Returns a handle to the fused ops and the `new_containing_op`.
  
  The producer is typically a slice of a tileable op (i.e., implements
  TilingInterface). In that case, this transform computes the accessed
  producer slice inside of the containing op ("tile and fuse") and if required,
  creates a new containing op with outputs from the fused producer. Otherwise,
  the entire producer is cloned inside the containing op ("clone and fuse").
  
  The containing op handle must be associated with exactly one payload op. The
  producer op handle may be associated with multiple payload ops. This
  transform fuses producers one-by-one, always picking an unspecified producer
  that has at least one use inside the containing op among the
  producers. A producer can be listed multiple times in the handle.
  
  Note: If a producer has multiple uses inside the containing op, it is
  currently tiled and/or cloned multiple times into the containing op.
  TODO: Reuse already fused OpResults instead of tiling/cloning a second time
  when possible. Fuse producers according to a topological sorting to achieve
  the largest amount of reuse.
  
  #### Return modes
  
  If at least one producer could not be fused, this operation produces a
  silenceable failure.  This is the case when tiling fails or when no
  producer op could be found among the remaining producers that has at least
  one use within the containing op. I.e., "producers" that are not consumed
  within the containing op are rejected by this operation.
  
  This operation consumes the producer handle.
  This operation only reads the containing op handle.
  """

  OPERATION_NAME = "transform.structured.fuse_into_containing_op"

  _ODS_REGIONS = (0, True)

  def __init__(self, fused_op: _ods_ir.Type, new_containing_op: _ods_ir.Type, producer_op: _ods_ir.Value, containing_op: _ods_ir.Value, *, loc: _Optional[_ods_ir.Location] = None, ip: _Optional[_ods_ir.InsertionPoint] = None):
    operands = []
    attributes = {}
    regions = None
    operands.append(producer_op)
    operands.append(containing_op)
    _ods_context = _ods_get_default_loc_context(loc)
    results = []
    results.append(fused_op)
    results.append(new_containing_op)
    _ods_successors = None
    super().__init__(self.OPERATION_NAME, self._ODS_REGIONS, self._ODS_OPERAND_SEGMENTS, self._ODS_RESULT_SEGMENTS, attributes=attributes, results=results, operands=operands, successors=_ods_successors, regions=regions, loc=loc, ip=ip)

  @builtins.property
  def producer_op(self) -> _ods_ir.Value:
    return self.operation.operands[0]

  @builtins.property
  def containing_op(self) -> _ods_ir.Value:
    return self.operation.operands[1]

  @builtins.property
  def fused_op(self) -> _ods_ir.OpResult:
    return self.operation.results[0]

  @builtins.property
  def new_containing_op(self) -> _ods_ir.OpResult:
    return self.operation.results[1]

@_ods_cext.register_op_adaptor(FuseIntoContainingOp)
class FuseIntoContainingOpAdaptor(_ods_ir.OpAdaptor):
  OPERATION_NAME = "transform.structured.fuse_into_containing_op"

  @builtins.property
  def producer_op(self) -> _ods_ir.Value:
    return self.operands[0]

  @builtins.property
  def containing_op(self) -> _ods_ir.Value:
    return self.operands[1]

def structured_fuse_into_containing_op(fused_op: _ods_ir.Type, new_containing_op: _ods_ir.Type, producer_op: _ods_ir.Value, containing_op: _ods_ir.Value, *, loc: _Optional[_ods_ir.Location] = None, ip: _Optional[_ods_ir.InsertionPoint] = None) -> _ods_ir.OpResultList:
  return FuseIntoContainingOp(fused_op=fused_op, new_containing_op=new_containing_op, producer_op=producer_op, containing_op=containing_op, loc=loc, ip=ip).results

@_ods_cext.register_operation(_Dialect)
class FuseOp(_ods_ir.OpView):
  r"""
  Tiles the operations pointed to by the target handle and fuses their
  producers greedily using the options provided as attributes. Tile sizes
  and loop interchange permutation can be provided as either static
  attributes or dynamic values (transform parameters or payload handles).
  
  Additionally, tile sizes can also be provided as a single handle containing
  variadic number of values. In that case, the number of loops generated is
  determined at runtime from the number of values in the packed handle.
  For each target, created loops are appended to the single return handle in
  the same order as the target operations.
  
  If `apply_cleanup` is true then slice canonicalization is applied between
  fusion steps. If `use_forall` is true then tiling method generates a
  `scf.forall` loop instead of `scf.for` loops.
  """

  OPERATION_NAME = "transform.structured.fuse"

  _ODS_OPERAND_SEGMENTS = [1,-1,-1,0,]

  _ODS_REGIONS = (0, True)

  def __init__(self, transformed: _ods_ir.Type, loops: _Sequence[_ods_ir.Type], target: _ods_ir.Value, tile_sizes: _Sequence[_ods_ir.Value], tile_interchange: _Sequence[_ods_ir.Value], *, packed_tile_sizes: _Optional[_ods_ir.Value] = None, static_tile_sizes: _Optional[_Union[_Sequence[int], _ods_ir.DenseI64ArrayAttr]] = None, static_tile_interchange: _Optional[_Union[_Sequence[int], _ods_ir.DenseI64ArrayAttr]] = None, apply_cleanup: _Optional[bool] = None, use_forall: _Optional[bool] = None, loc: _Optional[_ods_ir.Location] = None, ip: _Optional[_ods_ir.InsertionPoint] = None):
    operands = []
    attributes = {}
    regions = None
    operands.append(target)
    operands.append(_get_op_results_or_values(tile_sizes))
    operands.append(_get_op_results_or_values(tile_interchange))
    operands.append(packed_tile_sizes)
    _ods_context = _ods_get_default_loc_context(loc)
    if static_tile_sizes is not None: attributes["static_tile_sizes"] = (static_tile_sizes if (
        isinstance(static_tile_sizes, _ods_ir.Attribute) or
        not _ods_ir.AttrBuilder.contains('DenseI64ArrayAttr')) else
          _ods_ir.AttrBuilder.get('DenseI64ArrayAttr')(static_tile_sizes, context=_ods_context))
    if static_tile_interchange is not None: attributes["static_tile_interchange"] = (static_tile_interchange if (
        isinstance(static_tile_interchange, _ods_ir.Attribute) or
        not _ods_ir.AttrBuilder.contains('DenseI64ArrayAttr')) else
          _ods_ir.AttrBuilder.get('DenseI64ArrayAttr')(static_tile_interchange, context=_ods_context))
    if bool(apply_cleanup): attributes["apply_cleanup"] = _ods_ir.UnitAttr.get(
      _ods_get_default_loc_context(loc))
    if bool(use_forall): attributes["use_forall"] = _ods_ir.UnitAttr.get(
      _ods_get_default_loc_context(loc))
    results = []
    results.append(transformed)
    results.extend(loops)
    _ods_successors = None
    super().__init__(self.OPERATION_NAME, self._ODS_REGIONS, self._ODS_OPERAND_SEGMENTS, self._ODS_RESULT_SEGMENTS, attributes=attributes, results=results, operands=operands, successors=_ods_successors, regions=regions, loc=loc, ip=ip)

  @builtins.property
  def target(self) -> _ods_ir.Value:
    operand_range = _ods_segmented_accessor(
         self.operation.operands,
         self.operation.attributes["operandSegmentSizes"], 0)
    return operand_range[0]

  @builtins.property
  def tile_sizes(self) -> _ods_ir.OpOperandList:
    operand_range = _ods_segmented_accessor(
         self.operation.operands,
         self.operation.attributes["operandSegmentSizes"], 1)
    return operand_range

  @builtins.property
  def tile_interchange(self) -> _ods_ir.OpOperandList:
    operand_range = _ods_segmented_accessor(
         self.operation.operands,
         self.operation.attributes["operandSegmentSizes"], 2)
    return operand_range

  @builtins.property
  def packed_tile_sizes(self) -> _Optional[_ods_ir.Value]:
    operand_range = _ods_segmented_accessor(
         self.operation.operands,
         self.operation.attributes["operandSegmentSizes"], 3)
    return operand_range[0] if len(operand_range) > 0 else None

  @builtins.property
  def static_tile_sizes(self) -> _Optional[_ods_ir.DenseI64ArrayAttr]:
    if "static_tile_sizes" not in self.operation.attributes:
      return None
    return self.operation.attributes["static_tile_sizes"]

  @static_tile_sizes.setter
  def static_tile_sizes(self, value: _Optional[_ods_ir.DenseI64ArrayAttr]):
    if value is not None:
      self.operation.attributes["static_tile_sizes"] = value
    elif "static_tile_sizes" in self.operation.attributes:
      del self.operation.attributes["static_tile_sizes"]

  @static_tile_sizes.deleter
  def static_tile_sizes(self):
    del self.operation.attributes["static_tile_sizes"]

  @builtins.property
  def static_tile_interchange(self) -> _Optional[_ods_ir.DenseI64ArrayAttr]:
    if "static_tile_interchange" not in self.operation.attributes:
      return None
    return self.operation.attributes["static_tile_interchange"]

  @static_tile_interchange.setter
  def static_tile_interchange(self, value: _Optional[_ods_ir.DenseI64ArrayAttr]):
    if value is not None:
      self.operation.attributes["static_tile_interchange"] = value
    elif "static_tile_interchange" in self.operation.attributes:
      del self.operation.attributes["static_tile_interchange"]

  @static_tile_interchange.deleter
  def static_tile_interchange(self):
    del self.operation.attributes["static_tile_interchange"]

  @builtins.property
  def apply_cleanup(self) -> bool:
    return "apply_cleanup" in self.operation.attributes

  @apply_cleanup.setter
  def apply_cleanup(self, value):
    if bool(value):
      self.operation.attributes["apply_cleanup"] = _ods_ir.UnitAttr.get()
    elif "apply_cleanup" in self.operation.attributes:
      del self.operation.attributes["apply_cleanup"]

  @apply_cleanup.deleter
  def apply_cleanup(self):
    del self.operation.attributes["apply_cleanup"]

  @builtins.property
  def use_forall(self) -> bool:
    return "use_forall" in self.operation.attributes

  @use_forall.setter
  def use_forall(self, value):
    if bool(value):
      self.operation.attributes["use_forall"] = _ods_ir.UnitAttr.get()
    elif "use_forall" in self.operation.attributes:
      del self.operation.attributes["use_forall"]

  @use_forall.deleter
  def use_forall(self):
    del self.operation.attributes["use_forall"]

  @builtins.property
  def transformed(self) -> _ods_ir.OpResult:
    return self.operation.results[0]

  @builtins.property
  def loops(self) -> _ods_ir.OpResultList:
    _ods_variadic_group_length = len(self.operation.results) - 2 + 1
    return self.operation.results[1:1 + _ods_variadic_group_length]

@_ods_cext.register_op_adaptor(FuseOp)
class FuseOpAdaptor(_ods_ir.OpAdaptor):
  OPERATION_NAME = "transform.structured.fuse"

  @builtins.property
  def target(self) -> _ods_ir.Value:
    operand_range = _ods_segmented_accessor(
         self.operands,
         self.attributes["operandSegmentSizes"], 0)
    return operand_range[0]

  @builtins.property
  def tile_sizes(self) -> _ods_ir.OpOperandList:
    operand_range = _ods_segmented_accessor(
         self.operands,
         self.attributes["operandSegmentSizes"], 1)
    return operand_range

  @builtins.property
  def tile_interchange(self) -> _ods_ir.OpOperandList:
    operand_range = _ods_segmented_accessor(
         self.operands,
         self.attributes["operandSegmentSizes"], 2)
    return operand_range

  @builtins.property
  def packed_tile_sizes(self) -> _Optional[_ods_ir.Value]:
    operand_range = _ods_segmented_accessor(
         self.operands,
         self.attributes["operandSegmentSizes"], 3)
    return operand_range[0] if len(operand_range) > 0 else None

  @builtins.property
  def static_tile_sizes(self) -> _Optional[_ods_ir.DenseI64ArrayAttr]:
    if "static_tile_sizes" not in self.attributes:
      return None
    return self.attributes["static_tile_sizes"]

  @builtins.property
  def static_tile_interchange(self) -> _Optional[_ods_ir.DenseI64ArrayAttr]:
    if "static_tile_interchange" not in self.attributes:
      return None
    return self.attributes["static_tile_interchange"]

  @builtins.property
  def apply_cleanup(self) -> bool:
    return "apply_cleanup" in self.attributes

  @builtins.property
  def use_forall(self) -> bool:
    return "use_forall" in self.attributes

def structured_fuse(transformed: _ods_ir.Type, loops: _Sequence[_ods_ir.Type], target: _ods_ir.Value, tile_sizes: _Sequence[_ods_ir.Value], tile_interchange: _Sequence[_ods_ir.Value], *, packed_tile_sizes: _Optional[_ods_ir.Value] = None, static_tile_sizes: _Optional[_Union[_Sequence[int], _ods_ir.DenseI64ArrayAttr]] = None, static_tile_interchange: _Optional[_Union[_Sequence[int], _ods_ir.DenseI64ArrayAttr]] = None, apply_cleanup: _Optional[bool] = None, use_forall: _Optional[bool] = None, loc: _Optional[_ods_ir.Location] = None, ip: _Optional[_ods_ir.InsertionPoint] = None) -> _Union[_ods_ir.OpResult, _ods_ir.OpResultList, FuseOp]:
  op = FuseOp(transformed=transformed, loops=loops, target=target, tile_sizes=tile_sizes, tile_interchange=tile_interchange, packed_tile_sizes=packed_tile_sizes, static_tile_sizes=static_tile_sizes, static_tile_interchange=static_tile_interchange, apply_cleanup=apply_cleanup, use_forall=use_forall, loc=loc, ip=ip); results = op.results
  return results if len(results) > 1 else (results[0] if len(results) == 1 else op)

@_ods_cext.register_operation(_Dialect)
class GeneralizeOp(_ods_ir.OpView):
  r"""
  Transforms a named structured operation into the generic form with the
  explicit attached region.
  
  #### Return modes
  
  This operation ignores non-Linalg ops and drops them in the return.
  If all the operations referred to by the `target` handle generalize
  properly, the transform succeeds. Otherwise the transform produces a
  silenceable failure.  The return handle points to only the subset of
  successfully produced equivalent generic operations, which can be empty or
  contain the original ops if they were already in generic form.
  """

  OPERATION_NAME = "transform.structured.generalize"

  _ODS_REGIONS = (0, True)

  def __init__(self, transformed: _ods_ir.Type, target: _ods_ir.Value, *, loc: _Optional[_ods_ir.Location] = None, ip: _Optional[_ods_ir.InsertionPoint] = None):
    operands = []
    attributes = {}
    regions = None
    operands.append(target)
    _ods_context = _ods_get_default_loc_context(loc)
    results = []
    results.append(transformed)
    _ods_successors = None
    super().__init__(self.OPERATION_NAME, self._ODS_REGIONS, self._ODS_OPERAND_SEGMENTS, self._ODS_RESULT_SEGMENTS, attributes=attributes, results=results, operands=operands, successors=_ods_successors, regions=regions, loc=loc, ip=ip)

  @builtins.property
  def target(self) -> _ods_ir.Value:
    return self.operation.operands[0]

  @builtins.property
  def transformed(self) -> _ods_ir.OpResult:
    return self.operation.results[0]

@_ods_cext.register_op_adaptor(GeneralizeOp)
class GeneralizeOpAdaptor(_ods_ir.OpAdaptor):
  OPERATION_NAME = "transform.structured.generalize"

  @builtins.property
  def target(self) -> _ods_ir.Value:
    return self.operands[0]

def structured_generalize(transformed: _ods_ir.Type, target: _ods_ir.Value, *, loc: _Optional[_ods_ir.Location] = None, ip: _Optional[_ods_ir.InsertionPoint] = None) -> _ods_ir.OpResult:
  return GeneralizeOp(transformed=transformed, target=target, loc=loc, ip=ip).result

@_ods_cext.register_operation(_Dialect)
class HoistPadBuildPackingLoopNestOp(_ods_ir.OpView):
  r"""
  Helper transform used to hoist a tensor.pad target operation. This operation
  creates the packing loop nest required by the hoist_pad operation and makes
  that functionality available independently.
  
  TODO: In the future, we should consider rewriting as a linalg.pack after
  hoisting since this abstraction is now available.
  
  #### Return modes
  
  This operation ignores non-tensor.pad ops and drops them in the result.
  If any non-tensor.pad is passed, the transform emits a silenceable failure.
  
  The return handle points to only the subset of successfully created packing
  loop nests, which can be empty.
  """

  OPERATION_NAME = "transform.structured.hoist_pad.build_packing_loop_nest"

  _ODS_REGIONS = (0, True)

  def __init__(self, packing_loop: _ods_ir.Type, target: _ods_ir.Value, loop: _ods_ir.Value, *, transpose: _Optional[_Union[_Sequence[int], _ods_ir.DenseI64ArrayAttr]] = None, loc: _Optional[_ods_ir.Location] = None, ip: _Optional[_ods_ir.InsertionPoint] = None):
    operands = []
    attributes = {}
    regions = None
    operands.append(target)
    operands.append(loop)
    _ods_context = _ods_get_default_loc_context(loc)
    if transpose is not None: attributes["transpose"] = (transpose if (
        isinstance(transpose, _ods_ir.Attribute) or
        not _ods_ir.AttrBuilder.contains('DenseI64ArrayAttr')) else
          _ods_ir.AttrBuilder.get('DenseI64ArrayAttr')(transpose, context=_ods_context))
    results = []
    results.append(packing_loop)
    _ods_successors = None
    super().__init__(self.OPERATION_NAME, self._ODS_REGIONS, self._ODS_OPERAND_SEGMENTS, self._ODS_RESULT_SEGMENTS, attributes=attributes, results=results, operands=operands, successors=_ods_successors, regions=regions, loc=loc, ip=ip)

  @builtins.property
  def target(self) -> _ods_ir.Value:
    return self.operation.operands[0]

  @builtins.property
  def loop(self) -> _ods_ir.Value:
    return self.operation.operands[1]

  @builtins.property
  def transpose(self) -> _ods_ir.DenseI64ArrayAttr:
    return self.operation.attributes["transpose"]

  @transpose.setter
  def transpose(self, value: _ods_ir.DenseI64ArrayAttr):
    if value is None:
      raise ValueError("'None' not allowed as value for mandatory attributes")
    self.operation.attributes["transpose"] = value

  @builtins.property
  def packing_loop(self) -> _ods_ir.OpResult:
    return self.operation.results[0]

@_ods_cext.register_op_adaptor(HoistPadBuildPackingLoopNestOp)
class HoistPadBuildPackingLoopNestOpAdaptor(_ods_ir.OpAdaptor):
  OPERATION_NAME = "transform.structured.hoist_pad.build_packing_loop_nest"

  @builtins.property
  def target(self) -> _ods_ir.Value:
    return self.operands[0]

  @builtins.property
  def loop(self) -> _ods_ir.Value:
    return self.operands[1]

  @builtins.property
  def transpose(self) -> _ods_ir.DenseI64ArrayAttr:
    return self.attributes["transpose"]

def structured_hoist_pad_build_packing_loop_nest(packing_loop: _ods_ir.Type, target: _ods_ir.Value, loop: _ods_ir.Value, *, transpose: _Optional[_Union[_Sequence[int], _ods_ir.DenseI64ArrayAttr]] = None, loc: _Optional[_ods_ir.Location] = None, ip: _Optional[_ods_ir.InsertionPoint] = None) -> _ods_ir.OpResult:
  return HoistPadBuildPackingLoopNestOp(packing_loop=packing_loop, target=target, loop=loop, transpose=transpose, loc=loc, ip=ip).result

@_ods_cext.register_operation(_Dialect)
class HoistPadOp(_ods_ir.OpView):
  r"""
  Hoist the tensor.pad target operation by at most the given number of loops.
  Optionally apply the transpose attribute to the inner dimensions.
  
  TODO: In the future, we should consider rewriting as a linalg.pack after
  hoisting since this abstraction is now available.
  TODO: Maybe also return the linalg.generic transpose created at some point.
  
  #### Return modes
  
  This operation ignores non-tensor.pad ops and drops them in the result.
  If any non-tensor.pad is passed, the transform emits a silenceable failure.
  
  If all the operations referred to by the `target` handle padproperly, the
  transform succeeds. Otherwise the transform produces a silenceable failure.
  
  The return handle points to only the subset of successfully hoisted
  tensor.pad operations, which can be empty.
  """

  OPERATION_NAME = "transform.structured.hoist_pad"

  _ODS_REGIONS = (0, True)

  def __init__(self, transformed: _ods_ir.Type, target: _ods_ir.Value, num_loops: _Union[int, _ods_ir.IntegerAttr], *, transpose: _Optional[_Union[_Sequence[int], _ods_ir.DenseI64ArrayAttr]] = None, loc: _Optional[_ods_ir.Location] = None, ip: _Optional[_ods_ir.InsertionPoint] = None):
    operands = []
    attributes = {}
    regions = None
    operands.append(target)
    _ods_context = _ods_get_default_loc_context(loc)
    attributes["num_loops"] = (num_loops if (
    isinstance(num_loops, _ods_ir.Attribute) or
    not _ods_ir.AttrBuilder.contains('I64Attr')) else
      _ods_ir.AttrBuilder.get('I64Attr')(num_loops, context=_ods_context))
    if transpose is not None: attributes["transpose"] = (transpose if (
        isinstance(transpose, _ods_ir.Attribute) or
        not _ods_ir.AttrBuilder.contains('DenseI64ArrayAttr')) else
          _ods_ir.AttrBuilder.get('DenseI64ArrayAttr')(transpose, context=_ods_context))
    results = []
    results.append(transformed)
    _ods_successors = None
    super().__init__(self.OPERATION_NAME, self._ODS_REGIONS, self._ODS_OPERAND_SEGMENTS, self._ODS_RESULT_SEGMENTS, attributes=attributes, results=results, operands=operands, successors=_ods_successors, regions=regions, loc=loc, ip=ip)

  @builtins.property
  def target(self) -> _ods_ir.Value:
    return self.operation.operands[0]

  @builtins.property
  def num_loops(self) -> _ods_ir.IntegerAttr:
    return self.operation.attributes["num_loops"]

  @num_loops.setter
  def num_loops(self, value: _ods_ir.IntegerAttr):
    if value is None:
      raise ValueError("'None' not allowed as value for mandatory attributes")
    self.operation.attributes["num_loops"] = value

  @builtins.property
  def transpose(self) -> _ods_ir.DenseI64ArrayAttr:
    return self.operation.attributes["transpose"]

  @transpose.setter
  def transpose(self, value: _ods_ir.DenseI64ArrayAttr):
    if value is None:
      raise ValueError("'None' not allowed as value for mandatory attributes")
    self.operation.attributes["transpose"] = value

  @builtins.property
  def transformed(self) -> _ods_ir.OpResult:
    return self.operation.results[0]

@_ods_cext.register_op_adaptor(HoistPadOp)
class HoistPadOpAdaptor(_ods_ir.OpAdaptor):
  OPERATION_NAME = "transform.structured.hoist_pad"

  @builtins.property
  def target(self) -> _ods_ir.Value:
    return self.operands[0]

  @builtins.property
  def num_loops(self) -> _ods_ir.IntegerAttr:
    return self.attributes["num_loops"]

  @builtins.property
  def transpose(self) -> _ods_ir.DenseI64ArrayAttr:
    return self.attributes["transpose"]

def structured_hoist_pad(transformed: _ods_ir.Type, target: _ods_ir.Value, num_loops: _Union[int, _ods_ir.IntegerAttr], *, transpose: _Optional[_Union[_Sequence[int], _ods_ir.DenseI64ArrayAttr]] = None, loc: _Optional[_ods_ir.Location] = None, ip: _Optional[_ods_ir.InsertionPoint] = None) -> _ods_ir.OpResult:
  return HoistPadOp(transformed=transformed, target=target, num_loops=num_loops, transpose=transpose, loc=loc, ip=ip).result

@_ods_cext.register_operation(_Dialect)
class HoistRedundantVectorBroadcastsOp(_ods_ir.OpView):
  r"""
  Hoist vector.extract / vector.broadcasts pairs out of immediately
  enclosing scf::ForOp iteratively.
  
  #### Return modes:
  
  The operation always succeeds and returns a handle to the transformed
  function op.
  """

  OPERATION_NAME = "transform.structured.hoist_redundant_vector_broadcasts"

  _ODS_REGIONS = (0, True)

  def __init__(self, transformed: _ods_ir.Type, target: _ods_ir.Value, *, loc: _Optional[_ods_ir.Location] = None, ip: _Optional[_ods_ir.InsertionPoint] = None):
    operands = []
    attributes = {}
    regions = None
    operands.append(target)
    _ods_context = _ods_get_default_loc_context(loc)
    results = []
    results.append(transformed)
    _ods_successors = None
    super().__init__(self.OPERATION_NAME, self._ODS_REGIONS, self._ODS_OPERAND_SEGMENTS, self._ODS_RESULT_SEGMENTS, attributes=attributes, results=results, operands=operands, successors=_ods_successors, regions=regions, loc=loc, ip=ip)

  @builtins.property
  def target(self) -> _ods_ir.Value:
    return self.operation.operands[0]

  @builtins.property
  def transformed(self) -> _ods_ir.OpResult:
    return self.operation.results[0]

@_ods_cext.register_op_adaptor(HoistRedundantVectorBroadcastsOp)
class HoistRedundantVectorBroadcastsOpAdaptor(_ods_ir.OpAdaptor):
  OPERATION_NAME = "transform.structured.hoist_redundant_vector_broadcasts"

  @builtins.property
  def target(self) -> _ods_ir.Value:
    return self.operands[0]

def structured_hoist_redundant_vector_broadcasts(transformed: _ods_ir.Type, target: _ods_ir.Value, *, loc: _Optional[_ods_ir.Location] = None, ip: _Optional[_ods_ir.InsertionPoint] = None) -> _ods_ir.OpResult:
  return HoistRedundantVectorBroadcastsOp(transformed=transformed, target=target, loc=loc, ip=ip).result

@_ods_cext.register_operation(_Dialect)
class HoistRedundantVectorTransfersOp(_ods_ir.OpView):
  r"""
  Hoist vector.transfer_read / vector.transfer_write pairs out of immediately
  enclosing scf::ForOp iteratively, if the following conditions are true:
     1. The 2 ops access the same memref with the same indices.
     2. All operands are invariant under the enclosing scf::ForOp.
     3. No uses of the memref either dominate the transfer_read or are
     dominated by the transfer_write (i.e. no aliasing between the write and
     the read across the loop)
  
  WARNING: This hoisting does not model parallelism and is generally incorrect
  when used on distributed loops with memref semantics!
  TODO: obsolete and should be retired.
  
  #### Return modes:
  
  The operation always succeeds and returns a handle to the transformed
  function op.
  """

  OPERATION_NAME = "transform.structured.hoist_redundant_vector_transfers"

  _ODS_REGIONS = (0, True)

  def __init__(self, transformed: _ods_ir.Type, target: _ods_ir.Value, *, verify_non_zero_trip: _Optional[bool] = None, loc: _Optional[_ods_ir.Location] = None, ip: _Optional[_ods_ir.InsertionPoint] = None):
    operands = []
    attributes = {}
    regions = None
    operands.append(target)
    _ods_context = _ods_get_default_loc_context(loc)
    if bool(verify_non_zero_trip): attributes["verify_non_zero_trip"] = _ods_ir.UnitAttr.get(
      _ods_get_default_loc_context(loc))
    results = []
    results.append(transformed)
    _ods_successors = None
    super().__init__(self.OPERATION_NAME, self._ODS_REGIONS, self._ODS_OPERAND_SEGMENTS, self._ODS_RESULT_SEGMENTS, attributes=attributes, results=results, operands=operands, successors=_ods_successors, regions=regions, loc=loc, ip=ip)

  @builtins.property
  def target(self) -> _ods_ir.Value:
    return self.operation.operands[0]

  @builtins.property
  def verify_non_zero_trip(self) -> bool:
    return "verify_non_zero_trip" in self.operation.attributes

  @verify_non_zero_trip.setter
  def verify_non_zero_trip(self, value):
    if bool(value):
      self.operation.attributes["verify_non_zero_trip"] = _ods_ir.UnitAttr.get()
    elif "verify_non_zero_trip" in self.operation.attributes:
      del self.operation.attributes["verify_non_zero_trip"]

  @verify_non_zero_trip.deleter
  def verify_non_zero_trip(self):
    del self.operation.attributes["verify_non_zero_trip"]

  @builtins.property
  def transformed(self) -> _ods_ir.OpResult:
    return self.operation.results[0]

@_ods_cext.register_op_adaptor(HoistRedundantVectorTransfersOp)
class HoistRedundantVectorTransfersOpAdaptor(_ods_ir.OpAdaptor):
  OPERATION_NAME = "transform.structured.hoist_redundant_vector_transfers"

  @builtins.property
  def target(self) -> _ods_ir.Value:
    return self.operands[0]

  @builtins.property
  def verify_non_zero_trip(self) -> bool:
    return "verify_non_zero_trip" in self.attributes

def structured_hoist_redundant_vector_transfers(transformed: _ods_ir.Type, target: _ods_ir.Value, *, verify_non_zero_trip: _Optional[bool] = None, loc: _Optional[_ods_ir.Location] = None, ip: _Optional[_ods_ir.InsertionPoint] = None) -> _ods_ir.OpResult:
  return HoistRedundantVectorTransfersOp(transformed=transformed, target=target, verify_non_zero_trip=verify_non_zero_trip, loc=loc, ip=ip).result

@_ods_cext.register_operation(_Dialect)
class InsertSliceToCopyOp(_ods_ir.OpView):
  r"""
  Targeted rewrite of an tensor.insert_slice to linalg.copy.
  This is useful to materialize copies explicitly before bufferization and
  transform them, avoiding the need to rediscover them after bufferization.
  
  If the insert_slice source is already a linalg.copy, only return the source
  op (i.e. do not create an additional linalg.copy op).
  
  #### Return modes:
  
  The operation always succeeds and returns a handle to the relevant
  linalg.copy op.
  """

  OPERATION_NAME = "transform.structured.insert_slice_to_copy"

  _ODS_REGIONS = (0, True)

  def __init__(self, transformed: _ods_ir.Type, target: _ods_ir.Value, *, loc: _Optional[_ods_ir.Location] = None, ip: _Optional[_ods_ir.InsertionPoint] = None):
    operands = []
    attributes = {}
    regions = None
    operands.append(target)
    _ods_context = _ods_get_default_loc_context(loc)
    results = []
    results.append(transformed)
    _ods_successors = None
    super().__init__(self.OPERATION_NAME, self._ODS_REGIONS, self._ODS_OPERAND_SEGMENTS, self._ODS_RESULT_SEGMENTS, attributes=attributes, results=results, operands=operands, successors=_ods_successors, regions=regions, loc=loc, ip=ip)

  @builtins.property
  def target(self) -> _ods_ir.Value:
    return self.operation.operands[0]

  @builtins.property
  def transformed(self) -> _ods_ir.OpResult:
    return self.operation.results[0]

@_ods_cext.register_op_adaptor(InsertSliceToCopyOp)
class InsertSliceToCopyOpAdaptor(_ods_ir.OpAdaptor):
  OPERATION_NAME = "transform.structured.insert_slice_to_copy"

  @builtins.property
  def target(self) -> _ods_ir.Value:
    return self.operands[0]

def structured_insert_slice_to_copy(transformed: _ods_ir.Type, target: _ods_ir.Value, *, loc: _Optional[_ods_ir.Location] = None, ip: _Optional[_ods_ir.InsertionPoint] = None) -> _ods_ir.OpResult:
  return InsertSliceToCopyOp(transformed=transformed, target=target, loc=loc, ip=ip).result

@_ods_cext.register_operation(_Dialect)
class InterchangeOp(_ods_ir.OpView):
  r"""
  Interchanges the iterators of the operations pointed to by the target handle
  using the iterator interchange attribute.
  
  #### Return modes
  
  This operation ignores non-linalg::Generic ops and drops them in the return.
  This operation fails if the interchange attribute is invalid.
  If all the operations referred to by the `target` handle interchange
  properly, the transform succeeds.
  If any interchange fails, the transform produces a definite failure.
  The return handle points to only the subset of successfully produced
  interchanged operations, which can be empty.
  """

  OPERATION_NAME = "transform.structured.interchange"

  _ODS_REGIONS = (0, True)

  def __init__(self, transformed: _ods_ir.Type, target: _ods_ir.Value, *, iterator_interchange: _Optional[_Union[_Sequence[int], _ods_ir.DenseI64ArrayAttr]] = None, loc: _Optional[_ods_ir.Location] = None, ip: _Optional[_ods_ir.InsertionPoint] = None):
    operands = []
    attributes = {}
    regions = None
    operands.append(target)
    _ods_context = _ods_get_default_loc_context(loc)
    if iterator_interchange is not None: attributes["iterator_interchange"] = (iterator_interchange if (
        isinstance(iterator_interchange, _ods_ir.Attribute) or
        not _ods_ir.AttrBuilder.contains('DenseI64ArrayAttr')) else
          _ods_ir.AttrBuilder.get('DenseI64ArrayAttr')(iterator_interchange, context=_ods_context))
    results = []
    results.append(transformed)
    _ods_successors = None
    super().__init__(self.OPERATION_NAME, self._ODS_REGIONS, self._ODS_OPERAND_SEGMENTS, self._ODS_RESULT_SEGMENTS, attributes=attributes, results=results, operands=operands, successors=_ods_successors, regions=regions, loc=loc, ip=ip)

  @builtins.property
  def target(self) -> _ods_ir.Value:
    return self.operation.operands[0]

  @builtins.property
  def iterator_interchange(self) -> _Optional[_ods_ir.DenseI64ArrayAttr]:
    if "iterator_interchange" not in self.operation.attributes:
      return None
    return self.operation.attributes["iterator_interchange"]

  @iterator_interchange.setter
  def iterator_interchange(self, value: _Optional[_ods_ir.DenseI64ArrayAttr]):
    if value is not None:
      self.operation.attributes["iterator_interchange"] = value
    elif "iterator_interchange" in self.operation.attributes:
      del self.operation.attributes["iterator_interchange"]

  @iterator_interchange.deleter
  def iterator_interchange(self):
    del self.operation.attributes["iterator_interchange"]

  @builtins.property
  def transformed(self) -> _ods_ir.OpResult:
    return self.operation.results[0]

@_ods_cext.register_op_adaptor(InterchangeOp)
class InterchangeOpAdaptor(_ods_ir.OpAdaptor):
  OPERATION_NAME = "transform.structured.interchange"

  @builtins.property
  def target(self) -> _ods_ir.Value:
    return self.operands[0]

  @builtins.property
  def iterator_interchange(self) -> _Optional[_ods_ir.DenseI64ArrayAttr]:
    if "iterator_interchange" not in self.attributes:
      return None
    return self.attributes["iterator_interchange"]

def structured_interchange(transformed: _ods_ir.Type, target: _ods_ir.Value, *, iterator_interchange: _Optional[_Union[_Sequence[int], _ods_ir.DenseI64ArrayAttr]] = None, loc: _Optional[_ods_ir.Location] = None, ip: _Optional[_ods_ir.InsertionPoint] = None) -> _ods_ir.OpResult:
  return InterchangeOp(transformed=transformed, target=target, iterator_interchange=iterator_interchange, loc=loc, ip=ip).result

@_ods_cext.register_operation(_Dialect)
class LinalgCopyToMemrefOp(_ods_ir.OpView):
  r"""
  Targeted rewrite of a linalg.copy on memrefs to a memref.copy.
  This is useful when bufferizing copies to a linalg.copy, later applying some
  transformations, and then rewriting the copy into a memref.copy.
  If the element types of the source and destination differ, or if the source
  is a scalar, the transform produces a silenceable failure.
  """

  OPERATION_NAME = "transform.structured.linalg_copy_to_memref"

  _ODS_REGIONS = (0, True)

  def __init__(self, transformed: _ods_ir.Type, target: _ods_ir.Value, *, loc: _Optional[_ods_ir.Location] = None, ip: _Optional[_ods_ir.InsertionPoint] = None):
    operands = []
    attributes = {}
    regions = None
    operands.append(target)
    _ods_context = _ods_get_default_loc_context(loc)
    results = []
    results.append(transformed)
    _ods_successors = None
    super().__init__(self.OPERATION_NAME, self._ODS_REGIONS, self._ODS_OPERAND_SEGMENTS, self._ODS_RESULT_SEGMENTS, attributes=attributes, results=results, operands=operands, successors=_ods_successors, regions=regions, loc=loc, ip=ip)

  @builtins.property
  def target(self) -> _ods_ir.Value:
    return self.operation.operands[0]

  @builtins.property
  def transformed(self) -> _ods_ir.OpResult:
    return self.operation.results[0]

@_ods_cext.register_op_adaptor(LinalgCopyToMemrefOp)
class LinalgCopyToMemrefOpAdaptor(_ods_ir.OpAdaptor):
  OPERATION_NAME = "transform.structured.linalg_copy_to_memref"

  @builtins.property
  def target(self) -> _ods_ir.Value:
    return self.operands[0]

def structured_linalg_copy_to_memref(transformed: _ods_ir.Type, target: _ods_ir.Value, *, loc: _Optional[_ods_ir.Location] = None, ip: _Optional[_ods_ir.InsertionPoint] = None) -> _ods_ir.OpResult:
  return LinalgCopyToMemrefOp(transformed=transformed, target=target, loc=loc, ip=ip).result

@_ods_cext.register_operation(_Dialect)
class LowerPackOp(_ods_ir.OpView):
  r"""
  Rewrite a linalg.pack into tensor.pad + tensor.expand_shape + linalg.transpose.
  
  #### Return modes
  
  This operation ignores non-pack ops and drops them in the return. This
  operation produces a silenceable failure if the rewrite fails for any
  reason. If all the operations referred to by the `target` are rewritten,
  the transform succeeds. Return handles to the newly produced pad,
  expand_shape and transpose ops.
  """

  OPERATION_NAME = "transform.structured.lower_pack"

  _ODS_REGIONS = (0, True)

  def __init__(self, pad_op: _ods_ir.Type, expand_shape_op: _ods_ir.Type, transpose_op: _ods_ir.Type, target: _ods_ir.Value, *, lowerPadLikeWithInsertSlice: _Optional[_Union[bool, _ods_ir.BoolAttr]] = None, loc: _Optional[_ods_ir.Location] = None, ip: _Optional[_ods_ir.InsertionPoint] = None):
    operands = []
    attributes = {}
    regions = None
    operands.append(target)
    _ods_context = _ods_get_default_loc_context(loc)
    if lowerPadLikeWithInsertSlice is not None: attributes["lowerPadLikeWithInsertSlice"] = (lowerPadLikeWithInsertSlice if (
        isinstance(lowerPadLikeWithInsertSlice, _ods_ir.Attribute) or
        not _ods_ir.AttrBuilder.contains('BoolAttr')) else
          _ods_ir.AttrBuilder.get('BoolAttr')(lowerPadLikeWithInsertSlice, context=_ods_context))
    results = []
    results.append(pad_op)
    results.append(expand_shape_op)
    results.append(transpose_op)
    _ods_successors = None
    super().__init__(self.OPERATION_NAME, self._ODS_REGIONS, self._ODS_OPERAND_SEGMENTS, self._ODS_RESULT_SEGMENTS, attributes=attributes, results=results, operands=operands, successors=_ods_successors, regions=regions, loc=loc, ip=ip)

  @builtins.property
  def target(self) -> _ods_ir.Value:
    return self.operation.operands[0]

  @builtins.property
  def lowerPadLikeWithInsertSlice(self) -> _ods_ir.BoolAttr:
    return self.operation.attributes["lowerPadLikeWithInsertSlice"]

  @lowerPadLikeWithInsertSlice.setter
  def lowerPadLikeWithInsertSlice(self, value: _ods_ir.BoolAttr):
    if value is None:
      raise ValueError("'None' not allowed as value for mandatory attributes")
    self.operation.attributes["lowerPadLikeWithInsertSlice"] = value

  @builtins.property
  def pad_op(self) -> _ods_ir.OpResult:
    return self.operation.results[0]

  @builtins.property
  def expand_shape_op(self) -> _ods_ir.OpResult:
    return self.operation.results[1]

  @builtins.property
  def transpose_op(self) -> _ods_ir.OpResult:
    return self.operation.results[2]

@_ods_cext.register_op_adaptor(LowerPackOp)
class LowerPackOpAdaptor(_ods_ir.OpAdaptor):
  OPERATION_NAME = "transform.structured.lower_pack"

  @builtins.property
  def target(self) -> _ods_ir.Value:
    return self.operands[0]

  @builtins.property
  def lowerPadLikeWithInsertSlice(self) -> _ods_ir.BoolAttr:
    return self.attributes["lowerPadLikeWithInsertSlice"]

def structured_lower_pack(pad_op: _ods_ir.Type, expand_shape_op: _ods_ir.Type, transpose_op: _ods_ir.Type, target: _ods_ir.Value, *, lower_pad_like_with_insert_slice: _Optional[_Union[bool, _ods_ir.BoolAttr]] = None, loc: _Optional[_ods_ir.Location] = None, ip: _Optional[_ods_ir.InsertionPoint] = None) -> _ods_ir.OpResultList:
  return LowerPackOp(pad_op=pad_op, expand_shape_op=expand_shape_op, transpose_op=transpose_op, target=target, lowerPadLikeWithInsertSlice=lower_pad_like_with_insert_slice, loc=loc, ip=ip).results

@_ods_cext.register_operation(_Dialect)
class LowerUnPackOp(_ods_ir.OpView):
  r"""
  Lower a linalg.unpack into empty + linalg.transpose + tensor.collapse_shape +
  tensor.extract_slice + linalg.copy.
  
  #### Return modes
  
  This operation ignores non-unpack ops and drops them in the return. This
  operation produces a silenceable failure if the rewrite fails for any
  reason. If all the operations referred to by the `target` are rewritten,
  the transform succeeds. Return handles to the newly produced empty,
  transpose, collapse_shape, extract_slice and copy ops.
  """

  OPERATION_NAME = "transform.structured.lower_unpack"

  _ODS_REGIONS = (0, True)

  def __init__(self, empty_op: _ods_ir.Type, transpose_op: _ods_ir.Type, collapse_shape_op: _ods_ir.Type, extract_slice_op: _ods_ir.Type, copy_op: _ods_ir.Type, target: _ods_ir.Value, *, lowerUnpadLikeWithExtractSlice: _Optional[_Union[bool, _ods_ir.BoolAttr]] = None, loc: _Optional[_ods_ir.Location] = None, ip: _Optional[_ods_ir.InsertionPoint] = None):
    operands = []
    attributes = {}
    regions = None
    operands.append(target)
    _ods_context = _ods_get_default_loc_context(loc)
    if lowerUnpadLikeWithExtractSlice is not None: attributes["lowerUnpadLikeWithExtractSlice"] = (lowerUnpadLikeWithExtractSlice if (
        isinstance(lowerUnpadLikeWithExtractSlice, _ods_ir.Attribute) or
        not _ods_ir.AttrBuilder.contains('BoolAttr')) else
          _ods_ir.AttrBuilder.get('BoolAttr')(lowerUnpadLikeWithExtractSlice, context=_ods_context))
    results = []
    results.append(empty_op)
    results.append(transpose_op)
    results.append(collapse_shape_op)
    results.append(extract_slice_op)
    results.append(copy_op)
    _ods_successors = None
    super().__init__(self.OPERATION_NAME, self._ODS_REGIONS, self._ODS_OPERAND_SEGMENTS, self._ODS_RESULT_SEGMENTS, attributes=attributes, results=results, operands=operands, successors=_ods_successors, regions=regions, loc=loc, ip=ip)

  @builtins.property
  def target(self) -> _ods_ir.Value:
    return self.operation.operands[0]

  @builtins.property
  def lowerUnpadLikeWithExtractSlice(self) -> _ods_ir.BoolAttr:
    return self.operation.attributes["lowerUnpadLikeWithExtractSlice"]

  @lowerUnpadLikeWithExtractSlice.setter
  def lowerUnpadLikeWithExtractSlice(self, value: _ods_ir.BoolAttr):
    if value is None:
      raise ValueError("'None' not allowed as value for mandatory attributes")
    self.operation.attributes["lowerUnpadLikeWithExtractSlice"] = value

  @builtins.property
  def empty_op(self) -> _ods_ir.OpResult:
    return self.operation.results[0]

  @builtins.property
  def transpose_op(self) -> _ods_ir.OpResult:
    return self.operation.results[1]

  @builtins.property
  def collapse_shape_op(self) -> _ods_ir.OpResult:
    return self.operation.results[2]

  @builtins.property
  def extract_slice_op(self) -> _ods_ir.OpResult:
    return self.operation.results[3]

  @builtins.property
  def copy_op(self) -> _ods_ir.OpResult:
    return self.operation.results[4]

@_ods_cext.register_op_adaptor(LowerUnPackOp)
class LowerUnPackOpAdaptor(_ods_ir.OpAdaptor):
  OPERATION_NAME = "transform.structured.lower_unpack"

  @builtins.property
  def target(self) -> _ods_ir.Value:
    return self.operands[0]

  @builtins.property
  def lowerUnpadLikeWithExtractSlice(self) -> _ods_ir.BoolAttr:
    return self.attributes["lowerUnpadLikeWithExtractSlice"]

def structured_lower_unpack(empty_op: _ods_ir.Type, transpose_op: _ods_ir.Type, collapse_shape_op: _ods_ir.Type, extract_slice_op: _ods_ir.Type, copy_op: _ods_ir.Type, target: _ods_ir.Value, *, lower_unpad_like_with_extract_slice: _Optional[_Union[bool, _ods_ir.BoolAttr]] = None, loc: _Optional[_ods_ir.Location] = None, ip: _Optional[_ods_ir.InsertionPoint] = None) -> _ods_ir.OpResultList:
  return LowerUnPackOp(empty_op=empty_op, transpose_op=transpose_op, collapse_shape_op=collapse_shape_op, extract_slice_op=extract_slice_op, copy_op=copy_op, target=target, lowerUnpadLikeWithExtractSlice=lower_unpad_like_with_extract_slice, loc=loc, ip=ip).results

@_ods_cext.register_operation(_Dialect)
class MapCopyToThreadsOp(_ods_ir.OpView):
  r"""
  Targeted mapping of a linalg.copy / tensor.pad operation on tensors to a GPU
  thread mapping.
  
  This operation implements a greedy heuristic that determines a good
  distribution of threads to break down the copy/pad operation into.
  The heuristic is driven by considerations related to the underlying
  architecture for which good high-level decisions are needed assuming certain
  hardware features. Relevant features are exposed via first-class attributes
  to control the behavior of the transformation at a high level.
  
  For now, a single heuristic is implemented and can be extended on a per-need
  basis.
  
  #### Return modes
  
  This operation fails definitely if there is an unsupported op (i.e., not
  linalg.copy / tensor.pad) among the targeted op. Otherwise, the operation
  always succeeds and returns a handle to the relevant tiled linalg.copy /
  tensor.pad op and the enclosing scf.forall op.
  """

  OPERATION_NAME = "transform.structured.gpu.map_copy_to_threads"

  _ODS_REGIONS = (0, True)

  def __init__(self, forall_op: _ods_ir.Type, tiled_op: _ods_ir.Type, target: _ods_ir.Value, total_num_threads: _Union[int, _ods_ir.IntegerAttr], desired_bit_alignment: _Union[int, _ods_ir.IntegerAttr], *, loc: _Optional[_ods_ir.Location] = None, ip: _Optional[_ods_ir.InsertionPoint] = None):
    operands = []
    attributes = {}
    regions = None
    operands.append(target)
    _ods_context = _ods_get_default_loc_context(loc)
    attributes["total_num_threads"] = (total_num_threads if (
    isinstance(total_num_threads, _ods_ir.Attribute) or
    not _ods_ir.AttrBuilder.contains('I64Attr')) else
      _ods_ir.AttrBuilder.get('I64Attr')(total_num_threads, context=_ods_context))
    attributes["desired_bit_alignment"] = (desired_bit_alignment if (
    isinstance(desired_bit_alignment, _ods_ir.Attribute) or
    not _ods_ir.AttrBuilder.contains('I64Attr')) else
      _ods_ir.AttrBuilder.get('I64Attr')(desired_bit_alignment, context=_ods_context))
    results = []
    results.append(forall_op)
    results.append(tiled_op)
    _ods_successors = None
    super().__init__(self.OPERATION_NAME, self._ODS_REGIONS, self._ODS_OPERAND_SEGMENTS, self._ODS_RESULT_SEGMENTS, attributes=attributes, results=results, operands=operands, successors=_ods_successors, regions=regions, loc=loc, ip=ip)

  @builtins.property
  def target(self) -> _ods_ir.Value:
    return self.operation.operands[0]

  @builtins.property
  def total_num_threads(self) -> _ods_ir.IntegerAttr:
    return self.operation.attributes["total_num_threads"]

  @total_num_threads.setter
  def total_num_threads(self, value: _ods_ir.IntegerAttr):
    if value is None:
      raise ValueError("'None' not allowed as value for mandatory attributes")
    self.operation.attributes["total_num_threads"] = value

  @builtins.property
  def desired_bit_alignment(self) -> _ods_ir.IntegerAttr:
    return self.operation.attributes["desired_bit_alignment"]

  @desired_bit_alignment.setter
  def desired_bit_alignment(self, value: _ods_ir.IntegerAttr):
    if value is None:
      raise ValueError("'None' not allowed as value for mandatory attributes")
    self.operation.attributes["desired_bit_alignment"] = value

  @builtins.property
  def forall_op(self) -> _ods_ir.OpResult:
    return self.operation.results[0]

  @builtins.property
  def tiled_op(self) -> _ods_ir.OpResult:
    return self.operation.results[1]

@_ods_cext.register_op_adaptor(MapCopyToThreadsOp)
class MapCopyToThreadsOpAdaptor(_ods_ir.OpAdaptor):
  OPERATION_NAME = "transform.structured.gpu.map_copy_to_threads"

  @builtins.property
  def target(self) -> _ods_ir.Value:
    return self.operands[0]

  @builtins.property
  def total_num_threads(self) -> _ods_ir.IntegerAttr:
    return self.attributes["total_num_threads"]

  @builtins.property
  def desired_bit_alignment(self) -> _ods_ir.IntegerAttr:
    return self.attributes["desired_bit_alignment"]

def structured_gpu_map_copy_to_threads(forall_op: _ods_ir.Type, tiled_op: _ods_ir.Type, target: _ods_ir.Value, total_num_threads: _Union[int, _ods_ir.IntegerAttr], desired_bit_alignment: _Union[int, _ods_ir.IntegerAttr], *, loc: _Optional[_ods_ir.Location] = None, ip: _Optional[_ods_ir.InsertionPoint] = None) -> _ods_ir.OpResultList:
  return MapCopyToThreadsOp(forall_op=forall_op, tiled_op=tiled_op, target=target, total_num_threads=total_num_threads, desired_bit_alignment=desired_bit_alignment, loc=loc, ip=ip).results

@_ods_cext.register_operation(_Dialect)
class MatchOp(_ods_ir.OpView):
  r"""
  Match op with the specified constraints, within the target op.
  
  The following constraints are supported:
    - interface: an optional MatchInterfaceEnum specifying an enum
      representation for an interface to target.
    - ops: an optional StrArrayAttr specifying the concrete name of an op.
      Multiple names can be specified. Matched ops must have one of specified
      names.
    - attribute: the matched op must have all specified attributes (with their
      specified values).
    - filter_result_type: the matched op must return exactly this one type.
    - filter_operand_types: all the operands of the matched op must must be of
      this type. If more than a type is specified, then the length of the list
      must be equal to the number of operands in the matched op, and the match
      will succeed only if the operand types match all the types in the list
      in the order in which they are specified.
  
  Note: Only ops that satisfy all specified constraints are matched.
  
  TODO: Extend with regions to allow a limited form of constraints.
  
  #### Return modes
  
  This op traverses the ops nested under `target` and returns the handles to
  all the operations that match the requirements.
  
  This op fails if the target is not a handle to exactly one operation.
  Otherwise it succeeds.
  
  This operation does not consume the target handle and produces new handles:
  it is a navigation op.
  """

  OPERATION_NAME = "transform.structured.match"

  _ODS_REGIONS = (0, True)

  def __init__(self, results_: _ods_ir.Type, target: _ods_ir.Value, *, ops: _Optional[_Union[_Sequence[str], _ods_ir.ArrayAttr]] = None, interface: _Optional[_Union[_Any, _ods_ir.Attribute]] = None, op_attrs: _Optional[_Union[dict, _ods_ir.DictAttr]] = None, filter_result_type: _Optional[_Union[_ods_ir.Type, _ods_ir.TypeAttr]] = None, filter_operand_types: _Optional[_Union[_Any, _ods_ir.ArrayAttr]] = None, loc: _Optional[_ods_ir.Location] = None, ip: _Optional[_ods_ir.InsertionPoint] = None):
    operands = []
    attributes = {}
    regions = None
    operands.append(target)
    _ods_context = _ods_get_default_loc_context(loc)
    if ops is not None: attributes["ops"] = (ops if (
        isinstance(ops, _ods_ir.Attribute) or
        not _ods_ir.AttrBuilder.contains('StrArrayAttr')) else
          _ods_ir.AttrBuilder.get('StrArrayAttr')(ops, context=_ods_context))
    if interface is not None: attributes["interface"] = (interface if (
        isinstance(interface, _ods_ir.Attribute) or
        not _ods_ir.AttrBuilder.contains('MatchInterfaceEnum')) else
          _ods_ir.AttrBuilder.get('MatchInterfaceEnum')(interface, context=_ods_context))
    if op_attrs is not None: attributes["op_attrs"] = (op_attrs if (
        isinstance(op_attrs, _ods_ir.Attribute) or
        not _ods_ir.AttrBuilder.contains('DictionaryAttr')) else
          _ods_ir.AttrBuilder.get('DictionaryAttr')(op_attrs, context=_ods_context))
    if filter_result_type is not None: attributes["filter_result_type"] = (filter_result_type if (
        isinstance(filter_result_type, _ods_ir.Attribute) or
        not _ods_ir.AttrBuilder.contains('TypeAttr')) else
          _ods_ir.AttrBuilder.get('TypeAttr')(filter_result_type, context=_ods_context))
    if filter_operand_types is not None: attributes["filter_operand_types"] = (filter_operand_types if (
        isinstance(filter_operand_types, _ods_ir.Attribute) or
        not _ods_ir.AttrBuilder.contains('TypeArrayAttr')) else
          _ods_ir.AttrBuilder.get('TypeArrayAttr')(filter_operand_types, context=_ods_context))
    results = []
    results.append(results_)
    _ods_successors = None
    super().__init__(self.OPERATION_NAME, self._ODS_REGIONS, self._ODS_OPERAND_SEGMENTS, self._ODS_RESULT_SEGMENTS, attributes=attributes, results=results, operands=operands, successors=_ods_successors, regions=regions, loc=loc, ip=ip)

  @builtins.property
  def target(self) -> _ods_ir.Value:
    return self.operation.operands[0]

  @builtins.property
  def ops(self) -> _Optional[_ods_ir.ArrayAttr]:
    if "ops" not in self.operation.attributes:
      return None
    return self.operation.attributes["ops"]

  @ops.setter
  def ops(self, value: _Optional[_ods_ir.ArrayAttr]):
    if value is not None:
      self.operation.attributes["ops"] = value
    elif "ops" in self.operation.attributes:
      del self.operation.attributes["ops"]

  @ops.deleter
  def ops(self):
    del self.operation.attributes["ops"]

  @builtins.property
  def interface(self) -> _Optional[_ods_ir.Attribute]:
    if "interface" not in self.operation.attributes:
      return None
    return self.operation.attributes["interface"]

  @interface.setter
  def interface(self, value: _Optional[_ods_ir.Attribute]):
    if value is not None:
      self.operation.attributes["interface"] = value
    elif "interface" in self.operation.attributes:
      del self.operation.attributes["interface"]

  @interface.deleter
  def interface(self):
    del self.operation.attributes["interface"]

  @builtins.property
  def op_attrs(self) -> _Optional[_ods_ir.DictAttr]:
    if "op_attrs" not in self.operation.attributes:
      return None
    return self.operation.attributes["op_attrs"]

  @op_attrs.setter
  def op_attrs(self, value: _Optional[_ods_ir.DictAttr]):
    if value is not None:
      self.operation.attributes["op_attrs"] = value
    elif "op_attrs" in self.operation.attributes:
      del self.operation.attributes["op_attrs"]

  @op_attrs.deleter
  def op_attrs(self):
    del self.operation.attributes["op_attrs"]

  @builtins.property
  def filter_result_type(self) -> _Optional[_ods_ir.TypeAttr]:
    if "filter_result_type" not in self.operation.attributes:
      return None
    return self.operation.attributes["filter_result_type"]

  @filter_result_type.setter
  def filter_result_type(self, value: _Optional[_ods_ir.TypeAttr]):
    if value is not None:
      self.operation.attributes["filter_result_type"] = value
    elif "filter_result_type" in self.operation.attributes:
      del self.operation.attributes["filter_result_type"]

  @filter_result_type.deleter
  def filter_result_type(self):
    del self.operation.attributes["filter_result_type"]

  @builtins.property
  def filter_operand_types(self) -> _Optional[_ods_ir.ArrayAttr]:
    if "filter_operand_types" not in self.operation.attributes:
      return None
    return self.operation.attributes["filter_operand_types"]

  @filter_operand_types.setter
  def filter_operand_types(self, value: _Optional[_ods_ir.ArrayAttr]):
    if value is not None:
      self.operation.attributes["filter_operand_types"] = value
    elif "filter_operand_types" in self.operation.attributes:
      del self.operation.attributes["filter_operand_types"]

  @filter_operand_types.deleter
  def filter_operand_types(self):
    del self.operation.attributes["filter_operand_types"]

  @builtins.property
  def results_(self) -> _ods_ir.OpResult:
    return self.operation.results[0]

@_ods_cext.register_op_adaptor(MatchOp)
class MatchOpAdaptor(_ods_ir.OpAdaptor):
  OPERATION_NAME = "transform.structured.match"

  @builtins.property
  def target(self) -> _ods_ir.Value:
    return self.operands[0]

  @builtins.property
  def ops(self) -> _Optional[_ods_ir.ArrayAttr]:
    if "ops" not in self.attributes:
      return None
    return self.attributes["ops"]

  @builtins.property
  def interface(self) -> _Optional[_ods_ir.Attribute]:
    if "interface" not in self.attributes:
      return None
    return self.attributes["interface"]

  @builtins.property
  def op_attrs(self) -> _Optional[_ods_ir.DictAttr]:
    if "op_attrs" not in self.attributes:
      return None
    return self.attributes["op_attrs"]

  @builtins.property
  def filter_result_type(self) -> _Optional[_ods_ir.TypeAttr]:
    if "filter_result_type" not in self.attributes:
      return None
    return self.attributes["filter_result_type"]

  @builtins.property
  def filter_operand_types(self) -> _Optional[_ods_ir.ArrayAttr]:
    if "filter_operand_types" not in self.attributes:
      return None
    return self.attributes["filter_operand_types"]

def structured_match(results_: _ods_ir.Type, target: _ods_ir.Value, *, ops: _Optional[_Union[_Sequence[str], _ods_ir.ArrayAttr]] = None, interface: _Optional[_Union[_Any, _ods_ir.Attribute]] = None, op_attrs: _Optional[_Union[dict, _ods_ir.DictAttr]] = None, filter_result_type: _Optional[_Union[_ods_ir.Type, _ods_ir.TypeAttr]] = None, filter_operand_types: _Optional[_Union[_Any, _ods_ir.ArrayAttr]] = None, loc: _Optional[_ods_ir.Location] = None, ip: _Optional[_ods_ir.InsertionPoint] = None) -> _ods_ir.OpResult:
  return MatchOp(results_=results_, target=target, ops=ops, interface=interface, op_attrs=op_attrs, filter_result_type=filter_result_type, filter_operand_types=filter_operand_types, loc=loc, ip=ip).result

@_ods_cext.register_operation(_Dialect)
class MultiTileSizesOp(_ods_ir.OpView):
  r"""
  Emits the IR computing the tile sizes `s1` and `s2` such that:
  
    - there exists a combination of `n` tiles of size `s1` and `m` tiles of
      size `s2` that covers the entirety of the iteration space `dimension` of
      the target structured op;
    - `s1`, `s2` is less than or equal to `target_size`;
    - `s1` and `s2` are divisible by `divisor.
  
  For example, for a dimension of size 54 with target size 12 and divisor 2,
  this can emit the IR computing the tile size 10, used for 3 tiles, and 12,
  used for 2 tiles, totally 10*3 + 12*2 = 54. Note that when the divisor does
  not divide the original dimension size, it is impossible to compute such
  tile sizes. An assertion is emitted to guard against this in the dynamic
  case.
  
  Expects the target size and the divisor to be strictly positive. Folds the
  IR as much as possible, normally obtaining constant sizes and numbers of
  tiles for a statically known dimension.
  
  This does *not* consume the target handle and produces three handles each
  pointing to single-result index-typed operations (which may be arithmetic
  constant operations) defining the two respective tile sizes and the product
  of the first tile size with the number of tiles of that size (useful for
  splitting the iteration space).
  
  This operation composes with the regular tiling when applied per-dimension:
  
  ```mlir
  %sz1, %sz2, %split = structured.multitile_sizes %target
                       { target_size = 10, dimension = 1 }
                     : !transform.any_op, !transform.param<i64>,
                       !transform.param<i64>, !transform.param<i64>
  %handles = structured.split %target after %split { dimension = 1 }
              : !transform.any_op, !transform.param<i64>
  %low, %high = transform.split_handle %handles : (!transform.any_op)
                    -> (!transform.any_op, !transform.any_op)
  %tiled_low, %loop1 = structured.tile_using_for %low [0, %sz1]
                     : (!transform.any_op, !transform.param<i64>)
                    -> (!transform.any_op, !transform.any_op)
  %tiled_high, %loop2 = structured.tile_using_for %high [0, %sz2]
                      : (!transform.any_op, !transform.param<i64>)
                     -> (!transform.any_op, !transform.any_op)
  %common = merge_handles %tiled_low, %tiled_high : !transform.any_op
  
  %sz3, %sz4, %split = structured.multitile_size %target
                       { target_size = 42, dimension = 0 }
                     : !transform.any_op, !transform.any_op,
                       !transform.any_op, !transform.any_op
  %sz3r, %sz4r, %splitr = replicate num(%common) %sz3, %sz4, %splitr
           : !transform.any_op, !transform.any_op, !transform.any_op
  structured.split %common after %splitr { dimension = 0 }
           : !transform.any_op, !transform.any_op
  // ...
  ```
  """

  OPERATION_NAME = "transform.structured.multitile_sizes"

  _ODS_REGIONS = (0, True)

  def __init__(self, low_size: _ods_ir.Type, high_size: _ods_ir.Type, split_point: _ods_ir.Type, target: _ods_ir.Value, dimension: _Union[int, _ods_ir.IntegerAttr], target_size: _Union[int, _ods_ir.IntegerAttr], *, divisor: _Optional[_Union[int, _ods_ir.IntegerAttr]] = None, loc: _Optional[_ods_ir.Location] = None, ip: _Optional[_ods_ir.InsertionPoint] = None):
    operands = []
    attributes = {}
    regions = None
    operands.append(target)
    _ods_context = _ods_get_default_loc_context(loc)
    attributes["dimension"] = (dimension if (
    isinstance(dimension, _ods_ir.Attribute) or
    not _ods_ir.AttrBuilder.contains('I64Attr')) else
      _ods_ir.AttrBuilder.get('I64Attr')(dimension, context=_ods_context))
    attributes["target_size"] = (target_size if (
    isinstance(target_size, _ods_ir.Attribute) or
    not _ods_ir.AttrBuilder.contains('I64Attr')) else
      _ods_ir.AttrBuilder.get('I64Attr')(target_size, context=_ods_context))
    if divisor is not None: attributes["divisor"] = (divisor if (
        isinstance(divisor, _ods_ir.Attribute) or
        not _ods_ir.AttrBuilder.contains('I64Attr')) else
          _ods_ir.AttrBuilder.get('I64Attr')(divisor, context=_ods_context))
    results = []
    results.append(low_size)
    results.append(high_size)
    results.append(split_point)
    _ods_successors = None
    super().__init__(self.OPERATION_NAME, self._ODS_REGIONS, self._ODS_OPERAND_SEGMENTS, self._ODS_RESULT_SEGMENTS, attributes=attributes, results=results, operands=operands, successors=_ods_successors, regions=regions, loc=loc, ip=ip)

  @builtins.property
  def target(self) -> _ods_ir.Value:
    return self.operation.operands[0]

  @builtins.property
  def dimension(self) -> _ods_ir.IntegerAttr:
    return self.operation.attributes["dimension"]

  @dimension.setter
  def dimension(self, value: _ods_ir.IntegerAttr):
    if value is None:
      raise ValueError("'None' not allowed as value for mandatory attributes")
    self.operation.attributes["dimension"] = value

  @builtins.property
  def target_size(self) -> _ods_ir.IntegerAttr:
    return self.operation.attributes["target_size"]

  @target_size.setter
  def target_size(self, value: _ods_ir.IntegerAttr):
    if value is None:
      raise ValueError("'None' not allowed as value for mandatory attributes")
    self.operation.attributes["target_size"] = value

  @builtins.property
  def divisor(self) -> _ods_ir.IntegerAttr:
    return self.operation.attributes["divisor"]

  @divisor.setter
  def divisor(self, value: _ods_ir.IntegerAttr):
    if value is None:
      raise ValueError("'None' not allowed as value for mandatory attributes")
    self.operation.attributes["divisor"] = value

  @builtins.property
  def low_size(self) -> _ods_ir.OpResult:
    return self.operation.results[0]

  @builtins.property
  def high_size(self) -> _ods_ir.OpResult:
    return self.operation.results[1]

  @builtins.property
  def split_point(self) -> _ods_ir.OpResult:
    return self.operation.results[2]

@_ods_cext.register_op_adaptor(MultiTileSizesOp)
class MultiTileSizesOpAdaptor(_ods_ir.OpAdaptor):
  OPERATION_NAME = "transform.structured.multitile_sizes"

  @builtins.property
  def target(self) -> _ods_ir.Value:
    return self.operands[0]

  @builtins.property
  def dimension(self) -> _ods_ir.IntegerAttr:
    return self.attributes["dimension"]

  @builtins.property
  def target_size(self) -> _ods_ir.IntegerAttr:
    return self.attributes["target_size"]

  @builtins.property
  def divisor(self) -> _ods_ir.IntegerAttr:
    return self.attributes["divisor"]

def structured_multitile_sizes(low_size: _ods_ir.Type, high_size: _ods_ir.Type, split_point: _ods_ir.Type, target: _ods_ir.Value, dimension: _Union[int, _ods_ir.IntegerAttr], target_size: _Union[int, _ods_ir.IntegerAttr], *, divisor: _Optional[_Union[int, _ods_ir.IntegerAttr]] = None, loc: _Optional[_ods_ir.Location] = None, ip: _Optional[_ods_ir.InsertionPoint] = None) -> _ods_ir.OpResultList:
  return MultiTileSizesOp(low_size=low_size, high_size=high_size, split_point=split_point, target=target, dimension=dimension, target_size=target_size, divisor=divisor, loc=loc, ip=ip).results

@_ods_cext.register_operation(_Dialect)
class PackGreedilyOp(_ods_ir.OpView):
  r"""
  Target a Linalg op and rewrite it into packed LinalgOp form by trying to
  infer whether a known suboperation is embedded
  
  Different packing strategies are applied in order, when one applies
  successfully, the transform returns:
    1. Matmul packing: Try to infer a matmul operation embedded in the target op.
       Specifically, this looks for 2 parallel dimensions that participate in
       an outer-product and 1 reduction dimension.
       These dimensions are referred as (m, n, k) to match canonical matmul
       terminology.
  
       The packed sizes for (m, n, k) are specified by `matmul_packed_sizes`
       and the optional `matmul_padded_sizes_next_multiple_of`.
       When an entry `matmul_packed_sizes[i]` is non-0, the corresponding
       dimension is packed by `matmul_packed_sizes[i]`.
       Otherwise, the dimension is merely padded to the next multiple of
       `matmul_padded_sizes_next_multiple_of[i]`.
  
       `matmul_padded_sizes_next_multiple_of` is optional and is expected to
       either be empty or of size `3`, matching the size of `matmul_packed_sizes`.
       For each individual element of `matmul_packed_sizes` and
       `matmul_padded_sizes_next_multiple_of`, only one of them is allowed to
       be non-zero.
  
       The ordering of the packed dimensions (mm, nn, kk) is specified by the
       `matmul_inner_dims_order` attribute.
  
  Packing occurs as follows:
    1. Find the dimensions to pack according to the strategy.
    2. The target is converted to linalg.generic form.
    3. An interchange transform is applied to isolate the dimensions to pack as
       the most minor indexing dimensions of the linalg.generic. The most minor
       dimensions are themselves ordered according to `inner_dims_order`.
    4. An elementwise traversal of `matmul_packed_sizes` and
       `matmul_padded_sizes_next_multiple_of` is performed and for each
       dimension `d`, either pack to `matmul_packed_sizes[d]` or pad to the
       `matmul_padded_sizes_next_multiple_of[d]`.
    5. Packing/padding is performed by the amounts determined in step 4. and
       following `inner_dims_order`.
  
  By normalizing the most minor dimensions to `inner_dims_order`, the transform
  guarantees that packing immediately generates inner dimensions in a desirable
  layout.
  
  Outer dimension layout permutations are not controlled by this transform op
  at the moment and can be obtained by composing with the pack_transpose
  transformation.
  
  #### Return modes
  
  This operation ignores non-Linalg ops and drops them in the return.
  It returns the list of packed Linalg ops or the original op when all available
  packing strategies failed to apply.
  """

  OPERATION_NAME = "transform.structured.pack_greedily"

  _ODS_REGIONS = (0, True)

  def __init__(self, packed_op: _ods_ir.Type, target: _ods_ir.Value, matmul_packed_sizes: _Sequence[_ods_ir.Value], *, static_matmul_packed_sizes: _Optional[_Union[_Sequence[int], _ods_ir.DenseI64ArrayAttr]] = None, matmul_padded_sizes_next_multiple_of: _Optional[_Union[_Sequence[int], _ods_ir.DenseI64ArrayAttr]] = None, matmul_inner_dims_order: _Optional[_Union[_Sequence[int], _ods_ir.DenseI64ArrayAttr]] = None, loc: _Optional[_ods_ir.Location] = None, ip: _Optional[_ods_ir.InsertionPoint] = None):
    operands = []
    attributes = {}
    regions = None
    operands.append(target)
    operands.extend(_get_op_results_or_values(matmul_packed_sizes))
    _ods_context = _ods_get_default_loc_context(loc)
    if static_matmul_packed_sizes is not None: attributes["static_matmul_packed_sizes"] = (static_matmul_packed_sizes if (
        isinstance(static_matmul_packed_sizes, _ods_ir.Attribute) or
        not _ods_ir.AttrBuilder.contains('DenseI64ArrayAttr')) else
          _ods_ir.AttrBuilder.get('DenseI64ArrayAttr')(static_matmul_packed_sizes, context=_ods_context))
    if matmul_padded_sizes_next_multiple_of is not None: attributes["matmul_padded_sizes_next_multiple_of"] = (matmul_padded_sizes_next_multiple_of if (
        isinstance(matmul_padded_sizes_next_multiple_of, _ods_ir.Attribute) or
        not _ods_ir.AttrBuilder.contains('DenseI64ArrayAttr')) else
          _ods_ir.AttrBuilder.get('DenseI64ArrayAttr')(matmul_padded_sizes_next_multiple_of, context=_ods_context))
    if matmul_inner_dims_order is not None: attributes["matmul_inner_dims_order"] = (matmul_inner_dims_order if (
        isinstance(matmul_inner_dims_order, _ods_ir.Attribute) or
        not _ods_ir.AttrBuilder.contains('DenseI64ArrayAttr')) else
          _ods_ir.AttrBuilder.get('DenseI64ArrayAttr')(matmul_inner_dims_order, context=_ods_context))
    results = []
    results.append(packed_op)
    _ods_successors = None
    super().__init__(self.OPERATION_NAME, self._ODS_REGIONS, self._ODS_OPERAND_SEGMENTS, self._ODS_RESULT_SEGMENTS, attributes=attributes, results=results, operands=operands, successors=_ods_successors, regions=regions, loc=loc, ip=ip)

  @builtins.property
  def target(self) -> _ods_ir.Value:
    return self.operation.operands[0]

  @builtins.property
  def matmul_packed_sizes(self) -> _ods_ir.OpOperandList:
    _ods_variadic_group_length = len(self.operation.operands) - 2 + 1
    return self.operation.operands[1:1 + _ods_variadic_group_length]

  @builtins.property
  def static_matmul_packed_sizes(self) -> _ods_ir.DenseI64ArrayAttr:
    return self.operation.attributes["static_matmul_packed_sizes"]

  @static_matmul_packed_sizes.setter
  def static_matmul_packed_sizes(self, value: _ods_ir.DenseI64ArrayAttr):
    if value is None:
      raise ValueError("'None' not allowed as value for mandatory attributes")
    self.operation.attributes["static_matmul_packed_sizes"] = value

  @builtins.property
  def matmul_padded_sizes_next_multiple_of(self) -> _ods_ir.DenseI64ArrayAttr:
    return self.operation.attributes["matmul_padded_sizes_next_multiple_of"]

  @matmul_padded_sizes_next_multiple_of.setter
  def matmul_padded_sizes_next_multiple_of(self, value: _ods_ir.DenseI64ArrayAttr):
    if value is None:
      raise ValueError("'None' not allowed as value for mandatory attributes")
    self.operation.attributes["matmul_padded_sizes_next_multiple_of"] = value

  @builtins.property
  def matmul_inner_dims_order(self) -> _ods_ir.DenseI64ArrayAttr:
    return self.operation.attributes["matmul_inner_dims_order"]

  @matmul_inner_dims_order.setter
  def matmul_inner_dims_order(self, value: _ods_ir.DenseI64ArrayAttr):
    if value is None:
      raise ValueError("'None' not allowed as value for mandatory attributes")
    self.operation.attributes["matmul_inner_dims_order"] = value

  @builtins.property
  def packed_op(self) -> _ods_ir.OpResult:
    return self.operation.results[0]

@_ods_cext.register_op_adaptor(PackGreedilyOp)
class PackGreedilyOpAdaptor(_ods_ir.OpAdaptor):
  OPERATION_NAME = "transform.structured.pack_greedily"

  @builtins.property
  def target(self) -> _ods_ir.Value:
    return self.operands[0]

  @builtins.property
  def matmul_packed_sizes(self) -> _ods_ir.OpOperandList:
    _ods_variadic_group_length = len(self.operands) - 2 + 1
    return self.operands[1:1 + _ods_variadic_group_length]

  @builtins.property
  def static_matmul_packed_sizes(self) -> _ods_ir.DenseI64ArrayAttr:
    return self.attributes["static_matmul_packed_sizes"]

  @builtins.property
  def matmul_padded_sizes_next_multiple_of(self) -> _ods_ir.DenseI64ArrayAttr:
    return self.attributes["matmul_padded_sizes_next_multiple_of"]

  @builtins.property
  def matmul_inner_dims_order(self) -> _ods_ir.DenseI64ArrayAttr:
    return self.attributes["matmul_inner_dims_order"]

def structured_pack_greedily(packed_op: _ods_ir.Type, target: _ods_ir.Value, matmul_packed_sizes: _Sequence[_ods_ir.Value], *, static_matmul_packed_sizes: _Optional[_Union[_Sequence[int], _ods_ir.DenseI64ArrayAttr]] = None, matmul_padded_sizes_next_multiple_of: _Optional[_Union[_Sequence[int], _ods_ir.DenseI64ArrayAttr]] = None, matmul_inner_dims_order: _Optional[_Union[_Sequence[int], _ods_ir.DenseI64ArrayAttr]] = None, loc: _Optional[_ods_ir.Location] = None, ip: _Optional[_ods_ir.InsertionPoint] = None) -> _ods_ir.OpResult:
  return PackGreedilyOp(packed_op=packed_op, target=target, matmul_packed_sizes=matmul_packed_sizes, static_matmul_packed_sizes=static_matmul_packed_sizes, matmul_padded_sizes_next_multiple_of=matmul_padded_sizes_next_multiple_of, matmul_inner_dims_order=matmul_inner_dims_order, loc=loc, ip=ip).result

@_ods_cext.register_operation(_Dialect)
class PackOp(_ods_ir.OpView):
  r"""
  Pack a LinalgOp by applying a data tiling transformation on the op and
  packing the operands according to the `packed_sizes` specification.
  
  Iterator dimensions are tiled in their canonical order in the op spec.
  Operands are packed according to the same canonical order of the op iterator
  dimensions.
  
  Specifying a packed size of 0 for an iterator removes it from consideration
  for packing.
  
  `linalg.pack` (resp. `linalg.unpack`) operations are inserted for the operands
  (resp. results) that need to be packed (resp. unpacked) according to the
  `packed_sizes` specification.
  
  #### Example
  
  Consider a `linalg.matmul` with indexing maps:
  ```
    //              M   N   K       M   K
    // affine_map<(d0, d1, d2) -> (d0, d2)>
    //                              K   N
    // affine_map<(d0, d1, d2) -> (d2, d1)>
    //                              M   N
    // affine_map<(d0, d1, d2) -> (d0, d1)>
    %0 = linalg.matmul  ins(%A, %B: tensor<?x?xf32>, tensor<?x?xf32>)
                       outs(    %C: tensor<?x?xf32>)
  ```
  
  Specifying packed_sizes [2, 3, 4] results in tiling the iterator dimensions
  M, N and K, in this order, in both the op and its operands.
  ```
    //              M   N   K   m   n   k       M   K   m   k
    // affine_map<(d0, d1, d2, d3, d4, d5) -> (d0, d2, d3, d5)>
    //                                          K   N   n   k
    // affine_map<(d0, d1, d2, d3, d4, d5) -> (d2, d1, d4, d5)>
    //                                          M   N   m   n
    // affine_map<(d0, d1, d2, d3, d4, d5) -> (d0, d1, d3, d4)>
    %0 = linalg.generic_representing_some_higher_d_matmul
          ins(%A, %B: tensor<?x?x2x4xf32>, tensor<?x?x4x3xf32>)
         outs(    %C: tensor<?x?x2x3xf32>)
  ```
  In particular, note that the second operand `B` has shape `KxNxnxk` (and not
  `KxNxkxn` as one could expect by looking **only** at the operand).
  
  Other layouts can be obtained unsurprisingly from this canonical
  transformation by composing the resulting operation with a
  `transform.structured.pack_transpose` op.
  This composition allows separating concerns and composes better compared
  to adding additional permutation attributes to this transform op.
  
  #### Return modes
  
  This operation applies to a single Linalg op, otherwise it fails.
  This operation may produce a definite failure if the packing fails for any
  reason.
  
  The returned handle point to the packed LinalgOp.
  """

  OPERATION_NAME = "transform.structured.pack"

  _ODS_REGIONS = (0, True)

  def __init__(self, packed_op: _ods_ir.Type, target: _ods_ir.Value, packed_sizes: _Sequence[_ods_ir.Value], *, static_packed_sizes: _Optional[_Union[_Sequence[int], _ods_ir.DenseI64ArrayAttr]] = None, loc: _Optional[_ods_ir.Location] = None, ip: _Optional[_ods_ir.InsertionPoint] = None):
    operands = []
    attributes = {}
    regions = None
    operands.append(target)
    operands.extend(_get_op_results_or_values(packed_sizes))
    _ods_context = _ods_get_default_loc_context(loc)
    if static_packed_sizes is not None: attributes["static_packed_sizes"] = (static_packed_sizes if (
        isinstance(static_packed_sizes, _ods_ir.Attribute) or
        not _ods_ir.AttrBuilder.contains('DenseI64ArrayAttr')) else
          _ods_ir.AttrBuilder.get('DenseI64ArrayAttr')(static_packed_sizes, context=_ods_context))
    results = []
    results.append(packed_op)
    _ods_successors = None
    super().__init__(self.OPERATION_NAME, self._ODS_REGIONS, self._ODS_OPERAND_SEGMENTS, self._ODS_RESULT_SEGMENTS, attributes=attributes, results=results, operands=operands, successors=_ods_successors, regions=regions, loc=loc, ip=ip)

  @builtins.property
  def target(self) -> _ods_ir.Value:
    return self.operation.operands[0]

  @builtins.property
  def packed_sizes(self) -> _ods_ir.OpOperandList:
    _ods_variadic_group_length = len(self.operation.operands) - 2 + 1
    return self.operation.operands[1:1 + _ods_variadic_group_length]

  @builtins.property
  def static_packed_sizes(self) -> _ods_ir.DenseI64ArrayAttr:
    return self.operation.attributes["static_packed_sizes"]

  @static_packed_sizes.setter
  def static_packed_sizes(self, value: _ods_ir.DenseI64ArrayAttr):
    if value is None:
      raise ValueError("'None' not allowed as value for mandatory attributes")
    self.operation.attributes["static_packed_sizes"] = value

  @builtins.property
  def packed_op(self) -> _ods_ir.OpResult:
    return self.operation.results[0]

@_ods_cext.register_op_adaptor(PackOp)
class PackOpAdaptor(_ods_ir.OpAdaptor):
  OPERATION_NAME = "transform.structured.pack"

  @builtins.property
  def target(self) -> _ods_ir.Value:
    return self.operands[0]

  @builtins.property
  def packed_sizes(self) -> _ods_ir.OpOperandList:
    _ods_variadic_group_length = len(self.operands) - 2 + 1
    return self.operands[1:1 + _ods_variadic_group_length]

  @builtins.property
  def static_packed_sizes(self) -> _ods_ir.DenseI64ArrayAttr:
    return self.attributes["static_packed_sizes"]

def structured_pack(packed_op: _ods_ir.Type, target: _ods_ir.Value, packed_sizes: _Sequence[_ods_ir.Value], *, static_packed_sizes: _Optional[_Union[_Sequence[int], _ods_ir.DenseI64ArrayAttr]] = None, loc: _Optional[_ods_ir.Location] = None, ip: _Optional[_ods_ir.InsertionPoint] = None) -> _ods_ir.OpResult:
  return PackOp(packed_op=packed_op, target=target, packed_sizes=packed_sizes, static_packed_sizes=static_packed_sizes, loc=loc, ip=ip).result

@_ods_cext.register_operation(_Dialect)
class PackTransposeOp(_ods_ir.OpView):
  r"""
  Apply a transposition to a single `linalg.pack` (resp. `linalg.unpack`) and
  update the `linalg.generic` op that consumes (resp. produces) the operation.
  
  This transform allows composing a simple `structured.pack` with additional
  transpositions to e.g. match the data format required by a specific library
  call or ISA instruction.
  
  The transpose spec must specify at least one of `outer_perm` or `inner_perm`
  attributes, which will act upon the `outer_dims_perm` or `inner_dims_pos` of
  the specified `linalg.pack` or `linalg.unpack` op.
  
  If the `target` of this op is a `linalg.pack` then a new `tensor.empty` will
  be created along with transposed versions of the `linalg.pack` and the
  consuming `linalg.generic`, which is expected to be the sole consumer.
  
  If the `target` of this op is a `linalg.unpack` then the whole pack / compute
  / unpack chain will be transposed and transposed clones of `linalg.pack`,
  the consuming `linalg.generic` and the tail `linalg.pack` will be created.
  
  #### Return modes
  
  This operation targets a single `linalg.pack` / `linalg.unpack` op and a
  single matching `linalg.generic` that consumes / produces the op. Otherwise,
  it produces a silenceableFailure.
  
  This operation may produce a silenceableFailure if the transpose spec is
  ill-formed (i.e. `outer_perm` or `inner_perm` are not permutations of the
  proper rank) or if the transposition of all involved operations fails for any
  reason.
  
  This operation returns 3 handles, one to the transformed LinalgOp, one to
  the transformed `linalg.pack` and one to the transformed `linalg.unpack`.
  The last handle for `linalg.unpack` is empty if `target_pack_or_unpack_op`
  was not itself a `linalg.unpack`.
  """

  OPERATION_NAME = "transform.structured.pack_transpose"

  _ODS_REGIONS = (0, True)

  def __init__(self, packed_op: _ods_ir.Type, pack_op: _ods_ir.Type, un_pack_op: _ods_ir.Type, target_pack_or_un_pack_op: _ods_ir.Value, target_linalg_op: _ods_ir.Value, *, outer_perm: _Optional[_Union[_Sequence[int], _ods_ir.DenseI64ArrayAttr]] = None, inner_perm: _Optional[_Union[_Sequence[int], _ods_ir.DenseI64ArrayAttr]] = None, loc: _Optional[_ods_ir.Location] = None, ip: _Optional[_ods_ir.InsertionPoint] = None):
    operands = []
    attributes = {}
    regions = None
    operands.append(target_pack_or_un_pack_op)
    operands.append(target_linalg_op)
    _ods_context = _ods_get_default_loc_context(loc)
    if outer_perm is not None: attributes["outer_perm"] = (outer_perm if (
        isinstance(outer_perm, _ods_ir.Attribute) or
        not _ods_ir.AttrBuilder.contains('DenseI64ArrayAttr')) else
          _ods_ir.AttrBuilder.get('DenseI64ArrayAttr')(outer_perm, context=_ods_context))
    if inner_perm is not None: attributes["inner_perm"] = (inner_perm if (
        isinstance(inner_perm, _ods_ir.Attribute) or
        not _ods_ir.AttrBuilder.contains('DenseI64ArrayAttr')) else
          _ods_ir.AttrBuilder.get('DenseI64ArrayAttr')(inner_perm, context=_ods_context))
    results = []
    results.append(packed_op)
    results.append(pack_op)
    results.append(un_pack_op)
    _ods_successors = None
    super().__init__(self.OPERATION_NAME, self._ODS_REGIONS, self._ODS_OPERAND_SEGMENTS, self._ODS_RESULT_SEGMENTS, attributes=attributes, results=results, operands=operands, successors=_ods_successors, regions=regions, loc=loc, ip=ip)

  @builtins.property
  def target_pack_or_un_pack_op(self) -> _ods_ir.Value:
    return self.operation.operands[0]

  @builtins.property
  def target_linalg_op(self) -> _ods_ir.Value:
    return self.operation.operands[1]

  @builtins.property
  def outer_perm(self) -> _Optional[_ods_ir.DenseI64ArrayAttr]:
    if "outer_perm" not in self.operation.attributes:
      return None
    return self.operation.attributes["outer_perm"]

  @outer_perm.setter
  def outer_perm(self, value: _Optional[_ods_ir.DenseI64ArrayAttr]):
    if value is not None:
      self.operation.attributes["outer_perm"] = value
    elif "outer_perm" in self.operation.attributes:
      del self.operation.attributes["outer_perm"]

  @outer_perm.deleter
  def outer_perm(self):
    del self.operation.attributes["outer_perm"]

  @builtins.property
  def inner_perm(self) -> _Optional[_ods_ir.DenseI64ArrayAttr]:
    if "inner_perm" not in self.operation.attributes:
      return None
    return self.operation.attributes["inner_perm"]

  @inner_perm.setter
  def inner_perm(self, value: _Optional[_ods_ir.DenseI64ArrayAttr]):
    if value is not None:
      self.operation.attributes["inner_perm"] = value
    elif "inner_perm" in self.operation.attributes:
      del self.operation.attributes["inner_perm"]

  @inner_perm.deleter
  def inner_perm(self):
    del self.operation.attributes["inner_perm"]

  @builtins.property
  def packed_op(self) -> _ods_ir.OpResult:
    return self.operation.results[0]

  @builtins.property
  def pack_op(self) -> _ods_ir.OpResult:
    return self.operation.results[1]

  @builtins.property
  def un_pack_op(self) -> _ods_ir.OpResult:
    return self.operation.results[2]

@_ods_cext.register_op_adaptor(PackTransposeOp)
class PackTransposeOpAdaptor(_ods_ir.OpAdaptor):
  OPERATION_NAME = "transform.structured.pack_transpose"

  @builtins.property
  def target_pack_or_un_pack_op(self) -> _ods_ir.Value:
    return self.operands[0]

  @builtins.property
  def target_linalg_op(self) -> _ods_ir.Value:
    return self.operands[1]

  @builtins.property
  def outer_perm(self) -> _Optional[_ods_ir.DenseI64ArrayAttr]:
    if "outer_perm" not in self.attributes:
      return None
    return self.attributes["outer_perm"]

  @builtins.property
  def inner_perm(self) -> _Optional[_ods_ir.DenseI64ArrayAttr]:
    if "inner_perm" not in self.attributes:
      return None
    return self.attributes["inner_perm"]

def structured_pack_transpose(packed_op: _ods_ir.Type, pack_op: _ods_ir.Type, un_pack_op: _ods_ir.Type, target_pack_or_un_pack_op: _ods_ir.Value, target_linalg_op: _ods_ir.Value, *, outer_perm: _Optional[_Union[_Sequence[int], _ods_ir.DenseI64ArrayAttr]] = None, inner_perm: _Optional[_Union[_Sequence[int], _ods_ir.DenseI64ArrayAttr]] = None, loc: _Optional[_ods_ir.Location] = None, ip: _Optional[_ods_ir.InsertionPoint] = None) -> _ods_ir.OpResultList:
  return PackTransposeOp(packed_op=packed_op, pack_op=pack_op, un_pack_op=un_pack_op, target_pack_or_un_pack_op=target_pack_or_un_pack_op, target_linalg_op=target_linalg_op, outer_perm=outer_perm, inner_perm=inner_perm, loc=loc, ip=ip).results

@_ods_cext.register_operation(_Dialect)
class PadOp(_ods_ir.OpView):
  r"""
  Pads the operations pointed to by the target handle using the options
  provides as operation attributes. The operation returns a handle to the
  padded operation and to the padding operation ("tensor.pad").
  
  To preserve tensor SSA use-def chains, the unpadded result is copied back to
  the original destination tensor of the targeted op. The op that copies back
  the result can be customized with `copy_back_op`:
  
  * "bufferization.materialize_in_destination" (default)
  * "linalg.copy"
  * "none" (no copy back)
  
  #### Return modes
  
  This operation ignores non-Linalg ops and drops them in the return.
  This operation may produce a definite failure if the padding fails for any
  reason.
  
  If all the operations referred to by the `target` handle pad
  properly, the transform succeeds. Otherwise the transform produces a
  silenceable failure.
  The return handle points to only the subset of successfully produced
  padded operations, which can be empty.
  """

  OPERATION_NAME = "transform.structured.pad"

  _ODS_REGIONS = (0, True)

  def __init__(self, padded: _ods_ir.Type, pad: _ods_ir.Type, copy: _ods_ir.Type, target: _ods_ir.Value, pad_to_multiple_of: _Sequence[_ods_ir.Value], *, padding_values: _Optional[_Union[_Sequence[_ods_ir.Attribute], _ods_ir.ArrayAttr]] = None, padding_dimensions: _Optional[_Union[_Sequence[int], _ods_ir.ArrayAttr]] = None, static_pad_to_multiple_of: _Optional[_Union[_Sequence[int], _ods_ir.DenseI64ArrayAttr]] = None, nofold_flags: _Optional[_Union[_Sequence[int], _ods_ir.ArrayAttr]] = None, transpose_paddings: _Optional[_Union[_Any, _ods_ir.ArrayAttr]] = None, copy_back_op: _Optional[_Union[str, _ods_ir.StringAttr]] = None, use_prescribed_tensor_shapes: _Optional[bool] = None, loc: _Optional[_ods_ir.Location] = None, ip: _Optional[_ods_ir.InsertionPoint] = None):
    operands = []
    attributes = {}
    regions = None
    operands.append(target)
    operands.extend(_get_op_results_or_values(pad_to_multiple_of))
    _ods_context = _ods_get_default_loc_context(loc)
    if padding_values is not None: attributes["padding_values"] = (padding_values if (
        isinstance(padding_values, _ods_ir.Attribute) or
        not _ods_ir.AttrBuilder.contains('ArrayAttr')) else
          _ods_ir.AttrBuilder.get('ArrayAttr')(padding_values, context=_ods_context))
    if padding_dimensions is not None: attributes["padding_dimensions"] = (padding_dimensions if (
        isinstance(padding_dimensions, _ods_ir.Attribute) or
        not _ods_ir.AttrBuilder.contains('I64ArrayAttr')) else
          _ods_ir.AttrBuilder.get('I64ArrayAttr')(padding_dimensions, context=_ods_context))
    if static_pad_to_multiple_of is not None: attributes["static_pad_to_multiple_of"] = (static_pad_to_multiple_of if (
        isinstance(static_pad_to_multiple_of, _ods_ir.Attribute) or
        not _ods_ir.AttrBuilder.contains('DenseI64ArrayAttr')) else
          _ods_ir.AttrBuilder.get('DenseI64ArrayAttr')(static_pad_to_multiple_of, context=_ods_context))
    if nofold_flags is not None: attributes["nofold_flags"] = (nofold_flags if (
        isinstance(nofold_flags, _ods_ir.Attribute) or
        not _ods_ir.AttrBuilder.contains('I64ArrayAttr')) else
          _ods_ir.AttrBuilder.get('I64ArrayAttr')(nofold_flags, context=_ods_context))
    if transpose_paddings is not None: attributes["transpose_paddings"] = (transpose_paddings if (
        isinstance(transpose_paddings, _ods_ir.Attribute) or
        not _ods_ir.AttrBuilder.contains('anonymous_624')) else
          _ods_ir.AttrBuilder.get('anonymous_624')(transpose_paddings, context=_ods_context))
    if copy_back_op is not None: attributes["copy_back_op"] = (copy_back_op if (
        isinstance(copy_back_op, _ods_ir.Attribute) or
        not _ods_ir.AttrBuilder.contains('StrAttr')) else
          _ods_ir.AttrBuilder.get('StrAttr')(copy_back_op, context=_ods_context))
    if bool(use_prescribed_tensor_shapes): attributes["use_prescribed_tensor_shapes"] = _ods_ir.UnitAttr.get(
      _ods_get_default_loc_context(loc))
    results = []
    results.append(padded)
    results.append(pad)
    results.append(copy)
    _ods_successors = None
    super().__init__(self.OPERATION_NAME, self._ODS_REGIONS, self._ODS_OPERAND_SEGMENTS, self._ODS_RESULT_SEGMENTS, attributes=attributes, results=results, operands=operands, successors=_ods_successors, regions=regions, loc=loc, ip=ip)

  @builtins.property
  def target(self) -> _ods_ir.Value:
    return self.operation.operands[0]

  @builtins.property
  def pad_to_multiple_of(self) -> _ods_ir.OpOperandList:
    _ods_variadic_group_length = len(self.operation.operands) - 2 + 1
    return self.operation.operands[1:1 + _ods_variadic_group_length]

  @builtins.property
  def padding_values(self) -> _ods_ir.ArrayAttr:
    return self.operation.attributes["padding_values"]

  @padding_values.setter
  def padding_values(self, value: _ods_ir.ArrayAttr):
    if value is None:
      raise ValueError("'None' not allowed as value for mandatory attributes")
    self.operation.attributes["padding_values"] = value

  @builtins.property
  def padding_dimensions(self) -> _ods_ir.ArrayAttr:
    return self.operation.attributes["padding_dimensions"]

  @padding_dimensions.setter
  def padding_dimensions(self, value: _ods_ir.ArrayAttr):
    if value is None:
      raise ValueError("'None' not allowed as value for mandatory attributes")
    self.operation.attributes["padding_dimensions"] = value

  @builtins.property
  def static_pad_to_multiple_of(self) -> _Optional[_ods_ir.DenseI64ArrayAttr]:
    if "static_pad_to_multiple_of" not in self.operation.attributes:
      return None
    return self.operation.attributes["static_pad_to_multiple_of"]

  @static_pad_to_multiple_of.setter
  def static_pad_to_multiple_of(self, value: _Optional[_ods_ir.DenseI64ArrayAttr]):
    if value is not None:
      self.operation.attributes["static_pad_to_multiple_of"] = value
    elif "static_pad_to_multiple_of" in self.operation.attributes:
      del self.operation.attributes["static_pad_to_multiple_of"]

  @static_pad_to_multiple_of.deleter
  def static_pad_to_multiple_of(self):
    del self.operation.attributes["static_pad_to_multiple_of"]

  @builtins.property
  def nofold_flags(self) -> _ods_ir.ArrayAttr:
    return self.operation.attributes["nofold_flags"]

  @nofold_flags.setter
  def nofold_flags(self, value: _ods_ir.ArrayAttr):
    if value is None:
      raise ValueError("'None' not allowed as value for mandatory attributes")
    self.operation.attributes["nofold_flags"] = value

  @builtins.property
  def transpose_paddings(self) -> _ods_ir.ArrayAttr:
    return self.operation.attributes["transpose_paddings"]

  @transpose_paddings.setter
  def transpose_paddings(self, value: _ods_ir.ArrayAttr):
    if value is None:
      raise ValueError("'None' not allowed as value for mandatory attributes")
    self.operation.attributes["transpose_paddings"] = value

  @builtins.property
  def copy_back_op(self) -> _ods_ir.StringAttr:
    return self.operation.attributes["copy_back_op"]

  @copy_back_op.setter
  def copy_back_op(self, value: _ods_ir.StringAttr):
    if value is None:
      raise ValueError("'None' not allowed as value for mandatory attributes")
    self.operation.attributes["copy_back_op"] = value

  @builtins.property
  def use_prescribed_tensor_shapes(self) -> bool:
    return "use_prescribed_tensor_shapes" in self.operation.attributes

  @use_prescribed_tensor_shapes.setter
  def use_prescribed_tensor_shapes(self, value):
    if bool(value):
      self.operation.attributes["use_prescribed_tensor_shapes"] = _ods_ir.UnitAttr.get()
    elif "use_prescribed_tensor_shapes" in self.operation.attributes:
      del self.operation.attributes["use_prescribed_tensor_shapes"]

  @use_prescribed_tensor_shapes.deleter
  def use_prescribed_tensor_shapes(self):
    del self.operation.attributes["use_prescribed_tensor_shapes"]

  @builtins.property
  def padded(self) -> _ods_ir.OpResult:
    return self.operation.results[0]

  @builtins.property
  def pad(self) -> _ods_ir.OpResult:
    return self.operation.results[1]

  @builtins.property
  def copy(self) -> _ods_ir.OpResult:
    return self.operation.results[2]

@_ods_cext.register_op_adaptor(PadOp)
class PadOpAdaptor(_ods_ir.OpAdaptor):
  OPERATION_NAME = "transform.structured.pad"

  @builtins.property
  def target(self) -> _ods_ir.Value:
    return self.operands[0]

  @builtins.property
  def pad_to_multiple_of(self) -> _ods_ir.OpOperandList:
    _ods_variadic_group_length = len(self.operands) - 2 + 1
    return self.operands[1:1 + _ods_variadic_group_length]

  @builtins.property
  def padding_values(self) -> _ods_ir.ArrayAttr:
    return self.attributes["padding_values"]

  @builtins.property
  def padding_dimensions(self) -> _ods_ir.ArrayAttr:
    return self.attributes["padding_dimensions"]

  @builtins.property
  def static_pad_to_multiple_of(self) -> _Optional[_ods_ir.DenseI64ArrayAttr]:
    if "static_pad_to_multiple_of" not in self.attributes:
      return None
    return self.attributes["static_pad_to_multiple_of"]

  @builtins.property
  def nofold_flags(self) -> _ods_ir.ArrayAttr:
    return self.attributes["nofold_flags"]

  @builtins.property
  def transpose_paddings(self) -> _ods_ir.ArrayAttr:
    return self.attributes["transpose_paddings"]

  @builtins.property
  def copy_back_op(self) -> _ods_ir.StringAttr:
    return self.attributes["copy_back_op"]

  @builtins.property
  def use_prescribed_tensor_shapes(self) -> bool:
    return "use_prescribed_tensor_shapes" in self.attributes

def structured_pad(padded: _ods_ir.Type, pad: _ods_ir.Type, copy: _ods_ir.Type, target: _ods_ir.Value, pad_to_multiple_of: _Sequence[_ods_ir.Value], *, padding_values: _Optional[_Union[_Sequence[_ods_ir.Attribute], _ods_ir.ArrayAttr]] = None, padding_dimensions: _Optional[_Union[_Sequence[int], _ods_ir.ArrayAttr]] = None, static_pad_to_multiple_of: _Optional[_Union[_Sequence[int], _ods_ir.DenseI64ArrayAttr]] = None, nofold_flags: _Optional[_Union[_Sequence[int], _ods_ir.ArrayAttr]] = None, transpose_paddings: _Optional[_Union[_Any, _ods_ir.ArrayAttr]] = None, copy_back_op: _Optional[_Union[str, _ods_ir.StringAttr]] = None, use_prescribed_tensor_shapes: _Optional[bool] = None, loc: _Optional[_ods_ir.Location] = None, ip: _Optional[_ods_ir.InsertionPoint] = None) -> _ods_ir.OpResultList:
  return PadOp(padded=padded, pad=pad, copy=copy, target=target, pad_to_multiple_of=pad_to_multiple_of, padding_values=padding_values, padding_dimensions=padding_dimensions, static_pad_to_multiple_of=static_pad_to_multiple_of, nofold_flags=nofold_flags, transpose_paddings=transpose_paddings, copy_back_op=copy_back_op, use_prescribed_tensor_shapes=use_prescribed_tensor_shapes, loc=loc, ip=ip).results

@_ods_cext.register_operation(_Dialect)
class PadTilingInterfaceOp(_ods_ir.OpView):
  r"""
  Pads the **iteration domain** of the operations pointed to by the target
  handle using the options provided as operation attributes. Padding the
  iteration domain induces a padding of the operands that is consistent
  across the op semantics and, unlike for simple elementwise ops, may not be
  trivially deducible or specifiable on operands only (e.g. convolutions).
  Currently, only a limited set of projected permutation maps are supported.
  
  The specification of `padding_sizes` follows that of `tile_sizes` during
  tiling: the value "0" on a particular iterator encode "no padding". Like in
  the case of tiling, an automatic completion by 0 to the operation rank
  occurs.
  
  This transformation returns a handle to the padded operation and to the
  padding operation ("tensor.pad").
  
  TODO: in the future this should be moved out of a specific Linalg
  implementation file and into a more general "Structured" file.
  
  #### Return modes
  
  This operation ignores non-IndexingMapOpInterface ops and drops them in the
  return. In the future, this operation will support all TilingInterfaceOps
  for which the contract between iteration domain and operands can be 
  reified.    
  
  This operation may produce a definite failure if the padding fails for any
  reason.
  
  If all the operations referred to by the `target` handle pad properly, the
  transform succeeds. Otherwise the transform produces a silenceable failure.
  The return handle points to only the subset of successfully produced
  padded operations, which can be empty.
  """

  OPERATION_NAME = "transform.structured.pad_tiling_interface"

  _ODS_REGIONS = (0, True)

  def __init__(self, padded: _ods_ir.Type, pad: _ods_ir.Type, target: _ods_ir.Value, padding_sizes: _Sequence[_ods_ir.Value], *, padding_values: _Optional[_Union[_Sequence[_ods_ir.Attribute], _ods_ir.ArrayAttr]] = None, static_padding_sizes: _Optional[_Union[_Sequence[int], _ods_ir.DenseI64ArrayAttr]] = None, pad_to_multiple_of: _Optional[bool] = None, loc: _Optional[_ods_ir.Location] = None, ip: _Optional[_ods_ir.InsertionPoint] = None):
    operands = []
    attributes = {}
    regions = None
    operands.append(target)
    operands.extend(_get_op_results_or_values(padding_sizes))
    _ods_context = _ods_get_default_loc_context(loc)
    if padding_values is not None: attributes["padding_values"] = (padding_values if (
        isinstance(padding_values, _ods_ir.Attribute) or
        not _ods_ir.AttrBuilder.contains('ArrayAttr')) else
          _ods_ir.AttrBuilder.get('ArrayAttr')(padding_values, context=_ods_context))
    if static_padding_sizes is not None: attributes["static_padding_sizes"] = (static_padding_sizes if (
        isinstance(static_padding_sizes, _ods_ir.Attribute) or
        not _ods_ir.AttrBuilder.contains('DenseI64ArrayAttr')) else
          _ods_ir.AttrBuilder.get('DenseI64ArrayAttr')(static_padding_sizes, context=_ods_context))
    if bool(pad_to_multiple_of): attributes["pad_to_multiple_of"] = _ods_ir.UnitAttr.get(
      _ods_get_default_loc_context(loc))
    results = []
    results.append(padded)
    results.append(pad)
    _ods_successors = None
    super().__init__(self.OPERATION_NAME, self._ODS_REGIONS, self._ODS_OPERAND_SEGMENTS, self._ODS_RESULT_SEGMENTS, attributes=attributes, results=results, operands=operands, successors=_ods_successors, regions=regions, loc=loc, ip=ip)

  @builtins.property
  def target(self) -> _ods_ir.Value:
    return self.operation.operands[0]

  @builtins.property
  def padding_sizes(self) -> _ods_ir.OpOperandList:
    _ods_variadic_group_length = len(self.operation.operands) - 2 + 1
    return self.operation.operands[1:1 + _ods_variadic_group_length]

  @builtins.property
  def padding_values(self) -> _ods_ir.ArrayAttr:
    return self.operation.attributes["padding_values"]

  @padding_values.setter
  def padding_values(self, value: _ods_ir.ArrayAttr):
    if value is None:
      raise ValueError("'None' not allowed as value for mandatory attributes")
    self.operation.attributes["padding_values"] = value

  @builtins.property
  def static_padding_sizes(self) -> _Optional[_ods_ir.DenseI64ArrayAttr]:
    if "static_padding_sizes" not in self.operation.attributes:
      return None
    return self.operation.attributes["static_padding_sizes"]

  @static_padding_sizes.setter
  def static_padding_sizes(self, value: _Optional[_ods_ir.DenseI64ArrayAttr]):
    if value is not None:
      self.operation.attributes["static_padding_sizes"] = value
    elif "static_padding_sizes" in self.operation.attributes:
      del self.operation.attributes["static_padding_sizes"]

  @static_padding_sizes.deleter
  def static_padding_sizes(self):
    del self.operation.attributes["static_padding_sizes"]

  @builtins.property
  def pad_to_multiple_of(self) -> bool:
    return "pad_to_multiple_of" in self.operation.attributes

  @pad_to_multiple_of.setter
  def pad_to_multiple_of(self, value):
    if bool(value):
      self.operation.attributes["pad_to_multiple_of"] = _ods_ir.UnitAttr.get()
    elif "pad_to_multiple_of" in self.operation.attributes:
      del self.operation.attributes["pad_to_multiple_of"]

  @pad_to_multiple_of.deleter
  def pad_to_multiple_of(self):
    del self.operation.attributes["pad_to_multiple_of"]

  @builtins.property
  def padded(self) -> _ods_ir.OpResult:
    return self.operation.results[0]

  @builtins.property
  def pad(self) -> _ods_ir.OpResult:
    return self.operation.results[1]

@_ods_cext.register_op_adaptor(PadTilingInterfaceOp)
class PadTilingInterfaceOpAdaptor(_ods_ir.OpAdaptor):
  OPERATION_NAME = "transform.structured.pad_tiling_interface"

  @builtins.property
  def target(self) -> _ods_ir.Value:
    return self.operands[0]

  @builtins.property
  def padding_sizes(self) -> _ods_ir.OpOperandList:
    _ods_variadic_group_length = len(self.operands) - 2 + 1
    return self.operands[1:1 + _ods_variadic_group_length]

  @builtins.property
  def padding_values(self) -> _ods_ir.ArrayAttr:
    return self.attributes["padding_values"]

  @builtins.property
  def static_padding_sizes(self) -> _Optional[_ods_ir.DenseI64ArrayAttr]:
    if "static_padding_sizes" not in self.attributes:
      return None
    return self.attributes["static_padding_sizes"]

  @builtins.property
  def pad_to_multiple_of(self) -> bool:
    return "pad_to_multiple_of" in self.attributes

def structured_pad_tiling_interface(padded: _ods_ir.Type, pad: _ods_ir.Type, target: _ods_ir.Value, padding_sizes: _Sequence[_ods_ir.Value], *, padding_values: _Optional[_Union[_Sequence[_ods_ir.Attribute], _ods_ir.ArrayAttr]] = None, static_padding_sizes: _Optional[_Union[_Sequence[int], _ods_ir.DenseI64ArrayAttr]] = None, pad_to_multiple_of: _Optional[bool] = None, loc: _Optional[_ods_ir.Location] = None, ip: _Optional[_ods_ir.InsertionPoint] = None) -> _ods_ir.OpResultList:
  return PadTilingInterfaceOp(padded=padded, pad=pad, target=target, padding_sizes=padding_sizes, padding_values=padding_values, static_padding_sizes=static_padding_sizes, pad_to_multiple_of=pad_to_multiple_of, loc=loc, ip=ip).results

@_ods_cext.register_operation(_Dialect)
class PromoteOp(_ods_ir.OpView):
  r"""
  Promotes the specified operands of the target into a separate memory buffer.
  
  At this point, this transform does not allow customizing alloc/dealloc
  functions nor the behavior on copy in/out operations.
  
  #### Return modes
  
  This operation applies to a single Linalg op that satisfies the
  `promoteSubviewsPrecondition`, otherwise it fails.
  
  If the operations referred to by the `target` handle promote
  properly, the transform succeeds.
  
  When successful, the return handle points to the $target operation that
  was modified inplace.
  """

  OPERATION_NAME = "transform.structured.promote"

  _ODS_REGIONS = (0, True)

  def __init__(self, transformed: _ods_ir.Type, target: _ods_ir.Value, *, operands_to_promote: _Optional[_Union[_Sequence[int], _ods_ir.ArrayAttr]] = None, use_full_tile_buffers: _Optional[_Union[_Sequence[bool], _ods_ir.ArrayAttr]] = None, use_full_tiles_by_default: _Optional[bool] = None, use_original_subview_size: _Optional[bool] = None, use_alloca: _Optional[bool] = None, memory_space: _Optional[_Union[_Any, _ods_ir.Attribute]] = None, mapping: _Optional[_Union[_Any, _ods_ir.ArrayAttr]] = None, alignment: _Optional[_Union[int, _ods_ir.IntegerAttr]] = None, loc: _Optional[_ods_ir.Location] = None, ip: _Optional[_ods_ir.InsertionPoint] = None):
    operands = []
    attributes = {}
    regions = None
    operands.append(target)
    _ods_context = _ods_get_default_loc_context(loc)
    if operands_to_promote is not None: attributes["operands_to_promote"] = (operands_to_promote if (
        isinstance(operands_to_promote, _ods_ir.Attribute) or
        not _ods_ir.AttrBuilder.contains('I64ArrayAttr')) else
          _ods_ir.AttrBuilder.get('I64ArrayAttr')(operands_to_promote, context=_ods_context))
    if use_full_tile_buffers is not None: attributes["use_full_tile_buffers"] = (use_full_tile_buffers if (
        isinstance(use_full_tile_buffers, _ods_ir.Attribute) or
        not _ods_ir.AttrBuilder.contains('BoolArrayAttr')) else
          _ods_ir.AttrBuilder.get('BoolArrayAttr')(use_full_tile_buffers, context=_ods_context))
    if bool(use_full_tiles_by_default): attributes["use_full_tiles_by_default"] = _ods_ir.UnitAttr.get(
      _ods_get_default_loc_context(loc))
    if bool(use_original_subview_size): attributes["use_original_subview_size"] = _ods_ir.UnitAttr.get(
      _ods_get_default_loc_context(loc))
    if bool(use_alloca): attributes["use_alloca"] = _ods_ir.UnitAttr.get(
      _ods_get_default_loc_context(loc))
    if memory_space is not None: attributes["memory_space"] = (memory_space if (
        isinstance(memory_space, _ods_ir.Attribute) or
        not _ods_ir.AttrBuilder.contains('AnyAttr')) else
          _ods_ir.AttrBuilder.get('AnyAttr')(memory_space, context=_ods_context))
    if mapping is not None: attributes["mapping"] = (mapping if (
        isinstance(mapping, _ods_ir.Attribute) or
        not _ods_ir.AttrBuilder.contains('DeviceMappingArrayAttr')) else
          _ods_ir.AttrBuilder.get('DeviceMappingArrayAttr')(mapping, context=_ods_context))
    if alignment is not None: attributes["alignment"] = (alignment if (
        isinstance(alignment, _ods_ir.Attribute) or
        not _ods_ir.AttrBuilder.contains('I64Attr')) else
          _ods_ir.AttrBuilder.get('I64Attr')(alignment, context=_ods_context))
    results = []
    results.append(transformed)
    _ods_successors = None
    super().__init__(self.OPERATION_NAME, self._ODS_REGIONS, self._ODS_OPERAND_SEGMENTS, self._ODS_RESULT_SEGMENTS, attributes=attributes, results=results, operands=operands, successors=_ods_successors, regions=regions, loc=loc, ip=ip)

  @builtins.property
  def target(self) -> _ods_ir.Value:
    return self.operation.operands[0]

  @builtins.property
  def operands_to_promote(self) -> _ods_ir.ArrayAttr:
    return self.operation.attributes["operands_to_promote"]

  @operands_to_promote.setter
  def operands_to_promote(self, value: _ods_ir.ArrayAttr):
    if value is None:
      raise ValueError("'None' not allowed as value for mandatory attributes")
    self.operation.attributes["operands_to_promote"] = value

  @builtins.property
  def use_full_tile_buffers(self) -> _ods_ir.ArrayAttr:
    return self.operation.attributes["use_full_tile_buffers"]

  @use_full_tile_buffers.setter
  def use_full_tile_buffers(self, value: _ods_ir.ArrayAttr):
    if value is None:
      raise ValueError("'None' not allowed as value for mandatory attributes")
    self.operation.attributes["use_full_tile_buffers"] = value

  @builtins.property
  def use_full_tiles_by_default(self) -> bool:
    return "use_full_tiles_by_default" in self.operation.attributes

  @use_full_tiles_by_default.setter
  def use_full_tiles_by_default(self, value):
    if bool(value):
      self.operation.attributes["use_full_tiles_by_default"] = _ods_ir.UnitAttr.get()
    elif "use_full_tiles_by_default" in self.operation.attributes:
      del self.operation.attributes["use_full_tiles_by_default"]

  @use_full_tiles_by_default.deleter
  def use_full_tiles_by_default(self):
    del self.operation.attributes["use_full_tiles_by_default"]

  @builtins.property
  def use_original_subview_size(self) -> bool:
    return "use_original_subview_size" in self.operation.attributes

  @use_original_subview_size.setter
  def use_original_subview_size(self, value):
    if bool(value):
      self.operation.attributes["use_original_subview_size"] = _ods_ir.UnitAttr.get()
    elif "use_original_subview_size" in self.operation.attributes:
      del self.operation.attributes["use_original_subview_size"]

  @use_original_subview_size.deleter
  def use_original_subview_size(self):
    del self.operation.attributes["use_original_subview_size"]

  @builtins.property
  def use_alloca(self) -> bool:
    return "use_alloca" in self.operation.attributes

  @use_alloca.setter
  def use_alloca(self, value):
    if bool(value):
      self.operation.attributes["use_alloca"] = _ods_ir.UnitAttr.get()
    elif "use_alloca" in self.operation.attributes:
      del self.operation.attributes["use_alloca"]

  @use_alloca.deleter
  def use_alloca(self):
    del self.operation.attributes["use_alloca"]

  @builtins.property
  def memory_space(self) -> _Optional[_ods_ir.Attribute]:
    if "memory_space" not in self.operation.attributes:
      return None
    return self.operation.attributes["memory_space"]

  @memory_space.setter
  def memory_space(self, value: _Optional[_ods_ir.Attribute]):
    if value is not None:
      self.operation.attributes["memory_space"] = value
    elif "memory_space" in self.operation.attributes:
      del self.operation.attributes["memory_space"]

  @memory_space.deleter
  def memory_space(self):
    del self.operation.attributes["memory_space"]

  @builtins.property
  def mapping(self) -> _Optional[_ods_ir.ArrayAttr]:
    if "mapping" not in self.operation.attributes:
      return None
    return self.operation.attributes["mapping"]

  @mapping.setter
  def mapping(self, value: _Optional[_ods_ir.ArrayAttr]):
    if value is not None:
      self.operation.attributes["mapping"] = value
    elif "mapping" in self.operation.attributes:
      del self.operation.attributes["mapping"]

  @mapping.deleter
  def mapping(self):
    del self.operation.attributes["mapping"]

  @builtins.property
  def alignment(self) -> _Optional[_ods_ir.IntegerAttr]:
    if "alignment" not in self.operation.attributes:
      return None
    return self.operation.attributes["alignment"]

  @alignment.setter
  def alignment(self, value: _Optional[_ods_ir.IntegerAttr]):
    if value is not None:
      self.operation.attributes["alignment"] = value
    elif "alignment" in self.operation.attributes:
      del self.operation.attributes["alignment"]

  @alignment.deleter
  def alignment(self):
    del self.operation.attributes["alignment"]

  @builtins.property
  def transformed(self) -> _ods_ir.OpResult:
    return self.operation.results[0]

@_ods_cext.register_op_adaptor(PromoteOp)
class PromoteOpAdaptor(_ods_ir.OpAdaptor):
  OPERATION_NAME = "transform.structured.promote"

  @builtins.property
  def target(self) -> _ods_ir.Value:
    return self.operands[0]

  @builtins.property
  def operands_to_promote(self) -> _ods_ir.ArrayAttr:
    return self.attributes["operands_to_promote"]

  @builtins.property
  def use_full_tile_buffers(self) -> _ods_ir.ArrayAttr:
    return self.attributes["use_full_tile_buffers"]

  @builtins.property
  def use_full_tiles_by_default(self) -> bool:
    return "use_full_tiles_by_default" in self.attributes

  @builtins.property
  def use_original_subview_size(self) -> bool:
    return "use_original_subview_size" in self.attributes

  @builtins.property
  def use_alloca(self) -> bool:
    return "use_alloca" in self.attributes

  @builtins.property
  def memory_space(self) -> _Optional[_ods_ir.Attribute]:
    if "memory_space" not in self.attributes:
      return None
    return self.attributes["memory_space"]

  @builtins.property
  def mapping(self) -> _Optional[_ods_ir.ArrayAttr]:
    if "mapping" not in self.attributes:
      return None
    return self.attributes["mapping"]

  @builtins.property
  def alignment(self) -> _Optional[_ods_ir.IntegerAttr]:
    if "alignment" not in self.attributes:
      return None
    return self.attributes["alignment"]

def structured_promote(transformed: _ods_ir.Type, target: _ods_ir.Value, *, operands_to_promote: _Optional[_Union[_Sequence[int], _ods_ir.ArrayAttr]] = None, use_full_tile_buffers: _Optional[_Union[_Sequence[bool], _ods_ir.ArrayAttr]] = None, use_full_tiles_by_default: _Optional[bool] = None, use_original_subview_size: _Optional[bool] = None, use_alloca: _Optional[bool] = None, memory_space: _Optional[_Union[_Any, _ods_ir.Attribute]] = None, mapping: _Optional[_Union[_Any, _ods_ir.ArrayAttr]] = None, alignment: _Optional[_Union[int, _ods_ir.IntegerAttr]] = None, loc: _Optional[_ods_ir.Location] = None, ip: _Optional[_ods_ir.InsertionPoint] = None) -> _ods_ir.OpResult:
  return PromoteOp(transformed=transformed, target=target, operands_to_promote=operands_to_promote, use_full_tile_buffers=use_full_tile_buffers, use_full_tiles_by_default=use_full_tiles_by_default, use_original_subview_size=use_original_subview_size, use_alloca=use_alloca, memory_space=memory_space, mapping=mapping, alignment=alignment, loc=loc, ip=ip).result

@_ods_cext.register_operation(_Dialect)
class PromoteTensorOp(_ods_ir.OpView):
  r"""
  Requests that a tensor value lives in a specific memory space for its
  lifetime. This is achieved by allocating a new tensor in the desired
  memory space with `bufferization.alloc_tensor` and optionally materializing
  the source value into that allocation with
  `bufferization.materialize_in_destination`. All uses of the original value
  are then redirected to the promoted value.
  
  The generated code for promoting tensor value %0 resembles the following:
  
    %1 = bufferization.alloc_tensor(<dynamic dims of %0>)
         { memory_space = memory_space }
    // Note: the materialization is omitted if %0 is never read and is only
    // written into (i.e., it behaves as a result tensor).
    %2 = bufferization.materialize_in_destination %0 in %1
    // ...
    <all users of %0 now use %2 instead>
  
  Deallocation is not handled by this transform.
  
  Return modes:
  - Produces a silenceable failure if the given handle does not point to
    tensor-typed values.
  - Succeeds otherwise and returns a handle to the promoted value(s), i.e.,
    the result of materialization if present and the allocation otherwise.
  """

  OPERATION_NAME = "transform.structured.promote_tensor"

  _ODS_REGIONS = (0, True)

  def __init__(self, tensor: _ods_ir.Value, *, memory_space: _Optional[_Union[_Any, _ods_ir.Attribute]] = None, results: _Optional[_Sequence[_ods_ir.Type]] = None, loc: _Optional[_ods_ir.Location] = None, ip: _Optional[_ods_ir.InsertionPoint] = None):
    operands = []
    attributes = {}
    regions = None
    operands.append(tensor)
    _ods_context = _ods_get_default_loc_context(loc)
    if memory_space is not None: attributes["memory_space"] = (memory_space if (
        isinstance(memory_space, _ods_ir.Attribute) or
        not _ods_ir.AttrBuilder.contains('AnyAttr')) else
          _ods_ir.AttrBuilder.get('AnyAttr')(memory_space, context=_ods_context))
    if results is None: results = [operands[0].type] * 1
    _ods_successors = None
    super().__init__(self.OPERATION_NAME, self._ODS_REGIONS, self._ODS_OPERAND_SEGMENTS, self._ODS_RESULT_SEGMENTS, attributes=attributes, results=results, operands=operands, successors=_ods_successors, regions=regions, loc=loc, ip=ip)

  @builtins.property
  def tensor(self) -> _ods_ir.Value:
    return self.operation.operands[0]

  @builtins.property
  def memory_space(self) -> _Optional[_ods_ir.Attribute]:
    if "memory_space" not in self.operation.attributes:
      return None
    return self.operation.attributes["memory_space"]

  @memory_space.setter
  def memory_space(self, value: _Optional[_ods_ir.Attribute]):
    if value is not None:
      self.operation.attributes["memory_space"] = value
    elif "memory_space" in self.operation.attributes:
      del self.operation.attributes["memory_space"]

  @memory_space.deleter
  def memory_space(self):
    del self.operation.attributes["memory_space"]

  @builtins.property
  def promoted(self) -> _ods_ir.OpResult:
    return self.operation.results[0]

@_ods_cext.register_op_adaptor(PromoteTensorOp)
class PromoteTensorOpAdaptor(_ods_ir.OpAdaptor):
  OPERATION_NAME = "transform.structured.promote_tensor"

  @builtins.property
  def tensor(self) -> _ods_ir.Value:
    return self.operands[0]

  @builtins.property
  def memory_space(self) -> _Optional[_ods_ir.Attribute]:
    if "memory_space" not in self.attributes:
      return None
    return self.attributes["memory_space"]

def structured_promote_tensor(tensor: _ods_ir.Value, *, memory_space: _Optional[_Union[_Any, _ods_ir.Attribute]] = None, results: _Optional[_Sequence[_ods_ir.Type]] = None, loc: _Optional[_ods_ir.Location] = None, ip: _Optional[_ods_ir.InsertionPoint] = None) -> _ods_ir.OpResult:
  return PromoteTensorOp(tensor=tensor, memory_space=memory_space, results=results, loc=loc, ip=ip).result

@_ods_cext.register_operation(_Dialect)
class ReplaceOp(_ods_ir.OpView):
  r"""
  Replace all `target` payload ops with the single op that is contained in
  this op's region. All targets must have zero arguments and must be isolated
  from above.
  
  This op is for debugging/experiments only.
  
  #### Return modes
  
  This operation consumes the `target` handle.
  """

  OPERATION_NAME = "transform.structured.replace"

  _ODS_REGIONS = (1, True)

  def __init__(self, replacement: _ods_ir.Type, target: _ods_ir.Value, *, loc: _Optional[_ods_ir.Location] = None, ip: _Optional[_ods_ir.InsertionPoint] = None):
    operands = []
    attributes = {}
    regions = None
    operands.append(target)
    _ods_context = _ods_get_default_loc_context(loc)
    results = []
    results.append(replacement)
    _ods_successors = None
    super().__init__(self.OPERATION_NAME, self._ODS_REGIONS, self._ODS_OPERAND_SEGMENTS, self._ODS_RESULT_SEGMENTS, attributes=attributes, results=results, operands=operands, successors=_ods_successors, regions=regions, loc=loc, ip=ip)

  @builtins.property
  def target(self) -> _ods_ir.Value:
    return self.operation.operands[0]

  @builtins.property
  def replacement(self) -> _ods_ir.OpResult:
    return self.operation.results[0]

  @builtins.property
  def bodyRegion(self) -> _ods_ir.Region:
    return self.regions[0]

@_ods_cext.register_op_adaptor(ReplaceOp)
class ReplaceOpAdaptor(_ods_ir.OpAdaptor):
  OPERATION_NAME = "transform.structured.replace"

  @builtins.property
  def target(self) -> _ods_ir.Value:
    return self.operands[0]

def structured_replace(replacement: _ods_ir.Type, target: _ods_ir.Value, *, loc: _Optional[_ods_ir.Location] = None, ip: _Optional[_ods_ir.InsertionPoint] = None) -> _ods_ir.OpResult:
  return ReplaceOp(replacement=replacement, target=target, loc=loc, ip=ip).result

@_ods_cext.register_operation(_Dialect)
class RewriteInDestinationPassingStyleOp(_ods_ir.OpView):
  r"""
  Rewrite a supported tensor operation that is not in destination-passing style
  into a form that is in destination-passing style.
  Currently supported operations are:
    - tensor.pad
    - tensor.generate
    - tensor.from_elements
  This dichotomy hints at a future interface, for now the implementation just
  switches between different implementation.
  
  #### Return modes
  
  This operation ignores non-unsupported ops and drops them from the return.
  If all the operations referred to by the `target` handle generalize
  properly, the transform succeeds. Otherwise the transform produces a
  silenceable failure.
  The return handle points to a subset of successfully produced operations:
    - `tensor.pad` case, the returned handle points to the tensor.insert_slice.
    - `tensor.generate` case, the returned handle points to the linalg.generic.
    - `tensor.from_elements` case, the returned handle points to the last
      `tensor.insert`.
  """

  OPERATION_NAME = "transform.structured.rewrite_in_destination_passing_style"

  _ODS_REGIONS = (0, True)

  def __init__(self, transformed: _ods_ir.Type, target: _ods_ir.Value, *, loc: _Optional[_ods_ir.Location] = None, ip: _Optional[_ods_ir.InsertionPoint] = None):
    operands = []
    attributes = {}
    regions = None
    operands.append(target)
    _ods_context = _ods_get_default_loc_context(loc)
    results = []
    results.append(transformed)
    _ods_successors = None
    super().__init__(self.OPERATION_NAME, self._ODS_REGIONS, self._ODS_OPERAND_SEGMENTS, self._ODS_RESULT_SEGMENTS, attributes=attributes, results=results, operands=operands, successors=_ods_successors, regions=regions, loc=loc, ip=ip)

  @builtins.property
  def target(self) -> _ods_ir.Value:
    return self.operation.operands[0]

  @builtins.property
  def transformed(self) -> _ods_ir.OpResult:
    return self.operation.results[0]

@_ods_cext.register_op_adaptor(RewriteInDestinationPassingStyleOp)
class RewriteInDestinationPassingStyleOpAdaptor(_ods_ir.OpAdaptor):
  OPERATION_NAME = "transform.structured.rewrite_in_destination_passing_style"

  @builtins.property
  def target(self) -> _ods_ir.Value:
    return self.operands[0]

def structured_rewrite_in_destination_passing_style(transformed: _ods_ir.Type, target: _ods_ir.Value, *, loc: _Optional[_ods_ir.Location] = None, ip: _Optional[_ods_ir.InsertionPoint] = None) -> _ods_ir.OpResult:
  return RewriteInDestinationPassingStyleOp(transformed=transformed, target=target, loc=loc, ip=ip).result

@_ods_cext.register_operation(_Dialect)
class ScalarizeOp(_ods_ir.OpView):
  r"""
  Indicates that ops of a specific kind in the given function should be
  scalarized (i.e. their dynamic dimensions tiled by 1).
  
  #### Return modes:
  
  This operation ignores non-Linalg ops and drops them in the return.
  This operation produces definite failure if the scalarization fails for any
  reason.
  If all the operations referred to by the `target` handle scalarize
  properly, the transform succeeds. Otherwise the transform produces a
  silenceable failure.
  
  The return handle points to only the subset of successfully produced
  tiled-by-1 operations, which can be empty.
  
  This operation does not return handles to the tiled loop.
  We make this design choice because it is hard to know ahead of time the
  number of loops that will be produced (it depends on the number of dynamic
  dimensions after multiple transformations have been applied).
  Loops can always be recovered by navigating from the tiled operations if
  needed.
  """

  OPERATION_NAME = "transform.structured.scalarize"

  _ODS_REGIONS = (0, True)

  def __init__(self, result: _ods_ir.Type, target: _ods_ir.Value, *, loc: _Optional[_ods_ir.Location] = None, ip: _Optional[_ods_ir.InsertionPoint] = None):
    operands = []
    attributes = {}
    regions = None
    operands.append(target)
    _ods_context = _ods_get_default_loc_context(loc)
    results = []
    results.append(result)
    _ods_successors = None
    super().__init__(self.OPERATION_NAME, self._ODS_REGIONS, self._ODS_OPERAND_SEGMENTS, self._ODS_RESULT_SEGMENTS, attributes=attributes, results=results, operands=operands, successors=_ods_successors, regions=regions, loc=loc, ip=ip)

  @builtins.property
  def target(self) -> _ods_ir.Value:
    return self.operation.operands[0]

  @builtins.property
  def result(self) -> _ods_ir.OpResult:
    return self.operation.results[0]

@_ods_cext.register_op_adaptor(ScalarizeOp)
class ScalarizeOpAdaptor(_ods_ir.OpAdaptor):
  OPERATION_NAME = "transform.structured.scalarize"

  @builtins.property
  def target(self) -> _ods_ir.Value:
    return self.operands[0]

def structured_scalarize(result: _ods_ir.Type, target: _ods_ir.Value, *, loc: _Optional[_ods_ir.Location] = None, ip: _Optional[_ods_ir.InsertionPoint] = None) -> _ods_ir.OpResult:
  return ScalarizeOp(result=result, target=target, loc=loc, ip=ip).result

@_ods_cext.register_operation(_Dialect)
class SpecializeOp(_ods_ir.OpView):
  r"""
  Transforms a generic operation into the equivalent named or category form.
  
  By default, operations are specialized into named forms.
  
  #### Return modes
  
  This operation ignores non-Linalg ops and drops them in the return. If all
  the operations referred to by the `target` handle specialize, the transform
  succeeds; otherwise, the operation produces a silenceable failure. The return
  handle points to only the subset of successfully produced equivalent specialized
  operations, which can be empty or contain the original ops if they were already
  in the target form.
  """

  OPERATION_NAME = "transform.structured.specialize"

  _ODS_REGIONS = (0, True)

  def __init__(self, transformed: _ods_ir.Type, target: _ods_ir.Value, *, emit_category: _Optional[_Union[bool, _ods_ir.BoolAttr]] = None, loc: _Optional[_ods_ir.Location] = None, ip: _Optional[_ods_ir.InsertionPoint] = None):
    operands = []
    attributes = {}
    regions = None
    operands.append(target)
    _ods_context = _ods_get_default_loc_context(loc)
    if emit_category is not None: attributes["emit_category"] = (emit_category if (
        isinstance(emit_category, _ods_ir.Attribute) or
        not _ods_ir.AttrBuilder.contains('BoolAttr')) else
          _ods_ir.AttrBuilder.get('BoolAttr')(emit_category, context=_ods_context))
    results = []
    results.append(transformed)
    _ods_successors = None
    super().__init__(self.OPERATION_NAME, self._ODS_REGIONS, self._ODS_OPERAND_SEGMENTS, self._ODS_RESULT_SEGMENTS, attributes=attributes, results=results, operands=operands, successors=_ods_successors, regions=regions, loc=loc, ip=ip)

  @builtins.property
  def target(self) -> _ods_ir.Value:
    return self.operation.operands[0]

  @builtins.property
  def emit_category(self) -> _ods_ir.BoolAttr:
    return self.operation.attributes["emit_category"]

  @emit_category.setter
  def emit_category(self, value: _ods_ir.BoolAttr):
    if value is None:
      raise ValueError("'None' not allowed as value for mandatory attributes")
    self.operation.attributes["emit_category"] = value

  @builtins.property
  def transformed(self) -> _ods_ir.OpResult:
    return self.operation.results[0]

@_ods_cext.register_op_adaptor(SpecializeOp)
class SpecializeOpAdaptor(_ods_ir.OpAdaptor):
  OPERATION_NAME = "transform.structured.specialize"

  @builtins.property
  def target(self) -> _ods_ir.Value:
    return self.operands[0]

  @builtins.property
  def emit_category(self) -> _ods_ir.BoolAttr:
    return self.attributes["emit_category"]

def structured_specialize(transformed: _ods_ir.Type, target: _ods_ir.Value, *, emit_category: _Optional[_Union[bool, _ods_ir.BoolAttr]] = None, loc: _Optional[_ods_ir.Location] = None, ip: _Optional[_ods_ir.InsertionPoint] = None) -> _ods_ir.OpResult:
  return SpecializeOp(transformed=transformed, target=target, emit_category=emit_category, loc=loc, ip=ip).result

@_ods_cext.register_operation(_Dialect)
class SplitOp(_ods_ir.OpView):
  r"""
  Splits the given `target` op into two or more complementary
  parts, which combined cover the entire iteration domain of the original op.
  The split is performed along the iteration space dimension provided as
  chunk size attribute specifying the size of the lower part; the remaining
  range in the iteration space is assigned as the upper part. In case of
  dimension overflow, the transformation fails. The split is performed at the
  dimension iterator value specified as either the static chunk size
  attribute when it is known at transform IR construction time or
  as the handle to an operation producing a single index-typed value
  when it is computed by payload IR. In the latter case, the chunk size
  point must be set to `ShapedType::kDynamic` and the dynamic size handle
  must point to as many value-producing operations as there are structured
  operations pointed to by the target handle.
  
  The operation consumes the target handle, but preserves the chunk size
  handle if provided. Without the `multiway` attribute, it produces a
  new handle that is a list of the two parts of the structured op after
  splitting, whose lower index part corresponding to the part with lower
  iteration space indices.
  
  Multiway split mode is enabled by specifying the `multiway` attribute.
  In this mode a single `target` op is split into multiple parts covering
  the iteration space of the specified dimension. `static_chunk_sizes` and
  `dynamic_chunk_sizes` in this case is a list of chunk sizes that the given
  dimension should be split into. With `multiway` it also produces a handle;
  The result handle is a list of the multiple parts of the structured op
  after splitting, where the target dimensions for each linalg op in the
  list corresponds to the chunk sizes specfied in the input split list.
  If the chunk sizes do not cover the entire iteration space, the leftover
  chunk is the last payload in the result handle.
  
  As the result handle is most of time a list, an `transform.split_handle`
  is needed to access individual handle.
  """

  OPERATION_NAME = "transform.structured.split"

  _ODS_REGIONS = (0, True)

  def __init__(self, split_list: _ods_ir.Type, target: _ods_ir.Value, dimension: _Union[int, _ods_ir.IntegerAttr], static_chunk_sizes: _Union[int, _ods_ir.IntegerAttr], *, dynamic_chunk_sizes: _Optional[_ods_ir.Value] = None, multiway: _Optional[bool] = None, loc: _Optional[_ods_ir.Location] = None, ip: _Optional[_ods_ir.InsertionPoint] = None):
    operands = []
    attributes = {}
    regions = None
    operands.append(target)
    if dynamic_chunk_sizes is not None: operands.append(dynamic_chunk_sizes)
    _ods_context = _ods_get_default_loc_context(loc)
    attributes["dimension"] = (dimension if (
    isinstance(dimension, _ods_ir.Attribute) or
    not _ods_ir.AttrBuilder.contains('I64Attr')) else
      _ods_ir.AttrBuilder.get('I64Attr')(dimension, context=_ods_context))
    attributes["static_chunk_sizes"] = (static_chunk_sizes if (
    isinstance(static_chunk_sizes, _ods_ir.Attribute) or
    not _ods_ir.AttrBuilder.contains('I64Attr')) else
      _ods_ir.AttrBuilder.get('I64Attr')(static_chunk_sizes, context=_ods_context))
    if bool(multiway): attributes["multiway"] = _ods_ir.UnitAttr.get(
      _ods_get_default_loc_context(loc))
    results = []
    results.append(split_list)
    _ods_successors = None
    super().__init__(self.OPERATION_NAME, self._ODS_REGIONS, self._ODS_OPERAND_SEGMENTS, self._ODS_RESULT_SEGMENTS, attributes=attributes, results=results, operands=operands, successors=_ods_successors, regions=regions, loc=loc, ip=ip)

  @builtins.property
  def target(self) -> _ods_ir.Value:
    return self.operation.operands[0]

  @builtins.property
  def dynamic_chunk_sizes(self) -> _Optional[_ods_ir.Value]:
    return None if len(self.operation.operands) < 2 else self.operation.operands[1]

  @builtins.property
  def dimension(self) -> _ods_ir.IntegerAttr:
    return self.operation.attributes["dimension"]

  @dimension.setter
  def dimension(self, value: _ods_ir.IntegerAttr):
    if value is None:
      raise ValueError("'None' not allowed as value for mandatory attributes")
    self.operation.attributes["dimension"] = value

  @builtins.property
  def static_chunk_sizes(self) -> _ods_ir.IntegerAttr:
    return self.operation.attributes["static_chunk_sizes"]

  @static_chunk_sizes.setter
  def static_chunk_sizes(self, value: _ods_ir.IntegerAttr):
    if value is None:
      raise ValueError("'None' not allowed as value for mandatory attributes")
    self.operation.attributes["static_chunk_sizes"] = value

  @builtins.property
  def multiway(self) -> bool:
    return "multiway" in self.operation.attributes

  @multiway.setter
  def multiway(self, value):
    if bool(value):
      self.operation.attributes["multiway"] = _ods_ir.UnitAttr.get()
    elif "multiway" in self.operation.attributes:
      del self.operation.attributes["multiway"]

  @multiway.deleter
  def multiway(self):
    del self.operation.attributes["multiway"]

  @builtins.property
  def split_list(self) -> _ods_ir.OpResult:
    return self.operation.results[0]

@_ods_cext.register_op_adaptor(SplitOp)
class SplitOpAdaptor(_ods_ir.OpAdaptor):
  OPERATION_NAME = "transform.structured.split"

  @builtins.property
  def target(self) -> _ods_ir.Value:
    return self.operands[0]

  @builtins.property
  def dynamic_chunk_sizes(self) -> _Optional[_ods_ir.Value]:
    return None if len(self.operands) < 2 else self.operands[1]

  @builtins.property
  def dimension(self) -> _ods_ir.IntegerAttr:
    return self.attributes["dimension"]

  @builtins.property
  def static_chunk_sizes(self) -> _ods_ir.IntegerAttr:
    return self.attributes["static_chunk_sizes"]

  @builtins.property
  def multiway(self) -> bool:
    return "multiway" in self.attributes

def structured_split(split_list: _ods_ir.Type, target: _ods_ir.Value, dimension: _Union[int, _ods_ir.IntegerAttr], static_chunk_sizes: _Union[int, _ods_ir.IntegerAttr], *, dynamic_chunk_sizes: _Optional[_ods_ir.Value] = None, multiway: _Optional[bool] = None, loc: _Optional[_ods_ir.Location] = None, ip: _Optional[_ods_ir.InsertionPoint] = None) -> _ods_ir.OpResult:
  return SplitOp(split_list=split_list, target=target, dimension=dimension, static_chunk_sizes=static_chunk_sizes, dynamic_chunk_sizes=dynamic_chunk_sizes, multiway=multiway, loc=loc, ip=ip).result

@_ods_cext.register_operation(_Dialect)
class SplitReductionOp(_ods_ir.OpView):
  r"""
  Indicates that the given `target` op should be transformed with the
  `splitReduction` transformation and split factor provided as attribute.
  
  The `splitReduction` transformation splits the first single linalg op
  reduction into a parallel and reduction dimension.
  A new `linalg.generic` op is created to perform the rest of the reduction.
  
  The transformation supports different configurations attributes:
    - split_factor: the factor by which to split (i.e. the size of the
      remaining reduction after splitting).
    - insert_split_dimension: the dimension in the temporary tensor into
      which the new parallel dimension is inserted.
    - inner_parallel: specifies whether the parallel dimension is before or
      after the reduction dimension in the splitting op.
    - use_scaling_algorithm: whether to use a scaling based formulation that
      does not create an ExpandShapeOp (default: do not use scaling)
    - use_alloc: whether to use an alloc op to allocate the temporary
      tensor (default: do not use alloc op)
  
  #### Return modes
  
  This operation ignores non-Linalg ops and drops them in the return.
  This operation produces a definite failure if the splitting fails for any
  reason.
  
  If all the operations referred to by the `target` handle split
  properly, the transform succeeds. Otherwise the transform produces a
  silenceable failure.  The 4 returned handles points to only the subset of
  successfully produced computational operations, which can all be empty.
  This 4 returned handles point to:
    - the init op (or tensor_alloc op if use_alloc = true),
    - the fill op used to initialize the neutral element,
    - the split op and
    - the result-combining op.
  
  #### Example (default: `use_scaling_algorithm = false, use_alloc = false`):
  
  ```
    %r = linalg.generic {indexing_maps = [affine_map<(d0) -> (d0)>,
                                          affine_map<(d0) -> ()>],
          iterator_types = ["reduction"]}
    ins(%in : tensor<32xf32>)
    outs(%out : tensor<f32>) {
    ^bb0(%arg1: f32, %arg2: f32):
      %y = arith.addf %arg1, %arg2 : f32
      linalg.yield %y : f32
    } -> tensor<f32>
  ```
  
  is split into:
  
  ```
    %cst = arith.constant 0.000000e+00 : f32
    %0 = tensor.expand_shape %in [[0, 1]] : tensor<32xf32> into tensor<4x8xf32>
    %1 = tensor.empty() : tensor<4xf32>
    %2 = linalg.fill ins(%cst : f32) outs(%1 : tensor<4xf32>) -> tensor<4xf32>
    %3 = linalg.generic {indexing_maps = [affine_map<(d0, d1) -> (d0, d1)>,
                                          affine_map<(d0, d1) -> (d0)>],
      iterator_types = ["parallel", "reduction"]}
      ins(%0 : tensor<4x8xf32>) outs(%2 : tensor<4xf32>) {
      ^bb0(%arg3: f32, %arg5: f32):
      %5 = arith.addf %arg3, %arg4 : f32
      linalg.yield %5 : f32
    } -> tensor<4xf32>
    %r = linalg.generic {indexing_maps = [affine_map<(d0) -> (d0)>,
                                          affine_map<(d0) -> ()>],
      iterator_types = ["reduction"]}
      ins(%3 : tensor<4xf32>) outs(%out : tensor<f32>) {
      ^bb0(%arg3: f32, %arg4: f32):
      %5 = arith.addf %arg3, %arg4 : f32
      linalg.yield %5 : f32
    } -> tensor<f32>
  ```
  
  #### Example (`use_scaling_algorithm = true, use_alloc = true`):
  
  Instead of introducing an ExpandShapeOp, this scaling-based implementation
  rewrites a reduction dimension `k` into `k * split_factor + kk`.
  The dimension `kk` is added as an extra parallel dimension to the
  intermediate output tensor at position `insert_split_dimension`.
  
  Consider a minimal example where `k` is reduced:
      O(i, j) += I(i, j, k)
  Assume i=3, j=5, k=128, split_factor=16 and insert_split_dimension=0.
  The compute is rewritten as:
    a. O_i(kk, i, j) += I(i, j, 16 * k + kk)
    b. O(i, j) += O_i(kk, i, j)
  The intermediate tensor O_i is of shape (128/16)x3x5 == 8x3x5.
  
  #### Example:
  
  ```
   %0 = linalg.matmul ins(%A, %B: tensor<16x256xf32>, tensor<256x32xf32>)
     outs(%C: tensor<16x32xf32>) -> tensor<16x32xf32>
  ```
  
  Is transformed to:
  
  ```
   #map0 = affine_map<(d0, d1, d2, d3) -> (d0, d2 * 4 + d3)>
   #map1 = affine_map<(d0, d1, d2, d3) -> (d2 * 4 + d3, d1)>
   #map2 = affine_map<(d0, d1, d2, d3) -> (d2, d3)>
   #map3 = affine_map<(d0, d1, d2, d3) -> (d0, d1, d2)>
   #map4 = affine_map<(d0, d1, d2) -> (d0, d1, d2)>
   #map5 = affine_map<(d0, d1, d2) -> (d0, d1)>
   %0 = tensor.empty() : tensor<16x32x64xf32>
   %cst = arith.constant 0.000000e+00 : f32
   %1 = linalg.fill ins(%cst : f32) outs(%0 : tensor<16x32x64xf32>) ->
      tensor<16x32x64xf32>
   %2 = tensor.empty() : tensor<64x4xi1>
  
   %3 = linalg.generic {indexing_maps = [#map0, #map1, #map2, #map3],
     iterator_types = ["parallel", "parallel", "parallel", "reduction"]}
     ins(%A, %B, %2 : tensor<16x256xf32>, tensor<256x32xf32>, tensor<64x4xi1>)
     outs(%1 : tensor<16x32x64xf32>) {
       ^bb0(%arg3: f32, %arg4: f32, %arg5: i1, %arg6: f32):
         %5 = arith.mulf %arg3, %arg4 : f32
         %6 = arith.addf %arg6, %5 : f32
         linalg.yield %6 : f32
   } -> tensor<16x32x64xf32>
  
   %4 = linalg.generic {indexing_maps = [#map4, #map5],
     iterator_types = ["parallel", "parallel", "reduction"]}
     ins(%3 : tensor<16x32x64xf32>)
     outs(%C : tensor<16x32xf32>) {
       ^bb0(%arg3: f32, %arg4: f32):
         %5 = arith.addf %arg3, %arg4 : f32
         linalg.yield %5 : f32
   } -> tensor<16x32xf32>
  
   return %4 : tensor<16x32xf32>
  ```
  """

  OPERATION_NAME = "transform.structured.split_reduction"

  _ODS_REGIONS = (0, True)

  def __init__(self, init_or_alloc_op: _ods_ir.Type, fill_op: _ods_ir.Type, split_linalg_op: _ods_ir.Type, combining_linalg_op: _ods_ir.Type, target: _ods_ir.Value, *, split_factor: _Optional[_Union[int, _ods_ir.IntegerAttr]] = None, insert_split_dimension: _Optional[_Union[int, _ods_ir.IntegerAttr]] = None, inner_parallel: _Optional[bool] = None, use_scaling_algorithm: _Optional[bool] = None, use_alloc: _Optional[bool] = None, loc: _Optional[_ods_ir.Location] = None, ip: _Optional[_ods_ir.InsertionPoint] = None):
    operands = []
    attributes = {}
    regions = None
    operands.append(target)
    _ods_context = _ods_get_default_loc_context(loc)
    if split_factor is not None: attributes["split_factor"] = (split_factor if (
        isinstance(split_factor, _ods_ir.Attribute) or
        not _ods_ir.AttrBuilder.contains('I64Attr')) else
          _ods_ir.AttrBuilder.get('I64Attr')(split_factor, context=_ods_context))
    if insert_split_dimension is not None: attributes["insert_split_dimension"] = (insert_split_dimension if (
        isinstance(insert_split_dimension, _ods_ir.Attribute) or
        not _ods_ir.AttrBuilder.contains('I64Attr')) else
          _ods_ir.AttrBuilder.get('I64Attr')(insert_split_dimension, context=_ods_context))
    if bool(inner_parallel): attributes["inner_parallel"] = _ods_ir.UnitAttr.get(
      _ods_get_default_loc_context(loc))
    if bool(use_scaling_algorithm): attributes["use_scaling_algorithm"] = _ods_ir.UnitAttr.get(
      _ods_get_default_loc_context(loc))
    if bool(use_alloc): attributes["use_alloc"] = _ods_ir.UnitAttr.get(
      _ods_get_default_loc_context(loc))
    results = []
    results.append(init_or_alloc_op)
    results.append(fill_op)
    results.append(split_linalg_op)
    results.append(combining_linalg_op)
    _ods_successors = None
    super().__init__(self.OPERATION_NAME, self._ODS_REGIONS, self._ODS_OPERAND_SEGMENTS, self._ODS_RESULT_SEGMENTS, attributes=attributes, results=results, operands=operands, successors=_ods_successors, regions=regions, loc=loc, ip=ip)

  @builtins.property
  def target(self) -> _ods_ir.Value:
    return self.operation.operands[0]

  @builtins.property
  def split_factor(self) -> _ods_ir.IntegerAttr:
    return self.operation.attributes["split_factor"]

  @split_factor.setter
  def split_factor(self, value: _ods_ir.IntegerAttr):
    if value is None:
      raise ValueError("'None' not allowed as value for mandatory attributes")
    self.operation.attributes["split_factor"] = value

  @builtins.property
  def insert_split_dimension(self) -> _ods_ir.IntegerAttr:
    return self.operation.attributes["insert_split_dimension"]

  @insert_split_dimension.setter
  def insert_split_dimension(self, value: _ods_ir.IntegerAttr):
    if value is None:
      raise ValueError("'None' not allowed as value for mandatory attributes")
    self.operation.attributes["insert_split_dimension"] = value

  @builtins.property
  def inner_parallel(self) -> bool:
    return "inner_parallel" in self.operation.attributes

  @inner_parallel.setter
  def inner_parallel(self, value):
    if bool(value):
      self.operation.attributes["inner_parallel"] = _ods_ir.UnitAttr.get()
    elif "inner_parallel" in self.operation.attributes:
      del self.operation.attributes["inner_parallel"]

  @inner_parallel.deleter
  def inner_parallel(self):
    del self.operation.attributes["inner_parallel"]

  @builtins.property
  def use_scaling_algorithm(self) -> bool:
    return "use_scaling_algorithm" in self.operation.attributes

  @use_scaling_algorithm.setter
  def use_scaling_algorithm(self, value):
    if bool(value):
      self.operation.attributes["use_scaling_algorithm"] = _ods_ir.UnitAttr.get()
    elif "use_scaling_algorithm" in self.operation.attributes:
      del self.operation.attributes["use_scaling_algorithm"]

  @use_scaling_algorithm.deleter
  def use_scaling_algorithm(self):
    del self.operation.attributes["use_scaling_algorithm"]

  @builtins.property
  def use_alloc(self) -> bool:
    return "use_alloc" in self.operation.attributes

  @use_alloc.setter
  def use_alloc(self, value):
    if bool(value):
      self.operation.attributes["use_alloc"] = _ods_ir.UnitAttr.get()
    elif "use_alloc" in self.operation.attributes:
      del self.operation.attributes["use_alloc"]

  @use_alloc.deleter
  def use_alloc(self):
    del self.operation.attributes["use_alloc"]

  @builtins.property
  def init_or_alloc_op(self) -> _ods_ir.OpResult:
    return self.operation.results[0]

  @builtins.property
  def fill_op(self) -> _ods_ir.OpResult:
    return self.operation.results[1]

  @builtins.property
  def split_linalg_op(self) -> _ods_ir.OpResult:
    return self.operation.results[2]

  @builtins.property
  def combining_linalg_op(self) -> _ods_ir.OpResult:
    return self.operation.results[3]

@_ods_cext.register_op_adaptor(SplitReductionOp)
class SplitReductionOpAdaptor(_ods_ir.OpAdaptor):
  OPERATION_NAME = "transform.structured.split_reduction"

  @builtins.property
  def target(self) -> _ods_ir.Value:
    return self.operands[0]

  @builtins.property
  def split_factor(self) -> _ods_ir.IntegerAttr:
    return self.attributes["split_factor"]

  @builtins.property
  def insert_split_dimension(self) -> _ods_ir.IntegerAttr:
    return self.attributes["insert_split_dimension"]

  @builtins.property
  def inner_parallel(self) -> bool:
    return "inner_parallel" in self.attributes

  @builtins.property
  def use_scaling_algorithm(self) -> bool:
    return "use_scaling_algorithm" in self.attributes

  @builtins.property
  def use_alloc(self) -> bool:
    return "use_alloc" in self.attributes

def structured_split_reduction(init_or_alloc_op: _ods_ir.Type, fill_op: _ods_ir.Type, split_linalg_op: _ods_ir.Type, combining_linalg_op: _ods_ir.Type, target: _ods_ir.Value, *, split_factor: _Optional[_Union[int, _ods_ir.IntegerAttr]] = None, insert_split_dimension: _Optional[_Union[int, _ods_ir.IntegerAttr]] = None, inner_parallel: _Optional[bool] = None, use_scaling_algorithm: _Optional[bool] = None, use_alloc: _Optional[bool] = None, loc: _Optional[_ods_ir.Location] = None, ip: _Optional[_ods_ir.InsertionPoint] = None) -> _ods_ir.OpResultList:
  return SplitReductionOp(init_or_alloc_op=init_or_alloc_op, fill_op=fill_op, split_linalg_op=split_linalg_op, combining_linalg_op=combining_linalg_op, target=target, split_factor=split_factor, insert_split_dimension=insert_split_dimension, inner_parallel=inner_parallel, use_scaling_algorithm=use_scaling_algorithm, use_alloc=use_alloc, loc=loc, ip=ip).results

@_ods_cext.register_operation(_Dialect)
class TileReductionUsingForOp(_ods_ir.OpView):
  r"""
  Indicates that the given `target` op should be transformed with the
  `tileReduction` transformation with the tile size provided as attribute.
  
  This transformation tiles the `target` along the reduction dimensions. It
  creates a tensor initialized with the identity value. Then it creates nested
  loops with a parallel version of `target` op inside. The parallel op
  dimensions are less or equal to the tile size passed by user.
  After the loop a merge operation is created to do a final reduction with the
  partial reductions.
  The initial tensor always uses the tile size dimension. This may overallocate
  if the tile size is greater than the reduction dimension.
  
  #### Return modes
  
  Returns 4 handles associated with (in order):
    - the fill op used to initialize the neutral element,
    - the parallel tiled op and
    - the result-combining op,
    - the parent `for` op.
  
  The `reduction_dims` can be used to specify the subset of reduction dimensions
  of the operation to tile. If left unspecified, all reduction dimensions are
  tiled.
  
  #### Example:
  
  ```
    %red = linalg.generic {indexing_maps = [affine_map<(d0, d1) -> (d0, d1)>,
                                            affine_map<(d0, d1) -> (d0)>],
    iterator_types = ["parallel", "reduction"]}
    ins(%arg0 : tensor<?x?xf32>)
    outs(%out : tensor<?xf32>) {
      ^bb0(%arg7: f32, %arg9: f32):
      %1 = arith.addf %arg7, %arg9 : f32
      linalg.yield %1 : f32
    } -> tensor<?xf32>
    return %red : tensor<?xf32>
  ```
  
  is transformed into:
  
  ```
    %0 = tensor.empty(%dim_1) : tensor<?x5xf32>
    %1 = linalg.fill ins(%cst : f32) outs(%0 : tensor<?x5xf32>) -> tensor<?x5xf32>
    %2 = scf.for %arg2 = %c0 to %dim_0 step %c5 iter_args(%arg3 = %1) -> (tensor<?x5xf32>) {
      %extracted_slice = tensor.extract_slice %1[0, 0] [%dim, 5] [1, 1] : tensor<?x5xf32> to tensor<?x5xf32>
      %extracted_slice_2 = tensor.extract_slice %arg0[0, %arg2] [%dim, 5] [1, 1] : tensor<?x?xf32> to tensor<?x5xf32>
      %4 = linalg.generic {indexing_maps = [affine_map<(d0, d1) -> (d0, d1)>,
                                            affine_map<(d0, d1) -> (d0, d1)>],
      iterator_types = ["parallel", "parallel"]}
      ins(%extracted_slice_2 : tensor<?x5xf32>)
      outs(%extracted_slice : tensor<?x5xf32>) {
      ^bb0(%in: f32, %out: f32):
        %5 = arith.addf %in, %out : f32
        linalg.yield %5 : f32
      } -> tensor<?x5xf32>
      %dim_3 = tensor.dim %1, %c0 : tensor<?x5xf32>
      %inserted_slice = tensor.insert_slice %4 into %arg3[0, 0] [%dim_3, 5] [1, 1] : tensor<?x5xf32> into tensor<?x5xf32>
      scf.yield %inserted_slice : tensor<?x5xf32>
    }
    %3 = linalg.generic {indexing_maps = [affine_map<(d0, d1) -> (d0, d1)>,
                                          affine_map<(d0, d1) -> (d0)>],
    iterator_types = ["parallel", "reduction"]}
    ins(%2 : tensor<?x5xf32>)
    outs(%arg1 : tensor<?xf32>) {
    ^bb0(%in: f32, %out: f32):
      %4 = arith.addf %in, %out : f32
      linalg.yield %4 : f32
    } -> tensor<?xf32>
  ```
  """

  OPERATION_NAME = "transform.structured.tile_reduction_using_for"

  _ODS_REGIONS = (0, True)

  def __init__(self, fill_op: _Sequence[_ods_ir.Type], split_op: _ods_ir.Type, combining_op: _ods_ir.Type, for_op: _ods_ir.Type, target: _ods_ir.Value, *, reduction_dims: _Optional[_Union[_Sequence[int], _ods_ir.ArrayAttr]] = None, tile_sizes: _Optional[_Union[_Sequence[int], _ods_ir.ArrayAttr]] = None, loc: _Optional[_ods_ir.Location] = None, ip: _Optional[_ods_ir.InsertionPoint] = None):
    operands = []
    attributes = {}
    regions = None
    operands.append(target)
    _ods_context = _ods_get_default_loc_context(loc)
    if reduction_dims is not None: attributes["reduction_dims"] = (reduction_dims if (
        isinstance(reduction_dims, _ods_ir.Attribute) or
        not _ods_ir.AttrBuilder.contains('I64ArrayAttr')) else
          _ods_ir.AttrBuilder.get('I64ArrayAttr')(reduction_dims, context=_ods_context))
    if tile_sizes is not None: attributes["tile_sizes"] = (tile_sizes if (
        isinstance(tile_sizes, _ods_ir.Attribute) or
        not _ods_ir.AttrBuilder.contains('I64ArrayAttr')) else
          _ods_ir.AttrBuilder.get('I64ArrayAttr')(tile_sizes, context=_ods_context))
    results = []
    results.extend(fill_op)
    results.append(split_op)
    results.append(combining_op)
    results.append(for_op)
    _ods_successors = None
    super().__init__(self.OPERATION_NAME, self._ODS_REGIONS, self._ODS_OPERAND_SEGMENTS, self._ODS_RESULT_SEGMENTS, attributes=attributes, results=results, operands=operands, successors=_ods_successors, regions=regions, loc=loc, ip=ip)

  @builtins.property
  def target(self) -> _ods_ir.Value:
    return self.operation.operands[0]

  @builtins.property
  def reduction_dims(self) -> _ods_ir.ArrayAttr:
    return self.operation.attributes["reduction_dims"]

  @reduction_dims.setter
  def reduction_dims(self, value: _ods_ir.ArrayAttr):
    if value is None:
      raise ValueError("'None' not allowed as value for mandatory attributes")
    self.operation.attributes["reduction_dims"] = value

  @builtins.property
  def tile_sizes(self) -> _ods_ir.ArrayAttr:
    return self.operation.attributes["tile_sizes"]

  @tile_sizes.setter
  def tile_sizes(self, value: _ods_ir.ArrayAttr):
    if value is None:
      raise ValueError("'None' not allowed as value for mandatory attributes")
    self.operation.attributes["tile_sizes"] = value

  @builtins.property
  def fill_op(self) -> _ods_ir.OpResultList:
    _ods_variadic_group_length = len(self.operation.results) - 4 + 1
    return self.operation.results[0:0 + _ods_variadic_group_length]

  @builtins.property
  def split_op(self) -> _ods_ir.OpResult:
    _ods_variadic_group_length = len(self.operation.results) - 4 + 1
    return self.operation.results[1 + _ods_variadic_group_length - 1]

  @builtins.property
  def combining_op(self) -> _ods_ir.OpResult:
    _ods_variadic_group_length = len(self.operation.results) - 4 + 1
    return self.operation.results[2 + _ods_variadic_group_length - 1]

  @builtins.property
  def for_op(self) -> _ods_ir.OpResult:
    _ods_variadic_group_length = len(self.operation.results) - 4 + 1
    return self.operation.results[3 + _ods_variadic_group_length - 1]

@_ods_cext.register_op_adaptor(TileReductionUsingForOp)
class TileReductionUsingForOpAdaptor(_ods_ir.OpAdaptor):
  OPERATION_NAME = "transform.structured.tile_reduction_using_for"

  @builtins.property
  def target(self) -> _ods_ir.Value:
    return self.operands[0]

  @builtins.property
  def reduction_dims(self) -> _ods_ir.ArrayAttr:
    return self.attributes["reduction_dims"]

  @builtins.property
  def tile_sizes(self) -> _ods_ir.ArrayAttr:
    return self.attributes["tile_sizes"]

def structured_tile_reduction_using_for(fill_op: _Sequence[_ods_ir.Type], split_op: _ods_ir.Type, combining_op: _ods_ir.Type, for_op: _ods_ir.Type, target: _ods_ir.Value, *, reduction_dims: _Optional[_Union[_Sequence[int], _ods_ir.ArrayAttr]] = None, tile_sizes: _Optional[_Union[_Sequence[int], _ods_ir.ArrayAttr]] = None, loc: _Optional[_ods_ir.Location] = None, ip: _Optional[_ods_ir.InsertionPoint] = None) -> _Union[_ods_ir.OpResult, _ods_ir.OpResultList, TileReductionUsingForOp]:
  op = TileReductionUsingForOp(fill_op=fill_op, split_op=split_op, combining_op=combining_op, for_op=for_op, target=target, reduction_dims=reduction_dims, tile_sizes=tile_sizes, loc=loc, ip=ip); results = op.results
  return results if len(results) > 1 else (results[0] if len(results) == 1 else op)

@_ods_cext.register_operation(_Dialect)
class TileReductionUsingForallOp(_ods_ir.OpView):
  r"""
  Tile a PartialReductionOpInterface op to a tiled `scf.forall` doing
  partial reduction.
  
  This transformation tiles the `target` along the reduction dimensions. It
  creates a tensor initialized with the identity value. Then it creates a
  `scf.forall` loops with the number threads given by `num_threads`.
  The op is tiled op with a size equal to `floordiv(size, num_threads)`.
  All the partial reduction value is are parallel inserted to create a new
  tensor. After the loop a merge operation is created to do a final reduction
  with the partial reductions tensor.
  If an extra `tile_sizes` parameter is passed the tiles are cyclically
  distributed on the threads of the `scf.foralls` loop.
  
  #### Return modes
  
  Returns 4 handles associated with (in order):
    - the fill op used to initialize the neutral element,
    - the parallel tiled op and
    - the result-combining op,
    - the parent `forall` op.
  
  #### Example:
  
  ```
    %red = linalg.generic {indexing_maps = [affine_map<(d0, d1) -> (d0, d1)>,
                                            affine_map<(d0, d1) -> (d0)>],
    iterator_types = ["parallel", "reduction"]}
    ins(%arg0 : tensor<?x?xf32>)
    outs(%out : tensor<?xf32>) {
      ^bb0(%arg7: f32, %arg9: f32):
      %1 = arith.addf %arg7, %arg9 : f32
      linalg.yield %1 : f32
    } -> tensor<?xf32>
    return %red : tensor<?xf32>
  ```
  
  is transformed into:
  
  ```
    %0 = tensor.empty(%dim_1) : tensor<?x5xf32>
    %1 = linalg.fill ins(%cst : f32) outs(%0 : tensor<?x5xf32>) -> tensor<?x5xf32>
    %2 = scf.forall (%arg2) in (%c5) shared_outs(%arg3 = %1) -> (tensor<?x5xf32>) {
      %4 = affine.min #map(%arg2)[%dim_0]
      %5 = affine.max #map1(%4)
      %extracted_slice = tensor.extract_slice %arg3[0, %arg2] [%dim, 1] [1, 1] : tensor<?x5xf32> to tensor<?xf32>
      %6 = affine.apply #map2(%arg2)[%dim_0]
      %extracted_slice_2 = tensor.extract_slice %arg0[0, %6] [%dim, %5] [1, 1] : tensor<?x?xf32> to tensor<?x?xf32>
      %extracted_slice_3 = tensor.extract_slice %extracted_slice[0] [%dim] [1] : tensor<?xf32> to tensor<?xf32>
      %7 = linalg.generic {indexing_maps = [#map3, #map4], iterator_types = ["parallel", "reduction"]} ins(%extracted_slice_2 : tensor<?x?xf32>) outs(%extracted_slice_3 : tensor<?xf32>) {
      ^bb0(%in: f32, %out: f32):
        %9 = arith.addf %in, %out : f32
        linalg.yield %9 : f32
      } -> tensor<?xf32>
      scf.forall.in_parallel {
        tensor.parallel_insert_slice %7 into %arg3[0, %arg2] [%dim, 1] [1, 1] : tensor<?xf32> into tensor<?x5xf32>
      }
    } {mapping = []}
    %3 = linalg.generic {indexing_maps = [#map3, #map4], iterator_types = ["parallel", "reduction"]} ins(%2 : tensor<?x5xf32>) outs(%arg1 : tensor<?xf32>) {
    ^bb0(%in: f32, %out: f32):
      %4 = arith.addf %in, %out : f32
      linalg.yield %4 : f32
    } -> tensor<?xf32>
  ```
  """

  OPERATION_NAME = "transform.structured.tile_reduction_using_forall"

  _ODS_REGIONS = (0, True)

  def __init__(self, fill_op: _Sequence[_ods_ir.Type], split_op: _ods_ir.Type, combining_op: _ods_ir.Type, forall_op: _ods_ir.Type, target: _ods_ir.Value, *, reduction_dims: _Optional[_Union[_Sequence[int], _ods_ir.ArrayAttr]] = None, num_threads: _Optional[_Union[_Sequence[int], _ods_ir.DenseI64ArrayAttr]] = None, tile_sizes: _Optional[_Union[_Sequence[int], _ods_ir.DenseI64ArrayAttr]] = None, mapping: _Optional[_Union[_Any, _ods_ir.ArrayAttr]] = None, loc: _Optional[_ods_ir.Location] = None, ip: _Optional[_ods_ir.InsertionPoint] = None):
    operands = []
    attributes = {}
    regions = None
    operands.append(target)
    _ods_context = _ods_get_default_loc_context(loc)
    if reduction_dims is not None: attributes["reduction_dims"] = (reduction_dims if (
        isinstance(reduction_dims, _ods_ir.Attribute) or
        not _ods_ir.AttrBuilder.contains('I64ArrayAttr')) else
          _ods_ir.AttrBuilder.get('I64ArrayAttr')(reduction_dims, context=_ods_context))
    if num_threads is not None: attributes["num_threads"] = (num_threads if (
        isinstance(num_threads, _ods_ir.Attribute) or
        not _ods_ir.AttrBuilder.contains('DenseI64ArrayAttr')) else
          _ods_ir.AttrBuilder.get('DenseI64ArrayAttr')(num_threads, context=_ods_context))
    if tile_sizes is not None: attributes["tile_sizes"] = (tile_sizes if (
        isinstance(tile_sizes, _ods_ir.Attribute) or
        not _ods_ir.AttrBuilder.contains('DenseI64ArrayAttr')) else
          _ods_ir.AttrBuilder.get('DenseI64ArrayAttr')(tile_sizes, context=_ods_context))
    if mapping is not None: attributes["mapping"] = (mapping if (
        isinstance(mapping, _ods_ir.Attribute) or
        not _ods_ir.AttrBuilder.contains('DeviceMappingArrayAttr')) else
          _ods_ir.AttrBuilder.get('DeviceMappingArrayAttr')(mapping, context=_ods_context))
    results = []
    results.extend(fill_op)
    results.append(split_op)
    results.append(combining_op)
    results.append(forall_op)
    _ods_successors = None
    super().__init__(self.OPERATION_NAME, self._ODS_REGIONS, self._ODS_OPERAND_SEGMENTS, self._ODS_RESULT_SEGMENTS, attributes=attributes, results=results, operands=operands, successors=_ods_successors, regions=regions, loc=loc, ip=ip)

  @builtins.property
  def target(self) -> _ods_ir.Value:
    return self.operation.operands[0]

  @builtins.property
  def reduction_dims(self) -> _ods_ir.ArrayAttr:
    return self.operation.attributes["reduction_dims"]

  @reduction_dims.setter
  def reduction_dims(self, value: _ods_ir.ArrayAttr):
    if value is None:
      raise ValueError("'None' not allowed as value for mandatory attributes")
    self.operation.attributes["reduction_dims"] = value

  @builtins.property
  def num_threads(self) -> _ods_ir.DenseI64ArrayAttr:
    return self.operation.attributes["num_threads"]

  @num_threads.setter
  def num_threads(self, value: _ods_ir.DenseI64ArrayAttr):
    if value is None:
      raise ValueError("'None' not allowed as value for mandatory attributes")
    self.operation.attributes["num_threads"] = value

  @builtins.property
  def tile_sizes(self) -> _ods_ir.DenseI64ArrayAttr:
    return self.operation.attributes["tile_sizes"]

  @tile_sizes.setter
  def tile_sizes(self, value: _ods_ir.DenseI64ArrayAttr):
    if value is None:
      raise ValueError("'None' not allowed as value for mandatory attributes")
    self.operation.attributes["tile_sizes"] = value

  @builtins.property
  def mapping(self) -> _Optional[_ods_ir.ArrayAttr]:
    if "mapping" not in self.operation.attributes:
      return None
    return self.operation.attributes["mapping"]

  @mapping.setter
  def mapping(self, value: _Optional[_ods_ir.ArrayAttr]):
    if value is not None:
      self.operation.attributes["mapping"] = value
    elif "mapping" in self.operation.attributes:
      del self.operation.attributes["mapping"]

  @mapping.deleter
  def mapping(self):
    del self.operation.attributes["mapping"]

  @builtins.property
  def fill_op(self) -> _ods_ir.OpResultList:
    _ods_variadic_group_length = len(self.operation.results) - 4 + 1
    return self.operation.results[0:0 + _ods_variadic_group_length]

  @builtins.property
  def split_op(self) -> _ods_ir.OpResult:
    _ods_variadic_group_length = len(self.operation.results) - 4 + 1
    return self.operation.results[1 + _ods_variadic_group_length - 1]

  @builtins.property
  def combining_op(self) -> _ods_ir.OpResult:
    _ods_variadic_group_length = len(self.operation.results) - 4 + 1
    return self.operation.results[2 + _ods_variadic_group_length - 1]

  @builtins.property
  def forall_op(self) -> _ods_ir.OpResult:
    _ods_variadic_group_length = len(self.operation.results) - 4 + 1
    return self.operation.results[3 + _ods_variadic_group_length - 1]

@_ods_cext.register_op_adaptor(TileReductionUsingForallOp)
class TileReductionUsingForallOpAdaptor(_ods_ir.OpAdaptor):
  OPERATION_NAME = "transform.structured.tile_reduction_using_forall"

  @builtins.property
  def target(self) -> _ods_ir.Value:
    return self.operands[0]

  @builtins.property
  def reduction_dims(self) -> _ods_ir.ArrayAttr:
    return self.attributes["reduction_dims"]

  @builtins.property
  def num_threads(self) -> _ods_ir.DenseI64ArrayAttr:
    return self.attributes["num_threads"]

  @builtins.property
  def tile_sizes(self) -> _ods_ir.DenseI64ArrayAttr:
    return self.attributes["tile_sizes"]

  @builtins.property
  def mapping(self) -> _Optional[_ods_ir.ArrayAttr]:
    if "mapping" not in self.attributes:
      return None
    return self.attributes["mapping"]

def structured_tile_reduction_using_forall(fill_op: _Sequence[_ods_ir.Type], split_op: _ods_ir.Type, combining_op: _ods_ir.Type, forall_op: _ods_ir.Type, target: _ods_ir.Value, *, reduction_dims: _Optional[_Union[_Sequence[int], _ods_ir.ArrayAttr]] = None, num_threads: _Optional[_Union[_Sequence[int], _ods_ir.DenseI64ArrayAttr]] = None, tile_sizes: _Optional[_Union[_Sequence[int], _ods_ir.DenseI64ArrayAttr]] = None, mapping: _Optional[_Union[_Any, _ods_ir.ArrayAttr]] = None, loc: _Optional[_ods_ir.Location] = None, ip: _Optional[_ods_ir.InsertionPoint] = None) -> _Union[_ods_ir.OpResult, _ods_ir.OpResultList, TileReductionUsingForallOp]:
  op = TileReductionUsingForallOp(fill_op=fill_op, split_op=split_op, combining_op=combining_op, forall_op=forall_op, target=target, reduction_dims=reduction_dims, num_threads=num_threads, tile_sizes=tile_sizes, mapping=mapping, loc=loc, ip=ip); results = op.results
  return results if len(results) > 1 else (results[0] if len(results) == 1 else op)

@_ods_cext.register_operation(_Dialect)
class TileUsingForOp(_ods_ir.OpView):
  r"""
  Indicates that the given `target` op should be tiled with the given sizes.
  This transform generates a loop nest with a smaller ("tiled") target
  operation in its body. Currently limited to LinalgOps.
  
  Tile sizes may be known at transformation time, in which case they are
  expected to be provided in the `static_size` attribute, or not, in which
  case the tile value must be computed by the payload IR and the handle to the
  operation computing it must be provided through `dynamic_sizes`. When the
  sizes are not known statically, the corresponding entry in the
  `static_sizes` attribute must be set to `ShapedType::kDynamic`. Only
  the dynamic sizes must be provided in `dynamic_sizes`, i.e., there should
  be as many handles as `ShapedType::kDynamic` values in the
  `static_sizes` attribute. A static size of `0` indicates that the dimension
  should not be tiled. No loop will be generated for such dimensions. If all
  tile sizes are `0`, this transform is effectively a no-op.
  
  This op returns handles to the tiled op (in the generated loop nest) and the
  generated loops. The number of loops is the number of tile sizes that are
  statically known to be non-zero.
  
  #### Return modes
  
  On success, the resulting handles are associated with co-indexed lists of
  tiled operations and loops around them.
  
  This operation only supports Linalg ops and produces a silenceable failure
  if the input contains any non-Linalg ops. The ops preceding it in the list
  associated with the `target` handle will have been tiled.
  
  This operation produces a silenceable failure if the `dynamic_sizes` handles
  are associated with lists of payload operations of a size different than
  that of the list associated with the `target` handle.
  
  If the internal implementation of tiling for any of the operations fails,
  produces a definite failure.
  """

  OPERATION_NAME = "transform.structured.tile_using_for"

  _ODS_REGIONS = (0, True)

  def __init__(self, tiled_linalg_op: _ods_ir.Type, loops: _Sequence[_ods_ir.Type], target: _ods_ir.Value, dynamic_sizes: _Sequence[_ods_ir.Value], *, static_sizes: _Optional[_Union[_Sequence[int], _ods_ir.DenseI64ArrayAttr]] = None, interchange: _Optional[_Union[_Sequence[int], _ods_ir.DenseI64ArrayAttr]] = None, scalable_sizes: _Optional[_Union[_Sequence[bool], _ods_ir.DenseBoolArrayAttr]] = None, loc: _Optional[_ods_ir.Location] = None, ip: _Optional[_ods_ir.InsertionPoint] = None):
    operands = []
    attributes = {}
    regions = None
    operands.append(target)
    operands.extend(_get_op_results_or_values(dynamic_sizes))
    _ods_context = _ods_get_default_loc_context(loc)
    if static_sizes is not None: attributes["static_sizes"] = (static_sizes if (
        isinstance(static_sizes, _ods_ir.Attribute) or
        not _ods_ir.AttrBuilder.contains('DenseI64ArrayAttr')) else
          _ods_ir.AttrBuilder.get('DenseI64ArrayAttr')(static_sizes, context=_ods_context))
    if interchange is not None: attributes["interchange"] = (interchange if (
        isinstance(interchange, _ods_ir.Attribute) or
        not _ods_ir.AttrBuilder.contains('DenseI64ArrayAttr')) else
          _ods_ir.AttrBuilder.get('DenseI64ArrayAttr')(interchange, context=_ods_context))
    if scalable_sizes is not None: attributes["scalable_sizes"] = (scalable_sizes if (
        isinstance(scalable_sizes, _ods_ir.Attribute) or
        not _ods_ir.AttrBuilder.contains('DenseBoolArrayAttr')) else
          _ods_ir.AttrBuilder.get('DenseBoolArrayAttr')(scalable_sizes, context=_ods_context))
    results = []
    results.append(tiled_linalg_op)
    results.extend(loops)
    _ods_successors = None
    super().__init__(self.OPERATION_NAME, self._ODS_REGIONS, self._ODS_OPERAND_SEGMENTS, self._ODS_RESULT_SEGMENTS, attributes=attributes, results=results, operands=operands, successors=_ods_successors, regions=regions, loc=loc, ip=ip)

  @builtins.property
  def target(self) -> _ods_ir.Value:
    return self.operation.operands[0]

  @builtins.property
  def dynamic_sizes(self) -> _ods_ir.OpOperandList:
    _ods_variadic_group_length = len(self.operation.operands) - 2 + 1
    return self.operation.operands[1:1 + _ods_variadic_group_length]

  @builtins.property
  def static_sizes(self) -> _Optional[_ods_ir.DenseI64ArrayAttr]:
    if "static_sizes" not in self.operation.attributes:
      return None
    return self.operation.attributes["static_sizes"]

  @static_sizes.setter
  def static_sizes(self, value: _Optional[_ods_ir.DenseI64ArrayAttr]):
    if value is not None:
      self.operation.attributes["static_sizes"] = value
    elif "static_sizes" in self.operation.attributes:
      del self.operation.attributes["static_sizes"]

  @static_sizes.deleter
  def static_sizes(self):
    del self.operation.attributes["static_sizes"]

  @builtins.property
  def interchange(self) -> _Optional[_ods_ir.DenseI64ArrayAttr]:
    if "interchange" not in self.operation.attributes:
      return None
    return self.operation.attributes["interchange"]

  @interchange.setter
  def interchange(self, value: _Optional[_ods_ir.DenseI64ArrayAttr]):
    if value is not None:
      self.operation.attributes["interchange"] = value
    elif "interchange" in self.operation.attributes:
      del self.operation.attributes["interchange"]

  @interchange.deleter
  def interchange(self):
    del self.operation.attributes["interchange"]

  @builtins.property
  def scalable_sizes(self) -> _Optional[_ods_ir.DenseBoolArrayAttr]:
    if "scalable_sizes" not in self.operation.attributes:
      return None
    return self.operation.attributes["scalable_sizes"]

  @scalable_sizes.setter
  def scalable_sizes(self, value: _Optional[_ods_ir.DenseBoolArrayAttr]):
    if value is not None:
      self.operation.attributes["scalable_sizes"] = value
    elif "scalable_sizes" in self.operation.attributes:
      del self.operation.attributes["scalable_sizes"]

  @scalable_sizes.deleter
  def scalable_sizes(self):
    del self.operation.attributes["scalable_sizes"]

  @builtins.property
  def tiled_linalg_op(self) -> _ods_ir.OpResult:
    return self.operation.results[0]

  @builtins.property
  def loops(self) -> _ods_ir.OpResultList:
    _ods_variadic_group_length = len(self.operation.results) - 2 + 1
    return self.operation.results[1:1 + _ods_variadic_group_length]

@_ods_cext.register_op_adaptor(TileUsingForOp)
class TileUsingForOpAdaptor(_ods_ir.OpAdaptor):
  OPERATION_NAME = "transform.structured.tile_using_for"

  @builtins.property
  def target(self) -> _ods_ir.Value:
    return self.operands[0]

  @builtins.property
  def dynamic_sizes(self) -> _ods_ir.OpOperandList:
    _ods_variadic_group_length = len(self.operands) - 2 + 1
    return self.operands[1:1 + _ods_variadic_group_length]

  @builtins.property
  def static_sizes(self) -> _Optional[_ods_ir.DenseI64ArrayAttr]:
    if "static_sizes" not in self.attributes:
      return None
    return self.attributes["static_sizes"]

  @builtins.property
  def interchange(self) -> _Optional[_ods_ir.DenseI64ArrayAttr]:
    if "interchange" not in self.attributes:
      return None
    return self.attributes["interchange"]

  @builtins.property
  def scalable_sizes(self) -> _Optional[_ods_ir.DenseBoolArrayAttr]:
    if "scalable_sizes" not in self.attributes:
      return None
    return self.attributes["scalable_sizes"]

def structured_tile_using_for(tiled_linalg_op: _ods_ir.Type, loops: _Sequence[_ods_ir.Type], target: _ods_ir.Value, dynamic_sizes: _Sequence[_ods_ir.Value], *, static_sizes: _Optional[_Union[_Sequence[int], _ods_ir.DenseI64ArrayAttr]] = None, interchange: _Optional[_Union[_Sequence[int], _ods_ir.DenseI64ArrayAttr]] = None, scalable_sizes: _Optional[_Union[_Sequence[bool], _ods_ir.DenseBoolArrayAttr]] = None, loc: _Optional[_ods_ir.Location] = None, ip: _Optional[_ods_ir.InsertionPoint] = None) -> _Union[_ods_ir.OpResult, _ods_ir.OpResultList, TileUsingForOp]:
  op = TileUsingForOp(tiled_linalg_op=tiled_linalg_op, loops=loops, target=target, dynamic_sizes=dynamic_sizes, static_sizes=static_sizes, interchange=interchange, scalable_sizes=scalable_sizes, loc=loc, ip=ip); results = op.results
  return results if len(results) > 1 else (results[0] if len(results) == 1 else op)

@_ods_cext.register_operation(_Dialect)
class TileUsingForallOp(_ods_ir.OpView):
  r"""
  Tile a TilingInterface op to a tiled `scf.forall`.
  
  Tiling is applied by either specifying `num_threads` or `tile_size`. If
  `num_threads` is specified, then the tile size for each dimension `i` is
  calculated dynamically via `ceilDiv(dimSize[i], num_threads[i])`.
  `num_threads` and `tile_size` can be either static index attributes or
  operation handles (or a mix thereof). Operation handles must be mapped to
  exactly one op that has exactly one result of index type.
  
  Static zero tile sizes indicate that the dimension is not tiled and can be
  thought of as tiling by the full size of data.
  
  It is the user's responsibility to ensure that `num_threads/tile_sizes` is
  a valid tiling specification (i.e. that only tiles parallel dimensions,
  e.g. in the Linalg case). If the dimension is not parallelizable, a warning
  is issued to notify the user that the generated code is not safe to
  parallelize.
  
  If non-empty, the `mapping` is added as an attribute to the
  resulting `scf.forall`.
  
  Note: `tile_sizes` and `num_threads` are variadic. Each tile size/number of
  threads can be an index attribute or a transform handle that is mapped to
  exactly one payload op with exactly one index result.
  
  #### Return modes
  
  This operation ignores ops that do not implement the TilingInterface and
  drops them in the return.
  
  If all the operations referred to by the `target` handle tile
  successfully, the transform succeeds.
  Otherwise the transform produces a silenceable failure.
  
  The two returned handles point to only the subset of successfully produced
  tiled operations, which can all be empty.
  
  These two returned handles point to:
    - the tiled op that implements TilingInterface,
    - the new scf.forall op.
  
  #### Example using `num_threads`
  
  ```
  %0 = transform.structured.match ops{["linalg.matmul"]} in %arg1
     : (!transform.any_op) -> !transform.any_op
  %3:2 = transform.structured.tile_using_forall %0 num_threads [10, 20]
     : (!transform.any_op) -> (!transform.any_op, !transform.any_op)
  ```
  
  #### Example using `tile_sizes`
  
  ```
  %0 = transform.structured.match ops{["linalg.matmul"]} in %arg1
     : (!transform.any_op) -> !transform.any_op
  %sz = transform.structured.match ...
  %3:2 = transform.structured.tile_using_forall %0 tile_sizes [0, %sz, 20]
     : (!transform.any_op, !transform.any_op) -> (!transform.any_op, !transform.any_op)
  ```
  """

  OPERATION_NAME = "transform.structured.tile_using_forall"

  _ODS_OPERAND_SEGMENTS = [1,-1,-1,0,0,]

  _ODS_REGIONS = (0, True)

  def __init__(self, tiled_op: _ods_ir.Type, forall_op: _ods_ir.Type, target: _ods_ir.Value, num_threads: _Sequence[_ods_ir.Value], tile_sizes: _Sequence[_ods_ir.Value], *, packed_num_threads: _Optional[_ods_ir.Value] = None, packed_tile_sizes: _Optional[_ods_ir.Value] = None, static_num_threads: _Optional[_Union[_Sequence[int], _ods_ir.DenseI64ArrayAttr]] = None, static_tile_sizes: _Optional[_Union[_Sequence[int], _ods_ir.DenseI64ArrayAttr]] = None, mapping: _Optional[_Union[_Any, _ods_ir.ArrayAttr]] = None, loc: _Optional[_ods_ir.Location] = None, ip: _Optional[_ods_ir.InsertionPoint] = None):
    operands = []
    attributes = {}
    regions = None
    operands.append(target)
    operands.append(_get_op_results_or_values(num_threads))
    operands.append(_get_op_results_or_values(tile_sizes))
    operands.append(packed_num_threads)
    operands.append(packed_tile_sizes)
    _ods_context = _ods_get_default_loc_context(loc)
    if static_num_threads is not None: attributes["static_num_threads"] = (static_num_threads if (
        isinstance(static_num_threads, _ods_ir.Attribute) or
        not _ods_ir.AttrBuilder.contains('DenseI64ArrayAttr')) else
          _ods_ir.AttrBuilder.get('DenseI64ArrayAttr')(static_num_threads, context=_ods_context))
    if static_tile_sizes is not None: attributes["static_tile_sizes"] = (static_tile_sizes if (
        isinstance(static_tile_sizes, _ods_ir.Attribute) or
        not _ods_ir.AttrBuilder.contains('DenseI64ArrayAttr')) else
          _ods_ir.AttrBuilder.get('DenseI64ArrayAttr')(static_tile_sizes, context=_ods_context))
    if mapping is not None: attributes["mapping"] = (mapping if (
        isinstance(mapping, _ods_ir.Attribute) or
        not _ods_ir.AttrBuilder.contains('DeviceMappingArrayAttr')) else
          _ods_ir.AttrBuilder.get('DeviceMappingArrayAttr')(mapping, context=_ods_context))
    results = []
    results.append(tiled_op)
    results.append(forall_op)
    _ods_successors = None
    super().__init__(self.OPERATION_NAME, self._ODS_REGIONS, self._ODS_OPERAND_SEGMENTS, self._ODS_RESULT_SEGMENTS, attributes=attributes, results=results, operands=operands, successors=_ods_successors, regions=regions, loc=loc, ip=ip)

  @builtins.property
  def target(self) -> _ods_ir.Value:
    operand_range = _ods_segmented_accessor(
         self.operation.operands,
         self.operation.attributes["operandSegmentSizes"], 0)
    return operand_range[0]

  @builtins.property
  def num_threads(self) -> _ods_ir.OpOperandList:
    operand_range = _ods_segmented_accessor(
         self.operation.operands,
         self.operation.attributes["operandSegmentSizes"], 1)
    return operand_range

  @builtins.property
  def tile_sizes(self) -> _ods_ir.OpOperandList:
    operand_range = _ods_segmented_accessor(
         self.operation.operands,
         self.operation.attributes["operandSegmentSizes"], 2)
    return operand_range

  @builtins.property
  def packed_num_threads(self) -> _Optional[_ods_ir.Value]:
    operand_range = _ods_segmented_accessor(
         self.operation.operands,
         self.operation.attributes["operandSegmentSizes"], 3)
    return operand_range[0] if len(operand_range) > 0 else None

  @builtins.property
  def packed_tile_sizes(self) -> _Optional[_ods_ir.Value]:
    operand_range = _ods_segmented_accessor(
         self.operation.operands,
         self.operation.attributes["operandSegmentSizes"], 4)
    return operand_range[0] if len(operand_range) > 0 else None

  @builtins.property
  def static_num_threads(self) -> _Optional[_ods_ir.DenseI64ArrayAttr]:
    if "static_num_threads" not in self.operation.attributes:
      return None
    return self.operation.attributes["static_num_threads"]

  @static_num_threads.setter
  def static_num_threads(self, value: _Optional[_ods_ir.DenseI64ArrayAttr]):
    if value is not None:
      self.operation.attributes["static_num_threads"] = value
    elif "static_num_threads" in self.operation.attributes:
      del self.operation.attributes["static_num_threads"]

  @static_num_threads.deleter
  def static_num_threads(self):
    del self.operation.attributes["static_num_threads"]

  @builtins.property
  def static_tile_sizes(self) -> _Optional[_ods_ir.DenseI64ArrayAttr]:
    if "static_tile_sizes" not in self.operation.attributes:
      return None
    return self.operation.attributes["static_tile_sizes"]

  @static_tile_sizes.setter
  def static_tile_sizes(self, value: _Optional[_ods_ir.DenseI64ArrayAttr]):
    if value is not None:
      self.operation.attributes["static_tile_sizes"] = value
    elif "static_tile_sizes" in self.operation.attributes:
      del self.operation.attributes["static_tile_sizes"]

  @static_tile_sizes.deleter
  def static_tile_sizes(self):
    del self.operation.attributes["static_tile_sizes"]

  @builtins.property
  def mapping(self) -> _Optional[_ods_ir.ArrayAttr]:
    if "mapping" not in self.operation.attributes:
      return None
    return self.operation.attributes["mapping"]

  @mapping.setter
  def mapping(self, value: _Optional[_ods_ir.ArrayAttr]):
    if value is not None:
      self.operation.attributes["mapping"] = value
    elif "mapping" in self.operation.attributes:
      del self.operation.attributes["mapping"]

  @mapping.deleter
  def mapping(self):
    del self.operation.attributes["mapping"]

  @builtins.property
  def tiled_op(self) -> _ods_ir.OpResult:
    return self.operation.results[0]

  @builtins.property
  def forall_op(self) -> _ods_ir.OpResult:
    return self.operation.results[1]

@_ods_cext.register_op_adaptor(TileUsingForallOp)
class TileUsingForallOpAdaptor(_ods_ir.OpAdaptor):
  OPERATION_NAME = "transform.structured.tile_using_forall"

  @builtins.property
  def target(self) -> _ods_ir.Value:
    operand_range = _ods_segmented_accessor(
         self.operands,
         self.attributes["operandSegmentSizes"], 0)
    return operand_range[0]

  @builtins.property
  def num_threads(self) -> _ods_ir.OpOperandList:
    operand_range = _ods_segmented_accessor(
         self.operands,
         self.attributes["operandSegmentSizes"], 1)
    return operand_range

  @builtins.property
  def tile_sizes(self) -> _ods_ir.OpOperandList:
    operand_range = _ods_segmented_accessor(
         self.operands,
         self.attributes["operandSegmentSizes"], 2)
    return operand_range

  @builtins.property
  def packed_num_threads(self) -> _Optional[_ods_ir.Value]:
    operand_range = _ods_segmented_accessor(
         self.operands,
         self.attributes["operandSegmentSizes"], 3)
    return operand_range[0] if len(operand_range) > 0 else None

  @builtins.property
  def packed_tile_sizes(self) -> _Optional[_ods_ir.Value]:
    operand_range = _ods_segmented_accessor(
         self.operands,
         self.attributes["operandSegmentSizes"], 4)
    return operand_range[0] if len(operand_range) > 0 else None

  @builtins.property
  def static_num_threads(self) -> _Optional[_ods_ir.DenseI64ArrayAttr]:
    if "static_num_threads" not in self.attributes:
      return None
    return self.attributes["static_num_threads"]

  @builtins.property
  def static_tile_sizes(self) -> _Optional[_ods_ir.DenseI64ArrayAttr]:
    if "static_tile_sizes" not in self.attributes:
      return None
    return self.attributes["static_tile_sizes"]

  @builtins.property
  def mapping(self) -> _Optional[_ods_ir.ArrayAttr]:
    if "mapping" not in self.attributes:
      return None
    return self.attributes["mapping"]

def structured_tile_using_forall(tiled_op: _ods_ir.Type, forall_op: _ods_ir.Type, target: _ods_ir.Value, num_threads: _Sequence[_ods_ir.Value], tile_sizes: _Sequence[_ods_ir.Value], *, packed_num_threads: _Optional[_ods_ir.Value] = None, packed_tile_sizes: _Optional[_ods_ir.Value] = None, static_num_threads: _Optional[_Union[_Sequence[int], _ods_ir.DenseI64ArrayAttr]] = None, static_tile_sizes: _Optional[_Union[_Sequence[int], _ods_ir.DenseI64ArrayAttr]] = None, mapping: _Optional[_Union[_Any, _ods_ir.ArrayAttr]] = None, loc: _Optional[_ods_ir.Location] = None, ip: _Optional[_ods_ir.InsertionPoint] = None) -> _ods_ir.OpResultList:
  return TileUsingForallOp(tiled_op=tiled_op, forall_op=forall_op, target=target, num_threads=num_threads, tile_sizes=tile_sizes, packed_num_threads=packed_num_threads, packed_tile_sizes=packed_tile_sizes, static_num_threads=static_num_threads, static_tile_sizes=static_tile_sizes, mapping=mapping, loc=loc, ip=ip).results

@_ods_cext.register_operation(_Dialect)
class TransposeConv2DOp(_ods_ir.OpView):
  r"""
  Convert linalg.conv_2d_nhwc_fhwc into linalg.conv_2d_nhwc_hwcf by introducing
  a linalg.transpose on the filter tensor/memref.
  
  Whilst the fhwc filter channel ordering can be desirable for certain targets
  and is a more direct mapping to higher level dialects such as TOSA (which only
  supports this ordering) hwcf is better suited for transformations such as
  img2col which can make use of optimized BLAS routines such as GEMM.
  
  Returns one handle:
  - The final operation of the sequence that replaces the original
    convolution.
  
  #### Return modes:
  
  Returns a definite failure if target is not isolated from above.
  Returns a silenceable failure if the pattern application failed.
  """

  OPERATION_NAME = "transform.structured.transpose_conv2d"

  _ODS_REGIONS = (0, True)

  def __init__(self, transformed: _ods_ir.Type, target: _ods_ir.Value, *, loc: _Optional[_ods_ir.Location] = None, ip: _Optional[_ods_ir.InsertionPoint] = None):
    operands = []
    attributes = {}
    regions = None
    operands.append(target)
    _ods_context = _ods_get_default_loc_context(loc)
    results = []
    results.append(transformed)
    _ods_successors = None
    super().__init__(self.OPERATION_NAME, self._ODS_REGIONS, self._ODS_OPERAND_SEGMENTS, self._ODS_RESULT_SEGMENTS, attributes=attributes, results=results, operands=operands, successors=_ods_successors, regions=regions, loc=loc, ip=ip)

  @builtins.property
  def target(self) -> _ods_ir.Value:
    return self.operation.operands[0]

  @builtins.property
  def transformed(self) -> _ods_ir.OpResult:
    return self.operation.results[0]

@_ods_cext.register_op_adaptor(TransposeConv2DOp)
class TransposeConv2DOpAdaptor(_ods_ir.OpAdaptor):
  OPERATION_NAME = "transform.structured.transpose_conv2d"

  @builtins.property
  def target(self) -> _ods_ir.Value:
    return self.operands[0]

def structured_transpose_conv2d(transformed: _ods_ir.Type, target: _ods_ir.Value, *, loc: _Optional[_ods_ir.Location] = None, ip: _Optional[_ods_ir.InsertionPoint] = None) -> _ods_ir.OpResult:
  return TransposeConv2DOp(transformed=transformed, target=target, loc=loc, ip=ip).result

@_ods_cext.register_operation(_Dialect)
class TransposeMatmulOp(_ods_ir.OpView):
  r"""
  Convert Linalg matmul ops to transposed variants.
  
  By default the LHS matrix is transposed. Specify `<rhs>` to instead
  transpose RHS matrix.
  
  #### Return modes:
  
  This operation fails if `target` is unsupported, i.e., not a
  `linalg.matmul` or `linalg.batch_matmul`. Otherwise, the operation succeeds
  and returns a handle to the transposed matmul op.
  """

  OPERATION_NAME = "transform.structured.transpose_matmul"

  _ODS_REGIONS = (0, True)

  def __init__(self, transformed: _ods_ir.Type, target: _ods_ir.Value, *, inputToTranspose: _Optional[_Union[_Any, _ods_ir.Attribute]] = None, loc: _Optional[_ods_ir.Location] = None, ip: _Optional[_ods_ir.InsertionPoint] = None):
    operands = []
    attributes = {}
    regions = None
    operands.append(target)
    _ods_context = _ods_get_default_loc_context(loc)
    if inputToTranspose is not None: attributes["inputToTranspose"] = (inputToTranspose if (
        isinstance(inputToTranspose, _ods_ir.Attribute) or
        not _ods_ir.AttrBuilder.contains('TransposeMatmulInput')) else
          _ods_ir.AttrBuilder.get('TransposeMatmulInput')(inputToTranspose, context=_ods_context))
    results = []
    results.append(transformed)
    _ods_successors = None
    super().__init__(self.OPERATION_NAME, self._ODS_REGIONS, self._ODS_OPERAND_SEGMENTS, self._ODS_RESULT_SEGMENTS, attributes=attributes, results=results, operands=operands, successors=_ods_successors, regions=regions, loc=loc, ip=ip)

  @builtins.property
  def target(self) -> _ods_ir.Value:
    return self.operation.operands[0]

  @builtins.property
  def inputToTranspose(self) -> _ods_ir.Attribute:
    return self.operation.attributes["inputToTranspose"]

  @inputToTranspose.setter
  def inputToTranspose(self, value: _ods_ir.Attribute):
    if value is None:
      raise ValueError("'None' not allowed as value for mandatory attributes")
    self.operation.attributes["inputToTranspose"] = value

  @builtins.property
  def transformed(self) -> _ods_ir.OpResult:
    return self.operation.results[0]

@_ods_cext.register_op_adaptor(TransposeMatmulOp)
class TransposeMatmulOpAdaptor(_ods_ir.OpAdaptor):
  OPERATION_NAME = "transform.structured.transpose_matmul"

  @builtins.property
  def target(self) -> _ods_ir.Value:
    return self.operands[0]

  @builtins.property
  def inputToTranspose(self) -> _ods_ir.Attribute:
    return self.attributes["inputToTranspose"]

def structured_transpose_matmul(transformed: _ods_ir.Type, target: _ods_ir.Value, *, input_to_transpose: _Optional[_Union[_Any, _ods_ir.Attribute]] = None, loc: _Optional[_ods_ir.Location] = None, ip: _Optional[_ods_ir.InsertionPoint] = None) -> _ods_ir.OpResult:
  return TransposeMatmulOp(transformed=transformed, target=target, inputToTranspose=input_to_transpose, loc=loc, ip=ip).result

@_ods_cext.register_operation(_Dialect)
class VectorizeChildrenAndApplyPatternsOp(_ods_ir.OpView):
  r"""
  Vectorizes all children contained in the given `target` using the
  configuration specified by the attributes of this op. This only vectorizes
  structured ops that operate on shaped types and does not vectorize loops or
  straight-line. Internally, it applies a set of rewrite patterns, some of
  which enable vectorization and some of which clean up the results.
  Therefore, it can only be applied to an op with the "isolated from above"
  property. This transformation only fails if the entire pattern rewriting
  failed, i.e., it does **not** fail when no ops were vectorized.
  
  Finer granularity can be achieved either with the `VectorizeOp` for
  individual ops or by outlining the target part of the payload IR into, e.g.,
  a function, performing this transformation, and inlining it back.
  
  Note that this transformation invalidates the handles to any payload IR
  operation that is contained inside the vectorization target.
  
  This transformation supports the following attributes:
  - `fold_type_extensions_into_contract`: a `UnitAttr` to enable the folding of
    type extension operations into `vector.contract` to create a mixed precision
    operation.
  - `vectorize_padding`: a `UnitAttr` to activate the vectorization of
    `tensor.pad` ops. Different pipelines may prefer to lower such ops to
    loops.
  - `disable_multi_reduction_to_contract_patterns`: a `UnitAttr` to deactivate
    the rewrite of `vector.multi_reduction` to `vector.contract`. This is
    intended to be used in tests only.
  - `disable_transfer_permutation_map_lowering_patterns`: a `UnitAttr` to
    deactivate the rewrite of `vector.transfer` with permutation maps into
    explicit `vector.transpose` operations. This is intended to be used in
    tests only but may be promoted to a first class attribute in the future.
  
  #### Return modes:
  
  This operation produces a definite failure if vectorization fails for any
  reason.
  The operation always returns the handle to the target op that is expected
  to be isolated from above.
  """

  OPERATION_NAME = "transform.structured.vectorize_children_and_apply_patterns"

  _ODS_REGIONS = (0, True)

  def __init__(self, transformed: _ods_ir.Type, target: _ods_ir.Value, *, fold_type_extensions_into_contract: _Optional[bool] = None, vectorize_padding: _Optional[bool] = None, vectorize_nd_extract: _Optional[bool] = None, flatten_1d_depthwise_conv: _Optional[bool] = None, disable_multi_reduction_to_contract_patterns: _Optional[bool] = None, disable_transfer_permutation_map_lowering_patterns: _Optional[bool] = None, loc: _Optional[_ods_ir.Location] = None, ip: _Optional[_ods_ir.InsertionPoint] = None):
    operands = []
    attributes = {}
    regions = None
    operands.append(target)
    _ods_context = _ods_get_default_loc_context(loc)
    if bool(fold_type_extensions_into_contract): attributes["fold_type_extensions_into_contract"] = _ods_ir.UnitAttr.get(
      _ods_get_default_loc_context(loc))
    if bool(vectorize_padding): attributes["vectorize_padding"] = _ods_ir.UnitAttr.get(
      _ods_get_default_loc_context(loc))
    if bool(vectorize_nd_extract): attributes["vectorize_nd_extract"] = _ods_ir.UnitAttr.get(
      _ods_get_default_loc_context(loc))
    if bool(flatten_1d_depthwise_conv): attributes["flatten_1d_depthwise_conv"] = _ods_ir.UnitAttr.get(
      _ods_get_default_loc_context(loc))
    if bool(disable_multi_reduction_to_contract_patterns): attributes["disable_multi_reduction_to_contract_patterns"] = _ods_ir.UnitAttr.get(
      _ods_get_default_loc_context(loc))
    if bool(disable_transfer_permutation_map_lowering_patterns): attributes["disable_transfer_permutation_map_lowering_patterns"] = _ods_ir.UnitAttr.get(
      _ods_get_default_loc_context(loc))
    results = []
    results.append(transformed)
    _ods_successors = None
    super().__init__(self.OPERATION_NAME, self._ODS_REGIONS, self._ODS_OPERAND_SEGMENTS, self._ODS_RESULT_SEGMENTS, attributes=attributes, results=results, operands=operands, successors=_ods_successors, regions=regions, loc=loc, ip=ip)

  @builtins.property
  def target(self) -> _ods_ir.Value:
    return self.operation.operands[0]

  @builtins.property
  def fold_type_extensions_into_contract(self) -> bool:
    return "fold_type_extensions_into_contract" in self.operation.attributes

  @fold_type_extensions_into_contract.setter
  def fold_type_extensions_into_contract(self, value):
    if bool(value):
      self.operation.attributes["fold_type_extensions_into_contract"] = _ods_ir.UnitAttr.get()
    elif "fold_type_extensions_into_contract" in self.operation.attributes:
      del self.operation.attributes["fold_type_extensions_into_contract"]

  @fold_type_extensions_into_contract.deleter
  def fold_type_extensions_into_contract(self):
    del self.operation.attributes["fold_type_extensions_into_contract"]

  @builtins.property
  def vectorize_padding(self) -> bool:
    return "vectorize_padding" in self.operation.attributes

  @vectorize_padding.setter
  def vectorize_padding(self, value):
    if bool(value):
      self.operation.attributes["vectorize_padding"] = _ods_ir.UnitAttr.get()
    elif "vectorize_padding" in self.operation.attributes:
      del self.operation.attributes["vectorize_padding"]

  @vectorize_padding.deleter
  def vectorize_padding(self):
    del self.operation.attributes["vectorize_padding"]

  @builtins.property
  def vectorize_nd_extract(self) -> bool:
    return "vectorize_nd_extract" in self.operation.attributes

  @vectorize_nd_extract.setter
  def vectorize_nd_extract(self, value):
    if bool(value):
      self.operation.attributes["vectorize_nd_extract"] = _ods_ir.UnitAttr.get()
    elif "vectorize_nd_extract" in self.operation.attributes:
      del self.operation.attributes["vectorize_nd_extract"]

  @vectorize_nd_extract.deleter
  def vectorize_nd_extract(self):
    del self.operation.attributes["vectorize_nd_extract"]

  @builtins.property
  def flatten_1d_depthwise_conv(self) -> bool:
    return "flatten_1d_depthwise_conv" in self.operation.attributes

  @flatten_1d_depthwise_conv.setter
  def flatten_1d_depthwise_conv(self, value):
    if bool(value):
      self.operation.attributes["flatten_1d_depthwise_conv"] = _ods_ir.UnitAttr.get()
    elif "flatten_1d_depthwise_conv" in self.operation.attributes:
      del self.operation.attributes["flatten_1d_depthwise_conv"]

  @flatten_1d_depthwise_conv.deleter
  def flatten_1d_depthwise_conv(self):
    del self.operation.attributes["flatten_1d_depthwise_conv"]

  @builtins.property
  def disable_multi_reduction_to_contract_patterns(self) -> bool:
    return "disable_multi_reduction_to_contract_patterns" in self.operation.attributes

  @disable_multi_reduction_to_contract_patterns.setter
  def disable_multi_reduction_to_contract_patterns(self, value):
    if bool(value):
      self.operation.attributes["disable_multi_reduction_to_contract_patterns"] = _ods_ir.UnitAttr.get()
    elif "disable_multi_reduction_to_contract_patterns" in self.operation.attributes:
      del self.operation.attributes["disable_multi_reduction_to_contract_patterns"]

  @disable_multi_reduction_to_contract_patterns.deleter
  def disable_multi_reduction_to_contract_patterns(self):
    del self.operation.attributes["disable_multi_reduction_to_contract_patterns"]

  @builtins.property
  def disable_transfer_permutation_map_lowering_patterns(self) -> bool:
    return "disable_transfer_permutation_map_lowering_patterns" in self.operation.attributes

  @disable_transfer_permutation_map_lowering_patterns.setter
  def disable_transfer_permutation_map_lowering_patterns(self, value):
    if bool(value):
      self.operation.attributes["disable_transfer_permutation_map_lowering_patterns"] = _ods_ir.UnitAttr.get()
    elif "disable_transfer_permutation_map_lowering_patterns" in self.operation.attributes:
      del self.operation.attributes["disable_transfer_permutation_map_lowering_patterns"]

  @disable_transfer_permutation_map_lowering_patterns.deleter
  def disable_transfer_permutation_map_lowering_patterns(self):
    del self.operation.attributes["disable_transfer_permutation_map_lowering_patterns"]

  @builtins.property
  def transformed(self) -> _ods_ir.OpResult:
    return self.operation.results[0]

@_ods_cext.register_op_adaptor(VectorizeChildrenAndApplyPatternsOp)
class VectorizeChildrenAndApplyPatternsOpAdaptor(_ods_ir.OpAdaptor):
  OPERATION_NAME = "transform.structured.vectorize_children_and_apply_patterns"

  @builtins.property
  def target(self) -> _ods_ir.Value:
    return self.operands[0]

  @builtins.property
  def fold_type_extensions_into_contract(self) -> bool:
    return "fold_type_extensions_into_contract" in self.attributes

  @builtins.property
  def vectorize_padding(self) -> bool:
    return "vectorize_padding" in self.attributes

  @builtins.property
  def vectorize_nd_extract(self) -> bool:
    return "vectorize_nd_extract" in self.attributes

  @builtins.property
  def flatten_1d_depthwise_conv(self) -> bool:
    return "flatten_1d_depthwise_conv" in self.attributes

  @builtins.property
  def disable_multi_reduction_to_contract_patterns(self) -> bool:
    return "disable_multi_reduction_to_contract_patterns" in self.attributes

  @builtins.property
  def disable_transfer_permutation_map_lowering_patterns(self) -> bool:
    return "disable_transfer_permutation_map_lowering_patterns" in self.attributes

def structured_vectorize_children_and_apply_patterns(transformed: _ods_ir.Type, target: _ods_ir.Value, *, fold_type_extensions_into_contract: _Optional[bool] = None, vectorize_padding: _Optional[bool] = None, vectorize_nd_extract: _Optional[bool] = None, flatten_1d_depthwise_conv: _Optional[bool] = None, disable_multi_reduction_to_contract_patterns: _Optional[bool] = None, disable_transfer_permutation_map_lowering_patterns: _Optional[bool] = None, loc: _Optional[_ods_ir.Location] = None, ip: _Optional[_ods_ir.InsertionPoint] = None) -> _ods_ir.OpResult:
  return VectorizeChildrenAndApplyPatternsOp(transformed=transformed, target=target, fold_type_extensions_into_contract=fold_type_extensions_into_contract, vectorize_padding=vectorize_padding, vectorize_nd_extract=vectorize_nd_extract, flatten_1d_depthwise_conv=flatten_1d_depthwise_conv, disable_multi_reduction_to_contract_patterns=disable_multi_reduction_to_contract_patterns, disable_transfer_permutation_map_lowering_patterns=disable_transfer_permutation_map_lowering_patterns, loc=loc, ip=ip).result

@_ods_cext.register_operation(_Dialect)
class VectorizeOp(_ods_ir.OpView):
  r"""
  Vectorize the target ops, which must be Linalg ops.
  
  Use the optional vector sizes to specify exactly what configuration the
  vectorizer should use. It will then use masked vectors of the specified
  size to enforce this configuration ("masked vectorization"). If no vector
  sizes are specified, the vectorizer will infer the shapes to use from the
  target Linalg ops ("regular vectorization"). More specifically:
  
  ```mlir
  # Masked vectorization - vector sizes are specified explicitly
  transform.structured.vectorize %target vector_sizes [1, 4] : !transform.any_op
  # Regular vectorization - vector sizes are inferred from the target Op
  transform.structured.vectorize %target : !transform.any_op
  ```
  
  The vector sizes can be either static or dynamic (SSA values). In case of
  SSA values, the handle must be mapped to exactly one payload op with
  exactly one index-typed result.
  
  Note: The input vector sizes must be bigger than or equal to their
  counterpart iteration space sizes.
  
  Typically this operator should be applied to linalg operations that have
  already been tiled to the appropriate sizes.
  
  #### Return modes:
  
  This operation produces a silenceable failure if at least one target op is
  not a Linalg op or fails to vectorize. It produces a definite failure if
  the dynamic vector sizes (SSA values) do not satisfy the constraints
  mentioned above.
  """

  OPERATION_NAME = "transform.structured.vectorize"

  _ODS_REGIONS = (0, True)

  def __init__(self, target: _ods_ir.Value, vector_sizes: _Sequence[_ods_ir.Value], *, static_vector_sizes: _Optional[_Union[_Sequence[int], _ods_ir.DenseI64ArrayAttr]] = None, vectorize_nd_extract: _Optional[bool] = None, assume_dynamic_dims_match_vec_sizes: _Optional[bool] = None, create_named_contraction: _Optional[bool] = None, scalable_sizes: _Optional[_Union[_Sequence[bool], _ods_ir.DenseBoolArrayAttr]] = None, loc: _Optional[_ods_ir.Location] = None, ip: _Optional[_ods_ir.InsertionPoint] = None):
    operands = []
    attributes = {}
    regions = None
    operands.append(target)
    operands.extend(_get_op_results_or_values(vector_sizes))
    _ods_context = _ods_get_default_loc_context(loc)
    if static_vector_sizes is not None: attributes["static_vector_sizes"] = (static_vector_sizes if (
        isinstance(static_vector_sizes, _ods_ir.Attribute) or
        not _ods_ir.AttrBuilder.contains('DenseI64ArrayAttr')) else
          _ods_ir.AttrBuilder.get('DenseI64ArrayAttr')(static_vector_sizes, context=_ods_context))
    if bool(vectorize_nd_extract): attributes["vectorize_nd_extract"] = _ods_ir.UnitAttr.get(
      _ods_get_default_loc_context(loc))
    if bool(assume_dynamic_dims_match_vec_sizes): attributes["assume_dynamic_dims_match_vec_sizes"] = _ods_ir.UnitAttr.get(
      _ods_get_default_loc_context(loc))
    if bool(create_named_contraction): attributes["create_named_contraction"] = _ods_ir.UnitAttr.get(
      _ods_get_default_loc_context(loc))
    if scalable_sizes is not None: attributes["scalable_sizes"] = (scalable_sizes if (
        isinstance(scalable_sizes, _ods_ir.Attribute) or
        not _ods_ir.AttrBuilder.contains('DenseBoolArrayAttr')) else
          _ods_ir.AttrBuilder.get('DenseBoolArrayAttr')(scalable_sizes, context=_ods_context))
    results = []
    _ods_successors = None
    super().__init__(self.OPERATION_NAME, self._ODS_REGIONS, self._ODS_OPERAND_SEGMENTS, self._ODS_RESULT_SEGMENTS, attributes=attributes, results=results, operands=operands, successors=_ods_successors, regions=regions, loc=loc, ip=ip)

  @builtins.property
  def target(self) -> _ods_ir.Value:
    return self.operation.operands[0]

  @builtins.property
  def vector_sizes(self) -> _ods_ir.OpOperandList:
    _ods_variadic_group_length = len(self.operation.operands) - 2 + 1
    return self.operation.operands[1:1 + _ods_variadic_group_length]

  @builtins.property
  def static_vector_sizes(self) -> _Optional[_ods_ir.DenseI64ArrayAttr]:
    if "static_vector_sizes" not in self.operation.attributes:
      return None
    return self.operation.attributes["static_vector_sizes"]

  @static_vector_sizes.setter
  def static_vector_sizes(self, value: _Optional[_ods_ir.DenseI64ArrayAttr]):
    if value is not None:
      self.operation.attributes["static_vector_sizes"] = value
    elif "static_vector_sizes" in self.operation.attributes:
      del self.operation.attributes["static_vector_sizes"]

  @static_vector_sizes.deleter
  def static_vector_sizes(self):
    del self.operation.attributes["static_vector_sizes"]

  @builtins.property
  def vectorize_nd_extract(self) -> bool:
    return "vectorize_nd_extract" in self.operation.attributes

  @vectorize_nd_extract.setter
  def vectorize_nd_extract(self, value):
    if bool(value):
      self.operation.attributes["vectorize_nd_extract"] = _ods_ir.UnitAttr.get()
    elif "vectorize_nd_extract" in self.operation.attributes:
      del self.operation.attributes["vectorize_nd_extract"]

  @vectorize_nd_extract.deleter
  def vectorize_nd_extract(self):
    del self.operation.attributes["vectorize_nd_extract"]

  @builtins.property
  def assume_dynamic_dims_match_vec_sizes(self) -> bool:
    return "assume_dynamic_dims_match_vec_sizes" in self.operation.attributes

  @assume_dynamic_dims_match_vec_sizes.setter
  def assume_dynamic_dims_match_vec_sizes(self, value):
    if bool(value):
      self.operation.attributes["assume_dynamic_dims_match_vec_sizes"] = _ods_ir.UnitAttr.get()
    elif "assume_dynamic_dims_match_vec_sizes" in self.operation.attributes:
      del self.operation.attributes["assume_dynamic_dims_match_vec_sizes"]

  @assume_dynamic_dims_match_vec_sizes.deleter
  def assume_dynamic_dims_match_vec_sizes(self):
    del self.operation.attributes["assume_dynamic_dims_match_vec_sizes"]

  @builtins.property
  def create_named_contraction(self) -> bool:
    return "create_named_contraction" in self.operation.attributes

  @create_named_contraction.setter
  def create_named_contraction(self, value):
    if bool(value):
      self.operation.attributes["create_named_contraction"] = _ods_ir.UnitAttr.get()
    elif "create_named_contraction" in self.operation.attributes:
      del self.operation.attributes["create_named_contraction"]

  @create_named_contraction.deleter
  def create_named_contraction(self):
    del self.operation.attributes["create_named_contraction"]

  @builtins.property
  def scalable_sizes(self) -> _Optional[_ods_ir.DenseBoolArrayAttr]:
    if "scalable_sizes" not in self.operation.attributes:
      return None
    return self.operation.attributes["scalable_sizes"]

  @scalable_sizes.setter
  def scalable_sizes(self, value: _Optional[_ods_ir.DenseBoolArrayAttr]):
    if value is not None:
      self.operation.attributes["scalable_sizes"] = value
    elif "scalable_sizes" in self.operation.attributes:
      del self.operation.attributes["scalable_sizes"]

  @scalable_sizes.deleter
  def scalable_sizes(self):
    del self.operation.attributes["scalable_sizes"]

@_ods_cext.register_op_adaptor(VectorizeOp)
class VectorizeOpAdaptor(_ods_ir.OpAdaptor):
  OPERATION_NAME = "transform.structured.vectorize"

  @builtins.property
  def target(self) -> _ods_ir.Value:
    return self.operands[0]

  @builtins.property
  def vector_sizes(self) -> _ods_ir.OpOperandList:
    _ods_variadic_group_length = len(self.operands) - 2 + 1
    return self.operands[1:1 + _ods_variadic_group_length]

  @builtins.property
  def static_vector_sizes(self) -> _Optional[_ods_ir.DenseI64ArrayAttr]:
    if "static_vector_sizes" not in self.attributes:
      return None
    return self.attributes["static_vector_sizes"]

  @builtins.property
  def vectorize_nd_extract(self) -> bool:
    return "vectorize_nd_extract" in self.attributes

  @builtins.property
  def assume_dynamic_dims_match_vec_sizes(self) -> bool:
    return "assume_dynamic_dims_match_vec_sizes" in self.attributes

  @builtins.property
  def create_named_contraction(self) -> bool:
    return "create_named_contraction" in self.attributes

  @builtins.property
  def scalable_sizes(self) -> _Optional[_ods_ir.DenseBoolArrayAttr]:
    if "scalable_sizes" not in self.attributes:
      return None
    return self.attributes["scalable_sizes"]

def structured_vectorize(target: _ods_ir.Value, vector_sizes: _Sequence[_ods_ir.Value], *, static_vector_sizes: _Optional[_Union[_Sequence[int], _ods_ir.DenseI64ArrayAttr]] = None, vectorize_nd_extract: _Optional[bool] = None, assume_dynamic_dims_match_vec_sizes: _Optional[bool] = None, create_named_contraction: _Optional[bool] = None, scalable_sizes: _Optional[_Union[_Sequence[bool], _ods_ir.DenseBoolArrayAttr]] = None, loc: _Optional[_ods_ir.Location] = None, ip: _Optional[_ods_ir.InsertionPoint] = None) -> VectorizeOp:
  return VectorizeOp(target=target, vector_sizes=vector_sizes, static_vector_sizes=static_vector_sizes, vectorize_nd_extract=vectorize_nd_extract, assume_dynamic_dims_match_vec_sizes=assume_dynamic_dims_match_vec_sizes, create_named_contraction=create_named_contraction, scalable_sizes=scalable_sizes, loc=loc, ip=ip)

@_ods_cext.register_operation(_Dialect)
class WinogradConv2DOp(_ods_ir.OpView):
  r"""
  Winograd Conv2D algorithm will convert linalg Conv2D operation into batched
  matrix multiply. Before the matrix multiply, it will convert filter and
  input into a format suitable for batched matrix multiply. After the matrix
  multiply, it will convert output to the final result tensor.
  
  The algorithm F(m x m, r x r) is
  
  Y = A^T x [(G x g x G^T) @ (B^T x d x B)] x A
  
  The size of output Y is m x m. The size of filter g is r x r. The size of
  input d is (m + r - 1) x (m + r - 1). A^T, A, G^T, G, B^T, and B are
  transformation matrices.
  
  #### Return modes:
  
  This operation produces a silenceable failure if `target` is unsupported.
  Otherwise, the operation succeeds and returns a handle of the sequence that
  replaces the original convolution.
  """

  OPERATION_NAME = "transform.structured.winograd_conv2d"

  _ODS_REGIONS = (0, True)

  def __init__(self, transformed: _ods_ir.Type, target: _ods_ir.Value, fmr: _Union[_Any, _ods_ir.Attribute], *, loc: _Optional[_ods_ir.Location] = None, ip: _Optional[_ods_ir.InsertionPoint] = None):
    operands = []
    attributes = {}
    regions = None
    operands.append(target)
    _ods_context = _ods_get_default_loc_context(loc)
    attributes["fmr"] = (fmr if (
    isinstance(fmr, _ods_ir.Attribute) or
    not _ods_ir.AttrBuilder.contains('WinogradConv2DFmr')) else
      _ods_ir.AttrBuilder.get('WinogradConv2DFmr')(fmr, context=_ods_context))
    results = []
    results.append(transformed)
    _ods_successors = None
    super().__init__(self.OPERATION_NAME, self._ODS_REGIONS, self._ODS_OPERAND_SEGMENTS, self._ODS_RESULT_SEGMENTS, attributes=attributes, results=results, operands=operands, successors=_ods_successors, regions=regions, loc=loc, ip=ip)

  @builtins.property
  def target(self) -> _ods_ir.Value:
    return self.operation.operands[0]

  @builtins.property
  def fmr(self) -> _ods_ir.Attribute:
    return self.operation.attributes["fmr"]

  @fmr.setter
  def fmr(self, value: _ods_ir.Attribute):
    if value is None:
      raise ValueError("'None' not allowed as value for mandatory attributes")
    self.operation.attributes["fmr"] = value

  @builtins.property
  def transformed(self) -> _ods_ir.OpResult:
    return self.operation.results[0]

@_ods_cext.register_op_adaptor(WinogradConv2DOp)
class WinogradConv2DOpAdaptor(_ods_ir.OpAdaptor):
  OPERATION_NAME = "transform.structured.winograd_conv2d"

  @builtins.property
  def target(self) -> _ods_ir.Value:
    return self.operands[0]

  @builtins.property
  def fmr(self) -> _ods_ir.Attribute:
    return self.attributes["fmr"]

def structured_winograd_conv2d(transformed: _ods_ir.Type, target: _ods_ir.Value, fmr: _Union[_Any, _ods_ir.Attribute], *, loc: _Optional[_ods_ir.Location] = None, ip: _Optional[_ods_ir.InsertionPoint] = None) -> _ods_ir.OpResult:
  return WinogradConv2DOp(transformed=transformed, target=target, fmr=fmr, loc=loc, ip=ip).result
