[llvm] a4e2a51 - [InstSimplify] Add (~A & B) | ~(A | B) --> ~A

Dávid Bolvanský via llvm-commits llvm-commits at lists.llvm.org
Sat Jan 16 07:52:35 PST 2021


Ok, I see what you mean for outer or. I will fix it.


> Dňa 16. 1. 2021 o 16:28 užívateľ Dávid Bolvanský <david.bolvansky at gmail.com> napísal:
> 
> And - yes, I can improve the comments (it works well when swapped - not is and’s op0)
> 
> Or - yes,  but “and” is always op0. (Complexivity canonicalization).
> 
> 
> 
>> Dňa 16. 1. 2021 o 16:01 užívateľ Roman Lebedev <lebedev.ri at gmail.com> napísal:
>> 
>> On Sat, Jan 16, 2021 at 5:54 PM Dávid Bolvanský via llvm-commits
>> <llvm-commits at lists.llvm.org> wrote:
>>> 
>>> 
>>> Author: Dávid Bolvanský
>>> Date: 2021-01-16T15:43:34+01:00
>>> New Revision: a4e2a5145a29af678139f33e94ab3df0fc973e59
>>> 
>>> URL: https://github.com/llvm/llvm-project/commit/a4e2a5145a29af678139f33e94ab3df0fc973e59
>>> DIFF: https://github.com/llvm/llvm-project/commit/a4e2a5145a29af678139f33e94ab3df0fc973e59.diff
>>> 
>>> LOG: [InstSimplify] Add (~A & B) | ~(A | B) --> ~A
>>> 
>>> Added:
>>> 
>>> 
>>> Modified:
>>>   llvm/lib/Analysis/InstructionSimplify.cpp
>>>   llvm/test/Transforms/InstSimplify/or.ll
>>> 
>>> Removed:
>>> 
>>> 
>>> 
>>> ################################################################################
>>> diff  --git a/llvm/lib/Analysis/InstructionSimplify.cpp b/llvm/lib/Analysis/InstructionSimplify.cpp
>>> index 2ae4228495e3..6266e922f8c9 100644
>>> --- a/llvm/lib/Analysis/InstructionSimplify.cpp
>>> +++ b/llvm/lib/Analysis/InstructionSimplify.cpp
>>> @@ -2262,6 +2262,12 @@ static Value *SimplifyOrInst(Value *Op0, Value *Op1, const SimplifyQuery &Q,
>>>       match(Op0, m_c_Xor(m_Not(m_Specific(A)), m_Specific(B)))))
>>>    return Op0;
>>> 
>>> +  // (~A & B) | ~(A | B) --> ~A
>>> +  // (~A & B) | ~(B | A) --> ~A
>> Are the 'and' and outer 'or' not commutative?
>> 
>>> +  if (match(Op0, m_And(m_Not(m_Value(A)), m_Value(B))) &&
>>> +      match(Op1, m_Not(m_c_Or(m_Specific(A), m_Specific(B)))))
>>> +    return cast<BinaryOperator>(Op0)->getOperand(0);
>>> +
>>>  if (Value *V = simplifyAndOrOfCmps(Q, Op0, Op1, false))
>>>    return V;
>>> 
>>> 
>>> diff  --git a/llvm/test/Transforms/InstSimplify/or.ll b/llvm/test/Transforms/InstSimplify/or.ll
>>> index e8284264c612..7e7361d12395 100644
>>> --- a/llvm/test/Transforms/InstSimplify/or.ll
>>> +++ b/llvm/test/Transforms/InstSimplify/or.ll
>>> @@ -301,3 +301,97 @@ define i32 @poison(i32 %x) {
>>>  %v = or i32 %x, poison
>>>  ret i32 %v
>>> }
>>> +
>>> +declare void @use(i32)
>>> +
>>> +define i32 @and_or_not_or(i32 %A, i32 %B) {
>>> +; CHECK-LABEL: @and_or_not_or(
>>> +; CHECK-NEXT:    [[I:%.*]] = xor i32 [[B:%.*]], -1
>>> +; CHECK-NEXT:    ret i32 [[I]]
>>> +;
>>> +  %i = xor i32 %B, -1
>>> +  %i2 = and i32 %i, %A
>>> +  %i3 = or i32 %B, %A
>>> +  %i4 = xor i32 %i3, -1
>>> +  %i5 = or i32 %i2, %i4
>>> +  ret i32 %i5
>>> +}
>>> +
>>> +define i32 @and_or_not_or2(i32 %A, i32 %B) {
>>> +; CHECK-LABEL: @and_or_not_or2(
>>> +; CHECK-NEXT:    [[I:%.*]] = xor i32 [[A:%.*]], -1
>>> +; CHECK-NEXT:    ret i32 [[I]]
>>> +;
>>> +  %i = xor i32 %A, -1
>>> +  %i2 = and i32 %i, %B
>>> +  %i3 = or i32 %B, %A
>>> +  %i4 = xor i32 %i3, -1
>>> +  %i5 = or i32 %i2, %i4
>>> +  ret i32 %i5
>>> +}
>>> +
>>> +define <4 x i32> @and_or_not_or3_vec(<4 x i32> %A, <4 x i32> %B) {
>>> +; CHECK-LABEL: @and_or_not_or3_vec(
>>> +; CHECK-NEXT:    [[I:%.*]] = xor <4 x i32> [[A:%.*]], <i32 -1, i32 -1, i32 -1, i32 -1>
>>> +; CHECK-NEXT:    ret <4 x i32> [[I]]
>>> +;
>>> +  %i = xor <4 x i32> %A, <i32 -1, i32 -1, i32 -1, i32 -1>
>>> +  %i2 = and <4 x i32> %i, %B
>>> +  %i3 = or <4 x i32> %B, %A
>>> +  %i4 = xor <4 x i32> %i3, <i32 -1, i32 -1, i32 -1, i32 -1>
>>> +  %i5 = or <4 x i32> %i2, %i4
>>> +  ret <4 x i32> %i5
>>> +}
>>> +
>>> +define i32 @and_or_not_or4_use(i32 %A, i32 %B) {
>>> +; CHECK-LABEL: @and_or_not_or4_use(
>>> +; CHECK-NEXT:    [[I:%.*]] = xor i32 [[A:%.*]], -1
>>> +; CHECK-NEXT:    [[I2:%.*]] = and i32 [[I]], [[B:%.*]]
>>> +; CHECK-NEXT:    tail call void @use(i32 [[I2]])
>>> +; CHECK-NEXT:    ret i32 [[I]]
>>> +;
>>> +  %i = xor i32 %A, -1
>>> +  %i2 = and i32 %i, %B
>>> +  tail call void @use(i32 %i2)
>>> +  %i3 = or i32 %B, %A
>>> +  %i4 = xor i32 %i3, -1
>>> +  %i5 = or i32 %i2, %i4
>>> +  ret i32 %i5
>>> +}
>>> +
>>> +define i32 @and_or_not_or4_use2(i32 %A, i32 %B) {
>>> +; CHECK-LABEL: @and_or_not_or4_use2(
>>> +; CHECK-NEXT:    [[I:%.*]] = or i32 [[B:%.*]], [[A:%.*]]
>>> +; CHECK-NEXT:    [[I2:%.*]] = xor i32 [[I]], -1
>>> +; CHECK-NEXT:    tail call void @use(i32 [[I2]])
>>> +; CHECK-NEXT:    [[I3:%.*]] = xor i32 [[A]], -1
>>> +; CHECK-NEXT:    ret i32 [[I3]]
>>> +;
>>> +  %i = or i32 %B, %A
>>> +  %i2 = xor i32 %i, -1
>>> +  tail call void @use(i32 %i2)
>>> +  %i3 = xor i32 %A, -1
>>> +  %i4 = and i32 %i3, %B
>>> +  %i5 = or i32 %i4, %i2
>>> +  ret i32 %i5
>>> +}
>>> +
>>> +define i32 @and_or_not_or4_use3(i32 %A, i32 %B) {
>>> +; CHECK-LABEL: @and_or_not_or4_use3(
>>> +; CHECK-NEXT:    [[I:%.*]] = or i32 [[B:%.*]], [[A:%.*]]
>>> +; CHECK-NEXT:    [[I2:%.*]] = xor i32 [[I]], -1
>>> +; CHECK-NEXT:    tail call void @use(i32 [[I2]])
>>> +; CHECK-NEXT:    [[I3:%.*]] = xor i32 [[A]], -1
>>> +; CHECK-NEXT:    [[I4:%.*]] = and i32 [[I3]], [[B]]
>>> +; CHECK-NEXT:    tail call void @use(i32 [[I4]])
>>> +; CHECK-NEXT:    ret i32 [[I3]]
>>> +;
>>> +  %i = or i32 %B, %A
>>> +  %i2 = xor i32 %i, -1
>>> +  tail call void @use(i32 %i2)
>>> +  %i3 = xor i32 %A, -1
>>> +  %i4 = and i32 %i3, %B
>>> +  tail call void @use(i32 %i4)
>>> +  %i5 = or i32 %i4, %i2
>>> +  ret i32 %i5
>>> +}
>>> 
>>> 
>>> 
>>> _______________________________________________
>>> llvm-commits mailing list
>>> llvm-commits at lists.llvm.org
>>> https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits


More information about the llvm-commits mailing list