Skip to content
4 changes: 2 additions & 2 deletions mlir/include/mlir/Dialect/Affine/IR/AffineOps.td
Original file line number Diff line number Diff line change
Expand Up @@ -118,8 +118,8 @@ def AffineForOp : Affine_Op<"for",
[AttrSizedOperandSegments, AutomaticAllocationScope,
ImplicitAffineTerminator, ConditionallySpeculatable,
RecursiveMemoryEffects, DeclareOpInterfaceMethods<LoopLikeOpInterface,
["getSingleInductionVar", "getSingleLowerBound", "getSingleStep",
"getSingleUpperBound", "getYieldedValuesMutable",
["getInductionVars", "getMixedLowerBound", "getMixedStep",
"getMixedUpperBound", "getYieldedValuesMutable",
"replaceWithAdditionalYields"]>,
DeclareOpInterfaceMethods<RegionBranchOpInterface,
["getEntrySuccessorOperands"]>]> {
Expand Down
37 changes: 6 additions & 31 deletions mlir/include/mlir/Dialect/SCF/IR/SCFOps.td
Original file line number Diff line number Diff line change
Expand Up @@ -136,8 +136,8 @@ def ExecuteRegionOp : SCF_Op<"execute_region", [
def ForOp : SCF_Op<"for",
[AutomaticAllocationScope, DeclareOpInterfaceMethods<LoopLikeOpInterface,
["getInitsMutable", "getLoopResults", "getRegionIterArgs",
"getSingleInductionVar", "getSingleLowerBound", "getSingleStep",
"getSingleUpperBound", "getYieldedValuesMutable",
"getInductionVars", "getMixedLowerBound", "getMixedStep",
"getMixedUpperBound", "getYieldedValuesMutable",
"promoteIfSingleIteration", "replaceWithAdditionalYields",
"yieldTiledValuesAndReplace"]>,
AllTypesMatch<["lowerBound", "upperBound", "step"]>,
Expand Down Expand Up @@ -301,8 +301,8 @@ def ForallOp : SCF_Op<"forall", [
AttrSizedOperandSegments,
AutomaticAllocationScope,
DeclareOpInterfaceMethods<LoopLikeOpInterface,
["getInitsMutable", "getRegionIterArgs", "getSingleInductionVar",
"getSingleLowerBound", "getSingleUpperBound", "getSingleStep",
["getInitsMutable", "getRegionIterArgs", "getInductionVars",
"getMixedLowerBound", "getMixedUpperBound", "getMixedStep",
"promoteIfSingleIteration", "yieldTiledValuesAndReplace"]>,
RecursiveMemoryEffects,
SingleBlockImplicitTerminator<"scf::InParallelOp">,
Expand Down Expand Up @@ -510,24 +510,6 @@ def ForallOp : SCF_Op<"forall", [
];

let extraClassDeclaration = [{
// Get lower bounds as OpFoldResult.
SmallVector<OpFoldResult> getMixedLowerBound() {
Builder b(getOperation()->getContext());
return getMixedValues(getStaticLowerBound(), getDynamicLowerBound(), b);
}

// Get upper bounds as OpFoldResult.
SmallVector<OpFoldResult> getMixedUpperBound() {
Builder b(getOperation()->getContext());
return getMixedValues(getStaticUpperBound(), getDynamicUpperBound(), b);
}

// Get steps as OpFoldResult.
SmallVector<OpFoldResult> getMixedStep() {
Builder b(getOperation()->getContext());
return getMixedValues(getStaticStep(), getDynamicStep(), b);
}

/// Get lower bounds as values.
SmallVector<Value> getLowerBound(OpBuilder &b) {
return getValueOrCreateConstantIndexOp(b, getLoc(), getMixedLowerBound());
Expand Down Expand Up @@ -584,10 +566,6 @@ def ForallOp : SCF_Op<"forall", [
getNumDynamicControlOperands() + getRank());
}

::mlir::ValueRange getInductionVars() {
return getBody()->getArguments().take_front(getRank());
}

::mlir::Value getInductionVar(int64_t idx) {
return getInductionVars()[idx];
}
Expand Down Expand Up @@ -765,8 +743,8 @@ def IfOp : SCF_Op<"if", [DeclareOpInterfaceMethods<RegionBranchOpInterface, [
def ParallelOp : SCF_Op<"parallel",
[AutomaticAllocationScope,
AttrSizedOperandSegments,
DeclareOpInterfaceMethods<LoopLikeOpInterface, ["getSingleInductionVar",
"getSingleLowerBound", "getSingleUpperBound", "getSingleStep"]>,
DeclareOpInterfaceMethods<LoopLikeOpInterface, ["getInductionVars",
"getMixedLowerBound", "getMixedUpperBound", "getMixedStep"]>,
RecursiveMemoryEffects,
DeclareOpInterfaceMethods<RegionBranchOpInterface>,
SingleBlockImplicitTerminator<"scf::ReduceOp">,
Expand Down Expand Up @@ -846,9 +824,6 @@ def ParallelOp : SCF_Op<"parallel",
];

let extraClassDeclaration = [{
ValueRange getInductionVars() {
return getBody()->getArguments();
}
unsigned getNumLoops() { return getStep().size(); }
unsigned getNumReductions() { return getInitVals().size(); }
}];
Expand Down
69 changes: 49 additions & 20 deletions mlir/include/mlir/Interfaces/LoopLikeInterface.td
Original file line number Diff line number Diff line change
Expand Up @@ -93,51 +93,47 @@ def LoopLikeOpInterface : OpInterface<"LoopLikeOpInterface"> {
}]
>,
InterfaceMethod<[{
If there is a single induction variable return it, otherwise return
std::nullopt.
Return all induction variables.
}],
/*retTy=*/"::std::optional<::mlir::Value>",
/*methodName=*/"getSingleInductionVar",
/*retTy=*/"::mlir::ValueRange",
/*methodName=*/"getInductionVars",
/*args=*/(ins),
/*methodBody=*/"",
/*defaultImplementation=*/[{
return std::nullopt;
return {};
}]
>,
InterfaceMethod<[{
Return the single lower bound value or attribute if it exists, otherwise
return std::nullopt.
Return all lower bounds.
}],
/*retTy=*/"::std::optional<::mlir::OpFoldResult>",
/*methodName=*/"getSingleLowerBound",
/*retTy=*/"::llvm::SmallVector<::mlir::OpFoldResult>",
/*methodName=*/"getMixedLowerBound",
/*args=*/(ins),
/*methodBody=*/"",
/*defaultImplementation=*/[{
return std::nullopt;
return {};
}]
>,
InterfaceMethod<[{
Return the single step value or attribute if it exists, otherwise
return std::nullopt.
Return all steps.
}],
/*retTy=*/"::std::optional<::mlir::OpFoldResult>",
/*methodName=*/"getSingleStep",
/*retTy=*/"::llvm::SmallVector<::mlir::OpFoldResult>",
/*methodName=*/"getMixedStep",
/*args=*/(ins),
/*methodBody=*/"",
/*defaultImplementation=*/[{
return std::nullopt;
return {};
}]
>,
InterfaceMethod<[{
Return the single upper bound value or attribute if it exists, otherwise
return std::nullopt.
Return all upper bounds.
}],
/*retTy=*/"::std::optional<::mlir::OpFoldResult>",
/*methodName=*/"getSingleUpperBound",
/*retTy=*/"::llvm::SmallVector<::mlir::OpFoldResult>",
/*methodName=*/"getMixedUpperBound",
/*args=*/(ins),
/*methodBody=*/"",
/*defaultImplementation=*/[{
return std::nullopt;
return {};
}]
>,
InterfaceMethod<[{
Expand Down Expand Up @@ -235,6 +231,39 @@ def LoopLikeOpInterface : OpInterface<"LoopLikeOpInterface"> {
}];

let extraSharedClassDeclaration = [{
/// If there is a single induction variable return it, otherwise return
/// std::nullopt.
::std::optional<::mlir::Value> getSingleInductionVar() {
auto inductionVars = this->getInductionVars();
if (inductionVars.size() == 1)
return inductionVars[0];
return std::nullopt;
}
/// Return the single lower bound value or attribute if it exists, otherwise
/// return std::nullopt.
::std::optional<::mlir::OpFoldResult> getSingleLowerBound() {
auto lowerBounds = this->getMixedLowerBound();
if (lowerBounds.size() == 1)
return lowerBounds[0];
return std::nullopt;
}
/// Return the single step value or attribute if it exists, otherwise
/// return std::nullopt.
::std::optional<::mlir::OpFoldResult> getSingleStep() {
auto steps = this->getMixedStep();
if (steps.size() == 1)
return steps[0];
return std::nullopt;
}
/// Return the single upper bound value or attribute if it exists, otherwise
/// return std::nullopt.
::std::optional<::mlir::OpFoldResult> getSingleUpperBound() {
auto upperBounds = this->getMixedUpperBound();
if (upperBounds.size() == 1)
return upperBounds[0];
return std::nullopt;
}

/// Append the specified additional "init" operands: replace this loop with
/// a new loop that has the additional init operands. The loop body of this
/// loop is moved over to the new loop.
Expand Down
20 changes: 9 additions & 11 deletions mlir/lib/Dialect/Affine/IR/AffineOps.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2454,27 +2454,25 @@ bool AffineForOp::matchingBoundOperandList() {

SmallVector<Region *> AffineForOp::getLoopRegions() { return {&getRegion()}; }

std::optional<Value> AffineForOp::getSingleInductionVar() {
return getInductionVar();
}
ValueRange AffineForOp::getInductionVars() { return {getInductionVar()}; }

std::optional<OpFoldResult> AffineForOp::getSingleLowerBound() {
SmallVector<OpFoldResult> AffineForOp::getMixedLowerBound() {
if (!hasConstantLowerBound())
return std::nullopt;
return {};
OpBuilder b(getContext());
return OpFoldResult(b.getI64IntegerAttr(getConstantLowerBound()));
return {OpFoldResult(b.getI64IntegerAttr(getConstantLowerBound()))};
}

std::optional<OpFoldResult> AffineForOp::getSingleStep() {
SmallVector<OpFoldResult> AffineForOp::getMixedStep() {
OpBuilder b(getContext());
return OpFoldResult(b.getI64IntegerAttr(getStepAsInt()));
return {OpFoldResult(b.getI64IntegerAttr(getStepAsInt()))};
}

std::optional<OpFoldResult> AffineForOp::getSingleUpperBound() {
SmallVector<OpFoldResult> AffineForOp::getMixedUpperBound() {
if (!hasConstantUpperBound())
return std::nullopt;
return {};
OpBuilder b(getContext());
return OpFoldResult(b.getI64IntegerAttr(getConstantUpperBound()));
return {OpFoldResult(b.getI64IntegerAttr(getConstantUpperBound()))};
}

FailureOr<LoopLikeOpInterface> AffineForOp::replaceWithAdditionalYields(
Expand Down
70 changes: 27 additions & 43 deletions mlir/lib/Dialect/SCF/IR/SCF.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -378,20 +378,18 @@ LogicalResult ForOp::verifyRegions() {
return success();
}

std::optional<Value> ForOp::getSingleInductionVar() {
return getInductionVar();
}
ValueRange ForOp::getInductionVars() { return {getInductionVar()}; }

std::optional<OpFoldResult> ForOp::getSingleLowerBound() {
return OpFoldResult(getLowerBound());
SmallVector<OpFoldResult> ForOp::getMixedLowerBound() {
return {OpFoldResult(getLowerBound())};
}

std::optional<OpFoldResult> ForOp::getSingleStep() {
return OpFoldResult(getStep());
SmallVector<OpFoldResult> ForOp::getMixedStep() {
return {OpFoldResult(getStep())};
}

std::optional<OpFoldResult> ForOp::getSingleUpperBound() {
return OpFoldResult(getUpperBound());
SmallVector<OpFoldResult> ForOp::getMixedUpperBound() {
return {OpFoldResult(getUpperBound())};
}

std::optional<ResultRange> ForOp::getLoopResults() { return getResults(); }
Expand Down Expand Up @@ -1428,28 +1426,26 @@ SmallVector<Operation *> ForallOp::getCombiningOps(BlockArgument bbArg) {
return storeOps;
}

std::optional<Value> ForallOp::getSingleInductionVar() {
if (getRank() != 1)
return std::nullopt;
return getInductionVar(0);
ValueRange ForallOp::getInductionVars() {
return getBody()->getArguments().take_front(getRank());
}

std::optional<OpFoldResult> ForallOp::getSingleLowerBound() {
if (getRank() != 1)
return std::nullopt;
return getMixedLowerBound()[0];
// Get lower bounds as OpFoldResult.
SmallVector<OpFoldResult> ForallOp::getMixedLowerBound() {
Builder b(getOperation()->getContext());
return getMixedValues(getStaticLowerBound(), getDynamicLowerBound(), b);
}

std::optional<OpFoldResult> ForallOp::getSingleUpperBound() {
if (getRank() != 1)
return std::nullopt;
return getMixedUpperBound()[0];
// Get upper bounds as OpFoldResult.
SmallVector<OpFoldResult> ForallOp::getMixedUpperBound() {
Builder b(getOperation()->getContext());
return getMixedValues(getStaticUpperBound(), getDynamicUpperBound(), b);
}

std::optional<OpFoldResult> ForallOp::getSingleStep() {
if (getRank() != 1)
return std::nullopt;
return getMixedStep()[0];
// Get steps as OpFoldResult.
SmallVector<OpFoldResult> ForallOp::getMixedStep() {
Builder b(getOperation()->getContext());
return getMixedValues(getStaticStep(), getDynamicStep(), b);
}

ForallOp mlir::scf::getForallOpThreadIndexOwner(Value val) {
Expand Down Expand Up @@ -3008,29 +3004,17 @@ void ParallelOp::print(OpAsmPrinter &p) {

SmallVector<Region *> ParallelOp::getLoopRegions() { return {&getRegion()}; }

std::optional<Value> ParallelOp::getSingleInductionVar() {
if (getNumLoops() != 1)
return std::nullopt;
return getBody()->getArgument(0);
}
ValueRange ParallelOp::getInductionVars() { return getBody()->getArguments(); }

std::optional<OpFoldResult> ParallelOp::getSingleLowerBound() {
if (getNumLoops() != 1)
return std::nullopt;
return getLowerBound()[0];
SmallVector<OpFoldResult> ParallelOp::getMixedLowerBound() {
return getLowerBound();
}

std::optional<OpFoldResult> ParallelOp::getSingleUpperBound() {
if (getNumLoops() != 1)
return std::nullopt;
return getUpperBound()[0];
SmallVector<OpFoldResult> ParallelOp::getMixedUpperBound() {
return getUpperBound();
}

std::optional<OpFoldResult> ParallelOp::getSingleStep() {
if (getNumLoops() != 1)
return std::nullopt;
return getStep()[0];
}
SmallVector<OpFoldResult> ParallelOp::getMixedStep() { return getStep(); }

ParallelOp mlir::scf::getParallelForInductionVarOwner(Value val) {
auto ivArg = llvm::dyn_cast<BlockArgument>(val);
Expand Down
8 changes: 8 additions & 0 deletions mlir/unittests/Dialect/SCF/LoopLikeSCFOpsTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,10 @@ class SCFLoopLikeTest : public ::testing::Test {
std::optional<OpFoldResult> maybeIndVar =
loopLikeOp.getSingleInductionVar();
EXPECT_TRUE(maybeIndVar.has_value());
EXPECT_EQ(loopLikeOp.getInductionVars().size(), 1u);
EXPECT_EQ(loopLikeOp.getMixedLowerBound().size(), 1u);
EXPECT_EQ(loopLikeOp.getMixedStep().size(), 1u);
EXPECT_EQ(loopLikeOp.getMixedLowerBound().size(), 1u);
}

void checkMultidimensional(LoopLikeOpInterface loopLikeOp) {
Expand All @@ -48,6 +52,10 @@ class SCFLoopLikeTest : public ::testing::Test {
std::optional<OpFoldResult> maybeIndVar =
loopLikeOp.getSingleInductionVar();
EXPECT_FALSE(maybeIndVar.has_value());
EXPECT_EQ(loopLikeOp.getInductionVars().size(), 2u);
EXPECT_EQ(loopLikeOp.getMixedLowerBound().size(), 2u);
EXPECT_EQ(loopLikeOp.getMixedStep().size(), 2u);
EXPECT_EQ(loopLikeOp.getMixedLowerBound().size(), 2u);
}

MLIRContext context;
Expand Down