Moved discussion from 40486. Sanjay Patel says: Arthur O'Dwyer said: > If you're still looking for work ;) I see improvement, but not perfection, > in Uint128::negate(). Here's an example. > https://godbolt.org/z/BGRoQ4 > xorl %eax, %eax > xorl %ecx, %ecx > subq (%rdi), %rcx > sbbq 8(%rdi), %rax > movq %rcx, (%rdi) > movq %rax, 8(%rdi) > retq > I'm not sure if GCC's codegen is perfect, or if there's a way to use "sbbq" > to save an instruction here somehow. > negq (%rdi) > adcq $0, 8(%rdi) > negq 8(%rdi) > ret Hmmm...those 2 tests are independent of what we've done so far: 1. In the uint128 case, we're not forming the overflow intrinsic in IR (CGP) because that's not a legal type (native type for x86). 2. In the uint64 case, we are forming the overflow intrinsic now (so it's better than before), but the x86 lowering needs to be improved. Since they end up with identical asm, I'm hoping that is a single x86-specific backend fix in lowering X86ISD::SUB to 'neg'. Do you mind filing a new bug report with those examples? It's hard to keep all of these problems organized with the overlap.
This is fixed in trunk, I think from the work on [Bug #40483] trunk / 9.0: wider_tests::Tests<unsigned __int128>::neg(unsigned __int128*): xorl %eax, %eax negq (%rdi) sbbq 8(%rdi), %rax movq %rax, 8(%rdi) retq wider_tests::Tests<Wider<unsigned long> >::neg(Wider<unsigned long>*): xorl %eax, %eax negq (%rdi) sbbq 8(%rdi), %rax movq %rax, 8(%rdi) retq vs 8.0: wider_tests::Tests<unsigned __int128>::neg(unsigned __int128*): xorl %eax, %eax xorl %ecx, %ecx subq (%rdi), %rcx sbbq 8(%rdi), %rax movq %rcx, (%rdi) movq %rax, 8(%rdi) retq wider_tests::Tests<Wider<unsigned long> >::neg(Wider<unsigned long>*): movq (%rdi), %rax testq %rax, %rax setne %cl negq %rax xorl %edx, %edx addb $-1, %cl sbbq 8(%rdi), %rdx movq %rax, (%rdi) movq %rdx, 8(%rdi) retq