[llvm] [InstCombine] Fold abs(X, false) --> abs(X, true) If X != INT_MIN (PR #219527)
via llvm-commits
llvm-commits at lists.llvm.org
Fri Aug 28 10:19:30 PDT 2026
llvmorg-github-actions[bot] wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-llvm-transforms
Author: Tadeusz (tadeuszjt)
<details>
<summary>Changes</summary>
The second argument of the `llvm.abs` intrinsic determines the behaviour when `X == INT_MIN`. If false, `llvm.abs` will return `INT_MIN`. If true, the return would be a poison. Therefore, the flag can be changed to true if it is known that `X != INT_MIN`.
Alive2 proof: https://alive2.llvm.org/ce/z/NorBAu
Closes: #<!-- -->219528
---
Full diff: https://github.com/llvm/llvm-project/pull/219527.diff
2 Files Affected:
- (modified) llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp (+13)
- (modified) llvm/test/Transforms/InstCombine/abs-intrinsic.ll (+25)
``````````diff
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
index 1402c12f2025f..e8a3b9157116c 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
@@ -2216,6 +2216,19 @@ Instruction *InstCombinerImpl::visitCallInst(CallInst &CI) {
{XY, II->getArgOperand(1)});
}
+ // abs(x, false) -> abs(x, true) if x != INT_MIN
+ if (!IntMinIsPoison) {
+ if (auto *IntTy = dyn_cast<IntegerType>(IIOperand->getType())) {
+ unsigned BitWidth = IntTy->getBitWidth();
+ Constant *IntMin =
+ ConstantInt::get(IntTy, APInt::getSignedMinValue(BitWidth));
+
+ if (isKnownNonEqual(IIOperand, IntMin, SQ.getWithInstruction(II)))
+ return CallInst::Create(II->getCalledFunction(),
+ {IIOperand, Builder.getTrue()});
+ }
+ }
+
if (std::optional<bool> Known =
getKnownSignOrZero(IIOperand, SQ.getWithInstruction(II))) {
// abs(x) -> x if x >= 0 (include abs(x-y) --> x - y where x >= y)
diff --git a/llvm/test/Transforms/InstCombine/abs-intrinsic.ll b/llvm/test/Transforms/InstCombine/abs-intrinsic.ll
index f93d0b366ef11..a76f4f0e67406 100644
--- a/llvm/test/Transforms/InstCombine/abs-intrinsic.ll
+++ b/llvm/test/Transforms/InstCombine/abs-intrinsic.ll
@@ -1199,3 +1199,28 @@ define i1 @abs_cmp_ugt_poison_multiuse(i32 %x) {
%cmp = icmp ugt i32 %x.abs, 31
ret i1 %cmp
}
+
+define i8 @abs_no_poison_ne_int_min(i8 %x) {
+; CHECK-LABEL: @abs_no_poison_ne_int_min(
+; CHECK-NEXT: [[CMP:%.*]] = icmp ne i8 [[X:%.*]], -128
+; CHECK-NEXT: call void @llvm.assume(i1 [[CMP]])
+; CHECK-NEXT: [[ABS:%.*]] = call i8 @llvm.abs.i8(i8 [[X]], i1 true)
+; CHECK-NEXT: ret i8 [[ABS]]
+;
+ %cmp = icmp ne i8 %x, -128
+ call void @llvm.assume(i1 %cmp)
+ %abs = call i8 @llvm.abs.i8(i8 %x, i1 false)
+ ret i8 %abs
+}
+
+define i1 @abs_no_poison_ne_int_min_eq_fold(i32 %x) {
+; CHECK-LABEL: @abs_no_poison_ne_int_min_eq_fold(
+; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i32 [[X:%.*]], -1
+; CHECK-NEXT: ret i1 [[CMP]]
+;
+ %x1 = or i32 %x, 1
+ %abs = call i32 @llvm.abs.i32(i32 %x1, i1 false)
+ %cmp = icmp eq i32 %abs, %x1
+ ret i1 %cmp
+}
+
``````````
</details>
https://github.com/llvm/llvm-project/pull/219527
More information about the llvm-commits
mailing list