From e8c9f99362c108425f0a28a4ef7cb3910296428b Mon Sep 17 00:00:00 2001 From: Zentrik Date: Tue, 29 Aug 2023 13:15:27 +0100 Subject: [PATCH] Add docstring and tests --- base/compiler/ssair/passes.jl | 14 +++++++++++++- test/compiler/EscapeAnalysis/EAUtils.jl | 5 +++-- test/compiler/irpasses.jl | 22 ++++++++++++++++++++++ 3 files changed, 38 insertions(+), 3 deletions(-) diff --git a/base/compiler/ssair/passes.jl b/base/compiler/ssair/passes.jl index e68d7fbeb2c9a2..dd502b42c6dfed 100644 --- a/base/compiler/ssair/passes.jl +++ b/base/compiler/ssair/passes.jl @@ -1963,6 +1963,18 @@ function perform_symbolic_evaluation(stmt::PhiNode, ssa_to_ssa, blockidx) return svec(key...) end +""" + gnv!(ir::IRCode) -> newir::IRCode + +Global Value Numbering (GVN) pass. + +This is based on the NewGVN pass in LLVM. + +GVN partitions all the statements in the IR into congruence classes. All elements in a congruence class are guaranteed to be the same. + +It implements the RPO value numbering algorithm based on the paper "SCC based value numbering" by L. Taylor Simpson. +The elimination step is based on the implemenation in LLVM's NewGVN pass. +""" function gvn!(ir::IRCode) changed = true ssa_to_ssa = fill(0, length(ir.stmts.stmt)) # Map from ssa to ssa of equivalent value @@ -1973,7 +1985,7 @@ function gvn!(ir::IRCode) while changed changed = false - # RPO Traversal + # Reverse Post Order traversal of dominator tree for (blockidx, block) in enumerate(ir.cfg.blocks), i in block.stmts if !(ir.stmts.stmt[i] isa Expr) & !(ir.stmts.stmt[i] isa PhiNode) ssa_to_ssa[i] = i diff --git a/test/compiler/EscapeAnalysis/EAUtils.jl b/test/compiler/EscapeAnalysis/EAUtils.jl index bb3273b3e707ae..e77841066c4877 100644 --- a/test/compiler/EscapeAnalysis/EAUtils.jl +++ b/test/compiler/EscapeAnalysis/EAUtils.jl @@ -63,8 +63,8 @@ import Core: CodeInstance, MethodInstance, CodeInfo import .CC: InferenceResult, OptimizationState, IRCode, copy as cccopy, - @timeit, convert_to_ircode, slot2reg, compact!, ssa_inlining_pass!, sroa_pass!, - adce_pass!, JLOptions, verify_ir, verify_linetable + @timeit, convert_to_ircode, slot2reg, compact!, ssa_inlining_pass!, gvn!, + sroa_pass!, adce_pass!, JLOptions, verify_ir, verify_linetable import .EA: analyze_escapes, ArgEscapeCache, EscapeInfo, EscapeState, is_ipo_profitable # when working outside of Core.Compiler, @@ -222,6 +222,7 @@ function run_passes_with_ea(interp::EscapeAnalyzer, ci::CodeInfo, sv::Optimizati interp.state = state interp.linfo = sv.linfo end + @timeit "GVN" ir = gvn!(ir) @timeit "SROA" ir = sroa_pass!(ir) @timeit "ADCE" ir = adce_pass!(ir) @timeit "compact 3" ir = compact!(ir) diff --git a/test/compiler/irpasses.jl b/test/compiler/irpasses.jl index 3638218e0508a3..f622fe227f8f03 100644 --- a/test/compiler/irpasses.jl +++ b/test/compiler/irpasses.jl @@ -1452,3 +1452,25 @@ end fully_eliminated(; retval=Core.Argument(2)) do x::Float64 return ifelse(isa(x, Float64), x, exp(x)) end + +# Test that gvn! works on example from the paper "SCC based value numbering" by L. Taylor Simpson. +let src = @eval Module() begin + function g() + x = 1 + y = 1 + while true + x += 1 + y += 1 + end + end + code_typed(g, Tuple{})[1][1] + end + nphi = 0 + for stmt in src.code + if stmt isa Core.PhiNode + nphi += 1 + end + end + @test nphi == 1 + @test count(iscall((src, Base.add_int)), src.code) == 1 +end \ No newline at end of file