Skip to content

[flang][debug] Add support for common blocks. #112398

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 5 commits into from
Jan 28, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 7 additions & 5 deletions flang/lib/Optimizer/CodeGen/CodeGen.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2996,11 +2996,13 @@ struct GlobalOpConversion : public fir::FIROpConversion<fir::GlobalOp> {
llvm::SmallVector<mlir::Attribute> dbgExprs;

if (auto fusedLoc = mlir::dyn_cast<mlir::FusedLoc>(global.getLoc())) {
if (auto gvAttr =
mlir::dyn_cast_or_null<mlir::LLVM::DIGlobalVariableAttr>(
fusedLoc.getMetadata())) {
dbgExprs.push_back(mlir::LLVM::DIGlobalVariableExpressionAttr::get(
global.getContext(), gvAttr, mlir::LLVM::DIExpressionAttr()));
if (auto gvExprAttr = mlir::dyn_cast_if_present<mlir::ArrayAttr>(
fusedLoc.getMetadata())) {
for (auto attr : gvExprAttr.getAsRange<mlir::Attribute>())
Copy link
Contributor

Choose a reason for hiding this comment

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

Should there be a if(auto dbgAttr = mlir::dyn_cast<DIGlobalVariableExpressionAttr>(attr)) to ensure these is indeed debug info?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Although only DIGlobalVariableExpressionAttr are added in ArrayAttr at the moment but I guess it is better to have this check to be safe. I will add it before merge. Please also see my comments here on why this interface is relatively less type strict.

Copy link
Contributor

Choose a reason for hiding this comment

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

Thanks for the change and link.

if (auto dbgAttr =
mlir::dyn_cast<mlir::LLVM::DIGlobalVariableExpressionAttr>(
attr))
dbgExprs.push_back(dbgAttr);
}
}

Expand Down
114 changes: 113 additions & 1 deletion flang/lib/Optimizer/Transforms/AddDebugInfo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -59,10 +59,19 @@ class AddDebugInfoPass : public fir::impl::AddDebugInfoBase<AddDebugInfoPass> {

private:
llvm::StringMap<mlir::LLVM::DIModuleAttr> moduleMap;
llvm::StringMap<mlir::LLVM::DICommonBlockAttr> commonBlockMap;
// List of GlobalVariableExpressionAttr that are attached to a given global
// that represents the storage for common block.
llvm::DenseMap<fir::GlobalOp, llvm::SmallVector<mlir::Attribute>>
globalToGlobalExprsMap;

mlir::LLVM::DIModuleAttr getOrCreateModuleAttr(
const std::string &name, mlir::LLVM::DIFileAttr fileAttr,
mlir::LLVM::DIScopeAttr scope, unsigned line, bool decl);
mlir::LLVM::DICommonBlockAttr
getOrCreateCommonBlockAttr(llvm::StringRef name,
mlir::LLVM::DIFileAttr fileAttr,
mlir::LLVM::DIScopeAttr scope, unsigned line);

void handleGlobalOp(fir::GlobalOp glocalOp, mlir::LLVM::DIFileAttr fileAttr,
mlir::LLVM::DIScopeAttr scope,
Expand All @@ -73,6 +82,12 @@ class AddDebugInfoPass : public fir::impl::AddDebugInfoBase<AddDebugInfoPass> {
mlir::LLVM::DICompileUnitAttr cuAttr,
fir::DebugTypeGenerator &typeGen,
mlir::SymbolTable *symbolTable);
bool createCommonBlockGlobal(fir::cg::XDeclareOp declOp,
const std::string &name,
mlir::LLVM::DIFileAttr fileAttr,
mlir::LLVM::DIScopeAttr scopeAttr,
fir::DebugTypeGenerator &typeGen,
mlir::SymbolTable *symbolTable);
std::optional<mlir::LLVM::DIModuleAttr>
getModuleAttrFromGlobalOp(fir::GlobalOp globalOp,
mlir::LLVM::DIFileAttr fileAttr,
Expand All @@ -90,6 +105,67 @@ bool debugInfoIsAlreadySet(mlir::Location loc) {

} // namespace

bool AddDebugInfoPass::createCommonBlockGlobal(
fir::cg::XDeclareOp declOp, const std::string &name,
mlir::LLVM::DIFileAttr fileAttr, mlir::LLVM::DIScopeAttr scopeAttr,
fir::DebugTypeGenerator &typeGen, mlir::SymbolTable *symbolTable) {
mlir::MLIRContext *context = &getContext();
mlir::OpBuilder builder(context);
std::optional<std::int64_t> optint;
mlir::Operation *op = declOp.getMemref().getDefiningOp();

if (auto conOp = mlir::dyn_cast_if_present<fir::ConvertOp>(op))
op = conOp.getValue().getDefiningOp();

if (auto cordOp = mlir::dyn_cast_if_present<fir::CoordinateOp>(op)) {
optint = fir::getIntIfConstant(cordOp.getOperand(1));
if (!optint)
return false;
op = cordOp.getRef().getDefiningOp();
if (auto conOp2 = mlir::dyn_cast_if_present<fir::ConvertOp>(op))
op = conOp2.getValue().getDefiningOp();

if (auto addrOfOp = mlir::dyn_cast_if_present<fir::AddrOfOp>(op)) {
mlir::SymbolRefAttr sym = addrOfOp.getSymbol();
if (auto global =
symbolTable->lookup<fir::GlobalOp>(sym.getRootReference())) {

unsigned line = getLineFromLoc(global.getLoc());
llvm::StringRef commonName(sym.getRootReference());
// FIXME: We are trying to extract the name of the common block from the
// name of the global. As part of mangling, GetCommonBlockObjectName can
// add a trailing _ in the name of that global. The demangle function
// does not seem to handle such cases. So the following hack is used to
// remove the trailing '_'.
if (commonName != Fortran::common::blankCommonObjectName &&
commonName.back() == '_')
commonName = commonName.drop_back();
mlir::LLVM::DICommonBlockAttr commonBlock =
getOrCreateCommonBlockAttr(commonName, fileAttr, scopeAttr, line);
mlir::LLVM::DITypeAttr diType = typeGen.convertType(
fir::unwrapRefType(declOp.getType()), fileAttr, scopeAttr, declOp);
line = getLineFromLoc(declOp.getLoc());
auto gvAttr = mlir::LLVM::DIGlobalVariableAttr::get(
context, commonBlock, mlir::StringAttr::get(context, name),
declOp.getUniqName(), fileAttr, line, diType,
/*isLocalToUnit*/ false, /*isDefinition*/ true, /* alignInBits*/ 0);
mlir::LLVM::DIExpressionAttr expr;
if (*optint != 0) {
llvm::SmallVector<mlir::LLVM::DIExpressionElemAttr> ops;
ops.push_back(mlir::LLVM::DIExpressionElemAttr::get(
context, llvm::dwarf::DW_OP_plus_uconst, *optint));
expr = mlir::LLVM::DIExpressionAttr::get(context, ops);
}
auto dbgExpr = mlir::LLVM::DIGlobalVariableExpressionAttr::get(
global.getContext(), gvAttr, expr);
globalToGlobalExprsMap[global].push_back(dbgExpr);
return true;
}
}
}
return false;
}

void AddDebugInfoPass::handleDeclareOp(fir::cg::XDeclareOp declOp,
mlir::LLVM::DIFileAttr fileAttr,
mlir::LLVM::DIScopeAttr scopeAttr,
Expand All @@ -101,6 +177,11 @@ void AddDebugInfoPass::handleDeclareOp(fir::cg::XDeclareOp declOp,

if (result.first != fir::NameUniquer::NameKind::VARIABLE)
return;

if (createCommonBlockGlobal(declOp, result.second.name, fileAttr, scopeAttr,
typeGen, symbolTable))
return;

// If this DeclareOp actually represents a global then treat it as such.
if (auto global = symbolTable->lookup<fir::GlobalOp>(declOp.getUniqName())) {
handleGlobalOp(global, fileAttr, scopeAttr, typeGen, symbolTable, declOp);
Expand Down Expand Up @@ -136,6 +217,22 @@ void AddDebugInfoPass::handleDeclareOp(fir::cg::XDeclareOp declOp,
declOp->setLoc(builder.getFusedLoc({declOp->getLoc()}, localVarAttr));
}

mlir::LLVM::DICommonBlockAttr AddDebugInfoPass::getOrCreateCommonBlockAttr(
llvm::StringRef name, mlir::LLVM::DIFileAttr fileAttr,
mlir::LLVM::DIScopeAttr scope, unsigned line) {
mlir::MLIRContext *context = &getContext();
mlir::LLVM::DICommonBlockAttr cbAttr;
if (auto iter{commonBlockMap.find(name)}; iter != commonBlockMap.end()) {
cbAttr = iter->getValue();
} else {
cbAttr = mlir::LLVM::DICommonBlockAttr::get(
context, scope, nullptr, mlir::StringAttr::get(context, name), fileAttr,
line);
commonBlockMap[name] = cbAttr;
}
return cbAttr;
}

// The `module` does not have a first class representation in the `FIR`. We
// extract information about it from the name of the identifiers and keep a
// map to avoid duplication.
Expand Down Expand Up @@ -227,7 +324,10 @@ void AddDebugInfoPass::handleGlobalOp(fir::GlobalOp globalOp,
mlir::StringAttr::get(context, globalOp.getName()), fileAttr, line,
diType, /*isLocalToUnit*/ false,
/*isDefinition*/ globalOp.isInitialized(), /* alignInBits*/ 0);
globalOp->setLoc(builder.getFusedLoc({globalOp->getLoc()}, gvAttr));
auto dbgExpr = mlir::LLVM::DIGlobalVariableExpressionAttr::get(
globalOp.getContext(), gvAttr, nullptr);
auto arrayAttr = mlir::ArrayAttr::get(context, {dbgExpr});
globalOp->setLoc(builder.getFusedLoc({globalOp.getLoc()}, arrayAttr));
}

void AddDebugInfoPass::handleFuncOp(mlir::func::FuncOp funcOp,
Expand Down Expand Up @@ -409,6 +509,11 @@ void AddDebugInfoPass::handleFuncOp(mlir::func::FuncOp funcOp,
if (&funcOp.front() == declOp->getBlock())
handleDeclareOp(declOp, fileAttr, spAttr, typeGen, symbolTable);
});
// commonBlockMap ensures that we don't create multiple DICommonBlockAttr of
// the same name in one function. But it is ok (rather required) to create
// them in different functions if common block of the same name has been used
// there.
commonBlockMap.clear();
}

void AddDebugInfoPass::runOnOperation() {
Expand Down Expand Up @@ -461,6 +566,13 @@ void AddDebugInfoPass::runOnOperation() {
module.walk([&](mlir::func::FuncOp funcOp) {
handleFuncOp(funcOp, fileAttr, cuAttr, typeGen, &symbolTable);
});
mlir::OpBuilder builder(context);
// We have processed all function. Attach common block variables to the
// global that represent the storage.
for (auto [global, exprs] : globalToGlobalExprsMap) {
auto arrayAttr = mlir::ArrayAttr::get(context, exprs);
global->setLoc(builder.getFusedLoc({global.getLoc()}, arrayAttr));
}
// Process any global which was not processed through DeclareOp.
if (debugLevel == mlir::LLVM::DIEmissionKind::Full) {
// Process 'GlobalOp' only if full debug info is requested.
Expand Down
138 changes: 138 additions & 0 deletions flang/test/Integration/debug-common-block-1.f90
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
! RUN: %flang_fc1 -emit-llvm -debug-info-kind=standalone %s -o - | FileCheck %s

subroutine f1
real(kind=4) :: x, y, xa, ya
common // x, y
common /a/ xa, ya
x = 1.1
y = 2.2
xa = 3.3
ya = 4.4
print *, x, y, xa, ya
end subroutine
! CHECK-DAG: ![[XF1:[0-9]+]] = {{.*}}!DIGlobalVariable(name: "x", linkageName: "_QFf1Ex", scope: ![[CBF1:[0-9]+]], file: !5, line: [[@LINE-9]], type: ![[REAL:[0-9]+]]{{.*}})
! CHECK-DAG: ![[EXPXF1:[0-9]+]] = !DIGlobalVariableExpression(var: ![[XF1]], expr: !DIExpression())
! CHECK-DAG: ![[YF1:[0-9]+]] = {{.*}}!DIGlobalVariable(name: "y", linkageName: "_QFf1Ey", scope: ![[CBF1]], file: !{{[0-9]+}}, line: [[@LINE-11]], type: ![[REAL]]{{.*}})
! CHECK-DAG: ![[EXPYF1:[0-9]+]] = !DIGlobalVariableExpression(var: ![[YF1]], expr: !DIExpression(DW_OP_plus_uconst, 4))
! CHECK-DAG: ![[XAF1:[0-9]+]] = {{.*}}!DIGlobalVariable(name: "xa", linkageName: "_QFf1Exa", scope: ![[CBAF1:[0-9]+]], file: !{{[0-9]+}}, line: [[@LINE-13]], type: ![[REAL]]{{.*}})
! CHECK-DAG: ![[EXPXAF1:[0-9]+]] = !DIGlobalVariableExpression(var: ![[XAF1]], expr: !DIExpression())
! CHECK-DAG: ![[YAF1:[0-9]+]] = {{.*}}!DIGlobalVariable(name: "ya", linkageName: "_QFf1Eya", scope: ![[CBAF1]], file: !{{[0-9]+}}, line: [[@LINE-15]], type: ![[REAL]]{{.*}})
! CHECK-DAG: ![[EXPYAF1:[0-9]+]] = !DIGlobalVariableExpression(var: ![[YAF1]], expr: !DIExpression(DW_OP_plus_uconst, 4))


subroutine f2
real(kind=4) :: x, y, z, xa, ya, za
common // x, y, z
common /a/ xa, ya, za
print *, x, y, z, xa, ya, za
end subroutine
! CHECK-DAG: ![[XF2:[0-9]+]] = {{.*}}!DIGlobalVariable(name: "x", linkageName: "_QFf2Ex", scope: ![[CBF2:[0-9]+]], file: !{{[0-9]+}}, line: [[@LINE-5]], type: ![[REAL]]{{.*}})
! CHECK-DAG: ![[EXPXF2:[0-9]+]] = !DIGlobalVariableExpression(var: ![[XF2]], expr: !DIExpression())
! CHECK-DAG: ![[YF2:[0-9]+]] = {{.*}}!DIGlobalVariable(name: "y", linkageName: "_QFf2Ey", scope: ![[CBF2]], file: !{{[0-9]+}}, line: [[@LINE-7]], type: ![[REAL]]{{.*}})
! CHECK-DAG: ![[EXPYF2:[0-9]+]] = !DIGlobalVariableExpression(var: ![[YF2]], expr: !DIExpression(DW_OP_plus_uconst, 4))
! CHECK-DAG: ![[ZF2:[0-9]+]] = {{.*}}!DIGlobalVariable(name: "z", linkageName: "_QFf2Ez", scope: ![[CBF2]], file: !{{[0-9]+}}, line: [[@LINE-9]], type: ![[REAL]]{{.*}})
! CHECK-DAG: ![[EXPZF2:[0-9]+]] = !DIGlobalVariableExpression(var: ![[ZF2]], expr: !DIExpression(DW_OP_plus_uconst, 8))
! CHECK-DAG: ![[XAF2:[0-9]+]] = {{.*}}!DIGlobalVariable(name: "xa", linkageName: "_QFf2Exa", scope: ![[CBAF2:[0-9]+]], file: !{{[0-9]+}}, line: [[@LINE-11]], type: ![[REAL]]{{.*}})
! CHECK-DAG: ![[EXPXAF2:[0-9]+]] = !DIGlobalVariableExpression(var: ![[XAF2]], expr: !DIExpression())
! CHECK-DAG: ![[YAF2:[0-9]+]] = {{.*}}!DIGlobalVariable(name: "ya", linkageName: "_QFf2Eya", scope: ![[CBAF2]], file: !{{[0-9]+}}, line: [[@LINE-13]], type: ![[REAL]]{{.*}})
! CHECK-DAG: ![[EXPYAF2:[0-9]+]] = !DIGlobalVariableExpression(var: ![[YAF2]], expr: !DIExpression(DW_OP_plus_uconst, 4))
! CHECK-DAG: ![[ZAF2:[0-9]+]] = {{.*}}!DIGlobalVariable(name: "za", linkageName: "_QFf2Eza", scope: ![[CBAF2]], file: !{{[0-9]+}}, line: [[@LINE-15]], type: ![[REAL]]{{.*}})
! CHECK-DAG: ![[EXPZAF2:[0-9]+]] = !DIGlobalVariableExpression(var: ![[ZAF2]], expr: !DIExpression(DW_OP_plus_uconst, 8))

subroutine f3
integer(kind=4) :: x = 42, xa = 42
common // x
common /a/ xa
print *, x
print *, xa
end subroutine
! CHECK-DAG: ![[XF3:[0-9]+]] = {{.*}}!DIGlobalVariable(name: "x", linkageName: "_QFf3Ex", scope: ![[CBF3:[0-9]+]], file: !{{[0-9]+}}, line: [[@LINE-6]], type: ![[INT:[0-9]+]]{{.*}})
! CHECK-DAG: ![[EXPXF3:[0-9]+]] = !DIGlobalVariableExpression(var: ![[XF3]], expr: !DIExpression())
! CHECK-DAG: ![[XAF3:[0-9]+]] = {{.*}}!DIGlobalVariable(name: "xa", linkageName: "_QFf3Exa", scope: ![[CBAF3:[0-9]+]], file: !{{[0-9]+}}, line: [[@LINE-8]], type: ![[INT]]{{.*}})
! CHECK-DAG: ![[EXPXAF3:[0-9]+]] = !DIGlobalVariableExpression(var: ![[XAF3]], expr: !DIExpression())

program test
real(kind=4) :: v1, v2, v3, va1, va2, va3
common // v1, v2, v3
common /a/ va1, va2, va3
call f1()
call f2()
call f3()
print *, v1, va1, va3
END
! CHECK-DAG: ![[V1:[0-9]+]] = {{.*}}!DIGlobalVariable(name: "v1", linkageName: "_QFEv1", scope: ![[CBM:[0-9]+]], file: !{{[0-9]+}}, line: [[@LINE-8]], type: ![[REAL]]{{.*}})
! CHECK-DAG: ![[EXPV1:[0-9]+]] = !DIGlobalVariableExpression(var: ![[V1]], expr: !DIExpression())
! CHECK-DAG: ![[V2:[0-9]+]] = {{.*}}!DIGlobalVariable(name: "v2", linkageName: "_QFEv2", scope: ![[CBM]], file: !{{[0-9]+}}, line: [[@LINE-10]], type: ![[REAL]]{{.*}})
! CHECK-DAG: ![[EXPV2:[0-9]+]] = !DIGlobalVariableExpression(var: ![[V2]], expr: !DIExpression(DW_OP_plus_uconst, 4))
! CHECK-DAG: ![[V3:[0-9]+]] = {{.*}}!DIGlobalVariable(name: "v3", linkageName: "_QFEv3", scope: ![[CBM]], file: !{{[0-9]+}}, line: [[@LINE-12]], type: ![[REAL]]{{.*}})
! CHECK-DAG: ![[EXPV3:[0-9]+]] = !DIGlobalVariableExpression(var: ![[V3]], expr: !DIExpression(DW_OP_plus_uconst, 8))
! CHECK-DAG: ![[VA1:[0-9]+]] = {{.*}}!DIGlobalVariable(name: "va1", linkageName: "_QFEva1", scope: ![[CBAM:[0-9]+]], file: !{{[0-9]+}}, line: [[@LINE-14]], type: ![[REAL]]{{.*}})
! CHECK-DAG: ![[EXPVA1:[0-9]+]] = !DIGlobalVariableExpression(var: ![[VA1]], expr: !DIExpression())
! CHECK-DAG: ![[VA2:[0-9]+]] = {{.*}}!DIGlobalVariable(name: "va2", linkageName: "_QFEva2", scope: ![[CBAM]], file: !{{[0-9]+}}, line: [[@LINE-16]], type: ![[REAL]]{{.*}})
! CHECK-DAG: ![[EXPVA2:[0-9]+]] = !DIGlobalVariableExpression(var: ![[VA2]], expr: !DIExpression(DW_OP_plus_uconst, 4))
! CHECK-DAG: ![[VA3:[0-9]+]] = {{.*}}!DIGlobalVariable(name: "va3", linkageName: "_QFEva3", scope: ![[CBAM]], file: !{{[0-9]+}}, line: [[@LINE-18]], type: ![[REAL]]{{.*}})
! CHECK-DAG: ![[EXPVA3:[0-9]+]] = !DIGlobalVariableExpression(var: ![[VA3]], expr: !DIExpression(DW_OP_plus_uconst, 8))


! CHECK-DAG: ![[REAL]] = !DIBasicType(name: "real", size: 32, encoding: DW_ATE_float)
! CHECK-DAG: ![[INT]] = !DIBasicType(name: "integer", size: 32, encoding: DW_ATE_signed)

! CHECK-DAG: ![[F1:[0-9]+]] = {{.*}}!DISubprogram(name: "f1"{{.*}})
! CHECK-DAG: ![[CBF1]] = !DICommonBlock(scope: ![[F1]], declaration: null, name: "__BLNK__"{{.*}})
! CHECK-DAG: ![[CBAF1]] = !DICommonBlock(scope: ![[F1]], declaration: null, name: "a"{{.*}})

! CHECK-DAG: ![[F2:[0-9]+]] = {{.*}}!DISubprogram(name: "f2"{{.*}})
! CHECK-DAG: ![[CBF2]] = !DICommonBlock(scope: ![[F2]], declaration: null, name: "__BLNK__"{{.*}})
! CHECK-DAG: ![[CBAF2]] = !DICommonBlock(scope: ![[F2]], declaration: null, name: "a"{{.*}})

! CHECK-DAG: ![[F3:[0-9]+]] = {{.*}}!DISubprogram(name: "f3"{{.*}})
! CHECK-DAG: ![[CBF3]] = !DICommonBlock(scope: ![[F3]], declaration: null, name: "__BLNK__"{{.*}})
! CHECK-DAG: ![[CBAF3]] = !DICommonBlock(scope: ![[F3]], declaration: null, name: "a"{{.*}})

! CHECK-DAG: ![[MAIN:[0-9]+]] = {{.*}}!DISubprogram(name: "test"{{.*}})
! CHECK-DAG: ![[CBM]] = !DICommonBlock(scope: ![[MAIN]], declaration: null, name: "__BLNK__"{{.*}})
! CHECK-DAG: ![[CBAM]] = !DICommonBlock(scope: ![[MAIN]], declaration: null, name: "a"{{.*}})

! Using CHECK-DAG-SAME so that we are not dependent on order of variable in these lists.
! CHECK-DAG: @__BLNK__ = global{{.*}}
! CHECK-DAG-SAME: !dbg ![[EXPXF1]]
! CHECK-DAG-SAME: !dbg ![[EXPYF1]]
! CHECK-DAG-SAME: !dbg ![[EXPXF2]]
! CHECK-DAG-SAME: !dbg ![[EXPYF2]]
! CHECK-DAG-SAME: !dbg ![[EXPZF2]]
! CHECK-DAG-SAME: !dbg ![[EXPXF3]]
! CHECK-DAG-SAME: !dbg ![[EXPV1]]
! CHECK-DAG-SAME: !dbg ![[EXPV2]]
! CHECK-DAG-SAME: !dbg ![[EXPV3]]

! CHECK-DAG: @a_ = global{{.*}}
! CHECK-DAG-SAME: !dbg ![[EXPXAF1]]
! CHECK-DAG-SAME: !dbg ![[EXPYAF1]]
! CHECK-DAG-SAME: !dbg ![[EXPXAF2]]
! CHECK-DAG-SAME: !dbg ![[EXPYAF2]]
! CHECK-DAG-SAME: !dbg ![[EXPZAF2]]
! CHECK-DAG-SAME: !dbg ![[EXPXAF3]]
! CHECK-DAG-SAME: !dbg ![[EXPVA1]]
! CHECK-DAG-SAME: !dbg ![[EXPVA2]]
! CHECK-DAG-SAME: !dbg ![[EXPVA3]]

! CHECK-DAG: !DICompileUnit({{.*}}, globals: ![[GLOBALS:[0-9]+]])
! CHECK-DAG: ![[GLOBALS]]
! CHECK-DAG-SAME: ![[EXPXF1]]
! CHECK-DAG-SAME: ![[EXPYF1]]
! CHECK-DAG-SAME: ![[EXPXAF1]]
! CHECK-DAG-SAME: ![[EXPYAF1]]
! CHECK-DAG-SAME: ![[EXPXF2]]
! CHECK-DAG-SAME: ![[EXPYF2]]
! CHECK-DAG-SAME: ![[EXPZF2]]
! CHECK-DAG-SAME: ![[EXPXAF2]]
! CHECK-DAG-SAME: ![[EXPYAF2]]
! CHECK-DAG-SAME: ![[EXPZAF2]]
! CHECK-DAG-SAME: ![[EXPXF3]]
! CHECK-DAG-SAME: ![[EXPXAF3]]
! CHECK-DAG-SAME: ![[EXPV1]]
! CHECK-DAG-SAME: ![[EXPV2]]
! CHECK-DAG-SAME: ![[EXPV3]]
! CHECK-DAG-SAME: ![[EXPVA1]]
! CHECK-DAG-SAME: ![[EXPVA2]]
! CHECK-DAG-SAME: ![[EXPVA3]]
Loading
Loading