diff --git a/src/irgen.jl b/src/irgen.jl index 7d8ee4be..cde75090 100644 --- a/src/irgen.jl +++ b/src/irgen.jl @@ -633,16 +633,8 @@ function add_kernel_state!(mod::LLVM.Module) # ensure the old (stateless) functions don't have uses anymore, and remove them for f in keys(workmap) - for use in uses(f) - val = user(use) - if val isa ConstantExpr - # XXX: shouldn't clone_into! remove unused CEs? - isempty(uses(val)) || error("old function still has uses (via a constant expr)") - LLVM.unsafe_destroy!(val) - else - error("old function still has uses") - end - end + prune_constexpr_uses!(f) + @assert isempty(uses(f)) replace_metadata_uses!(f, workmap[f]) erase!(f) end diff --git a/src/metal.jl b/src/metal.jl index 79f9df6e..4f303196 100644 --- a/src/metal.jl +++ b/src/metal.jl @@ -406,14 +406,7 @@ function add_global_address_spaces!(@nospecialize(job::CompilerJob), mod::LLVM.M # delete old globals for (old, new) in global_map - for use in uses(old) - val = user(use) - if val isa ConstantExpr - # XXX: shouldn't clone_into! remove unused CEs? - isempty(uses(val)) || error("old function still has uses (via a constant expr)") - LLVM.unsafe_destroy!(val) - end - end + prune_constexpr_uses!(old) @assert isempty(uses(old)) replace_metadata_uses!(old, new) erase!(old) @@ -637,12 +630,7 @@ function add_input_arguments!(@nospecialize(job::CompilerJob), mod::LLVM.Module, # drop unused constants that may be referring to the old functions # XXX: can we do this differently? for f in worklist - for use in uses(f) - val = user(use) - if val isa LLVM.ConstantExpr && isempty(uses(val)) - LLVM.unsafe_destroy!(val) - end - end + prune_constexpr_uses!(f) end # update other uses of the old function, modifying call sites to pass the arguments diff --git a/src/utils.jl b/src/utils.jl index 3ddf8da9..cc031225 100644 --- a/src/utils.jl +++ b/src/utils.jl @@ -132,3 +132,20 @@ macro unlocked(ex) end esc(combinedef(def)) end + + +## constant expression pruning + +# for some reason, after cloning the LLVM IR can contain unused constant expressions. +# these result in false positives when checking that values are unused and can be deleted. +# this helper function removes such unused constant expression uses of a value. +# the process needs to be recursive, as constant expressions can refer to one another. +function prune_constexpr_uses!(root::LLVM.Value) + for use in uses(root) + val = user(use) + if val isa ConstantExpr + prune_constexpr_uses!(val) + isempty(uses(val)) && LLVM.unsafe_destroy!(val) + end + end +end