diff --git a/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp b/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp index f6d51b945ae0..9bbc5b281abe 100644 --- a/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp @@ -807,7 +807,6 @@ Value *InstCombiner::FoldAndOfICmps(ICmpInst *LHS, ICmpInst *RHS) { } } - // FIXME: The code below is duplicated in FoldOrOfICmps. // From here on, we only handle: // (icmp1 A, C1) & (icmp2 A, C2) --> something simpler. if (LHS0 != RHS0) @@ -826,14 +825,11 @@ Value *InstCombiner::FoldAndOfICmps(ICmpInst *LHS, ICmpInst *RHS) { // Ensure that the larger constant is on the RHS. bool ShouldSwap; - if (CmpInst::isUnsigned(PredL) || CmpInst::isUnsigned(PredR)) { - // We have an unsigned compare (possibly with an equality compare), so treat - // the constants as unsigned. - ShouldSwap = LHSC->getValue().ugt(RHSC->getValue()); - } else { - // Equality transforms treat the constants as signed. + if (CmpInst::isSigned(PredL) || + (ICmpInst::isEquality(PredL) && CmpInst::isSigned(PredR))) ShouldSwap = LHSC->getValue().sgt(RHSC->getValue()); - } + else + ShouldSwap = LHSC->getValue().ugt(RHSC->getValue()); if (ShouldSwap) { std::swap(LHS, RHS); @@ -881,6 +877,10 @@ Value *InstCombiner::FoldAndOfICmps(ICmpInst *LHS, ICmpInst *RHS) { case ICmpInst::ICMP_SGT: // (X != 13 & X s> 15) -> X s> 15 return RHS; case ICmpInst::ICMP_NE: + // Special case to get the ordering right when the values wrap around + // zero. + if (LHSC->getValue() == 0 && RHSC->getValue().isAllOnesValue()) + std::swap(LHSC, RHSC); if (LHSC == SubOne(RHSC)) { // (X != 13 & X != 14) -> X-13 >u 1 Constant *AddC = ConstantExpr::getNeg(LHSC); Value *Add = Builder->CreateAdd(LHS0, AddC, LHS0->getName() + ".off"); @@ -1727,7 +1727,6 @@ Value *InstCombiner::FoldOrOfICmps(ICmpInst *LHS, ICmpInst *RHS, return Builder->CreateICmpULE(LHS0, LHSC); } - // FIXME: The code below is duplicated in FoldAndOfICmps. // From here on, we only handle: // (icmp1 A, C1) | (icmp2 A, C2) --> something simpler. if (LHS0 != RHS0) @@ -1746,14 +1745,11 @@ Value *InstCombiner::FoldOrOfICmps(ICmpInst *LHS, ICmpInst *RHS, // Ensure that the larger constant is on the RHS. bool ShouldSwap; - if (CmpInst::isUnsigned(PredL) || CmpInst::isUnsigned(PredR)) { - // We have an unsigned compare (possibly with an equality compare), so treat - // the constants as unsigned. - ShouldSwap = LHSC->getValue().ugt(RHSC->getValue()); - } else { - // Equality transforms treat the constants as signed. + if (CmpInst::isSigned(PredL) || + (ICmpInst::isEquality(PredL) && CmpInst::isSigned(PredR))) ShouldSwap = LHSC->getValue().sgt(RHSC->getValue()); - } + else + ShouldSwap = LHSC->getValue().ugt(RHSC->getValue()); if (ShouldSwap) { std::swap(LHS, RHS); diff --git a/llvm/test/Transforms/InstCombine/or.ll b/llvm/test/Transforms/InstCombine/or.ll index 64835ea9b839..2ac6f5b11047 100644 --- a/llvm/test/Transforms/InstCombine/or.ll +++ b/llvm/test/Transforms/InstCombine/or.ll @@ -223,9 +223,10 @@ define i1 @test19(i32 %A) { define i1 @or_icmps_eq_diff1(i32 %x) { ; CHECK-LABEL: @or_icmps_eq_diff1( -; CHECK-NEXT: [[X_OFF:%.*]] = add i32 %x, 1 -; CHECK-NEXT: [[TMP1:%.*]] = icmp ult i32 [[X_OFF]], 2 -; CHECK-NEXT: ret i1 [[TMP1]] +; CHECK-NEXT: [[CMP1:%.*]] = icmp eq i32 %x, -1 +; CHECK-NEXT: [[CMP2:%.*]] = icmp eq i32 %x, 0 +; CHECK-NEXT: [[LOGIC:%.*]] = or i1 [[CMP1]], [[CMP2]] +; CHECK-NEXT: ret i1 [[LOGIC]] ; %cmp1 = icmp eq i32 %x, -1 %cmp2 = icmp eq i32 %x, 0