Skip to content

Commit 725c6b1

Browse files
committed
Add matrix constant evaluation via decomposition to vector ops
Decomposes MatTimesVec and VecTimesMat into vector operations when the matrix structure is known (CompositeConstruct with 2/3/4 columns). MatTimesVec becomes a sum of scaled columns (VecTimesScalar + VecFAdd). VecTimesMat becomes per-column dot products. These vector operations already have constant folding, enabling compile-time evaluation. Matrix-to-matrix operations (MatTimesMat, Transpose, MatTimesScalar) decompose indirectly through existing associativity rules that reduce to MatTimesVec/VecTimesMat when consumed by vector operations.
1 parent ec2a149 commit 725c6b1

1 file changed

Lines changed: 58 additions & 0 deletions

File tree

rust/spirv-tools-opt/src/rules/matrix.egg

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -142,6 +142,64 @@
142142

143143
; For now, these would require an Identity constructor
144144

145+
; =============================================================================
146+
; Matrix Constant Evaluation via Decomposition
147+
; =============================================================================
148+
; Break matrix-to-vector operations into vector ops when the matrix structure
149+
; is known (CompositeConstruct with known columns). The resulting vector
150+
; operations (VecTimesScalar, Dot, VecFAdd) already have constant folding.
151+
;
152+
; Note: MatTimesMat, Transpose, and MatTimesScalar produce matrix results
153+
; which would require creating CompositeConstruct values in rule conclusions.
154+
; Since CompositeConstruct is a function (not constructor), this is not
155+
; directly possible. Instead, matrix-matrix operations decompose indirectly
156+
; through existing associativity rules:
157+
; (A * B) * v = A * (B * v) [then MatTimesVec decomposes]
158+
; v * (A * B) = (v * A) * B [then VecTimesMat decomposes]
159+
160+
; --- MatTimesVec: result = sum of scaled columns ---
161+
; M * v where M = [c0, c1, ...] gives sum(ci * v[i])
162+
163+
; 2-column matrix * vector
164+
(rule ((= e (MatTimesVec m v))
165+
(= m (CompositeConstruct (ECons c0 (ECons c1 (ENil))))))
166+
((union e (VecFAdd (VecTimesScalar c0 (VecExtract v 0))
167+
(VecTimesScalar c1 (VecExtract v 1))))))
168+
169+
; 3-column matrix * vector
170+
(rule ((= e (MatTimesVec m v))
171+
(= m (CompositeConstruct (ECons c0 (ECons c1 (ECons c2 (ENil)))))))
172+
((union e (VecFAdd (VecFAdd (VecTimesScalar c0 (VecExtract v 0))
173+
(VecTimesScalar c1 (VecExtract v 1)))
174+
(VecTimesScalar c2 (VecExtract v 2))))))
175+
176+
; 4-column matrix * vector
177+
(rule ((= e (MatTimesVec m v))
178+
(= m (CompositeConstruct (ECons c0 (ECons c1 (ECons c2 (ECons c3 (ENil))))))))
179+
((union e (VecFAdd (VecFAdd (VecTimesScalar c0 (VecExtract v 0))
180+
(VecTimesScalar c1 (VecExtract v 1)))
181+
(VecFAdd (VecTimesScalar c2 (VecExtract v 2))
182+
(VecTimesScalar c3 (VecExtract v 3)))))))
183+
184+
; --- VecTimesMat: result[i] = dot(v, column_i) ---
185+
186+
; vector * 2-column matrix
187+
(rule ((= e (VecTimesMat v m))
188+
(= m (CompositeConstruct (ECons c0 (ECons c1 (ENil))))))
189+
((union e (Vec2 (FloatToExpr (Dot v c0)) (FloatToExpr (Dot v c1))))))
190+
191+
; vector * 3-column matrix
192+
(rule ((= e (VecTimesMat v m))
193+
(= m (CompositeConstruct (ECons c0 (ECons c1 (ECons c2 (ENil)))))))
194+
((union e (Vec3 (FloatToExpr (Dot v c0)) (FloatToExpr (Dot v c1))
195+
(FloatToExpr (Dot v c2))))))
196+
197+
; vector * 4-column matrix
198+
(rule ((= e (VecTimesMat v m))
199+
(= m (CompositeConstruct (ECons c0 (ECons c1 (ECons c2 (ECons c3 (ENil))))))))
200+
((union e (Vec4 (FloatToExpr (Dot v c0)) (FloatToExpr (Dot v c1))
201+
(FloatToExpr (Dot v c2)) (FloatToExpr (Dot v c3))))))
202+
145203
; =============================================================================
146204
; Matrix Loop Invariant Rules - ONE-DIRECTIONAL
147205
; =============================================================================

0 commit comments

Comments
 (0)