Skip to content

Commit 26304f7

Browse files
Kenoaviatesk
andauthored
lattice: Properly percolate down tmerge (#46881)
We were skipping the parent lattice of the partials lattice, which may make external lattice implementation nonfunctional. Co-authored-by: Shuhei Kadowaki <40514306+aviatesk@users.noreply.github.com>
1 parent c0d5ffb commit 26304f7

File tree

2 files changed

+43
-14
lines changed

2 files changed

+43
-14
lines changed

β€Žbase/compiler/typelimits.jlβ€Ž

Lines changed: 33 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -433,6 +433,8 @@ function tmerge(lattice::ConditionalsLattice, @nospecialize(typea), @nospecializ
433433
end
434434
return Bool
435435
end
436+
typea = widenconditional(typea)
437+
typeb = widenconditional(typeb)
436438
return tmerge(widenlattice(lattice), typea, typeb)
437439
end
438440

@@ -471,8 +473,9 @@ end
471473

472474
function tmerge(lattice::PartialsLattice, @nospecialize(typea), @nospecialize(typeb))
473475
# type-lattice for Const and PartialStruct wrappers
474-
if ((isa(typea, PartialStruct) || isa(typea, Const)) &&
475-
(isa(typeb, PartialStruct) || isa(typeb, Const)))
476+
acp = isa(typea, Const) || isa(typea, PartialStruct)
477+
bcp = isa(typeb, Const) || isa(typeb, PartialStruct)
478+
if acp && bcp
476479
aty = widenconst(typea)
477480
bty = widenconst(typeb)
478481
if aty === bty
@@ -521,22 +524,40 @@ function tmerge(lattice::PartialsLattice, @nospecialize(typea), @nospecialize(ty
521524
return anyrefine ? PartialStruct(aty, fields) : aty
522525
end
523526
end
527+
# Don't widen const here - external AbstractInterpreter might insert lattice
528+
# layers between us and `ConstsLattice`.
529+
isa(typea, PartialStruct) && (typea = widenconst(typea))
530+
isa(typeb, PartialStruct) && (typeb = widenconst(typeb))
524531

525532
# type-lattice for PartialOpaque wrapper
526-
if isa(typea, PartialOpaque) && isa(typeb, PartialOpaque) && widenconst(typea) == widenconst(typeb)
527-
if !(typea.source === typeb.source &&
528-
typea.parent === typeb.parent)
529-
return widenconst(typea)
533+
apo = isa(typea, PartialOpaque)
534+
bpo = isa(typeb, PartialOpaque)
535+
if apo && bpo
536+
aty = widenconst(typea)
537+
bty = widenconst(typeb)
538+
if aty == bty
539+
if !(typea.source === typeb.source &&
540+
typea.parent === typeb.parent)
541+
return widenconst(typea)
542+
end
543+
return PartialOpaque(typea.typ, tmerge(typea.env, typeb.env),
544+
typea.parent, typea.source)
530545
end
531-
return PartialOpaque(typea.typ, tmerge(typea.env, typeb.env),
532-
typea.parent, typea.source)
546+
typea = aty
547+
typeb = bty
548+
elseif apo
549+
typea = widenconst(typea)
550+
elseif bpo
551+
typeb = widenconst(typeb)
533552
end
534553

535-
# no special type-inference lattice, join the types
536-
typea, typeb = widenconst(typea), widenconst(typeb)
537-
@assert isa(typea, Type); @assert isa(typeb, Type)
554+
return tmerge(widenlattice(lattice), typea, typeb)
555+
end
538556

539-
return tmerge(JLTypeLattice(), typea, typeb)
557+
function tmerge(lattice::ConstsLattice, @nospecialize(typea), @nospecialize(typeb))
558+
# the equality of the constants can be checked here, but the equivalent check is usually
559+
# done by `tmerge_fast_path` at earlier lattice stage
560+
return tmerge(widenlattice(lattice), widenconst(typea), widenconst(typeb))
540561
end
541562

542563
function tmerge(::JLTypeLattice, @nospecialize(typea::Type), @nospecialize(typeb::Type))

β€Žtest/compiler/AbstractInterpreter.jlβ€Ž

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -127,14 +127,14 @@ import .CC:
127127
struct TaintLattice{PL<:AbstractLattice} <: CC.AbstractLattice
128128
parent::PL
129129
end
130-
CC.widen(𝕃::TaintLattice) = 𝕃.parent
130+
CC.widenlattice(𝕃::TaintLattice) = 𝕃.parent
131131
CC.is_valid_lattice(𝕃::TaintLattice, @nospecialize(elm)) =
132132
is_valid_lattice(widenlattice(𝕃), elem) || isa(elm, Taint)
133133

134134
struct InterTaintLattice{PL<:AbstractLattice} <: CC.AbstractLattice
135135
parent::PL
136136
end
137-
CC.widen(𝕃::InterTaintLattice) = 𝕃.parent
137+
CC.widenlattice(𝕃::InterTaintLattice) = 𝕃.parent
138138
CC.is_valid_lattice(𝕃::InterTaintLattice, @nospecialize(elm)) =
139139
is_valid_lattice(widenlattice(𝕃), elem) || isa(elm, InterTaint)
140140

@@ -156,6 +156,9 @@ struct Taint
156156
end
157157
end
158158
Taint(@nospecialize(typ), id::Int) = Taint(typ, push!(BitSet(), id))
159+
function Base.:(==)(a::Taint, b::Taint)
160+
return a.typ == b.typ && a.slots == b.slots
161+
end
159162

160163
struct InterTaint
161164
typ
@@ -169,6 +172,9 @@ struct InterTaint
169172
end
170173
end
171174
InterTaint(@nospecialize(typ), id::Int) = InterTaint(typ, push!(BitSet(), id))
175+
function Base.:(==)(a::InterTaint, b::InterTaint)
176+
return a.typ == b.typ && a.slots == b.slots
177+
end
172178

173179
const AnyTaint = Union{Taint, InterTaint}
174180

@@ -229,4 +235,6 @@ function CC.widenreturn(𝕃::InferenceLattice{<:InterTaintLattice}, @nospeciali
229235
return CC.widenreturn(widenlattice(𝕃), rt, bestguess, nargs, slottypes, changes)
230236
end
231237

238+
@test CC.tmerge(typeinf_lattice(TaintInterpreter()), Taint(Int, 1), Taint(Int, 2)) == Taint(Int, BitSet(1:2))
239+
232240
# code_typed(ifelse, (Bool, Int, Int); interp=TaintInterpreter())

0 commit comments

Comments
Β (0)