Skip to content

Commit 2dc91ad

Browse files
committed
[ValueTracking] use KnownBits to compute fpclass from bitcast
1 parent 1193f7d commit 2dc91ad

File tree

2 files changed

+134
-0
lines changed

2 files changed

+134
-0
lines changed

llvm/lib/Analysis/ValueTracking.cpp

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5921,6 +5921,36 @@ void computeKnownFPClass(const Value *V, const APInt &DemandedElts,
59215921

59225922
break;
59235923
}
5924+
case Instruction::BitCast: {
5925+
const Type *Ty = Op->getType();
5926+
const Value *Casted = Op->getOperand(0);
5927+
if (Ty->isVectorTy() || !Casted->getType()->isIntOrIntVectorTy())
5928+
break;
5929+
5930+
KnownBits Bits(Ty->getScalarSizeInBits());
5931+
computeKnownBits(Casted, Bits, Depth + 1, Q);
5932+
5933+
// Transfer information from the sign bit.
5934+
if (Bits.Zero.isSignBitSet())
5935+
Known.signBitMustBeZero();
5936+
else if (Bits.One.isSignBitSet())
5937+
Known.signBitMustBeOne();
5938+
5939+
if (Ty->isIEEE()) {
5940+
// IEEE floats are NaN when all bits of the exponent plus at least one of
5941+
// the fraction bits are 1. This means:
5942+
// - If we assume unknown bits are 0 and the value is NaN, it will
5943+
// always be NaN
5944+
// - If we assume unknown bits are 1 and the value is not NaN, it can
5945+
// never be NaN
5946+
if (APFloat(Ty->getFltSemantics(), Bits.One).isNaN())
5947+
Known.KnownFPClasses = fcNan;
5948+
else if (!APFloat(Ty->getFltSemantics(), ~Bits.Zero).isNaN())
5949+
Known.knownNot(fcNan);
5950+
}
5951+
5952+
break;
5953+
}
59245954
default:
59255955
break;
59265956
}

llvm/test/Transforms/Attributor/nofpclass.ll

Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2690,6 +2690,110 @@ entry:
26902690
ret double %abs
26912691
}
26922692

