llvm-project
1a473478 - [InstCombine] fold (sext(ucmp/scmp(X, Y)) -> ucmp/scmp(X, Y) (#191182)

Commit
29 days ago
[InstCombine] fold (sext(ucmp/scmp(X, Y)) -> ucmp/scmp(X, Y) (#191182) relates: https://github.com/llvm/llvm-project/issues/190538 related PR: https://github.com/llvm/llvm-project/pull/190787 This PR folds (sext(ucmp/scmp(X, Y)) -> ucmp/scmp(X, Y). Since ucmp/scmp return -1, 0, 1, if you see the sequence: ```llvm %_3 = tail call i8 @llvm.ucmp.i8.i64(i64 %a, i64 %b) %_0 = sext i8 %_3 to i64 ``` It's fine to turn this into: ```llvm %_0 = tail call i64 @llvm.ucmp.i64.i64(i64 %a, i64 %b) ``` [Alive Proof](https://alive2.llvm.org/ce/z/VmeKM2) Likewise for scmp: ```llvm %_3 = tail call i8 @llvm.scmp.i8.i64(i64 %a, i64 %b) %_0 = sext i8 %_3 to i64 ``` ```llvm %_0 = tail call i64 @llvm.scmp.i64.i64(i64 %a, i64 %b) ``` [Alive Proof](https://alive2.llvm.org/ce/z/WSm7YS) For ucmp, a simple way to get this is to cmp two rust unsigned integers: ```rust pub fn compare(a: u64, b: u64) -> i64 { a.cmp(&b) as i64 } ``` Which gets this: ```llvm define noundef range(i64 -1, 2) i64 @compare(i64 noundef %a, i64 noundef %b) unnamed_addr { start: %_3 = tail call i8 @llvm.ucmp.i8.i64(i64 %a, i64 %b) %_0 = sext i8 %_3 to i64 ret i64 %_0 } declare range(i8 -1, 2) i8 @llvm.ucmp.i8.i64(i64, i64) ``` For scmp, swapping to i64s will suffice: ```rust pub fn compare(a: i64, b: i64) -> i64 { a.cmp(&b) as i64 } ``` ```llvm define noundef range(i64 -1, 2) i64 @compare(i64 noundef %a, i64 noundef %b) unnamed_addr { start: %_3 = tail call i8 @llvm.scmp.i8.i64(i64 %a, i64 %b) %_0 = sext i8 %_3 to i64 ret i64 %_0 } declare range(i8 -1, 2) i8 @llvm.scmp.i8.i64(i64, i64) ```
Author
Parents
Loading