; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --check-attributes --version 2 ; RUN: opt -aa-pipeline=basic-aa -passes=attributor -attributor-manifest-internal -attributor-annotate-decl-cs -S < %s | FileCheck %s --check-prefixes=CHECK,TUNIT ; RUN: opt -aa-pipeline=basic-aa -passes=attributor-cgscc -attributor-manifest-internal -attributor-annotate-decl-cs -S < %s | FileCheck %s --check-prefixes=CHECK,CGSCC declare nofpclass(nan) float @ret_nofpclass_nan() declare [2 x [3 x float]] @ret_array() declare float @extern() declare float @extern.f32(float) declare void @extern.use(float) declare void @extern.use.array([2 x [3 x float]]) declare void @llvm.assume(i1 noundef) declare void @unknown() declare half @llvm.fabs.f16(half) declare float @llvm.fabs.f32(float) declare void @extern.use.f16(half) declare i1 @llvm.is.fpclass.f32(float, i32 immarg) declare float @llvm.experimental.constrained.sitofp.f32.i32(i32, metadata, metadata) declare float @llvm.experimental.constrained.uitofp.f32.i32(i32, metadata, metadata) declare float @llvm.arithmetic.fence.f32(float) define float @returned_0() { ; CHECK-LABEL: define noundef nofpclass(nan inf nzero sub norm) float @returned_0() { ; CHECK-NEXT: call void @unknown() ; CHECK-NEXT: ret float 0.000000e+00 ; call void @unknown() ret float 0.0 } define float @returned_neg0() { ; CHECK-LABEL: define noundef nofpclass(nan inf pzero sub norm) float @returned_neg0() { ; CHECK-NEXT: call void @unknown() ; CHECK-NEXT: ret float -0.000000e+00 ; call void @unknown() ret float -0.0 } define float @returned_undef() { ; CHECK-LABEL: define nofpclass(all) float @returned_undef() { ; CHECK-NEXT: call void @unknown() ; CHECK-NEXT: ret float undef ; call void @unknown() ret float undef } define float @returned_poison() { ; CHECK-LABEL: define nofpclass(all) float @returned_poison() { ; CHECK-NEXT: call void @unknown() ; CHECK-NEXT: ret float poison ; call void @unknown() ret float poison } define double @returned_snan() { ; CHECK-LABEL: define noundef nofpclass(qnan inf zero sub norm) double @returned_snan() { ; CHECK-NEXT: call void @unknown() ; CHECK-NEXT: ret double 0x7FF0000000000001 ; call void @unknown() ret double 0x7FF0000000000001 } define double @returned_qnan() { ; CHECK-LABEL: define noundef nofpclass(snan inf zero sub norm) double @returned_qnan() { ; CHECK-NEXT: call void @unknown() ; CHECK-NEXT: ret double 0x7FF8000000000000 ; call void @unknown() ret double 0x7FF8000000000000 } define <2 x double> @returned_zero_vector() { ; CHECK-LABEL: define noundef nofpclass(nan inf nzero sub norm) <2 x double> @returned_zero_vector() { ; CHECK-NEXT: call void @unknown() ; CHECK-NEXT: ret <2 x double> zeroinitializer ; call void @unknown() ret <2 x double> zeroinitializer } define <2 x double> @returned_negzero_vector() { ; CHECK-LABEL: define noundef nofpclass(nan inf pzero sub norm) <2 x double> @returned_negzero_vector() { ; CHECK-NEXT: call void @unknown() ; CHECK-NEXT: ret <2 x double> ; call void @unknown() ret <2 x double> } ; Test a vector element that's a constant but not ConstantFP. define <2 x double> @returned_strange_constant_vector_elt() { ; CHECK-LABEL: define <2 x double> @returned_strange_constant_vector_elt() { ; CHECK-NEXT: call void @unknown() ; CHECK-NEXT: ret <2 x double> ; call void @unknown() ret <2 x double> } ; Test a vector element that's an undef/poison define <3 x double> @returned_undef_constant_vector_elt() { ; CHECK-LABEL: define nofpclass(nan inf pzero sub norm) <3 x double> @returned_undef_constant_vector_elt() { ; CHECK-NEXT: call void @unknown() ; CHECK-NEXT: ret <3 x double> ; call void @unknown() ret <3 x double> } define <2 x double> @returned_qnan_zero_vector() { ; CHECK-LABEL: define noundef nofpclass(snan inf nzero sub norm) <2 x double> @returned_qnan_zero_vector() { ; CHECK-NEXT: call void @unknown() ; CHECK-NEXT: ret <2 x double> ; call void @unknown() ret <2 x double> } ; Return a float trivially nofpclass(nan) (call return attribute) define float @return_nofpclass_nan_decl_return() { ; CHECK-LABEL: define nofpclass(nan) float @return_nofpclass_nan_decl_return() { ; CHECK-NEXT: [[RET:%.*]] = call nofpclass(nan) float @ret_nofpclass_nan() ; CHECK-NEXT: ret float [[RET]] ; %ret = call float @ret_nofpclass_nan() ret float %ret } ; Return a float trivially nofpclass(nan) (argument attribute) define float @return_nofpclass_nan_arg(float returned nofpclass(nan) %p) { ; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none) ; CHECK-LABEL: define nofpclass(nan) float @return_nofpclass_nan_arg ; CHECK-SAME: (float returned nofpclass(nan) [[P:%.*]]) #[[ATTR3:[0-9]+]] { ; CHECK-NEXT: ret float [[P]] ; ret float %p } define [2 x [3 x float]] @return_nofpclass_inf_ret_array() { ; CHECK-LABEL: define nofpclass(inf) [2 x [3 x float]] @return_nofpclass_inf_ret_array() { ; CHECK-NEXT: [[RET:%.*]] = call nofpclass(inf) [2 x [3 x float]] @ret_array() ; CHECK-NEXT: ret [2 x [3 x float]] [[RET]] ; %ret = call nofpclass(inf) [2 x [3 x float]] @ret_array() ret [2 x [3 x float]] %ret } define float @returned_nnan_fadd(float %arg0, float %arg1) { ; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none) ; CHECK-LABEL: define nofpclass(nan) float @returned_nnan_fadd ; CHECK-SAME: (float nofpclass(nan) [[ARG0:%.*]], float nofpclass(nan) [[ARG1:%.*]]) #[[ATTR3]] { ; CHECK-NEXT: [[FADD:%.*]] = fadd nnan float [[ARG0]], [[ARG1]] ; CHECK-NEXT: ret float [[FADD]] ; %fadd = fadd nnan float %arg0, %arg1 ret float %fadd } define float @return_nofpclass_nan_callsite() { ; CHECK-LABEL: define nofpclass(nan) float @return_nofpclass_nan_callsite() { ; CHECK-NEXT: [[CALL:%.*]] = call nofpclass(nan) float @extern() ; CHECK-NEXT: ret float [[CALL]] ; %call = call nofpclass(nan) float @extern() ret float %call } ; Can union the return classes define nofpclass(inf) float @return_ninf_nofpclass_nan_callsite() { ; CHECK-LABEL: define nofpclass(nan inf) float @return_ninf_nofpclass_nan_callsite() { ; CHECK-NEXT: [[CALL:%.*]] = call nofpclass(nan) float @extern() ; CHECK-NEXT: ret float [[CALL]] ; %call = call nofpclass(nan) float @extern() ret float %call } define void @arg_used_by_nofpclass_nan_callsite(float %arg) { ; CHECK-LABEL: define void @arg_used_by_nofpclass_nan_callsite ; CHECK-SAME: (float [[ARG:%.*]]) { ; CHECK-NEXT: call void @extern.use(float nofpclass(nan) [[ARG]]) ; CHECK-NEXT: ret void ; call void @extern.use(float nofpclass(nan) %arg) ret void } ; Callsite can union the incoming and outgoing define void @ninf_arg_used_by_nofpclass_nan_callsite(float nofpclass(inf) %arg) { ; CHECK-LABEL: define void @ninf_arg_used_by_nofpclass_nan_callsite ; CHECK-SAME: (float nofpclass(inf) [[ARG:%.*]]) { ; CHECK-NEXT: call void @extern.use(float nofpclass(nan inf) [[ARG]]) ; CHECK-NEXT: ret void ; call void @extern.use(float nofpclass(nan) %arg) ret void } define void @ninf_arg_used_by_callsite_array([2 x [3 x float]] nofpclass(inf) %arg) { ; CHECK-LABEL: define void @ninf_arg_used_by_callsite_array ; CHECK-SAME: ([2 x [3 x float]] nofpclass(inf) [[ARG:%.*]]) { ; CHECK-NEXT: call void @extern.use.array([2 x [3 x float]] nofpclass(inf) [[ARG]]) ; CHECK-NEXT: ret void ; call void @extern.use.array([2 x [3 x float]] %arg) ret void } define void @nofpclass_call_use_after_unannotated_use(float %arg) { ; CHECK-LABEL: define void @nofpclass_call_use_after_unannotated_use ; CHECK-SAME: (float [[ARG:%.*]]) { ; CHECK-NEXT: call void @extern(float [[ARG]]) #[[ATTR17:[0-9]+]] ; CHECK-NEXT: call void @extern(float nofpclass(nan inf) [[ARG]]) ; CHECK-NEXT: ret void ; call void @extern(float %arg) willreturn nounwind ; < annotate this use call void @extern(float nofpclass(nan inf) %arg) ret void } define float @mutually_recursive0(float %arg) { ; TUNIT: Function Attrs: mustprogress nofree nosync nounwind willreturn memory(none) ; TUNIT-LABEL: define nofpclass(all) float @mutually_recursive0 ; TUNIT-SAME: (float [[ARG:%.*]]) #[[ATTR4:[0-9]+]] { ; TUNIT-NEXT: ret float undef ; ; CGSCC: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none) ; CGSCC-LABEL: define nofpclass(all) float @mutually_recursive0 ; CGSCC-SAME: (float [[ARG:%.*]]) #[[ATTR3]] { ; CGSCC-NEXT: ret float undef ; %call = call float @mutually_recursive1(float %arg) ret float %call } define float @mutually_recursive1(float %arg) { ; TUNIT: Function Attrs: mustprogress nofree nosync nounwind willreturn memory(none) ; TUNIT-LABEL: define nofpclass(all) float @mutually_recursive1 ; TUNIT-SAME: (float [[ARG:%.*]]) #[[ATTR4]] { ; TUNIT-NEXT: ret float undef ; ; CGSCC: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none) ; CGSCC-LABEL: define nofpclass(all) float @mutually_recursive1 ; CGSCC-SAME: (float [[ARG:%.*]]) #[[ATTR3]] { ; CGSCC-NEXT: ret float undef ; %call = call float @mutually_recursive0(float %arg) ret float %call } define float @recursive_phi(ptr %ptr) { ; CHECK-LABEL: define nofpclass(nan) float @recursive_phi ; CHECK-SAME: (ptr nofree [[PTR:%.*]]) { ; CHECK-NEXT: entry: ; CHECK-NEXT: [[RET:%.*]] = call nofpclass(nan) float @ret_nofpclass_nan() ; CHECK-NEXT: br label [[LOOP:%.*]] ; CHECK: loop: ; CHECK-NEXT: [[PHI:%.*]] = phi float [ [[RET]], [[ENTRY:%.*]] ], [ [[RET]], [[LOOP]] ] ; CHECK-NEXT: [[COND:%.*]] = load volatile i1, ptr [[PTR]], align 1 ; CHECK-NEXT: br i1 [[COND]], label [[LOOP]], label [[EXIT:%.*]] ; CHECK: exit: ; CHECK-NEXT: ret float [[RET]] ; entry: %ret = call float @ret_nofpclass_nan() br label %loop loop: %phi = phi float [%ret, %entry], [%phi, %loop] %cond = load volatile i1, ptr %ptr br i1 %cond, label %loop, label %exit exit: ret float %phi } ; Should be able to infer nofpclass(nan) return define float @fcmp_uno_check(float %arg) local_unnamed_addr { ; CHECK-LABEL: define float @fcmp_uno_check ; CHECK-SAME: (float [[ARG:%.*]]) local_unnamed_addr { ; CHECK-NEXT: entry: ; CHECK-NEXT: [[ISNAN:%.*]] = fcmp uno float [[ARG]], 0.000000e+00 ; CHECK-NEXT: br i1 [[ISNAN]], label [[BB0:%.*]], label [[BB1:%.*]] ; CHECK: bb0: ; CHECK-NEXT: [[CALL:%.*]] = call nofpclass(nan) float @ret_nofpclass_nan() ; CHECK-NEXT: br label [[BB1]] ; CHECK: bb1: ; CHECK-NEXT: [[PHI:%.*]] = phi float [ [[CALL]], [[BB0]] ], [ [[ARG]], [[ENTRY:%.*]] ] ; CHECK-NEXT: ret float [[PHI]] ; entry: %isnan = fcmp uno float %arg, 0.0 br i1 %isnan, label %bb0, label %bb1 bb0: %call = call float @ret_nofpclass_nan() br label %bb1 bb1: %phi = phi float [ %call, %bb0 ], [ %arg, %entry ] ret float %phi } ; Should be able to infer nofpclass(nan) on %arg use define void @fcmp_ord_guard_callsite_arg(float %arg) { ; CHECK-LABEL: define void @fcmp_ord_guard_callsite_arg ; CHECK-SAME: (float [[ARG:%.*]]) { ; CHECK-NEXT: entry: ; CHECK-NEXT: [[IS_NOT_NAN:%.*]] = fcmp ord float [[ARG]], 0.000000e+00 ; CHECK-NEXT: br i1 [[IS_NOT_NAN]], label [[BB0:%.*]], label [[BB1:%.*]] ; CHECK: bb0: ; CHECK-NEXT: call void @extern.use(float [[ARG]]) ; CHECK-NEXT: br label [[BB1]] ; CHECK: bb1: ; CHECK-NEXT: ret void ; entry: %is.not.nan = fcmp ord float %arg, 0.0 br i1 %is.not.nan, label %bb0, label %bb1 bb0: call void @extern.use(float %arg) br label %bb1 bb1: ret void } ; Should be able to infer nofpclass on both %arg uses define float @fcmp_ord_assume_callsite_arg_return(float %arg) { ; CHECK-LABEL: define nofpclass(nan) float @fcmp_ord_assume_callsite_arg_return ; CHECK-SAME: (float returned nofpclass(nan) [[ARG:%.*]]) { ; CHECK-NEXT: entry: ; CHECK-NEXT: [[IS_NOT_NAN:%.*]] = fcmp ord float [[ARG]], 0.000000e+00 ; CHECK-NEXT: call void @llvm.assume(i1 noundef [[IS_NOT_NAN]]) #[[ATTR18:[0-9]+]] ; CHECK-NEXT: call void @extern.use(float nofpclass(nan) [[ARG]]) ; CHECK-NEXT: ret float [[ARG]] ; entry: %is.not.nan = fcmp ord float %arg, 0.0 call void @llvm.assume(i1 %is.not.nan) call void @extern.use(float %arg) ret float %arg } define internal float @returned_dead() { ; CHECK-LABEL: define internal nofpclass(nan inf nzero sub norm) float @returned_dead() { ; CHECK-NEXT: call void @unknown() ; CHECK-NEXT: ret float undef ; call void @unknown() ret float 0.0 } define void @returned_dead_caller() { ; CHECK-LABEL: define void @returned_dead_caller() { ; CHECK-NEXT: [[TMP1:%.*]] = call float @returned_dead() ; CHECK-NEXT: ret void ; call float @returned_dead() ret void } define internal float @only_nofpclass_inf_callers(float %arg) { ; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none) ; CHECK-LABEL: define internal float @only_nofpclass_inf_callers ; CHECK-SAME: (float nofpclass(inf) [[ARG:%.*]]) #[[ATTR3]] { ; CHECK-NEXT: [[ADD:%.*]] = fadd float [[ARG]], [[ARG]] ; CHECK-NEXT: ret float [[ADD]] ; %add = fadd float %arg, %arg ret float %add } define float @call_noinf_0(float nofpclass(inf) %arg) { ; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none) ; TUNIT-LABEL: define float @call_noinf_0 ; TUNIT-SAME: (float nofpclass(inf) [[ARG:%.*]]) #[[ATTR3]] { ; TUNIT-NEXT: [[RESULT:%.*]] = call float @only_nofpclass_inf_callers(float nofpclass(inf) [[ARG]]) #[[ATTR19:[0-9]+]] ; TUNIT-NEXT: ret float [[RESULT]] ; ; CGSCC: Function Attrs: mustprogress nofree nosync nounwind willreturn memory(none) ; CGSCC-LABEL: define float @call_noinf_0 ; CGSCC-SAME: (float nofpclass(inf) [[ARG:%.*]]) #[[ATTR4:[0-9]+]] { ; CGSCC-NEXT: [[RESULT:%.*]] = call float @only_nofpclass_inf_callers(float nofpclass(inf) [[ARG]]) #[[ATTR19:[0-9]+]] ; CGSCC-NEXT: ret float [[RESULT]] ; %result = call float @only_nofpclass_inf_callers(float %arg) ret float %result } define float @call_noinf_1(float %arg) { ; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none) ; TUNIT-LABEL: define float @call_noinf_1 ; TUNIT-SAME: (float [[ARG:%.*]]) #[[ATTR3]] { ; TUNIT-NEXT: [[RESULT:%.*]] = call float @only_nofpclass_inf_callers(float nofpclass(inf) [[ARG]]) #[[ATTR19]] ; TUNIT-NEXT: ret float [[RESULT]] ; ; CGSCC: Function Attrs: mustprogress nofree nosync nounwind willreturn memory(none) ; CGSCC-LABEL: define float @call_noinf_1 ; CGSCC-SAME: (float [[ARG:%.*]]) #[[ATTR4]] { ; CGSCC-NEXT: [[RESULT:%.*]] = call float @only_nofpclass_inf_callers(float nofpclass(inf) [[ARG]]) #[[ATTR19]] ; CGSCC-NEXT: ret float [[RESULT]] ; %result = call float @only_nofpclass_inf_callers(float nofpclass(inf) %arg) ret float %result } ; TODO: Should be able to infer nofpclass(inf) on return define internal float @only_nofpclass_inf_return_users(float %arg) { ; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none) ; CHECK-LABEL: define internal float @only_nofpclass_inf_return_users ; CHECK-SAME: (float [[ARG:%.*]]) #[[ATTR3]] { ; CHECK-NEXT: [[ADD:%.*]] = fadd float [[ARG]], [[ARG]] ; CHECK-NEXT: ret float [[ADD]] ; %add = fadd float %arg, %arg ret float %add } define float @call_noinf_return_0(float %arg) { ; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none) ; TUNIT-LABEL: define nofpclass(inf) float @call_noinf_return_0 ; TUNIT-SAME: (float [[ARG:%.*]]) #[[ATTR3]] { ; TUNIT-NEXT: [[RESULT:%.*]] = call nofpclass(inf) float @only_nofpclass_inf_return_users(float [[ARG]]) #[[ATTR19]] ; TUNIT-NEXT: ret float [[RESULT]] ; ; CGSCC: Function Attrs: mustprogress nofree nosync nounwind willreturn memory(none) ; CGSCC-LABEL: define nofpclass(inf) float @call_noinf_return_0 ; CGSCC-SAME: (float nofpclass(inf) [[ARG:%.*]]) #[[ATTR4]] { ; CGSCC-NEXT: [[RESULT:%.*]] = call nofpclass(inf) float @only_nofpclass_inf_return_users(float nofpclass(inf) [[ARG]]) #[[ATTR19]] ; CGSCC-NEXT: ret float [[RESULT]] ; %result = call nofpclass(inf) float @only_nofpclass_inf_return_users(float %arg) ret float %result } define float @call_noinf_return_1(float %arg) { ; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none) ; TUNIT-LABEL: define nofpclass(inf) float @call_noinf_return_1 ; TUNIT-SAME: (float [[ARG:%.*]]) #[[ATTR3]] { ; TUNIT-NEXT: [[RESULT:%.*]] = call nofpclass(inf) float @only_nofpclass_inf_return_users(float [[ARG]]) #[[ATTR19]] ; TUNIT-NEXT: ret float [[RESULT]] ; ; CGSCC: Function Attrs: mustprogress nofree nosync nounwind willreturn memory(none) ; CGSCC-LABEL: define nofpclass(inf) float @call_noinf_return_1 ; CGSCC-SAME: (float nofpclass(inf) [[ARG:%.*]]) #[[ATTR4]] { ; CGSCC-NEXT: [[RESULT:%.*]] = call nofpclass(inf) float @only_nofpclass_inf_return_users(float nofpclass(inf) [[ARG]]) #[[ATTR19]] ; CGSCC-NEXT: ret float [[RESULT]] ; %result = call nofpclass(inf) float @only_nofpclass_inf_return_users(float %arg) ret float %result } define float @fcmp_olt_assume_one_0_callsite_arg_return(float %arg) { ; CHECK-LABEL: define nofpclass(nan zero) float @fcmp_olt_assume_one_0_callsite_arg_return ; CHECK-SAME: (float returned nofpclass(nan zero) [[ARG:%.*]]) { ; CHECK-NEXT: entry: ; CHECK-NEXT: [[IS_NOT_ZERO_OR_NAN:%.*]] = fcmp one float [[ARG]], 0.000000e+00 ; CHECK-NEXT: call void @llvm.assume(i1 noundef [[IS_NOT_ZERO_OR_NAN]]) #[[ATTR18]] ; CHECK-NEXT: call void @extern.use(float nofpclass(nan zero) [[ARG]]) ; CHECK-NEXT: ret float [[ARG]] ; entry: %is.not.zero.or.nan = fcmp one float %arg, 0.0 call void @llvm.assume(i1 %is.not.zero.or.nan) call void @extern.use(float %arg) ret float %arg } define float @fcmp_olt_assume_une_0_callsite_arg_return(float %arg) { ; CHECK-LABEL: define nofpclass(zero) float @fcmp_olt_assume_une_0_callsite_arg_return ; CHECK-SAME: (float returned nofpclass(zero) [[ARG:%.*]]) { ; CHECK-NEXT: entry: ; CHECK-NEXT: [[IS_NOT_ZERO_OR_NAN:%.*]] = fcmp une float [[ARG]], 0.000000e+00 ; CHECK-NEXT: call void @llvm.assume(i1 noundef [[IS_NOT_ZERO_OR_NAN]]) #[[ATTR18]] ; CHECK-NEXT: call void @extern.use(float nofpclass(zero) [[ARG]]) ; CHECK-NEXT: ret float [[ARG]] ; entry: %is.not.zero.or.nan = fcmp une float %arg, 0.0 call void @llvm.assume(i1 %is.not.zero.or.nan) call void @extern.use(float %arg) ret float %arg } define half @fcmp_assume_issubnormal_callsite_arg_return(half %arg) { ; CHECK-LABEL: define nofpclass(nan inf nzero nsub norm) half @fcmp_assume_issubnormal_callsite_arg_return ; CHECK-SAME: (half returned nofpclass(nan inf nzero nsub norm) [[ARG:%.*]]) { ; CHECK-NEXT: entry: ; CHECK-NEXT: [[FABS:%.*]] = call nofpclass(ninf nzero nsub nnorm) half @llvm.fabs.f16(half nofpclass(nan inf nzero nsub norm) [[ARG]]) #[[ATTR20:[0-9]+]] ; CHECK-NEXT: [[IS_SUBNORMAL:%.*]] = fcmp olt half [[FABS]], 0xH0400 ; CHECK-NEXT: call void @llvm.assume(i1 noundef [[IS_SUBNORMAL]]) #[[ATTR18]] ; CHECK-NEXT: call void @extern.use.f16(half nofpclass(nan inf nzero nsub norm) [[ARG]]) ; CHECK-NEXT: ret half [[ARG]] ; entry: %fabs = call half @llvm.fabs.f16(half %arg) %is.subnormal = fcmp olt half %fabs, 0xH0400 call void @llvm.assume(i1 %is.subnormal) call void @extern.use.f16(half %arg) ret half %arg } ; Assume is after the call, shouldn't mark callsite. define half @fcmp_assume_not_inf_after_call(half %arg) { ; CHECK-LABEL: define half @fcmp_assume_not_inf_after_call ; CHECK-SAME: (half returned [[ARG:%.*]]) { ; CHECK-NEXT: entry: ; CHECK-NEXT: call void @extern.use.f16(half [[ARG]]) ; CHECK-NEXT: [[NOT_INF:%.*]] = fcmp oeq half [[ARG]], 0xH7C00 ; CHECK-NEXT: call void @llvm.assume(i1 noundef [[NOT_INF]]) ; CHECK-NEXT: ret half [[ARG]] ; entry: call void @extern.use.f16(half %arg) %not.inf = fcmp oeq half %arg, 0xH7C00 call void @llvm.assume(i1 %not.inf) ret half %arg } ; Assume not subnormal or zero, and not infinity define half @fcmp_assume2_callsite_arg_return(half %arg) { ; CHECK-LABEL: define nofpclass(nan inf zero sub nnorm) half @fcmp_assume2_callsite_arg_return ; CHECK-SAME: (half returned nofpclass(nan inf zero sub nnorm) [[ARG:%.*]]) { ; CHECK-NEXT: entry: ; CHECK-NEXT: [[FABS:%.*]] = call nofpclass(nan ninf nzero nsub nnorm) half @llvm.fabs.f16(half nofpclass(nan inf zero sub nnorm) [[ARG]]) #[[ATTR20]] ; CHECK-NEXT: [[NOT_SUBNORMAL_OR_ZERO:%.*]] = fcmp oge half [[FABS]], 0xH0400 ; CHECK-NEXT: call void @llvm.assume(i1 noundef [[NOT_SUBNORMAL_OR_ZERO]]) #[[ATTR18]] ; CHECK-NEXT: [[NOT_INF:%.*]] = fcmp one half [[ARG]], 0xH7C00 ; CHECK-NEXT: call void @llvm.assume(i1 noundef [[NOT_INF]]) #[[ATTR18]] ; CHECK-NEXT: call void @extern.use.f16(half nofpclass(nan inf zero sub nnorm) [[ARG]]) ; CHECK-NEXT: ret half [[ARG]] ; entry: %fabs = call half @llvm.fabs.f16(half %arg) %not.subnormal.or.zero = fcmp oge half %fabs, 0xH0400 call void @llvm.assume(i1 %not.subnormal.or.zero) %not.inf = fcmp one half %arg, 0xH7C00 call void @llvm.assume(i1 %not.inf) call void @extern.use.f16(half %arg) ret half %arg } define float @is_fpclass_assume_arg_return(float %arg) { ; CHECK-LABEL: define nofpclass(nan pinf pzero sub nnorm) float @is_fpclass_assume_arg_return ; CHECK-SAME: (float returned nofpclass(nan pinf pzero sub nnorm) [[ARG:%.*]]) { ; CHECK-NEXT: entry: ; CHECK-NEXT: [[CLASS_TEST:%.*]] = call i1 @llvm.is.fpclass.f32(float nofpclass(nan pinf pzero sub nnorm) [[ARG]], i32 noundef 292) #[[ATTR20]] ; CHECK-NEXT: call void @llvm.assume(i1 noundef [[CLASS_TEST]]) #[[ATTR18]] ; CHECK-NEXT: call void @extern.use(float nofpclass(nan pinf pzero sub nnorm) [[ARG]]) ; CHECK-NEXT: ret float [[ARG]] ; entry: %class.test = call i1 @llvm.is.fpclass.f32(float %arg, i32 292) call void @llvm.assume(i1 %class.test) call void @extern.use(float %arg) ret float %arg } ; Make sure we don't get confused by looking at an unrelated assume ; based on the fabs of the value. define half @assume_fcmp_fabs_with_other_fabs_assume(half %arg) { ; CHECK-LABEL: define nofpclass(nan inf zero nsub norm) half @assume_fcmp_fabs_with_other_fabs_assume ; CHECK-SAME: (half returned nofpclass(nan inf zero nsub norm) [[ARG:%.*]]) { ; CHECK-NEXT: entry: ; CHECK-NEXT: [[FABS:%.*]] = call nofpclass(nan inf zero nsub norm) half @llvm.fabs.f16(half nofpclass(nan inf zero nsub norm) [[ARG]]) #[[ATTR20]] ; CHECK-NEXT: [[UNRELATED_FABS:%.*]] = fcmp one half [[FABS]], 0xH0000 ; CHECK-NEXT: call void @llvm.assume(i1 noundef [[UNRELATED_FABS]]) #[[ATTR18]] ; CHECK-NEXT: [[IS_SUBNORMAL:%.*]] = fcmp olt half [[FABS]], 0xH0400 ; CHECK-NEXT: call void @llvm.assume(i1 noundef [[IS_SUBNORMAL]]) #[[ATTR18]] ; CHECK-NEXT: call void @extern.use.f16(half nofpclass(nan inf zero nsub norm) [[ARG]]) ; CHECK-NEXT: call void @extern.use.f16(half nofpclass(nan inf zero nsub norm) [[FABS]]) ; CHECK-NEXT: ret half [[ARG]] ; entry: %fabs = call half @llvm.fabs.f16(half %arg) %unrelated.fabs = fcmp one half %fabs, 0.0 call void @llvm.assume(i1 %unrelated.fabs) %is.subnormal = fcmp olt half %fabs, 0xH0400 call void @llvm.assume(i1 %is.subnormal) call void @extern.use.f16(half %arg) call void @extern.use.f16(half %fabs) ret half %arg } ; Make sure if looking through the fabs finds a different source ; value, we still identify a test mask by ignoring the fabs define half @assume_fcmp_fabs_with_other_fabs_assume_fallback(half %arg) { ; CHECK-LABEL: define nofpclass(nan inf nzero sub norm) half @assume_fcmp_fabs_with_other_fabs_assume_fallback ; CHECK-SAME: (half returned nofpclass(nan inf nzero sub norm) [[ARG:%.*]]) { ; CHECK-NEXT: entry: ; CHECK-NEXT: [[FABS:%.*]] = call nofpclass(nan inf nzero sub norm) half @llvm.fabs.f16(half nofpclass(nan inf nzero sub norm) [[ARG]]) #[[ATTR20]] ; CHECK-NEXT: call void @llvm.assume(i1 noundef true) #[[ATTR18]] ; CHECK-NEXT: [[UNRELATED_FABS:%.*]] = fcmp oeq half [[FABS]], 0xH0000 ; CHECK-NEXT: call void @llvm.assume(i1 noundef [[UNRELATED_FABS]]) #[[ATTR18]] ; CHECK-NEXT: call void @llvm.assume(i1 noundef true) #[[ATTR18]] ; CHECK-NEXT: call void @extern.use.f16(half nofpclass(nan inf nzero sub norm) [[ARG]]) ; CHECK-NEXT: call void @extern.use.f16(half nofpclass(nan inf nzero sub norm) [[FABS]]) ; CHECK-NEXT: ret half [[ARG]] ; entry: %fabs = call half @llvm.fabs.f16(half %arg) %one.inf = fcmp one half %arg, 0xH7C00 call void @llvm.assume(i1 %one.inf) %unrelated.fabs = fcmp oeq half %fabs, 0.0 call void @llvm.assume(i1 %unrelated.fabs) %is.subnormal = fcmp olt half %fabs, 0xH0400 call void @llvm.assume(i1 %is.subnormal) call void @extern.use.f16(half %arg) call void @extern.use.f16(half %fabs) ret half %arg } define float @assume_bundles(i1 %c, float %ret) { ; CHECK-LABEL: define float @assume_bundles ; CHECK-SAME: (i1 noundef [[C:%.*]], float returned [[RET:%.*]]) { ; CHECK-NEXT: entry: ; CHECK-NEXT: br i1 [[C]], label [[A:%.*]], label [[B:%.*]] ; CHECK: A: ; CHECK-NEXT: call void @llvm.assume(i1 noundef true) #[[ATTR18]] [ "nofpclass"(float [[RET]], i32 3) ] ; CHECK-NEXT: call void @extern.use(float nofpclass(nan) [[RET]]) ; CHECK-NEXT: ret float [[RET]] ; CHECK: B: ; CHECK-NEXT: call void @llvm.assume(i1 noundef true) [ "nofpclass"(float [[RET]], i32 12) ] ; CHECK-NEXT: call void @extern.use(float nofpclass(ninf nnorm) [[RET]]) ; CHECK-NEXT: ret float [[RET]] ; entry: br i1 %c, label %A, label %B A: call void @llvm.assume(i1 true) [ "nofpclass"(float %ret, i32 3) ] call void @extern.use(float %ret) ret float %ret B: call void @llvm.assume(i1 true) [ "nofpclass"(float %ret, i32 12) ] call void @extern.use(float %ret) ret float %ret } define float @returned_load(ptr %ptr) { ; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: read) ; CHECK-LABEL: define float @returned_load ; CHECK-SAME: (ptr nocapture nofree noundef nonnull readonly align 4 dereferenceable(4) [[PTR:%.*]]) #[[ATTR5:[0-9]+]] { ; CHECK-NEXT: [[LOAD:%.*]] = load float, ptr [[PTR]], align 4 ; CHECK-NEXT: ret float [[LOAD]] ; %load = load float, ptr %ptr ret float %load } define float @pass_nofpclass_inf_through_memory(float nofpclass(inf) %arg) { ; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none) ; TUNIT-LABEL: define float @pass_nofpclass_inf_through_memory ; TUNIT-SAME: (float nofpclass(inf) [[ARG:%.*]]) #[[ATTR3]] { ; TUNIT-NEXT: [[ALLOCA:%.*]] = alloca float, align 4 ; TUNIT-NEXT: store float [[ARG]], ptr [[ALLOCA]], align 4 ; TUNIT-NEXT: [[RET:%.*]] = call float @returned_load(ptr noalias nocapture nofree noundef nonnull readonly align 4 dereferenceable(4) [[ALLOCA]]) #[[ATTR21:[0-9]+]] ; TUNIT-NEXT: ret float [[RET]] ; ; CGSCC: Function Attrs: mustprogress nofree nosync nounwind willreturn memory(none) ; CGSCC-LABEL: define float @pass_nofpclass_inf_through_memory ; CGSCC-SAME: (float nofpclass(inf) [[ARG:%.*]]) #[[ATTR4]] { ; CGSCC-NEXT: [[ALLOCA:%.*]] = alloca float, align 4 ; CGSCC-NEXT: store float [[ARG]], ptr [[ALLOCA]], align 4 ; CGSCC-NEXT: [[RET:%.*]] = call float @returned_load(ptr noalias nocapture nofree noundef nonnull readonly align 4 dereferenceable(4) [[ALLOCA]]) #[[ATTR21:[0-9]+]] ; CGSCC-NEXT: ret float [[RET]] ; %alloca = alloca float store float %arg, ptr %alloca %ret = call float @returned_load(ptr %alloca) ret float %ret } define float @returned_fabs(float %x) { ; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none) ; TUNIT-LABEL: define nofpclass(ninf nzero nsub nnorm) float @returned_fabs ; TUNIT-SAME: (float nofpclass(ninf nzero nsub nnorm) [[X:%.*]]) #[[ATTR3]] { ; TUNIT-NEXT: [[FABS:%.*]] = call nofpclass(ninf nzero nsub nnorm) float @llvm.fabs.f32(float nofpclass(ninf nzero nsub nnorm) [[X]]) #[[ATTR22:[0-9]+]] ; TUNIT-NEXT: ret float [[FABS]] ; ; CGSCC: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none) ; CGSCC-LABEL: define nofpclass(ninf nzero nsub nnorm) float @returned_fabs ; CGSCC-SAME: (float nofpclass(ninf nzero nsub nnorm) [[X:%.*]]) #[[ATTR3]] { ; CGSCC-NEXT: [[FABS:%.*]] = call nofpclass(ninf nzero nsub nnorm) float @llvm.fabs.f32(float nofpclass(ninf nzero nsub nnorm) [[X]]) #[[ATTR19]] ; CGSCC-NEXT: ret float [[FABS]] ; %fabs = call float @llvm.fabs.f32(float %x) ret float %fabs } define float @returned_fabs_nosnan(float nofpclass(snan) %x) { ; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none) ; TUNIT-LABEL: define nofpclass(snan ninf nzero nsub nnorm) float @returned_fabs_nosnan ; TUNIT-SAME: (float nofpclass(snan ninf nzero nsub nnorm) [[X:%.*]]) #[[ATTR3]] { ; TUNIT-NEXT: [[FABS:%.*]] = call nofpclass(snan ninf nzero nsub nnorm) float @llvm.fabs.f32(float nofpclass(snan ninf nzero nsub nnorm) [[X]]) #[[ATTR22]] ; TUNIT-NEXT: ret float [[FABS]] ; ; CGSCC: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none) ; CGSCC-LABEL: define nofpclass(snan ninf nzero nsub nnorm) float @returned_fabs_nosnan ; CGSCC-SAME: (float nofpclass(snan ninf nzero nsub nnorm) [[X:%.*]]) #[[ATTR3]] { ; CGSCC-NEXT: [[FABS:%.*]] = call nofpclass(snan ninf nzero nsub nnorm) float @llvm.fabs.f32(float nofpclass(snan ninf nzero nsub nnorm) [[X]]) #[[ATTR19]] ; CGSCC-NEXT: ret float [[FABS]] ; %fabs = call float @llvm.fabs.f32(float %x) ret float %fabs } define float @returned_fabs_noqnan(float nofpclass(qnan) %x) { ; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none) ; TUNIT-LABEL: define nofpclass(qnan ninf nzero nsub nnorm) float @returned_fabs_noqnan ; TUNIT-SAME: (float nofpclass(qnan ninf nzero nsub nnorm) [[X:%.*]]) #[[ATTR3]] { ; TUNIT-NEXT: [[FABS:%.*]] = call nofpclass(qnan ninf nzero nsub nnorm) float @llvm.fabs.f32(float nofpclass(qnan ninf nzero nsub nnorm) [[X]]) #[[ATTR22]] ; TUNIT-NEXT: ret float [[FABS]] ; ; CGSCC: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none) ; CGSCC-LABEL: define nofpclass(qnan ninf nzero nsub nnorm) float @returned_fabs_noqnan ; CGSCC-SAME: (float nofpclass(qnan ninf nzero nsub nnorm) [[X:%.*]]) #[[ATTR3]] { ; CGSCC-NEXT: [[FABS:%.*]] = call nofpclass(qnan ninf nzero nsub nnorm) float @llvm.fabs.f32(float nofpclass(qnan ninf nzero nsub nnorm) [[X]]) #[[ATTR19]] ; CGSCC-NEXT: ret float [[FABS]] ; %fabs = call float @llvm.fabs.f32(float %x) ret float %fabs } define float @returned_fabs_nonan(float nofpclass(nan) %x) { ; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none) ; TUNIT-LABEL: define nofpclass(nan ninf nzero nsub nnorm) float @returned_fabs_nonan ; TUNIT-SAME: (float nofpclass(nan ninf nzero nsub nnorm) [[X:%.*]]) #[[ATTR3]] { ; TUNIT-NEXT: [[FABS:%.*]] = call nofpclass(nan ninf nzero nsub nnorm) float @llvm.fabs.f32(float nofpclass(nan ninf nzero nsub nnorm) [[X]]) #[[ATTR22]] ; TUNIT-NEXT: ret float [[FABS]] ; ; CGSCC: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none) ; CGSCC-LABEL: define nofpclass(nan ninf nzero nsub nnorm) float @returned_fabs_nonan ; CGSCC-SAME: (float nofpclass(nan ninf nzero nsub nnorm) [[X:%.*]]) #[[ATTR3]] { ; CGSCC-NEXT: [[FABS:%.*]] = call nofpclass(nan ninf nzero nsub nnorm) float @llvm.fabs.f32(float nofpclass(nan ninf nzero nsub nnorm) [[X]]) #[[ATTR19]] ; CGSCC-NEXT: ret float [[FABS]] ; %fabs = call float @llvm.fabs.f32(float %x) ret float %fabs } define float @returned_fabs_noinf(float nofpclass(inf) %x) { ; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none) ; TUNIT-LABEL: define nofpclass(inf nzero nsub nnorm) float @returned_fabs_noinf ; TUNIT-SAME: (float nofpclass(inf nzero nsub nnorm) [[X:%.*]]) #[[ATTR3]] { ; TUNIT-NEXT: [[FABS:%.*]] = call nofpclass(inf nzero nsub nnorm) float @llvm.fabs.f32(float nofpclass(inf nzero nsub nnorm) [[X]]) #[[ATTR22]] ; TUNIT-NEXT: ret float [[FABS]] ; ; CGSCC: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none) ; CGSCC-LABEL: define nofpclass(inf nzero nsub nnorm) float @returned_fabs_noinf ; CGSCC-SAME: (float nofpclass(inf nzero nsub nnorm) [[X:%.*]]) #[[ATTR3]] { ; CGSCC-NEXT: [[FABS:%.*]] = call nofpclass(inf nzero nsub nnorm) float @llvm.fabs.f32(float nofpclass(inf nzero nsub nnorm) [[X]]) #[[ATTR19]] ; CGSCC-NEXT: ret float [[FABS]] ; %fabs = call float @llvm.fabs.f32(float %x) ret float %fabs } define float @returned_fabs_nopos(float nofpclass(psub pnorm pinf) %x) { ; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none) ; TUNIT-LABEL: define nofpclass(ninf nzero nsub nnorm) float @returned_fabs_nopos ; TUNIT-SAME: (float nofpclass(inf nzero sub norm) [[X:%.*]]) #[[ATTR3]] { ; TUNIT-NEXT: [[FABS:%.*]] = call nofpclass(ninf nzero nsub nnorm) float @llvm.fabs.f32(float nofpclass(inf nzero sub norm) [[X]]) #[[ATTR22]] ; TUNIT-NEXT: ret float [[FABS]] ; ; CGSCC: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none) ; CGSCC-LABEL: define nofpclass(ninf nzero nsub nnorm) float @returned_fabs_nopos ; CGSCC-SAME: (float nofpclass(inf nzero sub norm) [[X:%.*]]) #[[ATTR3]] { ; CGSCC-NEXT: [[FABS:%.*]] = call nofpclass(ninf nzero nsub nnorm) float @llvm.fabs.f32(float nofpclass(inf nzero sub norm) [[X]]) #[[ATTR19]] ; CGSCC-NEXT: ret float [[FABS]] ; %fabs = call float @llvm.fabs.f32(float %x) ret float %fabs } define float @returned_fabs_nopos_nopzero(float nofpclass(psub pnorm pinf pzero) %x) { ; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none) ; TUNIT-LABEL: define nofpclass(ninf nzero nsub nnorm) float @returned_fabs_nopos_nopzero ; TUNIT-SAME: (float nofpclass(inf zero sub norm) [[X:%.*]]) #[[ATTR3]] { ; TUNIT-NEXT: [[FABS:%.*]] = call nofpclass(ninf nzero nsub nnorm) float @llvm.fabs.f32(float nofpclass(inf zero sub norm) [[X]]) #[[ATTR22]] ; TUNIT-NEXT: ret float [[FABS]] ; ; CGSCC: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none) ; CGSCC-LABEL: define nofpclass(ninf nzero nsub nnorm) float @returned_fabs_nopos_nopzero ; CGSCC-SAME: (float nofpclass(inf zero sub norm) [[X:%.*]]) #[[ATTR3]] { ; CGSCC-NEXT: [[FABS:%.*]] = call nofpclass(ninf nzero nsub nnorm) float @llvm.fabs.f32(float nofpclass(inf zero sub norm) [[X]]) #[[ATTR19]] ; CGSCC-NEXT: ret float [[FABS]] ; %fabs = call float @llvm.fabs.f32(float %x) ret float %fabs } define float @returned_fabs_nopos_nozero(float nofpclass(psub pnorm pinf zero) %x) { ; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none) ; TUNIT-LABEL: define nofpclass(ninf zero nsub nnorm) float @returned_fabs_nopos_nozero ; TUNIT-SAME: (float nofpclass(inf zero sub norm) [[X:%.*]]) #[[ATTR3]] { ; TUNIT-NEXT: [[FABS:%.*]] = call nofpclass(ninf zero nsub nnorm) float @llvm.fabs.f32(float nofpclass(inf zero sub norm) [[X]]) #[[ATTR22]] ; TUNIT-NEXT: ret float [[FABS]] ; ; CGSCC: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none) ; CGSCC-LABEL: define nofpclass(ninf zero nsub nnorm) float @returned_fabs_nopos_nozero ; CGSCC-SAME: (float nofpclass(inf zero sub norm) [[X:%.*]]) #[[ATTR3]] { ; CGSCC-NEXT: [[FABS:%.*]] = call nofpclass(ninf zero nsub nnorm) float @llvm.fabs.f32(float nofpclass(inf zero sub norm) [[X]]) #[[ATTR19]] ; CGSCC-NEXT: ret float [[FABS]] ; %fabs = call float @llvm.fabs.f32(float %x) ret float %fabs } define float @returned_fabs_nopos_nonan(float nofpclass(psub pnorm pinf nan) %x) { ; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none) ; TUNIT-LABEL: define nofpclass(nan ninf nzero nsub nnorm) float @returned_fabs_nopos_nonan ; TUNIT-SAME: (float nofpclass(nan inf nzero sub norm) [[X:%.*]]) #[[ATTR3]] { ; TUNIT-NEXT: [[FABS:%.*]] = call nofpclass(nan ninf nzero nsub nnorm) float @llvm.fabs.f32(float nofpclass(nan inf nzero sub norm) [[X]]) #[[ATTR22]] ; TUNIT-NEXT: ret float [[FABS]] ; ; CGSCC: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none) ; CGSCC-LABEL: define nofpclass(nan ninf nzero nsub nnorm) float @returned_fabs_nopos_nonan ; CGSCC-SAME: (float nofpclass(nan inf nzero sub norm) [[X:%.*]]) #[[ATTR3]] { ; CGSCC-NEXT: [[FABS:%.*]] = call nofpclass(nan ninf nzero nsub nnorm) float @llvm.fabs.f32(float nofpclass(nan inf nzero sub norm) [[X]]) #[[ATTR19]] ; CGSCC-NEXT: ret float [[FABS]] ; %fabs = call float @llvm.fabs.f32(float %x) ret float %fabs } define float @returned_fabs_noneg(float nofpclass(nsub nnorm ninf) %x) { ; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none) ; TUNIT-LABEL: define nofpclass(ninf nzero nsub nnorm) float @returned_fabs_noneg ; TUNIT-SAME: (float nofpclass(ninf nzero nsub nnorm) [[X:%.*]]) #[[ATTR3]] { ; TUNIT-NEXT: [[FABS:%.*]] = call nofpclass(ninf nzero nsub nnorm) float @llvm.fabs.f32(float nofpclass(ninf nzero nsub nnorm) [[X]]) #[[ATTR22]] ; TUNIT-NEXT: ret float [[FABS]] ; ; CGSCC: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none) ; CGSCC-LABEL: define nofpclass(ninf nzero nsub nnorm) float @returned_fabs_noneg ; CGSCC-SAME: (float nofpclass(ninf nzero nsub nnorm) [[X:%.*]]) #[[ATTR3]] { ; CGSCC-NEXT: [[FABS:%.*]] = call nofpclass(ninf nzero nsub nnorm) float @llvm.fabs.f32(float nofpclass(ninf nzero nsub nnorm) [[X]]) #[[ATTR19]] ; CGSCC-NEXT: ret float [[FABS]] ; %fabs = call float @llvm.fabs.f32(float %x) ret float %fabs } define float @returned_fabs_noneg_nonzero(float nofpclass(nsub nnorm ninf nzero) %x) { ; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none) ; TUNIT-LABEL: define nofpclass(ninf nzero nsub nnorm) float @returned_fabs_noneg_nonzero ; TUNIT-SAME: (float nofpclass(ninf nzero nsub nnorm) [[X:%.*]]) #[[ATTR3]] { ; TUNIT-NEXT: [[FABS:%.*]] = call nofpclass(ninf nzero nsub nnorm) float @llvm.fabs.f32(float nofpclass(ninf nzero nsub nnorm) [[X]]) #[[ATTR22]] ; TUNIT-NEXT: ret float [[FABS]] ; ; CGSCC: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none) ; CGSCC-LABEL: define nofpclass(ninf nzero nsub nnorm) float @returned_fabs_noneg_nonzero ; CGSCC-SAME: (float nofpclass(ninf nzero nsub nnorm) [[X:%.*]]) #[[ATTR3]] { ; CGSCC-NEXT: [[FABS:%.*]] = call nofpclass(ninf nzero nsub nnorm) float @llvm.fabs.f32(float nofpclass(ninf nzero nsub nnorm) [[X]]) #[[ATTR19]] ; CGSCC-NEXT: ret float [[FABS]] ; %fabs = call float @llvm.fabs.f32(float %x) ret float %fabs } define float @returned_fabs_noneg_nozero(float nofpclass(nsub nnorm ninf zero) %x) { ; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none) ; TUNIT-LABEL: define nofpclass(ninf zero nsub nnorm) float @returned_fabs_noneg_nozero ; TUNIT-SAME: (float nofpclass(ninf zero nsub nnorm) [[X:%.*]]) #[[ATTR3]] { ; TUNIT-NEXT: [[FABS:%.*]] = call nofpclass(ninf zero nsub nnorm) float @llvm.fabs.f32(float nofpclass(ninf zero nsub nnorm) [[X]]) #[[ATTR22]] ; TUNIT-NEXT: ret float [[FABS]] ; ; CGSCC: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none) ; CGSCC-LABEL: define nofpclass(ninf zero nsub nnorm) float @returned_fabs_noneg_nozero ; CGSCC-SAME: (float nofpclass(ninf zero nsub nnorm) [[X:%.*]]) #[[ATTR3]] { ; CGSCC-NEXT: [[FABS:%.*]] = call nofpclass(ninf zero nsub nnorm) float @llvm.fabs.f32(float nofpclass(ninf zero nsub nnorm) [[X]]) #[[ATTR19]] ; CGSCC-NEXT: ret float [[FABS]] ; %fabs = call float @llvm.fabs.f32(float %x) ret float %fabs } define float @returned_fabs_noneg_nonan(float nofpclass(nsub nnorm ninf nan) %x) { ; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none) ; TUNIT-LABEL: define nofpclass(nan ninf nzero nsub nnorm) float @returned_fabs_noneg_nonan ; TUNIT-SAME: (float nofpclass(nan ninf nzero nsub nnorm) [[X:%.*]]) #[[ATTR3]] { ; TUNIT-NEXT: [[FABS:%.*]] = call nofpclass(nan ninf nzero nsub nnorm) float @llvm.fabs.f32(float nofpclass(nan ninf nzero nsub nnorm) [[X]]) #[[ATTR22]] ; TUNIT-NEXT: ret float [[FABS]] ; ; CGSCC: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none) ; CGSCC-LABEL: define nofpclass(nan ninf nzero nsub nnorm) float @returned_fabs_noneg_nonan ; CGSCC-SAME: (float nofpclass(nan ninf nzero nsub nnorm) [[X:%.*]]) #[[ATTR3]] { ; CGSCC-NEXT: [[FABS:%.*]] = call nofpclass(nan ninf nzero nsub nnorm) float @llvm.fabs.f32(float nofpclass(nan ninf nzero nsub nnorm) [[X]]) #[[ATTR19]] ; CGSCC-NEXT: ret float [[FABS]] ; %fabs = call float @llvm.fabs.f32(float %x) ret float %fabs } define float @returned_fabs_nonsub_nopnorm_nonzero(float nofpclass(nsub pnorm nzero) %x) { ; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none) ; TUNIT-LABEL: define nofpclass(ninf nzero nsub nnorm) float @returned_fabs_nonsub_nopnorm_nonzero ; TUNIT-SAME: (float nofpclass(ninf nzero nsub norm) [[X:%.*]]) #[[ATTR3]] { ; TUNIT-NEXT: [[FABS:%.*]] = call nofpclass(ninf nzero nsub nnorm) float @llvm.fabs.f32(float nofpclass(ninf nzero nsub norm) [[X]]) #[[ATTR22]] ; TUNIT-NEXT: ret float [[FABS]] ; ; CGSCC: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none) ; CGSCC-LABEL: define nofpclass(ninf nzero nsub nnorm) float @returned_fabs_nonsub_nopnorm_nonzero ; CGSCC-SAME: (float nofpclass(ninf nzero nsub norm) [[X:%.*]]) #[[ATTR3]] { ; CGSCC-NEXT: [[FABS:%.*]] = call nofpclass(ninf nzero nsub nnorm) float @llvm.fabs.f32(float nofpclass(ninf nzero nsub norm) [[X]]) #[[ATTR19]] ; CGSCC-NEXT: ret float [[FABS]] ; %fabs = call float @llvm.fabs.f32(float %x) ret float %fabs } define float @returned_fabs_nopsub_nonnorm_nopzero(float nofpclass(psub nnorm pzero) %x) { ; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none) ; TUNIT-LABEL: define nofpclass(ninf nzero nsub nnorm) float @returned_fabs_nopsub_nonnorm_nopzero ; TUNIT-SAME: (float nofpclass(ninf zero sub nnorm) [[X:%.*]]) #[[ATTR3]] { ; TUNIT-NEXT: [[FABS:%.*]] = call nofpclass(ninf nzero nsub nnorm) float @llvm.fabs.f32(float nofpclass(ninf zero sub nnorm) [[X]]) #[[ATTR22]] ; TUNIT-NEXT: ret float [[FABS]] ; ; CGSCC: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none) ; CGSCC-LABEL: define nofpclass(ninf nzero nsub nnorm) float @returned_fabs_nopsub_nonnorm_nopzero ; CGSCC-SAME: (float nofpclass(ninf zero sub nnorm) [[X:%.*]]) #[[ATTR3]] { ; CGSCC-NEXT: [[FABS:%.*]] = call nofpclass(ninf nzero nsub nnorm) float @llvm.fabs.f32(float nofpclass(ninf zero sub nnorm) [[X]]) #[[ATTR19]] ; CGSCC-NEXT: ret float [[FABS]] ; %fabs = call float @llvm.fabs.f32(float %x) ret float %fabs } define float @returned_fabs_nonnorm_nozero(float nofpclass(nnorm nzero) %x) { ; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none) ; TUNIT-LABEL: define nofpclass(ninf nzero nsub nnorm) float @returned_fabs_nonnorm_nozero ; TUNIT-SAME: (float nofpclass(ninf nzero nsub nnorm) [[X:%.*]]) #[[ATTR3]] { ; TUNIT-NEXT: [[FABS:%.*]] = call nofpclass(ninf nzero nsub nnorm) float @llvm.fabs.f32(float nofpclass(ninf nzero nsub nnorm) [[X]]) #[[ATTR22]] ; TUNIT-NEXT: ret float [[FABS]] ; ; CGSCC: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none) ; CGSCC-LABEL: define nofpclass(ninf nzero nsub nnorm) float @returned_fabs_nonnorm_nozero ; CGSCC-SAME: (float nofpclass(ninf nzero nsub nnorm) [[X:%.*]]) #[[ATTR3]] { ; CGSCC-NEXT: [[FABS:%.*]] = call nofpclass(ninf nzero nsub nnorm) float @llvm.fabs.f32(float nofpclass(ninf nzero nsub nnorm) [[X]]) #[[ATTR19]] ; CGSCC-NEXT: ret float [[FABS]] ; %fabs = call float @llvm.fabs.f32(float %x) ret float %fabs } define float @returned_fneg(float %x) { ; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none) ; CHECK-LABEL: define float @returned_fneg ; CHECK-SAME: (float [[X:%.*]]) #[[ATTR3]] { ; CHECK-NEXT: [[FNEG:%.*]] = fneg float [[X]] ; CHECK-NEXT: ret float [[FNEG]] ; %fneg = fneg float %x ret float %fneg } define float @returned_fneg_nosnan(float nofpclass(snan) %x) { ; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none) ; CHECK-LABEL: define nofpclass(snan) float @returned_fneg_nosnan ; CHECK-SAME: (float nofpclass(snan) [[X:%.*]]) #[[ATTR3]] { ; CHECK-NEXT: [[FNEG:%.*]] = fneg float [[X]] ; CHECK-NEXT: ret float [[FNEG]] ; %fneg = fneg float %x ret float %fneg } define float @returned_fneg_noqnan(float nofpclass(qnan) %x) { ; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none) ; CHECK-LABEL: define nofpclass(qnan) float @returned_fneg_noqnan ; CHECK-SAME: (float nofpclass(qnan) [[X:%.*]]) #[[ATTR3]] { ; CHECK-NEXT: [[FNEG:%.*]] = fneg float [[X]] ; CHECK-NEXT: ret float [[FNEG]] ; %fneg = fneg float %x ret float %fneg } define float @returned_fneg_nosnan_ninf_flag(float nofpclass(snan) %x) { ; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none) ; CHECK-LABEL: define nofpclass(snan inf) float @returned_fneg_nosnan_ninf_flag ; CHECK-SAME: (float nofpclass(snan inf) [[X:%.*]]) #[[ATTR3]] { ; CHECK-NEXT: [[FNEG:%.*]] = fneg ninf float [[X]] ; CHECK-NEXT: ret float [[FNEG]] ; %fneg = fneg ninf float %x ret float %fneg } define float @returned_fneg_nonan(float nofpclass(nan) %x) { ; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none) ; CHECK-LABEL: define nofpclass(nan) float @returned_fneg_nonan ; CHECK-SAME: (float nofpclass(nan) [[X:%.*]]) #[[ATTR3]] { ; CHECK-NEXT: [[FNEG:%.*]] = fneg float [[X]] ; CHECK-NEXT: ret float [[FNEG]] ; %fneg = fneg float %x ret float %fneg } define float @returned_fneg_noinf(float nofpclass(inf) %x) { ; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none) ; CHECK-LABEL: define nofpclass(inf) float @returned_fneg_noinf ; CHECK-SAME: (float nofpclass(inf) [[X:%.*]]) #[[ATTR3]] { ; CHECK-NEXT: [[FNEG:%.*]] = fneg float [[X]] ; CHECK-NEXT: ret float [[FNEG]] ; %fneg = fneg float %x ret float %fneg } define float @returned_fneg_noneg(float nofpclass(ninf nsub nnorm nzero) %x) { ; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none) ; CHECK-LABEL: define nofpclass(pinf pzero psub pnorm) float @returned_fneg_noneg ; CHECK-SAME: (float nofpclass(inf zero sub norm) [[X:%.*]]) #[[ATTR3]] { ; CHECK-NEXT: [[FNEG:%.*]] = fneg float [[X]] ; CHECK-NEXT: ret float [[FNEG]] ; %fneg = fneg float %x ret float %fneg } define float @returned_fneg_noneg_nnan_flag(float nofpclass(ninf nsub nnorm nzero) %x) { ; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none) ; CHECK-LABEL: define nofpclass(nan pinf pzero psub pnorm) float @returned_fneg_noneg_nnan_flag ; CHECK-SAME: (float nofpclass(all) [[X:%.*]]) #[[ATTR3]] { ; CHECK-NEXT: [[FNEG:%.*]] = fneg nnan float [[X]] ; CHECK-NEXT: ret float [[FNEG]] ; %fneg = fneg nnan float %x ret float %fneg } define float @returned_fneg_nonsubnnorm(float nofpclass(nsub nnorm) %x) { ; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none) ; CHECK-LABEL: define nofpclass(psub pnorm) float @returned_fneg_nonsubnnorm ; CHECK-SAME: (float nofpclass(sub norm) [[X:%.*]]) #[[ATTR3]] { ; CHECK-NEXT: [[FNEG:%.*]] = fneg float [[X]] ; CHECK-NEXT: ret float [[FNEG]] ; %fneg = fneg float %x ret float %fneg } define float @returned_fneg_nopos(float nofpclass(pinf psub pnorm pzero) %x) { ; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none) ; CHECK-LABEL: define nofpclass(ninf nzero nsub nnorm) float @returned_fneg_nopos ; CHECK-SAME: (float nofpclass(inf zero sub norm) [[X:%.*]]) #[[ATTR3]] { ; CHECK-NEXT: [[FNEG:%.*]] = fneg float [[X]] ; CHECK-NEXT: ret float [[FNEG]] ; %fneg = fneg float %x ret float %fneg } define float @returned_fneg_nopnormpsub(float nofpclass(psub pnorm) %x) { ; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none) ; CHECK-LABEL: define nofpclass(nsub nnorm) float @returned_fneg_nopnormpsub ; CHECK-SAME: (float nofpclass(sub norm) [[X:%.*]]) #[[ATTR3]] { ; CHECK-NEXT: [[FNEG:%.*]] = fneg float [[X]] ; CHECK-NEXT: ret float [[FNEG]] ; %fneg = fneg float %x ret float %fneg } define float @returned_fneg_mixed(float nofpclass(psub nnorm nzero qnan ninf) %x) { ; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none) ; CHECK-LABEL: define nofpclass(qnan pinf pzero nsub pnorm) float @returned_fneg_mixed ; CHECK-SAME: (float nofpclass(qnan inf zero sub norm) [[X:%.*]]) #[[ATTR3]] { ; CHECK-NEXT: [[FNEG:%.*]] = fneg float [[X]] ; CHECK-NEXT: ret float [[FNEG]] ; %fneg = fneg float %x ret float %fneg } define float @returned_fneg_fabs(float %x) { ; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none) ; TUNIT-LABEL: define nofpclass(pinf pzero psub pnorm) float @returned_fneg_fabs ; TUNIT-SAME: (float nofpclass(inf zero sub norm) [[X:%.*]]) #[[ATTR3]] { ; TUNIT-NEXT: [[FABS:%.*]] = call nofpclass(inf zero sub norm) float @llvm.fabs.f32(float nofpclass(inf zero sub norm) [[X]]) #[[ATTR22]] ; TUNIT-NEXT: [[FNEG_FABS:%.*]] = fneg float [[FABS]] ; TUNIT-NEXT: ret float [[FNEG_FABS]] ; ; CGSCC: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none) ; CGSCC-LABEL: define nofpclass(pinf pzero psub pnorm) float @returned_fneg_fabs ; CGSCC-SAME: (float nofpclass(inf zero sub norm) [[X:%.*]]) #[[ATTR3]] { ; CGSCC-NEXT: [[FABS:%.*]] = call nofpclass(inf zero sub norm) float @llvm.fabs.f32(float nofpclass(inf zero sub norm) [[X]]) #[[ATTR19]] ; CGSCC-NEXT: [[FNEG_FABS:%.*]] = fneg float [[FABS]] ; CGSCC-NEXT: ret float [[FNEG_FABS]] ; %fabs = call float @llvm.fabs.f32(float %x) %fneg.fabs = fneg float %fabs ret float %fneg.fabs } define float @returned_fneg_fabs_nosnan(float nofpclass(snan) %x) { ; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none) ; TUNIT-LABEL: define nofpclass(snan pinf pzero psub pnorm) float @returned_fneg_fabs_nosnan ; TUNIT-SAME: (float nofpclass(snan inf zero sub norm) [[X:%.*]]) #[[ATTR3]] { ; TUNIT-NEXT: [[FABS:%.*]] = call nofpclass(snan inf zero sub norm) float @llvm.fabs.f32(float nofpclass(snan inf zero sub norm) [[X]]) #[[ATTR22]] ; TUNIT-NEXT: [[FNEG_FABS:%.*]] = fneg float [[FABS]] ; TUNIT-NEXT: ret float [[FNEG_FABS]] ; ; CGSCC: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none) ; CGSCC-LABEL: define nofpclass(snan pinf pzero psub pnorm) float @returned_fneg_fabs_nosnan ; CGSCC-SAME: (float nofpclass(snan inf zero sub norm) [[X:%.*]]) #[[ATTR3]] { ; CGSCC-NEXT: [[FABS:%.*]] = call nofpclass(snan inf zero sub norm) float @llvm.fabs.f32(float nofpclass(snan inf zero sub norm) [[X]]) #[[ATTR19]] ; CGSCC-NEXT: [[FNEG_FABS:%.*]] = fneg float [[FABS]] ; CGSCC-NEXT: ret float [[FNEG_FABS]] ; %fabs = call float @llvm.fabs.f32(float %x) %fneg.fabs = fneg float %fabs ret float %fneg.fabs } define float @returned_fneg_fabs_noqnan(float nofpclass(qnan) %x) { ; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none) ; TUNIT-LABEL: define nofpclass(qnan pinf pzero psub pnorm) float @returned_fneg_fabs_noqnan ; TUNIT-SAME: (float nofpclass(qnan inf zero sub norm) [[X:%.*]]) #[[ATTR3]] { ; TUNIT-NEXT: [[FABS:%.*]] = call nofpclass(qnan inf zero sub norm) float @llvm.fabs.f32(float nofpclass(qnan inf zero sub norm) [[X]]) #[[ATTR22]] ; TUNIT-NEXT: [[FNEG_FABS:%.*]] = fneg float [[FABS]] ; TUNIT-NEXT: ret float [[FNEG_FABS]] ; ; CGSCC: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none) ; CGSCC-LABEL: define nofpclass(qnan pinf pzero psub pnorm) float @returned_fneg_fabs_noqnan ; CGSCC-SAME: (float nofpclass(qnan inf zero sub norm) [[X:%.*]]) #[[ATTR3]] { ; CGSCC-NEXT: [[FABS:%.*]] = call nofpclass(qnan inf zero sub norm) float @llvm.fabs.f32(float nofpclass(qnan inf zero sub norm) [[X]]) #[[ATTR19]] ; CGSCC-NEXT: [[FNEG_FABS:%.*]] = fneg float [[FABS]] ; CGSCC-NEXT: ret float [[FNEG_FABS]] ; %fabs = call float @llvm.fabs.f32(float %x) %fneg.fabs = fneg float %fabs ret float %fneg.fabs } define float @returned_fneg_fabs_nonan(float nofpclass(nan) %x) { ; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none) ; TUNIT-LABEL: define nofpclass(nan pinf pzero psub pnorm) float @returned_fneg_fabs_nonan ; TUNIT-SAME: (float nofpclass(all) [[X:%.*]]) #[[ATTR3]] { ; TUNIT-NEXT: [[FABS:%.*]] = call float @llvm.fabs.f32(float nofpclass(all) [[X]]) #[[ATTR22]] ; TUNIT-NEXT: [[FNEG_FABS:%.*]] = fneg float [[FABS]] ; TUNIT-NEXT: ret float [[FNEG_FABS]] ; ; CGSCC: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none) ; CGSCC-LABEL: define nofpclass(nan pinf pzero psub pnorm) float @returned_fneg_fabs_nonan ; CGSCC-SAME: (float nofpclass(all) [[X:%.*]]) #[[ATTR3]] { ; CGSCC-NEXT: [[FABS:%.*]] = call float @llvm.fabs.f32(float nofpclass(all) [[X]]) #[[ATTR19]] ; CGSCC-NEXT: [[FNEG_FABS:%.*]] = fneg float [[FABS]] ; CGSCC-NEXT: ret float [[FNEG_FABS]] ; %fabs = call float @llvm.fabs.f32(float %x) %fneg.fabs = fneg float %fabs ret float %fneg.fabs } define float @returned_fneg_fabs_noneg(float nofpclass(ninf nsub nnorm nzero) %x) { ; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none) ; TUNIT-LABEL: define nofpclass(pinf pzero psub pnorm) float @returned_fneg_fabs_noneg ; TUNIT-SAME: (float nofpclass(inf zero sub norm) [[X:%.*]]) #[[ATTR3]] { ; TUNIT-NEXT: [[FABS:%.*]] = call nofpclass(inf zero sub norm) float @llvm.fabs.f32(float nofpclass(inf zero sub norm) [[X]]) #[[ATTR22]] ; TUNIT-NEXT: [[FNEG_FABS:%.*]] = fneg float [[FABS]] ; TUNIT-NEXT: ret float [[FNEG_FABS]] ; ; CGSCC: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none) ; CGSCC-LABEL: define nofpclass(pinf pzero psub pnorm) float @returned_fneg_fabs_noneg ; CGSCC-SAME: (float nofpclass(inf zero sub norm) [[X:%.*]]) #[[ATTR3]] { ; CGSCC-NEXT: [[FABS:%.*]] = call nofpclass(inf zero sub norm) float @llvm.fabs.f32(float nofpclass(inf zero sub norm) [[X]]) #[[ATTR19]] ; CGSCC-NEXT: [[FNEG_FABS:%.*]] = fneg float [[FABS]] ; CGSCC-NEXT: ret float [[FNEG_FABS]] ; %fabs = call float @llvm.fabs.f32(float %x) %fneg.fabs = fneg float %fabs ret float %fneg.fabs } define float @returned_fneg_fabs_nopos(float nofpclass(pinf psub pnorm pzero) %x) { ; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none) ; TUNIT-LABEL: define nofpclass(pinf pzero psub pnorm) float @returned_fneg_fabs_nopos ; TUNIT-SAME: (float nofpclass(inf zero sub norm) [[X:%.*]]) #[[ATTR3]] { ; TUNIT-NEXT: [[FABS:%.*]] = call nofpclass(inf zero sub norm) float @llvm.fabs.f32(float nofpclass(inf zero sub norm) [[X]]) #[[ATTR22]] ; TUNIT-NEXT: [[FNEG_FABS:%.*]] = fneg float [[FABS]] ; TUNIT-NEXT: ret float [[FNEG_FABS]] ; ; CGSCC: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none) ; CGSCC-LABEL: define nofpclass(pinf pzero psub pnorm) float @returned_fneg_fabs_nopos ; CGSCC-SAME: (float nofpclass(inf zero sub norm) [[X:%.*]]) #[[ATTR3]] { ; CGSCC-NEXT: [[FABS:%.*]] = call nofpclass(inf zero sub norm) float @llvm.fabs.f32(float nofpclass(inf zero sub norm) [[X]]) #[[ATTR19]] ; CGSCC-NEXT: [[FNEG_FABS:%.*]] = fneg float [[FABS]] ; CGSCC-NEXT: ret float [[FNEG_FABS]] ; %fabs = call float @llvm.fabs.f32(float %x) %fneg.fabs = fneg float %fabs ret float %fneg.fabs } define float @returned_fneg_fabs_mixed(float nofpclass(psub nnorm nzero qnan ninf) %x) { ; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none) ; TUNIT-LABEL: define nofpclass(qnan pinf pzero psub pnorm) float @returned_fneg_fabs_mixed ; TUNIT-SAME: (float nofpclass(qnan inf zero sub norm) [[X:%.*]]) #[[ATTR3]] { ; TUNIT-NEXT: [[FABS:%.*]] = call nofpclass(qnan inf zero sub norm) float @llvm.fabs.f32(float nofpclass(qnan inf zero sub norm) [[X]]) #[[ATTR22]] ; TUNIT-NEXT: [[FNEG_FABS:%.*]] = fneg float [[FABS]] ; TUNIT-NEXT: ret float [[FNEG_FABS]] ; ; CGSCC: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none) ; CGSCC-LABEL: define nofpclass(qnan pinf pzero psub pnorm) float @returned_fneg_fabs_mixed ; CGSCC-SAME: (float nofpclass(qnan inf zero sub norm) [[X:%.*]]) #[[ATTR3]] { ; CGSCC-NEXT: [[FABS:%.*]] = call nofpclass(qnan inf zero sub norm) float @llvm.fabs.f32(float nofpclass(qnan inf zero sub norm) [[X]]) #[[ATTR19]] ; CGSCC-NEXT: [[FNEG_FABS:%.*]] = fneg float [[FABS]] ; CGSCC-NEXT: ret float [[FNEG_FABS]] ; %fabs = call float @llvm.fabs.f32(float %x) %fneg.fabs = fneg float %fabs ret float %fneg.fabs } define float @returned_fneg_fabs_ninf_flag_fabs(float %x) { ; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none) ; TUNIT-LABEL: define nofpclass(inf pzero psub pnorm) float @returned_fneg_fabs_ninf_flag_fabs ; TUNIT-SAME: (float nofpclass(inf zero sub norm) [[X:%.*]]) #[[ATTR3]] { ; TUNIT-NEXT: [[FABS:%.*]] = call ninf nofpclass(inf zero sub norm) float @llvm.fabs.f32(float nofpclass(inf zero sub norm) [[X]]) #[[ATTR22]] ; TUNIT-NEXT: [[FNEG_FABS:%.*]] = fneg float [[FABS]] ; TUNIT-NEXT: ret float [[FNEG_FABS]] ; ; CGSCC: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none) ; CGSCC-LABEL: define nofpclass(inf pzero psub pnorm) float @returned_fneg_fabs_ninf_flag_fabs ; CGSCC-SAME: (float nofpclass(inf zero sub norm) [[X:%.*]]) #[[ATTR3]] { ; CGSCC-NEXT: [[FABS:%.*]] = call ninf nofpclass(inf zero sub norm) float @llvm.fabs.f32(float nofpclass(inf zero sub norm) [[X]]) #[[ATTR19]] ; CGSCC-NEXT: [[FNEG_FABS:%.*]] = fneg float [[FABS]] ; CGSCC-NEXT: ret float [[FNEG_FABS]] ; %fabs = call ninf float @llvm.fabs.f32(float %x) %fneg.fabs = fneg float %fabs ret float %fneg.fabs } define float @returned_fneg_fabs_ninf_flag_fneg(float %x) { ; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none) ; TUNIT-LABEL: define nofpclass(inf pzero psub pnorm) float @returned_fneg_fabs_ninf_flag_fneg ; TUNIT-SAME: (float nofpclass(inf zero sub norm) [[X:%.*]]) #[[ATTR3]] { ; TUNIT-NEXT: [[FABS:%.*]] = call nofpclass(inf zero sub norm) float @llvm.fabs.f32(float nofpclass(inf zero sub norm) [[X]]) #[[ATTR22]] ; TUNIT-NEXT: [[FNEG_FABS:%.*]] = fneg ninf float [[FABS]] ; TUNIT-NEXT: ret float [[FNEG_FABS]] ; ; CGSCC: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none) ; CGSCC-LABEL: define nofpclass(inf pzero psub pnorm) float @returned_fneg_fabs_ninf_flag_fneg ; CGSCC-SAME: (float nofpclass(inf zero sub norm) [[X:%.*]]) #[[ATTR3]] { ; CGSCC-NEXT: [[FABS:%.*]] = call nofpclass(inf zero sub norm) float @llvm.fabs.f32(float nofpclass(inf zero sub norm) [[X]]) #[[ATTR19]] ; CGSCC-NEXT: [[FNEG_FABS:%.*]] = fneg ninf float [[FABS]] ; CGSCC-NEXT: ret float [[FNEG_FABS]] ; %fabs = call float @llvm.fabs.f32(float %x) %fneg.fabs = fneg ninf float %fabs ret float %fneg.fabs } define float @uitofp_i32_to_f32(i32 %arg) { ; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none) ; CHECK-LABEL: define nofpclass(nan inf nzero sub nnorm) float @uitofp_i32_to_f32 ; CHECK-SAME: (i32 [[ARG:%.*]]) #[[ATTR3]] { ; CHECK-NEXT: [[CVT:%.*]] = uitofp i32 [[ARG]] to float ; CHECK-NEXT: ret float [[CVT]] ; %cvt = uitofp i32 %arg to float ret float %cvt } define float @sitofp_i32_to_f32(i32 %arg) { ; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none) ; CHECK-LABEL: define nofpclass(nan inf nzero sub) float @sitofp_i32_to_f32 ; CHECK-SAME: (i32 [[ARG:%.*]]) #[[ATTR3]] { ; CHECK-NEXT: [[CVT:%.*]] = sitofp i32 [[ARG]] to float ; CHECK-NEXT: ret float [[CVT]] ; %cvt = sitofp i32 %arg to float ret float %cvt } define <2 x float> @uitofp_v2i32_to_v2f32(<2 x i32> %arg) { ; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none) ; CHECK-LABEL: define nofpclass(nan inf nzero sub nnorm) <2 x float> @uitofp_v2i32_to_v2f32 ; CHECK-SAME: (<2 x i32> [[ARG:%.*]]) #[[ATTR3]] { ; CHECK-NEXT: [[CVT:%.*]] = uitofp <2 x i32> [[ARG]] to <2 x float> ; CHECK-NEXT: ret <2 x float> [[CVT]] ; %cvt = uitofp <2 x i32> %arg to <2 x float> ret <2 x float> %cvt } define <2 x float> @sitofp_v2i32_to_v2i32(<2 x i32> %arg) { ; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none) ; CHECK-LABEL: define nofpclass(nan inf nzero sub) <2 x float> @sitofp_v2i32_to_v2i32 ; CHECK-SAME: (<2 x i32> [[ARG:%.*]]) #[[ATTR3]] { ; CHECK-NEXT: [[CVT:%.*]] = sitofp <2 x i32> [[ARG]] to <2 x float> ; CHECK-NEXT: ret <2 x float> [[CVT]] ; %cvt = sitofp <2 x i32> %arg to <2 x float> ret <2 x float> %cvt } define half @uitofp_i17_to_f16(i17 %arg) { ; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none) ; CHECK-LABEL: define nofpclass(nan ninf nzero sub nnorm) half @uitofp_i17_to_f16 ; CHECK-SAME: (i17 [[ARG:%.*]]) #[[ATTR3]] { ; CHECK-NEXT: [[CVT:%.*]] = uitofp i17 [[ARG]] to half ; CHECK-NEXT: ret half [[CVT]] ; %cvt = uitofp i17 %arg to half ret half %cvt } define half @sitofp_i17_to_f16(i17 %arg) { ; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none) ; CHECK-LABEL: define nofpclass(nan nzero sub) half @sitofp_i17_to_f16 ; CHECK-SAME: (i17 [[ARG:%.*]]) #[[ATTR3]] { ; CHECK-NEXT: [[CVT:%.*]] = sitofp i17 [[ARG]] to half ; CHECK-NEXT: ret half [[CVT]] ; %cvt = sitofp i17 %arg to half ret half %cvt } define <2 x half> @uitofp_v2i17_to_v2f16(<2 x i17> %arg) { ; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none) ; CHECK-LABEL: define nofpclass(nan ninf nzero sub nnorm) <2 x half> @uitofp_v2i17_to_v2f16 ; CHECK-SAME: (<2 x i17> [[ARG:%.*]]) #[[ATTR3]] { ; CHECK-NEXT: [[CVT:%.*]] = uitofp <2 x i17> [[ARG]] to <2 x half> ; CHECK-NEXT: ret <2 x half> [[CVT]] ; %cvt = uitofp <2 x i17> %arg to <2 x half> ret <2 x half> %cvt } define <2 x half> @sitofp_v2i17_to_v2i17(<2 x i17> %arg) { ; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none) ; CHECK-LABEL: define nofpclass(nan nzero sub) <2 x half> @sitofp_v2i17_to_v2i17 ; CHECK-SAME: (<2 x i17> [[ARG:%.*]]) #[[ATTR3]] { ; CHECK-NEXT: [[CVT:%.*]] = sitofp <2 x i17> [[ARG]] to <2 x half> ; CHECK-NEXT: ret <2 x half> [[CVT]] ; %cvt = sitofp <2 x i17> %arg to <2 x half> ret <2 x half> %cvt } define float @assume_intersection_not_zero_and_not_nan(float %arg) { ; CHECK-LABEL: define nofpclass(nan zero) float @assume_intersection_not_zero_and_not_nan ; CHECK-SAME: (float returned nofpclass(nan zero) [[ARG:%.*]]) { ; CHECK-NEXT: entry: ; CHECK-NEXT: [[IS_NOT_ZERO_OR_NAN:%.*]] = fcmp une float [[ARG]], 0.000000e+00 ; CHECK-NEXT: call void @llvm.assume(i1 noundef [[IS_NOT_ZERO_OR_NAN]]) #[[ATTR18]] ; CHECK-NEXT: [[IS_ORD:%.*]] = fcmp ord float [[ARG]], 0.000000e+00 ; CHECK-NEXT: call void @llvm.assume(i1 noundef [[IS_ORD]]) #[[ATTR18]] ; CHECK-NEXT: call void @extern.use(float nofpclass(nan zero) [[ARG]]) ; CHECK-NEXT: ret float [[ARG]] ; entry: %is.not.zero.or.nan = fcmp une float %arg, 0.0 call void @llvm.assume(i1 %is.not.zero.or.nan) %is.ord = fcmp ord float %arg, 0.0 call void @llvm.assume(i1 %is.ord) call void @extern.use(float %arg) ret float %arg } define float @assume_intersection_class(float %arg) { ; CHECK-LABEL: define nofpclass(nan inf zero sub nnorm) float @assume_intersection_class ; CHECK-SAME: (float returned nofpclass(nan inf zero sub nnorm) [[ARG:%.*]]) { ; CHECK-NEXT: entry: ; CHECK-NEXT: [[POS_NORMAL_OR_POS_SUBNORMAL:%.*]] = call i1 @llvm.is.fpclass.f32(float nofpclass(nan inf zero sub nnorm) [[ARG]], i32 noundef 384) #[[ATTR20]] ; CHECK-NEXT: call void @llvm.assume(i1 noundef [[POS_NORMAL_OR_POS_SUBNORMAL]]) #[[ATTR18]] ; CHECK-NEXT: [[IS_NORMAL:%.*]] = call i1 @llvm.is.fpclass.f32(float nofpclass(nan inf zero sub nnorm) [[ARG]], i32 noundef 264) #[[ATTR20]] ; CHECK-NEXT: call void @llvm.assume(i1 noundef [[IS_NORMAL]]) #[[ATTR18]] ; CHECK-NEXT: call void @extern.use(float nofpclass(nan inf zero sub nnorm) [[ARG]]) ; CHECK-NEXT: ret float [[ARG]] ; entry: %pos.normal.or.pos.subnormal = call i1 @llvm.is.fpclass.f32(float %arg, i32 384) call void @llvm.assume(i1 %pos.normal.or.pos.subnormal) %is.normal = call i1 @llvm.is.fpclass.f32(float %arg, i32 264) call void @llvm.assume(i1 %is.normal) call void @extern.use(float %arg) ret float %arg } define float @assume_intersection_none(float %arg) { ; CHECK-LABEL: define nofpclass(all) float @assume_intersection_none ; CHECK-SAME: (float returned nofpclass(all) [[ARG:%.*]]) { ; CHECK-NEXT: entry: ; CHECK-NEXT: [[CLASS1:%.*]] = call i1 @llvm.is.fpclass.f32(float nofpclass(all) [[ARG]], i32 noundef 682) #[[ATTR20]] ; CHECK-NEXT: call void @llvm.assume(i1 noundef [[CLASS1]]) #[[ATTR18]] ; CHECK-NEXT: [[CLASS2:%.*]] = call i1 @llvm.is.fpclass.f32(float nofpclass(all) [[ARG]], i32 noundef 341) #[[ATTR20]] ; CHECK-NEXT: call void @llvm.assume(i1 noundef [[CLASS2]]) #[[ATTR18]] ; CHECK-NEXT: call void @extern.use(float nofpclass(all) [[ARG]]) ; CHECK-NEXT: ret float [[ARG]] ; entry: %class1 = call i1 @llvm.is.fpclass.f32(float %arg, i32 682) call void @llvm.assume(i1 %class1) %class2 = call i1 @llvm.is.fpclass.f32(float %arg, i32 341) call void @llvm.assume(i1 %class2) call void @extern.use(float %arg) ret float %arg } define float @returned_extractelement_dynamic_index(<4 x float> nofpclass(nan) %vec, i32 %idx) { ; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none) ; CHECK-LABEL: define nofpclass(nan) float @returned_extractelement_dynamic_index ; CHECK-SAME: (<4 x float> nofpclass(nan) [[VEC:%.*]], i32 [[IDX:%.*]]) #[[ATTR3]] { ; CHECK-NEXT: [[EXTRACT:%.*]] = extractelement <4 x float> [[VEC]], i32 [[IDX]] ; CHECK-NEXT: ret float [[EXTRACT]] ; %extract = extractelement <4 x float> %vec, i32 %idx ret float %extract } define float @returned_extractelement_index0(<4 x float> nofpclass(nan) %vec) { ; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none) ; CHECK-LABEL: define nofpclass(nan) float @returned_extractelement_index0 ; CHECK-SAME: (<4 x float> nofpclass(nan) [[VEC:%.*]]) #[[ATTR3]] { ; CHECK-NEXT: [[EXTRACT:%.*]] = extractelement <4 x float> [[VEC]], i32 0 ; CHECK-NEXT: ret float [[EXTRACT]] ; %extract = extractelement <4 x float> %vec, i32 0 ret float %extract } define float @returned_extractelement_index_oob(<4 x float> nofpclass(nan) %vec) { ; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none) ; CHECK-LABEL: define nofpclass(nan) float @returned_extractelement_index_oob ; CHECK-SAME: (<4 x float> nofpclass(nan) [[VEC:%.*]]) #[[ATTR3]] { ; CHECK-NEXT: [[EXTRACT:%.*]] = extractelement <4 x float> [[VEC]], i32 5 ; CHECK-NEXT: ret float [[EXTRACT]] ; %extract = extractelement <4 x float> %vec, i32 5 ret float %extract } define float @returned_extractelement_scalable( nofpclass(nan) %vec) { ; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none) ; CHECK-LABEL: define float @returned_extractelement_scalable ; CHECK-SAME: ( nofpclass(nan) [[VEC:%.*]]) #[[ATTR3]] { ; CHECK-NEXT: [[EXTRACT:%.*]] = extractelement [[VEC]], i32 0 ; CHECK-NEXT: ret float [[EXTRACT]] ; %extract = extractelement %vec, i32 0 ret float %extract } define float @returned_extractvalue([4 x float] nofpclass(nan) %array) { ; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none) ; CHECK-LABEL: define nofpclass(nan) float @returned_extractvalue ; CHECK-SAME: ([4 x float] nofpclass(nan) [[ARRAY:%.*]]) #[[ATTR3]] { ; CHECK-NEXT: [[EXTRACT:%.*]] = extractvalue [4 x float] [[ARRAY]], 0 ; CHECK-NEXT: ret float [[EXTRACT]] ; %extract = extractvalue [4 x float] %array, 0 ret float %extract } define float @return_nofpclass_freeze_nan_arg(float nofpclass(nan) %arg) { ; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none) ; CHECK-LABEL: define noundef float @return_nofpclass_freeze_nan_arg ; CHECK-SAME: (float nofpclass(nan) [[ARG:%.*]]) #[[ATTR3]] { ; CHECK-NEXT: [[FREEZE:%.*]] = freeze float [[ARG]] ; CHECK-NEXT: ret float [[FREEZE]] ; %freeze = freeze float %arg ret float %freeze } define float @return_nofpclass_extractelement_freeze_pinf_arg(<2 x float> nofpclass(pinf) %arg) { ; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none) ; CHECK-LABEL: define noundef float @return_nofpclass_extractelement_freeze_pinf_arg ; CHECK-SAME: (<2 x float> nofpclass(pinf) [[ARG:%.*]]) #[[ATTR3]] { ; CHECK-NEXT: [[FREEZE:%.*]] = freeze <2 x float> [[ARG]] ; CHECK-NEXT: [[ELT:%.*]] = extractelement <2 x float> [[FREEZE]], i32 0 ; CHECK-NEXT: ret float [[ELT]] ; %freeze = freeze <2 x float> %arg %elt = extractelement <2 x float> %freeze, i32 0 ret float %elt } define <4 x float> @insertelement_constant_chain() { ; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none) ; CHECK-LABEL: define nofpclass(nan ninf nzero sub) <4 x float> @insertelement_constant_chain ; CHECK-SAME: () #[[ATTR3]] { ; CHECK-NEXT: [[INS_0:%.*]] = insertelement <4 x float> poison, float 1.000000e+00, i32 0 ; CHECK-NEXT: [[INS_1:%.*]] = insertelement <4 x float> [[INS_0]], float 0.000000e+00, i32 1 ; CHECK-NEXT: [[INS_2:%.*]] = insertelement <4 x float> [[INS_1]], float -9.000000e+00, i32 2 ; CHECK-NEXT: [[INS_3:%.*]] = insertelement <4 x float> [[INS_2]], float 0x7FF0000000000000, i32 3 ; CHECK-NEXT: ret <4 x float> [[INS_3]] ; %ins.0 = insertelement <4 x float> poison, float 1.0, i32 0 %ins.1 = insertelement <4 x float> %ins.0, float 0.0, i32 1 %ins.2 = insertelement <4 x float> %ins.1, float -9.0, i32 2 %ins.3 = insertelement <4 x float> %ins.2, float 0x7FF0000000000000, i32 3 ret <4 x float> %ins.3 } define @insertelement_scalable_constant_chain() { ; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none) ; CHECK-LABEL: define @insertelement_scalable_constant_chain ; CHECK-SAME: () #[[ATTR3]] { ; CHECK-NEXT: [[INS_0:%.*]] = insertelement poison, float 1.000000e+00, i32 0 ; CHECK-NEXT: [[INS_1:%.*]] = insertelement [[INS_0]], float 0.000000e+00, i32 1 ; CHECK-NEXT: [[INS_2:%.*]] = insertelement [[INS_1]], float -9.000000e+00, i32 2 ; CHECK-NEXT: [[INS_3:%.*]] = insertelement [[INS_2]], float 0x7FF0000000000000, i32 3 ; CHECK-NEXT: ret [[INS_3]] ; %ins.0 = insertelement poison, float 1.0, i32 0 %ins.1 = insertelement %ins.0, float 0.0, i32 1 %ins.2 = insertelement %ins.1, float -9.0, i32 2 %ins.3 = insertelement %ins.2, float 0x7FF0000000000000, i32 3 ret %ins.3 } define <4 x float> @insertelement_unknown_base(<4 x float> %arg0) { ; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none) ; CHECK-LABEL: define <4 x float> @insertelement_unknown_base ; CHECK-SAME: (<4 x float> [[ARG0:%.*]]) #[[ATTR3]] { ; CHECK-NEXT: [[INSERT:%.*]] = insertelement <4 x float> [[ARG0]], float 0.000000e+00, i32 1 ; CHECK-NEXT: ret <4 x float> [[INSERT]] ; %insert = insertelement <4 x float> %arg0, float 0.0, i32 1 ret <4 x float> %insert } define float @insertelement_extractelement_same(<4 x float> %arg0) { ; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none) ; CHECK-LABEL: define nofpclass(nan inf nzero sub norm) float @insertelement_extractelement_same ; CHECK-SAME: (<4 x float> nofpclass(nan inf nzero sub norm) [[ARG0:%.*]]) #[[ATTR3]] { ; CHECK-NEXT: [[INSERT:%.*]] = insertelement <4 x float> [[ARG0]], float 0.000000e+00, i32 1 ; CHECK-NEXT: [[EXTRACT:%.*]] = extractelement <4 x float> [[INSERT]], i32 1 ; CHECK-NEXT: ret float [[EXTRACT]] ; %insert = insertelement <4 x float> %arg0, float 0.0, i32 1 %extract = extractelement <4 x float> %insert, i32 1 ret float %extract } define float @insertelement_extractelement_different(<4 x float> nofpclass(zero) %arg0) { ; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none) ; CHECK-LABEL: define nofpclass(zero) float @insertelement_extractelement_different ; CHECK-SAME: (<4 x float> nofpclass(zero) [[ARG0:%.*]]) #[[ATTR3]] { ; CHECK-NEXT: [[INSERT:%.*]] = insertelement <4 x float> [[ARG0]], float 0.000000e+00, i32 1 ; CHECK-NEXT: [[EXTRACT:%.*]] = extractelement <4 x float> [[INSERT]], i32 2 ; CHECK-NEXT: ret float [[EXTRACT]] ; %insert = insertelement <4 x float> %arg0, float 0.0, i32 1 %extract = extractelement <4 x float> %insert, i32 2 ret float %extract } define float @insertelement_extractelement_unknown(<4 x float> nofpclass(zero) %arg0, i32 %idx) { ; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none) ; CHECK-LABEL: define nofpclass(nzero) float @insertelement_extractelement_unknown ; CHECK-SAME: (<4 x float> nofpclass(zero) [[ARG0:%.*]], i32 [[IDX:%.*]]) #[[ATTR3]] { ; CHECK-NEXT: [[INSERT:%.*]] = insertelement <4 x float> [[ARG0]], float 0.000000e+00, i32 1 ; CHECK-NEXT: [[EXTRACT:%.*]] = extractelement <4 x float> [[INSERT]], i32 [[IDX]] ; CHECK-NEXT: ret float [[EXTRACT]] ; %insert = insertelement <4 x float> %arg0, float 0.0, i32 1 %extract = extractelement <4 x float> %insert, i32 %idx ret float %extract } define <4 x float> @insertelement_index_oob_chain() { ; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none) ; CHECK-LABEL: define <4 x float> @insertelement_index_oob_chain ; CHECK-SAME: () #[[ATTR3]] { ; CHECK-NEXT: [[INSERT:%.*]] = insertelement <4 x float> zeroinitializer, float 0x7FF0000000000000, i32 4 ; CHECK-NEXT: ret <4 x float> [[INSERT]] ; %insert = insertelement <4 x float> zeroinitializer, float 0x7FF0000000000000, i32 4 ret <4 x float> %insert } define <2 x float> @multiple_extractelement(<4 x float> nofpclass(zero) %arg0) { ; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none) ; CHECK-LABEL: define nofpclass(zero) <2 x float> @multiple_extractelement ; CHECK-SAME: (<4 x float> nofpclass(zero) [[ARG0:%.*]]) #[[ATTR3]] { ; CHECK-NEXT: [[INSERT:%.*]] = insertelement <4 x float> [[ARG0]], float 0.000000e+00, i32 1 ; CHECK-NEXT: [[EXTRACT2:%.*]] = extractelement <4 x float> [[INSERT]], i32 2 ; CHECK-NEXT: [[EXTRACT3:%.*]] = extractelement <4 x float> [[INSERT]], i32 3 ; CHECK-NEXT: [[INS_0:%.*]] = insertelement <2 x float> poison, float [[EXTRACT3]], i32 0 ; CHECK-NEXT: [[INS_1:%.*]] = insertelement <2 x float> [[INS_0]], float [[EXTRACT2]], i32 1 ; CHECK-NEXT: ret <2 x float> [[INS_1]] ; %insert = insertelement <4 x float> %arg0, float 0.0, i32 1 %extract2 = extractelement <4 x float> %insert, i32 2 %extract3 = extractelement <4 x float> %insert, i32 3 %ins.0 = insertelement <2 x float> poison, float %extract3, i32 0 %ins.1 = insertelement <2 x float> %ins.0, float %extract2, i32 1 ret <2 x float> %ins.1 } ; FIXME: Doesn't actually reach computeKnownFPClass define <4 x float> @shufflevector_constexpr() { ; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none) ; CHECK-LABEL: define <4 x float> @shufflevector_constexpr ; CHECK-SAME: () #[[ATTR3]] { ; CHECK-NEXT: ret <4 x float> ; ret <4 x float> shufflevector (<2 x float> , <2 x float> , <4 x i32> ) } define <4 x float> @shufflevector_concat_disjoint(<2 x float> nofpclass(nan) %arg0, <2 x float> nofpclass(inf) %arg1) { ; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none) ; CHECK-LABEL: define <4 x float> @shufflevector_concat_disjoint ; CHECK-SAME: (<2 x float> nofpclass(nan) [[ARG0:%.*]], <2 x float> nofpclass(inf) [[ARG1:%.*]]) #[[ATTR3]] { ; CHECK-NEXT: [[SHUFFLE:%.*]] = shufflevector <2 x float> [[ARG0]], <2 x float> [[ARG1]], <4 x i32> ; CHECK-NEXT: ret <4 x float> [[SHUFFLE]] ; %shuffle = shufflevector <2 x float> %arg0, <2 x float> %arg1, <4 x i32> ret <4 x float> %shuffle } define <4 x float> @shufflevector_concat_overlap(<2 x float> nofpclass(nan norm psub) %arg0, <2 x float> nofpclass(inf nan sub) %arg1) { ; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none) ; CHECK-LABEL: define nofpclass(nan psub) <4 x float> @shufflevector_concat_overlap ; CHECK-SAME: (<2 x float> nofpclass(nan psub norm) [[ARG0:%.*]], <2 x float> nofpclass(nan inf sub) [[ARG1:%.*]]) #[[ATTR3]] { ; CHECK-NEXT: [[SHUFFLE:%.*]] = shufflevector <2 x float> [[ARG0]], <2 x float> [[ARG1]], <4 x i32> ; CHECK-NEXT: ret <4 x float> [[SHUFFLE]] ; %shuffle = shufflevector <2 x float> %arg0, <2 x float> %arg1, <4 x i32> ret <4 x float> %shuffle } define <4 x float> @shufflevector_unknown_lhs(<2 x float> %arg0, <2 x float> nofpclass(inf) %arg1) { ; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none) ; CHECK-LABEL: define <4 x float> @shufflevector_unknown_lhs ; CHECK-SAME: (<2 x float> [[ARG0:%.*]], <2 x float> nofpclass(inf) [[ARG1:%.*]]) #[[ATTR3]] { ; CHECK-NEXT: [[SHUFFLE:%.*]] = shufflevector <2 x float> [[ARG0]], <2 x float> [[ARG1]], <4 x i32> ; CHECK-NEXT: ret <4 x float> [[SHUFFLE]] ; %shuffle = shufflevector <2 x float> %arg0, <2 x float> %arg1, <4 x i32> ret <4 x float> %shuffle } define <4 x float> @shufflevector_unknown_rhs(<2 x float> nofpclass(inf) %arg0, <2 x float> %arg1) { ; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none) ; CHECK-LABEL: define <4 x float> @shufflevector_unknown_rhs ; CHECK-SAME: (<2 x float> nofpclass(inf) [[ARG0:%.*]], <2 x float> [[ARG1:%.*]]) #[[ATTR3]] { ; CHECK-NEXT: [[SHUFFLE:%.*]] = shufflevector <2 x float> [[ARG0]], <2 x float> [[ARG1]], <4 x i32> ; CHECK-NEXT: ret <4 x float> [[SHUFFLE]] ; %shuffle = shufflevector <2 x float> %arg0, <2 x float> %arg1, <4 x i32> ret <4 x float> %shuffle } define <4 x float> @shufflevector_unknown_all(<2 x float> %arg0, <2 x float> %arg1) { ; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none) ; CHECK-LABEL: define <4 x float> @shufflevector_unknown_all ; CHECK-SAME: (<2 x float> [[ARG0:%.*]], <2 x float> [[ARG1:%.*]]) #[[ATTR3]] { ; CHECK-NEXT: [[SHUFFLE:%.*]] = shufflevector <2 x float> [[ARG0]], <2 x float> [[ARG1]], <4 x i32> ; CHECK-NEXT: ret <4 x float> [[SHUFFLE]] ; %shuffle = shufflevector <2 x float> %arg0, <2 x float> %arg1, <4 x i32> ret <4 x float> %shuffle } define <4 x float> @shufflevector_only_demand_lhs(<2 x float> nofpclass(inf) %arg0, <2 x float> %arg1) { ; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none) ; CHECK-LABEL: define nofpclass(inf) <4 x float> @shufflevector_only_demand_lhs ; CHECK-SAME: (<2 x float> nofpclass(inf) [[ARG0:%.*]], <2 x float> nofpclass(inf) [[ARG1:%.*]]) #[[ATTR3]] { ; CHECK-NEXT: [[SHUFFLE:%.*]] = shufflevector <2 x float> [[ARG0]], <2 x float> [[ARG1]], <4 x i32> ; CHECK-NEXT: ret <4 x float> [[SHUFFLE]] ; %shuffle = shufflevector <2 x float> %arg0, <2 x float> %arg1, <4 x i32> ret <4 x float> %shuffle } define <4 x float> @shufflevector_only_demand_rhs(<2 x float> %arg0, <2 x float> nofpclass(inf) %arg1) { ; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none) ; CHECK-LABEL: define nofpclass(inf) <4 x float> @shufflevector_only_demand_rhs ; CHECK-SAME: (<2 x float> nofpclass(inf) [[ARG0:%.*]], <2 x float> nofpclass(inf) [[ARG1:%.*]]) #[[ATTR3]] { ; CHECK-NEXT: [[SHUFFLE:%.*]] = shufflevector <2 x float> [[ARG0]], <2 x float> [[ARG1]], <4 x i32> ; CHECK-NEXT: ret <4 x float> [[SHUFFLE]] ; %shuffle = shufflevector <2 x float> %arg0, <2 x float> %arg1, <4 x i32> ret <4 x float> %shuffle } define <4 x float> @shufflevector_undef_demanded(<2 x float> %arg0, <2 x float> nofpclass(inf) %arg1) { ; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none) ; CHECK-LABEL: define <4 x float> @shufflevector_undef_demanded ; CHECK-SAME: (<2 x float> [[ARG0:%.*]], <2 x float> nofpclass(inf) [[ARG1:%.*]]) #[[ATTR3]] { ; CHECK-NEXT: [[SHUFFLE:%.*]] = shufflevector <2 x float> [[ARG0]], <2 x float> [[ARG1]], <4 x i32> poison ; CHECK-NEXT: ret <4 x float> [[SHUFFLE]] ; %shuffle = shufflevector <2 x float> %arg0, <2 x float> %arg1, <4 x i32> undef ret <4 x float> %shuffle } define <4 x float> @shufflevector_zeroinit_demanded(<2 x float> %arg0, <2 x float> nofpclass(inf) %arg1) { ; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none) ; CHECK-LABEL: define <4 x float> @shufflevector_zeroinit_demanded ; CHECK-SAME: (<2 x float> [[ARG0:%.*]], <2 x float> nofpclass(inf) [[ARG1:%.*]]) #[[ATTR3]] { ; CHECK-NEXT: [[SHUFFLE:%.*]] = shufflevector <2 x float> [[ARG0]], <2 x float> [[ARG1]], <4 x i32> zeroinitializer ; CHECK-NEXT: ret <4 x float> [[SHUFFLE]] ; %shuffle = shufflevector <2 x float> %arg0, <2 x float> %arg1, <4 x i32> zeroinitializer ret <4 x float> %shuffle } define float @shufflevector_extractelt0(<2 x float> %arg0, <2 x float> nofpclass(inf) %arg1) { ; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none) ; CHECK-LABEL: define float @shufflevector_extractelt0 ; CHECK-SAME: (<2 x float> [[ARG0:%.*]], <2 x float> nofpclass(inf) [[ARG1:%.*]]) #[[ATTR3]] { ; CHECK-NEXT: [[SHUFFLE:%.*]] = shufflevector <2 x float> [[ARG0]], <2 x float> [[ARG1]], <4 x i32> ; CHECK-NEXT: [[EXTRACT:%.*]] = extractelement <4 x float> [[SHUFFLE]], i32 0 ; CHECK-NEXT: ret float [[EXTRACT]] ; %shuffle = shufflevector <2 x float> %arg0, <2 x float> %arg1, <4 x i32> %extract = extractelement <4 x float> %shuffle, i32 0 ret float %extract } define float @shufflevector_extractelt1(<2 x float> %arg0, <2 x float> nofpclass(inf) %arg1) { ; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none) ; CHECK-LABEL: define nofpclass(inf) float @shufflevector_extractelt1 ; CHECK-SAME: (<2 x float> nofpclass(inf) [[ARG0:%.*]], <2 x float> nofpclass(inf) [[ARG1:%.*]]) #[[ATTR3]] { ; CHECK-NEXT: [[SHUFFLE:%.*]] = shufflevector <2 x float> [[ARG0]], <2 x float> [[ARG1]], <4 x i32> ; CHECK-NEXT: [[EXTRACT:%.*]] = extractelement <4 x float> [[SHUFFLE]], i32 1 ; CHECK-NEXT: ret float [[EXTRACT]] ; %shuffle = shufflevector <2 x float> %arg0, <2 x float> %arg1, <4 x i32> %extract = extractelement <4 x float> %shuffle, i32 1 ret float %extract } define float @shufflevector_extractelt2(<2 x float> %arg0, <2 x float> nofpclass(inf) %arg1) { ; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none) ; CHECK-LABEL: define float @shufflevector_extractelt2 ; CHECK-SAME: (<2 x float> [[ARG0:%.*]], <2 x float> nofpclass(inf) [[ARG1:%.*]]) #[[ATTR3]] { ; CHECK-NEXT: [[SHUFFLE:%.*]] = shufflevector <2 x float> [[ARG0]], <2 x float> [[ARG1]], <4 x i32> ; CHECK-NEXT: [[EXTRACT:%.*]] = extractelement <4 x float> [[SHUFFLE]], i32 2 ; CHECK-NEXT: ret float [[EXTRACT]] ; %shuffle = shufflevector <2 x float> %arg0, <2 x float> %arg1, <4 x i32> %extract = extractelement <4 x float> %shuffle, i32 2 ret float %extract } define float @shufflevector_extractelt3(<2 x float> %arg0, <2 x float> nofpclass(inf) %arg1) { ; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none) ; CHECK-LABEL: define float @shufflevector_extractelt3 ; CHECK-SAME: (<2 x float> [[ARG0:%.*]], <2 x float> nofpclass(inf) [[ARG1:%.*]]) #[[ATTR3]] { ; CHECK-NEXT: [[SHUFFLE:%.*]] = shufflevector <2 x float> [[ARG0]], <2 x float> [[ARG1]], <4 x i32> ; CHECK-NEXT: [[EXTRACT:%.*]] = extractelement <4 x float> [[SHUFFLE]], i32 3 ; CHECK-NEXT: ret float [[EXTRACT]] ; %shuffle = shufflevector <2 x float> %arg0, <2 x float> %arg1, <4 x i32> %extract = extractelement <4 x float> %shuffle, i32 3 ret float %extract } define i32 @fptosi(float nofpclass(inf nan) %arg) { ; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none) ; CHECK-LABEL: define i32 @fptosi ; CHECK-SAME: (float nofpclass(nan inf) [[ARG:%.*]]) #[[ATTR3]] { ; CHECK-NEXT: [[FPTOSI:%.*]] = fptosi float [[ARG]] to i32 ; CHECK-NEXT: [[ADD:%.*]] = add i32 [[FPTOSI]], 1 ; CHECK-NEXT: ret i32 [[ADD]] ; %fptosi = fptosi float %arg to i32 %add = add i32 %fptosi, 1 ret i32 %add } define float @fptrunc(double nofpclass(inf nan) %arg) { ; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none) ; CHECK-LABEL: define nofpclass(ninf nzero nsub nnorm) float @fptrunc ; CHECK-SAME: (double nofpclass(nan inf nzero nsub nnorm) [[ARG:%.*]]) #[[ATTR3]] { ; CHECK-NEXT: [[CAST:%.*]] = fptrunc double [[ARG]] to float ; CHECK-NEXT: [[MUL:%.*]] = fmul float [[CAST]], [[CAST]] ; CHECK-NEXT: ret float [[MUL]] ; %cast = fptrunc double %arg to float %mul = fmul float %cast, %cast ret float %mul } define double @fpext(float nofpclass(inf nan) %arg) { ; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none) ; CHECK-LABEL: define nofpclass(nan ninf nzero nsub nnorm) double @fpext ; CHECK-SAME: (float nofpclass(nan inf nzero sub nnorm) [[ARG:%.*]]) #[[ATTR3]] { ; CHECK-NEXT: [[CAST:%.*]] = fpext float [[ARG]] to double ; CHECK-NEXT: [[MUL:%.*]] = fmul double [[CAST]], [[CAST]] ; CHECK-NEXT: ret double [[MUL]] ; %cast = fpext float %arg to double %mul = fmul double %cast, %cast ret double %mul } define float @atomicrmw_fadd(ptr %ptr, float nofpclass(inf nan) %val) { ; CHECK: Function Attrs: mustprogress nofree norecurse nounwind willreturn memory(argmem: readwrite) ; CHECK-LABEL: define float @atomicrmw_fadd ; CHECK-SAME: (ptr nocapture nofree noundef nonnull dereferenceable(4) [[PTR:%.*]], float nofpclass(nan inf) [[VAL:%.*]]) #[[ATTR6:[0-9]+]] { ; CHECK-NEXT: [[RESULT:%.*]] = atomicrmw fadd ptr [[PTR]], float [[VAL]] seq_cst, align 4 ; CHECK-NEXT: ret float [[RESULT]] ; %result = atomicrmw fadd ptr %ptr, float %val seq_cst ret float %result } define float @load(ptr %ptr, float nofpclass(nan inf) %val) { ; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: readwrite) ; CHECK-LABEL: define nofpclass(ninf nzero nsub nnorm) float @load ; CHECK-SAME: (ptr nocapture nofree noundef nonnull align 4 dereferenceable(4) [[PTR:%.*]], float nofpclass(nan inf) [[VAL:%.*]]) #[[ATTR7:[0-9]+]] { ; CHECK-NEXT: store float [[VAL]], ptr [[PTR]], align 4 ; CHECK-NEXT: [[LOAD:%.*]] = load float, ptr [[PTR]], align 4 ; CHECK-NEXT: [[MUL:%.*]] = fmul float [[LOAD]], [[LOAD]] ; CHECK-NEXT: ret float [[MUL]] ; store float %val, ptr %ptr %load = load float, ptr %ptr %mul = fmul float %load, %load ret float %mul } define float @load_atomic(ptr %ptr, float nofpclass(nan inf) %val) { ; CHECK: Function Attrs: mustprogress nofree norecurse nounwind willreturn memory(argmem: readwrite) ; CHECK-LABEL: define nofpclass(ninf nzero nsub nnorm) float @load_atomic ; CHECK-SAME: (ptr nocapture nofree noundef nonnull align 4 dereferenceable(4) [[PTR:%.*]], float nofpclass(nan inf) [[VAL:%.*]]) #[[ATTR6]] { ; CHECK-NEXT: store atomic float [[VAL]], ptr [[PTR]] seq_cst, align 4 ; CHECK-NEXT: [[LOAD:%.*]] = load atomic float, ptr [[PTR]] seq_cst, align 4 ; CHECK-NEXT: [[MUL:%.*]] = fmul float [[LOAD]], [[LOAD]] ; CHECK-NEXT: ret float [[MUL]] ; store atomic float %val, ptr %ptr seq_cst, align 4 %load = load atomic float, ptr %ptr seq_cst, align 4 %mul = fmul float %load, %load ret float %mul } define <8 x float> @shufflevector_shufflevector(<4 x float> nofpclass(inf nan) %arg0, <4 x float> nofpclass(inf nan zero) %arg1) { ; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none) ; CHECK-LABEL: define nofpclass(nan inf) <8 x float> @shufflevector_shufflevector ; CHECK-SAME: (<4 x float> nofpclass(nan inf) [[ARG0:%.*]], <4 x float> nofpclass(nan inf zero) [[ARG1:%.*]]) #[[ATTR3]] { ; CHECK-NEXT: [[SHUFFLE0:%.*]] = shufflevector <4 x float> [[ARG0]], <4 x float> [[ARG0]], <4 x i32> ; CHECK-NEXT: [[SHUFFLE1:%.*]] = shufflevector <4 x float> [[ARG1]], <4 x float> [[ARG1]], <4 x i32> ; CHECK-NEXT: [[SHUFFLE2:%.*]] = shufflevector <4 x float> [[SHUFFLE0]], <4 x float> [[SHUFFLE1]], <8 x i32> ; CHECK-NEXT: ret <8 x float> [[SHUFFLE2]] ; %shuffle0 = shufflevector <4 x float> %arg0, <4 x float> %arg0, <4 x i32> %shuffle1 = shufflevector <4 x float> %arg1, <4 x float> %arg1, <4 x i32> %shuffle2 = shufflevector <4 x float> %shuffle0, <4 x float> %shuffle1, <8 x i32> ret <8 x float> %shuffle2 } define float @constrained_sitofp(i32 %arg) strictfp { ; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind strictfp willreturn memory(inaccessiblemem: readwrite) ; CHECK-LABEL: define nofpclass(nan nzero sub) float @constrained_sitofp ; CHECK-SAME: (i32 [[ARG:%.*]]) #[[ATTR8:[0-9]+]] { ; CHECK-NEXT: [[VAL:%.*]] = call nofpclass(nan nzero sub) float @llvm.experimental.constrained.sitofp.f32.i32(i32 [[ARG]], metadata !"round.dynamic", metadata !"fpexcept.strict") #[[ATTR20]] ; CHECK-NEXT: ret float [[VAL]] ; %val = call float @llvm.experimental.constrained.sitofp.f32.i32(i32 %arg, metadata !"round.dynamic", metadata !"fpexcept.strict") ret float %val } define float @constrained_uitofp(i32 %arg) strictfp { ; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind strictfp willreturn memory(inaccessiblemem: readwrite) ; CHECK-LABEL: define nofpclass(nan ninf nzero sub nnorm) float @constrained_uitofp ; CHECK-SAME: (i32 [[ARG:%.*]]) #[[ATTR8]] { ; CHECK-NEXT: [[VAL:%.*]] = call nofpclass(nan ninf nzero sub nnorm) float @llvm.experimental.constrained.uitofp.f32.i32(i32 [[ARG]], metadata !"round.dynamic", metadata !"fpexcept.strict") #[[ATTR20]] ; CHECK-NEXT: ret float [[VAL]] ; %val = call float @llvm.experimental.constrained.uitofp.f32.i32(i32 %arg, metadata !"round.dynamic", metadata !"fpexcept.strict") ret float %val } define float @fadd_p0(float %arg0) { ; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none) ; CHECK-LABEL: define nofpclass(nzero) float @fadd_p0 ; CHECK-SAME: (float nofpclass(nzero) [[ARG0:%.*]]) #[[ATTR3]] { ; CHECK-NEXT: [[ADD:%.*]] = fadd float [[ARG0]], 0.000000e+00 ; CHECK-NEXT: ret float [[ADD]] ; %add = fadd float %arg0, 0.0 ret float %add } define float @fadd_n0(float %arg0) { ; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none) ; CHECK-LABEL: define float @fadd_n0 ; CHECK-SAME: (float [[ARG0:%.*]]) #[[ATTR3]] { ; CHECK-NEXT: [[ADD:%.*]] = fadd float [[ARG0]], -0.000000e+00 ; CHECK-NEXT: ret float [[ADD]] ; %add = fadd float %arg0, -0.0 ret float %add } define float @fsub_p0(float %arg0) { ; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none) ; CHECK-LABEL: define float @fsub_p0 ; CHECK-SAME: (float [[ARG0:%.*]]) #[[ATTR3]] { ; CHECK-NEXT: [[SUB:%.*]] = fsub float [[ARG0]], 0.000000e+00 ; CHECK-NEXT: ret float [[SUB]] ; %sub = fsub float %arg0, 0.0 ret float %sub } define float @fsub_n0(float %arg0) { ; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none) ; CHECK-LABEL: define nofpclass(nzero) float @fsub_n0 ; CHECK-SAME: (float nofpclass(nzero) [[ARG0:%.*]]) #[[ATTR3]] { ; CHECK-NEXT: [[SUB:%.*]] = fsub float [[ARG0]], -0.000000e+00 ; CHECK-NEXT: ret float [[SUB]] ; %sub = fsub float %arg0, -0.0 ret float %sub } define float @fsub_p0_commute(float %arg0) { ; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none) ; CHECK-LABEL: define nofpclass(nzero) float @fsub_p0_commute ; CHECK-SAME: (float nofpclass(nzero) [[ARG0:%.*]]) #[[ATTR3]] { ; CHECK-NEXT: [[SUB:%.*]] = fsub float 0.000000e+00, [[ARG0]] ; CHECK-NEXT: ret float [[SUB]] ; %sub = fsub float 0.0, %arg0 ret float %sub } define float @fsub_n0_commute(float %arg0) { ; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none) ; CHECK-LABEL: define float @fsub_n0_commute ; CHECK-SAME: (float [[ARG0:%.*]]) #[[ATTR3]] { ; CHECK-NEXT: [[SUB:%.*]] = fsub float -0.000000e+00, [[ARG0]] ; CHECK-NEXT: ret float [[SUB]] ; %sub = fsub float -0.0, %arg0 ret float %sub } define float @fadd_p0_ftz_daz(float %arg0) #3 { ; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none) ; CHECK-LABEL: define nofpclass(nzero) float @fadd_p0_ftz_daz ; CHECK-SAME: (float nofpclass(nzero) [[ARG0:%.*]]) #[[ATTR9:[0-9]+]] { ; CHECK-NEXT: [[ADD:%.*]] = fadd float [[ARG0]], 0.000000e+00 ; CHECK-NEXT: ret float [[ADD]] ; %add = fadd float %arg0, 0.0 ret float %add } define float @fadd_n0_ftz_daz(float %arg0) #0 { ; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none) ; CHECK-LABEL: define float @fadd_n0_ftz_daz ; CHECK-SAME: (float [[ARG0:%.*]]) #[[ATTR10:[0-9]+]] { ; CHECK-NEXT: [[ADD:%.*]] = fadd float [[ARG0]], -0.000000e+00 ; CHECK-NEXT: ret float [[ADD]] ; %add = fadd float %arg0, -0.0 ret float %add } define float @fsub_p0_ftz_daz(float %arg0) #0 { ; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none) ; CHECK-LABEL: define float @fsub_p0_ftz_daz ; CHECK-SAME: (float [[ARG0:%.*]]) #[[ATTR10]] { ; CHECK-NEXT: [[SUB:%.*]] = fsub float [[ARG0]], 0.000000e+00 ; CHECK-NEXT: ret float [[SUB]] ; %sub = fsub float %arg0, 0.0 ret float %sub } define float @fsub_n0_ftz_daz(float %arg0) #0 { ; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none) ; CHECK-LABEL: define float @fsub_n0_ftz_daz ; CHECK-SAME: (float [[ARG0:%.*]]) #[[ATTR10]] { ; CHECK-NEXT: [[SUB:%.*]] = fsub float [[ARG0]], -0.000000e+00 ; CHECK-NEXT: ret float [[SUB]] ; %sub = fsub float %arg0, -0.0 ret float %sub } define float @fsub_p0_commute_ftz_daz(float %arg0) #0 { ; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none) ; CHECK-LABEL: define float @fsub_p0_commute_ftz_daz ; CHECK-SAME: (float [[ARG0:%.*]]) #[[ATTR10]] { ; CHECK-NEXT: [[SUB:%.*]] = fsub float 0.000000e+00, [[ARG0]] ; CHECK-NEXT: ret float [[SUB]] ; %sub = fsub float 0.0, %arg0 ret float %sub } define float @fsub_n0_commute_ftz_daz(float %arg0) #0 { ; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none) ; CHECK-LABEL: define float @fsub_n0_commute_ftz_daz ; CHECK-SAME: (float [[ARG0:%.*]]) #[[ATTR10]] { ; CHECK-NEXT: [[SUB:%.*]] = fsub float -0.000000e+00, [[ARG0]] ; CHECK-NEXT: ret float [[SUB]] ; %sub = fsub float -0.0, %arg0 ret float %sub } define float @fadd_p0_ieee_daz(float %arg0) #2 { ; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none) ; CHECK-LABEL: define nofpclass(nzero) float @fadd_p0_ieee_daz ; CHECK-SAME: (float nofpclass(nzero) [[ARG0:%.*]]) #[[ATTR11:[0-9]+]] { ; CHECK-NEXT: [[ADD:%.*]] = fadd float [[ARG0]], 0.000000e+00 ; CHECK-NEXT: ret float [[ADD]] ; %add = fadd float %arg0, 0.0 ret float %add } define float @fadd_p0_dapz_ieee(float %arg0) #4 { ; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none) ; CHECK-LABEL: define nofpclass(nzero) float @fadd_p0_dapz_ieee ; CHECK-SAME: (float nofpclass(nzero) [[ARG0:%.*]]) #[[ATTR12:[0-9]+]] { ; CHECK-NEXT: [[ADD:%.*]] = fadd float [[ARG0]], 0.000000e+00 ; CHECK-NEXT: ret float [[ADD]] ; %add = fadd float %arg0, 0.0 ret float %add } define float @fadd_n0_ieee_daz(float %arg0) #2 { ; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none) ; CHECK-LABEL: define float @fadd_n0_ieee_daz ; CHECK-SAME: (float [[ARG0:%.*]]) #[[ATTR11]] { ; CHECK-NEXT: [[ADD:%.*]] = fadd float [[ARG0]], -0.000000e+00 ; CHECK-NEXT: ret float [[ADD]] ; %add = fadd float %arg0, -0.0 ret float %add } define float @fsub_p0_ieee_daz(float %arg0) #2 { ; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none) ; CHECK-LABEL: define float @fsub_p0_ieee_daz ; CHECK-SAME: (float [[ARG0:%.*]]) #[[ATTR11]] { ; CHECK-NEXT: [[SUB:%.*]] = fsub float [[ARG0]], 0.000000e+00 ; CHECK-NEXT: ret float [[SUB]] ; %sub = fsub float %arg0, 0.0 ret float %sub } define float @fsub_n0_ieee_daz(float %arg0) #2 { ; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none) ; CHECK-LABEL: define nofpclass(nzero) float @fsub_n0_ieee_daz ; CHECK-SAME: (float nofpclass(nzero) [[ARG0:%.*]]) #[[ATTR11]] { ; CHECK-NEXT: [[SUB:%.*]] = fsub float [[ARG0]], -0.000000e+00 ; CHECK-NEXT: ret float [[SUB]] ; %sub = fsub float %arg0, -0.0 ret float %sub } define float @fsub_p0_commute_ieee_daz(float %arg0) #2 { ; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none) ; CHECK-LABEL: define nofpclass(nzero) float @fsub_p0_commute_ieee_daz ; CHECK-SAME: (float nofpclass(nzero) [[ARG0:%.*]]) #[[ATTR11]] { ; CHECK-NEXT: [[SUB:%.*]] = fsub float 0.000000e+00, [[ARG0]] ; CHECK-NEXT: ret float [[SUB]] ; %sub = fsub float 0.0, %arg0 ret float %sub } define float @fsub_n0_commute_ieee_daz(float %arg0) #1 { ; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none) ; CHECK-LABEL: define float @fsub_n0_commute_ieee_daz ; CHECK-SAME: (float [[ARG0:%.*]]) #[[ATTR13:[0-9]+]] { ; CHECK-NEXT: [[SUB:%.*]] = fsub float -0.000000e+00, [[ARG0]] ; CHECK-NEXT: ret float [[SUB]] ; %sub = fsub float -0.0, %arg0 ret float %sub } define float @fadd_never_negzero_or_negsub(float nofpclass(nzero nsub) %a, float nofpclass(nzero nsub) %b) { ; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none) ; CHECK-LABEL: define nofpclass(nzero) float @fadd_never_negzero_or_negsub ; CHECK-SAME: (float nofpclass(nzero nsub) [[A:%.*]], float nofpclass(nzero nsub) [[B:%.*]]) #[[ATTR3]] { ; CHECK-NEXT: [[ADD:%.*]] = fadd float [[A]], [[B]] ; CHECK-NEXT: ret float [[ADD]] ; %add = fadd float %a, %b ret float %add } define float @fadd_never_negzero_or_negsub_daz(float nofpclass(nzero nsub) %a, float nofpclass(nzero nsub) %b) #2 { ; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none) ; CHECK-LABEL: define nofpclass(nzero) float @fadd_never_negzero_or_negsub_daz ; CHECK-SAME: (float nofpclass(nzero nsub) [[A:%.*]], float nofpclass(nzero nsub) [[B:%.*]]) #[[ATTR11]] { ; CHECK-NEXT: [[ADD:%.*]] = fadd float [[A]], [[B]] ; CHECK-NEXT: ret float [[ADD]] ; %add = fadd float %a, %b ret float %add } define float @fadd_never_negzero_or_negsub_dapz(float nofpclass(nzero nsub) %a, float nofpclass(nzero nsub) %b) #5 { ; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none) ; CHECK-LABEL: define nofpclass(nzero) float @fadd_never_negzero_or_negsub_dapz ; CHECK-SAME: (float nofpclass(nzero nsub) [[A:%.*]], float nofpclass(nzero nsub) [[B:%.*]]) #[[ATTR14:[0-9]+]] { ; CHECK-NEXT: [[ADD:%.*]] = fadd float [[A]], [[B]] ; CHECK-NEXT: ret float [[ADD]] ; %add = fadd float %a, %b ret float %add } define float @fadd_never_negzero_or_possub(float nofpclass(nzero psub) %a, float nofpclass(nzero psub) %b) { ; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none) ; CHECK-LABEL: define nofpclass(nzero) float @fadd_never_negzero_or_possub ; CHECK-SAME: (float nofpclass(nzero psub) [[A:%.*]], float nofpclass(nzero psub) [[B:%.*]]) #[[ATTR3]] { ; CHECK-NEXT: [[ADD:%.*]] = fadd float [[A]], [[B]] ; CHECK-NEXT: ret float [[ADD]] ; %add = fadd float %a, %b ret float %add } define float @fadd_never_negzero_or_possub_daz(float nofpclass(nzero psub) %a, float nofpclass(nzero psub) %b) #2 { ; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none) ; CHECK-LABEL: define float @fadd_never_negzero_or_possub_daz ; CHECK-SAME: (float nofpclass(nzero psub) [[A:%.*]], float nofpclass(nzero psub) [[B:%.*]]) #[[ATTR11]] { ; CHECK-NEXT: [[ADD:%.*]] = fadd float [[A]], [[B]] ; CHECK-NEXT: ret float [[ADD]] ; %add = fadd float %a, %b ret float %add } define float @fadd_never_negzero_or_possub_dapz(float nofpclass(nzero psub) %a, float nofpclass(nzero psub) %b) #5 { ; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none) ; CHECK-LABEL: define nofpclass(nzero) float @fadd_never_negzero_or_possub_dapz ; CHECK-SAME: (float nofpclass(nzero psub) [[A:%.*]], float nofpclass(nzero psub) [[B:%.*]]) #[[ATTR14]] { ; CHECK-NEXT: [[ADD:%.*]] = fadd float [[A]], [[B]] ; CHECK-NEXT: ret float [[ADD]] ; %add = fadd float %a, %b ret float %add } define float @fadd_never_negzero_or_sub_daz(float nofpclass(nzero sub) %a, float nofpclass(nzero sub) %b) #2 { ; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none) ; CHECK-LABEL: define nofpclass(nzero) float @fadd_never_negzero_or_sub_daz ; CHECK-SAME: (float nofpclass(nzero sub) [[A:%.*]], float nofpclass(nzero sub) [[B:%.*]]) #[[ATTR11]] { ; CHECK-NEXT: [[ADD:%.*]] = fadd float [[A]], [[B]] ; CHECK-NEXT: ret float [[ADD]] ; %add = fadd float %a, %b ret float %add } define float @fadd_never_negzero_or_sub_dapz(float nofpclass(nzero sub) %a, float nofpclass(nzero sub) %b) #5 { ; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none) ; CHECK-LABEL: define nofpclass(nzero) float @fadd_never_negzero_or_sub_dapz ; CHECK-SAME: (float nofpclass(nzero sub) [[A:%.*]], float nofpclass(nzero sub) [[B:%.*]]) #[[ATTR14]] { ; CHECK-NEXT: [[ADD:%.*]] = fadd float [[A]], [[B]] ; CHECK-NEXT: ret float [[ADD]] ; %add = fadd float %a, %b ret float %add } define float @fadd_known_positive_lhs(float nofpclass(ninf nsub nnorm) %arg0, float %arg1) { ; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none) ; CHECK-LABEL: define float @fadd_known_positive_lhs ; CHECK-SAME: (float nofpclass(ninf nsub nnorm) [[ARG0:%.*]], float [[ARG1:%.*]]) #[[ATTR3]] { ; CHECK-NEXT: [[ADD:%.*]] = fadd float [[ARG0]], [[ARG1]] ; CHECK-NEXT: ret float [[ADD]] ; %add = fadd float %arg0, %arg1 ret float %add } define float @fadd_known_positive_rhs(float %arg0, float nofpclass(ninf nsub nnorm) %arg1) { ; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none) ; CHECK-LABEL: define float @fadd_known_positive_rhs ; CHECK-SAME: (float [[ARG0:%.*]], float nofpclass(ninf nsub nnorm) [[ARG1:%.*]]) #[[ATTR3]] { ; CHECK-NEXT: [[ADD:%.*]] = fadd float [[ARG0]], [[ARG1]] ; CHECK-NEXT: ret float [[ADD]] ; %add = fadd float %arg0, %arg1 ret float %add } define float @fadd_known_positive(float nofpclass(ninf nsub nnorm) %arg0, float nofpclass(ninf nsub nnorm) %arg1) { ; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none) ; CHECK-LABEL: define nofpclass(ninf nsub nnorm) float @fadd_known_positive ; CHECK-SAME: (float nofpclass(ninf nsub nnorm) [[ARG0:%.*]], float nofpclass(ninf nsub nnorm) [[ARG1:%.*]]) #[[ATTR3]] { ; CHECK-NEXT: [[ADD:%.*]] = fadd float [[ARG0]], [[ARG1]] ; CHECK-NEXT: ret float [[ADD]] ; %add = fadd float %arg0, %arg1 ret float %add } define float @fadd_known_positive_daz(float nofpclass(ninf nsub nnorm) %arg0, float nofpclass(ninf nsub nnorm) %arg1) #0 { ; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none) ; CHECK-LABEL: define nofpclass(ninf nsub nnorm) float @fadd_known_positive_daz ; CHECK-SAME: (float nofpclass(ninf nsub nnorm) [[ARG0:%.*]], float nofpclass(ninf nsub nnorm) [[ARG1:%.*]]) #[[ATTR10]] { ; CHECK-NEXT: [[ADD:%.*]] = fadd float [[ARG0]], [[ARG1]] ; CHECK-NEXT: ret float [[ADD]] ; %add = fadd float %arg0, %arg1 ret float %add } define float @fadd_known_positive_nzero_lhs(float nofpclass(ninf nsub nnorm nzero) %arg0, float nofpclass(ninf nsub nnorm) %arg1) { ; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none) ; CHECK-LABEL: define nofpclass(ninf nzero nsub nnorm) float @fadd_known_positive_nzero_lhs ; CHECK-SAME: (float nofpclass(ninf nzero nsub nnorm) [[ARG0:%.*]], float nofpclass(ninf nzero nsub nnorm) [[ARG1:%.*]]) #[[ATTR3]] { ; CHECK-NEXT: [[ADD:%.*]] = fadd float [[ARG0]], [[ARG1]] ; CHECK-NEXT: ret float [[ADD]] ; %add = fadd float %arg0, %arg1 ret float %add } define float @fadd_known_positive_nzero_rhs(float nofpclass(ninf nsub nnorm) %arg0, float nofpclass(ninf nsub nnorm nzero) %arg1) { ; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none) ; CHECK-LABEL: define nofpclass(ninf nzero nsub nnorm) float @fadd_known_positive_nzero_rhs ; CHECK-SAME: (float nofpclass(ninf nzero nsub nnorm) [[ARG0:%.*]], float nofpclass(ninf nzero nsub nnorm) [[ARG1:%.*]]) #[[ATTR3]] { ; CHECK-NEXT: [[ADD:%.*]] = fadd float [[ARG0]], [[ARG1]] ; CHECK-NEXT: ret float [[ADD]] ; %add = fadd float %arg0, %arg1 ret float %add } define float @fadd_known_positive_nzero(float nofpclass(ninf nsub nnorm nzero) %arg0, float nofpclass(ninf nsub nnorm nzero) %arg1) { ; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none) ; CHECK-LABEL: define nofpclass(ninf nzero nsub nnorm) float @fadd_known_positive_nzero ; CHECK-SAME: (float nofpclass(ninf nzero nsub nnorm) [[ARG0:%.*]], float nofpclass(ninf nzero nsub nnorm) [[ARG1:%.*]]) #[[ATTR3]] { ; CHECK-NEXT: [[ADD:%.*]] = fadd float [[ARG0]], [[ARG1]] ; CHECK-NEXT: ret float [[ADD]] ; %add = fadd float %arg0, %arg1 ret float %add } define float @fadd_known_positive_nzero_ftz_daz(float nofpclass(ninf nsub nnorm nzero) %arg0, float nofpclass(ninf nsub nnorm nzero) %arg1) #0 { ; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none) ; CHECK-LABEL: define nofpclass(ninf nsub nnorm) float @fadd_known_positive_nzero_ftz_daz ; CHECK-SAME: (float nofpclass(ninf nzero nsub nnorm) [[ARG0:%.*]], float nofpclass(ninf nzero nsub nnorm) [[ARG1:%.*]]) #[[ATTR10]] { ; CHECK-NEXT: [[ADD:%.*]] = fadd float [[ARG0]], [[ARG1]] ; CHECK-NEXT: ret float [[ADD]] ; %add = fadd float %arg0, %arg1 ret float %add } define float @fadd_known_positive_nzero_ftz(float nofpclass(ninf nsub nnorm nzero) %arg0, float nofpclass(ninf nsub nnorm nzero) %arg1) #1 { ; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none) ; CHECK-LABEL: define nofpclass(ninf nsub nnorm) float @fadd_known_positive_nzero_ftz ; CHECK-SAME: (float nofpclass(ninf nzero nsub nnorm) [[ARG0:%.*]], float nofpclass(ninf nzero nsub nnorm) [[ARG1:%.*]]) #[[ATTR13]] { ; CHECK-NEXT: [[ADD:%.*]] = fadd float [[ARG0]], [[ARG1]] ; CHECK-NEXT: ret float [[ADD]] ; %add = fadd float %arg0, %arg1 ret float %add } define float @fadd_known_positive_nzero_daz(float nofpclass(ninf nsub nnorm nzero) %arg0, float nofpclass(ninf nsub nnorm nzero) %arg1) #2 { ; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none) ; CHECK-LABEL: define nofpclass(ninf nzero nsub nnorm) float @fadd_known_positive_nzero_daz ; CHECK-SAME: (float nofpclass(ninf nzero nsub nnorm) [[ARG0:%.*]], float nofpclass(ninf nzero nsub nnorm) [[ARG1:%.*]]) #[[ATTR11]] { ; CHECK-NEXT: [[ADD:%.*]] = fadd float [[ARG0]], [[ARG1]] ; CHECK-NEXT: ret float [[ADD]] ; %add = fadd float %arg0, %arg1 ret float %add } define float @fadd_known_positive_normal(float nofpclass(ninf nnorm nzero) %arg0, float nofpclass(ninf nnorm nzero) %arg1) { ; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none) ; CHECK-LABEL: define nofpclass(nzero) float @fadd_known_positive_normal ; CHECK-SAME: (float nofpclass(ninf nzero nnorm) [[ARG0:%.*]], float nofpclass(ninf nzero nnorm) [[ARG1:%.*]]) #[[ATTR3]] { ; CHECK-NEXT: [[ADD:%.*]] = fadd float [[ARG0]], [[ARG1]] ; CHECK-NEXT: ret float [[ADD]] ; %add = fadd float %arg0, %arg1 ret float %add } define float @fadd_known_positive_normal_daz(float nofpclass(ninf nnorm nzero) %arg0, float nofpclass(ninf nnorm nzero) %arg1) #0 { ; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none) ; CHECK-LABEL: define float @fadd_known_positive_normal_daz ; CHECK-SAME: (float nofpclass(ninf nzero nnorm) [[ARG0:%.*]], float nofpclass(ninf nzero nnorm) [[ARG1:%.*]]) #[[ATTR10]] { ; CHECK-NEXT: [[ADD:%.*]] = fadd float [[ARG0]], [[ARG1]] ; CHECK-NEXT: ret float [[ADD]] ; %add = fadd float %arg0, %arg1 ret float %add } define float @fadd_known_positive_normal_except0_daz(float nofpclass(ninf nnorm) %arg0, float nofpclass(ninf nnorm) %arg1) #0 { ; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none) ; CHECK-LABEL: define float @fadd_known_positive_normal_except0_daz ; CHECK-SAME: (float nofpclass(ninf nnorm) [[ARG0:%.*]], float nofpclass(ninf nnorm) [[ARG1:%.*]]) #[[ATTR10]] { ; CHECK-NEXT: [[ADD:%.*]] = fadd float [[ARG0]], [[ARG1]] ; CHECK-NEXT: ret float [[ADD]] ; %add = fadd float %arg0, %arg1 ret float %add } define float @fadd_known_positive_normal_dapz(float nofpclass(ninf nnorm nzero) %arg0, float nofpclass(ninf nnorm nzero) %arg1) #3 { ; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none) ; CHECK-LABEL: define nofpclass(nzero) float @fadd_known_positive_normal_dapz ; CHECK-SAME: (float nofpclass(ninf nzero nnorm) [[ARG0:%.*]], float nofpclass(ninf nzero nnorm) [[ARG1:%.*]]) #[[ATTR9]] { ; CHECK-NEXT: [[ADD:%.*]] = fadd float [[ARG0]], [[ARG1]] ; CHECK-NEXT: ret float [[ADD]] ; %add = fadd float %arg0, %arg1 ret float %add } define internal float @returns_fence(float %arg) { ; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none) ; TUNIT-LABEL: define internal float @returns_fence ; TUNIT-SAME: (float nofpclass(nan inf) [[ARG:%.*]]) #[[ATTR3]] { ; TUNIT-NEXT: [[RET:%.*]] = call float @llvm.arithmetic.fence.f32(float [[ARG]]) #[[ATTR22]] ; TUNIT-NEXT: ret float [[RET]] ; ; CGSCC: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none) ; CGSCC-LABEL: define internal float @returns_fence ; CGSCC-SAME: (float nofpclass(nan inf) [[ARG:%.*]]) #[[ATTR3]] { ; CGSCC-NEXT: [[RET:%.*]] = call float @llvm.arithmetic.fence.f32(float nofpclass(nan inf) [[ARG]]) #[[ATTR19]] ; CGSCC-NEXT: ret float [[RET]] ; %ret = call float @llvm.arithmetic.fence.f32(float %arg) ret float %ret } ; Check that the func0 callsite is marked with both no inf and no nan define internal float @refine_callsite_attribute(float nofpclass(inf) %arg) { ; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none) ; TUNIT-LABEL: define internal float @refine_callsite_attribute ; TUNIT-SAME: (float nofpclass(inf) [[ARG:%.*]]) #[[ATTR3]] { ; TUNIT-NEXT: [[FUNC0:%.*]] = call float @returns_fence(float nofpclass(nan inf) [[ARG]]) #[[ATTR19]] ; TUNIT-NEXT: [[RET:%.*]] = call float @llvm.arithmetic.fence.f32(float [[FUNC0]]) #[[ATTR22]] ; TUNIT-NEXT: ret float [[RET]] ; ; CGSCC: Function Attrs: mustprogress nofree nosync nounwind willreturn memory(none) ; CGSCC-LABEL: define internal float @refine_callsite_attribute ; CGSCC-SAME: (float nofpclass(inf) [[ARG:%.*]]) #[[ATTR4]] { ; CGSCC-NEXT: [[FUNC0:%.*]] = call float @returns_fence(float nofpclass(nan inf) [[ARG]]) #[[ATTR19]] ; CGSCC-NEXT: [[RET:%.*]] = call float @llvm.arithmetic.fence.f32(float [[FUNC0]]) #[[ATTR19]] ; CGSCC-NEXT: ret float [[RET]] ; %func0 = call float @returns_fence(float nofpclass(nan) %arg) %ret = call float @llvm.arithmetic.fence.f32(float %func0) ret float %ret } define float @user(float %arg) { ; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none) ; TUNIT-LABEL: define float @user ; TUNIT-SAME: (float [[ARG:%.*]]) #[[ATTR3]] { ; TUNIT-NEXT: [[FUNC1:%.*]] = call float @refine_callsite_attribute(float nofpclass(inf) [[ARG]]) #[[ATTR19]] ; TUNIT-NEXT: ret float [[FUNC1]] ; ; CGSCC: Function Attrs: mustprogress nofree nosync nounwind willreturn memory(none) ; CGSCC-LABEL: define float @user ; CGSCC-SAME: (float [[ARG:%.*]]) #[[ATTR4]] { ; CGSCC-NEXT: [[FUNC1:%.*]] = call float @refine_callsite_attribute(float nofpclass(inf) [[ARG]]) #[[ATTR19]] ; CGSCC-NEXT: ret float [[FUNC1]] ; %func1 = call float @refine_callsite_attribute(float %arg) ret float %func1 } ; value is passed through memory define internal float @through_memory0(ptr %ptr.arg) { ; CGSCC: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none) ; CGSCC-LABEL: define internal float @through_memory0 ; CGSCC-SAME: (float [[TMP0:%.*]]) #[[ATTR3]] { ; CGSCC-NEXT: [[PTR_ARG_PRIV:%.*]] = alloca float, align 4 ; CGSCC-NEXT: store float [[TMP0]], ptr [[PTR_ARG_PRIV]], align 4 ; CGSCC-NEXT: [[LOAD:%.*]] = load float, ptr [[PTR_ARG_PRIV]], align 4 ; CGSCC-NEXT: ret float [[LOAD]] ; %load = load float, ptr %ptr.arg ret float %load } ; value is passed through memory and goes through an inferrable FP user define internal float @through_memory1(ptr %ptr.arg) { ; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none) ; TUNIT-LABEL: define internal float @through_memory1 ; TUNIT-SAME: (float [[TMP0:%.*]]) #[[ATTR3]] { ; TUNIT-NEXT: [[PTR_ARG_PRIV:%.*]] = alloca float, align 4 ; TUNIT-NEXT: store float [[TMP0]], ptr [[PTR_ARG_PRIV]], align 4 ; TUNIT-NEXT: [[LOAD:%.*]] = load float, ptr [[PTR_ARG_PRIV]], align 4 ; TUNIT-NEXT: [[CALL:%.*]] = call float @llvm.arithmetic.fence.f32(float [[LOAD]]) #[[ATTR22]] ; TUNIT-NEXT: ret float [[CALL]] ; ; CGSCC: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none) ; CGSCC-LABEL: define internal float @through_memory1 ; CGSCC-SAME: (float [[TMP0:%.*]]) #[[ATTR3]] { ; CGSCC-NEXT: [[PTR_ARG_PRIV:%.*]] = alloca float, align 4 ; CGSCC-NEXT: store float [[TMP0]], ptr [[PTR_ARG_PRIV]], align 4 ; CGSCC-NEXT: [[LOAD:%.*]] = load float, ptr [[PTR_ARG_PRIV]], align 4 ; CGSCC-NEXT: [[CALL:%.*]] = call float @llvm.arithmetic.fence.f32(float [[LOAD]]) #[[ATTR19]] ; CGSCC-NEXT: ret float [[CALL]] ; %load = load float, ptr %ptr.arg %call = call float @llvm.arithmetic.fence.f32(float %load) ret float %call } ; value is passed through memory and goes through an uninferrable FP user define internal float @through_memory2(ptr %ptr.arg) { ; CHECK: Function Attrs: memory(readwrite, argmem: none) ; CHECK-LABEL: define internal float @through_memory2 ; CHECK-SAME: (float [[TMP0:%.*]]) #[[ATTR15:[0-9]+]] { ; CHECK-NEXT: [[PTR_ARG_PRIV:%.*]] = alloca float, align 4 ; CHECK-NEXT: store float [[TMP0]], ptr [[PTR_ARG_PRIV]], align 4 ; CHECK-NEXT: [[LOAD:%.*]] = load float, ptr [[PTR_ARG_PRIV]], align 4 ; CHECK-NEXT: [[CALL:%.*]] = call float @extern.f32(float [[LOAD]]) ; CHECK-NEXT: ret float [[CALL]] ; %load = load float, ptr %ptr.arg %call = call float @extern.f32(float %load) ret float %call } define float @call_through_memory0(float nofpclass(nan) %val) { ; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none) ; TUNIT-LABEL: define nofpclass(nan) float @call_through_memory0 ; TUNIT-SAME: (float returned nofpclass(nan) [[VAL:%.*]]) #[[ATTR3]] { ; TUNIT-NEXT: [[ALLOCA:%.*]] = alloca float, align 4 ; TUNIT-NEXT: store float [[VAL]], ptr [[ALLOCA]], align 4 ; TUNIT-NEXT: ret float [[VAL]] ; ; CGSCC: Function Attrs: mustprogress nofree nosync nounwind willreturn memory(none) ; CGSCC-LABEL: define float @call_through_memory0 ; CGSCC-SAME: (float nofpclass(nan) [[VAL:%.*]]) #[[ATTR4]] { ; CGSCC-NEXT: [[ALLOCA:%.*]] = alloca float, align 4 ; CGSCC-NEXT: store float [[VAL]], ptr [[ALLOCA]], align 4 ; CGSCC-NEXT: [[THROUGH_MEMORY:%.*]] = call float @through_memory0(float nofpclass(nan) [[VAL]]) #[[ATTR19]] ; CGSCC-NEXT: ret float [[THROUGH_MEMORY]] ; %alloca = alloca float store float %val, ptr %alloca %through_memory = call float @through_memory0(ptr %alloca) ret float %through_memory } define float @call_through_memory1(float nofpclass(nan) %val) { ; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none) ; TUNIT-LABEL: define float @call_through_memory1 ; TUNIT-SAME: (float nofpclass(nan) [[VAL:%.*]]) #[[ATTR3]] { ; TUNIT-NEXT: [[ALLOCA:%.*]] = alloca float, align 4 ; TUNIT-NEXT: store float [[VAL]], ptr [[ALLOCA]], align 4 ; TUNIT-NEXT: [[TMP1:%.*]] = load float, ptr [[ALLOCA]], align 4 ; TUNIT-NEXT: [[THROUGH_MEMORY:%.*]] = call float @through_memory1(float [[TMP1]]) #[[ATTR21]] ; TUNIT-NEXT: ret float [[THROUGH_MEMORY]] ; ; CGSCC: Function Attrs: mustprogress nofree nosync nounwind willreturn memory(none) ; CGSCC-LABEL: define float @call_through_memory1 ; CGSCC-SAME: (float nofpclass(nan) [[VAL:%.*]]) #[[ATTR4]] { ; CGSCC-NEXT: [[ALLOCA:%.*]] = alloca float, align 4 ; CGSCC-NEXT: store float [[VAL]], ptr [[ALLOCA]], align 4 ; CGSCC-NEXT: [[THROUGH_MEMORY:%.*]] = call float @through_memory1(float nofpclass(nan) [[VAL]]) #[[ATTR19]] ; CGSCC-NEXT: ret float [[THROUGH_MEMORY]] ; %alloca = alloca float store float %val, ptr %alloca %through_memory = call float @through_memory1(ptr %alloca) ret float %through_memory } define float @call_through_memory2(float nofpclass(nan) %val) { ; TUNIT-LABEL: define float @call_through_memory2 ; TUNIT-SAME: (float nofpclass(nan) [[VAL:%.*]]) { ; TUNIT-NEXT: [[ALLOCA:%.*]] = alloca float, align 4 ; TUNIT-NEXT: store float [[VAL]], ptr [[ALLOCA]], align 4 ; TUNIT-NEXT: [[TMP1:%.*]] = load float, ptr [[ALLOCA]], align 4 ; TUNIT-NEXT: [[THROUGH_MEMORY:%.*]] = call float @through_memory2(float [[TMP1]]) ; TUNIT-NEXT: ret float [[THROUGH_MEMORY]] ; ; CGSCC-LABEL: define float @call_through_memory2 ; CGSCC-SAME: (float nofpclass(nan) [[VAL:%.*]]) { ; CGSCC-NEXT: [[ALLOCA:%.*]] = alloca float, align 4 ; CGSCC-NEXT: store float [[VAL]], ptr [[ALLOCA]], align 4 ; CGSCC-NEXT: [[THROUGH_MEMORY:%.*]] = call float @through_memory2(float nofpclass(nan) [[VAL]]) ; CGSCC-NEXT: ret float [[THROUGH_MEMORY]] ; %alloca = alloca float store float %val, ptr %alloca %through_memory = call float @through_memory2(ptr %alloca) ret float %through_memory } define amdgpu_kernel void @fast_pow_kernel(ptr addrspace(1) nocapture noundef writeonly align 4 %out, ptr addrspace(1) nocapture noundef readonly align 4 %in1, ptr addrspace(1) nocapture noundef readonly align 4 %in2) { ; CHECK-LABEL: define amdgpu_kernel void @fast_pow_kernel ; CHECK-SAME: (ptr addrspace(1) nocapture nofree noundef writeonly align 4 [[OUT:%.*]], ptr addrspace(1) nocapture nofree noundef readonly align 4 [[IN1:%.*]], ptr addrspace(1) nocapture nofree noundef readonly align 4 [[IN2:%.*]]) { ; CHECK-NEXT: entry: ; CHECK-NEXT: [[CALL:%.*]] = tail call i64 @_Z13get_global_idj(i32 noundef 0) ; CHECK-NEXT: [[SEXT:%.*]] = shl i64 [[CALL]], 32 ; CHECK-NEXT: [[IDXPROM:%.*]] = ashr exact i64 [[SEXT]], 32 ; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds float, ptr addrspace(1) [[IN1]], i64 [[IDXPROM]] ; CHECK-NEXT: [[I:%.*]] = load float, ptr addrspace(1) [[ARRAYIDX]], align 4 ; CHECK-NEXT: [[ARRAYIDX2:%.*]] = getelementptr inbounds float, ptr addrspace(1) [[IN2]], i64 [[IDXPROM]] ; CHECK-NEXT: [[I1:%.*]] = load float, ptr addrspace(1) [[ARRAYIDX2]], align 4 ; CHECK-NEXT: [[CALL3:%.*]] = tail call reassoc nnan ninf nsz arcp afn nofpclass(nan inf) float @pow_wrapper(float noundef nofpclass(nan inf) [[I]], float noundef nofpclass(nan inf) [[I1]]) ; CHECK-NEXT: [[ARRAYIDX5:%.*]] = getelementptr inbounds float, ptr addrspace(1) [[OUT]], i64 [[IDXPROM]] ; CHECK-NEXT: store float [[CALL3]], ptr addrspace(1) [[ARRAYIDX5]], align 4 ; CHECK-NEXT: ret void ; entry: %call = tail call i64 @_Z13get_global_idj(i32 noundef 0) %sext = shl i64 %call, 32 %idxprom = ashr exact i64 %sext, 32 %arrayidx = getelementptr inbounds float, ptr addrspace(1) %in1, i64 %idxprom %i = load float, ptr addrspace(1) %arrayidx, align 4 %arrayidx2 = getelementptr inbounds float, ptr addrspace(1) %in2, i64 %idxprom %i1 = load float, ptr addrspace(1) %arrayidx2, align 4 %call3 = tail call reassoc nnan ninf nsz arcp afn nofpclass(nan inf) float @pow_wrapper(float noundef nofpclass(nan inf) %i, float noundef nofpclass(nan inf) %i1) %arrayidx5 = getelementptr inbounds float, ptr addrspace(1) %out, i64 %idxprom store float %call3, ptr addrspace(1) %arrayidx5, align 4 ret void } define internal float @pow_wrapper(float %arg, float %arg1) { ; TUNIT: Function Attrs: norecurse ; TUNIT-LABEL: define internal float @pow_wrapper ; TUNIT-SAME: (float noundef nofpclass(nan inf) [[ARG:%.*]], float noundef nofpclass(nan inf) [[ARG1:%.*]]) #[[ATTR16:[0-9]+]] { ; TUNIT-NEXT: bb: ; TUNIT-NEXT: [[I:%.*]] = tail call float @pow_impl(float noundef nofpclass(nan inf) [[ARG]], float noundef nofpclass(nan inf) [[ARG1]]) ; TUNIT-NEXT: ret float [[I]] ; ; CGSCC-LABEL: define internal float @pow_wrapper ; CGSCC-SAME: (float noundef nofpclass(nan inf) [[ARG:%.*]], float noundef nofpclass(nan inf) [[ARG1:%.*]]) { ; CGSCC-NEXT: bb: ; CGSCC-NEXT: [[I:%.*]] = tail call float @pow_impl(float noundef nofpclass(nan inf) [[ARG]], float noundef nofpclass(nan inf) [[ARG1]]) ; CGSCC-NEXT: ret float [[I]] ; bb: %i = tail call float @pow_impl(float %arg, float %arg1) ret float %i } ; nofpclass(nan inf) should reach here through pow_wrapper define internal float @pow_impl(float %arg, float %arg1) { ; TUNIT: Function Attrs: norecurse ; TUNIT-LABEL: define internal float @pow_impl ; TUNIT-SAME: (float noundef nofpclass(nan inf) [[ARG:%.*]], float noundef nofpclass(nan inf) [[ARG1:%.*]]) #[[ATTR16]] { ; TUNIT-NEXT: bb: ; TUNIT-NEXT: [[IMPLEMENT_POW:%.*]] = call float asm " ; TUNIT-NEXT: ret float [[IMPLEMENT_POW]] ; ; CGSCC: Function Attrs: norecurse ; CGSCC-LABEL: define internal float @pow_impl ; CGSCC-SAME: (float [[ARG:%.*]], float [[ARG1:%.*]]) #[[ATTR16:[0-9]+]] { ; CGSCC-NEXT: bb: ; CGSCC-NEXT: [[IMPLEMENT_POW:%.*]] = call float asm " ; CGSCC-NEXT: ret float [[IMPLEMENT_POW]] ; bb: %implement.pow = call float asm " ; do pow $0, $1, $2", "=v,v,v"(float %arg, float %arg1) ret float %implement.pow } declare i64 @_Z13get_global_idj(i32 noundef) attributes #0 = { "denormal-fp-math"="preserve-sign,preserve-sign" } attributes #1 = { "denormal-fp-math"="preserve-sign,ieee" } attributes #2 = { "denormal-fp-math"="ieee,preserve-sign" } attributes #3 = { "denormal-fp-math"="positive-zero,positive-zero" } attributes #4 = { "denormal-fp-math"="positive-zero,ieee" } attributes #5 = { "denormal-fp-math"="ieee,positive-zero" }