Hi! Just to elaborate a bit futher on top of what Martin already explained:
On 2026-06-01T15:06:42+0200, Martin Jambor <[email protected]> wrote: > On Thu, May 28 2026, Sebastian Galindo via Gcc wrote: >> I'm implementing some OpenACC directives but since I'm a new contributor >> with a very simple but conceptual question that I prefer asking in the >> mailing list rather than believing some unclear explanation from AI. >> >> I know that some directives (Talking about OpenMP / OpenACC) >> imply futher optimizations or variables treatment and that case >> is defined as a tree node (TREEDEF). In the other side, built-in >> is required when it's a runtime call that can be resolved in the >> front-end (?). > > Did you mean to write "that CANNOT be resolved by a front-end?" (Or any > stage of compilation, for that matter?). > > The thing is, especially in the OpenMP/OpenACC context, the same stuff > can be represented by both. For example there is an OMP_PARALLEL tree > code that is generated by the front-ends to represent OpenMP parallel > construct which then however gets lowered/expanded to a call to > builtin_GOMP_parallel which stays until the end of the compilation and > the call is emitted to the assembly (and is implemented in the run-time > library libgomp). > > So, if you eventually need a call to libgomp, you will need to use a > (call to) a builtin function. However, how you convey other information > from the front-ends to lowering/expansion and beyond is upon you, I guess. > >> I'm not sure about that and I would appreciate some examples. Not >> necessarily in the case of OpenACC / OpenMP, but some useful examples to >> judge if some statement requires built-in or define a tree node for that >> (if requires special treatment). If applicable, we try to lower OpenACC/OpenMP directives to calls to (libgomp) builtin functions as soon as possible. That's for the simple reason that we then don't have to have special compiler-internal representation/handling for each of them, individually. The concept of a function call, of course, already is well-established ;-) and totally sufficient for "simple" directives that the compiler just passes through, and doesn't transform/optimize any futher. One example of this is '#pragma acc wait' directly after parsing getting mapped to a 'GOACC_wait' call (via 'BUILT_IN_GOACC_WAIT'). Other directives, that the compiler does further transform/optimize, are mapped to an appropriate internal representation, for example: '#pragma acc enter data' -> 'OACC_ENTER_DATA' node -> 'BUILT_IN_GOACC_ENTER_DATA' function call. '#pragma acc routine' just sets certain attributes on the 'tree' that it applies to. '#pragma acc loop' -> 'OACC_LOOP' node -> 'GIMPLE_OMP_FOR' node with 'GF_OMP_FOR_KIND_OACC_LOOP' -> 'IFN_GOACC_LOOP' etc., which eventually get lowered by the respective back end to whatever control flow is appropriate (without any function call into libgomp). For your case of OpenACC 'init' etc., I'd assume those are in category "simple", so directely in the front ends map to 'GOACC_[...]' function calls (via 'BUILT_IN_GOACC_[...]'). In case that any further compiler-side handling turns out to be necessary, that mapping step would move later in the pass pipeline, as necessary. Grüße Thomas > See above. Compile a simple OpenMP/OpenACC example with -fdump-tree-all > and see how things change throughout the GCC pass pipeline. > > Hope this helps, > > Martin
