@@ -54,30 +54,38 @@ function substitute_broadcast(
5454 warncheckarg:: Int ,
5555 safe:: Bool
5656)
57+ # Lower the expression to get the compiler's intermediate representation (IR).
5758 ci = first (Meta. lower (LoopVectorization, q). args). code
5859 nargs = length (ci) - 1
59- lb = Expr (:block )
60+ lb = Expr (:block ) # This will become the `let` block
6061 syms = Vector {Symbol} (undef, nargs)
6162 configarg = (inline, u₁, u₂, v, true , threads, warncheckarg, safe)
6263 unroll_param_tup =
6364 Expr (:call , lv (:avx_config_val ), :(Val {$configarg} ()), staticexpr (0 ))
6465
66+ # Iterate through each instruction from the lowered code.
6567 for n ∈ 1 : nargs
6668 _ciₙ = ci[n]
67- syms[n] = Symbol (' %' , n)
69+ syms[n] = Symbol (' %' , n) # Temporary variable for this instruction's result
6870
69- local rhs
7071 if _ciₙ isa Core. SSAValue
71- rhs = syms[_ciₙ. id]
72+ # Case 1: The instruction is a reference to a previous result.
73+ # Create the assignment expression directly.
74+ push! (lb. args, Expr (:(= ), syms[n], syms[_ciₙ. id]))
7275
7376 elseif _ciₙ isa GlobalRef
77+ # Case 2: The instruction is a global reference.
7478 if _ciₙ. mod === Base || _ciₙ. mod === Core
75- rhs = lv (_ciₙ. name)
79+ # It's a base operator like `+`. Qualify it and create the assignment.
80+ push! (lb. args, Expr (:(= ), syms[n], lv (_ciₙ. name)))
7681 else
77- rhs = _ciₙ. name
82+ # It's a user-defined global (e.g., `a`). Do not qualify it.
83+ push! (lb. args, Expr (:(= ), syms[n], _ciₙ. name))
7884 end
7985
8086 elseif _ciₙ isa Expr && _ciₙ. head === :call
87+ # Case 3: A function call to be transformed (e.g., `materialize`).
88+ # This branch handles its own logic via `add_ci_call!`.
8189 f = first (_ciₙ. args)
8290 if isglobalref (f, Base, :materialize! )
8391 add_ci_call! (lb, lv (:vmaterialize! ), _ciₙ. args, syms, n, unroll_param_tup, mod)
@@ -86,16 +94,21 @@ function substitute_broadcast(
8694 else
8795 add_ci_call! (lb, f, _ciₙ. args, syms, n)
8896 end
89- continue
97+
9098 else
91- rhs = _ciₙ
99+ # Case 4 (Catch-all): A local variable or a literal value.
100+ # Create the assignment directly, leaving the value as is.
101+ push! (lb. args, Expr (:(= ), syms[n], _ciₙ))
92102 end
93- push! (lb. args, Expr (:(= ), syms[n], rhs))
94103 end
104+
105+ # Extract the final return value from the generated `let` block.
95106 ret:: Expr = pop! (lb. args):: Expr
96107 if Meta. isexpr (ret, :(= ), 2 )
97108 ret = (ret. args[2 ]):: Expr
98109 end
110+
111+ # Escape the entire `let` block to ensure hygiene for local variables.
99112 esc (Expr (:let , lb, Expr (:block , ret)))
100113end
101114
0 commit comments