How build a whileop?

Silly for me. Though I’m newer to MLIR, I thought I have ask many question these days. Bur I really need to ask a more question.

I want to make a new whileOp like:

%res = scf.while (%arg1 = %init1) : (f32) -> f32 {
  // "Before" region.
  // In a "while" loop, this region computes the condition.
  %condition = call @evaluate_condition(%arg1) : (f32) -> i1

  // Forward the argument (as result or "after" region argument).
  scf.condition(%condition) %arg1 : f32

} do {
^bb0(%arg2: f32):
  // "After" region.
  // In a "while" loop, this region is the loop body.
  %next = call @payload(%arg2) : (f32) -> f32

  // Forward the new value to the "before" region.
  // The operand types must match the types of the `scf.while` operands.
  scf.yield %next : f32

I have seen the source code, and I found:

  static void build(::mlir::OpBuilder &odsBuilder, ::mlir::OperationState &odsState, TypeRange resultTypes, ValueRange operands, function_ref<void(OpBuilder &, Location, ValueRange)> beforeBuilder, function_ref<void(OpBuilder &, Location, ValueRange)> afterBuilder);
  static void build(::mlir::OpBuilder &, ::mlir::OperationState &odsState, ::mlir::TypeRange resultTypes, ::mlir::ValueRange operands, ::llvm::ArrayRef<::mlir::NamedAttribute> attributes = {});

How should I use them? (:expressionless: MLIR has too few example for important API and I did feel silly at all. Thank for all patient answers. MLIR discourse really help me a lot.

Have you looked at mlir/test/lib/Dialect/SCF/TestWhileOpBuilder.cpp?

Oh, I never see it. My llvm version is a little old.(about three months) I’ll look at it.

I have seen it, but I still have a question, this is: How to make a new whileOp with:

(%arg1 = %init1)

I understand the %arg1 is a Value. But it’s a fresh one, How can I get it? I only know get Value from a existed Operation.

This is the args argument to the lambda that builds the body in the test case.

Hello? I have a remained question… I found this method was implemented in 1 month ago. But for oldder version of MLIR or some waiting update Op like IndexSwitchOp, what should I do if I have build a Op like:

%27:7 = "scf.index_switch"(%26) ({
}) {cases = array<i64>} : (index) -> (i32, i32, i1)

I have tried to add YieldOp on the default block. But it never works and tells me:

standalone-opt: /home/saltyfish/src/llvm-project/llvm/include/llvm/ADT/ilist_iterator.h:138: reference llvm::ilist_iterator<llvm::ilist_detail::node_options<mlir::Block, true, false, void>, false, false>::operator*() const [OptionsT = llvm::ilist_detail::node_options<mlir::Block, true, false, void>, IsReverse = false, IsConst = false]: Assertion `!NodePtr->isKnownSentinel()' failed.

This assertions means you’re accessing an empty block, what does your code look like?
If you build with Debug mode, you should have a backtrace that should point at the issue.
(I suspect you may be looking for a block in the region without adding a block there yourself first).

In general, I open the generated header tools/mlir//include/mlir/Dialect/SCF/IR/, find the class, and look at the build methods, for IndexSwitchOp it is:

  static void build(::mlir::OpBuilder &odsBuilder, ::mlir::OperationState &odsState, ::mlir::TypeRange results, ::mlir::Value arg, ::mlir::DenseI64ArrayAttr cases, unsigned caseRegionsCount);
  static void build(::mlir::OpBuilder &odsBuilder, ::mlir::OperationState &odsState, ::mlir::TypeRange results, ::mlir::Value arg, ::llvm::ArrayRef<int64_t> cases, unsigned caseRegionsCount);
  static void build(::mlir::OpBuilder &, ::mlir::OperationState &odsState, ::mlir::TypeRange resultTypes, ::mlir::ValueRange operands, ::llvm::ArrayRef<::mlir::NamedAttribute> attributes, unsigned numRegions);

When you use builder.create<IndexSwitchOp>(...) the first two arguments of the build() methods are implicit and handled by the builder, so you just need to provide the ones after.