add one more bitfield optimization, allowing clang to generate
authorChris Lattner <sabre@nondot.org>
Mon, 11 Jan 2010 06:55:24 +0000 (06:55 +0000)
committerChris Lattner <sabre@nondot.org>
Mon, 11 Jan 2010 06:55:24 +0000 (06:55 +0000)
good code on PR4216:

_test_bitfield:                                             ## @test_bitfield
orl $32962, %edi
movl $4294941946, %eax
andq %rdi, %rax
ret

instead of:

_test_bitfield:
        movl    $4294941696, %ecx
        movl    %edi, %eax
        orl     $194, %edi
        orl     $32768, %eax
        andq    $250, %rdi
        andq    %rax, %rcx
        movq    %rdi, %rax
        orq     %rcx, %rax
        ret

Evan is looking into the remaining andq+imm -> andl optimization.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@93147 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
test/Transforms/InstCombine/or.ll

index a8dd1b88c9738dbe5599fb36d484aacb4cb3f241..af300fc3577b187a68860459d6df9850a6ee0cdd 100644 (file)
@@ -1544,9 +1544,9 @@ Instruction *InstCombiner::visitOr(BinaryOperator &I) {
         }
       }
       
-      // ((V | N) & C1) | (V & C2) --> (V|N) & (C1|C2)
-      // iff (C1&C2) == 0 and (N&~C1) == 0
       if ((C1->getValue() & C2->getValue()) == 0) {
+        // ((V | N) & C1) | (V & C2) --> (V|N) & (C1|C2)
+        // iff (C1&C2) == 0 and (N&~C1) == 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)
@@ -1560,6 +1560,19 @@ Instruction *InstCombiner::visitOr(BinaryOperator &I) {
           return BinaryOperator::CreateAnd(B,
                                ConstantInt::get(B->getContext(),
                                                 C1->getValue()|C2->getValue()));
+        
+        // ((V|C3)&C1) | ((V|C4)&C2) --> (V|C3|C4)&(C1|C2)
+        // iff (C1&C2) == 0 and (C3&~C1) == 0 and (C4&~C2) == 0.
+        ConstantInt *C3 = 0, *C4 = 0;
+        if (match(A, m_Or(m_Value(V1), m_ConstantInt(C3))) &&
+            (C3->getValue() & ~C1->getValue()) == 0 &&
+            match(B, m_Or(m_Specific(V1), m_ConstantInt(C4))) &&
+            (C4->getValue() & ~C2->getValue()) == 0) {
+          V2 = Builder->CreateOr(V1, ConstantExpr::getOr(C3, C4), "bitfield");
+          return BinaryOperator::CreateAnd(V2,
+                               ConstantInt::get(B->getContext(),
+                                                C1->getValue()|C2->getValue()));
+        }
       }
     }
     
index 822dfb3d55073066b4c0964ce6d1c88c98a08994..2040f3da8f9cee9a9878be94bb508c50e451cd70 100644 (file)
@@ -320,3 +320,19 @@ entry:
 ; CHECK: %E = and i32 %B, -25350
 ; CHECK: ret i32 %E
 }
+
+; PR4216
+define i64 @test31(i64 %A) nounwind readnone ssp noredzone {
+  %B = or i64 %A, 194
+  %D = and i64 %B, 250
+
+  %C = or i64 %A, 32768
+  %E = and i64 %C, 4294941696
+
+  %F = or i64 %D, %E
+  ret i64 %F
+; CHECK: @test31
+; CHECK-NEXT: %bitfield = or i64 %A, 32962
+; CHECK-NEXT: %F = and i64 %bitfield, 4294941946
+; CHECK-NEXT: ret i64 %F
+}