From a2f3d7735d5e4fdb915d99a8f902f71d82047af5 Mon Sep 17 00:00:00 2001 From: Shuhei Kadowaki <40514306+aviatesk@users.noreply.github.com> Date: Thu, 3 Aug 2023 14:03:42 -0400 Subject: [PATCH] optimizer: move inlineable constants into argument position during `compact!`-ion (#50767) In code like below ```julia Base.@assume_effects :nothrow function erase_before_inlining(x, y) z = sin(y) if x return "julia" end return z end let y::Float64 length(erase_before_inlining(true, y)) end ``` the constant prop' can figure out the constant return type of `erase_before_inlining(true, y)` while it is profitable not to inline expand it since otherwise we left some `!:nothrow` callees there (xref: https://github.com/JuliaLang/julia/pull/47305). In order to workaround this problem, this commit makes `compact!`move inlineable constants into argument positions so that the such "inlineable, but safe as a whole" calls to be erased during compaction. This should give us general compile-time performance improvement too as we no longer need to expand the IR for those calls. Requires: - #50764 - #50765 - #50768 --- base/compiler/ssair/ir.jl | 7 ++++++- test/compiler/EscapeAnalysis/interprocedural.jl | 6 ++---- test/compiler/inline.jl | 17 +++++++++++++++++ 3 files changed, 25 insertions(+), 5 deletions(-) diff --git a/base/compiler/ssair/ir.jl b/base/compiler/ssair/ir.jl index 4c287adaff251..8839812957279 100644 --- a/base/compiler/ssair/ir.jl +++ b/base/compiler/ssair/ir.jl @@ -1341,7 +1341,12 @@ function process_node!(compact::IncrementalCompact, result_idx::Int, inst::Instr return result_idx end end - ssa_rename[idx] = SSAValue(result_idx) + typ = inst[:type] + if isa(typ, Const) && is_inlineable_constant(typ.val) + ssa_rename[idx] = quoted(typ.val) + else + ssa_rename[idx] = SSAValue(result_idx) + end result[result_idx][:inst] = stmt result_idx += 1 elseif isa(stmt, PiNode) diff --git a/test/compiler/EscapeAnalysis/interprocedural.jl b/test/compiler/EscapeAnalysis/interprocedural.jl index 756e5489ed637..15d2a878d253b 100644 --- a/test/compiler/EscapeAnalysis/interprocedural.jl +++ b/test/compiler/EscapeAnalysis/interprocedural.jl @@ -98,10 +98,8 @@ identity_if_string(x::SafeRef) = nothing let result = code_escapes((SafeRef{String},); optimize=false) do x identity_if_string(x) end - i = only(findall(iscall((result.ir, identity_if_string)), result.ir.stmts.inst)) - r = only(findall(isreturn, result.ir.stmts.inst)) - @test !has_thrown_escape(result.state[Argument(2)], i) - @test !has_return_escape(result.state[Argument(2)], r) + @test !has_thrown_escape(result.state[Argument(2)]) + @test !has_return_escape(result.state[Argument(2)]) end let result = code_escapes((Union{SafeRef{String},Vector{String}},); optimize=false) do x identity_if_string(x) diff --git a/test/compiler/inline.jl b/test/compiler/inline.jl index 638f7e0185568..be9a2e98e2dc3 100644 --- a/test/compiler/inline.jl +++ b/test/compiler/inline.jl @@ -2065,3 +2065,20 @@ end # https://github.com/JuliaLang/julia/issues/50612 f50612(x) = UInt32(x) @test all(!isinvoke(:UInt32),get_code(f50612,Tuple{Char})) + +# move inlineable constant values into statement position during `compact!`-ion +# so that we don't inline DCE-eligibile calls +Base.@assume_effects :nothrow function erase_before_inlining(x, y) + z = sin(y) + if x + return "julia" + end + return z +end +@test fully_eliminated((Float64,); retval=5) do y + length(erase_before_inlining(true, y)) +end +@test fully_eliminated((Float64,); retval=(5,5)) do y + z = erase_before_inlining(true, y) + return length(z), length(z) +end