Bug 115637 - gimple_regimplify_operands doesn't handle VALUE_EXPR inside a MEM_REF / OpenMP declare target link
Summary: gimple_regimplify_operands doesn't handle VALUE_EXPR inside a MEM_REF / OpenM...
Status: RESOLVED FIXED
Alias: None
Product: gcc
Classification: Unclassified
Component: middle-end (show other bugs)
Version: 15.0
: P3 normal
Target Milestone: ---
Assignee: Not yet assigned to anyone
URL:
Keywords: openmp, wrong-code
Depends on:
Blocks:
 
Reported: 2024-06-25 10:46 UTC by Tobias Burnus
Modified: 2024-08-01 07:24 UTC (History)
1 user (show)

See Also:
Host:
Target:
Build:
Known to work:
Known to fail:
Last reconfirmed:


Attachments
Fortran testcase – requires '-fopenmp' and configured offloading - and patch for PR115559 (332 bytes, text/plain)
2024-06-25 10:46 UTC, Tobias Burnus
Details
WIP patch - shows the location but fails as DECL_P is not a is_gimple_stmt (813 bytes, patch)
2024-06-25 12:50 UTC, Tobias Burnus
Details | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Tobias Burnus 2024-06-25 10:46:14 UTC
Created attachment 58511 [details]
Fortran testcase – requires '-fopenmp' and configured offloading - and patch for PR115559

gimple_regimplify_operands doesn't expand the value expression of 'arr2' in:

MEM <uint128_t> [(c_char * {ref-all})&arr2]

with arr2 having the value expression:

            value-expr <mem_ref 0x7ffff72ed9d8 type <array_type 0x7ffff72e9540>
                arg:0 <var_decl 0x7ffff72f21b0 arr2$13$linkptr>
                arg:1 <integer_cst 0x7ffff72d8ac8 constant 0>>>


The code is produced for the attached code, which requires offloading, -fopenmp and the patch for PR fortran/115559.

While 'omp declare target link(arr2)' has no direct effect on the host code, it replaces on the device a variable such as
  int arr[4];
by
  int *arr$linkptr;
and all user of arr by (arr$linkref[0]). On the device side, the following code is produced:

  MEM <uint128_t> [(c_char * {ref-all})&arr2] = _7;
  _2 = arr2[_1];

the replacement of the latter works:
  _20 = arr2.13.linkptr;

but the 'MEM <uint128_t> [(c_char * {ref-all})&arr2] = _7;' remains and causes later the link error:

   ld: error: undefined symbol: arr2.13

for the offload side.


 * * *

The replacement is done via omp-offload.cc's pass_omp_target_link::execute.

Here,
  gimple_regimplify_operands (gsi_stmt (gsi), &gsi);
is then called for the MEMREF - which starts some regimplification, in particular, the following is then reached:

gimplify.cc's gimplify_expr
...
        /* We arrive here through the various re-gimplifcation paths.  */
        case MEM_REF:
          /* First try re-folding the whole thing.  */
          tmp = fold_binary (MEM_REF, TREE_TYPE (*expr_p),
                             TREE_OPERAND (*expr_p, 0),
                             TREE_OPERAND (*expr_p, 1));
          if (tmp)
… (tmp == NULL) …
              break;
            }
          /* Avoid re-gimplifying the address operand if it is already
             in suitable form.  Re-gimplifying would mark the address
             operand addressable.  Always gimplify when not in SSA form
             as we still may have to gimplify decls with value-exprs.  */
          if (!gimplify_ctxp || !gimple_in_ssa_p (cfun)
              || !is_gimple_mem_ref_addr (TREE_OPERAND (*expr_p, 0)))
            {
              ret = gimplify_expr (&TREE_OPERAND (*expr_p, 0), pre_p, post_p,
                                   is_gimple_mem_ref_addr, fb_rvalue);
              if (ret == GS_ERROR)
                break;
            } 
          recalculate_side_effects (*expr_p);


* * *

