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 49866 - Optimize C++ spaceship comparison
Summary: Optimize C++ spaceship comparison
Status: RESOLVED FIXED
Alias: None
Product: libraries
Classification: Unclassified
Component: Scalar Optimizations (show other bugs)
Version: trunk
Hardware: PC Linux
: P enhancement
Assignee: Sanjay Patel
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2021-04-06 12:22 PDT by Marc Glisse
Modified: 2021-04-12 13:40 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 Marc Glisse 2021-04-06 12:22:55 PDT
Similar to gcc's https://gcc.gnu.org/bugzilla/show_bug.cgi?id=94589 , it would be nice to optimize (x<=>y)@0 to x@y for all comparisons @, and clang/llvm seems to manage for some but not all.

#include <compare>
int n(int x){return (x<=>0)<0;}

Debian clang version 13.0.0-++20210129063721+010b176cdefb-1~exp1
x86_64-pc-linux-gnu

	movl	%edi, %eax
	shrl	$24, %eax
	testl	%edi, %edi
	setne	%cl
	testb	%al, %al
	sets	%al
	andb	%cl, %al
	movzbl	%al, %eax
	retq
Comment 1 Roman Lebedev 2021-04-06 12:24:38 PDT
Can you please post relevant standalone snippets here, as links to godbolt?
Comment 2 David Bolvansky 2021-04-06 12:53:01 PDT
#include <compare>

bool test1(int x, int y){return (x<=>y)<0;}

bool test2(int x){return (x<=>1)<0;}

bool test3(int x){return (x<=>0)>0;}

bool test4(int x){return (x<=>0)<0;}


define dso_local zeroext i1 @_Z5test1ii(i32 %0, i32 %1) local_unnamed_addr #0 {
  %3 = icmp slt i32 %0, %1
  ret i1 %3
}

define dso_local zeroext i1 @_Z5test2i(i32 %0) local_unnamed_addr #0 {
  %2 = icmp slt i32 %0, 1
  ret i1 %2
}

define dso_local zeroext i1 @_Z5test3i(i32 %0) local_unnamed_addr #0 {
  %2 = icmp sgt i32 %0, 0
  ret i1 %2
}

define dso_local zeroext i1 @_Z5test4i(i32 %0) local_unnamed_addr #0 {
  %2 = lshr i32 %0, 24
  %3 = trunc i32 %2 to i8
  %4 = icmp ne i32 %0, 0
  %5 = icmp slt i8 %3, 0
  %6 = and i1 %4, %5
  ret i1 %6
}



https://godbolt.org/z/n78v1dahz
Comment 3 David Bolvansky 2021-04-06 12:54:37 PDT
----------------------------------------
define i1 @src(i32 %0) {
%1:
  %2 = icmp slt i32 %0, 0
  %3 = select i1 %2, i8 255, i8 1
  %4 = icmp eq i32 %0, 0
  %5 = select i1 %4, i8 0, i8 %3
  %6 = icmp slt i8 %5, 0
  ret i1 %6
}
=>
define i1 @tgt(i32 %0) {
%1:
  %2 = icmp slt i32 %0, 0
  ret i1 %2
}
Transformation seems to be correct!

https://alive2.llvm.org/ce/z/jAqWw4


We somehow miss this transformation for SLT, 
https://godbolt.org/z/8KrnKj1sh
for SGT it works now:
https://godbolt.org/z/PaKbY48Pv
Comment 4 Sanjay Patel 2021-04-12 10:30:27 PDT
Looks like we're just missing a basic icmp fold for a truncated value:
https://alive2.llvm.org/ce/z/6vQvrP

I'll post a patch.
Comment 5 Sanjay Patel 2021-04-12 13:40:56 PDT
This should get the example in the description:
https://reviews.llvm.org/rG5354a213a0e3

If there are other examples, please reopen or file more bugs. Thanks!