diff --git a/libclc/clc/lib/generic/math/clc_pow.inc b/libclc/clc/lib/generic/math/clc_pow.inc index 98e154984aaa..8b1f820268ba 100644 --- a/libclc/clc/lib/generic/math/clc_pow.inc +++ b/libclc/clc/lib/generic/math/clc_pow.inc @@ -330,6 +330,15 @@ _CLC_DEF _CLC_OVERLOAD __CLC_GENTYPE __clc_pow(__CLC_GENTYPE x, const __CLC_GENTYPE lnof2_by_64_head = 0.010830424260348081; const __CLC_GENTYPE lnof2_by_64_tail = -4.359010638708991e-10; + // If v is so large that we need to return INFINITY, or so small that we + // need to return 0, set v to known values that will produce that result. Do + // not try to continue the computation with the original v and patch it up + // afterwards because v may be so large that temp is out of range of int, in + // which case that conversion, and a value based on that conversion being + // passed to __clc_ldexp, results in undefined behavior. + v = v > max_exp_arg ? 1000.0 : v; + v = v < min_exp_arg ? -1000.0 : v; + __CLC_GENTYPE temp = v * sixtyfour_by_lnof2; __CLC_INTN n = __CLC_CONVERT_INTN(temp); __CLC_GENTYPE dn = __CLC_CONVERT_GENTYPE(n); @@ -357,10 +366,6 @@ _CLC_DEF _CLC_OVERLOAD __CLC_GENTYPE __clc_pow(__CLC_GENTYPE x, expv = __clc_fma(f, q, f2) + f1; expv = __clc_ldexp(expv, m); - - expv = v > max_exp_arg ? __CLC_AS_GENTYPE((__CLC_ULONGN)0x7FF0000000000000L) - : expv; - expv = v < min_exp_arg ? 0.0 : expv; } // See whether y is an integer. diff --git a/libclc/clc/lib/generic/math/clc_pown.inc b/libclc/clc/lib/generic/math/clc_pown.inc index 8bdc407e9ac8..483fd2faf271 100644 --- a/libclc/clc/lib/generic/math/clc_pown.inc +++ b/libclc/clc/lib/generic/math/clc_pown.inc @@ -317,6 +317,15 @@ _CLC_DEF _CLC_OVERLOAD __CLC_GENTYPE __clc_pown(__CLC_GENTYPE x, const __CLC_GENTYPE lnof2_by_64_head = 0.010830424260348081; const __CLC_GENTYPE lnof2_by_64_tail = -4.359010638708991e-10; + // If v is so large that we need to return INFINITY, or so small that we + // need to return 0, set v to known values that will produce that result. Do + // not try to continue the computation with the original v and patch it up + // afterwards because v may be so large that temp is out of range of int, in + // which case that conversion, and a value based on that conversion being + // passed to __clc_ldexp, results in undefined behavior. + v = v > max_exp_arg ? 1000.0 : v; + v = v < min_exp_arg ? -1000.0 : v; + __CLC_GENTYPE temp = v * sixtyfour_by_lnof2; __CLC_INTN n = __CLC_CONVERT_INTN(temp); __CLC_GENTYPE dn = __CLC_CONVERT_GENTYPE(n); @@ -344,10 +353,6 @@ _CLC_DEF _CLC_OVERLOAD __CLC_GENTYPE __clc_pown(__CLC_GENTYPE x, expv = __clc_fma(f, q, f2) + f1; expv = __clc_ldexp(expv, m); - - expv = v > max_exp_arg ? __CLC_AS_GENTYPE((__CLC_ULONGN)0x7FF0000000000000L) - : expv; - expv = v < min_exp_arg ? 0.0 : expv; } // See whether y is an integer. diff --git a/libclc/clc/lib/generic/math/clc_powr.inc b/libclc/clc/lib/generic/math/clc_powr.inc index fbdf3d85de2b..1244f7f6ac5d 100644 --- a/libclc/clc/lib/generic/math/clc_powr.inc +++ b/libclc/clc/lib/generic/math/clc_powr.inc @@ -316,6 +316,15 @@ _CLC_DEF _CLC_OVERLOAD __CLC_GENTYPE __clc_powr(__CLC_GENTYPE x, const __CLC_GENTYPE lnof2_by_64_head = 0.010830424260348081; const __CLC_GENTYPE lnof2_by_64_tail = -4.359010638708991e-10; + // If v is so large that we need to return INFINITY, or so small that we + // need to return 0, set v to known values that will produce that result. Do + // not try to continue the computation with the original v and patch it up + // afterwards because v may be so large that temp is out of range of int, in + // which case that conversion, and a value based on that conversion being + // passed to __clc_ldexp, results in undefined behavior. + v = v > max_exp_arg ? 1000.0 : v; + v = v < min_exp_arg ? -1000.0 : v; + __CLC_GENTYPE temp = v * sixtyfour_by_lnof2; __CLC_INTN n = __CLC_CONVERT_INTN(temp); __CLC_GENTYPE dn = __CLC_CONVERT_GENTYPE(n); @@ -343,10 +352,6 @@ _CLC_DEF _CLC_OVERLOAD __CLC_GENTYPE __clc_powr(__CLC_GENTYPE x, expv = __clc_fma(f, q, f2) + f1; expv = __clc_ldexp(expv, m); - - expv = v > max_exp_arg ? __CLC_AS_GENTYPE((__CLC_ULONGN)0x7FF0000000000000L) - : expv; - expv = v < min_exp_arg ? 0.0 : expv; } // See whether y is an integer. diff --git a/libclc/clc/lib/generic/math/clc_rootn.inc b/libclc/clc/lib/generic/math/clc_rootn.inc index 0c459ae5c3cb..996f88f14535 100644 --- a/libclc/clc/lib/generic/math/clc_rootn.inc +++ b/libclc/clc/lib/generic/math/clc_rootn.inc @@ -323,6 +323,15 @@ _CLC_DEF _CLC_OVERLOAD __CLC_GENTYPE __clc_rootn(__CLC_GENTYPE x, const __CLC_GENTYPE lnof2_by_64_head = 0.010830424260348081; const __CLC_GENTYPE lnof2_by_64_tail = -4.359010638708991e-10; + // If v is so large that we need to return INFINITY, or so small that we + // need to return 0, set v to known values that will produce that result. Do + // not try to continue the computation with the original v and patch it up + // afterwards because v may be so large that temp is out of range of int, in + // which case that conversion, and a value based on that conversion being + // passed to __clc_ldexp, results in undefined behavior. + v = v > max_exp_arg ? 1000.0 : v; + v = v < min_exp_arg ? -1000.0 : v; + __CLC_GENTYPE temp = v * sixtyfour_by_lnof2; __CLC_INTN n = __CLC_CONVERT_INTN(temp); __CLC_GENTYPE dn = __CLC_CONVERT_GENTYPE(n); @@ -350,10 +359,6 @@ _CLC_DEF _CLC_OVERLOAD __CLC_GENTYPE __clc_rootn(__CLC_GENTYPE x, expv = __clc_fma(f, q, f2) + f1; expv = __clc_ldexp(expv, m); - - expv = v > max_exp_arg ? __CLC_AS_GENTYPE((__CLC_ULONGN)0x7FF0000000000000L) - : expv; - expv = v < min_exp_arg ? 0.0 : expv; } // See whether y is an integer.