| ; 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(ninf norm sub zero nan) half @returns_pinf() |
| declare nofpclass(pinf norm sub zero nan) half @returns_ninf() |
| declare nofpclass(norm sub zero nan) half @returns_inf() |
| declare nofpclass(inf norm sub zero) half @returns_nan() |
| declare nofpclass(norm sub zero) half @returns_inf_or_nan() |
| declare nofpclass(qnan inf norm sub zero) half @returns_snan() |
| declare nofpclass(snan inf norm sub zero) half @returns_qnan() |
| declare nofpclass(nan inf norm sub pzero) half @returns_nzero() |
| declare nofpclass(nan inf norm sub nzero) half @returns_pzero() |
| declare nofpclass(nan inf norm sub) half @returns_zero() |
| declare nofpclass(pinf pnorm psub pzero nan) half @returns_negative() |
| declare nofpclass(ninf nnorm nsub nzero nan) half @returns_positive() |
| |
| declare [2 x half] @returns_array() |
| declare { half } @returns_one_elt_struct() |
| declare { half, i32 } @returns_frexp_struct() |
| |
| define nofpclass(nan) half @extractvalue_array_0() { |
| ; CHECK-LABEL: define nofpclass(nan) half @extractvalue_array_0() { |
| ; CHECK-NEXT: [[ARRAY:%.*]] = call [2 x half] @returns_array() |
| ; CHECK-NEXT: [[EXTRACT:%.*]] = extractvalue [2 x half] [[ARRAY]], 0 |
| ; CHECK-NEXT: ret half [[EXTRACT]] |
| ; |
| %array = call [2 x half] @returns_array() |
| %extract = extractvalue [2 x half] %array, 0 |
| ret half %extract |
| } |
| |
| define nofpclass(nan) half @extractvalue_array_1() { |
| ; CHECK-LABEL: define nofpclass(nan) half @extractvalue_array_1() { |
| ; CHECK-NEXT: [[ARRAY:%.*]] = call [2 x half] @returns_array() |
| ; CHECK-NEXT: [[EXTRACT:%.*]] = extractvalue [2 x half] [[ARRAY]], 1 |
| ; CHECK-NEXT: ret half [[EXTRACT]] |
| ; |
| %array = call [2 x half] @returns_array() |
| %extract = extractvalue [2 x half] %array, 1 |
| ret half %extract |
| } |
| |
| define nofpclass(nan) half @extractvalue_one_elt_struct() { |
| ; CHECK-LABEL: define nofpclass(nan) half @extractvalue_one_elt_struct() { |
| ; CHECK-NEXT: [[STRUCT:%.*]] = call { half } @returns_one_elt_struct() |
| ; CHECK-NEXT: [[EXTRACT:%.*]] = extractvalue { half } [[STRUCT]], 0 |
| ; CHECK-NEXT: ret half [[EXTRACT]] |
| ; |
| %struct = call { half } @returns_one_elt_struct() |
| %extract = extractvalue { half } %struct, 0 |
| ret half %extract |
| } |
| |
| define nofpclass(nan) half @extractvalue_not_frexp() { |
| ; CHECK-LABEL: define nofpclass(nan) half @extractvalue_not_frexp() { |
| ; CHECK-NEXT: [[STRUCT:%.*]] = call { half, i32 } @returns_frexp_struct() |
| ; CHECK-NEXT: [[EXTRACT:%.*]] = extractvalue { half, i32 } [[STRUCT]], 0 |
| ; CHECK-NEXT: ret half [[EXTRACT]] |
| ; |
| %struct = call { half, i32 } @returns_frexp_struct() |
| %extract = extractvalue { half, i32 } %struct, 0 |
| ret half %extract |
| } |
| |
| define nofpclass(snan inf norm sub zero) half @ret_only_qnan__frexp(half %unknown) { |
| ; CHECK-LABEL: define nofpclass(snan inf zero sub norm) half @ret_only_qnan__frexp( |
| ; CHECK-SAME: half [[UNKNOWN:%.*]]) { |
| ; CHECK-NEXT: ret half 0xH7E00 |
| ; |
| %frexp = call { half, i32 } @llvm.frexp.f16.i32(half %unknown) |
| %frexp.mant = extractvalue { half, i32 } %frexp, 0 |
| ret half %frexp.mant |
| } |
| |
| define nofpclass(qnan inf norm sub zero) half @ret_only_snan__frexp(half %unknown) { |
| ; CHECK-LABEL: define nofpclass(qnan inf zero sub norm) half @ret_only_snan__frexp( |
| ; CHECK-SAME: half [[UNKNOWN:%.*]]) { |
| ; CHECK-NEXT: ret half [[UNKNOWN]] |
| ; |
| %frexp = call { half, i32 } @llvm.frexp.f16.i32(half %unknown) |
| %frexp.mant = extractvalue { half, i32 } %frexp, 0 |
| ret half %frexp.mant |
| } |
| |
| define nofpclass(inf norm sub zero) half @ret_only_nan__frexp(half %unknown) { |
| ; CHECK-LABEL: define nofpclass(inf zero sub norm) half @ret_only_nan__frexp( |
| ; CHECK-SAME: half [[UNKNOWN:%.*]]) { |
| ; CHECK-NEXT: ret half 0xH7E00 |
| ; |
| %frexp = call { half, i32 } @llvm.frexp.f16.i32(half %unknown) |
| %frexp.mant = extractvalue { half, i32 } %frexp, 0 |
| ret half %frexp.mant |
| } |
| |
| define nofpclass(nan ninf norm sub zero) half @ret_only_pinf__frexp(half %unknown) { |
| ; CHECK-LABEL: define nofpclass(nan ninf zero sub norm) half @ret_only_pinf__frexp( |
| ; CHECK-SAME: half [[UNKNOWN:%.*]]) { |
| ; CHECK-NEXT: ret half 0xH7C00 |
| ; |
| %frexp = call { half, i32 } @llvm.frexp.f16.i32(half %unknown) |
| %frexp.mant = extractvalue { half, i32 } %frexp, 0 |
| ret half %frexp.mant |
| } |
| |
| define nofpclass(nan pinf norm sub zero) half @ret_only_ninf__frexp(half %unknown) { |
| ; CHECK-LABEL: define nofpclass(nan pinf zero sub norm) half @ret_only_ninf__frexp( |
| ; CHECK-SAME: half [[UNKNOWN:%.*]]) { |
| ; CHECK-NEXT: ret half 0xHFC00 |
| ; |
| %frexp = call { half, i32 } @llvm.frexp.f16.i32(half %unknown) |
| %frexp.mant = extractvalue { half, i32 } %frexp, 0 |
| ret half %frexp.mant |
| } |
| |
| define nofpclass(nan norm sub zero) half @ret_only_inf__frexp(half %unknown) { |
| ; CHECK-LABEL: define nofpclass(nan zero sub norm) half @ret_only_inf__frexp( |
| ; CHECK-SAME: half [[UNKNOWN:%.*]]) { |
| ; CHECK-NEXT: ret half [[UNKNOWN]] |
| ; |
| %frexp = call { half, i32 } @llvm.frexp.f16.i32(half %unknown) |
| %frexp.mant = extractvalue { half, i32 } %frexp, 0 |
| ret half %frexp.mant |
| } |
| |
| define nofpclass(nan inf norm sub nzero) half @ret_only_pzero__frexp(half %unknown) { |
| ; CHECK-LABEL: define nofpclass(nan inf nzero sub norm) half @ret_only_pzero__frexp( |
| ; CHECK-SAME: half [[UNKNOWN:%.*]]) { |
| ; CHECK-NEXT: ret half 0xH0000 |
| ; |
| %frexp = call { half, i32 } @llvm.frexp.f16.i32(half %unknown) |
| %frexp.mant = extractvalue { half, i32 } %frexp, 0 |
| ret half %frexp.mant |
| } |
| |
| define nofpclass(nan inf norm sub nzero) half @ret_only_nzero__frexp(half %unknown) { |
| ; CHECK-LABEL: define nofpclass(nan inf nzero sub norm) half @ret_only_nzero__frexp( |
| ; CHECK-SAME: half [[UNKNOWN:%.*]]) { |
| ; CHECK-NEXT: ret half 0xH0000 |
| ; |
| %frexp = call { half, i32 } @llvm.frexp.f16.i32(half %unknown) |
| %frexp.mant = extractvalue { half, i32 } %frexp, 0 |
| ret half %frexp.mant |
| } |
| |
| define nofpclass(nan inf norm sub) half @ret_only_zero__frexp(half %unknown) { |
| ; CHECK-LABEL: define nofpclass(nan inf sub norm) half @ret_only_zero__frexp( |
| ; CHECK-SAME: half [[UNKNOWN:%.*]]) { |
| ; CHECK-NEXT: [[FREXP:%.*]] = call { half, i32 } @llvm.frexp.f16.i32(half [[UNKNOWN]]) |
| ; CHECK-NEXT: [[FREXP_MANT:%.*]] = extractvalue { half, i32 } [[FREXP]], 0 |
| ; CHECK-NEXT: ret half [[FREXP_MANT]] |
| ; |
| %frexp = call { half, i32 } @llvm.frexp.f16.i32(half %unknown) |
| %frexp.mant = extractvalue { half, i32 } %frexp, 0 |
| ret half %frexp.mant |
| } |
| |
| define nofpclass(nan inf norm nsub zero) half @ret_only_psub__frexp(half %unknown) { |
| ; CHECK-LABEL: define nofpclass(nan inf zero nsub norm) half @ret_only_psub__frexp( |
| ; CHECK-SAME: half [[UNKNOWN:%.*]]) { |
| ; CHECK-NEXT: ret half poison |
| ; |
| %frexp = call { half, i32 } @llvm.frexp.f16.i32(half %unknown) |
| %frexp.mant = extractvalue { half, i32 } %frexp, 0 |
| ret half %frexp.mant |
| } |
| |
| define nofpclass(nan inf norm psub zero) half @ret_only_nsub__frexp(half %unknown) { |
| ; CHECK-LABEL: define nofpclass(nan inf zero psub norm) half @ret_only_nsub__frexp( |
| ; CHECK-SAME: half [[UNKNOWN:%.*]]) { |
| ; CHECK-NEXT: ret half poison |
| ; |
| %frexp = call { half, i32 } @llvm.frexp.f16.i32(half %unknown) |
| %frexp.mant = extractvalue { half, i32 } %frexp, 0 |
| ret half %frexp.mant |
| } |
| |
| define nofpclass(nan inf norm zero) half @ret_only_sub__frexp(half %unknown) { |
| ; CHECK-LABEL: define nofpclass(nan inf zero norm) half @ret_only_sub__frexp( |
| ; CHECK-SAME: half [[UNKNOWN:%.*]]) { |
| ; CHECK-NEXT: ret half poison |
| ; |
| %frexp = call { half, i32 } @llvm.frexp.f16.i32(half %unknown) |
| %frexp.mant = extractvalue { half, i32 } %frexp, 0 |
| ret half %frexp.mant |
| } |
| |
| define nofpclass(all) half @ret_nothing__frexp(half %unknown) { |
| ; CHECK-LABEL: define nofpclass(all) half @ret_nothing__frexp( |
| ; CHECK-SAME: half [[UNKNOWN:%.*]]) { |
| ; CHECK-NEXT: ret half poison |
| ; |
| %frexp = call { half, i32 } @llvm.frexp.f16.i32(half %unknown) |
| %frexp.mant = extractvalue { half, i32 } %frexp, 0 |
| ret half %frexp.mant |
| } |
| |
| define nofpclass(pinf) half @ret_nofpclass_pinf__frexp_select_unknown_or_pinf(i1 %cond, half %unknown) { |
| ; CHECK-LABEL: define nofpclass(pinf) half @ret_nofpclass_pinf__frexp_select_unknown_or_pinf( |
| ; CHECK-SAME: i1 [[COND:%.*]], half [[UNKNOWN:%.*]]) { |
| ; CHECK-NEXT: [[ONLY_PINF:%.*]] = call half @returns_pinf() |
| ; CHECK-NEXT: [[FREXP:%.*]] = call { half, i32 } @llvm.frexp.f16.i32(half [[UNKNOWN]]) |
| ; CHECK-NEXT: [[FREXP_MANT:%.*]] = extractvalue { half, i32 } [[FREXP]], 0 |
| ; CHECK-NEXT: ret half [[FREXP_MANT]] |
| ; |
| %only.pinf = call half @returns_pinf() |
| %select = select i1 %cond, half %unknown, half %only.pinf |
| %frexp = call { half, i32 } @llvm.frexp.f16.i32(half %select) |
| %frexp.mant = extractvalue { half, i32 } %frexp, 0 |
| ret half %frexp.mant |
| } |
| |
| define nofpclass(pinf) half @ret_nofpclass_pinf__frexp_select_unknown_or_pinf__use_other_output(i1 %cond, half %unknown, ptr %ptr) { |
| ; CHECK-LABEL: define nofpclass(pinf) half @ret_nofpclass_pinf__frexp_select_unknown_or_pinf__use_other_output( |
| ; CHECK-SAME: i1 [[COND:%.*]], half [[UNKNOWN:%.*]], ptr [[PTR:%.*]]) { |
| ; CHECK-NEXT: [[ONLY_PINF:%.*]] = call half @returns_pinf() |
| ; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[COND]], half [[UNKNOWN]], half [[ONLY_PINF]] |
| ; CHECK-NEXT: [[FREXP:%.*]] = call { half, i32 } @llvm.frexp.f16.i32(half [[SELECT]]) |
| ; CHECK-NEXT: [[FREXP_MANT:%.*]] = extractvalue { half, i32 } [[FREXP]], 0 |
| ; CHECK-NEXT: [[FREXP_EXP:%.*]] = extractvalue { half, i32 } [[FREXP]], 1 |
| ; CHECK-NEXT: store i32 [[FREXP_EXP]], ptr [[PTR]], align 4 |
| ; CHECK-NEXT: ret half [[FREXP_MANT]] |
| ; |
| %only.pinf = call half @returns_pinf() |
| %select = select i1 %cond, half %unknown, half %only.pinf |
| %frexp = call { half, i32 } @llvm.frexp.f16.i32(half %select) |
| %frexp.mant = extractvalue { half, i32 } %frexp, 0 |
| %frexp.exp = extractvalue { half, i32 } %frexp, 1 |
| store i32 %frexp.exp, ptr %ptr |
| ret half %frexp.mant |
| } |
| |
| define nofpclass(pinf) half @ret_nofpclass_pinf__frexp_select_unknown_or_pinf__multiple_uses(i1 %cond, half %unknown, ptr %ptr) { |
| ; CHECK-LABEL: define nofpclass(pinf) half @ret_nofpclass_pinf__frexp_select_unknown_or_pinf__multiple_uses( |
| ; CHECK-SAME: i1 [[COND:%.*]], half [[UNKNOWN:%.*]], ptr [[PTR:%.*]]) { |
| ; CHECK-NEXT: [[ONLY_PINF:%.*]] = call half @returns_pinf() |
| ; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[COND]], half [[UNKNOWN]], half [[ONLY_PINF]] |
| ; CHECK-NEXT: [[FREXP:%.*]] = call { half, i32 } @llvm.frexp.f16.i32(half [[SELECT]]) |
| ; CHECK-NEXT: [[FREXP_MANT:%.*]] = extractvalue { half, i32 } [[FREXP]], 0 |
| ; CHECK-NEXT: store half [[FREXP_MANT]], ptr [[PTR]], align 2 |
| ; CHECK-NEXT: ret half [[FREXP_MANT]] |
| ; |
| %only.pinf = call half @returns_pinf() |
| %select = select i1 %cond, half %unknown, half %only.pinf |
| %frexp = call { half, i32 } @llvm.frexp.f16.i32(half %select) |
| %frexp.mant = extractvalue { half, i32 } %frexp, 0 |
| store half %frexp.mant, ptr %ptr |
| ret half %frexp.mant |
| } |
| |
| define nofpclass(pinf) half @ret_nofpclass_pinf__frexp_select_unknown_or_pinf__use_struct(i1 %cond, half %unknown, ptr %ptr) { |
| ; CHECK-LABEL: define nofpclass(pinf) half @ret_nofpclass_pinf__frexp_select_unknown_or_pinf__use_struct( |
| ; CHECK-SAME: i1 [[COND:%.*]], half [[UNKNOWN:%.*]], ptr [[PTR:%.*]]) { |
| ; CHECK-NEXT: [[ONLY_PINF:%.*]] = call half @returns_pinf() |
| ; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[COND]], half [[UNKNOWN]], half [[ONLY_PINF]] |
| ; CHECK-NEXT: [[FREXP:%.*]] = call { half, i32 } @llvm.frexp.f16.i32(half [[SELECT]]) |
| ; CHECK-NEXT: [[FREXP_MANT:%.*]] = extractvalue { half, i32 } [[FREXP]], 0 |
| ; CHECK-NEXT: store { half, i32 } [[FREXP]], ptr [[PTR]], align 4 |
| ; CHECK-NEXT: ret half [[FREXP_MANT]] |
| ; |
| %only.pinf = call half @returns_pinf() |
| %select = select i1 %cond, half %unknown, half %only.pinf |
| %frexp = call { half, i32 } @llvm.frexp.f16.i32(half %select) |
| %frexp.mant = extractvalue { half, i32 } %frexp, 0 |
| %frexp.exp = extractvalue { half, i32 } %frexp, 1 |
| store { half, i32 } %frexp, ptr %ptr |
| ret half %frexp.mant |
| } |
| |
| define nofpclass(ninf) half @ret_nofpclass_ninf__frexp_select_unknown_or_ninf(i1 %cond, half %unknown) { |
| ; CHECK-LABEL: define nofpclass(ninf) half @ret_nofpclass_ninf__frexp_select_unknown_or_ninf( |
| ; CHECK-SAME: i1 [[COND:%.*]], half [[UNKNOWN:%.*]]) { |
| ; CHECK-NEXT: [[ONLY_NINF:%.*]] = call half @returns_ninf() |
| ; CHECK-NEXT: [[FREXP:%.*]] = call { half, i32 } @llvm.frexp.f16.i32(half [[UNKNOWN]]) |
| ; CHECK-NEXT: [[FREXP_MANT:%.*]] = extractvalue { half, i32 } [[FREXP]], 0 |
| ; CHECK-NEXT: ret half [[FREXP_MANT]] |
| ; |
| %only.ninf = call half @returns_ninf() |
| %select = select i1 %cond, half %unknown, half %only.ninf |
| %frexp = call { half, i32 } @llvm.frexp.f16.i32(half %select) |
| %frexp.mant = extractvalue { half, i32 } %frexp, 0 |
| ret half %frexp.mant |
| } |
| |
| define nofpclass(inf) half @ret_nofpclass_inf__frexp_select_unknown_or_inf(i1 %cond, half %unknown) { |
| ; CHECK-LABEL: define nofpclass(inf) half @ret_nofpclass_inf__frexp_select_unknown_or_inf( |
| ; CHECK-SAME: i1 [[COND:%.*]], half [[UNKNOWN:%.*]]) { |
| ; CHECK-NEXT: [[ONLY_INF:%.*]] = call half @returns_inf() |
| ; CHECK-NEXT: [[FREXP:%.*]] = call { half, i32 } @llvm.frexp.f16.i32(half [[UNKNOWN]]) |
| ; CHECK-NEXT: [[FREXP_MANT:%.*]] = extractvalue { half, i32 } [[FREXP]], 0 |
| ; CHECK-NEXT: ret half [[FREXP_MANT]] |
| ; |
| %only.inf = call half @returns_inf() |
| %select = select i1 %cond, half %unknown, half %only.inf |
| %frexp = call { half, i32 } @llvm.frexp.f16.i32(half %select) |
| %frexp.mant = extractvalue { half, i32 } %frexp, 0 |
| ret half %frexp.mant |
| } |
| |
| define nofpclass(snan) half @ret_nofpclass_snan__frexp_select_unknown_or_snan(i1 %cond, half %unknown) { |
| ; CHECK-LABEL: define nofpclass(snan) half @ret_nofpclass_snan__frexp_select_unknown_or_snan( |
| ; CHECK-SAME: i1 [[COND:%.*]], half [[UNKNOWN:%.*]]) { |
| ; CHECK-NEXT: [[ONLY_SNAN:%.*]] = call half @returns_snan() |
| ; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[COND]], half [[UNKNOWN]], half [[ONLY_SNAN]] |
| ; CHECK-NEXT: [[FREXP:%.*]] = call { half, i32 } @llvm.frexp.f16.i32(half [[SELECT]]) |
| ; CHECK-NEXT: [[FREXP_MANT:%.*]] = extractvalue { half, i32 } [[FREXP]], 0 |
| ; CHECK-NEXT: ret half [[FREXP_MANT]] |
| ; |
| %only.snan = call half @returns_snan() |
| %select = select i1 %cond, half %unknown, half %only.snan |
| %frexp = call { half, i32 } @llvm.frexp.f16.i32(half %select) |
| %frexp.mant = extractvalue { half, i32 } %frexp, 0 |
| ret half %frexp.mant |
| } |
| |
| define nofpclass(qnan) half @ret_nofpclass_qnan__frexp_select_unknown_qnan(i1 %cond, half %unknown) { |
| ; CHECK-LABEL: define nofpclass(qnan) half @ret_nofpclass_qnan__frexp_select_unknown_qnan( |
| ; CHECK-SAME: i1 [[COND:%.*]], half [[UNKNOWN:%.*]]) { |
| ; CHECK-NEXT: [[ONLY_QNAN:%.*]] = call half @returns_qnan() |
| ; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[COND]], half [[UNKNOWN]], half [[ONLY_QNAN]] |
| ; CHECK-NEXT: [[FREXP:%.*]] = call { half, i32 } @llvm.frexp.f16.i32(half [[SELECT]]) |
| ; CHECK-NEXT: [[FREXP_MANT:%.*]] = extractvalue { half, i32 } [[FREXP]], 0 |
| ; CHECK-NEXT: ret half [[FREXP_MANT]] |
| ; |
| %only.qnan = call half @returns_qnan() |
| %select = select i1 %cond, half %unknown, half %only.qnan |
| %frexp = call { half, i32 } @llvm.frexp.f16.i32(half %select) |
| %frexp.mant = extractvalue { half, i32 } %frexp, 0 |
| ret half %frexp.mant |
| } |
| |
| define nofpclass(nan) half @ret_nofpclass_nan__frexp_select_unknown_nan(i1 %cond, half %unknown) { |
| ; CHECK-LABEL: define nofpclass(nan) half @ret_nofpclass_nan__frexp_select_unknown_nan( |
| ; CHECK-SAME: i1 [[COND:%.*]], half [[UNKNOWN:%.*]]) { |
| ; CHECK-NEXT: [[ONLY_NAN:%.*]] = call half @returns_nan() |
| ; CHECK-NEXT: [[FREXP:%.*]] = call { half, i32 } @llvm.frexp.f16.i32(half [[UNKNOWN]]) |
| ; CHECK-NEXT: [[FREXP_MANT:%.*]] = extractvalue { half, i32 } [[FREXP]], 0 |
| ; CHECK-NEXT: ret half [[FREXP_MANT]] |
| ; |
| %only.nan = call half @returns_nan() |
| %select = select i1 %cond, half %unknown, half %only.nan |
| %frexp = call { half, i32 } @llvm.frexp.f16.i32(half %select) |
| %frexp.mant = extractvalue { half, i32 } %frexp, 0 |
| ret half %frexp.mant |
| } |
| |
| define nofpclass(pzero) half @ret_nofpclass_pzero__frexp_select_unknown_only_pzero(i1 %cond, half %unknown) { |
| ; CHECK-LABEL: define nofpclass(pzero) half @ret_nofpclass_pzero__frexp_select_unknown_only_pzero( |
| ; CHECK-SAME: i1 [[COND:%.*]], half [[UNKNOWN:%.*]]) { |
| ; CHECK-NEXT: [[ONLY_PZERO:%.*]] = call half @returns_pzero() |
| ; CHECK-NEXT: [[FREXP:%.*]] = call { half, i32 } @llvm.frexp.f16.i32(half [[UNKNOWN]]) |
| ; CHECK-NEXT: [[FREXP_MANT:%.*]] = extractvalue { half, i32 } [[FREXP]], 0 |
| ; CHECK-NEXT: ret half [[FREXP_MANT]] |
| ; |
| %only.pzero = call half @returns_pzero() |
| %select = select i1 %cond, half %unknown, half %only.pzero |
| %frexp = call { half, i32 } @llvm.frexp.f16.i32(half %select) |
| %frexp.mant = extractvalue { half, i32 } %frexp, 0 |
| ret half %frexp.mant |
| } |
| |
| define nofpclass(nzero) half @ret_nofpclass_nzero__frexp_select_unknown_or_not_nzero(i1 %cond, half %unknown) { |
| ; CHECK-LABEL: define nofpclass(nzero) half @ret_nofpclass_nzero__frexp_select_unknown_or_not_nzero( |
| ; CHECK-SAME: i1 [[COND:%.*]], half [[UNKNOWN:%.*]]) { |
| ; CHECK-NEXT: [[ONLY_NZERO:%.*]] = call half @returns_nzero() |
| ; CHECK-NEXT: [[FREXP:%.*]] = call { half, i32 } @llvm.frexp.f16.i32(half [[UNKNOWN]]) |
| ; CHECK-NEXT: [[FREXP_MANT:%.*]] = extractvalue { half, i32 } [[FREXP]], 0 |
| ; CHECK-NEXT: ret half [[FREXP_MANT]] |
| ; |
| %only.nzero = call half @returns_nzero() |
| %select = select i1 %cond, half %unknown, half %only.nzero |
| %frexp = call { half, i32 } @llvm.frexp.f16.i32(half %select) |
| %frexp.mant = extractvalue { half, i32 } %frexp, 0 |
| ret half %frexp.mant |
| } |
| |
| define nofpclass(zero) half @ret_nofpclass_zero__frexp_select_unknown_or_not_zero(i1 %cond, half %unknown) { |
| ; CHECK-LABEL: define nofpclass(zero) half @ret_nofpclass_zero__frexp_select_unknown_or_not_zero( |
| ; CHECK-SAME: i1 [[COND:%.*]], half [[UNKNOWN:%.*]]) { |
| ; CHECK-NEXT: [[ONLY_ZERO:%.*]] = call half @returns_zero() |
| ; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[COND]], half [[UNKNOWN]], half [[ONLY_ZERO]] |
| ; CHECK-NEXT: [[FREXP:%.*]] = call { half, i32 } @llvm.frexp.f16.i32(half [[SELECT]]) |
| ; CHECK-NEXT: [[FREXP_MANT:%.*]] = extractvalue { half, i32 } [[FREXP]], 0 |
| ; CHECK-NEXT: ret half [[FREXP_MANT]] |
| ; |
| %only.zero = call half @returns_zero() |
| %select = select i1 %cond, half %unknown, half %only.zero |
| %frexp = call { half, i32 } @llvm.frexp.f16.i32(half %select) |
| %frexp.mant = extractvalue { half, i32 } %frexp, 0 |
| ret half %frexp.mant |
| } |
| |
| define nofpclass(nnorm sub) half @pnorm_result_demands_psub_source(i1 %cond, half %unknown, half nofpclass(nan inf norm nsub zero) %only.psub) { |
| ; CHECK-LABEL: define nofpclass(sub nnorm) half @pnorm_result_demands_psub_source( |
| ; CHECK-SAME: i1 [[COND:%.*]], half [[UNKNOWN:%.*]], half nofpclass(nan inf zero nsub norm) [[ONLY_PSUB:%.*]]) { |
| ; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[COND]], half [[UNKNOWN]], half [[ONLY_PSUB]] |
| ; CHECK-NEXT: [[FREXP:%.*]] = call { half, i32 } @llvm.frexp.f16.i32(half [[SELECT]]) |
| ; CHECK-NEXT: [[FREXP_MANT:%.*]] = extractvalue { half, i32 } [[FREXP]], 0 |
| ; CHECK-NEXT: ret half [[FREXP_MANT]] |
| ; |
| %select = select i1 %cond, half %unknown, half %only.psub |
| %frexp = call { half, i32 } @llvm.frexp.f16.i32(half %select) |
| %frexp.mant = extractvalue { half, i32 } %frexp, 0 |
| ret half %frexp.mant |
| } |
| |
| define nofpclass(pnorm sub) half @nnorm_result_demands_psub_source(i1 %cond, half %unknown, half nofpclass(nan inf norm psub zero) %only.nsub) { |
| ; CHECK-LABEL: define nofpclass(sub pnorm) half @nnorm_result_demands_psub_source( |
| ; CHECK-SAME: i1 [[COND:%.*]], half [[UNKNOWN:%.*]], half nofpclass(nan inf zero psub norm) [[ONLY_NSUB:%.*]]) { |
| ; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[COND]], half [[UNKNOWN]], half [[ONLY_NSUB]] |
| ; CHECK-NEXT: [[FREXP:%.*]] = call { half, i32 } @llvm.frexp.f16.i32(half [[SELECT]]) |
| ; CHECK-NEXT: [[FREXP_MANT:%.*]] = extractvalue { half, i32 } [[FREXP]], 0 |
| ; CHECK-NEXT: ret half [[FREXP_MANT]] |
| ; |
| %select = select i1 %cond, half %unknown, half %only.nsub |
| %frexp = call { half, i32 } @llvm.frexp.f16.i32(half %select) |
| %frexp.mant = extractvalue { half, i32 } %frexp, 0 |
| ret half %frexp.mant |
| } |
| |
| define nofpclass(sub) half @norm_result_demands_sub_source(i1 %cond, half %unknown, half nofpclass(nan inf norm zero) %only.sub) { |
| ; CHECK-LABEL: define nofpclass(sub) half @norm_result_demands_sub_source( |
| ; CHECK-SAME: i1 [[COND:%.*]], half [[UNKNOWN:%.*]], half nofpclass(nan inf zero norm) [[ONLY_SUB:%.*]]) { |
| ; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[COND]], half [[UNKNOWN]], half [[ONLY_SUB]] |
| ; CHECK-NEXT: [[FREXP:%.*]] = call { half, i32 } @llvm.frexp.f16.i32(half [[SELECT]]) |
| ; CHECK-NEXT: [[FREXP_MANT:%.*]] = extractvalue { half, i32 } [[FREXP]], 0 |
| ; CHECK-NEXT: ret half [[FREXP_MANT]] |
| ; |
| %select = select i1 %cond, half %unknown, half %only.sub |
| %frexp = call { half, i32 } @llvm.frexp.f16.i32(half %select) |
| %frexp.mant = extractvalue { half, i32 } %frexp, 0 |
| ret half %frexp.mant |
| } |
| |
| define nofpclass(norm sub nzero) half @pzero_result_demands_psub_source(i1 %cond, half %unknown, half nofpclass(nan inf norm nsub zero) %only.psub) { |
| ; CHECK-LABEL: define nofpclass(nzero sub norm) half @pzero_result_demands_psub_source( |
| ; CHECK-SAME: i1 [[COND:%.*]], half [[UNKNOWN:%.*]], half nofpclass(nan inf zero nsub norm) [[ONLY_PSUB:%.*]]) { |
| ; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[COND]], half [[UNKNOWN]], half [[ONLY_PSUB]] |
| ; CHECK-NEXT: [[FREXP:%.*]] = call { half, i32 } @llvm.frexp.f16.i32(half [[SELECT]]) |
| ; CHECK-NEXT: [[FREXP_MANT:%.*]] = extractvalue { half, i32 } [[FREXP]], 0 |
| ; CHECK-NEXT: ret half [[FREXP_MANT]] |
| ; |
| %select = select i1 %cond, half %unknown, half %only.psub |
| %frexp = call { half, i32 } @llvm.frexp.f16.i32(half %select) |
| %frexp.mant = extractvalue { half, i32 } %frexp, 0 |
| ret half %frexp.mant |
| } |
| |
| define nofpclass(norm sub nzero) half @pzero_result_demands_pnorm_source(i1 %cond, half %unknown, half nofpclass(nan inf nnorm sub zero) %only.pnorm) { |
| ; CHECK-LABEL: define nofpclass(nzero sub norm) half @pzero_result_demands_pnorm_source( |
| ; CHECK-SAME: i1 [[COND:%.*]], half [[UNKNOWN:%.*]], half nofpclass(nan inf zero sub nnorm) [[ONLY_PNORM:%.*]]) { |
| ; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[COND]], half [[UNKNOWN]], half [[ONLY_PNORM]] |
| ; CHECK-NEXT: [[FREXP:%.*]] = call { half, i32 } @llvm.frexp.f16.i32(half [[SELECT]]) |
| ; CHECK-NEXT: [[FREXP_MANT:%.*]] = extractvalue { half, i32 } [[FREXP]], 0 |
| ; CHECK-NEXT: ret half [[FREXP_MANT]] |
| ; |
| %select = select i1 %cond, half %unknown, half %only.pnorm |
| %frexp = call { half, i32 } @llvm.frexp.f16.i32(half %select) |
| %frexp.mant = extractvalue { half, i32 } %frexp, 0 |
| ret half %frexp.mant |
| } |
| |
| define nofpclass(norm sub pzero) half @nzero_result_demands_nsub_source(i1 %cond, half %unknown, half nofpclass(nan inf norm psub zero) %only.nsub) { |
| ; CHECK-LABEL: define nofpclass(pzero sub norm) half @nzero_result_demands_nsub_source( |
| ; CHECK-SAME: i1 [[COND:%.*]], half [[UNKNOWN:%.*]], half nofpclass(nan inf zero psub norm) [[ONLY_NSUB:%.*]]) { |
| ; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[COND]], half [[UNKNOWN]], half [[ONLY_NSUB]] |
| ; CHECK-NEXT: [[FREXP:%.*]] = call { half, i32 } @llvm.frexp.f16.i32(half [[SELECT]]) |
| ; CHECK-NEXT: [[FREXP_MANT:%.*]] = extractvalue { half, i32 } [[FREXP]], 0 |
| ; CHECK-NEXT: ret half [[FREXP_MANT]] |
| ; |
| %select = select i1 %cond, half %unknown, half %only.nsub |
| %frexp = call { half, i32 } @llvm.frexp.f16.i32(half %select) |
| %frexp.mant = extractvalue { half, i32 } %frexp, 0 |
| ret half %frexp.mant |
| } |
| |
| define nofpclass(norm sub pzero) half @nzero_result_demands_nnorm_source(i1 %cond, half %unknown, half nofpclass(nan inf pnorm sub zero) %only.nnorm) { |
| ; CHECK-LABEL: define nofpclass(pzero sub norm) half @nzero_result_demands_nnorm_source( |
| ; CHECK-SAME: i1 [[COND:%.*]], half [[UNKNOWN:%.*]], half nofpclass(nan inf zero sub pnorm) [[ONLY_NNORM:%.*]]) { |
| ; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[COND]], half [[UNKNOWN]], half [[ONLY_NNORM]] |
| ; CHECK-NEXT: [[FREXP:%.*]] = call { half, i32 } @llvm.frexp.f16.i32(half [[SELECT]]) |
| ; CHECK-NEXT: [[FREXP_MANT:%.*]] = extractvalue { half, i32 } [[FREXP]], 0 |
| ; CHECK-NEXT: ret half [[FREXP_MANT]] |
| ; |
| %select = select i1 %cond, half %unknown, half %only.nnorm |
| %frexp = call { half, i32 } @llvm.frexp.f16.i32(half %select) |
| %frexp.mant = extractvalue { half, i32 } %frexp, 0 |
| ret half %frexp.mant |
| } |
| |
| define nofpclass(ninf nnorm nsub nzero) half @ret_only_positive_or_nan__frexp_select_negative_or_unknown(i1 %cond, half %unknown) { |
| ; CHECK-LABEL: define nofpclass(ninf nzero nsub nnorm) half @ret_only_positive_or_nan__frexp_select_negative_or_unknown( |
| ; CHECK-SAME: i1 [[COND:%.*]], half [[UNKNOWN:%.*]]) { |
| ; CHECK-NEXT: [[NEGATIVE:%.*]] = call half @returns_negative() |
| ; CHECK-NEXT: [[FREXP:%.*]] = call { half, i32 } @llvm.frexp.f16.i32(half [[UNKNOWN]]) |
| ; CHECK-NEXT: [[FREXP_MANT:%.*]] = extractvalue { half, i32 } [[FREXP]], 0 |
| ; CHECK-NEXT: ret half [[FREXP_MANT]] |
| ; |
| %negative = call half @returns_negative() |
| %select = select i1 %cond, half %unknown, half %negative |
| %frexp = call { half, i32 } @llvm.frexp.f16.i32(half %select) |
| %frexp.mant = extractvalue { half, i32 } %frexp, 0 |
| ret half %frexp.mant |
| } |
| |
| define nofpclass(pinf pnorm psub pzero) half @ret_only_negative_or_nan__frexp_select_positive_or_unknown(i1 %cond, half %unknown) { |
| ; CHECK-LABEL: define nofpclass(pinf pzero psub pnorm) half @ret_only_negative_or_nan__frexp_select_positive_or_unknown( |
| ; CHECK-SAME: i1 [[COND:%.*]], half [[UNKNOWN:%.*]]) { |
| ; CHECK-NEXT: [[POSITIVE:%.*]] = call half @returns_positive() |
| ; CHECK-NEXT: [[FREXP:%.*]] = call { half, i32 } @llvm.frexp.f16.i32(half [[UNKNOWN]]) |
| ; CHECK-NEXT: [[FREXP_MANT:%.*]] = extractvalue { half, i32 } [[FREXP]], 0 |
| ; CHECK-NEXT: ret half [[FREXP_MANT]] |
| ; |
| %positive = call half @returns_positive() |
| %select = select i1 %cond, half %unknown, half %positive |
| %frexp = call { half, i32 } @llvm.frexp.f16.i32(half %select) |
| %frexp.mant = extractvalue { half, i32 } %frexp, 0 |
| ret half %frexp.mant |
| } |
| |
| define nofpclass(snan) half @src_only_inf__frexp() { |
| ; CHECK-LABEL: define nofpclass(snan) half @src_only_inf__frexp() { |
| ; CHECK-NEXT: [[ONLY_INF:%.*]] = call half @returns_inf() |
| ; CHECK-NEXT: [[FREXP:%.*]] = call { half, i32 } @llvm.frexp.f16.i32(half [[ONLY_INF]]) |
| ; CHECK-NEXT: [[FREXP_MANT:%.*]] = extractvalue { half, i32 } [[FREXP]], 0 |
| ; CHECK-NEXT: ret half [[FREXP_MANT]] |
| ; |
| %only.inf = call half @returns_inf() |
| %frexp = call { half, i32 } @llvm.frexp.f16.i32(half %only.inf) |
| %frexp.mant = extractvalue { half, i32 } %frexp, 0 |
| ret half %frexp.mant |
| } |
| |
| define nofpclass(snan) half @src_only_nan__frexp() { |
| ; CHECK-LABEL: define nofpclass(snan) half @src_only_nan__frexp() { |
| ; CHECK-NEXT: [[ONLY_NAN:%.*]] = call half @returns_nan() |
| ; CHECK-NEXT: ret half 0xH7E00 |
| ; |
| %only.nan = call half @returns_nan() |
| %frexp = call { half, i32 } @llvm.frexp.f16.i32(half %only.nan) |
| %frexp.mant = extractvalue { half, i32 } %frexp, 0 |
| ret half %frexp.mant |
| } |
| |
| define nofpclass(snan) half @src_only_nan_or_inf__frexp() { |
| ; CHECK-LABEL: define nofpclass(snan) half @src_only_nan_or_inf__frexp() { |
| ; CHECK-NEXT: [[INF_OR_NAN:%.*]] = call half @returns_inf_or_nan() |
| ; CHECK-NEXT: [[FREXP:%.*]] = call { half, i32 } @llvm.frexp.f16.i32(half [[INF_OR_NAN]]) |
| ; CHECK-NEXT: [[FREXP_MANT:%.*]] = extractvalue { half, i32 } [[FREXP]], 0 |
| ; CHECK-NEXT: ret half [[FREXP_MANT]] |
| ; |
| %inf.or.nan = call half @returns_inf_or_nan() |
| %frexp = call { half, i32 } @llvm.frexp.f16.i32(half %inf.or.nan) |
| %frexp.mant = extractvalue { half, i32 } %frexp, 0 |
| ret half %frexp.mant |
| } |
| |
| define nofpclass(snan) half @src_only_zero__frexp() { |
| ; CHECK-LABEL: define nofpclass(snan) half @src_only_zero__frexp() { |
| ; CHECK-NEXT: [[ONLY_ZERO:%.*]] = call half @returns_zero() |
| ; CHECK-NEXT: [[FREXP:%.*]] = call { half, i32 } @llvm.frexp.f16.i32(half [[ONLY_ZERO]]) |
| ; CHECK-NEXT: [[FREXP_MANT:%.*]] = extractvalue { half, i32 } [[FREXP]], 0 |
| ; CHECK-NEXT: ret half [[FREXP_MANT]] |
| ; |
| %only.zero = call half @returns_zero() |
| %frexp = call { half, i32 } @llvm.frexp.f16.i32(half %only.zero) |
| %frexp.mant = extractvalue { half, i32 } %frexp, 0 |
| ret half %frexp.mant |
| } |
| |
| define nofpclass(nan) half @ret_no_nan_src_only_inf__frexp() { |
| ; CHECK-LABEL: define nofpclass(nan) half @ret_no_nan_src_only_inf__frexp() { |
| ; CHECK-NEXT: [[INF:%.*]] = call half @returns_inf() |
| ; CHECK-NEXT: [[FREXP:%.*]] = call { half, i32 } @llvm.frexp.f16.i32(half [[INF]]) |
| ; CHECK-NEXT: [[FREXP_MANT:%.*]] = extractvalue { half, i32 } [[FREXP]], 0 |
| ; CHECK-NEXT: ret half [[FREXP_MANT]] |
| ; |
| %inf = call half @returns_inf() |
| %frexp = call { half, i32 } @llvm.frexp.f16.i32(half %inf) |
| %frexp.mant = extractvalue { half, i32 } %frexp, 0 |
| ret half %frexp.mant |
| } |
| |
| define nofpclass(inf) half @ret_no_inf_src_only_nan__frexp() { |
| ; CHECK-LABEL: define nofpclass(inf) half @ret_no_inf_src_only_nan__frexp() { |
| ; CHECK-NEXT: [[NAN:%.*]] = call half @returns_nan() |
| ; CHECK-NEXT: ret half 0xH7E00 |
| ; |
| %nan = call half @returns_nan() |
| %frexp = call { half, i32 } @llvm.frexp.f16.i32(half %nan) |
| %frexp.mant = extractvalue { half, i32 } %frexp, 0 |
| ret half %frexp.mant |
| } |
| |
| define nofpclass(inf) half @multiple_extract_uses(i1 %cond, half %unknown, ptr noundef %ptr) { |
| ; CHECK-LABEL: define nofpclass(inf) half @multiple_extract_uses( |
| ; CHECK-SAME: i1 [[COND:%.*]], half [[UNKNOWN:%.*]], ptr noundef [[PTR:%.*]]) { |
| ; CHECK-NEXT: [[INF:%.*]] = call half @returns_inf() |
| ; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[COND]], half [[UNKNOWN]], half [[INF]] |
| ; CHECK-NEXT: [[FREXP:%.*]] = call { half, i32 } @llvm.frexp.f16.i32(half [[SELECT]]) |
| ; CHECK-NEXT: [[FREXP_MANT:%.*]] = extractvalue { half, i32 } [[FREXP]], 0 |
| ; CHECK-NEXT: [[FREXP_MANT2:%.*]] = extractvalue { half, i32 } [[FREXP]], 0 |
| ; CHECK-NEXT: store half [[FREXP_MANT2]], ptr [[PTR]], align 2 |
| ; CHECK-NEXT: ret half [[FREXP_MANT]] |
| ; |
| %inf = call half @returns_inf() |
| %select = select i1 %cond, half %unknown, half %inf |
| %frexp = call { half, i32 } @llvm.frexp.f16.i32(half %select) |
| %frexp.mant = extractvalue { half, i32 } %frexp, 0 |
| %frexp.mant2 = extractvalue { half, i32 } %frexp, 0 |
| store half %frexp.mant2, ptr %ptr |
| ret half %frexp.mant |
| } |
| |
| define nofpclass(snan) half @qnan_result_demands_snan_src(i1 %cond, half %unknown, half nofpclass(qnan inf norm sub zero) %only.snan) { |
| ; CHECK-LABEL: define nofpclass(snan) half @qnan_result_demands_snan_src( |
| ; CHECK-SAME: i1 [[COND:%.*]], half [[UNKNOWN:%.*]], half nofpclass(qnan inf zero sub norm) [[ONLY_SNAN:%.*]]) { |
| ; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[COND]], half [[UNKNOWN]], half [[ONLY_SNAN]] |
| ; CHECK-NEXT: [[FREXP:%.*]] = call { half, i32 } @llvm.frexp.f16.i32(half [[SELECT]]) |
| ; CHECK-NEXT: [[FREXP_MANT:%.*]] = extractvalue { half, i32 } [[FREXP]], 0 |
| ; CHECK-NEXT: ret half [[FREXP_MANT]] |
| ; |
| %select = select i1 %cond, half %unknown, half %only.snan |
| %frexp = call { half, i32 } @llvm.frexp.f16.i32(half %select) |
| %frexp.mant = extractvalue { half, i32 } %frexp, 0 |
| ret half %frexp.mant |
| } |