summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSanjay Patel <spatel@rotateright.com>2017-12-26 15:09:19 +0000
committerSanjay Patel <spatel@rotateright.com>2017-12-26 15:09:19 +0000
commitba5e1fbe8d22fd8cc29e3b654c66ed7c39584fe4 (patch)
treed34356d13b10204b2aa64c3de82548512b477d96
parent03438cb38e811137a5386d71ccb6379707cf7d52 (diff)
[ValueTracking] ignore FP signed-zero when detecting a casted-to-integer fmin/fmax pattern
This is a preliminary step for the patch discussed in D41136 (and denoted here with the FIXME comment). When we match an FP min/max that is cast to integer, any intermediate difference between +0.0 or -0.0 should be muted in the result by the conversion (either fptosi or fptoui) of the result. Thus, we can enable 'nsz' for the purpose of matching fmin/fmax. Note that there's probably room to generalize this more, possibly by fixing the current calls to the weak version of isKnownNonZero() in matchSelectPattern() to the more powerful recursive version. Differential Revision: https://reviews.llvm.org/D41333 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@321456 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--lib/Analysis/ValueTracking.cpp26
-rw-r--r--test/Transforms/InstCombine/minmax-fp.ll23
2 files changed, 36 insertions, 13 deletions
diff --git a/lib/Analysis/ValueTracking.cpp b/lib/Analysis/ValueTracking.cpp
index 2730daefa62..cd4cee63156 100644
--- a/lib/Analysis/ValueTracking.cpp
+++ b/lib/Analysis/ValueTracking.cpp
@@ -4238,14 +4238,14 @@ static SelectPatternResult matchSelectPattern(CmpInst::Predicate Pred,
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 @@ SelectPatternResult llvm::matchSelectPattern(Value *V, Value *&LHS, Value *&RHS,
// 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<CastInst>(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<CastInst>(FalseVal)->getOperand(0),
LHS, RHS);
+ }
}
return ::matchSelectPattern(Pred, FMF, CmpLHS, CmpRHS, TrueVal, FalseVal,
LHS, RHS);
diff --git a/test/Transforms/InstCombine/minmax-fp.ll b/test/Transforms/InstCombine/minmax-fp.ll
index 0851a5d435b..b94bce2dbb8 100644
--- a/test/Transforms/InstCombine/minmax-fp.ll
+++ b/test/Transforms/InstCombine/minmax-fp.ll
@@ -155,13 +155,13 @@ define i8 @t13(float %a) {
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
@@ -169,6 +169,19 @@ define i8 @t14(float %a) {
ret i8 %3
}
+define i8 @t14_commute(float %a) {
+; CHECK-LABEL: @t14_commute(
+; CHECK-NEXT: [[TMP1:%.*]] = fcmp ogt float %a, 0.000000e+00
+; CHECK-NEXT: [[TMP2:%.*]] = select i1 [[TMP1]], float %a, float 0.000000e+00
+; CHECK-NEXT: [[TMP3:%.*]] = fptosi float [[TMP2]] to i8
+; CHECK-NEXT: ret i8 [[TMP3]]
+;
+ %1 = fcmp ule float %a, 0.0
+ %2 = fptosi float %a to i8
+ %3 = select i1 %1, i8 0, i8 %2
+ ret i8 %3
+}
+
define i8 @t15(float %a) {
; CHECK-LABEL: @t15(
; CHECK-NEXT: [[DOTINV:%.*]] = fcmp nsz oge float %a, 0.000000e+00