-
Notifications
You must be signed in to change notification settings - Fork 14.2k
[mlir][Value] Add getNumUses, hasNUses, and hasNUsesOrMore to Value #142084
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
Conversation
We already have hasOneUse. Like llvm::Value we provide helper methods to query the number of uses of a Value. Add unittests for Value, because that was missing.
@llvm/pr-subscribers-mlir-core @llvm/pr-subscribers-mlir Author: Michael Maitland (michaelmaitland) ChangesWe already have hasOneUse. Like llvm::Value we provide helper methods to query the number of uses of a Value. Add unittests for Value, because that was missing. Full diff: https://github.com/llvm/llvm-project/pull/142084.diff 8 Files Affected:
diff --git a/mlir/docs/Tutorials/UnderstandingTheIRStructure.md b/mlir/docs/Tutorials/UnderstandingTheIRStructure.md
index 595d6949a03f3..30b50cb09490d 100644
--- a/mlir/docs/Tutorials/UnderstandingTheIRStructure.md
+++ b/mlir/docs/Tutorials/UnderstandingTheIRStructure.md
@@ -257,14 +257,10 @@ results and print informations about them:
llvm::outs() << " has no uses\n";
continue;
}
- if (result.hasOneUse()) {
+ if (result.hasOneUse())
llvm::outs() << " has a single use: ";
- } else {
- llvm::outs() << " has "
- << std::distance(result.getUses().begin(),
- result.getUses().end())
- << " uses:\n";
- }
+ else
+ llvm::outs() << " has " << result.getNumUses() << " uses:\n";
for (Operation *userOp : result.getUsers()) {
llvm::outs() << " - " << userOp->getName() << "\n";
}
diff --git a/mlir/include/mlir/IR/Value.h b/mlir/include/mlir/IR/Value.h
index d54e3c0ad26dd..4d6d89fa69a07 100644
--- a/mlir/include/mlir/IR/Value.h
+++ b/mlir/include/mlir/IR/Value.h
@@ -187,9 +187,23 @@ class Value {
/// Returns a range of all uses, which is useful for iterating over all uses.
use_range getUses() const { return {use_begin(), use_end()}; }
+ /// This method computes the number of uses of this Value.
+ ///
+ /// This is a linear time operation. Use hasOneUse, hasNUses, or
+ /// hasNUsesOrMore to check for specific values.
+ unsigned getNumUses() const;
+
/// Returns true if this value has exactly one use.
bool hasOneUse() const { return impl->hasOneUse(); }
+ /// Return true if this Value has exactly n uses.
+ bool hasNUses(unsigned n) const;
+
+ /// Return true if this value has n uses or more.
+ ///
+ /// This is logically equivalent to getNumUses() >= N.
+ bool hasNUsesOrMore(unsigned n) const;
+
/// Returns true if this value has no uses.
bool use_empty() const { return impl->use_empty(); }
diff --git a/mlir/lib/Bytecode/Reader/BytecodeReader.cpp b/mlir/lib/Bytecode/Reader/BytecodeReader.cpp
index 1052946d4550b..44458d010c6c8 100644
--- a/mlir/lib/Bytecode/Reader/BytecodeReader.cpp
+++ b/mlir/lib/Bytecode/Reader/BytecodeReader.cpp
@@ -1993,8 +1993,7 @@ LogicalResult BytecodeReader::Impl::sortUseListOrder(Value value) {
UseListOrderStorage customOrder =
valueToUseListMap.at(value.getAsOpaquePointer());
SmallVector<unsigned, 4> shuffle = std::move(customOrder.indices);
- uint64_t numUses =
- std::distance(value.getUses().begin(), value.getUses().end());
+ uint64_t numUses = value.getNumUses();
// If the encoding was a pair of indices `(src, dst)` for every permutation,
// reconstruct the shuffle vector for every use. Initialize the shuffle vector
diff --git a/mlir/lib/Dialect/SCF/IR/SCF.cpp b/mlir/lib/Dialect/SCF/IR/SCF.cpp
index 748379ea671be..5a0b8a058dd65 100644
--- a/mlir/lib/Dialect/SCF/IR/SCF.cpp
+++ b/mlir/lib/Dialect/SCF/IR/SCF.cpp
@@ -1787,7 +1787,7 @@ struct ForallOpReplaceConstantInductionVar : public OpRewritePattern<ForallOp> {
for (auto [lb, ub, step, iv] :
llvm::zip(op.getMixedLowerBound(), op.getMixedUpperBound(),
op.getMixedStep(), op.getInductionVars())) {
- if (iv.getUses().begin() == iv.getUses().end())
+ if (iv.hasNUses(0))
continue;
auto numIterations = constantTripCount(lb, ub, step);
if (!numIterations.has_value() || numIterations.value() != 1) {
diff --git a/mlir/lib/IR/Value.cpp b/mlir/lib/IR/Value.cpp
index 178765353cc10..7b3a9462a0917 100644
--- a/mlir/lib/IR/Value.cpp
+++ b/mlir/lib/IR/Value.cpp
@@ -51,6 +51,18 @@ Block *Value::getParentBlock() {
return llvm::cast<BlockArgument>(*this).getOwner();
}
+unsigned Value::getNumUses() const {
+ return (unsigned)std::distance(use_begin(), use_end());
+}
+
+bool Value::hasNUses(unsigned n) const {
+ return hasNItems(use_begin(), use_end(), n);
+}
+
+bool Value::hasNUsesOrMore(unsigned n) const {
+ return hasNItemsOrMore(use_begin(), use_end(), n);
+}
+
//===----------------------------------------------------------------------===//
// Value::UseLists
//===----------------------------------------------------------------------===//
diff --git a/mlir/test/lib/IR/TestPrintDefUse.cpp b/mlir/test/lib/IR/TestPrintDefUse.cpp
index 5d489a342f57d..b983366fc16dd 100644
--- a/mlir/test/lib/IR/TestPrintDefUse.cpp
+++ b/mlir/test/lib/IR/TestPrintDefUse.cpp
@@ -49,14 +49,10 @@ struct TestPrintDefUsePass
llvm::outs() << " has no uses\n";
continue;
}
- if (result.hasOneUse()) {
+ if (result.hasOneUse())
llvm::outs() << " has a single use: ";
- } else {
- llvm::outs() << " has "
- << std::distance(result.getUses().begin(),
- result.getUses().end())
- << " uses:\n";
- }
+ else
+ llvm::outs() << " has " << result.getNumUses() << " uses:\n";
for (Operation *userOp : result.getUsers()) {
llvm::outs() << " - " << userOp->getName() << "\n";
}
diff --git a/mlir/unittests/IR/CMakeLists.txt b/mlir/unittests/IR/CMakeLists.txt
index 821ff7d14dabd..9ab6029c3480d 100644
--- a/mlir/unittests/IR/CMakeLists.txt
+++ b/mlir/unittests/IR/CMakeLists.txt
@@ -17,6 +17,7 @@ add_mlir_unittest(MLIRIRTests
TypeTest.cpp
TypeAttrNamesTest.cpp
OpPropertiesTest.cpp
+ ValueTest.cpp
DEPENDS
MLIRTestInterfaceIncGen
diff --git a/mlir/unittests/IR/ValueTest.cpp b/mlir/unittests/IR/ValueTest.cpp
new file mode 100644
index 0000000000000..e31d9f32bc1d1
--- /dev/null
+++ b/mlir/unittests/IR/ValueTest.cpp
@@ -0,0 +1,90 @@
+//===- mlir/unittest/IR/ValueTest.cpp - Value unit tests ------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "../../test/lib/Dialect/Test/TestDialect.h"
+#include "../../test/lib/Dialect/Test/TestOps.h"
+#include "mlir/IR/Builders.h"
+#include "mlir/IR/BuiltinTypes.h"
+#include "mlir/IR/OperationSupport.h"
+#include "mlir/IR/Value.h"
+#include "gtest/gtest.h"
+
+using namespace mlir;
+
+static Operation *createOp(MLIRContext *context,
+ ArrayRef<Value> operands = std::nullopt,
+ ArrayRef<Type> resultTypes = std::nullopt,
+ unsigned int numRegions = 0) {
+ context->allowUnregisteredDialects();
+ return Operation::create(
+ UnknownLoc::get(context), OperationName("foo.bar", context), resultTypes,
+ operands, std::nullopt, nullptr, std::nullopt, numRegions);
+}
+
+namespace {
+
+TEST(ValueTest, getNumUses) {
+ MLIRContext context;
+ Builder builder(&context);
+
+ Operation *op0 =
+ createOp(&context, /*operands=*/std::nullopt, builder.getIntegerType(16));
+
+ Value v0 = op0->getResult(0);
+ EXPECT_EQ(v0.getNumUses(), (unsigned)0);
+
+ createOp(&context, {v0}, builder.getIntegerType(16));
+ EXPECT_EQ(v0.getNumUses(), (unsigned)1);
+
+ createOp(&context, {v0, v0}, builder.getIntegerType(16));
+ EXPECT_EQ(v0.getNumUses(), (unsigned)3);
+}
+
+TEST(ValueTest, hasNUses) {
+ MLIRContext context;
+ Builder builder(&context);
+
+ Operation *op =
+ createOp(&context, /*operands=*/std::nullopt, builder.getIntegerType(16));
+ Value v0 = op->getResult(0);
+ EXPECT_TRUE(v0.hasNUses(0));
+ EXPECT_FALSE(v0.hasNUses(1));
+
+ createOp(&context, {v0}, builder.getIntegerType(16));
+ EXPECT_FALSE(v0.hasNUses(0));
+ EXPECT_TRUE(v0.hasNUses(1));
+
+ createOp(&context, {v0, v0}, builder.getIntegerType(16));
+ EXPECT_FALSE(v0.hasNUses(0));
+ EXPECT_FALSE(v0.hasNUses(1));
+ EXPECT_TRUE(v0.hasNUses(3));
+}
+
+TEST(ValueTest, hasNUsesOrMore) {
+ MLIRContext context;
+ Builder builder(&context);
+
+ Operation *op =
+ createOp(&context, /*operands=*/std::nullopt, builder.getIntegerType(16));
+ Value v0 = op->getResult(0);
+ EXPECT_TRUE(v0.hasNUsesOrMore(0));
+ EXPECT_FALSE(v0.hasNUsesOrMore(1));
+
+ createOp(&context, {v0}, builder.getIntegerType(16));
+ EXPECT_TRUE(v0.hasNUsesOrMore(0));
+ EXPECT_TRUE(v0.hasNUsesOrMore(1));
+ EXPECT_FALSE(v0.hasNUsesOrMore(2));
+
+ createOp(&context, {v0, v0}, builder.getIntegerType(16));
+ EXPECT_TRUE(v0.hasNUsesOrMore(0));
+ EXPECT_TRUE(v0.hasNUsesOrMore(1));
+ EXPECT_TRUE(v0.hasNUsesOrMore(3));
+ EXPECT_FALSE(v0.hasNUsesOrMore(4));
+}
+
+} // end anonymous namespace
|
✅ With the latest revision this PR passed the C/C++ code formatter. |
LLVM Buildbot has detected a new failure on builder Full details are available at: https://lab.llvm.org/buildbot/#/builders/55/builds/12091 Here is the relevant piece of the build log for the reference
|
LLVM Buildbot has detected a new failure on builder Full details are available at: https://lab.llvm.org/buildbot/#/builders/24/builds/8975 Here is the relevant piece of the build log for the reference
|
LLVM Buildbot has detected a new failure on builder Full details are available at: https://lab.llvm.org/buildbot/#/builders/169/builds/11846 Here is the relevant piece of the build log for the reference
|
LLVM Buildbot has detected a new failure on builder Full details are available at: https://lab.llvm.org/buildbot/#/builders/52/builds/8722 Here is the relevant piece of the build log for the reference
|
…lvm#142084) We already have hasOneUse. Like llvm::Value we provide helper methods to query the number of uses of a Value. Add unittests for Value, because that was missing. --------- Co-authored-by: Michael Maitland <michaelmaitland@meta.com>
We already have hasOneUse. Like llvm::Value we provide helper methods to query the number of uses of a Value. Add unittests for Value, because that was missing.