148 changes: 67 additions & 81 deletions flang/lib/Lower/OpenMP/DataSharingProcessor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ namespace omp {

void DataSharingProcessor::processStep1(
mlir::omp::PrivateClauseOps *clauseOps,
llvm::SmallVectorImpl<const Fortran::semantics::Symbol *> *privateSyms) {
llvm::SmallVectorImpl<const semantics::Symbol *> *privateSyms) {
collectSymbolsForPrivatization();
collectDefaultSymbols();
collectImplicitSymbols();
Expand Down Expand Up @@ -57,14 +57,14 @@ void DataSharingProcessor::processStep2(mlir::Operation *op, bool isLoop) {
}

void DataSharingProcessor::insertDeallocs() {
for (const Fortran::semantics::Symbol *sym : privatizedSymbols)
if (Fortran::semantics::IsAllocatable(sym->GetUltimate())) {
for (const semantics::Symbol *sym : privatizedSymbols)
if (semantics::IsAllocatable(sym->GetUltimate())) {
if (!useDelayedPrivatization) {
converter.createHostAssociateVarCloneDealloc(*sym);
return;
}

Fortran::lower::SymbolBox hsb = converter.lookupOneLevelUpSymbol(*sym);
lower::SymbolBox hsb = converter.lookupOneLevelUpSymbol(*sym);
assert(hsb && "Host symbol box not found");
mlir::Type symType = hsb.getAddr().getType();
mlir::Location symLoc = hsb.getAddr().getLoc();
Expand All @@ -91,33 +91,32 @@ void DataSharingProcessor::insertDeallocs() {
}
}

void DataSharingProcessor::cloneSymbol(const Fortran::semantics::Symbol *sym) {
void DataSharingProcessor::cloneSymbol(const semantics::Symbol *sym) {
// Privatization for symbols which are pre-determined (like loop index
// variables) happen separately, for everything else privatize here.
if (sym->test(Fortran::semantics::Symbol::Flag::OmpPreDetermined))
if (sym->test(semantics::Symbol::Flag::OmpPreDetermined))
return;
bool success = converter.createHostAssociateVarClone(*sym);
(void)success;
assert(success && "Privatization failed due to existing binding");
}

void DataSharingProcessor::copyFirstPrivateSymbol(
const Fortran::semantics::Symbol *sym,
mlir::OpBuilder::InsertPoint *copyAssignIP) {
if (sym->test(Fortran::semantics::Symbol::Flag::OmpFirstPrivate))
const semantics::Symbol *sym, mlir::OpBuilder::InsertPoint *copyAssignIP) {
if (sym->test(semantics::Symbol::Flag::OmpFirstPrivate))
converter.copyHostAssociateVar(*sym, copyAssignIP);
}

void DataSharingProcessor::copyLastPrivateSymbol(
const Fortran::semantics::Symbol *sym,
const semantics::Symbol *sym,
[[maybe_unused]] mlir::OpBuilder::InsertPoint *lastPrivIP) {
if (sym->test(Fortran::semantics::Symbol::Flag::OmpLastPrivate))
if (sym->test(semantics::Symbol::Flag::OmpLastPrivate))
converter.copyHostAssociateVar(*sym, lastPrivIP);
}

void DataSharingProcessor::collectOmpObjectListSymbol(
const omp::ObjectList &objects,
llvm::SetVector<const Fortran::semantics::Symbol *> &symbolSet) {
llvm::SetVector<const semantics::Symbol *> &symbolSet) {
for (const omp::Object &object : objects)
symbolSet.insert(object.id());
}
Expand Down Expand Up @@ -150,9 +149,9 @@ bool DataSharingProcessor::needBarrier() {
// initialization of firstprivate variables and post-update of lastprivate
// variables.
// Emit implicit barrier for linear clause. Maybe on somewhere else.
for (const Fortran::semantics::Symbol *sym : privatizedSymbols) {
if (sym->test(Fortran::semantics::Symbol::Flag::OmpFirstPrivate) &&
sym->test(Fortran::semantics::Symbol::Flag::OmpLastPrivate))
for (const semantics::Symbol *sym : privatizedSymbols) {
if (sym->test(semantics::Symbol::Flag::OmpFirstPrivate) &&
sym->test(semantics::Symbol::Flag::OmpLastPrivate))
return true;
}
return false;
Expand Down Expand Up @@ -238,26 +237,26 @@ void DataSharingProcessor::insertLastPrivateCompare(mlir::Operation *op) {
}
}

static const Fortran::parser::CharBlock *
getSource(const Fortran::semantics::SemanticsContext &semaCtx,
const Fortran::lower::pft::Evaluation &eval) {
const Fortran::parser::CharBlock *source = nullptr;
static const parser::CharBlock *
getSource(const semantics::SemanticsContext &semaCtx,
const lower::pft::Evaluation &eval) {
const parser::CharBlock *source = nullptr;

auto ompConsVisit = [&](const Fortran::parser::OpenMPConstruct &x) {
std::visit(Fortran::common::visitors{
[&](const Fortran::parser::OpenMPSectionsConstruct &x) {
auto ompConsVisit = [&](const parser::OpenMPConstruct &x) {
std::visit(common::visitors{
[&](const parser::OpenMPSectionsConstruct &x) {
source = &std::get<0>(x.t).source;
},
[&](const Fortran::parser::OpenMPLoopConstruct &x) {
[&](const parser::OpenMPLoopConstruct &x) {
source = &std::get<0>(x.t).source;
},
[&](const Fortran::parser::OpenMPBlockConstruct &x) {
[&](const parser::OpenMPBlockConstruct &x) {
source = &std::get<0>(x.t).source;
},
[&](const Fortran::parser::OpenMPCriticalConstruct &x) {
[&](const parser::OpenMPCriticalConstruct &x) {
source = &std::get<0>(x.t).source;
},
[&](const Fortran::parser::OpenMPAtomicConstruct &x) {
[&](const parser::OpenMPAtomicConstruct &x) {
std::visit([&](const auto &x) { source = &x.source; },
x.u);
},
Expand All @@ -266,27 +265,20 @@ getSource(const Fortran::semantics::SemanticsContext &semaCtx,
x.u);
};

eval.visit(Fortran::common::visitors{
[&](const Fortran::parser::OpenMPConstruct &x) { ompConsVisit(x); },
[&](const Fortran::parser::OpenMPDeclarativeConstruct &x) {
source = &x.source;
},
[&](const Fortran::parser::OmpEndLoopDirective &x) {
source = &x.source;
},
eval.visit(common::visitors{
[&](const parser::OpenMPConstruct &x) { ompConsVisit(x); },
[&](const parser::OpenMPDeclarativeConstruct &x) { source = &x.source; },
[&](const parser::OmpEndLoopDirective &x) { source = &x.source; },
[&](const auto &x) {},
});

return source;
}

void DataSharingProcessor::collectSymbolsInNestedRegions(
Fortran::lower::pft::Evaluation &eval,
Fortran::semantics::Symbol::Flag flag,
llvm::SetVector<const Fortran::semantics::Symbol *>
&symbolsInNestedRegions) {
for (Fortran::lower::pft::Evaluation &nestedEval :
eval.getNestedEvaluations()) {
lower::pft::Evaluation &eval, semantics::Symbol::Flag flag,
llvm::SetVector<const semantics::Symbol *> &symbolsInNestedRegions) {
for (lower::pft::Evaluation &nestedEval : eval.getNestedEvaluations()) {
if (nestedEval.hasNestedEvaluations()) {
if (nestedEval.isConstruct())
// Recursively look for OpenMP constructs within `nestedEval`'s region
Expand All @@ -307,46 +299,45 @@ void DataSharingProcessor::collectSymbolsInNestedRegions(
// Later, in current context, all symbols in the set
// `defaultSymbols` - `symbolsInNestedRegions` will be privatized.
void DataSharingProcessor::collectSymbols(
Fortran::semantics::Symbol::Flag flag,
llvm::SetVector<const Fortran::semantics::Symbol *> &symbols) {
semantics::Symbol::Flag flag,
llvm::SetVector<const semantics::Symbol *> &symbols) {
// Collect all scopes associated with 'eval'.
llvm::SetVector<const Fortran::semantics::Scope *> clauseScopes;
std::function<void(const Fortran::semantics::Scope *)> collectScopes =
[&](const Fortran::semantics::Scope *scope) {
llvm::SetVector<const semantics::Scope *> clauseScopes;
std::function<void(const semantics::Scope *)> collectScopes =
[&](const semantics::Scope *scope) {
clauseScopes.insert(scope);
for (const Fortran::semantics::Scope &child : scope->children())
for (const semantics::Scope &child : scope->children())
collectScopes(&child);
};
const Fortran::parser::CharBlock *source =
const parser::CharBlock *source =
clauses.empty() ? getSource(semaCtx, eval) : &clauses.front().source;
const Fortran::semantics::Scope *curScope = nullptr;
const semantics::Scope *curScope = nullptr;
if (source && !source->empty()) {
curScope = &semaCtx.FindScope(*source);
collectScopes(curScope);
}
// Collect all symbols referenced in the evaluation being processed,
// that matches 'flag'.
llvm::SetVector<const Fortran::semantics::Symbol *> allSymbols;
llvm::SetVector<const semantics::Symbol *> allSymbols;
converter.collectSymbolSet(eval, allSymbols, flag,
/*collectSymbols=*/true,
/*collectHostAssociatedSymbols=*/true);
llvm::SetVector<const Fortran::semantics::Symbol *> symbolsInNestedRegions;
llvm::SetVector<const semantics::Symbol *> symbolsInNestedRegions;
collectSymbolsInNestedRegions(eval, flag, symbolsInNestedRegions);
// Filter-out symbols that must not be privatized.
bool collectImplicit = flag == Fortran::semantics::Symbol::Flag::OmpImplicit;
auto isPrivatizable = [](const Fortran::semantics::Symbol &sym) -> bool {
return !Fortran::semantics::IsProcedure(sym) &&
!sym.GetUltimate().has<Fortran::semantics::DerivedTypeDetails>() &&
!sym.GetUltimate().has<Fortran::semantics::NamelistDetails>() &&
!Fortran::semantics::IsImpliedDoIndex(sym.GetUltimate());
bool collectImplicit = flag == semantics::Symbol::Flag::OmpImplicit;
auto isPrivatizable = [](const semantics::Symbol &sym) -> bool {
return !semantics::IsProcedure(sym) &&
!sym.GetUltimate().has<semantics::DerivedTypeDetails>() &&
!sym.GetUltimate().has<semantics::NamelistDetails>() &&
!semantics::IsImpliedDoIndex(sym.GetUltimate());
};
for (const auto *sym : allSymbols) {
assert(curScope && "couldn't find current scope");
if (isPrivatizable(*sym) && !symbolsInNestedRegions.contains(sym) &&
!privatizedSymbols.contains(sym) &&
!sym->test(Fortran::semantics::Symbol::Flag::OmpPreDetermined) &&
(collectImplicit ||
!sym->test(Fortran::semantics::Symbol::Flag::OmpImplicit)) &&
!sym->test(semantics::Symbol::Flag::OmpPreDetermined) &&
(collectImplicit || !sym->test(semantics::Symbol::Flag::OmpImplicit)) &&
clauseScopes.contains(&sym->owner()))
symbols.insert(sym);
}
Expand All @@ -358,10 +349,9 @@ void DataSharingProcessor::collectDefaultSymbols() {
if (const auto *defaultClause =
std::get_if<omp::clause::Default>(&clause.u)) {
if (defaultClause->v == DataSharingAttribute::Private)
collectSymbols(Fortran::semantics::Symbol::Flag::OmpPrivate,
defaultSymbols);
collectSymbols(semantics::Symbol::Flag::OmpPrivate, defaultSymbols);
else if (defaultClause->v == DataSharingAttribute::Firstprivate)
collectSymbols(Fortran::semantics::Symbol::Flag::OmpFirstPrivate,
collectSymbols(semantics::Symbol::Flag::OmpFirstPrivate,
defaultSymbols);
}
}
Expand All @@ -370,16 +360,15 @@ void DataSharingProcessor::collectDefaultSymbols() {
void DataSharingProcessor::collectImplicitSymbols() {
// There will be no implicit symbols when a default clause is present.
if (defaultSymbols.empty())
collectSymbols(Fortran::semantics::Symbol::Flag::OmpImplicit,
implicitSymbols);
collectSymbols(semantics::Symbol::Flag::OmpImplicit, implicitSymbols);
}

void DataSharingProcessor::privatize(
mlir::omp::PrivateClauseOps *clauseOps,
llvm::SmallVectorImpl<const Fortran::semantics::Symbol *> *privateSyms) {
for (const Fortran::semantics::Symbol *sym : privatizedSymbols) {
llvm::SmallVectorImpl<const semantics::Symbol *> *privateSyms) {
for (const semantics::Symbol *sym : privatizedSymbols) {
if (const auto *commonDet =
sym->detailsIf<Fortran::semantics::CommonBlockDetails>()) {
sym->detailsIf<semantics::CommonBlockDetails>()) {
for (const auto &mem : commonDet->objects())
doPrivatize(&*mem, clauseOps, privateSyms);
} else
Expand All @@ -389,9 +378,9 @@ void DataSharingProcessor::privatize(

void DataSharingProcessor::copyLastPrivatize(mlir::Operation *op) {
insertLastPrivateCompare(op);
for (const Fortran::semantics::Symbol *sym : privatizedSymbols)
for (const semantics::Symbol *sym : privatizedSymbols)
if (const auto *commonDet =
sym->detailsIf<Fortran::semantics::CommonBlockDetails>()) {
sym->detailsIf<semantics::CommonBlockDetails>()) {
for (const auto &mem : commonDet->objects()) {
copyLastPrivateSymbol(&*mem, &lastPrivIP);
}
Expand All @@ -402,36 +391,34 @@ void DataSharingProcessor::copyLastPrivatize(mlir::Operation *op) {

void DataSharingProcessor::defaultPrivatize(
mlir::omp::PrivateClauseOps *clauseOps,
llvm::SmallVectorImpl<const Fortran::semantics::Symbol *> *privateSyms) {
for (const Fortran::semantics::Symbol *sym : defaultSymbols)
llvm::SmallVectorImpl<const semantics::Symbol *> *privateSyms) {
for (const semantics::Symbol *sym : defaultSymbols)
doPrivatize(sym, clauseOps, privateSyms);
}

void DataSharingProcessor::implicitPrivatize(
mlir::omp::PrivateClauseOps *clauseOps,
llvm::SmallVectorImpl<const Fortran::semantics::Symbol *> *privateSyms) {
for (const Fortran::semantics::Symbol *sym : implicitSymbols)
llvm::SmallVectorImpl<const semantics::Symbol *> *privateSyms) {
for (const semantics::Symbol *sym : implicitSymbols)
doPrivatize(sym, clauseOps, privateSyms);
}

void DataSharingProcessor::doPrivatize(
const Fortran::semantics::Symbol *sym,
mlir::omp::PrivateClauseOps *clauseOps,
llvm::SmallVectorImpl<const Fortran::semantics::Symbol *> *privateSyms) {
const semantics::Symbol *sym, mlir::omp::PrivateClauseOps *clauseOps,
llvm::SmallVectorImpl<const semantics::Symbol *> *privateSyms) {
if (!useDelayedPrivatization) {
cloneSymbol(sym);
copyFirstPrivateSymbol(sym);
return;
}

Fortran::lower::SymbolBox hsb = converter.lookupOneLevelUpSymbol(*sym);
lower::SymbolBox hsb = converter.lookupOneLevelUpSymbol(*sym);
assert(hsb && "Host symbol box not found");

mlir::Type symType = hsb.getAddr().getType();
mlir::Location symLoc = hsb.getAddr().getLoc();
std::string privatizerName = sym->name().ToString() + ".privatizer";
bool isFirstPrivate =
sym->test(Fortran::semantics::Symbol::Flag::OmpFirstPrivate);
bool isFirstPrivate = sym->test(semantics::Symbol::Flag::OmpFirstPrivate);

mlir::omp::PrivateClauseOp privatizerOp = [&]() {
auto moduleOp = firOpBuilder.getModule();
Expand Down Expand Up @@ -468,8 +455,7 @@ void DataSharingProcessor::doPrivatize(
hlfir::translateToExtendedValue(
symLoc, firOpBuilder, hlfir::Entity{allocRegion.getArgument(0)},
/*contiguousHint=*/
Fortran::evaluate::IsSimplyContiguous(
*sym, converter.getFoldingContext()))
evaluate::IsSimplyContiguous(*sym, converter.getFoldingContext()))
.first;

symTable->addSymbol(*sym, localExV);
Expand Down
66 changes: 31 additions & 35 deletions flang/lib/Lower/OpenMP/DataSharingProcessor.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,65 +37,61 @@ class DataSharingProcessor {
mlir::OpBuilder::InsertPoint insPt;
mlir::Value loopIV;
// Symbols in private, firstprivate, and/or lastprivate clauses.
llvm::SetVector<const Fortran::semantics::Symbol *> privatizedSymbols;
llvm::SetVector<const Fortran::semantics::Symbol *> defaultSymbols;
llvm::SetVector<const Fortran::semantics::Symbol *> implicitSymbols;
llvm::DenseMap<const Fortran::semantics::Symbol *, mlir::omp::PrivateClauseOp>
llvm::SetVector<const semantics::Symbol *> privatizedSymbols;
llvm::SetVector<const semantics::Symbol *> defaultSymbols;
llvm::SetVector<const semantics::Symbol *> implicitSymbols;
llvm::DenseMap<const semantics::Symbol *, mlir::omp::PrivateClauseOp>
symToPrivatizer;
Fortran::lower::AbstractConverter &converter;
Fortran::semantics::SemanticsContext &semaCtx;
lower::AbstractConverter &converter;
semantics::SemanticsContext &semaCtx;
fir::FirOpBuilder &firOpBuilder;
omp::List<omp::Clause> clauses;
Fortran::lower::pft::Evaluation &eval;
lower::pft::Evaluation &eval;
bool useDelayedPrivatization;
Fortran::lower::SymMap *symTable;
lower::SymMap *symTable;

bool needBarrier();
void
collectSymbols(Fortran::semantics::Symbol::Flag flag,
llvm::SetVector<const Fortran::semantics::Symbol *> &symbols);
void collectSymbols(semantics::Symbol::Flag flag,
llvm::SetVector<const semantics::Symbol *> &symbols);
void collectSymbolsInNestedRegions(
Fortran::lower::pft::Evaluation &eval,
Fortran::semantics::Symbol::Flag flag,
llvm::SetVector<const Fortran::semantics::Symbol *>
&symbolsInNestedRegions);
lower::pft::Evaluation &eval, semantics::Symbol::Flag flag,
llvm::SetVector<const semantics::Symbol *> &symbolsInNestedRegions);
void collectOmpObjectListSymbol(
const omp::ObjectList &objects,
llvm::SetVector<const Fortran::semantics::Symbol *> &symbolSet);
llvm::SetVector<const semantics::Symbol *> &symbolSet);
void collectSymbolsForPrivatization();
void insertBarrier();
void collectDefaultSymbols();
void collectImplicitSymbols();
void privatize(
mlir::omp::PrivateClauseOps *clauseOps,
llvm::SmallVectorImpl<const Fortran::semantics::Symbol *> *privateSyms);
void privatize(mlir::omp::PrivateClauseOps *clauseOps,
llvm::SmallVectorImpl<const semantics::Symbol *> *privateSyms);
void defaultPrivatize(
mlir::omp::PrivateClauseOps *clauseOps,
llvm::SmallVectorImpl<const Fortran::semantics::Symbol *> *privateSyms);
llvm::SmallVectorImpl<const semantics::Symbol *> *privateSyms);
void implicitPrivatize(
mlir::omp::PrivateClauseOps *clauseOps,
llvm::SmallVectorImpl<const Fortran::semantics::Symbol *> *privateSyms);
void doPrivatize(
const Fortran::semantics::Symbol *sym,
mlir::omp::PrivateClauseOps *clauseOps,
llvm::SmallVectorImpl<const Fortran::semantics::Symbol *> *privateSyms);
llvm::SmallVectorImpl<const semantics::Symbol *> *privateSyms);
void
doPrivatize(const semantics::Symbol *sym,
mlir::omp::PrivateClauseOps *clauseOps,
llvm::SmallVectorImpl<const semantics::Symbol *> *privateSyms);
void copyLastPrivatize(mlir::Operation *op);
void insertLastPrivateCompare(mlir::Operation *op);
void cloneSymbol(const Fortran::semantics::Symbol *sym);
void cloneSymbol(const semantics::Symbol *sym);
void
copyFirstPrivateSymbol(const Fortran::semantics::Symbol *sym,
copyFirstPrivateSymbol(const semantics::Symbol *sym,
mlir::OpBuilder::InsertPoint *copyAssignIP = nullptr);
void copyLastPrivateSymbol(const Fortran::semantics::Symbol *sym,
void copyLastPrivateSymbol(const semantics::Symbol *sym,
mlir::OpBuilder::InsertPoint *lastPrivIP);
void insertDeallocs();

public:
DataSharingProcessor(Fortran::lower::AbstractConverter &converter,
Fortran::semantics::SemanticsContext &semaCtx,
DataSharingProcessor(lower::AbstractConverter &converter,
semantics::SemanticsContext &semaCtx,
const List<Clause> &clauses,
Fortran::lower::pft::Evaluation &eval,
lower::pft::Evaluation &eval,
bool useDelayedPrivatization = false,
Fortran::lower::SymMap *symTable = nullptr)
lower::SymMap *symTable = nullptr)
: hasLastPrivateOp(false), converter(converter), semaCtx(semaCtx),
firOpBuilder(converter.getFirOpBuilder()), clauses(clauses), eval(eval),
useDelayedPrivatization(useDelayedPrivatization), symTable(symTable) {}
Expand All @@ -111,9 +107,9 @@ class DataSharingProcessor {
// Step2 performs the copying for lastprivates and requires knowledge of the
// MLIR operation to insert the last private update. Step2 adds
// dealocation code as well.
void processStep1(mlir::omp::PrivateClauseOps *clauseOps = nullptr,
llvm::SmallVectorImpl<const Fortran::semantics::Symbol *>
*privateSyms = nullptr);
void processStep1(
mlir::omp::PrivateClauseOps *clauseOps = nullptr,
llvm::SmallVectorImpl<const semantics::Symbol *> *privateSyms = nullptr);
void processStep2(mlir::Operation *op, bool isLoop);

void setLoopIV(mlir::Value iv) {
Expand Down
1,063 changes: 470 additions & 593 deletions flang/lib/Lower/OpenMP/OpenMP.cpp

Large diffs are not rendered by default.

52 changes: 21 additions & 31 deletions flang/lib/Lower/OpenMP/ReductionProcessor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -72,8 +72,8 @@ ReductionProcessor::ReductionIdentifier ReductionProcessor::getReductionType(

bool ReductionProcessor::supportedIntrinsicProcReduction(
const omp::clause::ProcedureDesignator &pd) {
Fortran::semantics::Symbol *sym = pd.v.id();
if (!sym->GetUltimate().attrs().test(Fortran::semantics::Attr::INTRINSIC))
semantics::Symbol *sym = pd.v.id();
if (!sym->GetUltimate().attrs().test(semantics::Attr::INTRINSIC))
return false;
auto redType = llvm::StringSwitch<bool>(getRealName(sym).ToString())
.Case("max", true)
Expand Down Expand Up @@ -180,7 +180,7 @@ ReductionProcessor::getReductionInitValue(mlir::Location loc, mlir::Type type,
case ReductionIdentifier::NEQV:
if (auto cplxTy = mlir::dyn_cast<fir::ComplexType>(type)) {
mlir::Type realTy =
Fortran::lower::convertReal(builder.getContext(), cplxTy.getFKind());
lower::convertReal(builder.getContext(), cplxTy.getFKind());
mlir::Value initRe = builder.createRealConstant(
loc, realTy, getOperationIdentity(redId, loc));
mlir::Value initIm = builder.createRealConstant(loc, realTy, 0);
Expand Down Expand Up @@ -657,36 +657,27 @@ mlir::omp::DeclareReductionOp ReductionProcessor::createDeclareReduction(
return decl;
}

// TODO: By-ref vs by-val reductions are currently toggled for the whole
// operation (possibly effecting multiple reduction variables).
// This could cause a problem with openmp target reductions because
// by-ref trivial types may not be supported.
bool ReductionProcessor::doReductionByRef(
const llvm::SmallVectorImpl<mlir::Value> &reductionVars) {
if (reductionVars.empty())
return false;
static bool doReductionByRef(mlir::Value reductionVar) {
if (forceByrefReduction)
return true;

for (mlir::Value reductionVar : reductionVars) {
if (auto declare =
mlir::dyn_cast<hlfir::DeclareOp>(reductionVar.getDefiningOp()))
reductionVar = declare.getMemref();
if (auto declare =
mlir::dyn_cast<hlfir::DeclareOp>(reductionVar.getDefiningOp()))
reductionVar = declare.getMemref();

if (!fir::isa_trivial(fir::unwrapRefType(reductionVar.getType())))
return true;

if (!fir::isa_trivial(fir::unwrapRefType(reductionVar.getType())))
return true;
}
return false;
}

void ReductionProcessor::addDeclareReduction(
mlir::Location currentLocation,
Fortran::lower::AbstractConverter &converter,
mlir::Location currentLocation, lower::AbstractConverter &converter,
const omp::clause::Reduction &reduction,
llvm::SmallVectorImpl<mlir::Value> &reductionVars,
llvm::SmallVectorImpl<bool> &reduceVarByRef,
llvm::SmallVectorImpl<mlir::Attribute> &reductionDeclSymbols,
llvm::SmallVectorImpl<const Fortran::semantics::Symbol *>
*reductionSymbols) {
llvm::SmallVectorImpl<const semantics::Symbol *> *reductionSymbols) {
fir::FirOpBuilder &firOpBuilder = converter.getFirOpBuilder();

if (std::get<std::optional<omp::clause::Reduction::ReductionModifier>>(
Expand Down Expand Up @@ -716,7 +707,7 @@ void ReductionProcessor::addDeclareReduction(
// should happen byref
fir::FirOpBuilder &builder = converter.getFirOpBuilder();
for (const Object &object : objectList) {
const Fortran::semantics::Symbol *symbol = object.id();
const semantics::Symbol *symbol = object.id();
if (reductionSymbols)
reductionSymbols->push_back(symbol);
mlir::Value symVal = converter.getSymbolAddress(*symbol);
Expand All @@ -731,8 +722,7 @@ void ReductionProcessor::addDeclareReduction(
// information needed to iterate over the array
if (mlir::isa<fir::SequenceType>(eleType)) {
// For Host associated symbols, use `SymbolBox` instead
Fortran::lower::SymbolBox symBox =
converter.lookupOneLevelUpSymbol(*symbol);
lower::SymbolBox symBox = converter.lookupOneLevelUpSymbol(*symbol);
hlfir::Entity entity{symBox.getAddr()};
entity = genVariableBox(currentLocation, builder, entity);
mlir::Value box = entity.getBase();
Expand Down Expand Up @@ -764,8 +754,8 @@ void ReductionProcessor::addDeclareReduction(
"reduction input var is a reference");

reductionVars.push_back(symVal);
reduceVarByRef.push_back(doReductionByRef(symVal));
}
const bool isByRef = doReductionByRef(reductionVars);

if (const auto &redDefinedOp =
std::get_if<omp::clause::DefinedOperator>(&redOperator.u)) {
Expand All @@ -787,7 +777,7 @@ void ReductionProcessor::addDeclareReduction(
break;
}

for (mlir::Value symVal : reductionVars) {
for (auto [symVal, isByRef] : llvm::zip(reductionVars, reduceVarByRef)) {
auto redType = mlir::cast<fir::ReferenceType>(symVal.getType());
const auto &kindMap = firOpBuilder.getKindMap();
if (mlir::isa<fir::LogicalType>(redType.getEleTy()))
Expand All @@ -811,7 +801,7 @@ void ReductionProcessor::addDeclareReduction(
*reductionIntrinsic)) {
ReductionProcessor::ReductionIdentifier redId =
ReductionProcessor::getReductionType(*reductionIntrinsic);
for (mlir::Value symVal : reductionVars) {
for (auto [symVal, isByRef] : llvm::zip(reductionVars, reduceVarByRef)) {
auto redType = mlir::cast<fir::ReferenceType>(symVal.getType());
if (!redType.getEleTy().isIntOrIndexOrFloat())
TODO(currentLocation,
Expand All @@ -828,12 +818,12 @@ void ReductionProcessor::addDeclareReduction(
}
}

const Fortran::semantics::SourceName
ReductionProcessor::getRealName(const Fortran::semantics::Symbol *symbol) {
const semantics::SourceName
ReductionProcessor::getRealName(const semantics::Symbol *symbol) {
return symbol->GetUltimate().name();
}

const Fortran::semantics::SourceName
const semantics::SourceName
ReductionProcessor::getRealName(const omp::clause::ProcedureDesignator &pd) {
return getRealName(pd.v.id());
}
Expand Down
17 changes: 7 additions & 10 deletions flang/lib/Lower/OpenMP/ReductionProcessor.h
Original file line number Diff line number Diff line change
Expand Up @@ -67,15 +67,12 @@ class ReductionProcessor {
static bool
supportedIntrinsicProcReduction(const omp::clause::ProcedureDesignator &pd);

static const Fortran::semantics::SourceName
getRealName(const Fortran::semantics::Symbol *symbol);
static const semantics::SourceName
getRealName(const semantics::Symbol *symbol);

static const Fortran::semantics::SourceName
static const semantics::SourceName
getRealName(const omp::clause::ProcedureDesignator &pd);

static bool
doReductionByRef(const llvm::SmallVectorImpl<mlir::Value> &reductionVars);

static std::string getReductionName(llvm::StringRef name,
const fir::KindMapping &kindMap,
mlir::Type ty, bool isByRef);
Expand Down Expand Up @@ -124,13 +121,13 @@ class ReductionProcessor {
/// Creates a reduction declaration and associates it with an OpenMP block
/// directive.
static void addDeclareReduction(
mlir::Location currentLocation,
Fortran::lower::AbstractConverter &converter,
mlir::Location currentLocation, lower::AbstractConverter &converter,
const omp::clause::Reduction &reduction,
llvm::SmallVectorImpl<mlir::Value> &reductionVars,
llvm::SmallVectorImpl<bool> &reduceVarByRef,
llvm::SmallVectorImpl<mlir::Attribute> &reductionDeclSymbols,
llvm::SmallVectorImpl<const Fortran::semantics::Symbol *>
*reductionSymbols = nullptr);
llvm::SmallVectorImpl<const semantics::Symbol *> *reductionSymbols =
nullptr);
};

template <typename FloatOp, typename IntegerOp>
Expand Down
100 changes: 46 additions & 54 deletions flang/lib/Lower/OpenMP/Utils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -52,22 +52,22 @@ int64_t getCollapseValue(const List<Clause> &clauses) {
}

void genObjectList(const ObjectList &objects,
Fortran::lower::AbstractConverter &converter,
lower::AbstractConverter &converter,
llvm::SmallVectorImpl<mlir::Value> &operands) {
for (const Object &object : objects) {
const Fortran::semantics::Symbol *sym = object.id();
const semantics::Symbol *sym = object.id();
assert(sym && "Expected Symbol");
if (mlir::Value variable = converter.getSymbolAddress(*sym)) {
operands.push_back(variable);
} else if (const auto *details =
sym->detailsIf<Fortran::semantics::HostAssocDetails>()) {
sym->detailsIf<semantics::HostAssocDetails>()) {
operands.push_back(converter.getSymbolAddress(details->symbol()));
converter.copySymbolBinding(details->symbol(), *sym);
}
}
}

mlir::Type getLoopVarType(Fortran::lower::AbstractConverter &converter,
mlir::Type getLoopVarType(lower::AbstractConverter &converter,
std::size_t loopVarTypeSize) {
// OpenMP runtime requires 32-bit or 64-bit loop variables.
loopVarTypeSize = loopVarTypeSize * 8;
Expand All @@ -85,24 +85,21 @@ mlir::Type getLoopVarType(Fortran::lower::AbstractConverter &converter,
return converter.getFirOpBuilder().getIntegerType(loopVarTypeSize);
}

Fortran::semantics::Symbol *
getIterationVariableSymbol(const Fortran::lower::pft::Evaluation &eval) {
return eval.visit(Fortran::common::visitors{
[&](const Fortran::parser::DoConstruct &doLoop) {
semantics::Symbol *
getIterationVariableSymbol(const lower::pft::Evaluation &eval) {
return eval.visit(common::visitors{
[&](const parser::DoConstruct &doLoop) {
if (const auto &maybeCtrl = doLoop.GetLoopControl()) {
using LoopControl = Fortran::parser::LoopControl;
using LoopControl = parser::LoopControl;
if (auto *bounds = std::get_if<LoopControl::Bounds>(&maybeCtrl->u)) {
static_assert(
std::is_same_v<decltype(bounds->name),
Fortran::parser::Scalar<Fortran::parser::Name>>);
static_assert(std::is_same_v<decltype(bounds->name),
parser::Scalar<parser::Name>>);
return bounds->name.thing.symbol;
}
}
return static_cast<Fortran::semantics::Symbol *>(nullptr);
},
[](auto &&) {
return static_cast<Fortran::semantics::Symbol *>(nullptr);
return static_cast<semantics::Symbol *>(nullptr);
},
[](auto &&) { return static_cast<semantics::Symbol *>(nullptr); },
});
}

Expand Down Expand Up @@ -139,12 +136,11 @@ createMapInfoOp(fir::FirOpBuilder &builder, mlir::Location loc,
}

static int
getComponentPlacementInParent(const Fortran::semantics::Symbol *componentSym) {
const auto *derived =
componentSym->owner()
.derivedTypeSpec()
->typeSymbol()
.detailsIf<Fortran::semantics::DerivedTypeDetails>();
getComponentPlacementInParent(const semantics::Symbol *componentSym) {
const auto *derived = componentSym->owner()
.derivedTypeSpec()
->typeSymbol()
.detailsIf<semantics::DerivedTypeDetails>();
assert(derived &&
"expected derived type details when processing component symbol");
for (auto [placement, name] : llvm::enumerate(derived->componentNames()))
Expand All @@ -155,7 +151,7 @@ getComponentPlacementInParent(const Fortran::semantics::Symbol *componentSym) {

static std::optional<Object>
getComponentObject(std::optional<Object> object,
Fortran::semantics::SemanticsContext &semaCtx) {
semantics::SemanticsContext &semaCtx) {
if (!object)
return std::nullopt;

Expand All @@ -176,7 +172,7 @@ getComponentObject(std::optional<Object> object,
static void
generateMemberPlacementIndices(const Object &object,
llvm::SmallVectorImpl<int> &indices,
Fortran::semantics::SemanticsContext &semaCtx) {
semantics::SemanticsContext &semaCtx) {
auto compObj = getComponentObject(object, semaCtx);
while (compObj) {
indices.push_back(getComponentPlacementInParent(compObj->id()));
Expand All @@ -189,16 +185,14 @@ generateMemberPlacementIndices(const Object &object,

void addChildIndexAndMapToParent(
const omp::Object &object,
std::map<const Fortran::semantics::Symbol *,
std::map<const semantics::Symbol *,
llvm::SmallVector<OmpMapMemberIndicesData>> &parentMemberIndices,
mlir::omp::MapInfoOp &mapOp,
Fortran::semantics::SemanticsContext &semaCtx) {
std::optional<Fortran::evaluate::DataRef> dataRef =
ExtractDataRef(object.designator);
mlir::omp::MapInfoOp &mapOp, semantics::SemanticsContext &semaCtx) {
std::optional<evaluate::DataRef> dataRef = ExtractDataRef(object.designator);
assert(dataRef.has_value() &&
"DataRef could not be extracted during mapping of derived type "
"cannot proceed");
const Fortran::semantics::Symbol *parentSym = &dataRef->GetFirstSymbol();
const semantics::Symbol *parentSym = &dataRef->GetFirstSymbol();
assert(parentSym && "Could not find parent symbol during lower of "
"a component member in OpenMP map clause");
llvm::SmallVector<int> indices;
Expand Down Expand Up @@ -236,14 +230,14 @@ static mlir::DenseIntElementsAttr createDenseElementsAttrFromIndices(
llvm::SmallVector<int64_t> shape;
calculateShapeAndFillIndices(shape, memberPlacementData);

llvm::SmallVector<int> indicesFlattened = std::accumulate(
memberPlacementData.begin(), memberPlacementData.end(),
llvm::SmallVector<int>(),
[](llvm::SmallVector<int> &x, OmpMapMemberIndicesData y) {
x.insert(x.end(), y.memberPlacementIndices.begin(),
y.memberPlacementIndices.end());
return x;
});
llvm::SmallVector<int> indicesFlattened =
std::accumulate(memberPlacementData.begin(), memberPlacementData.end(),
llvm::SmallVector<int>(),
[](llvm::SmallVector<int> &x, OmpMapMemberIndicesData y) {
x.insert(x.end(), y.memberPlacementIndices.begin(),
y.memberPlacementIndices.end());
return x;
});

return mlir::DenseIntElementsAttr::get(
mlir::VectorType::get(shape,
Expand All @@ -252,11 +246,11 @@ static mlir::DenseIntElementsAttr createDenseElementsAttrFromIndices(
}

void insertChildMapInfoIntoParent(
Fortran::lower::AbstractConverter &converter,
std::map<const Fortran::semantics::Symbol *,
lower::AbstractConverter &converter,
std::map<const semantics::Symbol *,
llvm::SmallVector<OmpMapMemberIndicesData>> &parentMemberIndices,
llvm::SmallVectorImpl<mlir::Value> &mapOperands,
llvm::SmallVectorImpl<const Fortran::semantics::Symbol *> &mapSyms,
llvm::SmallVectorImpl<const semantics::Symbol *> &mapSyms,
llvm::SmallVectorImpl<mlir::Type> *mapSymTypes,
llvm::SmallVectorImpl<mlir::Location> *mapSymLocs) {
for (auto indices : parentMemberIndices) {
Expand Down Expand Up @@ -323,30 +317,28 @@ void insertChildMapInfoIntoParent(
}
}

Fortran::semantics::Symbol *
getOmpObjectSymbol(const Fortran::parser::OmpObject &ompObject) {
Fortran::semantics::Symbol *sym = nullptr;
semantics::Symbol *getOmpObjectSymbol(const parser::OmpObject &ompObject) {
semantics::Symbol *sym = nullptr;
std::visit(
Fortran::common::visitors{
[&](const Fortran::parser::Designator &designator) {
common::visitors{
[&](const parser::Designator &designator) {
if (auto *arrayEle =
Fortran::parser::Unwrap<Fortran::parser::ArrayElement>(
designator)) {
parser::Unwrap<parser::ArrayElement>(designator)) {
// Use getLastName to retrieve the arrays symbol, this will
// provide the farthest right symbol (the last) in a designator,
// i.e. providing something like the following:
// "dtype1%dtype2%array[2:10]", will result in "array"
sym = GetLastName(arrayEle->base).symbol;
} else if (auto *structComp = Fortran::parser::Unwrap<
Fortran::parser::StructureComponent>(designator)) {
sym = structComp->component.symbol;
} else if (const Fortran::parser::Name *name =
Fortran::semantics::getDesignatorNameIfDataRef(
} else if (auto *structComp =
parser::Unwrap<parser::StructureComponent>(
designator)) {
sym = structComp->component.symbol;
} else if (const parser::Name *name =
semantics::getDesignatorNameIfDataRef(designator)) {
sym = name->symbol;
}
},
[&](const Fortran::parser::Name &name) { sym = name.symbol; }},
[&](const parser::Name &name) { sym = name.symbol; }},
ompObject.u);
return sym;
}
Expand Down
24 changes: 11 additions & 13 deletions flang/lib/Lower/OpenMP/Utils.h
Original file line number Diff line number Diff line change
Expand Up @@ -42,8 +42,7 @@ class AbstractConverter;
namespace omp {

using DeclareTargetCapturePair =
std::pair<mlir::omp::DeclareTargetCaptureClause,
const Fortran::semantics::Symbol &>;
std::pair<mlir::omp::DeclareTargetCaptureClause, const semantics::Symbol &>;

// A small helper structure for keeping track of a component members MapInfoOp
// and index data when lowering OpenMP map clauses. Keeps track of the
Expand All @@ -69,36 +68,35 @@ createMapInfoOp(fir::FirOpBuilder &builder, mlir::Location loc,

void addChildIndexAndMapToParent(
const omp::Object &object,
std::map<const Fortran::semantics::Symbol *,
std::map<const semantics::Symbol *,
llvm::SmallVector<OmpMapMemberIndicesData>> &parentMemberIndices,
mlir::omp::MapInfoOp &mapOp, Fortran::semantics::SemanticsContext &semaCtx);
mlir::omp::MapInfoOp &mapOp, semantics::SemanticsContext &semaCtx);

void insertChildMapInfoIntoParent(
Fortran::lower::AbstractConverter &converter,
std::map<const Fortran::semantics::Symbol *,
lower::AbstractConverter &converter,
std::map<const semantics::Symbol *,
llvm::SmallVector<OmpMapMemberIndicesData>> &parentMemberIndices,
llvm::SmallVectorImpl<mlir::Value> &mapOperands,
llvm::SmallVectorImpl<const Fortran::semantics::Symbol *> &mapSyms,
llvm::SmallVectorImpl<const semantics::Symbol *> &mapSyms,
llvm::SmallVectorImpl<mlir::Type> *mapSymTypes,
llvm::SmallVectorImpl<mlir::Location> *mapSymLocs);

mlir::Type getLoopVarType(Fortran::lower::AbstractConverter &converter,
mlir::Type getLoopVarType(lower::AbstractConverter &converter,
std::size_t loopVarTypeSize);

Fortran::semantics::Symbol *
getIterationVariableSymbol(const Fortran::lower::pft::Evaluation &eval);
semantics::Symbol *
getIterationVariableSymbol(const lower::pft::Evaluation &eval);

void gatherFuncAndVarSyms(
const ObjectList &objects, mlir::omp::DeclareTargetCaptureClause clause,
llvm::SmallVectorImpl<DeclareTargetCapturePair> &symbolAndClause);

int64_t getCollapseValue(const List<Clause> &clauses);

Fortran::semantics::Symbol *
getOmpObjectSymbol(const Fortran::parser::OmpObject &ompObject);
semantics::Symbol *getOmpObjectSymbol(const parser::OmpObject &ompObject);

void genObjectList(const ObjectList &objects,
Fortran::lower::AbstractConverter &converter,
lower::AbstractConverter &converter,
llvm::SmallVectorImpl<mlir::Value> &operands);

} // namespace omp
Expand Down
157 changes: 63 additions & 94 deletions flang/lib/Optimizer/Analysis/AliasAnalysis.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,11 +33,9 @@ static bool isDummyArgument(mlir::Value v) {
if (!blockArg)
return false;

mlir::Block *owner = blockArg.getOwner();
if (!owner->isEntryBlock() ||
!mlir::isa<mlir::FunctionOpInterface>(owner->getParentOp()))
return false;
return true;
auto *owner{blockArg.getOwner()};
return owner->isEntryBlock() &&
mlir::isa<mlir::FunctionOpInterface>(owner->getParentOp());
}

/// Temporary function to skip through all the no op operations
Expand All @@ -58,12 +56,17 @@ static mlir::Value getOriginalDef(mlir::Value v) {
namespace fir {

void AliasAnalysis::Source::print(llvm::raw_ostream &os) const {
if (auto v = llvm::dyn_cast<mlir::Value>(u))
if (auto v = llvm::dyn_cast<mlir::Value>(origin.u))
os << v;
else if (auto gbl = llvm::dyn_cast<mlir::SymbolRefAttr>(u))
else if (auto gbl = llvm::dyn_cast<mlir::SymbolRefAttr>(origin.u))
os << gbl;
os << " SourceKind: " << EnumToString(kind);
os << " Type: " << valueType << " ";
if (origin.isData) {
os << " following data ";
} else {
os << " following box reference ";
}
attributes.Dump(os, EnumToString);
}

Expand All @@ -80,6 +83,19 @@ bool AliasAnalysis::Source::isTargetOrPointer() const {
attributes.test(Attribute::Target);
}

bool AliasAnalysis::Source::isDummyArgument() const {
if (auto v = origin.u.dyn_cast<mlir::Value>()) {
return ::isDummyArgument(v);
}
return false;
}

bool AliasAnalysis::Source::isData() const { return origin.isData; }
bool AliasAnalysis::Source::isBoxData() const {
return mlir::isa<fir::BaseBoxType>(fir::unwrapRefType(valueType)) &&
origin.isData;
}

bool AliasAnalysis::Source::isRecordWithPointerComponent() const {
auto eleTy = fir::dyn_cast_ptrEleTy(valueType);
if (!eleTy)
Expand All @@ -92,70 +108,35 @@ AliasResult AliasAnalysis::alias(Value lhs, Value rhs) {
auto lhsSrc = getSource(lhs);
auto rhsSrc = getSource(rhs);
bool approximateSource = lhsSrc.approximateSource || rhsSrc.approximateSource;
LLVM_DEBUG(llvm::dbgs() << "AliasAnalysis::alias\n";
LLVM_DEBUG(llvm::dbgs() << "\nAliasAnalysis::alias\n";
llvm::dbgs() << " lhs: " << lhs << "\n";
llvm::dbgs() << " lhsSrc: " << lhsSrc << "\n";
llvm::dbgs() << " rhs: " << rhs << "\n";
llvm::dbgs() << " rhsSrc: " << rhsSrc << "\n";
llvm::dbgs() << "\n";);
llvm::dbgs() << " rhsSrc: " << rhsSrc << "\n";);

// Indirect case currently not handled. Conservatively assume
// it aliases with everything
if (lhsSrc.kind > SourceKind::Direct || rhsSrc.kind > SourceKind::Direct) {
if (lhsSrc.kind >= SourceKind::Indirect ||
rhsSrc.kind >= SourceKind::Indirect) {
return AliasResult::MayAlias;
}

// SourceKind::Direct is set for the addresses wrapped in a global boxes.
// ie: fir.global @_QMpointersEp : !fir.box<!fir.ptr<f32>>
// Though nothing is known about them, they would only alias with targets or
// pointers
bool directSourceToNonTargetOrPointer = false;
if (lhsSrc.u != rhsSrc.u || lhsSrc.kind != rhsSrc.kind) {
if ((lhsSrc.kind == SourceKind::Direct && !rhsSrc.isTargetOrPointer()) ||
(rhsSrc.kind == SourceKind::Direct && !lhsSrc.isTargetOrPointer()))
directSourceToNonTargetOrPointer = true;
}

if (lhsSrc.kind == SourceKind::Direct ||
rhsSrc.kind == SourceKind::Direct) {
if (!directSourceToNonTargetOrPointer)
return AliasResult::MayAlias;
}

if (lhsSrc.kind == rhsSrc.kind) {
if (lhsSrc.u == rhsSrc.u) {
if (lhsSrc.origin == rhsSrc.origin) {
LLVM_DEBUG(llvm::dbgs()
<< " aliasing because same source kind and origin\n");
if (approximateSource)
return AliasResult::MayAlias;
return AliasResult::MustAlias;
}

// Two host associated accesses may overlap due to an equivalence.
if (lhsSrc.kind == SourceKind::HostAssoc)
if (lhsSrc.kind == SourceKind::HostAssoc) {
LLVM_DEBUG(llvm::dbgs() << " aliasing because of host association\n");
return AliasResult::MayAlias;

// Allocate and global memory address cannot physically alias
if (lhsSrc.kind == SourceKind::Allocate ||
lhsSrc.kind == SourceKind::Global)
return AliasResult::NoAlias;

// Dummy TARGET/POINTER arguments may alias.
if (lhsSrc.isTargetOrPointer() && rhsSrc.isTargetOrPointer())
return AliasResult::MayAlias;

// Box for POINTER component inside an object of a derived type
// may alias box of a POINTER object, as well as boxes for POINTER
// components inside two objects of derived types may alias.
if ((lhsSrc.isRecordWithPointerComponent() && rhsSrc.isTargetOrPointer()) ||
(rhsSrc.isRecordWithPointerComponent() && lhsSrc.isTargetOrPointer()) ||
(lhsSrc.isRecordWithPointerComponent() &&
rhsSrc.isRecordWithPointerComponent()))
return AliasResult::MayAlias;

return AliasResult::NoAlias;
}
}

assert(lhsSrc.kind != rhsSrc.kind && "memory source kinds must be different");

Source *src1, *src2;
if (lhsSrc.kind < rhsSrc.kind) {
src1 = &lhsSrc;
Expand Down Expand Up @@ -186,17 +167,22 @@ AliasResult AliasAnalysis::alias(Value lhs, Value rhs) {
}

// Dummy TARGET/POINTER argument may alias with a global TARGET/POINTER.
if (src1->isTargetOrPointer() && src2->isTargetOrPointer())
if (src1->isTargetOrPointer() && src2->isTargetOrPointer() &&
src1->isData() == src2->isData()) {
LLVM_DEBUG(llvm::dbgs() << " aliasing because of target or pointer\n");
return AliasResult::MayAlias;
}

// Box for POINTER component inside an object of a derived type
// may alias box of a POINTER object, as well as boxes for POINTER
// components inside two objects of derived types may alias.
if ((src1->isRecordWithPointerComponent() && src2->isTargetOrPointer()) ||
(src2->isRecordWithPointerComponent() && src1->isTargetOrPointer()) ||
(src1->isRecordWithPointerComponent() &&
src2->isRecordWithPointerComponent()))
src2->isRecordWithPointerComponent())) {
LLVM_DEBUG(llvm::dbgs() << " aliasing because of pointer components\n");
return AliasResult::MayAlias;
}

return AliasResult::NoAlias;
}
Expand Down Expand Up @@ -262,7 +248,10 @@ AliasAnalysis::Source AliasAnalysis::getSource(mlir::Value v) {
mlir::Type ty;
bool breakFromLoop{false};
bool approximateSource{false};
bool followBoxAddr{mlir::isa<fir::BaseBoxType>(v.getType())};
bool followBoxData{mlir::isa<fir::BaseBoxType>(v.getType())};
bool isBoxRef{fir::isa_ref_type(v.getType()) &&
mlir::isa<fir::BaseBoxType>(fir::unwrapRefType(v.getType()))};
bool followingData = !isBoxRef;
mlir::SymbolRefAttr global;
Source::Attributes attributes;
while (defOp && !breakFromLoop) {
Expand All @@ -282,34 +271,32 @@ AliasAnalysis::Source AliasAnalysis::getSource(mlir::Value v) {
v = op->getOperand(0);
defOp = v.getDefiningOp();
if (mlir::isa<fir::BaseBoxType>(v.getType()))
followBoxAddr = true;
followBoxData = true;
})
.Case<fir::ArrayCoorOp, fir::CoordinateOp>([&](auto op) {
v = op->getOperand(0);
defOp = v.getDefiningOp();
if (mlir::isa<fir::BaseBoxType>(v.getType()))
followBoxAddr = true;
followBoxData = true;
approximateSource = true;
})
.Case<fir::EmboxOp, fir::ReboxOp>([&](auto op) {
if (followBoxAddr) {
if (followBoxData) {
v = op->getOperand(0);
defOp = v.getDefiningOp();
} else
breakFromLoop = true;
})
.Case<fir::LoadOp>([&](auto op) {
if (followBoxAddr && mlir::isa<fir::BaseBoxType>(op.getType())) {
// For now, support the load of an argument or fir.address_of
// TODO: generalize to all operations (in particular fir.alloca and
// fir.allocmem)
auto def = getOriginalDef(op.getMemref());
if (isDummyArgument(def) ||
def.template getDefiningOp<fir::AddrOfOp>()) {
v = def;
defOp = v.getDefiningOp();
return;
}
// If the load is from a leaf source, return the leaf. Do not track
// through indirections otherwise.
// TODO: Add support to fir.alloca and fir.allocmem
auto def = getOriginalDef(op.getMemref());
if (isDummyArgument(def) ||
def.template getDefiningOp<fir::AddrOfOp>()) {
v = def;
defOp = v.getDefiningOp();
return;
}
// No further tracking for addresses loaded from memory for now.
type = SourceKind::Indirect;
Expand All @@ -318,36 +305,18 @@ AliasAnalysis::Source AliasAnalysis::getSource(mlir::Value v) {
.Case<fir::AddrOfOp>([&](auto op) {
// Address of a global scope object.
ty = v.getType();

// When the global is a
// fir.global @_QMpointersEp : !fir.box<!fir.ptr<f32>>
// or
// fir.global @_QMpointersEp : !fir.box<!fir.heap<f32>>
//
// and when following through the wrapped address, capture
// the fact that there is nothing known about it. Therefore setting
// the source to Direct.
//
// When not following the wrapped address, then consider the address
// of the box, which has nothing to do with the wrapped address and
// lies in the global memory space.
if (followBoxAddr &&
mlir::isa<fir::BaseBoxType>(fir::unwrapRefType(ty)))
type = SourceKind::Direct;
else
type = SourceKind::Global;
type = SourceKind::Global;

auto globalOpName = mlir::OperationName(
fir::GlobalOp::getOperationName(), defOp->getContext());
if (fir::valueHasFirAttribute(
v, fir::GlobalOp::getTargetAttrName(globalOpName)))
attributes.set(Attribute::Target);

// TODO: Take followBoxAddr into account when setting the pointer
// TODO: Take followBoxData into account when setting the pointer
// attribute
if (Source::isPointerReference(ty))
attributes.set(Attribute::Pointer);

global = llvm::cast<fir::AddrOfOp>(op).getSymbol();
breakFromLoop = true;
})
Expand Down Expand Up @@ -393,7 +362,7 @@ AliasAnalysis::Source AliasAnalysis::getSource(mlir::Value v) {
// MustAlias after going through a designate operation
approximateSource = true;
if (mlir::isa<fir::BaseBoxType>(v.getType()))
followBoxAddr = true;
followBoxData = true;
})
.Default([&](auto op) {
defOp = nullptr;
Expand All @@ -412,10 +381,10 @@ AliasAnalysis::Source AliasAnalysis::getSource(mlir::Value v) {
attributes.set(Attribute::Pointer);
}

if (type == SourceKind::Global || type == SourceKind::Direct)
return {global, type, ty, attributes, approximateSource};

return {v, type, ty, attributes, approximateSource};
if (type == SourceKind::Global) {
return {{global, followingData}, type, ty, attributes, approximateSource};
}
return {{v, followingData}, type, ty, attributes, approximateSource};
}

} // namespace fir
17 changes: 10 additions & 7 deletions flang/lib/Optimizer/Transforms/AddAliasTags.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -145,7 +145,7 @@ void AddAliasTagsPass::runOnAliasInterface(fir::FirAliasTagOpInterface op,
source.kind == fir::AliasAnalysis::SourceKind::Argument) {
LLVM_DEBUG(llvm::dbgs().indent(2)
<< "Found reference to dummy argument at " << *op << "\n");
std::string name = getFuncArgName(source.u.get<mlir::Value>());
std::string name = getFuncArgName(source.origin.u.get<mlir::Value>());
if (!name.empty())
tag = state.getFuncTree(func).dummyArgDataTree.getTag(name);
else
Expand All @@ -155,18 +155,20 @@ void AddAliasTagsPass::runOnAliasInterface(fir::FirAliasTagOpInterface op,

// TBAA for global variables
} else if (enableGlobals &&
source.kind == fir::AliasAnalysis::SourceKind::Global) {
mlir::SymbolRefAttr glbl = source.u.get<mlir::SymbolRefAttr>();
source.kind == fir::AliasAnalysis::SourceKind::Global &&
!source.isBoxData()) {
mlir::SymbolRefAttr glbl = source.origin.u.get<mlir::SymbolRefAttr>();
const char *name = glbl.getRootReference().data();
LLVM_DEBUG(llvm::dbgs().indent(2) << "Found reference to global " << name
<< " at " << *op << "\n");
tag = state.getFuncTree(func).globalDataTree.getTag(name);

// TBAA for SourceKind::Direct
} else if (enableDirect &&
source.kind == fir::AliasAnalysis::SourceKind::Direct) {
if (source.u.is<mlir::SymbolRefAttr>()) {
mlir::SymbolRefAttr glbl = source.u.get<mlir::SymbolRefAttr>();
source.kind == fir::AliasAnalysis::SourceKind::Global &&
source.isBoxData()) {
if (source.origin.u.is<mlir::SymbolRefAttr>()) {
mlir::SymbolRefAttr glbl = source.origin.u.get<mlir::SymbolRefAttr>();
const char *name = glbl.getRootReference().data();
LLVM_DEBUG(llvm::dbgs().indent(2) << "Found reference to direct " << name
<< " at " << *op << "\n");
Expand All @@ -182,7 +184,8 @@ void AddAliasTagsPass::runOnAliasInterface(fir::FirAliasTagOpInterface op,
} else if (enableLocalAllocs &&
source.kind == fir::AliasAnalysis::SourceKind::Allocate) {
std::optional<llvm::StringRef> name;
mlir::Operation *sourceOp = source.u.get<mlir::Value>().getDefiningOp();
mlir::Operation *sourceOp =
source.origin.u.get<mlir::Value>().getDefiningOp();
if (auto alloc = mlir::dyn_cast_or_null<fir::AllocaOp>(sourceOp))
name = alloc.getUniqName();
else if (auto alloc = mlir::dyn_cast_or_null<fir::AllocMemOp>(sourceOp))
Expand Down
37 changes: 24 additions & 13 deletions flang/test/Analysis/AliasAnalysis/alias-analysis-2.fir
Original file line number Diff line number Diff line change
Expand Up @@ -37,14 +37,14 @@

// arg2 is a reference to a pointer. Modifying arg2 could
// modify a target with a pointer component
// CHECK-DAG: func.region0#0 <-> func.region0#2: MayAlias
// CHECK-DAG: func.region0#1 <-> func.region0#2: MayAlias
// CHECK-DAG: arg2.load#0 <-> func.region0#0: MayAlias
// CHECK-DAG: arg2.load#0 <-> func.region0#1: MayAlias

// However, the address wrapped by arg2, can alias with any target or
// pointer arguments
// CHECK-DAG: arg2.addr#0 <-> func.region0#0: MayAlias
// CHECK-DAG: arg2.addr#0 <-> func.region0#1: MayAlias
// CHECK-DAG: arg2.addr#0 <-> func.region0#2: MustAlias
// CHECK-DAG: arg2.load#0 <-> arg2.addr#0: MustAlias
// CHECK-DAG: boxp1.addr#0 <-> arg2.addr#0: MayAlias

func.func @_QFPtest(%arg0: !fir.ref<f32> {fir.bindc_name = "v1", fir.target}, %arg1: !fir.ref<f32> {fir.bindc_name = "v2", fir.target}, %arg2: !fir.ref<!fir.box<!fir.ptr<f32>>> ) attributes {test.ptr = "func"} {
Expand Down Expand Up @@ -80,7 +80,7 @@ func.func @_QFPtest(%arg0: !fir.ref<f32> {fir.bindc_name = "v1", fir.target}, %a
%14 = fir.box_addr %13 : (!fir.box<!fir.ptr<f32>>) -> !fir.ptr<f32>
fir.store %14 to %4 : !fir.ref<!fir.ptr<f32>>

%15 = fir.load %arg2 : !fir.ref<!fir.box<!fir.ptr<f32>>>
%15 = fir.load %arg2 {test.ptr = "arg2.load"} : !fir.ref<!fir.box<!fir.ptr<f32>>>
%16 = fir.box_addr %15 {test.ptr = "arg2.addr"} : (!fir.box<!fir.ptr<f32>>) -> !fir.ptr<f32>
return
}
Expand All @@ -99,10 +99,12 @@ func.func @_QFPtest(%arg0: !fir.ref<f32> {fir.bindc_name = "v1", fir.target}, %a
// CHECK-DAG: func.region0#1 <-> func.region0#2: MayAlias

// They can also modify targets that have pointer components
// CHECK-DAG: func.region0#0 <-> func.region0#1: MayAlias
// CHECK-DAG: func.region0#0 <-> func.region0#2: MayAlias
// CHECK-DAG: arg1.load#0 <-> func.region0#0: MayAlias
// CHECK-DAG: arg2.load#0 <-> func.region0#0: MayAlias

func.func @_QFPtest2(%arg0: !fir.ref<f32> {fir.bindc_name = "v1", fir.target}, %arg1: !fir.ref<!fir.box<!fir.ptr<f32>>>, %arg2: !fir.ref<!fir.box<!fir.ptr<f32>>> ) attributes {test.ptr = "func"} {
%0 = fir.load %arg1 {test.ptr = "arg1.load"} : !fir.ref<!fir.box<!fir.ptr<f32>>>
%1 = fir.load %arg2 {test.ptr = "arg2.load"} : !fir.ref<!fir.box<!fir.ptr<f32>>>
return
}

Expand Down Expand Up @@ -141,14 +143,14 @@ func.func @_QFPtest2(%arg0: !fir.ref<f32> {fir.bindc_name = "v1", fir.target}, %
// alias with the wrapped scalar _QFEvar2. We meant box_addr of _QMpointersEp
// CHECK-DAG: p#0 <-> box.addr#0: NoAlias

// TODO: Still need to handle more gracefully the difference between !fir.ref<!fir.box<>> and !fir.box<>
// CHECK-DAG: box.addr#0 <-> func.region0#0: MayAlias
// Handling gracefully the difference between !fir.ref<!fir.box<>> and !fir.box<>
// CHECK-DAG: box.addr#0 <-> func.region0#0: NoAlias

// var2, although it is a target, cannot alias with p
// A modification of p would only make them point to a new target but not modify it
// CHECK-DAG: var2#0 <-> p#0: NoAlias
// It can alias with p1, if p1 is a pointer component
// CHECK-DAG: var2#0 <-> func.region0#0: MayAlias
// CHECK-DAG: arg0.load#0 <-> var2#0: MayAlias
// It is the same as box.addr
// CHECK-DAG: var2#0 <-> box.addr#0: MustAlias

Expand All @@ -173,6 +175,7 @@ fir.global internal @_QFEvar2 target : f32 {
}

func.func @_QFPtest3(%arg0: !fir.ref<!fir.box<!fir.ptr<f32>>> {fir.bindc_name = "p1"}, %arg1: !fir.ref<f32>) attributes {test.ptr = "func"} {
%3 = fir.load %arg0 {test.ptr = "arg0.load"}: !fir.ref<!fir.box<!fir.ptr<f32>>>
%4 = fir.address_of(@_QFEvar2) {test.ptr = "var2"} : !fir.ref<f32>
%5 = fir.address_of(@_QMpointersEp) {test.ptr = "p"} : !fir.ref<!fir.box<!fir.ptr<f32>>>
%6 = fir.embox %4 : (!fir.ref<f32>) -> !fir.box<!fir.ptr<f32>>
Expand Down Expand Up @@ -214,10 +217,17 @@ func.func @_QFPtest3(%arg0: !fir.ref<!fir.box<!fir.ptr<f32>>> {fir.bindc_name =
// CHECK-DAG: var2_hlfir#1 <-> p_hlfir#0: NoAlias
// CHECK-DAG: var2_hlfir#1 <-> p_hlfir#1: NoAlias

// CHECK-DAG: var2#0 <-> func.region0#0: MayAlias
// CHECK-DAG: var2_fir#0 <-> func.region0#0: MayAlias
// CHECK-DAG: var2_hlfir#0 <-> func.region0#0: MayAlias
// CHECK-DAG: var2_hlfir#1 <-> func.region0#0: MayAlias
// The data cannot alias with the box references
// CHECK-DAG: var2#0 <-> func.region0#0: NoAlias
// CHECK-DAG: var2_fir#0 <-> func.region0#0: NoAlias
// CHECK-DAG: var2_hlfir#0 <-> func.region0#0: NoAlias
// CHECK-DAG: var2_hlfir#1 <-> func.region0#0: NoAlias

// But it can alias with the box's own data
// CHECK-DAG: arg0.load#0 <-> var2#0: MayAlias
// CHECK-DAG: arg0.load#0 <-> var2_fir#0: MayAlias
// CHECK-DAG: arg0.load#0 <-> var2_hlfir#0: MayAlias
// CHECK-DAG: arg0.load#0 <-> var2_hlfir#1: MayAlias

// CHECK-DAG: var2#0 <-> box.addr#0: MustAlias
// CHECK-DAG: var2#0 <-> box.addr_fir#0: MustAlias
Expand Down Expand Up @@ -255,6 +265,7 @@ fir.global internal @_QFEvar2 target : f32 {
}

func.func @_QFPtest4(%arg0: !fir.ref<!fir.box<!fir.ptr<f32>>> {fir.bindc_name = "p1"}, %arg1: !fir.ref<f32>) attributes {test.ptr = "func"} {
%3 = fir.load %arg0 {test.ptr = "arg0.load"} : !fir.ref<!fir.box<!fir.ptr<f32>>>
%4 = fir.address_of(@_QFEvar2) {test.ptr = "var2"} : !fir.ref<f32>
%fir_decl_var2 = fir.declare %4 {uniq_name = "var2_fir", test.ptr = "var2_fir"}: (!fir.ref<f32>) -> !fir.ref<f32>
%hlfir_decl_var2:2 = hlfir.declare %4 {uniq_name = "var2_hlfir", test.ptr = "var2_hlfir"}: (!fir.ref<f32>) -> (!fir.ref<f32>, !fir.ref<f32>)
Expand Down
4 changes: 2 additions & 2 deletions flang/test/Analysis/AliasAnalysis/alias-analysis-3.fir
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,8 @@
// FIXME: a's box cannot alias with raw reference to f32 (x), so MayAlias below must be NoAlias:
// CHECK: a#0 <-> func.region0#1: MayAlias

// FIXME: pointer_dummy's box cannot alias with raw reference to f32 (x), so MayAlias below must be NoAlias:
// CHECK: func.region0#0 <-> func.region0#1: MayAlias
// pointer_dummy's box cannot alias with raw reference to f32 (x)
// CHECK: func.region0#0 <-> func.region0#1: NoAlias

fir.global @_QMmEa : !fir.type<_QMmTt{pointer_component:!fir.box<!fir.ptr<f32>>}> {
%0 = fir.undefined !fir.type<_QMmTt{pointer_component:!fir.box<!fir.ptr<f32>>}>
Expand Down
59 changes: 59 additions & 0 deletions flang/test/Analysis/AliasAnalysis/alias-analysis-9.fir
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
// RUN: fir-opt %s -pass-pipeline='builtin.module(func.func(test-fir-alias-analysis))' 2>&1 | FileCheck %s


// module m
// type t
// type(t), pointer :: next
// integer :: i
// end type
// contains
// subroutine foo(x, y)
// type(t) :: x, y
// integer :: i1, i2
// i1 = x%next%i
// x = y
// i2 = x%next%i
// end subroutine
// end module

// CHECK-LABEL: Testing : "_QMmPfoo"
// TODO: x and y are non pointer, non target argument and therefore do not alias.
// CHECK-DAG: x#0 <-> y#0: MayAlias

// TODO: y is not a pointer object and therefore does not alias with the x%next component.
// Also assigning x to y would not modify x.next
// CHECK-DAG: y#0 <-> xnext1#0: MayAlias
// CHECK-DAG: y#0 <-> xnext2#0: MayAlias

// We need to catch the fact that assigning y to x will modify xnext.
// The only side-effect between the 2 loads of x.next is the assignment to x,
// therefore x needs to alias with x.next to prevent the loads from being merged.
// CHECK-DAG: x#0 <-> xnext1#0: MayAlias
// CHECK-DAG: x#0 <-> xnext2#0: MayAlias

// TODO: xnext1#0 <-> xnext2#0 are the same and therefore MustAlias but
// we are currently not comparing operands involved in offset computations
// CHECK-DAG: xnext1#0 <-> xnext2#0: MayAlias

func.func @_QMmPfoo(%arg0: !fir.ref<!fir.type<_QMmTt{next:!fir.box<!fir.ptr<!fir.type<_QMmTt>>>,i:i32}>> {fir.bindc_name = "x"}, %arg1: !fir.ref<!fir.type<_QMmTt{next:!fir.box<!fir.ptr<!fir.type<_QMmTt>>>,i:i32}>> {fir.bindc_name = "y"}) {
%0 = fir.alloca i32 {bindc_name = "i1", uniq_name = "_QMmFfooEi1"}
%1:2 = hlfir.declare %0 {uniq_name = "_QMmFfooEi1"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>)
%2 = fir.alloca i32 {bindc_name = "i2", uniq_name = "_QMmFfooEi2"}
%3:2 = hlfir.declare %2 {uniq_name = "_QMmFfooEi2"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>)
%4:2 = hlfir.declare %arg0 {uniq_name = "_QMmFfooEx", test.ptr = "x"} : (!fir.ref<!fir.type<_QMmTt{next:!fir.box<!fir.ptr<!fir.type<_QMmTt>>>,i:i32}>>) -> (!fir.ref<!fir.type<_QMmTt{next:!fir.box<!fir.ptr<!fir.type<_QMmTt>>>,i:i32}>>, !fir.ref<!fir.type<_QMmTt{next:!fir.box<!fir.ptr<!fir.type<_QMmTt>>>,i:i32}>>)
%5:2 = hlfir.declare %arg1 {uniq_name = "_QMmFfooEy", test.ptr = "y"} : (!fir.ref<!fir.type<_QMmTt{next:!fir.box<!fir.ptr<!fir.type<_QMmTt>>>,i:i32}>>) -> (!fir.ref<!fir.type<_QMmTt{next:!fir.box<!fir.ptr<!fir.type<_QMmTt>>>,i:i32}>>, !fir.ref<!fir.type<_QMmTt{next:!fir.box<!fir.ptr<!fir.type<_QMmTt>>>,i:i32}>>)
%6 = hlfir.designate %4#0{"next"} {fortran_attrs = #fir.var_attrs<pointer>, test.ptr = "xnext1"} : (!fir.ref<!fir.type<_QMmTt{next:!fir.box<!fir.ptr<!fir.type<_QMmTt>>>,i:i32}>>) -> !fir.ref<!fir.box<!fir.ptr<!fir.type<_QMmTt{next:!fir.box<!fir.ptr<!fir.type<_QMmTt>>>,i:i32}>>>>
%7 = fir.load %6 : !fir.ref<!fir.box<!fir.ptr<!fir.type<_QMmTt{next:!fir.box<!fir.ptr<!fir.type<_QMmTt>>>,i:i32}>>>>
%8 = fir.box_addr %7 : (!fir.box<!fir.ptr<!fir.type<_QMmTt{next:!fir.box<!fir.ptr<!fir.type<_QMmTt>>>,i:i32}>>>) -> !fir.ptr<!fir.type<_QMmTt{next:!fir.box<!fir.ptr<!fir.type<_QMmTt>>>,i:i32}>>
%9 = hlfir.designate %8{"i"} : (!fir.ptr<!fir.type<_QMmTt{next:!fir.box<!fir.ptr<!fir.type<_QMmTt>>>,i:i32}>>) -> !fir.ref<i32>
%10 = fir.load %9 : !fir.ref<i32>
hlfir.assign %10 to %1#0 : i32, !fir.ref<i32>
hlfir.assign %5#0 to %4#0 : !fir.ref<!fir.type<_QMmTt{next:!fir.box<!fir.ptr<!fir.type<_QMmTt>>>,i:i32}>>, !fir.ref<!fir.type<_QMmTt{next:!fir.box<!fir.ptr<!fir.type<_QMmTt>>>,i:i32}>>
%11 = hlfir.designate %4#0{"next"} {fortran_attrs = #fir.var_attrs<pointer>, test.ptr = "xnext2"} : (!fir.ref<!fir.type<_QMmTt{next:!fir.box<!fir.ptr<!fir.type<_QMmTt>>>,i:i32}>>) -> !fir.ref<!fir.box<!fir.ptr<!fir.type<_QMmTt{next:!fir.box<!fir.ptr<!fir.type<_QMmTt>>>,i:i32}>>>>
%12 = fir.load %11 : !fir.ref<!fir.box<!fir.ptr<!fir.type<_QMmTt{next:!fir.box<!fir.ptr<!fir.type<_QMmTt>>>,i:i32}>>>>
%13 = fir.box_addr %12 : (!fir.box<!fir.ptr<!fir.type<_QMmTt{next:!fir.box<!fir.ptr<!fir.type<_QMmTt>>>,i:i32}>>>) -> !fir.ptr<!fir.type<_QMmTt{next:!fir.box<!fir.ptr<!fir.type<_QMmTt>>>,i:i32}>>
%14 = hlfir.designate %13{"i"} : (!fir.ptr<!fir.type<_QMmTt{next:!fir.box<!fir.ptr<!fir.type<_QMmTt>>>,i:i32}>>) -> !fir.ref<i32>
%15 = fir.load %14 : !fir.ref<i32>
hlfir.assign %15 to %3#0 : i32, !fir.ref<i32>
return
}
2 changes: 1 addition & 1 deletion flang/test/Fir/omp-reduction-embox-codegen.fir
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ omp.declare_reduction @test_reduction : !fir.ref<!fir.box<i32>> init {

func.func @_QQmain() attributes {fir.bindc_name = "reduce"} {
%4 = fir.alloca !fir.box<i32>
omp.parallel byref reduction(@test_reduction %4 -> %arg0 : !fir.ref<!fir.box<i32>>) {
omp.parallel reduction(byref @test_reduction %4 -> %arg0 : !fir.ref<!fir.box<i32>>) {
omp.terminator
}
return
Expand Down
2 changes: 1 addition & 1 deletion flang/test/Lower/OpenMP/default-clause-byref.f90
Original file line number Diff line number Diff line change
Expand Up @@ -351,7 +351,7 @@ subroutine skipped_default_clause_checks()
type(it)::iii

!CHECK: omp.parallel {
!CHECK: omp.wsloop byref reduction(@min_byref_i32 %[[VAL_Z_DECLARE]]#0 -> %[[PRV:.+]] : !fir.ref<i32>) {
!CHECK: omp.wsloop reduction(byref @min_byref_i32 %[[VAL_Z_DECLARE]]#0 -> %[[PRV:.+]] : !fir.ref<i32>) {
!CHECK-NEXT: omp.loop_nest (%[[ARG:.*]]) {{.*}} {
!CHECK: omp.yield
!CHECK: }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,5 +26,5 @@ subroutine red_and_delayed_private

! CHECK-LABEL: _QPred_and_delayed_private
! CHECK: omp.parallel
! CHECK-SAME: reduction(@[[REDUCTION_SYM]] %{{.*}} -> %arg0 : !fir.ref<i32>)
! CHECK-SAME: reduction(byref @[[REDUCTION_SYM]] %{{.*}} -> %arg0 : !fir.ref<i32>)
! CHECK-SAME: private(@[[PRIVATIZER_SYM]] %{{.*}} -> %arg1 : !fir.ref<i32>) {
6 changes: 3 additions & 3 deletions flang/test/Lower/OpenMP/parallel-reduction-add-byref.f90
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@
!CHECK: %[[I_DECL:.*]]:2 = hlfir.declare %[[IREF]] {uniq_name = "_QFsimple_int_addEi"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>)
!CHECK: %[[I_START:.*]] = arith.constant 0 : i32
!CHECK: hlfir.assign %[[I_START]] to %[[I_DECL]]#0 : i32, !fir.ref<i32>
!CHECK: omp.parallel byref reduction(@[[RED_I32_NAME]] %[[I_DECL]]#0 -> %[[PRV:.+]] : !fir.ref<i32>) {
!CHECK: omp.parallel reduction(byref @[[RED_I32_NAME]] %[[I_DECL]]#0 -> %[[PRV:.+]] : !fir.ref<i32>) {
!CHECK: %[[P_DECL:.+]]:2 = hlfir.declare %[[PRV]] {{.*}} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>)
!CHECK: %[[LPRV:.+]] = fir.load %[[P_DECL]]#0 : !fir.ref<i32>
!CHECK: %[[I_INCR:.*]] = arith.constant 1 : i32
Expand All @@ -65,7 +65,7 @@ subroutine simple_int_add
!CHECK: %[[R_DECL:.*]]:2 = hlfir.declare %[[RREF]] {uniq_name = "_QFsimple_real_addEr"} : (!fir.ref<f32>) -> (!fir.ref<f32>, !fir.ref<f32>)
!CHECK: %[[R_START:.*]] = arith.constant 0.000000e+00 : f32
!CHECK: hlfir.assign %[[R_START]] to %[[R_DECL]]#0 : f32, !fir.ref<f32>
!CHECK: omp.parallel byref reduction(@[[RED_F32_NAME]] %[[R_DECL]]#0 -> %[[PRV:.+]] : !fir.ref<f32>) {
!CHECK: omp.parallel reduction(byref @[[RED_F32_NAME]] %[[R_DECL]]#0 -> %[[PRV:.+]] : !fir.ref<f32>) {
!CHECK: %[[P_DECL:.+]]:2 = hlfir.declare %[[PRV]] {{.*}} : (!fir.ref<f32>) -> (!fir.ref<f32>, !fir.ref<f32>)
!CHECK: %[[LPRV:.+]] = fir.load %[[P_DECL]]#0 : !fir.ref<f32>
!CHECK: %[[R_INCR:.*]] = arith.constant 1.500000e+00 : f32
Expand Down Expand Up @@ -94,7 +94,7 @@ subroutine simple_real_add
!CHECK: hlfir.assign %[[R_START]] to %[[R_DECL]]#0 : f32, !fir.ref<f32>
!CHECK: %[[I_START:.*]] = arith.constant 0 : i32
!CHECK: hlfir.assign %[[I_START]] to %[[I_DECL]]#0 : i32, !fir.ref<i32>
!CHECK: omp.parallel byref reduction(@[[RED_I32_NAME]] %[[I_DECL]]#0 -> %[[IPRV:.+]] : !fir.ref<i32>, @[[RED_F32_NAME]] %[[R_DECL]]#0 -> %[[RPRV:.+]] : !fir.ref<f32>) {
!CHECK: omp.parallel reduction(byref @[[RED_I32_NAME]] %[[I_DECL]]#0 -> %[[IPRV:.+]] : !fir.ref<i32>, byref @[[RED_F32_NAME]] %[[R_DECL]]#0 -> %[[RPRV:.+]] : !fir.ref<f32>) {
!CHECK: %[[IP_DECL:.+]]:2 = hlfir.declare %[[IPRV]] {{.*}} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>)
!CHECK: %[[RP_DECL:.+]]:2 = hlfir.declare %[[RPRV]] {{.*}} : (!fir.ref<f32>) -> (!fir.ref<f32>, !fir.ref<f32>)
!CHECK: %[[R_INCR:.*]] = arith.constant 1.500000e+00 : f32
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ program reduce
! CHECK: %[[VAL_14:.*]] = arith.constant 0 : i32
! CHECK: %[[VAL_15:.*]] = arith.constant 10 : i32
! CHECK: %[[VAL_16:.*]] = arith.constant 1 : i32
! CHECK: omp.wsloop byref reduction(@add_reduction_byref_box_heap_Uxi32 %[[VAL_3]]#0 -> %[[VAL_17:.*]] : !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>) {
! CHECK: omp.wsloop reduction(byref @add_reduction_byref_box_heap_Uxi32 %[[VAL_3]]#0 -> %[[VAL_17:.*]] : !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>) {
! CHECK-NEXT: omp.loop_nest (%[[VAL_18:.*]]) : i32 = (%[[VAL_14]]) to (%[[VAL_15]]) inclusive step (%[[VAL_16]]) {
! CHECK: %[[VAL_19:.*]]:2 = hlfir.declare %[[VAL_17]] {fortran_attrs = {{.*}}<allocatable>, uniq_name = "_QFEr"} : (!fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>) -> (!fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>, !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>)
! CHECK: fir.store %[[VAL_18]] to %[[VAL_13]]#1 : !fir.ref<i32>
Expand Down
2 changes: 1 addition & 1 deletion flang/test/Lower/OpenMP/parallel-reduction-array-lb.f90
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ program reduce
! CHECK: %[[VAL_6:.*]]:2 = hlfir.declare %[[VAL_0]](%[[VAL_5]]) {uniq_name = "_QFEi"} : (!fir.ref<!fir.array<3x2xi32>>, !fir.shapeshift<2>) -> (!fir.box<!fir.array<3x2xi32>>, !fir.ref<!fir.array<3x2xi32>>)
! CHECK: %[[VAL_7:.*]] = fir.alloca !fir.box<!fir.array<3x2xi32>>
! CHECK: fir.store %[[VAL_6]]#0 to %[[VAL_7]] : !fir.ref<!fir.box<!fir.array<3x2xi32>>>
! CHECK: omp.parallel byref reduction(@add_reduction_byref_box_3x2xi32 %[[VAL_7]] -> %[[VAL_8:.*]] : !fir.ref<!fir.box<!fir.array<3x2xi32>>>) {
! CHECK: omp.parallel reduction(byref @add_reduction_byref_box_3x2xi32 %[[VAL_7]] -> %[[VAL_8:.*]] : !fir.ref<!fir.box<!fir.array<3x2xi32>>>) {
! CHECK: %[[VAL_9:.*]]:2 = hlfir.declare %[[VAL_8]] {uniq_name = "_QFEi"} : (!fir.ref<!fir.box<!fir.array<3x2xi32>>>) -> (!fir.ref<!fir.box<!fir.array<3x2xi32>>>, !fir.ref<!fir.box<!fir.array<3x2xi32>>>)
! CHECK: %[[VAL_10:.*]] = arith.constant 3 : i32
! CHECK: %[[VAL_11:.*]] = fir.load %[[VAL_9]]#0 : !fir.ref<!fir.box<!fir.array<3x2xi32>>>
Expand Down
2 changes: 1 addition & 1 deletion flang/test/Lower/OpenMP/parallel-reduction-array.f90
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ program reduce
! CHECK: %[[VAL_4:.*]] = fir.embox %[[VAL_3]]#0(%[[VAL_2]]) : (!fir.ref<!fir.array<3xi32>>, !fir.shape<1>) -> !fir.box<!fir.array<3xi32>>
! CHECK: %[[VAL_5:.*]] = fir.alloca !fir.box<!fir.array<3xi32>>
! CHECK: fir.store %[[VAL_4]] to %[[VAL_5]] : !fir.ref<!fir.box<!fir.array<3xi32>>>
! CHECK: omp.parallel byref reduction(@add_reduction_byref_box_3xi32 %[[VAL_5]] -> %[[VAL_6:.*]] : !fir.ref<!fir.box<!fir.array<3xi32>>>) {
! CHECK: omp.parallel reduction(byref @add_reduction_byref_box_3xi32 %[[VAL_5]] -> %[[VAL_6:.*]] : !fir.ref<!fir.box<!fir.array<3xi32>>>) {
! CHECK: %[[VAL_7:.*]]:2 = hlfir.declare %[[VAL_6]] {uniq_name = "_QFEi"} : (!fir.ref<!fir.box<!fir.array<3xi32>>>) -> (!fir.ref<!fir.box<!fir.array<3xi32>>>, !fir.ref<!fir.box<!fir.array<3xi32>>>)
! CHECK: %[[VAL_8:.*]] = arith.constant 1 : i32
! CHECK: %[[VAL_9:.*]] = fir.load %[[VAL_7]]#0 : !fir.ref<!fir.box<!fir.array<3xi32>>>
Expand Down
2 changes: 1 addition & 1 deletion flang/test/Lower/OpenMP/parallel-reduction-array2.f90
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ program reduce
! CHECK: %[[VAL_4:.*]] = fir.embox %[[VAL_3]]#0(%[[VAL_2]]) : (!fir.ref<!fir.array<3xi32>>, !fir.shape<1>) -> !fir.box<!fir.array<3xi32>>
! CHECK: %[[VAL_5:.*]] = fir.alloca !fir.box<!fir.array<3xi32>>
! CHECK: fir.store %[[VAL_4]] to %[[VAL_5]] : !fir.ref<!fir.box<!fir.array<3xi32>>>
! CHECK: omp.parallel byref reduction(@add_reduction_byref_box_3xi32 %[[VAL_5]] -> %[[VAL_6:.*]] : !fir.ref<!fir.box<!fir.array<3xi32>>>) {
! CHECK: omp.parallel reduction(byref @add_reduction_byref_box_3xi32 %[[VAL_5]] -> %[[VAL_6:.*]] : !fir.ref<!fir.box<!fir.array<3xi32>>>) {
! CHECK: %[[VAL_7:.*]]:2 = hlfir.declare %[[VAL_6]] {uniq_name = "_QFEi"} : (!fir.ref<!fir.box<!fir.array<3xi32>>>) -> (!fir.ref<!fir.box<!fir.array<3xi32>>>, !fir.ref<!fir.box<!fir.array<3xi32>>>)
! CHECK: %[[VAL_8:.*]] = fir.load %[[VAL_7]]#0 : !fir.ref<!fir.box<!fir.array<3xi32>>>
! CHECK: %[[VAL_9:.*]] = arith.constant 1 : index
Expand Down
2 changes: 1 addition & 1 deletion flang/test/Lower/OpenMP/parallel-reduction-byref.f90
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
!CHECK: %[[RED_ACCUM_DECL:[_a-z0-9]+]]:2 = hlfir.declare %[[RED_ACCUM_REF]] {uniq_name = "_QFEi"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>)
!CHECK: %[[C0:[_a-z0-9]+]] = arith.constant 0 : i32
!CHECK: hlfir.assign %[[C0]] to %[[RED_ACCUM_DECL]]#0 : i32, !fir.ref<i32>
!CHECK: omp.parallel byref reduction(@[[REDUCTION_DECLARE]] %[[RED_ACCUM_DECL]]#0 -> %[[PRIVATE_RED:[a-z0-9]+]] : !fir.ref<i32>) {
!CHECK: omp.parallel reduction(byref @[[REDUCTION_DECLARE]] %[[RED_ACCUM_DECL]]#0 -> %[[PRIVATE_RED:[a-z0-9]+]] : !fir.ref<i32>) {
!CHECK: %[[PRIVATE_DECL:[_a-z0-9]+]]:2 = hlfir.declare %[[PRIVATE_RED]] {uniq_name = "_QFEi"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>)
!CHECK: %[[C1:[_a-z0-9]+]] = arith.constant 1 : i32
!CHECK: hlfir.assign %[[C1]] to %[[PRIVATE_DECL]]#0 : i32, !fir.ref<i32>
Expand Down
2 changes: 1 addition & 1 deletion flang/test/Lower/OpenMP/parallel-reduction3.f90
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@
! CHECK: %[[VAL_18:.*]] = arith.constant 1 : i32
! CHECK: %[[VAL_19:.*]] = fir.alloca !fir.box<!fir.array<?xi32>>
! CHECK: fir.store %[[VAL_12]]#0 to %[[VAL_19]] : !fir.ref<!fir.box<!fir.array<?xi32>>>
! CHECK: omp.wsloop byref reduction(@add_reduction_byref_box_Uxi32 %[[VAL_19]] -> %[[VAL_20:.*]] : !fir.ref<!fir.box<!fir.array<?xi32>>>) {
! CHECK: omp.wsloop reduction(byref @add_reduction_byref_box_Uxi32 %[[VAL_19]] -> %[[VAL_20:.*]] : !fir.ref<!fir.box<!fir.array<?xi32>>>) {
! CHECK-NEXT: omp.loop_nest (%[[VAL_21:.*]]) : i32 = (%[[VAL_16]]) to (%[[VAL_17]]) inclusive step (%[[VAL_18]]) {
! CHECK: %[[VAL_22:.*]]:2 = hlfir.declare %[[VAL_20]] {uniq_name = "_QFsEc"} : (!fir.ref<!fir.box<!fir.array<?xi32>>>) -> (!fir.ref<!fir.box<!fir.array<?xi32>>>, !fir.ref<!fir.box<!fir.array<?xi32>>>)
! CHECK: fir.store %[[VAL_21]] to %[[VAL_15]]#1 : !fir.ref<i32>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
! RUN: flang-new -fc1 -fopenmp -mmlir --force-byref-reduction -emit-hlfir %s -o - | FileCheck %s

! CHECK: omp.parallel {
! CHECK: omp.wsloop byref reduction(@add_reduction_byref_i32
! CHECK: omp.wsloop reduction(byref @add_reduction_byref_i32
subroutine sb
integer :: x
x = 0
Expand Down
14 changes: 7 additions & 7 deletions flang/test/Lower/OpenMP/wsloop-reduction-add-byref.f90
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@
! CHECK: %[[VAL_7:.*]] = arith.constant 1 : i32
! CHECK: %[[VAL_8:.*]] = arith.constant 100 : i32
! CHECK: %[[VAL_9:.*]] = arith.constant 1 : i32
! CHECK: omp.wsloop byref reduction(@add_reduction_byref_i32 %[[VAL_3]]#0 -> %[[VAL_10:.*]] : !fir.ref<i32>) {
! CHECK: omp.wsloop reduction(byref @add_reduction_byref_i32 %[[VAL_3]]#0 -> %[[VAL_10:.*]] : !fir.ref<i32>) {
! CHECK-NEXT: omp.loop_nest (%[[VAL_11:.*]]) : i32 = (%[[VAL_7]]) to (%[[VAL_8]]) inclusive step (%[[VAL_9]]) {
! CHECK: %[[VAL_12:.*]]:2 = hlfir.declare %[[VAL_10]] {uniq_name = "_QFsimple_int_reductionEx"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>)
! CHECK: fir.store %[[VAL_11]] to %[[VAL_6]]#1 : !fir.ref<i32>
Expand Down Expand Up @@ -125,7 +125,7 @@ subroutine simple_int_reduction
! CHECK: %[[VAL_7:.*]] = arith.constant 1 : i32
! CHECK: %[[VAL_8:.*]] = arith.constant 100 : i32
! CHECK: %[[VAL_9:.*]] = arith.constant 1 : i32
! CHECK: omp.wsloop byref reduction(@add_reduction_byref_f32 %[[VAL_3]]#0 -> %[[VAL_10:.*]] : !fir.ref<f32>) {
! CHECK: omp.wsloop reduction(byref @add_reduction_byref_f32 %[[VAL_3]]#0 -> %[[VAL_10:.*]] : !fir.ref<f32>) {
! CHECK-NEXT: omp.loop_nest (%[[VAL_11:.*]]) : i32 = (%[[VAL_7]]) to (%[[VAL_8]]) inclusive step (%[[VAL_9]]) {
! CHECK: %[[VAL_12:.*]]:2 = hlfir.declare %[[VAL_10]] {uniq_name = "_QFsimple_real_reductionEx"} : (!fir.ref<f32>) -> (!fir.ref<f32>, !fir.ref<f32>)
! CHECK: fir.store %[[VAL_11]] to %[[VAL_6]]#1 : !fir.ref<i32>
Expand Down Expand Up @@ -169,7 +169,7 @@ subroutine simple_real_reduction
! CHECK: %[[VAL_7:.*]] = arith.constant 1 : i32
! CHECK: %[[VAL_8:.*]] = arith.constant 100 : i32
! CHECK: %[[VAL_9:.*]] = arith.constant 1 : i32
! CHECK: omp.wsloop byref reduction(@add_reduction_byref_i32 %[[VAL_3]]#0 -> %[[VAL_10:.*]] : !fir.ref<i32>) {
! CHECK: omp.wsloop reduction(byref @add_reduction_byref_i32 %[[VAL_3]]#0 -> %[[VAL_10:.*]] : !fir.ref<i32>) {
! CHECK-NEXT: omp.loop_nest (%[[VAL_11:.*]]) : i32 = (%[[VAL_7]]) to (%[[VAL_8]]) inclusive step (%[[VAL_9]]) {
! CHECK: %[[VAL_12:.*]]:2 = hlfir.declare %[[VAL_10]] {uniq_name = "_QFsimple_int_reduction_switch_orderEx"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>)
! CHECK: fir.store %[[VAL_11]] to %[[VAL_6]]#1 : !fir.ref<i32>
Expand Down Expand Up @@ -211,7 +211,7 @@ subroutine simple_int_reduction_switch_order
! CHECK: %[[VAL_7:.*]] = arith.constant 1 : i32
! CHECK: %[[VAL_8:.*]] = arith.constant 100 : i32
! CHECK: %[[VAL_9:.*]] = arith.constant 1 : i32
! CHECK: omp.wsloop byref reduction(@add_reduction_byref_f32 %[[VAL_3]]#0 -> %[[VAL_10:.*]] : !fir.ref<f32>) {
! CHECK: omp.wsloop reduction(byref @add_reduction_byref_f32 %[[VAL_3]]#0 -> %[[VAL_10:.*]] : !fir.ref<f32>) {
! CHECK-NEXT: omp.loop_nest (%[[VAL_11:.*]]) : i32 = (%[[VAL_7]]) to (%[[VAL_8]]) inclusive step (%[[VAL_9]]) {
! CHECK: %[[VAL_12:.*]]:2 = hlfir.declare %[[VAL_10]] {uniq_name = "_QFsimple_real_reduction_switch_orderEx"} : (!fir.ref<f32>) -> (!fir.ref<f32>, !fir.ref<f32>)
! CHECK: fir.store %[[VAL_11]] to %[[VAL_6]]#1 : !fir.ref<i32>
Expand Down Expand Up @@ -262,7 +262,7 @@ subroutine simple_real_reduction_switch_order
! CHECK: %[[VAL_13:.*]] = arith.constant 1 : i32
! CHECK: %[[VAL_14:.*]] = arith.constant 100 : i32
! CHECK: %[[VAL_15:.*]] = arith.constant 1 : i32
! CHECK: omp.wsloop byref reduction(@add_reduction_byref_i32 %[[VAL_3]]#0 -> %[[VAL_16:.*]] : !fir.ref<i32>, @add_reduction_byref_i32 %[[VAL_5]]#0 -> %[[VAL_17:.*]] : !fir.ref<i32>, @add_reduction_byref_i32 %[[VAL_7]]#0 -> %[[VAL_18:.*]] : !fir.ref<i32>) {
! CHECK: omp.wsloop reduction(byref @add_reduction_byref_i32 %[[VAL_3]]#0 -> %[[VAL_16:.*]] : !fir.ref<i32>, byref @add_reduction_byref_i32 %[[VAL_5]]#0 -> %[[VAL_17:.*]] : !fir.ref<i32>, byref @add_reduction_byref_i32 %[[VAL_7]]#0 -> %[[VAL_18:.*]] : !fir.ref<i32>) {
! CHECK-NEXT: omp.loop_nest (%[[VAL_19:.*]]) : i32 = (%[[VAL_13]]) to (%[[VAL_14]]) inclusive step (%[[VAL_15]]) {
! CHECK: %[[VAL_20:.*]]:2 = hlfir.declare %[[VAL_16]] {uniq_name = "_QFmultiple_int_reductions_same_typeEx"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>)
! CHECK: %[[VAL_21:.*]]:2 = hlfir.declare %[[VAL_17]] {uniq_name = "_QFmultiple_int_reductions_same_typeEy"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>)
Expand Down Expand Up @@ -326,7 +326,7 @@ subroutine multiple_int_reductions_same_type
! CHECK: %[[VAL_13:.*]] = arith.constant 1 : i32
! CHECK: %[[VAL_14:.*]] = arith.constant 100 : i32
! CHECK: %[[VAL_15:.*]] = arith.constant 1 : i32
! CHECK: omp.wsloop byref reduction(@add_reduction_byref_f32 %[[VAL_3]]#0 -> %[[VAL_16:.*]] : !fir.ref<f32>, @add_reduction_byref_f32 %[[VAL_5]]#0 -> %[[VAL_17:.*]] : !fir.ref<f32>, @add_reduction_byref_f32 %[[VAL_7]]#0 -> %[[VAL_18:.*]] : !fir.ref<f32>) {
! CHECK: omp.wsloop reduction(byref @add_reduction_byref_f32 %[[VAL_3]]#0 -> %[[VAL_16:.*]] : !fir.ref<f32>, byref @add_reduction_byref_f32 %[[VAL_5]]#0 -> %[[VAL_17:.*]] : !fir.ref<f32>, byref @add_reduction_byref_f32 %[[VAL_7]]#0 -> %[[VAL_18:.*]] : !fir.ref<f32>) {
! CHECK-NEXT: omp.loop_nest (%[[VAL_19:.*]]) : i32 = (%[[VAL_13]]) to (%[[VAL_14]]) inclusive step (%[[VAL_15]]) {
! CHECK: %[[VAL_20:.*]]:2 = hlfir.declare %[[VAL_16]] {uniq_name = "_QFmultiple_real_reductions_same_typeEx"} : (!fir.ref<f32>) -> (!fir.ref<f32>, !fir.ref<f32>)
! CHECK: %[[VAL_21:.*]]:2 = hlfir.declare %[[VAL_17]] {uniq_name = "_QFmultiple_real_reductions_same_typeEy"} : (!fir.ref<f32>) -> (!fir.ref<f32>, !fir.ref<f32>)
Expand Down Expand Up @@ -397,7 +397,7 @@ subroutine multiple_real_reductions_same_type
! CHECK: %[[VAL_16:.*]] = arith.constant 1 : i32
! CHECK: %[[VAL_17:.*]] = arith.constant 100 : i32
! CHECK: %[[VAL_18:.*]] = arith.constant 1 : i32
! CHECK: omp.wsloop byref reduction(@add_reduction_byref_i32 %[[VAL_5]]#0 -> %[[VAL_19:.*]] : !fir.ref<i32>, @add_reduction_byref_i64 %[[VAL_7]]#0 -> %[[VAL_20:.*]] : !fir.ref<i64>, @add_reduction_byref_f32 %[[VAL_9]]#0 -> %[[VAL_21:.*]] : !fir.ref<f32>, @add_reduction_byref_f64 %[[VAL_3]]#0 -> %[[VAL_22:.*]] : !fir.ref<f64>) {
! CHECK: omp.wsloop reduction(byref @add_reduction_byref_i32 %[[VAL_5]]#0 -> %[[VAL_19:.*]] : !fir.ref<i32>, byref @add_reduction_byref_i64 %[[VAL_7]]#0 -> %[[VAL_20:.*]] : !fir.ref<i64>, byref @add_reduction_byref_f32 %[[VAL_9]]#0 -> %[[VAL_21:.*]] : !fir.ref<f32>, byref @add_reduction_byref_f64 %[[VAL_3]]#0 -> %[[VAL_22:.*]] : !fir.ref<f64>) {
! CHECK-NEXT: omp.loop_nest (%[[VAL_23:.*]]) : i32 = (%[[VAL_16]]) to (%[[VAL_17]]) inclusive step (%[[VAL_18]]) {
! CHECK: %[[VAL_24:.*]]:2 = hlfir.declare %[[VAL_19]] {uniq_name = "_QFmultiple_reductions_different_typeEx"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>)
! CHECK: %[[VAL_25:.*]]:2 = hlfir.declare %[[VAL_20]] {uniq_name = "_QFmultiple_reductions_different_typeEy"} : (!fir.ref<i64>) -> (!fir.ref<i64>, !fir.ref<i64>)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@
! CHECK: %[[VAL_7:.*]] = arith.constant 1 : i32
! CHECK: %[[VAL_8:.*]] = arith.constant 100 : i32
! CHECK: %[[VAL_9:.*]] = arith.constant 1 : i32
! CHECK: omp.wsloop byref reduction(@add_reduction_byref_i32 %[[VAL_3]]#0 -> %[[VAL_10:.*]] : !fir.ref<i32>) {
! CHECK: omp.wsloop reduction(byref @add_reduction_byref_i32 %[[VAL_3]]#0 -> %[[VAL_10:.*]] : !fir.ref<i32>) {
! CHECK-NEXT: omp.loop_nest (%[[VAL_11:.*]]) : i32 = (%[[VAL_7]]) to (%[[VAL_8]]) inclusive step (%[[VAL_9]]) {
! CHECK: %[[VAL_12:.*]]:2 = hlfir.declare %[[VAL_10]] {uniq_name = "_QFsimple_int_reductionEx"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>)
! CHECK: fir.store %[[VAL_11]] to %[[VAL_6]]#1 : !fir.ref<i32>
Expand Down
2 changes: 1 addition & 1 deletion flang/test/Lower/OpenMP/wsloop-reduction-allocatable.f90
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ program reduce
! CHECK: %[[VAL_11:.*]] = arith.constant 0 : i32
! CHECK: %[[VAL_12:.*]] = arith.constant 10 : i32
! CHECK: %[[VAL_13:.*]] = arith.constant 1 : i32
! CHECK: omp.wsloop byref reduction(@add_reduction_byref_box_heap_i32 %[[VAL_5]]#0 -> %[[VAL_14:.*]] : !fir.ref<!fir.box<!fir.heap<i32>>>) {
! CHECK: omp.wsloop reduction(byref @add_reduction_byref_box_heap_i32 %[[VAL_5]]#0 -> %[[VAL_14:.*]] : !fir.ref<!fir.box<!fir.heap<i32>>>) {
! CHECK-NEXT: omp.loop_nest (%[[VAL_15:.*]]) : i32 = (%[[VAL_11]]) to (%[[VAL_12]]) inclusive step (%[[VAL_13]]) {
! CHECK: %[[VAL_16:.*]]:2 = hlfir.declare %[[VAL_14]] {fortran_attrs = {{.*}}<allocatable>, uniq_name = "_QFEr"} : (!fir.ref<!fir.box<!fir.heap<i32>>>) -> (!fir.ref<!fir.box<!fir.heap<i32>>>, !fir.ref<!fir.box<!fir.heap<i32>>>)
! CHECK: fir.store %[[VAL_15]] to %[[VAL_10]]#1 : !fir.ref<i32>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ subroutine reduce(r)
! CHECK: %[[VAL_8:.*]] = arith.constant 1 : i32
! CHECK: %[[VAL_9:.*]] = fir.alloca !fir.box<!fir.array<?xf64>>
! CHECK: fir.store %[[VAL_3]]#1 to %[[VAL_9]] : !fir.ref<!fir.box<!fir.array<?xf64>>>
! CHECK: omp.wsloop byref reduction(@add_reduction_byref_box_Uxf64 %[[VAL_9]] -> %[[VAL_10:.*]] : !fir.ref<!fir.box<!fir.array<?xf64>>>) {
! CHECK: omp.wsloop reduction(byref @add_reduction_byref_box_Uxf64 %[[VAL_9]] -> %[[VAL_10:.*]] : !fir.ref<!fir.box<!fir.array<?xf64>>>) {
! CHECK-NEXT: omp.loop_nest (%[[VAL_11:.*]]) : i32 = (%[[VAL_6]]) to (%[[VAL_7]]) inclusive step (%[[VAL_8]]) {
! CHECK: %[[VAL_12:.*]]:2 = hlfir.declare %[[VAL_10]] {fortran_attrs = {{.*}}, uniq_name = "_QFFreduceEr"} : (!fir.ref<!fir.box<!fir.array<?xf64>>>) -> (!fir.ref<!fir.box<!fir.array<?xf64>>>, !fir.ref<!fir.box<!fir.array<?xf64>>>)
! CHECK: fir.store %[[VAL_11]] to %[[VAL_5]]#1 : !fir.ref<i32>
Expand Down
2 changes: 1 addition & 1 deletion flang/test/Lower/OpenMP/wsloop-reduction-array.f90
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ program reduce
! CHECK: %[[VAL_11:.*]] = fir.embox %[[VAL_5]]#0(%[[VAL_4]]) : (!fir.ref<!fir.array<2xi32>>, !fir.shape<1>) -> !fir.box<!fir.array<2xi32>>
! CHECK: %[[VAL_12:.*]] = fir.alloca !fir.box<!fir.array<2xi32>>
! CHECK: fir.store %[[VAL_11]] to %[[VAL_12]] : !fir.ref<!fir.box<!fir.array<2xi32>>>
! CHECK: omp.wsloop byref reduction(@add_reduction_byref_box_2xi32 %[[VAL_12]] -> %[[VAL_13:.*]] : !fir.ref<!fir.box<!fir.array<2xi32>>>) {
! CHECK: omp.wsloop reduction(byref @add_reduction_byref_box_2xi32 %[[VAL_12]] -> %[[VAL_13:.*]] : !fir.ref<!fir.box<!fir.array<2xi32>>>) {
! CHECK-NEXT: omp.loop_nest (%[[VAL_14:.*]]) : i32 = (%[[VAL_8]]) to (%[[VAL_9]]) inclusive step (%[[VAL_10]]) {
! CHECK: %[[VAL_15:.*]]:2 = hlfir.declare %[[VAL_13]] {uniq_name = "_QFEr"} : (!fir.ref<!fir.box<!fir.array<2xi32>>>) -> (!fir.ref<!fir.box<!fir.array<2xi32>>>, !fir.ref<!fir.box<!fir.array<2xi32>>>)
! CHECK: fir.store %[[VAL_14]] to %[[VAL_7]]#1 : !fir.ref<i32>
Expand Down
2 changes: 1 addition & 1 deletion flang/test/Lower/OpenMP/wsloop-reduction-array2.f90
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ program reduce
! CHECK: %[[VAL_11:.*]] = fir.embox %[[VAL_5]]#0(%[[VAL_4]]) : (!fir.ref<!fir.array<2xi32>>, !fir.shape<1>) -> !fir.box<!fir.array<2xi32>>
! CHECK: %[[VAL_12:.*]] = fir.alloca !fir.box<!fir.array<2xi32>>
! CHECK: fir.store %[[VAL_11]] to %[[VAL_12]] : !fir.ref<!fir.box<!fir.array<2xi32>>>
! CHECK: omp.wsloop byref reduction(@add_reduction_byref_box_2xi32 %[[VAL_12]] -> %[[VAL_13:.*]] : !fir.ref<!fir.box<!fir.array<2xi32>>>) {
! CHECK: omp.wsloop reduction(byref @add_reduction_byref_box_2xi32 %[[VAL_12]] -> %[[VAL_13:.*]] : !fir.ref<!fir.box<!fir.array<2xi32>>>) {
! CHECK-NEXT: omp.loop_nest (%[[VAL_14:.*]]) : i32 = (%[[VAL_8]]) to (%[[VAL_9]]) inclusive step (%[[VAL_10]]) {
! CHECK: %[[VAL_15:.*]]:2 = hlfir.declare %[[VAL_13]] {uniq_name = "_QFEr"} : (!fir.ref<!fir.box<!fir.array<2xi32>>>) -> (!fir.ref<!fir.box<!fir.array<2xi32>>>, !fir.ref<!fir.box<!fir.array<2xi32>>>)
! CHECK: fir.store %[[VAL_14]] to %[[VAL_7]]#1 : !fir.ref<i32>
Expand Down
2 changes: 1 addition & 1 deletion flang/test/Lower/OpenMP/wsloop-reduction-iand-byref.f90
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@
! CHECK: %[[VAL_9:.*]] = arith.constant 1 : i32
! CHECK: %[[VAL_10:.*]] = arith.constant 100 : i32
! CHECK: %[[VAL_11:.*]] = arith.constant 1 : i32
! CHECK: omp.wsloop byref reduction(@iand_byref_i32 %[[VAL_4]]#0 -> %[[VAL_12:.*]] : !fir.ref<i32>) {
! CHECK: omp.wsloop reduction(byref @iand_byref_i32 %[[VAL_4]]#0 -> %[[VAL_12:.*]] : !fir.ref<i32>) {
! CHECK-NEXT: omp.loop_nest (%[[VAL_13:.*]]) : i32 = (%[[VAL_9]]) to (%[[VAL_10]]) inclusive step (%[[VAL_11]]) {
! CHECK: %[[VAL_14:.*]]:2 = hlfir.declare %[[VAL_12]] {uniq_name = "_QFreduction_iandEx"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>)
! CHECK: fir.store %[[VAL_13]] to %[[VAL_8]]#1 : !fir.ref<i32>
Expand Down
2 changes: 1 addition & 1 deletion flang/test/Lower/OpenMP/wsloop-reduction-ieor-byref.f90
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
!CHECK: omp.parallel
!CHECK: %[[I_REF:.*]] = fir.alloca i32 {adapt.valuebyref, pinned}
!CHECK: %[[I_DECL:.*]]:2 = hlfir.declare %[[I_REF]] {uniq_name = "_QFreduction_ieorEi"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>)
!CHECK: omp.wsloop byref reduction(@ieor_byref_i32 %[[X_DECL]]#0 -> %[[PRV:.+]] : !fir.ref<i32>)
!CHECK: omp.wsloop reduction(byref @ieor_byref_i32 %[[X_DECL]]#0 -> %[[PRV:.+]] : !fir.ref<i32>)
!CHECK-NEXT: omp.loop_nest
!CHECK: %[[PRV_DECL:.+]]:2 = hlfir.declare %[[PRV]] {{.*}} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>)
!CHECK: fir.store %{{.*}} to %[[I_DECL]]#1 : !fir.ref<i32>
Expand Down
2 changes: 1 addition & 1 deletion flang/test/Lower/OpenMP/wsloop-reduction-ior-byref.f90
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@
! CHECK: %[[VAL_9:.*]] = arith.constant 1 : i32
! CHECK: %[[VAL_10:.*]] = arith.constant 100 : i32
! CHECK: %[[VAL_11:.*]] = arith.constant 1 : i32
! CHECK: omp.wsloop byref reduction(@ior_byref_i32 %[[VAL_4]]#0 -> %[[VAL_12:.*]] : !fir.ref<i32>) {
! CHECK: omp.wsloop reduction(byref @ior_byref_i32 %[[VAL_4]]#0 -> %[[VAL_12:.*]] : !fir.ref<i32>) {
! CHECK-NEXT: omp.loop_nest (%[[VAL_13:.*]]) : i32 = (%[[VAL_9]]) to (%[[VAL_10]]) inclusive step (%[[VAL_11]]) {
! CHECK: %[[VAL_14:.*]]:2 = hlfir.declare %[[VAL_12]] {uniq_name = "_QFreduction_iorEx"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>)
! CHECK: fir.store %[[VAL_13]] to %[[VAL_8]]#1 : !fir.ref<i32>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@
! CHECK: %[[VAL_12:.*]] = arith.constant 1 : i32
! CHECK: %[[VAL_13:.*]] = arith.constant 100 : i32
! CHECK: %[[VAL_14:.*]] = arith.constant 1 : i32
! CHECK: omp.wsloop byref reduction(@and_reduction %[[VAL_4]]#0 -> %[[VAL_15:.*]] : !fir.ref<!fir.logical<4>>) {
! CHECK: omp.wsloop reduction(byref @and_reduction %[[VAL_4]]#0 -> %[[VAL_15:.*]] : !fir.ref<!fir.logical<4>>) {
! CHECK-NEXT: omp.loop_nest (%[[VAL_16:.*]]) : i32 = (%[[VAL_12]]) to (%[[VAL_13]]) inclusive step (%[[VAL_14]]) {
! CHECK: %[[VAL_17:.*]]:2 = hlfir.declare %[[VAL_15]] {uniq_name = "_QFsimple_reductionEx"} : (!fir.ref<!fir.logical<4>>) -> (!fir.ref<!fir.logical<4>>, !fir.ref<!fir.logical<4>>)
! CHECK: fir.store %[[VAL_16]] to %[[VAL_11]]#1 : !fir.ref<i32>
Expand Down Expand Up @@ -92,7 +92,7 @@ end subroutine simple_reduction
! CHECK: %[[VAL_12:.*]] = arith.constant 1 : i32
! CHECK: %[[VAL_13:.*]] = arith.constant 100 : i32
! CHECK: %[[VAL_14:.*]] = arith.constant 1 : i32
! CHECK: omp.wsloop byref reduction(@and_reduction %[[VAL_4]]#0 -> %[[VAL_15:.*]] : !fir.ref<!fir.logical<4>>) {
! CHECK: omp.wsloop reduction(byref @and_reduction %[[VAL_4]]#0 -> %[[VAL_15:.*]] : !fir.ref<!fir.logical<4>>) {
! CHECK-NEXT: omp.loop_nest (%[[VAL_16:.*]]) : i32 = (%[[VAL_12]]) to (%[[VAL_13]]) inclusive step (%[[VAL_14]]) {
! CHECK: %[[VAL_17:.*]]:2 = hlfir.declare %[[VAL_15]] {uniq_name = "_QFsimple_reduction_switch_orderEx"} : (!fir.ref<!fir.logical<4>>) -> (!fir.ref<!fir.logical<4>>, !fir.ref<!fir.logical<4>>)
! CHECK: fir.store %[[VAL_16]] to %[[VAL_11]]#1 : !fir.ref<i32>
Expand Down Expand Up @@ -151,7 +151,7 @@ subroutine simple_reduction_switch_order(y)
! CHECK: %[[VAL_20:.*]] = arith.constant 1 : i32
! CHECK: %[[VAL_21:.*]] = arith.constant 100 : i32
! CHECK: %[[VAL_22:.*]] = arith.constant 1 : i32
! CHECK: omp.wsloop byref reduction(@and_reduction %[[VAL_7]]#0 -> %[[VAL_23:.*]] : !fir.ref<!fir.logical<4>>, @and_reduction %[[VAL_9]]#0 -> %[[VAL_24:.*]] : !fir.ref<!fir.logical<4>>, @and_reduction %[[VAL_11]]#0 -> %[[VAL_25:.*]] : !fir.ref<!fir.logical<4>>) {
! CHECK: omp.wsloop reduction(byref @and_reduction %[[VAL_7]]#0 -> %[[VAL_23:.*]] : !fir.ref<!fir.logical<4>>, byref @and_reduction %[[VAL_9]]#0 -> %[[VAL_24:.*]] : !fir.ref<!fir.logical<4>>, byref @and_reduction %[[VAL_11]]#0 -> %[[VAL_25:.*]] : !fir.ref<!fir.logical<4>>) {
! CHECK-NEXT: omp.loop_nest (%[[VAL_26:.*]]) : i32 = (%[[VAL_20]]) to (%[[VAL_21]]) inclusive step (%[[VAL_22]]) {
! CHECK: %[[VAL_27:.*]]:2 = hlfir.declare %[[VAL_23]] {uniq_name = "_QFmultiple_reductionsEx"} : (!fir.ref<!fir.logical<4>>) -> (!fir.ref<!fir.logical<4>>, !fir.ref<!fir.logical<4>>)
! CHECK: %[[VAL_28:.*]]:2 = hlfir.declare %[[VAL_24]] {uniq_name = "_QFmultiple_reductionsEy"} : (!fir.ref<!fir.logical<4>>) -> (!fir.ref<!fir.logical<4>>, !fir.ref<!fir.logical<4>>)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@
! CHECK: %[[VAL_12:.*]] = arith.constant 1 : i32
! CHECK: %[[VAL_13:.*]] = arith.constant 100 : i32
! CHECK: %[[VAL_14:.*]] = arith.constant 1 : i32
! CHECK: omp.wsloop byref reduction(@eqv_reduction %[[VAL_4]]#0 -> %[[VAL_15:.*]] : !fir.ref<!fir.logical<4>>) {
! CHECK: omp.wsloop reduction(byref @eqv_reduction %[[VAL_4]]#0 -> %[[VAL_15:.*]] : !fir.ref<!fir.logical<4>>) {
! CHECK-NEXT: omp.loop_nest (%[[VAL_16:.*]]) : i32 = (%[[VAL_12]]) to (%[[VAL_13]]) inclusive step (%[[VAL_14]]) {
! CHECK: %[[VAL_17:.*]]:2 = hlfir.declare %[[VAL_15]] {uniq_name = "_QFsimple_reductionEx"} : (!fir.ref<!fir.logical<4>>) -> (!fir.ref<!fir.logical<4>>, !fir.ref<!fir.logical<4>>)
! CHECK: fir.store %[[VAL_16]] to %[[VAL_11]]#1 : !fir.ref<i32>
Expand Down Expand Up @@ -91,7 +91,7 @@ subroutine simple_reduction(y)
! CHECK: %[[VAL_12:.*]] = arith.constant 1 : i32
! CHECK: %[[VAL_13:.*]] = arith.constant 100 : i32
! CHECK: %[[VAL_14:.*]] = arith.constant 1 : i32
! CHECK: omp.wsloop byref reduction(@eqv_reduction %[[VAL_4]]#0 -> %[[VAL_15:.*]] : !fir.ref<!fir.logical<4>>) {
! CHECK: omp.wsloop reduction(byref @eqv_reduction %[[VAL_4]]#0 -> %[[VAL_15:.*]] : !fir.ref<!fir.logical<4>>) {
! CHECK-NEXT: omp.loop_nest (%[[VAL_16:.*]]) : i32 = (%[[VAL_12]]) to (%[[VAL_13]]) inclusive step (%[[VAL_14]]) {
! CHECK: %[[VAL_17:.*]]:2 = hlfir.declare %[[VAL_15]] {uniq_name = "_QFsimple_reduction_switch_orderEx"} : (!fir.ref<!fir.logical<4>>) -> (!fir.ref<!fir.logical<4>>, !fir.ref<!fir.logical<4>>)
! CHECK: fir.store %[[VAL_16]] to %[[VAL_11]]#1 : !fir.ref<i32>
Expand Down Expand Up @@ -150,7 +150,7 @@ subroutine simple_reduction_switch_order(y)
! CHECK: %[[VAL_20:.*]] = arith.constant 1 : i32
! CHECK: %[[VAL_21:.*]] = arith.constant 100 : i32
! CHECK: %[[VAL_22:.*]] = arith.constant 1 : i32
! CHECK: omp.wsloop byref reduction(@eqv_reduction %[[VAL_7]]#0 -> %[[VAL_23:.*]] : !fir.ref<!fir.logical<4>>, @eqv_reduction %[[VAL_9]]#0 -> %[[VAL_24:.*]] : !fir.ref<!fir.logical<4>>, @eqv_reduction %[[VAL_11]]#0 -> %[[VAL_25:.*]] : !fir.ref<!fir.logical<4>>) {
! CHECK: omp.wsloop reduction(byref @eqv_reduction %[[VAL_7]]#0 -> %[[VAL_23:.*]] : !fir.ref<!fir.logical<4>>, byref @eqv_reduction %[[VAL_9]]#0 -> %[[VAL_24:.*]] : !fir.ref<!fir.logical<4>>, byref @eqv_reduction %[[VAL_11]]#0 -> %[[VAL_25:.*]] : !fir.ref<!fir.logical<4>>) {
! CHECK-NEXT: omp.loop_nest (%[[VAL_26:.*]]) : i32 = (%[[VAL_20]]) to (%[[VAL_21]]) inclusive step (%[[VAL_22]]) {
! CHECK: %[[VAL_27:.*]]:2 = hlfir.declare %[[VAL_23]] {uniq_name = "_QFmultiple_reductionsEx"} : (!fir.ref<!fir.logical<4>>) -> (!fir.ref<!fir.logical<4>>, !fir.ref<!fir.logical<4>>)
! CHECK: %[[VAL_28:.*]]:2 = hlfir.declare %[[VAL_24]] {uniq_name = "_QFmultiple_reductionsEy"} : (!fir.ref<!fir.logical<4>>) -> (!fir.ref<!fir.logical<4>>, !fir.ref<!fir.logical<4>>)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@
! CHECK: %[[VAL_12:.*]] = arith.constant 1 : i32
! CHECK: %[[VAL_13:.*]] = arith.constant 100 : i32
! CHECK: %[[VAL_14:.*]] = arith.constant 1 : i32
! CHECK: omp.wsloop byref reduction(@neqv_reduction %[[VAL_4]]#0 -> %[[VAL_15:.*]] : !fir.ref<!fir.logical<4>>) {
! CHECK: omp.wsloop reduction(byref @neqv_reduction %[[VAL_4]]#0 -> %[[VAL_15:.*]] : !fir.ref<!fir.logical<4>>) {
! CHECK-NEXT: omp.loop_nest (%[[VAL_16:.*]]) : i32 = (%[[VAL_12]]) to (%[[VAL_13]]) inclusive step (%[[VAL_14]]) {
! CHECK: %[[VAL_17:.*]]:2 = hlfir.declare %[[VAL_15]] {uniq_name = "_QFsimple_reductionEx"} : (!fir.ref<!fir.logical<4>>) -> (!fir.ref<!fir.logical<4>>, !fir.ref<!fir.logical<4>>)
! CHECK: fir.store %[[VAL_16]] to %[[VAL_11]]#1 : !fir.ref<i32>
Expand Down Expand Up @@ -92,7 +92,7 @@ subroutine simple_reduction(y)
! CHECK: %[[VAL_12:.*]] = arith.constant 1 : i32
! CHECK: %[[VAL_13:.*]] = arith.constant 100 : i32
! CHECK: %[[VAL_14:.*]] = arith.constant 1 : i32
! CHECK: omp.wsloop byref reduction(@neqv_reduction %[[VAL_4]]#0 -> %[[VAL_15:.*]] : !fir.ref<!fir.logical<4>>) {
! CHECK: omp.wsloop reduction(byref @neqv_reduction %[[VAL_4]]#0 -> %[[VAL_15:.*]] : !fir.ref<!fir.logical<4>>) {
! CHECK-NEXT: omp.loop_nest (%[[VAL_16:.*]]) : i32 = (%[[VAL_12]]) to (%[[VAL_13]]) inclusive step (%[[VAL_14]]) {
! CHECK: %[[VAL_17:.*]]:2 = hlfir.declare %[[VAL_15]] {uniq_name = "_QFsimple_reduction_switch_orderEx"} : (!fir.ref<!fir.logical<4>>) -> (!fir.ref<!fir.logical<4>>, !fir.ref<!fir.logical<4>>)
! CHECK: fir.store %[[VAL_16]] to %[[VAL_11]]#1 : !fir.ref<i32>
Expand Down Expand Up @@ -153,7 +153,7 @@ subroutine simple_reduction_switch_order(y)
! CHECK: %[[VAL_20:.*]] = arith.constant 1 : i32
! CHECK: %[[VAL_21:.*]] = arith.constant 100 : i32
! CHECK: %[[VAL_22:.*]] = arith.constant 1 : i32
! CHECK: omp.wsloop byref reduction(@neqv_reduction %[[VAL_7]]#0 -> %[[VAL_23:.*]] : !fir.ref<!fir.logical<4>>, @neqv_reduction %[[VAL_9]]#0 -> %[[VAL_24:.*]] : !fir.ref<!fir.logical<4>>, @neqv_reduction %[[VAL_11]]#0 -> %[[VAL_25:.*]] : !fir.ref<!fir.logical<4>>) {
! CHECK: omp.wsloop reduction(byref @neqv_reduction %[[VAL_7]]#0 -> %[[VAL_23:.*]] : !fir.ref<!fir.logical<4>>, byref @neqv_reduction %[[VAL_9]]#0 -> %[[VAL_24:.*]] : !fir.ref<!fir.logical<4>>, byref @neqv_reduction %[[VAL_11]]#0 -> %[[VAL_25:.*]] : !fir.ref<!fir.logical<4>>) {
! CHECK-NEXT: omp.loop_nest (%[[VAL_26:.*]]) : i32 = (%[[VAL_20]]) to (%[[VAL_21]]) inclusive step (%[[VAL_22]]) {
! CHECK: %[[VAL_27:.*]]:2 = hlfir.declare %[[VAL_23]] {uniq_name = "_QFmultiple_reductionsEx"} : (!fir.ref<!fir.logical<4>>) -> (!fir.ref<!fir.logical<4>>, !fir.ref<!fir.logical<4>>)
! CHECK: %[[VAL_28:.*]]:2 = hlfir.declare %[[VAL_24]] {uniq_name = "_QFmultiple_reductionsEy"} : (!fir.ref<!fir.logical<4>>) -> (!fir.ref<!fir.logical<4>>, !fir.ref<!fir.logical<4>>)
Expand Down
6 changes: 3 additions & 3 deletions flang/test/Lower/OpenMP/wsloop-reduction-logical-or-byref.f90
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@
! CHECK: %[[VAL_12:.*]] = arith.constant 1 : i32
! CHECK: %[[VAL_13:.*]] = arith.constant 100 : i32
! CHECK: %[[VAL_14:.*]] = arith.constant 1 : i32
! CHECK: omp.wsloop byref reduction(@or_reduction %[[VAL_4]]#0 -> %[[VAL_15:.*]] : !fir.ref<!fir.logical<4>>) {
! CHECK: omp.wsloop reduction(byref @or_reduction %[[VAL_4]]#0 -> %[[VAL_15:.*]] : !fir.ref<!fir.logical<4>>) {
! CHECK-NEXT: omp.loop_nest (%[[VAL_16:.*]]) : i32 = (%[[VAL_12]]) to (%[[VAL_13]]) inclusive step (%[[VAL_14]]) {
! CHECK: %[[VAL_17:.*]]:2 = hlfir.declare %[[VAL_15]] {uniq_name = "_QFsimple_reductionEx"} : (!fir.ref<!fir.logical<4>>) -> (!fir.ref<!fir.logical<4>>, !fir.ref<!fir.logical<4>>)
! CHECK: fir.store %[[VAL_16]] to %[[VAL_11]]#1 : !fir.ref<i32>
Expand Down Expand Up @@ -90,7 +90,7 @@ subroutine simple_reduction(y)
! CHECK: %[[VAL_12:.*]] = arith.constant 1 : i32
! CHECK: %[[VAL_13:.*]] = arith.constant 100 : i32
! CHECK: %[[VAL_14:.*]] = arith.constant 1 : i32
! CHECK: omp.wsloop byref reduction(@or_reduction %[[VAL_4]]#0 -> %[[VAL_15:.*]] : !fir.ref<!fir.logical<4>>) {
! CHECK: omp.wsloop reduction(byref @or_reduction %[[VAL_4]]#0 -> %[[VAL_15:.*]] : !fir.ref<!fir.logical<4>>) {
! CHECK-NEXT: omp.loop_nest (%[[VAL_16:.*]]) : i32 = (%[[VAL_12]]) to (%[[VAL_13]]) inclusive step (%[[VAL_14]]) {
! CHECK: %[[VAL_17:.*]]:2 = hlfir.declare %[[VAL_15]] {uniq_name = "_QFsimple_reduction_switch_orderEx"} : (!fir.ref<!fir.logical<4>>) -> (!fir.ref<!fir.logical<4>>, !fir.ref<!fir.logical<4>>)
! CHECK: fir.store %[[VAL_16]] to %[[VAL_11]]#1 : !fir.ref<i32>
Expand Down Expand Up @@ -149,7 +149,7 @@ subroutine simple_reduction_switch_order(y)
! CHECK: %[[VAL_20:.*]] = arith.constant 1 : i32
! CHECK: %[[VAL_21:.*]] = arith.constant 100 : i32
! CHECK: %[[VAL_22:.*]] = arith.constant 1 : i32
! CHECK: omp.wsloop byref reduction(@or_reduction %[[VAL_7]]#0 -> %[[VAL_23:.*]] : !fir.ref<!fir.logical<4>>, @or_reduction %[[VAL_9]]#0 -> %[[VAL_24:.*]] : !fir.ref<!fir.logical<4>>, @or_reduction %[[VAL_11]]#0 -> %[[VAL_25:.*]] : !fir.ref<!fir.logical<4>>) {
! CHECK: omp.wsloop reduction(byref @or_reduction %[[VAL_7]]#0 -> %[[VAL_23:.*]] : !fir.ref<!fir.logical<4>>, byref @or_reduction %[[VAL_9]]#0 -> %[[VAL_24:.*]] : !fir.ref<!fir.logical<4>>, byref @or_reduction %[[VAL_11]]#0 -> %[[VAL_25:.*]] : !fir.ref<!fir.logical<4>>) {
! CHECK-NEXT: omp.loop_nest (%[[VAL_26:.*]]) : i32 = (%[[VAL_20]]) to (%[[VAL_21]]) inclusive step (%[[VAL_22]]) {
! CHECK: %[[VAL_27:.*]]:2 = hlfir.declare %[[VAL_23]] {uniq_name = "_QFmultiple_reductionsEx"} : (!fir.ref<!fir.logical<4>>) -> (!fir.ref<!fir.logical<4>>, !fir.ref<!fir.logical<4>>)
! CHECK: %[[VAL_28:.*]]:2 = hlfir.declare %[[VAL_24]] {uniq_name = "_QFmultiple_reductionsEy"} : (!fir.ref<!fir.logical<4>>) -> (!fir.ref<!fir.logical<4>>, !fir.ref<!fir.logical<4>>)
Expand Down
Loading