diff --git a/mlir/include/mlir/Dialect/LLVMIR/LLVMIntrinsicOps.td b/mlir/include/mlir/Dialect/LLVMIR/LLVMIntrinsicOps.td --- a/mlir/include/mlir/Dialect/LLVMIR/LLVMIntrinsicOps.td +++ b/mlir/include/mlir/Dialect/LLVMIR/LLVMIntrinsicOps.td @@ -291,9 +291,13 @@ // argument variable would not work here, since the builder variables are // converted before entering the builder, which would result in an error // when attempting to convert an argument list. - FailureOr argOperand = moduleImport.convertValue(llvmOperands[0]); + + FailureOr argOperand = moduleImport.convertMetadataValue(llvmOperands[0]); + // Drop the intrinsic when its operand could not be converted. This can + // happen for use before definition cases that are allowed for debug + // intrinsics. if (failed(argOperand)) - return failure(); + return success(); $_op = $_builder.create<$_qualCppClassName>($_location, *argOperand, $_var_attr($varInfo)); }]; diff --git a/mlir/include/mlir/Target/LLVMIR/ModuleImport.h b/mlir/include/mlir/Target/LLVMIR/ModuleImport.h --- a/mlir/include/mlir/Target/LLVMIR/ModuleImport.h +++ b/mlir/include/mlir/Target/LLVMIR/ModuleImport.h @@ -119,6 +119,11 @@ /// LLVM values. FailureOr convertValue(llvm::Value *value); + /// Converts an LLVM metadata value to an MLIR value, or returns failure if + /// the conversion fails. Uses the `convertConstant` method to translate + /// constant LLVM values. + FailureOr convertMetadataValue(llvm::Value *value); + /// Converts a range of LLVM values to a range of MLIR values using the /// `convertValue` method, or returns failure if the conversion fails. FailureOr> convertValues(ArrayRef values); diff --git a/mlir/lib/Target/LLVMIR/ModuleImport.cpp b/mlir/lib/Target/LLVMIR/ModuleImport.cpp --- a/mlir/lib/Target/LLVMIR/ModuleImport.cpp +++ b/mlir/lib/Target/LLVMIR/ModuleImport.cpp @@ -1035,11 +1035,8 @@ } FailureOr ModuleImport::convertValue(llvm::Value *value) { - // A value may be wrapped as metadata, for example, when passed to a debug - // intrinsic. Unwrap these values before the conversion. - if (auto *nodeAsVal = dyn_cast(value)) - if (auto *node = dyn_cast(nodeAsVal->getMetadata())) - value = node->getValue(); + assert(!isa(value) && + "expected value to not be metadata"); // Return the mapped value if it has been converted before. if (valueMapping.count(value)) @@ -1055,6 +1052,27 @@ return emitError(loc) << "unhandled value: " << diag(*value); } +FailureOr ModuleImport::convertMetadataValue(llvm::Value *value) { + // A value may be wrapped as metadata, for example, when passed to a debug + // intrinsic. Unwrap these values before the conversion. + auto *nodeAsVal = dyn_cast(value); + if (!nodeAsVal) + return failure(); + auto *node = dyn_cast(nodeAsVal->getMetadata()); + if (!node) + return failure(); + value = node->getValue(); + + // Return the mapped value if it has been converted before. + if (valueMapping.count(value)) + return lookupValue(value); + + // Convert constants such as immediate values that have no mapping yet. + if (auto *constant = dyn_cast(value)) + return convertConstantExpr(constant); + return failure(); +} + FailureOr> ModuleImport::convertValues(ArrayRef values) { SmallVector remapped; diff --git a/mlir/test/Target/LLVMIR/Import/debug-info.ll b/mlir/test/Target/LLVMIR/Import/debug-info.ll --- a/mlir/test/Target/LLVMIR/Import/debug-info.ll +++ b/mlir/test/Target/LLVMIR/Import/debug-info.ll @@ -344,3 +344,26 @@ !3 = !DISubprogram(name: "variadic_func", scope: !2, file: !2, flags: DIFlagPrototyped, spFlags: DISPFlagOptimized, type: !4) !4 = !DISubroutineType(types: !5) !5 = !{null, null} + +; // ----- + +define void @dbg_use_before_def(ptr %arg) { + call void @llvm.dbg.value(metadata ptr %dbg_arg, metadata !7, metadata !DIExpression()), !dbg !9 + %dbg_arg = getelementptr double, ptr %arg, i64 16 + ret void +} + +declare void @llvm.dbg.value(metadata, metadata, metadata) + +!llvm.dbg.cu = !{!1} +!llvm.module.flags = !{!0} +!0 = !{i32 2, !"Debug Info Version", i32 3} +!1 = distinct !DICompileUnit(language: DW_LANG_C, file: !2) +!2 = !DIFile(filename: "debug-info.ll", directory: "/") +!3 = !DICompositeType(tag: DW_TAG_class_type, name: "class_field", file: !2, line: 42, flags: DIFlagTypePassByReference | DIFlagNonTrivial, elements: !4) +!4 = !{!6} +!5 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !3, flags: DIFlagArtificial | DIFlagObjectPointer) +!6 = !DIDerivedType(tag: DW_TAG_member, name: "call_field", file: !2, baseType: !5) +!7 = !DILocalVariable(scope: !8, name: "var", file: !2, type: !5); +!8 = distinct !DISubprogram(name: "dbg_use_before_def", scope: !2, file: !2, spFlags: DISPFlagDefinition, unit: !1) +!9 = !DILocation(line: 1, column: 2, scope: !8)