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

Reply via email to