Skip to content

Commit 6b9f044

Browse files
committed
GVN: generalize impliesEquivalence (NFC)
impliesEquivalenceIfTrue and impliesEquivalenceIfFalse can be extended to aggregates easily, although as the added tests show, the codepath cannot be exercised: GVN does not propogate values through a vector-select. Generalize the code anyway, as it opens up opportunities for optimizing GVN. While at it, note that the optimization is invalid for the no-signed-zeros case, and strip the bad FIXME. Alive2 proof: https://alive2.llvm.org/ce/z/vEaK8M
1 parent 7fa0d05 commit 6b9f044

File tree

2 files changed

+48
-24
lines changed

2 files changed

+48
-24
lines changed

llvm/lib/Transforms/Scalar/GVN.cpp

Lines changed: 20 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1998,19 +1998,17 @@ static bool impliesEquivalanceIfTrue(CmpInst* Cmp) {
19981998
// +0.0 vs 0.0 for all operators
19991999
if (Cmp->getPredicate() == CmpInst::Predicate::FCMP_OEQ ||
20002000
(Cmp->getPredicate() == CmpInst::Predicate::FCMP_UEQ &&
2001-
Cmp->getFastMathFlags().noNaNs())) {
2002-
Value *LHS = Cmp->getOperand(0);
2003-
Value *RHS = Cmp->getOperand(1);
2004-
// If we can prove either side non-zero, then equality must imply
2005-
// equivalence.
2006-
// FIXME: We should do this optimization if 'no signed zeros' is
2007-
// applicable via an instruction-level fast-math-flag or some other
2008-
// indicator that relaxed FP semantics are being used.
2009-
if (isa<ConstantFP>(LHS) && !cast<ConstantFP>(LHS)->isZero())
2001+
Cmp->hasNoNaNs())) {
2002+
Value *LHS = Cmp->getOperand(0);
2003+
Value *RHS = Cmp->getOperand(1);
2004+
// If we can prove either side non-zero, then equality must imply
2005+
// equivalence.
2006+
auto *ConstLHS = dyn_cast<Constant>(LHS),
2007+
*ConstRHS = dyn_cast<Constant>(RHS);
2008+
if (auto *Const = ConstLHS ? ConstLHS : ConstRHS) {
2009+
if (!Const->isZeroValue())
20102010
return true;
2011-
if (isa<ConstantFP>(RHS) && !cast<ConstantFP>(RHS)->isZero())
2012-
return true;
2013-
// TODO: Handle vector floating point constants
2011+
}
20142012
}
20152013
return false;
20162014
}
@@ -2023,20 +2021,18 @@ static bool impliesEquivalanceIfFalse(CmpInst* Cmp) {
20232021
// NaNs for unordered operators
20242022
// +0.0 vs 0.0 for all operators
20252023
if ((Cmp->getPredicate() == CmpInst::Predicate::FCMP_ONE &&
2026-
Cmp->getFastMathFlags().noNaNs()) ||
2024+
Cmp->hasNoNaNs()) ||
20272025
Cmp->getPredicate() == CmpInst::Predicate::FCMP_UNE) {
2028-
Value *LHS = Cmp->getOperand(0);
2029-
Value *RHS = Cmp->getOperand(1);
2030-
// If we can prove either side non-zero, then equality must imply
2031-
// equivalence.
2032-
// FIXME: We should do this optimization if 'no signed zeros' is
2033-
// applicable via an instruction-level fast-math-flag or some other
2034-
// indicator that relaxed FP semantics are being used.
2035-
if (isa<ConstantFP>(LHS) && !cast<ConstantFP>(LHS)->isZero())
2026+
Value *LHS = Cmp->getOperand(0);
2027+
Value *RHS = Cmp->getOperand(1);
2028+
// If we can prove either side non-zero, then equality must imply
2029+
// equivalence.
2030+
auto *ConstLHS = dyn_cast<Constant>(LHS),
2031+
*ConstRHS = dyn_cast<Constant>(RHS);
2032+
if (auto *Const = ConstLHS ? ConstLHS : ConstRHS) {
2033+
if (!Const->isZeroValue())
20362034
return true;
2037-
if (isa<ConstantFP>(RHS) && !cast<ConstantFP>(RHS)->isZero())
2038-
return true;
2039-
// TODO: Handle vector floating point constants
2035+
}
20402036
}
20412037
return false;
20422038
}

llvm/test/Transforms/GVN/edge.ll

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,20 @@ return:
117117
ret double %retval
118118
}
119119

120+
define <2 x double> @fcmp_oeq_not_zero_vec(<2 x double> %x, <2 x double> %y) {
121+
; CHECK-LABEL: define <2 x double> @fcmp_oeq_not_zero_vec(
122+
; CHECK-SAME: <2 x double> [[X:%.*]], <2 x double> [[Y:%.*]]) {
123+
; CHECK-NEXT: [[FCMP:%.*]] = fcmp oeq <2 x double> [[Y]], <double 2.000000e+00, double 2.000000e+00>
124+
; CHECK-NEXT: [[DIV:%.*]] = fdiv <2 x double> [[X]], [[Y]]
125+
; CHECK-NEXT: [[RETVAL:%.*]] = select <2 x i1> [[FCMP]], <2 x double> [[DIV]], <2 x double> [[X]]
126+
; CHECK-NEXT: ret <2 x double> [[RETVAL]]
127+
;
128+
%fcmp = fcmp oeq <2 x double> %y, <double 2.0, double 2.0>
129+
%div = fdiv <2 x double> %x, %y
130+
%retval = select <2 x i1> %fcmp, <2 x double> %div, <2 x double> %x
131+
ret <2 x double> %retval
132+
}
133+
120134
define double @fcmp_une_not_zero(double %x, double %y) {
121135
; CHECK-LABEL: define double @fcmp_une_not_zero(
122136
; CHECK-SAME: double [[X:%.*]], double [[Y:%.*]]) {
@@ -143,6 +157,20 @@ return:
143157
ret double %retval
144158
}
145159

160+
define <2 x double> @fcmp_une_not_zero_vec(<2 x double> %x, <2 x double> %y) {
161+
; CHECK-LABEL: define <2 x double> @fcmp_une_not_zero_vec(
162+
; CHECK-SAME: <2 x double> [[X:%.*]], <2 x double> [[Y:%.*]]) {
163+
; CHECK-NEXT: [[FCMP:%.*]] = fcmp une <2 x double> [[Y]], <double 2.000000e+00, double 2.000000e+00>
164+
; CHECK-NEXT: [[DIV:%.*]] = fdiv <2 x double> [[X]], [[Y]]
165+
; CHECK-NEXT: [[RETVAL:%.*]] = select <2 x i1> [[FCMP]], <2 x double> [[X]], <2 x double> [[DIV]]
166+
; CHECK-NEXT: ret <2 x double> [[RETVAL]]
167+
;
168+
%fcmp = fcmp une <2 x double> %y, <double 2.0, double 2.0>
169+
%div = fdiv <2 x double> %x, %y
170+
%retval = select <2 x i1> %fcmp, <2 x double> %x, <2 x double> %div
171+
ret <2 x double> %retval
172+
}
173+
146174
define double @fcmp_one_possibly_nan(double %x, double %y) {
147175
; CHECK-LABEL: define double @fcmp_one_possibly_nan(
148176
; CHECK-SAME: double [[X:%.*]], double [[Y:%.*]]) {

0 commit comments

Comments
 (0)