forked from OSchip/llvm-project
[InstCombine] fold logical and/or to xor
(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.
This commit is contained in:
parent
b78306c9f7
commit
d85505a932
|
@ -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))) &&
|
||||
|
|
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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>
|
||||
|
|
Loading…
Reference in New Issue