LLVM Bugzilla is read-only and represents the historical archive of all LLVM issues filled before November 26, 2021. Use github to submit LLVM bugs

Bug 40825 - [x86-64] Suboptimal codegen on uint128 negation
Summary: [x86-64] Suboptimal codegen on uint128 negation
Status: RESOLVED FIXED
Alias: None
Product: libraries
Classification: Unclassified
Component: Backend: X86 (show other bugs)
Version: trunk
Hardware: PC All
: P enhancement
Assignee: Unassigned LLVM Bugs
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2019-02-22 11:26 PST by Arthur O'Dwyer
Modified: 2019-07-25 07:25 PDT (History)
6 users (show)

See Also:
Fixed By Commit(s):


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Arthur O'Dwyer 2019-02-22 11:26:06 PST
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.
Comment 1 Simon Pilgrim 2019-07-25 07:25:33 PDT
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