
# 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 ApplyForLoopCanonicalizationPatternsOp(_ods_ir.OpView):
  r"""
  Collects patterns for canonicalizing operations inside SCF loop bodies.
  At the moment, only affine.min/max computations with iteration variables,
  loop bounds and loop steps are canonicalized.
  """

  OPERATION_NAME = "transform.apply_patterns.scf.for_loop_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(ApplyForLoopCanonicalizationPatternsOp)
class ApplyForLoopCanonicalizationPatternsOpAdaptor(_ods_ir.OpAdaptor):
  OPERATION_NAME = "transform.apply_patterns.scf.for_loop_canonicalization"

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

@_ods_cext.register_operation(_Dialect)
class ApplySCFStructuralConversionPatternsOp(_ods_ir.OpView):
  r"""
  Collects patterns for performing structural conversions of SCF operations.
  """

  OPERATION_NAME = "transform.apply_conversion_patterns.scf.structural_conversions"

  _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(ApplySCFStructuralConversionPatternsOp)
class ApplySCFStructuralConversionPatternsOpAdaptor(_ods_ir.OpAdaptor):
  OPERATION_NAME = "transform.apply_conversion_patterns.scf.structural_conversions"

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

@_ods_cext.register_operation(_Dialect)
class ApplySCFToControlFlowPatternsOp(_ods_ir.OpView):
  r"""
  Collects patterns that lower structured control flow ops to unstructured
  control flow.
  """

  OPERATION_NAME = "transform.apply_conversion_patterns.scf.scf_to_control_flow"

  _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(ApplySCFToControlFlowPatternsOp)
class ApplySCFToControlFlowPatternsOpAdaptor(_ods_ir.OpAdaptor):
  OPERATION_NAME = "transform.apply_conversion_patterns.scf.scf_to_control_flow"

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

