Issue 208318
Summary `IMAGE_INDEX` lowered argument type mismatch leads to erroneous runtime results (especially for corank > 1)
Labels flang:ir
Assignees JDPailleux
Reporter bonachea
    The recent merge of #192944 included a defect in the `IMAGE_INDEX` intrinsic, believed to affect all coarray arguments but especially those with corank > 1.

MRE:
```fortran
program coarray_image_index
  integer :: coarray1[10:*]
  integer :: coarray2[10:20, 30:*]
  integer :: coarray3[10:20, 30:40, 50:*]
  write(*,'(A,I4)') "IMAGE_INDEX(coarray1)= ", IMAGE_INDEX(coarray1,[10])
  write(*,'(A,I4)') "IMAGE_INDEX(coarray2)= ", IMAGE_INDEX(coarray2,[10,30])
  write(*,'(A,I4)') "IMAGE_INDEX(coarray3)= ", IMAGE_INDEX(coarray3,[10,30,50])
end program
```

Expected correct output (verified from a single-image run of NAG 7.2):
```
IMAGE_INDEX(coarray1)=    1
IMAGE_INDEX(coarray2)= 1
IMAGE_INDEX(coarray3)=    1
```

Flang's incorrect output: (from `main` @ e2d6498e3623)
```
pm$ flang --version
flang version 23.0.0git ([email protected]:llvm/llvm-project.git e2d6498e36235ecd9955d8d375a0c1a253c2e11a)
Target: x86_64-unknown-linux-gnu
Thread model: posix
InstalledDir: <redacted>/llvm/inst/bin
Build config: +assertions

pm$ flang -fcoarray -O0 -g image-index-bug.F90 -L../caffeine/inst-llvm23dev-debug/lib/ -lcaffeine-smp-seq -lgasnet-smp-seq -L/opt/cray/pe/pmi/default/lib -lpmi && env GASNET_PSHM_NODES=1 a.out
warning: Support for multi image Fortran features is still experimental and in development.
IMAGE_INDEX(coarray1)= 1
IMAGE_INDEX(coarray2)=    0
IMAGE_INDEX(coarray3)=    0
```

 Using a debugger I've observed what appears to be incorrect values passed in the `sub` argument to `prif::prif_image_index` for corank > 1, here is the corank==3 call:

```
Breakpoint 4, prif::prif_image_index (coarray_handle=..., sub=..., image_index=21845)
    at <redacted>/caffeine/src/caffeine/coarray_queries_s.F90:136
136         call image_index_helper(coarray_handle, sub, current_team, image_index)
(gdb) where
#0  prif::prif_image_index (coarray_handle=..., sub=..., image_index=21845)
    at <redacted>/caffeine/src/caffeine/coarray_queries_s.F90:136
#1 0x00005555555606c9 in COARRAY_IMAGE_INDEX () at image-index-bug.F90:7
(gdb) print sub(1)
$1 = 128849018890
(gdb) print sub(2)
$2 = 214748364830
(gdb) print sub(3)
$3 = 50
(gdb) print/x sub(1)
$4 = 0x1e0000000a
(gdb) print/x sub(2)
$5 = 0x320000001e
(gdb) print/x sub(3)
$6 = 0x32
```

Note that the high words of `sub(1)` and `sub(2)` appear to have been corrupted, and the garbage is exactly the low word of the next higher array element. This is consistent with a defect where array values are incorrectly passed as 32-bit integers when a 64-bit integer array is expected by the `sub` argument to `prif::prif_image_index`. The semantics of `prif::prif_image_index` is such that passing garbage values in `sub()` (outside the cobounds of the coarray dummy argument) produce a resulting `image_index` of 0, and that's exactly the code path the debugger observes for the corank 2 and 3 calls above.

