Skip to content

Commit

Permalink
Make MustAlias propagate ssadef to Conditional
Browse files Browse the repository at this point in the history
Another change will probably be needed to make sure that `MustAlias`
itself is invalidated by `.defssa`, but this is enough to make sure that
any Conditional derived from MustAlias works correctly.
  • Loading branch information
topolarity committed Aug 28, 2024
1 parent 2078345 commit e60a5ee
Show file tree
Hide file tree
Showing 5 changed files with 38 additions and 35 deletions.
18 changes: 10 additions & 8 deletions base/compiler/abstractinterpretation.jl
Original file line number Diff line number Diff line change
Expand Up @@ -392,7 +392,7 @@ function from_interprocedural!(interp::AbstractInterpreter, @nospecialize(rt), s
arginfo::ArgInfo, @nospecialize(maybecondinfo), vtypes::Union{VarTable,Nothing})
rt = collect_limitations!(rt, sv)
if isa(rt, InterMustAlias)
rt = from_intermustalias(typeinf_lattice(interp), rt, arginfo, sv)
rt = from_intermustalias(typeinf_lattice(interp), rt, arginfo, vtypes, sv)
elseif is_lattice_bool(ipo_lattice(interp), rt)
if maybecondinfo === nothing
rt = widenconditional(rt)
Expand All @@ -412,15 +412,17 @@ function collect_limitations!(@nospecialize(typ), sv::InferenceState)
return typ
end

