Skip to content

Commit 5ae2627

Browse files
authored
effects: pack bits better (#56737)
There is no reason to preserve duplicates of the bits for the value before and after inference, and many of the numbers in the comments had gotten incorrect. Now we are able to pack all 16 bits of currently defined bitflags into 20 bits, instead of 25 bits (although either case still rounds up to 32). There was also no reason for InferenceState to be mutating of CodeInfo during execution, so remove that mutation.
1 parent 2590e67 commit 5ae2627

File tree

4 files changed

+42
-44
lines changed

4 files changed

+42
-44
lines changed

Compiler/src/inferencestate.jl

Lines changed: 12 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -267,6 +267,7 @@ mutable struct InferenceState
267267
bb_vartables::Vector{Union{Nothing,VarTable}} # nothing if not analyzed yet
268268
bb_saw_latestworld::Vector{Bool}
269269
ssavaluetypes::Vector{Any}
270+
ssaflags::Vector{UInt32}
270271
edges::Vector{Any}
271272
stmt_info::Vector{CallInfo}
272273

@@ -343,6 +344,7 @@ mutable struct InferenceState
343344
bb_vartable1[i] = VarState(argtyp, i > nargtypes)
344345
end
345346
src.ssavaluetypes = ssavaluetypes = Any[ NOT_FOUND for i = 1:nssavalues ]
347+
ssaflags = copy(src.ssaflags)
346348

347349
unreachable = BitSet()
348350
pclimitations = IdSet{InferenceState}()
@@ -374,7 +376,7 @@ mutable struct InferenceState
374376

375377
this = new(
376378
mi, WorldWithRange(world, valid_worlds), mod, sptypes, slottypes, src, cfg, spec_info,
377-
currbb, currpc, ip, handler_info, ssavalue_uses, bb_vartables, bb_saw_latestworld, ssavaluetypes, edges, stmt_info,
379+
currbb, currpc, ip, handler_info, ssavalue_uses, bb_vartables, bb_saw_latestworld, ssavaluetypes, ssaflags, edges, stmt_info,
378380
tasks, pclimitations, limitations, cycle_backedges, callstack, parentid, frameid, cycleid,
379381
result, unreachable, bestguess, exc_bestguess, ipo_effects,
380382
restrict_abstract_call_sites, cache_mode, insert_coverage,
@@ -1004,25 +1006,22 @@ function callers_in_cycle(sv::InferenceState)
10041006
end
10051007
callers_in_cycle(sv::IRInterpretationState) = AbsIntCycle(sv.callstack::Vector{AbsIntState}, 0, 0)
10061008

1007-
get_curr_ssaflag(sv::InferenceState) = sv.src.ssaflags[sv.currpc]
1009+
get_curr_ssaflag(sv::InferenceState) = sv.ssaflags[sv.currpc]
10081010
get_curr_ssaflag(sv::IRInterpretationState) = sv.ir.stmts[sv.curridx][:flag]
10091011

1010-
has_curr_ssaflag(sv::InferenceState, flag::UInt32) = has_flag(sv.src.ssaflags[sv.currpc], flag)
1012+
has_curr_ssaflag(sv::InferenceState, flag::UInt32) = has_flag(sv.ssaflags[sv.currpc], flag)
10111013
has_curr_ssaflag(sv::IRInterpretationState, flag::UInt32) = has_flag(sv.ir.stmts[sv.curridx][:flag], flag)
10121014

10131015
function set_curr_ssaflag!(sv::InferenceState, flag::UInt32, mask::UInt32=typemax(UInt32))
1014-
curr_flag = sv.src.ssaflags[sv.currpc]
1015-
sv.src.ssaflags[sv.currpc] = (curr_flag & ~mask) | flag
1016-
end
1017-
function set_curr_ssaflag!(sv::IRInterpretationState, flag::UInt32, mask::UInt32=typemax(UInt32))
1018-
curr_flag = sv.ir.stmts[sv.curridx][:flag]
1019-
sv.ir.stmts[sv.curridx][:flag] = (curr_flag & ~mask) | flag
1016+
curr_flag = sv.ssaflags[sv.currpc]
1017+
sv.ssaflags[sv.currpc] = (curr_flag & ~mask) | flag
1018+
nothing
10201019
end
10211020

1022-
add_curr_ssaflag!(sv::InferenceState, flag::UInt32) = sv.src.ssaflags[sv.currpc] |= flag
1021+
add_curr_ssaflag!(sv::InferenceState, flag::UInt32) = sv.ssaflags[sv.currpc] |= flag
10231022
add_curr_ssaflag!(sv::IRInterpretationState, flag::UInt32) = add_flag!(sv.ir.stmts[sv.curridx], flag)
10241023

1025-
sub_curr_ssaflag!(sv::InferenceState, flag::UInt32) = sv.src.ssaflags[sv.currpc] &= ~flag
1024+
sub_curr_ssaflag!(sv::InferenceState, flag::UInt32) = sv.ssaflags[sv.currpc] &= ~flag
10261025
sub_curr_ssaflag!(sv::IRInterpretationState, flag::UInt32) = sub_flag!(sv.ir.stmts[sv.curridx], flag)
10271026

10281027
function merge_effects!(::AbstractInterpreter, caller::InferenceState, effects::Effects)
@@ -1035,8 +1034,8 @@ function merge_effects!(::AbstractInterpreter, caller::InferenceState, effects::
10351034
end
10361035
merge_effects!(::AbstractInterpreter, ::IRInterpretationState, ::Effects) = return
10371036

1038-
decode_statement_effects_override(sv::AbsIntState) =
1039-
decode_statement_effects_override(get_curr_ssaflag(sv))
1037+
decode_statement_effects_override(sv::InferenceState) = decode_statement_effects_override(sv.src.ssaflags[sv.currpc])
1038+
decode_statement_effects_override(sv::IRInterpretationState) = decode_statement_effects_override(UInt32(0))
10401039

10411040
struct InferenceLoopState
10421041
rt

Compiler/src/optimize.jl

Lines changed: 25 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -17,37 +17,41 @@ const SLOT_USEDUNDEF = 32 # slot has uses that might raise UndefVarError
1717

1818
const IR_FLAG_NULL = zero(UInt32)
1919
# This statement is marked as @inbounds by user.
20-
# Ff replaced by inlining, any contained boundschecks may be removed.
20+
# If replaced by inlining, any contained boundschecks may be removed.
2121
const IR_FLAG_INBOUNDS = one(UInt32) << 0
2222
# This statement is marked as @inline by user
2323
const IR_FLAG_INLINE = one(UInt32) << 1
2424
# This statement is marked as @noinline by user
2525
const IR_FLAG_NOINLINE = one(UInt32) << 2
26-
# An optimization pass has updated this statement in a way that may
27-
# have exposed information that inference did not see. Re-running
28-
# inference on this statement may be profitable.
29-
const IR_FLAG_REFINED = one(UInt32) << 3
3026
# This statement is proven :consistent
31-
const IR_FLAG_CONSISTENT = one(UInt32) << 4
27+
const IR_FLAG_CONSISTENT = one(UInt32) << 3
3228
# This statement is proven :effect_free
33-
const IR_FLAG_EFFECT_FREE = one(UInt32) << 5
29+
const IR_FLAG_EFFECT_FREE = one(UInt32) << 4
3430
# This statement is proven :nothrow
35-
const IR_FLAG_NOTHROW = one(UInt32) << 6
36-
# This statement is proven :terminates
37-
const IR_FLAG_TERMINATES = one(UInt32) << 7
38-
# This statement is proven :noub
39-
const IR_FLAG_NOUB = one(UInt32) << 8
40-
# TODO: Both of these should eventually go away once
41-
# This statement is :effect_free == EFFECT_FREE_IF_INACCESSIBLEMEMONLY
42-
const IR_FLAG_EFIIMO = one(UInt32) << 9
43-
# This statement is :inaccessiblememonly == INACCESSIBLEMEM_OR_ARGMEMONLY
44-
const IR_FLAG_INACCESSIBLEMEM_OR_ARGMEM = one(UInt32) << 10
31+
const IR_FLAG_NOTHROW = one(UInt32) << 5
32+
# This statement is proven :terminates_globally
33+
const IR_FLAG_TERMINATES = one(UInt32) << 6
34+
#const IR_FLAG_TERMINATES_LOCALLY = one(UInt32) << 7
35+
#const IR_FLAG_NOTASKSTATE = one(UInt32) << 8
36+
#const IR_FLAG_INACCESSIBLEMEM = one(UInt32) << 9
37+
const IR_FLAG_NOUB = one(UInt32) << 10
38+
#const IR_FLAG_NOUBINIB = one(UInt32) << 11
39+
#const IR_FLAG_CONSISTENTOVERLAY = one(UInt32) << 12
4540
# This statement is :nortcall
46-
const IR_FLAG_NORTCALL = one(UInt32) << 11
41+
const IR_FLAG_NORTCALL = one(UInt32) << 13
42+
# An optimization pass has updated this statement in a way that may
43+
# have exposed information that inference did not see. Re-running
44+
# inference on this statement may be profitable.
45+
const IR_FLAG_REFINED = one(UInt32) << 16
4746
# This statement has no users and may be deleted if flags get refined to IR_FLAGS_REMOVABLE
48-
const IR_FLAG_UNUSED = one(UInt32) << 12
47+
const IR_FLAG_UNUSED = one(UInt32) << 17
48+
# TODO: Both of these next two should eventually go away once
49+
# This statement is :effect_free == EFFECT_FREE_IF_INACCESSIBLEMEMONLY
50+
const IR_FLAG_EFIIMO = one(UInt32) << 18
51+
# This statement is :inaccessiblememonly == INACCESSIBLEMEM_OR_ARGMEMONLY
52+
const IR_FLAG_INACCESSIBLEMEM_OR_ARGMEM = one(UInt32) << 19
4953

50-
const NUM_IR_FLAGS = 13 # sync with julia.h
54+
const NUM_IR_FLAGS = 3 # sync with julia.h
5155

5256
const IR_FLAGS_EFFECTS =
5357
IR_FLAG_CONSISTENT | IR_FLAG_EFFECT_FREE | IR_FLAG_NOTHROW |
@@ -815,6 +819,7 @@ function scan_non_dataflow_flags!(inst::Instruction, sv::PostOptAnalysisState)
815819
sv.nortcall = false
816820
end
817821
end
822+
nothing
818823
end
819824

820825
function scan_inconsistency!(inst::Instruction, sv::PostOptAnalysisState)

Compiler/src/typeinfer.jl

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -413,6 +413,7 @@ function finishinfer!(me::InferenceState, interp::AbstractInterpreter)
413413
ipo_effects = result.ipo_effects = me.ipo_effects = adjust_effects(me)
414414
result.exc_result = me.exc_bestguess = refine_exception_type(me.exc_bestguess, ipo_effects)
415415
me.src.rettype = widenconst(ignorelimited(bestguess))
416+
me.src.ssaflags = me.ssaflags
416417
me.src.min_world = first(me.world.valid_worlds)
417418
me.src.max_world = last(me.world.valid_worlds)
418419
istoplevel = !(me.linfo.def isa Method)
@@ -936,7 +937,7 @@ function codeinfo_for_const(interp::AbstractInterpreter, mi::MethodInstance, @no
936937
tree.slotflags = fill(0x00, nargs)
937938
tree.ssavaluetypes = 1
938939
tree.debuginfo = DebugInfo(mi)
939-
tree.ssaflags = UInt32[0]
940+
tree.ssaflags = [IR_FLAG_NULL]
940941
tree.rettype = Core.Typeof(val)
941942
tree.edges = Core.svec()
942943
set_inlineable!(tree, true)

src/julia.h

Lines changed: 3 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -279,7 +279,7 @@ typedef union __jl_purity_overrides_t {
279279
} _jl_purity_overrides_t;
280280

281281
#define NUM_EFFECTS_OVERRIDES 11
282-
#define NUM_IR_FLAGS 13
282+
#define NUM_IR_FLAGS 3
283283

284284
// This type describes a single function body
285285
typedef struct _jl_code_info_t {
@@ -292,15 +292,8 @@ typedef struct _jl_code_info_t {
292292
// 1 << 0 = inbounds region
293293
// 1 << 1 = callsite inline region
294294
// 1 << 2 = callsite noinline region
295-
// 1 << 3 = refined statement
296-
// 1 << 4 = :consistent
297-
// 1 << 5 = :effect_free
298-
// 1 << 6 = :nothrow
299-
// 1 << 7 = :terminates
300-
// 1 << 8 = :noub
301-
// 1 << 9 = :effect_free_if_inaccessiblememonly
302-
// 1 << 10 = :inaccessiblemem_or_argmemonly
303-
// 1 << 11-19 = callsite effects overrides
295+
// 1 << 3-14 = purity
296+
// 1 << 16+ = reserved for inference
304297
// miscellaneous data:
305298
jl_array_t *slotnames; // names of local variables
306299
jl_array_t *slotflags; // local var bit flags

0 commit comments

Comments
 (0)