Dumping relevant MLIR:
```
pm$ flang -fcoarray -O0 -g image-index-bug.F90 -c  -mmlir --mlir-print-ir-after=mif-convert 2>&1 | grep -B8 'fir.call @_QMprifPprif_image_index' 
    %86 = fir.address_of(@_QQro.1xi4.0) : !fir.ref<!fir.array<1xi32>>
    %87 = fir.shape %c1 : (index) -> !fir.shape<1>
    %88 = fir.declare %86(%87) {fortran_attrs = #fir.var_attrs<parameter>, uniq_name = "_QQro.1xi4.0"} : (!fir.ref<!fir.array<1xi32>>, !fir.shape<1>) -> !fir.ref<!fir.array<1xi32>>
 %89 = fir.embox %34 : (!fir.ref<i32>) -> !fir.box<i32, corank:1>
    %90 = fir.embox %88(%87) : (!fir.ref<!fir.array<1xi32>>, !fir.shape<1>) -> !fir.box<!fir.array<1xi32>>
    %91 = fir.address_of(@_QFEcoarray1_coarray_handle) : !fir.ref<!fir.box<none>>
 %92 = fir.load %91 : !fir.ref<!fir.box<none>>
    %93 = fir.convert %90 : (!fir.box<!fir.array<1xi32>>) -> !fir.box<!fir.array<?xi64>>
    fir.call @_QMprifPprif_image_index(%92, %93, %2) : (!fir.box<none>, !fir.box<!fir.array<?xi64>>, !fir.ref<i32>) -> ()
--
    %104 = fir.address_of(@_QQro.2xi4.1) : !fir.ref<!fir.array<2xi32>>
    %105 = fir.shape %c2 : (index) -> !fir.shape<1>
    %106 = fir.declare %104(%105) {fortran_attrs = #fir.var_attrs<parameter>, uniq_name = "_QQro.2xi4.1"} : (!fir.ref<!fir.array<2xi32>>, !fir.shape<1>) -> !fir.ref<!fir.array<2xi32>>
 %107 = fir.embox %52 : (!fir.ref<i32>) -> !fir.box<i32, corank:2>
 %108 = fir.embox %106(%105) : (!fir.ref<!fir.array<2xi32>>, !fir.shape<1>) -> !fir.box<!fir.array<2xi32>>
    %109 = fir.address_of(@_QFEcoarray2_coarray_handle) : !fir.ref<!fir.box<none>>
 %110 = fir.load %109 : !fir.ref<!fir.box<none>>
    %111 = fir.convert %108 : (!fir.box<!fir.array<2xi32>>) -> !fir.box<!fir.array<?xi64>>
    fir.call @_QMprifPprif_image_index(%110, %111, %1) : (!fir.box<none>, !fir.box<!fir.array<?xi64>>, !fir.ref<i32>) -> ()
--
    %122 = fir.address_of(@_QQro.3xi4.2) : !fir.ref<!fir.array<3xi32>>
    %123 = fir.shape %c3 : (index) -> !fir.shape<1>
    %124 = fir.declare %122(%123) {fortran_attrs = #fir.var_attrs<parameter>, uniq_name = "_QQro.3xi4.2"} : (!fir.ref<!fir.array<3xi32>>, !fir.shape<1>) -> !fir.ref<!fir.array<3xi32>>
 %125 = fir.embox %72 : (!fir.ref<i32>) -> !fir.box<i32, corank:3>
 %126 = fir.embox %124(%123) : (!fir.ref<!fir.array<3xi32>>, !fir.shape<1>) -> !fir.box<!fir.array<3xi32>>
    %127 = fir.address_of(@_QFEcoarray3_coarray_handle) : !fir.ref<!fir.box<none>>
 %128 = fir.load %127 : !fir.ref<!fir.box<none>>
    %129 = fir.convert %126 : (!fir.box<!fir.array<3xi32>>) -> !fir.box<!fir.array<?xi64>>
    fir.call @_QMprifPprif_image_index(%128, %129, %0) : (!fir.box<none>, !fir.box<!fir.array<?xi64>>, !fir.ref<i32>) -> ()
```

Note the `sub` argument is produced by `fir.convert : (!fir.box<!fir.array<3xi32>>) -> !fir.box<!fir.array<?xi64>>`, but there doesn't appear to be allocation of a temporary 64-bit integer array as I'd expect.

This problem only _seems_ to affect coarrays with corank > 1, but I suspect that's just because corank==1 is reading a high word from out-of-bounds memory that happens to be zero.

CC: @ktras @rouson 
_______________________________________________
llvm-bugs mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-bugs

Reply via email to