[llvm] [InstCombine] Propagate nsw in (sub (and Op1, (neg X)), Op1) --> neg (and Op1, (add X, -1)) (PR #149366)
via llvm-commits
llvm-commits at lists.llvm.org
Thu Jul 17 10:45:23 PDT 2025
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-llvm-transforms
Author: AZero13 (AZero13)
<details>
<summary>Changes</summary>
https://alive2.llvm.org/ce/z/xSs-jy
---
Full diff: https://github.com/llvm/llvm-project/pull/149366.diff
2 Files Affected:
- (modified) llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp (+19-4)
- (modified) llvm/test/Transforms/InstCombine/hoist-negation-out-of-bias-calculation.ll (+39)
``````````diff
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp b/llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp
index 981c5271fb3f6..afc11a4cfbabf 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp
@@ -2588,10 +2588,25 @@ Instruction *InstCombinerImpl::visitSub(BinaryOperator &I) {
{
// (sub (and Op1, (neg X)), Op1) --> neg (and Op1, (add X, -1))
Value *X;
- if (match(Op0, m_OneUse(m_c_And(m_Specific(Op1),
- m_OneUse(m_Neg(m_Value(X))))))) {
- return BinaryOperator::CreateNeg(Builder.CreateAnd(
- Op1, Builder.CreateAdd(X, Constant::getAllOnesValue(I.getType()))));
+ BinaryOperator *NegInst;
+ if (match(Op0,
+ m_OneUse(m_c_And(m_Specific(Op1), m_OneUse(m_BinOp(NegInst))))) &&
+ match(NegInst, m_Neg(m_Value(X)))) {
+
+ // If neg X is nsw, then X - 1 must be too
+ bool AddHasNSW = NegInst->hasNoSignedWrap();
+
+ // If the original sub is nsw, then the final neg must be too
+ bool NegHasNSW = I.hasNoSignedWrap();
+
+ Value *Add =
+ Builder.CreateAdd(X, Constant::getAllOnesValue(I.getType()), "",
+ /*HasNUW=*/false, /*HasNSW=*/AddHasNSW);
+ Value *And = Builder.CreateAnd(Op1, Add);
+
+ // Use CreateNSWNeg or CreateNeg based on the flag
+ return NegHasNSW ? BinaryOperator::CreateNSWNeg(And)
+ : BinaryOperator::CreateNeg(And);
}
}
diff --git a/llvm/test/Transforms/InstCombine/hoist-negation-out-of-bias-calculation.ll b/llvm/test/Transforms/InstCombine/hoist-negation-out-of-bias-calculation.ll
index d4aa8b5dbf505..455fb1a292050 100644
--- a/llvm/test/Transforms/InstCombine/hoist-negation-out-of-bias-calculation.ll
+++ b/llvm/test/Transforms/InstCombine/hoist-negation-out-of-bias-calculation.ll
@@ -25,6 +25,45 @@ define i8 @t0(i8 %x, i8 %y) {
ret i8 %negbias
}
+define i8 @t0_nsw(i8 %x, i8 %y) {
+; CHECK-LABEL: @t0_nsw(
+; CHECK-NEXT: [[TMP1:%.*]] = add nsw i8 [[Y:%.*]], -1
+; CHECK-NEXT: [[TMP2:%.*]] = and i8 [[X:%.*]], [[TMP1]]
+; CHECK-NEXT: [[NEGBIAS:%.*]] = sub i8 0, [[TMP2]]
+; CHECK-NEXT: ret i8 [[NEGBIAS]]
+;
+ %negy = sub nsw i8 0, %y
+ %unbiasedx = and i8 %negy, %x
+ %negbias = sub i8 %unbiasedx, %x
+ ret i8 %negbias
+}
+
+define i8 @t0_nsw_2(i8 %x, i8 %y) {
+; CHECK-LABEL: @t0_nsw_2(
+; CHECK-NEXT: [[TMP1:%.*]] = add i8 [[Y:%.*]], -1
+; CHECK-NEXT: [[TMP2:%.*]] = and i8 [[X:%.*]], [[TMP1]]
+; CHECK-NEXT: [[NEGBIAS:%.*]] = sub nsw i8 0, [[TMP2]]
+; CHECK-NEXT: ret i8 [[NEGBIAS]]
+;
+ %negy = sub i8 0, %y
+ %unbiasedx = and i8 %negy, %x
+ %negbias = sub nsw i8 %unbiasedx, %x
+ ret i8 %negbias
+}
+
+define i8 @t0_nsw_3(i8 %x, i8 %y) {
+; CHECK-LABEL: @t0_nsw_3(
+; CHECK-NEXT: [[TMP1:%.*]] = add nsw i8 [[Y:%.*]], -1
+; CHECK-NEXT: [[TMP2:%.*]] = and i8 [[X:%.*]], [[TMP1]]
+; CHECK-NEXT: [[NEGBIAS:%.*]] = sub nsw i8 0, [[TMP2]]
+; CHECK-NEXT: ret i8 [[NEGBIAS]]
+;
+ %negy = sub nsw i8 0, %y
+ %unbiasedx = and i8 %negy, %x
+ %negbias = sub nsw i8 %unbiasedx, %x
+ ret i8 %negbias
+}
+
declare i8 @gen8()
define i8 @t1_commutative(i8 %y) {
``````````
</details>
https://github.com/llvm/llvm-project/pull/149366
More information about the llvm-commits
mailing list