@@ -1356,6 +1356,41 @@ class OmpParallelOpConversionManager {
1356
1356
unsigned privateArgEndIdx;
1357
1357
};
1358
1358
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
+ }
1359
1394
// / Converts the OpenMP parallel operation to LLVM IR.
1360
1395
static LogicalResult
1361
1396
convertOmpParallel (omp::ParallelOp opInst, llvm::IRBuilderBase &builder,
@@ -1611,34 +1646,14 @@ convertOmpParallel(omp::ParallelOp opInst, llvm::IRBuilderBase &builder,
1611
1646
continue ;
1612
1647
1613
1648
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);
1617
1650
1618
1651
// Clone the privatizer in case it is used by more than one parallel
1619
1652
// region. The privatizer is processed in-place (see below) before it
1620
1653
// gets inlined in the parallel region and therefore processing the
1621
1654
// 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)};
1642
1657
}
1643
1658
}
1644
1659
@@ -3434,6 +3449,56 @@ convertOmpTarget(Operation &opInst, llvm::IRBuilderBase &builder,
3434
3449
const auto &arg = targetRegion.front ().getArgument (argIndex);
3435
3450
moduleTranslation.mapValue (arg, mapOpValue);
3436
3451
}
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
+ }
3437
3502
llvm::BasicBlock *exitBlock = convertOmpOpRegions (
3438
3503
targetRegion, " omp.target" , builder, moduleTranslation, bodyGenStatus);
3439
3504
builder.SetInsertPoint (exitBlock);
0 commit comments