summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBenjamin Kramer <benny.kra@googlemail.com>2010-12-11 10:49:22 +0000
committerBenjamin Kramer <benny.kra@googlemail.com>2010-12-11 10:49:22 +0000
commit2f7228b80c6a129fa1d8eef8c3075085003d5b87 (patch)
treeaacb8a9b0c2bd9c3c104daf4eb3d1c7bcfadb862
parent20e3b4b380e949af32eeb4f184c51bfd62286f1a (diff)
downloadllvm-2f7228b80c6a129fa1d8eef8c3075085003d5b87.tar.gz
llvm-2f7228b80c6a129fa1d8eef8c3075085003d5b87.tar.bz2
llvm-2f7228b80c6a129fa1d8eef8c3075085003d5b87.tar.xz
Generalize the and-icmp-select instcombine further by allowing selects of the form
(x & 2^n) ? 2^m+C : C we can offset both arms by C to get the "(x & 2^n) ? 2^m : 0" form, optimize the select to a shift and apply the offset afterwards. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@121609 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--lib/Target/README.txt12
-rw-r--r--lib/Transforms/InstCombine/InstCombineSelect.cpp26
-rw-r--r--test/Transforms/InstCombine/select.ll50
3 files changed, 72 insertions, 16 deletions
diff --git a/lib/Target/README.txt b/lib/Target/README.txt
index 38f5af642d..35273344d7 100644
--- a/lib/Target/README.txt
+++ b/lib/Target/README.txt
@@ -1055,18 +1055,6 @@ Should also combine to x | 8. Currently not optimized with "clang
//===---------------------------------------------------------------------===//
-int a(int x) {return (x & 8) == 0 ? -1 : -9;}
-Should combine to (x | -9) ^ 8. Currently not optimized with "clang
--emit-llvm-bc | opt -std-compile-opts".
-
-//===---------------------------------------------------------------------===//
-
-int a(int x) {return (x & 8) == 0 ? -9 : -1;}
-Should combine to x | -9. Currently not optimized with "clang
--emit-llvm-bc | opt -std-compile-opts".
-
-//===---------------------------------------------------------------------===//
-
int a(int x) {return ((x | -9) ^ 8) & x;}
Should combine to x & -9. Currently not optimized with "clang
-emit-llvm-bc | opt -std-compile-opts".
diff --git a/lib/Transforms/InstCombine/InstCombineSelect.cpp b/lib/Transforms/InstCombine/InstCombineSelect.cpp
index 6f0da3eb64..82ce31128c 100644
--- a/lib/Transforms/InstCombine/InstCombineSelect.cpp
+++ b/lib/Transforms/InstCombine/InstCombineSelect.cpp
@@ -457,10 +457,6 @@ static Value *foldSelectICmpAnd(const SelectInst &SI, ConstantInt *TrueVal,
if (!IC || !IC->isEquality())
return 0;
- // One of the select arms must be zero.
- if (!TrueVal->isZero() && !FalseVal->isZero())
- return 0;
-
if (ConstantInt *C = dyn_cast<ConstantInt>(IC->getOperand(1)))
if (!C->isZero())
return 0;
@@ -471,6 +467,24 @@ static Value *foldSelectICmpAnd(const SelectInst &SI, ConstantInt *TrueVal,
!match(LHS, m_And(m_Value(), m_ConstantInt(AndRHS))))
return 0;
+ // If both select arms are non-zero see if we have a select of the form
+ // 'x ? 2^n + C : C'. Then we can offset both arms by C, use the logic
+ // for 'x ? 2^n : 0' and fix the thing up at the end.
+ ConstantInt *Offset = 0;
+ if (!TrueVal->isZero() && !FalseVal->isZero()) {
+ if ((TrueVal->getValue() - FalseVal->getValue()).isPowerOf2())
+ Offset = FalseVal;
+ else if ((FalseVal->getValue() - TrueVal->getValue()).isPowerOf2())
+ Offset = TrueVal;
+ else
+ return 0;
+
+ // Adjust TrueVal and FalseVal to the offset.
+ TrueVal = ConstantInt::get(Builder->getContext(),
+ TrueVal->getValue() - Offset->getValue());
+ FalseVal = ConstantInt::get(Builder->getContext(),
+ FalseVal->getValue() - Offset->getValue());
+ }
// Make sure the mask in the 'and' and one of the select arms is a power of 2.
if (!AndRHS->getValue().isPowerOf2() ||
@@ -496,6 +510,10 @@ static Value *foldSelectICmpAnd(const SelectInst &SI, ConstantInt *TrueVal,
ShouldNotVal ^= IC->getPredicate() == ICmpInst::ICMP_NE;
if (ShouldNotVal)
V = Builder->CreateXor(V, ValC);
+
+ // Apply an offset if needed.
+ if (Offset)
+ V = Builder->CreateAdd(V, Offset);
return V;
}
diff --git a/test/Transforms/InstCombine/select.ll b/test/Transforms/InstCombine/select.ll
index e9efa74e1a..fecc9d1c3f 100644
--- a/test/Transforms/InstCombine/select.ll
+++ b/test/Transforms/InstCombine/select.ll
@@ -248,6 +248,56 @@ define i32 @test15f(i32 %X) {
; CHECK: ret i32
}
+;; (a & 8) ? -1 : -9
+define i32 @test15g(i32 %X) {
+ %t1 = and i32 %X, 8
+ %t2 = icmp ne i32 %t1, 0
+ %t3 = select i1 %t2, i32 -1, i32 -9
+ ret i32 %t3
+; CHECK: @test15g
+; CHECK-NEXT: %1 = or i32 %X, -9
+; CHECK-NEXT: ret i32 %1
+}
+
+;; (a & 8) ? -9 : -1
+define i32 @test15h(i32 %X) {
+ %t1 = and i32 %X, 8
+ %t2 = icmp ne i32 %t1, 0
+ %t3 = select i1 %t2, i32 -9, i32 -1
+ ret i32 %t3
+; CHECK: @test15h
+; CHECK-NEXT: %1 = or i32 %X, -9
+; CHECK-NEXT: %2 = xor i32 %1, 8
+; CHECK-NEXT: ret i32 %2
+}
+
+;; (a & 2) ? 577 : 1089
+define i32 @test15i(i32 %X) {
+ %t1 = and i32 %X, 2
+ %t2 = icmp ne i32 %t1, 0
+ %t3 = select i1 %t2, i32 577, i32 1089
+ ret i32 %t3
+; CHECK: @test15i
+; CHECK-NEXT: %t1 = shl i32 %X, 8
+; CHECK-NEXT: %1 = and i32 %t1, 512
+; CHECK-NEXT: %2 = xor i32 %1, 512
+; CHECK-NEXT: %3 = add i32 %2, 577
+; CHECK-NEXT: ret i32 %3
+}
+
+;; (a & 2) ? 1089 : 577
+define i32 @test15j(i32 %X) {
+ %t1 = and i32 %X, 2
+ %t2 = icmp ne i32 %t1, 0
+ %t3 = select i1 %t2, i32 1089, i32 577
+ ret i32 %t3
+; CHECK: @test15j
+; CHECK-NEXT: %t1 = shl i32 %X, 8
+; CHECK-NEXT: %1 = and i32 %t1, 512
+; CHECK-NEXT: %2 = add i32 %1, 577
+; CHECK-NEXT: ret i32 %2
+}
+
define i32 @test16(i1 %C, i32* %P) {
%P2 = select i1 %C, i32* %P, i32* null
%V = load i32* %P2