-
Notifications
You must be signed in to change notification settings - Fork 277
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
[NFC] change ModulePortInfo to store in a single array and get rid of redundant APIs. This is preparation for not splitting inputs and outputs. #5680
Conversation
… redundant APIs. This is preparation for not splitting inputs and outputs.
else | ||
inputs.push_back(port); | ||
} | ||
explicit ModulePortInfo(ArrayRef<PortInfo> inputs, |
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 thought part of the reason to switch to ModuleType (name?) which is presumably the shift which this preparing for is to preserve module port ordering amongst inputs/outputs? If so, isn't sorting them here antithetical to that?
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 just a storage format change for the current class, so it is preserving existing behavior. Getting everything going through some iterators is the main point.
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.
If it's to facilitate efficient computation of at_input
, based on a quick skim of these changes, I don't see any uses of at_input
or at_output
.
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.
shit... didn't see your comment. fucking gh.
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 just a storage format change for the current class, so it is preserving existing behavior. Getting everything going through some iterators is the main point.
I'm not noticing any places where inputs or outputs are randomly accessed... all the places you modified work through iterators, afaict.
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.
though preserving existing behavior for the sake of incrementalism is reasonable.
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'm not noticing any places where inputs or outputs are randomly accessed
There are a couple places where things are deleted. Annoying,.
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.
Thanks for taking this on! Moving to a non-ordered list of ports is future work, yes? It could break a bunch of stuff, in particular tests I'd imagine.
@@ -307,7 +307,7 @@ static LogicalResult convertExtMemoryOps(HWModuleOp mod) { | |||
OpBuilder b(mod); | |||
|
|||
auto getMemoryIOInfo = [&](Location loc, Twine portName, unsigned argIdx, | |||
ArrayRef<hw::PortInfo> info, | |||
ArrayRef<hw::PortInfo *> info, |
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.
Why was it necessary to move to a pointer 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.
consequence of ArrayRef from a serquential container's iterators.
lib/Dialect/Calyx/CalyxOps.cpp
Outdated
@@ -1674,8 +1674,8 @@ verifyPrimitiveOpType(PrimitiveOp instance, | |||
<< "'."; | |||
|
|||
// Verify the instance result ports with those of its referenced component. | |||
SmallVector<hw::PortInfo> primitivePorts = referencedPrimitive.getAllPorts(); | |||
size_t numPorts = primitivePorts.size(); | |||
auto primitivePorts = getModulePortInfo(referencedPrimitive); |
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.
nit: plz don't use auto
here.
os << bitWidth.getName().str(); | ||
} else { | ||
unsigned int bitWidth = port.type.getIntOrFloatBitWidth(); | ||
os << bitWidth; | ||
} | ||
|
||
if (i + 1 < e) | ||
if (i + 1 < std::distance(ports.begin(), ports.end())) |
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 seems less efficient. Perhaps calculate e
outside of the loop?
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 just a subtract, and probably is hoisted, but I moved it.
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.
Wouldn't surprise me if the compiler wasn't able to do either optimization and defaulted to iterating through with a counter (which would be necessary if it were a linked list). I don't think smallvector.begin() returns a random_access_iterator...
but whatever.
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.
no, vector's model random_access_iterator whose specialized distance is arithmatic. It's not accidental or guessing that it's a subtration.
@@ -81,8 +81,7 @@ void ESILowerTypesPass::runOnOperation() { | |||
auto isWindowPort = [](hw::PortInfo p) { | |||
return hw::type_isa<WindowType>(p.type); | |||
}; | |||
return !(llvm::any_of(mod.getPorts().inputs, isWindowPort) || | |||
llvm::any_of(mod.getPorts().outputs, isWindowPort)); | |||
return !(llvm::any_of(mod.getPorts(), isWindowPort)); |
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.
Nice! Good demonstration of how this is useful.
for (auto [i, barg] : llvm::enumerate(bodyRegion.getArguments())) { | ||
inputIdx[info.inputs[i].name.str()] = i; | ||
inputIdx[info.at(i).name.str()] = i; |
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 should probably be at_input
to be not so reliant on the internal ordering.
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.
Or even better, switch to using an iterator.
for (auto i : llvm::reverse(argReplacementsIdxs)) | ||
wrapperModPortInfo.inputs.erase(wrapperModPortInfo.inputs.begin() + i); | ||
for (auto i : llvm::reverse(argReplacementsIdxs)) { | ||
wrapperModPortInfo.ports.erase(wrapperModPortInfo.begin_input() + i); |
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 generally bad practice to rely on code outside of a class to make necessary modifications to synchronized internal datastructures.
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.
Indeed. I was trying to avoid having mutation options at all, but a few places were doing things like this.
@@ -54,7 +54,7 @@ StringRef circt::msft::getValueName(Value v, const SymbolCache &syms, | |||
if (auto blockArg = v.dyn_cast<BlockArgument>()) { | |||
auto portInfo = | |||
getModulePortInfo(blockArg.getOwner()->getParent()->getParentOp()); | |||
return portInfo.inputs[blockArg.getArgNumber()].getName(); | |||
return (portInfo.begin_input() + blockArg.getArgNumber())->getName(); |
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, this is another case where at_input
is the more efficient way...
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 didn't exist yet when I wrote that. But it isn't actually anymore efficient, just more concise.
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.
ahh... yeah. I was thinking that if ports allowed mixed order inputs/outputs the input iterator would have to iterate through from the beginning. So this'll be problematic perf in the future. Not relevant for now.
const PortInfo &at_output(size_t idx) const { return ports[idx + numInputs]; } | ||
|
||
/// This contains a list of all ports. Input first. | ||
SmallVector<PortInfo> ports; |
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.
Why are the member variables public? Since they must be kept in sync, it's probably better to keep them private.
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.
there were a few places that were modifying things directly, but I've issolated those.
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'd be supportive of a completely immutable ModulePortInfo and requiring anything doing mutation to have a local mutated list of ports and recreate the ModulePortInfo from that.
No description provided.