Re: About GSOC.
Hello. I have already sent a patch for roundeven implementation but I do not know how do I commit my changes to GCC. Am I supposed to create a branch or anything etc? Also I have been trying to do folding for constant arguments and inspecting for only func (func (x)) -> func (x) right now. I made some changes to make this work including like : +(for fns (TRUNC_ALL FLOOR_ALL CEIL_ALL ROUND_ALL ROUNDEVEN_ALL NEARBYINT_ALL RINT_ALL) Also, BUILT_IN_ROUNDEVEN instead of ROUNDEVEN_ALL is not working here. Other changes regarding to this after inspecting round are included in this patch, but this seems not working and I am surely missing something. Do I need to include roundeven like round: DEFINE_INT_AND_FLOAT_ROUND_FN (ROUND) but this would require defining IROUNDEVEN in builtins.def but it is not supposed to? Thanks, --Tejas On Fri, 31 May 2019 at 19:00, Eric Gallager wrote: > > On 5/31/19, Nathan Sidwell wrote: > > On 5/30/19 5:38 PM, Segher Boessenkool wrote: > >> On Thu, May 30, 2019 at 07:08:45PM +0200, Martin Jambor wrote: > >>> Interesting, I was also puzzled for a moment. But notice that: > >>> > >>> int main () > >>> { > >>> _Float128 x = 18446744073709551617.5f128; > >>> _Float128 y = __builtin_roundf128 (x); > >>> } > >>> > >>> behaves as expected... the difference is of course the suffix pegged to > >>> the literal constant (see > >>> https://gcc.gnu.org/onlinedocs/gcc-9.1.0/gcc/Floating-Types.html). > >>> > >>> I would also expect GCC to use a larger type if a constant does not fit > >>> into a double, but apparently that does not happen. I would have to > >>> check but it is probably the right behavior according to the standard. > >> > >> 6.4.4.2/4: "An unsuffixed floating constant has type double." I don't > >> think your suggestion would be okay? > > > > Not only that, but > > > > 1) there isn't a literal suffix to mean 'double', so one couldn't > > override that extended type. > > There's not a standard one, but there is 'D' or 'd' as a GNU > extension. The fact that it's nonstandard, though, is what causes some > projects to ignore -Wunsuffixed-float-constants: > https://lists.gnu.org/archive/html/bug-gzip/2011-11/msg00017.html > > > 2) how do you define 'doesn't fit'? decimal 0.1 has a recurring binary > > representation. Should that become the longest floating point type? > > > > nathan > > > > -- > > Nathan Sidwell > > diff --git a/gcc/builtins.c b/gcc/builtins.c index 25e01e4092b..0b2d6bf82f9 100644 --- a/gcc/builtins.c +++ b/gcc/builtins.c @@ -2067,6 +2067,7 @@ mathfn_built_in_2 (tree type, combined_fn fn) CASE_MATHFN (REMQUO) CASE_MATHFN_FLOATN (RINT) CASE_MATHFN_FLOATN (ROUND) +CASE_MATHFN (ROUNDEVEN) CASE_MATHFN (SCALB) CASE_MATHFN (SCALBLN) CASE_MATHFN (SCALBN) diff --git a/gcc/builtins.def b/gcc/builtins.def index ef89729fd0c..f284a3eae3b 100644 --- a/gcc/builtins.def +++ b/gcc/builtins.def @@ -542,12 +542,18 @@ DEF_C99_BUILTIN(BUILT_IN_RINTL, "rintl", BT_FN_LONGDOUBLE_LONGDOUBLE, AT #define RINT_TYPE(F) BT_FN_##F##_##F DEF_EXT_LIB_FLOATN_NX_BUILTINS (BUILT_IN_RINT, "rint", RINT_TYPE, ATTR_CONST_NOTHROW_LEAF_LIST) #undef RINT_TYPE +DEF_EXT_LIB_BUILTIN(BUILT_IN_ROUNDEVEN, "roundeven", BT_FN_DOUBLE_DOUBLE, ATTR_CONST_NOTHROW_LEAF_LIST) +DEF_EXT_LIB_BUILTIN(BUILT_IN_ROUNDEVENF, "roundevenf", BT_FN_FLOAT_FLOAT, ATTR_CONST_NOTHROW_LEAF_LIST) +DEF_EXT_LIB_BUILTIN(BUILT_IN_ROUNDEVENL, "roundevenl", BT_FN_LONGDOUBLE_LONGDOUBLE, ATTR_CONST_NOTHROW_LEAF_LIST) DEF_C99_BUILTIN(BUILT_IN_ROUND, "round", BT_FN_DOUBLE_DOUBLE, ATTR_CONST_NOTHROW_LEAF_LIST) DEF_C99_BUILTIN(BUILT_IN_ROUNDF, "roundf", BT_FN_FLOAT_FLOAT, ATTR_CONST_NOTHROW_LEAF_LIST) DEF_C99_BUILTIN(BUILT_IN_ROUNDL, "roundl", BT_FN_LONGDOUBLE_LONGDOUBLE, ATTR_CONST_NOTHROW_LEAF_LIST) #define ROUND_TYPE(F) BT_FN_##F##_##F DEF_EXT_LIB_FLOATN_NX_BUILTINS (BUILT_IN_ROUND, "round", ROUND_TYPE, ATTR_CONST_NOTHROW_LEAF_LIST) #undef ROUND_TYPE +#define ROUNDEVEN_TYPE(F) BT_FN_##F##_##F +DEF_EXT_LIB_FLOATN_NX_BUILTINS (BUILT_IN_ROUNDEVEN, "roundeven", ROUNDEVEN_TYPE, ATTR_CONST_NOTHROW_LEAF_LIST) +#undef ROUNDEVEN_TYPE DEF_EXT_LIB_BUILTIN(BUILT_IN_SCALB, "scalb", BT_FN_DOUBLE_DOUBLE_DOUBLE, ATTR_MATHFN_FPROUNDING_ERRNO) DEF_EXT_LIB_BUILTIN(BUILT_IN_SCALBF, "scalbf", BT_FN_FLOAT_FLOAT_FLOAT, ATTR_MATHFN_FPROUNDING_ERRNO) DEF_EXT_LIB_BUILTIN(BUILT_IN_SCALBL, "scalbl", BT_FN_LONGDOUBLE_LONGDOUBLE_LONGDOUBLE, ATTR_MATHFN_FPROUNDING_ERRNO) diff --git a/gcc/fold-const-call.c b/gcc/fold-const-call.c index 06a420601c0..54315d057a2 100644 --- a/gcc/fold-const-call.c +++ b/gcc/fold-const-call.c @@ -792,6 +792,15 @@ fold_const_call_ss (real_value *result, combined_fn fn, } return false; +CASE_CFN_ROUNDEVEN: +CASE_CFN_ROUNDEVEN_FN: + if (!REAL_VALUE_ISNAN (*arg) || !flag_errno_math) + { +real_roundeven (result, format, arg); +return true; + } + return false; + CASE_CFN_LOGB: return fold
Re: About GSOC.
On Fri, 31 May 2019, Tejas Joshi wrote: > +/* Return true if integer part of R is even, else return false. */ > + > +bool > +is_even (REAL_VALUE_TYPE *r) > +{ > + if (REAL_EXP (r) <= 0) > +return false; But the integer part (truncation towards 0) of something in the interval (-1, 1) is of course even. > + else if (REAL_EXP (r) < SIGNIFICAND_BITS) > + { > +unsigned int n = SIGNIFICAND_BITS - REAL_EXP (r); > +int w = n / HOST_BITS_PER_LONG; > + > +unsigned long num = ((unsigned long)1 << (n % HOST_BITS_PER_LONG)); > + > +if ((r->sig[w] & num) == 0) > + return true; > + } > + return false; > +} Suppose REAL_EXP (r) == SIGNIFICAND_BITS. Then you still need to check the low bit in that case. Suppose REAL_EXP (r) > SIGNIFICAND_BITS. Then the number is definitely even, so you should return true, not false. The comment on this function needs to define what it does for infinity / NaN, and you should make sure it behaves accordingly. (If it should never be called for them, a gcc_assert would be appropriate.) What does this function do for zero? It should, of course, return that it is even. > +/* Return true if R is halfway between two integers, else return false. */ Again, define what this does for infinity / NaN and make sure it behaves accordingly. > +bool > +is_halfway_below (const REAL_VALUE_TYPE *r) > +{ > + if (REAL_EXP (r) < 0) > +return false; > + > + if (REAL_EXP (r) == 0) > + { > +unsigned long temp = ((unsigned long)1 << 63); unsigned long might be 32-bit; you can't assume it's 64-bit. You may mean (HOST_BITS_PER_LONG - 1) instead of 63. > +if (((r->sig[SIGSZ-1] & temp) != 0) && ((r->sig[SIGSZ-1] & (temp-1)) == > 0)) > + return true; > +else > + return false; This appears only to be checking the high word, not lower bits. > + else if (REAL_EXP (r) < SIGNIFICAND_BITS) > + { > +unsigned int n = SIGNIFICAND_BITS - REAL_EXP (r); > +int i, w = n / HOST_BITS_PER_LONG; So n is the bit position, and w is the word position, of the bit with value 1; n-1 is the position of the bit with value 0.5. > +for (i = 0; i < w; ++i) > +{ > + if (r->sig[i] != 0) > +return false; > +} If n is a multiple of HOST_BITS_PER_LONG (that is, the bits with values 0.5 and 1 are in different words), this will incorrectly return false when the 0.5 bit is set. > +unsigned long num = ((unsigned long)1 << ((n - 1) % HOST_BITS_PER_LONG)); > + > +if (((r->sig[w] & num) != 0) && ((r->sig[w] & (num-1)) == 0)) > + return true; And this also needs updating to handle the case where 0.5 and 1 are in different words correctly; currently it's checking bits that are all one word too high. It's possible that for both issues, you want w to be the word with the 0.5 bit, not the word with the 1 bit. For all the above, please add appropriate tests in the testsuite (for example, where 0.5 and 1 are in different words and the above would have produced incorrect results). -- Joseph S. Myers jos...@codesourcery.com
[GSoC'19, libgomp work-stealing] Task parallelism runtime
Hi, I've been studying the libgomp task parallelism system. I have a few questions. First, Tracing the events shows that only the main thread calls GOMP_task. How do the other worker threads enter the libgomp runtime? I can't find the entry point of the worker threads from the event tracing and the assembly dump. Second, How is the task priority set? Ray Kim
Re: [GSoC'19, libgomp work-stealing] Task parallelism runtime
On Tue, Jun 04, 2019 at 03:01:13AM +0900, 김규래 wrote: > Hi, > I've been studying the libgomp task parallelism system. > I have a few questions. > First, Tracing the events shows that only the main thread calls GOMP_task. No, any thread can call GOMP_task, in particular the thread that encountered the #pragma omp task construct. The GOMP_task function then decides based on the clauses of the construct (passed in various ways through the arguments of that function) whether it will be included (executed by the encountering thread), or queued for later execution. In the latter case, it will be scheduled during a barrier (implicit or explicit), see gomp_barrier_handle_tasks called from the bar.[ch] code, or at other spots, e.g. during taskwait construct (GOMP_taskwait) or at the end of taskgroup (GOMP_taskgroup_end). > How do the other worker threads enter the libgomp runtime? If you never encounter a parallel, teams or target construct, then there is just one thread that does everything (well, the library is written such that if you by hand pthread_create, each such thread acts as a separate initial thread from OpenMP POV). Threads are created e.g. during parallel construct (GOMP_parallel), where for non-nested parallelism as the standard requires it reuses existing threads if possible or spawns new ones, see mainly team.c (gomp_team_start) for the function that spawns new threads or awakes the ones waiting for work, or gomp_thread_start in the same file for the function actually run by the libgomp library created threads. > I can't find the entry point of the worker threads from the event tracing and > the assembly dump. > Second, How is the task priority set? By the user, through priority clause, passed to GOMP_task and then taken into account when handling tasks in the various queues. Jakub