It’s my daily series of question…Ahh
I want to build a scf::IndexSwitchOp. And I use:
ArrayRef<int64_t> CaseIndexs({1, 2, 3});
auto StateSwitch = builder.create<scf::IndexSwitchOp>(
TypeRange(
{builder.getI32Type(), builder.getI32Type(),
builder.getI1Type()}),
StateIndex.getResult(), CaseIndexs, 4);
As you know the mlir is like:
%27:3 = "scf.index_switch"(%26) ({
}, {
}, {
}, {
}, {
}) {cases = array<i64: 94415677222768, 94415677222768, 94415677222768>} : (index) -> (i32, i32, i1)
I have three sub-questions:
- Why case is like a big number?(Is there existing i32->i64 implicit transversion?)
- How should I build some Op in regions?(As we know before Jan 2023, the mlir only can build region without Op in one time)
- Is one region default region?
I have use below to build a indexswitchOp:
void DerecursionPass::runOnOperation() {
func::FuncOp func{getOperation()};
// Recursion Judgement
std::string funcName{func.getSymName().data()};
if (!(funcName=="test")) {
return;
}
OpBuilder builderMain(&func.front().front());
ImplicitLocOpBuilder builder(func.front().front().getLoc(), builderMain);
arith::ConstantOp zeroConstant = builder.create<arith::ConstantOp>(
builder.getI32Type(), builder.getI32IntegerAttr(0));
auto StateIndex =
builder.create<arith::IndexCastOp>(builder.getIndexType(), func.front().getArgument(0));
auto StateSwitch = builder.create<scf::IndexSwitchOp>(
TypeRange({builder.getI32Type()}), StateIndex.getResult(),
ArrayRef<int64_t>({1}), 0);
builderMain.setInsertionPoint(&StateSwitch.getDefaultBlock(),StateSwitch.getDefaultBlock().begin());
builder.create<scf::YieldOp>(zeroConstant.getResult());
builderMain.setInsertionPoint(&StateSwitch.getCaseBlock(0),StateSwitch.getCaseBlock(0).begin());
builder.create<scf::YieldOp>(zeroConstant.getResult());
}
But it show:
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.
Please try to not cross post in multiple threads.
auto StateSwitch = builder.create<scf::IndexSwitchOp>(
TypeRange({builder.getI32Type()}), StateIndex.getResult(),
ArrayRef<int64_t>({1}), 0);
The last 0
here is the number of regions that will be created, you set it to 0 so none?
I would think you’d need one for the default and one for the case.
I have built a indexswitchOp and I tried put YieldOp into it:
func::FuncOp func{getOperation()};
// Recursion Judgement
std::string funcName{func.getSymName().data()};
if (funcName=="test") {
return;
}
OpBuilder builderMain(&func.front().front());
ImplicitLocOpBuilder builder(func.front().front().getLoc(), builderMain);
arith::ConstantOp zeroConstant = builder.create<arith::ConstantOp>(
builder.getI32Type(), builder.getI32IntegerAttr(0));
auto StateIndex =
builder.create<arith::IndexCastOp>(builder.getIndexType(), func.front().getArgument(0));
auto StateSwitch = builder.create<scf::IndexSwitchOp>(
TypeRange({builder.getI32Type()}), StateIndex.getResult(),
ArrayRef<int64_t>({1}), 2);
builderMain.createBlock(&StateSwitch.getDefaultRegion());
//ImplicitLocOpBuilder builder1(StateSwitch.getLoc(),builderMain);
builder.create<scf::YieldOp>(StateSwitch.getDefaultBlock().front().getLoc(),
zeroConstant.getResult());
builderMain.createBlock(&StateSwitch.getCaseRegions()[0]);
builder.create<scf::YieldOp>(StateSwitch.getCaseBlock(0).front().getLoc(),
zeroConstant.getResult());
And it shows:
reference std::vector<mlir::BlockArgument>::operator[](size_type) [_Tp = mlir::BlockArgument, _Alloc = std::allocator<mlir::BlockArgument>]: Assertion '__n < this->size()' failed.
Whatever createBlock, it shows same message.
Try to build in debug mode and get backtraces, it should help getting the source location of where the issue is in your code. Also running this in a debugger should allow to pinpoint the issue fairly quickly.
In your code:
- I’m not sure why you have two builders.
- When you create an OpBuilder, it’ll have an insertion point right before the operation you’re providing. That means that the
builder.create<scf::YieldOp>(...
calls will insert the yield at the beginning of the first block in the function.
-
reference std::vector<mlir::BlockArgument>::operator[](size_type) [_Tp = mlir::BlockArgument, _Alloc = std::allocator<mlir::BlockArgument>]: Assertion '__n < this->size()' failed.
this assertions is saying that something tries to look for block arguments. Nothing in your code does this at the moment as far as I can tell, again the backtrace or a debugger would help.
I think the switchOp’s default don’t have blockargument. I have seen the IfOp implementation, but I don’t know how to do it without rewrite switchOp::build
Since the block isn’t created in the build
method, I’m not sure why rewriting it would help?
You create the block for the default here: builderMain.createBlock(&StateSwitch.getDefaultRegion());
; now it’s just a matter of adding the block argument to the block: StateSwitch.getDefaultBlock().addArgument(type, loc);
.
Let me explain completely…
I want to build a switchOp like:
%2 = scf.index_switch %1 : index -> i32
case 1 {
scf.yield %arg0 : i32
}
default {
scf.yield %arg0 : i32
}
I have build a switchOp with blank region and I want to build YieldOp in the region.
I have tried mentioned above and:
auto StateIndex =
builder.create<arith::IndexCastOp>(builder.getIndexType(), func.front().getArgument(0));
auto StateSwitch = builder.create<scf::IndexSwitchOp>(
TypeRange({builder.getI32Type()}), StateIndex.getResult(),
ArrayRef<int64_t>({1}), 2);
builder.createBlock(&StateSwitch.getDefaultRegion());
StateSwitch.getDefaultBlock().push_back(builder.create<scf::YieldOp>(func.front().getArgument(0)));
But it always show the same error:
/usr/bin/../lib/gcc/x86_64-linux-gnu/12/../../../../include/c++/12/bits/stl_vector.h:1123: reference std::vector<mlir::BlockArgument>::operator[](size_type) [_Tp = mlir::BlockArgument, _Alloc = std::allocator<mlir::BlockArgument>]: Assertion '__n < this->size()' failed.
I think may be the default block return value number is zero, but does it do it?
How could I get a normal indexswitchOp?/(ㄒoㄒ)/~~
I think I should only put YieldOp into region, but it seems it doesn’t work.
I suspect this is the part that asserts (the only place that seems to access an argument list).
How many argument does this function have? Can you print the function before this statement?
You should really start doing a bit more of print-style debugging or use a debugger.
Ok, I’ll do more on debugger.
I have changed too more before createblock. Thank you very much