Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[SCFToCalyx] If op with sequential condition #7687

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
151 changes: 137 additions & 14 deletions lib/Conversion/SCFToCalyx/SCFToCalyx.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,20 @@ using Scheduleable =

class IfLoweringStateInterface {
public:
void setCondReg(scf::IfOp op, calyx::RegisterOp regOp) {
Operation *operation = op.getOperation();
assert(condReg.count(operation) == 0 &&
"A condition register was already set for this scf::IfOp!\n");
condReg[operation] = regOp;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To avoid the double lookup here (once for count and once for the [] operator, we can do:

auto [it, succeeded] = condReg.insert(std::make_pair(operation, regOp));
assert(succeeded && "...");

}

calyx::RegisterOp getCondReg(scf::IfOp op) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this needed if its only used once?

auto it = condReg.find(op.getOperation());
if (it != condReg.end())
return it->second;
return nullptr;
}

void setThenGroup(scf::IfOp op, calyx::GroupOp group) {
Operation *operation = op.getOperation();
assert(thenGroup.count(operation) == 0 &&
Expand Down Expand Up @@ -172,6 +186,7 @@ class IfLoweringStateInterface {
}

private:
DenseMap<Operation *, calyx::RegisterOp> condReg;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I know this hasn't been the norm, but it would sure be nice to describe why this data structure exists for future readers :-)

DenseMap<Operation *, calyx::GroupOp> thenGroup;
DenseMap<Operation *, calyx::GroupOp> elseGroup;
DenseMap<Operation *, DenseMap<unsigned, calyx::RegisterOp>> resultRegs;
Expand Down Expand Up @@ -240,13 +255,36 @@ class ForLoopLoweringStateInterface
}
};

class PipeOpLoweringStateInterface {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not very satisfied with this approach though, having to introduce another interface to "remember" the register set for the sequential/pipelined library operator.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well, we'll definitely need some way to recall this mapping, since it isn't explicitly stated in the IR. If this is only necessary for lowering conditionals in if statements, then I think it would make more sense in the IfLoweringStateInterface.

With that said, I don't think this is the only Calyx control flow that will require this special treatment, i.e., while should be similar. What other approaches are you thinking about?

In any case, it would be nice to add documentation on why this interface exists.

public:
void setPipeResReg(Operation *op, calyx::RegisterOp reg) {
assert(isa<calyx::MultPipeLibOp>(op) || isa<calyx::DivUPipeLibOp>(op) ||
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

prefer: isa<calyx::MultPipeLibOp, calyx::DivUPipelibOp, ...>(op)

isa<calyx::DivSPipeLibOp>(op) || isa<calyx::RemUPipeLibOp>(op) ||
isa<calyx::RemSPipeLibOp>(op));
assert(resultRegs.count(op) == 0 &&
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Similar comment as above.

"A register was already set for this pipe operation!\n");
resultRegs[op] = reg;
}
// Get the register for a specific pipe operation
calyx::RegisterOp getPipeResReg(Operation *op) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Similarly for this function, it is used twice but only because you condition on an entire function call rather than the one element that is different: the function argument. I think we should avoid introducing this unless you think it improves readability.

auto it = resultRegs.find(op);
assert(it != resultRegs.end() &&
"No register was set for this pipe operation!\n");
return it->second;
}

private:
DenseMap<Operation *, calyx::RegisterOp> resultRegs;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A comment would be nice here!

};

