Skip to content

Commit

Permalink
[InstCombine] fold logical and/or to xor
Browse files Browse the repository at this point in the history
(A | B) & ~(A & B) --> A ^ B

https://alive2.llvm.org/ce/z/qpFMns

We already have the equivalent fold for real
logic instructions, but this pattern may occur
with selects too.

This is part of solving issue #58313.
  • Loading branch information
rotateright committed Oct 13, 2022
1 parent b78306c commit d85505a
Show file tree
Hide file tree
Showing 2 changed files with 9 additions and 11 deletions.
5 changes: 5 additions & 0 deletions llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2774,6 +2774,11 @@ Instruction *InstCombinerImpl::visitSelectInst(SelectInst &SI) {
match(TrueVal, m_Specific(B)) && match(FalseVal, m_Zero()))
return replaceOperand(SI, 0, A);

// ~(A & B) & (A | B) --> A ^ B
if (match(&SI, m_c_LogicalAnd(m_Not(m_LogicalAnd(m_Value(A), m_Value(B))),
m_c_LogicalOr(m_Deferred(A), m_Deferred(B)))))
return BinaryOperator::CreateXor(A, B);

Value *C;
// select (~a | c), a, b -> and a, (or c, freeze(b))
if (match(CondVal, m_c_Or(m_Not(m_Specific(TrueVal)), m_Value(C))) &&
Expand Down
15 changes: 4 additions & 11 deletions llvm/test/Transforms/InstCombine/logical-select.ll
Original file line number Diff line number Diff line change
Expand Up @@ -932,10 +932,7 @@ define i8 @sext_cond_extra_uses(i1 %cmp, i8 %a, i8 %b) {

define i1 @xor_commute0(i1 %x, i1 %y) {
; CHECK-LABEL: @xor_commute0(
; CHECK-NEXT: [[AND:%.*]] = select i1 [[X:%.*]], i1 [[Y:%.*]], i1 false
; CHECK-NEXT: [[OR:%.*]] = select i1 [[X]], i1 true, i1 [[Y]]
; CHECK-NEXT: [[NAND:%.*]] = xor i1 [[AND]], true
; CHECK-NEXT: [[AND2:%.*]] = select i1 [[NAND]], i1 [[OR]], i1 false
; CHECK-NEXT: [[AND2:%.*]] = xor i1 [[X:%.*]], [[Y:%.*]]
; CHECK-NEXT: ret i1 [[AND2]]
;
%and = select i1 %x, i1 %y, i1 false
Expand All @@ -948,10 +945,9 @@ define i1 @xor_commute0(i1 %x, i1 %y) {
define i1 @xor_commute1(i1 %x, i1 %y) {
; CHECK-LABEL: @xor_commute1(
; CHECK-NEXT: [[AND:%.*]] = select i1 [[X:%.*]], i1 [[Y:%.*]], i1 false
; CHECK-NEXT: [[OR:%.*]] = select i1 [[Y]], i1 true, i1 [[X]]
; CHECK-NEXT: [[NAND:%.*]] = xor i1 [[AND]], true
; CHECK-NEXT: call void @use1(i1 [[NAND]])
; CHECK-NEXT: [[AND2:%.*]] = select i1 [[NAND]], i1 [[OR]], i1 false
; CHECK-NEXT: [[AND2:%.*]] = xor i1 [[X]], [[Y]]
; CHECK-NEXT: ret i1 [[AND2]]
;
%and = select i1 %x, i1 %y, i1 false
Expand All @@ -970,7 +966,7 @@ define i1 @xor_commute2(i1 %x, i1 %y) {
; CHECK-NEXT: call void @use1(i1 [[OR]])
; CHECK-NEXT: [[NAND:%.*]] = xor i1 [[AND]], true
; CHECK-NEXT: call void @use1(i1 [[NAND]])
; CHECK-NEXT: [[AND2:%.*]] = select i1 [[OR]], i1 [[NAND]], i1 false
; CHECK-NEXT: [[AND2:%.*]] = xor i1 [[X]], [[Y]]
; CHECK-NEXT: ret i1 [[AND2]]
;
%and = select i1 %x, i1 %y, i1 false
Expand All @@ -985,10 +981,7 @@ define i1 @xor_commute2(i1 %x, i1 %y) {

define <2 x i1> @xor_commute3(<2 x i1> %x, <2 x i1> %y) {
; CHECK-LABEL: @xor_commute3(
; CHECK-NEXT: [[AND:%.*]] = select <2 x i1> [[X:%.*]], <2 x i1> [[Y:%.*]], <2 x i1> zeroinitializer
; CHECK-NEXT: [[OR:%.*]] = select <2 x i1> [[Y]], <2 x i1> <i1 true, i1 true>, <2 x i1> [[X]]
; CHECK-NEXT: [[NAND:%.*]] = xor <2 x i1> [[AND]], <i1 true, i1 true>
; CHECK-NEXT: [[AND2:%.*]] = select <2 x i1> [[OR]], <2 x i1> [[NAND]], <2 x i1> zeroinitializer
; CHECK-NEXT: [[AND2:%.*]] = xor <2 x i1> [[X:%.*]], [[Y:%.*]]
; CHECK-NEXT: ret <2 x i1> [[AND2]]
;
%and = select <2 x i1> %x, <2 x i1> %y, <2 x i1> <i1 false, i1 false>
Expand Down

0 comments on commit d85505a

Please sign in to comment.