Full 'debug_tree':

 <mem_ref 0x7ffff72edd98
    type <integer_type 0x7ffff72e9bd0 unsigned TI
        size <integer_cst 0x7ffff7202798 constant 128>
        unit-size <integer_cst 0x7ffff72027b0 constant 16>
        user align:32 warn_if_not_align:0 symtab:0 alias-set -1 canonical-type 0x7ffff720ba80 precision:128 min <integer_cst 0x7ffff72d8a20 0> max <integer_cst 0x7ffff72ed758 340282366920938463463374607431768211455>>
   
    arg:0 <addr_expr 0x7ffff72dcb20
        type <pointer_type 0x7ffff72e9dc8 type <array_type 0x7ffff72e9540>
            public unsigned DI
            size <integer_cst 0x7ffff7202468 constant 64>
            unit-size <integer_cst 0x7ffff7202480 constant 8>
            align:64 warn_if_not_align:0 symtab:0 alias-set -1 structural-equality>
        constant
        arg:0 <var_decl 0x7ffff72f2090 arr2 type <array_type 0x7ffff72e9540>
            addressable static nonlocal TI declare-target-link.f90:3:28 size <integer_cst 0x7ffff7202798 128> unit-size <integer_cst 0x7ffff72027b0 16>
            align:128 warn_if_not_align:0 context <function_decl 0x7ffff72ecf00 sub>
            attributes <tree_list 0x7ffff72ed578
                purpose <identifier_node 0x7ffff72ed550 omp declare target link>>
            value-expr <mem_ref 0x7ffff72ed9d8 type <array_type 0x7ffff72e9540>
                arg:0 <var_decl 0x7ffff72f21b0 arr2$13$linkptr>
                arg:1 <integer_cst 0x7ffff72d8ac8 constant 0>>>
        declare-target-link.f90:29:24 start: declare-target-link.f90:29:24 finish: declare-target-link.f90:29:24>
    arg:1 <integer_cst 0x7ffff72d8b40 type <pointer_type 0x7ffff72e9d20> constant 0>>
Comment 1 Tobias Burnus 2024-06-25 12:50:07 UTC
Created attachment 58512 [details]
WIP patch - shows the location but fails as DECL_P is not a is_gimple_stmt

The attached patch handles
  MEM <uint128_t> [(c_char * {ref-all})&arr2]
by changing
   &arr2  (= a ADDR_EXPR)
to
   arr2$13$linkptr   (= a VAR_DECL)

However, as the result simplified to a VAR_DECL != is_gimple_stmt(), it fails as gimplify_expr doesn't handle this.
Comment 2 Tobias Burnus 2024-07-30 21:26:28 UTC
Patch:
  https://gcc.gnu.org/pipermail/gcc-patches/2024-July/658737.html
Comment 3 GCC Commits 2024-08-01 07:21:30 UTC
The master branch has been updated by Tobias Burnus <burnus@gcc.gnu.org>:

https://gcc.gnu.org/g:c99cdcab4f1c497a872cf552138fd8ea27e9a5eb

commit r15-2472-gc99cdcab4f1c497a872cf552138fd8ea27e9a5eb
Author: Tobias Burnus <tburnus@baylibre.com>
Date:   Thu Aug 1 09:06:32 2024 +0200

    omp-offload.cc: Fix value-expr handling of 'declare target link' vars [PR115637]
    
    As the PR and included testcase shows, replacing 'arr2' by its value expression
    '*arr2$13$linkptr' failed for
      MEM <uint128_t> [(c_char * {ref-all})&arr2]
    which left 'arr2' in the code as unknown symbol. Now expand the value expression
    already in pass_omp_target_link::execute's process_link_var_op walk_gimple_stmt
    walk - and don't rely on gimple_regimplify_operands.
    
            PR middle-end/115637
    
    gcc/ChangeLog:
    
            * gimplify.cc (gimplify_body): Fix macro name in the comment.
            * omp-offload.cc (find_link_var_op): Rename to ...
            (process_link_var_op): ... this. Replace value expr.
            (pass_omp_target_link::execute): Update walk_gimple_stmt call.
    
    libgomp/ChangeLog:
    
            * testsuite/libgomp.fortran/declare-target-link.f90: Uncomment
            now working code.
    
    Co-authored-by: Richard Biener <rguenther@suse.de
Comment 4 Tobias Burnus 2024-08-01 07:24:33 UTC
FIXED on mainline (GCC 15).

* * *

For remaining 'declare target link' issues, see:
Follow-up/related issue are tracked elsewhere:

* C: Nested functions + declare target link → PR 115574
* Fortran: COMMON block issues + declare target link → PR 115577