[llvm-branch-commits] [flang] 4dbe04a - Revert "[flang] add option to generate runtime type info as external (#145901)"

via llvm-branch-commits llvm-branch-commits at lists.llvm.org
Fri Jun 27 05:04:53 PDT 2025


Author: jeanPerier
Date: 2025-06-27T14:04:51+02:00
New Revision: 4dbe04a551fe7ab7668a0351ef39cf8bbfe13798

URL: https://github.com/llvm/llvm-project/commit/4dbe04a551fe7ab7668a0351ef39cf8bbfe13798
DIFF: https://github.com/llvm/llvm-project/commit/4dbe04a551fe7ab7668a0351ef39cf8bbfe13798.diff

LOG: Revert "[flang] add option to generate runtime type info as external (#145901)"

This reverts commit e816817bbb2889a42d8d984736971635d77816f3.

Added: 
    

Modified: 
    flang/include/flang/Evaluate/tools.h
    flang/include/flang/Optimizer/CodeGen/CodeGen.h
    flang/include/flang/Optimizer/Passes/CommandLineOpts.h
    flang/include/flang/Optimizer/Support/Utils.h
    flang/include/flang/Semantics/runtime-type-info.h
    flang/lib/Evaluate/tools.cpp
    flang/lib/Lower/Bridge.cpp
    flang/lib/Lower/ConvertVariable.cpp
    flang/lib/Optimizer/CodeGen/CodeGen.cpp
    flang/lib/Optimizer/Passes/CommandLineOpts.cpp
    flang/lib/Optimizer/Passes/Pipelines.cpp
    flang/lib/Optimizer/Transforms/PolymorphicOpConversion.cpp
    flang/test/Lower/select-type-2.f90
    flang/test/Lower/select-type.f90

Removed: 
    flang/test/Integration/skip-external-rtti-definition.F90


################################################################################
diff  --git a/flang/include/flang/Evaluate/tools.h b/flang/include/flang/Evaluate/tools.h
index cad1b634f8924..d26a477ddded1 100644
--- a/flang/include/flang/Evaluate/tools.h
+++ b/flang/include/flang/Evaluate/tools.h
@@ -1585,7 +1585,6 @@ bool IsExtensibleType(const DerivedTypeSpec *);
 bool IsSequenceOrBindCType(const DerivedTypeSpec *);
 bool IsBuiltinDerivedType(const DerivedTypeSpec *derived, const char *name);
 bool IsBuiltinCPtr(const Symbol &);
-bool IsFromBuiltinModule(const Symbol &);
 bool IsEventType(const DerivedTypeSpec *);
 bool IsLockType(const DerivedTypeSpec *);
 bool IsNotifyType(const DerivedTypeSpec *);

diff  --git a/flang/include/flang/Optimizer/CodeGen/CodeGen.h b/flang/include/flang/Optimizer/CodeGen/CodeGen.h
index 93f07d8d5d4d9..0398d0f248e08 100644
--- a/flang/include/flang/Optimizer/CodeGen/CodeGen.h
+++ b/flang/include/flang/Optimizer/CodeGen/CodeGen.h
@@ -39,9 +39,6 @@ struct FIRToLLVMPassOptions {
   // that such programs would crash at runtime if the derived type descriptors
   // are required by the runtime, so this is only an option to help debugging.
   bool ignoreMissingTypeDescriptors = false;
-  // Similar to ignoreMissingTypeDescriptors, but generate external declaration
-  // for the missing type descriptor globals instead.
-  bool skipExternalRttiDefinition = false;
 
   // Generate TBAA information for FIR types and memory accessing operations.
   bool applyTBAA = false;

diff  --git a/flang/include/flang/Optimizer/Passes/CommandLineOpts.h b/flang/include/flang/Optimizer/Passes/CommandLineOpts.h
index 76ac9d0622d2b..1cfaf285e75e6 100644
--- a/flang/include/flang/Optimizer/Passes/CommandLineOpts.h
+++ b/flang/include/flang/Optimizer/Passes/CommandLineOpts.h
@@ -32,19 +32,6 @@ extern llvm::cl::opt<std::size_t> arrayStackAllocationThreshold;
 /// generated by the frontend.
 extern llvm::cl::opt<bool> ignoreMissingTypeDescriptors;
 
-/// Shared option in tools to only generate rtti static object definitions for
-/// derived types defined in the current compilation unit. Derived type
-/// descriptor object for types defined in other objects will only be declared
-/// as external. This also changes the linkage of rtti objects defined in the
-/// current compilation unit from linkonce_odr to external so that unused rtti
-/// objects are retained and can be accessed from other compilation units. This
-/// is an experimental option to explore compilation speed improvements and is
-/// an ABI breaking change because of the linkage change.
-/// It will also require linking against module file objects of modules defining
-/// only types (even for trivial types without type bound procedures, which
-/// 
diff ers from most compilers).
-extern llvm::cl::opt<bool> skipExternalRttiDefinition;
-
 /// Default optimization level used to create Flang pass pipeline is O0.
 extern llvm::OptimizationLevel defaultOptLevel;
 

diff  --git a/flang/include/flang/Optimizer/Support/Utils.h b/flang/include/flang/Optimizer/Support/Utils.h
index 83c936b7dcada..ec73af6ec72e9 100644
--- a/flang/include/flang/Optimizer/Support/Utils.h
+++ b/flang/include/flang/Optimizer/Support/Utils.h
@@ -35,6 +35,32 @@ inline std::int64_t toInt(mlir::arith::ConstantOp cop) {
       .getSExtValue();
 }
 
