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

via llvm-commits llvm-commits at lists.llvm.org
Mon Jun 9 14:46:25 PDT 2025


llvmbot wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-llvm-transforms

Author: Yash Solanki (yashnator)

<details>
<summary>Changes</summary>

Currently:

```cpp
int signum(int x) {
    if (x < 0) return -1;
    if (x > 0) return +1;
    return 0;
}
```

is not identified as `scmp(x,0)`.

This patch adds folding for the edge case: `(x > -1) ? zext(x != 0) : -1`, which is generated for the above signum and is equivalent to `scmp(x, 0)`. For other constants/variables, the fold is already optimised.

[Alive2 proof](https://alive2.llvm.org/ce/z/EYQZwV) (taken from issue)

Resolves #<!-- -->143259

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


2 Files Affected:

- (modified) llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp (+12) 
- (modified) llvm/test/Transforms/InstCombine/scmp.ll (+14) 


``````````diff
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp b/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp
index 8f46ae304353d..ec0cda18a6492 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp
@@ -3603,6 +3603,18 @@ Instruction *InstCombinerImpl::foldSelectToCmp(SelectInst &SI) {
        ICmpInst::getSwappedPredicate(ExtendedCmpPredicate) == Pred))
     Replace = true;
 
+  // Handle the edge case (x > -1) ? zext(x != 0), -1
+  if (IsSigned && ICmpInst::isGT(Pred) && match(FV, m_AllOnes()) &&
+      match(TV, m_ZExt(m_c_ICmp(ExtendedCmpPredicate, m_Specific(LHS),
+                                m_Zero()))) &&
+      (ExtendedCmpPredicate == ICmpInst::ICMP_NE ||
+       ICmpInst::getSwappedPredicate(ExtendedCmpPredicate) == Pred)) {
+    Value *Zero = ConstantInt::get(LHS->getType(), 0);
+    return replaceInstUsesWith(
+        SI,
+        Builder.CreateIntrinsic(SI.getType(), Intrinsic::scmp, {LHS, Zero}));
+  }
+
   // (x == y) ? 0 : (x > y ? 1 : -1)
   CmpPredicate FalseBranchSelectPredicate;
   const APInt *InnerTV, *InnerFV;
diff --git a/llvm/test/Transforms/InstCombine/scmp.ll b/llvm/test/Transforms/InstCombine/scmp.ll
index 2140a59de3fa9..b685ca20998bd 100644
--- a/llvm/test/Transforms/InstCombine/scmp.ll
+++ b/llvm/test/Transforms/InstCombine/scmp.ll
@@ -473,3 +473,17 @@ define i8 @scmp_from_select_eq_and_gt_neg3(i32 %x, i32 %y) {
   %r = select i1 %eq, i8 0, i8 %sel1
   ret i8 %r
 }
+
+; Fold (x > -1) ? zext(x != 0), -1 to scmp(x, 0)
+define i32 @scmp_x_0_from_gt_minus_1(i32 noundef %0) local_unnamed_addr #0 {
+; CHECK-LABEL: define i32 @scmp_x_0_from_gt_minus_1(
+; CHECK-SAME: i32 noundef [[TMP0:%.*]]) local_unnamed_addr {
+; CHECK-NEXT:    [[TMP2:%.*]] = call i32 @llvm.scmp.i32.i32(i32 [[TMP0]], i32 0)
+; CHECK-NEXT:    ret i32 [[TMP2]]
+;
+  %2 = icmp ne i32 %0, 0
+  %3 = zext i1 %2 to i32
+  %4 = icmp sgt i32 %0, -1
+  %5 = select i1 %4, i32 %3, i32 -1
+  ret i32 %5
+}

``````````

</details>


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


More information about the llvm-commits mailing list