@@ -1356,6 +1356,41 @@ class OmpParallelOpConversionManager {
13561356 unsigned privateArgEndIdx;
13571357};
13581358
1359+ // Looks up from the operation from and returns the PrivateClauseOp with
1360+ // name symbolName
1361+ static omp::PrivateClauseOp findPrivatizer (Operation *from,
1362+ SymbolRefAttr symbolName) {
1363+ omp::PrivateClauseOp privatizer =
1364+ SymbolTable::lookupNearestSymbolFrom<omp::PrivateClauseOp>(from,
1365+ symbolName);
1366+ assert (privatizer && " privatizer not found in the symbol table" );
1367+ return privatizer;
1368+ }
1369+ // clones the given privatizer. The original privatizer is used as
1370+ // the insert point for the clone.
1371+ static omp::PrivateClauseOp
1372+ clonePrivatizer (LLVM::ModuleTranslation &moduleTranslation,
1373+ omp::PrivateClauseOp privatizer, Operation *fromOperation) {
1374+ MLIRContext &context = moduleTranslation.getContext ();
1375+ mlir::IRRewriter opCloner (&context);
1376+ opCloner.setInsertionPoint (privatizer);
1377+ auto clone =
1378+ llvm::cast<mlir::omp::PrivateClauseOp>(opCloner.clone (*privatizer));
1379+
1380+ // Unique the clone name to avoid clashes in the symbol table.
1381+ unsigned counter = 0 ;
1382+ SmallString<256 > cloneName = SymbolTable::generateSymbolName<256 >(
1383+ privatizer.getSymName (),
1384+ [&](llvm::StringRef candidate) {
1385+ return SymbolTable::lookupNearestSymbolFrom (
1386+ fromOperation, StringAttr::get (&context, candidate)) !=
1387+ nullptr ;
1388+ },
1389+ counter);
1390+
1391+ clone.setSymName (cloneName);
1392+ return clone;
1393+ }
13591394// / Converts the OpenMP parallel operation to LLVM IR.
13601395static LogicalResult
13611396convertOmpParallel (omp::ParallelOp opInst, llvm::IRBuilderBase &builder,
@@ -1611,34 +1646,14 @@ convertOmpParallel(omp::ParallelOp opInst, llvm::IRBuilderBase &builder,
16111646 continue ;
16121647
16131648 SymbolRefAttr privSym = llvm::cast<SymbolRefAttr>(mlirPrivatizerAttr);
1614- omp::PrivateClauseOp privatizer =
1615- SymbolTable::lookupNearestSymbolFrom<omp::PrivateClauseOp>(
1616- opInst, privSym);
1649+ omp::PrivateClauseOp privatizer = findPrivatizer (opInst, privSym);
16171650
16181651 // Clone the privatizer in case it is used by more than one parallel
16191652 // region. The privatizer is processed in-place (see below) before it
16201653 // gets inlined in the parallel region and therefore processing the
16211654 // original op is dangerous.
1622-
1623- MLIRContext &context = moduleTranslation.getContext ();
1624- mlir::IRRewriter opCloner (&context);
1625- opCloner.setInsertionPoint (privatizer);
1626- auto clone = llvm::cast<mlir::omp::PrivateClauseOp>(
1627- opCloner.clone (*privatizer));
1628-
1629- // Unique the clone name to avoid clashes in the symbol table.
1630- unsigned counter = 0 ;
1631- SmallString<256 > cloneName = SymbolTable::generateSymbolName<256 >(
1632- privatizer.getSymName (),
1633- [&](llvm::StringRef candidate) {
1634- return SymbolTable::lookupNearestSymbolFrom (
1635- opInst, StringAttr::get (&context, candidate)) !=
1636- nullptr ;
1637- },
1638- counter);
1639-
1640- clone.setSymName (cloneName);
1641- return {mlirPrivVar, clone};
1655+ return {mlirPrivVar,
1656+ clonePrivatizer (moduleTranslation, privatizer, opInst)};
16421657 }
16431658 }
16441659
@@ -3434,6 +3449,56 @@ convertOmpTarget(Operation &opInst, llvm::IRBuilderBase &builder,
34343449 const auto &arg = targetRegion.front ().getArgument (argIndex);
34353450 moduleTranslation.mapValue (arg, mapOpValue);
34363451 }
3452+
3453+ // Do privatization after moduleTranslation has already recorded
3454+ // mapped values.
3455+ if (!targetOp.getPrivateVars ().empty ()) {
3456+ builder.restoreIP (allocaIP);
3457+
3458+ OperandRange privateVars = targetOp.getPrivateVars ();
3459+ std::optional<ArrayAttr> privateSyms = targetOp.getPrivateSyms ();
3460+ unsigned numMapVars = targetOp.getMapVars ().size ();
3461+ Block &firstTargetBlock = targetRegion.front ();
3462+ BlockArgument *blockArgsStart = firstTargetBlock.getArguments ().begin ();
3463+ BlockArgument *privArgsStart = blockArgsStart + numMapVars;
3464+ BlockArgument *privArgsEnd =
3465+ privArgsStart + targetOp.getPrivateVars ().size ();
3466+ MutableArrayRef privateBlockArgs (privArgsStart, privArgsEnd);
3467+
3468+ for (auto [privVar, privatizerNameAttr, privBlockArg] :
3469+ llvm::zip_equal (privateVars, *privateSyms, privateBlockArgs)) {
3470+
3471+ SymbolRefAttr privSym = llvm::cast<SymbolRefAttr>(privatizerNameAttr);
3472+ omp::PrivateClauseOp privatizer = findPrivatizer (&opInst, privSym);
3473+ if (privatizer.getDataSharingType () ==
3474+ omp::DataSharingClauseType::FirstPrivate ||
3475+ !privatizer.getDeallocRegion ().empty ()) {
3476+ opInst.emitError (" Translation of omp.target from MLIR to LLVMIR "
3477+ " failed because translation of firstprivate and "
3478+ " private allocatables is not supported yet" );
3479+ bodyGenStatus = failure ();
3480+ } else {
3481+ Region &allocRegion = privatizer.getAllocRegion ();
3482+ BlockArgument allocRegionArg = allocRegion.getArgument (0 );
3483+ moduleTranslation.mapValue (allocRegionArg,
3484+ moduleTranslation.lookupValue (privVar));
3485+ SmallVector<llvm::Value *, 1 > yieldedValues;
3486+ if (failed (inlineConvertOmpRegions (
3487+ allocRegion, " omp.targetop.privatizer" , builder,
3488+ moduleTranslation, &yieldedValues))) {
3489+ opInst.emitError (
3490+ " failed to inline `alloc` region of an `omp.private` "
3491+ " op in the target region" );
3492+ bodyGenStatus = failure ();
3493+ } else {
3494+ assert (yieldedValues.size () == 1 );
3495+ moduleTranslation.mapValue (privBlockArg, yieldedValues.front ());
3496+ }
3497+ moduleTranslation.forgetMapping (allocRegion);
3498+ builder.restoreIP (builder.saveIP ());
3499+ }
3500+ }
3501+ }
34373502 llvm::BasicBlock *exitBlock = convertOmpOpRegions (
34383503 targetRegion, " omp.target" , builder, moduleTranslation, bodyGenStatus);
34393504 builder.SetInsertPoint (exitBlock);
0 commit comments