Skip to content

Commit 1b9c97e

Browse files
committed
Change handling of reductions to better accomdate their use within the loop body, and don't unroll inner reductions where the unrolled loop is the reduction loop if that reduction is already tiled.
1 parent 9975011 commit 1b9c97e

34 files changed

+254
-134
lines changed

Manifest.toml

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -42,9 +42,9 @@ uuid = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c"
4242

4343
[[SIMDPirates]]
4444
deps = ["VectorizationBase"]
45-
git-tree-sha1 = "1a9cbe1be1f5d43ac49eeb38ca64dd78e50a0cc6"
45+
git-tree-sha1 = "8f89aa38f5e4e89f2a474ffdc850fc21d6ab9ed4"
4646
uuid = "21efa798-c60a-11e8-04d3-e1a92915a26a"
47-
version = "0.7.3"
47+
version = "0.7.4"
4848

4949
[[SLEEFPirates]]
5050
deps = ["Libdl", "SIMDPirates", "VectorizationBase"]
@@ -69,6 +69,6 @@ version = "0.1.0"
6969

7070
[[VectorizationBase]]
7171
deps = ["CpuId", "LinearAlgebra"]
72-
git-tree-sha1 = "83e32d4835fc4f4ecfd43eb59fa7fc00854b3d41"
72+
git-tree-sha1 = "2a83ab02d3fb6ad5de0c6d04103b0ca403d9a7d8"
7373
uuid = "3d5dd08c-fd9d-11e8-17fa-ed2836048c2f"
74-
version = "0.9.4"
74+
version = "0.9.5"

Project.toml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
name = "LoopVectorization"
22
uuid = "bdcacae8-1622-11e9-2a5c-532679323890"
33
authors = ["Chris Elrod <[email protected]>"]
4-
version = "0.6.23"
4+
version = "0.6.24"
55

66
[deps]
77
LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e"
@@ -13,10 +13,10 @@ VectorizationBase = "3d5dd08c-fd9d-11e8-17fa-ed2836048c2f"
1313

1414
[compat]
1515
OffsetArrays = "1"
16-
SIMDPirates = "0.7.3"
16+
SIMDPirates = "0.7.4"
1717
SLEEFPirates = "0.4"
1818
UnPack = "0"
19-
VectorizationBase = "0.9.3"
19+
VectorizationBase = "0.9.5"
2020
julia = "1.1"
2121

2222
[extras]

docs/src/assets/bench_AmulB_v1.svg

Lines changed: 1 addition & 1 deletion
Loading

docs/src/assets/bench_AmulBt_v1.svg

Lines changed: 1 addition & 1 deletion
Loading

docs/src/assets/bench_Amulvb_v1.svg

Lines changed: 1 addition & 1 deletion
Loading

docs/src/assets/bench_AplusAt_v1.svg

Lines changed: 1 addition & 1 deletion
Loading

docs/src/assets/bench_AtmulB_v1.svg

Lines changed: 1 addition & 1 deletion
Loading

docs/src/assets/bench_AtmulBt_v1.svg

Lines changed: 1 addition & 1 deletion
Loading

docs/src/assets/bench_Atmulvb_v1.svg

Lines changed: 1 addition & 1 deletion
Loading

docs/src/assets/bench_aplusBc_v1.svg

Lines changed: 1 addition & 1 deletion
Loading

docs/src/assets/bench_dot3_v1.svg

Lines changed: 1 addition & 1 deletion
Loading

docs/src/assets/bench_dot_v1.svg

Lines changed: 1 addition & 1 deletion
Loading

docs/src/assets/bench_exp_v1.svg

Lines changed: 1 addition & 1 deletion
Loading

docs/src/assets/bench_filter2d_3x3_v1.svg

Lines changed: 1 addition & 1 deletion
Loading

docs/src/assets/bench_filter2d_dynamic_v1.svg

Lines changed: 1 addition & 1 deletion
Loading

docs/src/assets/bench_filter2d_unrolled_v1.svg

Lines changed: 1 addition & 1 deletion
Loading

docs/src/assets/bench_logdettriangle_v1.svg

Lines changed: 1 addition & 1 deletion
Loading

docs/src/assets/bench_random_access_v1.svg

