@@ -13,6 +13,31 @@ call_result_unused(sv::InferenceState, currpc::Int) =
1313 isexpr (sv. src. code[currpc], :call ) && isempty (sv. ssavalue_uses[currpc])
1414call_result_unused (si:: StmtInfo ) = ! si. used
1515
16+ is_const_bool_or_bottom (@nospecialize (b)) = (isa (b, Const) && isa (b. val, Bool)) || b == Bottom
17+ function can_propagate_conditional (@nospecialize (rt), argtypes:: Vector{Any} )
18+ isa (rt, InterConditional) || return false
19+ if rt. slot > length (argtypes)
20+ # In the vararg tail - can't be conditional
21+ @assert isvarargtype (argtypes[end ])
22+ return false
23+ end
24+ return isa (argtypes[rt. slot], Conditional) &&
25+ is_const_bool_or_bottom (rt. thentype) && is_const_bool_or_bottom (rt. thentype)
26+ end
27+
28+ function propagate_conditional (rt:: InterConditional , cond:: Conditional )
29+ new_thentype = rt. thentype === Const (false ) ? cond. elsetype : cond. thentype
30+ new_elsetype = rt. elsetype === Const (true ) ? cond. thentype : cond. elsetype
31+ if rt. thentype == Bottom
32+ @assert rt. elsetype != Bottom
33+ return Conditional (cond. slot, Bottom, new_elsetype)
34+ elseif rt. elsetype == Bottom
35+ @assert rt. thentype != Bottom
36+ return Conditional (cond. slot, new_thentype, Bottom)
37+ end
38+ return Conditional (cond. slot, new_thentype, new_elsetype)
39+ end
40+
1641function abstract_call_gf_by_type (interp:: AbstractInterpreter , @nospecialize (f),
1742 arginfo:: ArgInfo , si:: StmtInfo , @nospecialize (atype),
1843 sv:: AbsIntState , max_methods:: Int )
@@ -156,6 +181,15 @@ function abstract_call_gf_by_type(interp::AbstractInterpreter, @nospecialize(f),
156181 end
157182 @assert ! (this_conditional isa Conditional || this_rt isa MustAlias) " invalid lattice element returned from inter-procedural context"
158183 seen += 1
184+
185+ if can_propagate_conditional (this_conditional, argtypes)
186+ # The only case where we need to keep this in rt is where
187+ # we can directly propagate the conditional to a slot argument
188+ # that is not one of our arguments, otherwise we keep all the
189+ # relevant information in `conditionals` below.
190+ this_rt = this_conditional
191+ end
192+
159193 rettype = rettype β β this_rt
160194 exctype = exctype β β this_exct
161195 if has_conditional (πβ, sv) && this_conditional != = Bottom && is_lattice_bool (πβ, rettype) && fargs != = nothing
@@ -409,6 +443,9 @@ function from_interconditional(πα΅’::AbstractLattice, @nospecialize(rt), sv::
409443 has_conditional (πα΅’, sv) || return widenconditional (rt)
410444 (; fargs, argtypes) = arginfo
411445 fargs === nothing && return widenconditional (rt)
446+ if can_propagate_conditional (rt, argtypes)
447+ return propagate_conditional (rt, argtypes[rt. slot]:: Conditional )
448+ end
412449 slot = 0
413450 alias = nothing
414451 thentype = elsetype = Any
@@ -2217,13 +2254,6 @@ function abstract_call_known(interp::AbstractInterpreter, @nospecialize(f),
22172254 end
22182255 elseif is_return_type (f)
22192256 return return_type_tfunc (interp, argtypes, si, sv)
2220- elseif la == 2 && istopfunction (f, :! )
2221- # handle Conditional propagation through !Bool
2222- aty = argtypes[2 ]
2223- if isa (aty, Conditional)
2224- call = abstract_call_gf_by_type (interp, f, ArgInfo (fargs, Any[Const (f), Bool]), si, Tuple{typeof (f), Bool}, sv, max_methods) # make sure we've inferred `!(::Bool)`
2225- return CallMeta (Conditional (aty. slot, aty. elsetype, aty. thentype), Any, call. effects, call. info)
2226- end
22272257 elseif la == 3 && istopfunction (f, :!= = )
22282258 # mark !== as exactly a negated call to ===
22292259 call = abstract_call_gf_by_type (interp, f, ArgInfo (fargs, Any[Const (f), Any, Any]), si, Tuple{typeof (f), Any, Any}, sv, max_methods)
@@ -3194,7 +3224,7 @@ function update_bestguess!(interp::AbstractInterpreter, frame::InferenceState,
31943224 # narrow representation of bestguess slightly to prepare for tmerge with rt
31953225 if rt isa InterConditional && bestguess isa Const
31963226 slot_id = rt. slot
3197- old_id_type = slottypes[slot_id]
3227+ old_id_type = widenconditional ( slottypes[slot_id])
31983228 if bestguess. val === true && rt. elsetype != = Bottom
31993229 bestguess = InterConditional (slot_id, old_id_type, Bottom)
32003230 elseif bestguess. val === false && rt. thentype != = Bottom
0 commit comments