| ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6 |
| ; RUN: opt -S -passes=instcombine < %s | FileCheck %s |
| |
| declare float @func() |
| |
| declare nofpclass(ninf nnorm nsub nzero nan) float @returns_positive() |
| declare nofpclass(ninf nnorm nsub nzero) float @returns_positive_or_nan() |
| |
| declare nofpclass(pinf pnorm psub pzero nan) float @returns_negative() |
| declare nofpclass(pinf pnorm psub pzero) float @returns_negative_or_nan() |
| |
| declare nofpclass(pinf pnorm psub zero nan) float @returns_negative_nonzero() |
| declare nofpclass(pinf pnorm psub zero nan) <2 x float> @returns_negative_nonzero_vec() |
| declare nofpclass(pinf pnorm psub zero) float @returns_negative_nonzero_or_nan() |
| declare nofpclass(qnan inf norm sub zero) float @returns_snan() |
| |
| ; -> qnan |
| define nofpclass(inf norm sub zero) float @ret_only_nan_sqrt(float %x) { |
| ; CHECK-LABEL: define nofpclass(inf zero sub norm) float @ret_only_nan_sqrt( |
| ; CHECK-SAME: float [[X:%.*]]) { |
| ; CHECK-NEXT: ret float 0x7FF8000000000000 |
| ; |
| %result = call float @llvm.sqrt.f32(float %x) |
| ret float %result |
| } |
| |
| ; -> copysign(0, x) |
| ; https://alive2.llvm.org/ce/z/ab5wX8 |
| define nofpclass(inf nan norm sub) float @ret_only_zero_sqrt(float %x) { |
| ; CHECK-LABEL: define nofpclass(nan inf sub norm) float @ret_only_zero_sqrt( |
| ; CHECK-SAME: float [[X:%.*]]) { |
| ; CHECK-NEXT: [[RESULT:%.*]] = call float @llvm.copysign.f32(float 0.000000e+00, float [[X]]) |
| ; CHECK-NEXT: ret float [[RESULT]] |
| ; |
| %result = call float @llvm.sqrt.f32(float %x) |
| ret float %result |
| } |
| |
| define nofpclass(inf nan norm sub) float @ret_only_zero_sqrt_insert_point(float %x) { |
| ; CHECK-LABEL: define nofpclass(nan inf sub norm) float @ret_only_zero_sqrt_insert_point( |
| ; CHECK-SAME: float [[X:%.*]]) { |
| ; CHECK-NEXT: [[RESULT:%.*]] = call float @llvm.copysign.f32(float 0.000000e+00, float [[X]]) |
| ; CHECK-NEXT: [[BARRIER:%.*]] = call float @llvm.arithmetic.fence.f32(float [[RESULT]]) |
| ; CHECK-NEXT: ret float [[BARRIER]] |
| ; |
| %result = call float @llvm.sqrt.f32(float %x) |
| %barrier = call float @llvm.arithmetic.fence.f32(float %result) |
| ret float %barrier |
| } |
| |
| define nofpclass(inf nan norm sub) float @ret_only_zero_sqrt_preserve_flags(float %x) { |
| ; CHECK-LABEL: define nofpclass(nan inf sub norm) float @ret_only_zero_sqrt_preserve_flags( |
| ; CHECK-SAME: float [[X:%.*]]) { |
| ; CHECK-NEXT: [[RESULT:%.*]] = call ninf float @llvm.copysign.f32(float 0.000000e+00, float [[X]]) |
| ; CHECK-NEXT: ret float [[RESULT]] |
| ; |
| %result = call ninf float @llvm.sqrt.f32(float %x) |
| ret float %result |
| } |
| |
| define nofpclass(inf nan norm sub) float @ret_only_zero_sqrt_nsz(float %x) { |
| ; CHECK-LABEL: define nofpclass(nan inf sub norm) float @ret_only_zero_sqrt_nsz( |
| ; CHECK-SAME: float [[X:%.*]]) { |
| ; CHECK-NEXT: ret float 0.000000e+00 |
| ; |
| %result = call nsz float @llvm.sqrt.f32(float %x) |
| ret float %result |
| } |
| |
| define nofpclass(inf nan norm sub) <2 x float> @ret_only_zero_sqrt_vec(<2 x float> %x) { |
| ; CHECK-LABEL: define nofpclass(nan inf sub norm) <2 x float> @ret_only_zero_sqrt_vec( |
| ; CHECK-SAME: <2 x float> [[X:%.*]]) { |
| ; CHECK-NEXT: [[RESULT:%.*]] = call <2 x float> @llvm.copysign.v2f32(<2 x float> zeroinitializer, <2 x float> [[X]]) |
| ; CHECK-NEXT: ret <2 x float> [[RESULT]] |
| ; |
| %result = call <2 x float> @llvm.sqrt.v2f32(<2 x float> %x) |
| ret <2 x float> %result |
| } |
| |
| ; -> pinf |
| define nofpclass(nan norm sub zero) float @ret_only_inf_sqrt(float %x) { |
| ; CHECK-LABEL: define nofpclass(nan zero sub norm) float @ret_only_inf_sqrt( |
| ; CHECK-SAME: float [[X:%.*]]) { |
| ; CHECK-NEXT: ret float 0x7FF0000000000000 |
| ; |
| %result = call float @llvm.sqrt.f32(float %x) |
| ret float %result |
| } |
| |
| define nofpclass(norm sub zero) float @ret_only_inf_nan_sqrt(float %x) { |
| ; CHECK-LABEL: define nofpclass(zero sub norm) float @ret_only_inf_nan_sqrt( |
| ; CHECK-SAME: float [[X:%.*]]) { |
| ; CHECK-NEXT: [[RESULT:%.*]] = call float @llvm.sqrt.f32(float [[X]]) |
| ; CHECK-NEXT: ret float [[RESULT]] |
| ; |
| %result = call float @llvm.sqrt.f32(float %x) |
| ret float %result |
| } |
| |
| ; Could still be -0 |
| define nofpclass(ninf) float @ret_only_ninf__sqrt__known_negative() { |
| ; CHECK-LABEL: define nofpclass(ninf) float @ret_only_ninf__sqrt__known_negative() { |
| ; CHECK-NEXT: [[KNOWN_NEGATIVE:%.*]] = call float @returns_negative() |
| ; CHECK-NEXT: [[RESULT:%.*]] = call float @llvm.sqrt.f32(float [[KNOWN_NEGATIVE]]) |
| ; CHECK-NEXT: ret float [[RESULT]] |
| ; |
| %known.negative = call float @returns_negative() |
| %result = call float @llvm.sqrt.f32(float %known.negative) |
| ret float %result |
| } |
| |
| ; -> qnan |
| define nofpclass(ninf) float @ret_only_ninf__sqrt__known_negative_nonzero() { |
| ; CHECK-LABEL: define nofpclass(ninf) float @ret_only_ninf__sqrt__known_negative_nonzero() { |
| ; CHECK-NEXT: [[KNOWN_NEGATIVE_NONZERO:%.*]] = call float @returns_negative_nonzero() |
| ; CHECK-NEXT: ret float 0x7FF8000000000000 |
| ; |
| %known.negative.nonzero = call float @returns_negative_nonzero() |
| %result = call float @llvm.sqrt.f32(float %known.negative.nonzero) |
| ret float %result |
| } |
| |
| ; -> qnan |
| define nofpclass(ninf) <2 x float> @ret_only_ninf__sqrt__known_negative_nonzero_vec() { |
| ; CHECK-LABEL: define nofpclass(ninf) <2 x float> @ret_only_ninf__sqrt__known_negative_nonzero_vec() { |
| ; CHECK-NEXT: [[KNOWN_NEGATIVE_NONZERO:%.*]] = call <2 x float> @returns_negative_nonzero_vec() |
| ; CHECK-NEXT: ret <2 x float> splat (float 0x7FF8000000000000) |
| ; |
| %known.negative.nonzero = call <2 x float> @returns_negative_nonzero_vec() |
| %result = call <2 x float> @llvm.sqrt.v2f32(<2 x float> %known.negative.nonzero) |
| ret <2 x float> %result |
| } |
| |
| ; The negative subnormal may be flushed to -0, which returns a non-nan result. |
| define nofpclass(ninf) float @ret_only_ninf__sqrt__known_negative_nonzero_daz() #0 { |
| ; CHECK-LABEL: define nofpclass(ninf) float @ret_only_ninf__sqrt__known_negative_nonzero_daz( |
| ; CHECK-SAME: ) #[[ATTR0:[0-9]+]] { |
| ; CHECK-NEXT: [[KNOWN_NEGATIVE_NONZERO:%.*]] = call float @returns_negative_nonzero() |
| ; CHECK-NEXT: [[RESULT:%.*]] = call float @llvm.sqrt.f32(float [[KNOWN_NEGATIVE_NONZERO]]) |
| ; CHECK-NEXT: ret float [[RESULT]] |
| ; |
| %known.negative.nonzero = call float @returns_negative_nonzero() |
| %result = call float @llvm.sqrt.f32(float %known.negative.nonzero) |
| ret float %result |
| } |
| |
| ; The negative subnormal may be flushed to -0, which returns a non-nan result. |
| define nofpclass(ninf) float @ret_only_ninf__sqrt__known_negative_nonzero_dynamic() #1 { |
| ; CHECK-LABEL: define nofpclass(ninf) float @ret_only_ninf__sqrt__known_negative_nonzero_dynamic( |
| ; CHECK-SAME: ) #[[ATTR1:[0-9]+]] { |
| ; CHECK-NEXT: [[KNOWN_NEGATIVE_NONZERO:%.*]] = call float @returns_negative_nonzero() |
| ; CHECK-NEXT: [[RESULT:%.*]] = call float @llvm.sqrt.f32(float [[KNOWN_NEGATIVE_NONZERO]]) |
| ; CHECK-NEXT: ret float [[RESULT]] |
| ; |
| %known.negative.nonzero = call float @returns_negative_nonzero() |
| %result = call float @llvm.sqrt.f32(float %known.negative.nonzero) |
| ret float %result |
| } |
| |
| ; Cannot fold select. Demanded nan results demand negative inputs. |
| define nofpclass(inf norm zero) float @ret_only_nan_or_sub__sqrt__select_unknown_or_known_neg_nonzero(i1 %cond, float %x) { |
| ; CHECK-LABEL: define nofpclass(inf zero norm) float @ret_only_nan_or_sub__sqrt__select_unknown_or_known_neg_nonzero( |
| ; CHECK-SAME: i1 [[COND:%.*]], float [[X:%.*]]) { |
| ; CHECK-NEXT: [[KNOWN_NEGATIVE_NONZERO:%.*]] = call float @returns_negative_nonzero() |
| ; CHECK-NEXT: ret float 0x7FF8000000000000 |
| ; |
| %known.negative.nonzero = call float @returns_negative_nonzero() |
| %select = select i1 %cond, float %x, float %known.negative.nonzero |
| %result = call float @llvm.sqrt.f32(float %select) |
| ret float %result |
| } |
| |
| ; Cannot fold select. Demanded nan results permits negative infinity |
| define nofpclass(inf norm zero) float @ret_only_nan_or_sub__sqrt__select_unknown_or_maybe_ninf(i1 %cond, float nofpclass(nan) %x) { |
| ; CHECK-LABEL: define nofpclass(inf zero norm) float @ret_only_nan_or_sub__sqrt__select_unknown_or_maybe_ninf( |
| ; CHECK-SAME: i1 [[COND:%.*]], float nofpclass(nan) [[X:%.*]]) { |
| ; CHECK-NEXT: [[MAYBE_NINF:%.*]] = call nofpclass(nan pinf sub norm) float @func() |
| ; CHECK-NEXT: ret float 0x7FF8000000000000 |
| ; |
| %maybe.ninf = call nofpclass(pinf norm sub nan) float @func() |
| %select = select i1 %cond, float %x, float %maybe.ninf |
| %result = call float @llvm.sqrt.f32(float %select) |
| ret float %result |
| } |
| |
| ; Cannot fold select. Demanded nan results permits negative normals |
| define nofpclass(inf norm zero) float @ret_only_nan_or_sub__sqrt__select_unknown_or_maybe_nnorm(i1 %cond, float nofpclass(nan) %x) { |
| ; CHECK-LABEL: define nofpclass(inf zero norm) float @ret_only_nan_or_sub__sqrt__select_unknown_or_maybe_nnorm( |
| ; CHECK-SAME: i1 [[COND:%.*]], float nofpclass(nan) [[X:%.*]]) { |
| ; CHECK-NEXT: [[MAYBE_NNORM:%.*]] = call nofpclass(nan inf sub pnorm) float @func() |
| ; CHECK-NEXT: ret float 0x7FF8000000000000 |
| ; |
| %maybe.nnorm = call nofpclass(inf pnorm sub nan) float @func() |
| %select = select i1 %cond, float %x, float %maybe.nnorm |
| %result = call float @llvm.sqrt.f32(float %select) |
| ret float %result |
| } |
| |
| ; Cannot fold select. Demanded nan results permits negative subnormals |
| define nofpclass(inf norm zero) float @ret_only_nan_or_sub__sqrt__select_unknown_or_maybe_nsub(i1 %cond, float nofpclass(nan) %x) { |
| ; CHECK-LABEL: define nofpclass(inf zero norm) float @ret_only_nan_or_sub__sqrt__select_unknown_or_maybe_nsub( |
| ; CHECK-SAME: i1 [[COND:%.*]], float nofpclass(nan) [[X:%.*]]) { |
| ; CHECK-NEXT: [[MAYBE_NSUB:%.*]] = call nofpclass(nan inf psub norm) float @func() |
| ; CHECK-NEXT: ret float 0x7FF8000000000000 |
| ; |
| %maybe.nsub = call nofpclass(inf norm psub nan) float @func() |
| %select = select i1 %cond, float %x, float %maybe.nsub |
| %result = call float @llvm.sqrt.f32(float %select) |
| ret float %result |
| } |
| |
| ; -> sqrt |
| define nofpclass(pinf) float @no_pinf_result_implies_no_pinf_source(i1 %cond, float %unknown) { |
| ; CHECK-LABEL: define nofpclass(pinf) float @no_pinf_result_implies_no_pinf_source( |
| ; CHECK-SAME: i1 [[COND:%.*]], float [[UNKNOWN:%.*]]) { |
| ; CHECK-NEXT: [[RESULT:%.*]] = call float @llvm.sqrt.f32(float [[UNKNOWN]]) |
| ; CHECK-NEXT: ret float [[RESULT]] |
| ; |
| %select = select i1 %cond, float %unknown, float 0x7ff0000000000000 |
| %result = call float @llvm.sqrt.f32(float %select) |
| ret float %result |
| } |
| |
| define nofpclass(nan inf zero sub nnorm) float @pnorm_result_demands_pnorm_source(i1 %cond, float nofpclass(nan) %not.nan) { |
| ; CHECK-LABEL: define nofpclass(nan inf zero sub nnorm) float @pnorm_result_demands_pnorm_source( |
| ; CHECK-SAME: i1 [[COND:%.*]], float nofpclass(nan) [[NOT_NAN:%.*]]) { |
| ; CHECK-NEXT: [[ONLY_PNORM:%.*]] = call nofpclass(nan inf zero sub nnorm) float @func() |
| ; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[COND]], float [[NOT_NAN]], float [[ONLY_PNORM]] |
| ; CHECK-NEXT: [[RESULT:%.*]] = call nnan ninf float @llvm.sqrt.f32(float [[SELECT]]) |
| ; CHECK-NEXT: ret float [[RESULT]] |
| ; |
| %only.pnorm = call nofpclass(nan inf nnorm sub zero) float @func() |
| %select = select i1 %cond, float %not.nan, float %only.pnorm |
| %result = call float @llvm.sqrt.f32(float %select) |
| ret float %result |
| } |
| |
| define nofpclass(nan inf zero sub nnorm) float @pnorm_result_demands_psub_source(i1 %cond, float nofpclass(nan) %not.nan) { |
| ; CHECK-LABEL: define nofpclass(nan inf zero sub nnorm) float @pnorm_result_demands_psub_source( |
| ; CHECK-SAME: i1 [[COND:%.*]], float nofpclass(nan) [[NOT_NAN:%.*]]) { |
| ; CHECK-NEXT: [[ONLY_PSUB:%.*]] = call nofpclass(nan inf zero nsub norm) float @func() |
| ; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[COND]], float [[NOT_NAN]], float [[ONLY_PSUB]] |
| ; CHECK-NEXT: [[RESULT:%.*]] = call nnan ninf float @llvm.sqrt.f32(float [[SELECT]]) |
| ; CHECK-NEXT: ret float [[RESULT]] |
| ; |
| %only.psub = call nofpclass(nan inf norm nsub zero) float @func() |
| %select = select i1 %cond, float %not.nan, float %only.psub |
| %result = call float @llvm.sqrt.f32(float %select) |
| ret float %result |
| } |
| |
| define nofpclass(nan inf zero nsub norm) float @psub_result_implies_not_pnorm_source(i1 %cond, float nofpclass(nan) %not.nan) { |
| ; CHECK-LABEL: define nofpclass(nan inf zero nsub norm) float @psub_result_implies_not_pnorm_source( |
| ; CHECK-SAME: i1 [[COND:%.*]], float nofpclass(nan) [[NOT_NAN:%.*]]) { |
| ; CHECK-NEXT: [[ONLY_PNORM:%.*]] = call nofpclass(nan inf zero sub nnorm) float @func() |
| ; CHECK-NEXT: ret float poison |
| ; |
| %only.pnorm = call nofpclass(nan inf nnorm sub zero) float @func() |
| %select = select i1 %cond, float %not.nan, float %only.pnorm |
| %result = call float @llvm.sqrt.f32(float %select) |
| ret float %result |
| } |
| |
| define nofpclass(nan) float @ret_no_nan__sqrt(float %x) { |
| ; CHECK-LABEL: define nofpclass(nan) float @ret_no_nan__sqrt( |
| ; CHECK-SAME: float [[X:%.*]]) { |
| ; CHECK-NEXT: [[RESULT:%.*]] = call nnan contract float @llvm.sqrt.f32(float [[X]]) |
| ; CHECK-NEXT: ret float [[RESULT]] |
| ; |
| %result = call contract float @llvm.sqrt.f32(float %x) |
| ret float %result |
| } |
| |
| define nofpclass(snan) float @ret_no_snan__sqrt__no_neg_inputs(float nofpclass(ninf nnorm nsub) %x) { |
| ; CHECK-LABEL: define nofpclass(snan) float @ret_no_snan__sqrt__no_neg_inputs( |
| ; CHECK-SAME: float nofpclass(ninf nsub nnorm) [[X:%.*]]) { |
| ; CHECK-NEXT: [[RESULT:%.*]] = call contract float @llvm.sqrt.f32(float [[X]]) |
| ; CHECK-NEXT: ret float [[RESULT]] |
| ; |
| %result = call contract float @llvm.sqrt.f32(float %x) |
| ret float %result |
| } |
| |
| define nofpclass(snan) float @ret_no_snan__sqrt__no_neg_or_nan_inputs(float nofpclass(nan ninf nnorm nsub) %x) { |
| ; CHECK-LABEL: define nofpclass(snan) float @ret_no_snan__sqrt__no_neg_or_nan_inputs( |
| ; CHECK-SAME: float nofpclass(nan ninf nsub nnorm) [[X:%.*]]) { |
| ; CHECK-NEXT: [[RESULT:%.*]] = call nnan contract float @llvm.sqrt.f32(float [[X]]) |
| ; CHECK-NEXT: ret float [[RESULT]] |
| ; |
| %result = call contract float @llvm.sqrt.f32(float %x) |
| ret float %result |
| } |
| |
| ; Need to drop noundef to add nnan flag |
| define nofpclass(snan) float @ret_no_snan__noundef_sqrt__no_neg_or_nan_inputs(float nofpclass(nan ninf nnorm nsub) %x) { |
| ; CHECK-LABEL: define nofpclass(snan) float @ret_no_snan__noundef_sqrt__no_neg_or_nan_inputs( |
| ; CHECK-SAME: float nofpclass(nan ninf nsub nnorm) [[X:%.*]]) { |
| ; CHECK-NEXT: [[RESULT:%.*]] = call nnan contract float @llvm.sqrt.f32(float [[X]]) |
| ; CHECK-NEXT: ret float [[RESULT]] |
| ; |
| %result = call contract noundef float @llvm.sqrt.f32(float %x) |
| ret float %result |
| } |
| |
| define nofpclass(snan) float @ret_no_snan__sqrt__no_pinf_inputs(float nofpclass(pinf) %x) { |
| ; CHECK-LABEL: define nofpclass(snan) float @ret_no_snan__sqrt__no_pinf_inputs( |
| ; CHECK-SAME: float nofpclass(pinf) [[X:%.*]]) { |
| ; CHECK-NEXT: [[RESULT:%.*]] = call contract float @llvm.sqrt.f32(float [[X]]) |
| ; CHECK-NEXT: ret float [[RESULT]] |
| ; |
| %result = call contract float @llvm.sqrt.f32(float %x) |
| ret float %result |
| } |
| |
| ; Cannot infer flags. A nan output could still be produced by a -inf |
| ; input. |
| define nofpclass(pinf) float @ret_no_pinf__sqrt(float %x) { |
| ; CHECK-LABEL: define nofpclass(pinf) float @ret_no_pinf__sqrt( |
| ; CHECK-SAME: float [[X:%.*]]) { |
| ; CHECK-NEXT: [[RESULT:%.*]] = call contract float @llvm.sqrt.f32(float [[X]]) |
| ; CHECK-NEXT: ret float [[RESULT]] |
| ; |
| %result = call contract float @llvm.sqrt.f32(float %x) |
| ret float %result |
| } |
| |
| ; Infer nnan and ninf |
| define nofpclass(nan pinf) float @ret_no_pinf_no_nan__sqrt(float %x) { |
| ; CHECK-LABEL: define nofpclass(nan pinf) float @ret_no_pinf_no_nan__sqrt( |
| ; CHECK-SAME: float [[X:%.*]]) { |
| ; CHECK-NEXT: [[RESULT:%.*]] = call nnan ninf contract float @llvm.sqrt.f32(float [[X]]) |
| ; CHECK-NEXT: ret float [[RESULT]] |
| ; |
| %result = call contract float @llvm.sqrt.f32(float %x) |
| ret float %result |
| } |
| |
| ; Infer nnan and ninf |
| define nofpclass(nan) float @ret_no_nan__sqrt__no_pinf_inputs(float nofpclass(pinf) %x) { |
| ; CHECK-LABEL: define nofpclass(nan) float @ret_no_nan__sqrt__no_pinf_inputs( |
| ; CHECK-SAME: float nofpclass(pinf) [[X:%.*]]) { |
| ; CHECK-NEXT: [[RESULT:%.*]] = call nnan ninf contract float @llvm.sqrt.f32(float [[X]]) |
| ; CHECK-NEXT: ret float [[RESULT]] |
| ; |
| %result = call contract float @llvm.sqrt.f32(float %x) |
| ret float %result |
| } |
| |
| ; Infer nnan and ninf |
| define nofpclass(nan) float @ret_no_nan__sqrt__no_inf_inputs(float nofpclass(inf) %x) { |
| ; CHECK-LABEL: define nofpclass(nan) float @ret_no_nan__sqrt__no_inf_inputs( |
| ; CHECK-SAME: float nofpclass(inf) [[X:%.*]]) { |
| ; CHECK-NEXT: [[RESULT:%.*]] = call nnan ninf contract float @llvm.sqrt.f32(float [[X]]) |
| ; CHECK-NEXT: ret float [[RESULT]] |
| ; |
| %result = call contract float @llvm.sqrt.f32(float %x) |
| ret float %result |
| } |
| |
| define nofpclass(snan) float @qnan_result_demands_snan_src(i1 %cond, float %unknown) { |
| ; CHECK-LABEL: define nofpclass(snan) float @qnan_result_demands_snan_src( |
| ; CHECK-SAME: i1 [[COND:%.*]], float [[UNKNOWN:%.*]]) { |
| ; CHECK-NEXT: [[SNAN:%.*]] = call float @returns_snan() |
| ; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[COND]], float [[SNAN]], float [[UNKNOWN]] |
| ; CHECK-NEXT: [[RESULT:%.*]] = call float @llvm.sqrt.f32(float [[SELECT]]) |
| ; CHECK-NEXT: ret float [[RESULT]] |
| ; |
| %snan = call float @returns_snan() |
| %select = select i1 %cond, float %snan, float %unknown |
| %result = call float @llvm.sqrt.f32(float %select) |
| ret float %result |
| } |
| |
| attributes #0 = { denormal_fpenv(preservesign) } |
| attributes #1 = { denormal_fpenv(dynamic) } |