-
Notifications
You must be signed in to change notification settings - Fork 124
Add 5-arg mul! Detection
#805
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 13 commits
270d17a
caf54ab
7aade81
6c2dee1
3c28cdc
08c601b
d15ee05
e8eec80
53ee3de
337e9b8
6abdbd9
468e8b7
138a2c4
742842c
8aade35
a0c5967
2a31c78
cacd14c
e8cda29
451c62e
6ef44a0
6b0925e
182cb04
283f172
fee1da5
180e465
f8ab20b
75447f5
32288b1
920260d
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,219 @@ | ||||||||||||||||||||||||||||||||||||||||||||
| # Pattern-based optimization templates for CSE | ||||||||||||||||||||||||||||||||||||||||||||
| struct OptimizationRule | ||||||||||||||||||||||||||||||||||||||||||||
| name::String | ||||||||||||||||||||||||||||||||||||||||||||
| detector::Function | ||||||||||||||||||||||||||||||||||||||||||||
| transformer::Function | ||||||||||||||||||||||||||||||||||||||||||||
| priority::Int | ||||||||||||||||||||||||||||||||||||||||||||
| end | ||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||
| function find_cse_expr(x, state) | ||||||||||||||||||||||||||||||||||||||||||||
| idx = findfirst(y -> nameof(lhs(y)) == nameof(x), state.sorted_exprs) | ||||||||||||||||||||||||||||||||||||||||||||
| isnothing(idx) ? nothing : (; expr = rhs(state.sorted_exprs[idx]), x) | ||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||
| end | ||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||
| function is_cse_var(x) | ||||||||||||||||||||||||||||||||||||||||||||
| startswith(string(nameof(x)), "##cse") | ||||||||||||||||||||||||||||||||||||||||||||
| end | ||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||
| function validate_mul_shapes(A, B, C) | ||||||||||||||||||||||||||||||||||||||||||||
| [shape(A)[1], shape(B)[2]] == shape(C) | ||||||||||||||||||||||||||||||||||||||||||||
| end | ||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||
| function validate_mul_shapes(A, B, C...) | ||||||||||||||||||||||||||||||||||||||||||||
| return true | ||||||||||||||||||||||||||||||||||||||||||||
| [shape(A)[1], shape(B)[2]] == shape(first(C)) | ||||||||||||||||||||||||||||||||||||||||||||
| end | ||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||
| function detect_matmul_add_pattern(expr::Code.Let, state::Code.CSEState) | ||||||||||||||||||||||||||||||||||||||||||||
| mul_candidates_idx = findall(expr.pairs) do x | ||||||||||||||||||||||||||||||||||||||||||||
| iscall(rhs(x)) || return false | ||||||||||||||||||||||||||||||||||||||||||||
| args = arguments(rhs(x)) | ||||||||||||||||||||||||||||||||||||||||||||
| all_arrays = all(y -> y <: AbstractArray, symtype.(args)) | ||||||||||||||||||||||||||||||||||||||||||||
| is_mul = operation(rhs(x)) === * | ||||||||||||||||||||||||||||||||||||||||||||
| all_arrays && is_mul | ||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||
| end | ||||||||||||||||||||||||||||||||||||||||||||
| mul_candidates = expr.pairs[mul_candidates_idx] | ||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||
| plus_candidates_idx = findall(expr.pairs) do x | ||||||||||||||||||||||||||||||||||||||||||||
| iscall(rhs(x)) || return false | ||||||||||||||||||||||||||||||||||||||||||||
| args = arguments(rhs(x)) | ||||||||||||||||||||||||||||||||||||||||||||
| all_arrays = all(y -> y <: AbstractArray, symtype.(args)) | ||||||||||||||||||||||||||||||||||||||||||||
| is_plus = operation(rhs(x)) === + | ||||||||||||||||||||||||||||||||||||||||||||
| all_arrays && is_plus | ||||||||||||||||||||||||||||||||||||||||||||
| end | ||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
73
to
79
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This check could be
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I seem to get |
||||||||||||||||||||||||||||||||||||||||||||
| plus_candidates = expr.pairs[plus_candidates_idx] | ||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||
| mul_vals = lhs.(mul_candidates) | ||||||||||||||||||||||||||||||||||||||||||||
| candidates = map(plus_candidates_idx, plus_candidates) do p_idx, p | ||||||||||||||||||||||||||||||||||||||||||||
| map(mul_candidates_idx, mul_vals) do m_idx, m_v | ||||||||||||||||||||||||||||||||||||||||||||
| if nameof(m_v) in nameof.(arguments(rhs(p))) | ||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||
| (m_idx, m_v) => (p_idx, expr.pairs[p_idx]) | ||||||||||||||||||||||||||||||||||||||||||||
| end | ||||||||||||||||||||||||||||||||||||||||||||
| end | ||||||||||||||||||||||||||||||||||||||||||||
| end | ||||||||||||||||||||||||||||||||||||||||||||
| candidates = filter(!isnothing, reduce(vcat, candidates)) | ||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
82
to
90
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. In fact, this entire block seems to be dead code? The result is not used anywhere
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yeah this block can be removed, there is a potentially faster and better check which maps the candidates to the Assignments, but that is not implemented yet.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. this block is now used, and the previous pattern matcher has been removed |
||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||
| pattern = map(plus_candidates_idx, plus_candidates) do plus_idx, c | ||||||||||||||||||||||||||||||||||||||||||||
| plus_args = arguments(rhs(c)) | ||||||||||||||||||||||||||||||||||||||||||||
| mul_pattern = map(mul_candidates_idx, mul_candidates) do mul_idx, m | ||||||||||||||||||||||||||||||||||||||||||||
| mul_val = lhs(m) | ||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||
| if nameof(mul_val) in nameof.(plus_args) | ||||||||||||||||||||||||||||||||||||||||||||
| A, B = arguments(rhs(m)) | ||||||||||||||||||||||||||||||||||||||||||||
| Cs = filter(x -> nameof(x) != nameof(mul_val), plus_args) | ||||||||||||||||||||||||||||||||||||||||||||
| validate_mul_shapes(A, B, Cs...) || return nothing | ||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||
| return (; A, B, Cs, mul_candidate = m, plus_candidate = c, mul_idx, plus_idx, pattern="A*B + C") | ||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||
| end | ||||||||||||||||||||||||||||||||||||||||||||
| end | ||||||||||||||||||||||||||||||||||||||||||||
| filter(!isnothing, mul_pattern) | ||||||||||||||||||||||||||||||||||||||||||||
| end | ||||||||||||||||||||||||||||||||||||||||||||
| isempty(pattern) ? nothing : pattern | ||||||||||||||||||||||||||||||||||||||||||||
| end | ||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||
| function transform_to_mul5_assignment(expr, match_data_, state::Code.CSEState) | ||||||||||||||||||||||||||||||||||||||||||||
| Cset = Set(filter(!is_cse_var, reduce(vcat,getproperty.(match_data_, :Cs)))) | ||||||||||||||||||||||||||||||||||||||||||||
| plus_candidates_idx = getproperty.(match_data_, :plus_idx) | ||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||
| final_temps = [] | ||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||
| m_ = map(match_data_) do match_data | ||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||
| A, B = match_data.A, match_data.B | ||||||||||||||||||||||||||||||||||||||||||||
| C = pop!(Cset) | ||||||||||||||||||||||||||||||||||||||||||||
| T = vartype(C) | ||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
110
to
119
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I believe |
||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||
| # Create temporary variable for the result | ||||||||||||||||||||||||||||||||||||||||||||
| temp_var_sym = gensym("mul5_temp") | ||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||
| temp_var = Sym{T}(temp_var_sym; type=symtype(C)) | ||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||
| copy_call = Term{T}(copy, [C]; type=symtype(C)) | ||||||||||||||||||||||||||||||||||||||||||||
| mul_call = Term{T}(LinearAlgebra.mul!, | ||||||||||||||||||||||||||||||||||||||||||||
| [temp_var, A, B, Const{T}(1), Const{T}(1)]; | ||||||||||||||||||||||||||||||||||||||||||||
| type=symtype(C)) | ||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
124
to
137
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Alternatively since we're not running CSE on the result of this pass, all of these can pass |
||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||
| # Add assignments to CSE state | ||||||||||||||||||||||||||||||||||||||||||||
| copy_assignment = Assignment(temp_var, copy_call) | ||||||||||||||||||||||||||||||||||||||||||||
| mul_assignment = Assignment(temp_var, mul_call) # This overwrites temp_var with mul! result | ||||||||||||||||||||||||||||||||||||||||||||
| final_assignment = Assignment(temp_var, temp_var) | ||||||||||||||||||||||||||||||||||||||||||||
| push!(final_temps, temp_var) | ||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||
| [copy_assignment, mul_assignment, final_assignment] | ||||||||||||||||||||||||||||||||||||||||||||
| end | ||||||||||||||||||||||||||||||||||||||||||||
| m = m_ |> Base.Fix1(reduce, vcat) | ||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||
| transformed_idxs = getproperty.(match_data_, :plus_idx) | ||||||||||||||||||||||||||||||||||||||||||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
No need to compute the same thing twice.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Removed |
||||||||||||||||||||||||||||||||||||||||||||
| substitution_map = get_substitution_map(match_data_, m_) | ||||||||||||||||||||||||||||||||||||||||||||
| rm_idxs = getproperty.(match_data_, :mul_idx) | ||||||||||||||||||||||||||||||||||||||||||||
| transformations = Dict() | ||||||||||||||||||||||||||||||||||||||||||||
| map(transformed_idxs, m_) do i, mm | ||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||
| bank(transformations, i, mm) | ||||||||||||||||||||||||||||||||||||||||||||
| end | ||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||
| new_pairs = [] | ||||||||||||||||||||||||||||||||||||||||||||
| for (i, e) in enumerate(expr.pairs) | ||||||||||||||||||||||||||||||||||||||||||||
| if i in transformed_idxs | ||||||||||||||||||||||||||||||||||||||||||||
| push!(new_pairs, transformations[i]...) | ||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||
| push!(new_pairs, transformations[i]...) | |
| append!(new_pairs, transformations[i]) |
Outdated
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| @show e |
Outdated
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why push! here only to filter it out later?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good catch, I needed to keep track of whether I had made any mistakes reconstructing the pairs. This will be removed before we are ready to merge
Outdated
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| push!(state.sorted_exprs, m...) | |
| append!(state.sorted_exprs, m) |
Outdated
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should use a for loop instead of a map. The latter does a bunch of extra work and allocates unnecessarily. plus_idxs also doesn't need to exist. It is unused.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fair enough
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| dic[key] = vcat(dic[key], value) | |
| else | |
| dic[key] = value | |
| push!(dic[key], value) | |
| else | |
| dic[key] = copy(value) |
Allocates once instead of every time a key is pushed.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't see how that helps? At the time of insertion, we don't actually know if there is a N-to-1 map trivially in this function. And assuming that will make us always do some extra legwork on the codegen side.
Outdated
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is a list of expressions, right?
| +(v...) | |
| SymbolicUtils.add_worker(vartype(first(v)), v...) |
Even better if substitution_map is concretely typed and the vartype can be lifted from there.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This one still needs to be addressed. Splatting is probably dynamic dispatch here, and will run the suggested replacement anyway. I'm assuming v is an indexable collection of symbolics/numbers/arrays of numbers.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is done now
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why is substitute_in_ir not just SymbolicUtils.substitute? You can even cache the substituter with subs = Substituter{false}(substitution_map) and just call map(subs, arguments(expr)).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Best I tried, SymbolicUtils.substitute didn't operate on IR, it worked on BasicSymbolic exprs directly. This can handle it on IR code.
Outdated
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| return Code.Term{Code.vartype(expr)}(operation(expr), new_args; type=Code.symtype(expr)) | |
| return Term{vartype(expr)}(operation(expr), new_args; type=symtype(expr)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is also done
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -145,10 +145,19 @@ const NUMBER_SIMPLIFIER = RestartedChain(( | |
| If(is_operation(^), Chain(POW_RULES)), | ||
| )) | ||
|
|
||
| is_array(x) = symtype(x) <: AbstractArray | ||
| const ARRAY_RULES = ( | ||
|
||
| @rule( ~a::is_array * ~b::is_array + ~c::is_array => begin | ||
| tmp = copy(~c) | ||
| LinearAlgebra.mul!(tmp, ~a, ~b, 1, 1) | ||
| end), | ||
| ) | ||
|
|
||
| const TRIG_EXP_SIMPLIFIER = Chain(TRIG_EXP_RULES) | ||
|
|
||
| const BOOLEAN_SIMPLIFIER = Chain(BOOLEAN_RULES) | ||
|
|
||
| const ARRAY_SIMPLIFIER = Chain(ARRAY_RULES) | ||
|
|
||
| function get_default_simplifier(; kw...) | ||
| IfElse(has_trig_exp, | ||
|
|
@@ -159,7 +168,9 @@ function get_default_simplifier(; kw...) | |
| Postwalk(Chain((If(x->symtype(x) <: Number, | ||
| NUMBER_SIMPLIFIER), | ||
| If(x->symtype(x) <: Bool, | ||
| BOOLEAN_SIMPLIFIER))) | ||
| BOOLEAN_SIMPLIFIER), | ||
| If(x -> symtype(x) <: AbstractArray, | ||
| ARRAY_SIMPLIFIER))) | ||
| ; kw...)) | ||
| end | ||
|
|
||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,72 @@ | ||
| using SymbolicUtils | ||
| using SymbolicUtils.Code | ||
| import SymbolicUtils as SU | ||
| using LinearAlgebra | ||
| using Test | ||
|
|
||
| # Helper function to check if optimization was applied | ||
| function has_mul5_optimization(ir) | ||
| if ir isa Code.Let | ||
| return any(ir.pairs) do assignment | ||
| rhs_expr = Code.rhs(assignment) | ||
| if SU.iscall(rhs_expr) | ||
| op = SU.operation(rhs_expr) | ||
| return op === LinearAlgebra.mul! | ||
| end | ||
| false | ||
| end | ||
| end | ||
| return false | ||
| end | ||
|
|
||
| # Helper function to build and evaluate both versions | ||
| function test_optimization(expr, args...) | ||
| cse_ir = SU.Code.cse(expr) | ||
| state = SU.Code.CSEState() | ||
| optimized_ir = SU.mul5_cse2(cse_ir, state) | ||
|
|
||
| # Check if optimization was applied | ||
| has_optimization = has_mul5_optimization(optimized_ir) | ||
| @test has_optimization | ||
|
|
||
| f_cse_expr = Func(collect(args), [], cse_ir) | ||
| f_cse = eval(toexpr(f_cse_expr)) | ||
|
|
||
| f_opt_expr = Func(collect(args), [], optimized_ir) | ||
| f_opt = eval(toexpr(f_opt_expr)) | ||
|
|
||
| test_A = randn(3, 3) | ||
| test_B = randn(3, 3) | ||
| test_C = randn(3, 3) | ||
| test_D = randn(3, 3) | ||
|
|
||
| # Get concrete test args | ||
| test_args = if length(args) == 3 | ||
| (test_A, test_B, test_C) | ||
| else | ||
| (test_A, test_B, test_C, test_D) | ||
| end | ||
|
|
||
| # Evaluate both versions | ||
| result_cse = invokelatest(f_cse, test_args...) | ||
| result_opt = invokelatest(f_opt, test_args...) | ||
|
|
||
| # Assert correctness | ||
| @test isapprox(result_cse, result_opt, rtol=1e-10) | ||
| end | ||
|
|
||
| @testset "Mul5 Optimization Tests" begin | ||
| @syms A[1:3, 1:3] B[1:3, 1:3] C[1:3, 1:3] D[1:3, 1:3] | ||
|
|
||
| expr1 = A * B + C | ||
| test_optimization(expr1, A, B, C) | ||
|
|
||
| expr2 = A * B + C + D | ||
| test_optimization(expr2, A, B, C, D) | ||
|
|
||
| expr4 = A * B + C + D + C * D # multiple correct patterns | ||
| test_optimization(expr4, A, B, C, D) | ||
|
|
||
| expr5 = sin.(A * B + C + D + C * D) | ||
| test_optimization(expr5, A, B, C, D) | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Try P = A + B
Q = B + C
R = C / D
P * Q + RDoes this correctly turn into
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. So the basic answer is we currently filter out some variables in our detection to find the C. @@ -67,13 +74,17 @@ function detect_matmul_add_pattern(expr::Code.Let, state::Code.CSEState)
- Cset = Set(filter(!is_cse_var, reduce(vcat,getproperty.(match_data_, :Cs))))
+ Cset = Set(Iterators.flatten(getproperty.(match_data_, :Cs)))I need a simplified version which correctly identifies which Cs are valid for our transformation. Fwiw with this applied: :(function (A, B, C, D)
#= /home/dhairyalgandhi/arpa/jsmo/clone/Symbolics.jl/src/build_function.jl:147 =# @inbounds begin
#= /home/dhairyalgandhi/arpa/jsmo/clone/Symbolics.jl/src/build_function.jl:147 =#
begin
#= /home/dhairyalgandhi/arpa/jsmo/clone/SymbolicUtils.jl/src/code.jl:507 =#
#= /home/dhairyalgandhi/arpa/jsmo/clone/SymbolicUtils.jl/src/code.jl:508 =#
#= /home/dhairyalgandhi/arpa/jsmo/clone/SymbolicUtils.jl/src/code.jl:509 =#
begin
var"##cse#1" = (/)(C, D)
var"##cse#2" = (+)(B, A)
var"##cse#3" = (+)(B, C)
var"##mul5_temp#554" = (copy)(var"##cse#1")
var"##mul5_temp#554" = (mul!)(var"##mul5_temp#554", var"##cse#2", var"##cse#3", 1, 1)
var"##mul5_temp#554" = var"##mul5_temp#554"
var"##mul5_temp#554"
end
end
end
end) |
||
| end | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
matmuladd.jlshould be part ofcode.jl, alongside all other codegen aspects.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
code.jlis set up as a module in a file, and it would be better to refactor it as a subpackage and not bloat the file too muchThere was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can't
include("matmuladd.jl")just be moved tocode.jl? The source doesn't need to be inlined.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done