public inbox for gcc@gcc.gnu.org
 help / color / mirror / Atom feed
* About gsoc
@ 2024-03-04  6:57 mokshagnareddyc
  2024-03-04 10:06 ` Jonathan Wakely
  2024-03-07 12:26 ` Martin Jambor
  0 siblings, 2 replies; 60+ messages in thread
From: mokshagnareddyc @ 2024-03-04  6:57 UTC (permalink / raw)
  To: gcc

Hello sir/mam
I am mokshagna reddy from Mahindra university and i am currently in my second year of under graduation in Btech artificial intelligence i had intrest in your organization and i know programming languages like c, c++,python   how can i contribute from now and can u send details about the project . Thank you hope i will get reply as soon as possible.
Sent from my iPhone

^ permalink raw reply	[flat|nested] 60+ messages in thread

* Re: About gsoc
  2024-03-04  6:57 About gsoc mokshagnareddyc
@ 2024-03-04 10:06 ` Jonathan Wakely
  2024-03-05  2:02   ` Dave Blanchard
  2024-03-07 12:26 ` Martin Jambor
  1 sibling, 1 reply; 60+ messages in thread
From: Jonathan Wakely @ 2024-03-04 10:06 UTC (permalink / raw)
  To: mokshagnareddyc; +Cc: gcc

On Mon, 4 Mar 2024 at 06:58, mokshagnareddyc--- via Gcc <gcc@gcc.gnu.org> wrote:
>
> Hello sir/mam
> I am mokshagna reddy from Mahindra university and i am currently in my second year of under graduation in Btech artificial intelligence i had intrest in your organization and i know programming languages like c, c++,python   how can i contribute from now and can u send details about the project . Thank you hope i will get reply as soon as possible.

If you want to apply for GSoC and convince people you're a suitable
candidate and would invest the necessary time and effort, maybe you
should find details of the project for yourself instead of asking
others to provide them.

A simple web search would have found https://gcc.gnu.org/wiki/SummerOfCode

^ permalink raw reply	[flat|nested] 60+ messages in thread

* Re: About gsoc
  2024-03-04 10:06 ` Jonathan Wakely
@ 2024-03-05  2:02   ` Dave Blanchard
  2024-03-05  9:31     ` Jonathan Wakely
  0 siblings, 1 reply; 60+ messages in thread
From: Dave Blanchard @ 2024-03-05  2:02 UTC (permalink / raw)
  To: gcc; +Cc: mokshagnareddyc

On Mon, 4 Mar 2024 10:06:34 +0000
Jonathan Wakely via Gcc <gcc@gcc.gnu.org> wrote:

> On Mon, 4 Mar 2024 at 06:58, mokshagnareddyc--- via Gcc <gcc@gcc.gnu.org> wrote:
> >
> > Hello sir/mam
> > I am mokshagna reddy from Mahindra university and i am currently in my second year of under graduation in Btech artificial intelligence i had intrest in your organization and i know programming languages like c, c++,python   how can i contribute from now and can u send details about the project . Thank you hope i will get reply as soon as possible.
> 
> If you want to apply for GSoC and convince people you're a suitable
> candidate and would invest the necessary time and effort, maybe you
> should find details of the project for yourself instead of asking
> others to provide them.
> 
> A simple web search would have found https://gcc.gnu.org/wiki/SummerOfCode

Wow, what a fucking prick this guy is.

My apologies to our friend Mr. Mokshagna Reddy for this extreme rudeness. 

Maybe he did you a favor with such a response. Why should anyone waste their time and energy donating free work to a dumpster fire project like GCC, when this is the thanks you get? I recommend contributing your valuable time to LLVM/clang or some other non-GNU project instead, where it will likely be more appreciated.

Dave

^ permalink raw reply	[flat|nested] 60+ messages in thread

* Re: About gsoc
  2024-03-05  2:02   ` Dave Blanchard
@ 2024-03-05  9:31     ` Jonathan Wakely
  2024-03-05  9:32       ` Jonathan Wakely
  0 siblings, 1 reply; 60+ messages in thread
From: Jonathan Wakely @ 2024-03-05  9:31 UTC (permalink / raw)
  To: Dave Blanchard; +Cc: gcc, mokshagnareddyc

On Tue, 5 Mar 2024 at 01:59, Dave Blanchard <dave@killthe.net> wrote:
>
> On Mon, 4 Mar 2024 10:06:34 +0000
> Jonathan Wakely via Gcc <gcc@gcc.gnu.org> wrote:
>
> > On Mon, 4 Mar 2024 at 06:58, mokshagnareddyc--- via Gcc <gcc@gcc.gnu.org> wrote:
> > >
> > > Hello sir/mam
> > > I am mokshagna reddy from Mahindra university and i am currently in my second year of under graduation in Btech artificial intelligence i had intrest in your organization and i know programming languages like c, c++,python   how can i contribute from now and can u send details about the project . Thank you hope i will get reply as soon as possible.
> >
> > If you want to apply for GSoC and convince people you're a suitable
> > candidate and would invest the necessary time and effort, maybe you
> > should find details of the project for yourself instead of asking
> > others to provide them.
> >
> > A simple web search would have found https://gcc.gnu.org/wiki/SummerOfCode
>
> Wow, what a fucking prick this guy is.
>
> My apologies to our friend Mr. Mokshagna Reddy for this extreme rudeness.
>
> Maybe he did you a favor with such a response. Why should anyone waste their time and energy donating free work to a dumpster fire project like GCC, when this is the thanks you get? I recommend contributing your valuable time to LLVM/clang or some other non-GNU project instead, where it will likely be more appreciated.

GSoC isn't free work, it's paid. Get a clue, or go away.

^ permalink raw reply	[flat|nested] 60+ messages in thread

* Re: About gsoc
  2024-03-05  9:31     ` Jonathan Wakely
@ 2024-03-05  9:32       ` Jonathan Wakely
  2024-03-11  1:17         ` Dave Blanchard
  0 siblings, 1 reply; 60+ messages in thread
From: Jonathan Wakely @ 2024-03-05  9:32 UTC (permalink / raw)
  To: Dave Blanchard; +Cc: gcc, mokshagnareddyc

On Tue, 5 Mar 2024 at 09:31, Jonathan Wakely <jwakely.gcc@gmail.com> wrote:
>
> On Tue, 5 Mar 2024 at 01:59, Dave Blanchard <dave@killthe.net> wrote:
> >
> > On Mon, 4 Mar 2024 10:06:34 +0000
> > Jonathan Wakely via Gcc <gcc@gcc.gnu.org> wrote:
> >
> > > On Mon, 4 Mar 2024 at 06:58, mokshagnareddyc--- via Gcc <gcc@gcc.gnu.org> wrote:
> > > >
> > > > Hello sir/mam
> > > > I am mokshagna reddy from Mahindra university and i am currently in my second year of under graduation in Btech artificial intelligence i had intrest in your organization and i know programming languages like c, c++,python   how can i contribute from now and can u send details about the project . Thank you hope i will get reply as soon as possible.
> > >
> > > If you want to apply for GSoC and convince people you're a suitable
> > > candidate and would invest the necessary time and effort, maybe you
> > > should find details of the project for yourself instead of asking
> > > others to provide them.
> > >
> > > A simple web search would have found https://gcc.gnu.org/wiki/SummerOfCode
> >
> > Wow, what a fucking prick this guy is.
> >
> > My apologies to our friend Mr. Mokshagna Reddy for this extreme rudeness.
> >
> > Maybe he did you a favor with such a response. Why should anyone waste their time and energy donating free work to a dumpster fire project like GCC, when this is the thanks you get? I recommend contributing your valuable time to LLVM/clang or some other non-GNU project instead, where it will likely be more appreciated.
>
> GSoC isn't free work, it's paid. Get a clue, or go away.

That's directed at Dave, in case it wasn't obvious. He contributes
nothing here except bile.

^ permalink raw reply	[flat|nested] 60+ messages in thread

* Re: About gsoc
  2024-03-04  6:57 About gsoc mokshagnareddyc
  2024-03-04 10:06 ` Jonathan Wakely
@ 2024-03-07 12:26 ` Martin Jambor
  1 sibling, 0 replies; 60+ messages in thread
From: Martin Jambor @ 2024-03-07 12:26 UTC (permalink / raw)
  To: mokshagnareddyc; +Cc: GCC Mailing List

Hello,

On Mon, Mar 04 2024, mokshagnareddyc--- via Gcc wrote:
> Hello sir/mam
> I am mokshagna reddy from Mahindra university and i am currently in my
> second year of under graduation in Btech artificial intelligence i had
> intrest in your organization and i know programming languages like c,
> c++,python how can i contribute from now and can u send details about
> the project.

We are delighted you found contributing to GCC interesting.

Please note that apart from C/C++ coding skills, most projects require
some rudimentary theoretical background in compilers.

Please look again at the "Before you apply" section of our GSoC page at
https://gcc.gnu.org/wiki/SummerOfCode#Before_you_apply and make sure you
are able to build, install and test GCC.  I strongly suggest that you
also try generating dumps of the IR of a simple compiled program and
stepping through some function during compilation in a debugger.

Afterwards, look at the suggested projects, try to identify the portion
of GCC source where it needs to be implemented and think about how.
Then email us back to this mailing list describing your current plan
together with any technical questions you'd like to have answered to
proceed further.  We'll be happy to help.

Good luck,

Martin

^ permalink raw reply	[flat|nested] 60+ messages in thread

* Re: About gsoc
  2024-03-05  9:32       ` Jonathan Wakely
@ 2024-03-11  1:17         ` Dave Blanchard
  2024-03-11  9:08           ` Mark Wielaard
  0 siblings, 1 reply; 60+ messages in thread
From: Dave Blanchard @ 2024-03-11  1:17 UTC (permalink / raw)
  To: gcc; +Cc: rms

On Tue, 5 Mar 2024 09:32:26 +0000
Jonathan Wakely <jwakely.gcc@gmail.com> wrote:

> On Tue, 5 Mar 2024 at 09:31, Jonathan Wakely <jwakely.gcc@gmail.com> wrote:
> >
> > On Tue, 5 Mar 2024 at 01:59, Dave Blanchard <dave@killthe.net> wrote:
> > >
> > > On Mon, 4 Mar 2024 10:06:34 +0000
> > > Jonathan Wakely via Gcc <gcc@gcc.gnu.org> wrote:
> > >
> > > > On Mon, 4 Mar 2024 at 06:58, mokshagnareddyc--- via Gcc <gcc@gcc.gnu.org> wrote:
> > > > >
> > > > > Hello sir/mam
> > > > > I am mokshagna reddy from Mahindra university and i am currently in my second year of under graduation in Btech artificial intelligence i had intrest in your organization and i know programming languages like c, c++,python   how can i contribute from now and can u send details about the project . Thank you hope i will get reply as soon as possible.
> > > >
> > > > If you want to apply for GSoC and convince people you're a suitable
> > > > candidate and would invest the necessary time and effort, maybe you
> > > > should find details of the project for yourself instead of asking
> > > > others to provide them.
> > > >
> > > > A simple web search would have found https://gcc.gnu.org/wiki/SummerOfCode
> > >
> > > Wow, what a fucking prick this guy is.
> > >
> > > My apologies to our friend Mr. Mokshagna Reddy for this extreme rudeness.
> > >
> > > Maybe he did you a favor with such a response. Why should anyone waste their time and energy donating free work to a dumpster fire project like GCC, when this is the thanks you get? I recommend contributing your valuable time to LLVM/clang or some other non-GNU project instead, where it will likely be more appreciated.
> >
> > GSoC isn't free work, it's paid. Get a clue, or go away.

Oh, I see! Since this poor young university student might expect to receive small payment  for his time spent in improving GCC--which is a very complex project that is not easily modified--therefore you're excused in treating him like yesterday's trash.

Makes perfect sense to you, I guess.

> 
> That's directed at Dave, in case it wasn't obvious. He contributes
> nothing here except bile.

Have you read any of your own posts? You are one of the biggest assholes I've encountered in the open source world, and I've met some real dicks. People like you have been driving newbies away from Linux/BSD for decades. You never learn.

What you call "bile" is merely me being the one guy who's willing to call you on your bullshit. This is hardly the first time you've shown your ass to someone who was trying to help the GCC project in some way. Remember Stefan Kanthak? Others may remember he pointed out serious problems with the GCC optimizer on x86-32 which you also rudely dismissed, calling him a noob, etc.

Are you an official representative of the GCC project, or just some random asshole who lurks here and thinks he owns the place? What do YOU actually contribute to this list that is so valuable it excuses your rudeness? I wonder if Mr. Stallman approves of you helping to drive away potential GNU contributors, at a time when this project needs fresh blood arguably more than ever. Let's find out.

Dave

^ permalink raw reply	[flat|nested] 60+ messages in thread

* Re: About gsoc
  2024-03-11  1:17         ` Dave Blanchard
@ 2024-03-11  9:08           ` Mark Wielaard
  0 siblings, 0 replies; 60+ messages in thread
From: Mark Wielaard @ 2024-03-11  9:08 UTC (permalink / raw)
  To: Dave Blanchard; +Cc: gcc, rms

Hi Dave,

On Sun, Mar 10, 2024 at 08:17:31PM -0500, Dave Blanchard wrote:
> > > On Tue, 5 Mar 2024 at 01:59, Dave Blanchard <dave@killthe.net> wrote:
> > > > Wow, what a fucking prick this guy is.
> > > > [...]
> You are one of the biggest assholes I've encountered in the open
> source world, and I've met some real dicks.

You have been warned before. Please stop sending these negative
unproductive messages to this list attacking well respected productive
maintainers of the project. Your attitude is not welcome.

Thanks,

Mark

^ permalink raw reply	[flat|nested] 60+ messages in thread

* Re: About gsoc
@ 2024-03-11 12:41 Julian Waters
  0 siblings, 0 replies; 60+ messages in thread
From: Julian Waters @ 2024-03-11 12:41 UTC (permalink / raw)
  To: gcc

Hello again, Dave. Have you managed to learn how a basic language
Interpreter works before commenting on the significantly-more-complex
gcc's efficiency? Or were you not able to because your IQ is below the
freezing point of water and you can't even understand what a basic
tree walker is?

Then again, with an address like killthe.net, why should we even take
you seriously? Hell, even though I miraculously agree that stuff like
GNU and Linux is not beginner friendly, and gcc could do with some
improvements in that department, no one wants to take any advice from
a self righteous and idiotic piece of shit like yourself. At least
Stefan was smart enough to bail when others pointed out the holes in
his examples of gcc's instruction selection allegedly being poor. You,
not so much. I doubt the clang people want you either, so do them a
favour and stay the hell away from LLVM, and this is coming from
someone who doesn't really like LLVM in the first place

^ permalink raw reply	[flat|nested] 60+ messages in thread

* Re: About GSOC.
  2019-06-12 18:52                                                                                   ` Tejas Joshi
@ 2019-06-13 12:33                                                                                     ` Tejas Joshi
  0 siblings, 0 replies; 60+ messages in thread
From: Tejas Joshi @ 2019-06-13 12:33 UTC (permalink / raw)
  To: gcc; +Cc: Martin Jambor, hubicka

Hello.
As further part of implementing roundeven is inlining, I was studying
machine descriptions and I have a few questions.

As suggested, builtin functions provided a strong model for
implementing roundeven. Keeping that in mind, I tried to inspect how
similar functions (round/ceil) would get inlined. As it is dependent
on target machine, (mine is i7, so should be x86_64 ? I wonder why
gcc/config/ does not have x86_64 or amd64 directory. Or is it i386
itself as extended?), should *.s file after compilation contain the
specific instruction if supported? I was unable to see such kind of
instruction on any -O level.

Different pattern names are available for machine descriptions
<https://gcc.gnu.org/onlinedocs/gccint/Standard-Names.html>, also for
round, ceil, etc. Will I have to add such pattern name for roundeven?
(is it the same as optab defined in optabs.def?)

Thanks,
-Tejas


On Thu, 13 Jun 2019 at 00:27, Tejas Joshi <tejasjoshi9673@gmail.com> wrote:
>
> Hello.
>
> > I don't think you should have the unreachable "return false;" in is_even.
> > The last "else if" can just be "else".
>
> I don't think return false in is_even is unreachable. As per my
> understanding, when one else if is true in the else if ladder, all the
> subsequent "else ifs" including "else" are ignored. When REAL_EXP is
> less than SIGNIFICAND_BITS, but the number is odd, the inner "if" for
> even-odd will not return true in which case should return false. That
> case will ignore next "else if" and will reach return false.
>
> > Suppose REAL_EXP (r) > SIGNIFICAND_BITS.  Then the number is definitely
> > even, so you should return true, not false.
>
> for this condition, else if can be modified to just else and return true.
> PATCH:
>
> gcc/ChangeLog:
>
> 2019-06-12  Tejas Joshi  <tejasjoshi9673@gmail.com>
>
>     * builtins.c (mathfn_built_in_2): Added CASE_MATHFN for ROUNDEVEN.
>     * builtins.def: Added function definitions for roundeven function
>     variants.
>     * fold-const-call.c (fold_const_call_ss): Added case for function
>     call and fold_const_conversion call for roundeven function.
>     * fold-const.c (negate_mathfn_p): Added case for roundeven function.
>     (tree_call_nonnegative_warnv_p): Added case for roundeven function.
>     (integer_valued_real_call_p): Added case for roundeven function.
>     * real.c (is_even): New function. Returns true if real number is
>     even, otherwise returns false.
>     (is_halfway_below): New function. Returns true if real number is
>     halfway between two integers, else return false.
>     (real_roundeven): New function. Round real number to nearest
>     integer, rounding halfway cases towards even.
>     * real.h (real_value): Added descriptive comments.
>     Added function declaration for roundeven function.
>
> gcc/testsuite/ChangeLog:
>
> 2019-06-12  Tejas Joshi  <tejasjoshi9673@gmail.com>
>
>     * gcc.dg/torture/builtin-round-roundeven.c: New test.
>     * gcc.dg/torture/builtin-round-roundevenf128.c: New test.
>
>
>
> On Tue, 11 Jun 2019 at 01:56, Joseph Myers <joseph@codesourcery.com> wrote:
> >
> > On Sun, 9 Jun 2019, Tejas Joshi wrote:
> >
> > > Hello.
> > > I have created another patch which addresses the above points,
> > > attached herewith.
> >
> > I don't think you should have the unreachable "return false;" in is_even.
> > The last "else if" can just be "else".
> >
> > > > a conditional with < not <=; if REAL_EXP (r) == SIGNIFICAND_BITS, the
> > > > least significant bit has value 1 and the number must be an integer).
> > >
> > > The number is integer because of the whole word spaces is occupied by
> > > integer part?
> > > Also, why would the least significant bit will have value 1 if
> > > REAL_EXP (r) == SIGNIFICAND_BITS, as it only concerns with 2^0th
> > > position (even or odd)?
> >
> > My understanding is that the significand is, as per the comments in
> > real.c, in the range [0.5, 1.0).  There are SIGNIFICAND_BITS bits.  The
> > bit above the most significant one has value 2^REAL_EXP.  The most
> > significant one has value 2^(REAL_EXP-1).  The least significant one has
> > value 2^(REAL_EXP-SIGNIFICAND_BITS).  If REAL_EXP == SIGNIFICAND_BITS,
> > that means the least significant bit has value 2^0 = 1, and there are no
> > bits with value 0.5 or below, so the number is an integer.
> >
> > --
> > Joseph S. Myers
> > joseph@codesourcery.com

^ permalink raw reply	[flat|nested] 60+ messages in thread

* Re: About GSOC.
  2019-06-10 20:26                                                                                 ` Joseph Myers
@ 2019-06-12 18:52                                                                                   ` Tejas Joshi
  2019-06-13 12:33                                                                                     ` Tejas Joshi
  0 siblings, 1 reply; 60+ messages in thread
From: Tejas Joshi @ 2019-06-12 18:52 UTC (permalink / raw)
  To: gcc; +Cc: Martin Jambor, hubicka, joseph

[-- Attachment #1: Type: text/plain, Size: 3266 bytes --]

Hello.

> I don't think you should have the unreachable "return false;" in is_even.
> The last "else if" can just be "else".

I don't think return false in is_even is unreachable. As per my
understanding, when one else if is true in the else if ladder, all the
subsequent "else ifs" including "else" are ignored. When REAL_EXP is
less than SIGNIFICAND_BITS, but the number is odd, the inner "if" for
even-odd will not return true in which case should return false. That
case will ignore next "else if" and will reach return false.

> Suppose REAL_EXP (r) > SIGNIFICAND_BITS.  Then the number is definitely
> even, so you should return true, not false.

for this condition, else if can be modified to just else and return true.
PATCH:

gcc/ChangeLog:

2019-06-12  Tejas Joshi  <tejasjoshi9673@gmail.com>

    * builtins.c (mathfn_built_in_2): Added CASE_MATHFN for ROUNDEVEN.
    * builtins.def: Added function definitions for roundeven function
    variants.
    * fold-const-call.c (fold_const_call_ss): Added case for function
    call and fold_const_conversion call for roundeven function.
    * fold-const.c (negate_mathfn_p): Added case for roundeven function.
    (tree_call_nonnegative_warnv_p): Added case for roundeven function.
    (integer_valued_real_call_p): Added case for roundeven function.
    * real.c (is_even): New function. Returns true if real number is
    even, otherwise returns false.
    (is_halfway_below): New function. Returns true if real number is
    halfway between two integers, else return false.
    (real_roundeven): New function. Round real number to nearest
    integer, rounding halfway cases towards even.
    * real.h (real_value): Added descriptive comments.
    Added function declaration for roundeven function.

gcc/testsuite/ChangeLog:

2019-06-12  Tejas Joshi  <tejasjoshi9673@gmail.com>

    * gcc.dg/torture/builtin-round-roundeven.c: New test.
    * gcc.dg/torture/builtin-round-roundevenf128.c: New test.



On Tue, 11 Jun 2019 at 01:56, Joseph Myers <joseph@codesourcery.com> wrote:
>
> On Sun, 9 Jun 2019, Tejas Joshi wrote:
>
> > Hello.
> > I have created another patch which addresses the above points,
> > attached herewith.
>
> I don't think you should have the unreachable "return false;" in is_even.
> The last "else if" can just be "else".
>
> > > a conditional with < not <=; if REAL_EXP (r) == SIGNIFICAND_BITS, the
> > > least significant bit has value 1 and the number must be an integer).
> >
> > The number is integer because of the whole word spaces is occupied by
> > integer part?
> > Also, why would the least significant bit will have value 1 if
> > REAL_EXP (r) == SIGNIFICAND_BITS, as it only concerns with 2^0th
> > position (even or odd)?
>
> My understanding is that the significand is, as per the comments in
> real.c, in the range [0.5, 1.0).  There are SIGNIFICAND_BITS bits.  The
> bit above the most significant one has value 2^REAL_EXP.  The most
> significant one has value 2^(REAL_EXP-1).  The least significant one has
> value 2^(REAL_EXP-SIGNIFICAND_BITS).  If REAL_EXP == SIGNIFICAND_BITS,
> that means the least significant bit has value 2^0 = 1, and there are no
> bits with value 0.5 or below, so the number is an integer.
>
> --
> Joseph S. Myers
> joseph@codesourcery.com

