aboutsummaryrefslogtreecommitdiffstats
path: root/lib/Transforms
diff options
context:
space:
mode:
authorChris Lattner <sabre@nondot.org>2005-09-18 03:42:07 +0000
committerChris Lattner <sabre@nondot.org>2005-09-18 03:42:07 +0000
commite9bed7d10759e86634793d6589f894d1e44f43e8 (patch)
treeac7bce9fb8289eeaae35ed991d17d26898a7b9f5 /lib/Transforms
parent1e122d1dc297f9386c11916df86fa0245b61041f (diff)
downloadexternal_llvm-e9bed7d10759e86634793d6589f894d1e44f43e8.zip
external_llvm-e9bed7d10759e86634793d6589f894d1e44f43e8.tar.gz
external_llvm-e9bed7d10759e86634793d6589f894d1e44f43e8.tar.bz2
Implement or.ll:test21. This teaches instcombine to be able to turn this:
struct { unsigned int bit0:1; unsigned int ubyte:31; } sdata; void foo() { sdata.ubyte++; } into this: foo: add DWORD PTR [sdata], 2 ret instead of this: foo: mov %EAX, DWORD PTR [sdata] mov %ECX, %EAX add %ECX, 2 and %ECX, -2 and %EAX, 1 or %EAX, %ECX mov DWORD PTR [sdata], %EAX ret git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@23376 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Transforms')
-rw-r--r--lib/Transforms/Scalar/InstructionCombining.cpp28
1 files changed, 25 insertions, 3 deletions
diff --git a/lib/Transforms/Scalar/InstructionCombining.cpp b/lib/Transforms/Scalar/InstructionCombining.cpp
index 13c0977..72bc340 100644
--- a/lib/Transforms/Scalar/InstructionCombining.cpp
+++ b/lib/Transforms/Scalar/InstructionCombining.cpp
@@ -1921,10 +1921,31 @@ Instruction *InstCombiner::visitOr(BinaryOperator &I) {
return BinaryOperator::createXor(InsertNewInstBefore(NOr, I), C1);
}
- // (A & C1)|(A & C2) == A & (C1|C2)
+ // (A & C1)|(B & C2)
if (match(Op0, m_And(m_Value(A), m_ConstantInt(C1))) &&
- match(Op1, m_And(m_Value(B), m_ConstantInt(C2))) && A == B)
- return BinaryOperator::createAnd(A, ConstantExpr::getOr(C1, C2));
+ match(Op1, m_And(m_Value(B), m_ConstantInt(C2)))) {
+
+ if (A == B) // (A & C1)|(A & C2) == A & (C1|C2)
+ return BinaryOperator::createAnd(A, ConstantExpr::getOr(C1, C2));
+
+
+ // if A == (add B, C3) or B == (add A, C4)
+ ConstantInt *C3 = 0;
+ Value *V = 0;
+ if ((match(A, m_Add(m_Value(V), m_ConstantInt(C3))) && V == B ||
+ match(B, m_Add(m_Value(V), m_ConstantInt(C3))) && V == A)) {
+ if (V == A) std::swap(C1, C2);
+ // We have: ((V + C3) & C1) | (V & C2)
+ // if C2 = ~C1 and (C3 & C2) == 0 and C2 is 0+1+
+ if (C1 == ConstantExpr::getNot(C2) &&
+ ConstantExpr::getAnd(C3, C2)->isNullValue() &&
+ (C2->getRawValue() & (C2->getRawValue()+1)) == 0) {
+ // Return V+C3.
+ std::cerr << "Simpl: " << *A << "Simpl2: " << *B << "Simpl3: " << I;
+ return ReplaceInstUsesWith(I, V == A ? B : A);
+ }
+ }
+ }
if (match(Op0, m_Not(m_Value(A)))) { // ~A | Op1
if (A == Op1) // ~A | A == -1
@@ -2040,6 +2061,7 @@ Instruction *InstCombiner::visitOr(BinaryOperator &I) {
}
}
}
+
return Changed ? &I : 0;
}