From: Chris Lattner Date: Mon, 4 Jan 2010 06:03:59 +0000 (+0000) Subject: implement an instcombine xform needed by clang's codegen X-Git-Url: http://demsky.eecs.uci.edu/git/?a=commitdiff_plain;h=e4412c1f0b636980d77a518b76e94559830eeaed;p=oota-llvm.git 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 --- 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 +}