From ce31a4fbec0ab21134898a799fcaa97247545709 Mon Sep 17 00:00:00 2001 From: ttomsa Date: Tue, 10 Feb 2026 17:22:21 +0000 Subject: [PATCH] move NOOPs to pre_isel_matcher and rm NOOP from spec --- tinygrad/renderer/isa/x86.py | 37 ++++++++++++++++++------------------ tinygrad/uop/spec.py | 8 ++------ 2 files changed, 21 insertions(+), 24 deletions(-) diff --git a/tinygrad/renderer/isa/x86.py b/tinygrad/renderer/isa/x86.py index 1d78c5e905..d14028e72e 100644 --- a/tinygrad/renderer/isa/x86.py +++ b/tinygrad/renderer/isa/x86.py @@ -16,17 +16,8 @@ extra_matcher = PatternMatcher([ (UPat.var('x', dtypes.bool).alu(Ops.CMPEQ, UPat.var('y')), lambda x,y: (x^y)^True), (UPat.var('x', dtypes.bool) !(y==x) (UPat(Ops.CMPNE, src=(UPat.var("y", dtypes.ints), UPat.var("x")), name="cmp"), lambda y,x,cmp: UOp(Ops.CMPEQ, cmp.dtype, (y,x))^True if y.dtype.count > 1 else None), - # noop of a noop is removed - (UPat(Ops.NOOP, src=(UPat(Ops.NOOP),), name="x"), lambda x: x.replace(src=x.src[0].src)), - # cast to < scalar int is a noop - (UPat.var("y", dtypes.ints).cast(dtypes.ints, name="x"), - lambda y,x: x.replace(op=Ops.NOOP) if x.dtype.itemsize < y.dtype.itemsize and y.dtype.count == 1 else None), # float where expects a mask TODO: handle float64 cmp to float32 where (UPat.var("m", dtypes.bool).where(UPat.var("a", dtypes.floats), UPat.var("b")), lambda m,a,b: m.cast(a.dtype).ne(0).where(a, b) if m.src[0].dtype not in dtypes.floats else None), # TODO: do we want this? Kinda not needed if DEVECTORIZE=0. If yes make it general (UPat(Ops.VECTORIZE, dtypes.float16, name="x"), lambda x: x.replace(dtype=dtypes.float32.vec(x.dtype.count), src=tuple(s.src[0] for s in x.src)).cast(x.dtype) if all(s.op is Ops.CAST for s in x.src) else None), - # moving elements of a single register to another without shuffling is a noop - (UPat(Ops.VECTORIZE, src=(UPat.var("y"),), allow_any_len=True, name="x"), - lambda y,x: UOp(Ops.NOOP, x.dtype, y.src) if all(s.op is Ops.GEP and s.src == y.src and s.arg[0] == i for i,s in enumerate(x.src)) else None), ]) # ***** X86 pre instruction selection ***** # these must be done in a separate matcher because they violate the spec pre_isel_matcher = PatternMatcher([ + # cast from pointer is a noop + (UPat.var("y").cast(name="x"), lambda y,x: x.replace(op=Ops.NOOP) if isinstance(y.dtype, PtrDType) else None), + # zero extending scalar 32bit int is a noop + (UPat.var("y", dtypes.uint32).cast(dtypes.int64s, name="x"), lambda y,x: x.replace(op=Ops.NOOP) if y.dtype.count == 1 else None), + # cast between signed and unsigned int is a noop + (UPat.var("y", dtypes.ints+(dtypes.bool,)).cast(dtypes.ints, name="x"), + lambda y,x: x.replace(op=Ops.NOOP) if x.dtype.itemsize == y.dtype.itemsize else None), + # cast to < scalar int is a noop + (UPat.var("y", dtypes.ints).cast(dtypes.ints, name="x"), + lambda y,x: x.replace(op=Ops.NOOP) if x.dtype.itemsize < y.dtype.itemsize and y.dtype.count == 1 else None), + # bitcasts between scalar floats and ints are real, rest are noops + (UPat.var("y").bitcast().named("x"), lambda y,x: None if y.dtype in dtypes.floats and x.dtype in dtypes.ints or \ + y.dtype in dtypes.ints and x.dtype in dtypes.floats else x.replace(op=Ops.NOOP)), + # noop of a noop is removed + (UPat(Ops.NOOP, src=(UPat(Ops.NOOP),), name="x"), lambda x: x.replace(src=x.src[0].src)), + # moving elements of a single register to another without shuffling is a noop + (UPat(Ops.VECTORIZE, src=(UPat.var("y"),), allow_any_len=True, name="x"), + lambda y,x: UOp(Ops.NOOP, x.dtype, y.src) if all(s.op is Ops.GEP and s.src == y.src and s.arg[0] == i for i,s in enumerate(x.src)) else None), # gated index becomes a conditional move on the index, the load/store are unconditional (UPat.var("base").index(UPat.var("idx"), UPat.var("gate")).load(UPat.var("alt"), name="x"), lambda base,idx,gate,alt,x: gate.where(base.index(idx, ptr=True), (l:=UOp(Ops.DEFINE_LOCAL, base.dtype.base.ptr(x.dtype.count), arg=0)).after(l.store(alt)) diff --git a/tinygrad/uop/spec.py b/tinygrad/uop/spec.py index 3785da3ce7..9f091c69e3 100644 --- a/tinygrad/uop/spec.py +++ b/tinygrad/uop/spec.py @@ -14,11 +14,10 @@ def validate_index(buf:UOp, idx:UOp, gate:UOp|None=None): if 0<=idx.vmin and idx.vmax