[mlir][llvm] Use before def debug intrinsic import
authorChristian Ulmann <christian.ulmann@nextsilicon.com>
Thu, 16 Feb 2023 14:44:05 +0000 (15:44 +0100)
committerChristian Ulmann <christian.ulmann@nextsilicon.com>
Thu, 16 Feb 2023 14:49:23 +0000 (15:49 +0100)
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

mlir/include/mlir/Dialect/LLVMIR/LLVMIntrinsicOps.td
mlir/include/mlir/Target/LLVMIR/ModuleImport.h
mlir/lib/Target/LLVMIR/ModuleImport.cpp
mlir/test/Target/LLVMIR/Import/debug-info.ll

index 227a192..76e5b34 100644 (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));
   }];
index aaf9b2c..be4f6e5 100644 (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);
index ed462d8..d24f586 100644 (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;
index 6dc5463..896d422 100644 (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)