-
Notifications
You must be signed in to change notification settings - Fork 13.5k
[mlir][llvm] Fix verifier for const float #74247
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
[mlir][llvm] Fix verifier for const float #74247
Conversation
@llvm/pr-subscribers-mlir @llvm/pr-subscribers-mlir-llvm Author: Rik Huijzer (rikhuijzer) ChangesFixes one of the cases of #56962. This PR basically moves some code from Full diff: https://github.com/llvm/llvm-project/pull/74247.diff 3 Files Affected:
diff --git a/mlir/lib/Dialect/LLVMIR/IR/LLVMDialect.cpp b/mlir/lib/Dialect/LLVMIR/IR/LLVMDialect.cpp
index f6c8f388732c3..71860363b8ea5 100644
--- a/mlir/lib/Dialect/LLVMIR/IR/LLVMDialect.cpp
+++ b/mlir/lib/Dialect/LLVMIR/IR/LLVMDialect.cpp
@@ -2539,6 +2539,20 @@ LogicalResult LLVM::ConstantOp::verify() {
if (!llvm::isa<IntegerAttr, ArrayAttr, FloatAttr, ElementsAttr>(getValue()))
return emitOpError()
<< "only supports integer, float, string or elements attributes";
+ if (auto floatAttr = dyn_cast<FloatAttr>(getValue())) {
+ const llvm::fltSemantics &sem = floatAttr.getValue().getSemantics();
+ unsigned floatWidth = APFloat::getSizeInBits(sem);
+ if (auto floatTy = dyn_cast<FloatType>(getType())) {
+ if (floatTy.getWidth() != floatWidth) {
+ return emitOpError() << "expected float type of width " << floatWidth;
+ }
+ }
+ // See the comment for getLLVMConstant for more details about why 8-bit
+ // floats can be represented by integers.
+ if (getType().isa<IntegerType>() && !getType().isInteger(floatWidth)) {
+ return emitOpError() << "expected integer type of width " << floatWidth;
+ }
+ }
return success();
}
diff --git a/mlir/test/Target/LLVMIR/llvmir-invalid.mlir b/mlir/test/Target/LLVMIR/llvmir-invalid.mlir
index e531c3cb4e240..0def5895fb330 100644
--- a/mlir/test/Target/LLVMIR/llvmir-invalid.mlir
+++ b/mlir/test/Target/LLVMIR/llvmir-invalid.mlir
@@ -31,6 +31,22 @@ llvm.func @struct_wrong_attribute_element_type() -> !llvm.struct<(f64, f64)> {
// -----
+llvm.func @incompatible_float_attribute_type() -> f32 {
+ // expected-error @below{{expected float type of width 64}}
+ %cst = llvm.mlir.constant(1.0 : f64) : f32
+ llvm.return %cst : f32
+}
+
+// -----
+
+llvm.func @incompatible_integer_type_for_float_attr() -> i32 {
+ // expected-error @below{{expected integer type of width 16}}
+ %cst = llvm.mlir.constant(1.0 : f16) : i32
+ llvm.return %cst : i32
+}
+
+// -----
+
// expected-error @below{{unsupported constant value}}
llvm.mlir.global internal constant @test([2.5, 7.4]) : !llvm.array<2 x f64>
diff --git a/mlir/test/Target/LLVMIR/llvmir.mlir b/mlir/test/Target/LLVMIR/llvmir.mlir
index ab8506ff163ef..3f84f9dc5a9b8 100644
--- a/mlir/test/Target/LLVMIR/llvmir.mlir
+++ b/mlir/test/Target/LLVMIR/llvmir.mlir
@@ -66,7 +66,7 @@ llvm.mlir.global external @explicit_undef() : i32 {
// CHECK: @int_gep = internal constant ptr getelementptr (i32, ptr @i32_global, i32 2)
llvm.mlir.global internal constant @int_gep() : !llvm.ptr {
%addr = llvm.mlir.addressof @i32_global : !llvm.ptr
- %_c0 = llvm.mlir.constant(2: i32) :i32
+ %_c0 = llvm.mlir.constant(2: i32) : i32
%gepinit = llvm.getelementptr %addr[%_c0] : (!llvm.ptr, i32) -> !llvm.ptr, i32
llvm.return %gepinit : !llvm.ptr
}
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the fix!
Continuation of #74247 to fix #56962. Fixes verifier for (Integer Attr): ```mlir llvm.mlir.constant(1 : index) : f32 ``` and (Dense Attr): ```mlir llvm.mlir.constant(dense<100.0> : vector<1xf64>) : f32 ``` ## Integer Attr The addition that this PR makes to `LLVM::ConstantOp::verify` is meant to be exactly verifying the code in `mlir::LLVM::detail::getLLVMConstant`: https://github.com/llvm/llvm-project/blob/9f78edbd20ed922cced9482f7791deb9899a6d82/mlir/lib/Target/LLVMIR/ModuleTranslation.cpp#L350-L353 One failure mode is when the `type` (`llvm.mlir.constant(<value>) : <type>`) is not an `Integer`, because then the `cast` in `getIntegerBitWidth` will crash: https://github.com/llvm/llvm-project/blob/dca432cb7b1c282f5dc861095813c4f40f109619/llvm/include/llvm/IR/DerivedTypes.h#L97-L99 So that's now caught in the verifier. Apart from that, I don't see anything we could check for. `sextOrTrunc` means "Sign extend or truncate to width" and that one is quite permissive. For example, the following doesn't have to be caught in the verifier as it doesn't crash during `mlir-translate -mlir-to-llvmir`: ```mlir llvm.func @main() -> f32 { %cst = llvm.mlir.constant(100 : i64) : f32 llvm.return %cst : f32 } ``` ## Dense Attr Crash if not either a MLIR Vector type or one of these: https://github.com/llvm/llvm-project/blob/9f78edbd20ed922cced9482f7791deb9899a6d82/mlir/lib/Target/LLVMIR/ModuleTranslation.cpp#L375-L391
Fixes one of the cases of #56962.
This PR basically moves some code from
mlir::LLVM::detail::getLLVMConstant
(source) over to the verifier ofLLVM::ConstantOp
. For now, I focused just on the case where the attribute is a float and ignored the integer case of #56962. Note that without this patch, both added tests will crash insidegetLLVMConstant
duringmlir-translate -mlir-to-llvmir
.