From: Sanjay Patel Date: Fri, 9 Dec 2022 15:58:27 +0000 (-0500) Subject: [InstCombine] allow more fast-math-flags to propagate in fneg-of-select fold X-Git-Tag: upstream/17.0.6~24493 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=93099c7d21727dd94383783020de4c89a6c5809c;p=platform%2Fupstream%2Fllvm.git [InstCombine] allow more fast-math-flags to propagate in fneg-of-select fold We were conservatively intersecting flags, but we can take the union here because forbidden special values (nsz/nnan/ninf) are not altered by fneg. So if they were guaranteed not present on the select or fneg, then they are guaranteed not present on the new select. Alive2 appears to agree on the test diffs (reduced to not include irrelevant flags like reassoc): https://alive2.llvm.org/ce/z/ViqqrO This prevents a potential regression if we tighten up the FMF behavior for fabs with NAN as suggested in issue #59279. --- diff --git a/llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp b/llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp index 6f1b0b9..9c6624f 100644 --- a/llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp @@ -2408,14 +2408,18 @@ Instruction *InstCombinerImpl::visitFNeg(UnaryOperator &I) { Value *Cond; if (match(Op, m_OneUse(m_Select(m_Value(Cond), m_Value(X), m_Value(Y))))) { // 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.) + // it is present on the original select. We union the flags from the select + // and fneg and then remove nsz if needed. auto propagateSelectFMF = [&](SelectInst *S, bool CommonOperand) { S->copyFastMathFlags(&I); - if (auto *OldSel = dyn_cast(Op)) + if (auto *OldSel = dyn_cast(Op)) { + FastMathFlags FMF = I.getFastMathFlags(); + FMF |= OldSel->getFastMathFlags(); + S->setFastMathFlags(FMF); if (!OldSel->hasNoSignedZeros() && !CommonOperand && !isGuaranteedNotToBeUndefOrPoison(OldSel->getCondition())) S->setHasNoSignedZeros(false); + } }; // -(Cond ? -P : Y) --> Cond ? P : -Y Value *P; diff --git a/llvm/test/Transforms/InstCombine/fneg.ll b/llvm/test/Transforms/InstCombine/fneg.ll index 41b2146..2c47b33 100644 --- a/llvm/test/Transforms/InstCombine/fneg.ll +++ b/llvm/test/Transforms/InstCombine/fneg.ll @@ -629,7 +629,7 @@ define float @select_fneg_true(float %x, float %y, i1 %b) { define <2 x float> @select_fneg_false(<2 x float> %x, <2 x float> %y, <2 x i1> %b) { ; CHECK-LABEL: @select_fneg_false( ; CHECK-NEXT: [[X_NEG:%.*]] = fneg nnan nsz <2 x float> [[X:%.*]] -; CHECK-NEXT: [[R:%.*]] = select nnan <2 x i1> [[B:%.*]], <2 x float> [[X_NEG]], <2 x float> [[Y:%.*]] +; CHECK-NEXT: [[R:%.*]] = select nnan ninf <2 x i1> [[B:%.*]], <2 x float> [[X_NEG]], <2 x float> [[Y:%.*]] ; CHECK-NEXT: ret <2 x float> [[R]] ; %ny = fneg nnan <2 x float> %y @@ -772,7 +772,7 @@ define float @select_fneg_use1(float %x, float %y, i1 %b) { ; CHECK-NEXT: [[NX:%.*]] = fneg ninf float [[X:%.*]] ; CHECK-NEXT: call void @use(float [[NX]]) ; CHECK-NEXT: [[Y_NEG:%.*]] = fneg float [[Y:%.*]] -; CHECK-NEXT: [[R:%.*]] = select i1 [[B:%.*]], float [[X]], float [[Y_NEG]] +; CHECK-NEXT: [[R:%.*]] = select fast i1 [[B:%.*]], float [[X]], float [[Y_NEG]] ; CHECK-NEXT: ret float [[R]] ; %nx = fneg ninf float %x