/// Handles the current state of lowering of a Calyx component. It is mainly
/// used as a key/value store for recording information during partial lowering,
/// which is required at later lowering passes.
class ComponentLoweringState : public calyx::ComponentLoweringStateInterface,
public WhileLoopLoweringStateInterface,
public ForLoopLoweringStateInterface,
public IfLoweringStateInterface,
public PipeOpLoweringStateInterface,
public calyx::SchedulerInterface<Scheduleable> {
public:
ComponentLoweringState(calyx::ComponentOp component)
Expand Down Expand Up @@ -339,7 +377,12 @@ class BuildOpGroups : public calyx::FuncOpPartialLoweringPattern {
/// source operation TSrcOp.
template <typename TGroupOp, typename TCalyxLibOp, typename TSrcOp>
LogicalResult buildLibraryOp(PatternRewriter &rewriter, TSrcOp op,
TypeRange srcTypes, TypeRange dstTypes) const {
TypeRange srcTypes, TypeRange dstTypes,
calyx::RegisterOp srcReg = nullptr,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please add comments about these.

calyx::RegisterOp dstReg = nullptr) const {
assert((srcReg && dstReg) || (!srcReg && !dstReg));
bool isSequential = srcReg && dstReg;

SmallVector<Type> types;
llvm::append_range(types, srcTypes);
llvm::append_range(types, dstTypes);
Expand All @@ -365,26 +408,54 @@ class BuildOpGroups : public calyx::FuncOpPartialLoweringPattern {

/// Create assignments to the inputs of the library op.
auto group = createGroupForOp<TGroupOp>(rewriter, op);

if (isSequential) {
auto groupOp = cast<calyx::GroupOp>(group);
getState<ComponentLoweringState>().addBlockScheduleable(op->getBlock(),
groupOp);
}

rewriter.setInsertionPointToEnd(group.getBodyBlock());
for (auto dstOp : enumerate(opInputPorts))
rewriter.create<calyx::AssignOp>(op.getLoc(), dstOp.value(),
op->getOperand(dstOp.index()));

for (auto dstOp : enumerate(opInputPorts)) {
if (isSequential)
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bug, should be:

Suggested change
if (isSequential)
if (isPipeLibOp(dstOp.value()))
rewriter.create<calyx::AssignOp>(op.getLoc(), dstOp.value(),
srcReg.getOut());

Then seems like we are checking isPipeLibOp twice, once in a caller function, another in a callee..

rewriter.create<calyx::AssignOp>(op.getLoc(), dstOp.value(),
srcReg.getOut());
else
rewriter.create<calyx::AssignOp>(op.getLoc(), dstOp.value(),
op->getOperand(dstOp.index()));
Comment on lines +421 to +426
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
if (isSequential)
rewriter.create<calyx::AssignOp>(op.getLoc(), dstOp.value(),
srcReg.getOut());
else
rewriter.create<calyx::AssignOp>(op.getLoc(), dstOp.value(),
op->getOperand(dstOp.index()));
auto srcOp = isSequential ? srcReg.getOut() : op->getOperand(dstOp.index());
rewriter.create<calyx::AssignOp>(op.getLoc(), dstOp.value(), srcOp);

Maybe this doesn't work, but I would try to limit the scope of your conditional.

}

/// Replace the result values of the source operator with the new operator.
for (auto res : enumerate(opOutputPorts)) {
getState<ComponentLoweringState>().registerEvaluatingGroup(res.value(),
group);
op->getResult(res.index()).replaceAllUsesWith(res.value());
if (isSequential)
op->getResult(res.index()).replaceAllUsesWith(dstReg.getOut());
else
op->getResult(res.index()).replaceAllUsesWith(res.value());
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same here.

}

if (isSequential) {
auto groupOp = cast<calyx::GroupOp>(group);
buildAssignmentsForRegisterWrite(
rewriter, groupOp,
getState<ComponentLoweringState>().getComponentOp(), dstReg,
calyxOp.getOut());
}

return success();
}

/// buildLibraryOp which provides in- and output types based on the operands
/// and results of the op argument.
template <typename TGroupOp, typename TCalyxLibOp, typename TSrcOp>
LogicalResult buildLibraryOp(PatternRewriter &rewriter, TSrcOp op) const {
LogicalResult buildLibraryOp(PatternRewriter &rewriter, TSrcOp op,
calyx::RegisterOp srcReg = nullptr,
calyx::RegisterOp dstReg = nullptr) const {
return buildLibraryOp<TGroupOp, TCalyxLibOp, TSrcOp>(
rewriter, op, op.getOperandTypes(), op->getResultTypes());
rewriter, op, op.getOperandTypes(), op->getResultTypes(), srcReg,
dstReg);
}

/// Creates a group named by the basic block which the input op resides in.
Expand All @@ -411,6 +482,7 @@ class BuildOpGroups : public calyx::FuncOpPartialLoweringPattern {
auto reg = createRegister(
op.getLoc(), rewriter, getComponent(), width.getIntOrFloatBitWidth(),
getState<ComponentLoweringState>().getUniqueName(opName));

// Operation pipelines are not combinational, so a GroupOp is required.
auto group = createGroupForOp<calyx::GroupOp>(rewriter, op);
OpBuilder builder(group->getRegion(0));
Expand Down Expand Up @@ -441,6 +513,8 @@ class BuildOpGroups : public calyx::FuncOpPartialLoweringPattern {
getState<ComponentLoweringState>().registerEvaluatingGroup(
opPipe.getRight(), group);

getState<ComponentLoweringState>().setPipeResReg(out.getDefiningOp(), reg);

return success();
}

Expand Down Expand Up @@ -939,9 +1013,43 @@ LogicalResult BuildOpGroups::buildOp(PatternRewriter &rewriter,

LogicalResult BuildOpGroups::buildOp(PatternRewriter &rewriter,
CmpIOp op) const {
auto isPipeLibOp = [](Value val) -> bool {
if (Operation *defOp = val.getDefiningOp()) {
return isa<calyx::MultPipeLibOp, calyx::DivUPipeLibOp,
calyx::DivSPipeLibOp, calyx::RemUPipeLibOp,
calyx::RemSPipeLibOp>(defOp);
}
return false;
};

switch (op.getPredicate()) {
case CmpIPredicate::eq:
case CmpIPredicate::eq: {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Isn't this the case for any conditional predicate used in a Calyx if? Just trying to make sure I understand correctly what's going on here. If this is true, don't feel pressured to make those changes now but you should add some assertions so that there is some sort of failure.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You are right, any comparison operator can be a condition check.
I'm only adding eq for now to use it as a prototype since some approaches need to be discussed (like the PipeLoweringState). Once we reach agreement, I will add support for all CmpIPredicate, which will just be cloning the same code from eq.

StringRef opName = op.getOperationName().split(".").second;
Type width = op.getResult().getType();
bool isSequential = isPipeLibOp(op.getLhs()) || isPipeLibOp(op.getRhs());
if (isSequential) {
auto condReg = createRegister(
op.getLoc(), rewriter, getComponent(), width.getIntOrFloatBitWidth(),
getState<ComponentLoweringState>().getUniqueName(opName));

for (auto *user : op->getUsers()) {
if (auto ifOp = dyn_cast<scf::IfOp>(user))
getState<ComponentLoweringState>().setCondReg(ifOp, condReg);
}

calyx::RegisterOp pipeResReg;
if (isPipeLibOp(op.getLhs()))
pipeResReg = getState<ComponentLoweringState>().getPipeResReg(
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please use curly braces if doing if/else / multi-line conditionals.

op.getLhs().getDefiningOp());
else
pipeResReg = getState<ComponentLoweringState>().getPipeResReg(
op.getRhs().getDefiningOp());

return buildLibraryOp<calyx::GroupOp, calyx::EqLibOp>(
rewriter, op, pipeResReg, condReg);
}
return buildLibraryOp<calyx::CombGroupOp, calyx::EqLibOp>(rewriter, op);
}
case CmpIPredicate::ne:
return buildLibraryOp<calyx::CombGroupOp, calyx::NeqLibOp>(rewriter, op);
case CmpIPredicate::uge:
Expand Down Expand Up @@ -1535,11 +1643,16 @@ class BuildControl : public calyx::FuncOpPartialLoweringPattern {
Location loc = ifOp->getLoc();

auto cond = ifOp.getCondition();
auto condGroup = getState<ComponentLoweringState>()
.getEvaluatingGroup<calyx::CombGroupOp>(cond);

auto symbolAttr = FlatSymbolRefAttr::get(
StringAttr::get(getContext(), condGroup.getSymName()));
FlatSymbolRefAttr symbolAttr = nullptr;
auto condReg = getState<ComponentLoweringState>().getCondReg(ifOp);
if (!condReg) {
auto condGroup = getState<ComponentLoweringState>()
.getEvaluatingGroup<calyx::CombGroupOp>(cond);

symbolAttr = FlatSymbolRefAttr::get(
StringAttr::get(getContext(), condGroup.getSymName()));
}

bool initElse = !ifOp.getElseRegion().empty();
auto ifCtrlOp = rewriter.create<calyx::IfOp>(
Expand All @@ -1551,8 +1664,13 @@ class BuildControl : public calyx::FuncOpPartialLoweringPattern {
rewriter.create<calyx::SeqOp>(ifOp.getThenRegion().getLoc());
auto *thenSeqOpBlock = thenSeqOp.getBodyBlock();

rewriter.setInsertionPointToEnd(thenSeqOpBlock);
auto *thenBlock = &ifOp.getThenRegion().front();
LogicalResult res = buildCFGControl(path, rewriter, thenSeqOpBlock,
/*preBlock=*/block, thenBlock);
if (res.failed())
return res;

rewriter.setInsertionPointToEnd(thenSeqOpBlock);
calyx::GroupOp thenGroup =
getState<ComponentLoweringState>().getThenGroup(ifOp);
rewriter.create<calyx::EnableOp>(thenGroup.getLoc(),
Expand All @@ -1565,8 +1683,13 @@ class BuildControl : public calyx::FuncOpPartialLoweringPattern {
rewriter.create<calyx::SeqOp>(ifOp.getElseRegion().getLoc());
auto *elseSeqOpBlock = elseSeqOp.getBodyBlock();

rewriter.setInsertionPointToEnd(elseSeqOpBlock);
auto *elseBlock = &ifOp.getElseRegion().front();
res = buildCFGControl(path, rewriter, elseSeqOpBlock,
/*preBlock=*/block, elseBlock);
if (res.failed())
return res;

rewriter.setInsertionPointToEnd(elseSeqOpBlock);
calyx::GroupOp elseGroup =
getState<ComponentLoweringState>().getElseGroup(ifOp);
rewriter.create<calyx::EnableOp>(elseGroup.getLoc(),
Expand Down
119 changes: 119 additions & 0 deletions test/Conversion/SCFToCalyx/convert_controlflow.mlir
Original file line number Diff line number Diff line change
Expand Up @@ -641,3 +641,122 @@ module {
return %1 : i32
}
}

// -----

// Test if ops with sequential condition check.

module {
// CHECK-LABEL: calyx.component @main(
// CHECK-SAME: %[[VAL_0:in0]]: i32,
// CHECK-SAME: %[[VAL_1:.*]]: i1 {clk},
// CHECK-SAME: %[[VAL_2:.*]]: i1 {reset},
// CHECK-SAME: %[[VAL_3:.*]]: i1 {go}) -> (
// CHECK-SAME: %[[VAL_4:out0]]: i32,
// CHECK-SAME: %[[VAL_5:.*]]: i1 {done}) {
// CHECK: %[[VAL_6:.*]] = hw.constant true
// CHECK: %[[VAL_7:.*]] = hw.constant false
// CHECK: %[[VAL_8:.*]] = hw.constant 1 : i32
// CHECK: %[[VAL_9:.*]] = hw.constant 2 : i32
// CHECK: %[[VAL_10:.*]], %[[VAL_11:.*]] = calyx.std_slice @std_slice_1 : i32, i7
// CHECK: %[[VAL_12:.*]], %[[VAL_13:.*]] = calyx.std_slice @std_slice_0 : i32, i7
// CHECK: %[[VAL_14:.*]], %[[VAL_15:.*]], %[[VAL_16:.*]], %[[VAL_17:.*]], %[[VAL_18:.*]], %[[VAL_19:.*]] = calyx.register @load_1_reg : i32, i1, i1, i1, i32, i1
// CHECK: %[[VAL_20:.*]], %[[VAL_21:.*]], %[[VAL_22:.*]], %[[VAL_23:.*]], %[[VAL_24:.*]], %[[VAL_25:.*]] = calyx.register @load_0_reg : i32, i1, i1, i1, i32, i1
// CHECK: %[[VAL_26:.*]], %[[VAL_27:.*]], %[[VAL_28:.*]] = calyx.std_eq @std_eq_0 : i32, i32, i1
// CHECK: %[[VAL_29:.*]], %[[VAL_30:.*]], %[[VAL_31:.*]], %[[VAL_32:.*]], %[[VAL_33:.*]], %[[VAL_34:.*]] = calyx.register @cmpi_0_reg : i1, i1, i1, i1, i1, i1
// CHECK: %[[VAL_35:.*]], %[[VAL_36:.*]], %[[VAL_37:.*]], %[[VAL_38:.*]], %[[VAL_39:.*]], %[[VAL_40:.*]] = calyx.register @remui_0_reg : i32, i1, i1, i1, i32, i1
// CHECK: %[[VAL_41:.*]], %[[VAL_42:.*]], %[[VAL_43:.*]], %[[VAL_44:.*]], %[[VAL_45:.*]], %[[VAL_46:.*]], %[[VAL_47:.*]] = calyx.std_remu_pipe @std_remu_pipe_0 : i1, i1, i1, i32, i32, i32, i1
// CHECK: %[[VAL_48:.*]], %[[VAL_49:.*]], %[[VAL_50:.*]], %[[VAL_51:.*]], %[[VAL_52:.*]], %[[VAL_53:.*]], %[[VAL_54:.*]], %[[VAL_55:.*]] = calyx.seq_mem @mem_0 <[120] x 32> [7] {external = true} : i7, i1, i1, i1, i1, i32, i32, i1
// CHECK: %[[VAL_56:.*]], %[[VAL_57:.*]], %[[VAL_58:.*]], %[[VAL_59:.*]], %[[VAL_60:.*]], %[[VAL_61:.*]] = calyx.register @if_res_0_reg : i32, i1, i1, i1, i32, i1
// CHECK: %[[VAL_62:.*]], %[[VAL_63:.*]], %[[VAL_64:.*]], %[[VAL_65:.*]], %[[VAL_66:.*]], %[[VAL_67:.*]] = calyx.register @ret_arg0_reg : i32, i1, i1, i1, i32, i1
// CHECK: calyx.wires {
// CHECK: calyx.assign %[[VAL_4]] = %[[VAL_66]] : i32
// CHECK: calyx.group @then_br_0 {
// CHECK: calyx.assign %[[VAL_56]] = %[[VAL_24]] : i32
// CHECK: calyx.assign %[[VAL_57]] = %[[VAL_6]] : i1
// CHECK: calyx.group_done %[[VAL_61]] : i1
// CHECK: }
// CHECK: calyx.group @else_br_0 {
// CHECK: calyx.assign %[[VAL_56]] = %[[VAL_18]] : i32
// CHECK: calyx.assign %[[VAL_57]] = %[[VAL_6]] : i1
// CHECK: calyx.group_done %[[VAL_61]] : i1
// CHECK: }
// CHECK: calyx.group @bb0_0 {
// CHECK: calyx.assign %[[VAL_44]] = %[[VAL_0]] : i32
// CHECK: calyx.assign %[[VAL_45]] = %[[VAL_9]] : i32
// CHECK: calyx.assign %[[VAL_35]] = %[[VAL_46]] : i32
// CHECK: calyx.assign %[[VAL_36]] = %[[VAL_47]] : i1
// CHECK: %[[VAL_68:.*]] = comb.xor %[[VAL_47]], %[[VAL_6]] : i1
// CHECK: calyx.assign %[[VAL_43]] = %[[VAL_68]] ? %[[VAL_6]] : i1
// CHECK: calyx.group_done %[[VAL_40]] : i1
// CHECK: }
// CHECK: calyx.group @bb0_1 {
// CHECK: calyx.assign %[[VAL_26]] = %[[VAL_39]] : i32
// CHECK: calyx.assign %[[VAL_27]] = %[[VAL_39]] : i32
// CHECK: calyx.assign %[[VAL_29]] = %[[VAL_28]] : i1
// CHECK: calyx.assign %[[VAL_30]] = %[[VAL_6]] : i1
// CHECK: calyx.group_done %[[VAL_34]] : i1
// CHECK: }
// CHECK: calyx.group @bb0_2 {
// CHECK: calyx.assign %[[VAL_10]] = %[[VAL_9]] : i32
// CHECK: calyx.assign %[[VAL_48]] = %[[VAL_11]] : i7
// CHECK: calyx.assign %[[VAL_51]] = %[[VAL_6]] : i1
// CHECK: calyx.assign %[[VAL_52]] = %[[VAL_7]] : i1
// CHECK: calyx.assign %[[VAL_20]] = %[[VAL_54]] : i32
// CHECK: calyx.assign %[[VAL_21]] = %[[VAL_55]] : i1
// CHECK: calyx.group_done %[[VAL_25]] : i1
// CHECK: }
// CHECK: calyx.group @bb0_3 {
// CHECK: calyx.assign %[[VAL_12]] = %[[VAL_8]] : i32
// CHECK: calyx.assign %[[VAL_48]] = %[[VAL_13]] : i7
// CHECK: calyx.assign %[[VAL_51]] = %[[VAL_6]] : i1
// CHECK: calyx.assign %[[VAL_52]] = %[[VAL_7]] : i1
// CHECK: calyx.assign %[[VAL_14]] = %[[VAL_54]] : i32
// CHECK: calyx.assign %[[VAL_15]] = %[[VAL_55]] : i1
// CHECK: calyx.group_done %[[VAL_19]] : i1
// CHECK: }
// CHECK: calyx.group @ret_assign_0 {
// CHECK: calyx.assign %[[VAL_62]] = %[[VAL_60]] : i32
// CHECK: calyx.assign %[[VAL_63]] = %[[VAL_6]] : i1
// CHECK: calyx.group_done %[[VAL_67]] : i1
// CHECK: }
// CHECK: }
// CHECK: calyx.control {
// CHECK: calyx.seq {
// CHECK: calyx.enable @bb0_0
// CHECK: calyx.enable @bb0_1
// CHECK: calyx.if %[[VAL_33]] {
// CHECK: calyx.seq {
// CHECK: calyx.enable @bb0_2
// CHECK: calyx.enable @then_br_0
// CHECK: }
// CHECK: } else {
// CHECK: calyx.seq {
// CHECK: calyx.enable @bb0_3
// CHECK: calyx.enable @else_br_0
// CHECK: }
// CHECK: }
// CHECK: calyx.enable @ret_assign_0
// CHECK: }
// CHECK: }
// CHECK: } {toplevel}
func.func @main(%arg0 : i32) -> i32 {
%1 = memref.alloc() : memref<120xi32>
%idx_one = arith.constant 1 : index
%two = arith.constant 2: i32
%rem = arith.remui %arg0, %two : i32
%cond = arith.cmpi eq, %arg0, %rem : i32

%res = scf.if %cond -> i32 {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: could we minimize what you're trying to test even further, e.g., do we need the else case, mem alloc, ...? It seems the critical piece is an if statement that uses the output of a sequential operation.

%idx = arith.addi %idx_one, %idx_one : index
%then_res = memref.load %1[%idx] : memref<120xi32>
scf.yield %then_res : i32
} else {
%idx = arith.muli %idx_one, %idx_one : index
%else_res = memref.load %1[%idx] : memref<120xi32>
scf.yield %else_res : i32
}

return %res : i32
}
}
Loading