Skip to content

[flang][debug] Support complex types. #92559

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

Merged
merged 4 commits into from
May 23, 2024
Merged

[flang][debug] Support complex types. #92559

merged 4 commits into from
May 23, 2024

Conversation

abidh
Copy link
Contributor

@abidh abidh commented May 17, 2024

This PR adds supports for conversion of complex type to corresponding DITypeAttr. Both fir and mlir types are supported.

Apart from lit testing, I have also tested the types in debugger and they work correctly. An exception is 128 bit complex which somehow requires that its name be different from complex. I am going to open a separate PR to add (kind=n) in the type names similar to what gfortran does.

This PR adds supports for conversion of complex type to corresponding
DITypeAttr. Both fir and mlir types are supported.

Apart from lit testing, I have also tested the types in debugger and
they work correctly. An exception is 128 bit complex which somehow
requires that its name be different from `complex`. I am going to open
a separate PR to add (kind=n) in the type names similar to what
gfortran does.
@llvmbot llvmbot added flang Flang issues not falling into any other category flang:fir-hlfir labels May 17, 2024
@llvmbot
Copy link
Member

llvmbot commented May 17, 2024

@llvm/pr-subscribers-flang-fir-hlfir

Author: Abid Qadeer (abidh)

Changes

This PR adds supports for conversion of complex type to corresponding DITypeAttr. Both fir and mlir types are supported.

Apart from lit testing, I have also tested the types in debugger and they work correctly. An exception is 128 bit complex which somehow requires that its name be different from complex. I am going to open a separate PR to add (kind=n) in the type names similar to what gfortran does.


Full diff: https://github.com/llvm/llvm-project/pull/92559.diff

3 Files Affected:

  • (modified) flang/lib/Optimizer/Transforms/DebugTypeGenerator.cpp (+10)
  • (added) flang/test/Transforms/debug-complex-1.fir (+39)
  • (added) flang/test/Transforms/debug-complex-2.f90 (+39)
diff --git a/flang/lib/Optimizer/Transforms/DebugTypeGenerator.cpp b/flang/lib/Optimizer/Transforms/DebugTypeGenerator.cpp
index 64c6547e06e0f..ad6e4813ef820 100644
--- a/flang/lib/Optimizer/Transforms/DebugTypeGenerator.cpp
+++ b/flang/lib/Optimizer/Transforms/DebugTypeGenerator.cpp
@@ -57,6 +57,16 @@ DebugTypeGenerator::convertType(mlir::Type Ty, mlir::LLVM::DIFileAttr fileAttr,
                         mlir::StringAttr::get(context, logTy.getMnemonic()),
                         kindMapping.getLogicalBitsize(logTy.getFKind()),
                         llvm::dwarf::DW_ATE_boolean);
