[llvm] [InstCombine] fold sub (and (add x, pow2), ~pow2), x -> and x, pow2 (PR #230796)

via llvm-commits llvm-commits at lists.llvm.org
Sat Oct 10 07:26:28 PDT 2026


llvmorg-github-actions[bot] wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-llvm-transforms

Author: Andreas Jonson (andjo403)

<details>
<summary>Changes</summary>

regression found in https://github.com/llvm/llvm-project/pull/184182

Proof: https://alive2.llvm.org/ce/z/DXHtNs

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


2 Files Affected:

- (modified) llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp (+4) 
- (modified) llvm/test/Transforms/InstCombine/sub.ll (+78) 


``````````diff
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp b/llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp
index 3ebcbe44c4c3d..53fb2b65122ca 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp
@@ -3103,6 +3103,10 @@ Instruction *InstCombinerImpl::visitSub(BinaryOperator &I) {
       }
     }
   }
+  if (match(Op0, m_And(m_Add(m_Value(X), m_Power2(AddC)), m_APInt(AndC))) &&
+      X == Op1 && *AddC == ~*AndC) {
+    return BinaryOperator::CreateAnd(X, ConstantInt::get(Ty, *AddC));
+  }
 
   return TryToNarrowDeduceFlags();
 }
diff --git a/llvm/test/Transforms/InstCombine/sub.ll b/llvm/test/Transforms/InstCombine/sub.ll
index 1e7fa477c362c..5b254d31abd1d 100644
--- a/llvm/test/Transforms/InstCombine/sub.ll
+++ b/llvm/test/Transforms/InstCombine/sub.ll
@@ -2948,3 +2948,81 @@ define i32 @sub_const_or_no_disjoint(i32 %x) {
   %r = sub i32 100, %a
   ret i32 %r
 }
+
+define i8 @sub_and_add(i8 %x) {
+; CHECK-LABEL: @sub_and_add(
+; CHECK-NEXT:    [[RET:%.*]] = and i8 [[X:%.*]], 1
+; CHECK-NEXT:    ret i8 [[RET]]
+;
+  %add = add i8 %x, 1
+  %and = and i8 %add, -2
+  %ret = sub i8 %and, %x
+  ret i8 %ret
+}
+
+define i8 @sub_and_add_multi_use(i8 %x) {
+; CHECK-LABEL: @sub_and_add_multi_use(
+; CHECK-NEXT:    [[ADD:%.*]] = add i8 [[X:%.*]], 2
+; CHECK-NEXT:    call void @use8(i8 [[ADD]])
+; CHECK-NEXT:    [[AND:%.*]] = and i8 [[ADD]], -3
+; CHECK-NEXT:    call void @use8(i8 [[AND]])
+; CHECK-NEXT:    [[RET:%.*]] = and i8 [[X]], 2
+; CHECK-NEXT:    ret i8 [[RET]]
+;
+  %add = add i8 %x, 2
+  call void @use8(i8 %add)
+  %and = and i8 %add, -3
+  call void @use8(i8 %and)
+  %ret = sub i8 %and, %x
+  ret i8 %ret
+}
+
+define <2 x i8> @sub_and_add_vec(<2 x i8> %x) {
+; CHECK-LABEL: @sub_and_add_vec(
+; CHECK-NEXT:    [[RET:%.*]] = and <2 x i8> [[X:%.*]], splat (i8 1)
+; CHECK-NEXT:    ret <2 x i8> [[RET]]
+;
+  %add = add <2 x i8> %x, <i8 1, i8 1>
+  %and = and <2 x i8> %add, <i8 -2, i8 -2>
+  %ret = sub <2 x i8> %and, %x
+  ret <2 x i8> %ret
+}
+
+define i8 @neg_sub_and_add_commuted(i8 %x) {
+; CHECK-LABEL: @neg_sub_and_add_commuted(
+; CHECK-NEXT:    [[ADD:%.*]] = add i8 [[X:%.*]], 1
+; CHECK-NEXT:    [[AND:%.*]] = and i8 [[ADD]], -2
+; CHECK-NEXT:    [[RET:%.*]] = sub i8 [[X]], [[AND]]
+; CHECK-NEXT:    ret i8 [[RET]]
+;
+  %add = add i8 %x, 1
+  %and = and i8 %add, -2
+  %ret = sub i8 %x, %and
+  ret i8 %ret
+}
+
+define i8 @neg_sub_and_add_2(i8 %x) {
+; CHECK-LABEL: @neg_sub_and_add_2(
+; CHECK-NEXT:    [[ADD:%.*]] = add i8 [[X:%.*]], 3
+; CHECK-NEXT:    [[AND:%.*]] = and i8 [[ADD]], -2
+; CHECK-NEXT:    [[RET:%.*]] = sub i8 [[AND]], [[X]]
+; CHECK-NEXT:    ret i8 [[RET]]
+;
+  %add = add i8 %x, 3
+  %and = and i8 %add, -2
+  %ret = sub i8 %and, %x
+  ret i8 %ret
+}
+
+define i8 @neg_sub_and_-4_add(i8 %x) {
+; CHECK-LABEL: @neg_sub_and_-4_add(
+; CHECK-NEXT:    [[ADD:%.*]] = add i8 [[X:%.*]], 1
+; CHECK-NEXT:    [[AND:%.*]] = and i8 [[ADD]], -4
+; CHECK-NEXT:    [[RET:%.*]] = add i8 [[AND]], [[X]]
+; CHECK-NEXT:    ret i8 [[RET]]
+;
+  %add = add i8 %x, 1
+  %and = and i8 %add, -4
+  %ret = add i8 %and, %x
+  ret i8 %ret
+}

``````````

</details>


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


More information about the llvm-commits mailing list