Skip to content

Commit c251d3d

Browse files
committed
set ssaflags on CodeInfo construction
1 parent 6406503 commit c251d3d

File tree

4 files changed

+84
-59
lines changed

4 files changed

+84
-59
lines changed

base/compiler/optimize.jl

+18-54
Original file line numberDiff line numberDiff line change
@@ -134,12 +134,14 @@ const SLOT_ASSIGNEDONCE = 16 # slot is assigned to only once
134134
const SLOT_USEDUNDEF = 32 # slot has uses that might raise UndefVarError
135135
# const SLOT_CALLED = 64
136136

137-
# This statement was marked as @inbounds by the user. If replaced by inlining,
138-
# any contained boundschecks may be removed
139-
const IR_FLAG_INBOUNDS = 0x01
140-
# This statement was marked as @inline by the user
137+
# NOTE make sure to sync the flag definitions below with julia.h and `jl_code_info_set_ir` in method.c
138+
139+
# This statement is marked as @inbounds by user.
140+
# Ff replaced by inlining, any contained boundschecks may be removed.
141+
const IR_FLAG_INBOUNDS = 0x01 << 0
142+
# This statement is marked as @inline by user
141143
const IR_FLAG_INLINE = 0x01 << 1
142-
# This statement was marked as @noinline by the user
144+
# This statement is marked as @noinline by user
143145
const IR_FLAG_NOINLINE = 0x01 << 2
144146
# This statement may be removed if its result is unused. In particular it must
145147
# thus be both pure and effect free.
@@ -374,75 +376,37 @@ function convert_to_ircode(ci::CodeInfo, code::Vector{Any}, coverage::Bool, sv::
374376
end
375377
renumber_ir_elements!(code, changemap, labelmap)
376378

377-
inbounds_depth = 0 # Number of stacked inbounds
378-
inline_flags = BitVector()
379379
meta = Any[]
380-
flags = fill(0x00, length(code))
381380
for i = 1:length(code)
382-
stmt = code[i]
383-
if isexpr(stmt, :inbounds)
384-
arg1 = stmt.args[1]
385-
if arg1 === true # push
386-
inbounds_depth += 1
387-
elseif arg1 === false # clear
388-
inbounds_depth = 0
389-
elseif inbounds_depth > 0 # pop
390-
inbounds_depth -= 1
391-
end
392-
stmt = nothing
393-
elseif isexpr(stmt, :inline)
394-
if stmt.args[1]::Bool
395-
push!(inline_flags, true)
396-
else
397-
pop!(inline_flags)
398-
end
399-
stmt = nothing
400-
elseif isexpr(stmt, :noinline)
401-
if stmt.args[1]::Bool
402-
push!(inline_flags, false)
403-
else
404-
pop!(inline_flags)
405-
end
406-
stmt = nothing
407-
else
408-
stmt = normalize(stmt, meta)
409-
end
410-
code[i] = stmt
411-
if stmt !== nothing
412-
if inbounds_depth > 0
413-
flags[i] |= IR_FLAG_INBOUNDS
414-
end
415-
if !isempty(inline_flags)
416-
if last(inline_flags)
417-
flags[i] |= IR_FLAG_INLINE
418-
else
419-
flags[i] |= IR_FLAG_NOINLINE
420-
end
421-
end
422-
end
381+
code[i] = remove_meta!(code[i], meta)
423382
end
424-
@assert isempty(inline_flags) "malformed meta flags"
425-
strip_trailing_junk!(ci, code, stmtinfo, flags)
383+
strip_trailing_junk!(ci, code, stmtinfo)
426384
cfg = compute_basic_blocks(code)
427385
types = Any[]
428-
stmts = InstructionStream(code, types, stmtinfo, ci.codelocs, flags)
386+
stmts = InstructionStream(code, types, stmtinfo, ci.codelocs, ci.ssaflags)
429387
ir = IRCode(stmts, cfg, collect(LineInfoNode, ci.linetable::Union{Vector{LineInfoNode},Vector{Any}}), sv.slottypes, meta, sv.sptypes)
430388
return ir
431389
end
432390

433-
function normalize(@nospecialize(stmt), meta::Vector{Any})
391+
function remove_meta!(@nospecialize(stmt), meta::Vector{Any})
434392
if isa(stmt, Expr)
435-
if stmt.head === :meta
393+
head = stmt.head
394+
if head === :meta
436395
args = stmt.args
437396
if length(args) > 0
438397
push!(meta, stmt)
439398
end
440399
return nothing
400+
elseif is_ssaflag_head(head)
401+
# we processed these flags in `jl_code_info_set_ir`
402+
return nothing
441403
end
442404
end
443405
return stmt
444406
end
445407

408+
is_ssaflag_head(head::Symbol) = head === :inbounds || head === :inline || head === :noinline
409+
446410
function slot2reg(ir::IRCode, ci::CodeInfo, sv::OptimizationState)
447411
# need `ci` for the slot metadata, IR for the code
448412
svdef = sv.linfo.def

base/compiler/ssair/slot2ssa.jl

+3-3
Original file line numberDiff line numberDiff line change
@@ -183,7 +183,7 @@ function rename_uses!(ir::IRCode, ci::CodeInfo, idx::Int, @nospecialize(stmt), r
183183
return fixemup!(stmt->true, stmt->renames[slot_id(stmt)], ir, ci, idx, stmt)
184184
end
185185

186-
function strip_trailing_junk!(ci::CodeInfo, code::Vector{Any}, info::Vector{Any}, flags::Vector{UInt8})
186+
function strip_trailing_junk!(ci::CodeInfo, code::Vector{Any}, info::Vector{Any})
187187
# Remove `nothing`s at the end, we don't handle them well
188188
# (we expect the last instruction to be a terminator)
189189
ssavaluetypes = ci.ssavaluetypes::Vector{Any}
@@ -193,7 +193,7 @@ function strip_trailing_junk!(ci::CodeInfo, code::Vector{Any}, info::Vector{Any}
193193
resize!(ssavaluetypes, i)
194194
resize!(ci.codelocs, i)
195195
resize!(info, i)
196-
resize!(flags, i)
196+
resize!(ci.ssaflags, i)
197197
break
198198
end
199199
end
@@ -205,7 +205,7 @@ function strip_trailing_junk!(ci::CodeInfo, code::Vector{Any}, info::Vector{Any}
205205
push!(ssavaluetypes, Union{})
206206
push!(ci.codelocs, 0)
207207
push!(info, nothing)
208-
push!(flags, 0x00)
208+
push!(ci.ssaflags, 0x00)
209209
end
210210
nothing
211211
end

src/julia.h

+2-1
Original file line numberDiff line numberDiff line change
@@ -255,7 +255,8 @@ typedef struct _jl_code_info_t {
255255
jl_value_t *ssavaluetypes; // types of ssa values (or count of them)
256256
jl_array_t *ssaflags; // flags associated with each statement:
257257
// 0 = inbounds
258-
// 1,2 = <reserved> inlinehint,always-inline,noinline
258+
// 1 = inline
259+
// 2 = noinline
259260
// 3 = <reserved> strict-ieee (strictfp)
260261
// 4 = effect-free (may be deleted if unused)
261262
// 5-6 = <unused>

src/method.c

+61-1
Original file line numberDiff line numberDiff line change
@@ -254,6 +254,11 @@ void jl_resolve_globals_in_ir(jl_array_t *stmts, jl_module_t *m, jl_svec_t *spar
254254
}
255255
}
256256

257+
jl_value_t* expr_arg1(jl_value_t* expr) {
258+
jl_array_t *args = ((jl_expr_t*)expr)->args;
259+
return jl_array_ptr_ref(args, 0);
260+
}
261+
257262
// copy a :lambda Expr into its CodeInfo representation,
258263
// including popping of known meta nodes
259264
static void jl_code_info_set_ir(jl_code_info_t *li, jl_expr_t *ir)
@@ -275,8 +280,17 @@ static void jl_code_info_set_ir(jl_code_info_t *li, jl_expr_t *ir)
275280
jl_gc_wb(li, li->code);
276281
size_t n = jl_array_len(body);
277282
jl_value_t **bd = (jl_value_t**)jl_array_ptr_data((jl_array_t*)li->code);
283+
li->ssaflags = jl_alloc_array_1d(jl_array_uint8_type, n);
284+
jl_gc_wb(li, li->ssaflags);
285+
int inbounds_depth = 0; // number of stacked inbounds
286+
// isempty(inline_flags): no user annotation
287+
// last(inline_flags) == 1: inline region
288+
// last(inline_flags) == 0: noinline region
289+
arraylist_t *inline_flags = arraylist_new((arraylist_t*)malloc_s(sizeof(arraylist_t)), 0);
278290
for (j = 0; j < n; j++) {
279291
jl_value_t *st = bd[j];
292+
int is_flag_stmt = 0;
293+
// check :meta expression
280294
if (jl_is_expr(st) && ((jl_expr_t*)st)->head == meta_sym) {
281295
size_t k, ins = 0, na = jl_expr_nargs(st);
282296
jl_array_t *meta = ((jl_expr_t*)st)->args;
@@ -298,10 +312,57 @@ static void jl_code_info_set_ir(jl_code_info_t *li, jl_expr_t *ir)
298312
else
299313
jl_array_del_end(meta, na - ins);
300314
}
315+
// check other flag expressions
316+
else if (jl_is_expr(st) && ((jl_expr_t*)st)->head == inbounds_sym) {
317+
is_flag_stmt = 1;
318+
jl_value_t *arg1 = expr_arg1(st);
319+
if (arg1 == (jl_value_t*)jl_true) // push
320+
inbounds_depth += 1;
321+
else if (arg1 == (jl_value_t*)jl_false) // clear
322+
inbounds_depth = 0;
323+
else if (inbounds_depth > 0) // pop
324+
inbounds_depth -= 1;
325+
}
326+
else if (jl_is_expr(st) && ((jl_expr_t*)st)->head == inline_sym) {
327+
is_flag_stmt = 1;
328+
jl_value_t *arg1 = expr_arg1(st);
329+
if (arg1 == (jl_value_t*)jl_true) // enter inline region
330+
arraylist_push(inline_flags, (void*)1);
331+
else { // exit inline region
332+
assert(arg1 == (jl_value_t*)jl_false);
333+
arraylist_pop(inline_flags);
334+
}
335+
}
336+
else if (jl_is_expr(st) && ((jl_expr_t*)st)->head == noinline_sym) {
337+
is_flag_stmt = 1;
338+
jl_value_t *arg1 = expr_arg1(st);
339+
if (arg1 == (jl_value_t*)jl_true) // enter noinline region
340+
arraylist_push(inline_flags, (void*)0);
341+
else { // exit noinline region
342+
assert(arg1 == (jl_value_t*)jl_false);
343+
arraylist_pop(inline_flags);
344+
}
345+
}
301346
else if (jl_is_expr(st) && ((jl_expr_t*)st)->head == return_sym) {
302347
jl_array_ptr_set(body, j, jl_new_struct(jl_returnnode_type, jl_exprarg(st, 0)));
303348
}
349+
350+
if (is_flag_stmt)
351+
jl_array_uint8_set(li->ssaflags, j, 0);
352+
else {
353+
uint8_t flag = 0;
354+
if (inbounds_depth > 0)
355+
flag |= 1 << 0;
356+
if (inline_flags->len > 0) {
357+
void* inline_flag = inline_flags->items[inline_flags->len - 1];
358+
flag |= 1 << (inline_flag ? 1 : 2);
359+
}
360+
jl_array_uint8_set(li->ssaflags, j, flag);
361+
}
304362
}
363+
assert(inline_flags->len == 0); // malformed otherwise
364+
arraylist_free(inline_flags);
365+
free(inline_flags);
305366
jl_array_t *vinfo = (jl_array_t*)jl_exprarg(ir, 1);
306367
jl_array_t *vis = (jl_array_t*)jl_array_ptr_ref(vinfo, 0);
307368
size_t nslots = jl_array_len(vis);
@@ -314,7 +375,6 @@ static void jl_code_info_set_ir(jl_code_info_t *li, jl_expr_t *ir)
314375
jl_gc_wb(li, li->slotflags);
315376
li->ssavaluetypes = jl_box_long(nssavalue);
316377
jl_gc_wb(li, li->ssavaluetypes);
317-
li->ssaflags = jl_alloc_array_1d(jl_array_uint8_type, 0);
318378

319379
// Flags that need to be copied to slotflags
320380
const uint8_t vinfo_mask = 8 | 16 | 32 | 64;

0 commit comments

Comments
 (0)