| ; 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 = fsub 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 = fsub 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:%.*]] = fsub half [[X]], [[Y]] |
| ; CHECK-NEXT: ret half [[ADD]] |
| ; |
| %add = fsub 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:%.*]] = fsub nnan ninf half [[X]], [[Y]] |
| ; CHECK-NEXT: ret half [[ADD]] |
| ; |
| %add = fsub 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 = fsub 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 = fsub 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:%.*]] = fsub nnan half [[X]], [[Y]] |
| ; CHECK-NEXT: ret half [[ADD]] |
| ; |
| %add = fsub 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 = fsub 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 = fsub half %x, %y |
| ret half %add |
| } |
| |
| define nofpclass(pinf) half @ret_nofpclass_pinf__fsub_select_unknown_or_pinf__unknown(i1 %cond, half %x, half %y) { |
| ; CHECK-LABEL: define nofpclass(pinf) half @ret_nofpclass_pinf__fsub_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:%.*]] = fsub half [[X_OR_PINF]], [[Y]] |
| ; CHECK-NEXT: ret half [[ADD]] |
| ; |
| %x.or.pinf = select i1 %cond, half %x, half 0xH7C00 |
| %add = fsub half %x.or.pinf, %y |
| ret half %add |
| } |
| |
| define nofpclass(pinf) half @ret_nofpclass_pinf__fsub_unknown__select_unknown_or_pinf(i1 %cond, half %x, half %y) { |
| ; CHECK-LABEL: define nofpclass(pinf) half @ret_nofpclass_pinf__fsub_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:%.*]] = fsub half [[X]], [[Y_OR_PINF]] |
| ; CHECK-NEXT: ret half [[ADD]] |
| ; |
| %y.or.pinf = select i1 %cond, half %y, half 0xH7C00 |
| %add = fsub half %x, %y.or.pinf |
| ret half %add |
| } |
| |
| define nofpclass(inf) half @ret_nofpclass_inf__fsub_select_unknown_or_inf__unknown(i1 %cond, half %x, half %y) { |
| ; CHECK-LABEL: define nofpclass(inf) half @ret_nofpclass_inf__fsub_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:%.*]] = fsub 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 = fsub half %x.or.inf, %y |
| ret half %add |
| } |
| |
| define nofpclass(inf) half @ret_nofpclass_inf__fsub_unknown__select_unknown_or_inf(i1 %cond, half %x, half %y) { |
| ; CHECK-LABEL: define nofpclass(inf) half @ret_nofpclass_inf__fsub_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:%.*]] = fsub 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 = fsub half %x, %y.or.inf |
| ret half %add |
| } |
| |
| define nofpclass(pinf) half @ret_nofpclass_pinf__fsub_select_unknown_or_pinf(i1 %cond, half %x, half %y) { |
| ; CHECK-LABEL: define nofpclass(pinf) half @ret_nofpclass_pinf__fsub_select_unknown_or_pinf( |
| ; CHECK-SAME: i1 [[COND:%.*]], half [[X:%.*]], half [[Y:%.*]]) { |
| ; CHECK-NEXT: [[TMP1:%.*]] = fsub half [[X]], [[Y]] |
| ; CHECK-NEXT: [[ADD:%.*]] = select i1 [[COND]], half [[TMP1]], half +qnan |
| ; CHECK-NEXT: ret half [[ADD]] |
| ; |
| %x.or.pinf = select i1 %cond, half %x, half 0xH7C00 |
| %y.or.pinf = select i1 %cond, half %y, half 0xH7C00 |
| %add = fsub half %x.or.pinf, %y.or.pinf |
| ret half %add |
| } |
| |
| define nofpclass(ninf) half @ret_nofpclass_ninf__fsub_select_unknown_or_ninf(i1 %cond, half %x, half %y) { |
| ; CHECK-LABEL: define nofpclass(ninf) half @ret_nofpclass_ninf__fsub_select_unknown_or_ninf( |
| ; CHECK-SAME: i1 [[COND:%.*]], half [[X:%.*]], half [[Y:%.*]]) { |
| ; CHECK-NEXT: [[TMP1:%.*]] = fsub half [[X]], [[Y]] |
| ; CHECK-NEXT: [[ADD:%.*]] = select i1 [[COND]], half [[TMP1]], half +qnan |
| ; CHECK-NEXT: ret half [[ADD]] |
| ; |
| %x.or.ninf = select i1 %cond, half %x, half 0xHFC00 |
| %y.or.ninf = select i1 %cond, half %y, half 0xHFC00 |
| %add = fsub half %x.or.ninf, %y.or.ninf |
| ret half %add |
| } |
| |
| define nofpclass(inf) half @ret_nofpclass_inf__fsub_select_unknown_or_inf(i1 %cond, half %x, half %y) { |
| ; CHECK-LABEL: define nofpclass(inf) half @ret_nofpclass_inf__fsub_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:%.*]] = fsub 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 = fsub half %x.or.inf, %y.or.inf |
| ret half %add |
| } |
| |
| define nofpclass(nan inf) half @ret_nofpclass_inf_nan__fsub_select_unknown_or_inf(i1 %cond, half %x, half %y) { |
| ; CHECK-LABEL: define nofpclass(nan inf) half @ret_nofpclass_inf_nan__fsub_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:%.*]] = fsub 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 = fsub 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:%.*]] = fsub 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 = fsub 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:%.*]] = fsub 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 = fsub 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:%.*]] = fsub 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 = fsub 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:%.*]] = fsub 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 = fsub 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:%.*]] = fsub 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 = fsub 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:%.*]] = fsub 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 = fsub 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:%.*]] = fsub 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 = fsub 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:%.*]] = fsub 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 = fsub 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:%.*]] = fsub half [[X]], [[Y]] |
| ; CHECK-NEXT: ret half [[ADD]] |
| ; |
| %add = fsub 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:%.*]] = fsub nnan half [[X]], [[Y]] |
| ; CHECK-NEXT: ret half [[ADD]] |
| ; |
| %add = fsub 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:%.*]] = fsub half [[X]], [[Y]] |
| ; CHECK-NEXT: ret half [[ADD]] |
| ; |
| %add = fsub 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:%.*]] = fsub ninf half [[X]], [[Y]] |
| ; CHECK-NEXT: ret half [[ADD]] |
| ; |
| %add = fsub 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:%.*]] = fsub nnan half [[X]], [[Y]] |
| ; CHECK-NEXT: ret half [[ADD]] |
| ; |
| %add = fsub 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:%.*]] = fsub nnan ninf half [[X]], [[Y]] |
| ; CHECK-NEXT: ret half [[ADD]] |
| ; |
| %add = fsub 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:%.*]] = fsub nnan half [[X]], [[Y]] |
| ; CHECK-NEXT: ret half [[ADD]] |
| ; |
| %add = fsub 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:%.*]] = fsub nnan half [[X]], [[Y]] |
| ; CHECK-NEXT: ret half [[ADD]] |
| ; |
| %add = fsub 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:%.*]] = fsub nnan half [[X]], [[Y]] |
| ; CHECK-NEXT: ret half [[ADD]] |
| ; |
| %add = fsub half %x, %y |
| ret half %add |
| } |
| |
| define nofpclass(nzero) half @inferred_nan_output__fsub__nnan__no_ninf_no_nan(half nofpclass(nan) %x, half nofpclass(nan ninf) %y) { |
| ; CHECK-LABEL: define nofpclass(nzero) half @inferred_nan_output__fsub__nnan__no_ninf_no_nan( |
| ; CHECK-SAME: half nofpclass(nan) [[X:%.*]], half nofpclass(nan ninf) [[Y:%.*]]) { |
| ; CHECK-NEXT: [[ADD:%.*]] = fsub half [[X]], [[Y]] |
| ; CHECK-NEXT: ret half [[ADD]] |
| ; |
| %add = fsub half %x, %y |
| ret half %add |
| } |
| |
| define nofpclass(nzero) half @inferred_nan_output__fsub__no_ninf_no_nan__no_nan(half nofpclass(nan ninf) %x, half nofpclass(nan) %y) { |
| ; CHECK-LABEL: define nofpclass(nzero) half @inferred_nan_output__fsub__no_ninf_no_nan__no_nan( |
| ; CHECK-SAME: half nofpclass(nan ninf) [[X:%.*]], half nofpclass(nan) [[Y:%.*]]) { |
| ; CHECK-NEXT: [[ADD:%.*]] = fsub half [[X]], [[Y]] |
| ; CHECK-NEXT: ret half [[ADD]] |
| ; |
| %add = fsub half %x, %y |
| ret half %add |
| } |
| |
| define nofpclass(nzero) half @inferred_nan_output__fsub__no_nan__no_pinf_no_nan(half nofpclass(nan) %x, half nofpclass(nan pinf) %y) { |
| ; CHECK-LABEL: define nofpclass(nzero) half @inferred_nan_output__fsub__no_nan__no_pinf_no_nan( |
| ; CHECK-SAME: half nofpclass(nan) [[X:%.*]], half nofpclass(nan pinf) [[Y:%.*]]) { |
| ; CHECK-NEXT: [[ADD:%.*]] = fsub half [[X]], [[Y]] |
| ; CHECK-NEXT: ret half [[ADD]] |
| ; |
| %add = fsub half %x, %y |
| ret half %add |
| } |
| |
| define nofpclass(nzero) half @inferred_nan_output__fsub__no_pinf_no_nan__no_nan(half nofpclass(nan pinf) %x, half nofpclass(nan) %y) { |
| ; CHECK-LABEL: define nofpclass(nzero) half @inferred_nan_output__fsub__no_pinf_no_nan__no_nan( |
| ; CHECK-SAME: half nofpclass(nan pinf) [[X:%.*]], half nofpclass(nan) [[Y:%.*]]) { |
| ; CHECK-NEXT: [[ADD:%.*]] = fsub half [[X]], [[Y]] |
| ; CHECK-NEXT: ret half [[ADD]] |
| ; |
| %add = fsub half %x, %y |
| ret half %add |
| } |
| |
| define nofpclass(nzero) half @inferred_nan_output__fsub__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__fsub__no_pinf_no_nan__no_pinf_no_nan( |
| ; CHECK-SAME: half nofpclass(nan pinf) [[X:%.*]], half nofpclass(nan pinf) [[Y:%.*]]) { |
| ; CHECK-NEXT: [[ADD:%.*]] = fsub half [[X]], [[Y]] |
| ; CHECK-NEXT: ret half [[ADD]] |
| ; |
| %add = fsub half %x, %y |
| ret half %add |
| } |
| |
| define nofpclass(nzero) half @inferred_nan_output__fsub__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__fsub__no_ninf_no_nan__no_ninf_no_nan( |
| ; CHECK-SAME: half nofpclass(nan ninf) [[X:%.*]], half nofpclass(nan ninf) [[Y:%.*]]) { |
| ; CHECK-NEXT: [[ADD:%.*]] = fsub half [[X]], [[Y]] |
| ; CHECK-NEXT: ret half [[ADD]] |
| ; |
| %add = fsub half %x, %y |
| ret half %add |
| } |
| |
| define nofpclass(nan) half @ret_nonan_fabs_fsub_known_positive_or_nan_sources() { |
| ; CHECK-LABEL: define nofpclass(nan) half @ret_nonan_fabs_fsub_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:%.*]] = fsub nnan half [[POSITIVE_OR_NAN0]], [[POSITIVE_OR_NAN1]] |
| ; CHECK-NEXT: [[FABS:%.*]] = call half @llvm.fabs.f16(half [[KNOWN_POSITIVE_ADD]]) |
| ; CHECK-NEXT: ret half [[FABS]] |
| ; |
| %positive.or.nan0 = call half @returns_positive_or_nan() |
| %positive.or.nan1 = call half @returns_positive_or_nan() |
| %known.positive.add = fsub 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_fsub_known_positive_sources() { |
| ; CHECK-LABEL: define nofpclass(nan) half @ret_nonan_fabs_fsub_known_positive_sources() { |
| ; CHECK-NEXT: [[POSITIVE0:%.*]] = call half @returns_positive() |
| ; CHECK-NEXT: [[POSITIVE1:%.*]] = call half @returns_positive() |
| ; CHECK-NEXT: ret half 0.000000e+00 |
| ; |
| %positive0 = call half @returns_positive() |
| %positive1 = call half @returns_positive() |
| %known.positive.add = fsub half %positive1, %positive1 |
| %fabs = call half @llvm.fabs.f16(half %known.positive.add) |
| ret half %fabs |
| } |
| |
| define nofpclass(snan) half @unknown__fsub__inf(half %unknown) { |
| ; CHECK-LABEL: define nofpclass(snan) half @unknown__fsub__inf( |
| ; CHECK-SAME: half [[UNKNOWN:%.*]]) { |
| ; CHECK-NEXT: [[INF:%.*]] = call half @returns_inf() |
| ; CHECK-NEXT: [[ADD:%.*]] = fsub half [[UNKNOWN]], [[INF]] |
| ; CHECK-NEXT: ret half [[ADD]] |
| ; |
| %inf = call half @returns_inf() |
| %add = fsub half %unknown, %inf |
| ret half %add |
| } |
| |
| define nofpclass(snan) half @inf__fsub__unknown(half %unknown) { |
| ; CHECK-LABEL: define nofpclass(snan) half @inf__fsub__unknown( |
| ; CHECK-SAME: half [[UNKNOWN:%.*]]) { |
| ; CHECK-NEXT: [[INF:%.*]] = call half @returns_inf() |
| ; CHECK-NEXT: [[ADD:%.*]] = fsub half [[INF]], [[UNKNOWN]] |
| ; CHECK-NEXT: ret half [[ADD]] |
| ; |
| %inf = call half @returns_inf() |
| %add = fsub half %inf, %unknown |
| ret half %add |
| } |
| |
| define nofpclass(snan) half @unknown__fsub__inf_or_nan(half %unknown) { |
| ; CHECK-LABEL: define nofpclass(snan) half @unknown__fsub__inf_or_nan( |
| ; CHECK-SAME: half [[UNKNOWN:%.*]]) { |
| ; CHECK-NEXT: [[INF_OR_NAN:%.*]] = call half @returns_inf_or_nan() |
| ; CHECK-NEXT: [[ADD:%.*]] = fsub half [[UNKNOWN]], [[INF_OR_NAN]] |
| ; CHECK-NEXT: ret half [[ADD]] |
| ; |
| %inf.or.nan = call half @returns_inf_or_nan() |
| %add = fsub half %unknown, %inf.or.nan |
| ret half %add |
| } |
| |
| define nofpclass(snan) half @inf_or_nan__fsub__unknown(half %unknown) { |
| ; CHECK-LABEL: define nofpclass(snan) half @inf_or_nan__fsub__unknown( |
| ; CHECK-SAME: half [[UNKNOWN:%.*]]) { |
| ; CHECK-NEXT: [[INF_OR_NAN:%.*]] = call half @returns_inf_or_nan() |
| ; CHECK-NEXT: [[ADD:%.*]] = fsub half [[INF_OR_NAN]], [[UNKNOWN]] |
| ; CHECK-NEXT: ret half [[ADD]] |
| ; |
| %inf.or.nan = call half @returns_inf_or_nan() |
| %add = fsub half %inf.or.nan, %unknown |
| ret half %add |
| } |
| |
| define nofpclass(nan) half @ret_nonan__unknown__fsub__inf(half %unknown) { |
| ; CHECK-LABEL: define nofpclass(nan) half @ret_nonan__unknown__fsub__inf( |
| ; CHECK-SAME: half [[UNKNOWN:%.*]]) { |
| ; CHECK-NEXT: [[INF:%.*]] = call half @returns_inf() |
| ; CHECK-NEXT: [[ADD:%.*]] = fsub nnan half [[UNKNOWN]], [[INF]] |
| ; CHECK-NEXT: ret half [[ADD]] |
| ; |
| %inf = call half @returns_inf() |
| %add = fsub half %unknown, %inf |
| ret half %add |
| } |
| |
| define nofpclass(nan) half @ret_nonan__inf__fsub__unknown(half %unknown) { |
| ; CHECK-LABEL: define nofpclass(nan) half @ret_nonan__inf__fsub__unknown( |
| ; CHECK-SAME: half [[UNKNOWN:%.*]]) { |
| ; CHECK-NEXT: [[INF:%.*]] = call half @returns_inf() |
| ; CHECK-NEXT: ret half [[INF]] |
| ; |
| %inf = call half @returns_inf() |
| %add = fsub half %inf, %unknown |
| ret half %add |
| } |
| |
| define nofpclass(nan) half @ret_nonan__unknown__fsub__inf_or_nan(half %unknown) { |
| ; CHECK-LABEL: define nofpclass(nan) half @ret_nonan__unknown__fsub__inf_or_nan( |
| ; CHECK-SAME: half [[UNKNOWN:%.*]]) { |
| ; CHECK-NEXT: [[INF_OR_NAN:%.*]] = call half @returns_inf_or_nan() |
| ; CHECK-NEXT: [[ADD:%.*]] = fsub nnan half [[UNKNOWN]], [[INF_OR_NAN]] |
| ; CHECK-NEXT: ret half [[ADD]] |
| ; |
| %inf.or.nan = call half @returns_inf_or_nan() |
| %add = fsub half %unknown, %inf.or.nan |
| ret half %add |
| } |
| |
| define nofpclass(nan) half @ret_nonan__inf_or_nan__fsub__unknown(half %unknown) { |
| ; CHECK-LABEL: define nofpclass(nan) half @ret_nonan__inf_or_nan__fsub__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 = fsub half %inf.or.nan, %unknown |
| ret half %add |
| } |
| |
| define nofpclass(snan) half @unknown__fsub__zero(half %unknown) { |
| ; CHECK-LABEL: define nofpclass(snan) half @unknown__fsub__zero( |
| ; CHECK-SAME: half [[UNKNOWN:%.*]]) { |
| ; CHECK-NEXT: [[ZERO:%.*]] = call half @returns_zero() |
| ; CHECK-NEXT: [[ADD:%.*]] = fsub half [[UNKNOWN]], [[ZERO]] |
| ; CHECK-NEXT: ret half [[ADD]] |
| ; |
| %zero = call half @returns_zero() |
| %add = fsub half %unknown, %zero |
| ret half %add |
| } |
| |
| define nofpclass(snan) half @zero__fsub__unknown(half %unknown) { |
| ; CHECK-LABEL: define nofpclass(snan) half @zero__fsub__unknown( |
| ; CHECK-SAME: half [[UNKNOWN:%.*]]) { |
| ; CHECK-NEXT: [[ZERO:%.*]] = call half @returns_zero() |
| ; CHECK-NEXT: [[ADD:%.*]] = fsub half [[ZERO]], [[UNKNOWN]] |
| ; CHECK-NEXT: ret half [[ADD]] |
| ; |
| %zero = call half @returns_zero() |
| %add = fsub half %zero, %unknown |
| ret half %add |
| } |
| |
| define nofpclass(nan) half @ret_nonan__unknown__fsub__zero(half %unknown) { |
| ; CHECK-LABEL: define nofpclass(nan) half @ret_nonan__unknown__fsub__zero( |
| ; CHECK-SAME: half [[UNKNOWN:%.*]]) { |
| ; CHECK-NEXT: [[ZERO:%.*]] = call half @returns_zero() |
| ; CHECK-NEXT: [[ADD:%.*]] = fsub nnan half [[UNKNOWN]], [[ZERO]] |
| ; CHECK-NEXT: ret half [[ADD]] |
| ; |
| %zero = call half @returns_zero() |
| %add = fsub half %unknown, %zero |
| ret half %add |
| } |
| |
| define nofpclass(nan) half @ret_nonan__zero__fsub__unknown(half %unknown) { |
| ; CHECK-LABEL: define nofpclass(nan) half @ret_nonan__zero__fsub__unknown( |
| ; CHECK-SAME: half [[UNKNOWN:%.*]]) { |
| ; CHECK-NEXT: [[ZERO:%.*]] = call half @returns_zero() |
| ; CHECK-NEXT: [[ADD:%.*]] = fsub nnan half [[ZERO]], [[UNKNOWN]] |
| ; CHECK-NEXT: ret half [[ADD]] |
| ; |
| %zero = call half @returns_zero() |
| %add = fsub half %zero, %unknown |
| ret half %add |
| } |
| |
| define nofpclass(snan) half @unknown__fsub__pzero(half %unknown) { |
| ; CHECK-LABEL: define nofpclass(snan) half @unknown__fsub__pzero( |
| ; CHECK-SAME: half [[UNKNOWN:%.*]]) { |
| ; CHECK-NEXT: [[PZERO:%.*]] = call half @returns_pzero() |
| ; CHECK-NEXT: ret half [[UNKNOWN]] |
| ; |
| %pzero = call half @returns_pzero() |
| %add = fsub half %unknown, %pzero |
| ret half %add |
| } |
| |
| define nofpclass(snan) half @pzero__fsub__unknown(half %unknown) { |
| ; CHECK-LABEL: define nofpclass(snan) half @pzero__fsub__unknown( |
| ; CHECK-SAME: half [[UNKNOWN:%.*]]) { |
| ; CHECK-NEXT: [[PZERO:%.*]] = call half @returns_pzero() |
| ; CHECK-NEXT: [[ADD:%.*]] = fsub half 0.000000e+00, [[UNKNOWN]] |
| ; CHECK-NEXT: ret half [[ADD]] |
| ; |
| %pzero = call half @returns_pzero() |
| %add = fsub half %pzero, %unknown |
| ret half %add |
| } |
| |
| define nofpclass(nan) half @ret_nonan__unknown__fsub__pzero(half %unknown) { |
| ; CHECK-LABEL: define nofpclass(nan) half @ret_nonan__unknown__fsub__pzero( |
| ; CHECK-SAME: half [[UNKNOWN:%.*]]) { |
| ; CHECK-NEXT: [[PZERO:%.*]] = call half @returns_pzero() |
| ; CHECK-NEXT: ret half [[UNKNOWN]] |
| ; |
| %pzero = call half @returns_pzero() |
| %add = fsub half %unknown, %pzero |
| ret half %add |
| } |
| |
| define nofpclass(nan) half @ret_nonan__pzero__fsub__unknown(half %unknown) { |
| ; CHECK-LABEL: define nofpclass(nan) half @ret_nonan__pzero__fsub__unknown( |
| ; CHECK-SAME: half [[UNKNOWN:%.*]]) { |
| ; CHECK-NEXT: [[PZERO:%.*]] = call half @returns_pzero() |
| ; CHECK-NEXT: [[ADD:%.*]] = fsub nnan half 0.000000e+00, [[UNKNOWN]] |
| ; CHECK-NEXT: ret half [[ADD]] |
| ; |
| %pzero = call half @returns_pzero() |
| %add = fsub half %pzero, %unknown |
| ret half %add |
| } |
| |
| define nofpclass(snan) half @unknown__fsub__nzero(half %unknown) { |
| ; CHECK-LABEL: define nofpclass(snan) half @unknown__fsub__nzero( |
| ; CHECK-SAME: half [[UNKNOWN:%.*]]) { |
| ; CHECK-NEXT: [[NZERO:%.*]] = call half @returns_nzero() |
| ; CHECK-NEXT: [[ADD:%.*]] = fadd half [[UNKNOWN]], 0.000000e+00 |
| ; CHECK-NEXT: ret half [[ADD]] |
| ; |
| %nzero = call half @returns_nzero() |
| %add = fsub half %unknown, %nzero |
| ret half %add |
| } |
| |
| define nofpclass(snan) half @nzero__fsub__unknown(half %unknown) { |
| ; CHECK-LABEL: define nofpclass(snan) half @nzero__fsub__unknown( |
| ; CHECK-SAME: half [[UNKNOWN:%.*]]) { |
| ; CHECK-NEXT: [[NZERO:%.*]] = call half @returns_nzero() |
| ; CHECK-NEXT: [[ADD:%.*]] = fneg half [[UNKNOWN]] |
| ; CHECK-NEXT: ret half [[ADD]] |
| ; |
| %nzero = call half @returns_nzero() |
| %add = fsub half %nzero, %unknown |
| ret half %add |
| } |
| |
| define nofpclass(snan) half @unknown__fsub__nzero_or_nan(half %unknown) { |
| ; CHECK-LABEL: define nofpclass(snan) half @unknown__fsub__nzero_or_nan( |
| ; CHECK-SAME: half [[UNKNOWN:%.*]]) { |
| ; CHECK-NEXT: [[NZERO_OR_NAN:%.*]] = call half @returns_nzero_or_nan() |
| ; CHECK-NEXT: [[ADD:%.*]] = fsub half [[UNKNOWN]], [[NZERO_OR_NAN]] |
| ; CHECK-NEXT: ret half [[ADD]] |
| ; |
| %nzero.or.nan = call half @returns_nzero_or_nan() |
| %add = fsub half %unknown, %nzero.or.nan |
| ret half %add |
| } |
| |
| define nofpclass(snan) half @nzero_or_nan__fsub__unknown(half %unknown) { |
| ; CHECK-LABEL: define nofpclass(snan) half @nzero_or_nan__fsub__unknown( |
| ; CHECK-SAME: half [[UNKNOWN:%.*]]) { |
| ; CHECK-NEXT: [[NZERO_OR_NAN:%.*]] = call half @returns_nzero_or_nan() |
| ; CHECK-NEXT: [[ADD:%.*]] = fsub half [[NZERO_OR_NAN]], [[UNKNOWN]] |
| ; CHECK-NEXT: ret half [[ADD]] |
| ; |
| %nzero.or.nan = call half @returns_nzero_or_nan() |
| %add = fsub half %nzero.or.nan, %unknown |
| ret half %add |
| } |
| |
| define nofpclass(nan) half @ret_nonan__unknown__fsub__nzero(half %unknown) { |
| ; CHECK-LABEL: define nofpclass(nan) half @ret_nonan__unknown__fsub__nzero( |
| ; CHECK-SAME: half [[UNKNOWN:%.*]]) { |
| ; CHECK-NEXT: [[NZERO:%.*]] = call half @returns_nzero() |
| ; CHECK-NEXT: [[ADD:%.*]] = fadd nnan half [[UNKNOWN]], 0.000000e+00 |
| ; CHECK-NEXT: ret half [[ADD]] |
| ; |
| %nzero = call half @returns_nzero() |
| %add = fsub half %unknown, %nzero |
| ret half %add |
| } |
| |
| define nofpclass(nan) half @ret_nonan__nzero__fsub__unknown(half %unknown) { |
| ; CHECK-LABEL: define nofpclass(nan) half @ret_nonan__nzero__fsub__unknown( |
| ; CHECK-SAME: half [[UNKNOWN:%.*]]) { |
| ; CHECK-NEXT: [[NZERO:%.*]] = call half @returns_nzero() |
| ; CHECK-NEXT: [[ADD:%.*]] = fneg half [[UNKNOWN]] |
| ; CHECK-NEXT: ret half [[ADD]] |
| ; |
| %nzero = call half @returns_nzero() |
| %add = fsub half %nzero, %unknown |
| ret half %add |
| } |
| |
| define nofpclass(snan) half @not_nzero__fsub__zero(half nofpclass(nzero) %not.nzero) { |
| ; CHECK-LABEL: define nofpclass(snan) half @not_nzero__fsub__zero( |
| ; CHECK-SAME: half nofpclass(nzero) [[NOT_NZERO:%.*]]) { |
| ; CHECK-NEXT: [[ZERO:%.*]] = call half @returns_zero() |
| ; CHECK-NEXT: [[ADD:%.*]] = fsub half [[NOT_NZERO]], [[ZERO]] |
| ; CHECK-NEXT: ret half [[ADD]] |
| ; |
| %zero = call half @returns_zero() |
| %add = fsub half %not.nzero, %zero |
| ret half %add |
| } |
| |
| define nofpclass(snan) half @zero__fsub__not_nzero(half nofpclass(nzero) %not.nzero) { |
| ; CHECK-LABEL: define nofpclass(snan) half @zero__fsub__not_nzero( |
| ; CHECK-SAME: half nofpclass(nzero) [[NOT_NZERO:%.*]]) { |
| ; CHECK-NEXT: [[ZERO:%.*]] = call half @returns_zero() |
| ; CHECK-NEXT: [[ADD:%.*]] = fsub half [[ZERO]], [[NOT_NZERO]] |
| ; CHECK-NEXT: ret half [[ADD]] |
| ; |
| %zero = call half @returns_zero() |
| %add = fsub half %zero, %not.nzero |
| ret half %add |
| } |
| |
| define nofpclass(snan) half @not_nzero__fsub__pzero(half nofpclass(nzero) %not.nzero) { |
| ; CHECK-LABEL: define nofpclass(snan) half @not_nzero__fsub__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 = fsub half %not.nzero, %pzero |
| ret half %add |
| } |
| |
| define nofpclass(snan) half @pzero__fsub__not_nzero(half nofpclass(nzero) %not.nzero) { |
| ; CHECK-LABEL: define nofpclass(snan) half @pzero__fsub__not_nzero( |
| ; CHECK-SAME: half nofpclass(nzero) [[NOT_NZERO:%.*]]) { |
| ; CHECK-NEXT: [[PZERO:%.*]] = call half @returns_pzero() |
| ; CHECK-NEXT: [[ADD:%.*]] = fsub half 0.000000e+00, [[NOT_NZERO]] |
| ; CHECK-NEXT: ret half [[ADD]] |
| ; |
| %pzero = call half @returns_pzero() |
| %add = fsub half %pzero, %not.nzero |
| ret half %add |
| } |
| |
| define nofpclass(snan) half @not_nzero__fsub__zero_or_nan(half nofpclass(nzero) %not.nzero) { |
| ; CHECK-LABEL: define nofpclass(snan) half @not_nzero__fsub__zero_or_nan( |
| ; CHECK-SAME: half nofpclass(nzero) [[NOT_NZERO:%.*]]) { |
| ; CHECK-NEXT: [[ZERO_OR_NAN:%.*]] = call half @returns_zero_or_nan() |
| ; CHECK-NEXT: [[ADD:%.*]] = fsub half [[NOT_NZERO]], [[ZERO_OR_NAN]] |
| ; CHECK-NEXT: ret half [[ADD]] |
| ; |
| %zero.or.nan = call half @returns_zero_or_nan() |
| %add = fsub half %not.nzero, %zero.or.nan |
| ret half %add |
| } |
| |
| define nofpclass(snan) half @zero_or_nan__fsub__not_nzero(half nofpclass(nzero) %not.nzero) { |
| ; CHECK-LABEL: define nofpclass(snan) half @zero_or_nan__fsub__not_nzero( |
| ; CHECK-SAME: half nofpclass(nzero) [[NOT_NZERO:%.*]]) { |
| ; CHECK-NEXT: [[ZERO_OR_NAN:%.*]] = call half @returns_zero_or_nan() |
| ; CHECK-NEXT: [[ADD:%.*]] = fsub half [[ZERO_OR_NAN]], [[NOT_NZERO]] |
| ; CHECK-NEXT: ret half [[ADD]] |
| ; |
| %zero.or.nan = call half @returns_zero_or_nan() |
| %add = fsub half %zero.or.nan, %not.nzero |
| ret half %add |
| } |
| |
| define nofpclass(snan) half @not_nzero__fsub__pzero_or_nan(half nofpclass(nzero) %not.nzero) { |
| ; CHECK-LABEL: define nofpclass(snan) half @not_nzero__fsub__pzero_or_nan( |
| ; CHECK-SAME: half nofpclass(nzero) [[NOT_NZERO:%.*]]) { |
| ; CHECK-NEXT: [[PZERO_OR_NAN:%.*]] = call half @returns_pzero_or_nan() |
| ; CHECK-NEXT: [[ADD:%.*]] = fsub half [[NOT_NZERO]], [[PZERO_OR_NAN]] |
| ; CHECK-NEXT: ret half [[ADD]] |
| ; |
| %pzero.or.nan = call half @returns_pzero_or_nan() |
| %add = fsub half %not.nzero, %pzero.or.nan |
| ret half %add |
| } |
| |
| define nofpclass(snan) half @pzero_or_nan__fsub__not_nzero(half nofpclass(nzero) %not.nzero) { |
| ; CHECK-LABEL: define nofpclass(snan) half @pzero_or_nan__fsub__not_nzero( |
| ; CHECK-SAME: half nofpclass(nzero) [[NOT_NZERO:%.*]]) { |
| ; CHECK-NEXT: [[PZERO_OR_NAN:%.*]] = call half @returns_pzero_or_nan() |
| ; CHECK-NEXT: [[ADD:%.*]] = fsub half [[PZERO_OR_NAN]], [[NOT_NZERO]] |
| ; CHECK-NEXT: ret half [[ADD]] |
| ; |
| %pzero.or.nan = call half @returns_pzero_or_nan() |
| %add = fsub half %pzero.or.nan, %not.nzero |
| ret half %add |
| } |
| |
| define nofpclass(snan) half @unknown__fsub_nsz__pzero(half %unknown) { |
| ; CHECK-LABEL: define nofpclass(snan) half @unknown__fsub_nsz__pzero( |
| ; CHECK-SAME: half [[UNKNOWN:%.*]]) { |
| ; CHECK-NEXT: [[PZERO:%.*]] = call half @returns_pzero() |
| ; CHECK-NEXT: ret half [[UNKNOWN]] |
| ; |
| %pzero = call half @returns_pzero() |
| %add = fsub nsz half %unknown, %pzero |
| ret half %add |
| } |
| |
| define nofpclass(snan) half @pzero__fsub_nsz__unknown(half %unknown) { |
| ; CHECK-LABEL: define nofpclass(snan) half @pzero__fsub_nsz__unknown( |
| ; CHECK-SAME: half [[UNKNOWN:%.*]]) { |
| ; CHECK-NEXT: [[PZERO:%.*]] = call half @returns_pzero() |
| ; CHECK-NEXT: [[ADD:%.*]] = fneg nsz half [[UNKNOWN]] |
| ; CHECK-NEXT: ret half [[ADD]] |
| ; |
| %pzero = call half @returns_pzero() |
| %add = fsub nsz half %pzero, %unknown |
| ret half %add |
| } |
| |
| define nofpclass(snan) half @unknown__fsub_nsz__pzero_or_nan(half %unknown) { |
| ; CHECK-LABEL: define nofpclass(snan) half @unknown__fsub_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 = fsub nsz half %unknown, %pzero.or.nan |
| ret half %add |
| } |
| |
| define nofpclass(snan) half @pzero_or_nan__fsub_nsz__unknown(half %unknown) { |
| ; CHECK-LABEL: define nofpclass(snan) half @pzero_or_nan__fsub_nsz__unknown( |
| ; CHECK-SAME: half [[UNKNOWN:%.*]]) { |
| ; CHECK-NEXT: [[PZERO_OR_NAN:%.*]] = call half @returns_pzero_or_nan() |
| ; CHECK-NEXT: [[ADD:%.*]] = fsub nsz half [[PZERO_OR_NAN]], [[UNKNOWN]] |
| ; CHECK-NEXT: ret half [[ADD]] |
| ; |
| %pzero.or.nan = call half @returns_pzero_or_nan() |
| %add = fsub nsz half %pzero.or.nan, %unknown |
| ret half %add |
| } |
| |
| define nofpclass(snan) half @unknown__fsub_nsz__zero(half %unknown) { |
| ; CHECK-LABEL: define nofpclass(snan) half @unknown__fsub_nsz__zero( |
| ; CHECK-SAME: half [[UNKNOWN:%.*]]) { |
| ; CHECK-NEXT: [[ZERO:%.*]] = call half @returns_zero() |
| ; CHECK-NEXT: [[ADD:%.*]] = fsub nsz half [[UNKNOWN]], [[ZERO]] |
| ; CHECK-NEXT: ret half [[ADD]] |
| ; |
| %zero = call half @returns_zero() |
| %add = fsub nsz half %unknown, %zero |
| ret half %add |
| } |
| |
| define nofpclass(snan) half @zero__fsub_nsz__unknown(half %unknown) { |
| ; CHECK-LABEL: define nofpclass(snan) half @zero__fsub_nsz__unknown( |
| ; CHECK-SAME: half [[UNKNOWN:%.*]]) { |
| ; CHECK-NEXT: [[ZERO:%.*]] = call half @returns_zero() |
| ; CHECK-NEXT: [[ADD:%.*]] = fsub nsz half [[ZERO]], [[UNKNOWN]] |
| ; CHECK-NEXT: ret half [[ADD]] |
| ; |
| %zero = call half @returns_zero() |
| %add = fsub nsz half %zero, %unknown |
| ret half %add |
| } |
| |
| define nofpclass(snan) half @unknown__fsub_nsz__zero_or_nan(half %unknown) { |
| ; CHECK-LABEL: define nofpclass(snan) half @unknown__fsub_nsz__zero_or_nan( |
| ; CHECK-SAME: half [[UNKNOWN:%.*]]) { |
| ; CHECK-NEXT: [[ZERO_OR_NAN:%.*]] = call half @returns_zero() |
| ; CHECK-NEXT: [[ADD:%.*]] = fsub nsz half [[UNKNOWN]], [[ZERO_OR_NAN]] |
| ; CHECK-NEXT: ret half [[ADD]] |
| ; |
| %zero.or.nan = call half @returns_zero() |
| %add = fsub nsz half %unknown, %zero.or.nan |
| ret half %add |
| } |
| |
| define nofpclass(snan) half @zero_or_nan__fsub_nsz__unknown(half %unknown) { |
| ; CHECK-LABEL: define nofpclass(snan) half @zero_or_nan__fsub_nsz__unknown( |
| ; CHECK-SAME: half [[UNKNOWN:%.*]]) { |
| ; CHECK-NEXT: [[ZERO_OR_NAN:%.*]] = call half @returns_zero_or_nan() |
| ; CHECK-NEXT: [[ADD:%.*]] = fsub nsz half [[ZERO_OR_NAN]], [[UNKNOWN]] |
| ; CHECK-NEXT: ret half [[ADD]] |
| ; |
| %zero.or.nan = call half @returns_zero_or_nan() |
| %add = fsub 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:%.*]] = fsub half [[SELECT]], [[NORMAL]] |
| ; CHECK-NEXT: ret half [[ADD]] |
| ; |
| %nan = call half @returns_nan() |
| %select = select i1 %cond, half %nan, half %unknown |
| %add = fsub 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:%.*]] = fsub half [[NORMAL]], [[SELECT]] |
| ; CHECK-NEXT: ret half [[ADD]] |
| ; |
| %nan = call half @returns_nan() |
| %select = select i1 %cond, half %nan, half %unknown |
| %add = fsub half %normal, %select |
| ret half %add |
| } |
| |
| define nofpclass(snan) half @not_nzero__fsub__pzero__daz(half nofpclass(nzero) %not.nzero) #0 { |
| ; CHECK-LABEL: define nofpclass(snan) half @not_nzero__fsub__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 = fsub half %not.nzero, %pzero |
| ret half %add |
| } |
| |
| define nofpclass(snan) half @pzero__fsub__not_nzero__daz(half nofpclass(nzero) %not.nzero) #0 { |
| ; CHECK-LABEL: define nofpclass(snan) half @pzero__fsub__not_nzero__daz( |
| ; CHECK-SAME: half nofpclass(nzero) [[NOT_NZERO:%.*]]) #[[ATTR0]] { |
| ; CHECK-NEXT: [[PZERO:%.*]] = call half @returns_pzero() |
| ; CHECK-NEXT: [[ADD:%.*]] = fsub half 0.000000e+00, [[NOT_NZERO]] |
| ; CHECK-NEXT: ret half [[ADD]] |
| ; |
| %pzero = call half @returns_pzero() |
| %add = fsub half %pzero, %not.nzero |
| ret half %add |
| } |
| |
| define nofpclass(snan) half @not_nzero__fsub__pzero__dynamic(half nofpclass(nzero) %not.nzero) #1 { |
| ; CHECK-LABEL: define nofpclass(snan) half @not_nzero__fsub__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 = fsub half %not.nzero, %pzero |
| ret half %add |
| } |
| |
| define nofpclass(snan) half @pzero__fsub__not_nzero__dynamic(half nofpclass(nzero) %not.nzero) #1 { |
| ; CHECK-LABEL: define nofpclass(snan) half @pzero__fsub__not_nzero__dynamic( |
| ; CHECK-SAME: half nofpclass(nzero) [[NOT_NZERO:%.*]]) #[[ATTR1]] { |
| ; CHECK-NEXT: [[PZERO:%.*]] = call half @returns_pzero() |
| ; CHECK-NEXT: [[ADD:%.*]] = fsub half 0.000000e+00, [[NOT_NZERO]] |
| ; CHECK-NEXT: ret half [[ADD]] |
| ; |
| %pzero = call half @returns_pzero() |
| %add = fsub half %pzero, %not.nzero |
| ret half %add |
| } |
| |
| define nofpclass(snan) half @not_nzero_nsub__fsub__pzero__daz(half nofpclass(nzero nsub) %not.nzero.nsub) #0 { |
| ; CHECK-LABEL: define nofpclass(snan) half @not_nzero_nsub__fsub__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 = fsub half %not.nzero.nsub, %pzero |
| ret half %add |
| } |
| |
| define nofpclass(snan) half @pzero__fsub__not_nzero_nsub__daz(half nofpclass(nzero nsub) %not.nzero.nsub) #0 { |
| ; CHECK-LABEL: define nofpclass(snan) half @pzero__fsub__not_nzero_nsub__daz( |
| ; CHECK-SAME: half nofpclass(nzero nsub) [[NOT_NZERO_NSUB:%.*]]) #[[ATTR0]] { |
| ; CHECK-NEXT: [[PZERO:%.*]] = call half @returns_pzero() |
| ; CHECK-NEXT: [[ADD:%.*]] = fsub half 0.000000e+00, [[NOT_NZERO_NSUB]] |
| ; CHECK-NEXT: ret half [[ADD]] |
| ; |
| %pzero = call half @returns_pzero() |
| %add = fsub half %pzero, %not.nzero.nsub |
| ret half %add |
| } |
| |
| define nofpclass(snan) half @not_nzero_nsub__fsub__pzero__dynamic(half nofpclass(nzero nsub) %not.nzero.nsub) #1 { |
| ; CHECK-LABEL: define nofpclass(snan) half @not_nzero_nsub__fsub__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 = fsub half %not.nzero.nsub, %pzero |
| ret half %add |
| } |
| |
| define nofpclass(snan) half @pzero__fsub__not_nzero_nsub__dynamic(half nofpclass(nzero nsub) %not.nzero.nsub) #1 { |
| ; CHECK-LABEL: define nofpclass(snan) half @pzero__fsub__not_nzero_nsub__dynamic( |
| ; CHECK-SAME: half nofpclass(nzero nsub) [[NOT_NZERO_NSUB:%.*]]) #[[ATTR1]] { |
| ; CHECK-NEXT: [[PZERO:%.*]] = call half @returns_pzero() |
| ; CHECK-NEXT: [[ADD:%.*]] = fsub half 0.000000e+00, [[NOT_NZERO_NSUB]] |
| ; CHECK-NEXT: ret half [[ADD]] |
| ; |
| %pzero = call half @returns_pzero() |
| %add = fsub half %pzero, %not.nzero.nsub |
| ret half %add |
| } |
| |
| define nofpclass(nan) half @ret_nonan__fsub_self__nonan(i1 %cond, half noundef %unknown) { |
| ; CHECK-LABEL: define nofpclass(nan) half @ret_nonan__fsub_self__nonan( |
| ; CHECK-SAME: i1 [[COND:%.*]], half noundef [[UNKNOWN:%.*]]) { |
| ; CHECK-NEXT: [[NAN:%.*]] = call noundef half @returns_nan() |
| ; CHECK-NEXT: ret half 0.000000e+00 |
| ; |
| %nan = call noundef half @returns_nan() |
| %select = select i1 %cond, half %nan, half %unknown |
| %add = fsub half %select, %select |
| ret half %add |
| } |
| |
| define nofpclass(nan) half @ret_nonan_fneg_fabs_fsub_known_negative_or_nan_sources() { |
| ; CHECK-LABEL: define nofpclass(nan) half @ret_nonan_fneg_fabs_fsub_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_SUB:%.*]] = fsub nnan half [[NEGATIVE_OR_NAN0]], [[NEGATIVE_OR_NAN1]] |
| ; CHECK-NEXT: [[FABS:%.*]] = call half @llvm.fabs.f16(half [[KNOWN_NEGATIVE_SUB]]) |
| ; 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.sub = fsub half %negative.or.nan0, %negative.or.nan1 |
| %fabs = call half @llvm.fabs.f16(half %known.negative.sub) |
| %neg.fabs = fneg half %fabs |
| ret half %neg.fabs |
| } |
| |
| define nofpclass(nan) half @ret_nonan_fneg_fabs_fsub_known_negative_sources() { |
| ; CHECK-LABEL: define nofpclass(nan) half @ret_nonan_fneg_fabs_fsub_known_negative_sources() { |
| ; CHECK-NEXT: [[NEGATIVE0:%.*]] = call half @returns_negative() |
| ; CHECK-NEXT: [[NEGATIVE1:%.*]] = call half @returns_negative() |
| ; CHECK-NEXT: [[KNOWN_NEGATIVE_OP:%.*]] = fsub 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 = fsub 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__fsub__known_negative_or_nan() { |
| ; CHECK-LABEL: define nofpclass(snan) half @ret_no_snan__known_positive_or_nan__fsub__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:%.*]] = fsub 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 = fsub half %positive.or.nan, %negative.or.nan |
| ret half %result |
| } |
| |
| define nofpclass(snan) half @ret_no_snan__known_negative_or_nan__fsub__known_positive_or_nan() { |
| ; CHECK-LABEL: define nofpclass(snan) half @ret_no_snan__known_negative_or_nan__fsub__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:%.*]] = fsub 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 = fsub half %negative.or.nan, %positive.or.nan |
| ret half %result |
| } |
| |
| define nofpclass(snan) half @ret_no_snan__known_positive__fsub__known_negative() { |
| ; CHECK-LABEL: define nofpclass(snan) half @ret_no_snan__known_positive__fsub__known_negative() { |
| ; CHECK-NEXT: [[POSITIVE:%.*]] = call half @returns_positive_or_nan() |
| ; CHECK-NEXT: [[NEGATIVE:%.*]] = call half @returns_negative_or_nan() |
| ; CHECK-NEXT: [[RESULT:%.*]] = fsub half [[POSITIVE]], [[NEGATIVE]] |
| ; CHECK-NEXT: ret half [[RESULT]] |
| ; |
| %positive = call half @returns_positive_or_nan() |
| %negative = call half @returns_negative_or_nan() |
| %result = fsub half %positive, %negative |
| ret half %result |
| } |
| |
| define nofpclass(snan) half @ret_no_snan__known_negative__fsub__known_positive() { |
| ; CHECK-LABEL: define nofpclass(snan) half @ret_no_snan__known_negative__fsub__known_positive() { |
| ; CHECK-NEXT: [[NEGATIVE:%.*]] = call half @returns_negative_or_nan() |
| ; CHECK-NEXT: [[POSITIVE:%.*]] = call half @returns_positive_or_nan() |
| ; CHECK-NEXT: [[RESULT:%.*]] = fsub half [[NEGATIVE]], [[POSITIVE]] |
| ; CHECK-NEXT: ret half [[RESULT]] |
| ; |
| %negative = call half @returns_negative_or_nan() |
| %positive = call half @returns_positive_or_nan() |
| %result = fsub half %negative, %positive |
| 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:%.*]] = fsub half [[SELECT]], [[UNKNOWN1]] |
| ; CHECK-NEXT: ret half [[RESULT]] |
| ; |
| %snan = call half @returns_snan() |
| %select = select i1 %cond, half %snan, half %unknown0 |
| %result = fsub 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:%.*]] = fsub half [[UNKNOWN1]], [[SELECT]] |
| ; CHECK-NEXT: ret half [[RESULT]] |
| ; |
| %snan = call half @returns_snan() |
| %select = select i1 %cond, half %snan, half %unknown0 |
| %result = fsub half %unknown1, %select |
| ret half %result |
| } |
| |
| attributes #0 = { denormal_fpenv(preservesign) } |
| attributes #1 = { denormal_fpenv(dynamic) } |