Skip to content

Commit 05f38df

Browse files
committed
address feedback
1 parent c7f0750 commit 05f38df

File tree

7 files changed

+150
-69
lines changed

7 files changed

+150
-69
lines changed

flang/include/flang/Evaluate/tools.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
#define FORTRAN_EVALUATE_TOOLS_H_
1111

1212
#include "traverse.h"
13+
#include "flang/Common/enum-set.h"
1314
#include "flang/Common/idioms.h"
1415
#include "flang/Common/template.h"
1516
#include "flang/Common/unwrap.h"
@@ -1397,6 +1398,8 @@ enum class Operator {
13971398
True,
13981399
};
13991400

1401+
using OperatorSet = common::EnumSet<Operator, 32>;
1402+
14001403
std::string ToString(Operator op);
14011404

14021405
template <typename... Ts, int Kind>
@@ -1509,6 +1512,11 @@ Operator OperationCode(const evaluate::ProcedureDesignator &proc);
15091512
std::pair<operation::Operator, std::vector<Expr<SomeType>>>
15101513
GetTopLevelOperation(const Expr<SomeType> &expr);
15111514

1515+
// Return information about the top-level operation (ignoring parentheses, and
1516+
// resizing converts)
1517+
std::pair<operation::Operator, std::vector<Expr<SomeType>>>
1518+
GetTopLevelOperationIgnoreResizing(const Expr<SomeType> &expr);
1519+
15121520
// Check if expr is same as x, or a sequence of Convert operations on x.
15131521
bool IsSameOrConvertOf(const Expr<SomeType> &expr, const Expr<SomeType> &x);
15141522

flang/lib/Evaluate/tools.cpp

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1809,10 +1809,15 @@ operation::Operator operation::OperationCode(const ProcedureDesignator &proc) {
18091809
}
18101810