@_ods_cext.register_operation(_Dialect)
class ForallToForOp(_ods_ir.OpView):
  r"""
  Converts the `scf.forall` operation pointed to by the given handle into a
  set of nested `scf.for` operations. Each new operation corresponds to one
  induction variable of the original "multifor" loop.
  
  The operand handle must be associated with exactly one payload operation.
  
  Loops with shared outputs are currently not supported.
  
  #### Return Modes
  
  Consumes the operand handle. Produces a silenceable failure if the operand
  is not associated with a single `scf.forall` payload operation.
  Returns as many handles as the given `forall` op has induction variables
  that are associated with the generated `scf.for` loops.
  Produces a silenceable failure if another number of resulting handles is
  requested.
  """

  OPERATION_NAME = "transform.loop.forall_to_for"

  _ODS_REGIONS = (0, True)

  def __init__(self, transformed: _Sequence[_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.extend(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.OpResultList:
    _ods_variadic_group_length = len(self.operation.results) - 1 + 1
    return self.operation.results[0:0 + _ods_variadic_group_length]

@_ods_cext.register_op_adaptor(ForallToForOp)
class ForallToForOpAdaptor(_ods_ir.OpAdaptor):
  OPERATION_NAME = "transform.loop.forall_to_for"

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

def loop_forall_to_for(transformed: _Sequence[_ods_ir.Type], target: _ods_ir.Value, *, loc: _Optional[_ods_ir.Location] = None, ip: _Optional[_ods_ir.InsertionPoint] = None) -> _Union[_ods_ir.OpResult, _ods_ir.OpResultList, ForallToForOp]:
  op = ForallToForOp(transformed=transformed, target=target, 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 ForallToParallelOp(_ods_ir.OpView):
  r"""
  Converts the `scf.forall` operation pointed to by the given handle into an
  `scf.parallel` operation.
  
  The operand handle must be associated with exactly one payload operation.
  
  Loops with outputs are not supported.
  
  #### Return Modes
  
  Consumes the operand handle. Produces a silenceable failure if the operand
  is not associated with a single `scf.forall` payload operation.
  Returns a handle to the new `scf.parallel` operation.
  Produces a silenceable failure if another number of resulting handles is
  requested.
  """

  OPERATION_NAME = "transform.loop.forall_to_parallel"

  _ODS_REGIONS = (0, True)

  def __init__(self, transformed: _Sequence[_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.extend(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.OpResultList:
    _ods_variadic_group_length = len(self.operation.results) - 1 + 1
    return self.operation.results[0:0 + _ods_variadic_group_length]

@_ods_cext.register_op_adaptor(ForallToParallelOp)
class ForallToParallelOpAdaptor(_ods_ir.OpAdaptor):
  OPERATION_NAME = "transform.loop.forall_to_parallel"

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

def loop_forall_to_parallel(transformed: _Sequence[_ods_ir.Type], target: _ods_ir.Value, *, loc: _Optional[_ods_ir.Location] = None, ip: _Optional[_ods_ir.InsertionPoint] = None) -> _Union[_ods_ir.OpResult, _ods_ir.OpResultList, ForallToParallelOp]:
  op = ForallToParallelOp(transformed=transformed, target=target, 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 HoistLoopInvariantSubsetsOp(_ods_ir.OpView):
  r"""
  This transform hoists loop-invariant subset ops out of the targeted
  loop-like op. It looks for matching subset extraction/insertion op pairs and
  hoists them. The loop body operates on a newly introduced region iter_arg.
  
  Subset ops are hoisted only from the targeted op. If subset ops should be
  hoisted from an entire loop nest, this transformation must be applied to
  each loop-like op of the loop nest, starting with the innermost loop and
  ending with the outermost loop.
  
  Example:
  ```
  %r = scf.for ... iter_args(%t = %a) -> (tensor<?xf32>) {
    %0 = tensor.extract_slice %t[0][5][1] : tensor<?xf32> to tensor<5xf32>
    %1 = "test.foo"(%0) : (tensor<5xf32>) -> (tensor<5xf32>)
    %2 = tensor.insert_slice %1 into %t[0][5][1]
        : tensor<5xf32> into tensor<?xf32>
    scf.yield %2 : tensor<?xf32>
  }
  ```
  Is transformed to:
  ```
  %0 = tensor.extract_slice %a[0][5][1] : tensor<?xf32> to tensor<5xf32>
  %new_loop:2 = scf.for ... iter_args(%t = %a, %h = %0) -> (tensor<?xf32>) {
    %1 = "test.foo"(%h) : (tensor<5xf32>) -> (tensor<5xf32>)
    scf.yield %t, %2 : tensor<?xf32>, tensor<5xf32>
  }
  %r = tensor.insert_slice %new_loop#1 into %new_loop#0
      : tensor<5xf32> into tensor<?xf32>
  ```
  
  Subset ops are hoisted only if there are no conflicting subset ops. E.g.,
  if there were a second overlapping extraction in the above example, no ops
  could be hoisted safely.
  
  This transform reads the target handle and modifies the payload. This
  transform does not invalidate any handles, but loop-like ops are replaced
  with new loop-like ops when a subset op is hoisted. The transform rewriter
  updates all handles accordingly.
  """

  OPERATION_NAME = "transform.loop.hoist_loop_invariant_subsets"

  _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(HoistLoopInvariantSubsetsOp)
class HoistLoopInvariantSubsetsOpAdaptor(_ods_ir.OpAdaptor):
  OPERATION_NAME = "transform.loop.hoist_loop_invariant_subsets"

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

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

@_ods_cext.register_operation(_Dialect)
class LoopCoalesceNestedOp(_ods_ir.OpView):
  r"""
  Given a loop, collects all nested loops (including imperfectly nested
  loops with operations between them) and coalesces them directly using
  coalesceLoops.
  
  #### Return modes
  
  The return handle points to the coalesced loop.
  """

  OPERATION_NAME = "transform.loop.coalesce_nested"

  _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(LoopCoalesceNestedOp)
class LoopCoalesceNestedOpAdaptor(_ods_ir.OpAdaptor):
  OPERATION_NAME = "transform.loop.coalesce_nested"

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

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

@_ods_cext.register_operation(_Dialect)
class LoopCoalesceOp(_ods_ir.OpView):
  r"""
  Given a perfect loop nest identified by the outermost loop,
  perform loop coalescing in a bottom-up one-by-one manner.
  
  #### Return modes
  
  The return handle points to the coalesced loop if coalescing happens, or
  the given input loop if coalescing does not happen.
  """

  OPERATION_NAME = "transform.loop.coalesce"

  _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(LoopCoalesceOp)
class LoopCoalesceOpAdaptor(_ods_ir.OpAdaptor):
  OPERATION_NAME = "transform.loop.coalesce"

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

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

@_ods_cext.register_operation(_Dialect)
class LoopFuseSiblingOp(_ods_ir.OpView):
  r"""
  Fuses the `target` loop into the `source` loop assuming they are
  independent of each other. In the fused loop, the arguments, body and
  results of `target` are placed _before_ those of `source`.
  
  For fusion of two `scf.for` loops, the bounds and step size must match. For
  fusion of two `scf.forall` loops, the bounds and the mapping must match.
  Otherwise a silencable failure is produced.
  
  The `target` and `source` handles must refer to exactly one operation,
  otherwise a definite failure is produced. It is the responsibility of the
  user to ensure that the `target` and `source` loops are independent of each
  other -- this op will only perform rudimentary legality checks.
  
  #### Return modes
  
  This operation consumes the `target` and `source` handles and produces the
  `fused_loop` handle, which points to the fused loop.
  """

  OPERATION_NAME = "transform.loop.fuse_sibling"

  _ODS_REGIONS = (0, True)

  def __init__(self, fused_loop: _ods_ir.Type, target: _ods_ir.Value, source: _ods_ir.Value, *, loc: _Optional[_ods_ir.Location] = None, ip: _Optional[_ods_ir.InsertionPoint] = None):
    operands = []
    attributes = {}
    regions = None
    operands.append(target)
    operands.append(source)
    _ods_context = _ods_get_default_loc_context(loc)
    results = []
    results.append(fused_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 source(self) -> _ods_ir.Value:
    return self.operation.operands[1]

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

@_ods_cext.register_op_adaptor(LoopFuseSiblingOp)
class LoopFuseSiblingOpAdaptor(_ods_ir.OpAdaptor):
  OPERATION_NAME = "transform.loop.fuse_sibling"

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

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

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

@_ods_cext.register_operation(_Dialect)
class LoopOutlineOp(_ods_ir.OpView):
  r"""
  Moves the loop into a separate function with the specified name and replaces
  the loop in the Payload IR with a call to that function. Takes care of
  forwarding values that are used in the loop as function arguments. If the
  operand is associated with more than one loop, each loop will be outlined
  into a separate function. The provided name is used as a _base_ for forming
  actual function names following `SymbolTable` auto-renaming scheme to avoid
  duplicate symbols. Expects that all ops in the Payload IR have a
  `SymbolTable` ancestor (typically true because of the top-level module).
  
  #### Return Modes
  
  Returns a handle to the list of outlined functions and a handle to the
  corresponding function call operations in the same order as the operand
  handle.
  
  Produces a definite failure if outlining failed for any of the targets.
  """

  OPERATION_NAME = "transform.loop.outline"

  _ODS_REGIONS = (0, True)

  def __init__(self, function: _ods_ir.Type, call: _ods_ir.Type, target: _ods_ir.Value, func_name: _Union[str, _ods_ir.StringAttr], *, 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["func_name"] = (func_name if (
    isinstance(func_name, _ods_ir.Attribute) or
    not _ods_ir.AttrBuilder.contains('StrAttr')) else
      _ods_ir.AttrBuilder.get('StrAttr')(func_name, context=_ods_context))
    results = []
    results.append(function)
    results.append(call)
    _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 func_name(self) -> _ods_ir.StringAttr:
    return self.operation.attributes["func_name"]

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

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

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

@_ods_cext.register_op_adaptor(LoopOutlineOp)
class LoopOutlineOpAdaptor(_ods_ir.OpAdaptor):
  OPERATION_NAME = "transform.loop.outline"

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

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

def loop_outline(function: _ods_ir.Type, call: _ods_ir.Type, target: _ods_ir.Value, func_name: _Union[str, _ods_ir.StringAttr], *, loc: _Optional[_ods_ir.Location] = None, ip: _Optional[_ods_ir.InsertionPoint] = None) -> _ods_ir.OpResultList:
  return LoopOutlineOp(function=function, call=call, target=target, func_name=func_name, loc=loc, ip=ip).results

@_ods_cext.register_operation(_Dialect)
class LoopPeelOp(_ods_ir.OpView):
  r"""
  Rewrite the given loop with a main loop and a partial (first or last) loop.
  When the `peelFront` option is set to true, the first iteration is peeled off.
  Otherwise, updates the given loop so that its step evenly divides its range and puts
  the remaining iteration into a separate loop or a conditional.
  
  In the absence of sufficient static information, this op may peel a loop,
  even if the step always divides the range evenly at runtime.
  
  #### Return modes
  
  This operation ignores non-scf::ForOp ops and drops them in the return.
  The op returns two loops, the peeled loop which has trip count divisible
  by the step, and the remainder loop.
  
  When `peelFront` is true, the first result (remainder loop) executes all
  but the first iteration of the target loop. The second result (peeled
  loop) corresponds to the first iteration of the loop which can be
  canonicalized away in the following optimizations.
  
  When `peelFront` is false, the first result (peeled loop) is the portion
  of the target loop with the highest upper bound that is divisible by the
  step. The second result (remainder loop) contains the remaining iterations. 
  
  Note that even though the Payload IR modification may be performed
  in-place, this operation consumes the operand handle and produces a new one.
  
  #### Return Modes
  
  Produces a definite failure if peeling fails.
  """

  OPERATION_NAME = "transform.loop.peel"

  _ODS_REGIONS = (0, True)

  def __init__(self, peeled_loop: _ods_ir.Type, remainder_loop: _ods_ir.Type, target: _ods_ir.Value, *, peel_front: _Optional[_Union[bool, _ods_ir.BoolAttr]] = None, fail_if_already_divisible: _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 peel_front is not None: attributes["peel_front"] = (peel_front if (
        isinstance(peel_front, _ods_ir.Attribute) or
        not _ods_ir.AttrBuilder.contains('BoolAttr')) else
          _ods_ir.AttrBuilder.get('BoolAttr')(peel_front, context=_ods_context))
    if fail_if_already_divisible is not None: attributes["fail_if_already_divisible"] = (fail_if_already_divisible if (
        isinstance(fail_if_already_divisible, _ods_ir.Attribute) or
        not _ods_ir.AttrBuilder.contains('BoolAttr')) else
          _ods_ir.AttrBuilder.get('BoolAttr')(fail_if_already_divisible, context=_ods_context))
    results = []
    results.append(peeled_loop)
    results.append(remainder_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 peel_front(self) -> _ods_ir.BoolAttr:
    return self.operation.attributes["peel_front"]

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

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

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

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

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

@_ods_cext.register_op_adaptor(LoopPeelOp)
class LoopPeelOpAdaptor(_ods_ir.OpAdaptor):
  OPERATION_NAME = "transform.loop.peel"

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

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

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

def loop_peel(peeled_loop: _ods_ir.Type, remainder_loop: _ods_ir.Type, target: _ods_ir.Value, *, peel_front: _Optional[_Union[bool, _ods_ir.BoolAttr]] = None, fail_if_already_divisible: _Optional[_Union[bool, _ods_ir.BoolAttr]] = None, loc: _Optional[_ods_ir.Location] = None, ip: _Optional[_ods_ir.InsertionPoint] = None) -> _ods_ir.OpResultList:
  return LoopPeelOp(peeled_loop=peeled_loop, remainder_loop=remainder_loop, target=target, peel_front=peel_front, fail_if_already_divisible=fail_if_already_divisible, loc=loc, ip=ip).results

@_ods_cext.register_operation(_Dialect)
class LoopPipelineOp(_ods_ir.OpView):
  r"""
  Transforms the given loops one by one to achieve software pipelining for
  each of them. That is, performs some amount of reads from memory before the
  loop rather than inside the loop, the same amount of writes into memory
  after the loop, and updates each iteration to read the data for a following
  iteration rather than the current one.
  
  The amount is specified by the attributes.
  
  The values read and about to be stored are transferred as loop iteration
  arguments. Currently supports memref and vector transfer operations as
  memory reads/writes.
  
  #### Return modes
  
  This operation ignores non-scf::For ops and drops them in the return.
  If all the operations referred to by the `target` PDLOperation pipeline
  properly, the transform succeeds. Otherwise the transform produces a
  silenceable failure.  The return handle points to only the subset of
  successfully produced pipelined loops, which can be empty.
  """

  OPERATION_NAME = "transform.loop.pipeline"

  _ODS_REGIONS = (0, True)

  def __init__(self, transformed: _ods_ir.Type, target: _ods_ir.Value, *, iteration_interval: _Optional[_Union[int, _ods_ir.IntegerAttr]] = None, read_latency: _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 iteration_interval is not None: attributes["iteration_interval"] = (iteration_interval if (
        isinstance(iteration_interval, _ods_ir.Attribute) or
        not _ods_ir.AttrBuilder.contains('I64Attr')) else
          _ods_ir.AttrBuilder.get('I64Attr')(iteration_interval, context=_ods_context))
    if read_latency is not None: attributes["read_latency"] = (read_latency if (
        isinstance(read_latency, _ods_ir.Attribute) or
        not _ods_ir.AttrBuilder.contains('I64Attr')) else
          _ods_ir.AttrBuilder.get('I64Attr')(read_latency, 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 iteration_interval(self) -> _ods_ir.IntegerAttr:
    return self.operation.attributes["iteration_interval"]

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

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

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

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

@_ods_cext.register_op_adaptor(LoopPipelineOp)
class LoopPipelineOpAdaptor(_ods_ir.OpAdaptor):
  OPERATION_NAME = "transform.loop.pipeline"

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

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

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

def loop_pipeline(transformed: _ods_ir.Type, target: _ods_ir.Value, *, iteration_interval: _Optional[_Union[int, _ods_ir.IntegerAttr]] = None, read_latency: _Optional[_Union[int, _ods_ir.IntegerAttr]] = None, loc: _Optional[_ods_ir.Location] = None, ip: _Optional[_ods_ir.InsertionPoint] = None) -> _ods_ir.OpResult:
  return LoopPipelineOp(transformed=transformed, target=target, iteration_interval=iteration_interval, read_latency=read_latency, loc=loc, ip=ip).result

@_ods_cext.register_operation(_Dialect)
class LoopPromoteIfOneIterationOp(_ods_ir.OpView):
  r"""
  Promotes the given target loop op if it has a single iteration. I.e., the
  loop op is removed and only the body remains.
  
  #### Return modes
  
  This transform fails if the target is mapped to ops that are loops. Ops are
  considered loops if they implement the `LoopLikeOpInterface`. Otherwise,
  this transform always succeeds. The transform consumes the target handle and
  modifies the payload.
  """

  OPERATION_NAME = "transform.loop.promote_if_one_iteration"

  _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(LoopPromoteIfOneIterationOp)
class LoopPromoteIfOneIterationOpAdaptor(_ods_ir.OpAdaptor):
  OPERATION_NAME = "transform.loop.promote_if_one_iteration"

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

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

@_ods_cext.register_operation(_Dialect)
class LoopUnrollAndJamOp(_ods_ir.OpView):
  r"""
  Unrolls & jams each loop associated with the given handle to have up to the given
  number of loop body copies per iteration. If the unroll factor is larger
  than the loop trip count, the latter is used as the unroll factor instead.
  
  #### Return modes
  
  This operation ignores non-`scf.for`, non-`affine.for` ops and drops them
  in the return. If all the operations referred to by the `target` operand
  unroll properly, the transform succeeds. Otherwise the transform produces a
  silenceable failure.
  
  Does not return handles as the operation may result in the loop being
  removed after a full unrolling.
  """

  OPERATION_NAME = "transform.loop.unroll_and_jam"

  _ODS_REGIONS = (0, True)

  def __init__(self, target: _ods_ir.Value, factor: _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["factor"] = (factor if (
    isinstance(factor, _ods_ir.Attribute) or
    not _ods_ir.AttrBuilder.contains('I64Attr')) else
      _ods_ir.AttrBuilder.get('I64Attr')(factor, 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 factor(self) -> _ods_ir.IntegerAttr:
    return self.operation.attributes["factor"]

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

@_ods_cext.register_op_adaptor(LoopUnrollAndJamOp)
class LoopUnrollAndJamOpAdaptor(_ods_ir.OpAdaptor):
  OPERATION_NAME = "transform.loop.unroll_and_jam"

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

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

def loop_unroll_and_jam(target: _ods_ir.Value, factor: _Union[int, _ods_ir.IntegerAttr], *, loc: _Optional[_ods_ir.Location] = None, ip: _Optional[_ods_ir.InsertionPoint] = None) -> LoopUnrollAndJamOp:
  return LoopUnrollAndJamOp(target=target, factor=factor, loc=loc, ip=ip)

@_ods_cext.register_operation(_Dialect)
class LoopUnrollOp(_ods_ir.OpView):
  r"""
  Unrolls each loop associated with the given handle to have up to the given
  number of loop body copies per iteration. If the unroll factor is larger
  than the loop trip count, the latter is used as the unroll factor instead.
  
  #### Return modes
  
  This operation ignores non-`scf.for`, non-`affine.for` ops and drops them
  in the return. If all the operations referred to by the `target` operand
  unroll properly, the transform succeeds. Otherwise the transform produces a
  silenceable failure.
  
  Does not return handles as the operation may result in the loop being
  removed after a full unrolling.
  """

  OPERATION_NAME = "transform.loop.unroll"

  _ODS_REGIONS = (0, True)

  def __init__(self, target: _ods_ir.Value, factor: _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["factor"] = (factor if (
    isinstance(factor, _ods_ir.Attribute) or
    not _ods_ir.AttrBuilder.contains('I64Attr')) else
      _ods_ir.AttrBuilder.get('I64Attr')(factor, 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 factor(self) -> _ods_ir.IntegerAttr:
    return self.operation.attributes["factor"]

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

@_ods_cext.register_op_adaptor(LoopUnrollOp)
class LoopUnrollOpAdaptor(_ods_ir.OpAdaptor):
  OPERATION_NAME = "transform.loop.unroll"

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

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

def loop_unroll(target: _ods_ir.Value, factor: _Union[int, _ods_ir.IntegerAttr], *, loc: _Optional[_ods_ir.Location] = None, ip: _Optional[_ods_ir.InsertionPoint] = None) -> LoopUnrollOp:
  return LoopUnrollOp(target=target, factor=factor, loc=loc, ip=ip)

@_ods_cext.register_operation(_Dialect)
class ParallelForToNestedForOps(_ods_ir.OpView):
  r"""
  Converts the `scf.parallel` operation pointed to by the given handle into a
  set of nested `scf.for` operations. Each new operation corresponds to one
  dimension of the original parallel loop.
  
  The operand handle must be associated with exactly one payload operation.
  
  Loops with shared outputs are currently not supported.
  
  #### Return Modes
  
  Consumes the operand handle. Produces a silenceable failure if the operand
  is not associated with a single `scf.parallel` payload operation.
  Returns as many handles as the given `parallel` op has dimensions that are
  associated with the generated `scf.for` loops.
  Produces a silenceable failure if another number of resulting handles is
  requested.
  """

  OPERATION_NAME = "transform.loop.parallel_for_to_nested_fors"

  _ODS_REGIONS = (0, True)

  def __init__(self, transformed: _Sequence[_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.extend(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.OpResultList:
    _ods_variadic_group_length = len(self.operation.results) - 1 + 1
    return self.operation.results[0:0 + _ods_variadic_group_length]

@_ods_cext.register_op_adaptor(ParallelForToNestedForOps)
class ParallelForToNestedForOpsAdaptor(_ods_ir.OpAdaptor):
  OPERATION_NAME = "transform.loop.parallel_for_to_nested_fors"

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

def loop_parallel_for_to_nested_fors(transformed: _Sequence[_ods_ir.Type], target: _ods_ir.Value, *, loc: _Optional[_ods_ir.Location] = None, ip: _Optional[_ods_ir.InsertionPoint] = None) -> _Union[_ods_ir.OpResult, _ods_ir.OpResultList, ParallelForToNestedForOps]:
  op = ParallelForToNestedForOps(transformed=transformed, target=target, 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 TakeAssumedBranchOp(_ods_ir.OpView):
  r"""
  Given an scf.if conditional, inject user-defined information that it is
  always safe to execute only the if or else branch.
  
  This is achieved by just replacing the scf.if by the content of one of its
  branches.
  
  This is particularly useful for user-controlled rewriting of conditionals
  that exist solely to guard against out-of-bounds behavior.
  
  At the moment, no assume or assert operation is emitted as it is not always
  desirable. In the future, this may be controlled by a dedicated attribute.
  
  #### Return modes
  
  The transform only consumes its operand and does not produce any result.
  The transform definitely fails if `take_else_branch` is specified and the
  `else` region is empty.
  """

  OPERATION_NAME = "transform.scf.take_assumed_branch"

  _ODS_REGIONS = (0, True)

  def __init__(self, target: _ods_ir.Value, *, take_else_branch: _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(take_else_branch): attributes["take_else_branch"] = _ods_ir.UnitAttr.get(
      _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]

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

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

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

@_ods_cext.register_op_adaptor(TakeAssumedBranchOp)
class TakeAssumedBranchOpAdaptor(_ods_ir.OpAdaptor):
  OPERATION_NAME = "transform.scf.take_assumed_branch"

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

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

def scf_take_assumed_branch(target: _ods_ir.Value, *, take_else_branch: _Optional[bool] = None, loc: _Optional[_ods_ir.Location] = None, ip: _Optional[_ods_ir.InsertionPoint] = None) -> TakeAssumedBranchOp:
  return TakeAssumedBranchOp(target=target, take_else_branch=take_else_branch, loc=loc, ip=ip)
