aboutsummaryrefslogtreecommitdiff
path: root/mlir/unittests
diff options
context:
space:
mode:
Diffstat (limited to 'mlir/unittests')
-rw-r--r--mlir/unittests/Analysis/Presburger/SimplexTest.cpp28
-rw-r--r--mlir/unittests/Dialect/OpenACC/OpenACCOpsTest.cpp4
-rw-r--r--mlir/unittests/Dialect/OpenACC/OpenACCUtilsTest.cpp189
-rw-r--r--mlir/unittests/Interfaces/ControlFlowInterfacesTest.cpp38
4 files changed, 239 insertions, 20 deletions
diff --git a/mlir/unittests/Analysis/Presburger/SimplexTest.cpp b/mlir/unittests/Analysis/Presburger/SimplexTest.cpp
index 63d0243..0955efd 100644
--- a/mlir/unittests/Analysis/Presburger/SimplexTest.cpp
+++ b/mlir/unittests/Analysis/Presburger/SimplexTest.cpp
@@ -20,26 +20,29 @@ using namespace mlir;
using namespace presburger;
/// Convenience functions to pass literals to Simplex.
-void addInequality(SimplexBase &simplex, ArrayRef<int64_t> coeffs) {
+static void addInequality(SimplexBase &simplex, ArrayRef<int64_t> coeffs) {
simplex.addInequality(getDynamicAPIntVec(coeffs));
}
-void addEquality(SimplexBase &simplex, ArrayRef<int64_t> coeffs) {
+static void addEquality(SimplexBase &simplex, ArrayRef<int64_t> coeffs) {
simplex.addEquality(getDynamicAPIntVec(coeffs));
}
-bool isRedundantInequality(Simplex &simplex, ArrayRef<int64_t> coeffs) {
+static bool isRedundantInequality(Simplex &simplex, ArrayRef<int64_t> coeffs) {
return simplex.isRedundantInequality(getDynamicAPIntVec(coeffs));
}
-bool isRedundantInequality(LexSimplex &simplex, ArrayRef<int64_t> coeffs) {
+static bool isRedundantInequality(LexSimplex &simplex,
+ ArrayRef<int64_t> coeffs) {
return simplex.isRedundantInequality(getDynamicAPIntVec(coeffs));
}
-bool isRedundantEquality(Simplex &simplex, ArrayRef<int64_t> coeffs) {
+static bool isRedundantEquality(Simplex &simplex, ArrayRef<int64_t> coeffs) {
return simplex.isRedundantEquality(getDynamicAPIntVec(coeffs));
}
-bool isSeparateInequality(LexSimplex &simplex, ArrayRef<int64_t> coeffs) {
+static bool isSeparateInequality(LexSimplex &simplex,
+ ArrayRef<int64_t> coeffs) {
return simplex.isSeparateInequality(getDynamicAPIntVec(coeffs));
}
-Simplex::IneqType findIneqType(Simplex &simplex, ArrayRef<int64_t> coeffs) {
+static Simplex::IneqType findIneqType(Simplex &simplex,
+ ArrayRef<int64_t> coeffs) {
return simplex.findIneqType(getDynamicAPIntVec(coeffs));
}
@@ -81,8 +84,9 @@ TEST(SimplexTest, addEquality_separate) {
EXPECT_TRUE(simplex.isEmpty());
}
-void expectInequalityMakesSetEmpty(Simplex &simplex, ArrayRef<int64_t> coeffs,
- bool expect) {
+static void expectInequalityMakesSetEmpty(Simplex &simplex,
+ ArrayRef<int64_t> coeffs,
+ bool expect) {
ASSERT_FALSE(simplex.isEmpty());
unsigned snapshot = simplex.getSnapshot();
addInequality(simplex, coeffs);
@@ -121,9 +125,9 @@ TEST(SimplexTest, addInequality_rollback) {
}
}
-Simplex simplexFromConstraints(unsigned nDim,
- ArrayRef<SmallVector<int64_t, 8>> ineqs,
- ArrayRef<SmallVector<int64_t, 8>> eqs) {
+static Simplex simplexFromConstraints(unsigned nDim,
+ ArrayRef<SmallVector<int64_t, 8>> ineqs,
+ ArrayRef<SmallVector<int64_t, 8>> eqs) {
Simplex simplex(nDim);
for (const auto &ineq : ineqs)
addInequality(simplex, ineq);
diff --git a/mlir/unittests/Dialect/OpenACC/OpenACCOpsTest.cpp b/mlir/unittests/Dialect/OpenACC/OpenACCOpsTest.cpp
index 6ac9a87..d6203b9 100644
--- a/mlir/unittests/Dialect/OpenACC/OpenACCOpsTest.cpp
+++ b/mlir/unittests/Dialect/OpenACC/OpenACCOpsTest.cpp
@@ -766,7 +766,9 @@ void testShortDataEntryOpBuildersMappableVar(OpBuilder &b, MLIRContext &context,
struct IntegerOpenACCMappableModel
: public mlir::acc::MappableType::ExternalModel<IntegerOpenACCMappableModel,
- IntegerType> {};
+ IntegerType> {
+ bool hasUnknownDimensions(mlir::Type type) const { return false; }
+};
TEST_F(OpenACCOpsTest, mappableTypeBuilderDataEntry) {
// First, set up the test by attaching MappableInterface to IntegerType.
diff --git a/mlir/unittests/Dialect/OpenACC/OpenACCUtilsTest.cpp b/mlir/unittests/Dialect/OpenACC/OpenACCUtilsTest.cpp
index 3fbbcc9..6f4e305 100644
--- a/mlir/unittests/Dialect/OpenACC/OpenACCUtilsTest.cpp
+++ b/mlir/unittests/Dialect/OpenACC/OpenACCUtilsTest.cpp
@@ -485,3 +485,192 @@ TEST_F(OpenACCUtilsTest, getVariableNameFromCopyin) {
std::string varName = getVariableName(copyinOp->getAccVar());
EXPECT_EQ(varName, name);
}
+
+//===----------------------------------------------------------------------===//
+// getRecipeName Tests
+//===----------------------------------------------------------------------===//
+
+TEST_F(OpenACCUtilsTest, getRecipeNamePrivateScalarMemref) {
+ // Create a scalar memref type
+ auto scalarMemrefTy = MemRefType::get({}, b.getI32Type());
+
+ // Test private recipe with scalar memref
+ std::string recipeName =
+ getRecipeName(RecipeKind::private_recipe, scalarMemrefTy);
+ EXPECT_EQ(recipeName, "privatization_memref_i32_");
+}
+
+TEST_F(OpenACCUtilsTest, getRecipeNameFirstprivateScalarMemref) {
+ // Create a scalar memref type
+ auto scalarMemrefTy = MemRefType::get({}, b.getF32Type());
+
+ // Test firstprivate recipe with scalar memref
+ std::string recipeName =
+ getRecipeName(RecipeKind::firstprivate_recipe, scalarMemrefTy);
+ EXPECT_EQ(recipeName, "firstprivatization_memref_f32_");
+}
+
+TEST_F(OpenACCUtilsTest, getRecipeNameReductionScalarMemref) {
+ // Create a scalar memref type
+ auto scalarMemrefTy = MemRefType::get({}, b.getI64Type());
+
+ // Test reduction recipe with scalar memref
+ std::string recipeName =
+ getRecipeName(RecipeKind::reduction_recipe, scalarMemrefTy);
+ EXPECT_EQ(recipeName, "reduction_memref_i64_");
+}
+
+TEST_F(OpenACCUtilsTest, getRecipeNamePrivate2DMemref) {
+ // Create a 2D memref type
+ auto memref2DTy = MemRefType::get({5, 10}, b.getF32Type());
+
+ // Test private recipe with 2D memref
+ std::string recipeName =
+ getRecipeName(RecipeKind::private_recipe, memref2DTy);
+ EXPECT_EQ(recipeName, "privatization_memref_5x10xf32_");
+}
+
+TEST_F(OpenACCUtilsTest, getRecipeNameFirstprivate2DMemref) {
+ // Create a 2D memref type
+ auto memref2DTy = MemRefType::get({8, 16}, b.getF64Type());
+
+ // Test firstprivate recipe with 2D memref
+ std::string recipeName =
+ getRecipeName(RecipeKind::firstprivate_recipe, memref2DTy);
+ EXPECT_EQ(recipeName, "firstprivatization_memref_8x16xf64_");
+}
+
+TEST_F(OpenACCUtilsTest, getRecipeNameReduction2DMemref) {
+ // Create a 2D memref type
+ auto memref2DTy = MemRefType::get({4, 8}, b.getI32Type());
+
+ // Test reduction recipe with 2D memref
+ std::string recipeName =
+ getRecipeName(RecipeKind::reduction_recipe, memref2DTy);
+ EXPECT_EQ(recipeName, "reduction_memref_4x8xi32_");
+}
+
+TEST_F(OpenACCUtilsTest, getRecipeNamePrivateDynamicMemref) {
+ // Create a memref with dynamic dimensions
+ auto dynamicMemrefTy =
+ MemRefType::get({ShapedType::kDynamic, 10}, b.getI32Type());
+
+ // Test private recipe with dynamic memref
+ std::string recipeName =
+ getRecipeName(RecipeKind::private_recipe, dynamicMemrefTy);
+ EXPECT_EQ(recipeName, "privatization_memref_Ux10xi32_");
+}
+
+TEST_F(OpenACCUtilsTest, getRecipeNamePrivateUnrankedMemref) {
+ // Create an unranked memref type
+ auto unrankedMemrefTy = UnrankedMemRefType::get(b.getI32Type(), 0);
+
+ // Test private recipe with unranked memref
+ std::string recipeName =
+ getRecipeName(RecipeKind::private_recipe, unrankedMemrefTy);
+ EXPECT_EQ(recipeName, "privatization_memref_Zxi32_");
+}
+
+//===----------------------------------------------------------------------===//
+// getBaseEntity Tests
+//===----------------------------------------------------------------------===//
+
+// Local implementation of PartialEntityAccessOpInterface for memref.subview.
+// This is implemented locally in the test rather than officially because memref
+// operations already have ViewLikeOpInterface, which serves a similar purpose
+// for walking through views to the base entity. This test demonstrates how
+// getBaseEntity() would work if the interface were attached to memref.subview.
+namespace {
+struct SubViewOpPartialEntityAccessOpInterface
+ : public acc::PartialEntityAccessOpInterface::ExternalModel<
+ SubViewOpPartialEntityAccessOpInterface, memref::SubViewOp> {
+ Value getBaseEntity(Operation *op) const {
+ auto subviewOp = cast<memref::SubViewOp>(op);
+ return subviewOp.getSource();
+ }
+
+ bool isCompleteView(Operation *op) const {
+ // For testing purposes, we'll consider it a partial view (return false).
+ // The real implementation would need to look at the offsets.
+ return false;
+ }
+};
+} // namespace
+
+TEST_F(OpenACCUtilsTest, getBaseEntityFromSubview) {
+ // Register the local interface implementation for memref.subview
+ memref::SubViewOp::attachInterface<SubViewOpPartialEntityAccessOpInterface>(
+ context);
+
+ // Create a base memref
+ auto memrefTy = MemRefType::get({10, 20}, b.getF32Type());
+ OwningOpRef<memref::AllocaOp> allocOp =
+ memref::AllocaOp::create(b, loc, memrefTy);
+ Value baseMemref = allocOp->getResult();
+
+ // Create a subview of the base memref with non-zero offsets
+ // This creates a 5x10 view starting at [2, 3] in the original 10x20 memref
+ SmallVector<OpFoldResult> offsets = {b.getIndexAttr(2), b.getIndexAttr(3)};
+ SmallVector<OpFoldResult> sizes = {b.getIndexAttr(5), b.getIndexAttr(10)};
+ SmallVector<OpFoldResult> strides = {b.getIndexAttr(1), b.getIndexAttr(1)};
+
+ OwningOpRef<memref::SubViewOp> subviewOp =
+ memref::SubViewOp::create(b, loc, baseMemref, offsets, sizes, strides);
+ Value subview = subviewOp->getResult();
+
+ // Test that getBaseEntity returns the base memref, not the subview
+ Value baseEntity = getBaseEntity(subview);
+ EXPECT_EQ(baseEntity, baseMemref);
+}
+
+TEST_F(OpenACCUtilsTest, getBaseEntityNoInterface) {
+ // Create a memref without the interface
+ auto memrefTy = MemRefType::get({10}, b.getI32Type());
+ OwningOpRef<memref::AllocaOp> allocOp =
+ memref::AllocaOp::create(b, loc, memrefTy);
+ Value varPtr = allocOp->getResult();
+
+ // Test that getBaseEntity returns the value itself when there's no interface
+ Value baseEntity = getBaseEntity(varPtr);
+ EXPECT_EQ(baseEntity, varPtr);
+}
+
+TEST_F(OpenACCUtilsTest, getBaseEntityChainedSubviews) {
+ // Register the local interface implementation for memref.subview
+ memref::SubViewOp::attachInterface<SubViewOpPartialEntityAccessOpInterface>(
+ context);
+
+ // Create a base memref
+ auto memrefTy = MemRefType::get({100, 200}, b.getI64Type());
+ OwningOpRef<memref::AllocaOp> allocOp =
+ memref::AllocaOp::create(b, loc, memrefTy);
+ Value baseMemref = allocOp->getResult();
+
+ // Create first subview
+ SmallVector<OpFoldResult> offsets1 = {b.getIndexAttr(10), b.getIndexAttr(20)};
+ SmallVector<OpFoldResult> sizes1 = {b.getIndexAttr(50), b.getIndexAttr(80)};
+ SmallVector<OpFoldResult> strides1 = {b.getIndexAttr(1), b.getIndexAttr(1)};
+
+ OwningOpRef<memref::SubViewOp> subview1Op =
+ memref::SubViewOp::create(b, loc, baseMemref, offsets1, sizes1, strides1);
+ Value subview1 = subview1Op->getResult();
+
+ // Create second subview (subview of subview)
+ SmallVector<OpFoldResult> offsets2 = {b.getIndexAttr(5), b.getIndexAttr(10)};
+ SmallVector<OpFoldResult> sizes2 = {b.getIndexAttr(20), b.getIndexAttr(30)};
+ SmallVector<OpFoldResult> strides2 = {b.getIndexAttr(1), b.getIndexAttr(1)};
+
+ OwningOpRef<memref::SubViewOp> subview2Op =
+ memref::SubViewOp::create(b, loc, subview1, offsets2, sizes2, strides2);
+ Value subview2 = subview2Op->getResult();
+
+ // Test that getBaseEntity on the nested subview returns the first subview
+ // (since our implementation returns the immediate source, not the ultimate
+ // base)
+ Value baseEntity = getBaseEntity(subview2);
+ EXPECT_EQ(baseEntity, subview1);
+
+ // Test that calling getBaseEntity again returns the original base
+ Value ultimateBase = getBaseEntity(baseEntity);
+ EXPECT_EQ(ultimateBase, baseMemref);
+}
diff --git a/mlir/unittests/Interfaces/ControlFlowInterfacesTest.cpp b/mlir/unittests/Interfaces/ControlFlowInterfacesTest.cpp
index f1aae15..2e6950f 100644
--- a/mlir/unittests/Interfaces/ControlFlowInterfacesTest.cpp
+++ b/mlir/unittests/Interfaces/ControlFlowInterfacesTest.cpp
@@ -13,17 +13,24 @@
#include "mlir/IR/OpDefinition.h"
#include "mlir/IR/OpImplementation.h"
#include "mlir/Parser/Parser.h"
+#include "llvm/Support/DebugLog.h"
#include <gtest/gtest.h>
using namespace mlir;
/// A dummy op that is also a terminator.
-struct DummyOp : public Op<DummyOp, OpTrait::IsTerminator> {
+struct DummyOp : public Op<DummyOp, OpTrait::IsTerminator, OpTrait::ZeroResults,
+ OpTrait::ZeroSuccessors,
+ RegionBranchTerminatorOpInterface::Trait> {
using Op::Op;
static ArrayRef<StringRef> getAttributeNames() { return {}; }
static StringRef getOperationName() { return "cftest.dummy_op"; }
+
+ MutableOperandRange getMutableSuccessorOperands(RegionSuccessor point) {
+ return MutableOperandRange(getOperation(), 0, 0);
+ }
};
/// All regions of this op are mutually exclusive.
@@ -39,6 +46,8 @@ struct MutuallyExclusiveRegionsOp
// Regions have no successors.
void getSuccessorRegions(RegionBranchPoint point,
SmallVectorImpl<RegionSuccessor> &regions) {}
+ using RegionBranchOpInterface::Trait<
+ MutuallyExclusiveRegionsOp>::getSuccessorRegions;
};
/// All regions of this op call each other in a large circle.
@@ -53,13 +62,18 @@ struct LoopRegionsOp
void getSuccessorRegions(RegionBranchPoint point,
SmallVectorImpl<RegionSuccessor> &regions) {
- if (Region *region = point.getRegionOrNull()) {
- if (point == (*this)->getRegion(1))
+ if (point.getTerminatorPredecessorOrNull()) {
+ Region *region =
+ point.getTerminatorPredecessorOrNull()->getParentRegion();
+ if (region == &(*this)->getRegion(1))
// This region also branches back to the parent.
- regions.push_back(RegionSuccessor());
+ regions.push_back(
+ RegionSuccessor(getOperation()->getParentOp(),
+ getOperation()->getParentOp()->getResults()));
regions.push_back(RegionSuccessor(region));
}
}
+ using RegionBranchOpInterface::Trait<LoopRegionsOp>::getSuccessorRegions;
};
/// Each region branches back it itself or the parent.
@@ -75,11 +89,17 @@ struct DoubleLoopRegionsOp
void getSuccessorRegions(RegionBranchPoint point,
SmallVectorImpl<RegionSuccessor> &regions) {
- if (Region *region = point.getRegionOrNull()) {
- regions.push_back(RegionSuccessor());
+ if (point.getTerminatorPredecessorOrNull()) {
+ Region *region =
+ point.getTerminatorPredecessorOrNull()->getParentRegion();
+ regions.push_back(
+ RegionSuccessor(getOperation()->getParentOp(),
+ getOperation()->getParentOp()->getResults()));
regions.push_back(RegionSuccessor(region));
}
}
+ using RegionBranchOpInterface::Trait<
+ DoubleLoopRegionsOp>::getSuccessorRegions;
};
/// Regions are executed sequentially.
@@ -93,11 +113,15 @@ struct SequentialRegionsOp
// Region 0 has Region 1 as a successor.
void getSuccessorRegions(RegionBranchPoint point,
SmallVectorImpl<RegionSuccessor> &regions) {
- if (point == (*this)->getRegion(0)) {
+ if (point.getTerminatorPredecessorOrNull() &&
+ point.getTerminatorPredecessorOrNull()->getParentRegion() ==
+ &(*this)->getRegion(0)) {
Operation *thisOp = this->getOperation();
regions.push_back(RegionSuccessor(&thisOp->getRegion(1)));
}
}
+ using RegionBranchOpInterface::Trait<
+ SequentialRegionsOp>::getSuccessorRegions;
};
/// A dialect putting all the above together.