================
@@ -702,6 +745,170 @@ void OmpStructureChecker::CheckTraitSimd(
}
}
+void OmpStructureChecker::CollectMetadirectiveConstructSelectors(
+ const parser::ProgramUnit &programUnit) {
+ metadirectiveConstructSelectors_.clear();
+ MetadirectiveConstructSelectorCollector collector{
+ metadirectiveConstructSelectors_};
+ parser::Walk(programUnit, collector);
+}
+
+OmpStructureChecker::ConstructTraitSequence
+OmpStructureChecker::GetConstructTraitsForPath(
+ const EffectiveDirectivePath &path) const {
+ ConstructTraitSequence constructTraits;
+ for (auto directive{path.rbegin()}; directive != path.rend(); ++directive) {
+ // The construct trait set starts at the innermost target construct.
+ if (llvm::omp::allTargetSet.test(*directive)) {
+ constructTraits.clear();
+ }
+ for (llvm::omp::Directive leaf :
+ llvm::omp::getLeafConstructsOrSelf(*directive)) {
+ if (leaf == llvm::omp::Directive::OMPD_nothing ||
+ leaf == llvm::omp::Directive::OMPD_unknown) {
+ continue;
+ }
+ llvm::omp::VariantMatchInfo leafVMI;
+ AppendConstructTraitsForDirective(leaf, leafVMI);
+ if (leafVMI.ConstructTraits.empty()) {
+ // Source constructs without selector traits still occupy positions
+ // in the scoring context, including leaves of combined directives.
+ constructTraits.push_back(llvm::omp::TraitProperty::invalid);
----------------
MattPD wrote:
This code counts every leaf of every enclosing directive, while lowering's
`collectEnclosingConstructTraits` derives positions from emitted-operation
ancestry. The two disagree on three shapes. In each one, semantics skips a
loop-nest check that the merge base and
https://github.com/llvm/llvm-project/pull/224431 report. Lowering then selects
the replacement and aborts with a "not yet implemented" error:
- `tile` and `unroll`: Semantics counts them. Lowering never sees them, because
their operations have no region.
- `teams distribute parallel do`: Semantics puts `parallel` at source position
2. Lowering puts it at operation position 1.
- `assume`: Semantics counts it. Lowering emits nothing for it. OpenMP 5.2
section 8.3.3 classifies `assume` as informational, so lowering has the correct
depth in this case.
You can reproduce the first case by saving the following to `tile.f90` and
running `flang -fc1 -fopenmp -fopenmp-version=52 -emit-hlfir -o - tile.f90`:
```fortran
subroutine tile_gap(n, a)
integer :: n, a(n,n), i, j
!$omp tile sizes(2)
do i = 1, n
!$omp metadirective &
!$omp& when(implementation={vendor(score(3): llvm)}: simd collapse(2)) &
!$omp& when(device={arch(x86_64)}: nothing)
do j = 1, n
a(j,i) = j
end do
end do
end subroutine
```
At the merge base and on https://github.com/llvm/llvm-project/pull/224431 this
reports "This construct requires a nest of depth 2". With this PR, semantics
counts `tile`, scores `arch(x86_64)` 2^2 + 1 = 5 against 4, treats the SIMD
replacement as unreachable, and omits the diagnostic. Lowering scores it 3
against 4, selects the SIMD replacement, and aborts with "not yet implemented:
METADIRECTIVE variant with COLLAPSE or ORDERED requires a deeper
perfectly-nested loop nest than is present". Removing the `tile` line restores
the diagnostic, and `!$omp unroll partial(2)` behaves the same way.
The commit message states the invariant ("Reachability must use the same
construct positions and depth as lowering"), but the tests do not compare the
two phases. Could the two phases derive the position sequence from one shared
source that skips informational leaves? Paired semantics and lowering tests
would then cover three shapes: a construct selector under `teams distribute
parallel do`, a metadirective inside `tile`, and a metadirective inside
`assume`. The lowering-side causes are in
https://github.com/llvm/llvm-project/pull/224431.
https://github.com/llvm/llvm-project/pull/219014
_______________________________________________
llvm-branch-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits