|
| 1 | +! Minimal reproducer for ifx 2025.1.1 SPIR-V ICE #5633 |
| 2 | +! |
| 3 | +! ICE trigger: multiple !$omp target teams loop regions in one module, each |
| 4 | +! calling a different !$omp declare target subroutine in the SAME module. |
| 5 | +! Subroutines access allocatable module arrays and a derived type with |
| 6 | +! array-of-arrays fields (interp_coeffs(2,2,2)) plus character field. |
| 7 | +! |
| 8 | +! Compile (expect ICE): |
| 9 | +! ifx -free -fiopenmp -fopenmp-targets=spir64 -O3 -c m_cl5_mini.f90 |
| 10 | +! Workaround (passes): |
| 11 | +! ifx -free -fiopenmp -fopenmp-targets=spir64 -O3 -fno-inline -c m_cl5_mini.f90 |
| 12 | + |
| 13 | +module m_cl5 |
| 14 | + |
| 15 | + implicit none |
| 16 | + private |
| 17 | + |
| 18 | + integer, parameter :: wp = kind(1.0d0) |
| 19 | + |
| 20 | + type :: patch_t |
| 21 | + integer :: geometry |
| 22 | + real(wp) :: radius, cx, cy, cz |
| 23 | + real(wp) :: lx, ly, lz |
| 24 | + real(wp), dimension(1:3,1:3) :: rot, rot_inv |
| 25 | + real(wp), dimension(1:3) :: offset |
| 26 | + character(LEN=200) :: label ! char field in device-mapped type |
| 27 | + end type patch_t |
| 28 | + |
| 29 | + type :: gp_t |
| 30 | + integer, dimension(3) :: loc |
| 31 | + real(wp), dimension(2, 2, 2) :: interp_coeffs ! 3D array in struct |
| 32 | + integer :: pid |
| 33 | + real(wp) :: levelset |
| 34 | + real(wp), dimension(3) :: levelset_norm |
| 35 | + integer :: xp, yp, zp |
| 36 | + end type gp_t |
| 37 | + |
| 38 | + type(patch_t), dimension(8), target :: patches |
| 39 | + real(wp), allocatable :: xc(:), yc(:), zc(:) |
| 40 | + !$omp declare target(patches, xc, yc, zc) |
| 41 | + |
| 42 | + public :: gp_t, s_init, s_finalize, s_dispatch |
| 43 | + |
| 44 | +contains |
| 45 | + |
| 46 | + subroutine s_init(n) |
| 47 | + integer, intent(in) :: n |
| 48 | + integer :: i |
| 49 | + allocate(xc(n), yc(n), zc(n)) |
| 50 | + do i = 1, n |
| 51 | + xc(i) = real(i,wp)*0.1_wp |
| 52 | + yc(i) = real(i,wp)*0.1_wp |
| 53 | + zc(i) = real(i,wp)*0.1_wp |
| 54 | + end do |
| 55 | + do i = 1, 8 |
| 56 | + patches(i)%geometry = i |
| 57 | + patches(i)%radius = 0.5_wp; patches(i)%cx = 0.5_wp |
| 58 | + patches(i)%cy = 0.5_wp; patches(i)%cz = 0.5_wp |
| 59 | + patches(i)%lx = 0.4_wp; patches(i)%ly = 0.4_wp; patches(i)%lz = 0.4_wp |
| 60 | + patches(i)%rot = 0.0_wp |
| 61 | + patches(i)%rot(1,1) = 1.0_wp; patches(i)%rot(2,2) = 1.0_wp; patches(i)%rot(3,3) = 1.0_wp |
| 62 | + patches(i)%rot_inv = patches(i)%rot |
| 63 | + patches(i)%offset = 0.0_wp |
| 64 | + patches(i)%label = 'none' |
| 65 | + end do |
| 66 | + !$omp target enter data map(to: patches, xc, yc, zc) |
| 67 | + end subroutine s_init |
| 68 | + |
| 69 | + subroutine s_finalize() |
| 70 | + !$omp target exit data map(delete: patches, xc, yc, zc) |
| 71 | + deallocate(xc, yc, zc) |
| 72 | + end subroutine s_finalize |
| 73 | + |
| 74 | + subroutine s_dispatch(gps, n) |
| 75 | + type(gp_t), intent(inout) :: gps(:) |
| 76 | + integer, intent(in) :: n |
| 77 | + integer :: i |
| 78 | + |
| 79 | + !$omp target teams loop private(i) map(tofrom:gps) |
| 80 | + do i = 1, n |
| 81 | + if (patches(gps(i)%pid)%geometry == 1) call s_geo1(gps(i)) |
| 82 | + end do |
| 83 | + |
| 84 | + !$omp target teams loop private(i) map(tofrom:gps) |
| 85 | + do i = 1, n |
| 86 | + if (patches(gps(i)%pid)%geometry == 2) call s_geo2(gps(i)) |
| 87 | + end do |
| 88 | + |
| 89 | + !$omp target teams loop private(i) map(tofrom:gps) |
| 90 | + do i = 1, n |
| 91 | + if (patches(gps(i)%pid)%geometry == 3) call s_geo3(gps(i)) |
| 92 | + end do |
| 93 | + |
| 94 | + !$omp target teams loop private(i) map(tofrom:gps) |
| 95 | + do i = 1, n |
| 96 | + if (patches(gps(i)%pid)%geometry == 4) call s_geo4(gps(i)) |
| 97 | + end do |
| 98 | + |
| 99 | + !$omp target teams loop private(i) map(tofrom:gps) |
| 100 | + do i = 1, n |
| 101 | + if (patches(gps(i)%pid)%geometry == 5) call s_geo5(gps(i)) |
| 102 | + end do |
| 103 | + |
| 104 | + !$omp target teams loop private(i) map(tofrom:gps) |
| 105 | + do i = 1, n |
| 106 | + if (patches(gps(i)%pid)%geometry == 6) call s_geo6(gps(i)) |
| 107 | + end do |
| 108 | + |
| 109 | + !$omp target teams loop private(i) map(tofrom:gps) |
| 110 | + do i = 1, n |
| 111 | + if (patches(gps(i)%pid)%geometry == 7) call s_geo7(gps(i)) |
| 112 | + end do |
| 113 | + |
| 114 | + !$omp target teams loop private(i) map(tofrom:gps) |
| 115 | + do i = 1, n |
| 116 | + if (patches(gps(i)%pid)%geometry == 8) call s_geo8(gps(i)) |
| 117 | + end do |
| 118 | + |
| 119 | + !$omp target teams loop private(i) map(tofrom:gps) |
| 120 | + do i = 1, n |
| 121 | + if (patches(gps(i)%pid)%geometry == 9) call s_geo9(gps(i)) |
| 122 | + end do |
| 123 | + |
| 124 | + !$omp target teams loop private(i) map(tofrom:gps) |
| 125 | + do i = 1, n |
| 126 | + if (patches(gps(i)%pid)%geometry == 10) call s_geo10(gps(i)) |
| 127 | + end do |
| 128 | + |
| 129 | + end subroutine s_dispatch |
| 130 | + |
| 131 | + subroutine s_geo1(gp) |
| 132 | + !$omp declare target |
| 133 | + type(gp_t), intent(inout) :: gp |
| 134 | + integer :: id, i, j, k |
| 135 | + real(wp), dimension(3) :: dv |
| 136 | + real(wp) :: d |
| 137 | + id = gp%pid; i = gp%loc(1); j = gp%loc(2); k = gp%loc(3) |
| 138 | + dv(1) = xc(i) - patches(id)%cx - real(gp%xp,wp)*0.1_wp |
| 139 | + dv(2) = yc(j) - patches(id)%cy - real(gp%yp,wp)*0.1_wp |
| 140 | + dv(3) = zc(k) - patches(id)%cz - real(gp%zp,wp)*0.1_wp |
| 141 | + d = sqrt(sum(dv**2)) |
| 142 | + gp%levelset = d - patches(id)%radius |
| 143 | + if (d > 0._wp) then; gp%levelset_norm = dv/d; else; gp%levelset_norm = 0._wp; end if |
| 144 | + end subroutine s_geo1 |
| 145 | + |
| 146 | + subroutine s_geo2(gp) |
| 147 | + !$omp declare target |
| 148 | + type(gp_t), intent(inout) :: gp |
| 149 | + integer :: id, i, j, k |
| 150 | + real(wp) :: dx, dy, dz |
| 151 | + id = gp%pid; i = gp%loc(1); j = gp%loc(2); k = gp%loc(3) |
| 152 | + dx = abs(xc(i) - patches(id)%cx) - patches(id)%lx/2._wp |
| 153 | + dy = abs(yc(j) - patches(id)%cy) - patches(id)%ly/2._wp |
| 154 | + dz = abs(zc(k) - patches(id)%cz) - patches(id)%lz/2._wp |
| 155 | + gp%levelset = max(dx, max(dy, dz)) |
| 156 | + gp%levelset_norm(1) = sign(1._wp, xc(i) - patches(id)%cx) |
| 157 | + gp%levelset_norm(2) = sign(1._wp, yc(j) - patches(id)%cy) |
| 158 | + gp%levelset_norm(3) = sign(1._wp, zc(k) - patches(id)%cz) |
| 159 | + end subroutine s_geo2 |
| 160 | + |
| 161 | + subroutine s_geo3(gp) |
| 162 | + !$omp declare target |
| 163 | + type(gp_t), intent(inout) :: gp |
| 164 | + integer :: id, i, j, k |
| 165 | + real(wp), dimension(3) :: dv, ldv |
| 166 | + real(wp) :: r2d |
| 167 | + id = gp%pid; i = gp%loc(1); j = gp%loc(2); k = gp%loc(3) |
| 168 | + dv(1) = xc(i) - patches(id)%cx; dv(2) = yc(j) - patches(id)%cy; dv(3) = zc(k) - patches(id)%cz |
| 169 | + ldv = matmul(patches(id)%rot_inv, dv) |
| 170 | + r2d = sqrt(ldv(1)**2 + ldv(2)**2) |
| 171 | + gp%levelset = r2d - patches(id)%radius |
| 172 | + if (r2d > 0._wp) then |
| 173 | + gp%levelset_norm(1) = ldv(1)/r2d; gp%levelset_norm(2) = ldv(2)/r2d |
| 174 | + else |
| 175 | + gp%levelset_norm(1) = 0._wp; gp%levelset_norm(2) = 0._wp |
| 176 | + end if |
| 177 | + gp%levelset_norm(3) = 0._wp |
| 178 | + end subroutine s_geo3 |
| 179 | + |
| 180 | + subroutine s_geo4(gp) |
| 181 | + !$omp declare target |
| 182 | + type(gp_t), intent(inout) :: gp |
| 183 | + integer :: id, i, j, k |
| 184 | + real(wp), dimension(3) :: dv, ldv |
| 185 | + real(wp) :: d |
| 186 | + id = gp%pid; i = gp%loc(1); j = gp%loc(2); k = gp%loc(3) |
| 187 | + dv(1) = xc(i) - patches(id)%cx; dv(2) = yc(j) - patches(id)%cy; dv(3) = zc(k) - patches(id)%cz |
| 188 | + ldv = matmul(patches(id)%rot_inv, dv) - patches(id)%offset |
| 189 | + d = sqrt(sum(ldv**2)) |
| 190 | + gp%levelset = d - patches(id)%radius |
| 191 | + gp%levelset_norm = ldv / max(d, 1.0e-12_wp) |
| 192 | + end subroutine s_geo4 |
| 193 | + |
| 194 | + subroutine s_geo5(gp) |
| 195 | + !$omp declare target |
| 196 | + type(gp_t), intent(inout) :: gp |
| 197 | + integer :: id, i, j |
| 198 | + real(wp) :: ax, ay, d |
| 199 | + real(wp), dimension(3) :: dv |
| 200 | + id = gp%pid; i = gp%loc(1); j = gp%loc(2) |
| 201 | + ax = patches(id)%lx/2._wp; ay = patches(id)%ly/2._wp |
| 202 | + dv(1) = (xc(i) - patches(id)%cx)/ax |
| 203 | + dv(2) = (yc(j) - patches(id)%cy)/ay |
| 204 | + dv(3) = 0._wp |
| 205 | + d = sqrt(dv(1)**2 + dv(2)**2) |
| 206 | + gp%levelset = d - 1._wp |
| 207 | + if (d > 0._wp) then; gp%levelset_norm = dv/d; else; gp%levelset_norm = 0._wp; end if |
| 208 | + end subroutine s_geo5 |
| 209 | + |
| 210 | + subroutine s_geo6(gp) |
| 211 | + !$omp declare target |
| 212 | + type(gp_t), intent(inout) :: gp |
| 213 | + integer :: id, i, j |
| 214 | + real(wp) :: dx, dy |
| 215 | + id = gp%pid; i = gp%loc(1); j = gp%loc(2) |
| 216 | + dx = abs(xc(i) - patches(id)%cx) - patches(id)%lx/2._wp |
| 217 | + dy = abs(yc(j) - patches(id)%cy) - patches(id)%ly/2._wp |
| 218 | + gp%levelset = max(dx, dy) |
| 219 | + gp%levelset_norm(1) = sign(1._wp, xc(i) - patches(id)%cx) |
| 220 | + gp%levelset_norm(2) = sign(1._wp, yc(j) - patches(id)%cy) |
| 221 | + gp%levelset_norm(3) = 0._wp |
| 222 | + end subroutine s_geo6 |
| 223 | + |
| 224 | + subroutine s_geo7(gp) |
| 225 | + !$omp declare target |
| 226 | + type(gp_t), intent(inout) :: gp |
| 227 | + integer :: id, i, j |
| 228 | + real(wp), dimension(3) :: dv, ldv |
| 229 | + real(wp) :: d |
| 230 | + id = gp%pid; i = gp%loc(1); j = gp%loc(2) |
| 231 | + dv(1) = xc(i) - patches(id)%cx; dv(2) = yc(j) - patches(id)%cy; dv(3) = 0._wp |
| 232 | + ldv = matmul(patches(id)%rot_inv, dv) - patches(id)%offset |
| 233 | + d = sqrt(sum(ldv(1:2)**2)) |
| 234 | + gp%levelset = d - patches(id)%radius |
| 235 | + gp%levelset_norm = ldv / max(d, 1.0e-12_wp) |
| 236 | + end subroutine s_geo7 |
| 237 | + |
| 238 | + subroutine s_geo8(gp) |
| 239 | + !$omp declare target |
| 240 | + type(gp_t), intent(inout) :: gp |
| 241 | + integer :: id, i, j |
| 242 | + real(wp) :: d1, d2, d3 |
| 243 | + real(wp), dimension(3) :: dv |
| 244 | + id = gp%pid; i = gp%loc(1); j = gp%loc(2) |
| 245 | + dv(1) = xc(i) - patches(id)%cx; dv(2) = yc(j) - patches(id)%cy; dv(3) = 0._wp |
| 246 | + d1 = dv(2) + patches(id)%ly/2._wp |
| 247 | + d2 = -dv(2) + dv(1)*sqrt(3._wp)/3._wp + patches(id)%ly/3._wp |
| 248 | + d3 = -dv(2) - dv(1)*sqrt(3._wp)/3._wp + patches(id)%ly/3._wp |
| 249 | + gp%levelset = min(max(-d1,-d2), max(-d1,-d3)) |
| 250 | + gp%levelset_norm(1) = dv(1)/max(sqrt(sum(dv(1:2)**2)),1e-12_wp) |
| 251 | + gp%levelset_norm(2) = dv(2)/max(sqrt(sum(dv(1:2)**2)),1e-12_wp) |
| 252 | + gp%levelset_norm(3) = 0._wp |
| 253 | + end subroutine s_geo8 |
| 254 | + |
| 255 | + subroutine s_geo9(gp) |
| 256 | + !$omp declare target |
| 257 | + type(gp_t), intent(inout) :: gp |
| 258 | + integer :: id, i, j |
| 259 | + real(wp), dimension(3) :: dv |
| 260 | + real(wp) :: d |
| 261 | + id = gp%pid; i = gp%loc(1); j = gp%loc(2) |
| 262 | + dv(1) = xc(i) - patches(id)%cx + patches(id)%lx*patches(id)%offset(1) |
| 263 | + dv(2) = yc(j) - patches(id)%cy + patches(id)%ly*patches(id)%offset(2) |
| 264 | + dv(3) = 0._wp |
| 265 | + d = sqrt(sum(dv**2)) |
| 266 | + gp%levelset = d - patches(id)%radius |
| 267 | + gp%levelset_norm = dv / max(d, 1.0e-12_wp) |
| 268 | + end subroutine s_geo9 |
| 269 | + |
| 270 | + subroutine s_geo10(gp) |
| 271 | + !$omp declare target |
| 272 | + type(gp_t), intent(inout) :: gp |
| 273 | + integer :: id, i, j, k |
| 274 | + real(wp), dimension(3) :: dv, ldv |
| 275 | + real(wp) :: d |
| 276 | + id = gp%pid; i = gp%loc(1); j = gp%loc(2); k = gp%loc(3) |
| 277 | + dv(1) = xc(i) - patches(id)%cx; dv(2) = yc(j) - patches(id)%cy; dv(3) = zc(k) - patches(id)%cz |
| 278 | + ldv = matmul(patches(id)%rot, dv) |
| 279 | + d = sqrt(sum(ldv**2)) |
| 280 | + gp%levelset = d - patches(id)%radius |
| 281 | + gp%levelset_norm = matmul(patches(id)%rot_inv, ldv) / max(d, 1.0e-12_wp) |
| 282 | + end subroutine s_geo10 |
| 283 | + |
| 284 | +end module m_cl5 |
| 285 | + |
| 286 | +program test_cl5 |
| 287 | + use m_cl5 |
| 288 | + implicit none |
| 289 | + integer, parameter :: N = 16 |
| 290 | + type(gp_t) :: gps(N) |
| 291 | + integer :: i |
| 292 | + call s_init(N) |
| 293 | + do i = 1, N |
| 294 | + gps(i)%levelset = 0.0d0 |
| 295 | + gps(i)%levelset_norm = 0.0d0 |
| 296 | + gps(i)%interp_coeffs = 0.0d0 |
| 297 | + gps(i)%loc = [mod(i,N)+1, mod(i*2,N)+1, mod(i*3,N)+1] |
| 298 | + gps(i)%pid = mod(i-1,8)+1 |
| 299 | + gps(i)%xp = 0; gps(i)%yp = 0; gps(i)%zp = 0 |
| 300 | + end do |
| 301 | + call s_dispatch(gps, N) |
| 302 | + write(*,*) 'levelset(1) =', gps(1)%levelset |
| 303 | + call s_finalize() |
| 304 | +end program test_cl5 |
0 commit comments