Index: lib/Analysis/ValueTracking.cpp =================================================================== --- lib/Analysis/ValueTracking.cpp +++ lib/Analysis/ValueTracking.cpp @@ -4238,14 +4238,14 @@ LHS = CmpLHS; RHS = CmpRHS; - // If the predicate is an "or-equal" (FP) predicate, then signed zeroes may - // return inconsistent results between implementations. - // (0.0 <= -0.0) ? 0.0 : -0.0 // Returns 0.0 - // minNum(0.0, -0.0) // May return -0.0 or 0.0 (IEEE 754-2008 5.3.1) - // Therefore we behave conservatively and only proceed if at least one of the - // operands is known to not be zero, or if we don't care about signed zeroes. + // Signed zero may return inconsistent results between implementations. + // (0.0 <= -0.0) ? 0.0 : -0.0 // Returns 0.0 + // minNum(0.0, -0.0) // May return -0.0 or 0.0 (IEEE 754-2008 5.3.1) + // Therefore, we behave conservatively and only proceed if at least one of the + // operands is known to not be zero or if we don't care about signed zero. switch (Pred) { default: break; + // FIXME: Include OGT/OLT/UGT/ULT. case CmpInst::FCMP_OGE: case CmpInst::FCMP_OLE: case CmpInst::FCMP_UGE: case CmpInst::FCMP_ULE: if (!FMF.noSignedZeros() && !isKnownNonZero(CmpLHS) && @@ -4493,14 +4493,24 @@ // Deal with type mismatches. if (CastOp && CmpLHS->getType() != TrueVal->getType()) { - if (Value *C = lookThroughCast(CmpI, TrueVal, FalseVal, CastOp)) + if (Value *C = lookThroughCast(CmpI, TrueVal, FalseVal, CastOp)) { + // If this is a potential fmin/fmax with a cast to integer, then ignore + // -0.0 because there is no corresponding integer value. + if (*CastOp == Instruction::FPToSI || *CastOp == Instruction::FPToUI) + FMF.setNoSignedZeros(); return ::matchSelectPattern(Pred, FMF, CmpLHS, CmpRHS, cast(TrueVal)->getOperand(0), C, LHS, RHS); - if (Value *C = lookThroughCast(CmpI, FalseVal, TrueVal, CastOp)) + } + if (Value *C = lookThroughCast(CmpI, FalseVal, TrueVal, CastOp)) { + // If this is a potential fmin/fmax with a cast to integer, then ignore + // -0.0 because there is no corresponding integer value. + if (*CastOp == Instruction::FPToSI || *CastOp == Instruction::FPToUI) + FMF.setNoSignedZeros(); return ::matchSelectPattern(Pred, FMF, CmpLHS, CmpRHS, C, cast(FalseVal)->getOperand(0), LHS, RHS); + } } return ::matchSelectPattern(Pred, FMF, CmpLHS, CmpRHS, TrueVal, FalseVal, LHS, RHS); Index: test/Transforms/InstCombine/minmax-fp.ll =================================================================== --- test/Transforms/InstCombine/minmax-fp.ll +++ test/Transforms/InstCombine/minmax-fp.ll @@ -155,13 +155,13 @@ ret i8 %3 } -; <= comparison, where %a could be -0.0. Not safe. +; %a could be -0.0, but it doesn't matter because the conversion to int is the same for 0.0 or -0.0. define i8 @t14(float %a) { ; CHECK-LABEL: @t14( -; CHECK-NEXT: [[TMP1:%.*]] = fcmp ule float %a, 0.000000e+00 -; CHECK-NEXT: [[TMP2:%.*]] = fptosi float %a to i8 -; CHECK-NEXT: [[TMP3:%.*]] = select i1 [[TMP1]], i8 [[TMP2]], i8 0 -; CHECK-NEXT: ret i8 [[TMP3]] +; CHECK-NEXT: [[DOTINV:%.*]] = fcmp oge float %a, 0.000000e+00 +; CHECK-NEXT: [[TMP1:%.*]] = select i1 [[DOTINV]], float 0.000000e+00, float %a +; CHECK-NEXT: [[TMP2:%.*]] = fptosi float [[TMP1]] to i8 +; CHECK-NEXT: ret i8 [[TMP2]] ; %1 = fcmp ule float %a, 0.0 %2 = fptosi float %a to i8