Hi folks,
I’m playing around with MLIR and hitting an issue with verification and Attribute::isa
.
TL;DR:
mlir::IntegerAttr::get(i32, 42).isa<mlir::IntegerAttr>()
yelds false
and I’m not sure I understand what is going on.
Details:
The original issue is coming from a simple Dialect.td
which prints verification errors like this:
loc("whatever":1:0): error: 'foobar.ui32' op attribute 'value' failed to satisfy constraint: 32-bit unsigned integer attribute
with the op in question being
%1 = "foobar.ui32"() {value = 42 : ui32} : () -> ui32
Upon investigation, I boiled the issue down to the following reproducer:
// main.cpp
#include <mlir/IR/BuiltinAttributes.h>
#include <mlir/IR/BuiltinTypes.h>
#include <mlir/IR/MLIRContext.h>
int main() {
mlir::MLIRContext context;
auto i32 = mlir::IntegerType::get(&context, 32);
mlir::IntegerAttr intAttr = mlir::IntegerAttr::get(i32, 42);
llvm::errs() << intAttr.isa<mlir::IntegerAttr>() << "\n";
// For debugging only
mlir::Attribute attr = intAttr;
llvm::errs() << "IntegerAttr: " << intAttr.getTypeID().getAsOpaquePointer() << "\n";
llvm::errs() << "Attribute: " << attr.getTypeID().getAsOpaquePointer() << "\n";
return 0;
}
cmake_minimum_required(VERSION 3.22)
project(MLIRAttrTest)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)
find_package(LLVM CONFIG REQUIRED)
find_package(MLIR CONFIG REQUIRED)
include_directories(${MLIR_INCLUDE_DIRS})
add_executable(MLIRAttrTest main.cpp)
target_compile_options(MLIRAttrTest PRIVATE -fno-rtti)
target_link_libraries(MLIRAttrTest LLVM MLIR)
I’m building the project on macOS with the following invocation (I’m using precompiled LLVM 13 from Homebrew):
> cmake -DCMAKE_PREFIX_PATH=/usr/local/opt/llvm/lib/cmake
> make MLIRAttrTest
> ./MLIRAttrTest
0
0x103830118
0x1068a5cb0
The first line outputs 0
meaning that effectively
mlir::IntegerAttr::get(i32, 42).isa<mlir::IntegerAttr>()
is false
.
The isa
call goes through
// mlir/IR/Attributes.h:102
template <typename U> bool Attribute::isa() const {
assert(impl && "isa<> used on a null attribute.");
return U::classof(*this);
}
and then through
// mlir/IR/StorageUniquerSupport.h:79
template <typename T> static bool classof(T val) {
static_assert(std::is_convertible<ConcreteT, T>::value,
"casting from a non-convertible type");
return val.getTypeID() == getTypeID();
}
with the val.getTypeID() == getTypeID()
yielding false
.
I modified the classof
method as follows:
template <typename T> static bool classof(T val) {
static_assert(std::is_convertible<ConcreteT, T>::value,
"casting from a non-convertible type");
auto this_ = getTypeID();
auto that = val.getTypeID();
llvm::errs() << "this: " << this_.getAsOpaquePointer() << "\n";
llvm::errs() << "that: " << that.getAsOpaquePointer() << "\n";
return this_ == that;
}
And the program now outputs this:
this: 0x10a0980f8
that: 0x10d10dcb0
0
IntegerAttr: 0x10a0980f8
Attribute: 0x10d10dcb0
I believe I don’t do anything obviously wrong, so any hints on why this happens (and how to use/workaround it) would be highly appreciated!
Thanks,
Alex.