Skip to content

Commit fab0c75

Browse files
Merge branch 'copy-inout-dev' into copy-inout-review
2 parents 905c315 + d9452c3 commit fab0c75

File tree

7 files changed

+119
-12
lines changed

7 files changed

+119
-12
lines changed

flang/include/flang/Evaluate/call.h

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -248,11 +248,7 @@ class ProcedureRef {
248248
ProcedureRef(ProcedureDesignator &&p, ActualArguments &&a,
249249
bool hasAlternateReturns = false)
250250
: proc_{std::move(p)}, arguments_{std::move(a)},
251-
hasAlternateReturns_{hasAlternateReturns} {
252-
// Gathers necessary information to determine the need for copy-in and
253-
// copy-out
254-
DetermineCopyInOut();
255-
}
251+
hasAlternateReturns_{hasAlternateReturns} {}
256252
~ProcedureRef();
257253
static void Deleter(ProcedureRef *);
258254

@@ -289,9 +285,9 @@ class ProcedureRef {
289285
bool operator==(const ProcedureRef &) const;
290286
llvm::raw_ostream &AsFortran(llvm::raw_ostream &) const;
291287

292-
protected:
293288
void DetermineCopyInOut();
294289

290+
protected:
295291
ProcedureDesignator proc_;
296292
ActualArguments arguments_;
297293
Chevrons chevrons_;

flang/include/flang/Evaluate/check-expression.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,9 @@ std::optional<bool> IsContiguous(const A &, FoldingContext &,
118118
extern template std::optional<bool> IsContiguous(const Expr<SomeType> &,
119119
FoldingContext &, bool namedConstantSectionsAreContiguous,
120120
bool firstDimensionStride1);
121+
extern template std::optional<bool> IsContiguous(const ActualArgument &,
122+
FoldingContext &, bool namedConstantSectionsAreContiguous,
123+
bool firstDimensionStride1);
121124
extern template std::optional<bool> IsContiguous(const ArrayRef &,
122125
FoldingContext &, bool namedConstantSectionsAreContiguous,
123126
bool firstDimensionStride1);

flang/include/flang/Evaluate/tools.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1123,6 +1123,7 @@ extern template semantics::UnorderedSymbolSet CollectCudaSymbols(
11231123

11241124
// Predicate: does a variable contain a vector-valued subscript (not a triplet)?
11251125
bool HasVectorSubscript(const Expr<SomeType> &);
1126+
bool HasVectorSubscript(const ActualArgument &);
11261127

11271128
// Predicate: does an expression contain constant?
11281129
bool HasConstant(const Expr<SomeType> &);

flang/lib/Evaluate/call.cpp

Lines changed: 95 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -248,19 +248,108 @@ ProcedureRef::~ProcedureRef() {}
248248

249249
void ProcedureRef::Deleter(ProcedureRef *p) { delete p; }
250250

251+
// We don't know the dummy argument info (e.g., procedure with implicit
252+
// interface
253+
static void DetermineCopyInOutArgument(
254+
const characteristics::Procedure &procInfo, ActualArgument &actual,
255+
semantics::SemanticsContext &sc) {
256+
if (actual.isAlternateReturn()) {
257+
return;
258+
}
259+
if (!evaluate::IsVariable(actual)) {
260+
// Actual argument expressions that aren’t variables are copy-in, but
261+
// not copy-out.
262+
actual.set_mayNeedCopyIn();
263+
} else if (!IsSimplyContiguous(actual, sc.foldingContext())) {
264+
// Actual arguments that are variables are copy-in when non-contiguous.
265+
// They are copy-out when don't have vector subscripts
266+
actual.set_mayNeedCopyIn();
267+
if (!HasVectorSubscript(actual)) {
268+
actual.set_mayNeedCopyOut();
269+
}
270+
} else if (ExtractCoarrayRef(actual)) {
271+
// Coindexed actual args need copy-in and copy-out
272+
actual.set_mayNeedCopyIn();
273+
actual.set_mayNeedCopyOut();
274+
}
275+
}
276+
277+
static void DetermineCopyInOutArgument(
278+
const characteristics::Procedure &procInfo, ActualArgument &actual,
279+
characteristics::DummyArgument &dummy, semantics::SemanticsContext &sc) {
280+
assert(procInfo.HasExplicitInterface() && "expect explicit interface proc");
281+
if (actual.isAlternateReturn()) {
282+
return;
283+
}
284+
// TODO
285+
}
286+
251287
void ProcedureRef::DetermineCopyInOut() {
252-
if (!proc().GetSymbol()) {
288+
if (!proc_.GetSymbol()) {
253289
return;
254290
}
255291
// Get folding context of the call site owner
256-
FoldingContext &fc{proc_.GetSymbol()->owner().context().foldingContext()};
257-
auto procInfo{characteristics::Procedure::Characterize(
258-
proc_, fc, /*emitError=*/true)};
292+
semantics::SemanticsContext &sc{proc_.GetSymbol()->owner().context()};
293+
FoldingContext &fc{sc.foldingContext()};
294+
auto procInfo{
295+
characteristics::Procedure::Characterize(proc_, fc, /*emitError=*/true)};
259296
if (!procInfo) {
260297
return;
261298
}
262-
// TODO: at this point have dummy arguments as procInfo->dummyArguments
263-
// and have actual arguments via arguments_
299+
if (!procInfo->HasExplicitInterface()) {
300+
for (auto &actual : arguments_) {
301+
if (!actual) {
302+
continue;
303+
}
304+
DetermineCopyInOutArgument(*procInfo, *actual, sc);
305+
}
306+
return;
307+
}
308+
// Don't change anything about actual or dummy arguments, except for
309+
// computing copy-in/copy-out information. If detect something wrong with
310+
// the arguments, stop processing and let semantic analysis generate the
311+
// error messages.
312+
size_t index{0};
313+
std::set<std::string> processedKeywords;
314+
bool seenKeyword{false};
315+
for (auto &actual : arguments_) {
316+
if (!actual) {
317+
continue;
318+
}
319+
if (index >= procInfo->dummyArguments.size()) {
320+
// More actual arguments than dummy arguments. Semantic analysis will
321+
// deal with the error.
322+
return;
323+
}
324+
if (actual->keyword()) {
325+
seenKeyword = true;
326+
auto actualName = actual->keyword()->ToString();
327+
if (processedKeywords.find(actualName) != processedKeywords.end()) {
328+
// Actual arguments with duplicate keywords. Semantic analysis will
329+
// deal with the error.
330+
return;
331+
} else {
332+
processedKeywords.insert(actualName);
333+
if (auto it = std::find_if(procInfo->dummyArguments.begin(),
334+
procInfo->dummyArguments.end(),
335+
[&](const characteristics::DummyArgument &dummy) {
336+
return dummy.name == actualName;
337+
});
338+
it != procInfo->dummyArguments.end()) {
339+
DetermineCopyInOutArgument(*procInfo, *actual, *it, sc);
340+
}
341+
}
342+
} else if (seenKeyword) {
343+
// Non-keyword actual argument after have seen at least one keyword
344+
// actual argument. Semantic analysis will deal with the error.
345+
return;
346+
} else {
347+
// Positional argument processing
348+
DetermineCopyInOutArgument(
349+
*procInfo, *actual, procInfo->dummyArguments[index], sc);
350+
}
351+
++index;
352+
}
264353
}
265354

266355
} // namespace Fortran::evaluate

flang/lib/Evaluate/check-expression.cpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1198,9 +1198,21 @@ std::optional<bool> IsContiguous(const A &x, FoldingContext &context,
11981198
}
11991199
}
12001200

1201+
std::optional<bool> IsContiguous(const ActualArgument &actual,
1202+
FoldingContext &fc, bool namedConstantSectionsAreContiguous,
1203+
bool firstDimensionStride1) {
1204+
auto *expr{actual.UnwrapExpr()};
1205+
return expr &&
1206+
IsContiguous(
1207+
*expr, fc, namedConstantSectionsAreContiguous, firstDimensionStride1);
1208+
}
1209+
12011210
template std::optional<bool> IsContiguous(const Expr<SomeType> &,
12021211
FoldingContext &, bool namedConstantSectionsAreContiguous,
12031212
bool firstDimensionStride1);
1213+
template std::optional<bool> IsContiguous(const ActualArgument &,
1214+
FoldingContext &, bool namedConstantSectionsAreContiguous,
1215+
bool firstDimensionStride1);
12041216
template std::optional<bool> IsContiguous(const ArrayRef &, FoldingContext &,
12051217
bool namedConstantSectionsAreContiguous, bool firstDimensionStride1);
12061218
template std::optional<bool> IsContiguous(const Substring &, FoldingContext &,

flang/lib/Evaluate/tools.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1203,6 +1203,11 @@ bool HasVectorSubscript(const Expr<SomeType> &expr) {
12031203
return HasVectorSubscriptHelper{}(expr);
12041204
}
12051205

1206+
bool HasVectorSubscript(const ActualArgument &actual) {
1207+
auto expr = actual.UnwrapExpr();
1208+
return expr && HasVectorSubscript(*expr);
1209+
}
1210+
12061211
// HasConstant()
12071212
struct HasConstantHelper : public AnyTraverse<HasConstantHelper, bool,
12081213
/*TraverseAssocEntityDetails=*/false> {

flang/lib/Semantics/expression.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3455,6 +3455,7 @@ void ExpressionAnalyzer::Analyze(const parser::CallStmt &callStmt) {
34553455
HasAlternateReturns(callee->arguments)},
34563456
ProcedureRef::Deleter);
34573457
DEREF(callStmt.typedCall.get()).set_chevrons(std::move(*chevrons));
3458+
DEREF(callStmt.typedCall.get()).DetermineCopyInOut();
34583459
return;
34593460
}
34603461
}

0 commit comments

Comments
 (0)