mirror of
https://github.com/llvm/llvm-project.git
synced 2025-04-17 23:36:40 +00:00

Fixes a bug in reductions when converting `teams loop` constructs with `reduction` clauses. According to the spec (v5.2, p340, 36): ``` The effect of the reduction clause is as if it is applied to all leaf constructs that permit the clause, except for the following constructs: * .... * The teams construct, when combined with the loop construct. ``` Therefore, for a combined directive similar to: `!$omp teams loop reduction(...)`, the earlier stages of the compiler assign the `reduction` clauses only to the `loop` leaf and not to the `teams` leaf. On the other hand, if we have a combined construct similar to: `!$omp teams distribute parallel do`, the `reduction` clauses are assigned both to the `teams` and the `do` leaves. We need to match this behavior when we convert `teams` op with a nested `loop` op since the target set of constructs/ops will be incorrect without moving the reductions up to the `teams` op as well. This PR introduces a pattern that does exactly this. Given the following input: ``` omp.teams { omp.loop reduction(@red_sym %red_op -> %red_arg : !fir.ref<i32>) { omp.loop_nest ... { ... } } } ``` this pattern updates the `omp.teams` op in-place to: ``` omp.teams reduction(@red_sym %red_op -> %teams_red_arg : !fir.ref<i32>) { omp.loop reduction(@red_sym %teams_red_arg -> %red_arg : !fir.ref<i32>) { omp.loop_nest ... { ... } } } ``` Note the following: * The nested `omp.loop` is not rewritten by this pattern, this happens through `GenericLoopConversionPattern`. * The reduction info are cloned from the nested `omp.loop` op to the parent `omp.teams` op. * The reduction operand of the `omp.loop` op is updated to be the **new** reduction block argument of the `omp.teams` op.