Skip to content

Commit 468e848

Browse files
committed
[flang][debug] Avoid redundant debug data generation for derived types.
Since llvm#122770, we have seen that compile time have become extremely slow for cyclic derived types. In 122770, we made the criteria to cache a 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 from Fujitsu get compiled under a minute. https://github.com/fujitsu/compiler-test-suite/blob/main/Fortran/0394/0394_0031.f90 The smaller testcase present in issue 124049 takes around half second. I also added check to make sure that duplicate entries of the DICompositeType are not present in the IR. Fixes llvm#124049 and llvm#123960.
1 parent 97c3a99 commit 468e848

File tree

3 files changed

+34
-5
lines changed

3 files changed

+34
-5
lines changed

flang/lib/Optimizer/Transforms/DebugTypeGenerator.cpp

+27-3
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

+1
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

+6-2
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)