diff --git a/clang/lib/CodeGen/CGStmtOpenMP.cpp b/clang/lib/CodeGen/CGStmtOpenMP.cpp --- a/clang/lib/CodeGen/CGStmtOpenMP.cpp +++ b/clang/lib/CodeGen/CGStmtOpenMP.cpp @@ -6533,6 +6533,8 @@ case OMPC_bind: case OMPC_align: case OMPC_cancellation_construct_type: + case OMPC_map_type: + case OMPC_map_type_modifier: llvm_unreachable("Clause is not allowed in 'omp atomic'."); } } diff --git a/flang/lib/Semantics/check-omp-structure.cpp b/flang/lib/Semantics/check-omp-structure.cpp --- a/flang/lib/Semantics/check-omp-structure.cpp +++ b/flang/lib/Semantics/check-omp-structure.cpp @@ -1867,6 +1867,8 @@ CHECK_SIMPLE_CLAUSE(Align, OMPC_align) CHECK_SIMPLE_CLAUSE(Compare, OMPC_compare) CHECK_SIMPLE_CLAUSE(CancellationConstructType, OMPC_cancellation_construct_type) +CHECK_SIMPLE_CLAUSE(MapType, OMPC_map_type) +CHECK_SIMPLE_CLAUSE(MapTypeModifier, OMPC_map_type_modifier) CHECK_REQ_SCALAR_INT_CLAUSE(Grainsize, OMPC_grainsize) CHECK_REQ_SCALAR_INT_CLAUSE(NumTasks, OMPC_num_tasks) diff --git a/llvm/include/llvm/Frontend/OpenMP/OMP.td b/llvm/include/llvm/Frontend/OpenMP/OMP.td --- a/llvm/include/llvm/Frontend/OpenMP/OMP.td +++ b/llvm/include/llvm/Frontend/OpenMP/OMP.td @@ -182,6 +182,47 @@ ]; } +def OMP_MAP_TYPE_To : ClauseVal<"to", 1, 1> {} +def OMP_MAP_TYPE_From : ClauseVal<"from", 2, 1> {} +def OMP_MAP_TYPE_ToFrom : ClauseVal<"tofrom", 3, 1> {} +def OMP_MAP_TYPE_Alloc : ClauseVal<"alloc", 4, 1> {} +def OMP_MAP_TYPE_Release : ClauseVal<"release", 5, 1> {} +def OMP_MAP_TYPE_Delete : ClauseVal<"delete", 6, 1> {} +def OMP_MAP_TYPE_None : ClauseVal<"none", 7, 0> { + let isDefault = 1; +} + +def OMPC_MapType : Clause<"map_type"> { + let enumClauseValue = "MapType"; + let allowedClauseValues = [ + OMP_MAP_TYPE_To, + OMP_MAP_TYPE_From, + OMP_MAP_TYPE_ToFrom, + OMP_MAP_TYPE_Alloc, + OMP_MAP_TYPE_Release, + OMP_MAP_TYPE_Delete, + OMP_MAP_TYPE_None + ]; +} + +def OMP_MAP_TYPE_MODIFIER_Always : ClauseVal<"always", 1, 1> {} +def OMP_MAP_TYPE_MODIFIER_Close : ClauseVal<"close", 2, 1> {} +def OMP_MAP_TYPE_MODIFIER_Present : ClauseVal<"present", 3, 1> {} +def OMP_MAP_TYPE_MODIFIER_None : ClauseVal<"none", 4, 0> { + let isDefault = 1; +} + +def OMPC_MapTypeModifier : Clause<"map_type_modifier"> { + let enumClauseValue = "MapTypeModifier"; + let allowedClauseValues = [ + OMP_MAP_TYPE_MODIFIER_Always, + OMP_MAP_TYPE_MODIFIER_Close, + OMP_MAP_TYPE_MODIFIER_Present, + //TODO : map-type-identifier mapper(mapper-identifier) + OMP_MAP_TYPE_MODIFIER_None + ]; +} + def OMPC_Ordered : Clause<"ordered"> { let clangClass = "OMPOrderedClause"; let flangClass = "ScalarIntConstantExpr"; diff --git a/mlir/include/mlir/Dialect/OpenMP/OpenMPOps.td b/mlir/include/mlir/Dialect/OpenMP/OpenMPOps.td --- a/mlir/include/mlir/Dialect/OpenMP/OpenMPOps.td +++ b/mlir/include/mlir/Dialect/OpenMP/OpenMPOps.td @@ -770,6 +770,169 @@ let assemblyFormat = "attr-dict"; } +//===---------------------------------------------------------------------===// +// 2.12.2 target data Construct +//===---------------------------------------------------------------------===// + +def Target_Data: OpenMP_Op<"target_data", [AttrSizedOperandSegments]>{ + let summary = "target data construct"; + let description = [{ + Map variables to a device data environment for the extent of the region. + + The omp target data directive maps variables to a device data + environment, and defines the lexical scope of the data environment + that is created. The omp target data directive can reduce data copies + to and from the offloading device when multiple target regions are using + the same data. + + The optional $if_expr parameter specifies a boolean result of a + conditional check. If this value is 1 or is not provided then the target + region runs on a device, if it is 0 then the target region is executed + on the host device. + + The optional $device parameter specifies the device number for the target + region. + + The optional $use_device_ptr specifies the device pointers to the + corresponding list items in the device data environment. + + The optional $use_device_addr specifies the address of the objects in the + device data enviornment. + + The $map_operands specifies operands in map clause. + + The $map_type specifies map-type within map clause and can take values to, + from, tofrom or alloc. + + The $map_type_modifier specifies the modifier and can be always, close, + present, iterator and mapper. + + TODO: depend clause and map_type_modifier values iterator and mapper. + }]; + + let arguments = (ins Optional:$if_expr, + Optional:$device, + Variadic:$use_device_ptr, + Variadic:$use_device_addr, + MapTypeModifierAttr:$map_type_modifier_val, + MapTypeAttr:$map_type_val, + Variadic:$map_operands); + + let regions = (region AnyRegion:$region); + + let assemblyFormat = [{ + (`if` `(` $if_expr^ `)` )? + (`device` `(` $device^ `:` type($device) `)` )? + (`use_device_ptr` `(` $use_device_ptr^ `:` type($use_device_ptr) `)` )? + (`use_device_addr` `(` $use_device_addr^ `:` type($use_device_addr) `)` )? + (`map` `(` $map_type_modifier_val `,` $map_type_val `:` $map_operands^ `:` type($map_operands) `)` )? + $region attr-dict + }]; + +} + +//===---------------------------------------------------------------------===// +// 2.12.3 target enter data Construct +//===---------------------------------------------------------------------===// + +def Target_EnterDataOp: OpenMP_Op<"target_enter_data", + [AttrSizedOperandSegments]>{ + let summary = "target enter data construct"; + let description = [{ + The target enter data directive specifies that variables are mapped to + a device data environment. The target enter data directive is a + stand-alone directive. + + The optional $if_expr parameter specifies a boolean result of a + conditional check. If this value is 1 or is not provided then the target + region runs on a device, if it is 0 then the target region is executed on + the host device. + + The optional $device parameter specifies the device number for the + target region. + + The optional $nowait eliminates the implicit barrier so the parent task + can make progress even if the target task is not yet completed. + + The $map_operands specifies operands in map clause. + + The $map_type specifies map-type within map clause and can take values to + or alloc. + + The $map_type_modifier specifies the modifier and can be always, close, + present, iterator and mapper. + + TODO: depend clause and map_type_modifier values iterator and mapper. + }]; + + let arguments = (ins Optional:$if_expr, + Optional:$device, + UnitAttr:$nowait, + MapTypeModifierAttr:$map_type_modifier_val, + MapTypeAttr:$map_type_val, + Variadic:$map_operands); + let hasCustomAssemblyFormat = 1; + let assemblyFormat = [{ + (`if` `(` $if_expr^ `)` )? + (`device` `(` $device^ `:` type($device) `)` )? + (`nowait` $nowait^ )? + (`map` `(` $map_type_modifier_val `,` $map_type_val `:` $map_operands^ `:` type($map_operands) `)` )? + attr-dict + }]; + +} + +//===---------------------------------------------------------------------===// +// 2.12.4 target exit data Construct +//===---------------------------------------------------------------------===// + +def Target_ExitDataOp: OpenMP_Op<"target_exit_data", + [AttrSizedOperandSegments]>{ + let summary = "target exit data construct"; + let description = [{ + The target exit data directive specifies that variables are mapped to a + device data environment. The target exit data directive is + a stand-alone directive. + + The optional $if_expr parameter specifies a boolean result of a + conditional check. If this value is 1 or is not provided then the target + region runs on a device, if it is 0 then the target region is executed + on the host device. + + The optional $device parameter specifies the device number for the + target region. + + The optional $nowait eliminates the implicit barrier so the parent + task can make progress even if the target task is not yet completed. + + The $map_operands specifies operands in map clause. + + The $map_type specifies map-type within map clause and can take values + from, release or delete. + + The $map_type_modifier specifies the modifier and can be always, close, + present, iterator and mapper. + + TODO: depend clause and map_type_modifier values iterator and mapper. + }]; + + let arguments = (ins Optional:$if_expr, + Optional:$device, + UnitAttr:$nowait, + MapTypeModifierAttr:$map_type_modifier_val, + MapTypeAttr:$map_type_val, + Variadic:$map_operands); + + let assemblyFormat = [{ + (`if` `(` $if_expr^ `)` )? + (`device` `(` $device^ `:` type($device) `)` )? + (`nowait` $nowait^ )? + (`map` `(` $map_type_modifier_val `,` $map_type_val `:` $map_operands^ `:` type($map_operands) `)` )? + attr-dict + }]; + +} + //===----------------------------------------------------------------------===// // 2.13.7 flush Construct //===----------------------------------------------------------------------===// diff --git a/mlir/test/Dialect/OpenMP/ops.mlir b/mlir/test/Dialect/OpenMP/ops.mlir --- a/mlir/test/Dialect/OpenMP/ops.mlir +++ b/mlir/test/Dialect/OpenMP/ops.mlir @@ -400,6 +400,26 @@ return } +// CHECK-LABEL: omp_target_data +func.func @omp_target_data (%if_cond : i1, %device : si32, %data1: memref, %data2: memref, %data3: memref) -> () { + + // CHECK: omp.target_data if(%arg0) device(%arg1 : si32) use_device_ptr(%arg2 : memref) use_device_addr(%arg3 : memref) map( present, tofrom : %arg4 : memref) { + "omp.target_data"(%if_cond, %device, %data1, %data2, %data3) ({ + // CHECK: omp.terminator + omp.terminator + }) {nowait, operand_segment_sizes = array, map_type_modifier_val = #omp, map_type_val = #omp} : ( i1, si32, memref, memref, memref ) -> () + + // CHECK: omp.target_enter_data if(%arg0) device(%arg1 : si32) nowait map( always, to : %arg2 : memref) + "omp.target_enter_data"(%if_cond, %device, %data1) {nowait, operand_segment_sizes = array, map_type_modifier_val = #omp, map_type_val = #omp} : ( i1, si32, memref ) -> () + + // CHECK: omp.target_exit_data if(%arg0) device(%arg1 : si32) nowait map( close, from : %arg2 : memref) + "omp.target_exit_data"(%if_cond, %device, %data1) {nowait, operand_segment_sizes = array, map_type_modifier_val = #omp, map_type_val = #omp} : ( i1, si32, memref ) -> () + + return +} + + + // CHECK-LABEL: omp_target_pretty func.func @omp_target_pretty(%if_cond : i1, %device : si32, %num_threads : i32) -> () { // CHECK: omp.target if({{.*}}) device({{.*}})