@@ -13,6 +13,31 @@ call_result_unused(sv::InferenceState, currpc::Int) =
13
13
isexpr (sv. src. code[currpc], :call ) && isempty (sv. ssavalue_uses[currpc])
14
14
call_result_unused (si:: StmtInfo ) = ! si. used
15
15
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
+
16
41
function abstract_call_gf_by_type (interp:: AbstractInterpreter , @nospecialize (f),
17
42
arginfo:: ArgInfo , si:: StmtInfo , @nospecialize (atype),
18
43
sv:: AbsIntState , max_methods:: Int )
@@ -156,6 +181,15 @@ function abstract_call_gf_by_type(interp::AbstractInterpreter, @nospecialize(f),
156
181
end
157
182
@assert ! (this_conditional isa Conditional || this_rt isa MustAlias) " invalid lattice element returned from inter-procedural context"
158
183
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
+
159
193
rettype = rettype ⊔ ₚ this_rt
160
194
exctype = exctype ⊔ ₚ this_exct
161
195
if has_conditional (𝕃ₚ, sv) && this_conditional != = Bottom && is_lattice_bool (𝕃ₚ, rettype) && fargs != = nothing
@@ -409,6 +443,9 @@ function from_interconditional(𝕃ᵢ::AbstractLattice, @nospecialize(rt), sv::
409
443
has_conditional (𝕃ᵢ, sv) || return widenconditional (rt)
410
444
(; fargs, argtypes) = arginfo
411
445
fargs === nothing && return widenconditional (rt)
446
+ if can_propagate_conditional (rt, argtypes)
447
+ return propagate_conditional (rt, argtypes[rt. slot]:: Conditional )
448
+ end
412
449
slot = 0
413
450
alias = nothing
414
451
thentype = elsetype = Any
@@ -2217,13 +2254,6 @@ function abstract_call_known(interp::AbstractInterpreter, @nospecialize(f),
2217
2254
end
2218
2255
elseif is_return_type (f)
2219
2256
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
2227
2257
elseif la == 3 && istopfunction (f, :!= = )
2228
2258
# mark !== as exactly a negated call to ===
2229
2259
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,
3194
3224
# narrow representation of bestguess slightly to prepare for tmerge with rt
3195
3225
if rt isa InterConditional && bestguess isa Const
3196
3226
slot_id = rt. slot
3197
- old_id_type = slottypes[slot_id]
3227
+ old_id_type = widenconditional ( slottypes[slot_id])
3198
3228
if bestguess. val === true && rt. elsetype != = Bottom
3199
3229
bestguess = InterConditional (slot_id, old_id_type, Bottom)
3200
3230
elseif bestguess. val === false && rt. thentype != = Bottom
0 commit comments