Skip to content

Commit 2e5a523

Browse files
authored
[flang][debug] Avoid redundant debug data generation for derived types. (#124473)
Since #122770, we have seen that compile time have become extremely slow for cyclic derived types. In #122770, we made the criteria to cache a derived type very strict. As a result, some types which are safe to cache were also being re-generated every type they were required. This increased the compile time and also the size of the debug info. Please see the description of PR# 122770. We decided that when processing `t1`, the type generated for `t2` and `t3` were not safe to cached. But our algorithm also denied caching to `t1` which as top level type was safe. ``` type t1 type(t2), pointer :: p1 end type type t2 type(t3), pointer :: p2 end type type t3 type(t1), pointer :: p3 end type ``` I have tinkered the check a bit so that top level type is always cached. To detect a top level type, we use a depth counter that get incremented before call to `convertRecordType` and decremented after it returns. After this change, the following [file](https://github.com/fujitsu/compiler-test-suite/blob/main/Fortran/0394/0394_0031.f90) from Fujitsu get compiled around 40s which is same as it was before #122770. The smaller testcase present in issue #124049 takes less than half a second. I also added check to make sure that duplicate entries of the `DICompositeType` are not present in the IR. Fixes #124049 and #123960.
1 parent aa34a6a commit 2e5a523

File tree

3 files changed

+34
-5
lines changed

3 files changed

+34
-5
lines changed

flang/lib/Optimizer/Transforms/DebugTypeGenerator.cpp

Lines changed: 27 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,8 @@ DebugTypeGenerator::DebugTypeGenerator(mlir::ModuleOp m,
4848
mlir::SymbolTable *symbolTable_,
4949
const mlir::DataLayout &dl)
5050
: module(m), symbolTable(symbolTable_), dataLayout{&dl},
51-
kindMapping(getKindMapping(m)), llvmTypeConverter(m, false, false, dl) {
51+
kindMapping(getKindMapping(m)), llvmTypeConverter(m, false, false, dl),
52+
derivedTypeDepth(0) {
5253
LLVM_DEBUG(llvm::dbgs() << "DITypeAttr generator\n");
5354

5455
mlir::MLIRContext *context = module.getContext();
@@ -407,7 +408,10 @@ mlir::LLVM::DITypeAttr DebugTypeGenerator::convertRecordType(
407408
/*baseType=*/nullptr, mlir::LLVM::DIFlags::Zero, offset * 8,
408409
/*alignInBits=*/0, elements, /*dataLocation=*/nullptr, /*rank=*/nullptr,
409410
/*allocated=*/nullptr, /*associated=*/nullptr);
410-
if (canCacheThisType) {
411+
412+
// derivedTypeDepth == 1 means that it is a top level type which is safe to
413+
// cache.
414+
if (canCacheThisType || derivedTypeDepth == 1) {
411415
typeCache[Ty] = finalAttr;
412416
} else {
413417
auto iter = typeCache.find(Ty);
@@ -663,7 +667,27 @@ DebugTypeGenerator::convertType(mlir::Type Ty, mlir::LLVM::DIFileAttr fileAttr,
663667
return convertCharacterType(charTy, fileAttr, scope, declOp,
664668
/*hasDescriptor=*/false);
665669
} else if (auto recTy = mlir::dyn_cast_if_present<fir::RecordType>(Ty)) {
666-
return convertRecordType(recTy, fileAttr, scope, declOp);
670+
// For nested derived types like shown below, the call sequence of the
671+
// convertRecordType will look something like as follows:
672+
// convertRecordType (t1)
673+
// convertRecordType (t2)
674+
// convertRecordType (t3)
675+
// We need to recognize when we are processing the top level type like t1
676+
// to make caching decision. The variable `derivedTypeDepth` is used for
677+
// this purpose and maintains the current depth of derived type processing.
678+
// type t1
679+
// type(t2), pointer :: p1
680+
// end type
681+
// type t2
682+
// type(t3), pointer :: p2
683+
// end type
684+
// type t2
685+
// integer a
686+
// end type
687+
derivedTypeDepth++;
688+
auto result = convertRecordType(recTy, fileAttr, scope, declOp);
689+
derivedTypeDepth--;
690+
return result;
667691
} else if (auto tupleTy = mlir::dyn_cast_if_present<mlir::TupleType>(Ty)) {
668692
return convertTupleType(tupleTy, fileAttr, scope, declOp);
669693
} else if (auto refTy = mlir::dyn_cast_if_present<fir::ReferenceType>(Ty)) {

flang/lib/Optimizer/Transforms/DebugTypeGenerator.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,7 @@ class DebugTypeGenerator {
9191
std::uint64_t lenOffset;
9292
std::uint64_t rankOffset;
9393
std::uint64_t rankSize;
94+
int32_t derivedTypeDepth;
9495
llvm::DenseMap<mlir::Type, mlir::LLVM::DITypeAttr> typeCache;
9596
};
9697

flang/test/Integration/debug-cyclic-derived-type-3.f90

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
! RUN: %flang_fc1 -emit-llvm -debug-info-kind=standalone %s -o -
1+
! RUN: %flang_fc1 -emit-llvm -debug-info-kind=standalone %s -o - | FileCheck %s
22

33
! mainly test that this program does not cause an assertion failure
44
! testcase for issue 122024
@@ -17,7 +17,7 @@ module m1
1717

1818
program test
1919
use m1
20-
type(t1),pointer :: foo
20+
type(t1),pointer :: foo, foo2
2121
allocate(foo)
2222
allocate(foo%x1)
2323
allocate(foo%x1%x2)
@@ -30,3 +30,7 @@ subroutine sub1(bar)
3030
use m1
3131
type(t2) :: bar
3232
end subroutine
33+
34+
! Test that file compiles ok and there is only one DICompositeType for "t1".
35+
!CHECK: !DICompositeType(tag: DW_TAG_structure_type, name: "t1"{{.*}})
36+
!CHECK-NOT: !DICompositeType(tag: DW_TAG_structure_type, name: "t1"{{.*}})

0 commit comments

Comments
 (0)