This is an archive of the discontinued LLVM Phabricator instance.

[TableGen] Fix bug in TableGen CodeGenPatterns when adding variants of the patterns.
ClosedPublic

Authored by aymanmus on Jun 19 2017, 1:38 AM.

Details

Summary

All patterns reside in a std::vector container, where new variants are added to it using the standard library's emplace_back function.
When calling this with a new element while there is no enough allocated space, a bigger space is allocated and all the old info in the small vector is copied to the newly allocated vector, then the old vector is freed.
The problem is that before doing this "copying", we take a reference of one of the elements in the old vector, and after the "copying" we add it to the new vector.
As the old vector is freed after the copying, the reference now does not point to a valid element.

Added new function to the API of CodeGenDAGPatterns class to return the same information as a copy in order to avoid this issue.

This was revealed in rL305465 that added many patterns and forced the reallocation of the vector which caused crashes in windows bots.

Diff Detail

Repository
rL LLVM

Event Timeline

aymanmus created this revision.Jun 19 2017, 1:38 AM
RKSimon edited edge metadata.Jun 19 2017, 4:16 AM

Any chance of a test case?

aymanmus added a comment.EditedJun 19 2017, 4:29 AM

@RKSimon, when I recommit my patch in D33188 the build will crash on windows without this.

craig.topper edited edge metadata.Jun 19 2017, 10:20 AM

Can we use add a move constructor to PatternToMatch, and use push_back(PatternToMatch(PatternsToMatch[i].getSrcRecord(), ....)? That's the right way to fix this I believe.

The only problematic thing here is that DstRegs was returned as reference, the rest of the class' elements are either pointers or integer types.
I think using a copy constructor instead of only copying the needed element is kind of an overhead, don't you agree?

P.s. from a fast experiment I did, I noticed there is a slight increase in build time in tablegen phase when using copy constructor.

We don't need a new method to copy a vector. The caller can always make a copy into a local variable first.

What we should try to do is avoid inserting an extra copy of the vector. What we should try to do is make the copy occur before the vector is resized not after.

I proposed adding a move constructor not a copy constructor so that calling push_back(PatternToMatch( will move the object into place after creating the object. This way the copy happens before and only moves happen after the vector is resized.

An alternative is to capture the DstRegs in a local variable and std::move it to the emplace_back call. Then we also need to change the signature of the constructor to take the vector by value and then std::move it into the class. This would require an audit and possible changes at all other uses of the constructor.

I think adding the move constructor is probably the simpler option.

This revision is now accepted and ready to land.Jun 26 2017, 11:35 AM
This revision was automatically updated to reflect the committed changes.