From e4412c1f0b636980d77a518b76e94559830eeaed Mon Sep 17 00:00:00 2001 From: Chris Lattner Date: Mon, 4 Jan 2010 06:03:59 +0000 Subject: [PATCH] implement an instcombine xform needed by clang's codegen on the example in PR4216. This doesn't trigger in the testsuite, so I'd really appreciate someone scrutinizing the logic for correctness. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@92458 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Target/README.txt | 13 ------------ .../Scalar/InstructionCombining.cpp | 20 ++++++++++++++++++- test/Transforms/InstCombine/or.ll | 13 ++++++++++++ 3 files changed, 32 insertions(+), 14 deletions(-) diff --git a/lib/Target/README.txt b/lib/Target/README.txt index a6e05fadefd..22dadfeb3dd 100644 --- a/lib/Target/README.txt +++ b/lib/Target/README.txt @@ -282,19 +282,6 @@ this requires TBAA. //===---------------------------------------------------------------------===// -This should be optimized to one 'and' and one 'or', from PR4216: - -define i32 @test_bitfield(i32 %bf.prev.low) nounwind ssp { -entry: - %bf.prev.lo.cleared10 = or i32 %bf.prev.low, 32962 ; [#uses=1] - %0 = and i32 %bf.prev.low, -65536 ; [#uses=1] - %1 = and i32 %bf.prev.lo.cleared10, 40186 ; [#uses=1] - %2 = or i32 %1, %0 ; [#uses=1] - ret i32 %2 -} - -//===---------------------------------------------------------------------===// - This isn't recognized as bswap by instcombine (yes, it really is bswap): unsigned long reverse(unsigned v) { diff --git a/lib/Transforms/Scalar/InstructionCombining.cpp b/lib/Transforms/Scalar/InstructionCombining.cpp index 363d8798f31..03885a5e05a 100644 --- a/lib/Transforms/Scalar/InstructionCombining.cpp +++ b/lib/Transforms/Scalar/InstructionCombining.cpp @@ -5213,12 +5213,30 @@ Instruction *InstCombiner::visitOr(BinaryOperator &I) { return ReplaceInstUsesWith(I, B); } } - V1 = 0; V2 = 0; V3 = 0; + + // ((V | N) & C1) | (V & C2) --> (V|N) & (C1|C2) + // iff (C1&C2) == 0 and (N&~C1) == 0 + if ((C1->getValue() & C2->getValue()) == 0) { + if (match(A, m_Or(m_Value(V1), m_Value(V2))) && + ((V1 == B && MaskedValueIsZero(V2, ~C1->getValue())) || // (V|N) + (V2 == B && MaskedValueIsZero(V1, ~C1->getValue())))) // (N|V) + return BinaryOperator::CreateAnd(A, + ConstantInt::get(A->getContext(), + C1->getValue()|C2->getValue())); + // Or commutes, try both ways. + if (match(B, m_Or(m_Value(V1), m_Value(V2))) && + ((V1 == A && MaskedValueIsZero(V2, ~C2->getValue())) || // (V|N) + (V2 == A && MaskedValueIsZero(V1, ~C2->getValue())))) // (N|V) + return BinaryOperator::CreateAnd(B, + ConstantInt::get(B->getContext(), + C1->getValue()|C2->getValue())); + } } // Check to see if we have any common things being and'ed. If so, find the // terms for V1 & (V2|V3). if (isOnlyUse(Op0) || isOnlyUse(Op1)) { + V1 = 0; if (A == B) // (A & C)|(A & D) == A & (C|D) V1 = A, V2 = C, V3 = D; else if (A == D) // (A & C)|(B & A) == A & (B|C) diff --git a/test/Transforms/InstCombine/or.ll b/test/Transforms/InstCombine/or.ll index 44228ba357c..822dfb3d550 100644 --- a/test/Transforms/InstCombine/or.ll +++ b/test/Transforms/InstCombine/or.ll @@ -307,3 +307,16 @@ define i1 @test29(i32* %A, i32* %B) { ; CHECK: ret i1 } +; PR4216 +define i32 @test30(i32 %A) { +entry: + %B = or i32 %A, 32962 + %C = and i32 %A, -65536 + %D = and i32 %B, 40186 + %E = or i32 %D, %C + ret i32 %E +; CHECK: @test30 +; CHECK: %B = or i32 %A, 32962 +; CHECK: %E = and i32 %B, -25350 +; CHECK: ret i32 %E +} -- 2.34.1