Issue |
146087
|
Summary |
Missed optimization when known bits would permit transforming an `and` into subtruction
|
Labels |
new issue
|
Assignees |
|
Reporter |
WaffleLapkin
|
Rust in which we spotted this originally: https://godbolt.org/z/8xM3P9xP5
Take this IR:
```llvm
define noundef i8 @f(i8 noundef %0) unnamed_addr {
; check if two highest bits are set
%2 = lshr i8 %0, 6
%3 = icmp eq i8 %2, 3
br i1 %3, label %4, label %7
4: ; preds = %1
; if so, get the value of the lower 6 bits + 1
%5 = and i8 %0, 63
%6 = add i8 %5, 1
br label %8
7: ; preds = %1
br label %8
8: ; preds = %7, %4
%9 = phi i8 [ %6, %4 ], [ -1, %7 ]
ret i8 %9
}
```
Today `--passes=instcombine` turns it into
```llvm
define noundef i8 @f(i8 noundef %0) unnamed_addr {
%2 = icmp ugt i8 %0, -65
br i1 %2, label %3, label %6
3:
%4 = and i8 %0, 63 ; 😢
%5 = add nuw nsw i8 %4, 1
br label %7
6:
br label %7
7:
%8 = phi i8 [ %5, %3 ], [ -1, %6 ]
ret i8 %8
}
```
However the `and` and `add` could be combined too -- they are used in the branch where `%0 > -65` (two highest bits in `%0` are set), which means that `and i8 %0, 63` (`& 0b111111`) could be replaced with `add i8, %0, -192` (`- 0b11000000`) and then trivially folded with the other `add`. That is, the resulting IR should look like this (https://alive2.llvm.org/ce/z/Go8nxD):
```llvm
define noundef i8 @tgt(i8 noundef %0) unnamed_addr {
%2 = icmp ugt i8 %0, -65
br i1 %2, label %3, label %6
3:
%5 = add nuw nsw i8 %0, -191 ; 🌸
br label %7
6:
br label %7
7:
%8 = phi i8 [ %5, %3 ], [ -1, %6 ]
ret i8 %8
}
```
_______________________________________________
llvm-bugs mailing list
llvm-bugs@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-bugs