@@ -2383,15 +2383,38 @@ def OpenACC_LoopOp : OpenACC_Op<"loop",
2383
2383
let summary = "loop construct";
2384
2384
2385
2385
let description = [{
2386
- The "acc.loop" operation represents the OpenACC loop construct. The lower
2387
- and upper bounds specify a half-open range: the range includes the lower
2388
- bound but does not include the upper bound. If the `inclusive` attribute is
2389
- set then the upper bound is included.
2386
+ The `acc.loop` operation represents the OpenACC loop construct and when
2387
+ bounds are included, the associated source language loop iterators. The
2388
+ lower and upper bounds specify a half-open range: the range includes the
2389
+ lower bound but does not include the upper bound. If the `inclusive`
2390
+ attribute is set then the upper bound is included.
2391
+
2392
+ In cases where the OpenACC loop directive needs to capture multiple
2393
+ source language loops, such as in the case of `collapse` or `tile`,
2394
+ the multiple induction arguments are used to capture each case. Having
2395
+ such a representation makes sure no intermediate transformation such
2396
+ as Loop Invariant Code Motion breaks the property requested by the
2397
+ clause on the loop constructs.
2398
+
2399
+ Each `acc.loop` holds private and reduction operands which are the
2400
+ ssa values from the corresponding `acc.private` or `acc.reduction`
2401
+ operations. Additionally, firstprivate operands are supported to
2402
+ represent cases where privatization is needed with initialization
2403
+ from an original value. While the OpenACC specification does not
2404
+ explicitly support firstprivate on loop constructs, this extension
2405
+ enables representing privatization scenarios that arise from an
2406
+ optimization and codegen pipeline operating on acc dialect.
2407
+
2408
+ The operation supports capturing information that it comes combined
2409
+ constructs (e.g., `parallel loop`, `kernels loop`, `serial loop`)
2410
+ through the `combined` attribute despite requiring the `acc.loop`
2411
+ to be decomposed from the compute operation representing compute
2412
+ construct.
2390
2413
2391
2414
Example:
2392
2415
2393
2416
```mlir
2394
- acc.loop gang() vector() (%arg3 : index, %arg4 : index, %arg5 : index) =
2417
+ acc.loop gang() vector() (%arg3 : index, %arg4 : index, %arg5 : index) =
2395
2418
(%c0, %c0, %c0 : index, index, index) to
2396
2419
(%c10, %c10, %c10 : index, index, index) step
2397
2420
(%c1, %c1, %c1 : index, index, index) {
@@ -2400,10 +2423,12 @@ def OpenACC_LoopOp : OpenACC_Op<"loop",
2400
2423
} attributes { collapse = [3] }
2401
2424
```
2402
2425
2403
- `collapse`, `gang`, `worker`, `vector`, `seq`, `independent`, `auto` and
2404
- `tile` operands are supported with `device_type` information. They should
2405
- only be accessed by the extra provided getters. If modified, the
2406
- corresponding `device_type` attributes must be modified as well.
2426
+ `collapse`, `gang`, `worker`, `vector`, `seq`, `independent`, `auto`,
2427
+ `cache`, and `tile` operands are supported with `device_type`
2428
+ information. These clauses should only be accessed through the provided
2429
+ device-type-aware getter methods. When modifying these operands, the
2430
+ corresponding `device_type` attributes must be updated to maintain
2431
+ consistency between operands and their target device types.
2407
2432
}];
2408
2433
2409
2434
let arguments = (ins
@@ -2433,6 +2458,8 @@ def OpenACC_LoopOp : OpenACC_Op<"loop",
2433
2458
Variadic<OpenACC_AnyPointerOrMappableType>:$cacheOperands,
2434
2459
Variadic<OpenACC_AnyPointerOrMappableType>:$privateOperands,
2435
2460
OptionalAttr<SymbolRefArrayAttr>:$privatizationRecipes,
2461
+ Variadic<OpenACC_AnyPointerOrMappableType>:$firstprivateOperands,
2462
+ OptionalAttr<SymbolRefArrayAttr>:$firstprivatizationRecipes,
2436
2463
Variadic<AnyType>:$reductionOperands,
2437
2464
OptionalAttr<SymbolRefArrayAttr>:$reductionRecipes,
2438
2465
OptionalAttr<OpenACC_CombinedConstructsAttr>:$combined
@@ -2589,6 +2616,10 @@ def OpenACC_LoopOp : OpenACC_Op<"loop",
2589
2616
/// Adds a private clause variable to this operation, including its recipe.
2590
2617
void addPrivatization(MLIRContext *, mlir::acc::PrivateOp op,
2591
2618
mlir::acc::PrivateRecipeOp recipe);
2619
+ /// Adds a firstprivate clause variable to this operation, including its
2620
+ /// recipe.
2621
+ void addFirstPrivatization(MLIRContext *, mlir::acc::FirstprivateOp op,
2622
+ mlir::acc::FirstprivateRecipeOp recipe);
2592
2623
/// Adds a reduction clause variable to this operation, including its
2593
2624
/// recipe.
2594
2625
void addReduction(MLIRContext *, mlir::acc::ReductionOp op,
@@ -2609,6 +2640,8 @@ def OpenACC_LoopOp : OpenACC_Op<"loop",
2609
2640
type($vectorOperands), $vectorOperandsDeviceType, $vector)
2610
2641
| `private` `(` custom<SymOperandList>(
2611
2642
$privateOperands, type($privateOperands), $privatizationRecipes) `)`
2643
+ | `firstprivate` `(` custom<SymOperandList>($firstprivateOperands,
2644
+ type($firstprivateOperands), $firstprivatizationRecipes) `)`
2612
2645
| `tile` `(` custom<DeviceTypeOperandsWithSegment>($tileOperands,
2613
2646
type($tileOperands), $tileOperandsDeviceType, $tileOperandsSegments)
2614
2647
`)`
@@ -2665,6 +2698,8 @@ def OpenACC_LoopOp : OpenACC_Op<"loop",
2665
2698
/*cacheOperands=*/{},
2666
2699
/*privateOperands=*/{},
2667
2700
/*privatizationRecipes=*/nullptr,
2701
+ /*firstprivateOperands=*/{},
2702
+ /*firstprivatizationRecipes=*/nullptr,
2668
2703
/*reductionOperands=*/{},
2669
2704
/*reductionRecipes=*/nullptr,
2670
2705
/*combined=*/nullptr);
0 commit comments