[llvm] [InstCombine] Canonicalize `(X +/- Y) & Y` into `~X & Y` when Y is a power of 2 (PR #67915)
via llvm-commits
llvm-commits at lists.llvm.org
Sun Oct 1 07:01:50 PDT 2023
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-llvm-transforms
<details>
<summary>Changes</summary>
This patch canonicalizes the pattern `(X +/- Y) & Y` into `~X & Y` when `Y` is a power of 2 or zero.
It will reduce the patterns to match in #<!-- -->67836 and exploit more optimization opportunities.
Alive2: https://alive2.llvm.org/ce/z/LBpvRF
---
Full diff: https://github.com/llvm/llvm-project/pull/67915.diff
2 Files Affected:
- (modified) llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp (+8)
- (modified) llvm/test/Transforms/InstCombine/and.ll (+40-4)
``````````diff
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp b/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
index cbdab3e9c5fb91d..4322cc96f5a2b6c 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
@@ -2250,6 +2250,14 @@ Instruction *InstCombinerImpl::visitAnd(BinaryOperator &I) {
return SelectInst::Create(Cmp, ConstantInt::getNullValue(Ty), Y);
}
+ // Canonicalize:
+ // (X +/- Y) & Y --> ~X & Y when Y is a power of 2.
+ if (match(&I, m_c_And(m_Value(Y), m_OneUse(m_CombineOr(
+ m_c_Add(m_Value(X), m_Deferred(Y)),
+ m_Sub(m_Value(X), m_Deferred(Y)))))) &&
+ isKnownToBeAPowerOfTwo(Y, /*OrZero*/ true, /*Depth*/ 0, &I))
+ return BinaryOperator::CreateAnd(Builder.CreateNot(X), Y);
+
const APInt *C;
if (match(Op1, m_APInt(C))) {
const APInt *XorC;
diff --git a/llvm/test/Transforms/InstCombine/and.ll b/llvm/test/Transforms/InstCombine/and.ll
index 90f027010e2aea6..eb39ff9014ff3a4 100644
--- a/llvm/test/Transforms/InstCombine/and.ll
+++ b/llvm/test/Transforms/InstCombine/and.ll
@@ -1595,8 +1595,8 @@ define <2 x i8> @flip_masked_bit_uniform(<2 x i8> %A) {
define <2 x i8> @flip_masked_bit_undef(<2 x i8> %A) {
; CHECK-LABEL: @flip_masked_bit_undef(
-; CHECK-NEXT: [[B:%.*]] = add <2 x i8> [[A:%.*]], <i8 16, i8 undef>
-; CHECK-NEXT: [[C:%.*]] = and <2 x i8> [[B]], <i8 16, i8 undef>
+; CHECK-NEXT: [[TMP1:%.*]] = xor <2 x i8> [[A:%.*]], <i8 -1, i8 -1>
+; CHECK-NEXT: [[C:%.*]] = and <2 x i8> [[TMP1]], <i8 16, i8 undef>
; CHECK-NEXT: ret <2 x i8> [[C]]
;
%B = add <2 x i8> %A, <i8 16, i8 undef>
@@ -1606,8 +1606,8 @@ define <2 x i8> @flip_masked_bit_undef(<2 x i8> %A) {
define <2 x i8> @flip_masked_bit_nonuniform(<2 x i8> %A) {
; CHECK-LABEL: @flip_masked_bit_nonuniform(
-; CHECK-NEXT: [[B:%.*]] = add <2 x i8> [[A:%.*]], <i8 16, i8 4>
-; CHECK-NEXT: [[C:%.*]] = and <2 x i8> [[B]], <i8 16, i8 4>
+; CHECK-NEXT: [[TMP1:%.*]] = xor <2 x i8> [[A:%.*]], <i8 -1, i8 -1>
+; CHECK-NEXT: [[C:%.*]] = and <2 x i8> [[TMP1]], <i8 16, i8 4>
; CHECK-NEXT: ret <2 x i8> [[C]]
;
%B = add <2 x i8> %A, <i8 16, i8 4>
@@ -2546,3 +2546,39 @@ define i32 @and_zext_eq_zero(i32 %A, i32 %C) {
%5 = and i32 %2, %4
ret i32 %5
}
+
+define i32 @canonicalize_and_add_power2_or_zero(i32 %x, i32 %y) {
+; CHECK-LABEL: @canonicalize_and_add_power2_or_zero(
+; CHECK-NEXT: [[NY:%.*]] = sub i32 0, [[Y:%.*]]
+; CHECK-NEXT: [[P2:%.*]] = and i32 [[NY]], [[Y]]
+; CHECK-NEXT: call void @use32(i32 [[P2]])
+; CHECK-NEXT: [[TMP1:%.*]] = xor i32 [[X:%.*]], -1
+; CHECK-NEXT: [[AND:%.*]] = and i32 [[P2]], [[TMP1]]
+; CHECK-NEXT: ret i32 [[AND]]
+;
+ %ny = sub i32 0, %y
+ %p2 = and i32 %y, %ny
+ call void @use32(i32 %p2) ; keep p2
+
+ %val = add i32 %x, %p2
+ %and = and i32 %val, %p2
+ ret i32 %and
+}
+
+define i32 @canonicalize_and_sub_power2_or_zero(i32 %x, i32 %y) {
+; CHECK-LABEL: @canonicalize_and_sub_power2_or_zero(
+; CHECK-NEXT: [[NY:%.*]] = sub i32 0, [[Y:%.*]]
+; CHECK-NEXT: [[P2:%.*]] = and i32 [[NY]], [[Y]]
+; CHECK-NEXT: call void @use32(i32 [[P2]])
+; CHECK-NEXT: [[TMP1:%.*]] = xor i32 [[X:%.*]], -1
+; CHECK-NEXT: [[AND:%.*]] = and i32 [[P2]], [[TMP1]]
+; CHECK-NEXT: ret i32 [[AND]]
+;
+ %ny = sub i32 0, %y
+ %p2 = and i32 %y, %ny
+ call void @use32(i32 %p2) ; keep p2
+
+ %val = sub i32 %x, %p2
+ %and = and i32 %val, %p2
+ ret i32 %and
+}
``````````
</details>
https://github.com/llvm/llvm-project/pull/67915
More information about the llvm-commits
mailing list