mirror of
https://github.com/llvm/llvm-project.git
synced 2025-05-01 20:56:05 +00:00
ConstantFolding: Constant fold denormal inputs to canonicalize for IEEE
This makes it possible to use canonicalize to perform a dynamic check for whether denormal flushing is enabled, which will fold out when the denormal mode is known. Previously it would only fold if denormal flushing were known enabled. https://reviews.llvm.org/D156107
This commit is contained in:
parent
68b7d3fffd
commit
a09d9b42f1
@ -1973,9 +1973,8 @@ static Constant *constantFoldCanonicalize(const Type *Ty, const CallBase *CI,
|
||||
DenormalMode DenormMode =
|
||||
CI->getFunction()->getDenormalMode(Src.getSemantics());
|
||||
|
||||
// TODO: Should allow folding for pure IEEE.
|
||||
if (DenormMode == DenormalMode::getIEEE())
|
||||
return nullptr;
|
||||
return ConstantFP::get(CI->getContext(), Src);
|
||||
|
||||
if (DenormMode.Input == DenormalMode::Dynamic)
|
||||
return nullptr;
|
||||
|
@ -75,8 +75,7 @@ define <2 x float> @canonicalize_poison_vector() {
|
||||
|
||||
define float @canonicalize_denorm() {
|
||||
; CHECK-LABEL: @canonicalize_denorm(
|
||||
; CHECK-NEXT: [[RET:%.*]] = call float @llvm.canonicalize.f32(float 0x380FFFFFC0000000)
|
||||
; CHECK-NEXT: ret float [[RET]]
|
||||
; CHECK-NEXT: ret float 0x380FFFFFC0000000
|
||||
;
|
||||
%ret = call float @llvm.canonicalize.f32(float bitcast (i32 8388607 to float))
|
||||
ret float %ret
|
||||
@ -370,8 +369,7 @@ define double @canonicalize_1.0_f64() {
|
||||
|
||||
define double @canonicalize_0x00000000000001_f64() {
|
||||
; CHECK-LABEL: @canonicalize_0x00000000000001_f64(
|
||||
; CHECK-NEXT: [[RET:%.*]] = call double @llvm.canonicalize.f64(double 4.940660e-324)
|
||||
; CHECK-NEXT: ret double [[RET]]
|
||||
; CHECK-NEXT: ret double 4.940660e-324
|
||||
;
|
||||
%ret = call double @llvm.canonicalize.f64(double 0x00000000000001)
|
||||
ret double %ret
|
||||
@ -415,8 +413,7 @@ define half @canonicalize_1.0_f16() {
|
||||
|
||||
define half @canonicalize_0x0001_f16() {
|
||||
; CHECK-LABEL: @canonicalize_0x0001_f16(
|
||||
; CHECK-NEXT: [[RET:%.*]] = call half @llvm.canonicalize.f16(half 0xH0001)
|
||||
; CHECK-NEXT: ret half [[RET]]
|
||||
; CHECK-NEXT: ret half 0xH0001
|
||||
;
|
||||
%ret = call half @llvm.canonicalize.f16(half 0xH0001)
|
||||
ret half %ret
|
||||
@ -460,8 +457,7 @@ define fp128 @canonicalize_1.0_fp128() {
|
||||
|
||||
define fp128 @canonicalize_0x00000000000000000000000000000001_fp128() {
|
||||
; CHECK-LABEL: @canonicalize_0x00000000000000000000000000000001_fp128(
|
||||
; CHECK-NEXT: [[RET:%.*]] = call fp128 @llvm.canonicalize.f128(fp128 0xL00000000000000000000000000000001)
|
||||
; CHECK-NEXT: ret fp128 [[RET]]
|
||||
; CHECK-NEXT: ret fp128 0xL00000000000000000000000000000001
|
||||
;
|
||||
%ret = call fp128 @llvm.canonicalize.fp128(fp128 0xL00000000000000000000000000000001)
|
||||
ret fp128 %ret
|
||||
@ -514,8 +510,7 @@ define bfloat @canonicalize_1.0_bf16() {
|
||||
|
||||
define bfloat @canonicalize_0x0001_bf16() {
|
||||
; CHECK-LABEL: @canonicalize_0x0001_bf16(
|
||||
; CHECK-NEXT: [[RET:%.*]] = call bfloat @llvm.canonicalize.bf16(bfloat 0xR0001)
|
||||
; CHECK-NEXT: ret bfloat [[RET]]
|
||||
; CHECK-NEXT: ret bfloat 0xR0001
|
||||
;
|
||||
%ret = call bfloat @llvm.canonicalize.bf16(bfloat 0xR0001)
|
||||
ret bfloat %ret
|
||||
@ -767,6 +762,243 @@ define ppc_fp128 @canonicalize_neg1.0_ppcf128() {
|
||||
ret ppc_fp128 %ret
|
||||
}
|
||||
|
||||
; --------------------------------------------------------------------
|
||||
; Test folds of using canonicalize + is.fpclass to inspect the denormal mode.
|
||||
; --------------------------------------------------------------------
|
||||
|
||||
define i1 @is_poszero_daz_enabled_check_dynamic() "denormal-fp-math"="ieee,dynamic" {
|
||||
; CHECK-LABEL: @is_poszero_daz_enabled_check_dynamic(
|
||||
; CHECK-NEXT: [[CANONICAL:%.*]] = call float @llvm.canonicalize.f32(float 0x36A0000000000000)
|
||||
; CHECK-NEXT: [[IS_POS_ZERO:%.*]] = call i1 @llvm.is.fpclass.f32(float [[CANONICAL]], i32 64)
|
||||
; CHECK-NEXT: ret i1 [[IS_POS_ZERO]]
|
||||
;
|
||||
%canonical = call float @llvm.canonicalize.f32(float bitcast (i32 1 to float))
|
||||
%is.pos.zero = call i1 @llvm.is.fpclass.f32(float %canonical, i32 64)
|
||||
ret i1 %is.pos.zero
|
||||
}
|
||||
|
||||
define i1 @is_preserve_sign_daz_enabled_check_dynamic() "denormal-fp-math"="ieee,dynamic" {
|
||||
; CHECK-LABEL: @is_preserve_sign_daz_enabled_check_dynamic(
|
||||
; CHECK-NEXT: [[CANONICAL:%.*]] = call float @llvm.canonicalize.f32(float 0xB6A0000000000000)
|
||||
; CHECK-NEXT: [[IS_NEG_ZERO:%.*]] = call i1 @llvm.is.fpclass.f32(float [[CANONICAL]], i32 32)
|
||||
; CHECK-NEXT: ret i1 [[IS_NEG_ZERO]]
|
||||
;
|
||||
%canonical = call float @llvm.canonicalize.f32(float bitcast (i32 -2147483647 to float))
|
||||
%is.neg.zero = call i1 @llvm.is.fpclass.f32(float %canonical, i32 32)
|
||||
ret i1 %is.neg.zero
|
||||
}
|
||||
|
||||
define i1 @is_positive_zero_daz_enabled_check_dynamic() "denormal-fp-math"="ieee,dynamic" {
|
||||
; CHECK-LABEL: @is_positive_zero_daz_enabled_check_dynamic(
|
||||
; CHECK-NEXT: [[CANONICAL:%.*]] = call float @llvm.canonicalize.f32(float 0xB6A0000000000000)
|
||||
; CHECK-NEXT: [[IS_POS_ZERO:%.*]] = call i1 @llvm.is.fpclass.f32(float [[CANONICAL]], i32 64)
|
||||
; CHECK-NEXT: ret i1 [[IS_POS_ZERO]]
|
||||
;
|
||||
%canonical = call float @llvm.canonicalize.f32(float bitcast (i32 -2147483647 to float))
|
||||
%is.pos.zero = call i1 @llvm.is.fpclass.f32(float %canonical, i32 64)
|
||||
ret i1 %is.pos.zero
|
||||
}
|
||||
|
||||
define i1 @is_any_daz_enabled_check_dynamic() "denormal-fp-math"="ieee,dynamic" {
|
||||
; CHECK-LABEL: @is_any_daz_enabled_check_dynamic(
|
||||
; CHECK-NEXT: [[CANONICAL:%.*]] = call float @llvm.canonicalize.f32(float 0xB6A0000000000000)
|
||||
; CHECK-NEXT: [[IS_ANY_ZERO:%.*]] = call i1 @llvm.is.fpclass.f32(float [[CANONICAL]], i32 96)
|
||||
; CHECK-NEXT: ret i1 [[IS_ANY_ZERO]]
|
||||
;
|
||||
%canonical = call float @llvm.canonicalize.f32(float bitcast (i32 -2147483647 to float))
|
||||
%is.any.zero = call i1 @llvm.is.fpclass.f32(float %canonical, i32 96)
|
||||
ret i1 %is.any.zero
|
||||
}
|
||||
|
||||
define i1 @is_not_daz_enabled_check_dynamic() "denormal-fp-math"="ieee,dynamic" {
|
||||
; CHECK-LABEL: @is_not_daz_enabled_check_dynamic(
|
||||
; CHECK-NEXT: [[CANONICAL:%.*]] = call float @llvm.canonicalize.f32(float 0x36A0000000000000)
|
||||
; CHECK-NEXT: [[IS_NOT_POS_ZERO:%.*]] = call i1 @llvm.is.fpclass.f32(float [[CANONICAL]], i32 959)
|
||||
; CHECK-NEXT: ret i1 [[IS_NOT_POS_ZERO]]
|
||||
;
|
||||
%canonical = call float @llvm.canonicalize.f32(float bitcast (i32 1 to float))
|
||||
%is.not.pos.zero = call i1 @llvm.is.fpclass.f32(float %canonical, i32 959)
|
||||
ret i1 %is.not.pos.zero
|
||||
}
|
||||
|
||||
define i1 @is_poszero_daz_enabled_check_ieee() "denormal-fp-math"="ieee,ieee" {
|
||||
; CHECK-LABEL: @is_poszero_daz_enabled_check_ieee(
|
||||
; CHECK-NEXT: ret i1 false
|
||||
;
|
||||
%canonical = call float @llvm.canonicalize.f32(float bitcast (i32 1 to float))
|
||||
%is.pos.zero = call i1 @llvm.is.fpclass.f32(float %canonical, i32 64)
|
||||
ret i1 %is.pos.zero
|
||||
}
|
||||
|
||||
define i1 @is_preserve_sign_daz_enabled_check_ieee() "denormal-fp-math"="ieee,ieee" {
|
||||
; CHECK-LABEL: @is_preserve_sign_daz_enabled_check_ieee(
|
||||
; CHECK-NEXT: ret i1 false
|
||||
;
|
||||
%canonical = call float @llvm.canonicalize.f32(float bitcast (i32 -2147483647 to float))
|
||||
%is.neg.zero = call i1 @llvm.is.fpclass.f32(float %canonical, i32 32)
|
||||
ret i1 %is.neg.zero
|
||||
}
|
||||
|
||||
define i1 @is_positive_zero_daz_enabled_check_ieee() "denormal-fp-math"="ieee,ieee" {
|
||||
; CHECK-LABEL: @is_positive_zero_daz_enabled_check_ieee(
|
||||
; CHECK-NEXT: ret i1 false
|
||||
;
|
||||
%canonical = call float @llvm.canonicalize.f32(float bitcast (i32 -2147483647 to float))
|
||||
%is.pos.zero = call i1 @llvm.is.fpclass.f32(float %canonical, i32 64)
|
||||
ret i1 %is.pos.zero
|
||||
}
|
||||
|
||||
define i1 @is_any_daz_enabled_check_ieee() "denormal-fp-math"="ieee,ieee" {
|
||||
; CHECK-LABEL: @is_any_daz_enabled_check_ieee(
|
||||
; CHECK-NEXT: ret i1 false
|
||||
;
|
||||
%canonical = call float @llvm.canonicalize.f32(float bitcast (i32 -2147483647 to float))
|
||||
%is.any.zero = call i1 @llvm.is.fpclass.f32(float %canonical, i32 96)
|
||||
ret i1 %is.any.zero
|
||||
}
|
||||
|
||||
define i1 @is_not_daz_enabled_check_ieee() "denormal-fp-math"="ieee,ieee" {
|
||||
; CHECK-LABEL: @is_not_daz_enabled_check_ieee(
|
||||
; CHECK-NEXT: ret i1 true
|
||||
;
|
||||
%canonical = call float @llvm.canonicalize.f32(float bitcast (i32 1 to float))
|
||||
%is.not.pos.zero = call i1 @llvm.is.fpclass.f32(float %canonical, i32 959)
|
||||
ret i1 %is.not.pos.zero
|
||||
}
|
||||
|
||||
define i1 @is_poszero_daz_enabled_check_preserve_sign() "denormal-fp-math"="ieee,preserve-sign" {
|
||||
; CHECK-LABEL: @is_poszero_daz_enabled_check_preserve_sign(
|
||||
; CHECK-NEXT: ret i1 true
|
||||
;
|
||||
%canonical = call float @llvm.canonicalize.f32(float bitcast (i32 1 to float))
|
||||
%is.pos.zero = call i1 @llvm.is.fpclass.f32(float %canonical, i32 64)
|
||||
ret i1 %is.pos.zero
|
||||
}
|
||||
|
||||
define i1 @is_preserve_sign_daz_enabled_check_preserve_sign() "denormal-fp-math"="ieee,preserve-sign" {
|
||||
; CHECK-LABEL: @is_preserve_sign_daz_enabled_check_preserve_sign(
|
||||
; CHECK-NEXT: ret i1 true
|
||||
;
|
||||
%canonical = call float @llvm.canonicalize.f32(float bitcast (i32 -2147483647 to float))
|
||||
%is.neg.zero = call i1 @llvm.is.fpclass.f32(float %canonical, i32 32)
|
||||
ret i1 %is.neg.zero
|
||||
}
|
||||
|
||||
define i1 @is_positive_zero_daz_enabled_check_preserve_sign() "denormal-fp-math"="ieee,preserve-sign" {
|
||||
; CHECK-LABEL: @is_positive_zero_daz_enabled_check_preserve_sign(
|
||||
; CHECK-NEXT: ret i1 false
|
||||
;
|
||||
%canonical = call float @llvm.canonicalize.f32(float bitcast (i32 -2147483647 to float))
|
||||
%is.pos.zero = call i1 @llvm.is.fpclass.f32(float %canonical, i32 64)
|
||||
ret i1 %is.pos.zero
|
||||
}
|
||||
|
||||
define i1 @is_any_daz_enabled_check_preserve_sign() "denormal-fp-math"="ieee,preserve-sign" {
|
||||
; CHECK-LABEL: @is_any_daz_enabled_check_preserve_sign(
|
||||
; CHECK-NEXT: ret i1 true
|
||||
;
|
||||
%canonical = call float @llvm.canonicalize.f32(float bitcast (i32 -2147483647 to float))
|
||||
%is.any.zero = call i1 @llvm.is.fpclass.f32(float %canonical, i32 96)
|
||||
ret i1 %is.any.zero
|
||||
}
|
||||
|
||||
define i1 @is_not_daz_enabled_check_preserve_sign() "denormal-fp-math"="ieee,preserve-sign" {
|
||||
; CHECK-LABEL: @is_not_daz_enabled_check_preserve_sign(
|
||||
; CHECK-NEXT: ret i1 false
|
||||
;
|
||||
%canonical = call float @llvm.canonicalize.f32(float bitcast (i32 1 to float))
|
||||
%is.not.pos.zero = call i1 @llvm.is.fpclass.f32(float %canonical, i32 959)
|
||||
ret i1 %is.not.pos.zero
|
||||
}
|
||||
|
||||
define i1 @is_poszero_daz_enabled_check_positive_zero() "denormal-fp-math"="ieee,positive-zero" {
|
||||
; CHECK-LABEL: @is_poszero_daz_enabled_check_positive_zero(
|
||||
; CHECK-NEXT: ret i1 true
|
||||
;
|
||||
%canonical = call float @llvm.canonicalize.f32(float bitcast (i32 1 to float))
|
||||
%is.pos.zero = call i1 @llvm.is.fpclass.f32(float %canonical, i32 64)
|
||||
ret i1 %is.pos.zero
|
||||
}
|
||||
|
||||
define i1 @is_preserve_sign_daz_enabled_check_positive_zero() "denormal-fp-math"="ieee,positive-zero" {
|
||||
; CHECK-LABEL: @is_preserve_sign_daz_enabled_check_positive_zero(
|
||||
; CHECK-NEXT: ret i1 false
|
||||
;
|
||||
%canonical = call float @llvm.canonicalize.f32(float bitcast (i32 -2147483647 to float))
|
||||
%is.neg.zero = call i1 @llvm.is.fpclass.f32(float %canonical, i32 32)
|
||||
ret i1 %is.neg.zero
|
||||
}
|
||||
|
||||
define i1 @is_positive_zero_daz_enabled_check_positive_zero() "denormal-fp-math"="ieee,positive-zero" {
|
||||
; CHECK-LABEL: @is_positive_zero_daz_enabled_check_positive_zero(
|
||||
; CHECK-NEXT: ret i1 true
|
||||
;
|
||||
%canonical = call float @llvm.canonicalize.f32(float bitcast (i32 -2147483647 to float))
|
||||
%is.pos.zero = call i1 @llvm.is.fpclass.f32(float %canonical, i32 64)
|
||||
ret i1 %is.pos.zero
|
||||
}
|
||||
|
||||
define i1 @is_any_daz_enabled_check_positive_zero() "denormal-fp-math"="ieee,positive-zero" {
|
||||
; CHECK-LABEL: @is_any_daz_enabled_check_positive_zero(
|
||||
; CHECK-NEXT: ret i1 true
|
||||
;
|
||||
%canonical = call float @llvm.canonicalize.f32(float bitcast (i32 -2147483647 to float))
|
||||
%is.any.zero = call i1 @llvm.is.fpclass.f32(float %canonical, i32 96)
|
||||
ret i1 %is.any.zero
|
||||
}
|
||||
|
||||
define i1 @is_not_daz_enabled_check_positive_zero() "denormal-fp-math"="ieee,positive-zero" {
|
||||
; CHECK-LABEL: @is_not_daz_enabled_check_positive_zero(
|
||||
; CHECK-NEXT: ret i1 false
|
||||
;
|
||||
%canonical = call float @llvm.canonicalize.f32(float bitcast (i32 1 to float))
|
||||
%is.not.pos.zero = call i1 @llvm.is.fpclass.f32(float %canonical, i32 959)
|
||||
ret i1 %is.not.pos.zero
|
||||
}
|
||||
|
||||
define i1 @is_poszero_daz_enabled_check_dynamic_bitcast() "denormal-fp-math"="ieee,dynamic" {
|
||||
; CHECK-LABEL: @is_poszero_daz_enabled_check_dynamic_bitcast(
|
||||
; CHECK-NEXT: [[CANONICAL:%.*]] = call float @llvm.canonicalize.f32(float 0x36A0000000000000)
|
||||
; CHECK-NEXT: [[BITCAST:%.*]] = bitcast float [[CANONICAL]] to i32
|
||||
; CHECK-NEXT: [[IS_POS_ZERO:%.*]] = icmp eq i32 [[BITCAST]], 0
|
||||
; CHECK-NEXT: ret i1 [[IS_POS_ZERO]]
|
||||
;
|
||||
%canonical = call float @llvm.canonicalize.f32(float bitcast (i32 1 to float))
|
||||
%bitcast = bitcast float %canonical to i32
|
||||
%is.pos.zero = icmp eq i32 %bitcast, 0
|
||||
ret i1 %is.pos.zero
|
||||
}
|
||||
|
||||
define i1 @is_poszero_daz_enabled_check_preserve_sign_bitcast() "denormal-fp-math"="ieee,preserve-sign" {
|
||||
; CHECK-LABEL: @is_poszero_daz_enabled_check_preserve_sign_bitcast(
|
||||
; CHECK-NEXT: ret i1 true
|
||||
;
|
||||
%canonical = call float @llvm.canonicalize.f32(float bitcast (i32 1 to float))
|
||||
%bitcast = bitcast float %canonical to i32
|
||||
%is.pos.zero = icmp eq i32 %bitcast, 0
|
||||
ret i1 %is.pos.zero
|
||||
}
|
||||
|
||||
define i1 @is_poszero_daz_enabled_check_positive_zero_bitcast() "denormal-fp-math"="ieee,positive-zero" {
|
||||
; CHECK-LABEL: @is_poszero_daz_enabled_check_positive_zero_bitcast(
|
||||
; CHECK-NEXT: ret i1 true
|
||||
;
|
||||
%canonical = call float @llvm.canonicalize.f32(float bitcast (i32 1 to float))
|
||||
%bitcast = bitcast float %canonical to i32
|
||||
%is.pos.zero = icmp eq i32 %bitcast, 0
|
||||
ret i1 %is.pos.zero
|
||||
}
|
||||
|
||||
define i1 @is_poszero_daz_enabled_check_ieee_bitcast() "denormal-fp-math"="ieee,ieee" {
|
||||
; CHECK-LABEL: @is_poszero_daz_enabled_check_ieee_bitcast(
|
||||
; CHECK-NEXT: ret i1 false
|
||||
;
|
||||
%canonical = call float @llvm.canonicalize.f32(float bitcast (i32 1 to float))
|
||||
%bitcast = bitcast float %canonical to i32
|
||||
%is.pos.zero = icmp eq i32 %bitcast, 0
|
||||
ret i1 %is.pos.zero
|
||||
}
|
||||
|
||||
declare bfloat @llvm.canonicalize.bf16(bfloat)
|
||||
declare half @llvm.canonicalize.f16(half)
|
||||
declare float @llvm.canonicalize.f32(float)
|
||||
@ -775,3 +1007,4 @@ declare double @llvm.canonicalize.f64(double)
|
||||
declare fp128 @llvm.canonicalize.fp128(fp128)
|
||||
declare x86_fp80 @llvm.canonicalize.f80(x86_fp80)
|
||||
declare ppc_fp128 @llvm.canonicalize.ppcf128(ppc_fp128)
|
||||
declare i1 @llvm.is.fpclass.f32(float, i32 immarg)
|
||||
|
Loading…
x
Reference in New Issue
Block a user