Skip to content

Commit c2cb493

Browse files
[mlir][remarks] Add support for Attributes in Remark Args (#170882)
Extend Remark::Arg to optionally store the original Attribute when constructed from one. This allows custom remark streamers to access the underlying attribute for type-specific handling, rather than being limited to the string representation. For example, a streamer processing an ArrayAttr argument can iterate over its elements, or a streamer can check the specific attribute type to apply custom formatting. Changes: - Add std::optional<Attribute> member to Remark::Arg - Update Arg(StringRef, Attribute) constructor to store the attribute - Add hasAttribute() and getAttribute() accessors - Add unit test for Arg with ArrayAttr
1 parent 8505a87 commit c2cb493

File tree

3 files changed

+51
-1
lines changed

3 files changed

+51
-1
lines changed

mlir/include/mlir/IR/Remarks.h

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -99,18 +99,30 @@ class Remark {
9999
}
100100

101101
// Remark argument that is a key-value pair that can be printed as machine
102-
// parsable args.
102+
// parsable args. For Attribute arguments, the original attribute is also
103+
// stored to allow custom streamers to handle them specially.
103104
struct Arg {
104105
std::string key;
105106
std::string val;
107+
/// Optional attribute storage for Attribute-based args. Allows streamers
108+
/// to access the original attribute for custom handling.
109+
std::optional<Attribute> attr;
110+
106111
Arg(llvm::StringRef m) : key("Remark"), val(m) {}
107112
Arg(llvm::StringRef k, llvm::StringRef v) : key(k), val(v) {}
108113
Arg(llvm::StringRef k, std::string v) : key(k), val(std::move(v)) {}
109114
Arg(llvm::StringRef k, const char *v) : Arg(k, llvm::StringRef(v)) {}
110115
Arg(llvm::StringRef k, Value v);
111116
Arg(llvm::StringRef k, Type t);
117+
Arg(llvm::StringRef k, Attribute a);
112118
Arg(llvm::StringRef k, bool b) : key(k), val(b ? "true" : "false") {}
113119

120+
/// Check if this arg has an associated attribute.
121+
bool hasAttribute() const { return attr.has_value(); }
122+
123+
/// Get the attribute if present.
124+
Attribute getAttribute() const { return attr.value_or(Attribute()); }
125+
114126
// One constructor for all arithmetic types except bool.
115127
template <typename T, typename = std::enable_if_t<std::is_arithmetic_v<T> &&
116128
!std::is_same_v<T, bool>>>

mlir/lib/IR/Remarks.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,11 @@ Remark::Arg::Arg(llvm::StringRef k, Type t) : key(k) {
3131
os << t;
3232
}
3333

34+
Remark::Arg::Arg(llvm::StringRef k, Attribute a) : key(k), attr(a) {
35+
llvm::raw_string_ostream os(val);
36+
os << a;
37+
}
38+
3439
void Remark::insert(llvm::StringRef s) { args.emplace_back(s); }
3540
void Remark::insert(Arg a) { args.push_back(std::move(a)); }
3641

mlir/unittests/IR/RemarkTest.cpp

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@
66
//
77
//===----------------------------------------------------------------------===//
88

9+
#include "mlir/IR/BuiltinAttributes.h"
10+
#include "mlir/IR/BuiltinTypes.h"
911
#include "mlir/IR/Diagnostics.h"
1012
#include "mlir/IR/MLIRContext.h"
1113
#include "mlir/IR/Remarks.h"
@@ -377,4 +379,35 @@ TEST(Remark, TestRemarkFinal) {
377379
EXPECT_NE(errOut.find(pass3Msg), std::string::npos); // shown
378380
EXPECT_NE(errOut.find(pass4Msg), std::string::npos); // shown
379381
}
382+
383+
TEST(Remark, TestArgWithAttribute) {
384+
MLIRContext context;
385+
386+
SmallVector<Attribute> elements;
387+
elements.push_back(IntegerAttr::get(IntegerType::get(&context, 32), 1));
388+
elements.push_back(IntegerAttr::get(IntegerType::get(&context, 32), 2));
389+
elements.push_back(IntegerAttr::get(IntegerType::get(&context, 32), 3));
390+
ArrayAttr arrayAttr = ArrayAttr::get(&context, elements);
391+
remark::detail::Remark::Arg argWithArray("Values", arrayAttr);
392+
393+
// Verify the attribute is stored
394+
EXPECT_TRUE(argWithArray.hasAttribute());
395+
EXPECT_EQ(argWithArray.getAttribute(), arrayAttr);
396+
397+
// Ensure it can be retrieved as an ArrayAttr.
398+
auto retrievedAttr = dyn_cast<ArrayAttr>(argWithArray.getAttribute());
399+
EXPECT_TRUE(retrievedAttr);
400+
EXPECT_EQ(retrievedAttr.size(), 3u);
401+
EXPECT_EQ(cast<IntegerAttr>(retrievedAttr[0]).getInt(), 1);
402+
EXPECT_EQ(cast<IntegerAttr>(retrievedAttr[1]).getInt(), 2);
403+
EXPECT_EQ(cast<IntegerAttr>(retrievedAttr[2]).getInt(), 3);
404+
405+
// Create an Arg without an Attribute (string-based)
406+
remark::detail::Remark::Arg argWithoutAttr("Key", "Value");
407+
408+
// Verify no attribute is stored
409+
EXPECT_FALSE(argWithoutAttr.hasAttribute());
410+
EXPECT_FALSE(argWithoutAttr.getAttribute()); // Returns null Attribute
411+
EXPECT_EQ(argWithoutAttr.val, "Value");
412+
}
380413
} // namespace

0 commit comments

Comments
 (0)