Skip to content

Commit 94e4d4b

Browse files
committed
test: add ifx #5633 ICE reproducers (matmul in declare-target sub)
m_ice_min.f90: 60-line minimum reproducer - matmul() inside ! declare target sub called from ! target teams loop - ICEs at O1/O2/O3; passes with -fno-inline - manual loops (no matmul intrinsic) compile fine, confirming matmul is trigger m_ice_repro.f90: structured reproducer matching real MFC m_compute_levelset - derived-type struct, allocatable module arrays, 10 separate target loops - same ICE pattern; confirms -fno-inline per-file workaround Bisection scripts (run_cl5b.sh, run_cl5c.sh) document the investigation: char field, interp_coeffs, loop count all ruled out matmul with struct-member or local matrix confirmed as trigger
1 parent 007e84d commit 94e4d4b

10 files changed

Lines changed: 1341 additions & 0 deletions

mini/m_cl4_mini.f90

Lines changed: 405 additions & 0 deletions
Large diffs are not rendered by default.

mini/m_cl5_mini.f90

Lines changed: 304 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,304 @@
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

mini/m_ice_min.f90

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
! ABSOLUTE MINIMUM reproducer for ifx 2025.1.1 SPIR-V ICE #5633
2+
!
3+
! Trigger: matmul() inside a !$omp declare target subroutine that is
4+
! inlined into a !$omp target teams loop kernel.
5+
!
6+
! ifx version: 2025.1.1 20250418 Hardware: Intel GPU Max 1100 (Ponte Vecchio)
7+
!
8+
! ICE (O1/O2/O3):
9+
! ifx -free -fiopenmp -fopenmp-targets=spir64 -O3 m_ice_min.f90
10+
! OK (inlining disabled):
11+
! ifx -free -fiopenmp -fopenmp-targets=spir64 -O3 -fno-inline m_ice_min.f90
12+
13+
module m_min
14+
15+
implicit none
16+
private
17+
18+
integer, parameter :: wp = kind(1.0d0)
19+
20+
real(wp), dimension(3, 3) :: A ! module-level 3x3 matrix
21+
real(wp), dimension(3) :: x ! module-level vector
22+
real(wp), dimension(3) :: b ! result vector
23+
!$omp declare target(A, x, b)
24+
25+
public :: s_run
26+
27+
contains
28+
29+
subroutine s_run(n)
30+
integer, intent(in) :: n
31+
integer :: i
32+
33+
A(1,:) = [1._wp, 0._wp, 0._wp]
34+
A(2,:) = [0._wp, 1._wp, 0._wp]
35+
A(3,:) = [0._wp, 0._wp, 1._wp]
36+
x = [1._wp, 2._wp, 3._wp]
37+
b = 0._wp
38+
!$omp target enter data map(to: A, x, b)
39+
40+
!$omp target teams loop private(i) map(to:A,x) map(tofrom:b)
41+
do i = 1, n
42+
call s_apply(i)
43+
end do
44+
45+
!$omp target exit data map(from: b)
46+
end subroutine s_run
47+
48+
subroutine s_apply(k)
49+
!$omp declare target
50+
integer, intent(in) :: k
51+
! matmul inside declare-target sub -- ICE trigger when inlined
52+
b = real(k, wp) * matmul(A, x)
53+
end subroutine s_apply
54+
55+
end module m_min
56+
57+
program test_min
58+
use m_min
59+
implicit none
60+
call s_run(4)
61+
end program test_min

0 commit comments

Comments
 (0)