[swift-dev] Weird dyn_cast code gen / performance problem
David Zarzycki
dave at znu.io
Mon Jan 1 10:30:31 CST 2018
Hello,
I noticed recently that the code gen of CanType::getClassOrBoundGenericClass() could be better and along the way I found a clang/LLVM bug. Where exactly, I do not know, although my bet is the LLVM optimizer.
When more than one dyn_cast() happens in a row, LLVM/clang emits redundant and pointless nullptr checks. Both Apple clang-900.0.39.2 and clang/llvm top-of-tree generate essentially the same code:
<+35>: movb 0x8(%rbx), %cl ; getKind()
<+38>: testq %rbx, %rbx ; XXX - nullptr check after deref is pointless
<+41>: je 0x1377df6 ; <+54>
<+43>: cmpb $0x12, %cl ; isa<ClassType>()
<+46>: jne 0x1377df6 ; <+54>
<+48>: addq $0x10, %rbx ; (void*)this + offsetof(ClassType, TheDecl)
<+52>: jmp 0x1377e06 ; <+70>
<+54>: xorl %eax, %eax ; the default return value (nullptr)
<+56>: testq %rbx, %rbx ; XXX - another pointless nullptr check?
<+59>: je 0x1377e09 ; <+73>
<+61>: cmpb $0x29, %cl ; isa<BoundGenericClassType>()
<+64>: jne 0x1377e09 ; <+73>
<+66>: addq $0x18, %rbx ; (void*)this + offsetof(BoundGenericClassType, TheDecl)
<+70>: movq (%rbx), %rax ; load the decl pointer
<+73>: popq %rbx
<+74>: retq
I’ve tried adding different “nonnull” spellings in various parts of both Swift and LLVM’s casting machinery, but with no luck. The only thing that seems to work is to create a free function that takes a non-null “const TypeBase *” parameter and then have CanType::getClassOrBoundGenericClass() call that.
FWIW – I *suspect* this is because LLVM’s casting machinery internally converts traditional pointers into C++ references before ultimately calling classof(&Val).
Before I file a bug against clang/llvm, might I be missing something? Can anybody think of a good workaround?
Dave
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-dev/attachments/20180101/33c6fe9f/attachment.html>
More information about the swift-dev
mailing list