-
Notifications
You must be signed in to change notification settings - Fork 83
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
dialects: (csl) builtin math lib for DSDs #2686
Conversation
Codecov ReportAll modified and coverable lines are covered by tests ✅
Additional details and impacted files@@ Coverage Diff @@
## main #2686 +/- ##
==========================================
+ Coverage 89.70% 89.74% +0.04%
==========================================
Files 366 367 +1
Lines 47071 47285 +214
Branches 7140 7191 +51
==========================================
+ Hits 42223 42437 +214
Misses 3745 3745
Partials 1103 1103 ☔ View full report in Codecov by Sentry. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I am still not sure about implementing a class for every version of each
builtin. I agree that this is the simpler solution to initially implement, I
feel like it will be harder to maintain and a bit more difficult to transform.
I think it should be possible to roll any number of builtins into the same
class. The two ideas I had yesterday were to:
- Provide the suffixes as part of the signature and a public function for the
printer to call, performing a match and returning the associated suffix. This
method would be quite easy to implement, but it adds printer specific
functionality to the dialect, which is undesirable. - Derive the suffix from the signature(s). There appears to be some sort of a
system for naming these builtins, however, some functions are
indistinguishable by signature alone, as they use untyped DSDs. - (This is the 3rd of the two ideas). Disregard concerns in 1st paragraph and
implement each builtin as its own class 🤷
xdsl/dialects/csl.py
Outdated
def verify_(self) -> None: | ||
def typcheck( | ||
op_typ: Attribute, | ||
sig_typ: AttrConstraint | Attribute | type[Attribute] | TypeVar, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I am not sure we need AttrConstraint
here, since we don't really use them anywhere else in the dialect (not directly any way). If you do think we should keep it, maybe consider using attr_constr_coercion
from irdl
, to convert everything to an AttrConstraint
then using the verify
method.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's the type signature copied over from operand_def
xdsl/dialects/csl.py
Outdated
@@ -883,6 +892,50 @@ def verify_(self) -> None: | |||
raise VerifyException(f"{self.name} can only operate on mem1d_dsd type") | |||
|
|||
|
|||
FunctionSignatures = list[ | |||
tuple[AttrConstraint | Attribute | type[Attribute] | TypeVar, ...] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ditto for use of AttrConstraint
.
I agree, but regrettably haven't really gotten to that part yet. Happy to include it in this PR if you like.
This may not really work with the current design, since the signature is based off of the var args, and we can't pass the precision as an operand. However, what we could do is pass the precision as an operand. Then in the
This would be really really good - however, I do see practical problems. For instance, if we get
Yes, I suppose it's between this and option 1. |
So I guess to summarise previous discussion:
I would favour having one op per function name emitted in the resulting CSL, except if there's a good reason not to. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
xdsl/dialects/csl.py
Outdated
case BuiltinOpPrecisionKind.mixed: | ||
return [] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is a way of saying "I support no mixed-precision modes", right?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yes
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It will cause it to fail the verification performed by the superclass
This is one reason... I wasn't proposing one single op to rule them all. But maybe all additions together, all |
@n-io i really appreciate you adding all the possible DSD operations, but we will realistically never use 90% of these... I don't think I've ever used a clz in regular code, let alone CSL 😅 |
Easy to do, but dito for control tasks 😂 |
If we want one op per function name emitted, that's done quickly and I'm happy to do it. It may actually not be a bad approach going forward, I suppose. We had a similar discussion regarding tasks, where in the end we decided to combine all types of tasks into one parameterised class. I'm happy either way, to be honest. One op to rule them all might actually make op rewriting rather complicated, also making it generally a lot harder to easily access common functionalities that xdsl provides us with. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, lgtm
xdsl/dialects/csl.py
Outdated
def verify_(self) -> None: | ||
def typcheck( | ||
op_typ: Attribute, | ||
sig_typ: AttrConstraint | Attribute | type[Attribute] | TypeVar, | ||
) -> bool: | ||
if isinstance(sig_typ, type): | ||
return isinstance(op_typ, sig_typ) | ||
else: | ||
return op_typ == sig_typ | ||
|
||
for sig in self.SIGNATURES: | ||
if len(self.ops) == len(sig): | ||
if all(typcheck(op.type, sig_t) for (op, sig_t) in zip(self.ops, sig)): | ||
return | ||
raise VerifyException("Cannot find matching type signature") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you add a unit test for this (just in python, not filecheck). I think this would increase confidence here
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Added a python test as suggested.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's 👍 from me as well, except the AttrConstraint
thing in the type checking function
It was the full union definition used by |
DSD builtin operations typically come with a variety of overloads. This PR proposes a base class handling ops and verification. The subclasses correspond to CSL builtin ops. Their implementation only needs to specify op name and the valid function signatures. The goal is to keep everything really simple.