This is an archive of the discontinued LLVM Phabricator instance.

[InstCombine] add zeroinitializer handling to memchr folders
Needs ReviewPublic

Authored by msebor on Jun 9 2022, 2:29 PM.

Details

Summary

Due to a limitation of the getConstantStringInfo function the memchr and memrchr folders are unable to fold calls with zeroinitialzer constant arrays. These are rare as global top-level objects but likely more common as members of other aggregates, the handling of which has been proposed in D125114. In anticipation of that enhancement this patch removes the getConstantStringInfo limitation and enables two of its clients, the memchr and memrchr handlers, to fold calls with zeroinitialzer constants. It adds a TODO comment to enhance the third client (memccpy).

The getConstantStringInfo change replaces the TrimAtNull input argument with an in-out ZeroInit argument. This preserves the common default mode of trimming the string at the first null byte while at the same time providing a way for the remaining clients to work with zeroinitializer constants larger than a single byte.

Diff Detail

Event Timeline

msebor created this revision.Jun 9 2022, 2:29 PM
Herald added a project: Restricted Project. · View Herald TranscriptJun 9 2022, 2:29 PM
Herald added a subscriber: hiraditya. · View Herald Transcript
msebor requested review of this revision.Jun 9 2022, 2:29 PM
Herald added a project: Restricted Project. · View Herald TranscriptJun 9 2022, 2:29 PM
msebor edited the summary of this revision. (Show Details)Jun 9 2022, 3:02 PM
nikic added a comment.Jun 15 2022, 7:44 AM

The resulting API here seems pretty unfortunate, because the zeroinitializer case needs to be handled separately from the rest. I also find the fact that passing in ZeroInit changes the interpretation of null bytes somewhat unintuitive.

I think a cleaner alternative would be to accept an additional std::string *Storage = nullptr parameter, which gets populated with the zero-filled string, and can then be handled as a StringRef in the same way as all the other cases.

Neither API is ideal: both require the client to handle the zeroinitializer specially to some extent. The difference is that one approach is optimally efficient at the cost of more code, while the other allows for more uniform handling at the cost of inefficiency (memory allocation and linear traversal over all zeros). Both are trade-offs, and although I don't feel strongly enough to insist on it, in D125114 we discussed a similar concern and agreed to work toward a more efficient solution there in the future. I have a similar preference for this change. If it turns out that the uniform handling is more important than optimal efficiency the API can easily be changed.

Ping: @nikic, do you have any further comments?

I'm still not a fan of this API. You already don't implement the necessary special handling for memccpy, and in the meantime we have gained additional uses of TrimAtNul for memcmp and soon strncmp. All of these will need special code to handle the zeroinitializer case. I don't think the ability to handle unrealistically large [2147483647 x i8] zeroinitializer style constants is important enough to warrant the additional complexity.