Skip to content

Commit 080bcac

Browse files
committed
[fix 1164] Make symbolIsGlobal the single point
Previously, the code was handling the promotion of local to global in non re-entrant program outside of symbolIsGlobal. This prevented the promotion to work on equivalence members, and also caused latter usage of symbolIsGlobal to be potentially incorrect. Move all the re-entrant logic in it, and use the symbol scope to deduce the re-entrant aspects instead of using a boolean that has to be threaded and is not always accessible after the PFT analysis. Remove isRecursive since it has no use anymore. There is a slight change in one of the namelist change because the namelist code used symbolIsGlobal and previously thought some symbol promoted to globals were in local memory.
1 parent 51bc26f commit 080bcac

File tree

4 files changed

+51
-38
lines changed

4 files changed

+51
-38
lines changed

flang/include/flang/Lower/PFTBuilder.h

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -596,17 +596,6 @@ struct FunctionLikeUnit : public ProgramUnit {
596596
FunctionLikeUnit(FunctionLikeUnit &&) = default;
597597
FunctionLikeUnit(const FunctionLikeUnit &) = delete;
598598

599-
/// Return true iff this function like unit is Fortran recursive (actually
600-
/// meaning it's reentrant).
601-
bool isRecursive() const {
602-
if (isMainProgram())
603-
return false;
604-
const auto &sym = getSubprogramSymbol();
605-
return sym.attrs().test(semantics::Attr::RECURSIVE) ||
606-
(!sym.attrs().test(semantics::Attr::NON_RECURSIVE) &&
607-
defaultRecursiveFunctionSetting());
608-
}
609-
610599
std::vector<Variable> getOrderedSymbolTable() { return varList[0]; }
611600

612601
bool isMainProgram() const {

flang/lib/Lower/PFTBuilder.cpp

Lines changed: 41 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1223,11 +1223,37 @@ bool Fortran::lower::definedInCommonBlock(const semantics::Symbol &sym) {
12231223
return semantics::FindCommonBlockContaining(sym);
12241224
}
12251225

1226+
static bool isReEntrant(const Fortran::semantics::Scope &scope) {
1227+
if (scope.kind() == Fortran::semantics::Scope::Kind::MainProgram)
1228+
return false;
1229+
if (scope.kind() == Fortran::semantics::Scope::Kind::Subprogram) {
1230+
const auto *sym = scope.symbol();
1231+
assert(sym && "Subprogram scope must have a symbol");
1232+
return sym->attrs().test(semantics::Attr::RECURSIVE) ||
1233+
(!sym->attrs().test(semantics::Attr::NON_RECURSIVE) &&
1234+
Fortran::lower::defaultRecursiveFunctionSetting());
1235+
}
1236+
if (scope.kind() == Fortran::semantics::Scope::Kind::Module)
1237+
return false;
1238+
return true;
1239+
}
1240+
12261241
/// Is the symbol `sym` a global?
12271242
bool Fortran::lower::symbolIsGlobal(const semantics::Symbol &sym) {
1228-
if (const auto *details = sym.detailsIf<semantics::ObjectEntityDetails>())
1243+
if (const auto *details = sym.detailsIf<semantics::ObjectEntityDetails>()) {
12291244
if (details->init())
12301245
return true;
1246+
if (!isReEntrant(sym.owner())) {
1247+
// Turn array and character of non re-entrant programs (like the main
1248+
// program) into global memory.
1249+
if (const auto *symTy = sym.GetType())
1250+
if (symTy->category() == semantics::DeclTypeSpec::Character)
1251+
if (auto e = symTy->characterTypeSpec().length().GetExplicit())
1252+
return true;
1253+
if (!details->shape().empty() || !details->coshape().empty())
1254+
return true;
1255+
}
1256+
}
12311257
return semantics::IsSaved(sym) || lower::definedInCommonBlock(sym);
12321258
}
12331259

@@ -1238,8 +1264,8 @@ namespace {
12381264
/// symbol table, which is sorted by name.
12391265
struct SymbolDependenceDepth {
12401266
explicit SymbolDependenceDepth(
1241-
std::vector<std::vector<lower::pft::Variable>> &vars, bool reentrant)
1242-
: vars{vars}, reentrant{reentrant} {}
1267+
std::vector<std::vector<lower::pft::Variable>> &vars)
1268+
: vars{vars} {}
12431269

12441270
void analyzeAliasesInCurrentScope(const semantics::Scope &scope) {
12451271
// FIXME: When this function is called on the scope of an internal
@@ -1348,7 +1374,6 @@ struct SymbolDependenceDepth {
13481374
llvm_unreachable("not yet implemented - derived type analysis");
13491375

13501376
// Symbol must be something lowering will have to allocate.
1351-
bool global = lower::symbolIsGlobal(sym);
13521377
int depth = 0;
13531378
const auto *symTy = sym.GetType();
13541379
assert(symTy && "symbol must have a type");
@@ -1361,12 +1386,9 @@ struct SymbolDependenceDepth {
13611386
if (const auto *details = sym.detailsIf<semantics::ObjectEntityDetails>()) {
13621387
// check CHARACTER's length
13631388
if (symTy->category() == semantics::DeclTypeSpec::Character)
1364-
if (auto e = symTy->characterTypeSpec().length().GetExplicit()) {
1365-
// turn variable into a global if this unit is not reentrant
1366-
global = global || !reentrant;
1389+
if (auto e = symTy->characterTypeSpec().length().GetExplicit())
13671390
for (const auto &s : evaluate::CollectSymbols(*e))
13681391
depth = std::max(analyze(s) + 1, depth);
1369-
}
13701392

13711393
auto doExplicit = [&](const auto &bound) {
13721394
if (bound.isExplicit()) {
@@ -1376,15 +1398,11 @@ struct SymbolDependenceDepth {
13761398
}
13771399
};
13781400
// handle any symbols in array bound declarations
1379-
if (!details->shape().empty())
1380-
global = global || !reentrant;
13811401
for (const auto &subs : details->shape()) {
13821402
doExplicit(subs.lbound());
13831403
doExplicit(subs.ubound());
13841404
}
13851405
// handle any symbols in coarray bound declarations
1386-
if (!details->coshape().empty())
1387-
global = global || !reentrant;
13881406
for (const auto &subs : details->coshape()) {
13891407
doExplicit(subs.lbound());
13901408
doExplicit(subs.ubound());
@@ -1395,6 +1413,7 @@ struct SymbolDependenceDepth {
13951413
depth = std::max(analyze(s) + 1, depth);
13961414
}
13971415
adjustSize(depth + 1);
1416+
auto global = lower::symbolIsGlobal(sym);
13981417
vars[depth].emplace_back(sym, global, depth);
13991418
if (semantics::IsAllocatable(sym))
14001419
vars[depth].back().setHeapAlloc();
@@ -1479,15 +1498,13 @@ struct SymbolDependenceDepth {
14791498
/// Set of Scope that have been analyzed for aliases.
14801499
llvm::SmallSet<const semantics::Scope *, 4> analyzedScopes;
14811500
std::vector<Fortran::lower::pft::Variable::AggregateStore> stores;
1482-
bool reentrant;
14831501
};
14841502
} // namespace
14851503

14861504
static void processSymbolTable(
14871505
const semantics::Scope &scope,
1488-
std::vector<std::vector<Fortran::lower::pft::Variable>> &varList,
1489-
bool reentrant) {
1490-
SymbolDependenceDepth sdd{varList, reentrant};
1506+
std::vector<std::vector<Fortran::lower::pft::Variable>> &varList) {
1507+
SymbolDependenceDepth sdd{varList};
14911508
sdd.analyzeAliasesInCurrentScope(scope);
14921509
for (const auto &iter : scope)
14931510
sdd.analyze(iter.second.get());
@@ -1510,12 +1527,12 @@ Fortran::lower::pft::FunctionLikeUnit::FunctionLikeUnit(
15101527
beginStmt = FunctionStatement(programStmt.value());
15111528
auto symbol = getSymbol(*beginStmt);
15121529
entryPointList[0].first = symbol;
1513-
processSymbolTable(*symbol->scope(), varList, isRecursive());
1530+
processSymbolTable(*symbol->scope(), varList);
15141531
} else {
15151532
processSymbolTable(
15161533
semanticsContext.FindScope(
15171534
std::get<parser::Statement<parser::EndProgramStmt>>(func.t).source),
1518-
varList, isRecursive());
1535+
varList);
15191536
}
15201537
}
15211538

@@ -1527,7 +1544,7 @@ Fortran::lower::pft::FunctionLikeUnit::FunctionLikeUnit(
15271544
endStmt{getFunctionStmt<parser::EndFunctionStmt>(func)} {
15281545
auto symbol = getSymbol(*beginStmt);
15291546
entryPointList[0].first = symbol;
1530-
processSymbolTable(*symbol->scope(), varList, isRecursive());
1547+
processSymbolTable(*symbol->scope(), varList);
15311548
}
15321549

15331550
Fortran::lower::pft::FunctionLikeUnit::FunctionLikeUnit(
@@ -1538,7 +1555,7 @@ Fortran::lower::pft::FunctionLikeUnit::FunctionLikeUnit(
15381555
endStmt{getFunctionStmt<parser::EndSubroutineStmt>(func)} {
15391556
auto symbol = getSymbol(*beginStmt);
15401557
entryPointList[0].first = symbol;
1541-
processSymbolTable(*symbol->scope(), varList, isRecursive());
1558+
processSymbolTable(*symbol->scope(), varList);
15421559
}
15431560

15441561
Fortran::lower::pft::FunctionLikeUnit::FunctionLikeUnit(
@@ -1549,7 +1566,7 @@ Fortran::lower::pft::FunctionLikeUnit::FunctionLikeUnit(
15491566
endStmt{getFunctionStmt<parser::EndMpSubprogramStmt>(func)} {
15501567
auto symbol = getSymbol(*beginStmt);
15511568
entryPointList[0].first = symbol;
1552-
processSymbolTable(*symbol->scope(), varList, isRecursive());
1569+
processSymbolTable(*symbol->scope(), varList);
15531570
}
15541571

15551572
Fortran::lower::HostAssociations &
@@ -1583,7 +1600,7 @@ Fortran::lower::pft::ModuleLikeUnit::ModuleLikeUnit(
15831600
: ProgramUnit{m, parent}, beginStmt{getModuleStmt<parser::ModuleStmt>(m)},
15841601
endStmt{getModuleStmt<parser::EndModuleStmt>(m)} {
15851602
auto symbol = getSymbol(beginStmt);
1586-
processSymbolTable(*symbol->scope(), varList, /*reentrant=*/false);
1603+
processSymbolTable(*symbol->scope(), varList);
15871604
}
15881605

15891606
Fortran::lower::pft::ModuleLikeUnit::ModuleLikeUnit(
@@ -1592,7 +1609,7 @@ Fortran::lower::pft::ModuleLikeUnit::ModuleLikeUnit(
15921609
m)},
15931610
endStmt{getModuleStmt<parser::EndSubmoduleStmt>(m)} {
15941611
auto symbol = getSymbol(beginStmt);
1595-
processSymbolTable(*symbol->scope(), varList, /*reentrant=*/false);
1612+
processSymbolTable(*symbol->scope(), varList);
15961613
}
15971614

15981615
parser::CharBlock
@@ -1686,8 +1703,7 @@ std::vector<Fortran::lower::pft::Variable>
16861703
Fortran::lower::pft::buildFuncResultDependencyList(
16871704
const Fortran::semantics::Symbol &symbol) {
16881705
std::vector<std::vector<pft::Variable>> variableList;
1689-
// reentrant does not matter, no locals involved for results ().
1690-
SymbolDependenceDepth sdd(variableList, /*reentrant=*/true);
1706+
SymbolDependenceDepth sdd(variableList);
16911707
sdd.analyzeAliasesInCurrentScope(symbol.owner());
16921708
sdd.analyze(symbol);
16931709
sdd.finalize();

flang/test/Lower/equivalence-1.f90

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,13 @@ SUBROUTINE s3
5454
! CHECK: %{{.*}} = fir.load %[[v2loc]] : !fir.ref<f32>
5555
PRINT *, r(9)
5656
END SUBROUTINE s3
57+
58+
! test that equivalence in main program containing arrays are placed in global memory.
59+
! CHECK: fir.global internal @_QEa : !fir.array<400000000xi8>
60+
integer :: a, b(100000000)
61+
equivalence (a, b)
62+
b(1) = 42
63+
print *, a
5764

5865
CALL s1
5966
CALL s2

flang/test/Lower/namelist.f90

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ program p
1717
! CHECK: fir.insert_value
1818
! CHECK: fir.address_of
1919
! CHECK: fir.insert_value
20-
! CHECK: fir.embox [[ccc]]
20+
! CHECK: fir.address_of(@_QEccc.desc) : !fir.ref<!fir.box<!fir.ptr<!fir.array<4x!fir.char<1,3>>>>>
2121
! CHECK: fir.insert_value
2222
! CHECK: fir.alloca tuple<!fir.ref<i8>, i64, !fir.ref<!fir.array<2xtuple<!fir.ref<i8>, !fir.ref<!fir.box<none>>>>>>
2323
! CHECK: fir.address_of
@@ -37,7 +37,7 @@ program p
3737
! CHECK: fir.insert_value
3838
! CHECK: fir.address_of
3939
! CHECK: fir.insert_value
40-
! CHECK: fir.embox [[ccc]]
40+
! CHECK: fir.address_of(@_QEccc.desc) : !fir.ref<!fir.box<!fir.ptr<!fir.array<4x!fir.char<1,3>>>>>
4141
! CHECK: fir.insert_value
4242
! CHECK: fir.alloca tuple<!fir.ref<i8>, i64, !fir.ref<!fir.array<2xtuple<!fir.ref<i8>, !fir.ref<!fir.box<none>>>>>>
4343
! CHECK: fir.address_of
@@ -72,3 +72,4 @@ subroutine sss
7272
! CHECK-DAG: fir.global linkonce @_QQcl.6A6A6A00 constant : !fir.char<1,4>
7373
! CHECK-DAG: fir.global linkonce @_QQcl.63636300 constant : !fir.char<1,4>
7474
! CHECK-DAG: fir.global linkonce @_QQcl.6E6E6E00 constant : !fir.char<1,4>
75+
! CHECK-DAG: fir.global linkonce @_QEccc.desc constant : !fir.box<!fir.ptr<!fir.array<4x!fir.char<1,3>>>>

0 commit comments

Comments
 (0)