Skip to content

Commit

Permalink
[InstSimplify] add logic fold for 'or' with 'xor'+'and'
Browse files Browse the repository at this point in the history
This replaces the 'or' from 4b30076 with an 'and'.
We have to guard against propagating undef elements from
vector 'not' values:
https://alive2.llvm.org/ce/z/irMwRc
  • Loading branch information
rotateright committed Dec 7, 2021
1 parent 4b48cdd commit 8a69b04
Show file tree
Hide file tree
Showing 3 changed files with 25 additions and 85 deletions.
8 changes: 8 additions & 0 deletions llvm/lib/Analysis/InstructionSimplify.cpp
Expand Up @@ -2245,6 +2245,14 @@ static Value *simplifyOrLogic(Value *X, Value *Y) {
match(Y, m_Not(m_c_Or(m_Specific(A), m_Specific(B)))))
return NotA;

// ~(A ^ B) | (A & B) --> ~(A & B)
// ~(A ^ B) | (B & A) --> ~(A & B)
Value *NotAB;
if (match(X, m_CombineAnd(m_NotForbidUndef(m_Xor(m_Value(A), m_Value(B))),
m_Value(NotAB))) &&
match(Y, m_c_And(m_Specific(A), m_Specific(B))))
return NotAB;

return nullptr;
}

Expand Down
68 changes: 0 additions & 68 deletions llvm/test/Transforms/InstSimplify/AndOrXor.ll
Expand Up @@ -756,74 +756,6 @@ define i32 @or_xorn_and_commute7(i32 %a, i32 %b) {
ret i32 %or
}

; (A & B) | ~(A ^ B) -> ~(A ^ B)

