From 70bce62c67dcf805c434940b573cdd088f6bc033 Mon Sep 17 00:00:00 2001 From: Sieds Lykles <93992551+S-Lykles@users.noreply.github.com> Date: Wed, 29 Oct 2025 12:17:09 +0100 Subject: [PATCH] dont collapse possibly empty symbolic range (#12994) * dont collapse a symbolic range based on min/max * refactor z3 renderer * include sink explicitely instead of dtypes.void * use dtype.scalar() --- test/unit/test_uop_symbolic.py | 4 ++++ tinygrad/uop/symbolic.py | 3 ++- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/test/unit/test_uop_symbolic.py b/test/unit/test_uop_symbolic.py index cdbbc265f9..9a2fca79c3 100644 --- a/test/unit/test_uop_symbolic.py +++ b/test/unit/test_uop_symbolic.py @@ -769,6 +769,10 @@ class TestSymbolic(unittest.TestCase): self.helper_test_variable(numerator, 3, 390, "(a*((a*4)+-1))") self.helper_test_variable((numerator//denominator)<=0, 1, 1, "True") + def test_symbolic_range_doesnt_collapse(self): + r0 = UOp.range((Variable("a", 1, 10)<5).cast(dtypes.index), 0) + self.helper_test_variable(r0, 0, 0, "r0") + def test_const_reciprocal(self): a = Variable("a", 1, 10, dtypes.float) # TODO: bounds for reciprocal diff --git a/tinygrad/uop/symbolic.py b/tinygrad/uop/symbolic.py index c6405db546..d8ec88566a 100644 --- a/tinygrad/uop/symbolic.py +++ b/tinygrad/uop/symbolic.py @@ -307,7 +307,8 @@ symbolic = symbolic_simple+commutative+PatternMatcher([ ((UPat.var("y")+UPat.var("c").where(UPat.var("t"), UPat.var("f"))) + UPat.var("c").where(UPat.var("tt"), UPat.var("ff")), \ lambda y,c,t,tt,f,ff: y+c.where(t+tt, f+ff) if t.op == tt.op == Ops.CONST or f.op == ff.op == Ops.CONST else None), # ALU/variable min==max -> CONST (slow!) - (UPat(GroupOp.ALU|{Ops.DEFINE_VAR, Ops.SPECIAL, Ops.RANGE}, name="x"), lambda x: x.const_like(x.vmin) if x.vmin == x.vmax else None), + (UPat(GroupOp.ALU|{Ops.DEFINE_VAR, Ops.SPECIAL}, name="x"), lambda x: x.const_like(x.vmin) if x.vmin == x.vmax else None), + (UPat(Ops.RANGE, src=(UPat(Ops.CONST,)), name="x"), lambda x: x.const_like(x.vmin) if x.vmin == x.vmax else None), # max folding (UPat.maximum(UPat.var("x"), UPat.var("y")), lambda x,y: x if x.vmin >= y.vmax else y if x.vmax <= y.vmin else None), # TODO: why does this rule break beautiful_mnist?