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
[SR-9440] String should provide a string-switch (multi-compare) #51904
Comments
For example, see https://bugs.swift.org/browse/SR-9426 |
Mind if I take this one? I will probably need a bit of guidance. I looked at the ICMP_EQ builtin, that got me started, but I am not exactly sure what method to use when comparing the strings themselves. Maybe just calling strcmp will be good enough? |
String honors Unicode Canonical Equivalence, so you will need to do the same. If you look at StringComparison.swift, you'll see the underlying methods to call for comparison. The series of `if` checks redundantly introspects the string being switched over, while a multi-compare function could introspect the string once. @eeckstein might be able to help you with the compiler-library interface. We want the function to take many strings to compare against, but don't want to actually allocate an array for the arguments. |
I did briefly look at the implementation in the standard library. Thanks for the overview of the requirements. I will reach out to Erik and work on this a bit more tomorrow. I will post my questions here unless there is a better place. Thanks for the quick response and help. |
We already have this kind of thing for the init(rawValue: String) of string enums. |
Thanks @eeckstein! I will play around with that a bit today and see if I can get something working. |
To clarify the goal, we want something like the following to produce a single block of assembly with no jumps (like what would happen if the arguments of type String were replaced with type Int): func test(a: String, b: String, c: String, d: String) -> Bool {
if a == b {
if b == c {
return c == d
}
return false
}
return false
} In this case, the compiler would have to realize that there was a nested set of if-statments and optimize those out. What would be the best method to do this? I assume it should be done in the SILOptimizer. In the PR you linked, you replace one string comparison function with another, would a function like that suffice, or is more complicated logic required? |
I don't think this is an important code pattern to optimize. It's doable in the optimizer, but it's very specific and there must be a good reason to optimize this kind of pattern. |
I see. So the optimization is inlining all the comparisons, so fewer branches are created? |
This is a slightly different issue but, I find it interesting that the assembly produced by the following program does not change significantly when `input` is switched on instead of `x`: let x = "0"
func test(input: String) -> Int {
switch x {
case "0": return 0
case "1": return 1
case "2": return 2
case "3": return 3
case "4": return 4
case "5": return 5
case "6": return 6
case "7": return 7
case "8": return 8
case "9": return 9
default: return 0
}
} |
Additional Detail from JIRA
md5: 811f73a6f0ff81d39486a5037b657dff
Issue Description:
String should provide an API usable from the compiler and optimizer that takes one string and compares it for equality against a series of other strings, saving code size and improving performance.
This would be a more efficient way of lowering a string switch. Currently, a string switch is lowered into a series of `if str == ...`. Benefits:
1. String equality has a fast-path checking bitwise comparison of the struct itself, but for a `N`-length switch the likelihood of that being hit is `1/N` at best. Inlining that otherwise-good check causes code size bloat.
2. String equality has to introspect each side of the comparison. A series of equality checks re-introspects the same string every time. This has runtime costs.
We might also be able to unify this with the existing code that does it for some String enums.
The text was updated successfully, but these errors were encountered: