summaryrefslogtreecommitdiffstats
path: root/llvm
diff options
context:
space:
mode:
authorSanjay Patel <spatel@rotateright.com>2017-05-04 19:51:34 +0000
committerSanjay Patel <spatel@rotateright.com>2017-05-04 19:51:34 +0000
commite42b4d566e97dc852f76532529e1318e041ab3ab (patch)
treec27969429322aecd36d9d4e0be181555945c1103 /llvm
parentf1deb837eee39ec6ddbe177be9de129f4fd59ee1 (diff)
downloadbcm5719-llvm-e42b4d566e97dc852f76532529e1318e041ab3ab.tar.gz
bcm5719-llvm-e42b4d566e97dc852f76532529e1318e041ab3ab.zip
[InstSimplify] add folds for or-of-casted-icmps
The sibling folds for 'and' with casts were added with https://reviews.llvm.org/rL273200. This is a preliminary step for adding the 'or' variants for the folds added with https://reviews.llvm.org/rL301260. The reason for the strange form with constant LHS in the 1st test is because there's another missing fold in that case for the inverted predicate. That should be fixed when we add the ConstantRange functionality for 'or-of-icmps' that already exists for 'and-of-icmps'. I'm hoping to share more code for the and/or cases, so we won't have these differences. This will allow us to remove code from InstCombine. It's also possible that we can remove some code here in InstSimplify. I think we have some duplicated folds because patterns are not matched in a general way. Differential Revision: https://reviews.llvm.org/D32876 llvm-svn: 302189
Diffstat (limited to 'llvm')
-rw-r--r--llvm/lib/Analysis/InstructionSimplify.cpp82
-rw-r--r--llvm/test/Transforms/InstSimplify/AndOrXor.ll17
2 files changed, 48 insertions, 51 deletions
diff --git a/llvm/lib/Analysis/InstructionSimplify.cpp b/llvm/lib/Analysis/InstructionSimplify.cpp
index 9d49a2059f1..43e387bdc4b 100644
--- a/llvm/lib/Analysis/InstructionSimplify.cpp
+++ b/llvm/lib/Analysis/InstructionSimplify.cpp
@@ -1521,7 +1521,7 @@ static Value *simplifyOrOfICmpsWithSameOperands(ICmpInst *Op0, ICmpInst *Op1) {
/// Commuted variants are assumed to be handled by calling this function again
/// with the parameters swapped.
-static Value *SimplifyAndOfICmps(ICmpInst *Op0, ICmpInst *Op1) {
+static Value *simplifyAndOfICmps(ICmpInst *Op0, ICmpInst *Op1) {
if (Value *X = simplifyUnsignedRangeCheck(Op0, Op1, /*IsAnd=*/true))
return X;
@@ -1593,7 +1593,7 @@ static Value *SimplifyAndOfICmps(ICmpInst *Op0, ICmpInst *Op1) {
/// Commuted variants are assumed to be handled by calling this function again
/// with the parameters swapped.
-static Value *SimplifyOrOfICmps(ICmpInst *Op0, ICmpInst *Op1) {
+static Value *simplifyOrOfICmps(ICmpInst *Op0, ICmpInst *Op1) {
if (Value *X = simplifyUnsignedRangeCheck(Op0, Op1, /*IsAnd=*/false))
return X;
@@ -1645,6 +1645,46 @@ static Value *SimplifyOrOfICmps(ICmpInst *Op0, ICmpInst *Op1) {
return nullptr;
}
+static Value *simplifyPossiblyCastedAndOrOfICmps(ICmpInst *Cmp0, ICmpInst *Cmp1,
+ bool IsAnd, CastInst *Cast) {
+ Value *V =
+ IsAnd ? simplifyAndOfICmps(Cmp0, Cmp1) : simplifyOrOfICmps(Cmp0, Cmp1);
+ if (!V)
+ return nullptr;
+ if (!Cast)
+ return V;
+
+ // If we looked through casts, we can only handle a constant simplification
+ // because we are not allowed to create a cast instruction here.
+ if (auto *C = dyn_cast<Constant>(V))
+ return ConstantExpr::getCast(Cast->getOpcode(), C, Cast->getType());
+
+ return nullptr;
+}
+
+static Value *simplifyAndOrOfICmps(Value *Op0, Value *Op1, bool IsAnd) {
+ // Look through casts of the 'and' operands to find compares.
+ auto *Cast0 = dyn_cast<CastInst>(Op0);
+ auto *Cast1 = dyn_cast<CastInst>(Op1);
+ if (Cast0 && Cast1 && Cast0->getOpcode() == Cast1->getOpcode() &&
+ Cast0->getSrcTy() == Cast1->getSrcTy()) {
+ Op0 = Cast0->getOperand(0);
+ Op1 = Cast1->getOperand(0);
+ }
+
+ auto *Cmp0 = dyn_cast<ICmpInst>(Op0);
+ auto *Cmp1 = dyn_cast<ICmpInst>(Op1);
+ if (!Cmp0 || !Cmp1)
+ return nullptr;
+
+ if (Value *V = simplifyPossiblyCastedAndOrOfICmps(Cmp0, Cmp1, IsAnd, Cast0))
+ return V;
+ if (Value *V = simplifyPossiblyCastedAndOrOfICmps(Cmp1, Cmp0, IsAnd, Cast0))
+ return V;
+
+ return nullptr;
+}
+
/// Given operands for an And, see if we can fold the result.
/// If not, this returns null.
static Value *SimplifyAndInst(Value *Op0, Value *Op1, const SimplifyQuery &Q,
@@ -1695,32 +1735,8 @@ static Value *SimplifyAndInst(Value *Op0, Value *Op1, const SimplifyQuery &Q,
return Op1;
}
- if (auto *ICILHS = dyn_cast<ICmpInst>(Op0)) {
- if (auto *ICIRHS = dyn_cast<ICmpInst>(Op1)) {
- if (Value *V = SimplifyAndOfICmps(ICILHS, ICIRHS))
- return V;
- if (Value *V = SimplifyAndOfICmps(ICIRHS, ICILHS))
- return V;
- }
- }
-
- // The compares may be hidden behind casts. Look through those and try the
- // same folds as above.
- auto *Cast0 = dyn_cast<CastInst>(Op0);
- auto *Cast1 = dyn_cast<CastInst>(Op1);
- if (Cast0 && Cast1 && Cast0->getOpcode() == Cast1->getOpcode() &&
- Cast0->getSrcTy() == Cast1->getSrcTy()) {
- auto *Cmp0 = dyn_cast<ICmpInst>(Cast0->getOperand(0));
- auto *Cmp1 = dyn_cast<ICmpInst>(Cast1->getOperand(0));
- if (Cmp0 && Cmp1) {
- Instruction::CastOps CastOpc = Cast0->getOpcode();
- Type *ResultType = Cast0->getType();
- if (auto *V = dyn_cast_or_null<Constant>(SimplifyAndOfICmps(Cmp0, Cmp1)))
- return ConstantExpr::getCast(CastOpc, V, ResultType);
- if (auto *V = dyn_cast_or_null<Constant>(SimplifyAndOfICmps(Cmp1, Cmp0)))
- return ConstantExpr::getCast(CastOpc, V, ResultType);
- }
- }
+ if (Value *V = simplifyAndOrOfICmps(Op0, Op1, true))
+ return V;
// Try some generic simplifications for associative operations.
if (Value *V = SimplifyAssociativeBinOp(Instruction::And, Op0, Op1, Q,
@@ -1826,14 +1842,8 @@ static Value *SimplifyOrInst(Value *Op0, Value *Op1, const SimplifyQuery &Q,
match(Op1, m_c_And(m_Not(m_Specific(A)), m_Specific(B)))))
return Op0;
- if (auto *ICILHS = dyn_cast<ICmpInst>(Op0)) {
- if (auto *ICIRHS = dyn_cast<ICmpInst>(Op1)) {
- if (Value *V = SimplifyOrOfICmps(ICILHS, ICIRHS))
- return V;
- if (Value *V = SimplifyOrOfICmps(ICIRHS, ICILHS))
- return V;
- }
- }
+ if (Value *V = simplifyAndOrOfICmps(Op0, Op1, false))
+ return V;
// Try some generic simplifications for associative operations.
if (Value *V = SimplifyAssociativeBinOp(Instruction::Or, Op0, Op1, Q,
diff --git a/llvm/test/Transforms/InstSimplify/AndOrXor.ll b/llvm/test/Transforms/InstSimplify/AndOrXor.ll
index 40f2e9bbdbc..e059d77f1fa 100644
--- a/llvm/test/Transforms/InstSimplify/AndOrXor.ll
+++ b/llvm/test/Transforms/InstSimplify/AndOrXor.ll
@@ -468,16 +468,9 @@ define <2 x i3> @and_of_different_cast_icmps_vec(<2 x i8> %i, <2 x i16> %j) {
ret <2 x i3> %and
}
-; FIXME: This should simplify.
-
define i32 @or_of_zexted_icmps(i32 %i) {
; CHECK-LABEL: @or_of_zexted_icmps(
-; CHECK-NEXT: [[CMP0:%.*]] = icmp ne i32 %i, 0
-; CHECK-NEXT: [[CONV0:%.*]] = zext i1 [[CMP0]] to i32
-; CHECK-NEXT: [[CMP1:%.*]] = icmp uge i32 4, %i
-; CHECK-NEXT: [[CONV1:%.*]] = zext i1 [[CMP1]] to i32
-; CHECK-NEXT: [[OR:%.*]] = or i32 [[CONV0]], [[CONV1]]
-; CHECK-NEXT: ret i32 [[OR]]
+; CHECK-NEXT: ret i32 1
;
%cmp0 = icmp ne i32 %i, 0
%conv0 = zext i1 %cmp0 to i32
@@ -487,17 +480,11 @@ define i32 @or_of_zexted_icmps(i32 %i) {
ret i32 %or
}
-; FIXME: This should simplify
; Try a different cast and weird vector types.
define i3 @or_of_bitcast_icmps_vec(<3 x i65> %i) {
; CHECK-LABEL: @or_of_bitcast_icmps_vec(
-; CHECK-NEXT: [[CMP0:%.*]] = icmp sge <3 x i65> %i, zeroinitializer
-; CHECK-NEXT: [[CONV0:%.*]] = bitcast <3 x i1> [[CMP0]] to i3
-; CHECK-NEXT: [[CMP1:%.*]] = icmp slt <3 x i65> %i, zeroinitializer
-; CHECK-NEXT: [[CONV1:%.*]] = bitcast <3 x i1> [[CMP1]] to i3
-; CHECK-NEXT: [[OR:%.*]] = or i3 [[CONV0]], [[CONV1]]
-; CHECK-NEXT: ret i3 [[OR]]
+; CHECK-NEXT: ret i3 bitcast (<3 x i1> <i1 true, i1 true, i1 true> to i3)
;
%cmp0 = icmp sge <3 x i65> %i, zeroinitializer
%conv0 = bitcast <3 x i1> %cmp0 to i3
OpenPOWER on IntegriCloud