-
Notifications
You must be signed in to change notification settings - Fork 10.5k
SIL optimizer: Add a new string optimization #33128
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
Conversation
3b336b4
to
6d73e2d
Compare
@swift-ci test |
@swift-ci benchmark |
@ravikandhadai This constant-folding for string interpolation works for the DefaultStringInterpolation. It would be cool if we could also make it work for the OSLog interpolation. Any thoughts on this? |
Performance: -O
Code size: -O
Performance: -Osize
Code size: -Osize
Performance: -Onone
Code size: -swiftlibs
How to read the dataThe tables contain differences in performance which are larger than 8% and differences in code size which are larger than 1%.If you see any unexpected regressions, you should consider fixing the Noise: Sometimes the performance results (not code size!) contain false Hardware Overview
|
Build failed |
Build failed |
6d73e2d
to
06e3265
Compare
@swift-ci test |
1 similar comment
@swift-ci test |
Build failed |
lib/AST/ASTContext.cpp
Outdated
auto *constructor = cast<ConstructorDecl>(initializer); | ||
auto Attrs = constructor->getAttrs(); | ||
for (auto *A : Attrs.getAttributes<SemanticsAttr, false>()) { | ||
if (A->Value != "string.makeUTF8") |
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.
Should this string "string.makeUTF8" be replaced by the macro: semantics::STRING_MAKE_UTF8
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.
yes. I'll change it
Making os_log use _typename would be similar to DefaultStringInterpolation implementation. It is tracked by rdar://65636690. So, I think this should enable constant fold the _typename in that case as well. |
} | ||
|
||
return false; | ||
} |
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 was wondering if there are any dead operands after this optimization, whether they all will be cleaned up by a later dead code elimination.
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 have noticed that String.makeUTF8 init may not get DCE'ed some times. If they aren't getting DCE'ed, there is a InstructionDeleter
utility that can deleted instructions and track their operands, which can later be checked for dead code and eliminated at the end of optimization.
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 should always be cleaned up because it's defined as "readonly". InstructionDeleter is not really required here, because this is done multiple times in following passes.
To be able to constant fold string interpolation, the right semantic attributes must be in place. Also, the interpolation's write function must be inlinable. For the _typeName constant folding, a semantic attribute is required.
…r _typeName constant propagation.
…e runtime function _typeName would do.
Optimizes String operations with constant operands. Specifically: * Replaces x.append(y) with x = y if x is empty. * Removes x.append("") * Replaces x.append(y) with x = x + y if x and y are constant strings. * Replaces _typeName(T.self) with a constant string if T is statically known. With this optimization it's possible to constant fold string interpolations, like "the \(Int.self) type" -> "the Int type" This new pass runs on high-level SIL, where semantic calls are still in place. rdar://problem/65642843
06e3265
to
7f684b6
Compare
@swift-ci test |
@eeckstein Just a quick question. If I understand correctly, this constant folding works for interpolation of metatypes because it is expecting the |
@ravikandhadai Yes, it depends on inlining of appendInterpolation. This works because it's very simple: it's just a string append. Note that _typeName constant propagation is done, regardless if it's in an interpolation. So even with this PR it should create a constant String argument if used in osLog. Not propagating constant osLog string arguments is probably not so bad, because it leaves a "%s" in the format string and passes an additional argument. I think this is not so much overhead. If the argument is used in many places, it can even save some data size. Propagation of constant String (or other) arguments could be done as a post-process, by scanning the format string and the arguments. |
In the case of There is a test suite that checks the combined effect of all the -O optimizations (OSLogFullOptTest.swift). The resulting LLVM IR should be similar to C os_log calls, where there are no closures, no arrays, no
That is right. But like here, in the os_log case also, one can just do
Yes that is right. The format string would be "%s" and there would be a payload that is a pointer (like char *) to the string's (UTF-8 encoded) bytes. But since this optimization reduces it to a string literal like "Int", ideally the payload must just be a pointer to the string literal (at the SIL level just a
Doing a post processing and combining the payload string literal into the format string is an interesting idea. It could save code size and performance. Payloads do create some boilerplate code. However, unfortunately, interpolated expressions can have an associated privacy specifier and formatting options. E.g. But one main problem I see with the post processing is that it the would have to happen somewhere lower in the optimization pipeline (which is where the payload may be found to be a constant), but should also have some special knowledge about os_log, especially on how to extract the format string, how to adjust the argument buffer after lifting a payload into the format string, because it requires tinkering with the headers which store the argument count and summary byte. Ideally, I would like to prevent hard coding that knowledge outside of |
Optimizes String operations with constant operands.
Specifically:
With this optimization it's possible to constant fold string interpolations, like "the (Int.self) type" -> "the Int type"
This new pass runs on high-level SIL, where semantic calls are still in place.
rdar://problem/65642843