@@ -3001,27 +3001,42 @@ void genACCSetOp(Fortran::lower::AbstractConverter &converter,
30013001 }
30023002}
30033003
3004+ static inline mlir::ArrayAttr
3005+ getArrayAttr (fir::FirOpBuilder &b,
3006+ llvm::SmallVector<mlir::Attribute> &attributes) {
3007+ return attributes.empty () ? nullptr : b.getArrayAttr (attributes);
3008+ }
3009+
3010+ static inline mlir::DenseI32ArrayAttr
3011+ getDenseI32ArrayAttr (fir::FirOpBuilder &builder,
3012+ llvm::SmallVector<int32_t > &values) {
3013+ return values.empty () ? nullptr : builder.getDenseI32ArrayAttr (values);
3014+ }
3015+
30043016static void
30053017genACCUpdateOp (Fortran::lower::AbstractConverter &converter,
30063018 mlir::Location currentLocation,
30073019 Fortran::semantics::SemanticsContext &semanticsContext,
30083020 Fortran::lower::StatementContext &stmtCtx,
30093021 const Fortran::parser::AccClauseList &accClauseList) {
3010- mlir::Value ifCond, async, waitDevnum;
3022+ mlir::Value ifCond, waitDevnum;
30113023 llvm::SmallVector<mlir::Value> dataClauseOperands, updateHostOperands,
3012- waitOperands, deviceTypeOperands;
3013- llvm::SmallVector<mlir::Attribute> deviceTypes;
3014-
3015- // Async and wait clause have optional values but can be present with
3016- // no value as well. When there is no value, the op has an attribute to
3017- // represent the clause.
3018- bool addAsyncAttr = false ;
3019- bool addWaitAttr = false ;
3020- bool addIfPresentAttr = false ;
3024+ waitOperands, deviceTypeOperands, asyncOperands;
3025+ llvm::SmallVector<mlir::Attribute> asyncOperandsDeviceTypes,
3026+ asyncOnlyDeviceTypes, waitOperandsDeviceTypes, waitOnlyDeviceTypes;
3027+ llvm::SmallVector<int32_t > waitOperandsSegments;
30213028
30223029 fir::FirOpBuilder &builder = converter.getFirOpBuilder ();
30233030
3024- // Lower clauses values mapped to operands.
3031+ // device_type attribute is set to `none` until a device_type clause is
3032+ // encountered.
3033+ llvm::SmallVector<mlir::Attribute> crtDeviceTypes;
3034+ crtDeviceTypes.push_back (mlir::acc::DeviceTypeAttr::get (
3035+ builder.getContext (), mlir::acc::DeviceType::None));
3036+
3037+ bool ifPresent = false ;
3038+
3039+ // Lower clauses values mapped to operands and array attributes.
30253040 // Keep track of each group of operands separately as clauses can appear
30263041 // more than once.
30273042 for (const Fortran::parser::AccClause &clause : accClauseList.v ) {
@@ -3031,15 +3046,19 @@ genACCUpdateOp(Fortran::lower::AbstractConverter &converter,
30313046 genIfClause (converter, clauseLocation, ifClause, ifCond, stmtCtx);
30323047 } else if (const auto *asyncClause =
30333048 std::get_if<Fortran::parser::AccClause::Async>(&clause.u )) {
3034- genAsyncClause (converter, asyncClause, async, addAsyncAttr, stmtCtx);
3049+ genAsyncClause (converter, asyncClause, asyncOperands,
3050+ asyncOperandsDeviceTypes, asyncOnlyDeviceTypes,
3051+ crtDeviceTypes, stmtCtx);
30353052 } else if (const auto *waitClause =
30363053 std::get_if<Fortran::parser::AccClause::Wait>(&clause.u )) {
3037- genWaitClause (converter, waitClause, waitOperands, waitDevnum,
3038- addWaitAttr, stmtCtx);
3054+ genWaitClause (converter, waitClause, waitOperands,
3055+ waitOperandsDeviceTypes, waitOnlyDeviceTypes,
3056+ waitOperandsSegments, waitDevnum, crtDeviceTypes, stmtCtx);
30393057 } else if (const auto *deviceTypeClause =
30403058 std::get_if<Fortran::parser::AccClause::DeviceType>(
30413059 &clause.u )) {
3042- gatherDeviceTypeAttrs (builder, deviceTypeClause, deviceTypes);
3060+ crtDeviceTypes.clear ();
3061+ gatherDeviceTypeAttrs (builder, deviceTypeClause, crtDeviceTypes);
30433062 } else if (const auto *hostClause =
30443063 std::get_if<Fortran::parser::AccClause::Host>(&clause.u )) {
30453064 genDataOperandOperations<mlir::acc::GetDevicePtrOp>(
@@ -3053,7 +3072,7 @@ genACCUpdateOp(Fortran::lower::AbstractConverter &converter,
30533072 dataClauseOperands, mlir::acc::DataClause::acc_update_device, false ,
30543073 /* implicit=*/ false );
30553074 } else if (std::get_if<Fortran::parser::AccClause::IfPresent>(&clause.u )) {
3056- addIfPresentAttr = true ;
3075+ ifPresent = true ;
30573076 } else if (const auto *selfClause =
30583077 std::get_if<Fortran::parser::AccClause::Self>(&clause.u )) {
30593078 const std::optional<Fortran::parser::AccSelfClause> &accSelfClause =
@@ -3070,30 +3089,17 @@ genACCUpdateOp(Fortran::lower::AbstractConverter &converter,
30703089
30713090 dataClauseOperands.append (updateHostOperands);
30723091
3073- // Prepare the operand segment size attribute and the operands value range.
3074- llvm::SmallVector<mlir::Value> operands;
3075- llvm::SmallVector<int32_t > operandSegments;
3076- addOperand (operands, operandSegments, ifCond);
3077- addOperand (operands, operandSegments, async);
3078- addOperand (operands, operandSegments, waitDevnum);
3079- addOperands (operands, operandSegments, waitOperands);
3080- addOperands (operands, operandSegments, dataClauseOperands);
3081-
3082- mlir::acc::UpdateOp updateOp = createSimpleOp<mlir::acc::UpdateOp>(
3083- builder, currentLocation, operands, operandSegments);
3084- if (!deviceTypes.empty ())
3085- updateOp.setDeviceTypesAttr (
3086- mlir::ArrayAttr::get (builder.getContext (), deviceTypes));
3092+ builder.create <mlir::acc::UpdateOp>(
3093+ currentLocation, ifCond, asyncOperands,
3094+ getArrayAttr (builder, asyncOperandsDeviceTypes),
3095+ getArrayAttr (builder, asyncOnlyDeviceTypes), waitDevnum, waitOperands,
3096+ getDenseI32ArrayAttr (builder, waitOperandsSegments),
3097+ getArrayAttr (builder, waitOperandsDeviceTypes),
3098+ getArrayAttr (builder, waitOnlyDeviceTypes), dataClauseOperands,
3099+ ifPresent);
30873100
30883101 genDataExitOperations<mlir::acc::GetDevicePtrOp, mlir::acc::UpdateHostOp>(
30893102 builder, updateHostOperands, /* structured=*/ false );
3090-
3091- if (addAsyncAttr)
3092- updateOp.setAsyncAttr (builder.getUnitAttr ());
3093- if (addWaitAttr)
3094- updateOp.setWaitAttr (builder.getUnitAttr ());
3095- if (addIfPresentAttr)
3096- updateOp.setIfPresentAttr (builder.getUnitAttr ());
30973103}
30983104
30993105static void
0 commit comments