From 43aeb001c959098167dec6272160ee73d187067c Mon Sep 17 00:00:00 2001 From: Sanjay Patel Date: Wed, 3 Aug 2016 18:59:03 +0000 Subject: [PATCH] [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 --- .../Transforms/InstCombine/InstCombineCompares.cpp | 34 +++++++++++++--------- llvm/test/Transforms/InstCombine/add.ll | 10 ++----- llvm/test/Transforms/InstCombine/compare-udiv.ll | 23 +++++---------- llvm/test/Transforms/InstCombine/getelementptr.ll | 15 +++++----- llvm/test/Transforms/InstCombine/sub.ll | 5 +--- llvm/test/Transforms/InstCombine/xor.ll | 10 ++----- 6 files changed, 42 insertions(+), 55 deletions(-) diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp index 9d94b27..4b949ab 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 e75c032..10c1592 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 de7e930..8eb0715 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 7446734..a3c2beb 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 3df7e50..78189c8 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 3441997..cd13777 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, -- 2.7.4