llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT--> @llvm/pr-subscribers-llvm-support Author: Matt Arsenault (arsenm) <details> <summary>Changes</summary> --- Full diff: https://github.com/llvm/llvm-project/pull/174849.diff 5 Files Affected: - (modified) llvm/include/llvm/Support/KnownFPClass.h (+6) - (modified) llvm/lib/Analysis/ValueTracking.cpp (+3-14) - (modified) llvm/lib/Support/KnownFPClass.cpp (+22) - (modified) llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp (+22) - (modified) llvm/test/Transforms/InstCombine/simplify-demanded-fpclass-fpext.ll (+9-18) ``````````diff diff --git a/llvm/include/llvm/Support/KnownFPClass.h b/llvm/include/llvm/Support/KnownFPClass.h index a3a485a961877..4d2f42202301a 100644 --- a/llvm/include/llvm/Support/KnownFPClass.h +++ b/llvm/include/llvm/Support/KnownFPClass.h @@ -20,6 +20,7 @@ namespace llvm { class APFloat; +struct fltSemantics; struct KnownFPClass { /// Floating-point classes the value could be one of. @@ -283,6 +284,11 @@ struct KnownFPClass { static LLVM_ABI KnownFPClass log(const KnownFPClass &Src, DenormalMode Mode = DenormalMode::getDynamic()); + /// Propagate known class for fpext. + static LLVM_ABI KnownFPClass fpext(const KnownFPClass &KnownSrc, + const fltSemantics &DstTy, + const fltSemantics &SrcTy); + void resetAll() { *this = KnownFPClass(); } }; diff --git a/llvm/lib/Analysis/ValueTracking.cpp b/llvm/lib/Analysis/ValueTracking.cpp index dbe74f463b57c..44b8713ede471 100644 --- a/llvm/lib/Analysis/ValueTracking.cpp +++ b/llvm/lib/Analysis/ValueTracking.cpp @@ -5750,27 +5750,16 @@ void computeKnownFPClass(const Value *V, const APInt &DemandedElts, break; } case Instruction::FPExt: { - // Infinity, nan and zero propagate from source. + KnownFPClass KnownSrc; computeKnownFPClass(Op->getOperand(0), DemandedElts, InterestedClasses, - Known, Q, Depth + 1); + KnownSrc, Q, Depth + 1); const fltSemantics &DstTy = Op->getType()->getScalarType()->getFltSemantics(); const fltSemantics &SrcTy = Op->getOperand(0)->getType()->getScalarType()->getFltSemantics(); - // All subnormal inputs should be in the normal range in the result type. - if (APFloat::isRepresentableAsNormalIn(SrcTy, DstTy)) { - if (Known.KnownFPClasses & fcPosSubnormal) - Known.KnownFPClasses |= fcPosNormal; - if (Known.KnownFPClasses & fcNegSubnormal) - Known.KnownFPClasses |= fcNegNormal; - Known.knownNot(fcSubnormal); - } - - // Sign bit of a nan isn't guaranteed. - if (!Known.isKnownNeverNaN()) - Known.SignBit = std::nullopt; + Known = KnownFPClass::fpext(KnownSrc, DstTy, SrcTy); break; } case Instruction::FPTrunc: { diff --git a/llvm/lib/Support/KnownFPClass.cpp b/llvm/lib/Support/KnownFPClass.cpp index a352f1267be27..7a60221f7e8f8 100644 --- a/llvm/lib/Support/KnownFPClass.cpp +++ b/llvm/lib/Support/KnownFPClass.cpp @@ -329,3 +329,25 @@ KnownFPClass KnownFPClass::log(const KnownFPClass &KnownSrc, return Known; } + +KnownFPClass KnownFPClass::fpext(const KnownFPClass &KnownSrc, + const fltSemantics &DstTy, + const fltSemantics &SrcTy) { + // Infinity, nan and zero propagate from source. + KnownFPClass Known = KnownSrc; + + // All subnormal inputs should be in the normal range in the result type. + if (APFloat::isRepresentableAsNormalIn(SrcTy, DstTy)) { + if (Known.KnownFPClasses & fcPosSubnormal) + Known.KnownFPClasses |= fcPosNormal; + if (Known.KnownFPClasses & fcNegSubnormal) + Known.KnownFPClasses |= fcNegNormal; + Known.knownNot(fcSubnormal); + } + + // Sign bit of a nan isn't guaranteed. + if (!Known.isKnownNeverNaN()) + Known.SignBit = std::nullopt; + + return Known; +} diff --git a/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp b/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp index c628f53f28cbb..1a575ae7b4bfd 100644 --- a/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp @@ -2241,6 +2241,28 @@ Value *InstCombinerImpl::SimplifyDemandedUseFPClass(Value *V, FPClassTest ValidResults = DemandedMask & Known.KnownFPClasses; return getFPClassConstant(VTy, ValidResults, /*IsCanonicalizing=*/true); } + case Instruction::FPExt: { + FPClassTest SrcDemandedMask = DemandedMask; + + // No subnormal result does not imply not-subnormal in the source type. + if ((DemandedMask & fcNegSubnormal) == fcNone) + SrcDemandedMask |= fcNegSubnormal; + if ((DemandedMask & fcPosSubnormal) == fcNone) + SrcDemandedMask |= fcPosSubnormal; + + KnownFPClass KnownSrc; + if (SimplifyDemandedFPClass(I, 0, SrcDemandedMask, KnownSrc, Depth + 1)) + return I; + + const fltSemantics &DstTy = VTy->getScalarType()->getFltSemantics(); + const fltSemantics &SrcTy = + I->getOperand(0)->getType()->getScalarType()->getFltSemantics(); + + Known = KnownFPClass::fpext(KnownSrc, DstTy, SrcTy); + FPClassTest ValidResults = DemandedMask & Known.KnownFPClasses; + + return getFPClassConstant(VTy, ValidResults, /*IsCanonicalizing=*/true); + } case Instruction::Call: { CallInst *CI = cast<CallInst>(I); const Intrinsic::ID IID = CI->getIntrinsicID(); diff --git a/llvm/test/Transforms/InstCombine/simplify-demanded-fpclass-fpext.ll b/llvm/test/Transforms/InstCombine/simplify-demanded-fpclass-fpext.ll index 4996a206a7e8f..a1f4b1e9428ac 100644 --- a/llvm/test/Transforms/InstCombine/simplify-demanded-fpclass-fpext.ll +++ b/llvm/test/Transforms/InstCombine/simplify-demanded-fpclass-fpext.ll @@ -46,8 +46,7 @@ define nofpclass(inf norm sub zero snan) float @ret_only_qnan__fpext(half %x) { define nofpclass(inf norm sub zero) float @ret_only_nan__fpext(half %x) { ; CHECK-LABEL: define nofpclass(inf zero sub norm) float @ret_only_nan__fpext( ; CHECK-SAME: half [[X:%.*]]) { -; CHECK-NEXT: [[RESULT:%.*]] = fpext half [[X]] to float -; CHECK-NEXT: ret float [[RESULT]] +; CHECK-NEXT: ret float 0x7FF8000000000000 ; %result = fpext half %x to float ret float %result @@ -114,8 +113,7 @@ define nofpclass(nan) float @ret_no_nan__fpext__select_nan_or_unknown(i1 %cond, ; CHECK-LABEL: define nofpclass(nan) float @ret_no_nan__fpext__select_nan_or_unknown( ; CHECK-SAME: i1 [[COND:%.*]], half [[UNKNOWN:%.*]]) { ; CHECK-NEXT: [[NAN:%.*]] = call half @returns_nan_f16() -; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[COND]], half [[NAN]], half [[UNKNOWN]] -; CHECK-NEXT: [[RESULT:%.*]] = fpext half [[SELECT]] to float +; CHECK-NEXT: [[RESULT:%.*]] = fpext half [[UNKNOWN]] to float ; CHECK-NEXT: ret float [[RESULT]] ; %nan = call half @returns_nan_f16() @@ -129,8 +127,7 @@ define nofpclass(pinf) float @ret_no_pinf__fpext__select_pinf_or_unknown(i1 %con ; CHECK-LABEL: define nofpclass(pinf) float @ret_no_pinf__fpext__select_pinf_or_unknown( ; CHECK-SAME: i1 [[COND:%.*]], half [[UNKNOWN:%.*]]) { ; CHECK-NEXT: [[PINF:%.*]] = call half @returns_pinf_f16() -; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[COND]], half [[PINF]], half [[UNKNOWN]] -; CHECK-NEXT: [[RESULT:%.*]] = fpext half [[SELECT]] to float +; CHECK-NEXT: [[RESULT:%.*]] = fpext half [[UNKNOWN]] to float ; CHECK-NEXT: ret float [[RESULT]] ; %pinf = call half @returns_pinf_f16() @@ -144,8 +141,7 @@ define nofpclass(ninf) float @ret_no_ninf__fpext__select_ninf_or_unknown(i1 %con ; CHECK-LABEL: define nofpclass(ninf) float @ret_no_ninf__fpext__select_ninf_or_unknown( ; CHECK-SAME: i1 [[COND:%.*]], half [[UNKNOWN:%.*]]) { ; CHECK-NEXT: [[NINF:%.*]] = call half @returns_ninf_f16() -; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[COND]], half [[NINF]], half [[UNKNOWN]] -; CHECK-NEXT: [[RESULT:%.*]] = fpext half [[SELECT]] to float +; CHECK-NEXT: [[RESULT:%.*]] = fpext half [[UNKNOWN]] to float ; CHECK-NEXT: ret float [[RESULT]] ; %ninf = call half @returns_ninf_f16() @@ -159,8 +155,7 @@ define nofpclass(inf) float @ret_no_inf__fpext__select_inf_or_unknown(i1 %cond, ; CHECK-LABEL: define nofpclass(inf) float @ret_no_inf__fpext__select_inf_or_unknown( ; CHECK-SAME: i1 [[COND:%.*]], half [[UNKNOWN:%.*]]) { ; CHECK-NEXT: [[INF:%.*]] = call half @returns_inf_f16() -; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[COND]], half [[INF]], half [[UNKNOWN]] -; CHECK-NEXT: [[RESULT:%.*]] = fpext half [[SELECT]] to float +; CHECK-NEXT: [[RESULT:%.*]] = fpext half [[UNKNOWN]] to float ; CHECK-NEXT: ret float [[RESULT]] ; %inf = call half @returns_inf_f16() @@ -174,8 +169,7 @@ define nofpclass(nan inf) float @ret_no_inf_no_nan__fpext__select_inf_or_nan_or_ ; CHECK-LABEL: define nofpclass(nan inf) float @ret_no_inf_no_nan__fpext__select_inf_or_nan_or_unknown( ; CHECK-SAME: i1 [[COND:%.*]], half [[UNKNOWN:%.*]]) { ; CHECK-NEXT: [[INF_OR_NAN:%.*]] = call half @returns_inf_or_nan_f16() -; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[COND]], half [[INF_OR_NAN]], half [[UNKNOWN]] -; CHECK-NEXT: [[RESULT:%.*]] = fpext half [[SELECT]] to float +; CHECK-NEXT: [[RESULT:%.*]] = fpext half [[UNKNOWN]] to float ; CHECK-NEXT: ret float [[RESULT]] ; %inf.or.nan = call half @returns_inf_or_nan_f16() @@ -447,8 +441,7 @@ define nofpclass(nzero) float @ret_no_nzero__fpext__select_nzero_or_unknown(i1 % ; CHECK-LABEL: define nofpclass(nzero) float @ret_no_nzero__fpext__select_nzero_or_unknown( ; CHECK-SAME: i1 [[COND:%.*]], half [[UNKNOWN:%.*]]) { ; CHECK-NEXT: [[NZERO:%.*]] = call half @returns_nzero_f16() -; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[COND]], half [[NZERO]], half [[UNKNOWN]] -; CHECK-NEXT: [[RESULT:%.*]] = fpext half [[SELECT]] to float +; CHECK-NEXT: [[RESULT:%.*]] = fpext half [[UNKNOWN]] to float ; CHECK-NEXT: ret float [[RESULT]] ; %nzero = call half @returns_nzero_f16() @@ -461,8 +454,7 @@ define nofpclass(pzero) float @ret_no_pzero__fpext__select_pzero_or_unknown(i1 % ; CHECK-LABEL: define nofpclass(pzero) float @ret_no_pzero__fpext__select_pzero_or_unknown( ; CHECK-SAME: i1 [[COND:%.*]], half [[UNKNOWN:%.*]]) { ; CHECK-NEXT: [[PZERO:%.*]] = call half @returns_pzero_f16() -; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[COND]], half [[PZERO]], half [[UNKNOWN]] -; CHECK-NEXT: [[RESULT:%.*]] = fpext half [[SELECT]] to float +; CHECK-NEXT: [[RESULT:%.*]] = fpext half [[UNKNOWN]] to float ; CHECK-NEXT: ret float [[RESULT]] ; %pzero = call half @returns_pzero_f16() @@ -475,8 +467,7 @@ define nofpclass(zero) float @ret_no_zero__fpext__select_zero_or_unknown(i1 %con ; CHECK-LABEL: define nofpclass(zero) float @ret_no_zero__fpext__select_zero_or_unknown( ; CHECK-SAME: i1 [[COND:%.*]], half [[UNKNOWN:%.*]]) { ; CHECK-NEXT: [[ZERO:%.*]] = call half @returns_zero_f16() -; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[COND]], half [[ZERO]], half [[UNKNOWN]] -; CHECK-NEXT: [[RESULT:%.*]] = fpext half [[SELECT]] to float +; CHECK-NEXT: [[RESULT:%.*]] = fpext half [[UNKNOWN]] to float ; CHECK-NEXT: ret float [[RESULT]] ; %zero = call half @returns_zero_f16() `````````` </details> https://github.com/llvm/llvm-project/pull/174849 _______________________________________________ llvm-branch-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