18111811
std::pair<operation::Operator, std::vector<Expr<SomeType>>>
1812-
GetTopLevelOperation(const Expr<SomeType> &expr) {
1812+
GetTopLevelOperationIgnoreResizing(const Expr<SomeType> &expr) {
18131813
return operation::ArgumentExtractor<true>{}(expr);
18141814
}
18151815

1816+
std::pair<operation::Operator, std::vector<Expr<SomeType>>>
1817+
GetTopLevelOperation(const Expr<SomeType> &expr) {
1818+
return operation::ArgumentExtractor<false>{}(expr);
1819+
}
1820+
18161821
namespace operation {
18171822
struct ConvertCollector
18181823
: public Traverse<ConvertCollector,
@@ -1946,14 +1951,12 @@ struct VariableFinder : public evaluate::AnyTraverse<VariableFinder> {
19461951

19471952
template <typename T>
19481953
bool operator()(const evaluate::Designator<T> &x) const {
1949-
auto copy{x};
1950-
return evaluate::AsGenericExpr(std::move(copy)) == var;
1954+
return evaluate::AsGenericExpr(common::Clone(x)) == var;
19511955
}
19521956

19531957
template <typename T>
19541958
bool operator()(const evaluate::FunctionRef<T> &x) const {
1955-
auto copy{x};
1956-
return evaluate::AsGenericExpr(std::move(copy)) == var;
1959+
return evaluate::AsGenericExpr(common::Clone(x)) == var;
19571960
}
19581961

19591962
private:

flang/lib/Lower/OpenMP/Atomic.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -607,7 +607,7 @@ genAtomicUpdate(lower::AbstractConverter &converter,
607607
// This must exist by now.
608608
semantics::SomeExpr rhs = assign.rhs;
609609
semantics::SomeExpr input = *evaluate::GetConvertInput(rhs);
610-
auto [opcode, args] = evaluate::GetTopLevelOperation(input);
610+
auto [opcode, args] = evaluate::GetTopLevelOperationIgnoreResizing(input);
611611
assert(!args.empty() && "Update operation without arguments");
612612

613613
// Pass args as an argument to avoid capturing a structured binding.
@@ -625,7 +625,8 @@ genAtomicUpdate(lower::AbstractConverter &converter,
625625
// operations with exactly two (non-optional) arguments.
626626
rhs = genReducedMinMax(rhs, atomArg, args);
627627
input = *evaluate::GetConvertInput(rhs);
628-
std::tie(opcode, args) = evaluate::GetTopLevelOperation(input);
628+
std::tie(opcode, args) =
629+
evaluate::GetTopLevelOperationIgnoreResizing(input);
629630
atomArg = nullptr; // No longer valid.
630631
}
631632
for (auto &arg : args) {

flang/lib/Semantics/check-acc-structure.cpp

Lines changed: 37 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -14,12 +14,8 @@
1414
#include "flang/Semantics/type.h"
1515
#include "flang/Support/Fortran.h"
1616
#include "llvm/Support/AtomicOrdering.h"
17-
#include "llvm/Support/raw_ostream.h"
18-
#include <optional>
1917

20-
// TODO: Move the parts that I am reusing from openmp-utils.h to
21-
// evaluate/tools.h
22-
#include "openmp-utils.h"
18+
#include <optional>
2319

2420
#define CHECK_SIMPLE_CLAUSE(X, Y) \
2521
void AccStructureChecker::Enter(const parser::AccClause::X &) { \
@@ -354,7 +350,7 @@ void AccStructureChecker::Leave(const parser::OpenACCAtomicConstruct &x) {
354350
}
355351

356352
void AccStructureChecker::CheckAtomicStmt(
357-
const parser::AssignmentStmt &assign, std::string &construct) {
353+
const parser::AssignmentStmt &assign, const std::string &construct) {
358354
const auto &var{std::get<parser::Variable>(assign.t)};
359355
const auto &expr{std::get<parser::Expr>(assign.t)};
360356
const auto *rhs{GetExpr(context_, expr)};
@@ -376,38 +372,30 @@ void AccStructureChecker::CheckAtomicStmt(
376372
}
377373
}
378374

375+
static constexpr evaluate::operation::OperatorSet validAccAtomicUpdateOperators{
376+
evaluate::operation::Operator::Add, evaluate::operation::Operator::Mul,
377+
evaluate::operation::Operator::Sub, evaluate::operation::Operator::Div,
378+
evaluate::operation::Operator::And, evaluate::operation::Operator::Or,
379+
evaluate::operation::Operator::Eqv, evaluate::operation::Operator::Neqv,
380+
evaluate::operation::Operator::Max, evaluate::operation::Operator::Min};
381+
379382
static bool IsValidAtomicUpdateOperation(
380383
const evaluate::operation::Operator &op) {
381-
switch (op) {
382-
case evaluate::operation::Operator::Add:
383-
case evaluate::operation::Operator::Mul:
384-
case evaluate::operation::Operator::Sub:
385-
case evaluate::operation::Operator::Div:
386-
case evaluate::operation::Operator::And:
387-
case evaluate::operation::Operator::Or:
388-
case evaluate::operation::Operator::Eqv:
389-
case evaluate::operation::Operator::Neqv:
390-
// 2909 intrinsic-procedure name is one of max, min, iand, ior, or ieor.
391-
case evaluate::operation::Operator::Max:
392-
case evaluate::operation::Operator::Min:
393-
// Currently all get mapped to And, Or, and Neqv
394-
// case evaluate::operation::Operator::Iand:
395-
// case evaluate::operation::Operator::Ior:
396-
// case evaluate::operation::Operator::Ieor:
397-
return true;
398-
case evaluate::operation::Operator::Convert:
399-
case evaluate::operation::Operator::Identity:
400-
default:
401-
return false;
402-
}
384+
return validAccAtomicUpdateOperators.test(op);
403385
}
404386

387+
// Couldn't reproduce this behavior with evaluate::UnwrapConvertedExpr which
388+
// is similar but only works within a single type category.
405389
static SomeExpr GetExprModuloConversion(const SomeExpr &expr) {
406390
const auto [op, args]{evaluate::GetTopLevelOperation(expr)};
407391
// Check: if it is a conversion then it must have at least one argument.
408-
CHECK((op != evaluate::operation::Operator::Convert || args.size() >= 1) &&
392+
CHECK(((op != evaluate::operation::Operator::Convert &&
393+
op != evaluate::operation::Operator::Resize) ||
394+
args.size() >= 1) &&
409395
"Invalid conversion operation");
410-
if (op == evaluate::operation::Operator::Convert && args.size() == 1) {
396+
if ((op == evaluate::operation::Operator::Convert ||
397+
op == evaluate::operation::Operator::Resize) &&
398+
args.size() >= 1) {
411399
return args[0];
412400
}
413401
return expr;
@@ -416,17 +404,15 @@ static SomeExpr GetExprModuloConversion(const SomeExpr &expr) {
416404
void AccStructureChecker::CheckAtomicUpdateStmt(
417405
const parser::AssignmentStmt &assign, const SomeExpr &updateVar,
418406
const SomeExpr *captureVar) {
419-
static std::string construct{"update"};
420-
CheckAtomicStmt(assign, construct);
407+
CheckAtomicStmt(assign, "update");
421408
const auto &expr{std::get<parser::Expr>(assign.t)};
422409
const auto *rhs{GetExpr(context_, expr)};
423410
if (rhs) {
424411
const auto [op, args]{
425412
evaluate::GetTopLevelOperation(GetExprModuloConversion(*rhs))};
426413
if (!IsValidAtomicUpdateOperation(op)) {
427414
context_.Say(expr.source,
428-
"Invalid atomic update operation, can only use: *, +, -, *, /, and, or, eqv, neqv, max, min, iand, ior, ieor"_err_en_US,
429-
construct);
415+
"Invalid atomic update operation, can only use: *, +, -, *, /, and, or, eqv, neqv, max, min, iand, ior, ieor"_err_en_US);
430416
} else {
431417
bool foundUpdateVar{false};
432418
for (const auto &arg : args) {
@@ -458,8 +444,7 @@ void AccStructureChecker::CheckAtomicUpdateStmt(
458444
void AccStructureChecker::CheckAtomicWriteStmt(
459445
const parser::AssignmentStmt &assign, const SomeExpr &updateVar,
460446
const SomeExpr *captureVar) {
461-
static std::string construct{"write"};
462-
CheckAtomicStmt(assign, construct);
447+
CheckAtomicStmt(assign, "write");
463448
const auto &expr{std::get<parser::Expr>(assign.t)};
464449
const auto *rhs{GetExpr(context_, expr)};
465450
if (rhs) {
@@ -474,15 +459,16 @@ void AccStructureChecker::CheckAtomicWriteStmt(
474459
void AccStructureChecker::CheckAtomicCaptureStmt(
475460
const parser::AssignmentStmt &assign, const SomeExpr *updateVar,
476461
const SomeExpr &captureVar) {
477-
static std::string construct{"capture"};
478-
CheckAtomicStmt(assign, construct);
462+
CheckAtomicStmt(assign, "capture");
479463
}
480464

481465
void AccStructureChecker::Enter(const parser::AccAtomicCapture &capture) {
482-
const Fortran::parser::AssignmentStmt &stmt1 =
483-
std::get<Fortran::parser::AccAtomicCapture::Stmt1>(capture.t).v.statement;
484-
const Fortran::parser::AssignmentStmt &stmt2 =
485-
std::get<Fortran::parser::AccAtomicCapture::Stmt2>(capture.t).v.statement;
466+
const Fortran::parser::AssignmentStmt &stmt1{
467+
std::get<Fortran::parser::AccAtomicCapture::Stmt1>(capture.t)
468+
.v.statement};
469+
const Fortran::parser::AssignmentStmt &stmt2{
470+
std::get<Fortran::parser::AccAtomicCapture::Stmt2>(capture.t)
471+
.v.statement};
486472
const auto &var1{std::get<parser::Variable>(stmt1.t)};
487473
const auto &var2{std::get<parser::Variable>(stmt2.t)};
488474
const auto *lhs1{GetExpr(context_, var1)};
@@ -507,7 +493,7 @@ void AccStructureChecker::Enter(const parser::AccAtomicCapture &capture) {
507493
bool stmt2CapturesLhs1{*lhs1 == GetExprModuloConversion(*rhs2)};
508494
if (stmt1CapturesLhs2 && !stmt2CapturesLhs1) {
509495
if (*lhs2 == GetExprModuloConversion(*rhs2)) {
510-
// a = b; b = b; Doesn't fit the spec;
496+
// a = b; b = b: Doesn't fit the spec.
511497
context_.Say(std::get<parser::Verbatim>(capture.t).source,
512498
"The assignments in this atomic capture construct do not update a variable and capture either its initial or final value"_err_en_US);
513499
// TODO: Add attatchment that a = b seems to be a capture,
@@ -533,14 +519,14 @@ void AccStructureChecker::Enter(const parser::AccAtomicCapture &capture) {
533519
// Add attatchment that a = a is not considered an update,
534520
// but b = a seems to be a capture.
535521
} else {
536-
// Take x = <expr>; v = x; as update; capture
522+
// Take x = <expr>; v = x: as update; capture
537523
const auto &updateVar{*lhs1};
538524
const auto &captureVar{*lhs2};
539525
CheckAtomicUpdateStmt(stmt1, updateVar, &captureVar);
540526
CheckAtomicCaptureStmt(stmt2, &updateVar, captureVar);
541527
}
542528
} else if (stmt1CapturesLhs2 && stmt2CapturesLhs1) {
543-
// x1 = x2; x2 = x1; Doesn't fit the spec;
529+
// x1 = x2; x2 = x1; Doesn't fit the spec.
544530
context_.Say(std::get<parser::Verbatim>(capture.t).source,
545531
"The assignments in this atomic capture construct do not update a variable and capture either its initial or final value"_err_en_US);
546532
// TODO: Add attatchment that both assignments seem to be captures.
@@ -550,40 +536,33 @@ void AccStructureChecker::Enter(const parser::AccAtomicCapture &capture) {
550536
"The assignments in this atomic capture construct do not update a variable and capture either its initial or final value"_err_en_US);
551537
// TODO: Add attatchment that neither assignment seems to be a capture.
552538
}
553-
return;
554539
}
555540

556541
void AccStructureChecker::Enter(const parser::AccAtomicUpdate &x) {
557542
const auto &assign{
558543
std::get<parser::Statement<parser::AssignmentStmt>>(x.t).statement};
559544
const auto &var{std::get<parser::Variable>(assign.t)};
560-
const auto *updateVar{GetExpr(context_, var)};
561-
if (!updateVar) {
562-
return;
545+
if (const auto *updateVar{GetExpr(context_, var)}) {
546+
CheckAtomicUpdateStmt(assign, *updateVar, /*captureVar=*/nullptr);
563547
}
564-
CheckAtomicUpdateStmt(assign, *updateVar, nullptr);
565548
}
566549

567550
void AccStructureChecker::Enter(const parser::AccAtomicWrite &x) {
568551
const auto &assign{
569552
std::get<parser::Statement<parser::AssignmentStmt>>(x.t).statement};
570553
const auto &var{std::get<parser::Variable>(assign.t)};
571-
const auto *updateVar{GetExpr(context_, var)};
572-
if (!updateVar) {
573-
return;
554+
if (const auto *updateVar{GetExpr(context_, var)}) {
555+
CheckAtomicWriteStmt(assign, *updateVar, /*captureVar=*/nullptr);
574556
}
575-
CheckAtomicWriteStmt(assign, *updateVar, nullptr);
576557
}
577558

578559
void AccStructureChecker::Enter(const parser::AccAtomicRead &x) {
579560
const auto &assign{
580561
std::get<parser::Statement<parser::AssignmentStmt>>(x.t).statement};
581562
const auto &var{std::get<parser::Variable>(assign.t)};
582-
const auto *captureVar{GetExpr(context_, var)};
583-
if (!captureVar) {
584-
return;
563+
if (const auto *captureVar{GetExpr(context_, var)}) {
564+
CheckAtomicCaptureStmt(assign, /*updateVar=*/nullptr, *captureVar);
585565
}
586-
CheckAtomicCaptureStmt(assign, nullptr, *captureVar);
587566
}
588567

589568
void AccStructureChecker::Enter(const parser::OpenACCCacheConstruct &x) {

flang/lib/Semantics/check-acc-structure.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ class AccStructureChecker
8484

8585
private:
8686
void CheckAtomicStmt(
87-
const parser::AssignmentStmt &assign, std::string &construct);
87+
const parser::AssignmentStmt &assign, const std::string &construct);
8888
void CheckAtomicUpdateStmt(const parser::AssignmentStmt &assign,
8989
const SomeExpr &updateVar, const SomeExpr *captureVar);
9090
void CheckAtomicCaptureStmt(const parser::AssignmentStmt &assign,

flang/lib/Semantics/check-omp-atomic.cpp

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -197,7 +197,8 @@ static std::pair<parser::CharBlock, parser::CharBlock> SplitAssignmentSource(
197197
}
198198

199199
static bool IsCheckForAssociated(const SomeExpr &cond) {
200-
return GetTopLevelOperation(cond).first == operation::Operator::Associated;
200+
return GetTopLevelOperationIgnoreResizing(cond).first ==
201+
operation::Operator::Associated;
201202
}
202203

203204
static bool IsMaybeAtomicWrite(const evaluate::Assignment &assign) {
@@ -607,7 +608,7 @@ void OmpStructureChecker::CheckAtomicUpdateAssignment(
607608
std::pair<operation::Operator, std::vector<SomeExpr>> top{
608609
operation::Operator::Unknown, {}};
609610
if (auto &&maybeInput{GetConvertInput(update.rhs)}) {
610-
top = GetTopLevelOperation(*maybeInput);
611+
top = GetTopLevelOperationIgnoreResizing(*maybeInput);
611612
}
612613
switch (top.first) {
613614
case operation::Operator::Add:
@@ -715,7 +716,7 @@ void OmpStructureChecker::CheckAtomicConditionalUpdateAssignment(
715716

716717
CheckAtomicVariable(atom, alsrc);
717718

718-
auto top{GetTopLevelOperation(cond)};
719+
auto top{GetTopLevelOperationIgnoreResizing(cond)};
719720
// Missing arguments to operations would have been diagnosed by now.
720721

721722
switch (top.first) {

0 commit comments

Comments
 (0)