define i32 @test55(i32 %a, i32 %b) {
; CHECK-LABEL: @test55(
; CHECK-NEXT: [[AND:%.*]] = and i32 [[A:%.*]], [[B:%.*]]
; CHECK-NEXT: [[XOR:%.*]] = xor i32 [[A]], [[B]]
; CHECK-NEXT: [[XNOR:%.*]] = xor i32 [[XOR]], -1
; CHECK-NEXT: [[OR:%.*]] = or i32 [[AND]], [[XNOR]]
; CHECK-NEXT: ret i32 [[OR]]
;
%and = and i32 %a, %b
%xor = xor i32 %a, %b
%xnor = xor i32 %xor, -1
%or = or i32 %and, %xnor
ret i32 %or
}

; ~(A ^ B) | (A & B) -> ~(A ^ B)

define i32 @test56(i32 %a, i32 %b) {
; CHECK-LABEL: @test56(
; CHECK-NEXT: [[AND:%.*]] = and i32 [[A:%.*]], [[B:%.*]]
; CHECK-NEXT: [[XOR:%.*]] = xor i32 [[A]], [[B]]
; CHECK-NEXT: [[XNOR:%.*]] = xor i32 [[XOR]], -1
; CHECK-NEXT: [[OR:%.*]] = or i32 [[XNOR]], [[AND]]
; CHECK-NEXT: ret i32 [[OR]]
;
%and = and i32 %a, %b
%xor = xor i32 %a, %b
%xnor = xor i32 %xor, -1
%or = or i32 %xnor, %and
ret i32 %or
}

; (B & A) | ~(A ^ B) -> ~(A ^ B)

define i32 @test57(i32 %a, i32 %b) {
; CHECK-LABEL: @test57(
; CHECK-NEXT: [[AND:%.*]] = and i32 [[B:%.*]], [[A:%.*]]
; CHECK-NEXT: [[XOR:%.*]] = xor i32 [[A]], [[B]]
; CHECK-NEXT: [[XNOR:%.*]] = xor i32 [[XOR]], -1
; CHECK-NEXT: [[OR:%.*]] = or i32 [[AND]], [[XNOR]]
; CHECK-NEXT: ret i32 [[OR]]
;
%and = and i32 %b, %a
%xor = xor i32 %a, %b
%xnor = xor i32 %xor, -1
%or = or i32 %and, %xnor
ret i32 %or
}

; ~(A ^ B) | (A & B) -> ~(A ^ B)

define i32 @test58(i32 %a, i32 %b) {
; CHECK-LABEL: @test58(
; CHECK-NEXT: [[AND:%.*]] = and i32 [[B:%.*]], [[A:%.*]]
; CHECK-NEXT: [[XOR:%.*]] = xor i32 [[A]], [[B]]
; CHECK-NEXT: [[XNOR:%.*]] = xor i32 [[XOR]], -1
; CHECK-NEXT: [[OR:%.*]] = or i32 [[XNOR]], [[AND]]
; CHECK-NEXT: ret i32 [[OR]]
;
%and = and i32 %b, %a
%xor = xor i32 %a, %b
%xnor = xor i32 %xor, -1
%or = or i32 %xnor, %and
ret i32 %or
}

define i8 @lshr_perfect_mask(i8 %x) {
; CHECK-LABEL: @lshr_perfect_mask(
; CHECK-NEXT: [[SH:%.*]] = lshr i8 [[X:%.*]], 5
Expand Down
34 changes: 17 additions & 17 deletions llvm/test/Transforms/InstSimplify/or.ll
Expand Up @@ -622,13 +622,13 @@ define i32 @shifted_all_ones_not_same_amt(i32 %shamt, i32 %other) {
ret i32 %o
}

; (A & B) | ~(A ^ B) --> ~(A ^ B)

define i4 @or_nxor_and_commute0(i4 %a, i4 %b) {
; CHECK-LABEL: @or_nxor_and_commute0(
; CHECK-NEXT: [[AND:%.*]] = and i4 [[A:%.*]], [[B:%.*]]
; CHECK-NEXT: [[XOR:%.*]] = xor i4 [[A]], [[B]]
; CHECK-NEXT: [[XOR:%.*]] = xor i4 [[A:%.*]], [[B:%.*]]
; CHECK-NEXT: [[NOT:%.*]] = xor i4 [[XOR]], -1
; CHECK-NEXT: [[R:%.*]] = or i4 [[AND]], [[NOT]]
; CHECK-NEXT: ret i4 [[R]]
; CHECK-NEXT: ret i4 [[NOT]]
;
%and = and i4 %a, %b
%xor = xor i4 %a, %b
Expand All @@ -639,11 +639,9 @@ define i4 @or_nxor_and_commute0(i4 %a, i4 %b) {

define <2 x i4> @or_nxor_and_commute1(<2 x i4> %a, <2 x i4> %b) {
; CHECK-LABEL: @or_nxor_and_commute1(
; CHECK-NEXT: [[AND:%.*]] = and <2 x i4> [[A:%.*]], [[B:%.*]]
; CHECK-NEXT: [[XOR:%.*]] = xor <2 x i4> [[A]], [[B]]
; CHECK-NEXT: [[XOR:%.*]] = xor <2 x i4> [[A:%.*]], [[B:%.*]]
; CHECK-NEXT: [[NOT:%.*]] = xor <2 x i4> [[XOR]], <i4 -1, i4 -1>
; CHECK-NEXT: [[R:%.*]] = or <2 x i4> [[NOT]], [[AND]]
; CHECK-NEXT: ret <2 x i4> [[R]]
; CHECK-NEXT: ret <2 x i4> [[NOT]]
;
%and = and <2 x i4> %a, %b
%xor = xor <2 x i4> %a, %b
Expand All @@ -654,11 +652,9 @@ define <2 x i4> @or_nxor_and_commute1(<2 x i4> %a, <2 x i4> %b) {

define i74 @or_nxor_and_commute2(i74 %a, i74 %b) {
; CHECK-LABEL: @or_nxor_and_commute2(
; CHECK-NEXT: [[AND:%.*]] = and i74 [[B:%.*]], [[A:%.*]]
; CHECK-NEXT: [[XOR:%.*]] = xor i74 [[A]], [[B]]
; CHECK-NEXT: [[XOR:%.*]] = xor i74 [[A:%.*]], [[B:%.*]]
; CHECK-NEXT: [[NOT:%.*]] = xor i74 [[XOR]], -1
; CHECK-NEXT: [[R:%.*]] = or i74 [[AND]], [[NOT]]
; CHECK-NEXT: ret i74 [[R]]
; CHECK-NEXT: ret i74 [[NOT]]
;
%and = and i74 %b, %a
%xor = xor i74 %a, %b
Expand All @@ -669,11 +665,9 @@ define i74 @or_nxor_and_commute2(i74 %a, i74 %b) {

define <2 x i4> @or_nxor_and_commute3(<2 x i4> %a, <2 x i4> %b) {
; CHECK-LABEL: @or_nxor_and_commute3(
; CHECK-NEXT: [[AND:%.*]] = and <2 x i4> [[B:%.*]], [[A:%.*]]
; CHECK-NEXT: [[XOR:%.*]] = xor <2 x i4> [[A]], [[B]]
; CHECK-NEXT: [[XOR:%.*]] = xor <2 x i4> [[A:%.*]], [[B:%.*]]
; CHECK-NEXT: [[NOT:%.*]] = xor <2 x i4> [[XOR]], <i4 -1, i4 -1>
; CHECK-NEXT: [[R:%.*]] = or <2 x i4> [[NOT]], [[AND]]
; CHECK-NEXT: ret <2 x i4> [[R]]
; CHECK-NEXT: ret <2 x i4> [[NOT]]
;
%and = and <2 x i4> %b, %a
%xor = xor <2 x i4> %a, %b
Expand All @@ -682,6 +676,8 @@ define <2 x i4> @or_nxor_and_commute3(<2 x i4> %a, <2 x i4> %b) {
ret <2 x i4> %r
}

; negative test - must have common operands

define i4 @or_nxor_and_wrong_val1(i4 %a, i4 %b, i4 %c) {
; CHECK-LABEL: @or_nxor_and_wrong_val1(
; CHECK-NEXT: [[AND:%.*]] = and i4 [[A:%.*]], [[C:%.*]]
Expand All @@ -697,6 +693,8 @@ define i4 @or_nxor_and_wrong_val1(i4 %a, i4 %b, i4 %c) {
ret i4 %r
}

; negative test - must have common operands

define i4 @or_nxor_and_wrong_val2(i4 %a, i4 %b, i4 %c) {
; CHECK-LABEL: @or_nxor_and_wrong_val2(
; CHECK-NEXT: [[AND:%.*]] = and i4 [[C:%.*]], [[B:%.*]]
Expand All @@ -712,6 +710,8 @@ define i4 @or_nxor_and_wrong_val2(i4 %a, i4 %b, i4 %c) {
ret i4 %r
}

; negative test - undef in 'not' is allowed

define <2 x i4> @or_nxor_and_undef_elt(<2 x i4> %a, <2 x i4> %b) {
; CHECK-LABEL: @or_nxor_and_undef_elt(
; CHECK-NEXT: [[AND:%.*]] = and <2 x i4> [[B:%.*]], [[A:%.*]]
Expand Down Expand Up @@ -807,7 +807,7 @@ define i4 @or_nxor_or_wrong_val2(i4 %a, i4 %b, i4 %c) {
ret i4 %r
}

; undef in 'not' is allowed
; negative test - undef in 'not' is allowed

define <2 x i4> @or_nxor_or_undef_elt(<2 x i4> %a, <2 x i4> %b) {
; CHECK-LABEL: @or_nxor_or_undef_elt(
Expand Down

0 comments on commit 8a69b04

Please sign in to comment.