summaryrefslogtreecommitdiffstats
path: root/llvm/lib
diff options
context:
space:
mode:
authorBill Wendling <isanbard@gmail.com>2008-12-01 01:07:11 +0000
committerBill Wendling <isanbard@gmail.com>2008-12-01 01:07:11 +0000
commit5b902c5b1ea925f4a95cb8876836a8ed85cc78c3 (patch)
tree29e9a27913679e6ce3e13ab107ded5984a5e3935 /llvm/lib
parent6f0730ff1110c196173096f7170de7b0ad990803 (diff)
downloadbcm5719-llvm-5b902c5b1ea925f4a95cb8876836a8ed85cc78c3.tar.gz
bcm5719-llvm-5b902c5b1ea925f4a95cb8876836a8ed85cc78c3.zip
Implement ((A|B)&1)|(B&-2) -> (A&1) | B transformation. This also takes care of
permutations of this pattern. llvm-svn: 60312
Diffstat (limited to 'llvm/lib')
-rw-r--r--llvm/lib/Target/README.txt6
-rw-r--r--llvm/lib/Transforms/Scalar/InstructionCombining.cpp67
2 files changed, 67 insertions, 6 deletions
diff --git a/llvm/lib/Target/README.txt b/llvm/lib/Target/README.txt
index 17b830d5d4a..fb6b0cd53d5 100644
--- a/llvm/lib/Target/README.txt
+++ b/llvm/lib/Target/README.txt
@@ -1147,12 +1147,6 @@ There's an unnecessary zext in the generated code with "clang
//===---------------------------------------------------------------------===//
-int a(int a, int b) {return ((a|b)&1) | (b&-2);}
-Should be combined to "(a&1)|b". Currently not optimized with "clang
--emit-llvm-bc | opt -std-compile-opts".
-
-//===---------------------------------------------------------------------===//
-
int a(unsigned b) {return ((b << 31) | (b << 30)) >> 31;}
Should be combined to "((b >> 1) | b) & 1". Currently not optimized
with "clang -emit-llvm-bc | opt -std-compile-opts".
diff --git a/llvm/lib/Transforms/Scalar/InstructionCombining.cpp b/llvm/lib/Transforms/Scalar/InstructionCombining.cpp
index 9cb1875b958..4e2e8a409bc 100644
--- a/llvm/lib/Transforms/Scalar/InstructionCombining.cpp
+++ b/llvm/lib/Transforms/Scalar/InstructionCombining.cpp
@@ -4649,6 +4649,73 @@ Instruction *InstCombiner::visitOr(BinaryOperator &I) {
}
}
+ // ((A|B)&1)|(B&-2) -> (A&1) | B
+ if (match(Op0, m_And(m_Or(m_Value(A), m_Value(B)), m_Value(C))) ||
+ match(Op0, m_And(m_Value(C), m_Or(m_Value(A), m_Value(B))))) {
+ if (ConstantInt *CI = dyn_cast<ConstantInt>(C)) {
+ if (CI->getValue() == 1) {
+ Value *V1 = 0, *C2 = 0;
+ if (match(Op1, m_And(m_Value(V1), m_Value(C2)))) {
+ ConstantInt *CI2 = dyn_cast<ConstantInt>(C2);
+
+ if (!CI2) {
+ std::swap(V1, C2);
+ CI2 = dyn_cast<ConstantInt>(C2);
+ }
+
+ if (CI2) {
+ APInt NegTwo = -APInt(CI2->getValue().getBitWidth(), 2, true);
+ if (CI2->getValue().eq(NegTwo)) {
+ if (V1 == B) {
+ Instruction *NewOp =
+ InsertNewInstBefore(BinaryOperator::CreateAnd(A, CI), I);
+ return BinaryOperator::CreateOr(NewOp, B);
+ }
+ if (V1 == A) {
+ Instruction *NewOp =
+ InsertNewInstBefore(BinaryOperator::CreateAnd(B, CI), I);
+ return BinaryOperator::CreateOr(NewOp, A);
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ // (B&-2)|((A|B)&1) -> (A&1) | B
+ if (match(Op1, m_And(m_Or(m_Value(A), m_Value(B)), m_Value(C))) ||
+ match(Op1, m_And(m_Value(C), m_Or(m_Value(A), m_Value(B))))) {
+ if (ConstantInt *CI = dyn_cast<ConstantInt>(C)) {
+ if (CI->getValue() == 1) {
+ Value *V1 = 0, *C2 = 0;
+ if (match(Op0, m_And(m_Value(V1), m_Value(C2)))) {
+ ConstantInt *CI2 = dyn_cast<ConstantInt>(C2);
+
+ if (!CI2) {
+ std::swap(V1, C2);
+ CI2 = dyn_cast<ConstantInt>(C2);
+ }
+
+ if (CI2) {
+ APInt NegTwo = -APInt(CI2->getValue().getBitWidth(), 2, true);
+ if (CI2->getValue().eq(NegTwo)) {
+ if (V1 == B) {
+ Instruction *NewOp =
+ InsertNewInstBefore(BinaryOperator::CreateAnd(A, CI), I);
+ return BinaryOperator::CreateOr(NewOp, B);
+ }
+ if (V1 == A) {
+ Instruction *NewOp =
+ InsertNewInstBefore(BinaryOperator::CreateAnd(B, CI), I);
+ return BinaryOperator::CreateOr(NewOp, A);
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
if (match(Op0, m_Not(m_Value(A)))) { // ~A | Op1
if (A == Op1) // ~A | A == -1
return ReplaceInstUsesWith(I, Constant::getAllOnesValue(I.getType()));
OpenPOWER on IntegriCloud