function from_intermustalias(𝕃ᡒ::AbstractLattice, rt::InterMustAlias, arginfo::ArgInfo, sv::AbsIntState)
function from_intermustalias(𝕃ᡒ::AbstractLattice, rt::InterMustAlias, arginfo::ArgInfo, vtypes::Union{VarTable,Nothing}, sv::AbsIntState)
fargs = arginfo.fargs
if fargs !== nothing && 1 ≀ rt.slot ≀ length(fargs)
arg = ssa_def_slot(fargs[rt.slot], sv)
if isa(arg, SlotNumber)
argtyp = widenslotwrapper(arginfo.argtypes[rt.slot])
βŠ‘ = partialorder(𝕃ᡒ)
if rt.vartyp βŠ‘ argtyp
return MustAlias(arg, rt.vartyp, rt.fldidx, rt.fldtyp)
@assert vtypes !== nothing
vtyp = vtypes[slot_id(arg)]
return MustAlias(arg, vtyp.ssadef, rt.vartyp, rt.fldidx, rt.fldtyp)
else
# TODO optimize this case?
end
Expand Down Expand Up @@ -1916,7 +1918,9 @@ function abstract_call_builtin(interp::AbstractInterpreter, f::Builtin, (; fargs
fldidx = maybe_const_fldidx(vartyp, a3.val)
if fldidx !== nothing
# wrap this aliasable field into `MustAlias` for possible constraint propagations
return MustAlias(var, vartyp, fldidx, rt)
@assert vtypes !== nothing
vtyp = vtypes[slot_id(var)]
return MustAlias(var, vtyp.ssadef, vartyp, fldidx, rt)
end
end
end
Expand Down Expand Up @@ -3068,7 +3072,7 @@ end

@nospecializeinfer function widenreturn(𝕃ᡒ::MustAliasesLattice, @nospecialize(rt), info::BestguessInfo)
if isa(rt, MustAlias)
if 1 ≀ rt.slot ≀ info.nargs
if 1 ≀ rt.slot ≀ info.nargs && rt.ssadef == 0
rt = InterMustAlias(rt)
else
rt = widenmustalias(rt)
Expand Down Expand Up @@ -3286,7 +3290,6 @@ end
function init_vartable!(vartable::VarTable, frame::InferenceState)
nargtypes = length(frame.result.argtypes)
for i = 1:length(vartable)
# TODO: This should probably be `0`, not typemin(Int)
vartable[i] = VarState(Bottom, #= ssadef =# typemin(Int), i > nargtypes)
end
return vartable
Expand Down Expand Up @@ -3612,8 +3615,7 @@ function apply_refinement!(𝕃ᡒ::AbstractLattice, slot::SlotNumber, @nospecia
end

function conditional_valid(condt::Conditional, currstate::VarTable)
# TODO: Remove typemin condition...
# @assert condt.ssadef != typemin(Int)
@assert condt.ssadef != typemin(Int)
return currstate[condt.slot].ssadef == condt.ssadef
end

Expand Down
2 changes: 0 additions & 2 deletions base/compiler/inferencestate.jl
Original file line number Diff line number Diff line change
Expand Up @@ -315,12 +315,10 @@ mutable struct InferenceState
nargtypes = length(argtypes)
for i = 1:nslots
argtyp = (i > nargtypes) ? Bottom : argtypes[i]
# 0 = function entry (think carefully)
if argtyp === Bool && has_conditional(typeinf_lattice(interp))
argtyp = Conditional(i, #= ssadef =# 0, Const(true), Const(false))
end
slottypes[i] = argtyp
# 0 = function entry (think carefully)
bb_vartable1[i] = VarState(argtyp, #= ssadef =# 0, i > nargtypes)
end
src.ssavaluetypes = ssavaluetypes = Any[ NOT_FOUND for i = 1:nssavalues ]
Expand Down
21 changes: 12 additions & 9 deletions base/compiler/typelattice.jl
Original file line number Diff line number Diff line change
Expand Up @@ -136,19 +136,20 @@ N.B. currently this lattice element is only used in abstractinterpret, not in op
"""
struct MustAlias
slot::Int
ssadef::Int
vartyp::Any
fldidx::Int
fldtyp::Any
function MustAlias(slot::Int, @nospecialize(vartyp), fldidx::Int, @nospecialize(fldtyp))
function MustAlias(slot::Int, ssadef::Int, @nospecialize(vartyp), fldidx::Int, @nospecialize(fldtyp))
assert_nested_slotwrapper(vartyp)
assert_nested_slotwrapper(fldtyp)
# @assert !isalreadyconst(vartyp) "vartyp is already const"
# @assert !isalreadyconst(fldtyp) "fldtyp is already const"
return new(slot, vartyp, fldidx, fldtyp)
return new(slot, ssadef, vartyp, fldidx, fldtyp)
end
end
MustAlias(var::SlotNumber, @nospecialize(vartyp), fldidx::Int, @nospecialize(fldtyp)) =
MustAlias(slot_id(var), vartyp, fldidx, fldtyp)
MustAlias(var::SlotNumber, ssadef::Int, @nospecialize(vartyp), fldidx::Int, @nospecialize(fldtyp)) =
MustAlias(slot_id(var), ssadef, vartyp, fldidx, fldtyp)

"""
alias::InterMustAlias
Expand All @@ -172,8 +173,10 @@ InterMustAlias(var::SlotNumber, @nospecialize(vartyp), fldidx::Int, @nospecializ
InterMustAlias(slot_id(var), vartyp, fldidx, fldtyp)

const AnyMustAlias = Union{MustAlias,InterMustAlias}
MustAlias(alias::InterMustAlias) = MustAlias(alias.slot, alias.vartyp, alias.fldidx, alias.fldtyp)
InterMustAlias(alias::MustAlias) = InterMustAlias(alias.slot, alias.vartyp, alias.fldidx, alias.fldtyp)
function InterMustAlias(alias::MustAlias)
@assert alias.ssadef == 0
InterMustAlias(alias.slot, alias.vartyp, alias.fldidx, alias.fldtyp)
end

struct PartialTypeVar
tv::TypeVar
Expand Down Expand Up @@ -392,7 +395,7 @@ end
end

@nospecializeinfer function form_mustalias_conditional(alias::MustAlias, @nospecialize(thentype), @nospecialize(elsetype))
(; slot, vartyp, fldidx) = alias
(; slot, ssadef, vartyp, fldidx) = alias
if isa(vartyp, PartialStruct)
fields = vartyp.fields
thenfields = thentype === Bottom ? nothing : copy(fields)
Expand All @@ -403,7 +406,7 @@ end
elsefields === nothing || (elsefields[i] = elsetype)
end
end
return Conditional(slot, typemin(Int), # TODO
return Conditional(slot, ssadef,
thenfields === nothing ? Bottom : PartialStruct(vartyp.typ, thenfields),
elsefields === nothing ? Bottom : PartialStruct(vartyp.typ, elsefields))
else
Expand All @@ -420,7 +423,7 @@ end
elsefields === nothing || push!(elsefields, t)
end
end
return Conditional(slot, typemin(Int),
return Conditional(slot, ssadef,
thenfields === nothing ? Bottom : PartialStruct(vartyp_widened, thenfields),
elsefields === nothing ? Bottom : PartialStruct(vartyp_widened, elsefields))
end
Expand Down
4 changes: 2 additions & 2 deletions test/compiler/AbstractInterpreter.jl
Original file line number Diff line number Diff line change
Expand Up @@ -411,9 +411,9 @@ CC.getsplit_impl(info::NoinlineCallInfo, idx::Int) = CC.getsplit(info.info, idx)
CC.getresult_impl(info::NoinlineCallInfo, idx::Int) = CC.getresult(info.info, idx)

function CC.abstract_call(interp::NoinlineInterpreter, arginfo::CC.ArgInfo, si::CC.StmtInfo,
vtypes::Union{VarTable,Nothing}, sv::CC.InferenceState, max_methods::Int)
vtypes::Union{CC.VarTable,Nothing}, sv::CC.InferenceState, max_methods::Int)
ret = @invoke CC.abstract_call(interp::CC.AbstractInterpreter,
arginfo::CC.ArgInfo, si::CC.StmtInfo, vtypes::Union{VarTable,Nothing}, sv::CC.InferenceState, max_methods::Int)
arginfo::CC.ArgInfo, si::CC.StmtInfo, vtypes::Union{CC.VarTable,Nothing}, sv::CC.InferenceState, max_methods::Int)
if sv.mod in noinline_modules(interp)
return CC.CallMeta(ret.rt, ret.exct, ret.effects, NoinlineCallInfo(ret.info))
end
Expand Down
28 changes: 14 additions & 14 deletions test/compiler/inference.jl
Original file line number Diff line number Diff line change
Expand Up @@ -2289,20 +2289,20 @@ let 𝕃ᡒ = InferenceLattice(MustAliasesLattice(BaseInferenceLattice.instance)
isa_tfunc(@nospecialize xs...) = Core.Compiler.isa_tfunc(𝕃ᡒ, xs...)
ifelse_tfunc(@nospecialize xs...) = Core.Compiler.ifelse_tfunc(𝕃ᡒ, xs...)

@test (MustAlias(2, AliasableField{Any}, 1, Int) βŠ‘ Int)
@test !(Int βŠ‘ MustAlias(2, AliasableField{Any}, 1, Int))
@test (Int βŠ‘ MustAlias(2, AliasableField{Any}, 1, Any))
@test (Const(42) βŠ‘ MustAlias(2, AliasableField{Any}, 1, Int))
@test !(MustAlias(2, AliasableField{Any}, 1, Any) βŠ‘ Int)
@test tmerge(MustAlias(2, AliasableField{Any}, 1, Any), Const(nothing)) === Any
@test tmerge(MustAlias(2, AliasableField{Any}, 1, Int), Const(nothing)) === Union{Int,Nothing}
@test tmerge(Const(nothing), MustAlias(2, AliasableField{Any}, 1, Any)) === Any
@test tmerge(Const(nothing), MustAlias(2, AliasableField{Any}, 1, Int)) === Union{Int,Nothing}
@test isa_tfunc(MustAlias(2, AliasableField{Any}, 1, Bool), Const(Bool)) === Const(true)
@test isa_tfunc(MustAlias(2, AliasableField{Any}, 1, Bool), Type{Bool}) === Const(true)
@test isa_tfunc(MustAlias(2, AliasableField{Any}, 1, Int), Type{Bool}) === Const(false)
@test ifelse_tfunc(MustAlias(2, AliasableField{Any}, 1, Bool), Int, Int) === Int
@test ifelse_tfunc(MustAlias(2, AliasableField{Any}, 1, Int), Int, Int) === Union{}
@test (MustAlias(2, 0, AliasableField{Any}, 1, Int) βŠ‘ Int)
@test !(Int βŠ‘ MustAlias(2, 0, AliasableField{Any}, 1, Int))
@test (Int βŠ‘ MustAlias(2, 0, AliasableField{Any}, 1, Any))
@test (Const(42) βŠ‘ MustAlias(2, 0, AliasableField{Any}, 1, Int))
@test !(MustAlias(2, 0, AliasableField{Any}, 1, Any) βŠ‘ Int)
@test tmerge(MustAlias(2, 0, AliasableField{Any}, 1, Any), Const(nothing)) === Any
@test tmerge(MustAlias(2, 0, AliasableField{Any}, 1, Int), Const(nothing)) === Union{Int,Nothing}
@test tmerge(Const(nothing), MustAlias(2, 0, AliasableField{Any}, 1, Any)) === Any
@test tmerge(Const(nothing), MustAlias(2, 0, AliasableField{Any}, 1, Int)) === Union{Int,Nothing}
@test isa_tfunc(MustAlias(2, 0, AliasableField{Any}, 1, Bool), Const(Bool)) === Const(true)
@test isa_tfunc(MustAlias(2, 0, AliasableField{Any}, 1, Bool), Type{Bool}) === Const(true)
@test isa_tfunc(MustAlias(2, 0, AliasableField{Any}, 1, Int), Type{Bool}) === Const(false)
@test ifelse_tfunc(MustAlias(2, 0, AliasableField{Any}, 1, Bool), Int, Int) === Int
@test ifelse_tfunc(MustAlias(2, 0, AliasableField{Any}, 1, Int), Int, Int) === Union{}
end

maybeget_mustalias_tmerge(x::AliasableField) = x.f
Expand Down

0 comments on commit e60a5ee

Please sign in to comment.