aboutsummaryrefslogtreecommitdiff
path: root/flang/lib/Lower/OpenMP
diff options
context:
space:
mode:
Diffstat (limited to 'flang/lib/Lower/OpenMP')
-rw-r--r--flang/lib/Lower/OpenMP/Atomic.cpp37
-rw-r--r--flang/lib/Lower/OpenMP/ClauseProcessor.cpp88
-rw-r--r--flang/lib/Lower/OpenMP/Clauses.cpp95
-rw-r--r--flang/lib/Lower/OpenMP/DataSharingProcessor.cpp30
-rw-r--r--flang/lib/Lower/OpenMP/OpenMP.cpp301
-rw-r--r--flang/lib/Lower/OpenMP/Utils.cpp109
-rw-r--r--flang/lib/Lower/OpenMP/Utils.h2
7 files changed, 407 insertions, 255 deletions
diff --git a/flang/lib/Lower/OpenMP/Atomic.cpp b/flang/lib/Lower/OpenMP/Atomic.cpp
index 6ea331c..c9a6dba 100644
--- a/flang/lib/Lower/OpenMP/Atomic.cpp
+++ b/flang/lib/Lower/OpenMP/Atomic.cpp
@@ -528,8 +528,8 @@ genAtomicRead(lower::AbstractConverter &converter,
}();
builder.restoreInsertionPoint(atomicAt);
- mlir::Operation *op = builder.create<mlir::omp::AtomicReadOp>(
- loc, atomAddr, toAddr, mlir::TypeAttr::get(atomType), hint,
+ mlir::Operation *op = mlir::omp::AtomicReadOp::create(
+ builder, loc, atomAddr, toAddr, mlir::TypeAttr::get(atomType), hint,
makeMemOrderAttr(converter, memOrder));
if (atomType != storeType) {
@@ -537,7 +537,7 @@ genAtomicRead(lower::AbstractConverter &converter,
// The READ operation could be a part of UPDATE CAPTURE, so make sure
// we don't emit extra code into the body of the atomic op.
builder.restoreInsertionPoint(postAt);
- mlir::Value load = builder.create<fir::LoadOp>(loc, toAddr);
+ mlir::Value load = fir::LoadOp::create(builder, loc, toAddr);
overrides.try_emplace(&atom, load);
converter.overrideExprValues(&overrides);
@@ -545,7 +545,7 @@ genAtomicRead(lower::AbstractConverter &converter,
fir::getBase(converter.genExprValue(assign.rhs, stmtCtx, &loc));
converter.resetExprOverrides();
- builder.create<fir::StoreOp>(loc, value, storeAddr);
+ fir::StoreOp::create(builder, loc, value, storeAddr);
}
return op;
}
@@ -581,8 +581,9 @@ genAtomicWrite(lower::AbstractConverter &converter,
mlir::Value converted = builder.createConvert(loc, atomType, value);
builder.restoreInsertionPoint(atomicAt);
- mlir::Operation *op = builder.create<mlir::omp::AtomicWriteOp>(
- loc, atomAddr, converted, hint, makeMemOrderAttr(converter, memOrder));
+ mlir::Operation *op =
+ mlir::omp::AtomicWriteOp::create(builder, loc, atomAddr, converted, hint,
+ makeMemOrderAttr(converter, memOrder));
return op;
}
@@ -606,7 +607,7 @@ genAtomicUpdate(lower::AbstractConverter &converter,
// This must exist by now.
semantics::SomeExpr rhs = assign.rhs;
semantics::SomeExpr input = *evaluate::GetConvertInput(rhs);
- auto [opcode, args] = evaluate::GetTopLevelOperation(input);
+ auto [opcode, args] = evaluate::GetTopLevelOperationIgnoreResizing(input);
assert(!args.empty() && "Update operation without arguments");
// Pass args as an argument to avoid capturing a structured binding.
@@ -624,7 +625,8 @@ genAtomicUpdate(lower::AbstractConverter &converter,
// operations with exactly two (non-optional) arguments.
rhs = genReducedMinMax(rhs, atomArg, args);
input = *evaluate::GetConvertInput(rhs);
- std::tie(opcode, args) = evaluate::GetTopLevelOperation(input);
+ std::tie(opcode, args) =
+ evaluate::GetTopLevelOperationIgnoreResizing(input);
atomArg = nullptr; // No longer valid.
}
for (auto &arg : args) {
@@ -634,9 +636,16 @@ genAtomicUpdate(lower::AbstractConverter &converter,
}
}
+ mlir::ModuleOp module = builder.getModule();
+ mlir::omp::AtomicControlAttr atomicControlAttr =
+ mlir::omp::AtomicControlAttr::get(
+ builder.getContext(), fir::getAtomicIgnoreDenormalMode(module),
+ fir::getAtomicFineGrainedMemory(module),
+ fir::getAtomicRemoteMemory(module));
builder.restoreInsertionPoint(atomicAt);
- auto updateOp = builder.create<mlir::omp::AtomicUpdateOp>(
- loc, atomAddr, hint, makeMemOrderAttr(converter, memOrder));
+ auto updateOp = mlir::omp::AtomicUpdateOp::create(
+ builder, loc, atomAddr, atomicControlAttr, hint,
+ makeMemOrderAttr(converter, memOrder));
mlir::Region &region = updateOp->getRegion(0);
mlir::Block *block = builder.createBlock(&region, {}, {atomType}, {loc});
@@ -647,7 +656,7 @@ genAtomicUpdate(lower::AbstractConverter &converter,
mlir::Value updated =
fir::getBase(converter.genExprValue(rhs, stmtCtx, &loc));
mlir::Value converted = builder.createConvert(loc, atomType, updated);
- builder.create<mlir::omp::YieldOp>(loc, converted);
+ mlir::omp::YieldOp::create(builder, loc, converted);
converter.resetExprOverrides();
builder.restoreInsertionPoint(postAt); // For naCtx cleanups
@@ -731,8 +740,8 @@ void Fortran::lower::omp::lowerAtomic(
"Expexcing two actions");
(void)action0;
(void)action1;
- captureOp = builder.create<mlir::omp::AtomicCaptureOp>(
- loc, hint, makeMemOrderAttr(converter, memOrder));
+ captureOp = mlir::omp::AtomicCaptureOp::create(
+ builder, loc, hint, makeMemOrderAttr(converter, memOrder));
// Set the non-atomic insertion point to before the atomic.capture.
preAt = getInsertionPointBefore(captureOp);
@@ -740,7 +749,7 @@ void Fortran::lower::omp::lowerAtomic(
builder.setInsertionPointToEnd(block);
// Set the atomic insertion point to before the terminator inside
// atomic.capture.
- mlir::Operation *term = builder.create<mlir::omp::TerminatorOp>(loc);
+ mlir::Operation *term = mlir::omp::TerminatorOp::create(builder, loc);
atomicAt = getInsertionPointBefore(term);
postAt = getInsertionPointAfter(captureOp);
hint = nullptr;
diff --git a/flang/lib/Lower/OpenMP/ClauseProcessor.cpp b/flang/lib/Lower/OpenMP/ClauseProcessor.cpp
index 74087d4..594f95e 100644
--- a/flang/lib/Lower/OpenMP/ClauseProcessor.cpp
+++ b/flang/lib/Lower/OpenMP/ClauseProcessor.cpp
@@ -723,7 +723,7 @@ bool ClauseProcessor::processCopyin() const {
// barrier is inserted following all of them.
firOpBuilder.restoreInsertionPoint(insPt);
if (hasCopyin)
- firOpBuilder.create<mlir::omp::BarrierOp>(converter.getCurrentLocation());
+ mlir::omp::BarrierOp::create(firOpBuilder, converter.getCurrentLocation());
return hasCopyin;
}
@@ -803,7 +803,7 @@ createCopyFunc(mlir::Location loc, lower::AbstractConverter &converter,
llvm::SmallVector<mlir::Type> argsTy = {varType, varType};
auto funcType = mlir::FunctionType::get(builder.getContext(), argsTy, {});
mlir::func::FuncOp funcOp =
- modBuilder.create<mlir::func::FuncOp>(loc, copyFuncName, funcType);
+ mlir::func::FuncOp::create(modBuilder, loc, copyFuncName, funcType);
funcOp.setVisibility(mlir::SymbolTable::Visibility::Private);
fir::factory::setInternalLinkage(funcOp);
builder.createBlock(&funcOp.getRegion(), funcOp.getRegion().end(), argsTy,
@@ -819,22 +819,22 @@ createCopyFunc(mlir::Location loc, lower::AbstractConverter &converter,
for (auto extent : typeInfo.getShape())
extents.push_back(
builder.createIntegerConstant(loc, builder.getIndexType(), extent));
- shape = builder.create<fir::ShapeOp>(loc, extents);
+ shape = fir::ShapeOp::create(builder, loc, extents);
}
mlir::Value dst = funcOp.getArgument(0);
mlir::Value src = funcOp.getArgument(1);
llvm::SmallVector<mlir::Value> typeparams;
if (typeInfo.isBoxChar()) {
// fir.boxchar will be passed here as fir.ref<fir.boxchar>
- auto loadDst = builder.create<fir::LoadOp>(loc, dst);
- auto loadSrc = builder.create<fir::LoadOp>(loc, src);
+ auto loadDst = fir::LoadOp::create(builder, loc, dst);
+ auto loadSrc = fir::LoadOp::create(builder, loc, src);
// get the actual fir.ref<fir.char> type
mlir::Type refType =
fir::ReferenceType::get(mlir::cast<fir::BoxCharType>(eleTy).getEleTy());
- auto unboxedDst = builder.create<fir::UnboxCharOp>(
- loc, refType, builder.getIndexType(), loadDst);
- auto unboxedSrc = builder.create<fir::UnboxCharOp>(
- loc, refType, builder.getIndexType(), loadSrc);
+ auto unboxedDst = fir::UnboxCharOp::create(builder, loc, refType,
+ builder.getIndexType(), loadDst);
+ auto unboxedSrc = fir::UnboxCharOp::create(builder, loc, refType,
+ builder.getIndexType(), loadSrc);
// Add length to type parameters
typeparams.push_back(unboxedDst.getResult(1));
dst = unboxedDst.getResult(0);
@@ -844,14 +844,14 @@ createCopyFunc(mlir::Location loc, lower::AbstractConverter &converter,
loc, builder.getCharacterLengthType(), *typeInfo.getCharLength());
typeparams.push_back(charLen);
}
- auto declDst = builder.create<hlfir::DeclareOp>(
- loc, dst, copyFuncName + "_dst", shape, typeparams,
+ auto declDst = hlfir::DeclareOp::create(
+ builder, loc, dst, copyFuncName + "_dst", shape, typeparams,
/*dummy_scope=*/nullptr, attrs);
- auto declSrc = builder.create<hlfir::DeclareOp>(
- loc, src, copyFuncName + "_src", shape, typeparams,
+ auto declSrc = hlfir::DeclareOp::create(
+ builder, loc, src, copyFuncName + "_src", shape, typeparams,
/*dummy_scope=*/nullptr, attrs);
converter.copyVar(loc, declDst.getBase(), declSrc.getBase(), varAttrs);
- builder.create<mlir::func::ReturnOp>(loc);
+ mlir::func::ReturnOp::create(builder, loc);
return funcOp;
}
@@ -882,8 +882,8 @@ bool ClauseProcessor::processCopyprivate(
if (mlir::isa<fir::BaseBoxType>(symType) ||
mlir::isa<fir::BoxCharType>(symType)) {
fir::FirOpBuilder &builder = converter.getFirOpBuilder();
- auto alloca = builder.create<fir::AllocaOp>(currentLocation, symType);
- builder.create<fir::StoreOp>(currentLocation, symVal, alloca);
+ auto alloca = fir::AllocaOp::create(builder, currentLocation, symType);
+ fir::StoreOp::create(builder, currentLocation, symVal, alloca);
cpVar = alloca;
}
@@ -1002,8 +1002,8 @@ bool ClauseProcessor::processDepend(lower::SymMap &symMap,
// allocations so this is not a reliable way to identify the dependency.
if (auto ref = mlir::dyn_cast<fir::ReferenceType>(dependVar.getType()))
if (fir::isa_box_type(ref.getElementType()))
- dependVar = builder.create<fir::LoadOp>(
- converter.getCurrentLocation(), dependVar);
+ dependVar = fir::LoadOp::create(
+ builder, converter.getCurrentLocation(), dependVar);
// The openmp dialect doesn't know what to do with boxes (and it would
// break layering to teach it about them). The dependency variable can be
@@ -1012,8 +1012,8 @@ bool ClauseProcessor::processDepend(lower::SymMap &symMap,
// Getting the address of the box data is okay because all the runtime
// ultimately cares about is the base address of the array.
if (fir::isa_box_type(dependVar.getType()))
- dependVar = builder.create<fir::BoxAddrOp>(
- converter.getCurrentLocation(), dependVar);
+ dependVar = fir::BoxAddrOp::create(
+ builder, converter.getCurrentLocation(), dependVar);
result.dependVars.push_back(dependVar);
}
@@ -1116,11 +1116,12 @@ bool ClauseProcessor::processInReduction(
collectReductionSyms(clause, inReductionSyms);
ReductionProcessor rp;
- rp.processReductionArguments<mlir::omp::DeclareReductionOp>(
- currentLocation, converter,
- std::get<typename omp::clause::ReductionOperatorList>(clause.t),
- inReductionVars, inReduceVarByRef, inReductionDeclSymbols,
- inReductionSyms);
+ if (!rp.processReductionArguments<mlir::omp::DeclareReductionOp>(
+ currentLocation, converter,
+ std::get<typename omp::clause::ReductionOperatorList>(clause.t),
+ inReductionVars, inReduceVarByRef, inReductionDeclSymbols,
+ inReductionSyms))
+ inReductionSyms.clear();
// Copy local lists into the output.
llvm::copy(inReductionVars, std::back_inserter(result.inReductionVars));
@@ -1315,7 +1316,8 @@ bool ClauseProcessor::processMap(
const parser::CharBlock &source) {
using Map = omp::clause::Map;
mlir::Location clauseLocation = converter.genLocation(source);
- const auto &[mapType, typeMods, mappers, iterator, objects] = clause.t;
+ const auto &[mapType, typeMods, refMod, mappers, iterator, objects] =
+ clause.t;
llvm::omp::OpenMPOffloadMappingFlags mapTypeBits =
llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_NONE;
std::string mapperIdName = "__implicit_mapper";
@@ -1342,16 +1344,13 @@ bool ClauseProcessor::processMap(
mapTypeBits |= llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_TO |
llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_FROM;
break;
- case Map::MapType::Alloc:
- case Map::MapType::Release:
+ case Map::MapType::Storage:
// alloc and release is the default map_type for the Target Data
// Ops, i.e. if no bits for map_type is supplied then alloc/release
- // is implicitly assumed based on the target directive. Default
- // value for Target Data and Enter Data is alloc and for Exit Data
- // it is release.
+ // (aka storage in 6.0+) is implicitly assumed based on the target
+ // directive. Default value for Target Data and Enter Data is alloc
+ // and for Exit Data it is release.
break;
- case Map::MapType::Delete:
- mapTypeBits |= llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_DELETE;
}
if (typeMods) {
@@ -1362,6 +1361,8 @@ bool ClauseProcessor::processMap(
mapTypeBits |= llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_PRESENT;
if (llvm::is_contained(*typeMods, Map::MapTypeModifier::Close))
mapTypeBits |= llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_CLOSE;
+ if (llvm::is_contained(*typeMods, Map::MapTypeModifier::Delete))
+ mapTypeBits |= llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_DELETE;
if (llvm::is_contained(*typeMods, Map::MapTypeModifier::OmpxHold))
mapTypeBits |= llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_OMPX_HOLD;
}
@@ -1461,10 +1462,12 @@ bool ClauseProcessor::processReduction(
}
ReductionProcessor rp;
- rp.processReductionArguments<mlir::omp::DeclareReductionOp>(
- currentLocation, converter,
- std::get<typename omp::clause::ReductionOperatorList>(clause.t),
- reductionVars, reduceVarByRef, reductionDeclSymbols, reductionSyms);
+ if (!rp.processReductionArguments<mlir::omp::DeclareReductionOp>(
+ currentLocation, converter,
+ std::get<typename omp::clause::ReductionOperatorList>(clause.t),
+ reductionVars, reduceVarByRef, reductionDeclSymbols,
+ reductionSyms))
+ reductionSyms.clear();
// Copy local lists into the output.
llvm::copy(reductionVars, std::back_inserter(result.reductionVars));
llvm::copy(reduceVarByRef, std::back_inserter(result.reductionByref));
@@ -1486,11 +1489,12 @@ bool ClauseProcessor::processTaskReduction(
collectReductionSyms(clause, taskReductionSyms);
ReductionProcessor rp;
- rp.processReductionArguments<mlir::omp::DeclareReductionOp>(
- currentLocation, converter,
- std::get<typename omp::clause::ReductionOperatorList>(clause.t),
- taskReductionVars, taskReduceVarByRef, taskReductionDeclSymbols,
- taskReductionSyms);
+ if (!rp.processReductionArguments<mlir::omp::DeclareReductionOp>(
+ currentLocation, converter,
+ std::get<typename omp::clause::ReductionOperatorList>(clause.t),
+ taskReductionVars, taskReduceVarByRef, taskReductionDeclSymbols,
+ taskReductionSyms))
+ taskReductionSyms.clear();
// Copy local lists into the output.
llvm::copy(taskReductionVars,
std::back_inserter(result.taskReductionVars));
diff --git a/flang/lib/Lower/OpenMP/Clauses.cpp b/flang/lib/Lower/OpenMP/Clauses.cpp
index 22a0721..686fba0 100644
--- a/flang/lib/Lower/OpenMP/Clauses.cpp
+++ b/flang/lib/Lower/OpenMP/Clauses.cpp
@@ -1001,19 +1001,21 @@ Map make(const parser::OmpClause::Map &inp,
semantics::SemanticsContext &semaCtx) {
// inp.v -> parser::OmpMapClause
CLAUSET_ENUM_CONVERT( //
- convert1, parser::OmpMapType::Value, Map::MapType,
+ convertMapType, parser::OmpMapType::Value, Map::MapType,
// clang-format off
- MS(Alloc, Alloc)
- MS(Delete, Delete)
- MS(From, From)
- MS(Release, Release)
- MS(To, To)
- MS(Tofrom, Tofrom)
+ MS(Alloc, Storage)
+ MS(Delete, Storage)
+ MS(Release, Storage)
+ MS(Storage, Storage)
+ MS(From, From)
+ MS(To, To)
+ MS(Tofrom, Tofrom)
// clang-format on
);
CLAUSET_ENUM_CONVERT( //
- convert2, parser::OmpMapTypeModifier::Value, Map::MapTypeModifier,
+ convertMapTypeMod, parser::OmpMapTypeModifier::Value,
+ Map::MapTypeModifier,
// clang-format off
MS(Always, Always)
MS(Close, Close)
@@ -1022,43 +1024,76 @@ Map make(const parser::OmpClause::Map &inp,
// clang-format on
);
+ CLAUSET_ENUM_CONVERT( //
+ convertRefMod, parser::OmpRefModifier::Value, Map::RefModifier,
+ // clang-format off
+ MS(Ref_Ptee, RefPtee)
+ MS(Ref_Ptr, RefPtr)
+ MS(Ref_Ptr_Ptee, RefPtrPtee)
+ // clang-format on
+ );
+
+ // Treat always, close, present, self, delete modifiers as map-type-
+ // modifiers.
auto &mods = semantics::OmpGetModifiers(inp.v);
- auto *t1 = semantics::OmpGetUniqueModifier<parser::OmpMapper>(mods);
- auto *t2 = semantics::OmpGetUniqueModifier<parser::OmpIterator>(mods);
- auto *t3 = semantics::OmpGetUniqueModifier<parser::OmpMapType>(mods);
- auto &t4 = std::get<parser::OmpObjectList>(inp.v.t);
- auto mappers = [&]() -> std::optional<List<Mapper>> {
+ auto *t1 = semantics::OmpGetUniqueModifier<parser::OmpMapType>(mods);
+ auto &t2 = std::get<parser::OmpObjectList>(inp.v.t);
+
+ auto type = [&]() -> std::optional<Map::MapType> {
if (t1)
- return List<Mapper>{Mapper{makeObject(t1->v, semaCtx)}};
+ return convertMapType(t1->v);
return std::nullopt;
}();
- auto iterator = [&]() -> std::optional<Iterator> {
- if (t2)
- return makeIterator(*t2, semaCtx);
+ llvm::DenseSet<Map::MapTypeModifier> modSet;
+ if (t1 && t1->v == parser::OmpMapType::Value::Delete)
+ modSet.insert(Map::MapTypeModifier::Delete);
+
+ for (auto *typeMod :
+ semantics::OmpGetRepeatableModifier<parser::OmpMapTypeModifier>(mods)) {
+ modSet.insert(convertMapTypeMod(typeMod->v));
+ }
+ if (semantics::OmpGetUniqueModifier<parser::OmpAlwaysModifier>(mods))
+ modSet.insert(Map::MapTypeModifier::Always);
+ if (semantics::OmpGetUniqueModifier<parser::OmpCloseModifier>(mods))
+ modSet.insert(Map::MapTypeModifier::Close);
+ if (semantics::OmpGetUniqueModifier<parser::OmpDeleteModifier>(mods))
+ modSet.insert(Map::MapTypeModifier::Delete);
+ if (semantics::OmpGetUniqueModifier<parser::OmpPresentModifier>(mods))
+ modSet.insert(Map::MapTypeModifier::Present);
+ if (semantics::OmpGetUniqueModifier<parser::OmpSelfModifier>(mods))
+ modSet.insert(Map::MapTypeModifier::Self);
+ if (semantics::OmpGetUniqueModifier<parser::OmpxHoldModifier>(mods))
+ modSet.insert(Map::MapTypeModifier::OmpxHold);
+
+ std::optional<Map::MapTypeModifiers> maybeTypeMods{};
+ if (!modSet.empty())
+ maybeTypeMods = Map::MapTypeModifiers(modSet.begin(), modSet.end());
+
+ auto refMod = [&]() -> std::optional<Map::RefModifier> {
+ if (auto *t = semantics::OmpGetUniqueModifier<parser::OmpRefModifier>(mods))
+ return convertRefMod(t->v);
return std::nullopt;
}();
- auto type = [&]() -> std::optional<Map::MapType> {
- if (t3)
- return convert1(t3->v);
+ auto mappers = [&]() -> std::optional<List<Mapper>> {
+ if (auto *t = semantics::OmpGetUniqueModifier<parser::OmpMapper>(mods))
+ return List<Mapper>{Mapper{makeObject(t->v, semaCtx)}};
return std::nullopt;
}();
- Map::MapTypeModifiers typeMods;
- for (auto *typeMod :
- semantics::OmpGetRepeatableModifier<parser::OmpMapTypeModifier>(mods)) {
- typeMods.push_back(convert2(typeMod->v));
- }
- std::optional<Map::MapTypeModifiers> maybeTypeMods{};
- if (!typeMods.empty())
- maybeTypeMods = std::move(typeMods);
+ auto iterator = [&]() -> std::optional<Iterator> {
+ if (auto *t = semantics::OmpGetUniqueModifier<parser::OmpIterator>(mods))
+ return makeIterator(*t, semaCtx);
+ return std::nullopt;
+ }();
return Map{{/*MapType=*/std::move(type),
/*MapTypeModifiers=*/std::move(maybeTypeMods),
- /*Mapper=*/std::move(mappers), /*Iterator=*/std::move(iterator),
- /*LocatorList=*/makeObjects(t4, semaCtx)}};
+ /*RefModifier=*/std::move(refMod), /*Mapper=*/std::move(mappers),
+ /*Iterator=*/std::move(iterator),
+ /*LocatorList=*/makeObjects(t2, semaCtx)}};
}
Match make(const parser::OmpClause::Match &inp,
diff --git a/flang/lib/Lower/OpenMP/DataSharingProcessor.cpp b/flang/lib/Lower/OpenMP/DataSharingProcessor.cpp
index 675a58e..2ac4d95 100644
--- a/flang/lib/Lower/OpenMP/DataSharingProcessor.cpp
+++ b/flang/lib/Lower/OpenMP/DataSharingProcessor.cpp
@@ -24,6 +24,7 @@
#include "flang/Optimizer/Dialect/FIROps.h"
#include "flang/Optimizer/HLFIR/HLFIRDialect.h"
#include "flang/Optimizer/HLFIR/HLFIROps.h"
+#include "flang/Parser/openmp-utils.h"
#include "flang/Semantics/attr.h"
#include "flang/Semantics/tools.h"
#include "llvm/ADT/Sequence.h"
@@ -291,7 +292,7 @@ void DataSharingProcessor::insertBarrier(
clauseOps->privateNeedsBarrier =
mlir::UnitAttr::get(&converter.getMLIRContext());
} else {
- firOpBuilder.create<mlir::omp::BarrierOp>(converter.getCurrentLocation());
+ mlir::omp::BarrierOp::create(firOpBuilder, converter.getCurrentLocation());
}
}
@@ -351,32 +352,32 @@ void DataSharingProcessor::insertLastPrivateCompare(mlir::Operation *op) {
loopOp.getIVs(), result.loopUpperBounds, result.loopSteps)) {
// v = iv + step
// cmp = step < 0 ? v < ub : v > ub
- mlir::Value v = firOpBuilder.create<mlir::arith::AddIOp>(loc, iv, step);
+ mlir::Value v = mlir::arith::AddIOp::create(firOpBuilder, loc, iv, step);
vs.push_back(v);
mlir::Value zero =
firOpBuilder.createIntegerConstant(loc, step.getType(), 0);
- mlir::Value negativeStep = firOpBuilder.create<mlir::arith::CmpIOp>(
- loc, mlir::arith::CmpIPredicate::slt, step, zero);
- mlir::Value vLT = firOpBuilder.create<mlir::arith::CmpIOp>(
- loc, mlir::arith::CmpIPredicate::slt, v, ub);
- mlir::Value vGT = firOpBuilder.create<mlir::arith::CmpIOp>(
- loc, mlir::arith::CmpIPredicate::sgt, v, ub);
- mlir::Value icmpOp = firOpBuilder.create<mlir::arith::SelectOp>(
- loc, negativeStep, vLT, vGT);
+ mlir::Value negativeStep = mlir::arith::CmpIOp::create(
+ firOpBuilder, loc, mlir::arith::CmpIPredicate::slt, step, zero);
+ mlir::Value vLT = mlir::arith::CmpIOp::create(
+ firOpBuilder, loc, mlir::arith::CmpIPredicate::slt, v, ub);
+ mlir::Value vGT = mlir::arith::CmpIOp::create(
+ firOpBuilder, loc, mlir::arith::CmpIPredicate::sgt, v, ub);
+ mlir::Value icmpOp = mlir::arith::SelectOp::create(
+ firOpBuilder, loc, negativeStep, vLT, vGT);
if (cmpOp)
- cmpOp = firOpBuilder.create<mlir::arith::AndIOp>(loc, cmpOp, icmpOp);
+ cmpOp = mlir::arith::AndIOp::create(firOpBuilder, loc, cmpOp, icmpOp);
else
cmpOp = icmpOp;
}
- auto ifOp = firOpBuilder.create<fir::IfOp>(loc, cmpOp, /*else*/ false);
+ auto ifOp = fir::IfOp::create(firOpBuilder, loc, cmpOp, /*else*/ false);
firOpBuilder.setInsertionPointToStart(&ifOp.getThenRegion().front());
for (auto [v, loopIV] : llvm::zip_equal(vs, loopIVs)) {
hlfir::Entity loopIVEntity{loopIV};
loopIVEntity =
hlfir::derefPointersAndAllocatables(loc, firOpBuilder, loopIVEntity);
- firOpBuilder.create<hlfir::AssignOp>(loc, v, loopIVEntity);
+ hlfir::AssignOp::create(firOpBuilder, loc, v, loopIVEntity);
}
lastPrivIP = firOpBuilder.saveInsertionPoint();
} else if (mlir::isa<mlir::omp::SectionsOp>(op)) {
@@ -465,7 +466,8 @@ bool DataSharingProcessor::isOpenMPPrivatizingConstruct(
// allow a privatizing clause) are: dispatch, distribute, do, for, loop,
// parallel, scope, sections, simd, single, target, target_data, task,
// taskgroup, taskloop, and teams.
- return llvm::is_contained(privatizing, extractOmpDirective(omp));
+ return llvm::is_contained(privatizing,
+ parser::omp::GetOmpDirectiveName(omp).v);
}
bool DataSharingProcessor::isOpenMPPrivatizingEvaluation(
diff --git a/flang/lib/Lower/OpenMP/OpenMP.cpp b/flang/lib/Lower/OpenMP/OpenMP.cpp
index fcb20fd..6a4ec77 100644
--- a/flang/lib/Lower/OpenMP/OpenMP.cpp
+++ b/flang/lib/Lower/OpenMP/OpenMP.cpp
@@ -31,6 +31,7 @@
#include "flang/Optimizer/Dialect/FIRType.h"
#include "flang/Optimizer/HLFIR/HLFIROps.h"
#include "flang/Parser/characters.h"
+#include "flang/Parser/openmp-utils.h"
#include "flang/Parser/parse-tree.h"
#include "flang/Semantics/openmp-directive-sets.h"
#include "flang/Semantics/tools.h"
@@ -410,8 +411,12 @@ static void processHostEvalClauses(lower::AbstractConverter &converter,
std::get<parser::OmpBeginBlockDirective>(ompConstruct.t);
beginClauseList =
&std::get<parser::OmpClauseList>(beginDirective.t);
- endClauseList = &std::get<parser::OmpClauseList>(
- std::get<parser::OmpEndBlockDirective>(ompConstruct.t).t);
+ if (auto &endDirective =
+ std::get<std::optional<parser::OmpEndBlockDirective>>(
+ ompConstruct.t)) {
+ endClauseList =
+ &std::get<parser::OmpClauseList>(endDirective->t);
+ }
},
[&](const parser::OpenMPLoopConstruct &ompConstruct) {
const auto &beginDirective =
@@ -421,9 +426,10 @@ static void processHostEvalClauses(lower::AbstractConverter &converter,
if (auto &endDirective =
std::get<std::optional<parser::OmpEndLoopDirective>>(
- ompConstruct.t))
+ ompConstruct.t)) {
endClauseList =
&std::get<parser::OmpClauseList>(endDirective->t);
+ }
},
[&](const auto &) {}},
ompEval->u);
@@ -446,7 +452,7 @@ static void processHostEvalClauses(lower::AbstractConverter &converter,
llvm::omp::Directive dir;
auto &nested = parent.getFirstNestedEvaluation();
if (const auto *ompEval = nested.getIf<parser::OpenMPConstruct>())
- dir = extractOmpDirective(*ompEval);
+ dir = parser::omp::GetOmpDirectiveName(*ompEval).v;
else
return std::nullopt;
@@ -486,7 +492,7 @@ static void processHostEvalClauses(lower::AbstractConverter &converter,
HostEvalInfo *hostInfo = getHostEvalInfoStackTop(converter);
assert(hostInfo && "expected HOST_EVAL info structure");
- switch (extractOmpDirective(*ompEval)) {
+ switch (parser::omp::GetOmpDirectiveName(*ompEval).v) {
case OMPD_teams_distribute_parallel_do:
case OMPD_teams_distribute_parallel_do_simd:
cp.processThreadLimit(stmtCtx, hostInfo->ops);
@@ -547,7 +553,8 @@ static void processHostEvalClauses(lower::AbstractConverter &converter,
const auto *ompEval = eval.getIf<parser::OpenMPConstruct>();
assert(ompEval &&
- llvm::omp::allTargetSet.test(extractOmpDirective(*ompEval)) &&
+ llvm::omp::allTargetSet.test(
+ parser::omp::GetOmpDirectiveName(*ompEval).v) &&
"expected TARGET construct evaluation");
(void)ompEval;
@@ -642,8 +649,8 @@ static void threadPrivatizeVars(lower::AbstractConverter &converter,
op = declOp.getMemref().getDefiningOp();
if (mlir::isa<mlir::omp::ThreadprivateOp>(op))
symValue = mlir::dyn_cast<mlir::omp::ThreadprivateOp>(op).getSymAddr();
- return firOpBuilder.create<mlir::omp::ThreadprivateOp>(
- currentLocation, symValue.getType(), symValue);
+ return mlir::omp::ThreadprivateOp::create(firOpBuilder, currentLocation,
+ symValue.getType(), symValue);
};
llvm::SetVector<const semantics::Symbol *> threadprivateSyms;
@@ -690,30 +697,35 @@ static void threadPrivatizeVars(lower::AbstractConverter &converter,
}
}
-static mlir::Operation *
-createAndSetPrivatizedLoopVar(lower::AbstractConverter &converter,
- mlir::Location loc, mlir::Value indexVal,
- const semantics::Symbol *sym) {
+static mlir::Operation *setLoopVar(lower::AbstractConverter &converter,
+ mlir::Location loc, mlir::Value indexVal,
+ const semantics::Symbol *sym) {
fir::FirOpBuilder &firOpBuilder = converter.getFirOpBuilder();
+
mlir::OpBuilder::InsertPoint insPt = firOpBuilder.saveInsertionPoint();
firOpBuilder.setInsertionPointToStart(firOpBuilder.getAllocaBlock());
-
mlir::Type tempTy = converter.genType(*sym);
-
- assert(converter.isPresentShallowLookup(*sym) &&
- "Expected symbol to be in symbol table.");
-
firOpBuilder.restoreInsertionPoint(insPt);
+
mlir::Value cvtVal = firOpBuilder.createConvert(loc, tempTy, indexVal);
hlfir::Entity lhs{converter.getSymbolAddress(*sym)};
lhs = hlfir::derefPointersAndAllocatables(loc, firOpBuilder, lhs);
mlir::Operation *storeOp =
- firOpBuilder.create<hlfir::AssignOp>(loc, cvtVal, lhs);
+ hlfir::AssignOp::create(firOpBuilder, loc, cvtVal, lhs);
return storeOp;
}
+static mlir::Operation *
+createAndSetPrivatizedLoopVar(lower::AbstractConverter &converter,
+ mlir::Location loc, mlir::Value indexVal,
+ const semantics::Symbol *sym) {
+ assert(converter.isPresentShallowLookup(*sym) &&
+ "Expected symbol to be in symbol table.");
+ return setLoopVar(converter, loc, indexVal, sym);
+}
+
// This helper function implements the functionality of "promoting" non-CPTR
// arguments of use_device_ptr to use_device_addr arguments (automagic
// conversion of use_device_ptr -> use_device_addr in these cases). The way we
@@ -1116,6 +1128,11 @@ struct OpWithBodyGenInfo {
return *this;
}
+ OpWithBodyGenInfo &setPrivatize(bool value) {
+ privatize = value;
+ return *this;
+ }
+
/// [inout] converter to use for the clauses.
lower::AbstractConverter &converter;
/// [in] Symbol table
@@ -1142,6 +1159,8 @@ struct OpWithBodyGenInfo {
/// [in] if set to `true`, skip generating nested evaluations and dispatching
/// any further leaf constructs.
bool genSkeletonOnly = false;
+ /// [in] enables handling of privatized variable unless set to `false`.
+ bool privatize = true;
};
/// Create the body (block) for an OpenMP Operation.
@@ -1156,8 +1175,8 @@ static void createBodyOfOp(mlir::Operation &op, const OpWithBodyGenInfo &info,
fir::FirOpBuilder &firOpBuilder = info.converter.getFirOpBuilder();
auto insertMarker = [](fir::FirOpBuilder &builder) {
- mlir::Value undef = builder.create<fir::UndefOp>(builder.getUnknownLoc(),
- builder.getIndexType());
+ mlir::Value undef = fir::UndefOp::create(builder, builder.getUnknownLoc(),
+ builder.getIndexType());
return undef.getDefiningOp();
};
@@ -1202,7 +1221,7 @@ static void createBodyOfOp(mlir::Operation &op, const OpWithBodyGenInfo &info,
// code will use the right symbols.
bool isLoop = llvm::omp::getDirectiveAssociation(info.dir) ==
llvm::omp::Association::Loop;
- bool privatize = info.clauses;
+ bool privatize = info.clauses && info.privatize;
firOpBuilder.setInsertionPoint(marker);
std::optional<DataSharingProcessor> tempDsp;
@@ -1271,7 +1290,7 @@ static void createBodyOfOp(mlir::Operation &op, const OpWithBodyGenInfo &info,
mlir::Block *exit = firOpBuilder.createBlock(&region);
for (mlir::Block *b : exits) {
firOpBuilder.setInsertionPointToEnd(b);
- firOpBuilder.create<mlir::cf::BranchOp>(info.loc, exit);
+ mlir::cf::BranchOp::create(firOpBuilder, info.loc, exit);
}
return exit;
};
@@ -1332,8 +1351,8 @@ static void genBodyOfTargetDataOp(
// Remembering the position for further insertion is important since
// there are hlfir.declares inserted above while setting block arguments
// and new code from the body should be inserted after that.
- mlir::Value undefMarker = firOpBuilder.create<fir::UndefOp>(
- dataOp.getLoc(), firOpBuilder.getIndexType());
+ mlir::Value undefMarker = fir::UndefOp::create(firOpBuilder, dataOp.getLoc(),
+ firOpBuilder.getIndexType());
// Create blocks for unstructured regions. This has to be done since
// blocks are initially allocated with the function as the parent region.
@@ -1342,7 +1361,7 @@ static void genBodyOfTargetDataOp(
firOpBuilder, eval.getNestedEvaluations());
}
- firOpBuilder.create<mlir::omp::TerminatorOp>(currentLocation);
+ mlir::omp::TerminatorOp::create(firOpBuilder, currentLocation);
// Set the insertion point after the marker.
firOpBuilder.setInsertionPointAfter(undefMarker.getDefiningOp());
@@ -1496,8 +1515,8 @@ static void genBodyOfTargetOp(
insertIndex, copyVal.getType(), copyVal.getLoc());
firOpBuilder.setInsertionPointToStart(entryBlock);
- auto loadOp = firOpBuilder.create<fir::LoadOp>(clonedValArg.getLoc(),
- clonedValArg);
+ auto loadOp = fir::LoadOp::create(firOpBuilder, clonedValArg.getLoc(),
+ clonedValArg);
val.replaceUsesWithIf(loadOp->getResult(0),
[entryBlock](mlir::OpOperand &use) {
return use.getOwner()->getBlock() == entryBlock;
@@ -1513,8 +1532,8 @@ static void genBodyOfTargetOp(
// marker will be deleted since there are not uses.
// In the HLFIR flow there are hlfir.declares inserted above while
// setting block arguments.
- mlir::Value undefMarker = firOpBuilder.create<fir::UndefOp>(
- targetOp.getLoc(), firOpBuilder.getIndexType());
+ mlir::Value undefMarker = fir::UndefOp::create(
+ firOpBuilder, targetOp.getLoc(), firOpBuilder.getIndexType());
// Create blocks for unstructured regions. This has to be done since
// blocks are initially allocated with the function as the parent region.
@@ -1524,7 +1543,7 @@ static void genBodyOfTargetOp(
firOpBuilder, eval.getNestedEvaluations());
}
- firOpBuilder.create<mlir::omp::TerminatorOp>(currentLocation);
+ mlir::omp::TerminatorOp::create(firOpBuilder, currentLocation);
// Create the insertion point after the marker.
firOpBuilder.setInsertionPointAfter(undefMarker.getDefiningOp());
@@ -1570,7 +1589,7 @@ static OpTy genWrapperOp(lower::AbstractConverter &converter,
fir::FirOpBuilder &firOpBuilder = converter.getFirOpBuilder();
// Create wrapper.
- auto op = firOpBuilder.create<OpTy>(loc, clauseOps);
+ auto op = OpTy::create(firOpBuilder, loc, clauseOps);
// Create entry block with arguments.
genEntryBlock(firOpBuilder, args, op.getRegion());
@@ -1983,7 +2002,7 @@ genCriticalOp(lower::AbstractConverter &converter, lower::SymMap &symTable,
clauseOps, nameStr);
mlir::OpBuilder modBuilder(mod.getBodyRegion());
- global = modBuilder.create<mlir::omp::CriticalDeclareOp>(loc, clauseOps);
+ global = mlir::omp::CriticalDeclareOp::create(modBuilder, loc, clauseOps);
}
nameAttr = mlir::FlatSymbolRefAttr::get(firOpBuilder.getContext(),
global.getSymName());
@@ -2069,6 +2088,154 @@ genLoopOp(lower::AbstractConverter &converter, lower::SymMap &symTable,
return loopOp;
}
+static mlir::omp::CanonicalLoopOp
+genCanonicalLoopOp(lower::AbstractConverter &converter, lower::SymMap &symTable,
+ semantics::SemanticsContext &semaCtx,
+ lower::pft::Evaluation &eval, mlir::Location loc,
+ const ConstructQueue &queue,
+ ConstructQueue::const_iterator item,
+ llvm::ArrayRef<const semantics::Symbol *> ivs,
+ llvm::omp::Directive directive) {
+ fir::FirOpBuilder &firOpBuilder = converter.getFirOpBuilder();
+
+ assert(ivs.size() == 1 && "Nested loops not yet implemented");
+ const semantics::Symbol *iv = ivs[0];
+
+ auto &nestedEval = eval.getFirstNestedEvaluation();
+ if (nestedEval.getIf<parser::DoConstruct>()->IsDoConcurrent()) {
+ // OpenMP specifies DO CONCURRENT only with the `!omp loop` construct. Will
+ // need to add special cases for this combination.
+ TODO(loc, "DO CONCURRENT as canonical loop not supported");
+ }
+
+ // Get the loop bounds (and increment)
+ auto &doLoopEval = nestedEval.getFirstNestedEvaluation();
+ auto *doStmt = doLoopEval.getIf<parser::NonLabelDoStmt>();
+ assert(doStmt && "Expected do loop to be in the nested evaluation");
+ auto &loopControl = std::get<std::optional<parser::LoopControl>>(doStmt->t);
+ assert(loopControl.has_value());
+ auto *bounds = std::get_if<parser::LoopControl::Bounds>(&loopControl->u);
+ assert(bounds && "Expected bounds for canonical loop");
+ lower::StatementContext stmtCtx;
+ mlir::Value loopLBVar = fir::getBase(
+ converter.genExprValue(*semantics::GetExpr(bounds->lower), stmtCtx));
+ mlir::Value loopUBVar = fir::getBase(
+ converter.genExprValue(*semantics::GetExpr(bounds->upper), stmtCtx));
+ mlir::Value loopStepVar = [&]() {
+ if (bounds->step) {
+ return fir::getBase(
+ converter.genExprValue(*semantics::GetExpr(bounds->step), stmtCtx));
+ }
+
+ // If `step` is not present, assume it is `1`.
+ return firOpBuilder.createIntegerConstant(loc, firOpBuilder.getI32Type(),
+ 1);
+ }();
+
+ // Get the integer kind for the loop variable and cast the loop bounds
+ size_t loopVarTypeSize = bounds->name.thing.symbol->GetUltimate().size();
+ mlir::Type loopVarType = getLoopVarType(converter, loopVarTypeSize);
+ loopLBVar = firOpBuilder.createConvert(loc, loopVarType, loopLBVar);
+ loopUBVar = firOpBuilder.createConvert(loc, loopVarType, loopUBVar);
+ loopStepVar = firOpBuilder.createConvert(loc, loopVarType, loopStepVar);
+
+ // Start lowering
+ mlir::Value zero = firOpBuilder.createIntegerConstant(loc, loopVarType, 0);
+ mlir::Value one = firOpBuilder.createIntegerConstant(loc, loopVarType, 1);
+ mlir::Value isDownwards = firOpBuilder.create<mlir::arith::CmpIOp>(
+ loc, mlir::arith::CmpIPredicate::slt, loopStepVar, zero);
+
+ // Ensure we are counting upwards. If not, negate step and swap lb and ub.
+ mlir::Value negStep =
+ firOpBuilder.create<mlir::arith::SubIOp>(loc, zero, loopStepVar);
+ mlir::Value incr = firOpBuilder.create<mlir::arith::SelectOp>(
+ loc, isDownwards, negStep, loopStepVar);
+ mlir::Value lb = firOpBuilder.create<mlir::arith::SelectOp>(
+ loc, isDownwards, loopUBVar, loopLBVar);
+ mlir::Value ub = firOpBuilder.create<mlir::arith::SelectOp>(
+ loc, isDownwards, loopLBVar, loopUBVar);
+
+ // Compute the trip count assuming lb <= ub. This guarantees that the result
+ // is non-negative and we can use unsigned arithmetic.
+ mlir::Value span = firOpBuilder.create<mlir::arith::SubIOp>(
+ loc, ub, lb, ::mlir::arith::IntegerOverflowFlags::nuw);
+ mlir::Value tcMinusOne =
+ firOpBuilder.create<mlir::arith::DivUIOp>(loc, span, incr);
+ mlir::Value tcIfLooping = firOpBuilder.create<mlir::arith::AddIOp>(
+ loc, tcMinusOne, one, ::mlir::arith::IntegerOverflowFlags::nuw);
+
+ // Fall back to 0 if lb > ub
+ mlir::Value isZeroTC = firOpBuilder.create<mlir::arith::CmpIOp>(
+ loc, mlir::arith::CmpIPredicate::slt, ub, lb);
+ mlir::Value tripcount = firOpBuilder.create<mlir::arith::SelectOp>(
+ loc, isZeroTC, zero, tcIfLooping);
+
+ // Create the CLI handle.
+ auto newcli = firOpBuilder.create<mlir::omp::NewCliOp>(loc);
+ mlir::Value cli = newcli.getResult();
+
+ auto ivCallback = [&](mlir::Operation *op)
+ -> llvm::SmallVector<const Fortran::semantics::Symbol *> {
+ mlir::Region &region = op->getRegion(0);
+
+ // Create the op's region skeleton (BB taking the iv as argument)
+ firOpBuilder.createBlock(&region, {}, {loopVarType}, {loc});
+
+ // Compute the value of the loop variable from the logical iteration number.
+ mlir::Value natIterNum = fir::getBase(region.front().getArgument(0));
+ mlir::Value scaled =
+ firOpBuilder.create<mlir::arith::MulIOp>(loc, natIterNum, loopStepVar);
+ mlir::Value userVal =
+ firOpBuilder.create<mlir::arith::AddIOp>(loc, loopLBVar, scaled);
+
+ // Write loop value to loop variable
+ mlir::Operation *storeOp = setLoopVar(converter, loc, userVal, iv);
+
+ firOpBuilder.setInsertionPointAfter(storeOp);
+ return {iv};
+ };
+
+ // Create the omp.canonical_loop operation
+ auto canonLoop = genOpWithBody<mlir::omp::CanonicalLoopOp>(
+ OpWithBodyGenInfo(converter, symTable, semaCtx, loc, nestedEval,
+ directive)
+ .setClauses(&item->clauses)
+ .setPrivatize(false)
+ .setGenRegionEntryCb(ivCallback),
+ queue, item, tripcount, cli);
+
+ firOpBuilder.setInsertionPointAfter(canonLoop);
+ return canonLoop;
+}
+
+static void genUnrollOp(Fortran::lower::AbstractConverter &converter,
+ Fortran::lower::SymMap &symTable,
+ lower::StatementContext &stmtCtx,
+ Fortran::semantics::SemanticsContext &semaCtx,
+ Fortran::lower::pft::Evaluation &eval,
+ mlir::Location loc, const ConstructQueue &queue,
+ ConstructQueue::const_iterator item) {
+ fir::FirOpBuilder &firOpBuilder = converter.getFirOpBuilder();
+
+ mlir::omp::LoopRelatedClauseOps loopInfo;
+ llvm::SmallVector<const semantics::Symbol *> iv;
+ collectLoopRelatedInfo(converter, loc, eval, item->clauses, loopInfo, iv);
+
+ // Clauses for unrolling not yet implemnted
+ ClauseProcessor cp(converter, semaCtx, item->clauses);
+ cp.processTODO<clause::Partial, clause::Full>(
+ loc, llvm::omp::Directive::OMPD_unroll);
+
+ // Emit the associated loop
+ auto canonLoop =
+ genCanonicalLoopOp(converter, symTable, semaCtx, eval, loc, queue, item,
+ iv, llvm::omp::Directive::OMPD_unroll);
+
+ // Apply unrolling to it
+ auto cli = canonLoop.getCli();
+ firOpBuilder.create<mlir::omp::UnrollHeuristicOp>(loc, cli);
+}
+
static mlir::omp::MaskedOp
genMaskedOp(lower::AbstractConverter &converter, lower::SymMap &symTable,
lower::StatementContext &stmtCtx,
@@ -2201,7 +2368,7 @@ genSectionsOp(lower::AbstractConverter &converter, lower::SymMap &symTable,
}
// SECTIONS construct.
- auto sectionsOp = builder.create<mlir::omp::SectionsOp>(loc, clauseOps);
+ auto sectionsOp = mlir::omp::SectionsOp::create(builder, loc, clauseOps);
// Create entry block with reduction variables as arguments.
EntryBlockArgs args;
@@ -2277,7 +2444,7 @@ genSectionsOp(lower::AbstractConverter &converter, lower::SymMap &symTable,
// races on post-update of lastprivate variables when `nowait`
// clause is present.
if (clauseOps.nowait && !lastprivates.empty())
- builder.create<mlir::omp::BarrierOp>(loc);
+ mlir::omp::BarrierOp::create(builder, loc);
return sectionsOp;
}
@@ -2429,7 +2596,7 @@ genTargetOp(lower::AbstractConverter &converter, lower::SymMap &symTable,
};
lower::pft::visitAllSymbols(eval, captureImplicitMap);
- auto targetOp = firOpBuilder.create<mlir::omp::TargetOp>(loc, clauseOps);
+ auto targetOp = mlir::omp::TargetOp::create(firOpBuilder, loc, clauseOps);
llvm::SmallVector<mlir::Value> hasDeviceAddrBaseValues, mapBaseValues;
extractMappedBaseValues(clauseOps.hasDeviceAddrVars, hasDeviceAddrBaseValues);
@@ -2509,7 +2676,7 @@ static OpTy genTargetEnterExitUpdateDataOp(
genTargetEnterExitUpdateDataClauses(converter, semaCtx, symTable, stmtCtx,
item->clauses, loc, directive, clauseOps);
- return firOpBuilder.create<OpTy>(loc, clauseOps);
+ return OpTy::create(firOpBuilder, loc, clauseOps);
}
static mlir::omp::TaskOp
@@ -3249,12 +3416,14 @@ static void genOMPDispatch(lower::AbstractConverter &converter,
newOp = genTeamsOp(converter, symTable, stmtCtx, semaCtx, eval, loc, queue,
item);
break;
- case llvm::omp::Directive::OMPD_tile:
- case llvm::omp::Directive::OMPD_unroll: {
+ case llvm::omp::Directive::OMPD_tile: {
unsigned version = semaCtx.langOptions().OpenMPVersion;
TODO(loc, "Unhandled loop directive (" +
llvm::omp::getOpenMPDirectiveName(dir, version) + ")");
}
+ case llvm::omp::Directive::OMPD_unroll:
+ genUnrollOp(converter, symTable, stmtCtx, semaCtx, eval, loc, queue, item);
+ break;
// case llvm::omp::Directive::OMPD_workdistribute:
case llvm::omp::Directive::OMPD_workshare:
newOp = genWorkshareOp(converter, symTable, stmtCtx, semaCtx, eval, loc,
@@ -3342,8 +3511,8 @@ genOMP(lower::AbstractConverter &converter, lower::SymMap &symTable,
firOpBuilder.setInsertionPointToStart(converter.getModuleOp().getBody());
auto mlirType = converter.genType(varType.declTypeSpec->derivedTypeSpec());
- auto declMapperOp = firOpBuilder.create<mlir::omp::DeclareMapperOp>(
- loc, mapperNameStr, mlirType);
+ auto declMapperOp = mlir::omp::DeclareMapperOp::create(
+ firOpBuilder, loc, mapperNameStr, mlirType);
auto &region = declMapperOp.getRegion();
firOpBuilder.createBlock(&region);
auto varVal = region.addArgument(firOpBuilder.getRefType(mlirType), loc);
@@ -3356,7 +3525,7 @@ genOMP(lower::AbstractConverter &converter, lower::SymMap &symTable,
List<Clause> clauses = makeClauses(*clauseList, semaCtx);
ClauseProcessor cp(converter, semaCtx, clauses);
cp.processMap(loc, stmtCtx, clauseOps);
- firOpBuilder.create<mlir::omp::DeclareMapperInfoOp>(loc, clauseOps.mapVars);
+ mlir::omp::DeclareMapperInfoOp::create(firOpBuilder, loc, clauseOps.mapVars);
}
static void
@@ -3552,16 +3721,19 @@ static void genOMP(lower::AbstractConverter &converter, lower::SymMap &symTable,
const parser::OpenMPBlockConstruct &blockConstruct) {
const auto &beginBlockDirective =
std::get<parser::OmpBeginBlockDirective>(blockConstruct.t);
- const auto &endBlockDirective =
- std::get<parser::OmpEndBlockDirective>(blockConstruct.t);
mlir::Location currentLocation =
converter.genLocation(beginBlockDirective.source);
const auto origDirective =
std::get<parser::OmpBlockDirective>(beginBlockDirective.t).v;
List<Clause> clauses = makeClauses(
std::get<parser::OmpClauseList>(beginBlockDirective.t), semaCtx);
- clauses.append(makeClauses(
- std::get<parser::OmpClauseList>(endBlockDirective.t), semaCtx));
+
+ if (const auto &endBlockDirective =
+ std::get<std::optional<parser::OmpEndBlockDirective>>(
+ blockConstruct.t)) {
+ clauses.append(makeClauses(
+ std::get<parser::OmpClauseList>(endBlockDirective->t), semaCtx));
+ }
assert(llvm::omp::blockConstructSet.test(origDirective) &&
"Expected block construct");
@@ -3690,12 +3862,26 @@ static void genOMP(lower::AbstractConverter &converter, lower::SymMap &symTable,
if (auto *ompNestedLoopCons{
std::get_if<common::Indirection<parser::OpenMPLoopConstruct>>(
&*optLoopCons)}) {
- genOMP(converter, symTable, semaCtx, eval, ompNestedLoopCons->value());
+ llvm::omp::Directive nestedDirective =
+ parser::omp::GetOmpDirectiveName(*ompNestedLoopCons).v;
+ switch (nestedDirective) {
+ case llvm::omp::Directive::OMPD_tile:
+ // Emit the omp.loop_nest with annotation for tiling
+ genOMP(converter, symTable, semaCtx, eval, ompNestedLoopCons->value());
+ break;
+ default: {
+ unsigned version = semaCtx.langOptions().OpenMPVersion;
+ TODO(currentLocation,
+ "Applying a loop-associated on the loop generated by the " +
+ llvm::omp::getOpenMPDirectiveName(nestedDirective, version) +
+ " construct");
+ }
+ }
}
}
llvm::omp::Directive directive =
- std::get<parser::OmpLoopDirective>(beginLoopDirective.t).v;
+ parser::omp::GetOmpDirectiveName(beginLoopDirective).v;
const parser::CharBlock &source =
std::get<parser::OmpLoopDirective>(beginLoopDirective.t).source;
ConstructQueue queue{
@@ -3758,8 +3944,8 @@ mlir::Operation *Fortran::lower::genOpenMPTerminator(fir::FirOpBuilder &builder,
mlir::Location loc) {
if (mlir::isa<mlir::omp::AtomicUpdateOp, mlir::omp::DeclareReductionOp,
mlir::omp::LoopNestOp>(op))
- return builder.create<mlir::omp::YieldOp>(loc);
- return builder.create<mlir::omp::TerminatorOp>(loc);
+ return mlir::omp::YieldOp::create(builder, loc);
+ return mlir::omp::TerminatorOp::create(builder, loc);
}
void Fortran::lower::genOpenMPConstruct(lower::AbstractConverter &converter,
@@ -3819,9 +4005,8 @@ void Fortran::lower::genThreadprivateOp(lower::AbstractConverter &converter,
return;
}
// Generate ThreadprivateOp and rebind the common block.
- mlir::Value commonThreadprivateValue =
- firOpBuilder.create<mlir::omp::ThreadprivateOp>(
- currentLocation, commonValue.getType(), commonValue);
+ mlir::Value commonThreadprivateValue = mlir::omp::ThreadprivateOp::create(
+ firOpBuilder, currentLocation, commonValue.getType(), commonValue);
converter.bindSymbol(*common, commonThreadprivateValue);
// Generate the threadprivate value for the common block member.
symThreadprivateValue = genCommonBlockMember(converter, currentLocation,
@@ -3841,10 +4026,10 @@ void Fortran::lower::genThreadprivateOp(lower::AbstractConverter &converter,
global = globalInitialization(converter, firOpBuilder, sym, var,
currentLocation);
- mlir::Value symValue = firOpBuilder.create<fir::AddrOfOp>(
- currentLocation, global.resultType(), global.getSymbol());
- symThreadprivateValue = firOpBuilder.create<mlir::omp::ThreadprivateOp>(
- currentLocation, symValue.getType(), symValue);
+ mlir::Value symValue = fir::AddrOfOp::create(
+ firOpBuilder, currentLocation, global.resultType(), global.getSymbol());
+ symThreadprivateValue = mlir::omp::ThreadprivateOp::create(
+ firOpBuilder, currentLocation, symValue.getType(), symValue);
} else {
mlir::Value symValue = converter.getSymbolAddress(sym);
@@ -3859,8 +4044,8 @@ void Fortran::lower::genThreadprivateOp(lower::AbstractConverter &converter,
if (mlir::isa<mlir::omp::ThreadprivateOp>(op))
return;
- symThreadprivateValue = firOpBuilder.create<mlir::omp::ThreadprivateOp>(
- currentLocation, symValue.getType(), symValue);
+ symThreadprivateValue = mlir::omp::ThreadprivateOp::create(
+ firOpBuilder, currentLocation, symValue.getType(), symValue);
}
fir::ExtendedValue sexv = converter.getSymbolExtendedValue(sym);
diff --git a/flang/lib/Lower/OpenMP/Utils.cpp b/flang/lib/Lower/OpenMP/Utils.cpp
index b194150..13fda97 100644
--- a/flang/lib/Lower/OpenMP/Utils.cpp
+++ b/flang/lib/Lower/OpenMP/Utils.cpp
@@ -20,6 +20,7 @@
#include <flang/Lower/PFTBuilder.h>
#include <flang/Optimizer/Builder/FIRBuilder.h>
#include <flang/Optimizer/Builder/Todo.h>
+#include <flang/Parser/openmp-utils.h>
#include <flang/Parser/parse-tree.h>
#include <flang/Parser/tools.h>
#include <flang/Semantics/tools.h>
@@ -115,7 +116,7 @@ createMapInfoOp(fir::FirOpBuilder &builder, mlir::Location loc,
mlir::omp::VariableCaptureKind mapCaptureType, mlir::Type retTy,
bool partialMap, mlir::FlatSymbolRefAttr mapperId) {
if (auto boxTy = llvm::dyn_cast<fir::BaseBoxType>(baseAddr.getType())) {
- baseAddr = builder.create<fir::BoxAddrOp>(loc, baseAddr);
+ baseAddr = fir::BoxAddrOp::create(builder, loc, baseAddr);
retTy = baseAddr.getType();
}
@@ -129,8 +130,8 @@ createMapInfoOp(fir::FirOpBuilder &builder, mlir::Location loc,
if (seqType.hasDynamicExtents())
varType = mlir::TypeAttr::get(seqType.getEleTy());
- mlir::omp::MapInfoOp op = builder.create<mlir::omp::MapInfoOp>(
- loc, retTy, baseAddr, varType,
+ mlir::omp::MapInfoOp op = mlir::omp::MapInfoOp::create(
+ builder, loc, retTy, baseAddr, varType,
builder.getIntegerAttr(builder.getIntegerType(64, false), mapType),
builder.getAttr<mlir::omp::VariableCaptureKindAttr>(mapCaptureType),
varPtrPtr, members, membersIndex, bounds, mapperId,
@@ -195,8 +196,8 @@ static void generateArrayIndices(lower::AbstractConverter &converter,
clauseLocation, firOpBuilder.getIndexType(), 1);
subscript = firOpBuilder.createConvert(
clauseLocation, firOpBuilder.getIndexType(), subscript);
- indices.push_back(firOpBuilder.create<mlir::arith::SubIOp>(clauseLocation,
- subscript, one));
+ indices.push_back(mlir::arith::SubIOp::create(firOpBuilder, clauseLocation,
+ subscript, one));
}
}
@@ -329,9 +330,10 @@ mlir::Value createParentSymAndGenIntermediateMaps(
subscriptIndices, objectList[i]);
assert(!subscriptIndices.empty() &&
"missing expected indices for map clause");
- curValue = firOpBuilder.create<fir::CoordinateOp>(
- clauseLocation, firOpBuilder.getRefType(arrType.getEleTy()),
- curValue, subscriptIndices);
+ curValue = fir::CoordinateOp::create(
+ firOpBuilder, clauseLocation,
+ firOpBuilder.getRefType(arrType.getEleTy()), curValue,
+ subscriptIndices);
}
}
@@ -345,9 +347,9 @@ mlir::Value createParentSymAndGenIntermediateMaps(
fir::IntOrValue idxConst = mlir::IntegerAttr::get(
firOpBuilder.getI32Type(), indices[currentIndicesIdx]);
mlir::Type memberTy = recordType.getType(indices[currentIndicesIdx]);
- curValue = firOpBuilder.create<fir::CoordinateOp>(
- clauseLocation, firOpBuilder.getRefType(memberTy), curValue,
- llvm::SmallVector<fir::IntOrValue, 1>{idxConst});
+ curValue = fir::CoordinateOp::create(
+ firOpBuilder, clauseLocation, firOpBuilder.getRefType(memberTy),
+ curValue, llvm::SmallVector<fir::IntOrValue, 1>{idxConst});
// If we're a final member, the map will be generated by the processMap
// call that invoked this function.
@@ -417,7 +419,7 @@ mlir::Value createParentSymAndGenIntermediateMaps(
// Load the currently accessed member, so we can continue to access
// further segments.
- curValue = firOpBuilder.create<fir::LoadOp>(clauseLocation, curValue);
+ curValue = fir::LoadOp::create(firOpBuilder, clauseLocation, curValue);
currentIndicesIdx++;
}
}
@@ -662,89 +664,6 @@ bool collectLoopRelatedInfo(
return found;
}
-/// Get the directive enumeration value corresponding to the given OpenMP
-/// construct PFT node.
-llvm::omp::Directive
-extractOmpDirective(const parser::OpenMPConstruct &ompConstruct) {
- return common::visit(
- common::visitors{
- [](const parser::OpenMPAllocatorsConstruct &c) {
- return llvm::omp::OMPD_allocators;
- },
- [](const parser::OpenMPAssumeConstruct &c) {
- return llvm::omp::OMPD_assume;
- },
- [](const parser::OpenMPAtomicConstruct &c) {
- return llvm::omp::OMPD_atomic;
- },
- [](const parser::OpenMPBlockConstruct &c) {
- return std::get<parser::OmpBlockDirective>(
- std::get<parser::OmpBeginBlockDirective>(c.t).t)
- .v;
- },
- [](const parser::OpenMPCriticalConstruct &c) {
- return llvm::omp::OMPD_critical;
- },
- [](const parser::OpenMPDeclarativeAllocate &c) {
- return llvm::omp::OMPD_allocate;
- },
- [](const parser::OpenMPDispatchConstruct &c) {
- return llvm::omp::OMPD_dispatch;
- },
- [](const parser::OpenMPExecutableAllocate &c) {
- return llvm::omp::OMPD_allocate;
- },
- [](const parser::OpenMPLoopConstruct &c) {
- return std::get<parser::OmpLoopDirective>(
- std::get<parser::OmpBeginLoopDirective>(c.t).t)
- .v;
- },
- [](const parser::OpenMPSectionConstruct &c) {
- return llvm::omp::OMPD_section;
- },
- [](const parser::OpenMPSectionsConstruct &c) {
- return std::get<parser::OmpSectionsDirective>(
- std::get<parser::OmpBeginSectionsDirective>(c.t).t)
- .v;
- },
- [](const parser::OpenMPStandaloneConstruct &c) {
- return common::visit(
- common::visitors{
- [](const parser::OpenMPSimpleStandaloneConstruct &c) {
- return c.v.DirId();
- },
- [](const parser::OpenMPFlushConstruct &c) {
- return llvm::omp::OMPD_flush;
- },
- [](const parser::OpenMPCancelConstruct &c) {
- return llvm::omp::OMPD_cancel;
- },
- [](const parser::OpenMPCancellationPointConstruct &c) {
- return llvm::omp::OMPD_cancellation_point;
- },
- [](const parser::OmpMetadirectiveDirective &c) {
- return llvm::omp::OMPD_metadirective;
- },
- [](const parser::OpenMPDepobjConstruct &c) {
- return llvm::omp::OMPD_depobj;
- },
- [](const parser::OpenMPInteropConstruct &c) {
- return llvm::omp::OMPD_interop;
- }},
- c.u);
- },
- [](const parser::OpenMPUtilityConstruct &c) {
- return common::visit(
- common::visitors{[](const parser::OmpErrorDirective &c) {
- return llvm::omp::OMPD_error;
- },
- [](const parser::OmpNothingDirective &c) {
- return llvm::omp::OMPD_nothing;
- }},
- c.u);
- }},
- ompConstruct.u);
-}
} // namespace omp
} // namespace lower
} // namespace Fortran
diff --git a/flang/lib/Lower/OpenMP/Utils.h b/flang/lib/Lower/OpenMP/Utils.h
index 8e3ad5c..11641ba 100644
--- a/flang/lib/Lower/OpenMP/Utils.h
+++ b/flang/lib/Lower/OpenMP/Utils.h
@@ -167,8 +167,6 @@ bool collectLoopRelatedInfo(
mlir::omp::LoopRelatedClauseOps &result,
llvm::SmallVectorImpl<const semantics::Symbol *> &iv);
-llvm::omp::Directive
-extractOmpDirective(const parser::OpenMPConstruct &ompConstruct);
} // namespace omp
} // namespace lower
} // namespace Fortran