[llvm] 598721f - [InstCombine] try harder to propagate 'nsz' through fneg-of-select
Sanjay Patel via llvm-commits
llvm-commits at lists.llvm.org
Tue Mar 15 08:05:41 PDT 2022
Author: Sanjay Patel
Date: 2022-03-15T11:05:29-04:00
New Revision: 598721f866156ba1259af37d9b30b1ec95983678
URL: https://github.com/llvm/llvm-project/commit/598721f866156ba1259af37d9b30b1ec95983678
DIFF: https://github.com/llvm/llvm-project/commit/598721f866156ba1259af37d9b30b1ec95983678.diff
LOG: [InstCombine] try harder to propagate 'nsz' through fneg-of-select
This can be viewed as swapping the select arms:
https://alive2.llvm.org/ce/z/jUvFMJ
...so we don't have the 'nsz' problem with the more general fold.
This unlocks other folds for the motivating fabs example.
This was discussed in issue #38828.
Added:
Modified:
llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp
llvm/test/Transforms/InstCombine/fneg.ll
Removed:
################################################################################
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp b/llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp
index ff186d1f3e7eb..de79fe0ec507d 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp
@@ -2268,10 +2268,10 @@ Instruction *InstCombinerImpl::visitFNeg(UnaryOperator &I) {
// Unlike most transforms, this one is not safe to propagate nsz unless
// it is present on the original select. (We are conservatively intersecting
// the nsz flags from the select and root fneg instruction.)
- auto propagateSelectFMF = [&](SelectInst *S) {
+ auto propagateSelectFMF = [&](SelectInst *S, bool CommonOperand) {
S->copyFastMathFlags(&I);
if (auto *OldSel = dyn_cast<SelectInst>(Op))
- if (!OldSel->hasNoSignedZeros() &&
+ if (!OldSel->hasNoSignedZeros() && !CommonOperand &&
!isGuaranteedNotToBeUndefOrPoison(OldSel->getCondition()))
S->setHasNoSignedZeros(false);
};
@@ -2280,14 +2280,14 @@ Instruction *InstCombinerImpl::visitFNeg(UnaryOperator &I) {
if (match(X, m_FNeg(m_Value(P)))) {
Value *NegY = Builder.CreateFNegFMF(Y, &I, Y->getName() + ".neg");
SelectInst *NewSel = SelectInst::Create(Cond, P, NegY);
- propagateSelectFMF(NewSel);
+ propagateSelectFMF(NewSel, P == Y);
return NewSel;
}
// -(Cond ? X : -P) --> Cond ? -X : P
if (match(Y, m_FNeg(m_Value(P)))) {
Value *NegX = Builder.CreateFNegFMF(X, &I, X->getName() + ".neg");
SelectInst *NewSel = SelectInst::Create(Cond, NegX, P);
- propagateSelectFMF(NewSel);
+ propagateSelectFMF(NewSel, P == X);
return NewSel;
}
}
diff --git a/llvm/test/Transforms/InstCombine/fneg.ll b/llvm/test/Transforms/InstCombine/fneg.ll
index 2af1e6ea26b5b..c111b0080ee0f 100644
--- a/llvm/test/Transforms/InstCombine/fneg.ll
+++ b/llvm/test/Transforms/InstCombine/fneg.ll
@@ -674,10 +674,12 @@ define float @select_fneg_false_nsz(float %x, float %y, i1 %b) {
ret float %r
}
+; Special-case for propagating nsz: it's ok when selecting between an operand and its negation.
+
define float @select_common_op_fneg_true(float %x, i1 %b) {
; CHECK-LABEL: @select_common_op_fneg_true(
; CHECK-NEXT: [[X_NEG:%.*]] = fneg nnan ninf nsz float [[X:%.*]]
-; CHECK-NEXT: [[R:%.*]] = select nnan ninf i1 [[B:%.*]], float [[X_NEG]], float [[X]]
+; CHECK-NEXT: [[R:%.*]] = select nnan ninf nsz i1 [[B:%.*]], float [[X_NEG]], float [[X]]
; CHECK-NEXT: ret float [[R]]
;
%nx = fneg float %x
@@ -689,7 +691,7 @@ define float @select_common_op_fneg_true(float %x, i1 %b) {
define float @select_common_op_fneg_false(float %x, i1 %b) {
; CHECK-LABEL: @select_common_op_fneg_false(
; CHECK-NEXT: [[X_NEG:%.*]] = fneg nnan ninf nsz float [[X:%.*]]
-; CHECK-NEXT: [[R:%.*]] = select nnan ninf i1 [[B:%.*]], float [[X_NEG]], float [[X]]
+; CHECK-NEXT: [[R:%.*]] = select nnan ninf nsz i1 [[B:%.*]], float [[X_NEG]], float [[X]]
; CHECK-NEXT: ret float [[R]]
;
%nx = fneg float %x
@@ -698,12 +700,12 @@ define float @select_common_op_fneg_false(float %x, i1 %b) {
ret float %r
}
+; The transform above allows follow-on folds to convert to fabs.
+
define float @fabs(float %a) {
; CHECK-LABEL: @fabs(
-; CHECK-NEXT: [[CMP:%.*]] = fcmp ogt float [[A:%.*]], 0.000000e+00
-; CHECK-NEXT: [[A_NEG:%.*]] = fneg nnan ninf nsz float [[A]]
-; CHECK-NEXT: [[FNEG1:%.*]] = select nnan ninf i1 [[CMP]], float [[A]], float [[A_NEG]]
-; CHECK-NEXT: ret float [[FNEG1]]
+; CHECK-NEXT: [[TMP1:%.*]] = call nnan ninf nsz float @llvm.fabs.f32(float [[A:%.*]])
+; CHECK-NEXT: ret float [[TMP1]]
;
%fneg = fneg float %a
%cmp = fcmp ogt float %a, %fneg
@@ -712,11 +714,13 @@ define float @fabs(float %a) {
ret float %fneg1
}
+; TODO: This should reduce to fneg-of-fabs.
+
define float @fnabs(float %a) {
; CHECK-LABEL: @fnabs(
; CHECK-NEXT: [[CMP:%.*]] = fcmp olt float [[A:%.*]], 0.000000e+00
; CHECK-NEXT: [[A_NEG:%.*]] = fneg fast float [[A]]
-; CHECK-NEXT: [[FNEG1:%.*]] = select reassoc nnan ninf arcp contract afn i1 [[CMP]], float [[A]], float [[A_NEG]]
+; CHECK-NEXT: [[FNEG1:%.*]] = select fast i1 [[CMP]], float [[A]], float [[A_NEG]]
; CHECK-NEXT: ret float [[FNEG1]]
;
%fneg = fneg float %a
More information about the llvm-commits
mailing list