@@ -29,6 +29,7 @@ def OpenMP_Dialect : Dialect {
29
29
let cppNamespace = "::mlir::omp";
30
30
let dependentDialects = ["::mlir::LLVM::LLVMDialect, ::mlir::func::FuncDialect"];
31
31
let useDefaultAttributePrinterParser = 1;
32
+ let useDefaultTypePrinterParser = 1;
32
33
}
33
34
34
35
// OmpCommon requires definition of OpenACC_Dialect.
@@ -89,6 +90,10 @@ def IntLikeType : AnyTypeOf<[AnyInteger, Index]>;
89
90
def OpenMP_PointerLikeType : TypeAlias<OpenMP_PointerLikeTypeInterface,
90
91
"OpenMP-compatible variable type">;
91
92
93
+ class OpenMP_Type<string name, string typeMnemonic> : TypeDef<OpenMP_Dialect, name> {
94
+ let mnemonic = typeMnemonic;
95
+ }
96
+
92
97
//===----------------------------------------------------------------------===//
93
98
// 2.12.7 Declare Target Directive
94
99
//===----------------------------------------------------------------------===//
@@ -1004,6 +1009,220 @@ def FlushOp : OpenMP_Op<"flush"> {
1004
1009
}];
1005
1010
}
1006
1011
1012
+ //===----------------------------------------------------------------------===//
1013
+ // Map related constructs
1014
+ //===----------------------------------------------------------------------===//
1015
+
1016
+ def CaptureThis : I32EnumAttrCase<"This", 0>;
1017
+ def CaptureByRef : I32EnumAttrCase<"ByRef", 1>;
1018
+ def CaptureByCopy : I32EnumAttrCase<"ByCopy", 2>;
1019
+ def CaptureVLAType : I32EnumAttrCase<"VLAType", 3>;
1020
+
1021
+ def VariableCaptureKind : I32EnumAttr<
1022
+ "VariableCaptureKind",
1023
+ "variable capture kind",
1024
+ [CaptureThis, CaptureByRef, CaptureByCopy, CaptureVLAType]> {
1025
+ let genSpecializedAttr = 0;
1026
+ let cppNamespace = "::mlir::omp";
1027
+ }
1028
+
1029
+ def VariableCaptureKindAttr : EnumAttr<OpenMP_Dialect, VariableCaptureKind,
1030
+ "variable_capture_kind"> {
1031
+ let assemblyFormat = "`(` $value `)`";
1032
+ }
1033
+
1034
+ def DataBoundsType : OpenMP_Type<"DataBounds", "data_bounds_ty"> {
1035
+ let summary = "Type for representing omp data clause bounds information";
1036
+ }
1037
+
1038
+ def DataBoundsOp : OpenMP_Op<"bounds",
1039
+ [AttrSizedOperandSegments, NoMemoryEffect]> {
1040
+ let summary = "Represents normalized bounds information for map clauses.";
1041
+
1042
+ let description = [{
1043
+ This operation is a variation on the OpenACC dialects DataBoundsOp. Within
1044
+ the OpenMP dialect it stores the bounds/range of data to be mapped to a
1045
+ device specified by map clauses on target directives. Within,
1046
+ the OpenMP dialect the DataBoundsOp is associated with MapInfoOp,
1047
+ helping to store bounds information for the mapped variable.
1048
+
1049
+ It is used to support OpenMP array sectioning, Fortran pointer and
1050
+ allocatable mapping and pointer/allocatable member of derived types.
1051
+ In all cases the DataBoundsOp holds information on the section of
1052
+ data to be mapped. Such as the upper bound and lower bound of the
1053
+ section of data to be mapped. This information is currently
1054
+ utilised by the LLVM-IR lowering to help generate instructions to
1055
+ copy data to and from the device when processing target operations.
1056
+
1057
+ The example below copys a section of a 10-element array; all except the
1058
+ first element, utilising OpenMP array sectioning syntax where array
1059
+ subscripts are provided to specify the bounds to be mapped to device.
1060
+ To simplify the examples, the constants are used directly, in reality
1061
+ they will be MLIR SSA values.
1062
+
1063
+ C++:
1064
+ ```
1065
+ int array[10];
1066
+ #pragma target map(array[1:9])
1067
+ ```
1068
+ =>
1069
+ ```mlir
1070
+ omp.bounds lower_bound(1) upper_bound(9) extent(9) start_idx(0)
1071
+ ```
1072
+
1073
+ Fortran:
1074
+ ```
1075
+ integer :: array(1:10)
1076
+ !$target map(array(2:10))
1077
+ ```
1078
+ =>
1079
+ ```mlir
1080
+ omp.bounds lower_bound(1) upper_bound(9) extent(9) start_idx(1)
1081
+ ```
1082
+
1083
+ For Fortran pointers and allocatables (as well as those that are
1084
+ members of derived types) the bounds information is provided by
1085
+ the Fortran compiler and runtime through descriptor information.
1086
+
1087
+ A basic pointer example can be found below (constants again
1088
+ provided for simplicity, where in reality SSA values will be
1089
+ used, in this case that point to data yielded by Fortran's
1090
+ descriptors):
1091
+
1092
+ Fortran:
1093
+ ```
1094
+ integer, pointer :: ptr(:)
1095
+ allocate(ptr(10))
1096
+ !$target map(ptr)
1097
+ ```
1098
+ =>
1099
+ ```mlir
1100
+ omp.bounds lower_bound(0) upper_bound(9) extent(10) start_idx(1)
1101
+ ```
1102
+
1103
+ This operation records the bounds information in a normalized fashion
1104
+ (zero-based). This works well with the `PointerLikeType`
1105
+ requirement in data clauses - since a `lower_bound` of 0 means looking
1106
+ at data at the zero offset from pointer.
1107
+
1108
+ This operation must have an `upper_bound` or `extent` (or both are allowed -
1109
+ but not checked for consistency). When the source language's arrays are
1110
+ not zero-based, the `start_idx` must specify the zero-position index.
1111
+ }];
1112
+
1113
+ let arguments = (ins Optional<IntLikeType>:$lower_bound,
1114
+ Optional<IntLikeType>:$upper_bound,
1115
+ Optional<IntLikeType>:$extent,
1116
+ Optional<IntLikeType>:$stride,
1117
+ DefaultValuedAttr<BoolAttr, "false">:$stride_in_bytes,
1118
+ Optional<IntLikeType>:$start_idx);
1119
+ let results = (outs DataBoundsType:$result);
1120
+
1121
+ let assemblyFormat = [{
1122
+ oilist(
1123
+ `lower_bound` `(` $lower_bound `:` type($lower_bound) `)`
1124
+ | `upper_bound` `(` $upper_bound `:` type($upper_bound) `)`
1125
+ | `extent` `(` $extent `:` type($extent) `)`
1126
+ | `stride` `(` $stride `:` type($stride) `)`
1127
+ | `start_idx` `(` $start_idx `:` type($start_idx) `)`
1128
+ ) attr-dict
1129
+ }];
1130
+
1131
+ let extraClassDeclaration = [{
1132
+ /// The number of variable operands.
1133
+ unsigned getNumVariableOperands() {
1134
+ return getNumOperands();
1135
+ }
1136
+
1137
+ /// The i-th variable operand passed.
1138
+ Value getVariableOperand(unsigned i) {
1139
+ return getOperands()[i];
1140
+ }
1141
+ }];
1142
+
1143
+ let hasVerifier = 1;
1144
+ }
1145
+
1146
+ def MapInfoOp : OpenMP_Op<"map_info", [AttrSizedOperandSegments]> {
1147
+ let arguments = (ins OpenMP_PointerLikeType:$var_ptr,
1148
+ Optional<OpenMP_PointerLikeType>:$var_ptr_ptr,
1149
+ Variadic<DataBoundsType>:$bounds, /* rank-0 to rank-{n-1} */
1150
+ OptionalAttr<UI64Attr>:$map_type,
1151
+ OptionalAttr<VariableCaptureKindAttr>:$map_capture_type,
1152
+ DefaultValuedAttr<BoolAttr, "false">:$implicit,
1153
+ OptionalAttr<StrAttr>:$name);
1154
+ let results = (outs OpenMP_PointerLikeType:$omp_ptr);
1155
+
1156
+ let description = [{
1157
+ The MapInfoOp captures information relating to individual OpenMP map clauses
1158
+ that are applied to certain OpenMP directives such as Target and Target Data.
1159
+
1160
+ For example, the map type modifier; such as from, tofrom and to, the variable
1161
+ being captured or the bounds of an array section being mapped.
1162
+
1163
+ It can be used to capture both implicit and explicit map information, where
1164
+ explicit is an argument directly specified to an OpenMP map clause or implicit
1165
+ where a variable is utilised in a target region but is defined externally to
1166
+ the target region.
1167
+
1168
+ This map information is later used to aid the lowering of the target operations
1169
+ they are attached to providing argument input and output context for kernels
1170
+ generated or the target data mapping environment.
1171
+
1172
+ Example (Fortran):
1173
+
1174
+ ```
1175
+ integer :: index
1176
+ !$target map(to: index)
1177
+ ```
1178
+ =>
1179
+ ```mlir
1180
+ omp.map_info var_ptr(%index_ssa) map_type(to) map_capture_type(ByRef) implicit(false)
1181
+ name(index)
1182
+ ```
1183
+
1184
+ Description of arguments:
1185
+ - `var_ptr`: The address of variable to copy.
1186
+ - `var_ptr_ptr`: Used when the variable copied is a member of a class, structure
1187
+ or derived type and refers to the originating struct.
1188
+ - `bounds`: Used when copying slices of array's, pointers or pointer members of
1189
+ objects (e.g. derived types or classes), indicates the bounds to be copied
1190
+ of the variable. When it's an array slice it is in rank order where rank 0
1191
+ is the inner-most dimension.
1192
+ - `implicit`: indicates where the map item has been specified explicitly in a
1193
+ map clause or captured implicitly by being used in a target region with no
1194
+ map or other data mapping construct.
1195
+ - 'map_clauses': OpenMP map type for this map capture, for example: from, to and
1196
+ always. It's a bitfield composed of the OpenMP runtime flags stored in
1197
+ OpenMPOffloadMappingFlags.
1198
+ - 'map_capture_type': Capture type for the variable e.g. this, byref, byvalue, byvla
1199
+ this can affect how the variable is lowered.
1200
+ - `name`: Holds the name of variable as specified in user clause (including bounds).
1201
+ }];
1202
+
1203
+ let assemblyFormat = [{
1204
+ `var_ptr` `(` $var_ptr `:` type($var_ptr) `)`
1205
+ oilist(
1206
+ `var_ptr_ptr` `(` $var_ptr_ptr `:` type($var_ptr_ptr) `)`
1207
+ | `map_clauses` `(` custom<MapClause>($map_type) `)`
1208
+ | `capture` `(` custom<CaptureType>($map_capture_type) `)`
1209
+ | `bounds` `(` $bounds `)`
1210
+ ) `->` type($omp_ptr) attr-dict
1211
+ }];
1212
+
1213
+ let extraClassDeclaration = [{
1214
+ /// The number of variable operands.
1215
+ unsigned getNumVariableOperands() {
1216
+ return getNumOperands();
1217
+ }
1218
+
1219
+ /// The i-th variable operand passed.
1220
+ Value getVariableOperand(unsigned i) {
1221
+ return getOperands()[i];
1222
+ }
1223
+ }];
1224
+ }
1225
+
1007
1226
//===---------------------------------------------------------------------===//
1008
1227
// 2.14.2 target data Construct
1009
1228
//===---------------------------------------------------------------------===//
@@ -1044,16 +1263,14 @@ def Target_DataOp: OpenMP_Op<"target_data", [AttrSizedOperandSegments]>{
1044
1263
Optional<AnyInteger>:$device,
1045
1264
Variadic<OpenMP_PointerLikeType>:$use_device_ptr,
1046
1265
Variadic<OpenMP_PointerLikeType>:$use_device_addr,
1047
- Variadic<OpenMP_PointerLikeType>:$map_operands,
1048
- OptionalAttr<I64ArrayAttr>:$map_types);
1266
+ Variadic<OpenMP_PointerLikeType>:$map_operands);
1049
1267
1050
1268
let regions = (region AnyRegion:$region);
1051
1269
1052
1270
let assemblyFormat = [{
1053
1271
oilist(`if` `(` $if_expr `:` type($if_expr) `)`
1054
1272
| `device` `(` $device `:` type($device) `)`
1055
- | `map`
1056
- `(` custom<MapClause>($map_operands, type($map_operands), $map_types) `)`
1273
+ | `map_entries` `(` $map_operands `:` type($map_operands) `)`
1057
1274
| `use_device_ptr` `(` $use_device_ptr `:` type($use_device_ptr) `)`
1058
1275
| `use_device_addr` `(` $use_device_addr `:` type($use_device_addr) `)`)
1059
1276
$region attr-dict
@@ -1095,15 +1312,14 @@ def Target_EnterDataOp: OpenMP_Op<"target_enter_data",
1095
1312
let arguments = (ins Optional<I1>:$if_expr,
1096
1313
Optional<AnyInteger>:$device,
1097
1314
UnitAttr:$nowait,
1098
- Variadic<OpenMP_PointerLikeType>:$map_operands,
1099
- I64ArrayAttr:$map_types);
1315
+ Variadic<OpenMP_PointerLikeType>:$map_operands);
1100
1316
1101
1317
let assemblyFormat = [{
1102
1318
oilist(`if` `(` $if_expr `:` type($if_expr) `)`
1103
1319
| `device` `(` $device `:` type($device) `)`
1104
- | `nowait` $nowait)
1105
- `map ` `(` custom<MapClause>( $map_operands, type($map_operands), $map_types ) `)`
1106
- attr-dict
1320
+ | `nowait` $nowait
1321
+ | `map_entries ` `(` $map_operands `:` type($map_operands) `)`
1322
+ ) attr-dict
1107
1323
}];
1108
1324
1109
1325
let hasVerifier = 1;
@@ -1142,15 +1358,14 @@ def Target_ExitDataOp: OpenMP_Op<"target_exit_data",
1142
1358
let arguments = (ins Optional<I1>:$if_expr,
1143
1359
Optional<AnyInteger>:$device,
1144
1360
UnitAttr:$nowait,
1145
- Variadic<OpenMP_PointerLikeType>:$map_operands,
1146
- I64ArrayAttr:$map_types);
1361
+ Variadic<OpenMP_PointerLikeType>:$map_operands);
1147
1362
1148
1363
let assemblyFormat = [{
1149
1364
oilist(`if` `(` $if_expr `:` type($if_expr) `)`
1150
1365
| `device` `(` $device `:` type($device) `)`
1151
- | `nowait` $nowait)
1152
- `map ` `(` custom<MapClause>( $map_operands, type($map_operands), $map_types ) `)`
1153
- attr-dict
1366
+ | `nowait` $nowait
1367
+ | `map_entries ` `(` $map_operands `:` type($map_operands) `)`
1368
+ ) attr-dict
1154
1369
}];
1155
1370
1156
1371
let hasVerifier = 1;
@@ -1186,8 +1401,7 @@ def TargetOp : OpenMP_Op<"target",[AttrSizedOperandSegments]> {
1186
1401
Optional<AnyInteger>:$device,
1187
1402
Optional<AnyInteger>:$thread_limit,
1188
1403
UnitAttr:$nowait,
1189
- Variadic<OpenMP_PointerLikeType>:$map_operands,
1190
- OptionalAttr<I64ArrayAttr>:$map_types);
1404
+ Variadic<OpenMP_PointerLikeType>:$map_operands);
1191
1405
1192
1406
let regions = (region AnyRegion:$region);
1193
1407
@@ -1196,7 +1410,7 @@ def TargetOp : OpenMP_Op<"target",[AttrSizedOperandSegments]> {
1196
1410
| `device` `(` $device `:` type($device) `)`
1197
1411
| `thread_limit` `(` $thread_limit `:` type($thread_limit) `)`
1198
1412
| `nowait` $nowait
1199
- | `map ` `(` custom<MapClause>( $map_operands, type($map_operands), $map_types ) `)`
1413
+ | `map_entries ` `(` $map_operands `:` type($map_operands) `)`
1200
1414
) $region attr-dict
1201
1415
}];
1202
1416
0 commit comments