diff options
| author | Craig Topper <craig.topper@intel.com> | 2017-08-10 20:35:34 +0000 |
|---|---|---|
| committer | Craig Topper <craig.topper@intel.com> | 2017-08-10 20:35:34 +0000 |
| commit | 9a6110b2d3ea6c037923aff08c21e047999c5a47 (patch) | |
| tree | 6ad00a591fe320f4f8f857af817e2f8179ed699d /llvm | |
| parent | 699ae0c173bd9f9a38523a7de354f5e9cc602ecc (diff) | |
| download | bcm5719-llvm-9a6110b2d3ea6c037923aff08c21e047999c5a47.tar.gz bcm5719-llvm-9a6110b2d3ea6c037923aff08c21e047999c5a47.zip | |
[InstCombine] Make (X|C1)^C2 -> X^(C1^C2) iff X&~C1 == 0 work for splat vectors
This also corrects the description to match what was actually implemented. The old comment said X^(C1|C2), but it implemented X^((C1|C2)&~(C1&C2)). I believe ((C1|C2)&~(C1&C2)) is equivalent to (C1^C2).
Differential Revision: https://reviews.llvm.org/D36505
llvm-svn: 310658
Diffstat (limited to 'llvm')
| -rw-r--r-- | llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp | 41 | ||||
| -rw-r--r-- | llvm/test/Transforms/InstCombine/or.ll | 13 | ||||
| -rw-r--r-- | llvm/test/Transforms/InstCombine/select-with-bitwise-ops.ll | 17 |
3 files changed, 38 insertions, 33 deletions
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp b/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp index bc8b0496ec7..5a13bbce835 100644 --- a/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp @@ -2365,53 +2365,48 @@ Instruction *InstCombiner::visitXor(BinaryOperator &I) { { const APInt *RHSC; if (match(Op1, m_APInt(RHSC))) { - Value *V; + Value *X; const APInt *C; - if (match(Op0, m_Sub(m_APInt(C), m_Value(V)))) { + if (match(Op0, m_Sub(m_APInt(C), m_Value(X)))) { // ~(c-X) == X-c-1 == X+(-c-1) if (RHSC->isAllOnesValue()) { Constant *NewC = ConstantInt::get(I.getType(), -(*C) - 1); - return BinaryOperator::CreateAdd(V, NewC); + return BinaryOperator::CreateAdd(X, NewC); } if (RHSC->isSignMask()) { // (C - X) ^ signmask -> (C + signmask - X) Constant *NewC = ConstantInt::get(I.getType(), *C + *RHSC); - return BinaryOperator::CreateSub(NewC, V); + return BinaryOperator::CreateSub(NewC, X); } - } else if (match(Op0, m_Add(m_Value(V), m_APInt(C)))) { + } else if (match(Op0, m_Add(m_Value(X), m_APInt(C)))) { // ~(X-c) --> (-c-1)-X if (RHSC->isAllOnesValue()) { Constant *NewC = ConstantInt::get(I.getType(), -(*C) - 1); - return BinaryOperator::CreateSub(NewC, V); + return BinaryOperator::CreateSub(NewC, X); } if (RHSC->isSignMask()) { // (X + C) ^ signmask -> (X + C + signmask) Constant *NewC = ConstantInt::get(I.getType(), *C + *RHSC); - return BinaryOperator::CreateAdd(V, NewC); + return BinaryOperator::CreateAdd(X, NewC); } } + + // (X|C1)^C2 -> X^(C1^C2) iff X&~C1 == 0 + if (match(Op0, m_Or(m_Value(X), m_APInt(C))) && + MaskedValueIsZero(X, *C, 0, &I)) { + Constant *NewC = ConstantInt::get(I.getType(), *C ^ *RHSC); + Worklist.Add(cast<Instruction>(Op0)); + I.setOperand(0, X); + I.setOperand(1, NewC); + return &I; + } } } if (ConstantInt *RHSC = dyn_cast<ConstantInt>(Op1)) { if (BinaryOperator *Op0I = dyn_cast<BinaryOperator>(Op0)) { if (ConstantInt *Op0CI = dyn_cast<ConstantInt>(Op0I->getOperand(1))) { - if (Op0I->getOpcode() == Instruction::Or) { - // (X|C1)^C2 -> X^(C1|C2) iff X&~C1 == 0 - if (MaskedValueIsZero(Op0I->getOperand(0), Op0CI->getValue(), - 0, &I)) { - Constant *NewRHS = ConstantExpr::getOr(Op0CI, RHSC); - // Anything in both C1 and C2 is known to be zero, remove it from - // NewRHS. - Constant *CommonBits = ConstantExpr::getAnd(Op0CI, RHSC); - NewRHS = ConstantExpr::getAnd(NewRHS, - ConstantExpr::getNot(CommonBits)); - Worklist.Add(Op0I); - I.setOperand(0, Op0I->getOperand(0)); - I.setOperand(1, NewRHS); - return &I; - } - } else if (Op0I->getOpcode() == Instruction::LShr) { + if (Op0I->getOpcode() == Instruction::LShr) { // ((X^C1) >> C2) ^ C3 -> (X>>C2) ^ ((C1>>C2)^C3) // E1 = "X ^ C1" BinaryOperator *E1; diff --git a/llvm/test/Transforms/InstCombine/or.ll b/llvm/test/Transforms/InstCombine/or.ll index 96907cf2bd5..6a4ed05c399 100644 --- a/llvm/test/Transforms/InstCombine/or.ll +++ b/llvm/test/Transforms/InstCombine/or.ll @@ -143,6 +143,19 @@ define i16 @test23(i16 %A) { ret i16 %D } +define <2 x i16> @test23vec(<2 x i16> %A) { +; CHECK-LABEL: @test23vec( +; CHECK-NEXT: [[B:%.*]] = lshr <2 x i16> [[A:%.*]], <i16 1, i16 1> +; CHECK-NEXT: [[D:%.*]] = xor <2 x i16> [[B]], <i16 -24575, i16 -24575> +; CHECK-NEXT: ret <2 x i16> [[D]] +; + %B = lshr <2 x i16> %A, <i16 1, i16 1> + ;; fold or into xor + %C = or <2 x i16> %B, <i16 -32768, i16 -32768> + %D = xor <2 x i16> %C, <i16 8193, i16 8193> + ret <2 x i16> %D +} + ; PR1738 define i1 @test24(double %X, double %Y) { ; CHECK-LABEL: @test24( diff --git a/llvm/test/Transforms/InstCombine/select-with-bitwise-ops.ll b/llvm/test/Transforms/InstCombine/select-with-bitwise-ops.ll index 39912c9c09d..602c05478a5 100644 --- a/llvm/test/Transforms/InstCombine/select-with-bitwise-ops.ll +++ b/llvm/test/Transforms/InstCombine/select-with-bitwise-ops.ll @@ -273,9 +273,8 @@ define <2 x i32> @test65vec(<2 x i64> %x) { ; CHECK-NEXT: [[TMP1:%.*]] = lshr <2 x i64> [[X:%.*]], <i64 3, i64 3> ; CHECK-NEXT: [[TMP2:%.*]] = trunc <2 x i64> [[TMP1]] to <2 x i32> ; CHECK-NEXT: [[TMP3:%.*]] = and <2 x i32> [[TMP2]], <i32 2, i32 2> -; CHECK-NEXT: [[TMP4:%.*]] = or <2 x i32> [[TMP3]], <i32 40, i32 40> -; CHECK-NEXT: [[TMP5:%.*]] = xor <2 x i32> [[TMP4]], <i32 2, i32 2> -; CHECK-NEXT: ret <2 x i32> [[TMP5]] +; CHECK-NEXT: [[TMP4:%.*]] = xor <2 x i32> [[TMP3]], <i32 42, i32 42> +; CHECK-NEXT: ret <2 x i32> [[TMP4]] ; %1 = and <2 x i64> %x, <i64 16, i64 16> %2 = icmp ne <2 x i64> %1, zeroinitializer @@ -302,9 +301,8 @@ define <2 x i32> @test66vec(<2 x i64> %x) { ; CHECK-NEXT: [[TMP1:%.*]] = lshr <2 x i64> [[X:%.*]], <i64 31, i64 31> ; CHECK-NEXT: [[TMP2:%.*]] = trunc <2 x i64> [[TMP1]] to <2 x i32> ; CHECK-NEXT: [[TMP3:%.*]] = and <2 x i32> [[TMP2]], <i32 2, i32 2> -; CHECK-NEXT: [[TMP4:%.*]] = or <2 x i32> [[TMP3]], <i32 40, i32 40> -; CHECK-NEXT: [[TMP5:%.*]] = xor <2 x i32> [[TMP4]], <i32 2, i32 2> -; CHECK-NEXT: ret <2 x i32> [[TMP5]] +; CHECK-NEXT: [[TMP4:%.*]] = xor <2 x i32> [[TMP3]], <i32 42, i32 42> +; CHECK-NEXT: ret <2 x i32> [[TMP4]] ; %1 = and <2 x i64> %x, <i64 4294967296, i64 4294967296> %2 = icmp ne <2 x i64> %1, zeroinitializer @@ -344,10 +342,9 @@ define <2 x i32> @test67vec(<2 x i16> %x) { ; CHECK-LABEL: @test67vec( ; CHECK-NEXT: [[TMP1:%.*]] = lshr <2 x i16> [[X:%.*]], <i16 1, i16 1> ; CHECK-NEXT: [[TMP2:%.*]] = and <2 x i16> [[TMP1]], <i16 2, i16 2> -; CHECK-NEXT: [[TMP3:%.*]] = or <2 x i16> [[TMP2]], <i16 40, i16 40> -; CHECK-NEXT: [[TMP4:%.*]] = xor <2 x i16> [[TMP3]], <i16 2, i16 2> -; CHECK-NEXT: [[TMP5:%.*]] = zext <2 x i16> [[TMP4]] to <2 x i32> -; CHECK-NEXT: ret <2 x i32> [[TMP5]] +; CHECK-NEXT: [[TMP3:%.*]] = xor <2 x i16> [[TMP2]], <i16 42, i16 42> +; CHECK-NEXT: [[TMP4:%.*]] = zext <2 x i16> [[TMP3]] to <2 x i32> +; CHECK-NEXT: ret <2 x i32> [[TMP4]] ; %1 = and <2 x i16> %x, <i16 4, i16 4> %2 = icmp ne <2 x i16> %1, zeroinitializer |

