@@ -190,17 +190,23 @@ struct NewSSAValue
190
190
id:: Int
191
191
end
192
192
193
- mutable struct UseRefIterator
193
+ mutable struct UseRef
194
194
stmt:: Any
195
+ op:: Int
196
+ UseRef (@nospecialize (a)) = new (a, 0 )
197
+ end
198
+ struct UseRefIterator
199
+ use:: Tuple{UseRef, Nothing}
195
200
relevant:: Bool
196
- UseRefIterator (@nospecialize (a), relevant:: Bool ) = new (a , relevant)
201
+ UseRefIterator (@nospecialize (a), relevant:: Bool ) = new (( UseRef (a), nothing ) , relevant)
197
202
end
198
- getindex (it:: UseRefIterator ) = it. stmt
203
+ getindex (it:: UseRefIterator ) = it. use[ 1 ] . stmt
199
204
200
- struct UseRef
201
- urs:: UseRefIterator
202
- use:: Int
203
- end
205
+ # TODO : stack-allocation
206
+ # struct UseRef
207
+ # urs::UseRefIterator
208
+ # use::Int
209
+ # end
204
210
205
211
struct OOBToken
206
212
end
@@ -209,41 +215,43 @@ struct UndefToken
209
215
end
210
216
211
217
function getindex (x:: UseRef )
212
- stmt = x. urs . stmt
218
+ stmt = x. stmt
213
219
if isa (stmt, Expr) && stmt. head === :(= )
214
220
rhs = stmt. args[2 ]
215
- if isa (rhs, Expr) && is_relevant_expr (rhs)
216
- x. use > length (rhs. args) && return OOBToken ()
217
- return rhs. args[x. use]
221
+ if isa (rhs, Expr)
222
+ if is_relevant_expr (rhs)
223
+ x. op > length (rhs. args) && return OOBToken ()
224
+ return rhs. args[x. op]
225
+ end
218
226
end
219
- x. use == 1 || return OOBToken ()
227
+ x. op == 1 || return OOBToken ()
220
228
return rhs
221
- elseif isa (stmt, Expr) && is_relevant_expr (stmt)
222
- x. use > length (stmt. args) && return OOBToken ()
223
- return stmt. args[x. use ]
229
+ elseif isa (stmt, Expr) # @assert is_relevant_expr(stmt)
230
+ x. op > length (stmt. args) && return OOBToken ()
231
+ return stmt. args[x. op ]
224
232
elseif isa (stmt, GotoIfNot)
225
- x. use == 1 || return OOBToken ()
233
+ x. op == 1 || return OOBToken ()
226
234
return stmt. cond
227
235
elseif isa (stmt, ReturnNode)
228
236
isdefined (stmt, :val ) || return OOBToken ()
229
- x. use == 1 || return OOBToken ()
237
+ x. op == 1 || return OOBToken ()
230
238
return stmt. val
231
239
elseif isa (stmt, PiNode)
232
240
isdefined (stmt, :val ) || return OOBToken ()
233
- x. use == 1 || return OOBToken ()
241
+ x. op == 1 || return OOBToken ()
234
242
return stmt. val
235
243
elseif isa (stmt, UpsilonNode)
236
244
isdefined (stmt, :val ) || return OOBToken ()
237
- x. use == 1 || return OOBToken ()
245
+ x. op == 1 || return OOBToken ()
238
246
return stmt. val
239
247
elseif isa (stmt, PhiNode)
240
- x. use > length (stmt. values) && return OOBToken ()
241
- isassigned (stmt. values, x. use ) || return UndefToken ()
242
- return stmt. values[x. use ]
248
+ x. op > length (stmt. values) && return OOBToken ()
249
+ isassigned (stmt. values, x. op ) || return UndefToken ()
250
+ return stmt. values[x. op ]
243
251
elseif isa (stmt, PhiCNode)
244
- x. use > length (stmt. values) && return OOBToken ()
245
- isassigned (stmt. values, x. use ) || return UndefToken ()
246
- return stmt. values[x. use ]
252
+ x. op > length (stmt. values) && return OOBToken ()
253
+ isassigned (stmt. values, x. op ) || return UndefToken ()
254
+ return stmt. values[x. op ]
247
255
else
248
256
return OOBToken ()
249
257
end
@@ -257,39 +265,41 @@ function is_relevant_expr(e::Expr)
257
265
end
258
266
259
267
function setindex! (x:: UseRef , @nospecialize (v))
260
- stmt = x. urs . stmt
268
+ stmt = x. stmt
261
269
if isa (stmt, Expr) && stmt. head === :(= )
262
270
rhs = stmt. args[2 ]
263
- if isa (rhs, Expr) && is_relevant_expr (rhs)
264
- x . use > length (rhs. args) && throw ( BoundsError () )
265
- rhs. args[x . use] = v
266
- else
267
- x . use == 1 || throw ( BoundsError ())
268
- stmt . args[ 2 ] = v
271
+ if isa (rhs, Expr)
272
+ if is_relevant_expr (rhs)
273
+ x . op > length ( rhs. args) && throw ( BoundsError ())
274
+ rhs . args[x . op] = v
275
+ return v
276
+ end
269
277
end
270
- elseif isa (stmt, Expr) && is_relevant_expr (stmt)
271
- x. use > length (stmt. args) && throw (BoundsError ())
272
- stmt. args[x. use] = v
278
+ x. op == 1 || throw (BoundsError ())
279
+ stmt. args[2 ] = v
280
+ elseif isa (stmt, Expr) # @assert is_relevant_expr(stmt)
281
+ x. op > length (stmt. args) && throw (BoundsError ())
282
+ stmt. args[x. op] = v
273
283
elseif isa (stmt, GotoIfNot)
274
- x. use == 1 || throw (BoundsError ())
275
- x. urs . stmt = GotoIfNot (v, stmt. dest)
284
+ x. op == 1 || throw (BoundsError ())
285
+ x. stmt = GotoIfNot (v, stmt. dest)
276
286
elseif isa (stmt, ReturnNode)
277
- x. use == 1 || throw (BoundsError ())
278
- x. urs . stmt = typeof (stmt)(v)
287
+ x. op == 1 || throw (BoundsError ())
288
+ x. stmt = typeof (stmt)(v)
279
289
elseif isa (stmt, UpsilonNode)
280
- x. use == 1 || throw (BoundsError ())
281
- x. urs . stmt = typeof (stmt)(v)
290
+ x. op == 1 || throw (BoundsError ())
291
+ x. stmt = typeof (stmt)(v)
282
292
elseif isa (stmt, PiNode)
283
- x. use == 1 || throw (BoundsError ())
284
- x. urs . stmt = typeof (stmt)(v, stmt. typ)
293
+ x. op == 1 || throw (BoundsError ())
294
+ x. stmt = typeof (stmt)(v, stmt. typ)
285
295
elseif isa (stmt, PhiNode)
286
- x. use > length (stmt. values) && throw (BoundsError ())
287
- isassigned (stmt. values, x. use ) || throw (BoundsError ())
288
- stmt. values[x. use ] = v
296
+ x. op > length (stmt. values) && throw (BoundsError ())
297
+ isassigned (stmt. values, x. op ) || throw (BoundsError ())
298
+ stmt. values[x. op ] = v
289
299
elseif isa (stmt, PhiCNode)
290
- x. use > length (stmt. values) && throw (BoundsError ())
291
- isassigned (stmt. values, x. use ) || throw (BoundsError ())
292
- stmt. values[x. use ] = v
300
+ x. op > length (stmt. values) && throw (BoundsError ())
301
+ isassigned (stmt. values, x. op ) || throw (BoundsError ())
302
+ stmt. values[x. op ] = v
293
303
else
294
304
throw (BoundsError ())
295
305
end
@@ -303,19 +313,31 @@ function userefs(@nospecialize(x))
303
313
return UseRefIterator (x, relevant)
304
314
end
305
315
306
- start (it:: UseRefIterator ) = 1
307
- @noinline function next (it:: UseRefIterator , use:: Int )
308
- while true
309
- x = UseRef (it, use)
310
- use += 1
311
- x[] === UndefToken () || return (x, use)
312
- end
313
- end
314
- @noinline function done (it:: UseRefIterator , use:: Int )
316
+ start (it:: UseRefIterator ) = (it. use[1 ]. op = 0 ; nothing )
317
+ next (it:: UseRefIterator , :: Nothing ) = it. use
318
+ @noinline function done (it:: UseRefIterator , :: Nothing )
315
319
it. relevant || return true
316
- x, _ = next (it, use)
317
- return x[] === OOBToken ()
318
- end
320
+ use = it. use[1 ]
321
+ while true
322
+ use. op += 1
323
+ y = use[]
324
+ y === OOBToken () && return true
325
+ y === UndefToken () || break
326
+ end
327
+ return false
328
+ end
329
+ # iterate(it::UseRefIterator) = (it.use[1].op = 0; iterate(it, nothing))
330
+ # @noinline function iterate(it::UseRefIterator, ::Nothing)
331
+ # it.relevant || return nothing
332
+ # use = it.use[1]
333
+ # while true
334
+ # use.op += 1
335
+ # y = use[]
336
+ # y === OOBToken() && return nothing
337
+ # y === UndefToken() || break
338
+ # end
339
+ # return it.use
340
+ # end
319
341
320
342
function scan_ssa_use! (used, @nospecialize (stmt))
321
343
if isa (stmt, SSAValue)
0 commit comments