| | |
|------------------|-----------------|…
|Previous ID | SR-15215 |
|Radar | rdar://problem/83297558 |
|Original Reporter | @karwa |
|Type | Bug |
<details>
<summary>Environment</summary>
Swift version 5.6-dev (LLVM 70b82c8b83f6294, Swift a66435c61f9a895)
Target: x86_64-unknown-linux-gnu
</details>
<details>
<summary>Additional Detail from JIRA</summary>
| | |
|------------------|-----------------|
|Votes | 1 |
|Component/s | Compiler |
|Labels | Bug |
|Assignee | None |
|Priority | Medium |
md5: 8c58205ab47b0a9798dd31351dc797cd
</details>
**Issue Description:**
Consider the following code:
``` java
func test(_ input: HasAnEnum) -> Int {
input.readValue()
}
enum MyEnum {
case one
case four
}
struct HasAnEnum {
var s1: String
var s2: String
var s3: String
var s4: String
var s5: String
var s6: String
var s7: String
var s8: String
var s9: String
var s10: String
var value: MyEnum
func readValue() -> Int {
let x = value
if case .four = x { return 4 }
return -1
}
}
```
In an optimised build, this generates the following assembly ([Godbolt](https://godbolt.org/#g:!((g:!((g:!((h:codeEditor,i:(filename:'1',fontScale:14,fontUsePx:'0',j:1,lang:swift,selection:(endColumn:54,endLineNumber:21,positionColumn:54,positionLineNumber:21,selectionStartColumn:54,selectionStartLineNumber:21,startColumn:54,startLineNumber:21),source:'func+test(_+input:+HasAnEnum)+-%3E+Int+%7B%0A++++input.readValue()%0A%7D%0A%0Aenum+MyEnum+%7B%0A++++case+one%0A++++case+four%0A%7D%0A%0Astruct+HasAnEnum+%7B%0A++++var+s1:+String%0A++++var+s2:+String%0A++++var+s3:+String%0A++++var+s4:+String%0A++++var+s5:+String%0A++++var+s6:+String%0A++++var+s7:+String%0A++++var+s8:+String%0A++++var+s9:+String%0A++++var+s10:+String%0A++++var+value:+MyEnum+//+Try+making+this+an+optional.%0A%0A++++func+readValue()+-%3E+Int+%7B%0A++++++++let+x+%3D+value%0A++++++++if+case+.four+%3D+x+%7B+return+4+%7D%0A++++++++return+-1%0A++++%7D%0A%7D'),l:'5',n:'0',o:'Swift+source+%231',t:'0')),k:48.13751087902524,l:'4',n:'0',o:'',s:0,t:'0'),(g:!((h:compiler,i:(compiler:swiftnightly,filters:(b:'0',binary:'1',commentOnly:'0',demangle:'0',directives:'0',execute:'1',intel:'0',libraryCode:'0',trim:'1'),flagsViewOpen:'1',fontScale:14,fontUsePx:'0',j:1,lang:swift,libs:!(),options:'-O',selection:(endColumn:1,endLineNumber:1,positionColumn:1,positionLineNumber:1,selectionStartColumn:1,selectionStartLineNumber:1,startColumn:1,startLineNumber:1),source:1,tree:'1'),l:'5',n:'0',o:'x86-64+swiftc+nightly+(Swift,+Editor+%231,+Compiler+%231)',t:'0')),k:51.862489120974764,l:'4',n:'0',o:'',s:0,t:'0')),l:'2',n:'0',o:'',t:'0')),version:4)):
output.test(output.HasAnEnum) -> Swift.Int:
movzx eax, byte ptr [rdi + 160]
lea rax, [rax + 4*rax]
add rax, -1
ret
Short, sweet. Just what you'd expect, right?
Now, let's add one character and watch the world go up in flames:
``` java
struct HasAnEnum {
// ...
var value: MyEnum? // <- Make this an optional
}
```
output.test(output.HasAnEnum) -> Swift.Int:
push rbx
sub rsp, 16
add rdi, 160
lea rbx, [rsp + 8]
mov rsi, rbx
call (outlined init with take of output.MyEnum?)
mov rsi, rsp
mov rdi, rbx
call (outlined init with take of output.MyEnum?)
movzx eax, byte ptr [rsp]
mov ecx, eax
and ecx, 1
cmp rax, 2
lea rcx, [rcx + 4*rcx - 1]
mov rax, -1
cmovne rax, rcx
add rsp, 16
pop rbx
ret
Boom. Now we're calling a bunch of runtime functions, and this code suddenly performs much worse while also being much larger.
In my code, this is a major performance issue. It dominates almost everything else we do... just to load a stored optional enum.
<img src="https://aws1.discourse-cdn.com/swift/optimized/3X/e/e/ee356c95c45fde95ced9957c4f5f79854cdb9d86_2_690x159.png" width="690" height="159" />
(This trace is from a function which writes a normalized URL string using scanned ranges from an input string. As you can see, the only thing more expensive than this is parsing/writing the path string, which has to simplify arbitrarily long and complex paths and percent-encode them. That's how expensive it is).
In fact, \>8% of the time spent writing the URL string is the load of this one optional. Wild.
<img src="https://aws1.discourse-cdn.com/swift/original/3X/c/1/c1c0abdabc5b6a4d493a7f69d263b62bc430380d.png" width="616" height="229" />