pub struct ForOperation<'c> { /* private fields */ }
Expand description

A for operation. For operation.

The scf.for operation represents a loop taking 3 SSA value as operands that represent the lower bound, upper bound and step respectively. The operation defines an SSA value for its induction variable. It has one region capturing the loop body. The induction variable is represented as an argument of this region. This SSA value is a signless integer or index. The step is a value of same type but required to be positive. The lower and upper bounds specify a half-open range: the range includes the lower bound but does not include the upper bound.

The body region must contain exactly one block that terminates with scf.yield. Calling ForOp::build will create such a region and insert the terminator implicitly if none is defined, so will the parsing even in cases when it is absent from the custom format. For example:

// Index case.
scf.for %iv = %lb to %ub step %step {
  ... // body
}
...
// Integer case.
scf.for %iv_32 = %lb_32 to %ub_32 step %step_32 : i32 {
  ... // body
}

scf.for can also operate on loop-carried variables and returns the final values after loop termination. The initial values of the variables are passed as additional SSA operands to the scf.for following the 3 loop control SSA values mentioned above (lower bound, upper bound and step). The operation region has an argument for the induction variable, followed by one argument for each loop-carried variable, representing the value of the variable at the current iteration.

The region must terminate with a scf.yield that passes the current values of all loop-carried variables to the next iteration, or to the scf.for result, if at the last iteration. The static type of a loop-carried variable may not change with iterations; its runtime type is allowed to change. Note, that when the loop-carried variables are present, calling ForOp::build will not insert the terminator implicitly. The caller must insert scf.yield in that case.

scf.for results hold the final values after the last iteration. For example, to sum-reduce a memref:

func.func @reduce(%buffer: memref<1024xf32>, %lb: index,
                  %ub: index, %step: index) -> (f32) {
  // Initial sum set to 0.
  %sum_0 = arith.constant 0.0 : f32
  // iter_args binds initial values to the loop's region arguments.
  %sum = scf.for %iv = %lb to %ub step %step
      iter_args(%sum_iter = %sum_0) -> (f32) {
    %t = load %buffer[%iv] : memref<1024xf32>
    %sum_next = arith.addf %sum_iter, %t : f32
    // Yield current iteration sum to next iteration %sum_iter or to %sum
    // if final iteration.
    scf.yield %sum_next : f32
  }
  return %sum : f32
}

If the scf.for defines any values, a yield must be explicitly present. The number and types of the scf.for results must match the initial values in the iter_args binding and the yield operands.

Another example with a nested scf.if (see scf.if for details) to perform conditional reduction:

func.func @conditional_reduce(%buffer: memref<1024xf32>, %lb: index,
                              %ub: index, %step: index) -> (f32) {
  %sum_0 = arith.constant 0.0 : f32
  %c0 = arith.constant 0.0 : f32
  %sum = scf.for %iv = %lb to %ub step %step
      iter_args(%sum_iter = %sum_0) -> (f32) {
    %t = load %buffer[%iv] : memref<1024xf32>
    %cond = arith.cmpf "ugt", %t, %c0 : f32
    %sum_next = scf.if %cond -> (f32) {
      %new_sum = arith.addf %sum_iter, %t : f32
      scf.yield %new_sum : f32
    } else {
      scf.yield %sum_iter : f32
    }
    scf.yield %sum_next : f32
  }
  return %sum : f32
}

Implementations§

source§

impl<'c> ForOperation<'c>

source

pub fn name() -> &'static str

Returns a name.

source

pub fn as_operation(&self) -> &Operation<'c>

Returns a generic operation.

source

pub fn builder( context: &'c Context, location: Location<'c> ) -> ForOperationBuilder<'c, Unset, Unset, Unset, Unset, Unset, Unset>

Creates a builder.

source

pub fn results(&self) -> impl Iterator<Item = OperationResult<'c, '_>>

source

pub fn lower_bound(&self) -> Result<Value<'c, '_>, Error>

source

pub fn upper_bound(&self) -> Result<Value<'c, '_>, Error>

source

pub fn step(&self) -> Result<Value<'c, '_>, Error>

source

pub fn init_args(&self) -> impl Iterator<Item = Value<'c, '_>>

source

pub fn region(&self) -> Result<RegionRef<'c, '_>, Error>

Trait Implementations§

source§

impl<'c> From<ForOperation<'c>> for Operation<'c>

source§

fn from(operation: ForOperation<'c>) -> Self

Converts to this type from the input type.
source§

impl<'c> TryFrom<Operation<'c>> for ForOperation<'c>

§

type Error = Error

The type returned in the event of a conversion error.
source§

fn try_from(operation: Operation<'c>) -> Result<Self, Self::Error>

Performs the conversion.

Auto Trait Implementations§

§

impl<'c> RefUnwindSafe for ForOperation<'c>

§

impl<'c> !Send for ForOperation<'c>

§

impl<'c> !Sync for ForOperation<'c>

§

impl<'c> Unpin for ForOperation<'c>

§

impl<'c> UnwindSafe for ForOperation<'c>

Blanket Implementations§

source§

impl<T> Any for T
where T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Borrow<T> for T
where T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

source§

impl<T, U> Into<U> for T
where U: From<T>,

source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

§

type Error = Infallible

The type returned in the event of a conversion error.
source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.