Skip to content

Commit a5865c3

Browse files
authored
[ValueTracking] Fix computeKnownFPClass for fpext (llvm#81972)
This patch adds the missing `subnormal -> normal` part for `fpext` in `computeKnownFPClass`. Fixes the miscompilation reported by llvm#80941 (comment).
1 parent 8cd5e67 commit a5865c3

File tree

3 files changed

+70
-3
lines changed

3 files changed

+70
-3
lines changed

Diff for: llvm/lib/Analysis/ValueTracking.cpp

+6-1
Original file line numberDiff line numberDiff line change
@@ -5173,8 +5173,13 @@ void computeKnownFPClass(const Value *V, const APInt &DemandedElts,
51735173
Op->getOperand(0)->getType()->getScalarType()->getFltSemantics();
51745174

51755175
// All subnormal inputs should be in the normal range in the result type.
5176-
if (APFloat::isRepresentableAsNormalIn(SrcTy, DstTy))
5176+
if (APFloat::isRepresentableAsNormalIn(SrcTy, DstTy)) {
5177+
if (Known.KnownFPClasses & fcPosSubnormal)
5178+
Known.KnownFPClasses |= fcPosNormal;
5179+
if (Known.KnownFPClasses & fcNegSubnormal)
5180+
Known.KnownFPClasses |= fcNegNormal;
51775181
Known.knownNot(fcSubnormal);
5182+
}
51785183

51795184
// Sign bit of a nan isn't guaranteed.
51805185
if (!Known.isKnownNeverNaN())

Diff for: llvm/test/Transforms/Attributor/nofpclass-fpext.ll

+32-2
Original file line numberDiff line numberDiff line change
@@ -142,7 +142,7 @@ define double @ret_fpext_f32_to_f64_nosub(float nofpclass(sub) %arg0) {
142142
}
143143

144144
define double @ret_fpext_f32_to_f64_nonorm(float nofpclass(norm) %arg0) {
145-
; CHECK-LABEL: define nofpclass(sub norm) double @ret_fpext_f32_to_f64_nonorm
145+
; CHECK-LABEL: define nofpclass(sub) double @ret_fpext_f32_to_f64_nonorm
146146
; CHECK-SAME: (float nofpclass(sub norm) [[ARG0:%.*]]) #[[ATTR0]] {
147147
; CHECK-NEXT: [[EXT:%.*]] = fpext float [[ARG0]] to double
148148
; CHECK-NEXT: ret double [[EXT]]
@@ -482,7 +482,37 @@ define double @ret_fpext_bf16_f64_nosub(bfloat nofpclass(sub) %arg0) {
482482
}
483483

484484
define double @ret_fpext_bf16_f64_nonorm(bfloat nofpclass(norm) %arg0) {
485-
; CHECK-LABEL: define nofpclass(sub norm) double @ret_fpext_bf16_f64_nonorm
485+
; CHECK-LABEL: define nofpclass(sub) double @ret_fpext_bf16_f64_nonorm
486+
; CHECK-SAME: (bfloat nofpclass(sub norm) [[ARG0:%.*]]) #[[ATTR0]] {
487+
; CHECK-NEXT: [[EXT:%.*]] = fpext bfloat [[ARG0]] to double
488+
; CHECK-NEXT: ret double [[EXT]]
489+
;
490+
%ext = fpext bfloat %arg0 to double
491+
ret double %ext
492+
}
493+
494+
define double @ret_fpext_bf16_f64_nonorm_psub(bfloat nofpclass(norm psub) %arg0) {
495+
; CHECK-LABEL: define nofpclass(sub pnorm) double @ret_fpext_bf16_f64_nonorm_psub
496+
; CHECK-SAME: (bfloat nofpclass(sub norm) [[ARG0:%.*]]) #[[ATTR0]] {
497+
; CHECK-NEXT: [[EXT:%.*]] = fpext bfloat [[ARG0]] to double
498+
; CHECK-NEXT: ret double [[EXT]]
499+
;
500+
%ext = fpext bfloat %arg0 to double
501+
ret double %ext
502+
}
503+
504+
define double @ret_fpext_bf16_f64_nonorm_nsub(bfloat nofpclass(norm nsub) %arg0) {
505+
; CHECK-LABEL: define nofpclass(sub nnorm) double @ret_fpext_bf16_f64_nonorm_nsub
506+
; CHECK-SAME: (bfloat nofpclass(sub norm) [[ARG0:%.*]]) #[[ATTR0]] {
507+
; CHECK-NEXT: [[EXT:%.*]] = fpext bfloat [[ARG0]] to double
508+
; CHECK-NEXT: ret double [[EXT]]
509+
;
510+
%ext = fpext bfloat %arg0 to double
511+
ret double %ext
512+
}
513+
514+
define double @ret_fpext_bf16_f64_nonorm_sub(bfloat nofpclass(norm sub) %arg0) {
515+
; CHECK-LABEL: define nofpclass(sub norm) double @ret_fpext_bf16_f64_nonorm_sub
486516
; CHECK-SAME: (bfloat nofpclass(sub norm) [[ARG0:%.*]]) #[[ATTR0]] {
487517
; CHECK-NEXT: [[EXT:%.*]] = fpext bfloat [[ARG0]] to double
488518
; CHECK-NEXT: ret double [[EXT]]

Diff for: llvm/test/Transforms/InstCombine/pr80941.ll

+32
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 4
2+
; RUN: opt -S -passes=instcombine < %s | FileCheck %s
3+
4+
define float @pr80941(float %arg) {
5+
; CHECK-LABEL: define float @pr80941(
6+
; CHECK-SAME: float [[ARG:%.*]]) {
7+
; CHECK-NEXT: entry:
8+
; CHECK-NEXT: [[COND:%.*]] = tail call i1 @llvm.is.fpclass.f32(float [[ARG]], i32 144)
9+
; CHECK-NEXT: br i1 [[COND]], label [[IF_THEN:%.*]], label [[IF_EXIT:%.*]]
10+
; CHECK: if.then:
11+
; CHECK-NEXT: [[FPEXT:%.*]] = fpext float [[ARG]] to double
12+
; CHECK-NEXT: [[SIGN:%.*]] = call double @llvm.copysign.f64(double 0.000000e+00, double [[FPEXT]])
13+
; CHECK-NEXT: [[FPTRUNC:%.*]] = fptrunc double [[SIGN]] to float
14+
; CHECK-NEXT: br label [[IF_EXIT]]
15+
; CHECK: if.exit:
16+
; CHECK-NEXT: [[RET:%.*]] = phi float [ [[FPTRUNC]], [[IF_THEN]] ], [ [[ARG]], [[ENTRY:%.*]] ]
17+
; CHECK-NEXT: ret float [[RET]]
18+
;
19+
entry:
20+
%cond = tail call i1 @llvm.is.fpclass.f32(float %arg, i32 144)
21+
br i1 %cond, label %if.then, label %if.exit
22+
23+
if.then:
24+
%fpext = fpext float %arg to double
25+
%sign = call double @llvm.copysign.f64(double 0.000000e+00, double %fpext)
26+
%fptrunc = fptrunc double %sign to float
27+
br label %if.exit
28+
29+
if.exit:
30+
%ret = phi float [ %fptrunc, %if.then ], [ %arg, %entry ]
31+
ret float %ret
32+
}

0 commit comments

Comments
 (0)