Index: lib/Transforms/InstCombine/InstCombineCompares.cpp =================================================================== --- lib/Transforms/InstCombine/InstCombineCompares.cpp +++ lib/Transforms/InstCombine/InstCombineCompares.cpp @@ -1709,7 +1709,7 @@ cast(ConstantExpr::getShl(AndCst, ShAmt)); ConstantInt *ShiftedRHSCst = cast(ConstantExpr::getShl(RHS, ShAmt)); - + if (!ShiftedAndCst->isNegative() && !ShiftedRHSCst->isNegative()) CanFold = true; } @@ -2212,27 +2212,30 @@ } break; case Instruction::Xor: - // For the xor case, we can xor two constants together, eliminating - // the explicit xor. - if (Constant *BOC = dyn_cast(BO->getOperand(1))) { - return new ICmpInst(ICI.getPredicate(), BO->getOperand(0), - ConstantExpr::getXor(RHS, BOC)); - } else if (RHSV == 0) { - // Replace ((xor A, B) != 0) with (A != B) - return new ICmpInst(ICI.getPredicate(), BO->getOperand(0), - BO->getOperand(1)); + if (BO->hasOneUse()) { + if (Constant *BOC = dyn_cast(BO->getOperand(1))) { + // For the xor case, we can xor two constants together, eliminating + // the explicit xor. + return new ICmpInst(ICI.getPredicate(), BO->getOperand(0), + ConstantExpr::getXor(RHS, BOC)); + } else if (RHSV == 0) { + // Replace ((xor A, B) != 0) with (A != B) + return new ICmpInst(ICI.getPredicate(), BO->getOperand(0), + BO->getOperand(1)); + } } break; case Instruction::Sub: - // Replace ((sub A, B) != C) with (B != A-C) if A & C are constants. - if (ConstantInt *BOp0C = dyn_cast(BO->getOperand(0))) { - if (BO->hasOneUse()) + if (BO->hasOneUse()) { + if (ConstantInt *BOp0C = dyn_cast(BO->getOperand(0))) { + // Replace ((sub A, B) != C) with (B != A-C) if A & C are constants. return new ICmpInst(ICI.getPredicate(), BO->getOperand(1), - ConstantExpr::getSub(BOp0C, RHS)); - } else if (RHSV == 0) { - // Replace ((sub A, B) != 0) with (A != B) - return new ICmpInst(ICI.getPredicate(), BO->getOperand(0), - BO->getOperand(1)); + ConstantExpr::getSub(BOp0C, RHS)); + } else if (RHSV == 0) { + // Replace ((sub A, B) != 0) with (A != B) + return new ICmpInst(ICI.getPredicate(), BO->getOperand(0), + BO->getOperand(1)); + } } break; case Instruction::Or: @@ -4197,21 +4200,21 @@ // This would allow us to handle (fptosi (x >>s 62) to float) if x is i64 f.e. unsigned InputSize = IntTy->getScalarSizeInBits(); - // Following test does NOT adjust InputSize downwards for signed inputs, - // because the most negative value still requires all the mantissa bits + // Following test does NOT adjust InputSize downwards for signed inputs, + // because the most negative value still requires all the mantissa bits // to distinguish it from one less than that value. if ((int)InputSize > MantissaWidth) { // Conversion would lose accuracy. Check if loss can impact comparison. int Exp = ilogb(RHS); if (Exp == APFloat::IEK_Inf) { int MaxExponent = ilogb(APFloat::getLargest(RHS.getSemantics())); - if (MaxExponent < (int)InputSize - !LHSUnsigned) + if (MaxExponent < (int)InputSize - !LHSUnsigned) // Conversion could create infinity. return nullptr; } else { - // Note that if RHS is zero or NaN, then Exp is negative + // Note that if RHS is zero or NaN, then Exp is negative // and first condition is trivially false. - if (MantissaWidth <= Exp && Exp <= (int)InputSize - !LHSUnsigned) + if (MantissaWidth <= Exp && Exp <= (int)InputSize - !LHSUnsigned) // Conversion could affect comparison. return nullptr; } Index: test/Transforms/InstCombine/prevent-cmp-merge.ll =================================================================== --- /dev/null +++ test/Transforms/InstCombine/prevent-cmp-merge.ll @@ -0,0 +1,41 @@ +; RUN: opt < %s -instcombine -S | FileCheck %s +; +; This test makes sure that InstCombine does not replace the sequence of +; xor/sub instruction followed by cmp instruction into a single cmp instruction +; if there is more than one use of xor/sub. + +define zeroext i1 @test1(i32 %lhs, i32 %rhs) { +; CHECK-LABEL: @test1( +; CHECK-NEXT: %xor = xor i32 %lhs, 5 +; CHECK-NEXT: %cmp1 = icmp eq i32 %xor, 10 + + %xor = xor i32 %lhs, 5 + %cmp1 = icmp eq i32 %xor, 10 + %cmp2 = icmp eq i32 %xor, %rhs + %sel = or i1 %cmp1, %cmp2 + ret i1 %sel +} + +define zeroext i1 @test2(i32 %lhs, i32 %rhs) { +; CHECK-LABEL: @test2( +; CHECK-NEXT: %xor = xor i32 %lhs, %rhs +; CHECK-NEXT: %cmp1 = icmp eq i32 %xor, 0 + + %xor = xor i32 %lhs, %rhs + %cmp1 = icmp eq i32 %xor, 0 + %cmp2 = icmp eq i32 %xor, 32 + %sel = xor i1 %cmp1, %cmp2 + ret i1 %sel +} + +define zeroext i1 @test3(i32 %lhs, i32 %rhs) { +; CHECK-LABEL: @test3( +; CHECK-NEXT: %sub = sub nsw i32 %lhs, %rhs +; CHECK-NEXT: %cmp1 = icmp eq i32 %sub, 0 + + %sub = sub nsw i32 %lhs, %rhs + %cmp1 = icmp eq i32 %sub, 0 + %cmp2 = icmp eq i32 %sub, 31 + %sel = or i1 %cmp1, %cmp2 + ret i1 %sel +}