I’m looking at the output of memcmp() expansion (D34904), and I noticed that there are many ways to produce the common positive/zero/negative comparison result in IR.
For the following 6 functionally equivalent C source functions, we produce 6 different versions of IR which leads to 6 different asm outputs for x86. Which of these should we choose as canonical IR form?
- Two selects
int zero_negone_one(int x, int y) {
if (x == y) return 0;
if (x < y) return -1;
return 1;
}
define i32 @zero_negone_one(i32, i32) {
%3 = icmp eq i32 %0, %1
%4 = icmp slt i32 %0, %1
%5 = select i1 %4, i32 -1, i32 1
%6 = select i1 %3, i32 0, i32 %5
ret i32 %6
}
- Two selects, but different
int zero_one_negone(int x, int y) {
if (x == y) return 0;
if (x > y) return 1;
return -1;
}
define i32 @zero_one_negone(i32, i32) {
%3 = icmp eq i32 %0, %1
%4 = icmp sgt i32 %0, %1
%5 = select i1 %4, i32 1, i32 -1
%6 = select i1 %3, i32 0, i32 %5
ret i32 %6
}
- Select and zext
int negone_one_zero(int x, int y) {
if (x < y) return -1;
if (x > y) return 1;
return 0;
}
define i32 @negone_one_zero(i32, i32) {
%3 = icmp slt i32 %0, %1
%4 = icmp sgt i32 %0, %1
%5 = zext i1 %4 to i32
%6 = select i1 %3, i32 -1, i32 %5
ret i32 %6
}
- Select and sext
int negone_zero_one(int x, int y) {
int sel = x < y ? -1 : 0;
if (x > y) return 1;
return sel;
}
define i32 @negone_zero_one(i32, i32) {
%3 = icmp sgt i32 %0, %1
%4 = icmp slt i32 %0, %1
%5 = sext i1 %4 to i32
%6 = select i1 %3, i32 1, i32 %5
ret i32 %6
}
- Subs and shifts
int neg101_sub_shifty(int x, int y) {
int r = (x - y) >> 31;
r += (unsigned)(y - x) >> 31;
return r;
}
define i32 @neg101_sub_shifty(i32, i32) {
%3 = sub nsw i32 %0, %1
%4 = ashr i32 %3, 31
%5 = sub nsw i32 %1, %0
%6 = lshr i32 %5, 31
%7 = add nsw i32 %4, %6
ret i32 %7
}
- Zexts and sub
int neg101_cmp_sub(int x, int y) {
return (x>y) - (x<y);
}
define i32 @neg101_cmp_sub(i32, i32) {
%3 = icmp sgt i32 %0, %1
%4 = zext i1 %3 to i32
%5 = icmp slt i32 %0, %1
%6 = zext i1 %5 to i32
%7 = sub nsw i32 %4, %6
ret i32 %7
}
Show these are logically equivalent:
http://rise4fun.com/Alive/b4D
Recent patch related to this pattern:
https://reviews.llvm.org/D34278