Lines changed: 1 addition & 1 deletion
Loading

docs/src/assets/bench_selfdot_v1.svg

Lines changed: 1 addition & 1 deletion
Loading

docs/src/assets/bench_sse_v1.svg

Lines changed: 1 addition & 1 deletion
Loading

src/add_compute.jl

Lines changed: 28 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ function setdiffv!(s4::AbstractVector{T}, s3::AbstractVector{T}, s1::AbstractVec
3333
end
3434
end
3535
function update_deps!(deps::Vector{Symbol}, reduceddeps::Vector{Symbol}, parent::Operation)
36-
mergesetv!(deps, loopdependencies(parent))#, reduceddependencies(parent))
36+
mergesetv!(deps, loopdependencies(parent))#, reduceddependencies(parent))
3737
if !(isload(parent) || isconstant(parent)) && !isreductcombineinstr(parent)
3838
mergesetv!(reduceddeps, reduceddependencies(parent))
3939
end
@@ -101,6 +101,18 @@ function isreductzero(op::Operation, ls::LoopSet, reduct_zero::Symbol)
101101
false
102102
end
103103

104+
# function substitute_op_in_parents!(vparents::Vector{Operation}, replacer::Operation, replacee::Operation)
105+
# for i ∈ eachindex(vparents)
106+
# opp = vparents[i]
107+
# if opp === replacee
108+
# vparents[i] = replacer
109+
# else
110+
# substitute_op_in_parents!(parents(opp), replacer, replacee)
111+
# end
112+
# end
113+
# end
114+
115+
104116
function add_reduction_update_parent!(
105117
vparents::Vector{Operation}, deps::Vector{Symbol}, reduceddeps::Vector{Symbol}, ls::LoopSet,
106118
parent::Operation, instr::Symbol, directdependency::Bool, elementbytes::Int
@@ -109,11 +121,14 @@ function add_reduction_update_parent!(
109121
isouterreduction = parent.instruction === LOOPCONSTANT
110122
Instr = instruction(ls, instr)
111123
instrclass = reduction_instruction_class(Instr) # key allows for faster lookups
124+
reduct_zero = reduction_zero(instrclass)
112125
# if parent is not an outer reduction...
113-
if !isouterreduction
114-
# and parent is not a reduction_zero
115-
reduct_zero = reduction_zero(instrclass)
126+
# if !isouterreduction && !isreductzero(parent, ls, reduct_zero)
127+
add_reduct_instruct = !isouterreduction && !isconstant(parent)
128+
if add_reduct_instruct
129+
# We add
116130
reductcombine = reduction_scalar_combine(instrclass)
131+
# reductcombine = :identity
117132
reductsym = gensym(:reduction)
118133
reductinit = add_constant!(ls, gensym(:reductzero), loopdependencies(parent), reductsym, elementbytes, :numericconstant)
119134
if reduct_zero === :zero
@@ -128,13 +143,13 @@ function add_reduction_update_parent!(
128143
end
129144
pushpreamble!(ls, op, name, reductinit)
130145
end
131-
if isreductzero(parent, ls, reduct_zero)
132-
reductcombine = reduction_combine_to(instrclass)
133-
end
146+
# if
147+
# reductcombine = reduction_combine_to(instrclass)
148+
# end
134149
else
135150
reductinit = parent
136151
reductsym = var
137-
reductcombine = Symbol("")
152+
reductcombine = :identity#Symbol("")
138153
end
139154
combineddeps = copy(deps); mergesetv!(combineddeps, reduceddeps)
140155
# directdependency && pushparent!(vparents, deps, reduceddeps, reductinit)#parent) # deps and reduced deps will not be disjoint
@@ -145,16 +160,20 @@ function add_reduction_update_parent!(
145160
else
146161
push!(vparents, reductinit)
147162
end
163+
# elseif !isouterreduction
164+
# substitute_op_in_parents!(vparents, reductinit, parent)
148165
end
149166
update_reduction_status!(vparents, reduceddeps, name(reductinit))
150167
# this is the op added by add_compute
151168
op = Operation(length(operations(ls)), reductsym, elementbytes, instr, compute, deps, reduceddeps, vparents)
152169
parent.instruction === LOOPCONSTANT && push!(ls.outer_reductions, identifier(op))
153170
opout = pushop!(ls, op, var) # note this overwrites the entry in the operations dict, but not the vector
154171
# isouterreduction || iszero(length(reduceddeps)) && return opout
172+
# return opout
155173
isouterreduction && return opout
156174
# create child op, which is the reduction combination
157-
childrdeps = Symbol[]; childparents = Operation[ op, parent ]
175+
childrdeps = Symbol[]; childparents = Operation[ op ]#, parent ]
176+
add_reduct_instruct && push!(childparents, parent)
158177
childdeps = loopdependencies(reductinit)
159178
setdiffv!(childrdeps, loopdependencies(op), childdeps)
160179
child = Operation(

src/costs.jl

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -198,9 +198,9 @@ const COST = Dict{Instruction,InstructionCost}(
198198
Instruction(:adjoint) => InstructionCost(0,0.0,0.0,0),
199199
Instruction(:transpose) => InstructionCost(0,0.0,0.0,0),
200200
Instruction(:prefetch) => InstructionCost(0,0.0,0.0,0),
201+
Instruction(:prefetch0) => InstructionCost(0,0.0,0.0,0),
201202
Instruction(:prefetch1) => InstructionCost(0,0.0,0.0,0),
202-
Instruction(:prefetch2) => InstructionCost(0,0.0,0.0,0),
203-
Instruction(:prefetch3) => InstructionCost(0,0.0,0.0,0)
203+
Instruction(:prefetch2) => InstructionCost(0,0.0,0.0,0)
204204
)
205205
@inline prefetch0(x, i) = SIMDPirates.prefetch(gep(stridedpointer(x), (extract_data(i) - 1,)), Val{3}(), Val{0}())
206206
@inline prefetch0(x, i, j) = SIMDPirates.prefetch(gep(stridedpointer(x), (extract_data(i) - 1, extract_data(j) - 1)), Val{3}(), Val{0}())
@@ -274,7 +274,7 @@ reduction_instruction_class(instr::Symbol) = get(REDUCTION_CLASS, instr, NaN)
274274
reduction_instruction_class(instr::Instruction) = reduction_instruction_class(instr.instr)
275275
function reduction_to_single_vector(x::Float64)
276276
# x == 1.0 ? :evadd : x == 2.0 ? :evmul : x == 3.0 ? :vor : x == 4.0 ? :vand : x == 5.0 ? :max : x == 6.0 ? :min : throw("Reduction not found.")
277-
x == 1.0 ? :evadd : x == 2.0 ? :evmul : x == 5.0 ? :max : x == 6.0 ? :min : throw("Reduction not found.")
277+
x == ADDITIVE_IN_REDUCTIONS ? :evadd : x == MULTIPLICATIVE_IN_REDUCTIONS ? :evmul : x == MAX ? :max : x == MIN ? :min : throw("Reduction not found.")
278278
end
279279
reduction_to_single_vector(x) = reduction_to_single_vector(reduction_instruction_class(x))
280280
# function reduction_to_scalar(x::Float64)
@@ -284,17 +284,17 @@ reduction_to_single_vector(x) = reduction_to_single_vector(reduction_instruction
284284
# reduction_to_scalar(x) = reduction_to_scalar(reduction_instruction_class(x))
285285
function reduction_scalar_combine(x::Float64)
286286
# x == 1.0 ? :reduced_add : x == 2.0 ? :reduced_prod : x == 3.0 ? :reduced_any : x == 4.0 ? :reduced_all : x == 5.0 ? :reduced_max : x == 6.0 ? :reduced_min : throw("Reduction not found.")
287-
x == 1.0 ? :reduced_add : x == 2.0 ? :reduced_prod : x == 5.0 ? :reduced_max : x == 6.0 ? :reduced_min : throw("Reduction not found.")
287+
x == ADDITIVE_IN_REDUCTIONS ? :reduced_add : x == MULTIPLICATIVE_IN_REDUCTIONS ? :reduced_prod : x == MAX ? :reduced_max : x == MIN ? :reduced_min : throw("Reduction not found.")
288288
end
289289
reduction_scalar_combine(x) = reduction_scalar_combine(reduction_instruction_class(x))
290290
function reduction_combine_to(x::Float64)
291291
# x == 1.0 ? :reduce_to_add : x == 2.0 ? :reduce_to_prod : x == 3.0 ? :reduce_to_any : x == 4.0 ? :reduce_to_all : x == 5.0 ? :reduce_to_max : x == 6.0 ? :reduce_to_min : throw("Reduction not found.")
292-
x == 1.0 ? :reduce_to_add : x == 2.0 ? :reduce_to_prod : x == 5.0 ? :reduce_to_max : x == 6.0 ? :reduce_to_min : throw("Reduction not found.")
292+
x == ADDITIVE_IN_REDUCTIONS ? :reduce_to_add : x == MULTIPLICATIVE_IN_REDUCTIONS ? :reduce_to_prod : x == MAX ? :reduce_to_max : x == MIN ? :reduce_to_min : throw("Reduction not found.")
293293
end
294294
reduction_combine_to(x) = reduction_combine_to(reduction_instruction_class(x))
295295
function reduction_zero(x::Float64)
296296
# x == 1.0 ? :zero : x == 2.0 ? :one : x == 3.0 ? :false : x == 4.0 ? :true : x == 5.0 ? :typemin : x == 6.0 ? :typemax : throw("Reduction not found.")
297-
x == 1.0 ? :zero : x == 2.0 ? :one : x == 5.0 ? :typemin : x == 6.0 ? :typemax : throw("Reduction not found.")
297+
x == ADDITIVE_IN_REDUCTIONS ? :zero : x == MULTIPLICATIVE_IN_REDUCTIONS ? :one : x == MAX ? :typemin : x == MIN ? :typemax : throw("Reduction not found.")
298298
end
299299
reduction_zero(x) = reduction_zero(reduction_instruction_class(x))
300300

src/determinestrategy.jl

Lines changed: 17 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -50,18 +50,18 @@ function register_pressure(op::Operation)
5050
end
5151
end
5252
function cost(ls::LoopSet, op::Operation, vectorized::Symbol, Wshift::Int, size_T::Int = op.elementbytes)
53-
isconstant(op) && return 0.0, 0, Int(length(loopdependencies(op)) > 0)
54-
isloopvalue(op) && return 0.0, 0, 0
53+
isconstant(op) && return 0.0, 0, Float64(length(loopdependencies(op)) > 0)
54+
isloopvalue(op) && return 0.0, 0, 0.0
5555
# Wshift == dependson(op, vectorized) ? Wshift : 0
5656
# c = first(cost(instruction(op), Wshift, size_T))::Int
5757
instr = Instruction(:LoopVectorization, instruction(op).instr)
5858
# instr = instruction(op)
5959
if length(parents(op)) == 1
6060
if instr == Instruction(:-) || instr === Instruction(:vsub) || instr == Instruction(:+) || instr == Instruction(:vadd)
61-
return 0.0, 0, 0
61+
return 0.0, 0, 0.0
6262
end
6363
elseif iscompute(op) && all(opp -> (isloopvalue(opp) | isconstant(opp)), parents(op))
64-
return 0.0, 0, 0
64+
return 0.0, 0, 0.0
6565
end
6666
opisvectorized = dependson(op, vectorized)
6767
srt, sl, srp = opisvectorized ? vector_cost(instr, Wshift, size_T) : scalar_cost(instr)
@@ -80,7 +80,7 @@ function cost(ls::LoopSet, op::Operation, vectorized::Symbol, Wshift::Int, size_
8080
sl *= 3
8181
end
8282
end
83-
srt, sl, srp
83+
srt, sl, Float64(srp)
8484
end
8585

8686
# Base._return_type()
@@ -336,7 +336,7 @@ function maybedemotesize(U::Int, N::Int)
336336
um1rep > urep ? U : Um1
337337
end
338338
function maybedemotesize(T::Int, N::Int, U::Int, Uloop::Loop, maxTbase::Int)
339-
T > 1 || return T
339+
T > 1 || return 1
340340
T == N && return T
341341
T = maybedemotesize(T, N)
342342
if !(isstaticloop(Uloop) && length(Uloop) == U)
@@ -451,11 +451,11 @@ function convolution_cost_factor(ls::LoopSet, op::Operation, u1::Symbol, u2::Sym
451451
if isstaticloop(loop) && length(loop) 4
452452
itersym = loop.itersymbol
453453
if itersym !== u1 && itersym !== u2
454-
return (0.25, 1.0)
454+
return (0.25, VectorizationBase.REGISTER_COUNT == 32 ? 2.0 : 1.0)
455455
end
456456
end
457457
end
458-
(0.25, 0.5)
458+
(0.25, VectorizationBase.REGISTER_COUNT == 32 ? 1.2 : 1.0)
459459
else
460460
(1.0, 1.0)
461461
end
@@ -529,7 +529,7 @@ function evaluate_cost_tile(
529529
factor1, factor2 = convolution_cost_factor(ls, op, unrolled, tiled, vectorized)
530530
rt *= factor1; rp *= factor2;
531531
end
532-
# @show op rt, lat, rp
532+
# @show isunrolled, istiled, op rt, lat, rp
533533
rp = opisininnerloop ? rp : 0 # we only care about register pressure within the inner most loop
534534
rt *= iters[id]
535535
if isunrolled && istiled # no cost decrease; cost must be repeated
@@ -546,6 +546,7 @@ function evaluate_cost_tile(
546546
reg_pressure[4] += rp
547547
end
548548
end
549+
# @show reg_pressure
549550
costpenalty = (sum(reg_pressure) > VectorizationBase.REGISTER_COUNT) ? 2 : 1
550551
# @show order, vectorized cost_vec reg_pressure
551552
# @show solve_tilesize(ls, unrolled, tiled, cost_vec, reg_pressure)
@@ -665,12 +666,15 @@ function choose_order(ls::LoopSet)
665666
end
666667
end
667668

668-
function register_pressure(ls::LoopSet)
669-
order, unroll, vec, U, T = choose_order(ls)
669+
function register_pressure(ls::LoopSet, U, T)
670670
if T == -1
671671
sum(register_pressure, operations(ls))
672672
else
673-
rp = @view ls.reg_pressure[:,1]
674-
tU * tT * rp[1] + tU * rp[2] + rp[3] + rp[4]
673+
rp = @view ls.reg_pres[:,1]
674+
U * T * rp[1] + U * rp[2] + rp[3] + rp[4]
675675
end
676676
end
677+
function register_pressure(ls::LoopSet)
678+
order, unroll, tile, vec, U, T = choose_order(ls)
679+
register_pressure(ls, U, T)
680+
end

src/graphs.jl

Lines changed: 0 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -1,41 +1,4 @@
11

2-
# """
3-
# ShortVector{T} simply wraps a Vector{T}, but uses a different hash function that is faster for short vectors to support using it as the keys of a Dict.
4-
# This hash function scales O(N) with length of the vectors, so it is slow for long vectors.
5-
# """
6-
# struct ShortVector{T} <: DenseVector{T}
7-
# data::Vector{T}
8-
# end
9-
# Base.@propagate_inbounds Base.getindex(x::ShortVector, I...) = x.data[I...]
10-
# Base.@propagate_inbounds Base.setindex!(x::ShortVector, v, I...) = x.data[I...] = v
11-
# ShortVector{T}(::UndefInitializer, N::Integer) where {T} = ShortVector{T}(Vector{T}(undef, N))
12-
# @inbounds Base.length(x::ShortVector) = length(x.data)
13-
# @inbounds Base.size(x::ShortVector) = size(x.data)
14-
# @inbounds Base.strides(x::ShortVector) = strides(x.data)
15-
# @inbounds Base.push!(x::ShortVector, v) = push!(x.data, v)
16-
# @inbounds Base.append!(x::ShortVector, v) = append!(x.data, v)
17-
# function Base.hash(x::ShortVector, h::UInt)
18-
# @inbounds for n ∈ eachindex(x)
19-
# h = hash(x[n], h)
20-
# end
21-
# h
22-
# end
23-
# function Base.isequal(a::ShortVector{T}, b::ShortVector{T}) where {T}
24-
# length(a) == length(b) || return false
25-
# @inbounds for i ∈ 1:length(a)
26-
# a[i] === b[i] || return false
27-
# end
28-
# true
29-
# end
30-
# Base.convert(::Type{Vector}, sv::ShortVector) = sv.data
31-
# Base.convert(::Type{Vector{T}}, sv::ShortVector{T}) where {T} = sv.data
32-
33-
34-
# For passing options like array types and mask
35-
# struct LoopSetOptions
36-
37-
# end
38-
392
struct UnrollSpecification
403
unrolledloopnum::Int
414
tiledloopnum::Int

src/lower_compute.jl

Lines changed: 26 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,10 @@ function lower_compute!(
88
opunrolled = unrolled loopdependencies(op)
99
)
1010

11-
var = op.variable
12-
mvar = mangledvar(op)
11+
var = name(op)
12+
instr = instruction(op)
1313
parents_op = parents(op)
14+
mvar = mangledvar(op)
1415
nparents = length(parents_op)
1516
parentstiled = if suffix === nothing
1617
optiled = false
@@ -25,13 +26,20 @@ function lower_compute!(
2526
optiled = true
2627
[tiled loopdependencies(opp) for opp parents_op]
2728
end
28-
parentsunrolled = [unrolled loopdependencies(opp) || unrolled reducedchildren(opp) for opp parents_op]
29+
parentsunrolled = isunrolled_sym.(parents_op, unrolled, tiled)
30+
if instr.instr === :identity && name(first(parents_op)) === var && isone(length(parents_op))
31+
if (opunrolled == first(parentsunrolled)) && ((!isnothing(suffix)) == first(parentstiled))
32+
return
33+
end
34+
end
35+
unrollsym = isunrolled_sym(op, unrolled, suffix)
2936
if !opunrolled && any(parentsunrolled)
3037
parents_op = copy(parents_op)
3138
for i eachindex(parentsunrolled)
3239
parentsunrolled[i] || continue
3340
parentsunrolled[i] = false
3441
parentop = parents_op[i]
42+
# @show op, parentop
3543
newparentop = Operation(
3644
parentop.identifier, gensym(parentop.variable), parentop.elementbytes, parentop.instruction, parentop.node_type,
3745
parentop.dependencies, parentop.reduced_deps, parentop.parents, parentop.ref, parentop.reduced_children
@@ -43,14 +51,18 @@ function lower_compute!(
4351
parentname = Symbol(parentname, suffix_)
4452
newparentname = Symbol(newparentname, suffix_)
4553
end
46-
for u 0:U-1
47-
push!(q.args, Expr(:(=), Symbol(newparentname, u), Symbol(parentname, u)))
54+
if isconstant(newparentop)
55+
push!(q.args, Expr(:(=), newparentname, Symbol(parentname, 0)))
56+
continue
57+
else
58+
for u 0:U-1
59+
push!(q.args, Expr(:(=), Symbol(newparentname, u), Symbol(parentname, u)))
60+
end
61+
reduce_expr!(q, newparentname, Instruction(reduction_to_single_vector(instruction(newparentop))), U)
62+
push!(q.args, Expr(:(=), newparentname, Symbol(newparentname, 0)))
4863
end
49-
reduce_expr!(q, newparentname, Instruction(reduction_to_single_vector(instruction(newparentop))), U)
50-
push!(q.args, Expr(:(=), newparentname, Symbol(newparentname, 0)))
5164
end
5265
end
53-
instr = op.instruction
5466
# cache unroll and tiling check of parents
5567
# not broadcasted, because we use frequent checks of individual bools
5668
# making BitArrays inefficient.
@@ -84,7 +96,7 @@ function lower_compute!(
8496
# modsuffix = ((u + suffix*U) & 3)
8597
modsuffix = (suffix & 3)
8698
Symbol(mvar, modsuffix)
87-
elseif opunrolled
99+
elseif unrollsym
88100
Symbol(mvar, u)
89101
else
90102
mvar
@@ -125,7 +137,11 @@ function lower_compute!(
125137
continue
126138
end
127139
end
128-
push!(q.args, Expr(:(=), varsym, instrcall))
140+
if instr.instr === :identity && isone(length(parents_op))
141+
push!(q.args, Expr(:(=), varsym, instrcall.args[2]))
142+
else
143+
push!(q.args, Expr(:(=), varsym, instrcall))
144+
end
129145
end
130146
end
131147

0 commit comments

Comments
 (0)