diff options
Diffstat (limited to 'flang/lib/Lower/OpenMP')
-rw-r--r-- | flang/lib/Lower/OpenMP/Atomic.cpp | 37 | ||||
-rw-r--r-- | flang/lib/Lower/OpenMP/ClauseProcessor.cpp | 88 | ||||
-rw-r--r-- | flang/lib/Lower/OpenMP/Clauses.cpp | 95 | ||||
-rw-r--r-- | flang/lib/Lower/OpenMP/DataSharingProcessor.cpp | 30 | ||||
-rw-r--r-- | flang/lib/Lower/OpenMP/OpenMP.cpp | 301 | ||||
-rw-r--r-- | flang/lib/Lower/OpenMP/Utils.cpp | 109 | ||||
-rw-r--r-- | flang/lib/Lower/OpenMP/Utils.h | 2 |
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 ®ion = updateOp->getRegion(0); mlir::Block *block = builder.createBlock(®ion, {}, {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(®ion); 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 ®ion = op->getRegion(0); + + // Create the op's region skeleton (BB taking the iv as argument) + firOpBuilder.createBlock(®ion, {}, {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 ®ion = declMapperOp.getRegion(); firOpBuilder.createBlock(®ion); 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 |