mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-12-16 16:16:45 +00:00
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. llvm-svn: 92458
This commit is contained in:
parent
8e83066d12
commit
ce3f5f3448
@ -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 ; <i32> [#uses=1]
|
||||
%0 = and i32 %bf.prev.low, -65536 ; <i32> [#uses=1]
|
||||
%1 = and i32 %bf.prev.lo.cleared10, 40186 ; <i32> [#uses=1]
|
||||
%2 = or i32 %1, %0 ; <i32> [#uses=1]
|
||||
ret i32 %2
|
||||
}
|
||||
|
||||
//===---------------------------------------------------------------------===//
|
||||
|
||||
This isn't recognized as bswap by instcombine (yes, it really is bswap):
|
||||
|
||||
unsigned long reverse(unsigned v) {
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user