[InstCombine] use m_APInt to allow icmp (binop X, Y), C folds with constant splat vectors

This removes the restriction for the icmp constant, but as noted by the FIXME comments, 
we still need to change individual checks for binop operand constants.

llvm-svn: 277629
This commit is contained in:
Sanjay Patel 2016-08-03 18:59:03 +00:00
parent bfb6072d84
commit 43aeb001c9
6 changed files with 42 additions and 55 deletions

View File

@ -2203,22 +2203,23 @@ Instruction *InstCombiner::foldICmpWithConstant(ICmpInst &ICI,
/// Simplify icmp_eq and icmp_ne instructions with binary operator LHS and
/// integer constant RHS.
Instruction *InstCombiner::foldICmpEqualityWithConstant(ICmpInst &ICI) {
// FIXME: If we use m_APInt() instead of m_ConstantInt(), it would enable
// vector types with constant splat vectors to be optimized too.
BinaryOperator *BO;
ConstantInt *RHS;
const APInt *RHSV;
// FIXME: Some of these folds could work with arbitrary constants, but this
// match is limited to scalars and vector splat constants.
if (!ICI.isEquality() || !match(ICI.getOperand(0), m_BinOp(BO)) ||
!match(ICI.getOperand(1), m_ConstantInt(RHS)))
!match(ICI.getOperand(1), m_APInt(RHSV)))
return nullptr;
const APInt &RHSV = RHS->getValue();
Constant *RHS = cast<Constant>(ICI.getOperand(1));
bool isICMP_NE = ICI.getPredicate() == ICmpInst::ICMP_NE;
Value *BOp0 = BO->getOperand(0), *BOp1 = BO->getOperand(1);
switch (BO->getOpcode()) {
case Instruction::SRem:
// If we have a signed (X % (2^c)) == 0, turn it into an unsigned one.
if (RHSV == 0 && isa<ConstantInt>(BOp1) && BO->hasOneUse()) {
// FIXME: Vectors are excluded by ConstantInt.
if (*RHSV == 0 && isa<ConstantInt>(BOp1) && BO->hasOneUse()) {
const APInt &V = cast<ConstantInt>(BOp1)->getValue();
if (V.sgt(1) && V.isPowerOf2()) {
Value *NewRem = Builder->CreateURem(BOp0, BOp1, BO->getName());
@ -2229,11 +2230,12 @@ Instruction *InstCombiner::foldICmpEqualityWithConstant(ICmpInst &ICI) {
break;
case Instruction::Add:
// Replace ((add A, B) != C) with (A != C-B) if B & C are constants.
// FIXME: Vectors are excluded by ConstantInt.
if (ConstantInt *BOp1C = dyn_cast<ConstantInt>(BOp1)) {
if (BO->hasOneUse())
return new ICmpInst(ICI.getPredicate(), BOp0,
ConstantExpr::getSub(RHS, BOp1C));
} else if (RHSV == 0) {
} else if (*RHSV == 0) {
// Replace ((add A, B) != 0) with (A != -B) if A or B is
// efficiently invertible, or if the add has just this one use.
if (Value *NegVal = dyn_castNegVal(BOp1))
@ -2254,7 +2256,7 @@ Instruction *InstCombiner::foldICmpEqualityWithConstant(ICmpInst &ICI) {
// the explicit xor.
return new ICmpInst(ICI.getPredicate(), BOp0,
ConstantExpr::getXor(RHS, BOC));
} else if (RHSV == 0) {
} else if (*RHSV == 0) {
// Replace ((xor A, B) != 0) with (A != B)
return new ICmpInst(ICI.getPredicate(), BOp0, BOp1);
}
@ -2262,11 +2264,12 @@ Instruction *InstCombiner::foldICmpEqualityWithConstant(ICmpInst &ICI) {
break;
case Instruction::Sub:
if (BO->hasOneUse()) {
// FIXME: Vectors are excluded by ConstantInt.
if (ConstantInt *BOp0C = dyn_cast<ConstantInt>(BOp0)) {
// Replace ((sub A, B) != C) with (B != A-C) if A & C are constants.
return new ICmpInst(ICI.getPredicate(), BOp1,
ConstantExpr::getSub(BOp0C, RHS));
} else if (RHSV == 0) {
} else if (*RHSV == 0) {
// Replace ((sub A, B) != 0) with (A != B)
return new ICmpInst(ICI.getPredicate(), BOp0, BOp1);
}
@ -2275,6 +2278,7 @@ Instruction *InstCombiner::foldICmpEqualityWithConstant(ICmpInst &ICI) {
case Instruction::Or:
// If bits are being or'd in that are not present in the constant we
// are comparing against, then the comparison could never succeed!
// FIXME: Vectors are excluded by ConstantInt.
if (ConstantInt *BOC = dyn_cast<ConstantInt>(BOp1)) {
Constant *NotCI = ConstantExpr::getNot(RHS);
if (!ConstantExpr::getAnd(BOC, NotCI)->isNullValue())
@ -2292,14 +2296,15 @@ Instruction *InstCombiner::foldICmpEqualityWithConstant(ICmpInst &ICI) {
break;
case Instruction::And:
// FIXME: Vectors are excluded by ConstantInt.
if (ConstantInt *BOC = dyn_cast<ConstantInt>(BOp1)) {
// If bits are being compared against that are and'd out, then the
// comparison can never succeed!
if ((RHSV & ~BOC->getValue()) != 0)
if ((*RHSV & ~BOC->getValue()) != 0)
return replaceInstUsesWith(ICI, Builder->getInt1(isICMP_NE));
// If we have ((X & C) == C), turn it into ((X & C) != 0).
if (RHS == BOC && RHSV.isPowerOf2())
if (RHS == BOC && RHSV->isPowerOf2())
return new ICmpInst(isICMP_NE ? ICmpInst::ICMP_EQ : ICmpInst::ICMP_NE,
BO, Constant::getNullValue(RHS->getType()));
@ -2316,7 +2321,7 @@ Instruction *InstCombiner::foldICmpEqualityWithConstant(ICmpInst &ICI) {
}
// ((X & ~7) == 0) --> X < 8
if (RHSV == 0 && isHighOnes(BOC)) {
if (*RHSV == 0 && isHighOnes(BOC)) {
Constant *NegX = ConstantExpr::getNeg(BOC);
ICmpInst::Predicate Pred =
isICMP_NE ? ICmpInst::ICMP_UGE : ICmpInst::ICMP_ULT;
@ -2325,7 +2330,8 @@ Instruction *InstCombiner::foldICmpEqualityWithConstant(ICmpInst &ICI) {
}
break;
case Instruction::Mul:
if (RHSV == 0 && BO->hasNoSignedWrap()) {
if (*RHSV == 0 && BO->hasNoSignedWrap()) {
// FIXME: Vectors are excluded by ConstantInt.
if (ConstantInt *BOC = dyn_cast<ConstantInt>(BOp1)) {
// The trivial case (mul X, 0) is handled by InstSimplify
// General case : (mul X, C) != 0 iff X != 0
@ -2337,7 +2343,7 @@ Instruction *InstCombiner::foldICmpEqualityWithConstant(ICmpInst &ICI) {
}
break;
case Instruction::UDiv:
if (RHSV == 0) {
if (*RHSV == 0) {
// (icmp eq/ne (udiv A, B), 0) -> (icmp ugt/ule i32 B, A)
ICmpInst::Predicate Pred =
isICMP_NE ? ICmpInst::ICMP_ULE : ICmpInst::ICMP_UGT;

View File

@ -109,12 +109,10 @@ define i1 @test10(i8 %A, i8 %b) {
ret i1 %c
}
; FIXME: Vectors should fold the same way.
define <2 x i1> @test10vec(<2 x i8> %a, <2 x i8> %b) {
; CHECK-LABEL: @test10vec(
; CHECK-NEXT: [[C:%.*]] = add <2 x i8> %a, %b
; CHECK-NEXT: [[D:%.*]] = icmp ne <2 x i8> [[C]], zeroinitializer
; CHECK-NEXT: [[C:%.*]] = sub <2 x i8> zeroinitializer, %b
; CHECK-NEXT: [[D:%.*]] = icmp ne <2 x i8> %a, [[C]]
; CHECK-NEXT: ret <2 x i1> [[D]]
;
%c = add <2 x i8> %a, %b
@ -133,11 +131,9 @@ define i1 @test11(i8 %A) {
ret i1 %c
}
; FIXME: Vectors should fold the same way.
define <2 x i1> @test11vec(<2 x i8> %a) {
; CHECK-LABEL: @test11vec(
; CHECK-NEXT: [[B:%.*]] = add <2 x i8> %a, <i8 -1, i8 -1>
; CHECK-NEXT: [[C:%.*]] = icmp ne <2 x i8> [[B]], zeroinitializer
; CHECK-NEXT: [[C:%.*]] = icmp ne <2 x i8> %a, <i8 1, i8 1>
; CHECK-NEXT: ret <2 x i1> [[C]]
;
%b = add <2 x i8> %a, <i8 -1, i8 -1>

View File

@ -1,8 +1,6 @@
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
; RUN: opt -instcombine -S < %s | FileCheck %s
; FIXME: Vectors should get the same folds as scalars for all tests.
define i1 @test1(i32 %n, i32 %d) {
; CHECK-LABEL: @test1(
; CHECK-NEXT: [[CMP1:%.*]] = icmp ugt i32 %d, %n
@ -15,8 +13,7 @@ define i1 @test1(i32 %n, i32 %d) {
define <2 x i1> @test1vec(<2 x i32> %n, <2 x i32> %d) {
; CHECK-LABEL: @test1vec(
; CHECK-NEXT: [[DIV:%.*]] = udiv <2 x i32> %n, %d
; CHECK-NEXT: [[CMP1:%.*]] = icmp eq <2 x i32> [[DIV]], zeroinitializer
; CHECK-NEXT: [[CMP1:%.*]] = icmp ugt <2 x i32> %d, %n
; CHECK-NEXT: ret <2 x i1> [[CMP1]]
;
%div = udiv <2 x i32> %n, %d
@ -36,8 +33,7 @@ define i1 @test2(i32 %d) {
define <2 x i1> @test2vec(<2 x i32> %d) {
; CHECK-LABEL: @test2vec(
; CHECK-NEXT: [[DIV:%.*]] = udiv <2 x i32> <i32 64, i32 63>, %d
; CHECK-NEXT: [[CMP1:%.*]] = icmp eq <2 x i32> [[DIV]], zeroinitializer
; CHECK-NEXT: [[CMP1:%.*]] = icmp ugt <2 x i32> %d, <i32 64, i32 63>
; CHECK-NEXT: ret <2 x i1> [[CMP1]]
;
%div = udiv <2 x i32> <i32 64, i32 63>, %d
@ -57,8 +53,7 @@ define i1 @test3(i32 %n, i32 %d) {
define <2 x i1> @test3vec(<2 x i32> %n, <2 x i32> %d) {
; CHECK-LABEL: @test3vec(
; CHECK-NEXT: [[DIV:%.*]] = udiv <2 x i32> %n, %d
; CHECK-NEXT: [[CMP1:%.*]] = icmp ne <2 x i32> [[DIV]], zeroinitializer
; CHECK-NEXT: [[CMP1:%.*]] = icmp ule <2 x i32> %d, %n
; CHECK-NEXT: ret <2 x i1> [[CMP1]]
;
%div = udiv <2 x i32> %n, %d
@ -78,8 +73,7 @@ define i1 @test4(i32 %d) {
define <2 x i1> @test4vec(<2 x i32> %d) {
; CHECK-LABEL: @test4vec(
; CHECK-NEXT: [[DIV:%.*]] = udiv <2 x i32> <i32 64, i32 65>, %d
; CHECK-NEXT: [[CMP1:%.*]] = icmp ne <2 x i32> [[DIV]], zeroinitializer
; CHECK-NEXT: [[CMP1:%.*]] = icmp ult <2 x i32> %d, <i32 65, i32 66>
; CHECK-NEXT: ret <2 x i1> [[CMP1]]
;
%div = udiv <2 x i32> <i32 64, i32 65>, %d
@ -98,9 +92,7 @@ define i1 @test5(i32 %d) {
define <2 x i1> @test5vec(<2 x i32> %d) {
; CHECK-LABEL: @test5vec(
; CHECK-NEXT: [[DIV:%.*]] = udiv <2 x i32> <i32 -1, i32 -1>, %d
; CHECK-NEXT: [[CMP1:%.*]] = icmp ne <2 x i32> [[DIV]], zeroinitializer
; CHECK-NEXT: ret <2 x i1> [[CMP1]]
; CHECK-NEXT: ret <2 x i1> <i1 true, i1 true>
;
%div = udiv <2 x i32> <i32 -1, i32 -1>, %d
%cmp1 = icmp ne <2 x i32> %div, zeroinitializer
@ -119,8 +111,7 @@ define i1 @test6(i32 %d) {
define <2 x i1> @test6vec(<2 x i32> %d) {
; CHECK-LABEL: @test6vec(
; CHECK-NEXT: [[DIV:%.*]] = udiv <2 x i32> <i32 5, i32 5>, %d
; CHECK-NEXT: [[CMP1:%.*]] = icmp ne <2 x i32> [[DIV]], zeroinitializer
; CHECK-NEXT: [[CMP1:%.*]] = icmp ult <2 x i32> %d, <i32 6, i32 6>
; CHECK-NEXT: ret <2 x i1> [[CMP1]]
;
%div = udiv <2 x i32> <i32 5, i32 5>, %d
@ -157,6 +148,8 @@ define i1 @test8(i32 %d) {
ret i1 %cmp1
}
; FIXME: Vectors should get the same folds as scalars for all tests.
define <2 x i1> @test8vec(<2 x i32> %d) {
; CHECK-LABEL: @test8vec(
; CHECK-NEXT: [[DIV:%.*]] = udiv <2 x i32> <i32 4, i32 4>, %d

View File

@ -177,9 +177,10 @@ define i1 @test13(i64 %X, %S* %P) {
define <2 x i1> @test13_vector(<2 x i64> %X, <2 x %S*> %P) nounwind {
; CHECK-LABEL: @test13_vector(
; CHECK-NEXT: shl nuw <2 x i64> %X, <i64 2, i64 2>
; CHECK-NEXT: add <2 x i64> %A.idx, <i64 4, i64 4>
; CHECK-NEXT: icmp eq <2 x i64> %A.offs, zeroinitializer
; CHECK-NEXT: [[A_IDX:%.*]] = shl nuw <2 x i64> %X, <i64 2, i64 2>
; CHECK-NEXT: [[C:%.*]] = icmp eq <2 x i64> [[A_IDX]], <i64 -4, i64 -4>
; CHECK-NEXT: ret <2 x i1> [[C]]
;
%A = getelementptr inbounds %S, <2 x %S*> %P, <2 x i64> zeroinitializer, <2 x i32> <i32 1, i32 1>, <2 x i64> %X
%B = getelementptr inbounds %S, <2 x %S*> %P, <2 x i64> <i64 0, i64 0>, <2 x i32> <i32 0, i32 0>
%C = icmp eq <2 x i32*> %A, %B
@ -198,10 +199,10 @@ define i1 @test13_as1(i16 %X, %S addrspace(1)* %P) {
define <2 x i1> @test13_vector_as1(<2 x i16> %X, <2 x %S addrspace(1)*> %P) {
; CHECK-LABEL: @test13_vector_as1(
; CHECK-NEXT: shl nuw <2 x i16> %X, <i16 2, i16 2>
; CHECK-NEXT: add <2 x i16> %A.idx, <i16 4, i16 4>
; CHECK-NEXT: icmp eq <2 x i16> %A.offs, zeroinitializer
; CHECK-NEXT: ret <2 x i1>
; CHECK-NEXT: [[A_IDX:%.*]] = shl nuw <2 x i16> %X, <i16 2, i16 2>
; CHECK-NEXT: [[C:%.*]] = icmp eq <2 x i16> [[A_IDX]], <i16 -4, i16 -4>
; CHECK-NEXT: ret <2 x i1> [[C]]
;
%A = getelementptr inbounds %S, <2 x %S addrspace(1)*> %P, <2 x i16> <i16 0, i16 0>, <2 x i32> <i32 1, i32 1>, <2 x i16> %X
%B = getelementptr inbounds %S, <2 x %S addrspace(1)*> %P, <2 x i16> <i16 0, i16 0>, <2 x i32> <i32 0, i32 0>
%C = icmp eq <2 x i32 addrspace(1)*> %A, %B

View File

@ -110,12 +110,9 @@ define i1 @test11(i8 %A, i8 %B) {
ret i1 %D
}
; FIXME: Vectors should get the same folds as scalars.
define <2 x i1> @test11vec(<2 x i8> %A, <2 x i8> %B) {
; CHECK-LABEL: @test11vec(
; CHECK-NEXT: [[C:%.*]] = sub <2 x i8> %A, %B
; CHECK-NEXT: [[D:%.*]] = icmp ne <2 x i8> [[C]], zeroinitializer
; CHECK-NEXT: [[D:%.*]] = icmp ne <2 x i8> %A, %B
; CHECK-NEXT: ret <2 x i1> [[D]]
;
%C = sub <2 x i8> %A, %B

View File

@ -105,12 +105,9 @@ define i1 @test9(i8 %A) {
ret i1 %C
}
; FIXME: Vectors should fold the same way.
define <2 x i1> @test9vec(<2 x i8> %a) {
; CHECK-LABEL: @test9vec(
; CHECK-NEXT: [[B:%.*]] = xor <2 x i8> %a, <i8 123, i8 123>
; CHECK-NEXT: [[C:%.*]] = icmp eq <2 x i8> [[B]], <i8 34, i8 34>
; CHECK-NEXT: [[C:%.*]] = icmp eq <2 x i8> %a, <i8 89, i8 89>
; CHECK-NEXT: ret <2 x i1> [[C]]
;
%b = xor <2 x i8> %a, <i8 123, i8 123>
@ -150,12 +147,9 @@ define i1 @test12(i8 %A) {
ret i1 %c
}
; FIXME: Vectors should fold the same way.
define <2 x i1> @test12vec(<2 x i8> %a) {
; CHECK-LABEL: @test12vec(
; CHECK-NEXT: [[B:%.*]] = xor <2 x i8> %a, <i8 4, i8 4>
; CHECK-NEXT: [[C:%.*]] = icmp ne <2 x i8> [[B]], zeroinitializer
; CHECK-NEXT: [[C:%.*]] = icmp ne <2 x i8> %a, <i8 4, i8 4>
; CHECK-NEXT: ret <2 x i1> [[C]]
;
%b = xor <2 x i8> %a, <i8 4, i8 4>