Skip to content

Commit

Permalink
[InstCombine] Canonicalize (X +/- Y) & Y into ~X & Y when Y is a …
Browse files Browse the repository at this point in the history
…power of 2 (#67915)

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
  • Loading branch information
dtcxzyw committed Oct 12, 2023
1 parent 2ceabf6 commit 8a7e547
Show file tree
Hide file tree
Showing 2 changed files with 22 additions and 14 deletions.
8 changes: 8 additions & 0 deletions llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
28 changes: 14 additions & 14 deletions llvm/test/Transforms/InstCombine/and.ll
Original file line number Diff line number Diff line change
Expand Up @@ -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>
Expand All @@ -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>
Expand Down Expand Up @@ -2553,8 +2553,8 @@ define i32 @canonicalize_and_add_power2_or_zero(i32 %x, i32 %y) {
; CHECK-NEXT: [[P2:%.*]] = and i32 [[NY]], [[Y]]
; CHECK-NEXT: call void @use32(i32 [[P2]])
; CHECK-NEXT: [[X2:%.*]] = mul i32 [[X:%.*]], [[X]]
; CHECK-NEXT: [[VAL:%.*]] = add i32 [[X2]], [[P2]]
; CHECK-NEXT: [[AND:%.*]] = and i32 [[VAL]], [[P2]]
; CHECK-NEXT: [[TMP1:%.*]] = xor i32 [[X2]], -1
; CHECK-NEXT: [[AND:%.*]] = and i32 [[P2]], [[TMP1]]
; CHECK-NEXT: ret i32 [[AND]]
;
%ny = sub i32 0, %y
Expand All @@ -2572,8 +2572,8 @@ define i32 @canonicalize_and_sub_power2_or_zero(i32 %x, i32 %y) {
; CHECK-NEXT: [[NY:%.*]] = sub i32 0, [[Y:%.*]]
; CHECK-NEXT: [[P2:%.*]] = and i32 [[NY]], [[Y]]
; CHECK-NEXT: call void @use32(i32 [[P2]])
; CHECK-NEXT: [[VAL:%.*]] = sub i32 [[X:%.*]], [[P2]]
; CHECK-NEXT: [[AND:%.*]] = and i32 [[VAL]], [[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
Expand All @@ -2590,8 +2590,8 @@ define i32 @canonicalize_and_add_power2_or_zero_commuted1(i32 %x, i32 %y) {
; CHECK-NEXT: [[NY:%.*]] = sub i32 0, [[Y:%.*]]
; CHECK-NEXT: [[P2:%.*]] = and i32 [[NY]], [[Y]]
; CHECK-NEXT: call void @use32(i32 [[P2]])
; CHECK-NEXT: [[VAL:%.*]] = add i32 [[P2]], [[X:%.*]]
; CHECK-NEXT: [[AND:%.*]] = and i32 [[VAL]], [[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
Expand All @@ -2609,8 +2609,8 @@ define i32 @canonicalize_and_add_power2_or_zero_commuted2(i32 %x, i32 %y) {
; CHECK-NEXT: [[P2:%.*]] = and i32 [[NY]], [[Y]]
; CHECK-NEXT: call void @use32(i32 [[P2]])
; CHECK-NEXT: [[X2:%.*]] = mul i32 [[X:%.*]], [[X]]
; CHECK-NEXT: [[VAL:%.*]] = add i32 [[X2]], [[P2]]
; CHECK-NEXT: [[AND:%.*]] = and i32 [[P2]], [[VAL]]
; CHECK-NEXT: [[TMP1:%.*]] = xor i32 [[X2]], -1
; CHECK-NEXT: [[AND:%.*]] = and i32 [[P2]], [[TMP1]]
; CHECK-NEXT: ret i32 [[AND]]
;
%ny = sub i32 0, %y
Expand All @@ -2628,8 +2628,8 @@ define i32 @canonicalize_and_add_power2_or_zero_commuted3(i32 %x, i32 %y) {
; CHECK-NEXT: [[NY:%.*]] = sub i32 0, [[Y:%.*]]
; CHECK-NEXT: [[P2:%.*]] = and i32 [[NY]], [[Y]]
; CHECK-NEXT: call void @use32(i32 [[P2]])
; CHECK-NEXT: [[VAL:%.*]] = add i32 [[P2]], [[X:%.*]]
; CHECK-NEXT: [[AND:%.*]] = and i32 [[P2]], [[VAL]]
; CHECK-NEXT: [[TMP1:%.*]] = xor i32 [[X:%.*]], -1
; CHECK-NEXT: [[AND:%.*]] = and i32 [[P2]], [[TMP1]]
; CHECK-NEXT: ret i32 [[AND]]
;
%ny = sub i32 0, %y
Expand Down

0 comments on commit 8a7e547

Please sign in to comment.