2693+
define float @bitcast_to_float_sign_0(i32 %arg) {
2694+
; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
2695+
; CHECK-LABEL: define nofpclass(ninf nzero nsub nnorm) float @bitcast_to_float_sign_0
2696+
; CHECK-SAME: (i32 [[ARG:%.*]]) #[[ATTR3]] {
2697+
; CHECK-NEXT: [[TMP1:%.*]] = lshr i32 [[ARG]], 1
2698+
; CHECK-NEXT: [[TMP2:%.*]] = bitcast i32 [[TMP1]] to float
2699+
; CHECK-NEXT: ret float [[TMP2]]
2700+
;
2701+
%1 = lshr i32 %arg, 1
2702+
%2 = bitcast i32 %1 to float
2703+
ret float %2
2704+
}
2705+
2706+
define float @bitcast_to_float_nnan(i32 %arg) {
2707+
; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
2708+
; CHECK-LABEL: define nofpclass(nan ninf nzero nsub nnorm) float @bitcast_to_float_nnan
2709+
; CHECK-SAME: (i32 [[ARG:%.*]]) #[[ATTR3]] {
2710+
; CHECK-NEXT: [[TMP1:%.*]] = lshr i32 [[ARG]], 2
2711+
; CHECK-NEXT: [[TMP2:%.*]] = bitcast i32 [[TMP1]] to float
2712+
; CHECK-NEXT: ret float [[TMP2]]
2713+
;
2714+
%1 = lshr i32 %arg, 2
2715+
%2 = bitcast i32 %1 to float
2716+
ret float %2
2717+
}
2718+
2719+
define float @bitcast_to_float_sign_1(i32 %arg) {
2720+
; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
2721+
; CHECK-LABEL: define nofpclass(pinf pzero psub pnorm) float @bitcast_to_float_sign_1
2722+
; CHECK-SAME: (i32 [[ARG:%.*]]) #[[ATTR3]] {
2723+
; CHECK-NEXT: [[TMP1:%.*]] = or i32 [[ARG]], -2147483648
2724+
; CHECK-NEXT: [[TMP2:%.*]] = bitcast i32 [[TMP1]] to float
2725+
; CHECK-NEXT: ret float [[TMP2]]
2726+
;
2727+
%1 = or i32 %arg, -2147483648
2728+
%2 = bitcast i32 %1 to float
2729+
ret float %2
2730+
}
2731+
2732+
define float @bitcast_to_float_nan(i32 %arg) {
2733+
; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
2734+
; CHECK-LABEL: define nofpclass(inf zero sub norm) float @bitcast_to_float_nan
2735+
; CHECK-SAME: (i32 [[ARG:%.*]]) #[[ATTR3]] {
2736+
; CHECK-NEXT: [[TMP1:%.*]] = or i32 [[ARG]], 2139095041
2737+
; CHECK-NEXT: [[TMP2:%.*]] = bitcast i32 [[TMP1]] to float
2738+
; CHECK-NEXT: ret float [[TMP2]]
2739+
;
2740+
%1 = or i32 %arg, 2139095041
2741+
%2 = bitcast i32 %1 to float
2742+
ret float %2
2743+
}
2744+
2745+
define double @bitcast_to_double_sign_0(i64 %arg) {
2746+
; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
2747+
; CHECK-LABEL: define nofpclass(ninf nzero nsub nnorm) double @bitcast_to_double_sign_0
2748+
; CHECK-SAME: (i64 [[ARG:%.*]]) #[[ATTR3]] {
2749+
; CHECK-NEXT: [[TMP1:%.*]] = lshr i64 [[ARG]], 1
2750+
; CHECK-NEXT: [[TMP2:%.*]] = bitcast i64 [[TMP1]] to double
2751+
; CHECK-NEXT: ret double [[TMP2]]
2752+
;
2753+
%1 = lshr i64 %arg, 1
2754+
%2 = bitcast i64 %1 to double
2755+
ret double %2
2756+
}
2757+
2758+
define double @bitcast_to_double_nnan(i64 %arg) {
2759+
; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
2760+
; CHECK-LABEL: define nofpclass(nan ninf nzero nsub nnorm) double @bitcast_to_double_nnan
2761+
; CHECK-SAME: (i64 [[ARG:%.*]]) #[[ATTR3]] {
2762+
; CHECK-NEXT: [[TMP1:%.*]] = lshr i64 [[ARG]], 2
2763+
; CHECK-NEXT: [[TMP2:%.*]] = bitcast i64 [[TMP1]] to double
2764+
; CHECK-NEXT: ret double [[TMP2]]
2765+
;
2766+
%1 = lshr i64 %arg, 2
2767+
%2 = bitcast i64 %1 to double
2768+
ret double %2
2769+
}
2770+
2771+
define double @bitcast_to_double_sign_1(i64 %arg) {
2772+
; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
2773+
; CHECK-LABEL: define nofpclass(pinf pzero psub pnorm) double @bitcast_to_double_sign_1
2774+
; CHECK-SAME: (i64 [[ARG:%.*]]) #[[ATTR3]] {
2775+
; CHECK-NEXT: [[TMP1:%.*]] = or i64 [[ARG]], -9223372036854775808
2776+
; CHECK-NEXT: [[TMP2:%.*]] = bitcast i64 [[TMP1]] to double
2777+
; CHECK-NEXT: ret double [[TMP2]]
2778+
;
2779+
%1 = or i64 %arg, -9223372036854775808
2780+
%2 = bitcast i64 %1 to double
2781+
ret double %2
2782+
}
2783+
2784+
define double @bitcast_to_double_nan(i64 %arg) {
2785+
; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
2786+
; CHECK-LABEL: define nofpclass(inf zero sub norm) double @bitcast_to_double_nan
2787+
; CHECK-SAME: (i64 [[ARG:%.*]]) #[[ATTR3]] {
2788+
; CHECK-NEXT: [[TMP1:%.*]] = or i64 [[ARG]], -4503599627370495
2789+
; CHECK-NEXT: [[TMP2:%.*]] = bitcast i64 [[TMP1]] to double
2790+
; CHECK-NEXT: ret double [[TMP2]]
2791+
;
2792+
%1 = or i64 %arg, -4503599627370495
2793+
%2 = bitcast i64 %1 to double
2794+
ret double %2
2795+
}
2796+
26932797
declare i64 @_Z13get_global_idj(i32 noundef)
26942798

26952799
attributes #0 = { "denormal-fp-math"="preserve-sign,preserve-sign" }

0 commit comments

Comments
 (0)