[mlir][llvm] Use before def debug intrinsic import

This commit adds special handling for the debug intrinsic value
handling. LLVM allows to relax the def before use property for debug
intrinsics, so this property cannot be assumed for metadata values.

Reviewed By: gysit

Differential Revision: https://reviews.llvm.org/D144177
This commit is contained in:
Christian Ulmann
2023-02-16 15:44:05 +01:00
parent 8421307b6b
commit 28542e99bb
4 changed files with 57 additions and 7 deletions

View File

@@ -291,9 +291,13 @@ class LLVM_DbgIntrOp<string name, string argName> : LLVM_IntrOp<name, [], [], []
// 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<Value> argOperand = moduleImport.convertValue(llvmOperands[0]);
FailureOr<Value> 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));
}];

View File

@@ -119,6 +119,11 @@ public:
/// LLVM values.
FailureOr<Value> 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<Value> 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<SmallVector<Value>> convertValues(ArrayRef<llvm::Value *> values);

View File

@@ -1132,11 +1132,8 @@ FailureOr<Value> ModuleImport::convertConstantExpr(llvm::Constant *constant) {
}
FailureOr<Value> 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<llvm::MetadataAsValue>(value))
if (auto *node = dyn_cast<llvm::ValueAsMetadata>(nodeAsVal->getMetadata()))
value = node->getValue();
assert(!isa<llvm::MetadataAsValue>(value) &&
"expected value to not be metadata");
// Return the mapped value if it has been converted before.
if (valueMapping.count(value))
@@ -1152,6 +1149,27 @@ FailureOr<Value> ModuleImport::convertValue(llvm::Value *value) {
return emitError(loc) << "unhandled value: " << diag(*value);
}
FailureOr<Value> 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<llvm::MetadataAsValue>(value);
if (!nodeAsVal)
return failure();
auto *node = dyn_cast<llvm::ValueAsMetadata>(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<llvm::Constant>(value))
return convertConstantExpr(constant);
return failure();
}
FailureOr<SmallVector<Value>>
ModuleImport::convertValues(ArrayRef<llvm::Value *> values) {
SmallVector<Value> remapped;

View File

@@ -344,3 +344,26 @@ declare !dbg !3 void @variadic_func()
!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)