aboutsummaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
authorChris Lattner <sabre@nondot.org>2010-01-04 06:03:59 +0000
committerChris Lattner <sabre@nondot.org>2010-01-04 06:03:59 +0000
commit4fcef8a8554259481cc451079eec65059fe68a2e (patch)
treec9a87c184827577f46b5ab6a46bea23b70ee068b /lib
parent991876a06d263c5fd22c99648c77a810bc0dea06 (diff)
downloadexternal_llvm-4fcef8a8554259481cc451079eec65059fe68a2e.zip
external_llvm-4fcef8a8554259481cc451079eec65059fe68a2e.tar.gz
external_llvm-4fcef8a8554259481cc451079eec65059fe68a2e.tar.bz2
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
Diffstat (limited to 'lib')
-rw-r--r--lib/Target/README.txt13
-rw-r--r--lib/Transforms/Scalar/InstructionCombining.cpp20
2 files changed, 19 insertions, 14 deletions
diff --git a/lib/Target/README.txt b/lib/Target/README.txt
index a6e05fa..22dadfe 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 ; <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) {
diff --git a/lib/Transforms/Scalar/InstructionCombining.cpp b/lib/Transforms/Scalar/InstructionCombining.cpp
index 363d879..03885a5 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)