Hi Sandra,

Sandra Loosemore wrote:
On 1/9/25 05:17, Tobias Burnus wrote:
A case where 'omp error' diagnostic should be delayed - and (here) suppressed:
["should" in the sense it would be good not in the sense "shall".]

program_control/sources/error.1.c:15:23: error: ‘pragma omp error’ encountered: GNU compiler required.
    15 |             otherwise(error at(compilation) severity(fatal) \
       |                       ^~~~~

Hmmm.  Here the 6.0 spec says: […] IOW, the spec doesn't require implementations to solve the halting problem ;-) but we could theoretically defer the error to suppress cases where the directive is optimized away.  How about I just file a PR for this for now?  It's a problem with #pragma omp error, not metadirective, anyway, so independent of this patch series.

Yes, putting it into an PR is good, as proposed. It is not directly related to metadirectives, but I metadirectives are the case that makes most sense to handle (possibly besides delimited declare variant) as it permits special case handling.

For a block under 'if (false)' it makes more sense to have the still diagnostic …

* * *

Here, it seems as if the 'target' + 'teams' without intervening code check has to be updated:

program_control/sources/metadirective.1.c:16:12: error: ‘target’ construct with nested ‘teams’ construct contains directives outside of the ‘teams’ construct […]

    #pragma omp target map(to:v1,v2) map(from:v3) device(0)
    #pragma omp metadirective \
                    when(     device={arch("nvptx")}: teams loop) \
                    otherwise(                     parallel loop)
      for (int i= 0; i< N; i++)  v3[i] = v1[i] * v2[i];
This diagnostic is coming from omp-low.cc rather than any of the front ends.  By that time the metadirective has been gimplified into a conditional for late resolution.  I'm not sure what the right thing to do here is; is there an actual problem with code generation if there is some expression to test a condition between the "target" and "teams"?

Yes. The problem is that there is no real "in between". 'target' + 'teams' works by 'target' handling all the device setup before/after – but then it directly launches the kernel with multiple teams on the device and no way to synchronize the teams.

Thus, it is semantically not possible to do something between starting the target region and entering the teams. Any code that happens to be there will either be ignored, run on the host or concurrently in multiple teams, none of which is correct.

This case clearly shows that pushing the outer "target" into each of the metadirective alternatives wouldn't work (because the test expression depends on it).  File another PR for now?

Yes, but that is a relatively common pattern to use 'teams' in some cases and not in others, which is underlined by showing up both in the example document and OpenMP_VV. Albeit using 'target teams' instead of 'teams' with an outer 'target' is an obvious alternative, reducing the usefullness a bit. Still, I expect this showing up in real-world code.

Thus, fine for a PR but we should also try to get this fixed.

* * *

Continuing with OpenMP_VV - I think the programmer meant 'device' and not 'target_device', but I think GCC overdoes the diagnostic, given that there
are only two 'target_device':

tests/5.1/metadirective/test_metadirective_target_device.c:30:15: sorry, unimplemented: ‘target_device’ tests/5.1/metadirective/test_metadirective_target_device.c:30:15: sorry, unimplemented: ‘target_device’ selector set inside of ‘target’ directive tests/5.1/metadirective/test_metadirective_target_device.c:30:15: sorry, unimplemented: ‘target_device’ selector set inside of ‘target’ directive tests/5.1/metadirective/test_metadirective_target_device.c:30:15: sorry, unimplemented: ‘target_device’ selector set inside of ‘target’ directive
...
I wonder whether we could get rid of some of them. On the other hand, as they
are nicely follow each other, it is not a Prio 1 issue.

This is my bad.  It's coming from omp_context_selector_matches() in omp-general.cc, where it just continues processing after the "sorry" error instead of returning 0.  Do you think it's correct for this to be a "sorry" instead of a warning, or just silently always failing to match?  It's a trivial fix, anyway.

Good question how to handle it best. Given that, e.g., 'omp_get_default_device()' etc. is unspecified, we might do whatever we want …

I think having a diagnostic is sensible — but maybe we should downgrade it to a -Wopenmp warning?

If we treat it as warning, we could consider regarding it on the device as default_device = it's me → 'device' and on the host handle it like a normal device. Or just say 'not matched' or …

Having multiple times this output is okayish.

Regarding the OpenMP_VV test case, I filed an issue: https://github.com/OpenMP-Validation-and-Verification/OpenMP_VV/issues/853 as they should either use 'device' or hoist it out of the target region and then use 'target_device' from the host side.

* * *

I'll fix this before reposting a new version of the remaining patches in the series.  The C++ code is very similar and needs the same fix.

Also, from offline discussion with Tobias:

BTW: The following seems to be valid but is rejected as the metadirective after 'for' is not handled: "error: loop nest expected before ‘#pragma’"
void f() {
  #pragma omp metadirective when(construct={target} : parallel)
    #pragma omp metadirective when(construct={target} : for)
      #pragma omp metadirective when(construct={target} : simd)
        for (int i =0 ; i < 1; i++)
          __builtin_printf("Hello world\n");
}
Unless that's simple to fix, I suggest to just queue it for a new PR.

It's not clear to me that this is supposed to be valid; metadirective is not included in the syntax for "canonical loop nest", nor is it a directive with the loop-transforming property.  Anyway, I think this would require changes beyond just suppressing the error message, so yeah, some low-priority PR would be appropriate here.

The PS solution is fine with me.

With metadirectives it is never quite clear whether they are supposed to act like an on-the-fly text replacement that, kind of, happens before parsing - or not. They are in a strange in-between state.

Thanks,

Tobias

Reply via email to