[llvm] c407769 - [InstCombine] (~(a | b) & c) | ~(c | (a ^ b)) -> ~((a | b) & (c | (b ^ a)))
Stanislav Mekhanoshin via llvm-commits
llvm-commits at lists.llvm.org
Mon Nov 22 10:49:32 PST 2021
Author: Stanislav Mekhanoshin
Date: 2021-11-22T10:49:21-08:00
New Revision: c407769f5e6c81d56de0b251aed5750a16a7651c
URL: https://github.com/llvm/llvm-project/commit/c407769f5e6c81d56de0b251aed5750a16a7651c
DIFF: https://github.com/llvm/llvm-project/commit/c407769f5e6c81d56de0b251aed5750a16a7651c.diff
LOG: [InstCombine] (~(a | b) & c) | ~(c | (a ^ b)) -> ~((a | b) & (c | (b ^ a)))
Transform
```
(~(a | b) & c) | ~(c | (a ^ b)) -> ~((a | b) & (c | (b ^ a)))
```
And swapped case:
```
(a | ~(b & c)) & ~(a & (b ^ c)) --> ~(a | b) | (a ^ b ^ c)
```
```
----------------------------------------
define i3 @src(i3 %a, i3 %b, i3 %c) {
%0:
%or1 = or i3 %b, %c
%not1 = xor i3 %or1, 7
%and1 = and i3 %a, %not1
%xor1 = xor i3 %b, %c
%or2 = or i3 %xor1, %a
%not2 = xor i3 %or2, 7
%or3 = or i3 %and1, %not2
ret i3 %or3
}
=>
define i3 @tgt(i3 %a, i3 %b, i3 %c) {
%0:
%obc = or i3 %b, %c
%xbc = xor i3 %b, %c
%o = or i3 %a, %xbc
%and = and i3 %obc, %o
%r = xor i3 %and, 7
ret i3 %r
}
Transformation seems to be correct!
```
```
----------------------------------------
define i4 @src(i4 %a, i4 %b, i4 %c) {
%0:
%and1 = and i4 %b, %c
%not1 = xor i4 %and1, 15
%or1 = or i4 %not1, %a
%xor1 = xor i4 %b, %c
%and2 = and i4 %xor1, %a
%not2 = xor i4 %and2, 15
%and3 = and i4 %or1, %not2
ret i4 %and3
}
=>
define i4 @tgt(i4 %a, i4 %b, i4 %c) {
%0:
%xor1 = xor i4 %b, %c
%xor2 = xor i4 %xor1, %a
%or1 = or i4 %a, %b
%not1 = xor i4 %or1, 15
%or2 = or i4 %xor2, %not1
ret i4 %or2
}
Transformation seems to be correct!
```
Differential Revision: https://reviews.llvm.org/D112955
Added:
Modified:
llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
llvm/test/Transforms/InstCombine/and-xor-or.ll
Removed:
################################################################################
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp b/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
index 4ef7ff31e0892..1e09766831613 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
@@ -1727,16 +1727,18 @@ static Instruction *foldComplexAndOrPatterns(BinaryOperator &I,
(Opcode == Instruction::And) ? Instruction::Or : Instruction::And;
Value *Op0 = I.getOperand(0), *Op1 = I.getOperand(1);
- Value *A, *B, *C;
+ Value *A, *B, *C, *X, *Y, *Z;
// (~(A | B) & C) | ... --> ...
// (~(A & B) | C) & ... --> ...
// TODO: One use checks are conservative. We just need to check that a total
// number of multiple used values does not exceed reduction
// in operations.
- if (match(Op0, m_c_BinOp(FlippedOpcode,
- m_Not(m_BinOp(Opcode, m_Value(A), m_Value(B))),
- m_Value(C)))) {
+ if (match(Op0,
+ m_c_BinOp(FlippedOpcode,
+ m_CombineAnd(m_Value(X), m_Not(m_BinOp(Opcode, m_Value(A),
+ m_Value(B)))),
+ m_Value(C)))) {
// (~(A | B) & C) | (~(A | C) & B) --> (B ^ C) & ~A
// (~(A & B) | C) & (~(A & C) | B) --> ~((B ^ C) & A)
if (match(Op1,
@@ -1776,6 +1778,28 @@ static Instruction *foldComplexAndOrPatterns(BinaryOperator &I,
m_c_BinOp(Opcode, m_Specific(B), m_Specific(C)))))))
return BinaryOperator::CreateNot(Builder.CreateBinOp(
Opcode, Builder.CreateBinOp(FlippedOpcode, A, C), B));
+
+ // (~(A | B) & C) | ~(C | (A ^ B)) --> ~((A | B) & (C | (A ^ B)))
+ // (~(A & B) | C) & ~(C & (A ^ B)) --> (A ^ B ^ C) | ~(A | C)
+ // Note: X = ~(A | B) or ~(A & B)
+ if (Op0->hasOneUse() &&
+ match(Op1, m_OneUse(m_Not(m_CombineAnd(
+ m_Value(Z),
+ m_c_BinOp(Opcode, m_Specific(C),
+ m_CombineAnd(m_Value(Y),
+ m_c_Xor(m_Specific(A),
+ m_Specific(B))))))))) {
+ Value *AndOr = cast<BinaryOperator>(X)->getOperand(0);
+ if (Opcode == Instruction::Or) {
+ // Z = (C | (A ^ B)
+ return BinaryOperator::CreateNot(Builder.CreateAnd(AndOr, Z));
+ } else if (X->hasOneUse() && AndOr->hasOneUse() && Z->hasOneUse()) {
+ // Y = A ^ B
+ Value *Xor = Builder.CreateXor(Y, C);
+ return BinaryOperator::CreateOr(
+ Xor, Builder.CreateNot(Builder.CreateOr(A, C)));
+ }
+ }
}
return nullptr;
diff --git a/llvm/test/Transforms/InstCombine/and-xor-or.ll b/llvm/test/Transforms/InstCombine/and-xor-or.ll
index adeb333b88c9e..a2baeea194107 100644
--- a/llvm/test/Transforms/InstCombine/and-xor-or.ll
+++ b/llvm/test/Transforms/InstCombine/and-xor-or.ll
@@ -2018,17 +2018,15 @@ define i32 @and_or_not_not_wrong_b(i32 %a, i32 %b, i32 %c, i32 %d) {
ret i32 %and3
}
-; (a & ~(b | c)) | ~(a | (b ^ c)) --> (~a & b & c) | ~(b | c)
+; (a & ~(b | c)) | ~(a | (b ^ c)) --> ~((b | c) & (a | (b ^ c)))
define i32 @and_not_or_or_not_or_xor(i32 %a, i32 %b, i32 %c) {
; CHECK-LABEL: @and_not_or_or_not_or_xor(
; CHECK-NEXT: [[OR1:%.*]] = or i32 [[B:%.*]], [[C:%.*]]
-; CHECK-NEXT: [[NOT1:%.*]] = xor i32 [[OR1]], -1
-; CHECK-NEXT: [[AND1:%.*]] = and i32 [[NOT1]], [[A:%.*]]
; CHECK-NEXT: [[XOR1:%.*]] = xor i32 [[B]], [[C]]
-; CHECK-NEXT: [[OR2:%.*]] = or i32 [[XOR1]], [[A]]
-; CHECK-NEXT: [[NOT2:%.*]] = xor i32 [[OR2]], -1
-; CHECK-NEXT: [[OR3:%.*]] = or i32 [[AND1]], [[NOT2]]
+; CHECK-NEXT: [[OR2:%.*]] = or i32 [[XOR1]], [[A:%.*]]
+; CHECK-NEXT: [[TMP1:%.*]] = and i32 [[OR1]], [[OR2]]
+; CHECK-NEXT: [[OR3:%.*]] = xor i32 [[TMP1]], -1
; CHECK-NEXT: ret i32 [[OR3]]
;
%or1 = or i32 %b, %c
@@ -2044,12 +2042,10 @@ define i32 @and_not_or_or_not_or_xor(i32 %a, i32 %b, i32 %c) {
define i32 @and_not_or_or_not_or_xor_commute1(i32 %a, i32 %b, i32 %c) {
; CHECK-LABEL: @and_not_or_or_not_or_xor_commute1(
; CHECK-NEXT: [[OR1:%.*]] = or i32 [[C:%.*]], [[B:%.*]]
-; CHECK-NEXT: [[NOT1:%.*]] = xor i32 [[OR1]], -1
-; CHECK-NEXT: [[AND1:%.*]] = and i32 [[NOT1]], [[A:%.*]]
; CHECK-NEXT: [[XOR1:%.*]] = xor i32 [[B]], [[C]]
-; CHECK-NEXT: [[OR2:%.*]] = or i32 [[XOR1]], [[A]]
-; CHECK-NEXT: [[NOT2:%.*]] = xor i32 [[OR2]], -1
-; CHECK-NEXT: [[OR3:%.*]] = or i32 [[AND1]], [[NOT2]]
+; CHECK-NEXT: [[OR2:%.*]] = or i32 [[XOR1]], [[A:%.*]]
+; CHECK-NEXT: [[TMP1:%.*]] = and i32 [[OR1]], [[OR2]]
+; CHECK-NEXT: [[OR3:%.*]] = xor i32 [[TMP1]], -1
; CHECK-NEXT: ret i32 [[OR3]]
;
%or1 = or i32 %c, %b
@@ -2066,12 +2062,10 @@ define i32 @and_not_or_or_not_or_xor_commute2(i32 %a0, i32 %b, i32 %c) {
; CHECK-LABEL: @and_not_or_or_not_or_xor_commute2(
; CHECK-NEXT: [[A:%.*]] = sdiv i32 42, [[A0:%.*]]
; CHECK-NEXT: [[OR1:%.*]] = or i32 [[B:%.*]], [[C:%.*]]
-; CHECK-NEXT: [[NOT1:%.*]] = xor i32 [[OR1]], -1
-; CHECK-NEXT: [[AND1:%.*]] = and i32 [[A]], [[NOT1]]
; CHECK-NEXT: [[XOR1:%.*]] = xor i32 [[B]], [[C]]
; CHECK-NEXT: [[OR2:%.*]] = or i32 [[XOR1]], [[A]]
-; CHECK-NEXT: [[NOT2:%.*]] = xor i32 [[OR2]], -1
-; CHECK-NEXT: [[OR3:%.*]] = or i32 [[AND1]], [[NOT2]]
+; CHECK-NEXT: [[TMP1:%.*]] = and i32 [[OR1]], [[OR2]]
+; CHECK-NEXT: [[OR3:%.*]] = xor i32 [[TMP1]], -1
; CHECK-NEXT: ret i32 [[OR3]]
;
%a = sdiv i32 42, %a0 ; thwart complexity-based canonicalization
@@ -2088,12 +2082,10 @@ define i32 @and_not_or_or_not_or_xor_commute2(i32 %a0, i32 %b, i32 %c) {
define i32 @and_not_or_or_not_or_xor_commute3(i32 %a, i32 %b, i32 %c) {
; CHECK-LABEL: @and_not_or_or_not_or_xor_commute3(
; CHECK-NEXT: [[OR1:%.*]] = or i32 [[B:%.*]], [[C:%.*]]
-; CHECK-NEXT: [[NOT1:%.*]] = xor i32 [[OR1]], -1
-; CHECK-NEXT: [[AND1:%.*]] = and i32 [[NOT1]], [[A:%.*]]
; CHECK-NEXT: [[XOR1:%.*]] = xor i32 [[C]], [[B]]
-; CHECK-NEXT: [[OR2:%.*]] = or i32 [[XOR1]], [[A]]
-; CHECK-NEXT: [[NOT2:%.*]] = xor i32 [[OR2]], -1
-; CHECK-NEXT: [[OR3:%.*]] = or i32 [[AND1]], [[NOT2]]
+; CHECK-NEXT: [[OR2:%.*]] = or i32 [[XOR1]], [[A:%.*]]
+; CHECK-NEXT: [[TMP1:%.*]] = and i32 [[OR1]], [[OR2]]
+; CHECK-NEXT: [[OR3:%.*]] = xor i32 [[TMP1]], -1
; CHECK-NEXT: ret i32 [[OR3]]
;
%or1 = or i32 %b, %c
@@ -2110,12 +2102,10 @@ define i32 @and_not_or_or_not_or_xor_commute4(i32 %a0, i32 %b, i32 %c) {
; CHECK-LABEL: @and_not_or_or_not_or_xor_commute4(
; CHECK-NEXT: [[A:%.*]] = sdiv i32 42, [[A0:%.*]]
; CHECK-NEXT: [[OR1:%.*]] = or i32 [[B:%.*]], [[C:%.*]]
-; CHECK-NEXT: [[NOT1:%.*]] = xor i32 [[OR1]], -1
-; CHECK-NEXT: [[AND1:%.*]] = and i32 [[A]], [[NOT1]]
; CHECK-NEXT: [[XOR1:%.*]] = xor i32 [[B]], [[C]]
; CHECK-NEXT: [[OR2:%.*]] = or i32 [[A]], [[XOR1]]
-; CHECK-NEXT: [[NOT2:%.*]] = xor i32 [[OR2]], -1
-; CHECK-NEXT: [[OR3:%.*]] = or i32 [[AND1]], [[NOT2]]
+; CHECK-NEXT: [[TMP1:%.*]] = and i32 [[OR1]], [[OR2]]
+; CHECK-NEXT: [[OR3:%.*]] = xor i32 [[TMP1]], -1
; CHECK-NEXT: ret i32 [[OR3]]
;
%a = sdiv i32 42, %a0 ; thwart complexity-based canonicalization
@@ -2132,12 +2122,10 @@ define i32 @and_not_or_or_not_or_xor_commute4(i32 %a0, i32 %b, i32 %c) {
define i32 @and_not_or_or_not_or_xor_commute5(i32 %a, i32 %b, i32 %c) {
; CHECK-LABEL: @and_not_or_or_not_or_xor_commute5(
; CHECK-NEXT: [[OR1:%.*]] = or i32 [[B:%.*]], [[C:%.*]]
-; CHECK-NEXT: [[NOT1:%.*]] = xor i32 [[OR1]], -1
-; CHECK-NEXT: [[AND1:%.*]] = and i32 [[NOT1]], [[A:%.*]]
; CHECK-NEXT: [[XOR1:%.*]] = xor i32 [[B]], [[C]]
-; CHECK-NEXT: [[OR2:%.*]] = or i32 [[XOR1]], [[A]]
-; CHECK-NEXT: [[NOT2:%.*]] = xor i32 [[OR2]], -1
-; CHECK-NEXT: [[OR3:%.*]] = or i32 [[AND1]], [[NOT2]]
+; CHECK-NEXT: [[OR2:%.*]] = or i32 [[XOR1]], [[A:%.*]]
+; CHECK-NEXT: [[TMP1:%.*]] = and i32 [[OR1]], [[OR2]]
+; CHECK-NEXT: [[OR3:%.*]] = xor i32 [[TMP1]], -1
; CHECK-NEXT: ret i32 [[OR3]]
;
%or1 = or i32 %b, %c
@@ -2153,12 +2141,10 @@ define i32 @and_not_or_or_not_or_xor_commute5(i32 %a, i32 %b, i32 %c) {
define i32 @and_not_or_or_not_or_xor_use1(i32 %a, i32 %b, i32 %c) {
; CHECK-LABEL: @and_not_or_or_not_or_xor_use1(
; CHECK-NEXT: [[OR1:%.*]] = or i32 [[B:%.*]], [[C:%.*]]
-; CHECK-NEXT: [[NOT1:%.*]] = xor i32 [[OR1]], -1
-; CHECK-NEXT: [[AND1:%.*]] = and i32 [[NOT1]], [[A:%.*]]
; CHECK-NEXT: [[XOR1:%.*]] = xor i32 [[B]], [[C]]
-; CHECK-NEXT: [[OR2:%.*]] = or i32 [[XOR1]], [[A]]
-; CHECK-NEXT: [[NOT2:%.*]] = xor i32 [[OR2]], -1
-; CHECK-NEXT: [[OR3:%.*]] = or i32 [[AND1]], [[NOT2]]
+; CHECK-NEXT: [[OR2:%.*]] = or i32 [[XOR1]], [[A:%.*]]
+; CHECK-NEXT: [[TMP1:%.*]] = and i32 [[OR1]], [[OR2]]
+; CHECK-NEXT: [[OR3:%.*]] = xor i32 [[TMP1]], -1
; CHECK-NEXT: call void @use(i32 [[OR1]])
; CHECK-NEXT: ret i32 [[OR3]]
;
@@ -2177,11 +2163,10 @@ define i32 @and_not_or_or_not_or_xor_use2(i32 %a, i32 %b, i32 %c) {
; CHECK-LABEL: @and_not_or_or_not_or_xor_use2(
; CHECK-NEXT: [[OR1:%.*]] = or i32 [[B:%.*]], [[C:%.*]]
; CHECK-NEXT: [[NOT1:%.*]] = xor i32 [[OR1]], -1
-; CHECK-NEXT: [[AND1:%.*]] = and i32 [[NOT1]], [[A:%.*]]
; CHECK-NEXT: [[XOR1:%.*]] = xor i32 [[B]], [[C]]
-; CHECK-NEXT: [[OR2:%.*]] = or i32 [[XOR1]], [[A]]
-; CHECK-NEXT: [[NOT2:%.*]] = xor i32 [[OR2]], -1
-; CHECK-NEXT: [[OR3:%.*]] = or i32 [[AND1]], [[NOT2]]
+; CHECK-NEXT: [[OR2:%.*]] = or i32 [[XOR1]], [[A:%.*]]
+; CHECK-NEXT: [[TMP1:%.*]] = and i32 [[OR1]], [[OR2]]
+; CHECK-NEXT: [[OR3:%.*]] = xor i32 [[TMP1]], -1
; CHECK-NEXT: call void @use(i32 [[NOT1]])
; CHECK-NEXT: ret i32 [[OR3]]
;
@@ -2222,12 +2207,10 @@ define i32 @and_not_or_or_not_or_xor_use3(i32 %a, i32 %b, i32 %c) {
define i32 @and_not_or_or_not_or_xor_use4(i32 %a, i32 %b, i32 %c) {
; CHECK-LABEL: @and_not_or_or_not_or_xor_use4(
; CHECK-NEXT: [[OR1:%.*]] = or i32 [[B:%.*]], [[C:%.*]]
-; CHECK-NEXT: [[NOT1:%.*]] = xor i32 [[OR1]], -1
-; CHECK-NEXT: [[AND1:%.*]] = and i32 [[NOT1]], [[A:%.*]]
; CHECK-NEXT: [[XOR1:%.*]] = xor i32 [[B]], [[C]]
-; CHECK-NEXT: [[OR2:%.*]] = or i32 [[XOR1]], [[A]]
-; CHECK-NEXT: [[NOT2:%.*]] = xor i32 [[OR2]], -1
-; CHECK-NEXT: [[OR3:%.*]] = or i32 [[AND1]], [[NOT2]]
+; CHECK-NEXT: [[OR2:%.*]] = or i32 [[XOR1]], [[A:%.*]]
+; CHECK-NEXT: [[TMP1:%.*]] = and i32 [[OR1]], [[OR2]]
+; CHECK-NEXT: [[OR3:%.*]] = xor i32 [[TMP1]], -1
; CHECK-NEXT: call void @use(i32 [[XOR1]])
; CHECK-NEXT: ret i32 [[OR3]]
;
@@ -2245,12 +2228,10 @@ define i32 @and_not_or_or_not_or_xor_use4(i32 %a, i32 %b, i32 %c) {
define i32 @and_not_or_or_not_or_xor_use5(i32 %a, i32 %b, i32 %c) {
; CHECK-LABEL: @and_not_or_or_not_or_xor_use5(
; CHECK-NEXT: [[OR1:%.*]] = or i32 [[B:%.*]], [[C:%.*]]
-; CHECK-NEXT: [[NOT1:%.*]] = xor i32 [[OR1]], -1
-; CHECK-NEXT: [[AND1:%.*]] = and i32 [[NOT1]], [[A:%.*]]
; CHECK-NEXT: [[XOR1:%.*]] = xor i32 [[B]], [[C]]
-; CHECK-NEXT: [[OR2:%.*]] = or i32 [[XOR1]], [[A]]
-; CHECK-NEXT: [[NOT2:%.*]] = xor i32 [[OR2]], -1
-; CHECK-NEXT: [[OR3:%.*]] = or i32 [[AND1]], [[NOT2]]
+; CHECK-NEXT: [[OR2:%.*]] = or i32 [[XOR1]], [[A:%.*]]
+; CHECK-NEXT: [[TMP1:%.*]] = and i32 [[OR1]], [[OR2]]
+; CHECK-NEXT: [[OR3:%.*]] = xor i32 [[TMP1]], -1
; CHECK-NEXT: call void @use(i32 [[OR2]])
; CHECK-NEXT: ret i32 [[OR3]]
;
@@ -2292,12 +2273,11 @@ define i32 @and_not_or_or_not_or_xor_use6(i32 %a, i32 %b, i32 %c) {
define i32 @or_not_and_and_not_and_xor(i32 %a, i32 %b, i32 %c) {
; CHECK-LABEL: @or_not_and_and_not_and_xor(
-; CHECK-NEXT: [[AND1:%.*]] = and i32 [[B:%.*]], [[C:%.*]]
-; CHECK-NEXT: [[NOT1:%.*]] = xor i32 [[AND1]], -1
-; CHECK-NEXT: [[OR1:%.*]] = or i32 [[NOT1]], [[A:%.*]]
-; CHECK-NEXT: [[XOR1:%.*]] = xor i32 [[B]], [[C]]
-; CHECK-NEXT: [[AND2:%.*]] = and i32 [[XOR1]], [[A]]
-; CHECK-NEXT: [[AND3:%.*]] = xor i32 [[AND2]], [[OR1]]
+; CHECK-NEXT: [[XOR1:%.*]] = xor i32 [[B:%.*]], [[C:%.*]]
+; CHECK-NEXT: [[TMP1:%.*]] = xor i32 [[XOR1]], [[A:%.*]]
+; CHECK-NEXT: [[TMP2:%.*]] = or i32 [[B]], [[A]]
+; CHECK-NEXT: [[TMP3:%.*]] = xor i32 [[TMP2]], -1
+; CHECK-NEXT: [[AND3:%.*]] = or i32 [[TMP1]], [[TMP3]]
; CHECK-NEXT: ret i32 [[AND3]]
;
%and1 = and i32 %b, %c
@@ -2312,12 +2292,11 @@ define i32 @or_not_and_and_not_and_xor(i32 %a, i32 %b, i32 %c) {
define i32 @or_not_and_and_not_and_xor_commute1(i32 %a, i32 %b, i32 %c) {
; CHECK-LABEL: @or_not_and_and_not_and_xor_commute1(
-; CHECK-NEXT: [[AND1:%.*]] = and i32 [[C:%.*]], [[B:%.*]]
-; CHECK-NEXT: [[NOT1:%.*]] = xor i32 [[AND1]], -1
-; CHECK-NEXT: [[OR1:%.*]] = or i32 [[NOT1]], [[A:%.*]]
-; CHECK-NEXT: [[XOR1:%.*]] = xor i32 [[B]], [[C]]
-; CHECK-NEXT: [[AND2:%.*]] = and i32 [[XOR1]], [[A]]
-; CHECK-NEXT: [[AND3:%.*]] = xor i32 [[AND2]], [[OR1]]
+; CHECK-NEXT: [[XOR1:%.*]] = xor i32 [[B:%.*]], [[C:%.*]]
+; CHECK-NEXT: [[TMP1:%.*]] = xor i32 [[XOR1]], [[A:%.*]]
+; CHECK-NEXT: [[TMP2:%.*]] = or i32 [[C]], [[A]]
+; CHECK-NEXT: [[TMP3:%.*]] = xor i32 [[TMP2]], -1
+; CHECK-NEXT: [[AND3:%.*]] = or i32 [[TMP1]], [[TMP3]]
; CHECK-NEXT: ret i32 [[AND3]]
;
%and1 = and i32 %c, %b
@@ -2333,12 +2312,11 @@ define i32 @or_not_and_and_not_and_xor_commute1(i32 %a, i32 %b, i32 %c) {
define i32 @or_not_and_and_not_and_xor_commute2(i32 %a0, i32 %b, i32 %c) {
; CHECK-LABEL: @or_not_and_and_not_and_xor_commute2(
; CHECK-NEXT: [[A:%.*]] = sdiv i32 42, [[A0:%.*]]
-; CHECK-NEXT: [[AND1:%.*]] = and i32 [[B:%.*]], [[C:%.*]]
-; CHECK-NEXT: [[NOT1:%.*]] = xor i32 [[AND1]], -1
-; CHECK-NEXT: [[OR1:%.*]] = or i32 [[A]], [[NOT1]]
-; CHECK-NEXT: [[XOR1:%.*]] = xor i32 [[B]], [[C]]
-; CHECK-NEXT: [[AND2:%.*]] = and i32 [[XOR1]], [[A]]
-; CHECK-NEXT: [[AND3:%.*]] = xor i32 [[AND2]], [[OR1]]
+; CHECK-NEXT: [[XOR1:%.*]] = xor i32 [[B:%.*]], [[C:%.*]]
+; CHECK-NEXT: [[TMP1:%.*]] = xor i32 [[XOR1]], [[A]]
+; CHECK-NEXT: [[TMP2:%.*]] = or i32 [[A]], [[B]]
+; CHECK-NEXT: [[TMP3:%.*]] = xor i32 [[TMP2]], -1
+; CHECK-NEXT: [[AND3:%.*]] = or i32 [[TMP1]], [[TMP3]]
; CHECK-NEXT: ret i32 [[AND3]]
;
%a = sdiv i32 42, %a0 ; thwart complexity-based canonicalization
@@ -2354,12 +2332,11 @@ define i32 @or_not_and_and_not_and_xor_commute2(i32 %a0, i32 %b, i32 %c) {
define i32 @or_not_and_and_not_and_xor_commute3(i32 %a, i32 %b, i32 %c) {
; CHECK-LABEL: @or_not_and_and_not_and_xor_commute3(
-; CHECK-NEXT: [[AND1:%.*]] = and i32 [[B:%.*]], [[C:%.*]]
-; CHECK-NEXT: [[NOT1:%.*]] = xor i32 [[AND1]], -1
-; CHECK-NEXT: [[OR1:%.*]] = or i32 [[NOT1]], [[A:%.*]]
-; CHECK-NEXT: [[XOR1:%.*]] = xor i32 [[C]], [[B]]
-; CHECK-NEXT: [[AND2:%.*]] = and i32 [[XOR1]], [[A]]
-; CHECK-NEXT: [[AND3:%.*]] = xor i32 [[AND2]], [[OR1]]
+; CHECK-NEXT: [[XOR1:%.*]] = xor i32 [[C:%.*]], [[B:%.*]]
+; CHECK-NEXT: [[TMP1:%.*]] = xor i32 [[XOR1]], [[A:%.*]]
+; CHECK-NEXT: [[TMP2:%.*]] = or i32 [[B]], [[A]]
+; CHECK-NEXT: [[TMP3:%.*]] = xor i32 [[TMP2]], -1
+; CHECK-NEXT: [[AND3:%.*]] = or i32 [[TMP1]], [[TMP3]]
; CHECK-NEXT: ret i32 [[AND3]]
;
%and1 = and i32 %b, %c
@@ -2375,12 +2352,11 @@ define i32 @or_not_and_and_not_and_xor_commute3(i32 %a, i32 %b, i32 %c) {
define i32 @or_not_and_and_not_and_xor_commute4(i32 %a0, i32 %b, i32 %c) {
; CHECK-LABEL: @or_not_and_and_not_and_xor_commute4(
; CHECK-NEXT: [[A:%.*]] = sdiv i32 42, [[A0:%.*]]
-; CHECK-NEXT: [[AND1:%.*]] = and i32 [[B:%.*]], [[C:%.*]]
-; CHECK-NEXT: [[NOT1:%.*]] = xor i32 [[AND1]], -1
-; CHECK-NEXT: [[OR1:%.*]] = or i32 [[A]], [[NOT1]]
-; CHECK-NEXT: [[XOR1:%.*]] = xor i32 [[B]], [[C]]
-; CHECK-NEXT: [[AND2:%.*]] = and i32 [[A]], [[XOR1]]
-; CHECK-NEXT: [[AND3:%.*]] = xor i32 [[AND2]], [[OR1]]
+; CHECK-NEXT: [[XOR1:%.*]] = xor i32 [[B:%.*]], [[C:%.*]]
+; CHECK-NEXT: [[TMP1:%.*]] = xor i32 [[XOR1]], [[A]]
+; CHECK-NEXT: [[TMP2:%.*]] = or i32 [[A]], [[B]]
+; CHECK-NEXT: [[TMP3:%.*]] = xor i32 [[TMP2]], -1
+; CHECK-NEXT: [[AND3:%.*]] = or i32 [[TMP1]], [[TMP3]]
; CHECK-NEXT: ret i32 [[AND3]]
;
%a = sdiv i32 42, %a0 ; thwart complexity-based canonicalization
@@ -2396,12 +2372,11 @@ define i32 @or_not_and_and_not_and_xor_commute4(i32 %a0, i32 %b, i32 %c) {
define i32 @or_not_and_and_not_and_xor_commute5(i32 %a, i32 %b, i32 %c) {
; CHECK-LABEL: @or_not_and_and_not_and_xor_commute5(
-; CHECK-NEXT: [[AND1:%.*]] = and i32 [[B:%.*]], [[C:%.*]]
-; CHECK-NEXT: [[NOT1:%.*]] = xor i32 [[AND1]], -1
-; CHECK-NEXT: [[OR1:%.*]] = or i32 [[NOT1]], [[A:%.*]]
-; CHECK-NEXT: [[XOR1:%.*]] = xor i32 [[B]], [[C]]
-; CHECK-NEXT: [[AND2:%.*]] = and i32 [[XOR1]], [[A]]
-; CHECK-NEXT: [[AND3:%.*]] = xor i32 [[AND2]], [[OR1]]
+; CHECK-NEXT: [[XOR1:%.*]] = xor i32 [[B:%.*]], [[C:%.*]]
+; CHECK-NEXT: [[TMP1:%.*]] = xor i32 [[XOR1]], [[A:%.*]]
+; CHECK-NEXT: [[TMP2:%.*]] = or i32 [[B]], [[A]]
+; CHECK-NEXT: [[TMP3:%.*]] = xor i32 [[TMP2]], -1
+; CHECK-NEXT: [[AND3:%.*]] = or i32 [[TMP1]], [[TMP3]]
; CHECK-NEXT: ret i32 [[AND3]]
;
%and1 = and i32 %b, %c
@@ -2482,12 +2457,11 @@ define i32 @or_not_and_and_not_and_xor_use3(i32 %a, i32 %b, i32 %c) {
define i32 @or_not_and_and_not_and_xor_use4(i32 %a, i32 %b, i32 %c) {
; CHECK-LABEL: @or_not_and_and_not_and_xor_use4(
-; CHECK-NEXT: [[AND1:%.*]] = and i32 [[B:%.*]], [[C:%.*]]
-; CHECK-NEXT: [[NOT1:%.*]] = xor i32 [[AND1]], -1
-; CHECK-NEXT: [[OR1:%.*]] = or i32 [[NOT1]], [[A:%.*]]
-; CHECK-NEXT: [[XOR1:%.*]] = xor i32 [[B]], [[C]]
-; CHECK-NEXT: [[AND2:%.*]] = and i32 [[XOR1]], [[A]]
-; CHECK-NEXT: [[AND3:%.*]] = xor i32 [[AND2]], [[OR1]]
+; CHECK-NEXT: [[XOR1:%.*]] = xor i32 [[B:%.*]], [[C:%.*]]
+; CHECK-NEXT: [[TMP1:%.*]] = xor i32 [[XOR1]], [[A:%.*]]
+; CHECK-NEXT: [[TMP2:%.*]] = or i32 [[B]], [[A]]
+; CHECK-NEXT: [[TMP3:%.*]] = xor i32 [[TMP2]], -1
+; CHECK-NEXT: [[AND3:%.*]] = or i32 [[TMP1]], [[TMP3]]
; CHECK-NEXT: call void @use(i32 [[XOR1]])
; CHECK-NEXT: ret i32 [[AND3]]
;
More information about the llvm-commits
mailing list