llvm / llvm-project

The LLVM Project is a collection of modular and reusable compiler and toolchain technologies.
http://llvm.org
Other
28.21k stars 11.64k forks source link

[X86] Failure to produce LEA from add(trunc(add(x, y)), C) #49269

Open LebedevRI opened 3 years ago

LebedevRI commented 3 years ago
Bugzilla Link 49925
Version trunk
OS Linux
CC @topperc,@RKSimon,@phoebewang,@rotateright

Extended Description

int good(int x, int y) {
    return (x + y) - 31;
}
char bad(int x, int y) {
    return x + y - 31;
}

https://godbolt.org/z/adncTno96

good(int, int): # @good(int, int)
  leal -31(%rdi,%rsi), %eax
  retq
bad(int, int): # @bad(int, int)
  leal (%rdi,%rsi), %eax
  addb $-31, %al
  retq

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

It seems we don't even try to run LEA peephole on that outer i8 add.

LebedevRI commented 3 years ago

I have looked at that a bit more, and it basically boils down to: it's easy to do, but i don't understand how to do that in tablegen.

RKSimon commented 2 years ago

CC @rotateright

Would we be better off just folding add(trunc(add(X,Y)),C) -> trunc(add(add(X,Y),ext(C)))?

define i8 @src(i16 %x, i16 %y) {
%0:
  %add = add i16 %y, %x
  %t = trunc i16 %add to i8
  %conv = add i8 %t, -31
  ret i8 %conv
}
=>
define i8 @tgt(i16 %x, i16 %y) {
%0:
  %add = add i16 %y, %x
  %conv = add i16 %add, -31
  %t = trunc i16 %conv to i8
  ret i8 %t
}
Transformation seems to be correct!
LebedevRI commented 2 years ago

IIRC we'd ideally essentially want to promote everything to i32 on X86? Given that, it may make sense.