Skip to content

Commit

Permalink
ValueTracking: Handle frem in computeKnownFPClass
Browse files Browse the repository at this point in the history
I barely understand what this does, but try to
handle the last case required to delete cannotBeOrderedLessThanZeroImpl.
Also improve by following fdiv handling for nans and identical operand case.
  • Loading branch information
arsenm committed Apr 26, 2023
1 parent 9d53db2 commit de7bfec
Show file tree
Hide file tree
Showing 2 changed files with 64 additions and 35 deletions.
67 changes: 48 additions & 19 deletions llvm/lib/Analysis/ValueTracking.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4525,7 +4525,8 @@ void computeKnownFPClass(const Value *V, const APInt &DemandedElts,
if (Depth == MaxAnalysisRecursionDepth)
return;

switch (Op->getOpcode()) {
const unsigned Opc = Op->getOpcode();
switch (Opc) {
case Instruction::FNeg: {
computeKnownFPClass(Op->getOperand(0), DemandedElts, InterestedClasses,
Known, Depth + 1, Q, TLI);
Expand Down Expand Up @@ -4823,20 +4824,28 @@ void computeKnownFPClass(const Value *V, const APInt &DemandedElts,

break;
}
case Instruction::FDiv: {
// X / X is always exactly 1.0 or a NaN.
case Instruction::FDiv:
case Instruction::FRem: {
if (Op->getOperand(0) == Op->getOperand(1)) {
// TODO: Could filter out snan if we inspect the operand
Known.KnownFPClasses = fcNan | fcPosNormal;
if (Op->getOpcode() == Instruction::FDiv) {
// X / X is always exactly 1.0 or a NaN.
Known.KnownFPClasses = fcNan | fcPosNormal;
} else {
// X % X is always exactly [+-]0.0 or a NaN.
Known.KnownFPClasses = fcNan | fcZero;
}

break;
}

const bool WantNan = (InterestedClasses & fcNan) != fcNone;
const bool WantNegative = (InterestedClasses & fcNegative) != fcNone;
if (!WantNan && !WantNegative)
const bool WantPositive =
Opc == Instruction::FRem && (InterestedClasses & fcPositive) != fcNone;
if (!WantNan && !WantNegative && !WantPositive)
break;

// TODO: FRem
KnownFPClass KnownLHS, KnownRHS;

computeKnownFPClass(Op->getOperand(1), DemandedElts,
Expand All @@ -4846,26 +4855,46 @@ void computeKnownFPClass(const Value *V, const APInt &DemandedElts,
bool KnowSomethingUseful =
KnownRHS.isKnownNeverNaN() || KnownRHS.isKnownNever(fcNegative);

if (KnowSomethingUseful) {
if (KnowSomethingUseful || WantPositive) {
const FPClassTest InterestedLHS =
WantPositive ? fcAllFlags
: fcNan | fcInf | fcZero | fcSubnormal | fcNegative;

computeKnownFPClass(Op->getOperand(0), DemandedElts,
fcNan | fcInf | fcZero | fcNegative, KnownLHS,
InterestedClasses & InterestedLHS, KnownLHS,
Depth + 1, Q, TLI);
}

const Function *F = cast<Instruction>(Op)->getFunction();

// Only 0/0, Inf/Inf, Inf REM x and x REM 0 produce NaN.
if (KnownLHS.isKnownNeverNaN() && KnownRHS.isKnownNeverNaN() &&
(KnownLHS.isKnownNeverInfinity() || KnownRHS.isKnownNeverInfinity()) &&
(KnownLHS.isKnownNeverLogicalZero(*F, Op->getType()) ||
KnownRHS.isKnownNeverLogicalZero(*F, Op->getType()))) {
Known.knownNot(fcNan);
}
if (Op->getOpcode() == Instruction::FDiv) {
// Only 0/0, Inf/Inf produce NaN.
if (KnownLHS.isKnownNeverNaN() && KnownRHS.isKnownNeverNaN() &&
(KnownLHS.isKnownNeverInfinity() ||
KnownRHS.isKnownNeverInfinity()) &&
(KnownLHS.isKnownNeverLogicalZero(*F, Op->getType()) ||
KnownRHS.isKnownNeverLogicalZero(*F, Op->getType()))) {
Known.knownNot(fcNan);
}

// X / -0.0 is -Inf (or NaN).
// +X / +X is +X
if (KnownLHS.isKnownNever(fcNegative) && KnownRHS.isKnownNever(fcNegative))
Known.knownNot(fcNegative);
// X / -0.0 is -Inf (or NaN).
// +X / +X is +X
if (KnownLHS.isKnownNever(fcNegative) && KnownRHS.isKnownNever(fcNegative))
Known.knownNot(fcNegative);
} else {
// Inf REM x and x REM 0 produce NaN.
if (KnownLHS.isKnownNeverNaN() && KnownRHS.isKnownNeverNaN() &&
KnownLHS.isKnownNeverInfinity() &&
KnownRHS.isKnownNeverLogicalZero(*F, Op->getType())) {
Known.knownNot(fcNan);
}

// The sign for frem is the same as the first operand.
if (KnownLHS.isKnownNever(fcNegative))
Known.knownNot(fcNegative);
if (KnownLHS.isKnownNever(fcPositive))
Known.knownNot(fcPositive);
}

break;
}
Expand Down
32 changes: 16 additions & 16 deletions llvm/test/Transforms/Attributor/nofpclass-frem.ll
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ define float @ret_frem_ieee_nonan_nozero__nonan_noinf(float nofpclass(nan zero)
}

define float @ret_frem_ieee_nonan_noinf__nonan_nozero(float nofpclass(nan inf) %arg0, float nofpclass(nan zero) %arg1) #0 {
; CHECK-LABEL: define float @ret_frem_ieee_nonan_noinf__nonan_nozero
; CHECK-LABEL: define nofpclass(nan) float @ret_frem_ieee_nonan_noinf__nonan_nozero
; CHECK-SAME: (float nofpclass(nan inf) [[ARG0:%.*]], float nofpclass(nan zero) [[ARG1:%.*]]) #[[ATTR0]] {
; CHECK-NEXT: [[FREM:%.*]] = frem float [[ARG0]], [[ARG1]]
; CHECK-NEXT: ret float [[FREM]]
Expand Down Expand Up @@ -122,7 +122,7 @@ define float @ret_frem_daz_nonan_nozero_nosub__nonan_noinf(float nofpclass(nan z
}

define float @ret_frem_daz_nonan_noinf__nonan_nozero_nosub(float nofpclass(nan inf) %arg0, float nofpclass(nan zero sub) %arg1) #1 {
; CHECK-LABEL: define float @ret_frem_daz_nonan_noinf__nonan_nozero_nosub
; CHECK-LABEL: define nofpclass(nan) float @ret_frem_daz_nonan_noinf__nonan_nozero_nosub
; CHECK-SAME: (float nofpclass(nan inf) [[ARG0:%.*]], float nofpclass(nan zero sub) [[ARG1:%.*]]) #[[ATTR1]] {
; CHECK-NEXT: [[FREM:%.*]] = frem float [[ARG0]], [[ARG1]]
; CHECK-NEXT: ret float [[FREM]]
Expand All @@ -142,7 +142,7 @@ define float @ret_frem_ieee_nonan_noinf__nonan_noinf(float nofpclass(nan) %arg0,
}

define float @ret_frem_ieee_nonan_noinf_nozero__nonan_noinf_nozero(float nofpclass(nan inf zero) %arg0, float nofpclass(nan inf zero) %arg1) #0 {
; CHECK-LABEL: define float @ret_frem_ieee_nonan_noinf_nozero__nonan_noinf_nozero
; CHECK-LABEL: define nofpclass(nan) float @ret_frem_ieee_nonan_noinf_nozero__nonan_noinf_nozero
; CHECK-SAME: (float nofpclass(nan inf zero) [[ARG0:%.*]], float nofpclass(nan inf zero) [[ARG1:%.*]]) #[[ATTR0]] {
; CHECK-NEXT: [[FREM:%.*]] = frem float [[ARG0]], [[ARG1]]
; CHECK-NEXT: ret float [[FREM]]
Expand Down Expand Up @@ -202,7 +202,7 @@ define float @ret_frem_ieee_nonan_noinf_nozero__nonan_noinf_noinf(float nofpclas
}

define float @ret_frem_ieee_nonan_noinf_noinf__nonan_noinf_nozero(float nofpclass(nan inf) %arg0, float nofpclass(nan inf zero) %arg1) #0 {
; CHECK-LABEL: define float @ret_frem_ieee_nonan_noinf_noinf__nonan_noinf_nozero
; CHECK-LABEL: define nofpclass(nan) float @ret_frem_ieee_nonan_noinf_noinf__nonan_noinf_nozero
; CHECK-SAME: (float nofpclass(nan inf) [[ARG0:%.*]], float nofpclass(nan inf zero) [[ARG1:%.*]]) #[[ATTR0]] {
; CHECK-NEXT: [[FREM:%.*]] = frem float [[ARG0]], [[ARG1]]
; CHECK-NEXT: ret float [[FREM]]
Expand Down Expand Up @@ -232,7 +232,7 @@ define float @ret_frem_ieee_nonan_noinf_noposzero__nonan_noinf_noinf(float nofpc
}

define float @ret_frem_ieee_nonan_noinf_nozero_nosub__nonan_noinf_nozero_nosub(float nofpclass(nan inf zero sub) %arg0, float nofpclass(nan inf zero sub) %arg1) #0 {
; CHECK-LABEL: define float @ret_frem_ieee_nonan_noinf_nozero_nosub__nonan_noinf_nozero_nosub
; CHECK-LABEL: define nofpclass(nan) float @ret_frem_ieee_nonan_noinf_nozero_nosub__nonan_noinf_nozero_nosub
; CHECK-SAME: (float nofpclass(nan inf zero sub) [[ARG0:%.*]], float nofpclass(nan inf zero sub) [[ARG1:%.*]]) #[[ATTR0]] {
; CHECK-NEXT: [[FREM:%.*]] = frem float [[ARG0]], [[ARG1]]
; CHECK-NEXT: ret float [[FREM]]
Expand All @@ -243,7 +243,7 @@ define float @ret_frem_ieee_nonan_noinf_nozero_nosub__nonan_noinf_nozero_nosub(f

; Denormal mode doesn't matter because sources are nofpclass(sub)
define float @ret_frem_daz_nonan_noinf_nozero_nosub__nonan_noinf_nozero_nosub(float nofpclass(nan inf zero sub) %arg0, float nofpclass(nan inf zero sub) %arg1) #1 {
; CHECK-LABEL: define float @ret_frem_daz_nonan_noinf_nozero_nosub__nonan_noinf_nozero_nosub
; CHECK-LABEL: define nofpclass(nan) float @ret_frem_daz_nonan_noinf_nozero_nosub__nonan_noinf_nozero_nosub
; CHECK-SAME: (float nofpclass(nan inf zero sub) [[ARG0:%.*]], float nofpclass(nan inf zero sub) [[ARG1:%.*]]) #[[ATTR1]] {
; CHECK-NEXT: [[FREM:%.*]] = frem float [[ARG0]], [[ARG1]]
; CHECK-NEXT: ret float [[FREM]]
Expand All @@ -253,7 +253,7 @@ define float @ret_frem_daz_nonan_noinf_nozero_nosub__nonan_noinf_nozero_nosub(fl
}

define float @ret_frem_dapz_nonan_noinf_nozero_nosub__nonan_noinf_nozero_nosub(float nofpclass(nan inf zero sub) %arg0, float nofpclass(nan inf zero sub) %arg1) #2 {
; CHECK-LABEL: define float @ret_frem_dapz_nonan_noinf_nozero_nosub__nonan_noinf_nozero_nosub
; CHECK-LABEL: define nofpclass(nan) float @ret_frem_dapz_nonan_noinf_nozero_nosub__nonan_noinf_nozero_nosub
; CHECK-SAME: (float nofpclass(nan inf zero sub) [[ARG0:%.*]], float nofpclass(nan inf zero sub) [[ARG1:%.*]]) #[[ATTR2]] {
; CHECK-NEXT: [[FREM:%.*]] = frem float [[ARG0]], [[ARG1]]
; CHECK-NEXT: ret float [[FREM]]
Expand All @@ -263,7 +263,7 @@ define float @ret_frem_dapz_nonan_noinf_nozero_nosub__nonan_noinf_nozero_nosub(f
}

define float @ret_frem_dynamic_nonan_noinf_nozero_nosub__nonan_noinf_nozero_nosub(float nofpclass(nan inf zero sub) %arg0, float nofpclass(nan inf zero sub) %arg1) #3 {
; CHECK-LABEL: define float @ret_frem_dynamic_nonan_noinf_nozero_nosub__nonan_noinf_nozero_nosub
; CHECK-LABEL: define nofpclass(nan) float @ret_frem_dynamic_nonan_noinf_nozero_nosub__nonan_noinf_nozero_nosub
; CHECK-SAME: (float nofpclass(nan inf zero sub) [[ARG0:%.*]], float nofpclass(nan inf zero sub) [[ARG1:%.*]]) #[[ATTR3]] {
; CHECK-NEXT: [[FREM:%.*]] = frem float [[ARG0]], [[ARG1]]
; CHECK-NEXT: ret float [[FREM]]
Expand All @@ -274,7 +274,7 @@ define float @ret_frem_dynamic_nonan_noinf_nozero_nosub__nonan_noinf_nozero_nosu

; Missing no-subnormal on lhs
define float @ret_frem_daz_nonan_noinf_nozero__nonan_noinf_nozero_nosub(float nofpclass(nan inf zero) %arg0, float nofpclass(nan inf zero sub) %arg1) #1 {
; CHECK-LABEL: define float @ret_frem_daz_nonan_noinf_nozero__nonan_noinf_nozero_nosub
; CHECK-LABEL: define nofpclass(nan) float @ret_frem_daz_nonan_noinf_nozero__nonan_noinf_nozero_nosub
; CHECK-SAME: (float nofpclass(nan inf zero) [[ARG0:%.*]], float nofpclass(nan inf zero sub) [[ARG1:%.*]]) #[[ATTR1]] {
; CHECK-NEXT: [[FREM:%.*]] = frem float [[ARG0]], [[ARG1]]
; CHECK-NEXT: ret float [[FREM]]
Expand Down Expand Up @@ -356,7 +356,7 @@ define float @ret_frem_daz_noinf__nozero_nosub(float nofpclass(inf) %arg0, float
}

define float @ret_frem_same_operands(float %arg) #0 {
; CHECK-LABEL: define float @ret_frem_same_operands
; CHECK-LABEL: define nofpclass(inf sub norm) float @ret_frem_same_operands
; CHECK-SAME: (float [[ARG:%.*]]) #[[ATTR0]] {
; CHECK-NEXT: [[FREM:%.*]] = frem float [[ARG]], [[ARG]]
; CHECK-NEXT: ret float [[FREM]]
Expand All @@ -366,7 +366,7 @@ define float @ret_frem_same_operands(float %arg) #0 {
}

define float @ret_frem_same_operands_nosnan(float nofpclass(snan) %arg) #0 {
; CHECK-LABEL: define float @ret_frem_same_operands_nosnan
; CHECK-LABEL: define nofpclass(inf sub norm) float @ret_frem_same_operands_nosnan
; CHECK-SAME: (float nofpclass(snan) [[ARG:%.*]]) #[[ATTR0]] {
; CHECK-NEXT: [[FREM:%.*]] = frem float [[ARG]], [[ARG]]
; CHECK-NEXT: ret float [[FREM]]
Expand All @@ -376,7 +376,7 @@ define float @ret_frem_same_operands_nosnan(float nofpclass(snan) %arg) #0 {
}

define float @ret_frem_same_operands_noqnan(float nofpclass(qnan) %arg) #0 {
; CHECK-LABEL: define float @ret_frem_same_operands_noqnan
; CHECK-LABEL: define nofpclass(inf sub norm) float @ret_frem_same_operands_noqnan
; CHECK-SAME: (float nofpclass(qnan) [[ARG:%.*]]) #[[ATTR0]] {
; CHECK-NEXT: [[FREM:%.*]] = frem float [[ARG]], [[ARG]]
; CHECK-NEXT: ret float [[FREM]]
Expand All @@ -386,7 +386,7 @@ define float @ret_frem_same_operands_noqnan(float nofpclass(qnan) %arg) #0 {
}

define float @ret_frem_same_operands_nonan(float nofpclass(nan) %arg) #0 {
; CHECK-LABEL: define float @ret_frem_same_operands_nonan
; CHECK-LABEL: define nofpclass(inf sub norm) float @ret_frem_same_operands_nonan
; CHECK-SAME: (float nofpclass(nan) [[ARG:%.*]]) #[[ATTR0]] {
; CHECK-NEXT: [[FREM:%.*]] = frem float [[ARG]], [[ARG]]
; CHECK-NEXT: ret float [[FREM]]
Expand Down Expand Up @@ -436,7 +436,7 @@ define float @ret_frem_no_neg(float nofpclass(ninf nsub nnorm) %arg0, float nofp
}

define float @ret_frem_no_neg_nzero(float nofpclass(ninf nsub nnorm nzero) %arg0, float nofpclass(ninf nsub nnorm nzero) %arg1) #0 {
; CHECK-LABEL: define float @ret_frem_no_neg_nzero
; CHECK-LABEL: define nofpclass(ninf nzero nsub nnorm) float @ret_frem_no_neg_nzero
; CHECK-SAME: (float nofpclass(ninf nzero nsub nnorm) [[ARG0:%.*]], float nofpclass(ninf nzero nsub nnorm) [[ARG1:%.*]]) #[[ATTR0]] {
; CHECK-NEXT: [[FREM:%.*]] = frem float [[ARG0]], [[ARG1]]
; CHECK-NEXT: ret float [[FREM]]
Expand All @@ -456,7 +456,7 @@ define float @ret_frem_no_neg_rhs_no_nzero(float nofpclass(ninf nsub nnorm) %arg
}

define float @ret_frem_no_neg_no_zero_rhs(float nofpclass(ninf nsub nnorm nzero) %arg0, float nofpclass(ninf nsub nnorm zero) %arg1) #0 {
; CHECK-LABEL: define float @ret_frem_no_neg_no_zero_rhs
; CHECK-LABEL: define nofpclass(ninf nzero nsub nnorm) float @ret_frem_no_neg_no_zero_rhs
; CHECK-SAME: (float nofpclass(ninf nzero nsub nnorm) [[ARG0:%.*]], float nofpclass(ninf zero nsub nnorm) [[ARG1:%.*]]) #[[ATTR0]] {
; CHECK-NEXT: [[FREM:%.*]] = frem float [[ARG0]], [[ARG1]]
; CHECK-NEXT: ret float [[FREM]]
Expand All @@ -466,7 +466,7 @@ define float @ret_frem_no_neg_no_zero_rhs(float nofpclass(ninf nsub nnorm nzero)
}

define float @ret_frem_no_pos_lhs(float nofpclass(pinf psub pnorm pzero) %arg0, float %arg1) #0 {
; CHECK-LABEL: define float @ret_frem_no_pos_lhs
; CHECK-LABEL: define nofpclass(pinf pzero psub pnorm) float @ret_frem_no_pos_lhs
; CHECK-SAME: (float nofpclass(pinf pzero psub pnorm) [[ARG0:%.*]], float [[ARG1:%.*]]) #[[ATTR0]] {
; CHECK-NEXT: [[FREM:%.*]] = frem float [[ARG0]], [[ARG1]]
; CHECK-NEXT: ret float [[FREM]]
Expand Down

0 comments on commit de7bfec

Please sign in to comment.