[-- Attachment #2: roundeven2.patch --]
[-- Type: text/x-patch, Size: 9089 bytes --]

diff --git a/gcc/builtins.c b/gcc/builtins.c
index 3463ffb1539..85a945877a4 100644
--- a/gcc/builtins.c
+++ b/gcc/builtins.c
@@ -2085,6 +2085,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 6d41bdb4f44..8bb7027aac7 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 702c8b4057a..d9b546e6803 100644
--- a/gcc/fold-const-call.c
+++ b/gcc/fold-const-call.c
@@ -836,6 +836,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_const_logb (result, arg, format);
 
@@ -898,6 +907,10 @@ fold_const_call_ss (wide_int *result, combined_fn fn,
       return fold_const_conversion (result, real_round, arg,
 				    precision, format);
 
+    CASE_CFN_ROUNDEVEN:
+    CASE_CFN_ROUNDEVEN_FN:
+      return fold_const_conversion (result, real_roundeven, arg, precision, format);
+
     CASE_CFN_IRINT:
     CASE_CFN_LRINT:
     CASE_CFN_LLRINT:
diff --git a/gcc/fold-const.c b/gcc/fold-const.c
index 0ca472d422f..07d82a17e25 100644
--- a/gcc/fold-const.c
+++ b/gcc/fold-const.c
@@ -329,6 +329,8 @@ negate_mathfn_p (combined_fn fn)
     CASE_CFN_LLROUND:
     CASE_CFN_LROUND:
     CASE_CFN_ROUND:
+    CASE_CFN_ROUNDEVEN:
+    CASE_CFN_ROUNDEVEN_FN:
     CASE_CFN_SIN:
     CASE_CFN_SINH:
     CASE_CFN_TAN:
@@ -13063,6 +13065,8 @@ tree_call_nonnegative_warnv_p (tree type, combined_fn fn, tree arg0, tree arg1,
     CASE_CFN_RINT_FN:
     CASE_CFN_ROUND:
     CASE_CFN_ROUND_FN:
+    CASE_CFN_ROUNDEVEN:
+    CASE_CFN_ROUNDEVEN_FN:
     CASE_CFN_SCALB:
     CASE_CFN_SCALBLN:
     CASE_CFN_SCALBN:
@@ -13586,6 +13590,8 @@ integer_valued_real_call_p (combined_fn fn, tree arg0, tree arg1, int depth)
     CASE_CFN_RINT_FN:
     CASE_CFN_ROUND:
     CASE_CFN_ROUND_FN:
+    CASE_CFN_ROUNDEVEN:
+    CASE_CFN_ROUNDEVEN_FN:
     CASE_CFN_TRUNC:
     CASE_CFN_TRUNC_FN:
       return true;
diff --git a/gcc/real.c b/gcc/real.c
index 0164f097a53..ab71430709f 100644
--- a/gcc/real.c
+++ b/gcc/real.c
@@ -5010,6 +5010,89 @@ real_round (REAL_VALUE_TYPE *r, format_helper fmt,
     real_convert (r, fmt, r);
 }
 
+/* Return true including 0 if integer part of R is even, else return
+   false. The function is not valid for rvc_inf and rvc_nan classes. */
+
+bool
+is_even (REAL_VALUE_TYPE *r)
+{
+  gcc_assert (r->cl != rvc_inf);
+  gcc_assert (r->cl != rvc_nan);
+
+  if (r->cl == rvc_zero)
+    return true;
+
+  /* For (-1,1), number is even. */
+  if (REAL_EXP (r) <= 0)
+    return true;
+
+  /* Check lowest bit, if not set, return true. */
+  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;
+  }
+
+  else
+    return true;
+
+  return false;
+}
+
+/* Return true if R is halfway between two integers, else return
+   false. The function is not valid for rvc_inf and rvc_nan classes. */
+
+bool
+is_halfway_below (const REAL_VALUE_TYPE *r)
+{
+  gcc_assert (r->cl != rvc_inf);
+  gcc_assert (r->cl != rvc_nan);
+  int i;
+
+  /* For numbers (-0.5,0) and (0,0.5). */
+  if (REAL_EXP (r) < 0)
+    return false;
+
+  else if (REAL_EXP (r) < SIGNIFICAND_BITS)
+  {
+    unsigned int n = SIGNIFICAND_BITS - REAL_EXP (r) - 1;
+    int w = n / HOST_BITS_PER_LONG;
+
+    for (i = 0; i < w; ++i)
+      if (r->sig[i] != 0)
+        return false;
+
+    unsigned long num = ((unsigned long)1 << (n % HOST_BITS_PER_LONG));
+
+    if (((r->sig[w] & num) != 0) && ((r->sig[w] & (num-1)) == 0))
+      return true;
+  }
+  return false;
+}
+
+/* Round X to nearest integer, rounding halfway cases towards even. */
+
+void
+real_roundeven (REAL_VALUE_TYPE *r, format_helper fmt,
+		const REAL_VALUE_TYPE *x)
+{
+  if (is_halfway_below (x))
+  {
+    do_add (r, x, &dconsthalf, x->sign);
+    if (!is_even (r))
+      do_add (r, r, &dconstm1, x->sign);
+    if (fmt)
+      real_convert (r, fmt, r);
+  }
+  else
+    real_round (r, fmt, x);
+}
+
 /* Set the sign of R to the sign of X.  */
 
 void
diff --git a/gcc/real.h b/gcc/real.h
index 95b9db83d24..76889bff0ea 100644
--- a/gcc/real.h
+++ b/gcc/real.h
@@ -41,11 +41,18 @@ struct GTY(()) real_value {
      sure they're packed together, otherwise REAL_VALUE_TYPE_SIZE will
      be miscomputed.  */
   unsigned int /* ENUM_BITFIELD (real_value_class) */ cl : 2;
+  /* 1 if number is decimal floating point */
   unsigned int decimal : 1;
+  /* 1 if number is negative */
   unsigned int sign : 1;
+  /* 1 if number is signalling */
   unsigned int signalling : 1;
+  /* 1 if number is canonical
+  All are generally used for handling cases in real.c */
   unsigned int canonical : 1;
+  /* unbiased exponent of the number */
   unsigned int uexp : EXP_BITS;
+  /* significand of the number */
   unsigned long sig[SIGSZ];
 };
 
@@ -500,6 +507,8 @@ extern void real_ceil (REAL_VALUE_TYPE *, format_helper,
 		       const REAL_VALUE_TYPE *);
 extern void real_round (REAL_VALUE_TYPE *, format_helper,
 			const REAL_VALUE_TYPE *);
+extern void real_roundeven (REAL_VALUE_TYPE *, format_helper,
+      const REAL_VALUE_TYPE *);
 
 /* Set the sign of R to the sign of X.  */
 extern void real_copysign (REAL_VALUE_TYPE *, const REAL_VALUE_TYPE *);
diff --git a/gcc/testsuite/gcc.dg/torture/builtin-round-roundeven.c b/gcc/testsuite/gcc.dg/torture/builtin-round-roundeven.c
new file mode 100644
index 00000000000..f75adf6ec8a
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/builtin-round-roundeven.c
@@ -0,0 +1,23 @@
+/* { dg-do link } */
+
+extern int link_error (int);
+
+#define TEST(FN, VALUE, RESULT) \
+  if (__builtin_##FN (VALUE) != RESULT) link_error (__LINE__);
+
+int
+main (void)
+{
+  TEST(roundeven,  0, 0);
+  TEST(roundeven,  0.5, 0);
+  TEST(roundeven,  -0.5, 0);
+  TEST(roundeven,  6, 6);
+  TEST(roundeven,  -8, -8);
+  TEST(roundeven,  2.5, 2);
+  TEST(roundeven,  3.5, 4);
+  TEST(roundeven,  -1.5, -2);
+  TEST(roundeven,  3.499, 3);
+  TEST(roundeven,  3.501, 4);
+
+  return 0;
+}
\ No newline at end of file
diff --git a/gcc/testsuite/gcc.dg/torture/builtin-round-roundevenf128.c b/gcc/testsuite/gcc.dg/torture/builtin-round-roundevenf128.c
new file mode 100644
index 00000000000..592bad49623
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/builtin-round-roundevenf128.c
@@ -0,0 +1,20 @@
+/* { dg-do link } */
+/* { dg-add-options float128 } */
+/* { dg-require-effective-target float128 } */
+
+extern int link_error (int);
+
+#define TEST(FN, VALUE, RESULT) \
+  if (__builtin_##FN##f128 (VALUE) != RESULT) link_error (__LINE__);
+
+int
+main (void)
+{
+  TEST(roundeven,  (0x1p64+0.5f128), (0x1p64f128));
+  TEST(roundeven,  (0x1p63+0.5f128), (0x1p63f128));
+  TEST(roundeven,  (0x1p63-0.5f128), (0x1p63f128));
+  TEST(roundeven,  (0x1p64-0.5f128), (0x1p64f128));
+  TEST(roundeven,  (0x1p64+0.501f128), (0x1p64+1.0f128));
+  TEST(roundeven,  (0x1.C00000000000039A5653p1f128), (0x1p2f128))
+  return 0;
+}
\ No newline at end of file

^ permalink raw reply	[flat|nested] 60+ messages in thread

* Re: About GSOC.
  2019-06-09  4:48                                                                               ` Tejas Joshi
@ 2019-06-10 20:26                                                                                 ` Joseph Myers
  2019-06-12 18:52                                                                                   ` Tejas Joshi
  0 siblings, 1 reply; 60+ messages in thread
From: Joseph Myers @ 2019-06-10 20:26 UTC (permalink / raw)
  To: Tejas Joshi; +Cc: gcc, Martin Jambor, hubicka

On Sun, 9 Jun 2019, Tejas Joshi wrote:

> Hello.
> I have created another patch which addresses the above points,
> attached herewith.

I don't think you should have the unreachable "return false;" in is_even.  
The last "else if" can just be "else".

> > a conditional with < not <=; if REAL_EXP (r) == SIGNIFICAND_BITS, the
> > least significant bit has value 1 and the number must be an integer).
> 
> The number is integer because of the whole word spaces is occupied by
> integer part?
> Also, why would the least significant bit will have value 1 if
> REAL_EXP (r) == SIGNIFICAND_BITS, as it only concerns with 2^0th
> position (even or odd)?

My understanding is that the significand is, as per the comments in 
real.c, in the range [0.5, 1.0).  There are SIGNIFICAND_BITS bits.  The 
bit above the most significant one has value 2^REAL_EXP.  The most 
significant one has value 2^(REAL_EXP-1).  The least significant one has 
value 2^(REAL_EXP-SIGNIFICAND_BITS).  If REAL_EXP == SIGNIFICAND_BITS, 
that means the least significant bit has value 2^0 = 1, and there are no 
bits with value 0.5 or below, so the number is an integer.

-- 
Joseph S. Myers
joseph@codesourcery.com

^ permalink raw reply	[flat|nested] 60+ messages in thread

* Re: About GSOC.
  2019-06-06 16:43                                                                             ` Joseph Myers
@ 2019-06-09  4:48                                                                               ` Tejas Joshi
  2019-06-10 20:26                                                                                 ` Joseph Myers
  0 siblings, 1 reply; 60+ messages in thread
From: Tejas Joshi @ 2019-06-09  4:48 UTC (permalink / raw)
  To: gcc; +Cc: Martin Jambor, hubicka, joseph

[-- Attachment #1: Type: text/plain, Size: 3387 bytes --]

Hello.
I have created another patch which addresses the above points,
attached herewith.

> a conditional with < not <=; if REAL_EXP (r) == SIGNIFICAND_BITS, the
> least significant bit has value 1 and the number must be an integer).

The number is integer because of the whole word spaces is occupied by
integer part?
Also, why would the least significant bit will have value 1 if
REAL_EXP (r) == SIGNIFICAND_BITS, as it only concerns with 2^0th
position (even or odd)?

Thanks,
-Tejas


On Thu, 6 Jun 2019 at 22:13, Joseph Myers <joseph@codesourcery.com> wrote:
>
> On Tue, 4 Jun 2019, Tejas Joshi wrote:
>
> > Hello.
> >
> > > NaN, and you should make sure it behaves accordingly.  (If it should never
> > > be called for them, a gcc_assert would be appropriate.)
> >
> > I can't find any documentation about how and when to use gcc_assert.
> > But I used it looking at the comment at its definition and locations
> > it is used, is this appropriate? Or is it supposed to be used before
> > calling the function? :
> >
> > +bool
> > +is_even (REAL_VALUE_TYPE *r)
> > +{
> > +  /* The function is not supposed to use for Inf and NaN. */
> > +  gcc_assert (r->cl != rvc_inf);
> > +  gcc_assert (r->cl != rvc_nan);
>
> I'd suggest making the comment above the function be clear about what
> classes of arguments are or are not valid, and then you don't need a
> comment on the assertions.
>
> Is REAL_EXP meaningful for rvc_zero?  If not, you should check for
> rvc_zero and handle it appropriately before doing anything checking
> REAL_EXP.
>
> > > 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.
> > > 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.
> >
> > I did not understand this. What is the bit with value 1?
>
> I don't understand your question.  The "sig" array contains
> SIGNIFICAND_BITS bits.  The most significant one has value 2^(REAL_EXP-1)
> and thus the least significant one has value
> 2^(REAL_EXP-SIGNIFICAND_BITS).  The ones we care about for the present
> purposes are the bit with value 1 (to tell whether an integer part is even
> or odd), the bit with value 0.5 and all the bits lower than that (to tell
> whether the fractional part is exactly 0.5 or not).
>
> > But when n is a multiple of HOST_BITS_PER_LONG, the function was
> > computing value of w wrong (e.g. for number 2^63 + 0.5). At such time,
> > would the following improvisation be acceptable in is_halfway_below?
>
> That still seems wrong.
>
> For testing for a halfway value you don't care about the bit with value 1.
> You do care about the bit with value 0.5, and you do care about the lower
> bits.
>
> So you should probably set n = SIGNIFICAND_BITS - REAL_EXP (r) - 1 (under
> a conditional with < not <=; if REAL_EXP (r) == SIGNIFICAND_BITS, the
> least significant bit has value 1 and the number must be an integer).
> That way, n is the bit position of the bit with value 0.5.  Then you can
> compute w from n without special casing to get the word position of the
> bit with value 0.5.  For the words below w you check they are entirely 0.
> For word w you need to check both that bit n is 1 and the lower bits are
> 0.
>
> --
> Joseph S. Myers
> joseph@codesourcery.com

[-- Attachment #2: roundeven1.patch --]
[-- Type: text/x-patch, Size: 10554 bytes --]

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_const_logb (result, arg, format);
 
@@ -854,6 +863,10 @@ fold_const_call_ss (wide_int *result, combined_fn fn,
       return fold_const_conversion (result, real_round, arg,
 				    precision, format);
 
+    CASE_CFN_ROUNDEVEN:
+    CASE_CFN_ROUNDEVEN_FN:
+      return fold_const_conversion (result, real_roundeven, arg, precision, format);
+
     CASE_CFN_IRINT:
     CASE_CFN_LRINT:
     CASE_CFN_LLRINT:
diff --git a/gcc/fold-const.c b/gcc/fold-const.c
index 59cedeafd71..ab96f197d5f 100644
--- a/gcc/fold-const.c
+++ b/gcc/fold-const.c
@@ -329,6 +329,8 @@ negate_mathfn_p (combined_fn fn)
     CASE_CFN_LLROUND:
     CASE_CFN_LROUND:
     CASE_CFN_ROUND:
+    CASE_CFN_ROUNDEVEN:
+    CASE_CFN_ROUNDEVEN_FN:
     CASE_CFN_SIN:
     CASE_CFN_SINH:
     CASE_CFN_TAN:
@@ -13060,6 +13062,8 @@ tree_call_nonnegative_warnv_p (tree type, combined_fn fn, tree arg0, tree arg1,
     CASE_CFN_RINT_FN:
     CASE_CFN_ROUND:
     CASE_CFN_ROUND_FN:
+    CASE_CFN_ROUNDEVEN:
+    CASE_CFN_ROUNDEVEN_FN:
     CASE_CFN_SCALB:
     CASE_CFN_SCALBLN:
     CASE_CFN_SCALBN:
@@ -13583,6 +13587,8 @@ integer_valued_real_call_p (combined_fn fn, tree arg0, tree arg1, int depth)
     CASE_CFN_RINT_FN:
     CASE_CFN_ROUND:
     CASE_CFN_ROUND_FN:
+    CASE_CFN_ROUNDEVEN:
+    CASE_CFN_ROUNDEVEN_FN:
     CASE_CFN_TRUNC:
     CASE_CFN_TRUNC_FN:
       return true;
diff --git a/gcc/internal-fn.def b/gcc/internal-fn.def
index cda314e1121..b89918815f9 100644
--- a/gcc/internal-fn.def
+++ b/gcc/internal-fn.def
@@ -224,6 +224,7 @@ DEF_INTERNAL_FLT_FLOATN_FN (FLOOR, ECF_CONST, floor, unary)
 DEF_INTERNAL_FLT_FLOATN_FN (NEARBYINT, ECF_CONST, nearbyint, unary)
 DEF_INTERNAL_FLT_FLOATN_FN (RINT, ECF_CONST, rint, unary)
 DEF_INTERNAL_FLT_FLOATN_FN (ROUND, ECF_CONST, round, unary)
+DEF_INTERNAL_FLT_FLOATN_FN (ROUNDEVEN, ECF_CONST, roundeven, unary)
 DEF_INTERNAL_FLT_FLOATN_FN (TRUNC, ECF_CONST, btrunc, unary)
 
 /* Binary math functions.  */
diff --git a/gcc/match.pd b/gcc/match.pd
index 7cc2374ffeb..fa18b499162 100644
--- a/gcc/match.pd
+++ b/gcc/match.pd
@@ -4229,7 +4229,7 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
  (abs @0))
 
 /* trunc(trunc(x)) -> trunc(x), etc.  */
-(for fns (TRUNC_ALL FLOOR_ALL CEIL_ALL ROUND_ALL NEARBYINT_ALL RINT_ALL)
+(for fns (TRUNC_ALL FLOOR_ALL CEIL_ALL ROUND_ALL BUILT_IN_ROUNDEVEN NEARBYINT_ALL RINT_ALL)
  (simplify
   (fns (fns @0))
   (fns @0)))
diff --git a/gcc/optabs.def b/gcc/optabs.def
index 5a67f5eed5e..eb9e22acd8f 100644
--- a/gcc/optabs.def
+++ b/gcc/optabs.def
@@ -267,6 +267,7 @@ OPTAB_D (fnms_optab, "fnms$a4")
 
 OPTAB_D (rint_optab, "rint$a2")
 OPTAB_D (round_optab, "round$a2")
+OPTAB_D (roundeven_optab, "roundeven$a2")
 OPTAB_D (floor_optab, "floor$a2")
 OPTAB_D (ceil_optab, "ceil$a2")
 OPTAB_D (btrunc_optab, "btrunc$a2")
diff --git a/gcc/real.c b/gcc/real.c
index f822ae82d61..e7d9bb367b5 100644
--- a/gcc/real.c
+++ b/gcc/real.c
@@ -5010,6 +5010,89 @@ real_round (REAL_VALUE_TYPE *r, format_helper fmt,
     real_convert (r, fmt, r);
 }
 
+/* Return true including 0 if integer part of R is even, else return
+   false. The function is not valid for rvc_inf and rvc_nan classes. */
+
+bool
+is_even (REAL_VALUE_TYPE *r)
+{
+  gcc_assert (r->cl != rvc_inf);
+  gcc_assert (r->cl != rvc_nan);
+
+  if (r->cl == rvc_zero)
+    return true;
+
+  /* For (-1,1) including 0, number is even. */
+  if (REAL_EXP (r) <= 0)
+    return true;
+
+  /* Check lowest bit, if not set, return true. */
+  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;
+  }
+
+  else if (REAL_EXP (r) > SIGNIFICAND_BITS)
+    return true;
+
+  return false;
+}
+
+/* Return true if R is halfway between two integers, else return
+   false. The function is not valid for rvc_inf and rvc_nan classes. */
+
+bool
+is_halfway_below (const REAL_VALUE_TYPE *r)
+{
+  gcc_assert (r->cl != rvc_inf);
+  gcc_assert (r->cl != rvc_nan);
+  int i;
+
+  /* For numbers (-0.5,0) and (0,0.5). */
+  if (REAL_EXP (r) < 0)
+    return false;
+
+  else if (REAL_EXP (r) < SIGNIFICAND_BITS)
+  {
+    unsigned int n = SIGNIFICAND_BITS - REAL_EXP (r) - 1;
+    int w = n / HOST_BITS_PER_LONG;
+
+    for (i = 0; i < w; ++i)
+      if (r->sig[i] != 0)
+        return false;
+
+    unsigned long num = ((unsigned long)1 << (n % HOST_BITS_PER_LONG));
+
+    if (((r->sig[w] & num) != 0) && ((r->sig[w] & (num-1)) == 0))
+      return true;
+  }
+  return false;
+}
+
+/* Round X to nearest integer, rounding halfway cases towards even. */
+
+void
+real_roundeven (REAL_VALUE_TYPE *r, format_helper fmt,
+		const REAL_VALUE_TYPE *x)
+{
+  if (is_halfway_below (x))
+  {
+    do_add (r, x, &dconsthalf, x->sign);
+    if (!is_even (r))
+      do_add (r, r, &dconstm1, x->sign);
+    if (fmt)
+      real_convert (r, fmt, r);
+  }
+  else
+    real_round (r, fmt, x);
+}
+
 /* Set the sign of R to the sign of X.  */
 
 void
diff --git a/gcc/real.h b/gcc/real.h
index 0ce42565708..ebe66d234af 100644
--- a/gcc/real.h
+++ b/gcc/real.h
@@ -41,11 +41,18 @@ struct GTY(()) real_value {
      sure they're packed together, otherwise REAL_VALUE_TYPE_SIZE will
      be miscomputed.  */
   unsigned int /* ENUM_BITFIELD (real_value_class) */ cl : 2;
+  /* 1 if number is decimal floating point */
   unsigned int decimal : 1;
+  /* 1 if number is negative */
   unsigned int sign : 1;
+  /* 1 if number is signalling */
   unsigned int signalling : 1;
+  /* 1 if number is canonical
+  All are generally used for handling cases in real.c */
   unsigned int canonical : 1;
+  /* unbiased exponent of the number */
   unsigned int uexp : EXP_BITS;
+  /* significand of the number */
   unsigned long sig[SIGSZ];
 };
 
@@ -499,6 +506,8 @@ extern void real_ceil (REAL_VALUE_TYPE *, format_helper,
 		       const REAL_VALUE_TYPE *);
 extern void real_round (REAL_VALUE_TYPE *, format_helper,
 			const REAL_VALUE_TYPE *);
+extern void real_roundeven (REAL_VALUE_TYPE *, format_helper,
+      const REAL_VALUE_TYPE *);
 
 /* Set the sign of R to the sign of X.  */
 extern void real_copysign (REAL_VALUE_TYPE *, const REAL_VALUE_TYPE *);
diff --git a/gcc/testsuite/gcc.dg/torture/builtin-round-roundeven.c b/gcc/testsuite/gcc.dg/torture/builtin-round-roundeven.c
new file mode 100644
index 00000000000..f75adf6ec8a
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/builtin-round-roundeven.c
@@ -0,0 +1,23 @@
+/* { dg-do link } */
+
+extern int link_error (int);
+
+#define TEST(FN, VALUE, RESULT) \
+  if (__builtin_##FN (VALUE) != RESULT) link_error (__LINE__);
+
+int
+main (void)
+{
+  TEST(roundeven,  0, 0);
+  TEST(roundeven,  0.5, 0);
+  TEST(roundeven,  -0.5, 0);
+  TEST(roundeven,  6, 6);
+  TEST(roundeven,  -8, -8);
+  TEST(roundeven,  2.5, 2);
+  TEST(roundeven,  3.5, 4);
+  TEST(roundeven,  -1.5, -2);
+  TEST(roundeven,  3.499, 3);
+  TEST(roundeven,  3.501, 4);
+
+  return 0;
+}
\ No newline at end of file
diff --git a/gcc/testsuite/gcc.dg/torture/builtin-round-roundevenf128.c b/gcc/testsuite/gcc.dg/torture/builtin-round-roundevenf128.c
new file mode 100644
index 00000000000..592bad49623
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/builtin-round-roundevenf128.c
@@ -0,0 +1,20 @@
+/* { dg-do link } */
+/* { dg-add-options float128 } */
+/* { dg-require-effective-target float128 } */
+
+extern int link_error (int);
+
+#define TEST(FN, VALUE, RESULT) \
+  if (__builtin_##FN##f128 (VALUE) != RESULT) link_error (__LINE__);
+
+int
+main (void)
+{
+  TEST(roundeven,  (0x1p64+0.5f128), (0x1p64f128));
+  TEST(roundeven,  (0x1p63+0.5f128), (0x1p63f128));
+  TEST(roundeven,  (0x1p63-0.5f128), (0x1p63f128));
+  TEST(roundeven,  (0x1p64-0.5f128), (0x1p64f128));
+  TEST(roundeven,  (0x1p64+0.501f128), (0x1p64+1.0f128));
+  TEST(roundeven,  (0x1.C00000000000039A5653p1f128), (0x1p2f128))
+  return 0;
+}
\ No newline at end of file

^ permalink raw reply	[flat|nested] 60+ messages in thread

* Re: About GSOC.
  2019-06-04  7:03                                                                           ` Tejas Joshi
  2019-06-05 12:19                                                                             ` Tejas Joshi
@ 2019-06-06 16:43                                                                             ` Joseph Myers
  2019-06-09  4:48                                                                               ` Tejas Joshi
  1 sibling, 1 reply; 60+ messages in thread
From: Joseph Myers @ 2019-06-06 16:43 UTC (permalink / raw)
  To: Tejas Joshi; +Cc: gcc, Martin Jambor, hubicka

On Tue, 4 Jun 2019, Tejas Joshi wrote:

> Hello.
> 
> > NaN, and you should make sure it behaves accordingly.  (If it should never
> > be called for them, a gcc_assert would be appropriate.)
> 
> I can't find any documentation about how and when to use gcc_assert.
> But I used it looking at the comment at its definition and locations
> it is used, is this appropriate? Or is it supposed to be used before
> calling the function? :
> 
> +bool
> +is_even (REAL_VALUE_TYPE *r)
> +{
> +  /* The function is not supposed to use for Inf and NaN. */
> +  gcc_assert (r->cl != rvc_inf);
> +  gcc_assert (r->cl != rvc_nan);

I'd suggest making the comment above the function be clear about what 
classes of arguments are or are not valid, and then you don't need a 
comment on the assertions.

Is REAL_EXP meaningful for rvc_zero?  If not, you should check for 
rvc_zero and handle it appropriately before doing anything checking 
REAL_EXP.

> > 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.
> > 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.
> 
> I did not understand this. What is the bit with value 1?

I don't understand your question.  The "sig" array contains 
SIGNIFICAND_BITS bits.  The most significant one has value 2^(REAL_EXP-1) 
and thus the least significant one has value 
2^(REAL_EXP-SIGNIFICAND_BITS).  The ones we care about for the present 
purposes are the bit with value 1 (to tell whether an integer part is even 
or odd), the bit with value 0.5 and all the bits lower than that (to tell 
whether the fractional part is exactly 0.5 or not).

> But when n is a multiple of HOST_BITS_PER_LONG, the function was
> computing value of w wrong (e.g. for number 2^63 + 0.5). At such time,
> would the following improvisation be acceptable in is_halfway_below?

That still seems wrong.

For testing for a halfway value you don't care about the bit with value 1.  
You do care about the bit with value 0.5, and you do care about the lower 
bits.

So you should probably set n = SIGNIFICAND_BITS - REAL_EXP (r) - 1 (under 
a conditional with < not <=; if REAL_EXP (r) == SIGNIFICAND_BITS, the 
least significant bit has value 1 and the number must be an integer).  
That way, n is the bit position of the bit with value 0.5.  Then you can 
compute w from n without special casing to get the word position of the 
bit with value 0.5.  For the words below w you check they are entirely 0.  
For word w you need to check both that bit n is 1 and the lower bits are 
0.

-- 
Joseph S. Myers
joseph@codesourcery.com

^ permalink raw reply	[flat|nested] 60+ messages in thread

* Re: About GSOC.
  2019-06-04  7:03                                                                           ` Tejas Joshi
@ 2019-06-05 12:19                                                                             ` Tejas Joshi
  2019-06-06 16:43                                                                             ` Joseph Myers
  1 sibling, 0 replies; 60+ messages in thread
From: Tejas Joshi @ 2019-06-05 12:19 UTC (permalink / raw)
  To: gcc; +Cc: Martin Jambor, hubicka, joseph

[-- Attachment #1: Type: text/plain, Size: 6814 bytes --]

Hello.
Following patch is tested on following test cases in the testsuite and
tests did not fail. I have considered most of the test cases this time
hopefully.

/* { dg-do link } */

extern int link_error (int);

#define TEST(FN, VALUE, RESULT) \
  if (__builtin_##FN (VALUE) != RESULT) link_error (__LINE__);

int
main (void)
{
  TEST(roundeven,  0, 0);
  TEST(roundeven,  0.5, 0);
  TEST(roundeven,  -0.5, 0);
  TEST(roundeven,  6, 6);
  TEST(roundeven,  -8, -8);
  TEST(roundeven,  2.5, 2);
  TEST(roundeven,  3.5, 4);
  TEST(roundeven,  -1.5, -2);
  TEST(roundeven,  3.499, 3);
  TEST(roundeven,  3.501, 4);

  return 0;
}
_Float128 test cases :

/* { dg-do link } */
/* { dg-add-options float128 } */
/* { dg-require-effective-target float128 } */

extern int link_error (int);

#define TEST(FN, VALUE, RESULT) \
  if (__builtin_##FN##f128 (VALUE) != RESULT) link_error (__LINE__);

int
main (void)
{
  TEST(roundeven,  (0x1p64+0.5f128), (0x1p64f128));
  TEST(roundeven,  (0x1p63+0.5f128), (0x1p63f128));
  TEST(roundeven,  (0x1p63-0.5f128), (0x1p63f128));
  TEST(roundeven,  (0x1p64-0.5f128), (0x1p64f128));
  TEST(roundeven,  (0x1p64+0.501f128), (0x1p64+1.0f128));
  TEST(roundeven,  (0x1.C00000000000039A5653p1f128), (0x1p2f128))
// the hex number is 3.50000000...01 which would fail for roundeven
but not for f128
  return 0;
}

Thanks,
-Tejas

On Tue, 4 Jun 2019 at 12:38, Tejas Joshi <tejasjoshi9673@gmail.com> wrote:
>
> Hello.
>
> > NaN, and you should make sure it behaves accordingly.  (If it should never
> > be called for them, a gcc_assert would be appropriate.)
>
> I can't find any documentation about how and when to use gcc_assert.
> But I used it looking at the comment at its definition and locations
> it is used, is this appropriate? Or is it supposed to be used before
> calling the function? :
>
> +bool
> +is_even (REAL_VALUE_TYPE *r)
> +{
> +  /* The function is not supposed to use for Inf and NaN. */
> +  gcc_assert (r->cl != rvc_inf);
> +  gcc_assert (r->cl != rvc_nan);
>
> > 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.
> > 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.
>
> I did not understand this. What is the bit with value 1?
> But when n is a multiple of HOST_BITS_PER_LONG, the function was
> computing value of w wrong (e.g. for number 2^63 + 0.5). At such time,
> would the following improvisation be acceptable in is_halfway_below?
>
> +bool
> +is_halfway_below (const REAL_VALUE_TYPE *r)
> +{
> +  /* The function is not supposed to use for Inf and NaN. */
> +  gcc_assert (r->cl != rvc_inf);
> +  gcc_assert (r->cl != rvc_nan);
> +  int i;
> +
> +  /* For numbers (-0.5,0) and (0,0.5). */
> +  if (REAL_EXP (r) < 0)
> +    return false;
> +
> +  else if (REAL_EXP (r) <= SIGNIFICAND_BITS)
> +  {
> +    unsigned int n = SIGNIFICAND_BITS - REAL_EXP (r);
> +    int w = n / HOST_BITS_PER_LONG;
> +
> +    if (n % HOST_BITS_PER_LONG == 0)
> +    {
> +      if (w > 0)
> +        w = w - 1;
> +      else
> +        w = 0;
> +    }
> +
> +    for (i = 0; i < w; ++i)
> +    {
> +      if (r->sig[i] != 0)
> +        return false;
> +    }
>
> Thanks.
>
>
> On Mon, 3 Jun 2019 at 22:08, Joseph Myers <joseph@codesourcery.com> wrote:
> >
> > 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
> > joseph@codesourcery.com

[-- Attachment #2: roundeven.patch --]
[-- Type: text/x-patch, Size: 8927 bytes --]

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_const_logb (result, arg, format);
 
@@ -854,6 +863,10 @@ fold_const_call_ss (wide_int *result, combined_fn fn,
       return fold_const_conversion (result, real_round, arg,
 				    precision, format);
 
+    CASE_CFN_ROUNDEVEN:
+    CASE_CFN_ROUNDEVEN_FN:
+      return fold_const_conversion (result, real_roundeven, arg, precision, format);
+
     CASE_CFN_IRINT:
     CASE_CFN_LRINT:
     CASE_CFN_LLRINT:
diff --git a/gcc/fold-const.c b/gcc/fold-const.c
index 59cedeafd71..ab96f197d5f 100644
--- a/gcc/fold-const.c
+++ b/gcc/fold-const.c
@@ -329,6 +329,8 @@ negate_mathfn_p (combined_fn fn)
     CASE_CFN_LLROUND:
     CASE_CFN_LROUND:
     CASE_CFN_ROUND:
+    CASE_CFN_ROUNDEVEN:
+    CASE_CFN_ROUNDEVEN_FN:
     CASE_CFN_SIN:
     CASE_CFN_SINH:
     CASE_CFN_TAN:
@@ -13060,6 +13062,8 @@ tree_call_nonnegative_warnv_p (tree type, combined_fn fn, tree arg0, tree arg1,
     CASE_CFN_RINT_FN:
     CASE_CFN_ROUND:
     CASE_CFN_ROUND_FN:
+    CASE_CFN_ROUNDEVEN:
+    CASE_CFN_ROUNDEVEN_FN:
     CASE_CFN_SCALB:
     CASE_CFN_SCALBLN:
     CASE_CFN_SCALBN:
@@ -13583,6 +13587,8 @@ integer_valued_real_call_p (combined_fn fn, tree arg0, tree arg1, int depth)
     CASE_CFN_RINT_FN:
     CASE_CFN_ROUND:
     CASE_CFN_ROUND_FN:
+    CASE_CFN_ROUNDEVEN:
+    CASE_CFN_ROUNDEVEN_FN:
     CASE_CFN_TRUNC:
     CASE_CFN_TRUNC_FN:
       return true;
diff --git a/gcc/internal-fn.def b/gcc/internal-fn.def
index cda314e1121..b89918815f9 100644
--- a/gcc/internal-fn.def
+++ b/gcc/internal-fn.def
@@ -224,6 +224,7 @@ DEF_INTERNAL_FLT_FLOATN_FN (FLOOR, ECF_CONST, floor, unary)
 DEF_INTERNAL_FLT_FLOATN_FN (NEARBYINT, ECF_CONST, nearbyint, unary)
 DEF_INTERNAL_FLT_FLOATN_FN (RINT, ECF_CONST, rint, unary)
 DEF_INTERNAL_FLT_FLOATN_FN (ROUND, ECF_CONST, round, unary)
+DEF_INTERNAL_FLT_FLOATN_FN (ROUNDEVEN, ECF_CONST, roundeven, unary)
 DEF_INTERNAL_FLT_FLOATN_FN (TRUNC, ECF_CONST, btrunc, unary)
 
 /* Binary math functions.  */
diff --git a/gcc/match.pd b/gcc/match.pd
index 7cc2374ffeb..fa18b499162 100644
--- a/gcc/match.pd
+++ b/gcc/match.pd
@@ -4229,7 +4229,7 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
  (abs @0))
 
 /* trunc(trunc(x)) -> trunc(x), etc.  */
-(for fns (TRUNC_ALL FLOOR_ALL CEIL_ALL ROUND_ALL NEARBYINT_ALL RINT_ALL)
+(for fns (TRUNC_ALL FLOOR_ALL CEIL_ALL ROUND_ALL BUILT_IN_ROUNDEVEN NEARBYINT_ALL RINT_ALL)
  (simplify
   (fns (fns @0))
   (fns @0)))
diff --git a/gcc/optabs.def b/gcc/optabs.def
index 5a67f5eed5e..eb9e22acd8f 100644
--- a/gcc/optabs.def
+++ b/gcc/optabs.def
@@ -267,6 +267,7 @@ OPTAB_D (fnms_optab, "fnms$a4")
 
 OPTAB_D (rint_optab, "rint$a2")
 OPTAB_D (round_optab, "round$a2")
+OPTAB_D (roundeven_optab, "roundeven$a2")
 OPTAB_D (floor_optab, "floor$a2")
 OPTAB_D (ceil_optab, "ceil$a2")
 OPTAB_D (btrunc_optab, "btrunc$a2")
diff --git a/gcc/real.c b/gcc/real.c
index f822ae82d61..aee11e52dd4 100644
--- a/gcc/real.c
+++ b/gcc/real.c
@@ -5010,6 +5010,96 @@ real_round (REAL_VALUE_TYPE *r, format_helper fmt,
     real_convert (r, fmt, r);
 }
 
+/* Return true including 0 if integer part of R is even, else return false. */
+
+bool
+is_even (REAL_VALUE_TYPE *r)
+{
+  /* The function is not supposed to use for Inf and NaN. */
+  gcc_assert (r->cl != rvc_inf);
+  gcc_assert (r->cl != rvc_nan);
+
+  /* For (-1,1) including 0, number is even. */
+  if (REAL_EXP (r) <= 0)
+    return true;
+
+  /* Check lowest bit, if not set, return true. */
+  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;
+  }
+
+  else if (REAL_EXP (r) > SIGNIFICAND_BITS)
+    return true;
+
+  return false;
+}
+
+/* Return true if R is halfway between two integers, else return false. */
+
+bool
+is_halfway_below (const REAL_VALUE_TYPE *r)
+{
+  /* The function is not supposed to use for Inf and NaN. */
+  gcc_assert (r->cl != rvc_inf);
+  gcc_assert (r->cl != rvc_nan);
+  int i;
+
+  /* For numbers (-0.5,0) and (0,0.5). */
+  if (REAL_EXP (r) < 0)
+    return false;
+
+  else if (REAL_EXP (r) <= SIGNIFICAND_BITS)
+  {
+    unsigned int n = SIGNIFICAND_BITS - REAL_EXP (r);
+    int w = n / HOST_BITS_PER_LONG;
+
+    if (n % HOST_BITS_PER_LONG == 0)
+    {
+      if (w > 0)
+        w = w - 1;
+      else
+        w = 0;
+    }
+
+    for (i = 0; i < w; ++i)
+    {
+      if (r->sig[i] != 0)
+        return false;
+    }
+
+    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;
+  }
+  return false;
+}
+
+/* Round X to nearest integer, rounding halfway cases towards even. */
+
+void
+real_roundeven (REAL_VALUE_TYPE *r, format_helper fmt,
+		const REAL_VALUE_TYPE *x)
+{
+  if (is_halfway_below (x))
+  {
+    do_add (r, x, &dconsthalf, x->sign);
+    if (!is_even (r))
+      do_add (r, r, &dconstm1, x->sign);
+    if (fmt)
+      real_convert (r, fmt, r);
+  }
+  else
+    real_round (r, fmt, x);
+}
+
 /* Set the sign of R to the sign of X.  */
 
 void
diff --git a/gcc/real.h b/gcc/real.h
index 0ce42565708..ebe66d234af 100644
--- a/gcc/real.h
+++ b/gcc/real.h
@@ -41,11 +41,18 @@ struct GTY(()) real_value {
      sure they're packed together, otherwise REAL_VALUE_TYPE_SIZE will
      be miscomputed.  */
   unsigned int /* ENUM_BITFIELD (real_value_class) */ cl : 2;
+  /* 1 if number is decimal floating point */
   unsigned int decimal : 1;
+  /* 1 if number is negative */
   unsigned int sign : 1;
+  /* 1 if number is signalling */
   unsigned int signalling : 1;
+  /* 1 if number is canonical
+  All are generally used for handling cases in real.c */
   unsigned int canonical : 1;
+  /* unbiased exponent of the number */
   unsigned int uexp : EXP_BITS;
+  /* significand of the number */
   unsigned long sig[SIGSZ];
 };
 
@@ -499,6 +506,8 @@ extern void real_ceil (REAL_VALUE_TYPE *, format_helper,
 		       const REAL_VALUE_TYPE *);
 extern void real_round (REAL_VALUE_TYPE *, format_helper,
 			const REAL_VALUE_TYPE *);
+extern void real_roundeven (REAL_VALUE_TYPE *, format_helper,
+      const REAL_VALUE_TYPE *);
 
 /* Set the sign of R to the sign of X.  */
 extern void real_copysign (REAL_VALUE_TYPE *, const REAL_VALUE_TYPE *);

^ permalink raw reply	[flat|nested] 60+ messages in thread

* Re: About GSOC.
  2019-06-03 16:38                                                                         ` Joseph Myers
@ 2019-06-04  7:03                                                                           ` Tejas Joshi
  2019-06-05 12:19                                                                             ` Tejas Joshi
  2019-06-06 16:43                                                                             ` Joseph Myers
  0 siblings, 2 replies; 60+ messages in thread
From: Tejas Joshi @ 2019-06-04  7:03 UTC (permalink / raw)
  To: gcc; +Cc: Martin Jambor, hubicka, joseph

Hello.

> NaN, and you should make sure it behaves accordingly.  (If it should never
> be called for them, a gcc_assert would be appropriate.)

I can't find any documentation about how and when to use gcc_assert.
But I used it looking at the comment at its definition and locations
it is used, is this appropriate? Or is it supposed to be used before
calling the function? :

+bool
+is_even (REAL_VALUE_TYPE *r)
+{
+  /* The function is not supposed to use for Inf and NaN. */
+  gcc_assert (r->cl != rvc_inf);
+  gcc_assert (r->cl != rvc_nan);

> 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.
> 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.

I did not understand this. What is the bit with value 1?
But when n is a multiple of HOST_BITS_PER_LONG, the function was
computing value of w wrong (e.g. for number 2^63 + 0.5). At such time,
would the following improvisation be acceptable in is_halfway_below?

+bool
+is_halfway_below (const REAL_VALUE_TYPE *r)
+{
+  /* The function is not supposed to use for Inf and NaN. */
+  gcc_assert (r->cl != rvc_inf);
+  gcc_assert (r->cl != rvc_nan);
+  int i;
+
+  /* For numbers (-0.5,0) and (0,0.5). */
+  if (REAL_EXP (r) < 0)
+    return false;
+
+  else if (REAL_EXP (r) <= SIGNIFICAND_BITS)
+  {
+    unsigned int n = SIGNIFICAND_BITS - REAL_EXP (r);
+    int w = n / HOST_BITS_PER_LONG;
+
+    if (n % HOST_BITS_PER_LONG == 0)
+    {
+      if (w > 0)
+        w = w - 1;
+      else
+        w = 0;
+    }
+
+    for (i = 0; i < w; ++i)
+    {
+      if (r->sig[i] != 0)
+        return false;
+    }

Thanks.


On Mon, 3 Jun 2019 at 22:08, Joseph Myers <joseph@codesourcery.com> wrote:
>
> 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
> joseph@codesourcery.com

^ permalink raw reply	[flat|nested] 60+ messages in thread

* Re: About GSOC.
  2019-05-31 10:28                                                                       ` Tejas Joshi
@ 2019-06-03 16:38                                                                         ` Joseph Myers
  2019-06-04  7:03                                                                           ` Tejas Joshi
  0 siblings, 1 reply; 60+ messages in thread
From: Joseph Myers @ 2019-06-03 16:38 UTC (permalink / raw)
  To: Tejas Joshi; +Cc: gcc, Martin Jambor, hubicka

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
joseph@codesourcery.com

^ permalink raw reply	[flat|nested] 60+ messages in thread

* Re: About GSOC.
  2019-05-31 13:30                                                                       ` Eric Gallager
@ 2019-06-03  9:37                                                                         ` Tejas Joshi
  0 siblings, 0 replies; 60+ messages in thread
From: Tejas Joshi @ 2019-06-03  9:37 UTC (permalink / raw)
  To: gcc; +Cc: Martin Jambor, hubicka

[-- Attachment #1: Type: text/plain, Size: 2437 bytes --]

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 <egall@gwmail.gwu.edu> wrote:
>
> On 5/31/19, Nathan Sidwell <nathan@acm.org> 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
> >

[-- Attachment #2: roundeven.patch --]
[-- Type: text/x-patch, Size: 8531 bytes --]

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_const_logb (result, arg, format);
 
@@ -854,6 +863,10 @@ fold_const_call_ss (wide_int *result, combined_fn fn,
       return fold_const_conversion (result, real_round, arg,
 				    precision, format);
 
+    CASE_CFN_ROUNDEVEN:
+    CASE_CFN_ROUNDEVEN_FN:
+      return fold_const_conversion (result, real_roundeven, arg, precision, format);
+
     CASE_CFN_IRINT:
     CASE_CFN_LRINT:
     CASE_CFN_LLRINT:
diff --git a/gcc/fold-const.c b/gcc/fold-const.c
index 59cedeafd71..ab96f197d5f 100644
--- a/gcc/fold-const.c
+++ b/gcc/fold-const.c
@@ -329,6 +329,8 @@ negate_mathfn_p (combined_fn fn)
     CASE_CFN_LLROUND:
     CASE_CFN_LROUND:
     CASE_CFN_ROUND:
+    CASE_CFN_ROUNDEVEN:
+    CASE_CFN_ROUNDEVEN_FN:
     CASE_CFN_SIN:
     CASE_CFN_SINH:
     CASE_CFN_TAN:
@@ -13060,6 +13062,8 @@ tree_call_nonnegative_warnv_p (tree type, combined_fn fn, tree arg0, tree arg1,
     CASE_CFN_RINT_FN:
     CASE_CFN_ROUND:
     CASE_CFN_ROUND_FN:
+    CASE_CFN_ROUNDEVEN:
+    CASE_CFN_ROUNDEVEN_FN:
     CASE_CFN_SCALB:
     CASE_CFN_SCALBLN:
     CASE_CFN_SCALBN:
@@ -13583,6 +13587,8 @@ integer_valued_real_call_p (combined_fn fn, tree arg0, tree arg1, int depth)
     CASE_CFN_RINT_FN:
     CASE_CFN_ROUND:
     CASE_CFN_ROUND_FN:
+    CASE_CFN_ROUNDEVEN:
+    CASE_CFN_ROUNDEVEN_FN:
     CASE_CFN_TRUNC:
     CASE_CFN_TRUNC_FN:
       return true;
diff --git a/gcc/internal-fn.def b/gcc/internal-fn.def
index cda314e1121..b89918815f9 100644
--- a/gcc/internal-fn.def
+++ b/gcc/internal-fn.def
@@ -224,6 +224,7 @@ DEF_INTERNAL_FLT_FLOATN_FN (FLOOR, ECF_CONST, floor, unary)
 DEF_INTERNAL_FLT_FLOATN_FN (NEARBYINT, ECF_CONST, nearbyint, unary)
 DEF_INTERNAL_FLT_FLOATN_FN (RINT, ECF_CONST, rint, unary)
 DEF_INTERNAL_FLT_FLOATN_FN (ROUND, ECF_CONST, round, unary)
+DEF_INTERNAL_FLT_FLOATN_FN (ROUNDEVEN, ECF_CONST, roundeven, unary)
 DEF_INTERNAL_FLT_FLOATN_FN (TRUNC, ECF_CONST, btrunc, unary)
 
 /* Binary math functions.  */
diff --git a/gcc/match.pd b/gcc/match.pd
index 7cc2374ffeb..98f4729f42d 100644
--- a/gcc/match.pd
+++ b/gcc/match.pd
@@ -4229,7 +4229,7 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
  (abs @0))
 
 /* trunc(trunc(x)) -> trunc(x), etc.  */
-(for fns (TRUNC_ALL FLOOR_ALL CEIL_ALL ROUND_ALL NEARBYINT_ALL RINT_ALL)
+(for fns (TRUNC_ALL FLOOR_ALL CEIL_ALL ROUND_ALL ROUNDEVEN_ALL NEARBYINT_ALL RINT_ALL)
  (simplify
   (fns (fns @0))
   (fns @0)))
diff --git a/gcc/optabs.def b/gcc/optabs.def
index 5a67f5eed5e..eb9e22acd8f 100644
--- a/gcc/optabs.def
+++ b/gcc/optabs.def
@@ -267,6 +267,7 @@ OPTAB_D (fnms_optab, "fnms$a4")
 
 OPTAB_D (rint_optab, "rint$a2")
 OPTAB_D (round_optab, "round$a2")
+OPTAB_D (roundeven_optab, "roundeven$a2")
 OPTAB_D (floor_optab, "floor$a2")
 OPTAB_D (ceil_optab, "ceil$a2")
 OPTAB_D (btrunc_optab, "btrunc$a2")
diff --git a/gcc/real.c b/gcc/real.c
index f822ae82d61..19c704ec0ec 100644
--- a/gcc/real.c
+++ b/gcc/real.c
@@ -5010,6 +5010,81 @@ real_round (REAL_VALUE_TYPE *r, format_helper fmt,
     real_convert (r, fmt, r);
 }
 
+/* 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;
+
+  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;
+}
+
+/* Return true if R is halfway between two integers, else return false. */
+
+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);
+
+    if (((r->sig[SIGSZ-1] & temp) != 0) && ((r->sig[SIGSZ-1] & (temp-1)) == 0))
+      return true;
+    else
+      return false;
+  }
+
+  else if (REAL_EXP (r) < SIGNIFICAND_BITS)
+  {
+    unsigned int n = SIGNIFICAND_BITS - REAL_EXP (r);
+    int i, w = n / HOST_BITS_PER_LONG;
+
+    for (i = 0; i < w; ++i)
+    {
+      if (r->sig[i] != 0)
+        return false;
+    }
+
+    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;
+  }
+  return false;
+}
+
+/* Round X to nearest integer, rounding halfway cases towards even. */
+
+void
+real_roundeven (REAL_VALUE_TYPE *r, format_helper fmt,
+		const REAL_VALUE_TYPE *x)
+{
+  fprintf (stderr, "\n%s\n", "in roundeven");
+  if (is_halfway_below (x))
+  {
+    do_add (r, x, &dconsthalf, x->sign);
+    if (!is_even (r))
+      do_add (r, r, &dconstm1, x->sign);
+  }
+  else
+    real_round (r, fmt, x);
+}
+
 /* Set the sign of R to the sign of X.  */
 
 void
diff --git a/gcc/real.h b/gcc/real.h
index 0ce42565708..ebe66d234af 100644
--- a/gcc/real.h
+++ b/gcc/real.h
@@ -41,11 +41,18 @@ struct GTY(()) real_value {
      sure they're packed together, otherwise REAL_VALUE_TYPE_SIZE will
      be miscomputed.  */
   unsigned int /* ENUM_BITFIELD (real_value_class) */ cl : 2;
+  /* 1 if number is decimal floating point */
   unsigned int decimal : 1;
+  /* 1 if number is negative */
   unsigned int sign : 1;
+  /* 1 if number is signalling */
   unsigned int signalling : 1;
+  /* 1 if number is canonical
+  All are generally used for handling cases in real.c */
   unsigned int canonical : 1;
+  /* unbiased exponent of the number */
   unsigned int uexp : EXP_BITS;
+  /* significand of the number */
   unsigned long sig[SIGSZ];
 };
 
@@ -499,6 +506,8 @@ extern void real_ceil (REAL_VALUE_TYPE *, format_helper,
 		       const REAL_VALUE_TYPE *);
 extern void real_round (REAL_VALUE_TYPE *, format_helper,
 			const REAL_VALUE_TYPE *);
+extern void real_roundeven (REAL_VALUE_TYPE *, format_helper,
+      const REAL_VALUE_TYPE *);
 
 /* Set the sign of R to the sign of X.  */
 extern void real_copysign (REAL_VALUE_TYPE *, const REAL_VALUE_TYPE *);

^ permalink raw reply	[flat|nested] 60+ messages in thread

* Re: About GSOC.
  2019-05-31 11:16                                                                     ` Nathan Sidwell
@ 2019-05-31 13:30                                                                       ` Eric Gallager
  2019-06-03  9:37                                                                         ` Tejas Joshi
  0 siblings, 1 reply; 60+ messages in thread
From: Eric Gallager @ 2019-05-31 13:30 UTC (permalink / raw)
  To: Nathan Sidwell
  Cc: Segher Boessenkool, Martin Jambor, Tejas Joshi, gcc, hubicka

On 5/31/19, Nathan Sidwell <nathan@acm.org> 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
>

^ permalink raw reply	[flat|nested] 60+ messages in thread

* Re: About GSOC.
  2019-05-30 21:38                                                                   ` Segher Boessenkool
  2019-05-31 10:11                                                                     ` Martin Jambor
@ 2019-05-31 11:16                                                                     ` Nathan Sidwell
  2019-05-31 13:30                                                                       ` Eric Gallager
  1 sibling, 1 reply; 60+ messages in thread
From: Nathan Sidwell @ 2019-05-31 11:16 UTC (permalink / raw)
  To: Segher Boessenkool, Martin Jambor; +Cc: Tejas Joshi, gcc, hubicka

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.
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

^ permalink raw reply	[flat|nested] 60+ messages in thread

* Re: About GSOC.
  2019-05-31 10:11                                                                     ` Martin Jambor
  2019-05-31 10:28                                                                       ` Tejas Joshi
@ 2019-05-31 11:13                                                                       ` Segher Boessenkool
  1 sibling, 0 replies; 60+ messages in thread
From: Segher Boessenkool @ 2019-05-31 11:13 UTC (permalink / raw)
  To: Martin Jambor; +Cc: Tejas Joshi, gcc, hubicka

On Fri, May 31, 2019 at 12:11:18PM +0200, Martin Jambor wrote:
> On Thu, May 30 2019, 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?
> 
> Sorry if I was not clear but I was definitely not suggesting that we
> change this (or anything).  I wrote that I was also surprised but
> believed that GCC was doing the correct thing.

Ah I see.  Yeah it tricked me too :-)

> Thanks for pointing out where exactly the standard says what has to be
> done though.

The text doesn't really leave room for extensions, either.


Segher

^ permalink raw reply	[flat|nested] 60+ messages in thread

* Re: About GSOC.
  2019-05-31 10:11                                                                     ` Martin Jambor
@ 2019-05-31 10:28                                                                       ` Tejas Joshi
  2019-06-03 16:38                                                                         ` Joseph Myers
  2019-05-31 11:13                                                                       ` Segher Boessenkool
  1 sibling, 1 reply; 60+ messages in thread
From: Tejas Joshi @ 2019-05-31 10:28 UTC (permalink / raw)
  To: gcc; +Cc: Martin Jambor, hubicka

[-- Attachment #1: Type: text/plain, Size: 2379 bytes --]

Hello.
The f128 suffix worked. Based on all the corrections you all pointed
out, I have created another patch. I think I took most of the things
under consideration but please mention if I missed anything. The
following test cases were inspected with this patch. I am not sure if
the second test case is supposed to be carried out like I did.

Thanks,
-Tejas

/* { dg-do link } */

extern int link_error (int);

#define TEST(FN, VALUE, RESULT) \
  if (__builtin_##FN (VALUE) != RESULT) link_error (__LINE__);

int
main (void)
{
  TEST(roundeven,  0, 0);
  TEST(roundeven,  0.5, 0);
  TEST(roundeven,  -0.5, 0);
  TEST(roundeven,  6, 6);
  TEST(roundeven,  -8, -8);
  TEST(roundeven,  2.5, 2);
  TEST(roundeven,  3.5, 4);
  TEST(roundeven,  -1.5, -2);
  TEST(roundeven,  3.499, 3);
  TEST(roundeven,  3.501, 4);

  return 0;
}

second test case :

/* { dg-do link } */
/* { dg-add-options float128 } */
/* { dg-require-effective-target float128 } */

extern int link_error (int);

#define TEST(FN, VALUE, RESULT) \
  if (__builtin_##FN (VALUE) != RESULT) link_error (__LINE__);

int
main (void)
{
  TEST(roundevenf128,  (0x1p64+0.5), (0x1p64));

  return 0;
}

On Fri, 31 May 2019 at 15:41, Martin Jambor <mjambor@suse.cz> wrote:
>
> On Thu, May 30 2019, 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?
>
> Sorry if I was not clear but I was definitely not suggesting that we
> change this (or anything).  I wrote that I was also surprised but
> believed that GCC was doing the correct thing.
>
> Thanks for pointing out where exactly the standard says what has to be
> done though.
>
> Martin

[-- Attachment #2: roundeven.patch --]
[-- Type: text/x-patch, Size: 7073 bytes --]

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_const_logb (result, arg, format);
 
@@ -854,6 +863,10 @@ fold_const_call_ss (wide_int *result, combined_fn fn,
       return fold_const_conversion (result, real_round, arg,
 				    precision, format);
 
+    CASE_CFN_ROUNDEVEN:
+    CASE_CFN_ROUNDEVEN_FN:
+      return fold_const_conversion (result, real_roundeven, arg, precision, format);
+
     CASE_CFN_IRINT:
     CASE_CFN_LRINT:
     CASE_CFN_LLRINT:
diff --git a/gcc/fold-const.c b/gcc/fold-const.c
index 59cedeafd71..ab96f197d5f 100644
--- a/gcc/fold-const.c
+++ b/gcc/fold-const.c
@@ -329,6 +329,8 @@ negate_mathfn_p (combined_fn fn)
     CASE_CFN_LLROUND:
     CASE_CFN_LROUND:
     CASE_CFN_ROUND:
+    CASE_CFN_ROUNDEVEN:
+    CASE_CFN_ROUNDEVEN_FN:
     CASE_CFN_SIN:
     CASE_CFN_SINH:
     CASE_CFN_TAN:
@@ -13060,6 +13062,8 @@ tree_call_nonnegative_warnv_p (tree type, combined_fn fn, tree arg0, tree arg1,
     CASE_CFN_RINT_FN:
     CASE_CFN_ROUND:
     CASE_CFN_ROUND_FN:
+    CASE_CFN_ROUNDEVEN:
+    CASE_CFN_ROUNDEVEN_FN:
     CASE_CFN_SCALB:
     CASE_CFN_SCALBLN:
     CASE_CFN_SCALBN:
@@ -13583,6 +13587,8 @@ integer_valued_real_call_p (combined_fn fn, tree arg0, tree arg1, int depth)
     CASE_CFN_RINT_FN:
     CASE_CFN_ROUND:
     CASE_CFN_ROUND_FN:
+    CASE_CFN_ROUNDEVEN:
+    CASE_CFN_ROUNDEVEN_FN:
     CASE_CFN_TRUNC:
     CASE_CFN_TRUNC_FN:
       return true;
diff --git a/gcc/real.c b/gcc/real.c
index f822ae82d61..541fa6b6e43 100644
--- a/gcc/real.c
+++ b/gcc/real.c
@@ -5010,6 +5010,80 @@ real_round (REAL_VALUE_TYPE *r, format_helper fmt,
     real_convert (r, fmt, r);
 }
 
+/* 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;
+
+  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;
+}
+
+/* Return true if R is halfway between two integers, else return false. */
+
+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);
+
+    if (((r->sig[SIGSZ-1] & temp) != 0) && ((r->sig[SIGSZ-1] & (temp-1)) == 0))
+      return true;
+    else
+      return false;
+  }
+
+  else if (REAL_EXP (r) < SIGNIFICAND_BITS)
+  {
+    unsigned int n = SIGNIFICAND_BITS - REAL_EXP (r);
+    int i, w = n / HOST_BITS_PER_LONG;
+
+    for (i = 0; i < w; ++i)
+    {
+      if (r->sig[i] != 0)
+        return false;
+    }
+
+    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;
+  }
+  return false;
+}
+
+/* Round X to nearest integer, rounding halfway cases towards even. */
+
+void
+real_roundeven (REAL_VALUE_TYPE *r, format_helper fmt,
+		const REAL_VALUE_TYPE *x)
+{
+  if (is_halfway_below (x))
+  {
+    do_add (r, x, &dconsthalf, x->sign);
+    if (!is_even (r))
+      do_add (r, r, &dconstm1, x->sign);
+  }
+  else
+    real_round (r, fmt, x);
+}
+
 /* Set the sign of R to the sign of X.  */
 
 void
diff --git a/gcc/real.h b/gcc/real.h
index 0ce42565708..ebe66d234af 100644
--- a/gcc/real.h
+++ b/gcc/real.h
@@ -41,11 +41,18 @@ struct GTY(()) real_value {
      sure they're packed together, otherwise REAL_VALUE_TYPE_SIZE will
      be miscomputed.  */
   unsigned int /* ENUM_BITFIELD (real_value_class) */ cl : 2;
+  /* 1 if number is decimal floating point */
   unsigned int decimal : 1;
+  /* 1 if number is negative */
   unsigned int sign : 1;
+  /* 1 if number is signalling */
   unsigned int signalling : 1;
+  /* 1 if number is canonical
+  All are generally used for handling cases in real.c */
   unsigned int canonical : 1;
+  /* unbiased exponent of the number */
   unsigned int uexp : EXP_BITS;
+  /* significand of the number */
   unsigned long sig[SIGSZ];
 };
 
@@ -499,6 +506,8 @@ extern void real_ceil (REAL_VALUE_TYPE *, format_helper,
 		       const REAL_VALUE_TYPE *);
 extern void real_round (REAL_VALUE_TYPE *, format_helper,
 			const REAL_VALUE_TYPE *);
+extern void real_roundeven (REAL_VALUE_TYPE *, format_helper,
+      const REAL_VALUE_TYPE *);
 
 /* Set the sign of R to the sign of X.  */
 extern void real_copysign (REAL_VALUE_TYPE *, const REAL_VALUE_TYPE *);

^ permalink raw reply	[flat|nested] 60+ messages in thread

* Re: About GSOC.
  2019-05-30 21:38                                                                   ` Segher Boessenkool
@ 2019-05-31 10:11                                                                     ` Martin Jambor
  2019-05-31 10:28                                                                       ` Tejas Joshi
  2019-05-31 11:13                                                                       ` Segher Boessenkool
  2019-05-31 11:16                                                                     ` Nathan Sidwell
  1 sibling, 2 replies; 60+ messages in thread
From: Martin Jambor @ 2019-05-31 10:11 UTC (permalink / raw)
  To: Segher Boessenkool; +Cc: Tejas Joshi, gcc, hubicka

On Thu, May 30 2019, 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?

Sorry if I was not clear but I was definitely not suggesting that we
change this (or anything).  I wrote that I was also surprised but
believed that GCC was doing the correct thing.

Thanks for pointing out where exactly the standard says what has to be
done though.

Martin

^ permalink raw reply	[flat|nested] 60+ messages in thread

* Re: About GSOC.
  2019-05-30 17:08                                                                 ` Martin Jambor
@ 2019-05-30 21:38                                                                   ` Segher Boessenkool
  2019-05-31 10:11                                                                     ` Martin Jambor
  2019-05-31 11:16                                                                     ` Nathan Sidwell
  0 siblings, 2 replies; 60+ messages in thread
From: Segher Boessenkool @ 2019-05-30 21:38 UTC (permalink / raw)
  To: Martin Jambor; +Cc: Tejas Joshi, gcc, hubicka

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?


Segher

^ permalink raw reply	[flat|nested] 60+ messages in thread

* Re: About GSOC.
  2019-05-29 18:45                                                               ` Tejas Joshi
@ 2019-05-30 17:08                                                                 ` Martin Jambor
  2019-05-30 21:38                                                                   ` Segher Boessenkool
  0 siblings, 1 reply; 60+ messages in thread
From: Martin Jambor @ 2019-05-30 17:08 UTC (permalink / raw)
  To: Tejas Joshi, gcc; +Cc: hubicka

Hi,

On Thu, May 30 2019, Tejas Joshi wrote:
> Hello.
> I tried to check the values for significand words using _Float128
> using a test program with value larger than 64 bit.
> Test program :
>
> int main ()
> {
>     _Float128 x = 18446744073709551617.5;   (i.e. 2^64 + 1.5 which is
> certainly longer than 64-bit)
>     _Float128 y = __builtin_roundf128 (x);
> }

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.

>
> The lower words of significand (sig[1] and sig[0] for 64-bit system)
> are still being zero. I haven't included the roundevenf128 yet but
> inspecting this on real_round function.

I figured out what was going on when I realized that in your testcase,
sig[0] was equal to 0x8000000000000000 and so some precision has been
lost.  Then it was easy to guess that it was because it was represented
in a narrower type.

Hope this helps,

Martin

^ permalink raw reply	[flat|nested] 60+ messages in thread

* Re: About GSOC.
  2019-05-29 11:21                                                             ` Tejas Joshi
@ 2019-05-29 18:45                                                               ` Tejas Joshi
  2019-05-30 17:08                                                                 ` Martin Jambor
  0 siblings, 1 reply; 60+ messages in thread
From: Tejas Joshi @ 2019-05-29 18:45 UTC (permalink / raw)
  To: gcc; +Cc: Martin Jambor, hubicka

Hello.
I tried to check the values for significand words using _Float128
using a test program with value larger than 64 bit.
Test program :

int main ()
{
    _Float128 x = 18446744073709551617.5;   (i.e. 2^64 + 1.5 which is
certainly longer than 64-bit)
    _Float128 y = __builtin_roundf128 (x);
}

The lower words of significand (sig[1] and sig[0] for 64-bit system)
are still being zero. I haven't included the roundevenf128 yet but
inspecting this on real_round function.
Am I missing something here?

Thanks.


On Wed, 29 May 2019 at 16:56, Tejas Joshi <tejasjoshi9673@gmail.com> wrote:
>
> Hello.
> My exams are finally over and I have started to address these points now. I intend to give my most of the time cause of holidays and will try to consider most of the cases for the patch this time .
>
> Thanks,
> -Tejas
>
> On Tue, 21 May 2019 at 03:18, Joseph Myers <joseph@codesourcery.com> wrote:
>>
>> On Mon, 20 May 2019, Martin Jambor wrote:
>>
>> > in addition to the things already pointed out by Joseph, I have the
>> > following comments.  But as Joseph has already pointed out, you should
>> > also test your patch on __float128 types, so please make sure your code
>> > gets invoked and works for something like:
>> >
>> >     if (__builtin_roundevenf128 (0x1p64q+0.5) != (0x1p64q))
>> >       link_error (__LINE__);
>>
>>  ... but with the f128 constant suffix not q, so it works on more
>> architectures (all those with _Float128 support, not just those with older
>> __float128 support).
>>
>> > > +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)
>> >
>> > ...and for the code to trigger for __builtin_roundevenf128 you have to
>> > define this builtin function too.  The easiest way is to do it in the
>> > same way it is done for BUILTIN_ROUND and many other functions, i.e. use
>> > DEF_EXT_LIB_FLOATN_NX_BUILTINS.
>>
>> Also note that TS 18661-1 has been merged into C2X.  I haven't yet updated
>> glibc headers to reflect this, but this means a new DEF_C2X_BUILTIN should
>> be added similar to DEF_C11_BUILTIN, and used for those three new
>> functions, instead of DEF_EXT_LIB_BUILTIN.  (And for the strdup and
>> strndup built-in functions, also added to C2X, but that's independent of
>> the present project.)
>>
>> --
>> Joseph S. Myers
>> joseph@codesourcery.com

^ permalink raw reply	[flat|nested] 60+ messages in thread

* Re: About GSOC.
  2019-05-20 21:48                                                           ` Joseph Myers
@ 2019-05-29 11:21                                                             ` Tejas Joshi
  2019-05-29 18:45                                                               ` Tejas Joshi
  0 siblings, 1 reply; 60+ messages in thread
From: Tejas Joshi @ 2019-05-29 11:21 UTC (permalink / raw)
  To: gcc; +Cc: Martin Jambor, hubicka

Hello.
My exams are finally over and I have started to address these points now. I
intend to give my most of the time cause of holidays and will try to
consider most of the cases for the patch this time .

Thanks,
-Tejas

On Tue, 21 May 2019 at 03:18, Joseph Myers <joseph@codesourcery.com> wrote:

> On Mon, 20 May 2019, Martin Jambor wrote:
>
> > in addition to the things already pointed out by Joseph, I have the
> > following comments.  But as Joseph has already pointed out, you should
> > also test your patch on __float128 types, so please make sure your code
> > gets invoked and works for something like:
> >
> >     if (__builtin_roundevenf128 (0x1p64q+0.5) != (0x1p64q))
> >       link_error (__LINE__);
>
>  ... but with the f128 constant suffix not q, so it works on more
> architectures (all those with _Float128 support, not just those with older
> __float128 support).
>
> > > +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)
> >
> > ...and for the code to trigger for __builtin_roundevenf128 you have to
> > define this builtin function too.  The easiest way is to do it in the
> > same way it is done for BUILTIN_ROUND and many other functions, i.e. use
> > DEF_EXT_LIB_FLOATN_NX_BUILTINS.
>
> Also note that TS 18661-1 has been merged into C2X.  I haven't yet updated
> glibc headers to reflect this, but this means a new DEF_C2X_BUILTIN should
> be added similar to DEF_C11_BUILTIN, and used for those three new
> functions, instead of DEF_EXT_LIB_BUILTIN.  (And for the strdup and
> strndup built-in functions, also added to C2X, but that's independent of
> the present project.)
>
> --
> Joseph S. Myers
> joseph@codesourcery.com
>

^ permalink raw reply	[flat|nested] 60+ messages in thread

* Re: About GSOC.
  2019-05-20 15:49                                                         ` Martin Jambor
@ 2019-05-20 21:48                                                           ` Joseph Myers
  2019-05-29 11:21                                                             ` Tejas Joshi
  0 siblings, 1 reply; 60+ messages in thread
From: Joseph Myers @ 2019-05-20 21:48 UTC (permalink / raw)
  To: Martin Jambor; +Cc: Tejas Joshi, gcc

On Mon, 20 May 2019, Martin Jambor wrote:

> in addition to the things already pointed out by Joseph, I have the
> following comments.  But as Joseph has already pointed out, you should
> also test your patch on __float128 types, so please make sure your code
> gets invoked and works for something like:
> 
>     if (__builtin_roundevenf128 (0x1p64q+0.5) != (0x1p64q))
>       link_error (__LINE__);

 ... but with the f128 constant suffix not q, so it works on more 
architectures (all those with _Float128 support, not just those with older 
__float128 support).

> > +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)
> 
> ...and for the code to trigger for __builtin_roundevenf128 you have to
> define this builtin function too.  The easiest way is to do it in the
> same way it is done for BUILTIN_ROUND and many other functions, i.e. use
> DEF_EXT_LIB_FLOATN_NX_BUILTINS.

Also note that TS 18661-1 has been merged into C2X.  I haven't yet updated 
glibc headers to reflect this, but this means a new DEF_C2X_BUILTIN should 
be added similar to DEF_C11_BUILTIN, and used for those three new 
functions, instead of DEF_EXT_LIB_BUILTIN.  (And for the strdup and 
strndup built-in functions, also added to C2X, but that's independent of 
the present project.)

-- 
Joseph S. Myers
joseph@codesourcery.com

^ permalink raw reply	[flat|nested] 60+ messages in thread

* Re: About GSOC.
  2019-05-08  7:30                                                       ` Tejas Joshi
  2019-05-08 14:21                                                         ` Tejas Joshi
  2019-05-09 16:55                                                         ` Joseph Myers
@ 2019-05-20 15:49                                                         ` Martin Jambor
  2019-05-20 21:48                                                           ` Joseph Myers
  2 siblings, 1 reply; 60+ messages in thread
From: Martin Jambor @ 2019-05-20 15:49 UTC (permalink / raw)
  To: Tejas Joshi, gcc

Hello Tejas,

On Wed, May 08 2019, Tejas Joshi wrote:
> Hello.
> I can't figure out from the documentation how to add test cases in the
> testsuite and inspect the results. How can I do that? Although, Taking
> the mentioned conditions under consideration, I have made another
> patch, attached.

in addition to the things already pointed out by Joseph, I have the
following comments.  But as Joseph has already pointed out, you should
also test your patch on __float128 types, so please make sure your code
gets invoked and works for something like:

    if (__builtin_roundevenf128 (0x1p64q+0.5) != (0x1p64q))
      link_error (__LINE__);


> diff --git a/gcc/builtins.def b/gcc/builtins.def
> index ef89729fd0c..e1d593a8765 100644
> --- a/gcc/builtins.def
> +++ b/gcc/builtins.def
> @@ -542,6 +542,9 @@ 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)

...and for the code to trigger for __builtin_roundevenf128 you have to
define this builtin function too.  The easiest way is to do it in the
same way it is done for BUILTIN_ROUND and many other functions, i.e. use
DEF_EXT_LIB_FLOATN_NX_BUILTINS.


> diff --git a/gcc/fold-const-call.c b/gcc/fold-const-call.c
> index 06a420601c0..7eafd91e9a2 100644
> --- a/gcc/fold-const-call.c
> +++ b/gcc/fold-const-call.c
> @@ -792,6 +792,14 @@ fold_const_call_ss (real_value *result, combined_fn fn,
>  	}
>        return false;
>  
> +    case CFN_BUILT_IN_ROUNDEVEN:

If you look at other cases in this switch statement, they all use
CASE_CFN_* macros.  These the get expanded to all the type variants of
the builting function, so please do the same thing and replace the case
with

    CASE_CFN_ROUNDEVEN:
    CASE_CFN_ROUNDEVEN_FN:


> +      if (!REAL_VALUE_ISNAN (*arg) || !flag_errno_math)
> +  {

Make sure you set your editor to follow the GNU coding style.  The
horizontal position of the curly braces here is incorrect.  Insisting on
coding style details may sound like excessive nit-picking but in the
long run it makes the sources much more readable.

> +    real_roundeven (result, format, arg);
> +    return true;
> +  }
> +      return false;
> +
>      CASE_CFN_LOGB:
>        return fold_const_logb (result, arg, format);
>  
> @@ -854,6 +862,9 @@ fold_const_call_ss (wide_int *result, combined_fn fn,
>        return fold_const_conversion (result, real_round, arg,
>  				    precision, format);
>  
> +    case CFN_BUILT_IN_ROUNDEVEN:

the comment about CASE_CFN_* macros applies here as well.

> +      return fold_const_conversion (result, real_roundeven, arg, precision, format);
> +
>      CASE_CFN_IRINT:
>      CASE_CFN_LRINT:
>      CASE_CFN_LLRINT:
> diff --git a/gcc/fold-const.c b/gcc/fold-const.c
> index 59cedeafd71..30c409e95bf 100644
> --- a/gcc/fold-const.c
> +++ b/gcc/fold-const.c
> @@ -329,6 +329,7 @@ negate_mathfn_p (combined_fn fn)
>      CASE_CFN_LLROUND:
>      CASE_CFN_LROUND:
>      CASE_CFN_ROUND:
> +    CASE_CFN_ROUNDEVEN:

and CASE_CFN_ROUNDEVEN_FN:

>      CASE_CFN_SIN:
>      CASE_CFN_SINH:
>      CASE_CFN_TAN:
> @@ -13060,6 +13061,8 @@ tree_call_nonnegative_warnv_p (tree type, combined_fn fn, tree arg0, tree arg1,
>      CASE_CFN_RINT_FN:
>      CASE_CFN_ROUND:
>      CASE_CFN_ROUND_FN:
> +    CASE_CFN_ROUNDEVEN:
> +    CASE_CFN_ROUNDEVEN_FN:
>      CASE_CFN_SCALB:
>      CASE_CFN_SCALBLN:
>      CASE_CFN_SCALBN:
> @@ -13583,6 +13586,8 @@ integer_valued_real_call_p (combined_fn fn, tree arg0, tree arg1, int depth)
>      CASE_CFN_RINT_FN:
>      CASE_CFN_ROUND:
>      CASE_CFN_ROUND_FN:
> +    CASE_CFN_ROUNDEVEN:
> +    CASE_CFN_ROUNDEVEN_FN:
>      CASE_CFN_TRUNC:
>      CASE_CFN_TRUNC_FN:
>        return true;
> diff --git a/gcc/real.c b/gcc/real.c
> index f822ae82d61..045dc758048 100644
> --- a/gcc/real.c
> +++ b/gcc/real.c
> @@ -5010,6 +5010,53 @@ real_round (REAL_VALUE_TYPE *r, format_helper fmt,
>      real_convert (r, fmt, r);
>  }
>  
> +/* Return true if integer part of R is even, else return false. */

If the function is supposed to work only on integer values (encoded as
REAL_VALUE_TYPE) then please write that into the function comment.

> +
> +bool
> +is_even (REAL_VALUE_TYPE *r)
> +{
> +  unsigned int n = SIGNIFICAND_BITS - REAL_EXP (r);

Otherwise, if you really wanted to make it work on integer parts of any
real number, this is clearly wrong for any value smaller than 0.5
(i.e. when REAL_EXP (r) is negative).

> +
> +  unsigned long num = ((unsigned long)1 << (n % HOST_BITS_PER_LONG));
> +
> +  if ((r->sig[SIGSZ-1] & num) == 0)
> +    return true;

I don't think you can expect that the digit you are looking for is in
the last element of sig.

> +  return false;
> +}
> +
> +/* Return true if R is halfway between two integers, else return false. */
> +
> +bool
> +is_halfway_below (const REAL_VALUE_TYPE *r)
> +{
> +  if (r->sig[0] != 0 && r->sig[1] != 0)
> +    return false;

If you try this code on the example I gave at the beginning of my email,
you will see that this condition is not met.


> +
> +  unsigned int n = SIGNIFICAND_BITS - REAL_EXP (r);

Joseph has already pointed out that you can and should bail out if
REAL_EXP (r) is negative, because then the number is in the internal
[-0.25, 0.25] or when it is too big because then it is already an
integer.

> +
> +  unsigned long num = ((unsigned long)1 << ((n - 1) % HOST_BITS_PER_LONG));
> +
> +  if (((r->sig[SIGSZ-1] & num) != 0) && ((r->sig[SIGSZ-1] & (num-1)) == 0))
> +    return true;

And he also pointed out this is wrong too, just think how 0x1p64q+0.5,
i.e. 2^64+ 2^(-1) is represented.  It just cannot fit into one 64-bit long.

Nevertheless, you are definitely on the right track and these things can
be confusing at first, so I'm looking forward to the next iteration of
the patch.

Martin

^ permalink raw reply	[flat|nested] 60+ messages in thread

* Re: About GSOC.
  2019-05-08 14:21                                                         ` Tejas Joshi
@ 2019-05-09 17:01                                                           ` Joseph Myers
  0 siblings, 0 replies; 60+ messages in thread
From: Joseph Myers @ 2019-05-09 17:01 UTC (permalink / raw)
  To: Tejas Joshi; +Cc: gcc

On Wed, 8 May 2019, Tejas Joshi wrote:

> Is this the way test cases should be added and checked?

Yes, that's appropriate for tests of roundeven optimization for constant 
arguments.

When you get onto testing roundevenf128 (to cover various cases with 
113-bit precision), you'll need to make those tests appropriately 
conditional on _Float128 support being available - either use "#ifdef 
__FLT128_MAX__" within the test, or have a separate test for those cases 
and use

/* { dg-add-options float128 } */
/* { dg-require-effective-target float128 } */

in that test.  ({ dg-add-options float128 } allows _Float128 tests to be 
run in configurations that only support _Float128 with some command-line 
options.)

-- 
Joseph S. Myers
joseph@codesourcery.com

^ permalink raw reply	[flat|nested] 60+ messages in thread

* Re: About GSOC.
  2019-05-08  7:30                                                       ` Tejas Joshi
  2019-05-08 14:21                                                         ` Tejas Joshi
@ 2019-05-09 16:55                                                         ` Joseph Myers
  2019-05-20 15:49                                                         ` Martin Jambor
  2 siblings, 0 replies; 60+ messages in thread
From: Joseph Myers @ 2019-05-09 16:55 UTC (permalink / raw)
  To: Tejas Joshi; +Cc: gcc

On Wed, 8 May 2019, Tejas Joshi wrote:

> Hello.
> I can't figure out from the documentation how to add test cases in the
> testsuite and inspect the results. How can I do that? Although, Taking
> the mentioned conditions under consideration, I have made another
> patch, attached.

This patch still has problems.  You can't assume that all of sig[0] and 
sig[1] are below the 0.5 bit.  You have to allow for the 0.5 bit possibly 
being in any word of the significand, not necessarily the SIGSZ - 1 word, 
meaning you have to loop over all words of the significand.  A word 
completely below the 0.5 bit can just be checked for being 0.  A word 
containing the 0.5 bit needs checking both the bits in that word below the 
0.5 bit, and checking that the 0.5 bit is 1.

REAL_EXP (r) could be bigger than SIGNIFICAND_BITS, so you need to handle 
that case (automatically an integer) rather than computing a spurious very 
large n.

This should illustrate testcases that need adding, to cover the various 
cases of where the 0.5 bit is and where any nonzero bit below it might be 
- my suggestion is to add such tests, make sure they fail with your 
existing patch, and only then fix the implementation to make them pass.  
For some of those tests, you'll need to test long double or _Float128.  
(Use DEF_EXT_LIB_FLOATN_NX_BUILTINS in builtins.def to add the built-in 
function variants such as roundevenf128; existing round-to-integer 
functions already have such variants.)

-- 
Joseph S. Myers
joseph@codesourcery.com

^ permalink raw reply	[flat|nested] 60+ messages in thread

* Re: About GSOC.
  2019-05-08  7:30                                                       ` Tejas Joshi
@ 2019-05-08 14:21                                                         ` Tejas Joshi
  2019-05-09 17:01                                                           ` Joseph Myers
  2019-05-09 16:55                                                         ` Joseph Myers
  2019-05-20 15:49                                                         ` Martin Jambor
  2 siblings, 1 reply; 60+ messages in thread
From: Tejas Joshi @ 2019-05-08 14:21 UTC (permalink / raw)
  To: gcc

Hello.
I have added a test case in the testsuite referring to an existing one
as "builtin-rounding-1.c" in the /testsuite/gcc.dg/torture directory.
As follows :

/* { dg-do link } */

extern int link_error (int);

#define TEST(FN, VALUE, RESULT) \
  if (__builtin_##FN (VALUE) != RESULT) link_error (__LINE__);

int
main (void)
{
  TEST(roundeven,  0, 0);
  TEST(roundeven,  0.5, 0);
  TEST(roundeven,  -0.5, 0);
  TEST(roundeven,  6, 6);
  TEST(roundeven,  -8, -8);
  TEST(roundeven,  2.5, 2);
  TEST(roundeven,  3.5, 4);
  TEST(roundeven,  -1.5, -2);
  TEST(roundeven,  3.499, 3);
  TEST(roundeven,  3.501, 4);

  return 0;
}

After checking for test case in the build directory using :
$ make check-gcc RUNTESTFLAGS="dg-torture.exp=builtin-round-roundeven.c"
test does not FAIL. Though, it FAILs for intentionally giving wrong RESULT.

Ex : TEST(roundeven,  3.501, 3);
Should fail I believe and thus giving output as:
FAIL: gcc.dg/torture/builtin-round-roundeven.c   -O0  (test for excess errors)
FAIL: gcc.dg/torture/builtin-round-roundeven.c   -O1  (test for excess errors)
FAIL: gcc.dg/torture/builtin-round-roundeven.c   -O2  (test for excess errors)
FAIL: gcc.dg/torture/builtin-round-roundeven.c   -O3 -g  (test for
excess errors)
FAIL: gcc.dg/torture/builtin-round-roundeven.c   -Os  (test for excess errors)
FAIL: gcc.dg/torture/builtin-round-roundeven.c   -O2 -flto
-fno-use-linker-plugin -flto-partition=none  (test for excess errors)
FAIL: gcc.dg/torture/builtin-round-roundeven.c   -O2 -flto
-fuse-linker-plugin -fno-fat-lto-objects  (test for excess errors)

Is this the way test cases should be added and checked?

Thanks.

On Wed, 8 May 2019 at 13:05, Tejas Joshi <tejasjoshi9673@gmail.com> wrote:
>
> Hello.
> I can't figure out from the documentation how to add test cases in the
> testsuite and inspect the results. How can I do that? Although, Taking
> the mentioned conditions under consideration, I have made another
> patch, attached.
>
> Thanks,
> -Tejas
>
>
> On Wed, 8 May 2019 at 09:01, Tejas Joshi <tejasjoshi9673@gmail.com> wrote:
> >
> > I should have taken all the test cases into consideration. Fool of me. I will try to make changes taking all the test cases into consideration along with the testsuite.
> > Thanks.
> >
> > On Wed, 8 May 2019 at 02:31, Joseph Myers <joseph@codesourcery.com> wrote:
> >>
> >> On Wed, 8 May 2019, Tejas Joshi wrote:
> >>
> >> > Hello.
> >> > As per my understanding, 3.5 would be represented in GCC as follows :
> >> > r->uexp  = 2
> >> > and
> >> > r->sig[2] = 1110000....00 in binary 64 bit. (first 2 bits being 3 and
> >> > following 1000....0 being 0.5, which later only happens for halfway cases)
> >> > So, if we clear out the significand part and the immediate bit to the right
> >> > which represent 0.5, the entire significand would become 0 due to bit-wise
> >> > ANDing.
> >> >
> >> > > +  tempsig[w] &= (((unsigned long)1 << ((n % HOST_BITS_PER_LONG) - 1)) -
> >> > > 1);
> >> > >
> >> >
> >> > That is what the following line intend to do. The clearing part would
> >> > change the significand, that's why significand was copied to a temporary
> >>
> >> That much is fine.  My issues are two other things:
> >>
> >> * The function would wrongly return true for 3, not just for 3.5, because
> >> it never checks the bit representing 0.5.  (If you don't care what it
> >> returns for 3, see my previous point about every function needing a
> >> comment defining its semantics.  Without such a comment, I have to guess,
> >> and my guess here is that the function should return true for 3.5 but
> >> false for 3 and for 3.5000...0001.)
> >>
> >> * The function would wrongly return true for 3.5000...0001, if there are
> >> enough 0s that all those low bits in sig[2] are 0, but some low bits in
> >> sig[1] or sig[0] are not 0.
> >>
> >> And also:
> >>
> >> * You should never need to modify parts of (a copy of) the significand in
> >> place.  Compare low parts of the significand (masked as needed) with 0.
> >> If not 0, just return false.  Likewise for comparing the 0.5 bit with 1.
> >> It's not that copying and modifying in place results in incorrect logic,
> >> it's simply excessively convoluted compared to things like:
> >>
> >>   if ((something & mask) != 0)
> >>     return false
> >>
> >> (the function is probably twice as long as necessary because of that
> >> copying).
> >>
> >> > array for checking. This logic is inspired by the clear_significand_below
> >> > function. Or isn't this the way it was meant to be implemented? Also, why
> >> > unsigned long sig[SIGSZ] has to be an array?
> >>
> >> What would it be other than an array?  It can't be a single scalar because
> >> floating-point significands may be longer than any supported integer type
> >> on the host (remember the IEEE binary128 case).  And if you made it a
> >> sequence of individually named fields, a load of loops would need to be
> >> manually unrolled, which would be much more error prone and hard to read.
> >>
> >> --
> >> Joseph S. Myers
> >> joseph@codesourcery.com

^ permalink raw reply	[flat|nested] 60+ messages in thread

* Re: About GSOC.
  2019-05-08  3:27                                                     ` Tejas Joshi
@ 2019-05-08  7:30                                                       ` Tejas Joshi
  2019-05-08 14:21                                                         ` Tejas Joshi
                                                                           ` (2 more replies)
  0 siblings, 3 replies; 60+ messages in thread
From: Tejas Joshi @ 2019-05-08  7:30 UTC (permalink / raw)
  To: gcc

[-- Attachment #1: Type: text/plain, Size: 3175 bytes --]

Hello.
I can't figure out from the documentation how to add test cases in the
testsuite and inspect the results. How can I do that? Although, Taking
the mentioned conditions under consideration, I have made another
patch, attached.

Thanks,
-Tejas


On Wed, 8 May 2019 at 09:01, Tejas Joshi <tejasjoshi9673@gmail.com> wrote:
>
> I should have taken all the test cases into consideration. Fool of me. I will try to make changes taking all the test cases into consideration along with the testsuite.
> Thanks.
>
> On Wed, 8 May 2019 at 02:31, Joseph Myers <joseph@codesourcery.com> wrote:
>>
>> On Wed, 8 May 2019, Tejas Joshi wrote:
>>
>> > Hello.
>> > As per my understanding, 3.5 would be represented in GCC as follows :
>> > r->uexp  = 2
>> > and
>> > r->sig[2] = 1110000....00 in binary 64 bit. (first 2 bits being 3 and
>> > following 1000....0 being 0.5, which later only happens for halfway cases)
>> > So, if we clear out the significand part and the immediate bit to the right
>> > which represent 0.5, the entire significand would become 0 due to bit-wise
>> > ANDing.
>> >
>> > > +  tempsig[w] &= (((unsigned long)1 << ((n % HOST_BITS_PER_LONG) - 1)) -
>> > > 1);
>> > >
>> >
>> > That is what the following line intend to do. The clearing part would
>> > change the significand, that's why significand was copied to a temporary
>>
>> That much is fine.  My issues are two other things:
>>
>> * The function would wrongly return true for 3, not just for 3.5, because
>> it never checks the bit representing 0.5.  (If you don't care what it
>> returns for 3, see my previous point about every function needing a
>> comment defining its semantics.  Without such a comment, I have to guess,
>> and my guess here is that the function should return true for 3.5 but
>> false for 3 and for 3.5000...0001.)
>>
>> * The function would wrongly return true for 3.5000...0001, if there are
>> enough 0s that all those low bits in sig[2] are 0, but some low bits in
>> sig[1] or sig[0] are not 0.
>>
>> And also:
>>
>> * You should never need to modify parts of (a copy of) the significand in
>> place.  Compare low parts of the significand (masked as needed) with 0.
>> If not 0, just return false.  Likewise for comparing the 0.5 bit with 1.
>> It's not that copying and modifying in place results in incorrect logic,
>> it's simply excessively convoluted compared to things like:
>>
>>   if ((something & mask) != 0)
>>     return false
>>
>> (the function is probably twice as long as necessary because of that
>> copying).
>>
>> > array for checking. This logic is inspired by the clear_significand_below
>> > function. Or isn't this the way it was meant to be implemented? Also, why
>> > unsigned long sig[SIGSZ] has to be an array?
>>
>> What would it be other than an array?  It can't be a single scalar because
>> floating-point significands may be longer than any supported integer type
>> on the host (remember the IEEE binary128 case).  And if you made it a
>> sequence of individually named fields, a load of loops would need to be
>> manually unrolled, which would be much more error prone and hard to read.
>>
>> --
>> Joseph S. Myers
>> joseph@codesourcery.com

[-- Attachment #2: roundeven.patch --]
[-- Type: text/x-patch, Size: 5121 bytes --]

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..e1d593a8765 100644
--- a/gcc/builtins.def
+++ b/gcc/builtins.def
@@ -542,6 +542,9 @@ 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)
diff --git a/gcc/fold-const-call.c b/gcc/fold-const-call.c
index 06a420601c0..7eafd91e9a2 100644
--- a/gcc/fold-const-call.c
+++ b/gcc/fold-const-call.c
@@ -792,6 +792,14 @@ fold_const_call_ss (real_value *result, combined_fn fn,
 	}
       return false;
 
+    case CFN_BUILT_IN_ROUNDEVEN:
+      if (!REAL_VALUE_ISNAN (*arg) || !flag_errno_math)
+  {
+    real_roundeven (result, format, arg);
+    return true;
+  }
+      return false;
+
     CASE_CFN_LOGB:
       return fold_const_logb (result, arg, format);
 
@@ -854,6 +862,9 @@ fold_const_call_ss (wide_int *result, combined_fn fn,
       return fold_const_conversion (result, real_round, arg,
 				    precision, format);
 
+    case CFN_BUILT_IN_ROUNDEVEN:
+      return fold_const_conversion (result, real_roundeven, arg, precision, format);
+
     CASE_CFN_IRINT:
     CASE_CFN_LRINT:
     CASE_CFN_LLRINT:
diff --git a/gcc/fold-const.c b/gcc/fold-const.c
index 59cedeafd71..30c409e95bf 100644
--- a/gcc/fold-const.c
+++ b/gcc/fold-const.c
@@ -329,6 +329,7 @@ negate_mathfn_p (combined_fn fn)
     CASE_CFN_LLROUND:
     CASE_CFN_LROUND:
     CASE_CFN_ROUND:
+    CASE_CFN_ROUNDEVEN:
     CASE_CFN_SIN:
     CASE_CFN_SINH:
     CASE_CFN_TAN:
@@ -13060,6 +13061,8 @@ tree_call_nonnegative_warnv_p (tree type, combined_fn fn, tree arg0, tree arg1,
     CASE_CFN_RINT_FN:
     CASE_CFN_ROUND:
     CASE_CFN_ROUND_FN:
+    CASE_CFN_ROUNDEVEN:
+    CASE_CFN_ROUNDEVEN_FN:
     CASE_CFN_SCALB:
     CASE_CFN_SCALBLN:
     CASE_CFN_SCALBN:
@@ -13583,6 +13586,8 @@ integer_valued_real_call_p (combined_fn fn, tree arg0, tree arg1, int depth)
     CASE_CFN_RINT_FN:
     CASE_CFN_ROUND:
     CASE_CFN_ROUND_FN:
+    CASE_CFN_ROUNDEVEN:
+    CASE_CFN_ROUNDEVEN_FN:
     CASE_CFN_TRUNC:
     CASE_CFN_TRUNC_FN:
       return true;
diff --git a/gcc/real.c b/gcc/real.c
index f822ae82d61..045dc758048 100644
--- a/gcc/real.c
+++ b/gcc/real.c
@@ -5010,6 +5010,53 @@ real_round (REAL_VALUE_TYPE *r, format_helper fmt,
     real_convert (r, fmt, r);
 }
 
+/* Return true if integer part of R is even, else return false. */
+
+bool
+is_even (REAL_VALUE_TYPE *r)
+{
+  unsigned int n = SIGNIFICAND_BITS - REAL_EXP (r);
+
+  unsigned long num = ((unsigned long)1 << (n % HOST_BITS_PER_LONG));
+
+  if ((r->sig[SIGSZ-1] & num) == 0)
+    return true;
+  return false;
+}
+
+/* Return true if R is halfway between two integers, else return false. */
+
+bool
+is_halfway_below (const REAL_VALUE_TYPE *r)
+{
+  if (r->sig[0] != 0 && r->sig[1] != 0)
+    return false;
+
+  unsigned int n = SIGNIFICAND_BITS - REAL_EXP (r);
+
+  unsigned long num = ((unsigned long)1 << ((n - 1) % HOST_BITS_PER_LONG));
+
+  if (((r->sig[SIGSZ-1] & num) != 0) && ((r->sig[SIGSZ-1] & (num-1)) == 0))
+    return true;
+  return false;
+}
+
+/* Round X to nearest integer, rounding halfway cases towards even. */
+
+void
+real_roundeven (REAL_VALUE_TYPE *r, format_helper fmt,
+		const REAL_VALUE_TYPE *x)
+{
+  if (is_halfway_below (x))
+  {
+    do_add (r, x, &dconsthalf, x->sign);
+    if (!is_even (r))
+      do_add (r, r, &dconstm1, x->sign);
+  }
+  else
+    real_round (r, fmt, x);
+}
+
 /* Set the sign of R to the sign of X.  */
 
 void
diff --git a/gcc/real.h b/gcc/real.h
index 0ce42565708..10898eae79e 100644
--- a/gcc/real.h
+++ b/gcc/real.h
@@ -499,6 +499,8 @@ extern void real_ceil (REAL_VALUE_TYPE *, format_helper,
 		       const REAL_VALUE_TYPE *);
 extern void real_round (REAL_VALUE_TYPE *, format_helper,
 			const REAL_VALUE_TYPE *);
+extern void real_roundeven (REAL_VALUE_TYPE *, format_helper,
+      const REAL_VALUE_TYPE *);
 
 /* Set the sign of R to the sign of X.  */
 extern void real_copysign (REAL_VALUE_TYPE *, const REAL_VALUE_TYPE *);

^ permalink raw reply	[flat|nested] 60+ messages in thread

* Re: About GSOC.
  2019-05-07 21:01                                                   ` Joseph Myers
@ 2019-05-08  3:27                                                     ` Tejas Joshi
  2019-05-08  7:30                                                       ` Tejas Joshi
  0 siblings, 1 reply; 60+ messages in thread
From: Tejas Joshi @ 2019-05-08  3:27 UTC (permalink / raw)
  To: gcc

I should have taken all the test cases into consideration. Fool of me. I
will try to make changes taking all the test cases into consideration along
with the testsuite.
Thanks.

On Wed, 8 May 2019 at 02:31, Joseph Myers <joseph@codesourcery.com> wrote:

> On Wed, 8 May 2019, Tejas Joshi wrote:
>
> > Hello.
> > As per my understanding, 3.5 would be represented in GCC as follows :
> > r->uexp  = 2
> > and
> > r->sig[2] = 1110000....00 in binary 64 bit. (first 2 bits being 3 and
> > following 1000....0 being 0.5, which later only happens for halfway
> cases)
> > So, if we clear out the significand part and the immediate bit to the
> right
> > which represent 0.5, the entire significand would become 0 due to
> bit-wise
> > ANDing.
> >
> > > +  tempsig[w] &= (((unsigned long)1 << ((n % HOST_BITS_PER_LONG) - 1))
> -
> > > 1);
> > >
> >
> > That is what the following line intend to do. The clearing part would
> > change the significand, that's why significand was copied to a temporary
>
> That much is fine.  My issues are two other things:
>
> * The function would wrongly return true for 3, not just for 3.5, because
> it never checks the bit representing 0.5.  (If you don't care what it
> returns for 3, see my previous point about every function needing a
> comment defining its semantics.  Without such a comment, I have to guess,
> and my guess here is that the function should return true for 3.5 but
> false for 3 and for 3.5000...0001.)
>
> * The function would wrongly return true for 3.5000...0001, if there are
> enough 0s that all those low bits in sig[2] are 0, but some low bits in
> sig[1] or sig[0] are not 0.
>
> And also:
>
> * You should never need to modify parts of (a copy of) the significand in
> place.  Compare low parts of the significand (masked as needed) with 0.
> If not 0, just return false.  Likewise for comparing the 0.5 bit with 1.
> It's not that copying and modifying in place results in incorrect logic,
> it's simply excessively convoluted compared to things like:
>
>   if ((something & mask) != 0)
>     return false
>
> (the function is probably twice as long as necessary because of that
> copying).
>
> > array for checking. This logic is inspired by the clear_significand_below
> > function. Or isn't this the way it was meant to be implemented? Also, why
> > unsigned long sig[SIGSZ] has to be an array?
>
> What would it be other than an array?  It can't be a single scalar because
> floating-point significands may be longer than any supported integer type
> on the host (remember the IEEE binary128 case).  And if you made it a
> sequence of individually named fields, a load of loops would need to be
> manually unrolled, which would be much more error prone and hard to read.
>
> --
> Joseph S. Myers
> joseph@codesourcery.com
>

^ permalink raw reply	[flat|nested] 60+ messages in thread

* Re: About GSOC.
  2019-05-07 19:38                                                 ` Tejas Joshi
@ 2019-05-07 21:01                                                   ` Joseph Myers
  2019-05-08  3:27                                                     ` Tejas Joshi
  0 siblings, 1 reply; 60+ messages in thread
From: Joseph Myers @ 2019-05-07 21:01 UTC (permalink / raw)
  To: Tejas Joshi; +Cc: gcc, Martin Jambor

On Wed, 8 May 2019, Tejas Joshi wrote:

> Hello.
> As per my understanding, 3.5 would be represented in GCC as follows :
> r->uexp  = 2
> and
> r->sig[2] = 1110000....00 in binary 64 bit. (first 2 bits being 3 and
> following 1000....0 being 0.5, which later only happens for halfway cases)
> So, if we clear out the significand part and the immediate bit to the right
> which represent 0.5, the entire significand would become 0 due to bit-wise
> ANDing.
> 
> > +  tempsig[w] &= (((unsigned long)1 << ((n % HOST_BITS_PER_LONG) - 1)) -
> > 1);
> >
> 
> That is what the following line intend to do. The clearing part would
> change the significand, that's why significand was copied to a temporary

That much is fine.  My issues are two other things:

* The function would wrongly return true for 3, not just for 3.5, because 
it never checks the bit representing 0.5.  (If you don't care what it 
returns for 3, see my previous point about every function needing a 
comment defining its semantics.  Without such a comment, I have to guess, 
and my guess here is that the function should return true for 3.5 but 
false for 3 and for 3.5000...0001.)

* The function would wrongly return true for 3.5000...0001, if there are 
enough 0s that all those low bits in sig[2] are 0, but some low bits in 
sig[1] or sig[0] are not 0.

And also:

* You should never need to modify parts of (a copy of) the significand in 
place.  Compare low parts of the significand (masked as needed) with 0.  
If not 0, just return false.  Likewise for comparing the 0.5 bit with 1.  
It's not that copying and modifying in place results in incorrect logic, 
it's simply excessively convoluted compared to things like:

  if ((something & mask) != 0)
    return false

(the function is probably twice as long as necessary because of that 
copying).

> array for checking. This logic is inspired by the clear_significand_below
> function. Or isn't this the way it was meant to be implemented? Also, why
> unsigned long sig[SIGSZ] has to be an array?

What would it be other than an array?  It can't be a single scalar because 
floating-point significands may be longer than any supported integer type 
on the host (remember the IEEE binary128 case).  And if you made it a 
sequence of individually named fields, a load of loops would need to be 
manually unrolled, which would be much more error prone and hard to read.

-- 
Joseph S. Myers
joseph@codesourcery.com

^ permalink raw reply	[flat|nested] 60+ messages in thread

* Re: About GSOC.
  2019-05-07 17:18                                               ` Joseph Myers
@ 2019-05-07 19:38                                                 ` Tejas Joshi
  2019-05-07 21:01                                                   ` Joseph Myers
  0 siblings, 1 reply; 60+ messages in thread
From: Tejas Joshi @ 2019-05-07 19:38 UTC (permalink / raw)
  To: gcc; +Cc: joseph, Martin Jambor

Hello.
Thanks for your inputs.

If it is meant to be testing whether a value is halfway between two
integers, there are two things you need to test.  You need to test whether
the bit with value 0.5 is 0 or 1 (which this function doesn't seem to
test) - and you also need to test whether *all* bits below it are zero or
not (this function only appears to check bits in a single word,
disregarding all the lower words, which is not correct).

Hello.
As per my understanding, 3.5 would be represented in GCC as follows :
r->uexp  = 2
and
r->sig[2] = 1110000....00 in binary 64 bit. (first 2 bits being 3 and
following 1000....0 being 0.5, which later only happens for halfway cases)
So, if we clear out the significand part and the immediate bit to the right
which represent 0.5, the entire significand would become 0 due to bit-wise
ANDing.

> +  tempsig[w] &= (((unsigned long)1 << ((n % HOST_BITS_PER_LONG) - 1)) -
> 1);
>

That is what the following line intend to do. The clearing part would
change the significand, that's why significand was copied to a temporary
array for checking. This logic is inspired by the clear_significand_below
function. Or isn't this the way it was meant to be implemented? Also, why
unsigned long sig[SIGSZ] has to be an array?

If n % HOST_BITS_PER_LONG is 0, this code would shift by -1, which isn't
>

Yes, the condition checking is necessary here. I will incorporate the
changes and find a way to check if the number is even or odd bit-wise and
add test cases in the test suite as soon as possible.
Thanks.

Regards,
-Tejas

On Tue, 7 May 2019 at 22:47, Joseph Myers <joseph@codesourcery.com> wrote:

> On Sat, 4 May 2019, Tejas Joshi wrote:
>
> > Hello.
> > Taking the notes from Joseph under consideration, I have developed a
> > fairly working patch for roundeven, attached herewith.
>
> There are several issues here.  One key one is that you haven't added any
> testcases to the GCC testsuite.  I'd expect tests added that test lots of
> different inputs, for all the float, double and long double types, to
> verify the results are as expected.  That would include various exactly
> halfway cases - but also cases that are halfway plus or minus 1ulp.  Tests
> would be appropriately conditional on the floating-point formats as needed
> - testing for IEEE binary128 long double, on configurations that have that
> type, would help cover certain cases, such as where the integer part
> exceeds 2^64 but there is still a fractional part.
>
> Given tests and confirmation that they have passed in various
> configurations, it's a lot easier to have confidence in the code - and if
> possible issues are spotted in the code, they may point the way to missing
> tests.  That is, tests are a key piece of a patch that makes it much
> easier to review the patch.
>
> > I have done bit-wise calculations to check for halfway cases, though
> > HOST_WIDE_INT is only used to check for even and odd numbers (or is it
> > necessary to do bit-wise for this too?). Also, why unsigned long
>
> Yes, you need to use bit-wise checks for odd and even numbers, because you
> can have a nonzero fractional part with an integer part that is too big to
> be represented in HOST_WIDE_INT.  With IEEE binary128, you can have 112
> bits in the integer part and still have 0.5 as the fractional part.
>
> > diff --git a/gcc/real.c b/gcc/real.c
> > index f822ae82d61..533d471a89b 100644
> > --- a/gcc/real.c
> > +++ b/gcc/real.c
> > @@ -5010,6 +5010,43 @@ real_round (REAL_VALUE_TYPE *r, format_helper fmt,
> >      real_convert (r, fmt, r);
> >  }
> >
> > +bool
> > +is_halfway_below (const REAL_VALUE_TYPE *r)
> > +{
> > +  unsigned long tempsig[SIGSZ];
> > +  unsigned int n = SIGNIFICAND_BITS - REAL_EXP (r);
> > +  int i, w = n / HOST_BITS_PER_LONG;
> > +
> > +  for (i = 0; i < SIGSZ; ++i)
> > +    tempsig[i] = r->sig[i];
> > +
> > +  for (i = 0; i < w; ++i)
> > +    tempsig[i] = 0;
> > +
> > +  tempsig[w] &= (((unsigned long)1 << ((n % HOST_BITS_PER_LONG) - 1)) -
> 1);
> > +
> > +  if (tempsig[w] == 0)
> > +    return true;
>
> > +  return false;
>
> The logic in this function does not make sense to me.
>
> First, it needs a comment above the function defining its exact
> semantics.
> Since it lacks a comment, I have to guess based on the name.
>
> If it is meant to be testing whether a value is halfway between two
> integers, there are two things you need to test.  You need to test whether
> the bit with value 0.5 is 0 or 1 (which this function doesn't seem to
> test) - and you also need to test whether *all* bits below it are zero or
> not (this function only appears to check bits in a single word,
> disregarding all the lower words, which is not correct).
>
> If n % HOST_BITS_PER_LONG is 0, this code would shift by -1, which isn't
> valid.  You need to allow for cases where either the division between 0.5
> and 0.25, or the division between 0.5 and 1, falls exactly at a word
> boundary in the representation of the significand.  It would be a good
> idea to include various such cases in the tests you add to the testsuite.
>
> In any case, there is no need to copy the significand into a temporary
> array in order to test whether low bits are 0.
>
> --
> Joseph S. Myers
> joseph@codesourcery.com
>

^ permalink raw reply	[flat|nested] 60+ messages in thread

* Re: About GSOC.
  2019-05-04 11:20                                             ` Tejas Joshi
@ 2019-05-07 17:18                                               ` Joseph Myers
  2019-05-07 19:38                                                 ` Tejas Joshi
  0 siblings, 1 reply; 60+ messages in thread
From: Joseph Myers @ 2019-05-07 17:18 UTC (permalink / raw)
  To: Tejas Joshi; +Cc: gcc, Martin Jambor

On Sat, 4 May 2019, Tejas Joshi wrote:

> Hello.
> Taking the notes from Joseph under consideration, I have developed a
> fairly working patch for roundeven, attached herewith.

There are several issues here.  One key one is that you haven't added any 
testcases to the GCC testsuite.  I'd expect tests added that test lots of 
different inputs, for all the float, double and long double types, to 
verify the results are as expected.  That would include various exactly 
halfway cases - but also cases that are halfway plus or minus 1ulp.  Tests 
would be appropriately conditional on the floating-point formats as needed 
- testing for IEEE binary128 long double, on configurations that have that 
type, would help cover certain cases, such as where the integer part 
exceeds 2^64 but there is still a fractional part.

Given tests and confirmation that they have passed in various 
configurations, it's a lot easier to have confidence in the code - and if 
possible issues are spotted in the code, they may point the way to missing 
tests.  That is, tests are a key piece of a patch that makes it much 
easier to review the patch.

> I have done bit-wise calculations to check for halfway cases, though
> HOST_WIDE_INT is only used to check for even and odd numbers (or is it
> necessary to do bit-wise for this too?). Also, why unsigned long

Yes, you need to use bit-wise checks for odd and even numbers, because you 
can have a nonzero fractional part with an integer part that is too big to 
be represented in HOST_WIDE_INT.  With IEEE binary128, you can have 112 
bits in the integer part and still have 0.5 as the fractional part.

> diff --git a/gcc/real.c b/gcc/real.c
> index f822ae82d61..533d471a89b 100644
> --- a/gcc/real.c
> +++ b/gcc/real.c
> @@ -5010,6 +5010,43 @@ real_round (REAL_VALUE_TYPE *r, format_helper fmt,
>      real_convert (r, fmt, r);
>  }
>  
> +bool
> +is_halfway_below (const REAL_VALUE_TYPE *r)
> +{
> +  unsigned long tempsig[SIGSZ];
> +  unsigned int n = SIGNIFICAND_BITS - REAL_EXP (r);
> +  int i, w = n / HOST_BITS_PER_LONG;
> +
> +  for (i = 0; i < SIGSZ; ++i)
> +    tempsig[i] = r->sig[i];
> +
> +  for (i = 0; i < w; ++i)
> +    tempsig[i] = 0;
> +
> +  tempsig[w] &= (((unsigned long)1 << ((n % HOST_BITS_PER_LONG) - 1)) - 1);
> +  
> +  if (tempsig[w] == 0)
> +    return true;

> +  return false;

The logic in this function does not make sense to me.

First, it needs a comment above the function defining its exact semantics.  
Since it lacks a comment, I have to guess based on the name.

If it is meant to be testing whether a value is halfway between two 
integers, there are two things you need to test.  You need to test whether 
the bit with value 0.5 is 0 or 1 (which this function doesn't seem to 
test) - and you also need to test whether *all* bits below it are zero or 
not (this function only appears to check bits in a single word, 
disregarding all the lower words, which is not correct).

If n % HOST_BITS_PER_LONG is 0, this code would shift by -1, which isn't 
valid.  You need to allow for cases where either the division between 0.5 
and 0.25, or the division between 0.5 and 1, falls exactly at a word 
boundary in the representation of the significand.  It would be a good 
idea to include various such cases in the tests you add to the testsuite.

In any case, there is no need to copy the significand into a temporary 
array in order to test whether low bits are 0.

-- 
Joseph S. Myers
joseph@codesourcery.com

^ permalink raw reply	[flat|nested] 60+ messages in thread

* Re: About GSOC.
  2019-04-04 13:04                                           ` Tejas Joshi
@ 2019-05-04 11:20                                             ` Tejas Joshi
  2019-05-07 17:18                                               ` Joseph Myers
  0 siblings, 1 reply; 60+ messages in thread
From: Tejas Joshi @ 2019-05-04 11:20 UTC (permalink / raw)
  To: gcc; +Cc: Martin Jambor, joseph

[-- Attachment #1: Type: text/plain, Size: 483 bytes --]

Hello.
Taking the notes from Joseph under consideration, I have developed a
fairly working patch for roundeven, attached herewith.
I have done bit-wise calculations to check for halfway cases, though
HOST_WIDE_INT is only used to check for even and odd numbers (or is it
necessary to do bit-wise for this too?). Also, why unsigned long
sig[SIGSZ] in real_value has to be an array? (for 64 bit system, its
an array of size 3, mostly first 2 values being 0?).
Thanks.

Regards,
-Tejas

[-- Attachment #2: roundeven.patch --]
[-- Type: text/x-patch, Size: 4836 bytes --]

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..e1d593a8765 100644
--- a/gcc/builtins.def
+++ b/gcc/builtins.def
@@ -542,6 +542,9 @@ 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)
diff --git a/gcc/fold-const-call.c b/gcc/fold-const-call.c
index 06a420601c0..7eafd91e9a2 100644
--- a/gcc/fold-const-call.c
+++ b/gcc/fold-const-call.c
@@ -792,6 +792,14 @@ fold_const_call_ss (real_value *result, combined_fn fn,
 	}
       return false;
 
+    case CFN_BUILT_IN_ROUNDEVEN:
+      if (!REAL_VALUE_ISNAN (*arg) || !flag_errno_math)
+  {
+    real_roundeven (result, format, arg);
+    return true;
+  }
+      return false;
+
     CASE_CFN_LOGB:
       return fold_const_logb (result, arg, format);
 
@@ -854,6 +862,9 @@ fold_const_call_ss (wide_int *result, combined_fn fn,
       return fold_const_conversion (result, real_round, arg,
 				    precision, format);
 
+    case CFN_BUILT_IN_ROUNDEVEN:
+      return fold_const_conversion (result, real_roundeven, arg, precision, format);
+
     CASE_CFN_IRINT:
     CASE_CFN_LRINT:
     CASE_CFN_LLRINT:
diff --git a/gcc/fold-const.c b/gcc/fold-const.c
index 59cedeafd71..30c409e95bf 100644
--- a/gcc/fold-const.c
+++ b/gcc/fold-const.c
@@ -329,6 +329,7 @@ negate_mathfn_p (combined_fn fn)
     CASE_CFN_LLROUND:
     CASE_CFN_LROUND:
     CASE_CFN_ROUND:
+    CASE_CFN_ROUNDEVEN:
     CASE_CFN_SIN:
     CASE_CFN_SINH:
     CASE_CFN_TAN:
@@ -13060,6 +13061,8 @@ tree_call_nonnegative_warnv_p (tree type, combined_fn fn, tree arg0, tree arg1,
     CASE_CFN_RINT_FN:
     CASE_CFN_ROUND:
     CASE_CFN_ROUND_FN:
+    CASE_CFN_ROUNDEVEN:
+    CASE_CFN_ROUNDEVEN_FN:
     CASE_CFN_SCALB:
     CASE_CFN_SCALBLN:
     CASE_CFN_SCALBN:
@@ -13583,6 +13586,8 @@ integer_valued_real_call_p (combined_fn fn, tree arg0, tree arg1, int depth)
     CASE_CFN_RINT_FN:
     CASE_CFN_ROUND:
     CASE_CFN_ROUND_FN:
+    CASE_CFN_ROUNDEVEN:
+    CASE_CFN_ROUNDEVEN_FN:
     CASE_CFN_TRUNC:
     CASE_CFN_TRUNC_FN:
       return true;
diff --git a/gcc/real.c b/gcc/real.c
index f822ae82d61..533d471a89b 100644
--- a/gcc/real.c
+++ b/gcc/real.c
@@ -5010,6 +5010,43 @@ real_round (REAL_VALUE_TYPE *r, format_helper fmt,
     real_convert (r, fmt, r);
 }
 
+bool
+is_halfway_below (const REAL_VALUE_TYPE *r)
+{
+  unsigned long tempsig[SIGSZ];
+  unsigned int n = SIGNIFICAND_BITS - REAL_EXP (r);
+  int i, w = n / HOST_BITS_PER_LONG;
+
+  for (i = 0; i < SIGSZ; ++i)
+    tempsig[i] = r->sig[i];
+
+  for (i = 0; i < w; ++i)
+    tempsig[i] = 0;
+
+  tempsig[w] &= (((unsigned long)1 << ((n % HOST_BITS_PER_LONG) - 1)) - 1);
+  
+  if (tempsig[w] == 0)
+    return true;
+  return false;
+}
+
+/* Round X to nearest integer, rounding halfway cases towards even. */
+
+void
+real_roundeven (REAL_VALUE_TYPE *r, format_helper fmt,
+		const REAL_VALUE_TYPE *x)
+{
+  if (is_halfway_below (x))
+  {
+    do_add (r, x, &dconsthalf, x->sign);
+    HOST_WIDE_INT i = real_to_integer (r);
+    if (i % 2)
+      do_add (r, r, &dconstm1, x->sign);
+  }
+  else
+    real_round (r, fmt, x);
+}
+
 /* Set the sign of R to the sign of X.  */
 
 void
diff --git a/gcc/real.h b/gcc/real.h
index 0ce42565708..10898eae79e 100644
--- a/gcc/real.h
+++ b/gcc/real.h
@@ -499,6 +499,8 @@ extern void real_ceil (REAL_VALUE_TYPE *, format_helper,
 		       const REAL_VALUE_TYPE *);
 extern void real_round (REAL_VALUE_TYPE *, format_helper,
 			const REAL_VALUE_TYPE *);
+extern void real_roundeven (REAL_VALUE_TYPE *, format_helper,
+      const REAL_VALUE_TYPE *);
 
 /* Set the sign of R to the sign of X.  */
 extern void real_copysign (REAL_VALUE_TYPE *, const REAL_VALUE_TYPE *);

^ permalink raw reply	[flat|nested] 60+ messages in thread

* Re: About GSOC.
  2019-04-01 19:53                                         ` Joseph Myers
@ 2019-04-04 13:04                                           ` Tejas Joshi
  2019-05-04 11:20                                             ` Tejas Joshi
  0 siblings, 1 reply; 60+ messages in thread
From: Tejas Joshi @ 2019-04-04 13:04 UTC (permalink / raw)
  To: gcc; +Cc: Martin Jambor

Hello.
Here is the proposal draft for the idea. Please review and suggest
changes or modifications.

https://docs.google.com/document/d/15DEXa5NZL6Q_X_zlME3NNJw2zVimFWzi16x7cgIDqL0/edit?usp=sharing

Thanks,
-Tejas

On Tue, 2 Apr 2019 at 01:23, Joseph Myers <joseph@codesourcery.com> wrote:
>
> On Sat, 30 Mar 2019, Tejas Joshi wrote:
>
> > Hello.
> > I have developed a fairly working patch for roundeven, attaching herewith.
> > The testcase function as follows :
> >
> > double f()
> > {
> >   double x = 4.5;
> >   double ret = __builtin_roundeven (x);
> >   return ret;
> > }
>
> Tests need to be added to the testsuite, covering a range of inputs and
> automatically verifying that the test is optimized correctly.
>
> "Round X to nearest even integer towards zero." is not correct.  The
> roundeven function does not round to an even integer.  It rounds to the
> nearest integer, whether even or odd - but, if two integers are equally
> close, the result is even (and for any input that is not halfway between
> two integers, it produces the same result as round (which rounds halfway
> cases away from zero) - so 2.501, 3 and 3.499 round to 3, but 2.5 rounds
> to 2 not 3, unlike round, and 3.5 rounds to 4, as with round).
>
> The function can't rely on arguments being in the range of HOST_WIDE_INT,
> so it needs to examine the REAL_VALUE_TYPE representation directly to
> determine whether it's half way between two integers and which way to
> round in that case.
>
> --
> Joseph S. Myers
> joseph@codesourcery.com

^ permalink raw reply	[flat|nested] 60+ messages in thread

* Re: About GSOC.
  2019-03-30 11:24                                       ` Tejas Joshi
@ 2019-04-01 19:53                                         ` Joseph Myers
  2019-04-04 13:04                                           ` Tejas Joshi
  0 siblings, 1 reply; 60+ messages in thread
From: Joseph Myers @ 2019-04-01 19:53 UTC (permalink / raw)
  To: Tejas Joshi; +Cc: gcc

On Sat, 30 Mar 2019, Tejas Joshi wrote:

> Hello.
> I have developed a fairly working patch for roundeven, attaching herewith.
> The testcase function as follows :
> 
> double f()
> {
>   double x = 4.5;
>   double ret = __builtin_roundeven (x);
>   return ret;
> }

Tests need to be added to the testsuite, covering a range of inputs and 
automatically verifying that the test is optimized correctly.

"Round X to nearest even integer towards zero." is not correct.  The 
roundeven function does not round to an even integer.  It rounds to the 
nearest integer, whether even or odd - but, if two integers are equally 
close, the result is even (and for any input that is not halfway between 
two integers, it produces the same result as round (which rounds halfway 
cases away from zero) - so 2.501, 3 and 3.499 round to 3, but 2.5 rounds 
to 2 not 3, unlike round, and 3.5 rounds to 4, as with round).

The function can't rely on arguments being in the range of HOST_WIDE_INT, 
so it needs to examine the REAL_VALUE_TYPE representation directly to 
determine whether it's half way between two integers and which way to 
round in that case.

-- 
Joseph S. Myers
joseph@codesourcery.com

^ permalink raw reply	[flat|nested] 60+ messages in thread

* Re: About GSOC.
  2019-02-24 12:05                                     ` Tejas Joshi
@ 2019-03-30 11:24                                       ` Tejas Joshi
  2019-04-01 19:53                                         ` Joseph Myers
  0 siblings, 1 reply; 60+ messages in thread
From: Tejas Joshi @ 2019-03-30 11:24 UTC (permalink / raw)
  To: gcc

[-- Attachment #1: Type: text/plain, Size: 7124 bytes --]

Hello.
I have developed a fairly working patch for roundeven, attaching herewith.
The testcase function as follows :

double f()
{
  double x = 4.5;
  double ret = __builtin_roundeven (x);
  return ret;
}

We can inspect the file foo.c.028t.ccp1, where we can see f() returns
value 4.0e+0.
I am also writing the proposal and make draft ready in couple of days
for community review.
Do roundeven have to be added in internals-fn.def to be called internal?

Thanks,
-Tejas


On Sun, 24 Feb 2019 at 17:39, Tejas Joshi <tejasjoshi9673@gmail.com> wrote:
>
> Hello.
> I had a little pause on roundeven due to seminars in my college. I've
> tried to implement roundeven but can not figure out what are just
> minimal needs to roundeven be called for a test program like
> __builtin_roundeven();
> Also, build exited returning status as:
>
> DEF_INTERNAL_FLT_FN (ROUNDEVEN) has no associated built-in functions
>
> Here is the .diff flie.
>
> Thanks,
> -Tejas
>
> On Mon, 4 Feb 2019 at 22:55, Tejas Joshi <tejasjoshi9673@gmail.com> wrote:
> >
> > Hi.
> > Although now, I am unable to build the compiler.
> > The build exited returning status as:
> >
> > DEF_INTERNAL_FLT_FN (ROUNDEVEN) has no associated built-in functions
> >
> > I have added the entry in fold_const_call_ss() and do not find any
> > other place to add the case.
> > Here is the latest patch.
> >
> > On Mon, 4 Feb 2019 at 22:14, Prathamesh Kulkarni
> > <prathamesh.kulkarni@linaro.org> wrote:
> > >
> > > On Mon, 4 Feb 2019 at 21:27, Tejas Joshi <tejasjoshi9673@gmail.com> wrote:
> > > >
> > > > Thanks.
> > > > > Did you add an entry for roundeven in builtins.def ?
> > > > Yes, I did.
> > > >
> > > > Find here the attached patch.diff for which I did the changes to
> > > > implement roundeven. There might be some unnecessary changes and some
> > > > necessary changes which have not been made.
> > > You haven't called roundeven() in the patch. You'll need to add an
> > > entry in fold_const_call_ss()
> > > similar to real_ceil, and probably in other places too.
> > >
> > > Thanks,
> > > Prathamesh
> > > >
> > > > Regards,
> > > > -Tejas
> > > >
> > > > On Mon, 4 Feb 2019 at 20:36, Prathamesh Kulkarni
> > > > <prathamesh.kulkarni@linaro.org> wrote:
> > > > >
> > > > > On Mon, 4 Feb 2019 at 20:10, Tejas Joshi <tejasjoshi9673@gmail.com> wrote:
> > > > > >
> > > > > > Hello.
> > > > > > I have implemented roundeven function in real.c as follows: (and
> > > > > > respective changes in real.h)
> > > > > It's a better idea to include all changes in patch instead of copy-pasting.
> > > > > Use the command:
> > > > > git diff > patch.diff
> > > > > which will create a file called "patch.diff" containing the changes
> > > > > and send it as an attachment.
> > > > > >
> > > > > > /* Round X to nearest even integer towards zero. */
> > > > > >
> > > > > > void
> > > > > > real_roundeven (REAL_VALUE_TYPE *r, format_helper fmt,
> > > > > >         const REAL_VALUE_TYPE *x)
> > > > > > {
> > > > > >   REAL_VALUE_TYPE t;
> > > > > >
> > > > > >   do_fix_trunc (&t, x);
> > > > > >   HOST_WIDE_INT i = real_to_integer (&t);
> > > > > >   if(i % 2)
> > > > > >     do_add (r, &t, &dconstm1, 0);
> > > > > >   else
> > > > > >     *r = t;
> > > > > > }
> > > > > >
> > > > > > Although I cant get it to test like
> > > > > >
> > > > > > int foo()
> > > > > > {
> > > > > >     double x = __builtin_roundeven (3.5);
> > > > > >     printf("%f",x);
> > > > > >     return (int) x;
> > > > > > }
> > > > > > Because I do not know its dependencies through other files. I tried to
> > > > > > track them down by inspecting real_ceil function, but it also includes
> > > > > > other optimization procedures like folding. How do I know enough
> > > > > > declarations to be made in respective files?
> > > > > Did you add an entry for roundeven in builtins.def ?
> > > > >
> > > > > Thanks,
> > > > > Prathamesh
> > > > > >
> > > > > > Thanks.
> > > > > > -Tejas
> > > > > >
> > > > > > On Mon, 28 Jan 2019 at 22:33, Tejas Joshi <tejasjoshi9673@gmail.com> wrote:
> > > > > > >
> > > > > > > Hello.
> > > > > > > Representations of real numbers in real.c are a little complex to
> > > > > > > understand right now for me. I am still trying to understand them and
> > > > > > > figure them out using gdb and cscope. Though conventions are given in
> > > > > > > comments in real.c, I will still be trying to figure it out. The
> > > > > > > equation and its bitwise representation is not pretty elaborated in
> > > > > > > any documentation I could find.
> > > > > > >
> > > > > > > x = s * b^e * \sum_{k=1}^p f_k * b^{-k}
> > > > > > >
> > > > > > >     where
> > > > > > >         s = sign (+- 1)
> > > > > > >         b = base or radix, here always 2
> > > > > > >         e = exponent
> > > > > > >         p = precision (the number of base-b digits in the significand)
> > > > > > >         f_k = the digits of the significand.
> > > > > > >
> > > > > > > In mean time, I've tried real_round function to work like roundeven. I
> > > > > > > will try to submit a clean patch along with roundeven implemented
> > > > > > > separately with changes like in builtins.def, adding cases, etc.
> > > > > > >
> > > > > > > void
> > > > > > > real_round (REAL_VALUE_TYPE *r, format_helper fmt,
> > > > > > >         const REAL_VALUE_TYPE *x)
> > > > > > > {
> > > > > > > #if 0
> > > > > > >   do_add (r, x, &dconsthalf, x->sign);
> > > > > > >   do_fix_trunc (r, r);
> > > > > > >   if (fmt)
> > > > > > >     real_convert (r, fmt, r);
> > > > > > > #endif
> > > > > > >   fprintf (stderr, "\nhere\n");
> > > > > > >   real_value z;
> > > > > > >   do_fix_trunc (&z, x);
> > > > > > >   HOST_WIDE_INT i = real_to_integer (&z);
> > > > > > >   fprintf (stderr, "\n i = %ld\n", i);
> > > > > > >   if (i % 2)
> > > > > > >     do_add (r, &z, &dconstm1, 0);
> > > > > > >   else
> > > > > > >     *r = z;
> > > > > > > }
> > > > > > >
> > > > > > > Thanks.
> > > > > > > -Tejas
> > > > > > >
> > > > > > > On Sat, 26 Jan 2019 at 03:02, Joseph Myers <joseph@codesourcery.com> wrote:
> > > > > > > >
> > > > > > > > On Sat, 26 Jan 2019, Tejas Joshi wrote:
> > > > > > > >
> > > > > > > > > function with byte-byte comparison which also include mpfr. (Correct
> > > > > > > > > me if I am wrong.) What is the significance of mpfr related to these
> > > > > > > > > internal representations?
> > > > > > > >
> > > > > > > > real.c provides a fixed-size representation of floating-point numbers that
> > > > > > > > allows for various non-IEEE formats supported by GCC, and also allows
> > > > > > > > functions from dfp.c to be used for decimal floating-point formats.
> > > > > > > >
> > > > > > > > MPFR is used in GCC to provide operations that are nontrivial to
> > > > > > > > implement, especially those that are nontrivial to implement in such a
> > > > > > > > fixed-size context.  real.c operations wrap around MPFR ones where
> > > > > > > > appropriate, doing whatever's needed in cases where there are non-IEEE
> > > > > > > > semantics or sets of values.
> > > > > > > >
> > > > > > > > --
> > > > > > > > Joseph S. Myers
> > > > > > > > joseph@codesourcery.com

[-- Attachment #2: roundeven.patch --]
[-- Type: text/x-patch, Size: 4321 bytes --]

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..e1d593a8765 100644
--- a/gcc/builtins.def
+++ b/gcc/builtins.def
@@ -542,6 +542,9 @@ 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)
diff --git a/gcc/fold-const-call.c b/gcc/fold-const-call.c
index 06a420601c0..7eafd91e9a2 100644
--- a/gcc/fold-const-call.c
+++ b/gcc/fold-const-call.c
@@ -792,6 +792,14 @@ fold_const_call_ss (real_value *result, combined_fn fn,
 	}
       return false;
 
+    case CFN_BUILT_IN_ROUNDEVEN:
+      if (!REAL_VALUE_ISNAN (*arg) || !flag_errno_math)
+  {
+    real_roundeven (result, format, arg);
+    return true;
+  }
+      return false;
+
     CASE_CFN_LOGB:
       return fold_const_logb (result, arg, format);
 
@@ -854,6 +862,9 @@ fold_const_call_ss (wide_int *result, combined_fn fn,
       return fold_const_conversion (result, real_round, arg,
 				    precision, format);
 
+    case CFN_BUILT_IN_ROUNDEVEN:
+      return fold_const_conversion (result, real_roundeven, arg, precision, format);
+
     CASE_CFN_IRINT:
     CASE_CFN_LRINT:
     CASE_CFN_LLRINT:
diff --git a/gcc/fold-const.c b/gcc/fold-const.c
index 59cedeafd71..30c409e95bf 100644
--- a/gcc/fold-const.c
+++ b/gcc/fold-const.c
@@ -329,6 +329,7 @@ negate_mathfn_p (combined_fn fn)
     CASE_CFN_LLROUND:
     CASE_CFN_LROUND:
     CASE_CFN_ROUND:
+    CASE_CFN_ROUNDEVEN:
     CASE_CFN_SIN:
     CASE_CFN_SINH:
     CASE_CFN_TAN:
@@ -13060,6 +13061,8 @@ tree_call_nonnegative_warnv_p (tree type, combined_fn fn, tree arg0, tree arg1,
     CASE_CFN_RINT_FN:
     CASE_CFN_ROUND:
     CASE_CFN_ROUND_FN:
+    CASE_CFN_ROUNDEVEN:
+    CASE_CFN_ROUNDEVEN_FN:
     CASE_CFN_SCALB:
     CASE_CFN_SCALBLN:
     CASE_CFN_SCALBN:
@@ -13583,6 +13586,8 @@ integer_valued_real_call_p (combined_fn fn, tree arg0, tree arg1, int depth)
     CASE_CFN_RINT_FN:
     CASE_CFN_ROUND:
     CASE_CFN_ROUND_FN:
+    CASE_CFN_ROUNDEVEN:
+    CASE_CFN_ROUNDEVEN_FN:
     CASE_CFN_TRUNC:
     CASE_CFN_TRUNC_FN:
       return true;
diff --git a/gcc/real.c b/gcc/real.c
index f822ae82d61..087478841e5 100644
--- a/gcc/real.c
+++ b/gcc/real.c
@@ -5010,6 +5010,22 @@ real_round (REAL_VALUE_TYPE *r, format_helper fmt,
     real_convert (r, fmt, r);
 }
 
+/* Round X to nearest even integer towards zero. */
+
+void
+real_roundeven (REAL_VALUE_TYPE *r, format_helper fmt,
+		const REAL_VALUE_TYPE *x)
+{
+  REAL_VALUE_TYPE t;
+
+  do_fix_trunc (&t, x);
+  HOST_WIDE_INT i = real_to_integer (&t);
+  if(i % 2)
+    do_add (r, &t, &dconstm1, 0);
+  else
+    *r = t;
+}
+
 /* Set the sign of R to the sign of X.  */
 
 void
diff --git a/gcc/real.h b/gcc/real.h
index 0ce42565708..10898eae79e 100644
--- a/gcc/real.h
+++ b/gcc/real.h
@@ -499,6 +499,8 @@ extern void real_ceil (REAL_VALUE_TYPE *, format_helper,
 		       const REAL_VALUE_TYPE *);
 extern void real_round (REAL_VALUE_TYPE *, format_helper,
 			const REAL_VALUE_TYPE *);
+extern void real_roundeven (REAL_VALUE_TYPE *, format_helper,
+      const REAL_VALUE_TYPE *);
 
 /* Set the sign of R to the sign of X.  */
 extern void real_copysign (REAL_VALUE_TYPE *, const REAL_VALUE_TYPE *);

[-- Attachment #3: foo.c.028t.ccp1 --]
[-- Type: application/octet-stream, Size: 1149 bytes --]


;; Function f (f, funcdef_no=0, decl_uid=1907, cgraph_uid=1, symbol_order=0)

Adding destination of edge (0 -> 2) to worklist

Simulating block 2

Visiting statement:
x_1 = 4.5e+0;
which is likely CONSTANT
Lattice value changed to CONSTANT 4.5e+0.  Adding SSA edges to worklist.
marking stmt to be not simulated again

Visiting statement:
ret_2 = __builtin_roundeven (x_1);
which is likely CONSTANT
Match-and-simplified __builtin_roundeven (x_1) to 4.0e+0
Lattice value changed to CONSTANT 4.0e+0.  Adding SSA edges to worklist.
marking stmt to be not simulated again

Visiting statement:
_3 = ret_2;
which is likely CONSTANT
Match-and-simplified ret_2 to 4.0e+0
Lattice value changed to CONSTANT 4.0e+0.  Adding SSA edges to worklist.
marking stmt to be not simulated again

Visiting statement:
return _3;
No interesting values produced.  Marked VARYING.

Substituting values and folding statements

Folding statement: return _3;
Folded into: return 4.0e+0;

Removing dead stmt _3 = ret_2;

Removing dead stmt ret_2 = __builtin_roundeven (x_1);

Removing dead stmt x_1 = 4.5e+0;

f ()
{
  double ret;
  double x;

  <bb 2> :
  return 4.0e+0;

}



^ permalink raw reply	[flat|nested] 60+ messages in thread

* Re: About GSOC.
  2019-02-04 17:22                                   ` Tejas Joshi
@ 2019-02-24 12:05                                     ` Tejas Joshi
  2019-03-30 11:24                                       ` Tejas Joshi
  0 siblings, 1 reply; 60+ messages in thread
From: Tejas Joshi @ 2019-02-24 12:05 UTC (permalink / raw)
  To: gcc; +Cc: joseph, Martin Jambor

[-- Attachment #1: Type: text/plain, Size: 6245 bytes --]

Hello.
I had a little pause on roundeven due to seminars in my college. I've
tried to implement roundeven but can not figure out what are just
minimal needs to roundeven be called for a test program like
__builtin_roundeven();
Also, build exited returning status as:

DEF_INTERNAL_FLT_FN (ROUNDEVEN) has no associated built-in functions

Here is the .diff flie.

Thanks,
-Tejas

On Mon, 4 Feb 2019 at 22:55, Tejas Joshi <tejasjoshi9673@gmail.com> wrote:
>
> Hi.
> Although now, I am unable to build the compiler.
> The build exited returning status as:
>
> DEF_INTERNAL_FLT_FN (ROUNDEVEN) has no associated built-in functions
>
> I have added the entry in fold_const_call_ss() and do not find any
> other place to add the case.
> Here is the latest patch.
>
> On Mon, 4 Feb 2019 at 22:14, Prathamesh Kulkarni
> <prathamesh.kulkarni@linaro.org> wrote:
> >
> > On Mon, 4 Feb 2019 at 21:27, Tejas Joshi <tejasjoshi9673@gmail.com> wrote:
> > >
> > > Thanks.
> > > > Did you add an entry for roundeven in builtins.def ?
> > > Yes, I did.
> > >
> > > Find here the attached patch.diff for which I did the changes to
> > > implement roundeven. There might be some unnecessary changes and some
> > > necessary changes which have not been made.
> > You haven't called roundeven() in the patch. You'll need to add an
> > entry in fold_const_call_ss()
> > similar to real_ceil, and probably in other places too.
> >
> > Thanks,
> > Prathamesh
> > >
> > > Regards,
> > > -Tejas
> > >
> > > On Mon, 4 Feb 2019 at 20:36, Prathamesh Kulkarni
> > > <prathamesh.kulkarni@linaro.org> wrote:
> > > >
> > > > On Mon, 4 Feb 2019 at 20:10, Tejas Joshi <tejasjoshi9673@gmail.com> wrote:
> > > > >
> > > > > Hello.
> > > > > I have implemented roundeven function in real.c as follows: (and
> > > > > respective changes in real.h)
> > > > It's a better idea to include all changes in patch instead of copy-pasting.
> > > > Use the command:
> > > > git diff > patch.diff
> > > > which will create a file called "patch.diff" containing the changes
> > > > and send it as an attachment.
> > > > >
> > > > > /* Round X to nearest even integer towards zero. */
> > > > >
> > > > > void
> > > > > real_roundeven (REAL_VALUE_TYPE *r, format_helper fmt,
> > > > >         const REAL_VALUE_TYPE *x)
> > > > > {
> > > > >   REAL_VALUE_TYPE t;
> > > > >
> > > > >   do_fix_trunc (&t, x);
> > > > >   HOST_WIDE_INT i = real_to_integer (&t);
> > > > >   if(i % 2)
> > > > >     do_add (r, &t, &dconstm1, 0);
> > > > >   else
> > > > >     *r = t;
> > > > > }
> > > > >
> > > > > Although I cant get it to test like
> > > > >
> > > > > int foo()
> > > > > {
> > > > >     double x = __builtin_roundeven (3.5);
> > > > >     printf("%f",x);
> > > > >     return (int) x;
> > > > > }
> > > > > Because I do not know its dependencies through other files. I tried to
> > > > > track them down by inspecting real_ceil function, but it also includes
> > > > > other optimization procedures like folding. How do I know enough
> > > > > declarations to be made in respective files?
> > > > Did you add an entry for roundeven in builtins.def ?
> > > >
> > > > Thanks,
> > > > Prathamesh
> > > > >
> > > > > Thanks.
> > > > > -Tejas
> > > > >
> > > > > On Mon, 28 Jan 2019 at 22:33, Tejas Joshi <tejasjoshi9673@gmail.com> wrote:
> > > > > >
> > > > > > Hello.
> > > > > > Representations of real numbers in real.c are a little complex to
> > > > > > understand right now for me. I am still trying to understand them and
> > > > > > figure them out using gdb and cscope. Though conventions are given in
> > > > > > comments in real.c, I will still be trying to figure it out. The
> > > > > > equation and its bitwise representation is not pretty elaborated in
> > > > > > any documentation I could find.
> > > > > >
> > > > > > x = s * b^e * \sum_{k=1}^p f_k * b^{-k}
> > > > > >
> > > > > >     where
> > > > > >         s = sign (+- 1)
> > > > > >         b = base or radix, here always 2
> > > > > >         e = exponent
> > > > > >         p = precision (the number of base-b digits in the significand)
> > > > > >         f_k = the digits of the significand.
> > > > > >
> > > > > > In mean time, I've tried real_round function to work like roundeven. I
> > > > > > will try to submit a clean patch along with roundeven implemented
> > > > > > separately with changes like in builtins.def, adding cases, etc.
> > > > > >
> > > > > > void
> > > > > > real_round (REAL_VALUE_TYPE *r, format_helper fmt,
> > > > > >         const REAL_VALUE_TYPE *x)
> > > > > > {
> > > > > > #if 0
> > > > > >   do_add (r, x, &dconsthalf, x->sign);
> > > > > >   do_fix_trunc (r, r);
> > > > > >   if (fmt)
> > > > > >     real_convert (r, fmt, r);
> > > > > > #endif
> > > > > >   fprintf (stderr, "\nhere\n");
> > > > > >   real_value z;
> > > > > >   do_fix_trunc (&z, x);
> > > > > >   HOST_WIDE_INT i = real_to_integer (&z);
> > > > > >   fprintf (stderr, "\n i = %ld\n", i);
> > > > > >   if (i % 2)
> > > > > >     do_add (r, &z, &dconstm1, 0);
> > > > > >   else
> > > > > >     *r = z;
> > > > > > }
> > > > > >
> > > > > > Thanks.
> > > > > > -Tejas
> > > > > >
> > > > > > On Sat, 26 Jan 2019 at 03:02, Joseph Myers <joseph@codesourcery.com> wrote:
> > > > > > >
> > > > > > > On Sat, 26 Jan 2019, Tejas Joshi wrote:
> > > > > > >
> > > > > > > > function with byte-byte comparison which also include mpfr. (Correct
> > > > > > > > me if I am wrong.) What is the significance of mpfr related to these
> > > > > > > > internal representations?
> > > > > > >
> > > > > > > real.c provides a fixed-size representation of floating-point numbers that
> > > > > > > allows for various non-IEEE formats supported by GCC, and also allows
> > > > > > > functions from dfp.c to be used for decimal floating-point formats.
> > > > > > >
> > > > > > > MPFR is used in GCC to provide operations that are nontrivial to
> > > > > > > implement, especially those that are nontrivial to implement in such a
> > > > > > > fixed-size context.  real.c operations wrap around MPFR ones where
> > > > > > > appropriate, doing whatever's needed in cases where there are non-IEEE
> > > > > > > semantics or sets of values.
> > > > > > >
> > > > > > > --
> > > > > > > Joseph S. Myers
> > > > > > > joseph@codesourcery.com

[-- Attachment #2: patch.diff --]
[-- Type: text/x-patch, Size: 6731 bytes --]

diff --git a/gcc/builtins.c b/gcc/builtins.c
index 25e01e4092b..25282d2122d 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_FLOATN (ROUNDEVEN)
     CASE_MATHFN (SCALB)
     CASE_MATHFN (SCALBLN)
     CASE_MATHFN (SCALBN)
diff --git a/gcc/builtins.def b/gcc/builtins.def
index ef89729fd0c..9b554333f57 100644
--- a/gcc/builtins.def
+++ b/gcc/builtins.def
@@ -542,9 +542,13 @@ 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_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 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
 #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
diff --git a/gcc/fold-const-call.c b/gcc/fold-const-call.c
index 06a420601c0..6f4fea63b0c 100644
--- a/gcc/fold-const-call.c
+++ b/gcc/fold-const-call.c
@@ -773,6 +773,16 @@ fold_const_call_ss (real_value *result, combined_fn fn,
     CASE_CFN_CEIL_FN:
       if (!REAL_VALUE_ISNAN (*arg) || !flag_errno_math)
 	{
+	  fprintf (stderr, "\n");
+	  fprintf (stderr, "cl: %u\n", arg->cl);
+	  fprintf (stderr, "sign: %u\n", arg->sign);
+	  fprintf (stderr, "signalling: %u\n", arg->signalling);
+	  fprintf (stderr, "canonical: %u\n", arg->canonical);
+	  fprintf (stderr, "uexp: %u\n", arg->uexp);
+	  
+	  fprintf (stderr, "sig: ");
+	  for (int i = 0; i < SIGSZ; i++)
+	    fprintf (stderr, "%lx ", arg->sig[i]);
 	  real_ceil (result, format, arg);
 	  return true;
 	}
@@ -792,6 +802,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_const_logb (result, arg, format);
 
diff --git a/gcc/fold-const.c b/gcc/fold-const.c
index 59cedeafd71..30c409e95bf 100644
--- a/gcc/fold-const.c
+++ b/gcc/fold-const.c
@@ -329,6 +329,7 @@ negate_mathfn_p (combined_fn fn)
     CASE_CFN_LLROUND:
     CASE_CFN_LROUND:
     CASE_CFN_ROUND:
+    CASE_CFN_ROUNDEVEN:
     CASE_CFN_SIN:
     CASE_CFN_SINH:
     CASE_CFN_TAN:
@@ -13060,6 +13061,8 @@ tree_call_nonnegative_warnv_p (tree type, combined_fn fn, tree arg0, tree arg1,
     CASE_CFN_RINT_FN:
     CASE_CFN_ROUND:
     CASE_CFN_ROUND_FN:
+    CASE_CFN_ROUNDEVEN:
+    CASE_CFN_ROUNDEVEN_FN:
     CASE_CFN_SCALB:
     CASE_CFN_SCALBLN:
     CASE_CFN_SCALBN:
@@ -13583,6 +13586,8 @@ integer_valued_real_call_p (combined_fn fn, tree arg0, tree arg1, int depth)
     CASE_CFN_RINT_FN:
     CASE_CFN_ROUND:
     CASE_CFN_ROUND_FN:
+    CASE_CFN_ROUNDEVEN:
+    CASE_CFN_ROUNDEVEN_FN:
     CASE_CFN_TRUNC:
     CASE_CFN_TRUNC_FN:
       return true;
diff --git a/gcc/internal-fn.def b/gcc/internal-fn.def
index cda314e1121..b89918815f9 100644
--- a/gcc/internal-fn.def
+++ b/gcc/internal-fn.def
@@ -224,6 +224,7 @@ DEF_INTERNAL_FLT_FLOATN_FN (FLOOR, ECF_CONST, floor, unary)
 DEF_INTERNAL_FLT_FLOATN_FN (NEARBYINT, ECF_CONST, nearbyint, unary)
 DEF_INTERNAL_FLT_FLOATN_FN (RINT, ECF_CONST, rint, unary)
 DEF_INTERNAL_FLT_FLOATN_FN (ROUND, ECF_CONST, round, unary)
+DEF_INTERNAL_FLT_FLOATN_FN (ROUNDEVEN, ECF_CONST, roundeven, unary)
 DEF_INTERNAL_FLT_FLOATN_FN (TRUNC, ECF_CONST, btrunc, unary)
 
 /* Binary math functions.  */
diff --git a/gcc/optabs.def b/gcc/optabs.def
index 5a67f5eed5e..eb9e22acd8f 100644
--- a/gcc/optabs.def
+++ b/gcc/optabs.def
@@ -267,6 +267,7 @@ OPTAB_D (fnms_optab, "fnms$a4")
 
 OPTAB_D (rint_optab, "rint$a2")
 OPTAB_D (round_optab, "round$a2")
+OPTAB_D (roundeven_optab, "roundeven$a2")
 OPTAB_D (floor_optab, "floor$a2")
 OPTAB_D (ceil_optab, "ceil$a2")
 OPTAB_D (btrunc_optab, "btrunc$a2")
diff --git a/gcc/real.c b/gcc/real.c
index f822ae82d61..9c57f50e8fc 100644
--- a/gcc/real.c
+++ b/gcc/real.c
@@ -1956,6 +1956,8 @@ real_to_hexadecimal (char *str, const REAL_VALUE_TYPE *r, size_t buf_size,
 int
 real_from_string (REAL_VALUE_TYPE *r, const char *str)
 {
+  fprintf (stderr, "\nreal_from_string: str = %s\n", str);
+      
   int exp = 0;
   bool sign = false;
 
@@ -5004,10 +5006,39 @@ void
 real_round (REAL_VALUE_TYPE *r, format_helper fmt,
 	    const REAL_VALUE_TYPE *x)
 {
+#if 0
   do_add (r, x, &dconsthalf, x->sign);
   do_fix_trunc (r, r);
   if (fmt)
     real_convert (r, fmt, r);
+#endif
+  fprintf (stderr, "\nhere\n");
+  real_value z;
+  do_fix_trunc (&z, x);
+  HOST_WIDE_INT i = real_to_integer (&z);
+  fprintf (stderr, "\n i = %ld\n", i);
+  if (i % 2)
+    do_add (r, &z, &dconstm1, 0);
+  else
+    *r = z;
+}
+
+/* Round X to nearest even integer towards zero. */
+
+void
+real_roundeven (REAL_VALUE_TYPE *r, format_helper fmt,
+		const REAL_VALUE_TYPE *x)
+{
+  REAL_VALUE_TYPE t;
+
+  do_fix_trunc (&t, x);
+  HOST_WIDE_INT i = real_to_integer (&t);
+  fprintf (stderr, "\nhere\n");
+  fprintf (stderr, "\n i = %ld\n", i);
+  if(i % 2)
+    do_add (r, &t, &dconstm1, 0);
+  else
+    *r = t;
 }
 
 /* Set the sign of R to the sign of X.  */
diff --git a/gcc/real.h b/gcc/real.h
index 0ce42565708..10898eae79e 100644
--- a/gcc/real.h
+++ b/gcc/real.h
@@ -499,6 +499,8 @@ extern void real_ceil (REAL_VALUE_TYPE *, format_helper,
 		       const REAL_VALUE_TYPE *);
 extern void real_round (REAL_VALUE_TYPE *, format_helper,
 			const REAL_VALUE_TYPE *);
+extern void real_roundeven (REAL_VALUE_TYPE *, format_helper,
+      const REAL_VALUE_TYPE *);
 
 /* Set the sign of R to the sign of X.  */
 extern void real_copysign (REAL_VALUE_TYPE *, const REAL_VALUE_TYPE *);
diff --git a/gcc/realmpfr.c b/gcc/realmpfr.c
index 10f05caaba3..4834fd017b1 100644
--- a/gcc/realmpfr.c
+++ b/gcc/realmpfr.c
@@ -98,6 +98,7 @@ real_from_mpfr (REAL_VALUE_TYPE *r, mpfr_srcptr m, const real_format *format,
 
   mpfr_free_str (rstr);
 
+  fprintf (stderr, "\nreal_from_mpfr: buf = %s\n", buf);
   real_from_string (r, buf);
 }
 

^ permalink raw reply	[flat|nested] 60+ messages in thread

* Re: About GSOC.
  2019-02-04 16:44                                 ` Prathamesh Kulkarni
@ 2019-02-04 17:22                                   ` Tejas Joshi
  2019-02-24 12:05                                     ` Tejas Joshi
  0 siblings, 1 reply; 60+ messages in thread
From: Tejas Joshi @ 2019-02-04 17:22 UTC (permalink / raw)
  To: gcc

[-- Attachment #1: Type: text/plain, Size: 5492 bytes --]

Hi.
Although now, I am unable to build the compiler.
The build exited returning status as:

DEF_INTERNAL_FLT_FN (ROUNDEVEN) has no associated built-in functions

I have added the entry in fold_const_call_ss() and do not find any
other place to add the case.
Here is the latest patch.

On Mon, 4 Feb 2019 at 22:14, Prathamesh Kulkarni
<prathamesh.kulkarni@linaro.org> wrote:
>
> On Mon, 4 Feb 2019 at 21:27, Tejas Joshi <tejasjoshi9673@gmail.com> wrote:
> >
> > Thanks.
> > > Did you add an entry for roundeven in builtins.def ?
> > Yes, I did.
> >
> > Find here the attached patch.diff for which I did the changes to
> > implement roundeven. There might be some unnecessary changes and some
> > necessary changes which have not been made.
> You haven't called roundeven() in the patch. You'll need to add an
> entry in fold_const_call_ss()
> similar to real_ceil, and probably in other places too.
>
> Thanks,
> Prathamesh
> >
> > Regards,
> > -Tejas
> >
> > On Mon, 4 Feb 2019 at 20:36, Prathamesh Kulkarni
> > <prathamesh.kulkarni@linaro.org> wrote:
> > >
> > > On Mon, 4 Feb 2019 at 20:10, Tejas Joshi <tejasjoshi9673@gmail.com> wrote:
> > > >
> > > > Hello.
> > > > I have implemented roundeven function in real.c as follows: (and
> > > > respective changes in real.h)
> > > It's a better idea to include all changes in patch instead of copy-pasting.
> > > Use the command:
> > > git diff > patch.diff
> > > which will create a file called "patch.diff" containing the changes
> > > and send it as an attachment.
> > > >
> > > > /* Round X to nearest even integer towards zero. */
> > > >
> > > > void
> > > > real_roundeven (REAL_VALUE_TYPE *r, format_helper fmt,
> > > >         const REAL_VALUE_TYPE *x)
> > > > {
> > > >   REAL_VALUE_TYPE t;
> > > >
> > > >   do_fix_trunc (&t, x);
> > > >   HOST_WIDE_INT i = real_to_integer (&t);
> > > >   if(i % 2)
> > > >     do_add (r, &t, &dconstm1, 0);
> > > >   else
> > > >     *r = t;
> > > > }
> > > >
> > > > Although I cant get it to test like
> > > >
> > > > int foo()
> > > > {
> > > >     double x = __builtin_roundeven (3.5);
> > > >     printf("%f",x);
> > > >     return (int) x;
> > > > }
> > > > Because I do not know its dependencies through other files. I tried to
> > > > track them down by inspecting real_ceil function, but it also includes
> > > > other optimization procedures like folding. How do I know enough
> > > > declarations to be made in respective files?
> > > Did you add an entry for roundeven in builtins.def ?
> > >
> > > Thanks,
> > > Prathamesh
> > > >
> > > > Thanks.
> > > > -Tejas
> > > >
> > > > On Mon, 28 Jan 2019 at 22:33, Tejas Joshi <tejasjoshi9673@gmail.com> wrote:
> > > > >
> > > > > Hello.
> > > > > Representations of real numbers in real.c are a little complex to
> > > > > understand right now for me. I am still trying to understand them and
> > > > > figure them out using gdb and cscope. Though conventions are given in
> > > > > comments in real.c, I will still be trying to figure it out. The
> > > > > equation and its bitwise representation is not pretty elaborated in
> > > > > any documentation I could find.
> > > > >
> > > > > x = s * b^e * \sum_{k=1}^p f_k * b^{-k}
> > > > >
> > > > >     where
> > > > >         s = sign (+- 1)
> > > > >         b = base or radix, here always 2
> > > > >         e = exponent
> > > > >         p = precision (the number of base-b digits in the significand)
> > > > >         f_k = the digits of the significand.
> > > > >
> > > > > In mean time, I've tried real_round function to work like roundeven. I
> > > > > will try to submit a clean patch along with roundeven implemented
> > > > > separately with changes like in builtins.def, adding cases, etc.
> > > > >
> > > > > void
> > > > > real_round (REAL_VALUE_TYPE *r, format_helper fmt,
> > > > >         const REAL_VALUE_TYPE *x)
> > > > > {
> > > > > #if 0
> > > > >   do_add (r, x, &dconsthalf, x->sign);
> > > > >   do_fix_trunc (r, r);
> > > > >   if (fmt)
> > > > >     real_convert (r, fmt, r);
> > > > > #endif
> > > > >   fprintf (stderr, "\nhere\n");
> > > > >   real_value z;
> > > > >   do_fix_trunc (&z, x);
> > > > >   HOST_WIDE_INT i = real_to_integer (&z);
> > > > >   fprintf (stderr, "\n i = %ld\n", i);
> > > > >   if (i % 2)
> > > > >     do_add (r, &z, &dconstm1, 0);
> > > > >   else
> > > > >     *r = z;
> > > > > }
> > > > >
> > > > > Thanks.
> > > > > -Tejas
> > > > >
> > > > > On Sat, 26 Jan 2019 at 03:02, Joseph Myers <joseph@codesourcery.com> wrote:
> > > > > >
> > > > > > On Sat, 26 Jan 2019, Tejas Joshi wrote:
> > > > > >
> > > > > > > function with byte-byte comparison which also include mpfr. (Correct
> > > > > > > me if I am wrong.) What is the significance of mpfr related to these
> > > > > > > internal representations?
> > > > > >
> > > > > > real.c provides a fixed-size representation of floating-point numbers that
> > > > > > allows for various non-IEEE formats supported by GCC, and also allows
> > > > > > functions from dfp.c to be used for decimal floating-point formats.
> > > > > >
> > > > > > MPFR is used in GCC to provide operations that are nontrivial to
> > > > > > implement, especially those that are nontrivial to implement in such a
> > > > > > fixed-size context.  real.c operations wrap around MPFR ones where
> > > > > > appropriate, doing whatever's needed in cases where there are non-IEEE
> > > > > > semantics or sets of values.
> > > > > >
> > > > > > --
> > > > > > Joseph S. Myers
> > > > > > joseph@codesourcery.com

[-- Attachment #2: patch.diff --]
[-- Type: text/x-patch, Size: 5556 bytes --]

diff --git a/gcc/builtins.c b/gcc/builtins.c
index 25e01e4092b..25282d2122d 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_FLOATN (ROUNDEVEN)
     CASE_MATHFN (SCALB)
     CASE_MATHFN (SCALBLN)
     CASE_MATHFN (SCALBN)
diff --git a/gcc/builtins.def b/gcc/builtins.def
index ef89729fd0c..f1b6830a49c 100644
--- a/gcc/builtins.def
+++ b/gcc/builtins.def
@@ -308,6 +308,7 @@ DEF_C99_BUILTIN        (BUILT_IN_CBRT, "cbrt", BT_FN_DOUBLE_DOUBLE, ATTR_MATHFN_
 DEF_C99_BUILTIN        (BUILT_IN_CBRTF, "cbrtf", BT_FN_FLOAT_FLOAT, ATTR_MATHFN_FPROUNDING)
 DEF_C99_BUILTIN        (BUILT_IN_CBRTL, "cbrtl", BT_FN_LONGDOUBLE_LONGDOUBLE, ATTR_MATHFN_FPROUNDING)
 DEF_LIB_BUILTIN        (BUILT_IN_CEIL, "ceil", BT_FN_DOUBLE_DOUBLE, ATTR_CONST_NOTHROW_LEAF_LIST)
+DEF_EXT_LIB_BUILTIN    (BUILT_IN_ROUNDEVEN, "roundeven", BT_FN_DOUBLE_DOUBLE, ATTR_CONST_NOTHROW_LEAF_LIST)
 DEF_C99_C90RES_BUILTIN (BUILT_IN_CEILF, "ceilf", BT_FN_FLOAT_FLOAT, ATTR_CONST_NOTHROW_LEAF_LIST)
 DEF_C99_C90RES_BUILTIN (BUILT_IN_CEILL, "ceill", BT_FN_LONGDOUBLE_LONGDOUBLE, ATTR_CONST_NOTHROW_LEAF_LIST)
 #define CEIL_TYPE(F) BT_FN_##F##_##F
diff --git a/gcc/fold-const-call.c b/gcc/fold-const-call.c
index 06a420601c0..6f4fea63b0c 100644
--- a/gcc/fold-const-call.c
+++ b/gcc/fold-const-call.c
@@ -773,6 +773,16 @@ fold_const_call_ss (real_value *result, combined_fn fn,
     CASE_CFN_CEIL_FN:
       if (!REAL_VALUE_ISNAN (*arg) || !flag_errno_math)
 	{
+	  fprintf (stderr, "\n");
+	  fprintf (stderr, "cl: %u\n", arg->cl);
+	  fprintf (stderr, "sign: %u\n", arg->sign);
+	  fprintf (stderr, "signalling: %u\n", arg->signalling);
+	  fprintf (stderr, "canonical: %u\n", arg->canonical);
+	  fprintf (stderr, "uexp: %u\n", arg->uexp);
+	  
+	  fprintf (stderr, "sig: ");
+	  for (int i = 0; i < SIGSZ; i++)
+	    fprintf (stderr, "%lx ", arg->sig[i]);
 	  real_ceil (result, format, arg);
 	  return true;
 	}
@@ -792,6 +802,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_const_logb (result, arg, format);
 
diff --git a/gcc/internal-fn.def b/gcc/internal-fn.def
index cda314e1121..b89918815f9 100644
--- a/gcc/internal-fn.def
+++ b/gcc/internal-fn.def
@@ -224,6 +224,7 @@ DEF_INTERNAL_FLT_FLOATN_FN (FLOOR, ECF_CONST, floor, unary)
 DEF_INTERNAL_FLT_FLOATN_FN (NEARBYINT, ECF_CONST, nearbyint, unary)
 DEF_INTERNAL_FLT_FLOATN_FN (RINT, ECF_CONST, rint, unary)
 DEF_INTERNAL_FLT_FLOATN_FN (ROUND, ECF_CONST, round, unary)
+DEF_INTERNAL_FLT_FLOATN_FN (ROUNDEVEN, ECF_CONST, roundeven, unary)
 DEF_INTERNAL_FLT_FLOATN_FN (TRUNC, ECF_CONST, btrunc, unary)
 
 /* Binary math functions.  */
diff --git a/gcc/optabs.def b/gcc/optabs.def
index 5a67f5eed5e..eb9e22acd8f 100644
--- a/gcc/optabs.def
+++ b/gcc/optabs.def
@@ -267,6 +267,7 @@ OPTAB_D (fnms_optab, "fnms$a4")
 
 OPTAB_D (rint_optab, "rint$a2")
 OPTAB_D (round_optab, "round$a2")
+OPTAB_D (roundeven_optab, "roundeven$a2")
 OPTAB_D (floor_optab, "floor$a2")
 OPTAB_D (ceil_optab, "ceil$a2")
 OPTAB_D (btrunc_optab, "btrunc$a2")
diff --git a/gcc/real.c b/gcc/real.c
index f822ae82d61..9c57f50e8fc 100644
--- a/gcc/real.c
+++ b/gcc/real.c
@@ -1956,6 +1956,8 @@ real_to_hexadecimal (char *str, const REAL_VALUE_TYPE *r, size_t buf_size,
 int
 real_from_string (REAL_VALUE_TYPE *r, const char *str)
 {
+  fprintf (stderr, "\nreal_from_string: str = %s\n", str);
+      
   int exp = 0;
   bool sign = false;
 
@@ -5004,10 +5006,39 @@ void
 real_round (REAL_VALUE_TYPE *r, format_helper fmt,
 	    const REAL_VALUE_TYPE *x)
 {
+#if 0
   do_add (r, x, &dconsthalf, x->sign);
   do_fix_trunc (r, r);
   if (fmt)
     real_convert (r, fmt, r);
+#endif
+  fprintf (stderr, "\nhere\n");
+  real_value z;
+  do_fix_trunc (&z, x);
+  HOST_WIDE_INT i = real_to_integer (&z);
+  fprintf (stderr, "\n i = %ld\n", i);
+  if (i % 2)
+    do_add (r, &z, &dconstm1, 0);
+  else
+    *r = z;
+}
+
+/* Round X to nearest even integer towards zero. */
+
+void
+real_roundeven (REAL_VALUE_TYPE *r, format_helper fmt,
+		const REAL_VALUE_TYPE *x)
+{
+  REAL_VALUE_TYPE t;
+
+  do_fix_trunc (&t, x);
+  HOST_WIDE_INT i = real_to_integer (&t);
+  fprintf (stderr, "\nhere\n");
+  fprintf (stderr, "\n i = %ld\n", i);
+  if(i % 2)
+    do_add (r, &t, &dconstm1, 0);
+  else
+    *r = t;
 }
 
 /* Set the sign of R to the sign of X.  */
diff --git a/gcc/real.h b/gcc/real.h
index 0ce42565708..10898eae79e 100644
--- a/gcc/real.h
+++ b/gcc/real.h
@@ -499,6 +499,8 @@ extern void real_ceil (REAL_VALUE_TYPE *, format_helper,
 		       const REAL_VALUE_TYPE *);
 extern void real_round (REAL_VALUE_TYPE *, format_helper,
 			const REAL_VALUE_TYPE *);
+extern void real_roundeven (REAL_VALUE_TYPE *, format_helper,
+      const REAL_VALUE_TYPE *);
 
 /* Set the sign of R to the sign of X.  */
 extern void real_copysign (REAL_VALUE_TYPE *, const REAL_VALUE_TYPE *);
diff --git a/gcc/realmpfr.c b/gcc/realmpfr.c
index 10f05caaba3..4834fd017b1 100644
--- a/gcc/realmpfr.c
+++ b/gcc/realmpfr.c
@@ -98,6 +98,7 @@ real_from_mpfr (REAL_VALUE_TYPE *r, mpfr_srcptr m, const real_format *format,
 
   mpfr_free_str (rstr);
 
+  fprintf (stderr, "\nreal_from_mpfr: buf = %s\n", buf);
   real_from_string (r, buf);
 }
 

^ permalink raw reply	[flat|nested] 60+ messages in thread

* Re: About GSOC.
  2019-02-04 15:56                               ` Tejas Joshi
@ 2019-02-04 16:44                                 ` Prathamesh Kulkarni
  2019-02-04 17:22                                   ` Tejas Joshi
  0 siblings, 1 reply; 60+ messages in thread
From: Prathamesh Kulkarni @ 2019-02-04 16:44 UTC (permalink / raw)
  To: Tejas Joshi; +Cc: GCC Development

On Mon, 4 Feb 2019 at 21:27, Tejas Joshi <tejasjoshi9673@gmail.com> wrote:
>
> Thanks.
> > Did you add an entry for roundeven in builtins.def ?
> Yes, I did.
>
> Find here the attached patch.diff for which I did the changes to
> implement roundeven. There might be some unnecessary changes and some
> necessary changes which have not been made.
You haven't called roundeven() in the patch. You'll need to add an
entry in fold_const_call_ss()
similar to real_ceil, and probably in other places too.

Thanks,
Prathamesh
>
> Regards,
> -Tejas
>
> On Mon, 4 Feb 2019 at 20:36, Prathamesh Kulkarni
> <prathamesh.kulkarni@linaro.org> wrote:
> >
> > On Mon, 4 Feb 2019 at 20:10, Tejas Joshi <tejasjoshi9673@gmail.com> wrote:
> > >
> > > Hello.
> > > I have implemented roundeven function in real.c as follows: (and
> > > respective changes in real.h)
> > It's a better idea to include all changes in patch instead of copy-pasting.
> > Use the command:
> > git diff > patch.diff
> > which will create a file called "patch.diff" containing the changes
> > and send it as an attachment.
> > >
> > > /* Round X to nearest even integer towards zero. */
> > >
> > > void
> > > real_roundeven (REAL_VALUE_TYPE *r, format_helper fmt,
> > >         const REAL_VALUE_TYPE *x)
> > > {
> > >   REAL_VALUE_TYPE t;
> > >
> > >   do_fix_trunc (&t, x);
> > >   HOST_WIDE_INT i = real_to_integer (&t);
> > >   if(i % 2)
> > >     do_add (r, &t, &dconstm1, 0);
> > >   else
> > >     *r = t;
> > > }
> > >
> > > Although I cant get it to test like
> > >
> > > int foo()
> > > {
> > >     double x = __builtin_roundeven (3.5);
> > >     printf("%f",x);
> > >     return (int) x;
> > > }
> > > Because I do not know its dependencies through other files. I tried to
> > > track them down by inspecting real_ceil function, but it also includes
> > > other optimization procedures like folding. How do I know enough
> > > declarations to be made in respective files?
> > Did you add an entry for roundeven in builtins.def ?
> >
> > Thanks,
> > Prathamesh
> > >
> > > Thanks.
> > > -Tejas
> > >
> > > On Mon, 28 Jan 2019 at 22:33, Tejas Joshi <tejasjoshi9673@gmail.com> wrote:
> > > >
> > > > Hello.
> > > > Representations of real numbers in real.c are a little complex to
> > > > understand right now for me. I am still trying to understand them and
> > > > figure them out using gdb and cscope. Though conventions are given in
> > > > comments in real.c, I will still be trying to figure it out. The
> > > > equation and its bitwise representation is not pretty elaborated in
> > > > any documentation I could find.
> > > >
> > > > x = s * b^e * \sum_{k=1}^p f_k * b^{-k}
> > > >
> > > >     where
> > > >         s = sign (+- 1)
> > > >         b = base or radix, here always 2
> > > >         e = exponent
> > > >         p = precision (the number of base-b digits in the significand)
> > > >         f_k = the digits of the significand.
> > > >
> > > > In mean time, I've tried real_round function to work like roundeven. I
> > > > will try to submit a clean patch along with roundeven implemented
> > > > separately with changes like in builtins.def, adding cases, etc.
> > > >
> > > > void
> > > > real_round (REAL_VALUE_TYPE *r, format_helper fmt,
> > > >         const REAL_VALUE_TYPE *x)
> > > > {
> > > > #if 0
> > > >   do_add (r, x, &dconsthalf, x->sign);
> > > >   do_fix_trunc (r, r);
> > > >   if (fmt)
> > > >     real_convert (r, fmt, r);
> > > > #endif
> > > >   fprintf (stderr, "\nhere\n");
> > > >   real_value z;
> > > >   do_fix_trunc (&z, x);
> > > >   HOST_WIDE_INT i = real_to_integer (&z);
> > > >   fprintf (stderr, "\n i = %ld\n", i);
> > > >   if (i % 2)
> > > >     do_add (r, &z, &dconstm1, 0);
> > > >   else
> > > >     *r = z;
> > > > }
> > > >
> > > > Thanks.
> > > > -Tejas
> > > >
> > > > On Sat, 26 Jan 2019 at 03:02, Joseph Myers <joseph@codesourcery.com> wrote:
> > > > >
> > > > > On Sat, 26 Jan 2019, Tejas Joshi wrote:
> > > > >
> > > > > > function with byte-byte comparison which also include mpfr. (Correct
> > > > > > me if I am wrong.) What is the significance of mpfr related to these
> > > > > > internal representations?
> > > > >
> > > > > real.c provides a fixed-size representation of floating-point numbers that
> > > > > allows for various non-IEEE formats supported by GCC, and also allows
> > > > > functions from dfp.c to be used for decimal floating-point formats.
> > > > >
> > > > > MPFR is used in GCC to provide operations that are nontrivial to
> > > > > implement, especially those that are nontrivial to implement in such a
> > > > > fixed-size context.  real.c operations wrap around MPFR ones where
> > > > > appropriate, doing whatever's needed in cases where there are non-IEEE
> > > > > semantics or sets of values.
> > > > >
> > > > > --
> > > > > Joseph S. Myers
> > > > > joseph@codesourcery.com

^ permalink raw reply	[flat|nested] 60+ messages in thread

* Re: About GSOC.
  2019-02-04 15:06                             ` Prathamesh Kulkarni
@ 2019-02-04 15:56                               ` Tejas Joshi
  2019-02-04 16:44                                 ` Prathamesh Kulkarni
  0 siblings, 1 reply; 60+ messages in thread
From: Tejas Joshi @ 2019-02-04 15:56 UTC (permalink / raw)
  To: gcc

[-- Attachment #1: Type: text/plain, Size: 4338 bytes --]

Thanks.
> Did you add an entry for roundeven in builtins.def ?
Yes, I did.

Find here the attached patch.diff for which I did the changes to
implement roundeven. There might be some unnecessary changes and some
necessary changes which have not been made.

Regards,
-Tejas

On Mon, 4 Feb 2019 at 20:36, Prathamesh Kulkarni
<prathamesh.kulkarni@linaro.org> wrote:
>
> On Mon, 4 Feb 2019 at 20:10, Tejas Joshi <tejasjoshi9673@gmail.com> wrote:
> >
> > Hello.
> > I have implemented roundeven function in real.c as follows: (and
> > respective changes in real.h)
> It's a better idea to include all changes in patch instead of copy-pasting.
> Use the command:
> git diff > patch.diff
> which will create a file called "patch.diff" containing the changes
> and send it as an attachment.
> >
> > /* Round X to nearest even integer towards zero. */
> >
> > void
> > real_roundeven (REAL_VALUE_TYPE *r, format_helper fmt,
> >         const REAL_VALUE_TYPE *x)
> > {
> >   REAL_VALUE_TYPE t;
> >
> >   do_fix_trunc (&t, x);
> >   HOST_WIDE_INT i = real_to_integer (&t);
> >   if(i % 2)
> >     do_add (r, &t, &dconstm1, 0);
> >   else
> >     *r = t;
> > }
> >
> > Although I cant get it to test like
> >
> > int foo()
> > {
> >     double x = __builtin_roundeven (3.5);
> >     printf("%f",x);
> >     return (int) x;
> > }
> > Because I do not know its dependencies through other files. I tried to
> > track them down by inspecting real_ceil function, but it also includes
> > other optimization procedures like folding. How do I know enough
> > declarations to be made in respective files?
> Did you add an entry for roundeven in builtins.def ?
>
> Thanks,
> Prathamesh
> >
> > Thanks.
> > -Tejas
> >
> > On Mon, 28 Jan 2019 at 22:33, Tejas Joshi <tejasjoshi9673@gmail.com> wrote:
> > >
> > > Hello.
> > > Representations of real numbers in real.c are a little complex to
> > > understand right now for me. I am still trying to understand them and
> > > figure them out using gdb and cscope. Though conventions are given in
> > > comments in real.c, I will still be trying to figure it out. The
> > > equation and its bitwise representation is not pretty elaborated in
> > > any documentation I could find.
> > >
> > > x = s * b^e * \sum_{k=1}^p f_k * b^{-k}
> > >
> > >     where
> > >         s = sign (+- 1)
> > >         b = base or radix, here always 2
> > >         e = exponent
> > >         p = precision (the number of base-b digits in the significand)
> > >         f_k = the digits of the significand.
> > >
> > > In mean time, I've tried real_round function to work like roundeven. I
> > > will try to submit a clean patch along with roundeven implemented
> > > separately with changes like in builtins.def, adding cases, etc.
> > >
> > > void
> > > real_round (REAL_VALUE_TYPE *r, format_helper fmt,
> > >         const REAL_VALUE_TYPE *x)
> > > {
> > > #if 0
> > >   do_add (r, x, &dconsthalf, x->sign);
> > >   do_fix_trunc (r, r);
> > >   if (fmt)
> > >     real_convert (r, fmt, r);
> > > #endif
> > >   fprintf (stderr, "\nhere\n");
> > >   real_value z;
> > >   do_fix_trunc (&z, x);
> > >   HOST_WIDE_INT i = real_to_integer (&z);
> > >   fprintf (stderr, "\n i = %ld\n", i);
> > >   if (i % 2)
> > >     do_add (r, &z, &dconstm1, 0);
> > >   else
> > >     *r = z;
> > > }
> > >
> > > Thanks.
> > > -Tejas
> > >
> > > On Sat, 26 Jan 2019 at 03:02, Joseph Myers <joseph@codesourcery.com> wrote:
> > > >
> > > > On Sat, 26 Jan 2019, Tejas Joshi wrote:
> > > >
> > > > > function with byte-byte comparison which also include mpfr. (Correct
> > > > > me if I am wrong.) What is the significance of mpfr related to these
> > > > > internal representations?
> > > >
> > > > real.c provides a fixed-size representation of floating-point numbers that
> > > > allows for various non-IEEE formats supported by GCC, and also allows
> > > > functions from dfp.c to be used for decimal floating-point formats.
> > > >
> > > > MPFR is used in GCC to provide operations that are nontrivial to
> > > > implement, especially those that are nontrivial to implement in such a
> > > > fixed-size context.  real.c operations wrap around MPFR ones where
> > > > appropriate, doing whatever's needed in cases where there are non-IEEE
> > > > semantics or sets of values.
> > > >
> > > > --
> > > > Joseph S. Myers
> > > > joseph@codesourcery.com

[-- Attachment #2: patch.diff --]
[-- Type: text/x-patch, Size: 3352 bytes --]

diff --git a/gcc/builtins.c b/gcc/builtins.c
index 25e01e4092b..25282d2122d 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_FLOATN (ROUNDEVEN)
     CASE_MATHFN (SCALB)
     CASE_MATHFN (SCALBLN)
     CASE_MATHFN (SCALBN)
diff --git a/gcc/builtins.def b/gcc/builtins.def
index ef89729fd0c..f1b6830a49c 100644
--- a/gcc/builtins.def
+++ b/gcc/builtins.def
@@ -308,6 +308,7 @@ DEF_C99_BUILTIN        (BUILT_IN_CBRT, "cbrt", BT_FN_DOUBLE_DOUBLE, ATTR_MATHFN_
 DEF_C99_BUILTIN        (BUILT_IN_CBRTF, "cbrtf", BT_FN_FLOAT_FLOAT, ATTR_MATHFN_FPROUNDING)
 DEF_C99_BUILTIN        (BUILT_IN_CBRTL, "cbrtl", BT_FN_LONGDOUBLE_LONGDOUBLE, ATTR_MATHFN_FPROUNDING)
 DEF_LIB_BUILTIN        (BUILT_IN_CEIL, "ceil", BT_FN_DOUBLE_DOUBLE, ATTR_CONST_NOTHROW_LEAF_LIST)
+DEF_EXT_LIB_BUILTIN    (BUILT_IN_ROUNDEVEN, "roundeven", BT_FN_DOUBLE_DOUBLE, ATTR_CONST_NOTHROW_LEAF_LIST)
 DEF_C99_C90RES_BUILTIN (BUILT_IN_CEILF, "ceilf", BT_FN_FLOAT_FLOAT, ATTR_CONST_NOTHROW_LEAF_LIST)
 DEF_C99_C90RES_BUILTIN (BUILT_IN_CEILL, "ceill", BT_FN_LONGDOUBLE_LONGDOUBLE, ATTR_CONST_NOTHROW_LEAF_LIST)
 #define CEIL_TYPE(F) BT_FN_##F##_##F
diff --git a/gcc/internal-fn.def b/gcc/internal-fn.def
index cda314e1121..b89918815f9 100644
--- a/gcc/internal-fn.def
+++ b/gcc/internal-fn.def
@@ -224,6 +224,7 @@ DEF_INTERNAL_FLT_FLOATN_FN (FLOOR, ECF_CONST, floor, unary)
 DEF_INTERNAL_FLT_FLOATN_FN (NEARBYINT, ECF_CONST, nearbyint, unary)
 DEF_INTERNAL_FLT_FLOATN_FN (RINT, ECF_CONST, rint, unary)
 DEF_INTERNAL_FLT_FLOATN_FN (ROUND, ECF_CONST, round, unary)
+DEF_INTERNAL_FLT_FLOATN_FN (ROUNDEVEN, ECF_CONST, roundeven, unary)
 DEF_INTERNAL_FLT_FLOATN_FN (TRUNC, ECF_CONST, btrunc, unary)
 
 /* Binary math functions.  */
diff --git a/gcc/optabs.def b/gcc/optabs.def
index 5a67f5eed5e..eb9e22acd8f 100644
--- a/gcc/optabs.def
+++ b/gcc/optabs.def
@@ -267,6 +267,7 @@ OPTAB_D (fnms_optab, "fnms$a4")
 
 OPTAB_D (rint_optab, "rint$a2")
 OPTAB_D (round_optab, "round$a2")
+OPTAB_D (roundeven_optab, "roundeven$a2")
 OPTAB_D (floor_optab, "floor$a2")
 OPTAB_D (ceil_optab, "ceil$a2")
 OPTAB_D (btrunc_optab, "btrunc$a2")
diff --git a/gcc/real.c b/gcc/real.c
index f822ae82d61..9c57f50e8fc 100644
--- a/gcc/real.c
+++ b/gcc/real.c
@@ -5004,10 +5006,39 @@ void
+/* Round X to nearest even integer towards zero. */
+
+void
+real_roundeven (REAL_VALUE_TYPE *r, format_helper fmt,
+		const REAL_VALUE_TYPE *x)
+{
+  REAL_VALUE_TYPE t;
+
+  do_fix_trunc (&t, x);
+  HOST_WIDE_INT i = real_to_integer (&t);
+  fprintf (stderr, "\nhere\n");
+  fprintf (stderr, "\n i = %ld\n", i);
+  if(i % 2)
+    do_add (r, &t, &dconstm1, 0);
+  else
+    *r = t;
 }
 
 /* Set the sign of R to the sign of X.  */
diff --git a/gcc/real.h b/gcc/real.h
index 0ce42565708..10898eae79e 100644
--- a/gcc/real.h
+++ b/gcc/real.h
@@ -499,6 +499,8 @@ extern void real_ceil (REAL_VALUE_TYPE *, format_helper,
 		       const REAL_VALUE_TYPE *);
 extern void real_round (REAL_VALUE_TYPE *, format_helper,
 			const REAL_VALUE_TYPE *);
+extern void real_roundeven (REAL_VALUE_TYPE *, format_helper,
+      const REAL_VALUE_TYPE *);
 
 /* Set the sign of R to the sign of X.  */
 extern void real_copysign (REAL_VALUE_TYPE *, const REAL_VALUE_TYPE *);

 

^ permalink raw reply	[flat|nested] 60+ messages in thread

* Re: About GSOC.
  2019-02-04 14:39                           ` Tejas Joshi
@ 2019-02-04 15:06                             ` Prathamesh Kulkarni
  2019-02-04 15:56                               ` Tejas Joshi
  0 siblings, 1 reply; 60+ messages in thread
From: Prathamesh Kulkarni @ 2019-02-04 15:06 UTC (permalink / raw)
  To: Tejas Joshi; +Cc: GCC Development

On Mon, 4 Feb 2019 at 20:10, Tejas Joshi <tejasjoshi9673@gmail.com> wrote:
>
> Hello.
> I have implemented roundeven function in real.c as follows: (and
> respective changes in real.h)
It's a better idea to include all changes in patch instead of copy-pasting.
Use the command:
git diff > patch.diff
which will create a file called "patch.diff" containing the changes
and send it as an attachment.
>
> /* Round X to nearest even integer towards zero. */
>
> void
> real_roundeven (REAL_VALUE_TYPE *r, format_helper fmt,
>         const REAL_VALUE_TYPE *x)
> {
>   REAL_VALUE_TYPE t;
>
>   do_fix_trunc (&t, x);
>   HOST_WIDE_INT i = real_to_integer (&t);
>   if(i % 2)
>     do_add (r, &t, &dconstm1, 0);
>   else
>     *r = t;
> }
>
> Although I cant get it to test like
>
> int foo()
> {
>     double x = __builtin_roundeven (3.5);
>     printf("%f",x);
>     return (int) x;
> }
> Because I do not know its dependencies through other files. I tried to
> track them down by inspecting real_ceil function, but it also includes
> other optimization procedures like folding. How do I know enough
> declarations to be made in respective files?
Did you add an entry for roundeven in builtins.def ?

Thanks,
Prathamesh
>
> Thanks.
> -Tejas
>
> On Mon, 28 Jan 2019 at 22:33, Tejas Joshi <tejasjoshi9673@gmail.com> wrote:
> >
> > Hello.
> > Representations of real numbers in real.c are a little complex to
> > understand right now for me. I am still trying to understand them and
> > figure them out using gdb and cscope. Though conventions are given in
> > comments in real.c, I will still be trying to figure it out. The
> > equation and its bitwise representation is not pretty elaborated in
> > any documentation I could find.
> >
> > x = s * b^e * \sum_{k=1}^p f_k * b^{-k}
> >
> >     where
> >         s = sign (+- 1)
> >         b = base or radix, here always 2
> >         e = exponent
> >         p = precision (the number of base-b digits in the significand)
> >         f_k = the digits of the significand.
> >
> > In mean time, I've tried real_round function to work like roundeven. I
> > will try to submit a clean patch along with roundeven implemented
> > separately with changes like in builtins.def, adding cases, etc.
> >
> > void
> > real_round (REAL_VALUE_TYPE *r, format_helper fmt,
> >         const REAL_VALUE_TYPE *x)
> > {
> > #if 0
> >   do_add (r, x, &dconsthalf, x->sign);
> >   do_fix_trunc (r, r);
> >   if (fmt)
> >     real_convert (r, fmt, r);
> > #endif
> >   fprintf (stderr, "\nhere\n");
> >   real_value z;
> >   do_fix_trunc (&z, x);
> >   HOST_WIDE_INT i = real_to_integer (&z);
> >   fprintf (stderr, "\n i = %ld\n", i);
> >   if (i % 2)
> >     do_add (r, &z, &dconstm1, 0);
> >   else
> >     *r = z;
> > }
> >
> > Thanks.
> > -Tejas
> >
> > On Sat, 26 Jan 2019 at 03:02, Joseph Myers <joseph@codesourcery.com> wrote:
> > >
> > > On Sat, 26 Jan 2019, Tejas Joshi wrote:
> > >
> > > > function with byte-byte comparison which also include mpfr. (Correct
> > > > me if I am wrong.) What is the significance of mpfr related to these
> > > > internal representations?
> > >
> > > real.c provides a fixed-size representation of floating-point numbers that
> > > allows for various non-IEEE formats supported by GCC, and also allows
> > > functions from dfp.c to be used for decimal floating-point formats.
> > >
> > > MPFR is used in GCC to provide operations that are nontrivial to
> > > implement, especially those that are nontrivial to implement in such a
> > > fixed-size context.  real.c operations wrap around MPFR ones where
> > > appropriate, doing whatever's needed in cases where there are non-IEEE
> > > semantics or sets of values.
> > >
> > > --
> > > Joseph S. Myers
> > > joseph@codesourcery.com

^ permalink raw reply	[flat|nested] 60+ messages in thread

* Re: About GSOC.
  2019-01-28 17:00                         ` Tejas Joshi
@ 2019-02-04 14:39                           ` Tejas Joshi
  2019-02-04 15:06                             ` Prathamesh Kulkarni
  0 siblings, 1 reply; 60+ messages in thread
From: Tejas Joshi @ 2019-02-04 14:39 UTC (permalink / raw)
  To: gcc

Hello.
I have implemented roundeven function in real.c as follows: (and
respective changes in real.h)

/* Round X to nearest even integer towards zero. */

void
real_roundeven (REAL_VALUE_TYPE *r, format_helper fmt,
        const REAL_VALUE_TYPE *x)
{
  REAL_VALUE_TYPE t;

  do_fix_trunc (&t, x);
  HOST_WIDE_INT i = real_to_integer (&t);
  if(i % 2)
    do_add (r, &t, &dconstm1, 0);
  else
    *r = t;
}

Although I cant get it to test like

int foo()
{
    double x = __builtin_roundeven (3.5);
    printf("%f",x);
    return (int) x;
}
Because I do not know its dependencies through other files. I tried to
track them down by inspecting real_ceil function, but it also includes
other optimization procedures like folding. How do I know enough
declarations to be made in respective files?

Thanks.
-Tejas

On Mon, 28 Jan 2019 at 22:33, Tejas Joshi <tejasjoshi9673@gmail.com> wrote:
>
> Hello.
> Representations of real numbers in real.c are a little complex to
> understand right now for me. I am still trying to understand them and
> figure them out using gdb and cscope. Though conventions are given in
> comments in real.c, I will still be trying to figure it out. The
> equation and its bitwise representation is not pretty elaborated in
> any documentation I could find.
>
> x = s * b^e * \sum_{k=1}^p f_k * b^{-k}
>
>     where
>         s = sign (+- 1)
>         b = base or radix, here always 2
>         e = exponent
>         p = precision (the number of base-b digits in the significand)
>         f_k = the digits of the significand.
>
> In mean time, I've tried real_round function to work like roundeven. I
> will try to submit a clean patch along with roundeven implemented
> separately with changes like in builtins.def, adding cases, etc.
>
> void
> real_round (REAL_VALUE_TYPE *r, format_helper fmt,
>         const REAL_VALUE_TYPE *x)
> {
> #if 0
>   do_add (r, x, &dconsthalf, x->sign);
>   do_fix_trunc (r, r);
>   if (fmt)
>     real_convert (r, fmt, r);
> #endif
>   fprintf (stderr, "\nhere\n");
>   real_value z;
>   do_fix_trunc (&z, x);
>   HOST_WIDE_INT i = real_to_integer (&z);
>   fprintf (stderr, "\n i = %ld\n", i);
>   if (i % 2)
>     do_add (r, &z, &dconstm1, 0);
>   else
>     *r = z;
> }
>
> Thanks.
> -Tejas
>
> On Sat, 26 Jan 2019 at 03:02, Joseph Myers <joseph@codesourcery.com> wrote:
> >
> > On Sat, 26 Jan 2019, Tejas Joshi wrote:
> >
> > > function with byte-byte comparison which also include mpfr. (Correct
> > > me if I am wrong.) What is the significance of mpfr related to these
> > > internal representations?
> >
> > real.c provides a fixed-size representation of floating-point numbers that
> > allows for various non-IEEE formats supported by GCC, and also allows
> > functions from dfp.c to be used for decimal floating-point formats.
> >
> > MPFR is used in GCC to provide operations that are nontrivial to
> > implement, especially those that are nontrivial to implement in such a
> > fixed-size context.  real.c operations wrap around MPFR ones where
> > appropriate, doing whatever's needed in cases where there are non-IEEE
> > semantics or sets of values.
> >
> > --
> > Joseph S. Myers
> > joseph@codesourcery.com

^ permalink raw reply	[flat|nested] 60+ messages in thread

* Re: About GSOC.
  2019-01-25 21:32                       ` Joseph Myers
@ 2019-01-28 17:00                         ` Tejas Joshi
  2019-02-04 14:39                           ` Tejas Joshi
  0 siblings, 1 reply; 60+ messages in thread
From: Tejas Joshi @ 2019-01-28 17:00 UTC (permalink / raw)
  To: gcc

Hello.
Representations of real numbers in real.c are a little complex to
understand right now for me. I am still trying to understand them and
figure them out using gdb and cscope. Though conventions are given in
comments in real.c, I will still be trying to figure it out. The
equation and its bitwise representation is not pretty elaborated in
any documentation I could find.

x = s * b^e * \sum_{k=1}^p f_k * b^{-k}

    where
        s = sign (+- 1)
        b = base or radix, here always 2
        e = exponent
        p = precision (the number of base-b digits in the significand)
        f_k = the digits of the significand.

In mean time, I've tried real_round function to work like roundeven. I
will try to submit a clean patch along with roundeven implemented
separately with changes like in builtins.def, adding cases, etc.

void
real_round (REAL_VALUE_TYPE *r, format_helper fmt,
        const REAL_VALUE_TYPE *x)
{
#if 0
  do_add (r, x, &dconsthalf, x->sign);
  do_fix_trunc (r, r);
  if (fmt)
    real_convert (r, fmt, r);
#endif
  fprintf (stderr, "\nhere\n");
  real_value z;
  do_fix_trunc (&z, x);
  HOST_WIDE_INT i = real_to_integer (&z);
  fprintf (stderr, "\n i = %ld\n", i);
  if (i % 2)
    do_add (r, &z, &dconstm1, 0);
  else
    *r = z;
}

Thanks.
-Tejas

On Sat, 26 Jan 2019 at 03:02, Joseph Myers <joseph@codesourcery.com> wrote:
>
> On Sat, 26 Jan 2019, Tejas Joshi wrote:
>
> > function with byte-byte comparison which also include mpfr. (Correct
> > me if I am wrong.) What is the significance of mpfr related to these
> > internal representations?
>
> real.c provides a fixed-size representation of floating-point numbers that
> allows for various non-IEEE formats supported by GCC, and also allows
> functions from dfp.c to be used for decimal floating-point formats.
>
> MPFR is used in GCC to provide operations that are nontrivial to
> implement, especially those that are nontrivial to implement in such a
> fixed-size context.  real.c operations wrap around MPFR ones where
> appropriate, doing whatever's needed in cases where there are non-IEEE
> semantics or sets of values.
>
> --
> Joseph S. Myers
> joseph@codesourcery.com

^ permalink raw reply	[flat|nested] 60+ messages in thread

* Re: About GSOC.
  2019-01-25 19:52                     ` Tejas Joshi
@ 2019-01-25 21:32                       ` Joseph Myers
  2019-01-28 17:00                         ` Tejas Joshi
  0 siblings, 1 reply; 60+ messages in thread
From: Joseph Myers @ 2019-01-25 21:32 UTC (permalink / raw)
  To: Tejas Joshi; +Cc: gcc

On Sat, 26 Jan 2019, Tejas Joshi wrote:

> function with byte-byte comparison which also include mpfr. (Correct
> me if I am wrong.) What is the significance of mpfr related to these
> internal representations?

real.c provides a fixed-size representation of floating-point numbers that 
allows for various non-IEEE formats supported by GCC, and also allows 
functions from dfp.c to be used for decimal floating-point formats.

MPFR is used in GCC to provide operations that are nontrivial to 
implement, especially those that are nontrivial to implement in such a 
fixed-size context.  real.c operations wrap around MPFR ones where 
appropriate, doing whatever's needed in cases where there are non-IEEE 
semantics or sets of values.

-- 
Joseph S. Myers
joseph@codesourcery.com

^ permalink raw reply	[flat|nested] 60+ messages in thread

* Re: About GSOC.
  2019-01-23 17:37                   ` Joseph Myers
@ 2019-01-25 19:52                     ` Tejas Joshi
  2019-01-25 21:32                       ` Joseph Myers
  0 siblings, 1 reply; 60+ messages in thread
From: Tejas Joshi @ 2019-01-25 19:52 UTC (permalink / raw)
  To: gcc

It took some time to get know using GDB, but upto some end I got it to
work. The enum real_value_class is used to classify the number into
zero, normal, infinity and NaN.
This class is represented by r->cl in real_value and values in struct
real_value are used as flags or representations while string to real
conversion (real_from_string) in real.c and other functions. The
decimal/hex string value is converted into real in real_from_string
function with byte-byte comparison which also include mpfr. (Correct
me if I am wrong.) What is the significance of mpfr related to these
internal representations?
Thanks.

-Tejas

On Wed, 23 Jan 2019 at 23:06, Joseph Myers <joseph@codesourcery.com> wrote:
>
> On Wed, 23 Jan 2019, Tejas Joshi wrote:
>
> > But I really dont know how to inspect a file like real.h (real_value)/real.c?
>
> Use cc1 to build a test program with selected floating-point constants in
> it.  Set breakpoints on appropriate functions in real.c (e.g. related to
> converting strings for real constants into the internal representation).
> Look at the representation produced for those constants to determine the
> particular conventions being used.
>
> --
> Joseph S. Myers
> joseph@codesourcery.com

^ permalink raw reply	[flat|nested] 60+ messages in thread

* Re: About GSOC.
  2019-01-23  4:00                 ` Tejas Joshi
@ 2019-01-23 17:37                   ` Joseph Myers
  2019-01-25 19:52                     ` Tejas Joshi
  0 siblings, 1 reply; 60+ messages in thread
From: Joseph Myers @ 2019-01-23 17:37 UTC (permalink / raw)
  To: Tejas Joshi; +Cc: gcc

On Wed, 23 Jan 2019, Tejas Joshi wrote:

> But I really dont know how to inspect a file like real.h (real_value)/real.c?

Use cc1 to build a test program with selected floating-point constants in 
it.  Set breakpoints on appropriate functions in real.c (e.g. related to 
converting strings for real constants into the internal representation).  
Look at the representation produced for those constants to determine the 
particular conventions being used.

-- 
Joseph S. Myers
joseph@codesourcery.com

^ permalink raw reply	[flat|nested] 60+ messages in thread

* Re: About GSOC.
  2019-01-23  2:55               ` Tejas Joshi
@ 2019-01-23  4:00                 ` Tejas Joshi
  2019-01-23 17:37                   ` Joseph Myers
  0 siblings, 1 reply; 60+ messages in thread
From: Tejas Joshi @ 2019-01-23  4:00 UTC (permalink / raw)
  To: gcc

I built gcc as a debuggable compiler as given using -g3. I am using
gdb and loaded the cc1 using:

gdb --args cc1

with output as:

Successfully loaded GDB hooks for GCC

But I really dont know how to inspect a file like real.h (real_value)/real.c?

Thanks.
-Tejas

On Wed, 23 Jan 2019 at 08:28, Tejas Joshi <tejasjoshi9673@gmail.com> wrote:
>
> > differ.  (It's the unoptimized, stage1 cc1 that should be run under a
> > debugger.  See <https://gcc.gnu.org/wiki/DebuggingGCC> for more details.)
>
> Hello.
> I normally configure GCC by (as you told)
>
> /configure --enable-languages=c,c++ --disable-bootstrap --disable-multilib
>
> And further as told in <https://gcc.gnu.org/wiki/DebuggingGCC>
>
> make STAGE1_CXXFLAGS="-g -O0" all-stage1
>
> but instead of -g to use -g3 is suggested for making macros debuggable
> and then use GDB.
> May I proceed the same?
>
> On Tue, 22 Jan 2019 at 04:33, Joseph Myers <joseph@codesourcery.com> wrote:
> >
> > On Tue, 22 Jan 2019, Tejas Joshi wrote:
> >
> > > the number like nan or normal in the functions. Though, attributes of
> > > struct real_value are pretty unclear to me regarding to the number it
> > > represents. (Am I right within this grasp?).
> >
> > It may be helpful to run the compiler under a debugger to examine how
> > particular real numbers are represented in real_value - that should help
> > answer questions such as what endianness is used for the significand, or
> > whether floating point values with a given exponent are in the range
> > [2^EXP, 2^(EXP+1)) or [2^(EXP-1), 2^EXP), where conventions commonly
> > differ.  (It's the unoptimized, stage1 cc1 that should be run under a
> > debugger.  See <https://gcc.gnu.org/wiki/DebuggingGCC> for more details.)
> >
> > And of course contribute comments in real.h once you've determined the
> > answers - because there are such areas where conventions about
> > representation of floating-point numbers commonly differ, it's
> > particularly valuable to have such comments because even someone familiar
> > with floating-point won't know which convention has been chosen by this
> > code in GCC.
> >
> > --
> > Joseph S. Myers
> > joseph@codesourcery.com

^ permalink raw reply	[flat|nested] 60+ messages in thread

* Re: About GSOC.
  2019-01-21 23:03             ` Joseph Myers
@ 2019-01-23  2:55               ` Tejas Joshi
  2019-01-23  4:00                 ` Tejas Joshi
  0 siblings, 1 reply; 60+ messages in thread
From: Tejas Joshi @ 2019-01-23  2:55 UTC (permalink / raw)
  To: gcc

> differ.  (It's the unoptimized, stage1 cc1 that should be run under a
> debugger.  See <https://gcc.gnu.org/wiki/DebuggingGCC> for more details.)

Hello.
I normally configure GCC by (as you told)

/configure --enable-languages=c,c++ --disable-bootstrap --disable-multilib

And further as told in <https://gcc.gnu.org/wiki/DebuggingGCC>

make STAGE1_CXXFLAGS="-g -O0" all-stage1

but instead of -g to use -g3 is suggested for making macros debuggable
and then use GDB.
May I proceed the same?

On Tue, 22 Jan 2019 at 04:33, Joseph Myers <joseph@codesourcery.com> wrote:
>
> On Tue, 22 Jan 2019, Tejas Joshi wrote:
>
> > the number like nan or normal in the functions. Though, attributes of
> > struct real_value are pretty unclear to me regarding to the number it
> > represents. (Am I right within this grasp?).
>
> It may be helpful to run the compiler under a debugger to examine how
> particular real numbers are represented in real_value - that should help
> answer questions such as what endianness is used for the significand, or
> whether floating point values with a given exponent are in the range
> [2^EXP, 2^(EXP+1)) or [2^(EXP-1), 2^EXP), where conventions commonly
> differ.  (It's the unoptimized, stage1 cc1 that should be run under a
> debugger.  See <https://gcc.gnu.org/wiki/DebuggingGCC> for more details.)
>
> And of course contribute comments in real.h once you've determined the
> answers - because there are such areas where conventions about
> representation of floating-point numbers commonly differ, it's
> particularly valuable to have such comments because even someone familiar
> with floating-point won't know which convention has been chosen by this
> code in GCC.
>
> --
> Joseph S. Myers
> joseph@codesourcery.com

^ permalink raw reply	[flat|nested] 60+ messages in thread

* Re: About GSOC.
  2019-01-21 19:13           ` Tejas Joshi
@ 2019-01-21 23:03             ` Joseph Myers
  2019-01-23  2:55               ` Tejas Joshi
  0 siblings, 1 reply; 60+ messages in thread
From: Joseph Myers @ 2019-01-21 23:03 UTC (permalink / raw)
  To: Tejas Joshi; +Cc: gcc

On Tue, 22 Jan 2019, Tejas Joshi wrote:

> the number like nan or normal in the functions. Though, attributes of
> struct real_value are pretty unclear to me regarding to the number it
> represents. (Am I right within this grasp?).

It may be helpful to run the compiler under a debugger to examine how 
particular real numbers are represented in real_value - that should help 
answer questions such as what endianness is used for the significand, or 
whether floating point values with a given exponent are in the range 
[2^EXP, 2^(EXP+1)) or [2^(EXP-1), 2^EXP), where conventions commonly 
differ.  (It's the unoptimized, stage1 cc1 that should be run under a 
debugger.  See <https://gcc.gnu.org/wiki/DebuggingGCC> for more details.)

And of course contribute comments in real.h once you've determined the 
answers - because there are such areas where conventions about 
representation of floating-point numbers commonly differ, it's 
particularly valuable to have such comments because even someone familiar 
with floating-point won't know which convention has been chosen by this 
code in GCC.

-- 
Joseph S. Myers
joseph@codesourcery.com

^ permalink raw reply	[flat|nested] 60+ messages in thread

* Re: About GSOC.
  2018-11-16 19:00         ` Joseph Myers
@ 2019-01-21 19:13           ` Tejas Joshi
  2019-01-21 23:03             ` Joseph Myers
  0 siblings, 1 reply; 60+ messages in thread
From: Tejas Joshi @ 2019-01-21 19:13 UTC (permalink / raw)
  Cc: gcc

Hello.
I've been inactive for some time due to exams but I have been studying
the real.h and IEEE 754 floating point format as far as I could.

> floating-point built-in functions.  That means you should instead
> understand REAL_EXP and the significands of floating-point values, and

In GCC's representation of REAL or may I say floating point numbers
(including decimal floating point values), values are defined in
macros in real.h like

#define SIGNIFICAND_BITS    (128 + HOST_BITS_PER_LONG)           (why
128+host-bits_per_long?, even quad precision has total 128 bits.)
#define EXP_BITS        (32 - 6)

This include EXP_BITS resolving to I believe, exponent bits and macro
REAL_EXP to exponent value which determines the value of the exponent
of REAL r, which is passed in real.c with mathematical calculations
like XOR and shifting (multiplication by 2) though the operation is
unclear. (Adding comment to these will also be helpful in a patch for
me!)

> true that it doesn't have a comment specifying its semantics directly, but
> the /* ENUM_BITFIELD (real_value_class) */ should give a strong hint,
> along with the values that are stored in that field.  By looking at how

As far as the struct real_value is concerned, I believe the values
associated with decimal, sign, etc are used for handling switch
conditions in functions of real.c and then carrying out specific
functions like clear_signifcand_below.
Relating to enumeration real_value_class, it determines the type of
the number like nan or normal in the functions. Though, attributes of
struct real_value are pretty unclear to me regarding to the number it
represents. (Am I right within this grasp?).
Thank you.

Regards,
-Tejas
<div dir="ltr"><br></div><br><div class="gmail_quote"><div dir="ltr"
class="gmail-m_1121032510469528392gmail_attr">On Fri, 16 Nov 2018 at
22:20, Joseph Myers &lt;<a href="mailto:joseph@codesourcery.com"
target="_blank">joseph@codesourcery.com</a>&gt;
wrote:<br></div><blockquote class="gmail_quote" style="margin: 0px 0px
0px 0.8ex; border-left: 1px solid rgb(204, 204, 204); padding-left:
1ex;">On Fri, 16 Nov 2018, Tejas Joshi wrote:<br>
<br>
&gt; About roundeven, there might be need to add case to<br>
&gt; expand_builtin_int_roundingfn similar to<br>
&gt; ceil, for expansion.<br>
&gt; But how is round() expanded since there's no<br>
&gt; entry for it in expand_builtin_int_roundingfn ?<br>
<br>
Please see the comment above expand_builtin_int_roundingfn, and that above <br>
expand_builtin_int_roundingfn_<wbr>2, which handle different sets of
functions.&nbsp; <br>
Those functions are of no relevance to adding support for built-in <br>
roundeven.&nbsp; (They might be of relevance to support for built-in fromfp <br>
functions, depending on whether the detailed semantics allows <br>
casts-to-integer of calls to other functions to be converted into calls to <br>
the fromfp functions.&nbsp; But I don't think inventing
__builtin_lroundeven <br>
would be appropriate.)<br>
<br>
&gt; Also, is it right to have an added case for roundeven in convert.c<br>
&gt; along CASE_FLT_FN (BUILT_IN_ROUND)<br>
&gt; in convert_to_integer_1?<br>
<br>
Not until doing things with fromfp functions.&nbsp; There is no
lroundeven (for <br>
example) in TS 18661-1.<br>
<br>
-- <br>
Joseph S. Myers<br>
<a href="mailto:joseph@codesourcery.com"
target="_blank">joseph@codesourcery.com</a><br>
</blockquote></div>

^ permalink raw reply	[flat|nested] 60+ messages in thread

* Re: About GSOC.
  2018-11-16 16:50       ` Tejas Joshi
@ 2018-11-16 19:00         ` Joseph Myers
  2019-01-21 19:13           ` Tejas Joshi
  0 siblings, 1 reply; 60+ messages in thread
From: Joseph Myers @ 2018-11-16 19:00 UTC (permalink / raw)
  To: Tejas Joshi; +Cc: gcc

On Fri, 16 Nov 2018, Tejas Joshi wrote:

> About roundeven, there might be need to add case to
> expand_builtin_int_roundingfn similar to
> ceil, for expansion.
> But how is round() expanded since there's no
> entry for it in expand_builtin_int_roundingfn ?

Please see the comment above expand_builtin_int_roundingfn, and that above 
expand_builtin_int_roundingfn_2, which handle different sets of functions.  
Those functions are of no relevance to adding support for built-in 
roundeven.  (They might be of relevance to support for built-in fromfp 
functions, depending on whether the detailed semantics allows 
casts-to-integer of calls to other functions to be converted into calls to 
the fromfp functions.  But I don't think inventing __builtin_lroundeven 
would be appropriate.)

> Also, is it right to have an added case for roundeven in convert.c
> along CASE_FLT_FN (BUILT_IN_ROUND)
> in convert_to_integer_1?

Not until doing things with fromfp functions.  There is no lroundeven (for 
example) in TS 18661-1.

-- 
Joseph S. Myers
joseph@codesourcery.com

^ permalink raw reply	[flat|nested] 60+ messages in thread

* Re: About GSOC.
  2018-10-23 16:51     ` Joseph Myers
@ 2018-11-16 16:50       ` Tejas Joshi
  2018-11-16 19:00         ` Joseph Myers
  0 siblings, 1 reply; 60+ messages in thread
From: Tejas Joshi @ 2018-11-16 16:50 UTC (permalink / raw)
  To: gcc

About roundeven, there might be need to add case to
expand_builtin_int_roundingfn similar to
ceil, for expansion.
But how is round() expanded since there's no
entry for it in expand_builtin_int_roundingfn ?

Also, is it right to have an added case for roundeven in convert.c
along CASE_FLT_FN (BUILT_IN_ROUND)
in convert_to_integer_1?

Thanks.
On Tue, 23 Oct 2018 at 22:21, Joseph Myers <joseph@codesourcery.com> wrote:
>
> On Tue, 23 Oct 2018, Martin Jambor wrote:
>
> > Hi Joseph,
> >
> > this seems related to your proposal GSoC proposal in the beginning
> > of this year.  Do you have any comments about Tejas's idea?  Do you
>
> My proposal was designed so that it would be possible to do some small
> piece, that is useful by itself, and so learn about some parts of the
> compiler, and then go onto another piece, and so learn about other parts
> of the compiler - as there are lots of separate pieces that are related,
> but each useful by itself as a contribution to GCC.  The parts Tejas
> refers to are good pieces to be looking at for one such piece (roundeven
> folding for constant arguments) (along with e.g. builtins.def to define
> the built-in functions).
>
> > think this would be a good (part of) a GSoC project next year?
>
> If a suitable mentor is available for it next year.
>
> > > It does tell that roundeven rounds its argument to nearest integral
> > > ties to even (least significant bit 0) returning integral value
> > > provided that the resulting value is exact.
> > > So, for the start, I'd be implementing this functionality for roundeven.
> > > As ita said in earlier mails that, similar functions like
> > > real_ceil are implemented
> > > in real.c and are used in fold-const-call.c.
> > > Roundeven might be implemented in similar way. Is it built-in
> > > (internal) function means not to be exposed to end-user?
> > > Studying some functions like real_ceil, there are call checks
> > > (flag_errno_math) so I believe similar would be needed for roundeven.
>
> The expectation for this part of the project would be that calls to both
> __builtin_roundeven and roundeven (and similar functions with f, l, f128
> etc. suffixes) would be folded when the arguments are constants (both
> direct calls with constants such as roundeven (2.5), and cases where
> GIMPLE optimization passes propagate a constant into the call, such as
> "double d = 2.5; return roundeven (d);").  This of course involves various
> internal functions in the compiler to implement that.
>
> If you compile code such as
>
> double
> f (void)
> {
>   double d = 2.5;
>   return ceil (d);
> }
>
> with -O2 -S -fdump-tree-all, you can look at the generated dump files to
> see which optimization pass the folding into constant 3.0 occurs in.
> Looking at such dumps is an important way of finding your way around the
> optimization passes in the compiler.
>
> > > In real.c where real_ceil is implemented, there are function calls
> > > (and implementations) like do_fix_trunc which also then call functions
> > > like decimal_do_dix_trunc (maybe the main functionality of
> > > do_fix_trunc?, other are just checks, like NaN or qNaN). I did not
>
> You can ignore any cases for decimal floating-point values (do gcc_assert
> (!r->decimal)), given that the project does not involve adding any decimal
> floating-point built-in functions.  That means you should instead
> understand REAL_EXP and the significands of floating-point values, and
> what functions such as clear_significand_below and test_significand_bit
> do, because you'll need to write your own logic like that in do_fix_trunc,
> with appropriate cases for whether the bits with values 0.5 and below form
> part of the significand.
>
> > > understand these functions really and what do they do. Also I did not
> > > understand the structure of REAL_VALUE_TYPE (r->cl and etc?)
>
> I suggest looking more closely at the definition of cl in real.h.  It's
> true that it doesn't have a comment specifying its semantics directly, but
> the /* ENUM_BITFIELD (real_value_class) */ should give a strong hint,
> along with the values that are stored in that field.  By looking at how
> all the fields in real_value are used, you should be able to deduce their
> semantics, and then send a GCC patch that adds a comment to each field
> with a more detailed description of its semantics, which would be a useful
> contribution by itself to help people reading real.c code in future.
>
> (struct real_format has more detailed comments on some of the fields.  I
> suggest using those as a model for the comments that ought to be written
> for the fields of struct real_value.)
>
> > > Also when does the real.c and fold-const-call.c comes in picture in
> > > the flow of GCC (Is it for GIMPLE level instruction selection (gimple
> > > stmnt to corresponding rtl instruction))?
>
> The code you're looking at is used in GIMPLE optimizations, and possibly
> folding before GIMPLE.
>
> Converting roundeven calls with non-constant arguments to appropriate
> instructions (for processors that have them, e.g. x86 with SSE 4.1 and
> later) is also useful, and will involve changes to optabs.def,
> internal-fn.def and target .md files.  But I'd advise doing one
> self-contained piece first (such as the folding for constant arguments)
> before moving on to others (such as generating appropriate instructions
> for the case of non-constant arguments).
>
> --
> Joseph S. Myers
> joseph@codesourcery.com

^ permalink raw reply	[flat|nested] 60+ messages in thread

* Re: About GSOC.
  2018-10-23 10:47   ` Martin Jambor
@ 2018-10-23 16:51     ` Joseph Myers
  2018-11-16 16:50       ` Tejas Joshi
  0 siblings, 1 reply; 60+ messages in thread
From: Joseph Myers @ 2018-10-23 16:51 UTC (permalink / raw)
  To: Martin Jambor; +Cc: Tejas Joshi, gcc

On Tue, 23 Oct 2018, Martin Jambor wrote:

> Hi Joseph,
> 
> this seems related to your proposal GSoC proposal in the beginning
> of this year.  Do you have any comments about Tejas's idea?  Do you

My proposal was designed so that it would be possible to do some small 
piece, that is useful by itself, and so learn about some parts of the 
compiler, and then go onto another piece, and so learn about other parts 
of the compiler - as there are lots of separate pieces that are related, 
but each useful by itself as a contribution to GCC.  The parts Tejas 
refers to are good pieces to be looking at for one such piece (roundeven 
folding for constant arguments) (along with e.g. builtins.def to define 
the built-in functions).

> think this would be a good (part of) a GSoC project next year?

If a suitable mentor is available for it next year.

> > It does tell that roundeven rounds its argument to nearest integral
> > ties to even (least significant bit 0) returning integral value
> > provided that the resulting value is exact.
> > So, for the start, I'd be implementing this functionality for roundeven.
> > As ita said in earlier mails that, similar functions like
> > real_ceil are implemented
> > in real.c and are used in fold-const-call.c.
> > Roundeven might be implemented in similar way. Is it built-in
> > (internal) function means not to be exposed to end-user?
> > Studying some functions like real_ceil, there are call checks
> > (flag_errno_math) so I believe similar would be needed for roundeven.

The expectation for this part of the project would be that calls to both 
__builtin_roundeven and roundeven (and similar functions with f, l, f128 
etc. suffixes) would be folded when the arguments are constants (both 
direct calls with constants such as roundeven (2.5), and cases where 
GIMPLE optimization passes propagate a constant into the call, such as 
"double d = 2.5; return roundeven (d);").  This of course involves various 
internal functions in the compiler to implement that.

If you compile code such as

double
f (void)
{
  double d = 2.5;
  return ceil (d);
}

with -O2 -S -fdump-tree-all, you can look at the generated dump files to 
see which optimization pass the folding into constant 3.0 occurs in.  
Looking at such dumps is an important way of finding your way around the 
optimization passes in the compiler.

> > In real.c where real_ceil is implemented, there are function calls
> > (and implementations) like do_fix_trunc which also then call functions
> > like decimal_do_dix_trunc (maybe the main functionality of
> > do_fix_trunc?, other are just checks, like NaN or qNaN). I did not

You can ignore any cases for decimal floating-point values (do gcc_assert 
(!r->decimal)), given that the project does not involve adding any decimal 
floating-point built-in functions.  That means you should instead 
understand REAL_EXP and the significands of floating-point values, and 
what functions such as clear_significand_below and test_significand_bit 
do, because you'll need to write your own logic like that in do_fix_trunc, 
with appropriate cases for whether the bits with values 0.5 and below form 
part of the significand.

> > understand these functions really and what do they do. Also I did not
> > understand the structure of REAL_VALUE_TYPE (r->cl and etc?)

I suggest looking more closely at the definition of cl in real.h.  It's 
true that it doesn't have a comment specifying its semantics directly, but 
the /* ENUM_BITFIELD (real_value_class) */ should give a strong hint, 
along with the values that are stored in that field.  By looking at how 
all the fields in real_value are used, you should be able to deduce their 
semantics, and then send a GCC patch that adds a comment to each field 
with a more detailed description of its semantics, which would be a useful 
contribution by itself to help people reading real.c code in future.

(struct real_format has more detailed comments on some of the fields.  I 
suggest using those as a model for the comments that ought to be written 
for the fields of struct real_value.)

> > Also when does the real.c and fold-const-call.c comes in picture in
> > the flow of GCC (Is it for GIMPLE level instruction selection (gimple
> > stmnt to corresponding rtl instruction))?

The code you're looking at is used in GIMPLE optimizations, and possibly 
folding before GIMPLE.

Converting roundeven calls with non-constant arguments to appropriate 
instructions (for processors that have them, e.g. x86 with SSE 4.1 and 
later) is also useful, and will involve changes to optabs.def, 
internal-fn.def and target .md files.  But I'd advise doing one 
self-contained piece first (such as the folding for constant arguments) 
before moving on to others (such as generating appropriate instructions 
for the case of non-constant arguments).

-- 
Joseph S. Myers
joseph@codesourcery.com

^ permalink raw reply	[flat|nested] 60+ messages in thread

* Re: About GSOC.
  2018-10-13  4:43 ` About GSOC Tejas Joshi
@ 2018-10-23 10:47   ` Martin Jambor
  2018-10-23 16:51     ` Joseph Myers
  0 siblings, 1 reply; 60+ messages in thread
From: Martin Jambor @ 2018-10-23 10:47 UTC (permalink / raw)
  To: Joseph Myers; +Cc: Tejas Joshi, gcc

Hi Joseph,

this seems related to your proposal GSoC proposal in the beginning
of this year.  Do you have any comments about Tejas's idea?  Do you
think this would be a good (part of) a GSoC project next year?

Thanks a lot,

Martin


On Sat, Oct 13 2018, Tejas Joshi wrote:
> Hello.
> I reached asking about GCC GSoC project about adding and
> folding functions
> like roundeven. I could not apply for the idea this year but
> interested in the peoject and
> really hoping it would be carry forwarded. Since I've been studying
> source code and about the project, I think working on this from now
> would give me some heads up and hands on with the source code.
>
> I did study <http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1778.pdf>.
> It does tell that roundeven rounds its argument to nearest integral
> ties to even (least significant bit 0) returning integral value
> provided that the resulting value is exact.
> So, for the start, I'd be implementing this functionality for roundeven.
> As ita said in earlier mails that, similar functions like
> real_ceil are implemented
> in real.c and are used in fold-const-call.c.
> Roundeven might be implemented in similar way. Is it built-in
> (internal) function means not to be exposed to end-user?
> Studying some functions like real_ceil, there are call checks
> (flag_errno_math) so I believe similar would be needed for roundeven.
>
> In real.c where real_ceil is implemented, there are function calls
> (and implementations) like do_fix_trunc which also then call functions
> like decimal_do_dix_trunc (maybe the main functionality of
> do_fix_trunc?, other are just checks, like NaN or qNaN). I did not
> understand these functions really and what do they do. Also I did not
> understand the structure of REAL_VALUE_TYPE (r->cl and etc?)
>
> Also when does the real.c and fold-const-call.c comes in picture in
> the flow of GCC (Is it for GIMPLE level instruction selection (gimple
> stmnt to corresponding rtl instruction))?
> Thanks.
>
> Regards,
> -Tejas

^ permalink raw reply	[flat|nested] 60+ messages in thread

* About GSOC.
       [not found] <CACMrGjCeaZ7EoYqjLYiAJXjOtOfpJNo9zcbWhfarfkiLMN8YYA@mail.gmail.com>
@ 2018-10-13  4:43 ` Tejas Joshi
  2018-10-23 10:47   ` Martin Jambor
  0 siblings, 1 reply; 60+ messages in thread
From: Tejas Joshi @ 2018-10-13  4:43 UTC (permalink / raw)
  To: gcc

Hello.
I reached asking about GCC GSoC project about adding and
folding functions
like roundeven. I could not apply for the idea this year but
interested in the peoject and
really hoping it would be carry forwarded. Since I've been studying
source code and about the project, I think working on this from now
would give me some heads up and hands on with the source code.

I did study <http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1778.pdf>.
It does tell that roundeven rounds its argument to nearest integral
ties to even (least significant bit 0) returning integral value
provided that the resulting value is exact.
So, for the start, I'd be implementing this functionality for roundeven.
As ita said in earlier mails that, similar functions like
real_ceil are implemented
in real.c and are used in fold-const-call.c.
Roundeven might be implemented in similar way. Is it built-in
(internal) function means not to be exposed to end-user?
Studying some functions like real_ceil, there are call checks
(flag_errno_math) so I believe similar would be needed for roundeven.

In real.c where real_ceil is implemented, there are function calls
(and implementations) like do_fix_trunc which also then call functions
like decimal_do_dix_trunc (maybe the main functionality of
do_fix_trunc?, other are just checks, like NaN or qNaN). I did not
understand these functions really and what do they do. Also I did not
understand the structure of REAL_VALUE_TYPE (r->cl and etc?)

Also when does the real.c and fold-const-call.c comes in picture in
the flow of GCC (Is it for GIMPLE level instruction selection (gimple
stmnt to corresponding rtl instruction))?
Thanks.

Regards,
-Tejas

^ permalink raw reply	[flat|nested] 60+ messages in thread

end of thread, other threads:[~2024-03-11 12:41 UTC | newest]

Thread overview: 60+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2024-03-04  6:57 About gsoc mokshagnareddyc
2024-03-04 10:06 ` Jonathan Wakely
2024-03-05  2:02   ` Dave Blanchard
2024-03-05  9:31     ` Jonathan Wakely
2024-03-05  9:32       ` Jonathan Wakely
2024-03-11  1:17         ` Dave Blanchard
2024-03-11  9:08           ` Mark Wielaard
2024-03-07 12:26 ` Martin Jambor
  -- strict thread matches above, loose matches on Subject: below --
2024-03-11 12:41 Julian Waters
     [not found] <CACMrGjCeaZ7EoYqjLYiAJXjOtOfpJNo9zcbWhfarfkiLMN8YYA@mail.gmail.com>
2018-10-13  4:43 ` About GSOC Tejas Joshi
2018-10-23 10:47   ` Martin Jambor
2018-10-23 16:51     ` Joseph Myers
2018-11-16 16:50       ` Tejas Joshi
2018-11-16 19:00         ` Joseph Myers
2019-01-21 19:13           ` Tejas Joshi
2019-01-21 23:03             ` Joseph Myers
2019-01-23  2:55               ` Tejas Joshi
2019-01-23  4:00                 ` Tejas Joshi
2019-01-23 17:37                   ` Joseph Myers
2019-01-25 19:52                     ` Tejas Joshi
2019-01-25 21:32                       ` Joseph Myers
2019-01-28 17:00                         ` Tejas Joshi
2019-02-04 14:39                           ` Tejas Joshi
2019-02-04 15:06                             ` Prathamesh Kulkarni
2019-02-04 15:56                               ` Tejas Joshi
2019-02-04 16:44                                 ` Prathamesh Kulkarni
2019-02-04 17:22                                   ` Tejas Joshi
2019-02-24 12:05                                     ` Tejas Joshi
2019-03-30 11:24                                       ` Tejas Joshi
2019-04-01 19:53                                         ` Joseph Myers
2019-04-04 13:04                                           ` Tejas Joshi
2019-05-04 11:20                                             ` Tejas Joshi
2019-05-07 17:18                                               ` Joseph Myers
2019-05-07 19:38                                                 ` Tejas Joshi
2019-05-07 21:01                                                   ` Joseph Myers
2019-05-08  3:27                                                     ` Tejas Joshi
2019-05-08  7:30                                                       ` Tejas Joshi
2019-05-08 14:21                                                         ` Tejas Joshi
2019-05-09 17:01                                                           ` Joseph Myers
2019-05-09 16:55                                                         ` Joseph Myers
2019-05-20 15:49                                                         ` Martin Jambor
2019-05-20 21:48                                                           ` Joseph Myers
2019-05-29 11:21                                                             ` Tejas Joshi
2019-05-29 18:45                                                               ` Tejas Joshi
2019-05-30 17:08                                                                 ` Martin Jambor
2019-05-30 21:38                                                                   ` Segher Boessenkool
2019-05-31 10:11                                                                     ` Martin Jambor
2019-05-31 10:28                                                                       ` Tejas Joshi
2019-06-03 16:38                                                                         ` Joseph Myers
2019-06-04  7:03                                                                           ` Tejas Joshi
2019-06-05 12:19                                                                             ` Tejas Joshi
2019-06-06 16:43                                                                             ` Joseph Myers
2019-06-09  4:48                                                                               ` Tejas Joshi
2019-06-10 20:26                                                                                 ` Joseph Myers
2019-06-12 18:52                                                                                   ` Tejas Joshi
2019-06-13 12:33                                                                                     ` Tejas Joshi
2019-05-31 11:13                                                                       ` Segher Boessenkool
2019-05-31 11:16                                                                     ` Nathan Sidwell
2019-05-31 13:30                                                                       ` Eric Gallager
2019-06-03  9:37                                                                         ` Tejas Joshi

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).