+  } else if (fir::isa_complex(Ty)) {
+    unsigned bitWidth;
+    if (auto cplxTy = mlir::dyn_cast_or_null<mlir::ComplexType>(Ty)) {
+      auto floatTy = mlir::cast<mlir::FloatType>(cplxTy.getElementType());
+      bitWidth = floatTy.getWidth();
+    } else if (auto cplxTy = mlir::dyn_cast_or_null<fir::ComplexType>(Ty))
+      bitWidth = kindMapping.getRealBitsize(cplxTy.getFKind());
+
+    return genBasicType(context, mlir::StringAttr::get(context, "complex"),
+                        bitWidth * 2, llvm::dwarf::DW_ATE_complex_float);
   } else {
     // FIXME: These types are currently unhandled. We are generating a
     // placeholder type to allow us to test supported bits.
diff --git a/flang/test/Transforms/debug-complex-1.fir b/flang/test/Transforms/debug-complex-1.fir
new file mode 100644
index 0000000000000..fe50da5914476
--- /dev/null
+++ b/flang/test/Transforms/debug-complex-1.fir
@@ -0,0 +1,39 @@
+// RUN: fir-opt --cg-rewrite="preserve-declare=true" --mlir-print-debuginfo %s | fir-opt --add-debug-info --mlir-print-debuginfo | FileCheck %s
+
+// check conversion of complex type of different size. Both fir and mlir
+// variants are checked.
+
+module attributes {fir.defaultkind = "a1c4d8i4l4r4", fir.kindmap = "", llvm.target_triple = "native"} {
+  func.func @test1(%x : !fir.complex<4>) -> !fir.complex<8> {
+  %1 = fir.convert %x : (!fir.complex<4>) -> !fir.complex<8>
+  return %1 : !fir.complex<8>
+  }loc(#loc1)
+  func.func @test2(%x : !fir.complex<4>) -> complex<f64> {
+  %1 = fir.convert %x : (!fir.complex<4>) -> complex<f64>
+  return %1 : complex<f64>
+  }loc(#loc2)
+  func.func @test3(%x : !fir.complex<4>) -> !fir.complex<16> {
+  %1 = fir.convert %x : (!fir.complex<4>) -> !fir.complex<16>
+  return %1 : !fir.complex<16>
+  }loc(#loc3)
+  func.func @test4(%x : !fir.complex<4>) -> complex<f128> {
+  %1 = fir.convert %x : (!fir.complex<4>) -> complex<f128>
+  return %1 : complex<f128>
+  }loc(#loc4)
+}
+#loc1 = loc("./simple.f90":2:1)
+#loc2 = loc("./simple.f90":5:1)
+#loc3 = loc("./simple.f90":8:1)
+#loc4 = loc("./simple.f90":11:1)
+
+// CHECK-DAG: #[[CMPX8:.*]] = #llvm.di_basic_type<tag = DW_TAG_base_type, name = "complex", sizeInBits = 128, encoding = DW_ATE_complex_float>
+// CHECK-DAG: #[[CMPX4:.*]] = #llvm.di_basic_type<tag = DW_TAG_base_type, name = "complex", sizeInBits = 64, encoding = DW_ATE_complex_float>
+// CHECK-DAG: #[[CMPX16:.*]] = #llvm.di_basic_type<tag = DW_TAG_base_type, name = "complex", sizeInBits = 256, encoding = DW_ATE_complex_float>
+
+// CHECK-DAG: #[[TY1:.*]] = #llvm.di_subroutine_type<{{.*}}types = #[[CMPX8]], #[[CMPX4]]>
+// CHECK-DAG: #[[TY2:.*]] = #llvm.di_subroutine_type<{{.*}}types = #[[CMPX16]], #[[CMPX4]]>
+
+// CHECK-DAG: #llvm.di_subprogram<{{.*}}name = "test1"{{.*}}type = #[[TY1]]>
+// CHECK-DAG: #llvm.di_subprogram<{{.*}}name = "test2"{{.*}}type = #[[TY1]]>
+// CHECK-DAG: #llvm.di_subprogram<{{.*}}name = "test3"{{.*}}type = #[[TY2]]>
+// CHECK-DAG: #llvm.di_subprogram<{{.*}}name = "test4"{{.*}}type = #[[TY2]]>
diff --git a/flang/test/Transforms/debug-complex-2.f90 b/flang/test/Transforms/debug-complex-2.f90
new file mode 100644
index 0000000000000..9d44a80a9e34d
--- /dev/null
+++ b/flang/test/Transforms/debug-complex-2.f90
@@ -0,0 +1,39 @@
+! RUN: %flang_fc1 -emit-fir -debug-info-kind=standalone -mmlir --mlir-print-debuginfo %s -o - | \
+! RUN: fir-opt --cg-rewrite="preserve-declare=true" --mlir-print-debuginfo | fir-opt --add-debug-info --mlir-print-debuginfo | FileCheck %s
+! RUN: %flang_fc1 -emit-llvm -debug-info-kind=standalone %s -o - | FileCheck  --check-prefix=LLVM %s
+
+program mn
+  complex(kind=4) :: c4
+  complex(kind=8) :: c8
+  complex(kind=16) :: r
+  r = fn1(c4, c8)
+  print *, r
+contains
+  function fn1(a, b) result (c)
+    complex(kind=4), intent(in) :: a
+    complex(kind=8), intent(in) :: b
+    complex(kind=16) :: c
+    c = a + b
+  end function
+end program
+
+! CHECK-DAG: #[[CMPX4:.*]] = #llvm.di_basic_type<tag = DW_TAG_base_type, name = "complex", sizeInBits = 64, encoding = DW_ATE_complex_float>
+! CHECK-DAG: #[[CMPX8:.*]] = #llvm.di_basic_type<tag = DW_TAG_base_type, name = "complex", sizeInBits = 128, encoding = DW_ATE_complex_float>
+! CHECK-DAG: #[[CMPX16:.*]] = #llvm.di_basic_type<tag = DW_TAG_base_type, name = "complex", sizeInBits = 256, encoding = DW_ATE_complex_float>
+
+! CHECK-DAG: #llvm.di_local_variable<{{.*}}name = "c4"{{.*}}type = #[[CMPX4]]>
+! CHECK-DAG: #llvm.di_local_variable<{{.*}}name = "c8"{{.*}}type = #[[CMPX8]]>
+! CHECK-DAG: #llvm.di_local_variable<{{.*}}name = "r"{{.*}}type = #[[CMPX16]]>
+! CHECK-DAG: #llvm.di_local_variable<{{.*}}name = "a"{{.*}}type = #[[CMPX4]]>
+! CHECK-DAG: #llvm.di_local_variable<{{.*}}name = "b"{{.*}}type = #[[CMPX8]]>
+! CHECK-DAG: #llvm.di_local_variable<{{.*}}name = "c"{{.*}}type = #[[CMPX16]]>
+
+! LLVM-DAG: ![[C4:.*]] = !DIBasicType(name: "complex", size: 64, encoding: DW_ATE_complex_float)
+! LLVM-DAG: ![[C8:.*]] = !DIBasicType(name: "complex", size: 128, encoding: DW_ATE_complex_float)
+! LLVM-DAG: ![[C16:.*]] = !DIBasicType(name: "complex", size: 256, encoding: DW_ATE_complex_float)
+! LLVM-DAG: !DILocalVariable(name: "c4"{{.*}}type: ![[C4]])
+! LLVM-DAG: !DILocalVariable(name: "c8"{{.*}}type: ![[C8]])
+! LLVM-DAG: !DILocalVariable(name: "r"{{.*}}type: ![[C16]])
+! LLVM-DAG: !DILocalVariable(name: "a"{{.*}}type: ![[C4]])
+! LLVM-DAG: !DILocalVariable(name: "b"{{.*}}type: ![[C8]])
+! LLVM-DAG: !DILocalVariable(name: "c"{{.*}}type: ![[C16]])

Copy link
Contributor

@tblah tblah left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for this!

@@ -57,6 +57,16 @@ DebugTypeGenerator::convertType(mlir::Type Ty, mlir::LLVM::DIFileAttr fileAttr,
mlir::StringAttr::get(context, logTy.getMnemonic()),
kindMapping.getLogicalBitsize(logTy.getFKind()),
llvm::dwarf::DW_ATE_boolean);
} else if (fir::isa_complex(Ty)) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LLVM has some guidelines regarding else after return. https://llvm.org/docs/CodingStandards.html#don-t-use-else-after-a-return

@@ -57,6 +57,16 @@ DebugTypeGenerator::convertType(mlir::Type Ty, mlir::LLVM::DIFileAttr fileAttr,
mlir::StringAttr::get(context, logTy.getMnemonic()),
kindMapping.getLogicalBitsize(logTy.getFKind()),
llvm::dwarf::DW_ATE_boolean);
} else if (fir::isa_complex(Ty)) {
unsigned bitWidth;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would it make sense to initialize this to some value to avoid an uninitialized warning or alternatively add an else case below to assert or llvm unreachable?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it is better to make the intention explicit. I have added an llvm_unreachable.

@@ -0,0 +1,39 @@
// RUN: fir-opt --cg-rewrite="preserve-declare=true" --mlir-print-debuginfo %s | fir-opt --add-debug-info --mlir-print-debuginfo | FileCheck %s
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does the cg-rewrite pass do anything useful here?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, only add-debug-info is needed. I have updated the test.

@@ -0,0 +1,28 @@
! RUN: %flang_fc1 -emit-fir -debug-info-kind=standalone -mmlir --mlir-print-debuginfo %s -o - | \
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does this test anything different from debug-complex-1.fir?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was going to remove it after the discussion in #91582. Done now.

1. Remove the fortran testcase as it was redundant.
2. Remove redundant command from RUN line.
3. Add an llvm_unreachable if we get a complex type which is not
   fir or mlir complex type.
Copy link
Contributor

@kiranchandramohan kiranchandramohan left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LG.

@abidh abidh merged commit 63a4133 into llvm:main May 23, 2024
4 checks passed
@abidh abidh deleted the complex branch June 4, 2024 09:43
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
flang:fir-hlfir flang Flang issues not falling into any other category
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants