aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChris Lattner <sabre@nondot.org>2010-01-11 06:55:24 +0000
committerChris Lattner <sabre@nondot.org>2010-01-11 06:55:24 +0000
commit8e76764de86d7906db5123626b65f593e159d9f3 (patch)
tree2ceb1b4cbdd050c6c96bdb99bf354ca4bff32a09
parent7acc4b12813117774deefb54c5febb49a215aa70 (diff)
add one more bitfield optimization, allowing clang to generate
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
-rw-r--r--lib/Transforms/InstCombine/InstCombineAndOrXor.cpp17
-rw-r--r--test/Transforms/InstCombine/or.ll16
2 files changed, 31 insertions, 2 deletions
diff --git a/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp b/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
index a8dd1b88c9..af300fc357 100644
--- a/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
+++ b/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
@@ -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()));
+ }
}
}
diff --git a/test/Transforms/InstCombine/or.ll b/test/Transforms/InstCombine/or.ll
index 822dfb3d55..2040f3da8f 100644
--- a/test/Transforms/InstCombine/or.ll
+++ b/test/Transforms/InstCombine/or.ll
@@ -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
+}