@@ -164,8 +164,20 @@ class OpenACCClauseCIREmitter final
164164 builder.setInsertionPoint (operation.computeOp );
165165 OpenACCClauseCIREmitter<typename OpTy::ComputeOpTy> computeEmitter{
166166 operation.computeOp , cgf, builder, dirKind, dirLoc};
167+
167168 computeEmitter.lastDeviceTypeValues = lastDeviceTypeValues;
169+
170+ // Async handler uses the first data operand to figure out where to insert
171+ // its information if it is present. This ensures that the new handler will
172+ // correctly set the insertion point for async.
173+ if (!dataOperands.empty ())
174+ computeEmitter.dataOperands .push_back (dataOperands.front ());
168175 computeEmitter.Visit (&c);
176+
177+ // Make sure all of the new data operands are kept track of here. The
178+ // combined constructs always apply 'async' to only the compute component,
179+ // so we need to collect these.
180+ dataOperands.append (computeEmitter.dataOperands );
169181 }
170182
171183 struct DataOperandInfo {
@@ -254,6 +266,8 @@ class OpenACCClauseCIREmitter final
254266 if constexpr (isOneOfTypes<OpTy, mlir::acc::ParallelOp, mlir::acc::SerialOp,
255267 mlir::acc::KernelsOp, mlir::acc::DataOp>)
256268 return operation.getAsyncOnlyAttr ();
269+ else if constexpr (isCombinedType<OpTy>)
270+ return operation.computeOp .getAsyncOnlyAttr ();
257271
258272 // Note: 'wait' has async as well, but it cannot have data clauses, so we
259273 // don't have to handle them here.
@@ -267,6 +281,8 @@ class OpenACCClauseCIREmitter final
267281 if constexpr (isOneOfTypes<OpTy, mlir::acc::ParallelOp, mlir::acc::SerialOp,
268282 mlir::acc::KernelsOp, mlir::acc::DataOp>)
269283 return operation.getAsyncOperandsDeviceTypeAttr ();
284+ else if constexpr (isCombinedType<OpTy>)
285+ return operation.computeOp .getAsyncOperandsDeviceTypeAttr ();
270286
271287 // Note: 'wait' has async as well, but it cannot have data clauses, so we
272288 // don't have to handle them here.
@@ -281,6 +297,8 @@ class OpenACCClauseCIREmitter final
281297 if constexpr (isOneOfTypes<OpTy, mlir::acc::ParallelOp, mlir::acc::SerialOp,
282298 mlir::acc::KernelsOp, mlir::acc::DataOp>)
283299 return operation.getAsyncOperands ();
300+ else if constexpr (isCombinedType<OpTy>)
301+ return operation.computeOp .getAsyncOperands ();
284302
285303 // Note: 'wait' has async as well, but it cannot have data clauses, so we
286304 // don't have to handle them here.
@@ -296,8 +314,6 @@ class OpenACCClauseCIREmitter final
296314 if (!hasAsyncClause || dataOperands.empty ())
297315 return ;
298316
299- // TODO: OpenACC: Handle this correctly for combined constructs.
300-
301317 for (mlir::Operation *dataOp : dataOperands) {
302318 llvm::TypeSwitch<mlir::Operation *, void >(dataOp)
303319 .Case <ACC_DATA_ENTRY_OPS, ACC_DATA_EXIT_OPS>([&](auto op) {
@@ -708,6 +724,8 @@ class OpenACCClauseCIREmitter final
708724 addDataOperand<mlir::acc::CopyinOp, mlir::acc::CopyoutOp>(
709725 var, mlir::acc::DataClause::acc_copy, /* structured=*/ true ,
710726 /* implicit=*/ false );
727+ } else if constexpr (isCombinedType<OpTy>) {
728+ applyToComputeOp (clause);
711729 } else {
712730 // TODO: When we've implemented this for everything, switch this to an
713731 // unreachable. data, declare, combined constructs remain.
0 commit comments