================
@@ -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