; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6 ; RUN: opt -S -passes=instcombine < %s | FileCheck %s declare nofpclass(nan inf sub norm) half @returns_zero() declare nofpclass(nan inf nzero sub norm) half @returns_pzero() declare nofpclass(nan inf pzero sub norm) half @returns_nzero() declare nofpclass(inf sub norm) half @returns_zero_or_nan() declare nofpclass(inf nzero sub norm) half @returns_pzero_or_nan() declare nofpclass(inf pzero sub norm) half @returns_nzero_or_nan() declare nofpclass(nan zero sub norm) half @returns_inf() declare nofpclass(nan ninf zero sub norm) half @returns_pinf() declare nofpclass(nan pinf zero sub norm) half @returns_ninf() declare nofpclass(zero sub norm) half @returns_inf_or_nan() declare nofpclass(ninf nzero nsub nnorm) half @returns_positive_or_nan() declare nofpclass(pinf pzero psub pnorm) half @returns_negative_or_nan() declare nofpclass(nan ninf nzero nsub nnorm) half @returns_positive() declare nofpclass(nan pinf pzero psub pnorm) half @returns_negative() declare nofpclass(inf zero sub norm) half @returns_nan() declare nofpclass(qnan inf zero sub norm) half @returns_snan() declare nofpclass(nan inf zero sub) half @returns_norm() declare nofpclass(nan inf zero sub pnorm) half @returns_nnorm() declare nofpclass(nan inf zero sub nnorm) half @returns_pnorm() declare nofpclass(nan inf zero norm) half @returns_sub() declare nofpclass(nan inf zero psub norm) half @returns_nsub() declare nofpclass(nan inf zero nsub norm) half @returns_psub() declare void @use(half) define nofpclass(inf zero sub norm) half @ret_only_nan(half %x, half %y) { ; CHECK-LABEL: define nofpclass(inf zero sub norm) half @ret_only_nan( ; CHECK-SAME: half [[X:%.*]], half [[Y:%.*]]) { ; CHECK-NEXT: ret half +qnan ; %add = fadd half %x, %y ret half %add } define nofpclass(snan inf zero sub norm) half @ret_only_qnan(half %x, half %y) { ; CHECK-LABEL: define nofpclass(snan inf zero sub norm) half @ret_only_qnan( ; CHECK-SAME: half [[X:%.*]], half [[Y:%.*]]) { ; CHECK-NEXT: ret half +qnan ; %add = fadd half %x, %y ret half %add } define nofpclass(qnan inf zero sub norm) half @ret_only_snan(half %x, half %y) { ; CHECK-LABEL: define nofpclass(qnan inf zero sub norm) half @ret_only_snan( ; CHECK-SAME: half [[X:%.*]], half [[Y:%.*]]) { ; CHECK-NEXT: [[ADD:%.*]] = fadd half [[X]], [[Y]] ; CHECK-NEXT: ret half [[ADD]] ; %add = fadd half %x, %y ret half %add } define nofpclass(nan inf sub norm) half @ret_only_zero(half %x, half %y) { ; CHECK-LABEL: define nofpclass(nan inf sub norm) half @ret_only_zero( ; CHECK-SAME: half [[X:%.*]], half [[Y:%.*]]) { ; CHECK-NEXT: [[ADD:%.*]] = fadd nnan ninf half [[X]], [[Y]] ; CHECK-NEXT: ret half [[ADD]] ; %add = fadd half %x, %y ret half %add } define nofpclass(nan inf nzero sub norm) half @ret_only_pzero(half %x, half %y) { ; CHECK-LABEL: define nofpclass(nan inf nzero sub norm) half @ret_only_pzero( ; CHECK-SAME: half [[X:%.*]], half [[Y:%.*]]) { ; CHECK-NEXT: ret half 0.000000e+00 ; %add = fadd half %x, %y ret half %add } define nofpclass(nan inf pzero sub norm) half @ret_only_nzero(half %x, half %y) { ; CHECK-LABEL: define nofpclass(nan inf pzero sub norm) half @ret_only_nzero( ; CHECK-SAME: half [[X:%.*]], half [[Y:%.*]]) { ; CHECK-NEXT: ret half -0.000000e+00 ; %add = fadd half %x, %y ret half %add } define nofpclass(nan zero sub norm) half @ret_only_inf(half %x, half %y) { ; CHECK-LABEL: define nofpclass(nan zero sub norm) half @ret_only_inf( ; CHECK-SAME: half [[X:%.*]], half [[Y:%.*]]) { ; CHECK-NEXT: [[ADD:%.*]] = fadd nnan half [[X]], [[Y]] ; CHECK-NEXT: ret half [[ADD]] ; %add = fadd half %x, %y ret half %add } define nofpclass(nan ninf zero sub norm) half @ret_only_pinf(half %x, half %y) { ; CHECK-LABEL: define nofpclass(nan ninf zero sub norm) half @ret_only_pinf( ; CHECK-SAME: half [[X:%.*]], half [[Y:%.*]]) { ; CHECK-NEXT: ret half +inf ; %add = fadd half %x, %y ret half %add } define nofpclass(nan pinf zero sub norm) half @ret_only_ninf(half %x, half %y) { ; CHECK-LABEL: define nofpclass(nan pinf zero sub norm) half @ret_only_ninf( ; CHECK-SAME: half [[X:%.*]], half [[Y:%.*]]) { ; CHECK-NEXT: ret half -inf ; %add = fadd half %x, %y ret half %add } define nofpclass(pinf) half @ret_nofpclass_pinf__fadd_select_unknown_or_pinf__unknown(i1 %cond, half %x, half %y) { ; CHECK-LABEL: define nofpclass(pinf) half @ret_nofpclass_pinf__fadd_select_unknown_or_pinf__unknown( ; CHECK-SAME: i1 [[COND:%.*]], half [[X:%.*]], half [[Y:%.*]]) { ; CHECK-NEXT: [[X_OR_PINF:%.*]] = select i1 [[COND]], half [[X]], half +inf ; CHECK-NEXT: [[ADD:%.*]] = fadd half [[X_OR_PINF]], [[Y]] ; CHECK-NEXT: ret half [[ADD]] ; %x.or.pinf = select i1 %cond, half %x, half 0xH7C00 %add = fadd half %x.or.pinf, %y ret half %add } define nofpclass(pinf) half @ret_nofpclass_pinf__fadd_unknown__select_unknown_or_pinf(i1 %cond, half %x, half %y) { ; CHECK-LABEL: define nofpclass(pinf) half @ret_nofpclass_pinf__fadd_unknown__select_unknown_or_pinf( ; CHECK-SAME: i1 [[COND:%.*]], half [[X:%.*]], half [[Y:%.*]]) { ; CHECK-NEXT: [[Y_OR_PINF:%.*]] = select i1 [[COND]], half [[Y]], half +inf ; CHECK-NEXT: [[ADD:%.*]] = fadd half [[X]], [[Y_OR_PINF]] ; CHECK-NEXT: ret half [[ADD]] ; %y.or.pinf = select i1 %cond, half %y, half 0xH7C00 %add = fadd half %x, %y.or.pinf ret half %add } define nofpclass(inf) half @ret_nofpclass_inf__fadd_select_unknown_or_inf__unknown(i1 %cond, half %x, half %y) { ; CHECK-LABEL: define nofpclass(inf) half @ret_nofpclass_inf__fadd_select_unknown_or_inf__unknown( ; CHECK-SAME: i1 [[COND:%.*]], half [[X:%.*]], half [[Y:%.*]]) { ; CHECK-NEXT: [[INF:%.*]] = call half @returns_inf() ; CHECK-NEXT: [[X_OR_INF:%.*]] = select i1 [[COND]], half [[X]], half [[INF]] ; CHECK-NEXT: [[ADD:%.*]] = fadd half [[X_OR_INF]], [[Y]] ; CHECK-NEXT: ret half [[ADD]] ; %inf = call half @returns_inf() %x.or.inf = select i1 %cond, half %x, half %inf %add = fadd half %x.or.inf, %y ret half %add } define nofpclass(inf) half @ret_nofpclass_inf__fadd_unknown__select_unknown_or_inf(i1 %cond, half %x, half %y) { ; CHECK-LABEL: define nofpclass(inf) half @ret_nofpclass_inf__fadd_unknown__select_unknown_or_inf( ; CHECK-SAME: i1 [[COND:%.*]], half [[X:%.*]], half [[Y:%.*]]) { ; CHECK-NEXT: [[INF:%.*]] = call half @returns_inf() ; CHECK-NEXT: [[Y_OR_INF:%.*]] = select i1 [[COND]], half [[Y]], half [[INF]] ; CHECK-NEXT: [[ADD:%.*]] = fadd half [[X]], [[Y_OR_INF]] ; CHECK-NEXT: ret half [[ADD]] ; %inf = call half @returns_inf() %y.or.inf = select i1 %cond, half %y, half %inf %add = fadd half %x, %y.or.inf ret half %add } define nofpclass(pinf) half @ret_nofpclass_pinf__fadd_select_unknown_or_pinf(i1 %cond, half %x, half %y) { ; CHECK-LABEL: define nofpclass(pinf) half @ret_nofpclass_pinf__fadd_select_unknown_or_pinf( ; CHECK-SAME: i1 [[COND:%.*]], half [[X:%.*]], half [[Y:%.*]]) { ; CHECK-NEXT: [[TMP1:%.*]] = fadd half [[X]], [[Y]] ; CHECK-NEXT: ret half [[TMP1]] ; %x.or.pinf = select i1 %cond, half %x, half 0xH7C00 %y.or.pinf = select i1 %cond, half %y, half 0xH7C00 %add = fadd half %x.or.pinf, %y.or.pinf ret half %add } define nofpclass(ninf) half @ret_nofpclass_ninf__fadd_select_unknown_or_ninf(i1 %cond, half %x, half %y) { ; CHECK-LABEL: define nofpclass(ninf) half @ret_nofpclass_ninf__fadd_select_unknown_or_ninf( ; CHECK-SAME: i1 [[COND:%.*]], half [[X:%.*]], half [[Y:%.*]]) { ; CHECK-NEXT: [[TMP1:%.*]] = fadd half [[X]], [[Y]] ; CHECK-NEXT: ret half [[TMP1]] ; %x.or.ninf = select i1 %cond, half %x, half 0xHFC00 %y.or.ninf = select i1 %cond, half %y, half 0xHFC00 %add = fadd half %x.or.ninf, %y.or.ninf ret half %add } define nofpclass(inf) half @ret_nofpclass_inf__fadd_select_unknown_or_inf(i1 %cond, half %x, half %y) { ; CHECK-LABEL: define nofpclass(inf) half @ret_nofpclass_inf__fadd_select_unknown_or_inf( ; CHECK-SAME: i1 [[COND:%.*]], half [[X:%.*]], half [[Y:%.*]]) { ; CHECK-NEXT: [[INF0:%.*]] = call half @returns_inf() ; CHECK-NEXT: [[INF1:%.*]] = call half @returns_inf() ; CHECK-NEXT: [[X_OR_INF:%.*]] = select i1 [[COND]], half [[X]], half [[INF0]] ; CHECK-NEXT: [[Y_OR_INF:%.*]] = select i1 [[COND]], half [[Y]], half [[INF1]] ; CHECK-NEXT: [[ADD:%.*]] = fadd half [[X_OR_INF]], [[Y_OR_INF]] ; CHECK-NEXT: ret half [[ADD]] ; %inf0 = call half @returns_inf() %inf1 = call half @returns_inf() %x.or.inf = select i1 %cond, half %x, half %inf0 %y.or.inf = select i1 %cond, half %y, half %inf1 %add = fadd half %x.or.inf, %y.or.inf ret half %add } define nofpclass(nan inf) half @ret_nofpclass_inf_nan__fadd_select_unknown_or_inf(i1 %cond, half %x, half %y) { ; CHECK-LABEL: define nofpclass(nan inf) half @ret_nofpclass_inf_nan__fadd_select_unknown_or_inf( ; CHECK-SAME: i1 [[COND:%.*]], half [[X:%.*]], half [[Y:%.*]]) { ; CHECK-NEXT: [[INF0:%.*]] = call half @returns_inf() ; CHECK-NEXT: [[INF1:%.*]] = call half @returns_inf() ; CHECK-NEXT: [[ADD:%.*]] = fadd nnan ninf half [[X]], [[Y]] ; CHECK-NEXT: ret half [[ADD]] ; %inf0 = call half @returns_inf() %inf1 = call half @returns_inf() %x.or.inf = select i1 %cond, half %x, half %inf0 %y.or.inf = select i1 %cond, half %y, half %inf1 %add = fadd half %x.or.inf, %y.or.inf ret half %add } ; Cannot prune the select, the result could be nan depending on %x define nofpclass(inf sub norm) half @nan_result_demands_inf_input_lhs(i1 %cond, half nofpclass(zero) %x, half nofpclass(zero inf nan) %y) { ; CHECK-LABEL: define nofpclass(inf sub norm) half @nan_result_demands_inf_input_lhs( ; CHECK-SAME: i1 [[COND:%.*]], half nofpclass(zero) [[X:%.*]], half nofpclass(nan inf zero) [[Y:%.*]]) { ; CHECK-NEXT: [[PINF:%.*]] = call half @returns_pinf() ; CHECK-NEXT: [[X_OR_INF:%.*]] = select i1 [[COND]], half [[X]], half +inf ; CHECK-NEXT: [[ADD:%.*]] = fadd half [[X_OR_INF]], [[Y]] ; CHECK-NEXT: ret half [[ADD]] ; %pinf = call half @returns_pinf() %x.or.inf = select i1 %cond, half %x, half %pinf %add = fadd half %x.or.inf, %y ret half %add } ; Cannot prune the select, the result could be nan depending on %y define nofpclass(inf sub norm) half @nan_result_demands_inf_input_rhs(i1 %cond, half nofpclass(zero) %x, half %y) { ; CHECK-LABEL: define nofpclass(inf sub norm) half @nan_result_demands_inf_input_rhs( ; CHECK-SAME: i1 [[COND:%.*]], half nofpclass(zero) [[X:%.*]], half [[Y:%.*]]) { ; CHECK-NEXT: [[PINF:%.*]] = call half @returns_pinf() ; CHECK-NEXT: [[Y_OR_INF:%.*]] = select i1 [[COND]], half [[Y]], half +inf ; CHECK-NEXT: [[ADD:%.*]] = fadd half [[X]], [[Y_OR_INF]] ; CHECK-NEXT: ret half [[ADD]] ; %pinf = call half @returns_pinf() %y.or.inf = select i1 %cond, half %y, half %pinf %add = fadd half %x, %y.or.inf ret half %add } ; Cannot prune the select define nofpclass(nan sub norm zero) half @inf_result_demands_inf_input_lhs(i1 %cond, half nofpclass(zero) %x, half nofpclass(zero) %y) { ; CHECK-LABEL: define nofpclass(nan zero sub norm) half @inf_result_demands_inf_input_lhs( ; CHECK-SAME: i1 [[COND:%.*]], half nofpclass(zero) [[X:%.*]], half nofpclass(zero) [[Y:%.*]]) { ; CHECK-NEXT: [[INF:%.*]] = call half @returns_inf() ; CHECK-NEXT: [[X_OR_INF:%.*]] = select i1 [[COND]], half [[X]], half [[INF]] ; CHECK-NEXT: [[ADD:%.*]] = fadd nnan half [[X_OR_INF]], [[Y]] ; CHECK-NEXT: ret half [[ADD]] ; %inf = call half @returns_inf() %x.or.inf = select i1 %cond, half %x, half %inf %add = fadd half %x.or.inf, %y ret half %add } ; Cannot prune the select define nofpclass(nan sub norm zero) half @inf_result_demands_inf_input_rhs(i1 %cond, half nofpclass(zero) %x, half nofpclass(zero) %y) { ; CHECK-LABEL: define nofpclass(nan zero sub norm) half @inf_result_demands_inf_input_rhs( ; CHECK-SAME: i1 [[COND:%.*]], half nofpclass(zero) [[X:%.*]], half nofpclass(zero) [[Y:%.*]]) { ; CHECK-NEXT: [[INF:%.*]] = call half @returns_inf() ; CHECK-NEXT: [[Y_OR_INF:%.*]] = select i1 [[COND]], half [[Y]], half [[INF]] ; CHECK-NEXT: [[ADD:%.*]] = fadd nnan half [[X]], [[Y_OR_INF]] ; CHECK-NEXT: ret half [[ADD]] ; %inf = call half @returns_inf() %y.or.inf = select i1 %cond, half %y, half %inf %add = fadd half %x, %y.or.inf ret half %add } ; Cannot prune the select define nofpclass(nan sub norm zero) half @inf_result_demands_pinf_input_lhs(i1 %cond, half nofpclass(zero) %x, half nofpclass(zero) %y) { ; CHECK-LABEL: define nofpclass(nan zero sub norm) half @inf_result_demands_pinf_input_lhs( ; CHECK-SAME: i1 [[COND:%.*]], half nofpclass(zero) [[X:%.*]], half nofpclass(zero) [[Y:%.*]]) { ; CHECK-NEXT: [[PINF:%.*]] = call half @returns_pinf() ; CHECK-NEXT: [[X_OR_INF:%.*]] = select i1 [[COND]], half [[X]], half +inf ; CHECK-NEXT: [[ADD:%.*]] = fadd nnan half [[X_OR_INF]], [[Y]] ; CHECK-NEXT: ret half [[ADD]] ; %pinf = call half @returns_pinf() %x.or.inf = select i1 %cond, half %x, half %pinf %add = fadd half %x.or.inf, %y ret half %add } ; Cannot prune the select define nofpclass(nan sub norm zero) half @inf_result_demands_pinf_input_rhs(i1 %cond, half nofpclass(zero) %x, half nofpclass(zero) %y) { ; CHECK-LABEL: define nofpclass(nan zero sub norm) half @inf_result_demands_pinf_input_rhs( ; CHECK-SAME: i1 [[COND:%.*]], half nofpclass(zero) [[X:%.*]], half nofpclass(zero) [[Y:%.*]]) { ; CHECK-NEXT: [[PINF:%.*]] = call half @returns_pinf() ; CHECK-NEXT: [[Y_OR_INF:%.*]] = select i1 [[COND]], half [[Y]], half +inf ; CHECK-NEXT: [[ADD:%.*]] = fadd nnan half [[X]], [[Y_OR_INF]] ; CHECK-NEXT: ret half [[ADD]] ; %pinf = call half @returns_pinf() %y.or.inf = select i1 %cond, half %y, half %pinf %add = fadd half %x, %y.or.inf ret half %add } ; Cannot prune the select define nofpclass(nan sub norm zero) half @inf_result_demands_ninf_input_lhs(i1 %cond, half nofpclass(zero) %x, half nofpclass(zero) %y) { ; CHECK-LABEL: define nofpclass(nan zero sub norm) half @inf_result_demands_ninf_input_lhs( ; CHECK-SAME: i1 [[COND:%.*]], half nofpclass(zero) [[X:%.*]], half nofpclass(zero) [[Y:%.*]]) { ; CHECK-NEXT: [[NINF:%.*]] = call half @returns_ninf() ; CHECK-NEXT: [[X_OR_INF:%.*]] = select i1 [[COND]], half [[X]], half -inf ; CHECK-NEXT: [[ADD:%.*]] = fadd nnan half [[X_OR_INF]], [[Y]] ; CHECK-NEXT: ret half [[ADD]] ; %ninf = call half @returns_ninf() %x.or.inf = select i1 %cond, half %x, half %ninf %add = fadd half %x.or.inf, %y ret half %add } ; Cannot prune the select define nofpclass(nan sub norm zero) half @inf_result_demands_ninf_input_rhs(i1 %cond, half nofpclass(zero) %x, half nofpclass(zero) %y) { ; CHECK-LABEL: define nofpclass(nan zero sub norm) half @inf_result_demands_ninf_input_rhs( ; CHECK-SAME: i1 [[COND:%.*]], half nofpclass(zero) [[X:%.*]], half nofpclass(zero) [[Y:%.*]]) { ; CHECK-NEXT: [[NINF:%.*]] = call half @returns_ninf() ; CHECK-NEXT: [[Y_OR_INF:%.*]] = select i1 [[COND]], half [[Y]], half -inf ; CHECK-NEXT: [[ADD:%.*]] = fadd nnan half [[X]], [[Y_OR_INF]] ; CHECK-NEXT: ret half [[ADD]] ; %ninf = call half @returns_ninf() %y.or.inf = select i1 %cond, half %y, half %ninf %add = fadd half %x, %y.or.inf ret half %add } ; Cannot add nnan flag from not-nan inputs, the result could still be ; nan define nofpclass(snan) half @no_nans_inputs(half nofpclass(nan) %x, half nofpclass(nan) %y) { ; CHECK-LABEL: define nofpclass(snan) half @no_nans_inputs( ; CHECK-SAME: half nofpclass(nan) [[X:%.*]], half nofpclass(nan) [[Y:%.*]]) { ; CHECK-NEXT: [[ADD:%.*]] = fadd half [[X]], [[Y]] ; CHECK-NEXT: ret half [[ADD]] ; %add = fadd half %x, %y ret half %add } ; Can add nnan flag if inputs and output known not-nan. define nofpclass(nan) half @no_nans_input_and_output(half nofpclass(nan) %x, half nofpclass(nan) %y) { ; CHECK-LABEL: define nofpclass(nan) half @no_nans_input_and_output( ; CHECK-SAME: half nofpclass(nan) [[X:%.*]], half nofpclass(nan) [[Y:%.*]]) { ; CHECK-NEXT: [[ADD:%.*]] = fadd nnan half [[X]], [[Y]] ; CHECK-NEXT: ret half [[ADD]] ; %add = fadd half %x, %y ret half %add } ; Cannot add ninf flag from not-inf inputs, the result could still be ; inf define nofpclass(snan) half @no_infs_inputs(half nofpclass(inf) %x, half nofpclass(inf) %y) { ; CHECK-LABEL: define nofpclass(snan) half @no_infs_inputs( ; CHECK-SAME: half nofpclass(inf) [[X:%.*]], half nofpclass(inf) [[Y:%.*]]) { ; CHECK-NEXT: [[ADD:%.*]] = fadd half [[X]], [[Y]] ; CHECK-NEXT: ret half [[ADD]] ; %add = fadd half %x, %y ret half %add } ; Can infer ninf flag define nofpclass(inf) half @no_infs_inputs_and_outputs(half nofpclass(inf) %x, half nofpclass(inf) %y) { ; CHECK-LABEL: define nofpclass(inf) half @no_infs_inputs_and_outputs( ; CHECK-SAME: half nofpclass(inf) [[X:%.*]], half nofpclass(inf) [[Y:%.*]]) { ; CHECK-NEXT: [[ADD:%.*]] = fadd ninf half [[X]], [[Y]] ; CHECK-NEXT: ret half [[ADD]] ; %add = fadd half %x, %y ret half %add } ; Can infer nnan flag, not ninf flag. define nofpclass(snan) half @no_nans_infs_inputs(half nofpclass(nan inf) %x, half nofpclass(nan inf) %y) { ; CHECK-LABEL: define nofpclass(snan) half @no_nans_infs_inputs( ; CHECK-SAME: half nofpclass(nan inf) [[X:%.*]], half nofpclass(nan inf) [[Y:%.*]]) { ; CHECK-NEXT: [[ADD:%.*]] = fadd nnan half [[X]], [[Y]] ; CHECK-NEXT: ret half [[ADD]] ; %add = fadd half %x, %y ret half %add } ; Can infer nnan, ninf define nofpclass(inf) half @no_nans_infs_inputs__noinfs_output(half nofpclass(nan inf) %x, half nofpclass(nan inf) %y) { ; CHECK-LABEL: define nofpclass(inf) half @no_nans_infs_inputs__noinfs_output( ; CHECK-SAME: half nofpclass(nan inf) [[X:%.*]], half nofpclass(nan inf) [[Y:%.*]]) { ; CHECK-NEXT: [[ADD:%.*]] = fadd nnan ninf half [[X]], [[Y]] ; CHECK-NEXT: ret half [[ADD]] ; %add = fadd half %x, %y ret half %add } ; Can only infer nnan, not ninf define nofpclass(nan) half @no_nans_infs_inputs__nonans_output(half nofpclass(nan inf) %x, half nofpclass(nan inf) %y) { ; CHECK-LABEL: define nofpclass(nan) half @no_nans_infs_inputs__nonans_output( ; CHECK-SAME: half nofpclass(nan inf) [[X:%.*]], half nofpclass(nan inf) [[Y:%.*]]) { ; CHECK-NEXT: [[ADD:%.*]] = fadd nnan half [[X]], [[Y]] ; CHECK-NEXT: ret half [[ADD]] ; %add = fadd half %x, %y ret half %add } ; Can infer nnan flag define nofpclass(nzero) half @inferred_nan_output__noinfs_only_lhs(half nofpclass(nan inf) %x, half nofpclass(nan) %y) { ; CHECK-LABEL: define nofpclass(nzero) half @inferred_nan_output__noinfs_only_lhs( ; CHECK-SAME: half nofpclass(nan inf) [[X:%.*]], half nofpclass(nan) [[Y:%.*]]) { ; CHECK-NEXT: [[ADD:%.*]] = fadd nnan half [[X]], [[Y]] ; CHECK-NEXT: ret half [[ADD]] ; %add = fadd half %x, %y ret half %add } ; Can infer nnan flag define nofpclass(nzero) half @inferred_nan_output__noinfs_only_rhs(half nofpclass(nan) %x, half nofpclass(nan inf) %y) { ; CHECK-LABEL: define nofpclass(nzero) half @inferred_nan_output__noinfs_only_rhs( ; CHECK-SAME: half nofpclass(nan) [[X:%.*]], half nofpclass(nan inf) [[Y:%.*]]) { ; CHECK-NEXT: [[ADD:%.*]] = fadd nnan half [[X]], [[Y]] ; CHECK-NEXT: ret half [[ADD]] ; %add = fadd half %x, %y ret half %add } define nofpclass(nzero) half @inferred_nan_output__fadd__nnan__no_ninf_no_nan(half nofpclass(nan) %x, half nofpclass(nan ninf) %y) { ; CHECK-LABEL: define nofpclass(nzero) half @inferred_nan_output__fadd__nnan__no_ninf_no_nan( ; CHECK-SAME: half nofpclass(nan) [[X:%.*]], half nofpclass(nan ninf) [[Y:%.*]]) { ; CHECK-NEXT: [[ADD:%.*]] = fadd half [[X]], [[Y]] ; CHECK-NEXT: ret half [[ADD]] ; %add = fadd half %x, %y ret half %add } define nofpclass(nzero) half @inferred_nan_output__fadd__no_ninf_no_nan__no_nan(half nofpclass(nan ninf) %x, half nofpclass(nan) %y) { ; CHECK-LABEL: define nofpclass(nzero) half @inferred_nan_output__fadd__no_ninf_no_nan__no_nan( ; CHECK-SAME: half nofpclass(nan ninf) [[X:%.*]], half nofpclass(nan) [[Y:%.*]]) { ; CHECK-NEXT: [[ADD:%.*]] = fadd half [[X]], [[Y]] ; CHECK-NEXT: ret half [[ADD]] ; %add = fadd half %x, %y ret half %add } define nofpclass(nzero) half @inferred_nan_output__fadd__no_nan__no_pinf_no_nan(half nofpclass(nan) %x, half nofpclass(nan pinf) %y) { ; CHECK-LABEL: define nofpclass(nzero) half @inferred_nan_output__fadd__no_nan__no_pinf_no_nan( ; CHECK-SAME: half nofpclass(nan) [[X:%.*]], half nofpclass(nan pinf) [[Y:%.*]]) { ; CHECK-NEXT: [[ADD:%.*]] = fadd half [[X]], [[Y]] ; CHECK-NEXT: ret half [[ADD]] ; %add = fadd half %x, %y ret half %add } define nofpclass(nzero) half @inferred_nan_output__fadd__no_pinf_no_nan__no_nan(half nofpclass(nan pinf) %x, half nofpclass(nan) %y) { ; CHECK-LABEL: define nofpclass(nzero) half @inferred_nan_output__fadd__no_pinf_no_nan__no_nan( ; CHECK-SAME: half nofpclass(nan pinf) [[X:%.*]], half nofpclass(nan) [[Y:%.*]]) { ; CHECK-NEXT: [[ADD:%.*]] = fadd half [[X]], [[Y]] ; CHECK-NEXT: ret half [[ADD]] ; %add = fadd half %x, %y ret half %add } define nofpclass(nzero) half @inferred_nan_output__fadd__no_pinf_no_nan__no_pinf_no_nan(half nofpclass(nan pinf) %x, half nofpclass(nan pinf) %y) { ; CHECK-LABEL: define nofpclass(nzero) half @inferred_nan_output__fadd__no_pinf_no_nan__no_pinf_no_nan( ; CHECK-SAME: half nofpclass(nan pinf) [[X:%.*]], half nofpclass(nan pinf) [[Y:%.*]]) { ; CHECK-NEXT: [[ADD:%.*]] = fadd nnan half [[X]], [[Y]] ; CHECK-NEXT: ret half [[ADD]] ; %add = fadd half %x, %y ret half %add } define nofpclass(nzero) half @inferred_nan_output__fadd__no_ninf_no_nan__no_ninf_no_nan(half nofpclass(nan ninf) %x, half nofpclass(nan ninf) %y) { ; CHECK-LABEL: define nofpclass(nzero) half @inferred_nan_output__fadd__no_ninf_no_nan__no_ninf_no_nan( ; CHECK-SAME: half nofpclass(nan ninf) [[X:%.*]], half nofpclass(nan ninf) [[Y:%.*]]) { ; CHECK-NEXT: [[ADD:%.*]] = fadd nnan half [[X]], [[Y]] ; CHECK-NEXT: ret half [[ADD]] ; %add = fadd half %x, %y ret half %add } ; Should be able to eliminate the fabs define nofpclass(nan) half @ret_nonan_fabs_fadd_known_positive_or_nan_sources() { ; CHECK-LABEL: define nofpclass(nan) half @ret_nonan_fabs_fadd_known_positive_or_nan_sources() { ; CHECK-NEXT: [[POSITIVE_OR_NAN0:%.*]] = call half @returns_positive_or_nan() ; CHECK-NEXT: [[POSITIVE_OR_NAN1:%.*]] = call half @returns_positive_or_nan() ; CHECK-NEXT: [[KNOWN_POSITIVE_ADD:%.*]] = fadd nnan half [[POSITIVE_OR_NAN0]], [[POSITIVE_OR_NAN1]] ; CHECK-NEXT: ret half [[KNOWN_POSITIVE_ADD]] ; %positive.or.nan0 = call half @returns_positive_or_nan() %positive.or.nan1 = call half @returns_positive_or_nan() %known.positive.add = fadd half %positive.or.nan0, %positive.or.nan1 %fabs = call half @llvm.fabs.f16(half %known.positive.add) ret half %fabs } ; Should be able to eliminate the fabs define nofpclass(nan) half @ret_nonan_fabs_fadd_known_positive_sources() { ; CHECK-LABEL: define nofpclass(nan) half @ret_nonan_fabs_fadd_known_positive_sources() { ; CHECK-NEXT: [[POSITIVE0:%.*]] = call half @returns_positive() ; CHECK-NEXT: [[POSITIVE1:%.*]] = call half @returns_positive() ; CHECK-NEXT: [[KNOWN_POSITIVE_ADD:%.*]] = fadd nnan half [[POSITIVE1]], [[POSITIVE1]] ; CHECK-NEXT: ret half [[KNOWN_POSITIVE_ADD]] ; %positive0 = call half @returns_positive() %positive1 = call half @returns_positive() %known.positive.add = fadd half %positive1, %positive1 %fabs = call half @llvm.fabs.f16(half %known.positive.add) ret half %fabs } define nofpclass(snan) half @unknown__fadd__inf(half %unknown) { ; CHECK-LABEL: define nofpclass(snan) half @unknown__fadd__inf( ; CHECK-SAME: half [[UNKNOWN:%.*]]) { ; CHECK-NEXT: [[INF:%.*]] = call half @returns_inf() ; CHECK-NEXT: [[ADD:%.*]] = fadd half [[UNKNOWN]], [[INF]] ; CHECK-NEXT: ret half [[ADD]] ; %inf = call half @returns_inf() %add = fadd half %unknown, %inf ret half %add } define nofpclass(snan) half @inf__fadd__unknown(half %unknown) { ; CHECK-LABEL: define nofpclass(snan) half @inf__fadd__unknown( ; CHECK-SAME: half [[UNKNOWN:%.*]]) { ; CHECK-NEXT: [[INF:%.*]] = call half @returns_inf() ; CHECK-NEXT: [[ADD:%.*]] = fadd half [[INF]], [[UNKNOWN]] ; CHECK-NEXT: ret half [[ADD]] ; %inf = call half @returns_inf() %add = fadd half %inf, %unknown ret half %add } define nofpclass(snan) half @unknown__fadd__inf_or_nan(half %unknown) { ; CHECK-LABEL: define nofpclass(snan) half @unknown__fadd__inf_or_nan( ; CHECK-SAME: half [[UNKNOWN:%.*]]) { ; CHECK-NEXT: [[INF_OR_NAN:%.*]] = call half @returns_inf_or_nan() ; CHECK-NEXT: [[ADD:%.*]] = fadd half [[UNKNOWN]], [[INF_OR_NAN]] ; CHECK-NEXT: ret half [[ADD]] ; %inf.or.nan = call half @returns_inf_or_nan() %add = fadd half %unknown, %inf.or.nan ret half %add } define nofpclass(snan) half @inf_or_nan__fadd__unknown(half %unknown) { ; CHECK-LABEL: define nofpclass(snan) half @inf_or_nan__fadd__unknown( ; CHECK-SAME: half [[UNKNOWN:%.*]]) { ; CHECK-NEXT: [[INF_OR_NAN:%.*]] = call half @returns_inf_or_nan() ; CHECK-NEXT: [[ADD:%.*]] = fadd half [[INF_OR_NAN]], [[UNKNOWN]] ; CHECK-NEXT: ret half [[ADD]] ; %inf.or.nan = call half @returns_inf_or_nan() %add = fadd half %inf.or.nan, %unknown ret half %add } define nofpclass(nan) half @ret_nonan__unknown__fadd__inf(half %unknown) { ; CHECK-LABEL: define nofpclass(nan) half @ret_nonan__unknown__fadd__inf( ; CHECK-SAME: half [[UNKNOWN:%.*]]) { ; CHECK-NEXT: [[INF:%.*]] = call half @returns_inf() ; CHECK-NEXT: ret half [[INF]] ; %inf = call half @returns_inf() %add = fadd half %unknown, %inf ret half %add } define nofpclass(nan) half @ret_nonan__inf__fadd__unknown(half %unknown) { ; CHECK-LABEL: define nofpclass(nan) half @ret_nonan__inf__fadd__unknown( ; CHECK-SAME: half [[UNKNOWN:%.*]]) { ; CHECK-NEXT: [[INF:%.*]] = call half @returns_inf() ; CHECK-NEXT: ret half [[INF]] ; %inf = call half @returns_inf() %add = fadd half %inf, %unknown ret half %add } define nofpclass(nan) half @ret_nonan__unknown__fadd__inf_or_nan(half %unknown) { ; CHECK-LABEL: define nofpclass(nan) half @ret_nonan__unknown__fadd__inf_or_nan( ; CHECK-SAME: half [[UNKNOWN:%.*]]) { ; CHECK-NEXT: [[INF_OR_NAN:%.*]] = call half @returns_inf_or_nan() ; CHECK-NEXT: ret half [[INF_OR_NAN]] ; %inf.or.nan = call half @returns_inf_or_nan() %add = fadd half %unknown, %inf.or.nan ret half %add } define nofpclass(nan) half @ret_nonan__inf_or_nan__fadd__unknown(half %unknown) { ; CHECK-LABEL: define nofpclass(nan) half @ret_nonan__inf_or_nan__fadd__unknown( ; CHECK-SAME: half [[UNKNOWN:%.*]]) { ; CHECK-NEXT: [[INF_OR_NAN:%.*]] = call half @returns_inf_or_nan() ; CHECK-NEXT: ret half [[INF_OR_NAN]] ; %inf.or.nan = call half @returns_inf_or_nan() %add = fadd half %inf.or.nan, %unknown ret half %add } define nofpclass(snan) half @unknown__fadd__zero(half %unknown) { ; CHECK-LABEL: define nofpclass(snan) half @unknown__fadd__zero( ; CHECK-SAME: half [[UNKNOWN:%.*]]) { ; CHECK-NEXT: [[ZERO:%.*]] = call half @returns_zero() ; CHECK-NEXT: [[ADD:%.*]] = fadd half [[UNKNOWN]], [[ZERO]] ; CHECK-NEXT: ret half [[ADD]] ; %zero = call half @returns_zero() %add = fadd half %unknown, %zero ret half %add } define nofpclass(snan) half @zero__fadd__unknown(half %unknown) { ; CHECK-LABEL: define nofpclass(snan) half @zero__fadd__unknown( ; CHECK-SAME: half [[UNKNOWN:%.*]]) { ; CHECK-NEXT: [[ZERO:%.*]] = call half @returns_zero() ; CHECK-NEXT: [[ADD:%.*]] = fadd half [[ZERO]], [[UNKNOWN]] ; CHECK-NEXT: ret half [[ADD]] ; %zero = call half @returns_zero() %add = fadd half %zero, %unknown ret half %add } define nofpclass(nan) half @ret_nonan__unknown__fadd__zero(half %unknown) { ; CHECK-LABEL: define nofpclass(nan) half @ret_nonan__unknown__fadd__zero( ; CHECK-SAME: half [[UNKNOWN:%.*]]) { ; CHECK-NEXT: [[ZERO:%.*]] = call half @returns_zero() ; CHECK-NEXT: [[ADD:%.*]] = fadd nnan half [[UNKNOWN]], [[ZERO]] ; CHECK-NEXT: ret half [[ADD]] ; %zero = call half @returns_zero() %add = fadd half %unknown, %zero ret half %add } define nofpclass(nan) half @ret_nonan__zero__fadd__unknown(half %unknown) { ; CHECK-LABEL: define nofpclass(nan) half @ret_nonan__zero__fadd__unknown( ; CHECK-SAME: half [[UNKNOWN:%.*]]) { ; CHECK-NEXT: [[ZERO:%.*]] = call half @returns_zero() ; CHECK-NEXT: [[ADD:%.*]] = fadd nnan half [[ZERO]], [[UNKNOWN]] ; CHECK-NEXT: ret half [[ADD]] ; %zero = call half @returns_zero() %add = fadd half %zero, %unknown ret half %add } define nofpclass(snan) half @unknown__fadd__pzero(half %unknown) { ; CHECK-LABEL: define nofpclass(snan) half @unknown__fadd__pzero( ; CHECK-SAME: half [[UNKNOWN:%.*]]) { ; CHECK-NEXT: [[PZERO:%.*]] = call half @returns_pzero() ; CHECK-NEXT: [[ADD:%.*]] = fadd half [[UNKNOWN]], 0.000000e+00 ; CHECK-NEXT: ret half [[ADD]] ; %pzero = call half @returns_pzero() %add = fadd half %unknown, %pzero ret half %add } define nofpclass(snan) half @pzero__fadd__unknown(half %unknown) { ; CHECK-LABEL: define nofpclass(snan) half @pzero__fadd__unknown( ; CHECK-SAME: half [[UNKNOWN:%.*]]) { ; CHECK-NEXT: [[PZERO:%.*]] = call half @returns_pzero() ; CHECK-NEXT: [[ADD:%.*]] = fadd half [[UNKNOWN]], 0.000000e+00 ; CHECK-NEXT: ret half [[ADD]] ; %pzero = call half @returns_pzero() %add = fadd half %pzero, %unknown ret half %add } define nofpclass(nan) half @ret_nonan__unknown__fadd__pzero(half %unknown) { ; CHECK-LABEL: define nofpclass(nan) half @ret_nonan__unknown__fadd__pzero( ; CHECK-SAME: half [[UNKNOWN:%.*]]) { ; CHECK-NEXT: [[PZERO:%.*]] = call half @returns_pzero() ; CHECK-NEXT: [[ADD:%.*]] = fadd nnan half [[UNKNOWN]], 0.000000e+00 ; CHECK-NEXT: ret half [[ADD]] ; %pzero = call half @returns_pzero() %add = fadd half %unknown, %pzero ret half %add } define nofpclass(nan) half @ret_nonan__pzero__fadd__unknown(half %unknown) { ; CHECK-LABEL: define nofpclass(nan) half @ret_nonan__pzero__fadd__unknown( ; CHECK-SAME: half [[UNKNOWN:%.*]]) { ; CHECK-NEXT: [[PZERO:%.*]] = call half @returns_pzero() ; CHECK-NEXT: [[ADD:%.*]] = fadd nnan half [[UNKNOWN]], 0.000000e+00 ; CHECK-NEXT: ret half [[ADD]] ; %pzero = call half @returns_pzero() %add = fadd half %pzero, %unknown ret half %add } define nofpclass(snan) half @unknown__fadd__nzero(half %unknown) { ; CHECK-LABEL: define nofpclass(snan) half @unknown__fadd__nzero( ; CHECK-SAME: half [[UNKNOWN:%.*]]) { ; CHECK-NEXT: [[NZERO:%.*]] = call half @returns_nzero() ; CHECK-NEXT: ret half [[UNKNOWN]] ; %nzero = call half @returns_nzero() %add = fadd half %unknown, %nzero ret half %add } define nofpclass(snan) half @nzero__fadd__unknown(half %unknown) { ; CHECK-LABEL: define nofpclass(snan) half @nzero__fadd__unknown( ; CHECK-SAME: half [[UNKNOWN:%.*]]) { ; CHECK-NEXT: [[NZERO:%.*]] = call half @returns_nzero() ; CHECK-NEXT: ret half [[UNKNOWN]] ; %nzero = call half @returns_nzero() %add = fadd half %nzero, %unknown ret half %add } define nofpclass(snan) half @unknown__fadd__nzero_or_nan(half %unknown) { ; CHECK-LABEL: define nofpclass(snan) half @unknown__fadd__nzero_or_nan( ; CHECK-SAME: half [[UNKNOWN:%.*]]) { ; CHECK-NEXT: [[NZERO_OR_NAN:%.*]] = call half @returns_nzero_or_nan() ; CHECK-NEXT: [[ADD:%.*]] = fadd half [[UNKNOWN]], [[NZERO_OR_NAN]] ; CHECK-NEXT: ret half [[ADD]] ; %nzero.or.nan = call half @returns_nzero_or_nan() %add = fadd half %unknown, %nzero.or.nan ret half %add } define nofpclass(snan) half @nzero_or_nan__fadd__unknown(half %unknown) { ; CHECK-LABEL: define nofpclass(snan) half @nzero_or_nan__fadd__unknown( ; CHECK-SAME: half [[UNKNOWN:%.*]]) { ; CHECK-NEXT: [[NZERO_OR_NAN:%.*]] = call half @returns_nzero_or_nan() ; CHECK-NEXT: [[ADD:%.*]] = fadd half [[NZERO_OR_NAN]], [[UNKNOWN]] ; CHECK-NEXT: ret half [[ADD]] ; %nzero.or.nan = call half @returns_nzero_or_nan() %add = fadd half %nzero.or.nan, %unknown ret half %add } define nofpclass(nan) half @ret_nonan__unknown__fadd__nzero(half %unknown) { ; CHECK-LABEL: define nofpclass(nan) half @ret_nonan__unknown__fadd__nzero( ; CHECK-SAME: half [[UNKNOWN:%.*]]) { ; CHECK-NEXT: [[NZERO:%.*]] = call half @returns_nzero() ; CHECK-NEXT: ret half [[UNKNOWN]] ; %nzero = call half @returns_nzero() %add = fadd half %unknown, %nzero ret half %add } define nofpclass(nan) half @ret_nonan__nzero__fadd__unknown(half %unknown) { ; CHECK-LABEL: define nofpclass(nan) half @ret_nonan__nzero__fadd__unknown( ; CHECK-SAME: half [[UNKNOWN:%.*]]) { ; CHECK-NEXT: [[NZERO:%.*]] = call half @returns_nzero() ; CHECK-NEXT: ret half [[UNKNOWN]] ; %nzero = call half @returns_nzero() %add = fadd half %nzero, %unknown ret half %add } define nofpclass(snan) half @not_nzero__fadd__zero(half nofpclass(nzero) %not.nzero) { ; CHECK-LABEL: define nofpclass(snan) half @not_nzero__fadd__zero( ; CHECK-SAME: half nofpclass(nzero) [[NOT_NZERO:%.*]]) { ; CHECK-NEXT: [[ZERO:%.*]] = call half @returns_zero() ; CHECK-NEXT: [[ADD:%.*]] = fadd half [[NOT_NZERO]], [[ZERO]] ; CHECK-NEXT: ret half [[ADD]] ; %zero = call half @returns_zero() %add = fadd half %not.nzero, %zero ret half %add } define nofpclass(snan) half @zero__fadd__not_nzero(half nofpclass(nzero) %not.nzero) { ; CHECK-LABEL: define nofpclass(snan) half @zero__fadd__not_nzero( ; CHECK-SAME: half nofpclass(nzero) [[NOT_NZERO:%.*]]) { ; CHECK-NEXT: [[ZERO:%.*]] = call half @returns_zero() ; CHECK-NEXT: [[ADD:%.*]] = fadd half [[ZERO]], [[NOT_NZERO]] ; CHECK-NEXT: ret half [[ADD]] ; %zero = call half @returns_zero() %add = fadd half %zero, %not.nzero ret half %add } define nofpclass(snan) half @not_nzero__fadd__pzero(half nofpclass(nzero) %not.nzero) { ; CHECK-LABEL: define nofpclass(snan) half @not_nzero__fadd__pzero( ; CHECK-SAME: half nofpclass(nzero) [[NOT_NZERO:%.*]]) { ; CHECK-NEXT: [[PZERO:%.*]] = call half @returns_pzero() ; CHECK-NEXT: ret half [[NOT_NZERO]] ; %pzero = call half @returns_pzero() %add = fadd half %not.nzero, %pzero ret half %add } define nofpclass(snan) half @pzero__fadd__not_nzero(half nofpclass(nzero) %not.nzero) { ; CHECK-LABEL: define nofpclass(snan) half @pzero__fadd__not_nzero( ; CHECK-SAME: half nofpclass(nzero) [[NOT_NZERO:%.*]]) { ; CHECK-NEXT: [[PZERO:%.*]] = call half @returns_pzero() ; CHECK-NEXT: ret half [[NOT_NZERO]] ; %pzero = call half @returns_pzero() %add = fadd half %pzero, %not.nzero ret half %add } define nofpclass(snan) half @not_nzero__fadd__zero_or_nan(half nofpclass(nzero) %not.nzero) { ; CHECK-LABEL: define nofpclass(snan) half @not_nzero__fadd__zero_or_nan( ; CHECK-SAME: half nofpclass(nzero) [[NOT_NZERO:%.*]]) { ; CHECK-NEXT: [[ZERO_OR_NAN:%.*]] = call half @returns_zero_or_nan() ; CHECK-NEXT: [[ADD:%.*]] = fadd half [[NOT_NZERO]], [[ZERO_OR_NAN]] ; CHECK-NEXT: ret half [[ADD]] ; %zero.or.nan = call half @returns_zero_or_nan() %add = fadd half %not.nzero, %zero.or.nan ret half %add } define nofpclass(snan) half @zero_or_nan__fadd__not_nzero(half nofpclass(nzero) %not.nzero) { ; CHECK-LABEL: define nofpclass(snan) half @zero_or_nan__fadd__not_nzero( ; CHECK-SAME: half nofpclass(nzero) [[NOT_NZERO:%.*]]) { ; CHECK-NEXT: [[ZERO_OR_NAN:%.*]] = call half @returns_zero_or_nan() ; CHECK-NEXT: [[ADD:%.*]] = fadd half [[ZERO_OR_NAN]], [[NOT_NZERO]] ; CHECK-NEXT: ret half [[ADD]] ; %zero.or.nan = call half @returns_zero_or_nan() %add = fadd half %zero.or.nan, %not.nzero ret half %add } define nofpclass(snan) half @not_nzero__fadd__pzero_or_nan(half nofpclass(nzero) %not.nzero) { ; CHECK-LABEL: define nofpclass(snan) half @not_nzero__fadd__pzero_or_nan( ; CHECK-SAME: half nofpclass(nzero) [[NOT_NZERO:%.*]]) { ; CHECK-NEXT: [[PZERO_OR_NAN:%.*]] = call half @returns_pzero_or_nan() ; CHECK-NEXT: [[ADD:%.*]] = fadd half [[NOT_NZERO]], [[PZERO_OR_NAN]] ; CHECK-NEXT: ret half [[ADD]] ; %pzero.or.nan = call half @returns_pzero_or_nan() %add = fadd half %not.nzero, %pzero.or.nan ret half %add } define nofpclass(snan) half @pzero_or_nan__fadd__not_nzero(half nofpclass(nzero) %not.nzero) { ; CHECK-LABEL: define nofpclass(snan) half @pzero_or_nan__fadd__not_nzero( ; CHECK-SAME: half nofpclass(nzero) [[NOT_NZERO:%.*]]) { ; CHECK-NEXT: [[PZERO_OR_NAN:%.*]] = call half @returns_pzero_or_nan() ; CHECK-NEXT: [[ADD:%.*]] = fadd half [[PZERO_OR_NAN]], [[NOT_NZERO]] ; CHECK-NEXT: ret half [[ADD]] ; %pzero.or.nan = call half @returns_pzero_or_nan() %add = fadd half %pzero.or.nan, %not.nzero ret half %add } define nofpclass(snan) half @unknown__fadd_nsz__pzero(half %unknown) { ; CHECK-LABEL: define nofpclass(snan) half @unknown__fadd_nsz__pzero( ; CHECK-SAME: half [[UNKNOWN:%.*]]) { ; CHECK-NEXT: [[PZERO:%.*]] = call half @returns_pzero() ; CHECK-NEXT: ret half [[UNKNOWN]] ; %pzero = call half @returns_pzero() %add = fadd nsz half %unknown, %pzero ret half %add } define nofpclass(snan) half @pzero__fadd_nsz__unknown(half %unknown) { ; CHECK-LABEL: define nofpclass(snan) half @pzero__fadd_nsz__unknown( ; CHECK-SAME: half [[UNKNOWN:%.*]]) { ; CHECK-NEXT: [[PZERO:%.*]] = call half @returns_pzero() ; CHECK-NEXT: ret half [[UNKNOWN]] ; %pzero = call half @returns_pzero() %add = fadd nsz half %pzero, %unknown ret half %add } define nofpclass(snan) half @unknown__fadd_nsz__pzero_or_nan(half %unknown) { ; CHECK-LABEL: define nofpclass(snan) half @unknown__fadd_nsz__pzero_or_nan( ; CHECK-SAME: half [[UNKNOWN:%.*]]) { ; CHECK-NEXT: [[PZERO_OR_NAN:%.*]] = call half @returns_pzero() ; CHECK-NEXT: ret half [[UNKNOWN]] ; %pzero.or.nan = call half @returns_pzero() %add = fadd nsz half %unknown, %pzero.or.nan ret half %add } define nofpclass(snan) half @pzero_or_nan__fadd_nsz__unknown(half %unknown) { ; CHECK-LABEL: define nofpclass(snan) half @pzero_or_nan__fadd_nsz__unknown( ; CHECK-SAME: half [[UNKNOWN:%.*]]) { ; CHECK-NEXT: [[PZERO_OR_NAN:%.*]] = call half @returns_pzero_or_nan() ; CHECK-NEXT: [[ADD:%.*]] = fadd nsz half [[PZERO_OR_NAN]], [[UNKNOWN]] ; CHECK-NEXT: ret half [[ADD]] ; %pzero.or.nan = call half @returns_pzero_or_nan() %add = fadd nsz half %pzero.or.nan, %unknown ret half %add } define nofpclass(snan) half @unknown__fadd_nsz__zero(half %unknown) { ; CHECK-LABEL: define nofpclass(snan) half @unknown__fadd_nsz__zero( ; CHECK-SAME: half [[UNKNOWN:%.*]]) { ; CHECK-NEXT: [[ZERO:%.*]] = call half @returns_zero() ; CHECK-NEXT: [[ADD:%.*]] = fadd nsz half [[UNKNOWN]], [[ZERO]] ; CHECK-NEXT: ret half [[ADD]] ; %zero = call half @returns_zero() %add = fadd nsz half %unknown, %zero ret half %add } define nofpclass(snan) half @zero__fadd_nsz__unknown(half %unknown) { ; CHECK-LABEL: define nofpclass(snan) half @zero__fadd_nsz__unknown( ; CHECK-SAME: half [[UNKNOWN:%.*]]) { ; CHECK-NEXT: [[ZERO:%.*]] = call half @returns_zero() ; CHECK-NEXT: [[ADD:%.*]] = fadd nsz half [[ZERO]], [[UNKNOWN]] ; CHECK-NEXT: ret half [[ADD]] ; %zero = call half @returns_zero() %add = fadd nsz half %zero, %unknown ret half %add } define nofpclass(snan) half @unknown__fadd_nsz__zero_or_nan(half %unknown) { ; CHECK-LABEL: define nofpclass(snan) half @unknown__fadd_nsz__zero_or_nan( ; CHECK-SAME: half [[UNKNOWN:%.*]]) { ; CHECK-NEXT: [[ZERO_OR_NAN:%.*]] = call half @returns_zero() ; CHECK-NEXT: [[ADD:%.*]] = fadd nsz half [[UNKNOWN]], [[ZERO_OR_NAN]] ; CHECK-NEXT: ret half [[ADD]] ; %zero.or.nan = call half @returns_zero() %add = fadd nsz half %unknown, %zero.or.nan ret half %add } define nofpclass(snan) half @zero_or_nan__fadd_nsz__unknown(half %unknown) { ; CHECK-LABEL: define nofpclass(snan) half @zero_or_nan__fadd_nsz__unknown( ; CHECK-SAME: half [[UNKNOWN:%.*]]) { ; CHECK-NEXT: [[ZERO_OR_NAN:%.*]] = call half @returns_zero_or_nan() ; CHECK-NEXT: [[ADD:%.*]] = fadd nsz half [[ZERO_OR_NAN]], [[UNKNOWN]] ; CHECK-NEXT: ret half [[ADD]] ; %zero.or.nan = call half @returns_zero_or_nan() %add = fadd nsz half %zero.or.nan, %unknown ret half %add } define nofpclass(inf) half @nan_result_demands_nan_input_lhs(i1 %cond, half %unknown, half nofpclass(inf nan zero sub) %normal) { ; CHECK-LABEL: define nofpclass(inf) half @nan_result_demands_nan_input_lhs( ; CHECK-SAME: i1 [[COND:%.*]], half [[UNKNOWN:%.*]], half nofpclass(nan inf zero sub) [[NORMAL:%.*]]) { ; CHECK-NEXT: [[NAN:%.*]] = call half @returns_nan() ; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[COND]], half [[NAN]], half [[UNKNOWN]] ; CHECK-NEXT: [[ADD:%.*]] = fadd half [[SELECT]], [[NORMAL]] ; CHECK-NEXT: ret half [[ADD]] ; %nan = call half @returns_nan() %select = select i1 %cond, half %nan, half %unknown %add = fadd half %select, %normal ret half %add } define nofpclass(inf) half @nan_result_demands_nan_input_rhs(i1 %cond, half %unknown, half nofpclass(inf nan zero sub) %normal) { ; CHECK-LABEL: define nofpclass(inf) half @nan_result_demands_nan_input_rhs( ; CHECK-SAME: i1 [[COND:%.*]], half [[UNKNOWN:%.*]], half nofpclass(nan inf zero sub) [[NORMAL:%.*]]) { ; CHECK-NEXT: [[NAN:%.*]] = call half @returns_nan() ; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[COND]], half [[NAN]], half [[UNKNOWN]] ; CHECK-NEXT: [[ADD:%.*]] = fadd half [[NORMAL]], [[SELECT]] ; CHECK-NEXT: ret half [[ADD]] ; %nan = call half @returns_nan() %select = select i1 %cond, half %nan, half %unknown %add = fadd half %normal, %select ret half %add } define nofpclass(snan) half @not_nzero__fadd__pzero__daz(half nofpclass(nzero) %not.nzero) #0 { ; CHECK-LABEL: define nofpclass(snan) half @not_nzero__fadd__pzero__daz( ; CHECK-SAME: half nofpclass(nzero) [[NOT_NZERO:%.*]]) #[[ATTR0:[0-9]+]] { ; CHECK-NEXT: [[PZERO:%.*]] = call half @returns_pzero() ; CHECK-NEXT: ret half [[NOT_NZERO]] ; %pzero = call half @returns_pzero() %add = fadd half %not.nzero, %pzero ret half %add } define nofpclass(snan) half @pzero__fadd__not_nzero__daz(half nofpclass(nzero) %not.nzero) #0 { ; CHECK-LABEL: define nofpclass(snan) half @pzero__fadd__not_nzero__daz( ; CHECK-SAME: half nofpclass(nzero) [[NOT_NZERO:%.*]]) #[[ATTR0]] { ; CHECK-NEXT: [[PZERO:%.*]] = call half @returns_pzero() ; CHECK-NEXT: ret half [[NOT_NZERO]] ; %pzero = call half @returns_pzero() %add = fadd half %pzero, %not.nzero ret half %add } define nofpclass(snan) half @not_nzero__fadd__pzero__dynamic(half nofpclass(nzero) %not.nzero) #1 { ; CHECK-LABEL: define nofpclass(snan) half @not_nzero__fadd__pzero__dynamic( ; CHECK-SAME: half nofpclass(nzero) [[NOT_NZERO:%.*]]) #[[ATTR1:[0-9]+]] { ; CHECK-NEXT: [[PZERO:%.*]] = call half @returns_pzero() ; CHECK-NEXT: ret half [[NOT_NZERO]] ; %pzero = call half @returns_pzero() %add = fadd half %not.nzero, %pzero ret half %add } define nofpclass(snan) half @pzero__fadd__not_nzero__dynamic(half nofpclass(nzero) %not.nzero) #1 { ; CHECK-LABEL: define nofpclass(snan) half @pzero__fadd__not_nzero__dynamic( ; CHECK-SAME: half nofpclass(nzero) [[NOT_NZERO:%.*]]) #[[ATTR1]] { ; CHECK-NEXT: [[PZERO:%.*]] = call half @returns_pzero() ; CHECK-NEXT: ret half [[NOT_NZERO]] ; %pzero = call half @returns_pzero() %add = fadd half %pzero, %not.nzero ret half %add } define nofpclass(snan) half @not_nzero_nsub__fadd__pzero__daz(half nofpclass(nzero nsub) %not.nzero.nsub) #0 { ; CHECK-LABEL: define nofpclass(snan) half @not_nzero_nsub__fadd__pzero__daz( ; CHECK-SAME: half nofpclass(nzero nsub) [[NOT_NZERO_NSUB:%.*]]) #[[ATTR0]] { ; CHECK-NEXT: [[PZERO:%.*]] = call half @returns_pzero() ; CHECK-NEXT: ret half [[NOT_NZERO_NSUB]] ; %pzero = call half @returns_pzero() %add = fadd half %not.nzero.nsub, %pzero ret half %add } define nofpclass(snan) half @pzero__fadd__not_nzero_nsub__daz(half nofpclass(nzero nsub) %not.nzero.nsub) #0 { ; CHECK-LABEL: define nofpclass(snan) half @pzero__fadd__not_nzero_nsub__daz( ; CHECK-SAME: half nofpclass(nzero nsub) [[NOT_NZERO_NSUB:%.*]]) #[[ATTR0]] { ; CHECK-NEXT: [[PZERO:%.*]] = call half @returns_pzero() ; CHECK-NEXT: ret half [[NOT_NZERO_NSUB]] ; %pzero = call half @returns_pzero() %add = fadd half %pzero, %not.nzero.nsub ret half %add } define nofpclass(snan) half @not_nzero_nsub__fadd__pzero__dynamic(half nofpclass(nzero nsub) %not.nzero.nsub) #1 { ; CHECK-LABEL: define nofpclass(snan) half @not_nzero_nsub__fadd__pzero__dynamic( ; CHECK-SAME: half nofpclass(nzero nsub) [[NOT_NZERO_NSUB:%.*]]) #[[ATTR1]] { ; CHECK-NEXT: [[PZERO:%.*]] = call half @returns_pzero() ; CHECK-NEXT: ret half [[NOT_NZERO_NSUB]] ; %pzero = call half @returns_pzero() %add = fadd half %not.nzero.nsub, %pzero ret half %add } define nofpclass(snan) half @pzero__fadd__not_nzero_nsub__dynamic(half nofpclass(nzero nsub) %not.nzero.nsub) #1 { ; CHECK-LABEL: define nofpclass(snan) half @pzero__fadd__not_nzero_nsub__dynamic( ; CHECK-SAME: half nofpclass(nzero nsub) [[NOT_NZERO_NSUB:%.*]]) #[[ATTR1]] { ; CHECK-NEXT: [[PZERO:%.*]] = call half @returns_pzero() ; CHECK-NEXT: ret half [[NOT_NZERO_NSUB]] ; %pzero = call half @returns_pzero() %add = fadd half %pzero, %not.nzero.nsub ret half %add } ; Cannot trim select define nofpclass(ninf norm nsub zero) half @fadd_self__pinf_result_demands_pnorm_source(i1 %cond, half noundef %unknown) { ; CHECK-LABEL: define nofpclass(ninf zero nsub norm) half @fadd_self__pinf_result_demands_pnorm_source( ; CHECK-SAME: i1 [[COND:%.*]], half noundef [[UNKNOWN:%.*]]) { ; CHECK-NEXT: [[PNORM:%.*]] = call noundef half @returns_pnorm() ; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[COND]], half [[PNORM]], half [[UNKNOWN]] ; CHECK-NEXT: [[ADD:%.*]] = fadd half [[SELECT]], [[SELECT]] ; CHECK-NEXT: ret half [[ADD]] ; %pnorm = call noundef half @returns_pnorm() %select = select i1 %cond, half %pnorm, half %unknown %add = fadd half %select, %select ret half %add } ; Cannot trim select define nofpclass(pinf norm psub zero) half @fadd_self__ninf_result_demands_nnorm_source(i1 %cond, half noundef %unknown) { ; CHECK-LABEL: define nofpclass(pinf zero psub norm) half @fadd_self__ninf_result_demands_nnorm_source( ; CHECK-SAME: i1 [[COND:%.*]], half noundef [[UNKNOWN:%.*]]) { ; CHECK-NEXT: [[NNORM:%.*]] = call noundef half @returns_nnorm() ; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[COND]], half [[NNORM]], half [[UNKNOWN]] ; CHECK-NEXT: [[ADD:%.*]] = fadd half [[SELECT]], [[SELECT]] ; CHECK-NEXT: ret half [[ADD]] ; %nnorm = call noundef half @returns_nnorm() %select = select i1 %cond, half %nnorm, half %unknown %add = fadd half %select, %select ret half %add } ; Cannot trim select define nofpclass(norm sub zero) half @fadd_self__inf_result_demands_norm_source(i1 %cond, half noundef %unknown) { ; CHECK-LABEL: define nofpclass(zero sub norm) half @fadd_self__inf_result_demands_norm_source( ; CHECK-SAME: i1 [[COND:%.*]], half noundef [[UNKNOWN:%.*]]) { ; CHECK-NEXT: [[NORM:%.*]] = call noundef half @returns_norm() ; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[COND]], half [[NORM]], half [[UNKNOWN]] ; CHECK-NEXT: [[ADD:%.*]] = fadd half [[SELECT]], [[SELECT]] ; CHECK-NEXT: ret half [[ADD]] ; %norm = call noundef half @returns_norm() %select = select i1 %cond, half %norm, half %unknown %add = fadd half %select, %select ret half %add } ; Cannot trim select define nofpclass(ninf nnorm sub zero) half @fadd_self__pnorm_result_demands_psub_source(i1 %cond, half noundef %unknown) { ; CHECK-LABEL: define nofpclass(ninf zero sub nnorm) half @fadd_self__pnorm_result_demands_psub_source( ; CHECK-SAME: i1 [[COND:%.*]], half noundef [[UNKNOWN:%.*]]) { ; CHECK-NEXT: [[PSUB:%.*]] = call noundef half @returns_psub() ; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[COND]], half [[PSUB]], half [[UNKNOWN]] ; CHECK-NEXT: [[ADD:%.*]] = fadd half [[SELECT]], [[SELECT]] ; CHECK-NEXT: ret half [[ADD]] ; %psub = call noundef half @returns_psub() %select = select i1 %cond, half %psub, half %unknown %add = fadd half %select, %select ret half %add } ; Cannot trim select define nofpclass(ninf pnorm sub zero) half @fadd_self__nnorm_result_demands_nsub_source(i1 %cond, half noundef %unknown) { ; CHECK-LABEL: define nofpclass(ninf zero sub pnorm) half @fadd_self__nnorm_result_demands_nsub_source( ; CHECK-SAME: i1 [[COND:%.*]], half noundef [[UNKNOWN:%.*]]) { ; CHECK-NEXT: [[NSUB:%.*]] = call noundef half @returns_nsub() ; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[COND]], half [[NSUB]], half [[UNKNOWN]] ; CHECK-NEXT: [[ADD:%.*]] = fadd half [[SELECT]], [[SELECT]] ; CHECK-NEXT: ret half [[ADD]] ; %nsub = call noundef half @returns_nsub() %select = select i1 %cond, half %nsub, half %unknown %add = fadd half %select, %select ret half %add } ; Cannot trim select define nofpclass(ninf sub zero) half @fadd_self__norm_result_demands_sub_source(i1 %cond, half noundef %unknown) { ; CHECK-LABEL: define nofpclass(ninf zero sub) half @fadd_self__norm_result_demands_sub_source( ; CHECK-SAME: i1 [[COND:%.*]], half noundef [[UNKNOWN:%.*]]) { ; CHECK-NEXT: [[SUB:%.*]] = call noundef half @returns_sub() ; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[COND]], half [[SUB]], half [[UNKNOWN]] ; CHECK-NEXT: [[ADD:%.*]] = fadd half [[SELECT]], [[SELECT]] ; CHECK-NEXT: ret half [[ADD]] ; %sub = call noundef half @returns_sub() %select = select i1 %cond, half %sub, half %unknown %add = fadd half %select, %select ret half %add } ; No zero output implies no zero inputs for fadd x, x define nofpclass(zero) half @ret_nozero__fadd_self__nozero(half noundef nofpclass(zero) %not.zero) { ; CHECK-LABEL: define nofpclass(zero) half @ret_nozero__fadd_self__nozero( ; CHECK-SAME: half noundef nofpclass(zero) [[NOT_ZERO:%.*]]) { ; CHECK-NEXT: [[ADD:%.*]] = fadd half [[NOT_ZERO]], [[NOT_ZERO]] ; CHECK-NEXT: ret half [[ADD]] ; %add = fadd half %not.zero, %not.zero ret half %add } ; No zero output implies no zero inputs for fadd x, x, can trim select define nofpclass(zero) half @ret_nozero__fadd_self__select_nozero(i1 %cond, half noundef %unknown) { ; CHECK-LABEL: define nofpclass(zero) half @ret_nozero__fadd_self__select_nozero( ; CHECK-SAME: i1 [[COND:%.*]], half noundef [[UNKNOWN:%.*]]) { ; CHECK-NEXT: [[ZERO:%.*]] = call noundef half @returns_zero() ; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[COND]], half [[ZERO]], half [[UNKNOWN]] ; CHECK-NEXT: [[ADD:%.*]] = fadd half [[SELECT]], [[SELECT]] ; CHECK-NEXT: ret half [[ADD]] ; %zero = call noundef half @returns_zero() %select = select i1 %cond, half %zero, half %unknown %add = fadd half %select, %select ret half %add } ; No zero output implies no zero inputs for fadd x, x, can trim select define nofpclass(pzero) half @ret_nopzero__fadd_self__nopzero(i1 %cond, half noundef %unknown) { ; CHECK-LABEL: define nofpclass(pzero) half @ret_nopzero__fadd_self__nopzero( ; CHECK-SAME: i1 [[COND:%.*]], half noundef [[UNKNOWN:%.*]]) { ; CHECK-NEXT: [[PZERO:%.*]] = call noundef half @returns_pzero() ; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[COND]], half [[PZERO]], half [[UNKNOWN]] ; CHECK-NEXT: [[ADD:%.*]] = fadd half [[SELECT]], [[SELECT]] ; CHECK-NEXT: ret half [[ADD]] ; %pzero = call noundef half @returns_pzero() %select = select i1 %cond, half %pzero, half %unknown %add = fadd half %select, %select ret half %add } ; No zero output implies no zero inputs for fadd x, x, can trim select define nofpclass(pzero) half @ret_nopzero__fadd_self__nonzero(i1 %cond, half noundef %unknown) { ; CHECK-LABEL: define nofpclass(pzero) half @ret_nopzero__fadd_self__nonzero( ; CHECK-SAME: i1 [[COND:%.*]], half noundef [[UNKNOWN:%.*]]) { ; CHECK-NEXT: [[NZERO:%.*]] = call noundef half @returns_nzero() ; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[COND]], half [[NZERO]], half [[UNKNOWN]] ; CHECK-NEXT: [[ADD:%.*]] = fadd half [[SELECT]], [[SELECT]] ; CHECK-NEXT: ret half [[ADD]] ; %nzero = call noundef half @returns_nzero() %select = select i1 %cond, half %nzero, half %unknown %add = fadd half %select, %select ret half %add } ; Cannot trim select define nofpclass(inf) half @ret_noinf__fadd_self__noinf(i1 %cond, half noundef %unknown) { ; CHECK-LABEL: define nofpclass(inf) half @ret_noinf__fadd_self__noinf( ; CHECK-SAME: i1 [[COND:%.*]], half noundef [[UNKNOWN:%.*]]) { ; CHECK-NEXT: [[INF:%.*]] = call noundef half @returns_inf() ; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[COND]], half [[INF]], half [[UNKNOWN]] ; CHECK-NEXT: [[ADD:%.*]] = fadd half [[SELECT]], [[SELECT]] ; CHECK-NEXT: ret half [[ADD]] ; %inf = call noundef half @returns_inf() %select = select i1 %cond, half %inf, half %unknown %add = fadd half %select, %select ret half %add } ; Trim select define nofpclass(nan) half @ret_nonan__fadd_self__nonan(i1 %cond, half noundef %unknown) { ; CHECK-LABEL: define nofpclass(nan) half @ret_nonan__fadd_self__nonan( ; CHECK-SAME: i1 [[COND:%.*]], half noundef [[UNKNOWN:%.*]]) { ; CHECK-NEXT: [[NAN:%.*]] = call noundef half @returns_nan() ; CHECK-NEXT: [[ADD:%.*]] = fadd nnan half [[UNKNOWN]], [[UNKNOWN]] ; CHECK-NEXT: ret half [[ADD]] ; %nan = call noundef half @returns_nan() %select = select i1 %cond, half %nan, half %unknown %add = fadd half %select, %select ret half %add } define nofpclass(nan) half @ret_nonan__fadd_self__nonan_maybe_undef0(i1 %cond, half %unknown) { ; CHECK-LABEL: define nofpclass(nan) half @ret_nonan__fadd_self__nonan_maybe_undef0( ; CHECK-SAME: i1 [[COND:%.*]], half [[UNKNOWN:%.*]]) { ; CHECK-NEXT: [[NAN:%.*]] = call noundef half @returns_nan() ; CHECK-NEXT: [[ADD:%.*]] = fadd nnan half [[UNKNOWN]], [[UNKNOWN]] ; CHECK-NEXT: ret half [[ADD]] ; %nan = call noundef half @returns_nan() %select = select i1 %cond, half %nan, half %unknown %add = fadd half %select, %select ret half %add } define nofpclass(nan) half @ret_nonan__fadd_self__nonan_maybe_undef1(i1 %cond, half noundef %unknown) { ; CHECK-LABEL: define nofpclass(nan) half @ret_nonan__fadd_self__nonan_maybe_undef1( ; CHECK-SAME: i1 [[COND:%.*]], half noundef [[UNKNOWN:%.*]]) { ; CHECK-NEXT: [[NAN:%.*]] = call half @returns_nan() ; CHECK-NEXT: [[ADD:%.*]] = fadd nnan half [[UNKNOWN]], [[UNKNOWN]] ; CHECK-NEXT: ret half [[ADD]] ; %nan = call half @returns_nan() %select = select i1 %cond, half %nan, half %unknown %add = fadd half %select, %select ret half %add } define nofpclass(nan) half @ret_nonan__fadd_self__nonan__other_use(i1 %cond, half noundef %unknown) { ; CHECK-LABEL: define nofpclass(nan) half @ret_nonan__fadd_self__nonan__other_use( ; CHECK-SAME: i1 [[COND:%.*]], half noundef [[UNKNOWN:%.*]]) { ; CHECK-NEXT: [[NAN:%.*]] = call noundef half @returns_nan() ; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[COND]], half [[NAN]], half [[UNKNOWN]] ; CHECK-NEXT: call void @use(half [[SELECT]]) ; CHECK-NEXT: [[ADD:%.*]] = fadd nnan half [[UNKNOWN]], [[UNKNOWN]] ; CHECK-NEXT: ret half [[ADD]] ; %nan = call noundef half @returns_nan() %select = select i1 %cond, half %nan, half %unknown call void @use(half %select) %add = fadd half %select, %select ret half %add } define nofpclass(sub) half @ret_nosub__fadd_self__nosub(i1 %cond, half noundef %unknown) { ; CHECK-LABEL: define nofpclass(sub) half @ret_nosub__fadd_self__nosub( ; CHECK-SAME: i1 [[COND:%.*]], half noundef [[UNKNOWN:%.*]]) { ; CHECK-NEXT: [[SUB:%.*]] = call noundef half @returns_sub() ; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[COND]], half [[SUB]], half [[UNKNOWN]] ; CHECK-NEXT: [[ADD:%.*]] = fadd half [[SELECT]], [[SELECT]] ; CHECK-NEXT: ret half [[ADD]] ; %sub = call noundef half @returns_sub() %select = select i1 %cond, half %sub, half %unknown %add = fadd half %select, %select ret half %add } define nofpclass(nsub) half @ret_nonsub__fadd_self__nonsub(i1 %cond, half noundef %unknown) { ; CHECK-LABEL: define nofpclass(nsub) half @ret_nonsub__fadd_self__nonsub( ; CHECK-SAME: i1 [[COND:%.*]], half noundef [[UNKNOWN:%.*]]) { ; CHECK-NEXT: [[NSUB:%.*]] = call noundef half @returns_nsub() ; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[COND]], half [[NSUB]], half [[UNKNOWN]] ; CHECK-NEXT: [[ADD:%.*]] = fadd half [[SELECT]], [[SELECT]] ; CHECK-NEXT: ret half [[ADD]] ; %nsub = call noundef half @returns_nsub() %select = select i1 %cond, half %nsub, half %unknown %add = fadd half %select, %select ret half %add } define nofpclass(psub) half @ret_nopsub__fadd_self__nopsub(i1 %cond, half noundef %unknown) { ; CHECK-LABEL: define nofpclass(psub) half @ret_nopsub__fadd_self__nopsub( ; CHECK-SAME: i1 [[COND:%.*]], half noundef [[UNKNOWN:%.*]]) { ; CHECK-NEXT: [[PSUB:%.*]] = call noundef half @returns_psub() ; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[COND]], half [[PSUB]], half [[UNKNOWN]] ; CHECK-NEXT: [[ADD:%.*]] = fadd half [[SELECT]], [[SELECT]] ; CHECK-NEXT: ret half [[ADD]] ; %psub = call noundef half @returns_psub() %select = select i1 %cond, half %psub, half %unknown %add = fadd half %select, %select ret half %add } define nofpclass(norm) half @ret_nonorm__fadd_self__nonorm(i1 %cond, half noundef %unknown) { ; CHECK-LABEL: define nofpclass(norm) half @ret_nonorm__fadd_self__nonorm( ; CHECK-SAME: i1 [[COND:%.*]], half noundef [[UNKNOWN:%.*]]) { ; CHECK-NEXT: [[NORM:%.*]] = call noundef half @returns_norm() ; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[COND]], half [[NORM]], half [[UNKNOWN]] ; CHECK-NEXT: [[ADD:%.*]] = fadd half [[SELECT]], [[SELECT]] ; CHECK-NEXT: ret half [[ADD]] ; %norm = call noundef half @returns_norm() %select = select i1 %cond, half %norm, half %unknown %add = fadd half %select, %select ret half %add } define nofpclass(nnorm) half @ret_nonnorm__fadd_self__nonnorm(i1 %cond, half noundef %unknown) { ; CHECK-LABEL: define nofpclass(nnorm) half @ret_nonnorm__fadd_self__nonnorm( ; CHECK-SAME: i1 [[COND:%.*]], half noundef [[UNKNOWN:%.*]]) { ; CHECK-NEXT: [[NNORM:%.*]] = call noundef half @returns_nnorm() ; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[COND]], half [[NNORM]], half [[UNKNOWN]] ; CHECK-NEXT: [[ADD:%.*]] = fadd half [[SELECT]], [[SELECT]] ; CHECK-NEXT: ret half [[ADD]] ; %nnorm = call noundef half @returns_nnorm() %select = select i1 %cond, half %nnorm, half %unknown %add = fadd half %select, %select ret half %add } define nofpclass(pnorm) half @ret_nopnorm__fadd_self__nopnorm(i1 %cond, half noundef %unknown) { ; CHECK-LABEL: define nofpclass(pnorm) half @ret_nopnorm__fadd_self__nopnorm( ; CHECK-SAME: i1 [[COND:%.*]], half noundef [[UNKNOWN:%.*]]) { ; CHECK-NEXT: [[PNORM:%.*]] = call noundef half @returns_pnorm() ; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[COND]], half [[PNORM]], half [[UNKNOWN]] ; CHECK-NEXT: [[ADD:%.*]] = fadd half [[SELECT]], [[SELECT]] ; CHECK-NEXT: ret half [[ADD]] ; %pnorm = call noundef half @returns_pnorm() %select = select i1 %cond, half %pnorm, half %unknown %add = fadd half %select, %select ret half %add } define nofpclass(ninf nnorm nsub nzero) half @ret_nonegative__fadd_self__nonegative(i1 %cond, half noundef %unknown) { ; CHECK-LABEL: define nofpclass(ninf nzero nsub nnorm) half @ret_nonegative__fadd_self__nonegative( ; CHECK-SAME: i1 [[COND:%.*]], half noundef [[UNKNOWN:%.*]]) { ; CHECK-NEXT: [[NEGATIVE:%.*]] = call noundef half @returns_negative() ; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[COND]], half [[NEGATIVE]], half [[UNKNOWN]] ; CHECK-NEXT: [[ADD:%.*]] = fadd half [[SELECT]], [[SELECT]] ; CHECK-NEXT: ret half [[ADD]] ; %negative = call noundef half @returns_negative() %select = select i1 %cond, half %negative, half %unknown %add = fadd half %select, %select ret half %add } define nofpclass(pinf pnorm psub pzero) half @ret_nopositive__fadd_self__nopositive(i1 %cond, half noundef %unknown) { ; CHECK-LABEL: define nofpclass(pinf pzero psub pnorm) half @ret_nopositive__fadd_self__nopositive( ; CHECK-SAME: i1 [[COND:%.*]], half noundef [[UNKNOWN:%.*]]) { ; CHECK-NEXT: [[POSITIVE:%.*]] = call noundef half @returns_positive() ; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[COND]], half [[POSITIVE]], half [[UNKNOWN]] ; CHECK-NEXT: [[ADD:%.*]] = fadd half [[SELECT]], [[SELECT]] ; CHECK-NEXT: ret half [[ADD]] ; %positive = call noundef half @returns_positive() %select = select i1 %cond, half %positive, half %unknown %add = fadd half %select, %select ret half %add } define nofpclass(ninf nnorm nsub nzero) half @ret_nonegative__fadd_self__nonegative_or_nan(i1 %cond, half noundef %unknown) { ; CHECK-LABEL: define nofpclass(ninf nzero nsub nnorm) half @ret_nonegative__fadd_self__nonegative_or_nan( ; CHECK-SAME: i1 [[COND:%.*]], half noundef [[UNKNOWN:%.*]]) { ; CHECK-NEXT: [[NEGATIVE_OR_NAN:%.*]] = call noundef half @returns_negative_or_nan() ; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[COND]], half [[NEGATIVE_OR_NAN]], half [[UNKNOWN]] ; CHECK-NEXT: [[ADD:%.*]] = fadd half [[SELECT]], [[SELECT]] ; CHECK-NEXT: ret half [[ADD]] ; %negative.or.nan = call noundef half @returns_negative_or_nan() %select = select i1 %cond, half %negative.or.nan, half %unknown %add = fadd half %select, %select ret half %add } define nofpclass(pinf pnorm psub pzero) half @ret_nopositive__fadd_self__nopositive_or_nan(i1 %cond, half noundef %unknown) { ; CHECK-LABEL: define nofpclass(pinf pzero psub pnorm) half @ret_nopositive__fadd_self__nopositive_or_nan( ; CHECK-SAME: i1 [[COND:%.*]], half noundef [[UNKNOWN:%.*]]) { ; CHECK-NEXT: [[POSITIVE_OR_NAN:%.*]] = call noundef half @returns_positive_or_nan() ; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[COND]], half [[POSITIVE_OR_NAN]], half [[UNKNOWN]] ; CHECK-NEXT: [[ADD:%.*]] = fadd half [[SELECT]], [[SELECT]] ; CHECK-NEXT: ret half [[ADD]] ; %positive.or.nan = call noundef half @returns_positive_or_nan() %select = select i1 %cond, half %positive.or.nan, half %unknown %add = fadd half %select, %select ret half %add } define nofpclass(nan ninf nnorm nsub nzero) half @ret_nonegative_nonan__fadd_self__nonegative_or_nan(i1 %cond, half noundef %unknown) { ; CHECK-LABEL: define nofpclass(nan ninf nzero nsub nnorm) half @ret_nonegative_nonan__fadd_self__nonegative_or_nan( ; CHECK-SAME: i1 [[COND:%.*]], half noundef [[UNKNOWN:%.*]]) { ; CHECK-NEXT: [[NEGATIVE_OR_NAN:%.*]] = call noundef half @returns_negative_or_nan() ; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[COND]], half [[NEGATIVE_OR_NAN]], half [[UNKNOWN]] ; CHECK-NEXT: [[ADD:%.*]] = fadd nnan half [[SELECT]], [[SELECT]] ; CHECK-NEXT: ret half [[ADD]] ; %negative.or.nan = call noundef half @returns_negative_or_nan() %select = select i1 %cond, half %negative.or.nan, half %unknown %add = fadd half %select, %select ret half %add } define nofpclass(nan pinf pnorm psub pzero) half @ret_nopositive_nonan__fadd_self__nopositive_or_nan(i1 %cond, half noundef %unknown) { ; CHECK-LABEL: define nofpclass(nan pinf pzero psub pnorm) half @ret_nopositive_nonan__fadd_self__nopositive_or_nan( ; CHECK-SAME: i1 [[COND:%.*]], half noundef [[UNKNOWN:%.*]]) { ; CHECK-NEXT: [[POSITIVE_OR_NAN:%.*]] = call noundef half @returns_positive_or_nan() ; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[COND]], half [[POSITIVE_OR_NAN]], half [[UNKNOWN]] ; CHECK-NEXT: [[ADD:%.*]] = fadd nnan half [[SELECT]], [[SELECT]] ; CHECK-NEXT: ret half [[ADD]] ; %positive.or.nan = call noundef half @returns_positive_or_nan() %select = select i1 %cond, half %positive.or.nan, half %unknown %add = fadd half %select, %select ret half %add } define nofpclass(nan) half @ret_nonan_fneg_fabs_fadd_known_negative_or_nan_sources() { ; CHECK-LABEL: define nofpclass(nan) half @ret_nonan_fneg_fabs_fadd_known_negative_or_nan_sources() { ; CHECK-NEXT: [[NEGATIVE_OR_NAN0:%.*]] = call half @returns_negative_or_nan() ; CHECK-NEXT: [[NEGATIVE_OR_NAN1:%.*]] = call half @returns_negative_or_nan() ; CHECK-NEXT: [[KNOWN_NEGATIVE_ADD:%.*]] = fadd nnan half [[NEGATIVE_OR_NAN0]], [[NEGATIVE_OR_NAN1]] ; CHECK-NEXT: [[FABS:%.*]] = call half @llvm.fabs.f16(half [[KNOWN_NEGATIVE_ADD]]) ; CHECK-NEXT: [[NEG_FABS:%.*]] = fneg half [[FABS]] ; CHECK-NEXT: ret half [[NEG_FABS]] ; %negative.or.nan0 = call half @returns_negative_or_nan() %negative.or.nan1 = call half @returns_negative_or_nan() %known.negative.add = fadd half %negative.or.nan0, %negative.or.nan1 %fabs = call half @llvm.fabs.f16(half %known.negative.add) %neg.fabs = fneg half %fabs ret half %neg.fabs } define nofpclass(nan) half @ret_nonan_fneg_fabs_fadd_known_negative_sources() { ; CHECK-LABEL: define nofpclass(nan) half @ret_nonan_fneg_fabs_fadd_known_negative_sources() { ; CHECK-NEXT: [[NEGATIVE0:%.*]] = call half @returns_negative() ; CHECK-NEXT: [[NEGATIVE1:%.*]] = call half @returns_negative() ; CHECK-NEXT: [[KNOWN_NEGATIVE_OP:%.*]] = fadd nnan half [[NEGATIVE0]], [[NEGATIVE1]] ; CHECK-NEXT: [[FABS:%.*]] = call half @llvm.fabs.f16(half [[KNOWN_NEGATIVE_OP]]) ; CHECK-NEXT: [[NEG_FABS:%.*]] = fneg half [[FABS]] ; CHECK-NEXT: ret half [[NEG_FABS]] ; %negative0 = call half @returns_negative() %negative1 = call half @returns_negative() %known.negative.op = fadd half %negative0, %negative1 %fabs = call half @llvm.fabs.f16(half %known.negative.op) %neg.fabs = fneg half %fabs ret half %neg.fabs } define nofpclass(snan) half @ret_no_snan__known_positive_or_nan__fadd__known_negative_or_nan() { ; CHECK-LABEL: define nofpclass(snan) half @ret_no_snan__known_positive_or_nan__fadd__known_negative_or_nan() { ; CHECK-NEXT: [[POSITIVE_OR_NAN:%.*]] = call half @returns_positive_or_nan() ; CHECK-NEXT: [[NEGATIVE_OR_NAN:%.*]] = call half @returns_negative_or_nan() ; CHECK-NEXT: [[RESULT:%.*]] = fadd half [[POSITIVE_OR_NAN]], [[NEGATIVE_OR_NAN]] ; CHECK-NEXT: ret half [[RESULT]] ; %positive.or.nan = call half @returns_positive_or_nan() %negative.or.nan = call half @returns_negative_or_nan() %result = fadd half %positive.or.nan, %negative.or.nan ret half %result } define nofpclass(snan) half @ret_no_snan__known_negative_or_nan__fadd__known_positive_or_nan() { ; CHECK-LABEL: define nofpclass(snan) half @ret_no_snan__known_negative_or_nan__fadd__known_positive_or_nan() { ; CHECK-NEXT: [[NEGATIVE_OR_NAN:%.*]] = call half @returns_negative_or_nan() ; CHECK-NEXT: [[POSITIVE_OR_NAN:%.*]] = call half @returns_positive_or_nan() ; CHECK-NEXT: [[RESULT:%.*]] = fadd half [[NEGATIVE_OR_NAN]], [[POSITIVE_OR_NAN]] ; CHECK-NEXT: ret half [[RESULT]] ; %negative.or.nan = call half @returns_negative_or_nan() %positive.or.nan = call half @returns_positive_or_nan() %result = fadd half %negative.or.nan, %positive.or.nan ret half %result } define nofpclass(snan) half @ret_no_snan__known_positive__fadd__known_negative() { ; CHECK-LABEL: define nofpclass(snan) half @ret_no_snan__known_positive__fadd__known_negative() { ; CHECK-NEXT: [[POSITIVE:%.*]] = call half @returns_positive_or_nan() ; CHECK-NEXT: [[NEGATIVE:%.*]] = call half @returns_negative_or_nan() ; CHECK-NEXT: [[RESULT:%.*]] = fadd half [[POSITIVE]], [[NEGATIVE]] ; CHECK-NEXT: ret half [[RESULT]] ; %positive = call half @returns_positive_or_nan() %negative = call half @returns_negative_or_nan() %result = fadd half %positive, %negative ret half %result } define nofpclass(snan) half @ret_no_snan__known_negative__fadd__known_positive() { ; CHECK-LABEL: define nofpclass(snan) half @ret_no_snan__known_negative__fadd__known_positive() { ; CHECK-NEXT: [[NEGATIVE:%.*]] = call half @returns_negative_or_nan() ; CHECK-NEXT: [[POSITIVE:%.*]] = call half @returns_positive_or_nan() ; CHECK-NEXT: [[RESULT:%.*]] = fadd half [[NEGATIVE]], [[POSITIVE]] ; CHECK-NEXT: ret half [[RESULT]] ; %negative = call half @returns_negative_or_nan() %positive = call half @returns_positive_or_nan() %result = fadd half %negative, %positive ret half %result } ;--------------------------------------------------------------------- ; Check not-0 outupt handling with different denormal modes ;--------------------------------------------------------------------- ; Can drop selects with daz define nofpclass(norm sub) half @demand_zero_select_sub_source__fadd_self__ieee(i1 %cond, half noundef %unknown) { ; CHECK-LABEL: define nofpclass(sub norm) half @demand_zero_select_sub_source__fadd_self__ieee( ; CHECK-SAME: i1 [[COND:%.*]], half noundef [[UNKNOWN:%.*]]) { ; CHECK-NEXT: [[SUB:%.*]] = call noundef half @returns_sub() ; CHECK-NEXT: ret half poison ; %sub = call noundef half @returns_sub() %select = select i1 %cond, half %unknown, half %sub %result = fadd half %sub, %sub ret half %result } define nofpclass(norm sub pzero) half @demand_nzero_select_nsub_source__fadd_self__ieee(i1 %cond, half noundef %unknown) { ; CHECK-LABEL: define nofpclass(pzero sub norm) half @demand_nzero_select_nsub_source__fadd_self__ieee( ; CHECK-SAME: i1 [[COND:%.*]], half noundef [[UNKNOWN:%.*]]) { ; CHECK-NEXT: [[NSUB:%.*]] = call noundef half @returns_nsub() ; CHECK-NEXT: ret half poison ; %nsub = call noundef half @returns_nsub() %select = select i1 %cond, half %unknown, half %nsub %result = fadd half %nsub, %nsub ret half %result } define nofpclass(norm sub pzero) half @demand_nzero_select_psub_source__fadd_self__ieee(i1 %cond, half noundef %unknown) { ; CHECK-LABEL: define nofpclass(pzero sub norm) half @demand_nzero_select_psub_source__fadd_self__ieee( ; CHECK-SAME: i1 [[COND:%.*]], half noundef [[UNKNOWN:%.*]]) { ; CHECK-NEXT: [[PSUB:%.*]] = call noundef half @returns_psub() ; CHECK-NEXT: ret half poison ; %psub = call noundef half @returns_psub() %select = select i1 %cond, half %unknown, half %psub %result = fadd half %psub, %psub ret half %result } define nofpclass(norm sub nzero) half @demand_pzero_select_psub_source__fadd_self__ieee(i1 %cond, half noundef %unknown) { ; CHECK-LABEL: define nofpclass(nzero sub norm) half @demand_pzero_select_psub_source__fadd_self__ieee( ; CHECK-SAME: i1 [[COND:%.*]], half noundef [[UNKNOWN:%.*]]) { ; CHECK-NEXT: [[PSUB:%.*]] = call noundef half @returns_psub() ; CHECK-NEXT: ret half poison ; %psub = call noundef half @returns_psub() %select = select i1 %cond, half %unknown, half %psub %result = fadd half %psub, %psub ret half %result } define nofpclass(norm sub nzero) half @demand_pzero_select_nsub_source__fadd_self__ieee(i1 %cond, half noundef %unknown) { ; CHECK-LABEL: define nofpclass(nzero sub norm) half @demand_pzero_select_nsub_source__fadd_self__ieee( ; CHECK-SAME: i1 [[COND:%.*]], half noundef [[UNKNOWN:%.*]]) { ; CHECK-NEXT: [[NSUB:%.*]] = call noundef half @returns_nsub() ; CHECK-NEXT: ret half poison ; %nsub = call noundef half @returns_nsub() %select = select i1 %cond, half %unknown, half %nsub %result = fadd half %nsub, %nsub ret half %result } ; Must keep select if ftz or daz define nofpclass(norm sub) half @demand_zero_select_sub_source__fadd_self__ftz_daz(i1 %cond, half noundef %unknown) #0 { ; CHECK-LABEL: define nofpclass(sub norm) half @demand_zero_select_sub_source__fadd_self__ftz_daz( ; CHECK-SAME: i1 [[COND:%.*]], half noundef [[UNKNOWN:%.*]]) #[[ATTR0]] { ; CHECK-NEXT: [[SUB:%.*]] = call noundef half @returns_sub() ; CHECK-NEXT: [[RESULT:%.*]] = fadd nnan half [[SUB]], [[SUB]] ; CHECK-NEXT: ret half [[RESULT]] ; %sub = call noundef half @returns_sub() %select = select i1 %cond, half %unknown, half %sub %result = fadd half %sub, %sub ret half %result } define nofpclass(norm sub pzero) half @demand_nzero_select_nsub_source__fadd_self__ftz_daz(i1 %cond, half noundef %unknown) #0 { ; CHECK-LABEL: define nofpclass(pzero sub norm) half @demand_nzero_select_nsub_source__fadd_self__ftz_daz( ; CHECK-SAME: i1 [[COND:%.*]], half noundef [[UNKNOWN:%.*]]) #[[ATTR0]] { ; CHECK-NEXT: [[NSUB:%.*]] = call noundef half @returns_nsub() ; CHECK-NEXT: [[RESULT:%.*]] = fadd nnan half [[NSUB]], [[NSUB]] ; CHECK-NEXT: ret half [[RESULT]] ; %nsub = call noundef half @returns_nsub() %select = select i1 %cond, half %unknown, half %nsub %result = fadd half %nsub, %nsub ret half %result } define nofpclass(norm sub pzero) half @demand_nzero_select_psub_source__fadd_self__ftz_daz(i1 %cond, half noundef %unknown) #0 { ; CHECK-LABEL: define nofpclass(pzero sub norm) half @demand_nzero_select_psub_source__fadd_self__ftz_daz( ; CHECK-SAME: i1 [[COND:%.*]], half noundef [[UNKNOWN:%.*]]) #[[ATTR0]] { ; CHECK-NEXT: [[PSUB:%.*]] = call noundef half @returns_psub() ; CHECK-NEXT: ret half poison ; %psub = call noundef half @returns_psub() %select = select i1 %cond, half %unknown, half %psub %result = fadd half %psub, %psub ret half %result } define nofpclass(norm sub nzero) half @demand_pzero_select_psub_source__fadd_self__ftz_daz(i1 %cond, half noundef %unknown) #0 { ; CHECK-LABEL: define nofpclass(nzero sub norm) half @demand_pzero_select_psub_source__fadd_self__ftz_daz( ; CHECK-SAME: i1 [[COND:%.*]], half noundef [[UNKNOWN:%.*]]) #[[ATTR0]] { ; CHECK-NEXT: [[PSUB:%.*]] = call noundef half @returns_psub() ; CHECK-NEXT: [[RESULT:%.*]] = fadd nnan half [[PSUB]], [[PSUB]] ; CHECK-NEXT: ret half [[RESULT]] ; %psub = call noundef half @returns_psub() %select = select i1 %cond, half %unknown, half %psub %result = fadd half %psub, %psub ret half %result } define nofpclass(norm sub nzero) half @demand_pzero_select_nsub_source__fadd_self__ftz_daz(i1 %cond, half noundef %unknown) #0 { ; CHECK-LABEL: define nofpclass(nzero sub norm) half @demand_pzero_select_nsub_source__fadd_self__ftz_daz( ; CHECK-SAME: i1 [[COND:%.*]], half noundef [[UNKNOWN:%.*]]) #[[ATTR0]] { ; CHECK-NEXT: [[NSUB:%.*]] = call noundef half @returns_nsub() ; CHECK-NEXT: ret half poison ; %nsub = call noundef half @returns_nsub() %select = select i1 %cond, half %unknown, half %nsub %result = fadd half %nsub, %nsub ret half %result } define nofpclass(norm sub) half @demand_zero_select_sub_source__fadd_self__ieee_daz(i1 %cond, half noundef %unknown) #2 { ; CHECK-LABEL: define nofpclass(sub norm) half @demand_zero_select_sub_source__fadd_self__ieee_daz( ; CHECK-SAME: i1 [[COND:%.*]], half noundef [[UNKNOWN:%.*]]) #[[ATTR2:[0-9]+]] { ; CHECK-NEXT: [[SUB:%.*]] = call noundef half @returns_sub() ; CHECK-NEXT: [[RESULT:%.*]] = fadd nnan half [[SUB]], [[SUB]] ; CHECK-NEXT: ret half [[RESULT]] ; %sub = call noundef half @returns_sub() %select = select i1 %cond, half %unknown, half %sub %result = fadd half %sub, %sub ret half %result } define nofpclass(norm sub pzero) half @demand_nzero_select_nsub_source__fadd_self__ieee_daz(i1 %cond, half noundef %unknown) #2 { ; CHECK-LABEL: define nofpclass(pzero sub norm) half @demand_nzero_select_nsub_source__fadd_self__ieee_daz( ; CHECK-SAME: i1 [[COND:%.*]], half noundef [[UNKNOWN:%.*]]) #[[ATTR2]] { ; CHECK-NEXT: [[NSUB:%.*]] = call noundef half @returns_nsub() ; CHECK-NEXT: [[RESULT:%.*]] = fadd nnan half [[NSUB]], [[NSUB]] ; CHECK-NEXT: ret half [[RESULT]] ; %nsub = call noundef half @returns_nsub() %select = select i1 %cond, half %unknown, half %nsub %result = fadd half %nsub, %nsub ret half %result } define nofpclass(norm sub pzero) half @demand_nzero_select_psub_source__fadd_self__ieee_daz(i1 %cond, half noundef %unknown) #2 { ; CHECK-LABEL: define nofpclass(pzero sub norm) half @demand_nzero_select_psub_source__fadd_self__ieee_daz( ; CHECK-SAME: i1 [[COND:%.*]], half noundef [[UNKNOWN:%.*]]) #[[ATTR2]] { ; CHECK-NEXT: [[PSUB:%.*]] = call noundef half @returns_psub() ; CHECK-NEXT: ret half poison ; %psub = call noundef half @returns_psub() %select = select i1 %cond, half %unknown, half %psub %result = fadd half %psub, %psub ret half %result } define nofpclass(norm sub nzero) half @demand_pzero_select_psub_source__fadd_self__ieee_daz(i1 %cond, half noundef %unknown) #2 { ; CHECK-LABEL: define nofpclass(nzero sub norm) half @demand_pzero_select_psub_source__fadd_self__ieee_daz( ; CHECK-SAME: i1 [[COND:%.*]], half noundef [[UNKNOWN:%.*]]) #[[ATTR2]] { ; CHECK-NEXT: [[PSUB:%.*]] = call noundef half @returns_psub() ; CHECK-NEXT: [[RESULT:%.*]] = fadd nnan half [[PSUB]], [[PSUB]] ; CHECK-NEXT: ret half [[RESULT]] ; %psub = call noundef half @returns_psub() %select = select i1 %cond, half %unknown, half %psub %result = fadd half %psub, %psub ret half %result } define nofpclass(norm sub nzero) half @demand_pzero_select_nsub_source__fadd_self__ieee_daz(i1 %cond, half noundef %unknown) #2 { ; CHECK-LABEL: define nofpclass(nzero sub norm) half @demand_pzero_select_nsub_source__fadd_self__ieee_daz( ; CHECK-SAME: i1 [[COND:%.*]], half noundef [[UNKNOWN:%.*]]) #[[ATTR2]] { ; CHECK-NEXT: [[NSUB:%.*]] = call noundef half @returns_nsub() ; CHECK-NEXT: ret half poison ; %nsub = call noundef half @returns_nsub() %select = select i1 %cond, half %unknown, half %nsub %result = fadd half %nsub, %nsub ret half %result } define nofpclass(norm sub) half @demand_zero_select_sub_source__fadd_self__ftz_ieee(i1 %cond, half noundef %unknown) #3 { ; CHECK-LABEL: define nofpclass(sub norm) half @demand_zero_select_sub_source__fadd_self__ftz_ieee( ; CHECK-SAME: i1 [[COND:%.*]], half noundef [[UNKNOWN:%.*]]) #[[ATTR3:[0-9]+]] { ; CHECK-NEXT: [[SUB:%.*]] = call noundef half @returns_sub() ; CHECK-NEXT: [[RESULT:%.*]] = fadd nnan half [[SUB]], [[SUB]] ; CHECK-NEXT: ret half [[RESULT]] ; %sub = call noundef half @returns_sub() %select = select i1 %cond, half %unknown, half %sub %result = fadd half %sub, %sub ret half %result } define nofpclass(norm sub pzero) half @demand_nzero_select_nsub_source__fadd_self__ftz_ieee(i1 %cond, half noundef %unknown) #3 { ; CHECK-LABEL: define nofpclass(pzero sub norm) half @demand_nzero_select_nsub_source__fadd_self__ftz_ieee( ; CHECK-SAME: i1 [[COND:%.*]], half noundef [[UNKNOWN:%.*]]) #[[ATTR3]] { ; CHECK-NEXT: [[NSUB:%.*]] = call noundef half @returns_nsub() ; CHECK-NEXT: [[RESULT:%.*]] = fadd nnan half [[NSUB]], [[NSUB]] ; CHECK-NEXT: ret half [[RESULT]] ; %nsub = call noundef half @returns_nsub() %select = select i1 %cond, half %unknown, half %nsub %result = fadd half %nsub, %nsub ret half %result } define nofpclass(norm sub pzero) half @demand_nzero_select_psub_source__fadd_self__ftz_ieee(i1 %cond, half noundef %unknown) #3 { ; CHECK-LABEL: define nofpclass(pzero sub norm) half @demand_nzero_select_psub_source__fadd_self__ftz_ieee( ; CHECK-SAME: i1 [[COND:%.*]], half noundef [[UNKNOWN:%.*]]) #[[ATTR3]] { ; CHECK-NEXT: [[PSUB:%.*]] = call noundef half @returns_psub() ; CHECK-NEXT: ret half poison ; %psub = call noundef half @returns_psub() %select = select i1 %cond, half %unknown, half %psub %result = fadd half %psub, %psub ret half %result } define nofpclass(norm sub nzero) half @demand_pzero_select_psub_source__fadd_self__ftz_ieee(i1 %cond, half noundef %unknown) #3 { ; CHECK-LABEL: define nofpclass(nzero sub norm) half @demand_pzero_select_psub_source__fadd_self__ftz_ieee( ; CHECK-SAME: i1 [[COND:%.*]], half noundef [[UNKNOWN:%.*]]) #[[ATTR3]] { ; CHECK-NEXT: [[PSUB:%.*]] = call noundef half @returns_psub() ; CHECK-NEXT: [[RESULT:%.*]] = fadd nnan half [[PSUB]], [[PSUB]] ; CHECK-NEXT: ret half [[RESULT]] ; %psub = call noundef half @returns_psub() %select = select i1 %cond, half %unknown, half %psub %result = fadd half %psub, %psub ret half %result } define nofpclass(norm sub nzero) half @demand_pzero_select_nsub_source__fadd_self__ftz_ieee(i1 %cond, half noundef %unknown) #3 { ; CHECK-LABEL: define nofpclass(nzero sub norm) half @demand_pzero_select_nsub_source__fadd_self__ftz_ieee( ; CHECK-SAME: i1 [[COND:%.*]], half noundef [[UNKNOWN:%.*]]) #[[ATTR3]] { ; CHECK-NEXT: [[NSUB:%.*]] = call noundef half @returns_nsub() ; CHECK-NEXT: ret half poison ; %nsub = call noundef half @returns_nsub() %select = select i1 %cond, half %unknown, half %nsub %result = fadd half %nsub, %nsub ret half %result } define nofpclass(norm sub) half @demand_zero_select_sub_source__fadd_self__dynamic_dynamic(i1 %cond, half noundef %unknown) #1 { ; CHECK-LABEL: define nofpclass(sub norm) half @demand_zero_select_sub_source__fadd_self__dynamic_dynamic( ; CHECK-SAME: i1 [[COND:%.*]], half noundef [[UNKNOWN:%.*]]) #[[ATTR1]] { ; CHECK-NEXT: [[SUB:%.*]] = call noundef half @returns_sub() ; CHECK-NEXT: [[RESULT:%.*]] = fadd nnan half [[SUB]], [[SUB]] ; CHECK-NEXT: ret half [[RESULT]] ; %sub = call noundef half @returns_sub() %select = select i1 %cond, half %unknown, half %sub %result = fadd half %sub, %sub ret half %result } define nofpclass(norm sub pzero) half @demand_nzero_select_nsub_source__fadd_self__dynamic_dynamic(i1 %cond, half noundef %unknown) #1 { ; CHECK-LABEL: define nofpclass(pzero sub norm) half @demand_nzero_select_nsub_source__fadd_self__dynamic_dynamic( ; CHECK-SAME: i1 [[COND:%.*]], half noundef [[UNKNOWN:%.*]]) #[[ATTR1]] { ; CHECK-NEXT: [[NSUB:%.*]] = call noundef half @returns_nsub() ; CHECK-NEXT: [[RESULT:%.*]] = fadd nnan half [[NSUB]], [[NSUB]] ; CHECK-NEXT: ret half [[RESULT]] ; %nsub = call noundef half @returns_nsub() %select = select i1 %cond, half %unknown, half %nsub %result = fadd half %nsub, %nsub ret half %result } define nofpclass(norm sub pzero) half @demand_nzero_select_psub_source__fadd__dynamic_dynamic(i1 %cond, half noundef %unknown) #1 { ; CHECK-LABEL: define nofpclass(pzero sub norm) half @demand_nzero_select_psub_source__fadd__dynamic_dynamic( ; CHECK-SAME: i1 [[COND:%.*]], half noundef [[UNKNOWN:%.*]]) #[[ATTR1]] { ; CHECK-NEXT: [[PSUB:%.*]] = call noundef half @returns_psub() ; CHECK-NEXT: ret half poison ; %psub = call noundef half @returns_psub() %select = select i1 %cond, half %unknown, half %psub %result = fadd half %psub, %psub ret half %result } define nofpclass(norm sub nzero) half @demand_pzero_select_psub_source__fadd_self__dynamic_dynamic(i1 %cond, half noundef %unknown) #1 { ; CHECK-LABEL: define nofpclass(nzero sub norm) half @demand_pzero_select_psub_source__fadd_self__dynamic_dynamic( ; CHECK-SAME: i1 [[COND:%.*]], half noundef [[UNKNOWN:%.*]]) #[[ATTR1]] { ; CHECK-NEXT: [[PSUB:%.*]] = call noundef half @returns_psub() ; CHECK-NEXT: [[RESULT:%.*]] = fadd nnan half [[PSUB]], [[PSUB]] ; CHECK-NEXT: ret half [[RESULT]] ; %psub = call noundef half @returns_psub() %select = select i1 %cond, half %unknown, half %psub %result = fadd half %psub, %psub ret half %result } define nofpclass(norm sub nzero) half @demand_pzero_select_nsub_source__fadd_self__dynamic_dynamic(i1 %cond, half noundef %unknown) #1 { ; CHECK-LABEL: define nofpclass(nzero sub norm) half @demand_pzero_select_nsub_source__fadd_self__dynamic_dynamic( ; CHECK-SAME: i1 [[COND:%.*]], half noundef [[UNKNOWN:%.*]]) #[[ATTR1]] { ; CHECK-NEXT: [[NSUB:%.*]] = call noundef half @returns_nsub() ; CHECK-NEXT: [[RESULT:%.*]] = fadd nnan half [[NSUB]], [[NSUB]] ; CHECK-NEXT: ret half [[RESULT]] ; %nsub = call noundef half @returns_nsub() %select = select i1 %cond, half %unknown, half %nsub %result = fadd half %nsub, %nsub ret half %result } define nofpclass(norm sub) half @demand_zero_select_sub_source__fadd_self__ieee_dapz(i1 %cond, half noundef %unknown) #4 { ; CHECK-LABEL: define nofpclass(sub norm) half @demand_zero_select_sub_source__fadd_self__ieee_dapz( ; CHECK-SAME: i1 [[COND:%.*]], half noundef [[UNKNOWN:%.*]]) #[[ATTR4:[0-9]+]] { ; CHECK-NEXT: [[SUB:%.*]] = call noundef half @returns_sub() ; CHECK-NEXT: [[RESULT:%.*]] = fadd nnan half [[SUB]], [[SUB]] ; CHECK-NEXT: ret half [[RESULT]] ; %sub = call noundef half @returns_sub() %select = select i1 %cond, half %unknown, half %sub %result = fadd half %sub, %sub ret half %result } define nofpclass(norm sub pzero) half @demand_nzero_select_nsub_source__fadd_self__ieee_dapz(i1 %cond, half noundef %unknown) #4 { ; CHECK-LABEL: define nofpclass(pzero sub norm) half @demand_nzero_select_nsub_source__fadd_self__ieee_dapz( ; CHECK-SAME: i1 [[COND:%.*]], half noundef [[UNKNOWN:%.*]]) #[[ATTR4]] { ; CHECK-NEXT: [[NSUB:%.*]] = call noundef half @returns_nsub() ; CHECK-NEXT: ret half -inf ; %nsub = call noundef half @returns_nsub() %select = select i1 %cond, half %unknown, half %nsub %result = fadd half %nsub, %nsub ret half %result } define nofpclass(norm sub pzero) half @demand_nzero_select_psub_source__fadd_self__ieee_dapz(i1 %cond, half noundef %unknown) #4 { ; CHECK-LABEL: define nofpclass(pzero sub norm) half @demand_nzero_select_psub_source__fadd_self__ieee_dapz( ; CHECK-SAME: i1 [[COND:%.*]], half noundef [[UNKNOWN:%.*]]) #[[ATTR4]] { ; CHECK-NEXT: [[PSUB:%.*]] = call noundef half @returns_psub() ; CHECK-NEXT: ret half poison ; %psub = call noundef half @returns_psub() %select = select i1 %cond, half %unknown, half %psub %result = fadd half %psub, %psub ret half %result } define nofpclass(norm sub nzero) half @demand_pzero_select_psub_source__fadd_self__ieee_dapz(i1 %cond, half noundef %unknown) #4 { ; CHECK-LABEL: define nofpclass(nzero sub norm) half @demand_pzero_select_psub_source__fadd_self__ieee_dapz( ; CHECK-SAME: i1 [[COND:%.*]], half noundef [[UNKNOWN:%.*]]) #[[ATTR4]] { ; CHECK-NEXT: [[PSUB:%.*]] = call noundef half @returns_psub() ; CHECK-NEXT: [[RESULT:%.*]] = fadd nnan half [[PSUB]], [[PSUB]] ; CHECK-NEXT: ret half [[RESULT]] ; %psub = call noundef half @returns_psub() %select = select i1 %cond, half %unknown, half %psub %result = fadd half %psub, %psub ret half %result } ; Special case, positive-zero result may be from negative denormal define nofpclass(norm sub nzero) half @demand_pzero_select_nsub_source__fadd_self__ieee_dapz(i1 %cond, half noundef %unknown) #4 { ; CHECK-LABEL: define nofpclass(nzero sub norm) half @demand_pzero_select_nsub_source__fadd_self__ieee_dapz( ; CHECK-SAME: i1 [[COND:%.*]], half noundef [[UNKNOWN:%.*]]) #[[ATTR4]] { ; CHECK-NEXT: [[NSUB:%.*]] = call noundef half @returns_nsub() ; CHECK-NEXT: [[RESULT:%.*]] = fadd nnan half [[NSUB]], [[NSUB]] ; CHECK-NEXT: ret half [[RESULT]] ; %nsub = call noundef half @returns_nsub() %select = select i1 %cond, half %unknown, half %nsub %result = fadd half %nsub, %nsub ret half %result } define nofpclass(norm sub) half @demand_zero_select_sub_source__fadd_self__ftpz_ieee(i1 %cond, half noundef %unknown) #5 { ; CHECK-LABEL: define nofpclass(sub norm) half @demand_zero_select_sub_source__fadd_self__ftpz_ieee( ; CHECK-SAME: i1 [[COND:%.*]], half noundef [[UNKNOWN:%.*]]) #[[ATTR5:[0-9]+]] { ; CHECK-NEXT: [[SUB:%.*]] = call noundef half @returns_sub() ; CHECK-NEXT: [[RESULT:%.*]] = fadd nnan half [[SUB]], [[SUB]] ; CHECK-NEXT: ret half [[RESULT]] ; %sub = call noundef half @returns_sub() %select = select i1 %cond, half %unknown, half %sub %result = fadd half %sub, %sub ret half %result } define nofpclass(norm sub pzero) half @demand_nzero_select_nsub_source__fadd_self__ftpz_ieee(i1 %cond, half noundef %unknown) #5 { ; CHECK-LABEL: define nofpclass(pzero sub norm) half @demand_nzero_select_nsub_source__fadd_self__ftpz_ieee( ; CHECK-SAME: i1 [[COND:%.*]], half noundef [[UNKNOWN:%.*]]) #[[ATTR5]] { ; CHECK-NEXT: [[NSUB:%.*]] = call noundef half @returns_nsub() ; CHECK-NEXT: ret half -inf ; %nsub = call noundef half @returns_nsub() %select = select i1 %cond, half %unknown, half %nsub %result = fadd half %nsub, %nsub ret half %result } define nofpclass(norm sub pzero) half @demand_nzero_select_psub_source__fadd_self__ftpz_ieee(i1 %cond, half noundef %unknown) #5 { ; CHECK-LABEL: define nofpclass(pzero sub norm) half @demand_nzero_select_psub_source__fadd_self__ftpz_ieee( ; CHECK-SAME: i1 [[COND:%.*]], half noundef [[UNKNOWN:%.*]]) #[[ATTR5]] { ; CHECK-NEXT: [[PSUB:%.*]] = call noundef half @returns_psub() ; CHECK-NEXT: ret half poison ; %psub = call noundef half @returns_psub() %select = select i1 %cond, half %unknown, half %psub %result = fadd half %psub, %psub ret half %result } define nofpclass(norm sub nzero) half @demand_pzero_select_psub_source__fadd_self__ftpz_ieee(i1 %cond, half noundef %unknown) #5 { ; CHECK-LABEL: define nofpclass(nzero sub norm) half @demand_pzero_select_psub_source__fadd_self__ftpz_ieee( ; CHECK-SAME: i1 [[COND:%.*]], half noundef [[UNKNOWN:%.*]]) #[[ATTR5]] { ; CHECK-NEXT: [[PSUB:%.*]] = call noundef half @returns_psub() ; CHECK-NEXT: [[RESULT:%.*]] = fadd nnan half [[PSUB]], [[PSUB]] ; CHECK-NEXT: ret half [[RESULT]] ; %psub = call noundef half @returns_psub() %select = select i1 %cond, half %unknown, half %psub %result = fadd half %psub, %psub ret half %result } ; Special case, positive-zero result may be from negative denormal define nofpclass(norm sub nzero) half @demand_pzero_select_nsub_source__fadd_self__ftpz_ieee(i1 %cond, half noundef %unknown) #5 { ; CHECK-LABEL: define nofpclass(nzero sub norm) half @demand_pzero_select_nsub_source__fadd_self__ftpz_ieee( ; CHECK-SAME: i1 [[COND:%.*]], half noundef [[UNKNOWN:%.*]]) #[[ATTR5]] { ; CHECK-NEXT: [[NSUB:%.*]] = call noundef half @returns_nsub() ; CHECK-NEXT: [[RESULT:%.*]] = fadd nnan half [[NSUB]], [[NSUB]] ; CHECK-NEXT: ret half [[RESULT]] ; %nsub = call noundef half @returns_nsub() %select = select i1 %cond, half %unknown, half %nsub %result = fadd half %nsub, %nsub ret half %result } define nofpclass(snan) half @not_nan__fadd__inf_or_nan(half nofpclass(nan) %not.nan) { ; CHECK-LABEL: define nofpclass(snan) half @not_nan__fadd__inf_or_nan( ; CHECK-SAME: half nofpclass(nan) [[NOT_NAN:%.*]]) { ; CHECK-NEXT: [[INF_OR_NAN:%.*]] = call half @returns_inf_or_nan() ; CHECK-NEXT: [[RESULT:%.*]] = fadd half [[NOT_NAN]], [[INF_OR_NAN]] ; CHECK-NEXT: ret half [[RESULT]] ; %inf.or.nan = call half @returns_inf_or_nan() %result = fadd half %not.nan, %inf.or.nan ret half %result } define nofpclass(snan) half @inf_or_nan__fadd__not_nan(half nofpclass(nan) %not.nan) { ; CHECK-LABEL: define nofpclass(snan) half @inf_or_nan__fadd__not_nan( ; CHECK-SAME: half nofpclass(nan) [[NOT_NAN:%.*]]) { ; CHECK-NEXT: [[INF_OR_NAN:%.*]] = call half @returns_inf_or_nan() ; CHECK-NEXT: [[RESULT:%.*]] = fadd half [[INF_OR_NAN]], [[NOT_NAN]] ; CHECK-NEXT: ret half [[RESULT]] ; %inf.or.nan = call half @returns_inf_or_nan() %result = fadd half %inf.or.nan, %not.nan ret half %result } define nofpclass(snan) half @qnan_result_self_demands_snan(i1 noundef %cond, half noundef %unknown) { ; CHECK-LABEL: define nofpclass(snan) half @qnan_result_self_demands_snan( ; CHECK-SAME: i1 noundef [[COND:%.*]], half noundef [[UNKNOWN:%.*]]) { ; CHECK-NEXT: [[SNAN:%.*]] = call noundef half @returns_snan() ; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[COND]], half [[SNAN]], half [[UNKNOWN]] ; CHECK-NEXT: [[RESULT:%.*]] = fadd half [[SELECT]], [[SELECT]] ; CHECK-NEXT: ret half [[RESULT]] ; %snan = call noundef half @returns_snan() %select = select i1 %cond, half %snan, half %unknown %result = fadd half %select, %select ret half %result } define nofpclass(snan) half @qnan_result_demands_snan_lhs(i1 %cond, half %unknown0, half %unknown1) { ; CHECK-LABEL: define nofpclass(snan) half @qnan_result_demands_snan_lhs( ; CHECK-SAME: i1 [[COND:%.*]], half [[UNKNOWN0:%.*]], half [[UNKNOWN1:%.*]]) { ; CHECK-NEXT: [[SNAN:%.*]] = call half @returns_snan() ; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[COND]], half [[SNAN]], half [[UNKNOWN0]] ; CHECK-NEXT: [[RESULT:%.*]] = fadd half [[SELECT]], [[UNKNOWN1]] ; CHECK-NEXT: ret half [[RESULT]] ; %snan = call half @returns_snan() %select = select i1 %cond, half %snan, half %unknown0 %result = fadd half %select, %unknown1 ret half %result } define nofpclass(snan) half @qnan_result_demands_snan_rhs(i1 %cond, half %unknown0, half %unknown1) { ; CHECK-LABEL: define nofpclass(snan) half @qnan_result_demands_snan_rhs( ; CHECK-SAME: i1 [[COND:%.*]], half [[UNKNOWN0:%.*]], half [[UNKNOWN1:%.*]]) { ; CHECK-NEXT: [[SNAN:%.*]] = call half @returns_snan() ; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[COND]], half [[SNAN]], half [[UNKNOWN0]] ; CHECK-NEXT: [[RESULT:%.*]] = fadd half [[UNKNOWN1]], [[SELECT]] ; CHECK-NEXT: ret half [[RESULT]] ; %snan = call half @returns_snan() %select = select i1 %cond, half %snan, half %unknown0 %result = fadd half %unknown1, %select ret half %result } attributes #0 = { denormal_fpenv(preservesign) } attributes #1 = { denormal_fpenv(dynamic) } attributes #2 = { denormal_fpenv(ieee|preservesign) } attributes #3 = { denormal_fpenv(preservesign|ieee) } attributes #4 = { denormal_fpenv(ieee|positivezero) } attributes #5 = { denormal_fpenv(positivezero|ieee) }