<table border="1" cellspacing="0" cellpadding="8">
<tr>
<th>Issue</th>
<td>
<a href=https://github.com/llvm/llvm-project/issues/208318>208318</a>
</td>
</tr>
<tr>
<th>Summary</th>
<td>
`IMAGE_INDEX` lowered argument type mismatch leads to erroneous runtime results (especially for corank > 1)
</td>
</tr>
<tr>
<th>Labels</th>
<td>
flang:ir
</td>
</tr>
<tr>
<th>Assignees</th>
<td>
JDPailleux
</td>
</tr>
<tr>
<th>Reporter</th>
<td>
bonachea
</td>
</tr>
</table>
<pre>
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 (git@github.com: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
</pre>
<img width="1" height="1" alt="" src="http://email.email.llvm.org/o/eJzUWV9z27ay_zTwyw41IEBS1IMfFMnq9Z0mbZPcmXueNCC5ktCQAAuAsnw-_RmA1D9LjtUmaed4MjEJY__9sPtbEBDWyrVCvCfpO8LY_85_FbKusdsRxkg6vxOd22hzX2glyg2Ku0JXz_efNwgGS1QOGjRrBL0Cwng8YZMkAanKuquwAgEVrrB0IBW4DQLJ6OP76U8Py8cP84f_JxkFqZyRysqSsBkUWEvcYgVOg1gFQVHXUGphjHgGYdZdg8pZKDoHaFsspajrZ3AbbRGepNtAqY1QX4DwB4hHhE4Jnb7_-EC4fyAZ7f-ttHFGKEKnrdFrI5q9iaVsxBqXUlW4I3QK3j1cowGvgE_302KSvoupH2NTks6_MpPtZzLqA-Q3CfErQkl4TF_IPxnpkLDcD7EZYWPCcv_0mBA2Ca8TIIydYs7yQxBsQvjc_92rfm3OrHcmnfvp32qT3WCTHWyyGf9ehvkNhvm5YTZLj9ZRVTDkymki9Qn2sGuxdFj55DM-aXXn2s4BYfkWjVxJrGBldAMCrFTrGqOQZmA65evmw_QnGI96aKYvtH915QAgfm3OHulXJ_BzJS9CWtRCrQkbW1_LZ1H5PCUsD_GQjDZCKl_HJKGArMqSSY48Y7yH7VRr2xCWwMorhijaorFS-xLsR4Z3YHxER3QtA3pr6UjiXzZdMSp1Q_i0rrcNYQv_K2qN_h1LN_KzT22nWFaTSZpWecXHqaBlLFjKS4ZxLHq_PguzxhDKLs-WWRJ16ovSTyqqpep20Vp1ftLGoKig0RXWfmqrrfSs8KisE3WN1VyagAafGayEzwDCHwbnCFtIZR1hi0L6KN91svYJolZy3UP4TliLxkmtbI_5GUCrPelFv1CI1hAyJgrEFBXderSYUIh-Ho0IW5SeKqXCwWTkzTNe4TaqsOjW3iFZELaAqN5PjWzTRhb_gKheC6vQHQd-JmyhW-94acQzYYvWK24bSdiiwpXoatdrhKhuGwmEZYRlgGoLP00_fXj4vPz10_-8X374Zf7wifB5DGKkO0fo9EkYJVUI_lPXtto4WGkDTVc72YcHi56XYYXCdQYtSAvWyboG3LVopCd_UYNQlW8oFW6x1q0fHL1VKm_WCQC8Wm_8fM6LUoH_80UdWl3RrT2bPxI23iLowqLx3expIxyItkVhrG9tBZ5U1VbUHVpofTZUJ33SdoWvq33P83Iko62Rq75Z-KezdpXRgOdpA_RUt0GDHkevtv8b4XPC5xxKUdcD45wH9c6g-NJqqRwkXsXrRuEI0nIjVFUj4fORz8oZ-AAOL6eO8jmL8yTd0zqAcJc1dJLU1pTnA3uLf3RoJNql9dVA-DTmGaH-f9j_-BBPbS83WLdoLr0e_GUzKDtjULmlQ9G89LznNJavq8I3myePbRjhFP7LUPKbNaA7SilN-5-MZuXEJ-Dsl-nHj9N_LU9qAULbnXgfrhAR4dPxGTCt8bkTAM3jPWpJDKESWZ4nExrn-YS-KsQOQiwIsTgZJznPkpy_LsQPQjwIpVemErbYXTiWhOl0FyPtf8RXBY_OpYMgZ71cjF8VPDqYHQQv-eSDdgjOU4Yv2Y1cb-BJm8qGLXbPC4Pznh5UdRxk-8FANZ4xNmKLUCCqsDXpWp84bBakvPK1MIXnXWkBd6J0YSuNUOunYNJb9O8Kdy44ggb6poQ1BtqFzxsZWLrUykrrPFGFbfhh4x9qZJAaqE6YE_6rn_fUJyxwFhXS7XfF1gsrEJAlp8ODsuDzsO8qnr-BNX0QCBYboZws9zB_nWh9X-rKTb9M3n_fAfZoDmFKdVyZYWEIy3XnrKxwoONCd6pf2f69D63qmub4tdNnkq66EkGAQesbplp75S-80iugx-UVLuzfThe21BVCK9wmvB361dCobOgfxz4BLGjqG4UFUegtDp9U865pvQ8Ga9wK5eD9z48fL3evf35HUwJETVNLA1Hkf0WhhiJpIrFyaAifN3IVlVpt0ThggQWzGMh4BmuDLUTvciBsvJJmFLifJHT523u_hL9erCMbw0CthKV5X5JeUFSVQWuXeuVXziv4zehRvJPJiIZvjLB9i_1UgyvCZ8NLiI7wWbyTPHjGH070jw_67Ua06MfKeNCV79sLRL5vD_rCPK_vXFF-UFRhWftiCu6HLEvz_ito_G74xF0K54yF_tOHe6GtMP0g4bNWGNFgwPXBJ06n5B9LJRocBNh56IyM53uPbwWAza6G8yLUW3D00U0OsWNTaN9YU55cdWkQfWGn0Lvhb77TD7uh6TnAE3ppJM_P4P0REPSu3ZJKk_grqbp42O98ly-3OK9nbm9baYVncE_YwVCtRXWwfbuSwWF-0LOv3D3Op0C-icAtiBG-2MksOXPhNjbIQ8T9aqUTPjywywU_D_S4ujf4c5z8Spbm_RYhio7oxTR5g5qYr8_4Fmpi1_IppukVbmJ_gZtiml0jp5gmPbwxTX8APe3Dv5We2PehJ3ZBTzEdX1JHyr6Zn9ipifzSREyzc3x_BAZXs_uVfJrcQlDs2wkqjukFQ_XW_yxFxXF8jaN6uN8kKfa3klQcTigHr_dP_zxNMfYGTXFfp-wWmuJX04rxKzTF_wpNseQqTTE2AByOL783Te3Dv5Wm-PehKX5JUyy95JDxt9MUPzWRXaEplpzj-yMwuJrdr-TT-Baa4t-Bplh-SVPB-p-mKTa5SlMB7jdpiv-9NOX_nw1eD0_0H6Gp6wcsV88LpN1_a4dTBZLRM6h_NMZZYPaiC2c_BqHSaBVhY3dyplMgiLrWpXBSh_sjAQ6bVhthnq8flQgbjqSr4cBk-IYPRzet0UWNDWhVP8PSIjZ2eXL7OqS-vbxb3fv5CLazXuvxxOH3zjoosBSdPT9yjj28BkXVn5cfjrb6yzHduUivouFIpMFGm-f-gGXjg1f7o_N_o9FDCLNZWJGEfnFGWP9gdGe1grvqnlcTPhF3eB-Pc54mnGbsbnM_SYtqFRcFj_OMixVLx3QisGJjEeeVSJM7ec8oy-iY5ozyccJGq6pI03GZjhktJis6JgnFRsh6VNfbZqTN-k5a2-E9ozmP87taFFjb4S49nHwQPpVmuEs39-HiqujWliS0ltbZox4nXY33l1fktX5Cg9XJodZzi9BI2whXbqBGUQVs0BitUHcWTKecbHA4LLI-Z09uyy9vCSZ3nanvN861NtwvLwhbnNy6HW60Tm_dCFuEwC1hiyH27T37TwAAAP__KENjNA">