-
Notifications
You must be signed in to change notification settings - Fork 444
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
Support for [lsb+:width] slices #4917
Conversation
4a72192
to
422673f
Compare
7ad797d
to
b7579c6
Compare
623c388
to
1149526
Compare
f07c9d6
to
bdba4e7
Compare
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.
Looks good to me!
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. I have only reviewed the new test program, but it is very cool to see that it exercises the ability of p4c to unroll a loop, and use the loop variable in a bit slice. Nice!
- allows for non-const lsb slices (width must still be const) Signed-off-by: Chris Dodd <cdodd@nvidia.com>
bool save = lhs; | ||
lhs = false; // slices on the LHS also read the data | ||
visit(expression->e0); | ||
visit(expression->e1); // this might not be a constant (for a PlusSlice) | ||
LOG3("FU Returned from " << expression); | ||
auto storage = getReads(expression->e0, true); | ||
reads(expression, storage); // true even in LHS |
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.
@ChrisDodd Shouldn't expression
also read expression->e1
if expression
is a IR::PlusSlice
? Something like this:
bool save = lhs;
lhs = false; // slices on the LHS also read the data
visit(expression->e0);
auto storage = getReads(expression->e0, true);
if (expression->is<IR::PlusSlice>()) {
visit(expression->e1); // this might not be a constant (for a PlusSlice)
auto idxStorage = getReads(expression->e1);
reads(expression, storage->join(idxStorage));
} else {
reads(expression, storage); // true even in LHS
}
LOG3("FU Returned from " << expression);
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.
Also, unrelated to this PR, but do you know why expression
reads expression->e0
? I'm not sure I understand how, in a slice assignment such as x[hi:lo] = rhs;
, x[hi:lo]
"reads" x
.
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 is not entirely clear to me exactly how this pass works and what it expects for its invariants, but I based this (ie, just setting reads(expression... from expression->e0 and not ->e1) on what is done in the ArrayIndex code a few lines after this. In particular no compound expression ever calls storage->join to create a union of its children.
Overall, a lot of things in this pass seem confusingly misnamed. reads
is just setting an element in an Expression* -> LocationSet map which generally just maps some expressions to the locations they read, but not all. So an expression like a[b]
the PathExpressions will be in the map, and the arrayIndex will just refer to a, not b. Whereas for a+b
, again the PathExpressions will be in the map, but the Add will not. The main (only?) purpose of this map is to print warnings in FindUninitialized::registerUses about potentially uninitialized things.
That gets into why (lvalue) slices "read" the storage location they are writing to -- the slice only writes part of the location, so previous writes are still "live". It seems likely this may cause spurious warnings though (if you have a variable that you write to with multiple slices that cover the whole thing, but you never write to it as a whole, you will probably get a warning about a subsequent read of the whole thing).
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 is not entirely clear to me exactly how this pass works and what it expects for its invariants, but I based this (ie, just setting reads(expression... from expression->e0 and not ->e1) on what is done in the ArrayIndex code a few lines after this. In particular no compound expression ever calls storage->join to create a union of its children.
I noticed the ArrayIndex
code too, and it also looks suspicious to me, although I don't know what the consequences are of not handling this case like I would expect it to be handled.
Initial support for Verilog-style
[lsb+:width]
slices, allowing variable index slices with a constant width.Most backends will probably require that these be strength-reduced to constant (normal) indexes, which will happen with eg. unrolled loops where the index depends on the loop index.