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
_______________________________________________
swift-dev mailing list
swift-dev@swift.org
https://lists.swift.org/mailman/listinfo/swift-dev