In the provided test case, DAG combiner fails to recognize and combine `(srl
(shl, i8:c0), i64:c1)` even though c0 == c1 in value (but exist as separate
SDNodes because of their different value types). The solution then is to compare
by value rather than node ID.
Note that InstCombine (and thus, opt) fails to combine this as well.
This was discovered with the following bit of C:
C #include <stdint.h> typedef struct { uint32_t low; uint32_t high; } pair; pair cmpxchg8b(uint64_t *m, pair src) { pair rv = {0, 0}; asm volatile("cmpxchg8b %2" : "+a"(rv.low), "+d"(rv.high), "+m"(m) : "b"(src.low), "c"(src.high) : "flags"); return rv; } unsigned f(uint64_t *m, unsigned a, unsigned b) { pair p = {a > 0, b > 0}; pair rv = cmpxchg8b(m, p); return rv.low != 0 && rv.high > 0; }
for which clang generates:
f: pushq %rbx testl %esi, %esi setne %al testl %edx, %edx setne %cl movzbl %al, %ebx movzbl %cl, %ecx movq %rdi, -8(%rsp) xorl %edx, %edx xorl %eax, %eax #APP cmpxchg8b -8(%rsp) #NO_APP testl %eax, %eax setne %al movl %edx, %ecx # <====== testq %rcx, %rcx setne %cl andb %al, %cl movzbl %cl, %eax popq %rbx retq
You can't use getZExtValue on an arbitrary constant; it will crash if the constant is too large.