================
@@ -8232,6 +8264,49 @@ convertOmpTarget(Operation &opInst, llvm::IRBuilderBase 
&builder,
   bool isOffloadEntry =
       isTargetDevice || !ompBuilder->Config.TargetTriples.empty();
 
+  // Validate and resolve in_reduction clauses on omp.target. We currently
+  // only support the non-offload host-fallback path: the per-task private
+  // pointer is obtained by calling __kmpc_task_reduction_get_th_data inside
+  // the to-be-outlined target task body. Threading that pointer through the
+  // device kernel argument list is left as follow-up work.
+  SmallVector<llvm::Value *> inRedOrigPtrs;
+  SmallVector<unsigned> inRedMapArgIdx;
+  if (!targetOp.getInReductionVars().empty()) {
+    if (isTargetDevice || isOffloadEntry)
+      return opInst.emitError(
+          "not yet implemented: in_reduction clause on omp.target with "
+          "offload / target-device compilation");
+    // The byref / cleanup-region / two-argument-initializer in_reduction
+    // shapes are rejected earlier by checkImplementationStatus, and symbol
+    // resolution is guaranteed by verifyReductionVarList.
+    //
+    // The target body has no dedicated in_reduction block argument: each
+    // in_reduction variable is accessed through its map_entries block 
argument,
+    // which the host redirects to the per-task reduction-private storage 
below.
+    // So each in_reduction variable must also be captured by the target via a
+    // map_entries entry referring to the same outer SSA value. That value is
+    // also used as the `orig` argument of the runtime lookup, so without a
+    // matching map entry the outlined kernel would reference a value defined 
in
+    // the host function and fail IR verification. Record, for each 
in_reduction
+    // variable, the position of its matching map entry so the corresponding 
map
+    // block argument can be redirected once we are inside the body.
+    llvm::SmallDenseMap<Value, unsigned> mapVarPtrToArgIdx;
+    for (auto [idx, mapV] : llvm::enumerate(targetOp.getMapVars()))
+      if (auto mapInfo = mapV.getDefiningOp<omp::MapInfoOp>())
+        mapVarPtrToArgIdx.try_emplace(mapInfo.getVarPtr(), idx);
----------------
MattPD wrote:

Nit: `try_emplace` keeps the first map index for a given `var_ptr`. So if an 
`omp.target` had two `map_entries` for the same value and the body used the 
second, the redirect below would rewire the first block argument while the body 
kept using the original pointer (a silent wrong reduction). Flang won't produce 
that today (it dedups via `isDuplicateMappedSymbol`), but the verifier doesn't 
forbid it, so this would want a graceful "not yet implemented" diagnostic 
rather than an `assert`. Worth adding to harden this path?

https://github.com/llvm/llvm-project/pull/199967
_______________________________________________
llvm-branch-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits

Reply via email to