-
Notifications
You must be signed in to change notification settings - Fork 404
[Comb] Integer Overflow Analysis #9130
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
Conversation
uenoku
left a comment
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.
Cool! I think this makes sense. I believe conceptually this is same asnuw in llvm. Can we can borrow the terminology (comb.nuw maybe?) for the consistency?
Not blocking but I even think we should add overflow attribute as part of comb.add/mul/sub etc instead of discardable attributes following Arith/llvm dialect:
https://github.com/llvm/llvm-project/blob/eaedab226cfcf99b92fbfc91b502096a11b45de8/mlir/include/mlir/Dialect/Arith/IR/ArithOps.td#L229-L232
Extending Comb ops can be done later so no blocking at all.
| patterns.add<CombOpAnnotate<comb::AddOp>, CombOpAnnotate<comb::MulOp>>( | ||
| patterns.getContext(), solver); | ||
|
|
||
| if (failed(applyPatternsGreedily(op, std::move(patterns)))) |
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.
Please use WalkPatternRewriteDriver since this is one-shot.
| return rewriter.notifyMatchFailure( | ||
| op, "Only support binary operations with one result"); | ||
|
|
||
| if (!isa<comb::AddOp>(op) && !isa<comb::MulOp>(op) && !isa<comb::SubOp>(op)) |
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.
Probably assertion is ok (maybe static_assert is better) since CombOpTy is a template type.
| if (!isa<comb::AddOp>(op) && !isa<comb::MulOp>(op) && !isa<comb::SubOp>(op)) | |
| assert(isa<comb::AddOp, comb::MulOp, comb::SubOp>(op)); |
|
Thanks for the comments @uenoku - have implemented the non-blocking changes. With regards to making overflow flags part of the operator - I think we need to agree on what the equivalent statement is for comb (from the arith description): Presumably the same is also sort of true - but I guess one would not want your synthesis engine to just optimise away hardware which it thinks is poison? |
uenoku
left a comment
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.
LGTM
| if (isa<comb::MulOp>(op)) | ||
| (void)a.umul_ov(b, overflowed); | ||
|
|
||
| op->setAttr("comb.nuw", BoolAttr::get(op->getContext(), overflowed)); |
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.
Maybe polarity is opposite? Also can we use UnitAttr instead of BoolAttr?
| op->setAttr("comb.nuw", BoolAttr::get(op->getContext(), overflowed)); | |
| if(!overflowed) | |
| op->setAttr("comb.nuw", UnitAttr::get(op->getContext())); |
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.
Apologies - yes my mistake - will update the polarity
I think this is true.
I agree we might not exploit poison to optimize aggregissively like LLVM does, but however every transformation that relies on nuw flag will assume that the operation never overflow, so the transformation will be entirely invalid if the operation actually overflows. From that perspective it's actually valid to consider overflow with nuw flag to be poison and replace them with arbitary value. |
Building on the Integer Range Analysis for the Comb dialect. We now implement an overflow detection to determine when a particular operation truncates a carry-out bit. For example:
This analysis will prove valuable for proving the correctness of downstream transformations to follow in a subsequent PR. The analysis inserts the result as an attribute that can be carried forward through a lowering pass to the datapath dialect, which will decompose basic operations, making them difficult to analyze locally.