From 279f2de36382a7802d85409d3b273894a0b3877f Mon Sep 17 00:00:00 2001 From: Roger-luo Date: Fri, 29 May 2020 18:11:14 -0400 Subject: [PATCH 01/10] find dependencies --- src/ir/utils.jl | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/src/ir/utils.jl b/src/ir/utils.jl index 1b3d2db..123cf28 100644 --- a/src/ir/utils.jl +++ b/src/ir/utils.jl @@ -80,3 +80,29 @@ function exprline(ir::IR, x::Variable) i > 0 || return get(ir.lines, ir[x].line, nothing) end + +function dependencies(ir::IR, x::IRTools.Variable) + var_stack = Variable[x] + path = Variable[] + args = IRTools.arguments(ir) + while !isempty(var_stack) + curr_var = pop!(var_stack) + if curr_var in args + continue + end + + stmt = ir[curr_var] + if (stmt.expr isa Expr) && (stmt.expr.head == :call) + for arg in stmt.expr.args + if arg isa Variable + # skip nodes we visited + if !(arg in path) + push!(var_stack, arg) + push!(path, arg) + end + end + end + end + end + return path +end From 82acdb9e991493981c3121c7d66f67346678d613 Mon Sep 17 00:00:00 2001 From: Roger-luo Date: Sun, 7 Jun 2020 21:50:23 -0400 Subject: [PATCH 02/10] rework dependencies --- src/IRTools.jl | 2 +- src/ir/utils.jl | 26 ------------------ src/passes/passes.jl | 65 ++++++++++++++++++++++++++++++++++++++++++++ test/analysis.jl | 28 ++++++++++++++++++- 4 files changed, 93 insertions(+), 28 deletions(-) diff --git a/src/IRTools.jl b/src/IRTools.jl index 9867939..c020efa 100644 --- a/src/IRTools.jl +++ b/src/IRTools.jl @@ -50,7 +50,7 @@ let exports = :[ definitions, usages, dominators, domtree, domorder, domorder!, renumber, merge_returns!, expand!, prune!, ssa!, inlineable!, log!, pis!, func, evalir, Simple, Loop, Multiple, reloop, stackify, functional, cond, WorkQueue, - Graph, liveness, interference, colouring, + Graph, liveness, interference, colouring, dependencies, find_dependency_path, # Reflection, Dynamo Meta, Lambda, meta, dynamo, transform, refresh, recurse!, self, varargs!, slots!, diff --git a/src/ir/utils.jl b/src/ir/utils.jl index 123cf28..1b3d2db 100644 --- a/src/ir/utils.jl +++ b/src/ir/utils.jl @@ -80,29 +80,3 @@ function exprline(ir::IR, x::Variable) i > 0 || return get(ir.lines, ir[x].line, nothing) end - -function dependencies(ir::IR, x::IRTools.Variable) - var_stack = Variable[x] - path = Variable[] - args = IRTools.arguments(ir) - while !isempty(var_stack) - curr_var = pop!(var_stack) - if curr_var in args - continue - end - - stmt = ir[curr_var] - if (stmt.expr isa Expr) && (stmt.expr.head == :call) - for arg in stmt.expr.args - if arg isa Variable - # skip nodes we visited - if !(arg in path) - push!(var_stack, arg) - push!(path, arg) - end - end - end - end - end - return path -end diff --git a/src/passes/passes.jl b/src/passes/passes.jl index 11ee3a8..f5ed3cb 100644 --- a/src/passes/passes.jl +++ b/src/passes/passes.jl @@ -41,6 +41,71 @@ function usages(b::Block) return uses end +usages(st::Statement) = usages(st.expr) +function usages(ex::Expr) + uses = Set{Variable}() + prewalk(ex) do x + x isa Variable && push!(uses, x) + return x + end + return uses +end + +""" + dependencies(ir::IR) + +Return the list of direct dependencies for each variable. +""" +function dependencies(ir::IR) + worklist = [block(ir, 1)] + deps = Dict() + while !isempty(worklist) + b = pop!(worklist) + for (v, st) in b + set = get!(deps, v, Set{Variable}()) + union!(set, usages(st)) + end + + brs = BasicBlock(b).branches + jump_next_block = true + for br in brs + jump_next_block = jump_next_block && (br.condition !== nothing) + if br.block > 0 + next_block = block(ir, br.block) + push!(worklist, next_block) + if !isempty(br.args) + for (x, y) in zip(arguments(next_block), br.args) + set = get!(deps, x, Set{Variable}()) + push!(set, y) + end + end + end + end + jump_next_block && push!(worklist, block(ir, b.block+1)) + end + return deps +end + +function _find_dependency_path(deps::Dict, x::Variable) + path = Set{Variable}() + stack = Variable[x] + while !isempty(stack) + curr = pop!(stack) + if haskey(deps, curr) + for v in deps[curr] + push!(path, v) + push!(stack, v) + end + end + end + return path +end + +function find_dependency_path(ir::IR, x::Variable) + deps = dependencies(ir) + return _find_dependency_path(deps, x) +end + function usecounts(ir::IR) counts = Dict{Variable,Int}() prewalk(ir) do x diff --git a/test/analysis.jl b/test/analysis.jl index 9123989..a3dda9a 100644 --- a/test/analysis.jl +++ b/test/analysis.jl @@ -1,5 +1,5 @@ using IRTools, Test -using IRTools: CFG, dominators, domtree +using IRTools: CFG, dominators, domtree, dependencies, find_dependency_path, var relu(x) = (y = x > 0 ? x : 0) ir = @code_ir relu(1) @@ -10,3 +10,29 @@ ir = @code_ir relu(1) @test domtree(CFG(ir)) == (1 => [2 => [], 3 => [], 4 => []]) @test domtree(CFG(ir)', entry = 4) == (4 => [1 => [], 2 => [], 3 => []]) + +function f(x) + x = sin(x) + y = cos(x) + + if x > 1 + x = cos(x) + 1 + else + x = y + 1 + end + return x +end + +ir = @code_ir f(1.0) + +@test dependencies(ir) == Dict( + var(9) => Set([var(8), var(7)]), + var(8) => Set([var(4)]), + var(7) => Set([var(6)]), + var(3) => Set([var(2)]), + var(5) => Set([var(3)]), + var(6) => Set([var(3)]), + var(4) => Set([var(3)]), +) + +@test find_dependency_path(ir, var(9)) == Set(var.([2, 8, 7, 3, 4, 6])) From f976ed57f81b367663c77c4d0e056ef05bf42be8 Mon Sep 17 00:00:00 2001 From: Roger-luo Date: Sun, 7 Jun 2020 22:41:23 -0400 Subject: [PATCH 03/10] let usage pass for other things --- src/passes/passes.jl | 2 ++ test/analysis.jl | 18 ++++++++++++++++++ 2 files changed, 20 insertions(+) diff --git a/src/passes/passes.jl b/src/passes/passes.jl index f5ed3cb..d88126c 100644 --- a/src/passes/passes.jl +++ b/src/passes/passes.jl @@ -42,6 +42,8 @@ function usages(b::Block) end usages(st::Statement) = usages(st.expr) +usages(ex) = Set{Variable}() + function usages(ex::Expr) uses = Set{Variable}() prewalk(ex) do x diff --git a/test/analysis.jl b/test/analysis.jl index a3dda9a..04d0fc1 100644 --- a/test/analysis.jl +++ b/test/analysis.jl @@ -36,3 +36,21 @@ ir = @code_ir f(1.0) ) @test find_dependency_path(ir, var(9)) == Set(var.([2, 8, 7, 3, 4, 6])) + +function f(x) + x = sin(x) + y = cos(x) + + @info "warning" x + + if x > 1 + x = cos(x) + 1 + else + x = y + 1 + end + return x +end + +ir = @code_ir f(1.0) + +@test find_dependency_path(ir, var(48)) == Set(var.([47, 46, 42, 45, 41, 3, 4, 2])) From 700cbedbf9b6f6a536818bda6c06376c70bd7d2b Mon Sep 17 00:00:00 2001 From: Roger-luo Date: Sat, 13 Jun 2020 15:08:23 -0400 Subject: [PATCH 04/10] rm info test --- test/analysis.jl | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/test/analysis.jl b/test/analysis.jl index 04d0fc1..6f3bb41 100644 --- a/test/analysis.jl +++ b/test/analysis.jl @@ -37,20 +37,20 @@ ir = @code_ir f(1.0) @test find_dependency_path(ir, var(9)) == Set(var.([2, 8, 7, 3, 4, 6])) -function f(x) - x = sin(x) - y = cos(x) +# function f(x) +# x = sin(x) +# y = cos(x) - @info "warning" x +# @info "warning" x - if x > 1 - x = cos(x) + 1 - else - x = y + 1 - end - return x -end +# if x > 1 +# x = cos(x) + 1 +# else +# x = y + 1 +# end +# return x +# end -ir = @code_ir f(1.0) +# ir = @code_ir f(1.0) -@test find_dependency_path(ir, var(48)) == Set(var.([47, 46, 42, 45, 41, 3, 4, 2])) +# @test find_dependency_path(ir, var(48)) == Set(var.([47, 46, 42, 45, 41, 3, 4, 2])) From 527527e01423352a7133d1b1382ca5ab4c259d1d Mon Sep 17 00:00:00 2001 From: Roger-luo Date: Sat, 13 Jun 2020 15:09:11 -0400 Subject: [PATCH 05/10] add broken --- test/analysis.jl | 27 ++++++++++++++------------- 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/test/analysis.jl b/test/analysis.jl index 6f3bb41..a25abd2 100644 --- a/test/analysis.jl +++ b/test/analysis.jl @@ -37,20 +37,21 @@ ir = @code_ir f(1.0) @test find_dependency_path(ir, var(9)) == Set(var.([2, 8, 7, 3, 4, 6])) -# function f(x) -# x = sin(x) -# y = cos(x) +function f(x) + x = sin(x) + y = cos(x) -# @info "warning" x + @info "warning" x -# if x > 1 -# x = cos(x) + 1 -# else -# x = y + 1 -# end -# return x -# end + if x > 1 + x = cos(x) + 1 + else + x = y + 1 + end + return x +end -# ir = @code_ir f(1.0) +ir = @code_ir f(1.0) -# @test find_dependency_path(ir, var(48)) == Set(var.([47, 46, 42, 45, 41, 3, 4, 2])) +# NOTE: this test is broken due to different IR generated by 1.0 and 1.2+ +@test_broken find_dependency_path(ir, var(48)) == Set(var.([47, 46, 42, 45, 41, 3, 4, 2])) From e6210603d9e2edd323f79d910010e0215a80a7cf Mon Sep 17 00:00:00 2001 From: Roger-luo Date: Sat, 13 Jun 2020 15:31:01 -0400 Subject: [PATCH 06/10] comment out a test --- test/analysis.jl | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/test/analysis.jl b/test/analysis.jl index a25abd2..a02ed02 100644 --- a/test/analysis.jl +++ b/test/analysis.jl @@ -37,21 +37,21 @@ ir = @code_ir f(1.0) @test find_dependency_path(ir, var(9)) == Set(var.([2, 8, 7, 3, 4, 6])) -function f(x) - x = sin(x) - y = cos(x) +# function f(x) +# x = sin(x) +# y = cos(x) - @info "warning" x +# @info "warning" x - if x > 1 - x = cos(x) + 1 - else - x = y + 1 - end - return x -end +# if x > 1 +# x = cos(x) + 1 +# else +# x = y + 1 +# end +# return x +# end -ir = @code_ir f(1.0) +# ir = @code_ir f(1.0) -# NOTE: this test is broken due to different IR generated by 1.0 and 1.2+ -@test_broken find_dependency_path(ir, var(48)) == Set(var.([47, 46, 42, 45, 41, 3, 4, 2])) +# # NOTE: this test is broken due to different IR generated by 1.0 and 1.2+ +# @test_broken find_dependency_path(ir, var(48)) == Set(var.([47, 46, 42, 45, 41, 3, 4, 2])) From a091c78f98f7cef943e0ed6eea5e6bdb43e412ea Mon Sep 17 00:00:00 2001 From: Roger-luo Date: Sun, 28 Jun 2020 03:58:35 -0400 Subject: [PATCH 07/10] rework dependencies --- src/passes/passes.jl | 78 +++++++++++++++++++++++++------------------- test/analysis.jl | 57 +++++++++++++++----------------- test/ir.jl | 24 ++++++++++++++ 3 files changed, 96 insertions(+), 63 deletions(-) diff --git a/src/passes/passes.jl b/src/passes/passes.jl index d88126c..f6640e0 100644 --- a/src/passes/passes.jl +++ b/src/passes/passes.jl @@ -46,13 +46,47 @@ usages(ex) = Set{Variable}() function usages(ex::Expr) uses = Set{Variable}() - prewalk(ex) do x + for x in ex.args x isa Variable && push!(uses, x) - return x end return uses end +function block_changes_deps(deps, ir, b) + for (v, st) in b + if haskey(deps, v) + (usages(st) ⊆ deps[v]) || return true + else + return true + end + end + + brs = branches(b) + for br in brs + if br.block > 0 + next_block = block(ir, br.block) + if !isempty(br.args) + for (x, y) in zip(arguments(next_block), br.args) + haskey(deps, x) && (y in deps[x]) && return true + end + end + end + end + return false +end + +function update_deps!(deps, v, direct) + set = get!(deps, v, Set{Variable}()) + union!(set, setdiff(direct, (v, ))) + + for x in direct + if (v != x) && haskey(deps, x) && !(deps[x] ⊆ set) + update_deps!(deps, v, deps[x]) + end + end + return deps +end + """ dependencies(ir::IR) @@ -64,48 +98,26 @@ function dependencies(ir::IR) while !isempty(worklist) b = pop!(worklist) for (v, st) in b - set = get!(deps, v, Set{Variable}()) - union!(set, usages(st)) + update_deps!(deps, v, usages(st)) end - brs = BasicBlock(b).branches - jump_next_block = true + brs = branches(b) for br in brs - jump_next_block = jump_next_block && (br.condition !== nothing) - if br.block > 0 + if br.block > 0 # reachable next_block = block(ir, br.block) - push!(worklist, next_block) - if !isempty(br.args) + if !isempty(br.args) # pass arguments for (x, y) in zip(arguments(next_block), br.args) - set = get!(deps, x, Set{Variable}()) - push!(set, y) + y isa Variable && update_deps!(deps, x, (y, )) end end - end - end - jump_next_block && push!(worklist, block(ir, b.block+1)) - end - return deps -end -function _find_dependency_path(deps::Dict, x::Variable) - path = Set{Variable}() - stack = Variable[x] - while !isempty(stack) - curr = pop!(stack) - if haskey(deps, curr) - for v in deps[curr] - push!(path, v) - push!(stack, v) + if block_changes_deps(deps, ir, next_block) + push!(worklist, next_block) + end end end end - return path -end - -function find_dependency_path(ir::IR, x::Variable) - deps = dependencies(ir) - return _find_dependency_path(deps, x) + return deps end function usecounts(ir::IR) diff --git a/test/analysis.jl b/test/analysis.jl index a02ed02..36e8cb0 100644 --- a/test/analysis.jl +++ b/test/analysis.jl @@ -25,33 +25,30 @@ end ir = @code_ir f(1.0) -@test dependencies(ir) == Dict( - var(9) => Set([var(8), var(7)]), - var(8) => Set([var(4)]), - var(7) => Set([var(6)]), - var(3) => Set([var(2)]), - var(5) => Set([var(3)]), - var(6) => Set([var(3)]), - var(4) => Set([var(3)]), -) - -@test find_dependency_path(ir, var(9)) == Set(var.([2, 8, 7, 3, 4, 6])) - -# function f(x) -# x = sin(x) -# y = cos(x) - -# @info "warning" x - -# if x > 1 -# x = cos(x) + 1 -# else -# x = y + 1 -# end -# return x -# end - -# ir = @code_ir f(1.0) - -# # NOTE: this test is broken due to different IR generated by 1.0 and 1.2+ -# @test_broken find_dependency_path(ir, var(48)) == Set(var.([47, 46, 42, 45, 41, 3, 4, 2])) +deps = dependencies(ir) + +@test deps[var(9)] == Set(var.([2, 8, 7, 3, 4, 6])) +@test deps[var(8)] == Set(var.([3, 2, 4])) +@test deps[var(7)] == Set(var.([6, 3, 2])) +@test deps[var(6)] == Set(var.([3, 2])) +@test deps[var(5)] == Set(var.([3, 2])) +@test deps[var(4)] == Set(var.([3, 2])) +@test deps[var(3)] == Set([var(2)]) + +function pow(x, n) + r = 1 + while n > 0 + n -= 1 + r *= x + end + return r +end + +ir = @code_ir pow(1.0, 2) +deps = dependencies(ir) + +@test deps[var(8)] == Set(var.([5, 2])) +@test deps[var(7)] == Set(var.([4, 3])) +@test deps[var(6)] == Set(var.([4, 3])) +@test deps[var(5)] == Set(var.([2, 8])) +@test deps[var(4)] == Set(var.([3, 7])) diff --git a/test/ir.jl b/test/ir.jl index 3c5873d..7008f61 100644 --- a/test/ir.jl +++ b/test/ir.jl @@ -32,3 +32,27 @@ end mylog2(x) = ccall((:log2, Base.Math.libm), Float64, (Float64,), x) @test foo(mylog2, 3.3) === mylog2(3.3) + + + +function mm3x3!(C, A, B) + A11 = A[1,1]; A12 = A[1,2]; A13 = A[1,3]; + A21 = A[2,1]; A22 = A[2,2]; A23 = A[2,3]; + A31 = A[3,1]; A32 = A[3,2]; A33 = A[3,3]; + + B11 = B[1,1]; B12 = B[1,2]; B13 = B[1,3]; + B21 = B[2,1]; B22 = B[2,2]; B23 = B[2,3]; + B31 = B[3,1]; B32 = B[3,2]; B33 = B[3,3]; + + C[1,1] = A11*B11 + A12*B21 + A13*B31 + C[1,2] = A11*B12 + A12*B22 + A13*B32 + C[1,3] = A11*B13 + A12*B23 + A13*B33 + + C[2,1] = A21*B11 + A22*B21 + A23*B31 + C[2,2] = A21*B12 + A22*B22 + A23*B32 + C[2,3] = A21*B13 + A22*B23 + A23*B33 + + C[3,1] = A31*B11 + A32*B21 + A33*B31 + C[3,2] = A31*B12 + A32*B22 + A33*B32 + C[3,3] = A31*B13 + A32*B23 + A33*B33 +end \ No newline at end of file From 5cb148673e9d2d9905480c51e342202a941d39ba Mon Sep 17 00:00:00 2001 From: Roger-luo Date: Wed, 1 Jul 2020 03:06:13 -0400 Subject: [PATCH 08/10] fix test --- src/IRTools.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/IRTools.jl b/src/IRTools.jl index 8f7eecb..4f9b039 100644 --- a/src/IRTools.jl +++ b/src/IRTools.jl @@ -47,7 +47,7 @@ let exports = :[ definitions, usages, dominators, domtree, domorder, domorder!, renumber, merge_returns!, expand!, prune!, ssa!, inlineable!, log!, pis!, func, evalir, Simple, Loop, Multiple, reloop, stackify, functional, cond, WorkQueue, - Graph, liveness, interference, colouring, inline, dependencies, find_dependency_path, + Graph, liveness, interference, colouring, inline, dependencies, # Reflection, Dynamo Meta, Lambda, meta, dynamo, transform, refresh, recurse!, self, varargs!, slots!, From 1f877a73c0295b587c8744358ad5a8218f1fbb88 Mon Sep 17 00:00:00 2001 From: Roger-luo Date: Wed, 1 Jul 2020 03:08:32 -0400 Subject: [PATCH 09/10] fix test --- test/analysis.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/analysis.jl b/test/analysis.jl index 36e8cb0..31940d6 100644 --- a/test/analysis.jl +++ b/test/analysis.jl @@ -1,5 +1,5 @@ using IRTools, Test -using IRTools: CFG, dominators, domtree, dependencies, find_dependency_path, var +using IRTools: CFG, dominators, domtree, dependencies, var relu(x) = (y = x > 0 ? x : 0) ir = @code_ir relu(1) From 6da6db85fb7307cca18205fcfdb62bc107bad925 Mon Sep 17 00:00:00 2001 From: Roger-luo Date: Wed, 1 Jul 2020 03:34:48 -0400 Subject: [PATCH 10/10] fix unconditional br --- src/passes/passes.jl | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/passes/passes.jl b/src/passes/passes.jl index f6640e0..8302615 100644 --- a/src/passes/passes.jl +++ b/src/passes/passes.jl @@ -102,7 +102,12 @@ function dependencies(ir::IR) end brs = branches(b) + jump_next_block = true for br in brs + if br.condition === nothing + jump_next_block = false + end + if br.block > 0 # reachable next_block = block(ir, br.block) if !isempty(br.args) # pass arguments @@ -116,6 +121,13 @@ function dependencies(ir::IR) end end end + + if jump_next_block + next_block = block(ir, b.id + 1) + if block_changes_deps(deps, ir, next_block) + push!(worklist, next_block) + end + end end return deps end