-
Notifications
You must be signed in to change notification settings - Fork 10.5k
[region-isolation] Fix join to be a true union operation including the symmetric difference. #69423
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
Merged
gottesmm
merged 6 commits into
swiftlang:main
from
gottesmm:pr-4c7e13d3cbc1677f17c72b86d9a02042e97eded1
Oct 26, 2023
Merged
Changes from all commits
Commits
Show all changes
6 commits
Select commit
Hold shift + click to select a range
e385f92
[region-isolation] Add unittests for SILOptimizer to top level unitte…
gottesmm 4c7e13d
[region-isolation] Fix join to be a true union operation including th…
gottesmm 93e98aa
Fix test I broke by mistake.
gottesmm 7b370b1
Add swiftIRGen to SwiftSILOptimizerTests for windows.
gottesmm 80940a0
Add swiftAST as well.
gottesmm 27db2e6
Add swiftFrontend.
gottesmm File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -225,6 +225,11 @@ static void horizontalUpdate(std::map<Element, Region> &map, Element key, | |
} | ||
|
||
class Partition { | ||
public: | ||
/// A class defined in PartitionUtils unittest used to grab state from | ||
/// Partition without exposing it to other users. | ||
struct PartitionTester; | ||
|
||
private: | ||
// Label each index with a non-negative (unsigned) label if it is associated | ||
// with a valid region, and with -1 if it is associated with a transferred | ||
|
@@ -351,6 +356,21 @@ class Partition { | |
return p; | ||
} | ||
|
||
static Partition separateRegions(ArrayRef<Element> indices) { | ||
Partition p; | ||
if (indices.empty()) | ||
return p; | ||
|
||
Region max_index = | ||
Region(*std::max_element(indices.begin(), indices.end())); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Maybe There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Sure. |
||
p.fresh_label = Region(max_index + 1); | ||
for (Element index : indices) { | ||
p.labels.insert_or_assign(index, Region(index)); | ||
} | ||
assert(p.is_canonical_correct()); | ||
return p; | ||
} | ||
|
||
// linear time - Test two partititons for equality by first putting them | ||
// in canonical form then comparing for exact equality. | ||
static bool equals(Partition &fst, Partition &snd) { | ||
|
@@ -370,30 +390,63 @@ class Partition { | |
// two passed partitions; the join labels each index labelled by both operands | ||
// and two indices are in the same region of the join iff they are in the same | ||
// region in either operand. | ||
static Partition join(Partition &fst, Partition &snd) { | ||
// ensure copies are made | ||
Partition fst_reduced = false; | ||
Partition snd_reduced = false; | ||
|
||
// make canonical copies of fst and snd, reduced to their intersected domain | ||
for (auto [i, _] : fst.labels) | ||
if (snd.labels.count(i)) { | ||
fst_reduced.labels.insert_or_assign(i, fst.labels.at(i)); | ||
snd_reduced.labels.insert_or_assign(i, snd.labels.at(i)); | ||
} | ||
static Partition join(const Partition &fst, const Partition &snd) { | ||
// First copy and canonicalize our inputs. | ||
Partition fst_reduced = fst; | ||
Partition snd_reduced = snd; | ||
|
||
fst_reduced.canonicalize(); | ||
snd_reduced.canonicalize(); | ||
|
||
// merging each index in fst with its label in snd ensures that all pairs | ||
// of indices that are in the same region in snd are also in the same region | ||
// in fst - the desired property | ||
for (const auto [i, snd_label] : snd_reduced.labels) { | ||
if (snd_label.isTransferred()) | ||
// if snd says that the region has been transferred, mark it transferred | ||
// in fst | ||
horizontalUpdate(fst_reduced.labels, i, Region::transferred()); | ||
else | ||
fst_reduced.merge(i, Element(snd_label)); | ||
// For each element in snd_reduced... | ||
for (const auto &[sndEltNumber, sndRegionNumber] : snd_reduced.labels) { | ||
// For values that are both in fst_reduced and snd_reduced, we need to | ||
// merge their regions. | ||
if (fst_reduced.labels.count(sndEltNumber)) { | ||
if (sndRegionNumber.isTransferred()) { | ||
// If snd says that the region has been transferred, mark it | ||
// transferred in fst. | ||
horizontalUpdate(fst_reduced.labels, sndEltNumber, | ||
Region::transferred()); | ||
continue; | ||
} | ||
|
||
// Otherwise merge. This maintains canonicality. | ||
fst_reduced.merge(sndEltNumber, Element(sndRegionNumber)); | ||
continue; | ||
} | ||
|
||
// Otherwise, we have an element in snd that is not in fst. First see if | ||
// our region is transferred. In such a case, just add this element as | ||
// transferred. | ||
if (sndRegionNumber.isTransferred()) { | ||
fst_reduced.labels.insert({sndEltNumber, Region::transferred()}); | ||
continue; | ||
} | ||
|
||
// Then check if the representative element number for this element in snd | ||
// is in fst. In that case, we know that we visited it before we visited | ||
// this elt number (since we are processing in order) so what ever is | ||
// mapped to that number in snd must be the correct number for this | ||
// element as well since this number is guaranteed to be greater than our | ||
// representative and the number mapped to our representative in fst must | ||
// be <= our representative. | ||
auto iter = fst_reduced.labels.find(Element(sndRegionNumber)); | ||
if (iter != fst_reduced.labels.end()) { | ||
fst_reduced.labels.insert({sndEltNumber, iter->second}); | ||
if (fst_reduced.fresh_label < Region(sndEltNumber)) | ||
fst_reduced.fresh_label = Region(sndEltNumber + 1); | ||
continue; | ||
} | ||
|
||
// Otherwise, we have an element that is not in fst and its representative | ||
// is not in fst. This means that we must be our representative in snd | ||
// since we should have visited our representative earlier if we were not | ||
// due to our traversal being in order. Thus just add this to fst_reduced. | ||
assert(sndEltNumber == Element(sndRegionNumber)); | ||
fst_reduced.labels.insert({sndEltNumber, sndRegionNumber}); | ||
if (fst_reduced.fresh_label < sndRegionNumber) | ||
fst_reduced.fresh_label = Region(sndEltNumber + 1); | ||
} | ||
|
||
LLVM_DEBUG(llvm::dbgs() << "JOIN PEFORMED: \nFST: "; | ||
|
@@ -581,6 +634,9 @@ class Partition { | |
} | ||
os << "]\n"; | ||
} | ||
|
||
/// Routine used in unittests | ||
Region getRegion(Element elt) const { return labels.at(elt); } | ||
}; | ||
|
||
} // namespace swift | ||
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
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.
Could this be declared in the test fixture and become a friend struct here instead that way
getRegion
could also be declared in the tester struct itself?