diff --git a/mlir/lib/Target/LLVMIR/ConvertFromLLVMIR.cpp b/mlir/lib/Target/LLVMIR/ConvertFromLLVMIR.cpp --- a/mlir/lib/Target/LLVMIR/ConvertFromLLVMIR.cpp +++ b/mlir/lib/Target/LLVMIR/ConvertFromLLVMIR.cpp @@ -17,6 +17,7 @@ #include "mlir/Target/LLVMIR/Import.h" #include "mlir/Tools/mlir-translate/Translation.h" #include "llvm/IR/Module.h" +#include "llvm/IR/Verifier.h" #include "llvm/IRReader/IRReader.h" #include "llvm/Support/SourceMgr.h" @@ -40,6 +41,8 @@ emitError(UnknownLoc::get(context)) << errStream.str(); return {}; } + if (llvm::verifyModule(*llvmModule, &llvm::errs())) + return nullptr; return translateLLVMIRToModule(std::move(llvmModule), context); }, [](DialectRegistry ®istry) { diff --git a/mlir/lib/Target/LLVMIR/Dialect/LLVMIR/LLVMIRToLLVMTranslation.cpp b/mlir/lib/Target/LLVMIR/Dialect/LLVMIR/LLVMIRToLLVMTranslation.cpp --- a/mlir/lib/Target/LLVMIR/Dialect/LLVMIR/LLVMIRToLLVMTranslation.cpp +++ b/mlir/lib/Target/LLVMIR/Dialect/LLVMIR/LLVMIRToLLVMTranslation.cpp @@ -107,30 +107,25 @@ static LogicalResult setProfilingAttr(OpBuilder &builder, llvm::MDNode *node, Operation *op, LLVM::ModuleImport &moduleImport) { - // Return success for empty metadata nodes since there is nothing to import. + // Return failure for empty metadata nodes since there is nothing to import. if (!node->getNumOperands()) - return op->emitWarning() << "expected non-empty profiling metadata node"; + return failure(); auto *name = dyn_cast(node->getOperand(0)); if (!name) - return op->emitWarning() - << "expected profiling metadata node to have a string identifier"; + return failure(); // Handle function entry count metadata. if (name->getString().equals("function_entry_count")) { - auto emitNodeWarning = [&]() { - return op->emitWarning() - << "expected function_entry_count to hold a single i64 value"; - }; // TODO support function entry count metadata with GUID fields. if (node->getNumOperands() != 2) - return emitNodeWarning(); + return failure(); llvm::ConstantInt *entryCount = llvm::mdconst::dyn_extract(node->getOperand(1)); if (!entryCount) - return emitNodeWarning(); + return failure(); if (auto funcOp = dyn_cast(op)) { funcOp.setFunctionEntryCount(entryCount->getZExtValue()); return success(); @@ -140,8 +135,7 @@ } if (!name->getString().equals("branch_weights")) - return op->emitWarning() - << "unknown profiling metadata node " << name->getString(); + return failure(); // Handle branch weights metadata. SmallVector branchWeights; @@ -150,7 +144,7 @@ llvm::ConstantInt *branchWeight = llvm::mdconst::dyn_extract(node->getOperand(i)); if (!branchWeight) - return op->emitWarning() << "expected branch weights to be integers"; + return failure(); branchWeights.push_back(branchWeight->getZExtValue()); } diff --git a/mlir/lib/Target/LLVMIR/LoopAnnotationImporter.cpp b/mlir/lib/Target/LLVMIR/LoopAnnotationImporter.cpp --- a/mlir/lib/Target/LLVMIR/LoopAnnotationImporter.cpp +++ b/mlir/lib/Target/LLVMIR/LoopAnnotationImporter.cpp @@ -463,8 +463,7 @@ for (const llvm::MDOperand &operand : node->operands()) { auto *childNode = dyn_cast(operand); if (!childNode) - return emitWarning(loc) - << "expected access group operands to be metadata nodes"; + return failure(); accessGroups.push_back(cast(operand.get())); } diff --git a/mlir/test/Target/LLVMIR/Import/basic.ll b/mlir/test/Target/LLVMIR/Import/basic.ll --- a/mlir/test/Target/LLVMIR/Import/basic.ll +++ b/mlir/test/Target/LLVMIR/Import/basic.ll @@ -69,11 +69,9 @@ invoke void @foo(ptr %1) to label %4 unwind label %2 ; CHECK: ^bb1: - ; CHECK: %{{[0-9]+}} = llvm.landingpad (catch %{{[0-9]+}} : !llvm.ptr) (catch %[[a1]] : !llvm.ptr) (filter %{{[0-9]+}} : !llvm.array<1 x i8>) : !llvm.struct<(ptr, i32)> + ; CHECK: %{{[0-9]+}} = llvm.landingpad (catch %{{[0-9]+}} : !llvm.ptr) (catch %[[a1]] : !llvm.ptr) (filter %{{[0-9]+}} : !llvm.array<1 x i1>) : !llvm.struct<(ptr, i32)> %3 = landingpad { ptr, i32 } catch ptr @_ZTIi catch ptr @_ZTIii - ; FIXME: Change filter to a constant array once they are handled. - ; Currently, even though it parses this, LLVM module is broken - filter [1 x i8] [i8 1] + filter [1 x i1] [i1 1] resume { ptr, i32 } %3 ; CHECK: ^bb2: diff --git a/mlir/test/Target/LLVMIR/Import/function-attributes.ll b/mlir/test/Target/LLVMIR/Import/function-attributes.ll --- a/mlir/test/Target/LLVMIR/Import/function-attributes.ll +++ b/mlir/test/Target/LLVMIR/Import/function-attributes.ll @@ -29,8 +29,6 @@ ; CHECK-LABEL: @func_arg_attrs ; CHECK-SAME: !llvm.ptr {llvm.byval = i64} ; CHECK-SAME: !llvm.ptr {llvm.byref = i64} -; CHECK-SAME: !llvm.ptr {llvm.sret = i64} -; CHECK-SAME: !llvm.ptr {llvm.inalloca = i64} ; CHECK-SAME: !llvm.ptr {llvm.noalias} ; CHECK-SAME: !llvm.ptr {llvm.readonly} ; CHECK-SAME: !llvm.ptr {llvm.nest} @@ -50,8 +48,6 @@ define ptr @func_arg_attrs( ptr byval(i64) %arg0, ptr byref(i64) %arg1, - ptr sret(i64) %arg2, - ptr inalloca(i64) %arg3, ptr noalias %arg4, ptr readonly %arg5, ptr nest %arg6, @@ -71,6 +67,18 @@ ret ptr %arg17 } +; CHECK-LABEL: @sret +; CHECK-SAME: !llvm.ptr {llvm.sret = i64} +define void @sret(ptr sret(i64) %arg0) { + ret void +} + +; CHECK-LABEL: @inalloca +; CHECK-SAME: !llvm.ptr {llvm.inalloca = i64} +define void @inalloca(ptr inalloca(i64) %arg0) { + ret void +} + ; CHECK-LABEL: @allocator ; CHECK-SAME: i64 {llvm.allocalign} ; CHECK-SAME: ptr {llvm.allocptr} diff --git a/mlir/test/Target/LLVMIR/Import/import-failure.ll b/mlir/test/Target/LLVMIR/Import/import-failure.ll --- a/mlir/test/Target/LLVMIR/Import/import-failure.ll +++ b/mlir/test/Target/LLVMIR/Import/import-failure.ll @@ -26,6 +26,7 @@ ; CHECK: import-failure.ll ; CHECK-SAME: error: unhandled instruction: ret ptr blockaddress(@unhandled_constant, %bb1) define ptr @unhandled_constant() { + br label %bb1 bb1: ret ptr blockaddress(@unhandled_constant, %bb1) } @@ -39,6 +40,7 @@ @private = private global ptr blockaddress(@unhandled_global, %bb1) define void @unhandled_global() { + br label %bb1 bb1: ret void } @@ -48,37 +50,15 @@ declare void @llvm.gcroot(ptr %arg1, ptr %arg2) ; CHECK: import-failure.ll -; CHECK-SAME: error: unhandled intrinsic: call void @llvm.gcroot(ptr %arg1, ptr %arg2) -define void @unhandled_intrinsic(ptr %arg1, ptr %arg2) { - call void @llvm.gcroot(ptr %arg1, ptr %arg2) +; CHECK-SAME: error: unhandled intrinsic: call void @llvm.gcroot(ptr %arg1, ptr null) +define void @unhandled_intrinsic() gc "example" { + %arg1 = alloca ptr + call void @llvm.gcroot(ptr %arg1, ptr null) ret void } ; // ----- -; CHECK: warning: unhandled metadata: !0 = !{!"unknown metadata"} on br i1 %arg1, label %bb1, label %bb2, !prof !0 -define i64 @unhandled_metadata(i1 %arg1, i64 %arg2) { -entry: - br i1 %arg1, label %bb1, label %bb2, !prof !0 -bb1: - ret i64 %arg2 -bb2: - ret i64 %arg2 -} - -!0 = !{!"unknown metadata"} - -; // ----- - -; CHECK: warning: unhandled function metadata: !0 = !{!"unknown metadata"} on define void @unhandled_func_metadata(i1 %arg1, i64 %arg2) !prof !0 -define void @unhandled_func_metadata(i1 %arg1, i64 %arg2) !prof !0 { - ret void -} - -!0 = !{!"unknown metadata"} - -; // ----- - declare void @llvm.dbg.value(metadata, metadata, metadata) ; CHECK: import-failure.ll @@ -102,17 +82,6 @@ ; // ----- -; global_ctors requires the appending linkage type. -; CHECK: import-failure.ll -; CHECK-SAME: error: unhandled global variable: @llvm.global_ctors -@llvm.global_ctors = global [1 x { i32, ptr, ptr }] [{ i32, ptr, ptr } { i32 0, ptr @foo, ptr null }] - -define void @foo() { - ret void -} - -; // ----- - ; global_dtors with non-null data fields cannot be represented in MLIR. ; CHECK: import-failure.ll ; CHECK-SAME: error: unhandled global variable: @llvm.global_dtors @@ -124,28 +93,6 @@ ; // ----- -; global_ctors without a data field should not be imported. -; CHECK: import-failure.ll -; CHECK-SAME: error: unhandled global variable: @llvm.global_ctors -@llvm.global_ctors = appending global [1 x { i32, ptr }] [{ i32, ptr } { i32 0, ptr @foo }] - -define void @foo() { - ret void -} - -; // ----- - -; global_dtors with a wrong argument order should not be imported. -; CHECK: import-failure.ll -; CHECK-SAME: error: unhandled global variable: @llvm.global_dtors -@llvm.global_dtors = appending global [1 x { ptr, i32, ptr }] [{ ptr, i32, ptr } { ptr @foo, i32 0, ptr null }] - -define void @foo() { - ret void -} - -; // ----- - ; CHECK: import-failure.ll ; CHECK-SAME: error: TBAA root node must have non-empty identity: !2 = !{!""} define dso_local void @tbaa(ptr %0) { @@ -159,73 +106,6 @@ ; // ----- -; CHECK: import-failure.ll -; CHECK-SAME: error: unsupported TBAA node format: !0 = !{!1, i64 0, i64 0} -define dso_local void @tbaa(ptr %0) { - store i8 1, ptr %0, align 4, !tbaa !2 - ret void -} - -!0 = !{!"Simple C/C++ TBAA"} -!1 = !{!"omnipotent char", !0, i64 0} -!2 = !{!1, i64 0, i64 0} - -; // ----- - -; CHECK: import-failure.ll -; CHECK-SAME: error: operand '1' must be MDNode: !1 = !{!"omnipotent char", i64 0, i64 0} -define dso_local void @tbaa(ptr %0) { - store i8 1, ptr %0, align 4, !tbaa !2 - ret void -} - -!0 = !{!"Simple C/C++ TBAA"} -!1 = !{!"omnipotent char", i64 0, i64 0} -!2 = !{!1, !1, i64 0} - -; // ----- - -; CHECK: import-failure.ll -; CHECK-SAME: error: missing member offset: !1 = !{!"agg_t", !2, i64 0, !2} -define dso_local void @tbaa(ptr %0) { - store i8 1, ptr %0, align 4, !tbaa !3 - ret void -} - -!0 = !{!"Simple C/C++ TBAA"} -!1 = !{!"omnipotent char", !0, i64 0} -!2 = !{!"agg_t", !1, i64 0, !1} -!3 = !{!2, !1, i64 0} - -; // ----- - -; CHECK: import-failure.ll -; CHECK-SAME: error: operand '4' must be ConstantInt: !1 = !{!"agg_t", !2, i64 0, !2, double 1.000000e+00} -define dso_local void @tbaa(ptr %0) { - store i8 1, ptr %0, align 4, !tbaa !3 - ret void -} - -!0 = !{!"Simple C/C++ TBAA"} -!1 = !{!"omnipotent char", !0, i64 0} -!2 = !{!"agg_t", !1, i64 0, !1, double 1.0} -!3 = !{!2, !1, i64 0} - -; // ----- - -; CHECK: import-failure.ll -; CHECK-SAME: error: operand '3' must be ConstantInt: !0 = !{!1, !1, i64 0, double 1.000000e+00} -define dso_local void @tbaa(ptr %0) { - store i8 1, ptr %0, align 4, !tbaa !2 - ret void -} - -!0 = !{!"Simple C/C++ TBAA"} -!1 = !{!"omnipotent char", !0, i64 0} -!2 = !{!1, !1, i64 0, double 1.0} - -; // ----- - ; CHECK: import-failure.ll ; CHECK-SAME: error: unsupported TBAA node format: !0 = !{!1, !1, i64 0, i64 4} define dso_local void @tbaa(ptr %0) { @@ -252,31 +132,6 @@ ; // ----- -; CHECK: import-failure.ll -; CHECK-SAME: warning: expected an access group node to be empty and distinct -; CHECK: error: unsupported access group node: !0 = !{!1} -define void @access_group(ptr %arg1) { - %1 = load i32, ptr %arg1, !llvm.access.group !0 - ret void -} - -!0 = !{!1} -!1 = distinct !{!"unsupported access group"} - -; // ----- - -; CHECK: import-failure.ll -; CHECK-SAME: warning: expected access group operands to be metadata nodes -; CHECK: error: unsupported access group node: !0 = !{i1 false} -define void @access_group(ptr %arg1) { - %1 = load i32, ptr %arg1, !llvm.access.group !0 - ret void -} - -!0 = !{i1 false} - -; // ----- - ; CHECK: import-failure.ll ; CHECK-SAME: warning: expected all loop properties to be either debug locations or metadata nodes ; CHECK: import-failure.ll @@ -454,70 +309,6 @@ ; // ----- -; CHECK: import-failure.ll -; CHECK-SAME: warning: expected non-empty profiling metadata node -; CHECK: warning: unhandled metadata: !0 = !{} -define void @cond_br(i1 %arg) { -entry: - br i1 %arg, label %bb1, label %bb2, !prof !0 -bb1: - ret void -bb2: - ret void -} - -!0 = !{} - -; // ----- - -; CHECK: import-failure.ll -; CHECK-SAME: warning: expected profiling metadata node to have a string identifier -; CHECK: import-failure.ll:{{.*}} warning: unhandled metadata: !0 = !{i32 64} -define void @cond_br(i1 %arg) { -entry: - br i1 %arg, label %bb1, label %bb2, !prof !0 -bb1: - ret void -bb2: - ret void -} - -!0 = !{i32 64} - -; // ----- - -; CHECK: import-failure.ll -; CHECK-SAME: warning: expected function_entry_count to hold a single i64 value -; CHECK: warning: unhandled function metadata: !0 = !{!"function_entry_count"} -define void @cond_br(i1 %arg) !prof !0 { -entry: - br i1 %arg, label %bb1, label %bb2 -bb1: - ret void -bb2: - ret void -} - -!0 = !{!"function_entry_count"} - -; // ----- - -; CHECK: import-failure.ll -; CHECK-SAME: warning: expected function_entry_count to hold a single i64 value -; CHECK: warning: unhandled function metadata: !0 = !{!"function_entry_count", !"string"} -define void @cond_br(i1 %arg) !prof !0 { -entry: - br i1 %arg, label %bb1, label %bb2 -bb1: - ret void -bb2: - ret void -} - -!0 = !{!"function_entry_count", !"string"} - -; // ----- - ; CHECK: import-failure.ll ; CHECK-SAME: warning: expected function_entry_count to be attached to a function ; CHECK: warning: unhandled metadata: !0 = !{!"function_entry_count", i64 42} @@ -531,80 +322,3 @@ } !0 = !{!"function_entry_count", i64 42} - -; // ----- - -; CHECK: import-failure.ll -; CHECK-SAME: warning: unknown profiling metadata node unknown_prof_type -; CHECK: warning: unhandled metadata: !0 = !{!"unknown_prof_type"} -define void @cond_br(i1 %arg) { -entry: - br i1 %arg, label %bb1, label %bb2, !prof !0 -bb1: - ret void -bb2: - ret void -} - -!0 = !{!"unknown_prof_type"} - -; // ----- - -; CHECK: import-failure.ll -; CHECK-SAME: warning: expected branch weights to be integers -; CHECK: warning: unhandled metadata: !0 = !{!"branch_weights", !"foo"} -define void @cond_br(i1 %arg) { -entry: - br i1 %arg, label %bb1, label %bb2, !prof !0 -bb1: - ret void -bb2: - ret void -} - -!0 = !{!"branch_weights", !"foo"} - -; // ----- - -; CHECK: import-failure.ll:{{.*}} warning: unhandled function metadata: !0 = !{!"branch_weights", i32 64} -define void @cond_br(i1 %arg) !prof !0 { - ret void -} - -!0 = !{!"branch_weights", i32 64} - -; // ----- - -; CHECK: import-failure.ll -; CHECK-SAME: error: unsupported alias scope node: ![[NODE:[0-9]+]] = distinct !{![[NODE]]} -define void @alias_scope(ptr %arg1) { - %1 = load i32, ptr %arg1, !alias.scope !0 - ret void -} - -!0 = !{!0} - -; // ----- - -; CHECK: import-failure.ll -; CHECK-SAME: error: unsupported alias scope node: ![[NODE:[0-9]+]] = distinct !{![[NODE]], !"The domain"} -define void @alias_scope(ptr %arg1) { - %1 = load i32, ptr %arg1, !alias.scope !1 - ret void -} - -!0 = distinct !{!0, !"The domain"} -!1 = !{!1, !0} - -; // ----- - -; CHECK: import-failure.ll -; CHECK-SAME: error: unsupported alias domain node: ![[NODE:[0-9]+]] = distinct !{![[NODE]], ![[NODE]]} -define void @alias_scope_domain(ptr %arg1) { - %1 = load i32, ptr %arg1, !alias.scope !2 - ret void -} - -!0 = distinct !{!0, !0} -!1 = !{!1, !0} -!2 = !{!1} diff --git a/mlir/test/Target/LLVMIR/Import/metadata-tbaa.ll b/mlir/test/Target/LLVMIR/Import/metadata-tbaa.ll --- a/mlir/test/Target/LLVMIR/Import/metadata-tbaa.ll +++ b/mlir/test/Target/LLVMIR/Import/metadata-tbaa.ll @@ -1,12 +1,12 @@ ; RUN: mlir-translate -import-llvm -split-input-file %s | FileCheck %s -// ----- - ; CHECK-LABEL: llvm.metadata @__llvm_global_metadata { -; CHECK-NEXT: llvm.tbaa_root @[[R0:tbaa_root_[0-9]+]] {id = "Simple C/C++ TBAA"} -; CHECK-NEXT: llvm.tbaa_tag @[[T0:tbaa_tag_[0-9]+]] {access_type = @[[R0]], base_type = @[[R0]], offset = 0 : i64} -; CHECK-NEXT: llvm.tbaa_root @[[R1:tbaa_root_[0-9]+]] {id = "Other language TBAA"} -; CHECK-NEXT: llvm.tbaa_tag @[[T1:tbaa_tag_[0-9]+]] {access_type = @[[R1]], base_type = @[[R1]], offset = 0 : i64} +; CHECK-DAG: llvm.tbaa_root @[[R0:tbaa_root_[0-9]+]] {id = "Simple C/C++ TBAA"} +; CHECK-DAG: llvm.tbaa_type_desc @[[D0:tbaa_type_desc_[0-9]+]] {id = "scalar type", members = {<@[[R0]], 0>}} +; CHECK-DAG: llvm.tbaa_tag @[[T0:tbaa_tag_[0-9]+]] {access_type = @[[D0]], base_type = @[[D0]], offset = 0 : i64} +; CHECK-DAG: llvm.tbaa_root @[[R1:tbaa_root_[0-9]+]] {id = "Other language TBAA"} +; CHECK-DAG: llvm.tbaa_type_desc @[[D1:tbaa_type_desc_[0-9]+]] {id = "other scalar type", members = {<@[[R1]], 0>}} +; CHECK-DAG: llvm.tbaa_tag @[[T1:tbaa_tag_[0-9]+]] {access_type = @[[D1]], base_type = @[[D1]], offset = 0 : i64} ; CHECK-NEXT: } ; CHECK: llvm.func @tbaa1 ; CHECK: llvm.store %{{.*}}, %{{.*}} { @@ -16,15 +16,18 @@ ; CHECK-SAME: tbaa = [@__llvm_global_metadata::@[[T1]]] ; CHECK-SAME: } : i8, !llvm.ptr define dso_local void @tbaa1(ptr %0, ptr %1) { - store i8 1, ptr %0, align 4, !tbaa !1 + store i8 1, ptr %0, align 4, !tbaa !0 store i8 1, ptr %1, align 4, !tbaa !3 ret void } -!0 = !{!"Simple C/C++ TBAA"} -!1 = !{!0, !0, i64 0} -!2 = !{!"Other language TBAA"} -!3 = !{!2, !2, i64 0} +!0 = !{!1, !1, i64 0} +!1 = !{!"scalar type", !2, i64 0} +!2 = !{!"Simple C/C++ TBAA"} + +!3 = !{!4, !4, i64 0} +!4 = !{!"other scalar type", !5, i64 0} +!5 = !{!"Other language TBAA"} // -----