[llvm] [llvm][InstCombine] Fold signum(x) into scmp(x, 0) (PR #143445)

Yash Solanki via llvm-commits llvm-commits at lists.llvm.org
Thu Jun 12 02:06:42 PDT 2025


================
@@ -0,0 +1,254 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 5
+; RUN: opt -passes=instcombine -S < %s | FileCheck %s
+
+; Fold (x < y) ? -1 : zext(x != y) to scmp(x, y)
+define i32 @scmp_x_y_from_lt(i32 %x, i32 %y) {
+; CHECK-LABEL: define i32 @scmp_x_y_from_lt(
+; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) {
+; CHECK-NEXT:    [[SEL:%.*]] = call i32 @llvm.scmp.i32.i32(i32 [[X]], i32 [[Y]])
+; CHECK-NEXT:    ret i32 [[SEL]]
+;
+  %cmp1 = icmp ne i32 %x, %y
+  %zext = zext i1 %cmp1 to i32
+  %cmp2 = icmp slt i32 %x, %y
+  %sel = select i1 %cmp2, i32 -1, i32 %zext
+  ret i32 %sel
+}
+
+; Fold (x < y) ? -1 : zext(x > y) to scmp(x, y)
+define i32 @scmp_x_y_from_lt_gt(i32 %x, i32 %y) {
+; CHECK-LABEL: define i32 @scmp_x_y_from_lt_gt(
+; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) {
+; CHECK-NEXT:    [[SEL:%.*]] = call i32 @llvm.scmp.i32.i32(i32 [[X]], i32 [[Y]])
+; CHECK-NEXT:    ret i32 [[SEL]]
+;
+  %cmp1 = icmp sgt i32 %x, %y
+  %zext = zext i1 %cmp1 to i32
+  %cmp2 = icmp slt i32 %x, %y
+  %sel = select i1 %cmp2, i32 -1, i32 %zext
+  ret i32 %sel
+}
+
+; Fold (x > y) ? 1 : sext(x != y) to scmp(x, y)
+define i32 @scmp_x_y_from_gt_sext_ne(i32 %x, i32 %y) {
+; CHECK-LABEL: define i32 @scmp_x_y_from_gt_sext_ne(
+; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) {
+; CHECK-NEXT:    [[SEL:%.*]] = call i32 @llvm.scmp.i32.i32(i32 [[X]], i32 [[Y]])
+; CHECK-NEXT:    ret i32 [[SEL]]
+;
+  %cmp1 = icmp ne i32 %x, %y
+  %sext = sext i1 %cmp1 to i32
+  %cmp2 = icmp sgt i32 %x, %y
+  %sel = select i1 %cmp2, i32 1, i32 %sext
+  ret i32 %sel
+}
+
+; Fold (x > y) ? 1 : sext(x < y) to scmp(x, y)
+define i32 @scmp_x_y_from_gt_sext_lt(i32 %x, i32 %y) {
+; CHECK-LABEL: define i32 @scmp_x_y_from_gt_sext_lt(
+; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) {
+; CHECK-NEXT:    [[SEL:%.*]] = call i32 @llvm.scmp.i32.i32(i32 [[X]], i32 [[Y]])
+; CHECK-NEXT:    ret i32 [[SEL]]
+;
+  %cmp1 = icmp slt i32 %x, %y
+  %sext = sext i1 %cmp1 to i32
+  %cmp2 = icmp sgt i32 %x, %y
+  %sel = select i1 %cmp2, i32 1, i32 %sext
+  ret i32 %sel
+}
+
+; Fold (x <= y - 1) ? -1 : zext(x != y) to ucmp(x, y)
+define i32 @ucmp_x_y_from_le_sub_zext_ne(i32 %x, i32 %y) {
+; CHECK-LABEL: define i32 @ucmp_x_y_from_le_sub_zext_ne(
+; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) {
+; CHECK-NEXT:    [[SEL:%.*]] = call i32 @llvm.ucmp.i32.i32(i32 [[X]], i32 [[Y]])
+; CHECK-NEXT:    ret i32 [[SEL]]
+;
+  %ym1 = sub i32 %y, 1
+  %cmp1 = icmp ule i32 %x, %ym1
+  %neq = icmp ne i32 %x, %y
+  %zext = zext i1 %neq to i32
+  %sel = select i1 %cmp1, i32 -1, i32 %zext
+  ret i32 %sel
+}
+
+; Fold (x <= y - 1) ? -1 : zext(x > y) to ucmp(x, y)
+define i32 @ucmp_x_y_from_le_sub_zext_gt(i32 %x, i32 %y) {
+; CHECK-LABEL: define i32 @ucmp_x_y_from_le_sub_zext_gt(
+; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) {
+; CHECK-NEXT:    [[SEL:%.*]] = call i32 @llvm.ucmp.i32.i32(i32 [[X]], i32 [[Y]])
+; CHECK-NEXT:    ret i32 [[SEL]]
+;
+  %ym1 = sub i32 %y, 1
+  %cmp1 = icmp ule i32 %x, %ym1
+  %gt = icmp ugt i32 %x, %y
+  %zext = zext i1 %gt to i32
+  %sel = select i1 %cmp1, i32 -1, i32 %zext
+  ret i32 %sel
+}
+
+; Fold (x >= y + 1) ? 1 : sext(x != y) to ucmp(x, y)
+define i32 @ucmp_x_y_from_ge_add_sext_ne(i32 %x, i32 %y) {
+; CHECK-LABEL: define i32 @ucmp_x_y_from_ge_add_sext_ne(
+; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) {
+; CHECK-NEXT:    [[SEL:%.*]] = call i32 @llvm.ucmp.i32.i32(i32 [[X]], i32 [[Y]])
+; CHECK-NEXT:    ret i32 [[SEL]]
+;
+  %yp1 = add i32 %y, 1
+  %cmp1 = icmp uge i32 %x, %yp1
+  %neq = icmp ne i32 %x, %y
+  %sext = sext i1 %neq to i32
+  %sel = select i1 %cmp1, i32 1, i32 %sext
+  ret i32 %sel
+}
+
+; Fold (x >= y + 1) ? 1 : sext(x < y) to ucmp(x, y)
+define i32 @ucmp_x_y_from_ge_add_sext_lt(i32 %x, i32 %y) {
+; CHECK-LABEL: define i32 @ucmp_x_y_from_ge_add_sext_lt(
+; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) {
+; CHECK-NEXT:    [[SEL:%.*]] = call i32 @llvm.ucmp.i32.i32(i32 [[X]], i32 [[Y]])
+; CHECK-NEXT:    ret i32 [[SEL]]
+;
+  %yp1 = add i32 %y, 1
+  %cmp1 = icmp uge i32 %x, %yp1
+  %lt = icmp ult i32 %x, %y
+  %sext = sext i1 %lt to i32
+  %sel = select i1 %cmp1, i32 1, i32 %sext
+  ret i32 %sel
+}
+
+; Fold (x > y - 1) ? zext(x != y) : -1 to scmp(x, y)
+define i32 @scmp_x_y_from_gt_sub_zext_ne(i32 %x, i32 %y) {
+; CHECK-LABEL: define i32 @scmp_x_y_from_gt_sub_zext_ne(
+; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) {
+; CHECK-NEXT:    [[SEL:%.*]] = call i32 @llvm.scmp.i32.i32(i32 [[X]], i32 [[Y]])
+; CHECK-NEXT:    ret i32 [[SEL]]
+;
+  %ym1 = sub i32 %y, 1
+  %cmp1 = icmp sgt i32 %x, %ym1
+  %ne = icmp ne i32 %x, %y
+  %zext = zext i1 %ne to i32
+  %sel = select i1 %cmp1, i32 %zext, i32 -1
+  ret i32 %sel
+}
+
+; Fold (x > y - 1) ? zext(x > y) : -1 to ucmp(x, y)
+define i32 @ucmp_x_y_from_gt_sub_zext_gt(i32 %x, i32 %y) {
+; CHECK-LABEL: define i32 @ucmp_x_y_from_gt_sub_zext_gt(
+; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) {
+; CHECK-NEXT:    [[SEL:%.*]] = call i32 @llvm.ucmp.i32.i32(i32 [[X]], i32 [[Y]])
+; CHECK-NEXT:    ret i32 [[SEL]]
+;
+  %ym1 = sub i32 %y, 1
+  %cmp1 = icmp ugt i32 %x, %ym1
+  %gt = icmp ugt i32 %x, %y
+  %zext = zext i1 %gt to i32
+  %sel = select i1 %cmp1, i32 %zext, i32 -1
+  ret i32 %sel
+}
+
+; Fold (x < y + 1) ? sext(x != y) : 1 to scmp(x, y)
+define i32 @scmp_x_y_from_lt_add_sext_ne(i32 %x, i32 %y) {
+; CHECK-LABEL: define i32 @scmp_x_y_from_lt_add_sext_ne(
+; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) {
+; CHECK-NEXT:    [[SEL:%.*]] = call i32 @llvm.scmp.i32.i32(i32 [[X]], i32 [[Y]])
+; CHECK-NEXT:    ret i32 [[SEL]]
+;
+  %yp1 = add i32 %y, 1
+  %cmp1 = icmp slt i32 %x, %yp1
+  %ne = icmp ne i32 %x, %y
+  %sext = sext i1 %ne to i32
+  %sel = select i1 %cmp1, i32 %sext, i32 1
+  ret i32 %sel
+}
+
+; Fold (x < y + 1) ? sext(x < y) : 1 to ucmp(x, y)
+define i32 @ucmp_x_y_from_lt_add_sext_lt(i32 %x, i32 %y) {
----------------
yashnator wrote:

I see. Canonical patterns handle variables, but not constants. I fix this

https://github.com/llvm/llvm-project/pull/143445


More information about the llvm-commits mailing list