diff --git a/llvm/lib/Analysis/ValueTracking.cpp b/llvm/lib/Analysis/ValueTracking.cpp index 5d6c3465a0c36..412115eb649c2 100644 --- a/llvm/lib/Analysis/ValueTracking.cpp +++ b/llvm/lib/Analysis/ValueTracking.cpp @@ -5083,8 +5083,13 @@ void computeKnownFPClass(const Value *V, const APInt &DemandedElts, 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 (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()) diff --git a/llvm/test/Transforms/Attributor/nofpclass-fpext.ll b/llvm/test/Transforms/Attributor/nofpclass-fpext.ll index 0ba114117ceec..ee36f949529d4 100644 --- a/llvm/test/Transforms/Attributor/nofpclass-fpext.ll +++ b/llvm/test/Transforms/Attributor/nofpclass-fpext.ll @@ -142,7 +142,7 @@ define double @ret_fpext_f32_to_f64_nosub(float nofpclass(sub) %arg0) { } define double @ret_fpext_f32_to_f64_nonorm(float nofpclass(norm) %arg0) { -; CHECK-LABEL: define nofpclass(sub norm) double @ret_fpext_f32_to_f64_nonorm +; CHECK-LABEL: define nofpclass(sub) double @ret_fpext_f32_to_f64_nonorm ; CHECK-SAME: (float nofpclass(sub norm) [[ARG0:%.*]]) #[[ATTR0]] { ; CHECK-NEXT: [[EXT:%.*]] = fpext float [[ARG0]] to double ; CHECK-NEXT: ret double [[EXT]] @@ -482,7 +482,37 @@ define double @ret_fpext_bf16_f64_nosub(bfloat nofpclass(sub) %arg0) { } define double @ret_fpext_bf16_f64_nonorm(bfloat nofpclass(norm) %arg0) { -; CHECK-LABEL: define nofpclass(sub norm) double @ret_fpext_bf16_f64_nonorm +; CHECK-LABEL: define nofpclass(sub) double @ret_fpext_bf16_f64_nonorm +; CHECK-SAME: (bfloat nofpclass(sub norm) [[ARG0:%.*]]) #[[ATTR0]] { +; CHECK-NEXT: [[EXT:%.*]] = fpext bfloat [[ARG0]] to double +; CHECK-NEXT: ret double [[EXT]] +; + %ext = fpext bfloat %arg0 to double + ret double %ext +} + +define double @ret_fpext_bf16_f64_nonorm_psub(bfloat nofpclass(norm psub) %arg0) { +; CHECK-LABEL: define nofpclass(sub pnorm) double @ret_fpext_bf16_f64_nonorm_psub +; CHECK-SAME: (bfloat nofpclass(sub norm) [[ARG0:%.*]]) #[[ATTR0]] { +; CHECK-NEXT: [[EXT:%.*]] = fpext bfloat [[ARG0]] to double +; CHECK-NEXT: ret double [[EXT]] +; + %ext = fpext bfloat %arg0 to double + ret double %ext +} + +define double @ret_fpext_bf16_f64_nonorm_nsub(bfloat nofpclass(norm nsub) %arg0) { +; CHECK-LABEL: define nofpclass(sub nnorm) double @ret_fpext_bf16_f64_nonorm_nsub +; CHECK-SAME: (bfloat nofpclass(sub norm) [[ARG0:%.*]]) #[[ATTR0]] { +; CHECK-NEXT: [[EXT:%.*]] = fpext bfloat [[ARG0]] to double +; CHECK-NEXT: ret double [[EXT]] +; + %ext = fpext bfloat %arg0 to double + ret double %ext +} + +define double @ret_fpext_bf16_f64_nonorm_sub(bfloat nofpclass(norm sub) %arg0) { +; CHECK-LABEL: define nofpclass(sub norm) double @ret_fpext_bf16_f64_nonorm_sub ; CHECK-SAME: (bfloat nofpclass(sub norm) [[ARG0:%.*]]) #[[ATTR0]] { ; CHECK-NEXT: [[EXT:%.*]] = fpext bfloat [[ARG0]] to double ; CHECK-NEXT: ret double [[EXT]] diff --git a/llvm/test/Transforms/InstCombine/pr80941.ll b/llvm/test/Transforms/InstCombine/pr80941.ll new file mode 100644 index 0000000000000..95242b1d1407b --- /dev/null +++ b/llvm/test/Transforms/InstCombine/pr80941.ll @@ -0,0 +1,32 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 4 +; RUN: opt -S -passes=instcombine < %s | FileCheck %s + +define float @pr80941(float %arg) { +; CHECK-LABEL: define float @pr80941( +; CHECK-SAME: float [[ARG:%.*]]) { +; CHECK-NEXT: entry: +; CHECK-NEXT: [[COND:%.*]] = tail call i1 @llvm.is.fpclass.f32(float [[ARG]], i32 144) +; CHECK-NEXT: br i1 [[COND]], label [[IF_THEN:%.*]], label [[IF_EXIT:%.*]] +; CHECK: if.then: +; CHECK-NEXT: [[FPEXT:%.*]] = fpext float [[ARG]] to double +; CHECK-NEXT: [[SIGN:%.*]] = call double @llvm.copysign.f64(double 0.000000e+00, double [[FPEXT]]) +; CHECK-NEXT: [[FPTRUNC:%.*]] = fptrunc double [[SIGN]] to float +; CHECK-NEXT: br label [[IF_EXIT]] +; CHECK: if.exit: +; CHECK-NEXT: [[RET:%.*]] = phi float [ [[FPTRUNC]], [[IF_THEN]] ], [ [[ARG]], [[ENTRY:%.*]] ] +; CHECK-NEXT: ret float [[RET]] +; +entry: + %cond = tail call i1 @llvm.is.fpclass.f32(float %arg, i32 144) + br i1 %cond, label %if.then, label %if.exit + +if.then: + %fpext = fpext float %arg to double + %sign = call double @llvm.copysign.f64(double 0.000000e+00, double %fpext) + %fptrunc = fptrunc double %sign to float + br label %if.exit + +if.exit: + %ret = phi float [ %fptrunc, %if.then ], [ %arg, %entry ] + ret float %ret +}