diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp index 9d94b276bf02..4b949ab6561d 100644 --- a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp @@ -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(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(BOp1) && BO->hasOneUse()) { + // FIXME: Vectors are excluded by ConstantInt. + if (*RHSV == 0 && isa(BOp1) && BO->hasOneUse()) { const APInt &V = cast(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(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(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(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(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(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; diff --git a/llvm/test/Transforms/InstCombine/add.ll b/llvm/test/Transforms/InstCombine/add.ll index e75c032174ed..10c15928efb5 100644 --- a/llvm/test/Transforms/InstCombine/add.ll +++ b/llvm/test/Transforms/InstCombine/add.ll @@ -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, -; CHECK-NEXT: [[C:%.*]] = icmp ne <2 x i8> [[B]], zeroinitializer +; CHECK-NEXT: [[C:%.*]] = icmp ne <2 x i8> %a, ; CHECK-NEXT: ret <2 x i1> [[C]] ; %b = add <2 x i8> %a, diff --git a/llvm/test/Transforms/InstCombine/compare-udiv.ll b/llvm/test/Transforms/InstCombine/compare-udiv.ll index de7e93070af7..8eb0715f7ec4 100644 --- a/llvm/test/Transforms/InstCombine/compare-udiv.ll +++ b/llvm/test/Transforms/InstCombine/compare-udiv.ll @@ -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> , %d -; CHECK-NEXT: [[CMP1:%.*]] = icmp eq <2 x i32> [[DIV]], zeroinitializer +; CHECK-NEXT: [[CMP1:%.*]] = icmp ugt <2 x i32> %d, ; CHECK-NEXT: ret <2 x i1> [[CMP1]] ; %div = udiv <2 x i32> , %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> , %d -; CHECK-NEXT: [[CMP1:%.*]] = icmp ne <2 x i32> [[DIV]], zeroinitializer +; CHECK-NEXT: [[CMP1:%.*]] = icmp ult <2 x i32> %d, ; CHECK-NEXT: ret <2 x i1> [[CMP1]] ; %div = udiv <2 x i32> , %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> , %d -; CHECK-NEXT: [[CMP1:%.*]] = icmp ne <2 x i32> [[DIV]], zeroinitializer -; CHECK-NEXT: ret <2 x i1> [[CMP1]] +; CHECK-NEXT: ret <2 x i1> ; %div = udiv <2 x i32> , %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> , %d -; CHECK-NEXT: [[CMP1:%.*]] = icmp ne <2 x i32> [[DIV]], zeroinitializer +; CHECK-NEXT: [[CMP1:%.*]] = icmp ult <2 x i32> %d, ; CHECK-NEXT: ret <2 x i1> [[CMP1]] ; %div = udiv <2 x i32> , %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> , %d diff --git a/llvm/test/Transforms/InstCombine/getelementptr.ll b/llvm/test/Transforms/InstCombine/getelementptr.ll index 7446734e210c..a3c2beb7eb2a 100644 --- a/llvm/test/Transforms/InstCombine/getelementptr.ll +++ b/llvm/test/Transforms/InstCombine/getelementptr.ll @@ -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, -; CHECK-NEXT: add <2 x i64> %A.idx, -; CHECK-NEXT: icmp eq <2 x i64> %A.offs, zeroinitializer +; CHECK-NEXT: [[A_IDX:%.*]] = shl nuw <2 x i64> %X, +; CHECK-NEXT: [[C:%.*]] = icmp eq <2 x i64> [[A_IDX]], +; CHECK-NEXT: ret <2 x i1> [[C]] +; %A = getelementptr inbounds %S, <2 x %S*> %P, <2 x i64> zeroinitializer, <2 x i32> , <2 x i64> %X %B = getelementptr inbounds %S, <2 x %S*> %P, <2 x i64> , <2 x i32> %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, -; CHECK-NEXT: add <2 x i16> %A.idx, -; 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, +; CHECK-NEXT: [[C:%.*]] = icmp eq <2 x i16> [[A_IDX]], +; CHECK-NEXT: ret <2 x i1> [[C]] +; %A = getelementptr inbounds %S, <2 x %S addrspace(1)*> %P, <2 x i16> , <2 x i32> , <2 x i16> %X %B = getelementptr inbounds %S, <2 x %S addrspace(1)*> %P, <2 x i16> , <2 x i32> %C = icmp eq <2 x i32 addrspace(1)*> %A, %B diff --git a/llvm/test/Transforms/InstCombine/sub.ll b/llvm/test/Transforms/InstCombine/sub.ll index 3df7e506f533..78189c802ad9 100644 --- a/llvm/test/Transforms/InstCombine/sub.ll +++ b/llvm/test/Transforms/InstCombine/sub.ll @@ -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 diff --git a/llvm/test/Transforms/InstCombine/xor.ll b/llvm/test/Transforms/InstCombine/xor.ll index 344199769b4d..cd137776bbfd 100644 --- a/llvm/test/Transforms/InstCombine/xor.ll +++ b/llvm/test/Transforms/InstCombine/xor.ll @@ -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, -; CHECK-NEXT: [[C:%.*]] = icmp eq <2 x i8> [[B]], +; CHECK-NEXT: [[C:%.*]] = icmp eq <2 x i8> %a, ; CHECK-NEXT: ret <2 x i1> [[C]] ; %b = xor <2 x i8> %a, @@ -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, -; CHECK-NEXT: [[C:%.*]] = icmp ne <2 x i8> [[B]], zeroinitializer +; CHECK-NEXT: [[C:%.*]] = icmp ne <2 x i8> %a, ; CHECK-NEXT: ret <2 x i1> [[C]] ; %b = xor <2 x i8> %a,