[PATCH] D41136: [EarlyCSE] recognize commuted and swapped variants of min/max as equivalent (PR35642)
Hal Finkel via Phabricator via llvm-commits
llvm-commits at lists.llvm.org
Thu Dec 14 11:15:50 PST 2017
hfinkel added a comment.
In https://reviews.llvm.org/D41136#955455, @spatel wrote:
> On closer inspection, I think matchSelectPattern is either not sufficient or broken because it doesn't handle -0.0 as we would require here:
>
> declare void @self_destruct_if_neg_zero(double)
> define double @fmin_any_ordered_commute(double %x, double %y) {
> %cmp1 = fcmp nnan olt double %x, %y ; if x=+0.0 and y=-0.0, returns false
> %cmp2 = fcmp nnan olt double %y, %x ; if x=+0.0 and y=-0.0, returns false
> %neg_zero_if_false = select i1 %cmp1, double %x, double %y ; returns -0.0
> %pos_zero_if_false = select i1 %cmp2, double %y, double %x ; returns +0.0
> call void @self_destruct_if_neg_zero(double %pos_zero_if_false)
> ret double %neg_zero_if_false
> }
>
>
> If we use what is returned by matchSelectPattern ( {SPF_FMINNUM, SPNB_RETURNS_ANY, false} ), we get:
>
> $ ./opt -early-cse fminmax.ll -S
>
> define double @fmin_any_ordered_commute(double %x, double %y) {
> %cmp1 = fcmp nnan olt double %x, %y
> %cmp2 = fcmp nnan olt double %y, %x
> %neg_zero_if_false = select i1 %cmp1, double %x, double %y
> call void @self_destruct_if_neg_zero(double %neg_zero_if_false) ; boom!
> ret double %neg_zero_if_false
> }
>
>
This seems inconsistent with the intent of matchSelectPattern, at least based on the comment:
// 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.
switch (Pred) {
default: break;
case CmpInst::FCMP_OGE: case CmpInst::FCMP_OLE:
case CmpInst::FCMP_UGE: case CmpInst::FCMP_ULE:
if (!FMF.noSignedZeros() && !isKnownNonZero(CmpLHS) &&
!isKnownNonZero(CmpRHS))
return {SPF_UNKNOWN, SPNB_NA, false};
}
It seems like there are cases missing here (e.g., this does not apply only to the GE/LE predicates)? Based on your example, it seems like we have the same problem with the GT/LT predicates.
Repository:
rL LLVM
https://reviews.llvm.org/D41136
More information about the llvm-commits
mailing list