Implement or.ll:test21. This teaches instcombine to be able to turn this:
authorChris Lattner <sabre@nondot.org>
Sun, 18 Sep 2005 03:42:07 +0000 (03:42 +0000)
committerChris Lattner <sabre@nondot.org>
Sun, 18 Sep 2005 03:42:07 +0000 (03:42 +0000)
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

lib/Transforms/Scalar/InstructionCombining.cpp

index 13c0977cb3044ad07c2cbf5cf1b782df1a7e1c5d..72bc34074ccb4da34380e4197152c3d3ff8a5242 100644 (file)
@@ -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;
 }