diff --git a/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp b/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp index 26983cf15801b..fae19549f0811 100644 --- a/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp @@ -1310,19 +1310,20 @@ Value *InstCombinerImpl::foldAndOfICmps(ICmpInst *LHS, ICmpInst *RHS, // This only handles icmp of constants: (icmp1 A, C1) & (icmp2 B, C2). Value *LHS0 = LHS->getOperand(0), *RHS0 = RHS->getOperand(0); - ConstantInt *LHSC, *RHSC; - if (!match(LHS->getOperand(1), m_ConstantInt(LHSC)) || - !match(RHS->getOperand(1), m_ConstantInt(RHSC))) + const APInt *LHSC, *RHSC; + if (!match(LHS->getOperand(1), m_APInt(LHSC)) || + !match(RHS->getOperand(1), m_APInt(RHSC))) return nullptr; if (LHSC == RHSC && PredL == PredR) { // (icmp ult A, C) & (icmp ult B, C) --> (icmp ult (A|B), C) // where C is a power of 2 or // (icmp eq A, 0) & (icmp eq B, 0) --> (icmp eq (A|B), 0) - if ((PredL == ICmpInst::ICMP_ULT && LHSC->getValue().isPowerOf2()) || + if ((PredL == ICmpInst::ICMP_ULT && LHSC->isPowerOf2()) || (PredL == ICmpInst::ICMP_EQ && LHSC->isZero())) { Value *NewOr = Builder.CreateOr(LHS0, RHS0); - return Builder.CreateICmp(PredL, NewOr, LHSC); + return Builder.CreateICmp(PredL, NewOr, + ConstantInt::get(NewOr->getType(), *LHSC)); } } @@ -1332,38 +1333,36 @@ Value *InstCombinerImpl::foldAndOfICmps(ICmpInst *LHS, ICmpInst *RHS, if (PredL == ICmpInst::ICMP_EQ && PredL == PredR && LHS->hasOneUse() && RHS->hasOneUse()) { Value *V; - ConstantInt *AndC, *SmallC = nullptr, *BigC = nullptr; + const APInt *AndC, *SmallC = nullptr, *BigC = nullptr; // (trunc x) == C1 & (and x, CA) == C2 // (and x, CA) == C2 & (trunc x) == C1 if (match(RHS0, m_Trunc(m_Value(V))) && - match(LHS0, m_And(m_Specific(V), m_ConstantInt(AndC)))) { + match(LHS0, m_And(m_Specific(V), m_APInt(AndC)))) { SmallC = RHSC; BigC = LHSC; } else if (match(LHS0, m_Trunc(m_Value(V))) && - match(RHS0, m_And(m_Specific(V), m_ConstantInt(AndC)))) { + match(RHS0, m_And(m_Specific(V), m_APInt(AndC)))) { SmallC = LHSC; BigC = RHSC; } if (SmallC && BigC) { - unsigned BigBitSize = BigC->getType()->getBitWidth(); - unsigned SmallBitSize = SmallC->getType()->getBitWidth(); + unsigned BigBitSize = BigC->getBitWidth(); + unsigned SmallBitSize = SmallC->getBitWidth(); // Check that the low bits are zero. APInt Low = APInt::getLowBitsSet(BigBitSize, SmallBitSize); - if ((Low & AndC->getValue()).isZero() && - (Low & BigC->getValue()).isZero()) { - Value *NewAnd = Builder.CreateAnd(V, Low | AndC->getValue()); - APInt N = SmallC->getValue().zext(BigBitSize) | BigC->getValue(); - Value *NewVal = ConstantInt::get(AndC->getType()->getContext(), N); + if ((Low & *AndC).isZero() && (Low & *BigC).isZero()) { + Value *NewAnd = Builder.CreateAnd(V, Low | *AndC); + APInt N = SmallC->zext(BigBitSize) | *BigC; + Value *NewVal = ConstantInt::get(NewAnd->getType(), N); return Builder.CreateICmp(PredL, NewAnd, NewVal); } } } - return foldAndOrOfICmpsUsingRanges(PredL, LHS0, LHSC->getValue(), - PredR, RHS0, RHSC->getValue(), + return foldAndOrOfICmpsUsingRanges(PredL, LHS0, *LHSC, PredR, RHS0, *RHSC, Builder, /* IsAnd */ true); } diff --git a/llvm/test/Transforms/InstCombine/and.ll b/llvm/test/Transforms/InstCombine/and.ll index 0e25d2d471039..392d752e40a76 100644 --- a/llvm/test/Transforms/InstCombine/and.ll +++ b/llvm/test/Transforms/InstCombine/and.ll @@ -307,13 +307,10 @@ define i1 @test23_logical(i32 %A) { ret i1 %D } -; FIXME: Vectors should fold too. define <2 x i1> @test23vec(<2 x i32> %A) { ; CHECK-LABEL: @test23vec( -; CHECK-NEXT: [[B:%.*]] = icmp sgt <2 x i32> [[A:%.*]], -; CHECK-NEXT: [[C:%.*]] = icmp slt <2 x i32> [[A]], -; CHECK-NEXT: [[D:%.*]] = and <2 x i1> [[B]], [[C]] -; CHECK-NEXT: ret <2 x i1> [[D]] +; CHECK-NEXT: [[TMP1:%.*]] = icmp eq <2 x i32> [[A:%.*]], +; CHECK-NEXT: ret <2 x i1> [[TMP1]] ; %B = icmp sgt <2 x i32> %A, %C = icmp sle <2 x i32> %A, @@ -369,13 +366,11 @@ define i1 @test25_logical(i32 %A) { ret i1 %D } -; FIXME: Vectors should fold too. define <2 x i1> @test25vec(<2 x i32> %A) { ; CHECK-LABEL: @test25vec( -; CHECK-NEXT: [[B:%.*]] = icmp sgt <2 x i32> [[A:%.*]], -; CHECK-NEXT: [[C:%.*]] = icmp slt <2 x i32> [[A]], -; CHECK-NEXT: [[D:%.*]] = and <2 x i1> [[B]], [[C]] -; CHECK-NEXT: ret <2 x i1> [[D]] +; CHECK-NEXT: [[TMP1:%.*]] = add <2 x i32> [[A:%.*]], +; CHECK-NEXT: [[TMP2:%.*]] = icmp ult <2 x i32> [[TMP1]], +; CHECK-NEXT: ret <2 x i1> [[TMP2]] ; %B = icmp sge <2 x i32> %A, %C = icmp slt <2 x i32> %A, diff --git a/llvm/test/Transforms/InstCombine/and2.ll b/llvm/test/Transforms/InstCombine/and2.ll index 03be031e930e6..bb8776a970eee 100644 --- a/llvm/test/Transforms/InstCombine/and2.ll +++ b/llvm/test/Transforms/InstCombine/and2.ll @@ -83,13 +83,11 @@ define i1 @test8_logical(i32 %i) { ret i1 %cond } -; FIXME: Vectors should fold too. define <2 x i1> @test8vec(<2 x i32> %i) { ; CHECK-LABEL: @test8vec( -; CHECK-NEXT: [[CMP1:%.*]] = icmp ne <2 x i32> [[I:%.*]], zeroinitializer -; CHECK-NEXT: [[CMP2:%.*]] = icmp ult <2 x i32> [[I]], -; CHECK-NEXT: [[COND:%.*]] = and <2 x i1> [[CMP1]], [[CMP2]] -; CHECK-NEXT: ret <2 x i1> [[COND]] +; CHECK-NEXT: [[TMP1:%.*]] = add <2 x i32> [[I:%.*]], +; CHECK-NEXT: [[TMP2:%.*]] = icmp ult <2 x i32> [[TMP1]], +; CHECK-NEXT: ret <2 x i1> [[TMP2]] ; %cmp1 = icmp ne <2 x i32> %i, zeroinitializer %cmp2 = icmp ult <2 x i32> %i, diff --git a/llvm/test/Transforms/InstCombine/merge-icmp.ll b/llvm/test/Transforms/InstCombine/merge-icmp.ll index 2a1ddf5e69f2d..1202324333d8d 100644 --- a/llvm/test/Transforms/InstCombine/merge-icmp.ll +++ b/llvm/test/Transforms/InstCombine/merge-icmp.ll @@ -34,12 +34,8 @@ define i1 @test1_logical(i16* %x) { define <2 x i1> @test1_vector(<2 x i16>* %x) { ; CHECK-LABEL: @test1_vector( ; CHECK-NEXT: [[LOAD:%.*]] = load <2 x i16>, <2 x i16>* [[X:%.*]], align 4 -; CHECK-NEXT: [[TRUNC:%.*]] = trunc <2 x i16> [[LOAD]] to <2 x i8> -; CHECK-NEXT: [[CMP1:%.*]] = icmp eq <2 x i8> [[TRUNC]], -; CHECK-NEXT: [[AND:%.*]] = and <2 x i16> [[LOAD]], -; CHECK-NEXT: [[CMP2:%.*]] = icmp eq <2 x i16> [[AND]], -; CHECK-NEXT: [[OR:%.*]] = and <2 x i1> [[CMP1]], [[CMP2]] -; CHECK-NEXT: ret <2 x i1> [[OR]] +; CHECK-NEXT: [[TMP1:%.*]] = icmp eq <2 x i16> [[LOAD]], +; CHECK-NEXT: ret <2 x i1> [[TMP1]] ; %load = load <2 x i16>, <2 x i16>* %x, align 4 %trunc = trunc <2 x i16> %load to <2 x i8> @@ -83,12 +79,8 @@ define i1 @test2_logical(i16* %x) { define <2 x i1> @test2_vector(<2 x i16>* %x) { ; CHECK-LABEL: @test2_vector( ; CHECK-NEXT: [[LOAD:%.*]] = load <2 x i16>, <2 x i16>* [[X:%.*]], align 4 -; CHECK-NEXT: [[AND:%.*]] = and <2 x i16> [[LOAD]], -; CHECK-NEXT: [[CMP1:%.*]] = icmp eq <2 x i16> [[AND]], -; CHECK-NEXT: [[TRUNC:%.*]] = trunc <2 x i16> [[LOAD]] to <2 x i8> -; CHECK-NEXT: [[CMP2:%.*]] = icmp eq <2 x i8> [[TRUNC]], -; CHECK-NEXT: [[OR:%.*]] = and <2 x i1> [[CMP1]], [[CMP2]] -; CHECK-NEXT: ret <2 x i1> [[OR]] +; CHECK-NEXT: [[TMP1:%.*]] = icmp eq <2 x i16> [[LOAD]], +; CHECK-NEXT: ret <2 x i1> [[TMP1]] ; %load = load <2 x i16>, <2 x i16>* %x, align 4 %and = and <2 x i16> %load,