+// Reconstruct binding tables for dynamic dispatch.
+using BindingTable = llvm::DenseMap<llvm::StringRef, unsigned>;
+using BindingTables = llvm::DenseMap<llvm::StringRef, BindingTable>;
+
+inline void buildBindingTables(BindingTables &bindingTables,
+                               mlir::ModuleOp mod) {
+
+  // The binding tables are defined in FIR after lowering inside fir.type_info
+  // operations. Go through each binding tables and store the procedure name and
+  // binding index for later use by the fir.dispatch conversion pattern.
+  for (auto typeInfo : mod.getOps<fir::TypeInfoOp>()) {
+    unsigned bindingIdx = 0;
+    BindingTable bindings;
+    if (typeInfo.getDispatchTable().empty()) {
+      bindingTables[typeInfo.getSymName()] = bindings;
+      continue;
+    }
+    for (auto dtEntry :
+         typeInfo.getDispatchTable().front().getOps<fir::DTEntryOp>()) {
+      bindings[dtEntry.getMethod()] = bindingIdx;
+      ++bindingIdx;
+    }
+    bindingTables[typeInfo.getSymName()] = bindings;
+  }
+}
+
 // Translate front-end KINDs for use in the IR and code gen.
 inline std::vector<fir::KindTy>
 fromDefaultKinds(const Fortran::common::IntrinsicTypeDefaultKinds &defKinds) {

diff  --git a/flang/include/flang/Semantics/runtime-type-info.h b/flang/include/flang/Semantics/runtime-type-info.h
index 6c5a061d1c1a2..e90d3ae8baf1e 100644
--- a/flang/include/flang/Semantics/runtime-type-info.h
+++ b/flang/include/flang/Semantics/runtime-type-info.h
@@ -38,10 +38,6 @@ RuntimeDerivedTypeTables BuildRuntimeDerivedTypeTables(SemanticsContext &);
 /// to describe other derived types at runtime in flang descriptor.
 constexpr char typeInfoBuiltinModule[]{"__fortran_type_info"};
 
-/// Name of the builtin derived type in __fortran_type_inf that is used for
-/// derived type descriptors.
-constexpr char typeDescriptorTypeName[]{"derivedtype"};
-
 /// Name of the bindings descriptor component in the DerivedType type of the
 /// __Fortran_type_info module
 constexpr char bindingDescCompName[]{"binding"};

diff  --git a/flang/lib/Evaluate/tools.cpp b/flang/lib/Evaluate/tools.cpp
index fcacdb93d662b..68838564f87ba 100644
--- a/flang/lib/Evaluate/tools.cpp
+++ b/flang/lib/Evaluate/tools.cpp
@@ -2334,11 +2334,6 @@ bool IsBuiltinCPtr(const Symbol &symbol) {
   return false;
 }
 
-bool IsFromBuiltinModule(const Symbol &symbol) {
-  const Scope &scope{symbol.GetUltimate().owner()};
-  return IsSameModule(&scope, scope.context().GetBuiltinsScope());
-}
-
 bool IsIsoCType(const DerivedTypeSpec *derived) {
   return IsBuiltinDerivedType(derived, "c_ptr") ||
       IsBuiltinDerivedType(derived, "c_funptr");

diff  --git a/flang/lib/Lower/Bridge.cpp b/flang/lib/Lower/Bridge.cpp
index 018bed4aacf0d..7b640dd497af3 100644
--- a/flang/lib/Lower/Bridge.cpp
+++ b/flang/lib/Lower/Bridge.cpp
@@ -52,7 +52,6 @@
 #include "flang/Optimizer/Dialect/FIROps.h"
 #include "flang/Optimizer/Dialect/Support/FIRContext.h"
 #include "flang/Optimizer/HLFIR/HLFIROps.h"
-#include "flang/Optimizer/Passes/CommandLineOpts.h"
 #include "flang/Optimizer/Support/DataLayout.h"
 #include "flang/Optimizer/Support/FatalError.h"
 #include "flang/Optimizer/Support/InternalNames.h"
@@ -263,7 +262,6 @@ class TypeInfoConverter {
   }
 
   void createTypeInfo(Fortran::lower::AbstractConverter &converter) {
-    createTypeInfoForTypeDescriptorBuiltinType(converter);
     while (!registeredTypeInfoA.empty()) {
       currentTypeInfoStack = ®isteredTypeInfoB;
       for (const TypeInfo &info : registeredTypeInfoA)
@@ -279,22 +277,10 @@ class TypeInfoConverter {
 private:
   void createTypeInfoOpAndGlobal(Fortran::lower::AbstractConverter &converter,
                                  const TypeInfo &info) {
-    if (!::skipExternalRttiDefinition)
-      Fortran::lower::createRuntimeTypeInfoGlobal(converter, info.symbol.get());
+    Fortran::lower::createRuntimeTypeInfoGlobal(converter, info.symbol.get());
     createTypeInfoOp(converter, info);
   }
 
-  void createTypeInfoForTypeDescriptorBuiltinType(
-      Fortran::lower::AbstractConverter &converter) {
-    if (registeredTypeInfoA.empty())
-      return;
-    auto builtinTypeInfoType = llvm::cast<fir::RecordType>(
-        converter.genType(registeredTypeInfoA[0].symbol.get()));
-    converter.getFirOpBuilder().createTypeInfoOp(
-        registeredTypeInfoA[0].loc, builtinTypeInfoType,
-        /*parentType=*/fir::RecordType{});
-  }
-
   void createTypeInfoOp(Fortran::lower::AbstractConverter &converter,
                         const TypeInfo &info) {
     fir::RecordType parentType{};

diff  --git a/flang/lib/Lower/ConvertVariable.cpp b/flang/lib/Lower/ConvertVariable.cpp
index 39599625a42c4..49e6ea02d51a7 100644
--- a/flang/lib/Lower/ConvertVariable.cpp
+++ b/flang/lib/Lower/ConvertVariable.cpp
@@ -38,7 +38,6 @@
 #include "flang/Optimizer/Dialect/FIROps.h"
 #include "flang/Optimizer/Dialect/Support/FIRContext.h"
 #include "flang/Optimizer/HLFIR/HLFIROps.h"
-#include "flang/Optimizer/Passes/CommandLineOpts.h"
 #include "flang/Optimizer/Support/FatalError.h"
 #include "flang/Optimizer/Support/InternalNames.h"
 #include "flang/Optimizer/Support/Utils.h"
@@ -653,13 +652,8 @@ getLinkageAttribute(fir::FirOpBuilder &builder,
   // Runtime type info for a same derived type is identical in each compilation
   // unit. It desired to avoid having to link against module that only define a
   // type. Therefore the runtime type info is generated everywhere it is needed
-  // with `linkonce_odr` LLVM linkage (unless the skipExternalRttiDefinition
-  // option is set, in which case one will need to link against objects of
-  // modules defining types). Builtin objects rtti is always generated because
-  // the builtin module is currently not compiled or part of the runtime.
-  if (var.isRuntimeTypeInfoData() &&
-      (!::skipExternalRttiDefinition ||
-       Fortran::semantics::IsFromBuiltinModule(var.getSymbol())))
+  // with `linkonce_odr` LLVM linkage.
+  if (var.isRuntimeTypeInfoData())
     return builder.createLinkOnceODRLinkage();
   if (var.isModuleOrSubmoduleVariable())
     return {}; // external linkage

diff  --git a/flang/lib/Optimizer/CodeGen/CodeGen.cpp b/flang/lib/Optimizer/CodeGen/CodeGen.cpp
index 2b018912b40e4..a3de3ae9d116a 100644
--- a/flang/lib/Optimizer/CodeGen/CodeGen.cpp
+++ b/flang/lib/Optimizer/CodeGen/CodeGen.cpp
@@ -1294,51 +1294,6 @@ genCUFAllocDescriptor(mlir::Location loc,
       .getResult();
 }
 
-/// Get the address of the type descriptor global variable that was created by
-/// lowering for derived type \p recType.
-template <typename ModOpTy>
-static mlir::Value
-getTypeDescriptor(ModOpTy mod, mlir::ConversionPatternRewriter &rewriter,
-                  mlir::Location loc, fir::RecordType recType,
-                  const fir::FIRToLLVMPassOptions &options) {
-  std::string name =
-      options.typeDescriptorsRenamedForAssembly
-          ? fir::NameUniquer::getTypeDescriptorAssemblyName(recType.getName())
-          : fir::NameUniquer::getTypeDescriptorName(recType.getName());
-  mlir::Type llvmPtrTy = ::getLlvmPtrType(mod.getContext());
-  if (auto global = mod.template lookupSymbol<fir::GlobalOp>(name))
-    return rewriter.create<mlir::LLVM::AddressOfOp>(loc, llvmPtrTy,
-                                                    global.getSymName());
-  // The global may have already been translated to LLVM.
-  if (auto global = mod.template lookupSymbol<mlir::LLVM::GlobalOp>(name))
-    return rewriter.create<mlir::LLVM::AddressOfOp>(loc, llvmPtrTy,
-                                                    global.getSymName());
-  // Type info derived types do not have type descriptors since they are the
-  // types defining type descriptors.
-  if (options.ignoreMissingTypeDescriptors ||
-      fir::NameUniquer::belongsToModule(
-          name, Fortran::semantics::typeInfoBuiltinModule))
-    return rewriter.create<mlir::LLVM::ZeroOp>(loc, llvmPtrTy);
-
-  if (!options.skipExternalRttiDefinition)
-    fir::emitFatalError(loc,
-                        "runtime derived type info descriptor was not "
-                        "generated and skipExternalRttiDefinition and "
-                        "ignoreMissingTypeDescriptors options are not set");
-
-  // Rtti for a derived type defined in another compilation unit and for which
-  // rtti was not defined in lowering because of the skipExternalRttiDefinition
-  // option. Generate the object declaration now.
-  auto insertPt = rewriter.saveInsertionPoint();
-  rewriter.setInsertionPoint(mod.getBody(), mod.getBody()->end());
-  mlir::LLVM::GlobalOp global = rewriter.create<mlir::LLVM::GlobalOp>(
-      loc, llvmPtrTy, /*constant=*/true, mlir::LLVM::Linkage::External, name,
-      mlir::Attribute());
-  rewriter.restoreInsertionPoint(insertPt);
-  return rewriter.create<mlir::LLVM::AddressOfOp>(loc, llvmPtrTy,
-                                                  global.getSymName());
-}
-
 /// Common base class for embox to descriptor conversion.
 template <typename OP>
 struct EmboxCommonConversion : public fir::FIROpConversion<OP> {
@@ -1451,6 +1406,36 @@ struct EmboxCommonConversion : public fir::FIROpConversion<OP> {
                        stride);
   }
 
+  /// Get the address of the type descriptor global variable that was created by
+  /// lowering for derived type \p recType.
+  template <typename ModOpTy>
+  mlir::Value
+  getTypeDescriptor(ModOpTy mod, mlir::ConversionPatternRewriter &rewriter,
+                    mlir::Location loc, fir::RecordType recType) const {
+    std::string name =
+        this->options.typeDescriptorsRenamedForAssembly
+            ? fir::NameUniquer::getTypeDescriptorAssemblyName(recType.getName())
+            : fir::NameUniquer::getTypeDescriptorName(recType.getName());
+    mlir::Type llvmPtrTy = ::getLlvmPtrType(mod.getContext());
+    if (auto global = mod.template lookupSymbol<fir::GlobalOp>(name)) {
+      return rewriter.create<mlir::LLVM::AddressOfOp>(loc, llvmPtrTy,
+                                                      global.getSymName());
+    }
+    if (auto global = mod.template lookupSymbol<mlir::LLVM::GlobalOp>(name)) {
+      // The global may have already been translated to LLVM.
+      return rewriter.create<mlir::LLVM::AddressOfOp>(loc, llvmPtrTy,
+                                                      global.getSymName());
+    }
+    // Type info derived types do not have type descriptors since they are the
+    // types defining type descriptors.
+    if (!this->options.ignoreMissingTypeDescriptors &&
+        !fir::NameUniquer::belongsToModule(
+            name, Fortran::semantics::typeInfoBuiltinModule))
+      fir::emitFatalError(
+          loc, "runtime derived type info descriptor was not generated");
+    return rewriter.create<mlir::LLVM::ZeroOp>(loc, llvmPtrTy);
+  }
+
   template <typename ModOpTy>
   mlir::Value populateDescriptor(mlir::Location loc, ModOpTy mod,
                                  fir::BaseBoxType boxTy, mlir::Type inputType,
@@ -1515,8 +1500,7 @@ struct EmboxCommonConversion : public fir::FIROpConversion<OP> {
           mlir::Type innerType = fir::unwrapInnerType(inputType);
           if (innerType && mlir::isa<fir::RecordType>(innerType)) {
             auto recTy = mlir::dyn_cast<fir::RecordType>(innerType);
-            typeDesc =
-                getTypeDescriptor(mod, rewriter, loc, recTy, this->options);
+            typeDesc = getTypeDescriptor(mod, rewriter, loc, recTy);
           } else {
             // Unlimited polymorphic type descriptor with no record type. Set
             // type descriptor address to a clean state.
@@ -1524,8 +1508,8 @@ struct EmboxCommonConversion : public fir::FIROpConversion<OP> {
                 loc, ::getLlvmPtrType(mod.getContext()));
           }
         } else {
-          typeDesc = getTypeDescriptor(
-              mod, rewriter, loc, fir::unwrapIfDerived(boxTy), this->options);
+          typeDesc = getTypeDescriptor(mod, rewriter, loc,
+                                       fir::unwrapIfDerived(boxTy));
         }
       }
       if (typeDesc)
@@ -3037,10 +3021,22 @@ struct TypeDescOpConversion : public fir::FIROpConversion<fir::TypeDescOp> {
     assert(mlir::isa<fir::RecordType>(inTy) && "expecting fir.type");
     auto recordType = mlir::dyn_cast<fir::RecordType>(inTy);
     auto module = typeDescOp.getOperation()->getParentOfType<mlir::ModuleOp>();
-    mlir::Value typeDesc = getTypeDescriptor(
-        module, rewriter, typeDescOp.getLoc(), recordType, this->options);
-    rewriter.replaceOp(typeDescOp, typeDesc);
-    return mlir::success();
+    std::string typeDescName =
+        this->options.typeDescriptorsRenamedForAssembly
+            ? fir::NameUniquer::getTypeDescriptorAssemblyName(
+                  recordType.getName())
+            : fir::NameUniquer::getTypeDescriptorName(recordType.getName());
+    auto llvmPtrTy = ::getLlvmPtrType(typeDescOp.getContext());
+    if (auto global = module.lookupSymbol<mlir::LLVM::GlobalOp>(typeDescName)) {
+      rewriter.replaceOpWithNewOp<mlir::LLVM::AddressOfOp>(
+          typeDescOp, llvmPtrTy, global.getSymName());
+      return mlir::success();
+    } else if (auto global = module.lookupSymbol<fir::GlobalOp>(typeDescName)) {
+      rewriter.replaceOpWithNewOp<mlir::LLVM::AddressOfOp>(
+          typeDescOp, llvmPtrTy, global.getSymName());
+      return mlir::success();
+    }
+    return mlir::failure();
   }
 };
 

diff  --git a/flang/lib/Optimizer/Passes/CommandLineOpts.cpp b/flang/lib/Optimizer/Passes/CommandLineOpts.cpp
index 014237542f24d..f95a280883cba 100644
--- a/flang/lib/Optimizer/Passes/CommandLineOpts.cpp
+++ b/flang/lib/Optimizer/Passes/CommandLineOpts.cpp
@@ -39,12 +39,6 @@ cl::opt<bool> ignoreMissingTypeDescriptors(
              "translating FIR to LLVM"),
     cl::init(false), cl::Hidden);
 
-cl::opt<bool> skipExternalRttiDefinition(
-    "skip-external-rtti-definition", llvm::cl::init(false),
-    llvm::cl::desc("do not define rtti static objects for types belonging to "
-                   "other compilation units"),
-    cl::Hidden);
-
 OptimizationLevel defaultOptLevel{OptimizationLevel::O0};
 
 codegenoptions::DebugInfoKind noDebugInfo{codegenoptions::NoDebugInfo};

diff  --git a/flang/lib/Optimizer/Passes/Pipelines.cpp b/flang/lib/Optimizer/Passes/Pipelines.cpp
index 42d9e7ba2418f..70f57bdeddd3f 100644
--- a/flang/lib/Optimizer/Passes/Pipelines.cpp
+++ b/flang/lib/Optimizer/Passes/Pipelines.cpp
@@ -108,7 +108,6 @@ void addFIRToLLVMPass(mlir::PassManager &pm,
                       const MLIRToLLVMPassPipelineConfig &config) {
   fir::FIRToLLVMPassOptions options;
   options.ignoreMissingTypeDescriptors = ignoreMissingTypeDescriptors;
-  options.skipExternalRttiDefinition = skipExternalRttiDefinition;
   options.applyTBAA = config.AliasAnalysis;
   options.forceUnifiedTBAATree = useOldAliasTags;
   options.typeDescriptorsRenamedForAssembly =

diff  --git a/flang/lib/Optimizer/Transforms/PolymorphicOpConversion.cpp b/flang/lib/Optimizer/Transforms/PolymorphicOpConversion.cpp
index 57eae1ff052a2..f9a4c4d0283c7 100644
--- a/flang/lib/Optimizer/Transforms/PolymorphicOpConversion.cpp
+++ b/flang/lib/Optimizer/Transforms/PolymorphicOpConversion.cpp
@@ -16,6 +16,7 @@
 #include "flang/Optimizer/Dialect/Support/KindMapping.h"
 #include "flang/Optimizer/Support/InternalNames.h"
 #include "flang/Optimizer/Support/TypeCode.h"
+#include "flang/Optimizer/Support/Utils.h"
 #include "flang/Optimizer/Transforms/Passes.h"
 #include "flang/Runtime/derived-api.h"
 #include "flang/Semantics/runtime-type-info.h"
@@ -37,45 +38,6 @@ namespace fir {
 using namespace fir;
 using namespace mlir;
 
-// Reconstruct binding tables for dynamic dispatch.
-using BindingTable = llvm::DenseMap<llvm::StringRef, unsigned>;
-using BindingTables = llvm::DenseMap<llvm::StringRef, BindingTable>;
-
-static std::string getTypeDescriptorTypeName() {
-  llvm::SmallVector<llvm::StringRef, 1> modules = {
-      Fortran::semantics::typeInfoBuiltinModule};
-  return fir::NameUniquer::doType(modules, /*proc=*/{}, /*blockId=*/0,
-                                  Fortran::semantics::typeDescriptorTypeName,
-                                  /*kinds=*/{});
-}
-
-static std::optional<mlir::Type>
-buildBindingTables(BindingTables &bindingTables, mlir::ModuleOp mod) {
-
-  std::optional<mlir::Type> typeDescriptorType;
-  std::string typeDescriptorTypeName = getTypeDescriptorTypeName();
-  // The binding tables are defined in FIR after lowering inside fir.type_info
-  // operations. Go through each binding tables and store the procedure name and
-  // binding index for later use by the fir.dispatch conversion pattern.
-  for (auto typeInfo : mod.getOps<fir::TypeInfoOp>()) {
-    if (!typeDescriptorType && typeInfo.getSymName() == typeDescriptorTypeName)
-      typeDescriptorType = typeInfo.getType();
-    unsigned bindingIdx = 0;
-    BindingTable bindings;
-    if (typeInfo.getDispatchTable().empty()) {
-      bindingTables[typeInfo.getSymName()] = bindings;
-      continue;
-    }
-    for (auto dtEntry :
-         typeInfo.getDispatchTable().front().getOps<fir::DTEntryOp>()) {
-      bindings[dtEntry.getMethod()] = bindingIdx;
-      ++bindingIdx;
-    }
-    bindingTables[typeInfo.getSymName()] = bindings;
-  }
-  return typeDescriptorType;
-}
-
 namespace {
 
 /// SelectTypeOp converted to an if-then-else chain
@@ -115,10 +77,9 @@ class SelectTypeConv : public OpConversionPattern<fir::SelectTypeOp> {
 struct DispatchOpConv : public OpConversionPattern<fir::DispatchOp> {
   using OpConversionPattern<fir::DispatchOp>::OpConversionPattern;
 
-  DispatchOpConv(mlir::MLIRContext *ctx, const BindingTables &bindingTables,
-                 std::optional<mlir::Type> typeDescriptorType)
+  DispatchOpConv(mlir::MLIRContext *ctx, const BindingTables &bindingTables)
       : mlir::OpConversionPattern<fir::DispatchOp>(ctx),
-        bindingTables(bindingTables), typeDescriptorType{typeDescriptorType} {}
+        bindingTables(bindingTables) {}
 
   llvm::LogicalResult
   matchAndRewrite(fir::DispatchOp dispatch, OpAdaptor adaptor,
@@ -150,11 +111,13 @@ struct DispatchOpConv : public OpConversionPattern<fir::DispatchOp> {
 
     mlir::Value passedObject = dispatch.getObject();
 
-    if (!typeDescriptorType)
-      return emitError(loc) << "cannot find " << getTypeDescriptorTypeName()
-                            << " fir.type_info that is required to get the "
-                               "related builtin type and lower fir.dispatch";
-    mlir::Type typeDescTy = *typeDescriptorType;
+    auto module = dispatch.getOperation()->getParentOfType<mlir::ModuleOp>();
+    Type typeDescTy;
+    std::string typeDescName =
+        NameUniquer::getTypeDescriptorName(recordType.getName());
+    if (auto global = module.lookupSymbol<fir::GlobalOp>(typeDescName)) {
+      typeDescTy = global.getType();
+    }
 
     // clang-format off
     // Before:
@@ -250,7 +213,6 @@ struct DispatchOpConv : public OpConversionPattern<fir::DispatchOp> {
 
 private:
   BindingTables bindingTables;
-  std::optional<mlir::Type> typeDescriptorType;
 };
 
 /// Convert FIR structured control flow ops to CFG ops.
@@ -267,11 +229,10 @@ class PolymorphicOpConversion
     mlir::RewritePatternSet patterns(context);
 
     BindingTables bindingTables;
-    std::optional<mlir::Type> typeDescriptorType =
-        buildBindingTables(bindingTables, mod);
+    buildBindingTables(bindingTables, mod);
 
     patterns.insert<SelectTypeConv>(context);
-    patterns.insert<DispatchOpConv>(context, bindingTables, typeDescriptorType);
+    patterns.insert<DispatchOpConv>(context, bindingTables);
     mlir::ConversionTarget target(*context);
     target.addLegalDialect<mlir::affine::AffineDialect,
                            mlir::cf::ControlFlowDialect, FIROpsDialect,
@@ -418,11 +379,16 @@ llvm::LogicalResult SelectTypeConv::genTypeLadderStep(
   } else if (auto a = mlir::dyn_cast<fir::SubclassAttr>(attr)) {
     // Retrieve the type descriptor from the type guard statement record type.
     assert(mlir::isa<fir::RecordType>(a.getType()) && "expect fir.record type");
-    mlir::Value typeDescAddr =
-        rewriter.create<fir::TypeDescOp>(loc, mlir::TypeAttr::get(a.getType()));
-    mlir::Type refNoneType = ReferenceType::get(rewriter.getNoneType());
+    fir::RecordType recTy = mlir::dyn_cast<fir::RecordType>(a.getType());
+    std::string typeDescName =
+        fir::NameUniquer::getTypeDescriptorName(recTy.getName());
+    auto typeDescGlobal = mod.lookupSymbol<fir::GlobalOp>(typeDescName);
+    auto typeDescAddr = rewriter.create<fir::AddrOfOp>(
+        loc, fir::ReferenceType::get(typeDescGlobal.getType()),
+        typeDescGlobal.getSymbol());
+    mlir::Type typeDescTy = ReferenceType::get(rewriter.getNoneType());
     mlir::Value typeDesc =
-        rewriter.create<ConvertOp>(loc, refNoneType, typeDescAddr);
+        rewriter.create<ConvertOp>(loc, typeDescTy, typeDescAddr);
 
     // Prepare the selector descriptor for the runtime call.
     mlir::Type descNoneTy = fir::BoxType::get(rewriter.getNoneType());
@@ -440,7 +406,7 @@ llvm::LogicalResult SelectTypeConv::genTypeLadderStep(
                                mlir::UnitAttr::get(rewriter.getContext()));
       callee =
           fir::createFuncOp(rewriter.getUnknownLoc(), mod, fctName,
-                            rewriter.getFunctionType({descNoneTy, refNoneType},
+                            rewriter.getFunctionType({descNoneTy, typeDescTy},
                                                      rewriter.getI1Type()),
                             {runtimeAttr});
     }
@@ -469,11 +435,20 @@ SelectTypeConv::genTypeDescCompare(mlir::Location loc, mlir::Value selector,
                                    mlir::Type ty, mlir::ModuleOp mod,
                                    mlir::PatternRewriter &rewriter) const {
   assert(mlir::isa<fir::RecordType>(ty) && "expect fir.record type");
-  mlir::Value typeDescAddr =
-      rewriter.create<fir::TypeDescOp>(loc, mlir::TypeAttr::get(ty));
-  mlir::Value selectorTdescAddr = rewriter.create<fir::BoxTypeDescOp>(
-      loc, typeDescAddr.getType(), selector);
+  fir::RecordType recTy = mlir::dyn_cast<fir::RecordType>(ty);
+  std::string typeDescName =
+      fir::NameUniquer::getTypeDescriptorName(recTy.getName());
+  auto typeDescGlobal = mod.lookupSymbol<fir::GlobalOp>(typeDescName);
+  if (!typeDescGlobal)
+    return {};
+  auto typeDescAddr = rewriter.create<fir::AddrOfOp>(
+      loc, fir::ReferenceType::get(typeDescGlobal.getType()),
+      typeDescGlobal.getSymbol());
   auto intPtrTy = rewriter.getIndexType();
+  mlir::Type tdescType =
+      fir::TypeDescType::get(mlir::NoneType::get(rewriter.getContext()));
+  mlir::Value selectorTdescAddr =
+      rewriter.create<fir::BoxTypeDescOp>(loc, tdescType, selector);
   auto typeDescInt =
       rewriter.create<fir::ConvertOp>(loc, intPtrTy, typeDescAddr);
   auto selectorTdescInt =

diff  --git a/flang/test/Integration/skip-external-rtti-definition.F90 b/flang/test/Integration/skip-external-rtti-definition.F90
deleted file mode 100644
index f86cc069b304d..0000000000000
--- a/flang/test/Integration/skip-external-rtti-definition.F90
+++ /dev/null
@@ -1,47 +0,0 @@
-! Test -skip-external-rtti-definition option
-
-!RUN: rm -rf %t && mkdir -p %t
-!RUN: %flang_fc1 -fsyntax-only -DSTEP=1 -J%t %s
-!RUN: %flang_fc1 -emit-llvm -J%t  %s -o - | FileCheck %s -check-prefix=LINKONCE
-!RUN: %flang_fc1 -emit-llvm -J%t -mllvm -skip-external-rtti-definition %s -o - | FileCheck %s -check-prefix=EXTERNAL
-
-#if STEP == 1
-module module_external_type_definition
- type t1
- end type
-end module
-#else
-
-module module_same_unit_type_definition
- type t2
- end type
-end module
-
-subroutine test
-  use module_external_type_definition
-  use module_same_unit_type_definition
-  interface
-  subroutine needs_descriptor(x)
-    class(*) :: x
-  end subroutine
-  end interface
-  type(t1) :: x1
-  type(t2) :: x2
-  call needs_descriptor(x1)
-  call needs_descriptor(x2)
-end subroutine
-
-#endif
-
-! LINKONCE-DAG: @_QMmodule_external_type_definitionEXnXt1 = linkonce_odr constant [2 x i8] c"t1", comdat
-! LINKONCE-DAG: @_QMmodule_external_type_definitionEXdtXt1 = linkonce_odr constant {{.*}} {
-! LINKONCE-DAG: @_QMmodule_same_unit_type_definitionEXnXt2 = linkonce_odr constant [2 x i8] c"t2", comdat
-! LINKONCE-DAG: @_QMmodule_same_unit_type_definitionEXdtXt2 = linkonce_odr constant {{.*}} {
-
-! EXTERNAL-NOT: @_QMmodule_external_type_definitionEXnXt1
-! EXTERNAL: @_QMmodule_same_unit_type_definitionEXnXt2 = constant [2 x i8] c"t2"
-! EXTERNAL-NOT: @_QMmodule_external_type_definitionEXnXt1
-! EXTERNAL: @_QMmodule_same_unit_type_definitionEXdtXt2 = constant {{.*}} {
-! EXTERNAL-NOT: @_QMmodule_external_type_definitionEXnXt1
-! EXTERNAL: @_QMmodule_external_type_definitionEXdtXt1 =  external constant ptr
-! EXTERNAL-NOT: @_QMmodule_external_type_definitionEXnXt1

diff  --git a/flang/test/Lower/select-type-2.f90 b/flang/test/Lower/select-type-2.f90
index 59485c176c76a..7b4cf96069e53 100644
--- a/flang/test/Lower/select-type-2.f90
+++ b/flang/test/Lower/select-type-2.f90
@@ -30,8 +30,8 @@ subroutine select_type1(a)
 
 ! CHECK-LABEL: func.func @_QMselect_type_2Pselect_type1(
 ! CHECK-SAME: %[[ARG0:.*]]: !fir.class<!fir.type<_QMselect_type_2Tp1{a:i32,b:i32}>> {fir.bindc_name = "a"}) {
-! CHECK:      %[[TDESC_P3_ADDR:.*]] = fir.type_desc !fir.type<_QMselect_type_2Tp3
-! CHECK:      %[[TDESC_P3_CONV:.*]] = fir.convert %[[TDESC_P3_ADDR]] : (!fir.tdesc{{.*}}>) -> !fir.ref<none>
+! CHECK:      %[[TDESC_P3_ADDR:.*]] = fir.address_of(@_QMselect_type_2E.dt.p3) : !fir.ref<!fir.type<{{.*}}>>
+! CHECK:      %[[TDESC_P3_CONV:.*]] = fir.convert %[[TDESC_P3_ADDR]] : (!fir.ref<!fir.type<{{.*}}>>) -> !fir.ref<none>
 ! CHECK:      %[[BOX_NONE:.*]] = fir.convert %[[ARG0]] : (!fir.class<!fir.type<_QMselect_type_2Tp1{a:i32,b:i32}>>) -> !fir.box<none>
 ! CHECK:      %[[CLASS_IS_CMP:.*]] = fir.call @_FortranAClassIs(%[[BOX_NONE]], %[[TDESC_P3_CONV]]) : (!fir.box<none>, !fir.ref<none>) -> i1
 ! CHECK:      cf.cond_br %[[CLASS_IS_CMP]], ^[[CLASS_IS_P3_BLK:.*]], ^[[NOT_CLASS_IS_P3_BLK:.*]]
@@ -40,8 +40,8 @@ subroutine select_type1(a)
 ! CHECK:    ^bb[[CLASS_IS_P1:[0-9]]]:
 ! CHECK:      cf.br ^bb[[END_SELECT_BLK:[0-9]]]
 ! CHECK:    ^[[NOT_CLASS_IS_P3_BLK]]:
-! CHECK:      %[[TDESC_P1_ADDR:.*]] = fir.type_desc !fir.type<_QMselect_type_2Tp1
-! CHECK:      %[[TDESC_P1_CONV:.*]] = fir.convert %[[TDESC_P1_ADDR]] : (!fir.tdesc{{.*}}>) -> !fir.ref<none>
+! CHECK:      %[[TDESC_P1_ADDR:.*]] = fir.address_of(@_QMselect_type_2E.dt.p1) : !fir.ref<!fir.type<{{.*}}>>
+! CHECK:      %[[TDESC_P1_CONV:.*]] = fir.convert %[[TDESC_P1_ADDR]] : (!fir.ref<!fir.type<{{.*}}>>) -> !fir.ref<none>
 ! CHECK:      %[[BOX_NONE:.*]] = fir.convert %[[ARG0]] : (!fir.class<!fir.type<_QMselect_type_2Tp1{a:i32,b:i32}>>) -> !fir.box<none>
 ! CHECK:      %[[CLASS_IS_CMP:.*]] = fir.call @_FortranAClassIs(%[[BOX_NONE]], %[[TDESC_P1_CONV]]) : (!fir.box<none>, !fir.ref<none>) -> i1
 ! CHECK:      cf.cond_br %[[CLASS_IS_CMP]], ^bb[[CLASS_IS_P1]], ^bb[[NOT_CLASS_IS_P1]]

diff  --git a/flang/test/Lower/select-type.f90 b/flang/test/Lower/select-type.f90
index e2ca87ad447c9..64dd639731ab1 100644
--- a/flang/test/Lower/select-type.f90
+++ b/flang/test/Lower/select-type.f90
@@ -68,15 +68,15 @@ subroutine select_type1(a)
 
 ! CFG-LABEL: func.func @_QMselect_type_lower_testPselect_type1(
 ! CFG-SAME: %[[ARG0:.*]]: !fir.class<!fir.type<_QMselect_type_lower_testTp1{a:i32,b:i32}>> {fir.bindc_name = "a"}) {
-! CFG:      %[[TDESC_P1_ADDR:.*]] = fir.type_desc !fir.type<_QMselect_type_lower_testTp1{a:i32,b:i32}>
-! CFG:      %[[BOX_TDESC:.*]] = fir.box_tdesc %[[ARG0]] : (!fir.class<!fir.type<_QMselect_type_lower_testTp1{a:i32,b:i32}>>) -> !fir.tdesc<!fir.type<_QMselect_type_lower_testTp1{a:i32,b:i32}>>
-! CFG:      %[[TDESC_P1_CONV:.*]] = fir.convert %[[TDESC_P1_ADDR]] : (!fir.tdesc<!fir.type<_QMselect_type_lower_testTp1{a:i32,b:i32}>>) -> index
-! CFG:      %[[BOX_TDESC_CONV:.*]] = fir.convert %[[BOX_TDESC]] : (!fir.tdesc<!fir.type<_QMselect_type_lower_testTp1{a:i32,b:i32}>>) -> index
+! CFG:      %[[TDESC_P1_ADDR:.*]] = fir.address_of(@_QMselect_type_lower_testE.dt.p1) : !fir.ref<!fir.type<{{.*}}>>
+! CFG:      %[[BOX_TDESC:.*]] = fir.box_tdesc %[[ARG0]] : (!fir.class<!fir.type<_QMselect_type_lower_testTp1{a:i32,b:i32}>>) -> !fir.tdesc<none>
+! CFG:      %[[TDESC_P1_CONV:.*]] = fir.convert %[[TDESC_P1_ADDR]] : (!fir.ref<!fir.type<{{.*}}>>) -> index
+! CFG:      %[[BOX_TDESC_CONV:.*]] = fir.convert %[[BOX_TDESC]] : (!fir.tdesc<none>) -> index
 ! CFG:      %[[TDESC_CMP:.*]] = arith.cmpi eq, %[[TDESC_P1_CONV]], %[[BOX_TDESC_CONV]] : index
 ! CFG:      cf.cond_br %[[TDESC_CMP]], ^[[TYPE_IS_P1_BLK:.*]], ^[[NOT_TYPE_IS_P1_BLK:.*]]
 ! CFG:    ^[[NOT_TYPE_IS_P1_BLK]]:
-! CFG:      %[[TDESC_P2_ADDR:.*]] = fir.type_desc !fir.type<_QMselect_type_lower_testTp2{{.*}}
-! CFG:      %[[TDESC_P2_CONV:.*]] = fir.convert %[[TDESC_P2_ADDR]] : (!fir.tdesc<{{.*}}>) -> !fir.ref<none>
+! CFG:      %[[TDESC_P2_ADDR:.*]] = fir.address_of(@_QMselect_type_lower_testE.dt.p2) : !fir.ref<!fir.type<{{.*}}>>
+! CFG:      %[[TDESC_P2_CONV:.*]] = fir.convert %[[TDESC_P2_ADDR]] : (!fir.ref<!fir.type<{{.*}}>>) -> !fir.ref<none>
 ! CFG:      %[[BOX_NONE:.*]] = fir.convert %[[ARG0]] : (!fir.class<!fir.type<_QMselect_type_lower_testTp1{a:i32,b:i32}>>) -> !fir.box<none>
 ! CFG:      %[[CLASS_IS:.*]] = fir.call @_FortranAClassIs(%[[BOX_NONE]], %[[TDESC_P2_CONV]]) : (!fir.box<none>, !fir.ref<none>) -> i1
 ! CFG:      cf.cond_br %[[CLASS_IS]], ^bb[[CLASS_IS_P2_BLK:.*]], ^[[NOT_CLASS_IS_P2_BLK:.*]]
@@ -87,8 +87,8 @@ subroutine select_type1(a)
 ! CFG:    ^bb[[CLASS_IS_P1_BLK:[0-9]]]:
 ! CFG:      cf.br ^[[END_SELECT_BLK:.*]]
 ! CFG:    ^[[NOT_CLASS_IS_P2_BLK]]:
-! CFG:      %[[TDESC_P1_ADDR:.*]] = fir.type_desc !fir.type<_QMselect_type_lower_testTp1{a:i32,b:i32}>
-! CFG:      %[[TDESC_P1_CONV:.*]] = fir.convert %[[TDESC_P1_ADDR]] : (!fir.tdesc<{{.*}}>) -> !fir.ref<none>
+! CFG:      %[[TDESC_P1_ADDR:.*]] = fir.address_of(@_QMselect_type_lower_testE.dt.p1) : !fir.ref<!fir.type<{{.*}}>>
+! CFG:      %[[TDESC_P1_CONV:.*]] = fir.convert %[[TDESC_P1_ADDR]] : (!fir.ref<!fir.type<{{.*}}>>) -> !fir.ref<none>
 ! CFG:      %[[BOX_NONE:.*]] = fir.convert %[[ARG0]] : (!fir.class<!fir.type<_QMselect_type_lower_testTp1{a:i32,b:i32}>>) -> !fir.box<none>
 ! CFG:      %[[CLASS_IS:.*]] = fir.call @_FortranAClassIs(%[[BOX_NONE]], %[[TDESC_P1_CONV]]) : (!fir.box<none>, !fir.ref<none>) -> i1
 ! CFG:      cf.cond_br %[[CLASS_IS]], ^bb[[CLASS_IS_P1_BLK]], ^bb[[NOT_CLASS_IS_P1_BLK]]
@@ -126,15 +126,15 @@ subroutine select_type2()
 ! CFG:     %[[GET_CLASS:.*]] = fir.call @_QMselect_type_lower_testPget_class() {{.*}} : () -> !fir.class<!fir.ptr<!fir.type<_QMselect_type_lower_testTp1{a:i32,b:i32}>>>
 ! CFG:     fir.save_result %[[GET_CLASS]] to %[[CLASS_ALLOCA]] : !fir.class<!fir.ptr<!fir.type<_QMselect_type_lower_testTp1{a:i32,b:i32}>>>, !fir.ref<!fir.class<!fir.ptr<!fir.type<_QMselect_type_lower_testTp1{a:i32,b:i32}>>>>
 ! CFG:     %[[LOAD_CLASS:.*]] = fir.load %[[CLASS_ALLOCA]] : !fir.ref<!fir.class<!fir.ptr<!fir.type<_QMselect_type_lower_testTp1{a:i32,b:i32}>>>>
-! CFG:     %[[TDESC_P1_ADDR:.*]] = fir.type_desc !fir.type<_QMselect_type_lower_testTp1{a:i32,b:i32}>
-! CFG:     %[[CLASS_TDESC:.*]] = fir.box_tdesc %[[LOAD_CLASS]] : (!fir.class<!fir.ptr<!fir.type<_QMselect_type_lower_testTp1{a:i32,b:i32}>>>) -> !fir.tdesc<{{.*}}>
-! CFG:     %[[TDESC_P1_CONV:.*]] = fir.convert %[[TDESC_P1_ADDR]] : (!fir.tdesc{{.*}}>) -> index
-! CFG:     %[[BOX_TDESC_CONV:.*]] = fir.convert %[[CLASS_TDESC]] : (!fir.tdesc<{{.*}}>) -> index
+! CFG:     %[[TDESC_P1_ADDR:.*]] = fir.address_of(@_QMselect_type_lower_testE.dt.p1) : !fir.ref<!fir.type<{{.*}}>>
+! CFG:     %[[CLASS_TDESC:.*]] = fir.box_tdesc %[[LOAD_CLASS]] : (!fir.class<!fir.ptr<!fir.type<_QMselect_type_lower_testTp1{a:i32,b:i32}>>>) -> !fir.tdesc<none>
+! CFG:     %[[TDESC_P1_CONV:.*]] = fir.convert %[[TDESC_P1_ADDR]] : (!fir.ref<!fir.type<{{.*}}>>) -> index
+! CFG:     %[[BOX_TDESC_CONV:.*]] = fir.convert %[[CLASS_TDESC]] : (!fir.tdesc<none>) -> index
 ! CFG:     %[[TDESC_CMP:.*]] = arith.cmpi eq, %[[TDESC_P1_CONV]], %[[BOX_TDESC_CONV]] : index
 ! CFG:     cf.cond_br %[[TDESC_CMP]], ^[[TYPE_IS_P1_BLK:.*]], ^[[NOT_TYPE_IS_P1_BLK:.*]]
 ! CFG:   ^[[NOT_TYPE_IS_P1_BLK]]:
-! CFG:     %[[TDESC_P1_ADDR:.*]] = fir.type_desc !fir.type<_QMselect_type_lower_testTp1{a:i32,b:i32}>
-! CFG:     %[[TDESC_P1_CONV:.*]] = fir.convert %[[TDESC_P1_ADDR]] : (!fir.tdesc{{.*}}>) -> !fir.ref<none>
+! CFG:     %[[TDESC_P1_ADDR:.*]] = fir.address_of(@_QMselect_type_lower_testE.dt.p1) : !fir.ref<!fir.type<{{.*}}>>
+! CFG:     %[[TDESC_P1_CONV:.*]] = fir.convert %[[TDESC_P1_ADDR]] : (!fir.ref<!fir.type<{{.*}}>>) -> !fir.ref<none>
 ! CFG:     %[[BOX_NONE:.*]] = fir.convert %[[LOAD_CLASS]] : (!fir.class<!fir.ptr<!fir.type<_QMselect_type_lower_testTp1{a:i32,b:i32}>>>) -> !fir.box<none>
 ! CFG:     %[[CLASS_IS:.*]] = fir.call @_FortranAClassIs(%[[BOX_NONE]], %[[TDESC_P1_CONV]]) : (!fir.box<none>, !fir.ref<none>) -> i1
 ! CFG:     cf.cond_br %[[CLASS_IS]], ^[[CLASS_IS_BLK:.*]], ^[[NOT_CLASS_IS_BLK:.*]]
@@ -176,15 +176,15 @@ subroutine select_type3(a)
 ! CFG-LABEL: func.func @_QMselect_type_lower_testPselect_type3(
 ! CFG-SAME: %[[ARG0:.*]]: !fir.ref<!fir.class<!fir.ptr<!fir.array<?x!fir.type<_QMselect_type_lower_testTp1{a:i32,b:i32}>>>>> {fir.bindc_name = "a"}) {
 ! CFG:      %[[SELECTOR:.*]] = fir.embox %{{.*}} source_box %{{.*}} : (!fir.ref<!fir.type<_QMselect_type_lower_testTp1{a:i32,b:i32}>>, !fir.class<{{.*}}>) -> !fir.class<!fir.type<_QMselect_type_lower_testTp1{a:i32,b:i32}>>
-! CFG:      %[[TDESC_P1_ADDR:.*]] = fir.type_desc !fir.type<_QMselect_type_lower_testTp1{a:i32,b:i32}>
-! CFG:      %[[SELECTOR_TDESC:.*]] = fir.box_tdesc %[[SELECTOR]] : (!fir.class<!fir.type<_QMselect_type_lower_testTp1{a:i32,b:i32}>>) -> !fir.tdesc<{{.*}}>
-! CFG:      %[[TDESC_P1_CONV:.*]] = fir.convert %[[TDESC_P1_ADDR]] : (!fir.tdesc{{.*}}>) -> index
-! CFG:      %[[TDESC_CONV:.*]] = fir.convert %[[SELECTOR_TDESC]] : (!fir.tdesc<{{.*}}>) -> index
+! CFG:      %[[TDESC_P1_ADDR:.*]] = fir.address_of(@_QMselect_type_lower_testE.dt.p1) : !fir.ref<!fir.type<{{.*}}>>
+! CFG:      %[[SELECTOR_TDESC:.*]] = fir.box_tdesc %[[SELECTOR]] : (!fir.class<!fir.type<_QMselect_type_lower_testTp1{a:i32,b:i32}>>) -> !fir.tdesc<none>
+! CFG:      %[[TDESC_P1_CONV:.*]] = fir.convert %[[TDESC_P1_ADDR]] : (!fir.ref<!fir.type<{{.*}}>>) -> index
+! CFG:      %[[TDESC_CONV:.*]] = fir.convert %[[SELECTOR_TDESC]] : (!fir.tdesc<none>) -> index
 ! CFG:      %[[TDESC_CMP:.*]] = arith.cmpi eq, %[[TDESC_P1_CONV]], %[[TDESC_CONV]] : index
 ! CFG:      cf.cond_br %[[TDESC_CMP]], ^[[TYPE_IS_P1_BLK:.*]], ^[[NOT_TYPE_IS_P1_BLK:.*]]
 ! CFG:    ^[[NOT_TYPE_IS_P1_BLK]]:
-! CFG:      %[[TDESC_P1_ADDR:.*]] = fir.type_desc !fir.type<_QMselect_type_lower_testTp1{a:i32,b:i32}>
-! CFG:      %[[TDESC_P1_CONV:.*]] = fir.convert %[[TDESC_P1_ADDR]] : (!fir.tdesc{{.*}}>) -> !fir.ref<none>
+! CFG:      %[[TDESC_P1_ADDR:.*]] = fir.address_of(@_QMselect_type_lower_testE.dt.p1) : !fir.ref<!fir.type<{{.*}}>>
+! CFG:      %[[TDESC_P1_CONV:.*]] = fir.convert %[[TDESC_P1_ADDR]] : (!fir.ref<!fir.type<{{.*}}>>) -> !fir.ref<none>
 ! CFG:      %[[BOX_NONE:.*]] = fir.convert %[[SELECTOR]] : (!fir.class<!fir.type<_QMselect_type_lower_testTp1{a:i32,b:i32}>>) -> !fir.box<none>
 ! CFG:      %[[CLASS_IS:.*]] = fir.call @_FortranAClassIs(%[[BOX_NONE]], %[[TDESC_P1_CONV]]) : (!fir.box<none>, !fir.ref<none>) -> i1
 ! CFG:      cf.cond_br %[[CLASS_IS]], ^[[CLASS_IS_BLK:.*]], ^[[NOT_CLASS_IS:.*]]
@@ -222,25 +222,25 @@ subroutine select_type4(a)
 
 ! CFG-LABEL: func.func @_QMselect_type_lower_testPselect_type4(
 ! CFG-SAME: %[[ARG0:.*]]: !fir.class<!fir.type<_QMselect_type_lower_testTp1{a:i32,b:i32}>> {fir.bindc_name = "a"}) {
-! CFG:      %[[TDESC_P3_8_ADDR:.*]] = fir.type_desc !fir.type<_QMselect_type_lower_testTp3K8
-! CFG:      %[[BOX_TDESC:.*]] = fir.box_tdesc %[[ARG0]] : (!fir.class<!fir.type<_QMselect_type_lower_testTp1{a:i32,b:i32}>>) -> !fir.tdesc<{{.*}}>
-! CFG:      %[[TDESC_P3_8_CONV:.*]] = fir.convert %[[TDESC_P3_8_ADDR]] : (!fir.tdesc{{.*}}>) -> index
-! CFG:      %[[BOX_TDESC_CONV:.*]] = fir.convert %[[BOX_TDESC]] : (!fir.tdesc<{{.*}}>) -> index
+! CFG:      %[[TDESC_P3_8_ADDR:.*]] = fir.address_of(@_QMselect_type_lower_testE.dt.p3.8) : !fir.ref<!fir.type<{{.*}}>>
+! CFG:      %[[BOX_TDESC:.*]] = fir.box_tdesc %[[ARG0]] : (!fir.class<!fir.type<_QMselect_type_lower_testTp1{a:i32,b:i32}>>) -> !fir.tdesc<none>
+! CFG:      %[[TDESC_P3_8_CONV:.*]] = fir.convert %[[TDESC_P3_8_ADDR]] : (!fir.ref<!fir.type<{{.*}}>>) -> index
+! CFG:      %[[BOX_TDESC_CONV:.*]] = fir.convert %[[BOX_TDESC]] : (!fir.tdesc<none>) -> index
 ! CFG:      %[[TDESC_CMP:.*]] = arith.cmpi eq, %[[TDESC_P3_8_CONV]], %[[BOX_TDESC_CONV]] : index
 ! CFG:      cf.cond_br %[[TDESC_CMP]], ^[[P3_8_BLK:.*]], ^[[NOT_P3_8_BLK:.*]]
 ! CFG:    ^[[NOT_P3_8_BLK]]:
-! CFG:      %[[TDESC_P3_4_ADDR:.*]] = fir.type_desc !fir.type<_QMselect_type_lower_testTp3K4
-! CFG:      %[[BOX_TDESC:.*]] = fir.box_tdesc %[[ARG0]] : (!fir.class<!fir.type<_QMselect_type_lower_testTp1{a:i32,b:i32}>>) -> !fir.tdesc<{{.*}}>
-! CFG:      %[[TDESC_P3_4_CONV:.*]] = fir.convert %[[TDESC_P3_4_ADDR]] : (!fir.tdesc{{.*}}>) -> index
-! CFG:      %[[BOX_TDESC_CONV:.*]] = fir.convert %[[BOX_TDESC]] : (!fir.tdesc<{{.*}}>) -> index
+! CFG:      %[[TDESC_P3_4_ADDR:.*]] = fir.address_of(@_QMselect_type_lower_testE.dt.p3.4) : !fir.ref<!fir.type<{{.*}}>>
+! CFG:      %[[BOX_TDESC:.*]] = fir.box_tdesc %[[ARG0]] : (!fir.class<!fir.type<_QMselect_type_lower_testTp1{a:i32,b:i32}>>) -> !fir.tdesc<none>
+! CFG:      %[[TDESC_P3_4_CONV:.*]] = fir.convert %[[TDESC_P3_4_ADDR]] : (!fir.ref<!fir.type<{{.*}}>>) -> index
+! CFG:      %[[BOX_TDESC_CONV:.*]] = fir.convert %[[BOX_TDESC]] : (!fir.tdesc<none>) -> index
 ! CFG:      %[[TDESC_CMP:.*]] = arith.cmpi eq, %[[TDESC_P3_4_CONV]], %[[BOX_TDESC_CONV]] : index
 ! CFG:      cf.cond_br %[[TDESC_CMP]], ^[[P3_4_BLK:.*]], ^[[NOT_P3_4_BLK:.*]]
 ! CFG:    ^[[P3_8_BLK]]:
 ! CFG:      _FortranAioOutputAscii
 ! CFG:      cf.br ^bb[[EXIT_SELECT_BLK:[0-9]]]
 ! CFG:    ^[[NOT_P3_4_BLK]]:
-! CFG:      %[[TDESC_P1_ADDR:.*]] = fir.type_desc !fir.type<_QMselect_type_lower_testTp1{a:i32,b:i32}>
-! CFG:      %[[TDESC_P1_CONV:.*]] = fir.convert %[[TDESC_P1_ADDR]] : (!fir.tdesc{{.*}}>) -> !fir.ref<none>
+! CFG:      %[[TDESC_P1_ADDR:.*]] = fir.address_of(@_QMselect_type_lower_testE.dt.p1) : !fir.ref<!fir.type<{{.*}}>>
+! CFG:      %[[TDESC_P1_CONV:.*]] = fir.convert %[[TDESC_P1_ADDR]] : (!fir.ref<!fir.type<{{.*}}>>) -> !fir.ref<none>
 ! CFG:      %[[BOX_NONE:.*]] = fir.convert %[[ARG0]] : (!fir.class<!fir.type<_QMselect_type_lower_testTp1{a:i32,b:i32}>>) -> !fir.box<none>
 ! CFG:      %[[CLASS_IS:.*]] = fir.call @_FortranAClassIs(%[[BOX_NONE]], %[[TDESC_P1_CONV]]) : (!fir.box<none>, !fir.ref<none>) -> i1
 ! CFG:      cf.cond_br %[[CLASS_IS]], ^[[P1_BLK:.*]], ^[[NOT_P1_BLK:.*]]
@@ -409,8 +409,8 @@ subroutine select_type7(a)
 
 ! CFG-LABEL: func.func @_QMselect_type_lower_testPselect_type7(
 ! CFG-SAME: %[[ARG0:.*]]: !fir.class<none> {fir.bindc_name = "a"}) {
-! CFG:      %[[TDESC_P4_ADDR:.*]] = fir.type_desc !fir.type<_QMselect_type_lower_testTp4
-! CFG:      %[[TDESC_P4_CONV:.*]] = fir.convert %[[TDESC_P4_ADDR]] : (!fir.tdesc{{.*}}>) -> !fir.ref<none>
+! CFG:      %[[TDESC_P4_ADDR:.*]] = fir.address_of(@_QMselect_type_lower_testE.dt.p4) : !fir.ref<!fir.type<{{.*}}>>
+! CFG:      %[[TDESC_P4_CONV:.*]] = fir.convert %[[TDESC_P4_ADDR]] : (!fir.ref<!fir.type<{{.*}}>>) -> !fir.ref<none>
 ! CFG:      %[[BOX_NONE:.*]] = fir.convert %[[ARG0]] : (!fir.class<none>) -> !fir.box<none>
 ! CFG:      %[[CLASS_IS_P4:.*]] = fir.call @_FortranAClassIs(%[[BOX_NONE]], %[[TDESC_P4_CONV]]) : (!fir.box<none>, !fir.ref<none>) -> i1
 ! CFG:      cf.cond_br %[[CLASS_IS_P4]], ^[[CLASS_IS_P4_BLK:.*]], ^[[CLASS_NOT_P4_BLK:.*]]
@@ -419,16 +419,16 @@ subroutine select_type7(a)
 ! CFG:    ^bb[[CLASS_IS_P1_BLK:[0-9]]]:
 ! CFG:      cf.br ^[[EXIT_SELECT_BLK:.*]]
 ! CFG:    ^bb[[CLASS_NOT_P2_BLK:[0-9]]]:
-! CFG:      %[[TDESC_P1_ADDR:.*]] = fir.type_desc !fir.type<_QMselect_type_lower_testTp1{a:i32,b:i32}>
-! CFG:      %[[TDESC_P1_CONV:.*]] = fir.convert %[[TDESC_P1_ADDR]] : (!fir.tdesc{{.*}}>) -> !fir.ref<none>
+! CFG:      %[[TDESC_P1_ADDR:.*]] = fir.address_of(@_QMselect_type_lower_testE.dt.p1) : !fir.ref<!fir.type<{{.*}}>>
+! CFG:      %[[TDESC_P1_CONV:.*]] = fir.convert %[[TDESC_P1_ADDR]] : (!fir.ref<!fir.type<{{.*}}>>) -> !fir.ref<none>
 ! CFG:      %[[BOX_NONE:.*]] = fir.convert %[[ARG0]] : (!fir.class<none>) -> !fir.box<none>
 ! CFG:      %[[CLASS_IS_P1:.*]] = fir.call @_FortranAClassIs(%[[BOX_NONE]], %[[TDESC_P1_CONV]]) : (!fir.box<none>, !fir.ref<none>) -> i1
 ! CFG:      cf.cond_br %[[CLASS_IS_P1]], ^bb[[CLASS_IS_P1_BLK]], ^bb[[CLASS_NOT_P1_BLK]]
 ! CFG:    ^bb[[CLASS_IS_P2_BLK:[0-9]]]:
 ! CFG:      cf.br ^[[EXIT_SELECT_BLK]]
 ! CFG:    ^[[CLASS_NOT_P4_BLK]]:
-! CFG:      %[[TDESC_P2_ADDR:.*]] = fir.type_desc !fir.type<_QMselect_type_lower_testTp2
-! CFG:      %[[TDESC_P2_CONV:.*]] = fir.convert %[[TDESC_P2_ADDR]] : (!fir.tdesc{{.*}}>) -> !fir.ref<none>
+! CFG:      %[[TDESC_P2_ADDR:.*]] = fir.address_of(@_QMselect_type_lower_testE.dt.p2) : !fir.ref<!fir.type<{{.*}}>>
+! CFG:      %[[TDESC_P2_CONV:.*]] = fir.convert %[[TDESC_P2_ADDR]] : (!fir.ref<!fir.type<{{.*}}>>) -> !fir.ref<none>
 ! CFG:      %[[BOX_NONE:.*]] = fir.convert %[[ARG0]] : (!fir.class<none>) -> !fir.box<none>
 ! CFG:      %[[CLASS_IS_P2:.*]] = fir.call @_FortranAClassIs(%[[BOX_NONE]], %[[TDESC_P2_CONV]]) : (!fir.box<none>, !fir.ref<none>) -> i1
 ! CFG:      cf.cond_br %[[CLASS_IS_P2]], ^bb[[CLASS_IS_P2_BLK]], ^bb[[CLASS_NOT_P2_BLK]]


        


More information about the llvm-branch-commits mailing list