[Formal][PropertyAnnotation] Annotating IOG-based invariants#855
[Formal][PropertyAnnotation] Annotating IOG-based invariants#855Basmet0 wants to merge 7 commits intoEPFL-LAP:mainfrom
Conversation
| void step() { | ||
| if (partials.empty()) | ||
| return; | ||
| auto checkpoint = partials.back(); |
There was a problem hiding this comment.
Maybe std::move is more efficient
auto checkpoint = std::move(partials.back());
partials.pop_back();
| llvm::DenseSet<mlir::Value> illegals; | ||
| // Is the partial IOG still following the rules? Note that DONE does not | ||
| // actually mean done, as the `unhandled` stack should also be empty. | ||
| enum PROGRESS { ILLEGAL, PARTIAL, DONE }; |
There was a problem hiding this comment.
enum Status {...}
// Is the partial IOG still following the rules? Note that DONE does not
// actually mean done, as theunhandledstack should also be empty.
I still don't get the difference between DONE and ACTUALLY_DONE?
| } | ||
| }; | ||
|
|
||
| struct IOGFinderCheckpoint { |
There was a problem hiding this comment.
Why not do something like
struct IOGCandidate {
Operation *entry;
std::vector<Operation *> units;
std::vector<Value> channels;
DenseSet<Value> illegalChannels;
// What you called "unhandled."
std::vector<Value> bfsQueue;
IOG getIOG() const {
return IOG{this->units, this->channels, this->entry};
}
};
| illegals.insert(channel); | ||
| } | ||
|
|
||
| Operation *getNextOp() { |
There was a problem hiding this comment.
std::optional<Operation *> ...
| // Handle the `endOp` if it has not yet been inserted into the IOG | ||
| if (!partial.contains(endOp)) { | ||
| return endOp; | ||
| } |
There was a problem hiding this comment.
I think this candidate class should be constructed from an endOp (so partial already contains the endOp to begin with
| // To fully handle a channel, both the operation before and after have to be | ||
| // handled | ||
| Operation *before = channel.getDefiningOp(); | ||
| if (before && !partial.contains(before)) { | ||
| partial.units.insert(before); | ||
| return before; | ||
| } |
There was a problem hiding this comment.
It looks quite messy that both getNextOp and step are taking care of both sides of a channel. Is it possible that we only handle the value owner here?
| enum PROGRESS { ILLEGAL, PARTIAL, DONE }; | ||
| PROGRESS progress = PARTIAL; | ||
| Operation *endOp; | ||
| std::vector<mlir::Value> entries; |
There was a problem hiding this comment.
this can be a const reference to avoid copying it everytime we create a new one
also can be unordered (DenseMap) so we can check if(entries.count(...))
| // This function takes a checkpoint and a list of channels. For each channel | ||
| // c, it pushes the IOG where *only* channel c is taken, and all the rest are | ||
| // illegal. Used for forks (which only allow exactly one of its outputs) and | ||
| // join operations (which only allow exactly one of its inputs) | ||
| template <typename T> | ||
| void followSingle(const IOGFinderCheckpoint &checkpoint, T options) { | ||
| for (mlir::Value channel : options) { | ||
| IOGFinderCheckpoint goHere = checkpoint; | ||
| goHere.follow(channel); | ||
| for (mlir::Value other : options) { | ||
| if (channel == other) | ||
| continue; | ||
| goHere.makeIllegal(other); | ||
| } | ||
| partials.push_back(goHere); | ||
| } | ||
| } |
There was a problem hiding this comment.
there is a thing called static method that returns a new instance of ..
… active fork in between
…t the first slot) edge case: As the MC is not part of the IOG, tokens "hidden" within MC are not accounted for
No description provided.