[Bug libstdc++/50724] isnan broken by -ffinite-math-only in g++

2011-10-14 Thread ejtttje at gmail dot com
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=50724

Ethan Tira-Thompson  changed:

   What|Removed |Added

 Status|RESOLVED|UNCONFIRMED
 Resolution|INVALID |

--- Comment #2 from Ethan Tira-Thompson  2011-10-14 
14:27:13 UTC ---
Well, that's not actually true: -fno-finite-math is telling the compiler to
assume finite results during computation, but that doesn't mean there are "no
NaNs".  For example, I need isnan/isfinite to validate my users' input before I
can ensure that invariant afterward.  Clearly the bit pattern still exists in
the universe.

I'd also argue classification functions are not "arithmetic" and thus not
covered by -fno-finite-math ("Allow optimizations for floating-point
arithmetic")

Finally, I think you're being quick to brush off the consistency issue, both
with earlier gcc versions and with math.h.  I find it quite disconcerting that
isnan behavior changes between the two headers.

Is your concern that __builtin_isnan is called internally during fp
computations and we need to optimize that away in order to provide the speed
advantages requested by -fno-finite-math?  In that case, I propose cmath should
be updated to check __FINITE_MATH_ONLY__ in its user-facing isnan and fall back
to a safe method like math.h is currently using (apparently __isnan/__isnanf).

Otherwise, as I established above, I don't think it's safe to 'optimize' away
the floating point classification functions: the first issue above is code
safety/security, the second is pedantic regarding documentation, and the third
is a consistency issue.

Thanks!


[Bug middle-end/50724] isnan broken by -ffinite-math-only in g++

2011-10-14 Thread ejtttje at gmail dot com
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=50724

--- Comment #9 from Ethan Tira-Thompson  2011-10-14 
20:07:41 UTC ---
Thanks, I think Michael hit the nail on the head for summarizing my intention,
I'm satisfied to file this as a feature request (although personally I'd still
call it a bug ;))

For reference regarding the test case, I agree with your point that 0.f/0
needn't be a reliable NaN generator under -ffast-math.  The original source was
actually using std::numeric_limits::quiet_NaN() and/or signaling_NaN(),
but I switched to 0.f/0 in order to test under C (not-++) and forgot to switch
back.  So yeah, considering numeric_limits still returns the NaN bit patterns
regardless of -ff-m-o, it's unbalanced that isnan is prevented from detecting
them.  Regardless, disabling classification routines is going beyond the scope
of "math" and "arithmetic" as per the name of the flag and its documentation.

(For those oversimplifying -ff-m-o as "No NaNs", perhaps you would like to add
a new -fno-nans or perhaps -fno-quiet-nans flag if that is what you really want
-ffinite-math-only to mean...)

In the three linked bug reports, the first is basically a "don't do that"
without discussion, the second specifically complains about the lack of
discussion, and the third is redirected toward fixing an issue in -mno-ieee
without resolving the -ffinite-math-only aspect.


[Bug middle-end/50724] isnan broken by -ffinite-math-only in g++

2011-10-14 Thread ejtttje at gmail dot com
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=50724

--- Comment #11 from Ethan Tira-Thompson  2011-10-14 
22:07:44 UTC ---
Marc: is this code perusable? I'm curious because I expect either the
calculations may generate NaN or not at all.  If they might and you even have
test cases to handle it, then I'm surprised you would ever want to support
running with -ff-m-o.  Conversely if you knew the code doesn't generate the
nonfinite values, then you don't need the classifications in the first
place...?

I'm guessing (and apologies if this is inaccurate) that this might boil down to
saying that you want to interpret an end user setting -ff-m-o as an opportunity
to skip validating their input or skip doing assertions during its processing,
which could be a reasonable thing to do, but that's a choice I'd rather leave
to individual developers, e.g. can also wrap code with #if
__FINITE_MATH_ONLY__==0 or such...

Or in other words, it's only a missed optimization if you wind up with
classification calls, whereas it's a full-fledged execution error when NaN gets
past validation.


[Bug middle-end/50724] isnan broken by -ffinite-math-only in g++

2011-10-15 Thread ejtttje at gmail dot com
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=50724

Ethan Tira-Thompson  changed:

   What|Removed |Added

 Status|RESOLVED|REOPENED
 Resolution|INVALID |

--- Comment #14 from Ethan Tira-Thompson  2011-10-15 
14:01:11 UTC ---
Richard said:
> The documentation states
> "Allow optimizations for floating-point arithmetic that
> assume that arguments and results are not NaNs or +-Infs."

Yes, that's my argument as well.  Note ARITHMETIC.  Also note MATH in the name
of both --finite-MATH-only, and -ffast-MATH it falls under.  And it doesn't
reference the 'math library' to qualify that.

Basically, if you want to close on this point, I want to see you explicitly
argue why the classification functions should be considered arithmetic.

I'm going to nail this down and list there are 5 classification functions
(fpclassify, infinite, isinf, isnan, isnormal) and the vast majority of the
other library functions are obviously proper arithmetic operations.  The ones
that aren't (signbit, copysign, nextafter, nan), you're exactly right that we
should carefully consider the result of NaN optimization ("special cases"). 
You don't have to do this if *you* don't want to, but it should be done and it
sounds like no one has.

> This has been discussed to death already, and the present behavior is how
> GCC behaved since ever.

Except also NOT TRUE.  It currently doesn't behave this way with math.h.  It
didn't behave this way in 4.1 (Fedora) or 4.2 (Apple).  I only got screwed by
this by the CHANGE in behavior on upgrading to 4.4.  (Not sure about 4.3).  I
already presented this in the original post at the top (except the Apple test
is a new data point; FYI Apple gcc math.h also 'works', so either 4.2 was
generally consistent or Apple likes to patch theirs for consistency)

This is further evidence gcc has not had a good policy discussion of where NaN
optimizations should be applied, because the implementation keeps changing, and
it's not even consistent between math.h and cmath within any given version
other than 4.2-Apple.

Marc said:
>> __FINITE_MATH_ONLY__
> Not very portable afaik.

Neither is -ffast-math, add a 'defined(__FINITE_MATH_ONLY__) &&' and it will be
applied opportunistically when available, or even better: the user can
-D__FINITE_MATH_ONLY__=1 themselves on non-gcc platforms and still get the
performance benefit you're looking for even without -ffast-math support, so
it's a double win.  IMHO, on the other hand it's harder and more error prone to
override isnan with my own implementation.


[Bug middle-end/50724] isnan broken by -ffinite-math-only in g++

2011-10-16 Thread ejtttje at gmail dot com
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=50724

Ethan Tira-Thompson  changed:

   What|Removed |Added

 Status|RESOLVED|REOPENED
 Resolution|INVALID |

--- Comment #17 from Ethan Tira-Thompson  2011-10-17 
04:12:31 UTC ---
Richard said:
> math.h is not part of GCC

But the point is there is value in consistency between math.h and cmath
regardless of who owns math.h.  I'm asserting that this value is greater than
that gained by 'optimizing away' the classification functions in cmath. 
Inconsistency leads to confused users and therefore bugs, missed optimization
is only going to cause slower code.  I get that you want to make the most of
-ffast-math, and if it were a big speedup it could be worthwhile, but it seems
reasonable that if someone is serious about optimizing away their
classification sanity checks in a release build, they would be better served by
using assert() or an #ifdef instead of relying of the vagaries of -ffast-math
for this purpose.

> The only way out I see that not breaks other users uses would be a new
> flag, like -fpreserve-ieee-fp-classification that, ontop of 
> -ffinite-math-only,

I'm not opposed to a new flag, but I'd suggest the reverse semantics. 
Disabling classification is an extra degree of non-compliance beyond ignoring
non-finite math operations.  I'd rather users add flags to progressively become
less compliant, rather than add a flag to get some compliance back.

But to rewind a second, I want to address the "breaks other users" comment...
here is the status AFAIK:
1) Older versions (4.1, 4.2) of gcc did not do this optimization of
classification functions.  Thus, "legacy" code expects classification to work
even in the face of -ffast-math, which was changed circa 4.3/4.4
2) Removing classification 'breaks' code because it fundamentally strips
execution paths which may otherwise be used.
3) Leaving classification in could be considered a missed optimization, but is
at worst only a performance penalty, not a change in execution values.
4) Personal conjecture: I doubt the classification routines are a performance
bottleneck in the areas where -ff-m-o is being applied, so (3) is pretty
minimal.  And I seriously doubt anyone is relying on the removal of
classification in a code-correctness context, that doesn't make any sense.

Are we on the same page with these points?  So if you are concerned with the
breakage of existing code, isn't the solution to revert to the previous scope
of the -ff-m-o optimization ASAP, and then if there is a desire to extend the
finite-only optimization to classification functions, *that* would be a new
feature request, perhaps with its own flag?

> (Note that they are folded to arithmetic, !(x==x), so that transform
> has to be disabled as well, and on some architectures you might get
> library calls because of this instead of inline expansions).

I'd rather leave comparison optimizations as they are under -ff-m-o, that seems
a sensible expectation of the 'arithmetic' scope, and is relatively well-known,
long-standing effect of -ffast-math.  It's only the 5 explicit fp
classification calls which I think deserve protection to allow data validation
in a non-hacky manner before doing core computations with the finite invariant.

Unless you are saying things like std::isnan cannot be implemented separately
from !(x==x)?  That has not been my understanding.


[Bug libstdc++/50724] cmath's floating-point classification implementations inconsistent with math.h

2011-10-17 Thread ejtttje at gmail dot com
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=50724

Ethan Tira-Thompson  changed:

   What|Removed |Added

 Status|RESOLVED|REOPENED
  Component|middle-end  |libstdc++
 Resolution|DUPLICATE   |
Summary|isnan broken by |cmath's floating-point
   |-ffinite-math-only in g++   |classification
   ||implementations
   ||inconsistent with math.h
   Severity|enhancement |normal

--- Comment #19 from Ethan Tira-Thompson  2011-10-17 
15:31:12 UTC ---
Richard said:
>> 1) Older versions (4.1, 4.2) of gcc did not do this optimization
> Sure they did.

Dude, I tested this in my very first post.  I'm only here because we had
working code which has broken on the upgrade to Ubuntu 10.04.  There's no point
in discussing with you if you're just going to deny the state of the world and
not offer any data to back up your side.  But before you start coding a test
case, read on, turns out I've already done this for you below.

> I expect the checks to be optimized away when using the FP exception path.

I hate using this rationale, but have you considered that this is not a
required or portable behavior and you shouldn't rely on it?  And what happens
if the checks are left in?  Is anything actually 'broken' by this?  You keep
using that word, I do not think it means what you think it means.  I lose data
validation when the classifications are disabled.  My code does something
fundamentally different as a result.  This is demonstrable 'breakage'.  To
quote a wise man, "We should not break this without a very very very good
reason.  Which this isn't." ;)

> [isnan implementation ...] So what's your point again?

There are various ways to define isnan and friends.  I'm requesting one which
is consistent with math.h's isnan and also previous behavior.  That could be
bitmask operations, it could be calling __isnan or math.h's isnan(), etc. 

I think we need some new data to move this along...
I did a little investigation on how these functions have been defined over
time:

In 4.1 and 4.2, cmath provides:
  std::isnan() forwards to __gnu_cxx::__capture_isnan()
  __gnu_cxx::__capture_isnan() forwards to math.h ::isnan()
  math.h ::isnan forwards to __isnan()
as of this patch:
http://gcc.gnu.org/viewcvs/trunk/libstdc%2B%2B-v3/include/c_std/cmath?r1=119611&r2=130443
This has changed to simply:
  std::isnan() forwards to __builtin_isnan()

Huh, that's interesting, let's cut out the middle men and see what these
underlying functions do across history:
  const float qNaN = std::numeric_limits::quiet_NaN();
  std::cout << __builtin_isnan(qNaN) << ' '
<< __isnan(qNaN) << ' '
<< !(qNaN==qNaN) << '\n';

Compiled with -ffast-math on 3 different machines
0 1 0 // Fedora 9, gcc 4.1.2
0 1 0 // Apple 10.7, gcc 4.2.1
0 1 0 // Ubuntu 10.04, gcc 4.4.3

Hey, you're right insofar as the 'internal' implementations haven't changed at
all.  What changed is where cmath sends its implementation (and fyi, I did
originally file this under libstdc++, just by lucky guess ;).  cmath used to
explicitly call the math.h definition (aka __isnan), which is not optimized by
-ffast-math.

For reference, I checked the headers on the Apple machine as well, and found
some relevant results.  cmath starts the same with std::isnan → __capture_isnan
→ ::isnan, but the abridged math.h ::isnan definition is:
  #if defined( __GNUC__ ) && 0 == __FINITE_MATH_ONLY__ 
#define isnan(x) __inline_isnanT((T)(x))
inline int __inline_isnanT( T __x ) { return __x != __x; }
  #else
#define isnan(x) __isnanT((T)(x))
extern int __isnanT(T);
  #endif
(full source
http://www.opensource.apple.com/source/Libm/Libm-315/Source/Intel/math.h)

Which is all prepended by this comment:
> Yes, that's right. You only get the fast iswhatever() macros if you do NOT
> turn on -ffast-math.  These inline functions require the compiler to be
> compiling to standard in order to work. -ffast-math, among other things,
> implies that NaNs don't happen. The compiler can in that case optimize
> x != x to be false always, wheras it would be true for NaNs. That breaks
> __inline_isnan() below.

So, to whatever degree you care what major users are doing, at least one
popular platform considers it breakage to disable fp classification, and falls
back on a function call to preserve it in the face of -ffast-math.

> The point is backward-compatible behavior of -ffast-math.

I agree!  And I even found the exact patch that broke it.  So would anyone (Hi
Paolo :)) like to chime in on the rationale of the linked patch above and how
best to restore consistency of the user-facing classification functions?

In particular, can std::isnan (and its classification

[Bug middle-end/50724] cmath's floating-point classification implementations inconsistent with math.h

2011-10-17 Thread ejtttje at gmail dot com
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=50724

Ethan Tira-Thompson  changed:

   What|Removed |Added

 Status|RESOLVED|REOPENED
 Resolution|DUPLICATE   |

--- Comment #22 from Ethan Tira-Thompson  2011-10-17 
16:46:27 UTC ---
Paolo: thanks for the quick reply, but it would help if you could explain why
that is the case?  Also, a follow-up, is __builtin_isnan and friends used
anywhere except cmath?  It appears not, other than tr1/special_function_util.h,
which is also providing an __isnan.


[Bug middle-end/50724] cmath's floating-point classification implementations inconsistent with math.h

2011-10-17 Thread ejtttje at gmail dot com
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=50724

Ethan Tira-Thompson  changed:

   What|Removed |Added

 Status|RESOLVED|REOPENED
 Resolution|DUPLICATE   |

--- Comment #24 from Ethan Tira-Thompson  2011-10-17 
18:38:05 UTC ---
Please don't change bug status without comment.  We already have bug 25975
listed as a duplicate in the history several times now.  That bug report was
never really resolved, the user just found a workaround and went away. 
Further, he was using math.h, which has been stated is outside gcc, whereas I
am addressing the cmath implementation.  So not even the same issue anyway.

So that we can find a resolution to this issue, please explain why cmath cannot
use math.h?  I'm assuming there's a good reason, I just don't know the history
there.  Is it performance, portability, licensing, what? (Those who don't
understand history (me) are doomed to repeat it...)

Alternatively, another potential solution would be to tweak the __builtins to
restore the original behavior in cmath, which is what you (Paolo) were actually
suggesting early on... grepping around, it certainly looks like cmath is the
only thing using them.  Am I missing anything there?


[Bug middle-end/50724] cmath's floating-point classification implementations inconsistent with math.h

2011-10-17 Thread ejtttje at gmail dot com
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=50724

Ethan Tira-Thompson  changed:

   What|Removed |Added

 Status|RESOLVED|REOPENED
 Resolution|DUPLICATE   |

--- Comment #26 from Ethan Tira-Thompson  2011-10-17 
19:21:56 UTC ---
I'm just asking about a patch that broke existing code and this is how you
respond?  It's nothing personal, mistakes happen, I'm just trying to figure out
how to fix it for others.  (And why'd you remove someone else's name off the cc
list?  Whatever...)  If you don't have time to support your code then just say
so or ignore it, no need to be an ass about it.


[Bug middle-end/50724] cmath's floating-point classification implementations inconsistent with math.h

2011-10-17 Thread ejtttje at gmail dot com
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=50724

Ethan Tira-Thompson  changed:

   What|Removed |Added

 Status|RESOLVED|REOPENED
 Resolution|DUPLICATE   |

--- Comment #28 from Ethan Tira-Thompson  2011-10-17 
20:21:27 UTC ---
So then there are a variety of potential solutions to evaluate:

A) Don't use the builtin, go back to __isnan, perhaps only when -ff-m-o is in
effect.  Paolo says this is bad, but it's not clear why.  Seems like a decent
solution except for his apparent disapproval.

B) Change the builtin implementation, just for example with bitmasks:
  inline bool isnan(float x) {
const int EXP  = 0x7f80;
const int FRAC = 0x007f;
const int y = *((int*)(&x));
return ((y&EXP)==EXP && (y&FRAC)!=0);
  }
(this is what I'm using to reproduce isnan in my own code, maybe there are
better ways?)
But this may be a portability issue to support different float point standards,
right?  That's just as much an argument to not have users trying to do this
themselves though.

C) This is getting out of my knowledge, but Paolo also suggested "splitting the
computation in parts via the new optimization attribute and pragma, keep the
is_nan & co classifications outside the -fast-math cores."  That sounds elegant
and possibly straightforward if it's just a matter of adding an attribute.

D) Combination of A, B and/or C: add new 'safe' builtins, have cmath use them
when -ff-m-o is in effect, but otherwise use the presumably faster/more easily
optimized normal builtins when these optimizations won't change behavior.

E) Screw compatibility with older gcc or Apple's current gcc or other forks,
just update the documentation.  Make it clear -ff-m-o includes both
classification and arithmetic functions, that this behavior is not portable or
consistent even within math.h vs. cmath, and let the users suck it up. 
Generating warnings on calling the nan-generation functions like nan(char*) or
numeric_limits::quiet_NaN() and maybe the classification functions too (e.g.
"isX always evaluates to true/false") would be a plus.

I'll be pretty disappointed with gcc quality control if you really choose (E),
but it's there.


[Bug middle-end/50724] cmath's floating-point classification implementations inconsistent with math.h

2011-10-17 Thread ejtttje at gmail dot com
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=50724

--- Comment #31 from Ethan Tira-Thompson  2011-10-18 
00:33:41 UTC ---
I don't see what the hurry is to close the bug while it's still under
discussion.  I guess you guys just like hit that 'resolved' button before
you've actually committed any resolution.  OK, when in Rome...

> Maybe you should consider that the maintainers have actually thought about
> it and might know what they're talking about?  What is __isnan? Is that
> reliably available on all supported platforms?  (Hint: no)  Is __builtin_isnan
> reliably available? (Hint: yes)

This was exactly the information I was asking for.  I explicitly asked if it
was a portability issue (vs. performance or licensing, thought perhaps maybe it
was some GPL thing).  Maybe it sounded patronizing because it was such a
obvious question to you, but please have a little patience with people who are
new to the project internals.  Heck, how many people do you think even know
that __isnan is from libm and __builtin_isnan is from gcc, or the relationship
between the two?  This stuff is not well documented nor common knowledge, and
if maintainers don't want to answer questions then what do you expect?

A fair bit of this thread has been wasted on a subset of maintainers saying
'gcc hasn't changed, finite-math has always been this way', directly in
response to me showing code demonstrating the change and eventually tracking
down the patch that caused it in spite of the derogatory comments, like even
yours just now.  So similarly you might consider a user who has spent a fair
bit of time finding the problem and presenting it to you on a silver platter,
is probably not hallucinating the whole thing. (Hint: no)  Fair enough?

This is probably moot, but if you'd like to get this back on topic, I'm still
on board.

So then, just for reference, does no part of gcc rely on libm now?  Or is there
a config mechanism that lets parts of gcc use libm when it is available?  I ask
because gcc (well, libstdc++) used to use libm, so that begs the question what
is the current status?

> If you want your code to conform to floating point standards THEN DON'T
> USE -ffinite-math-only! It's there in the manual for all to see.

My concern is not 'conformance' per se.  Obviously then I just wouldn't be
using the flag.

1) Inconsistency between math.h and cmath (unpredictable optimization
application, maybe I use math.h, but someone includes cmath before my header,
perhaps a precompiled header across translation units, now my code behaves
differently, and this might vary per-translation unit within the program.)
2) Inconsistency with older versions/forks of gcc (breaking legacy
code/portability, maybe even security issues?)
3) Insufficient documentation regarding the expected degree of non-compliance
("arithmetic" includes classification?)
4) What is really the *desired* degree of non-compliance in practical usage, is
this throwing out the baby with the bathwater?  (For most of the finite-math
effects, garbage-in-garbage-out is fair enough; but the classification
functions often lead to code paths with side effects, e.g. triggering UI,
skipping data records, etc, so it's a much broader effect.)

So yes, I could just not use the flag.  But it's useful, it's just gotten too
aggressive.  As a user, it's hard to reproduce isnan (and friends) to do
validation when finite-math is active (and since build systems make it easy for
end users to recompile with additional flags, it's not entirely controllable
either, other than saying "don't do that", I'd rather it wasn't
all-or-nothing.)  Since gcc used to provide this more limited finite-math
optimization, I was hoping it would not be hard to restore it.  I also used to
think there would be a concern regarding how the user-visible scope of
finite-math had changed, breaking code. *shrug*

> That would be something for user code to do, not the library.
> Feel free to do it in your code.

I can't add an attribute to the system isnan from my user code, or can I?  I've
never been quite sure what Paolo was referring to, can someone clue me in?  It
sounded like he was saying the builtins could be given an attribute to specify
-fno-finite-math-only which would only affect their specific usage?  Maybe he
just meant I could apply different flags in different translation units of my
own code, in which case I've misunderstood.  Basically, what's the "new
optimization attribute and pragma"?

Thanks!


[Bug rtl-optimization/50782] New: optimize pragma not applying fast-math

2011-10-18 Thread ejtttje at gmail dot com
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=50782

 Bug #: 50782
   Summary: optimize pragma not applying fast-math
Classification: Unclassified
   Product: gcc
   Version: unknown
Status: UNCONFIRMED
  Severity: normal
  Priority: P3
 Component: rtl-optimization
AssignedTo: unassig...@gcc.gnu.org
ReportedBy: ejtt...@gmail.com


Summary: The optimize attribute works, but the pragma doesn't (for fast-math).

Test case:

#include 
#include 
#include 

float n = std::numeric_limits::quiet_NaN();

void test1() __attribute__((optimize("fast-math")));
void test1() {
std::cout << std::isnan(n)<<__builtin_isnan(n)<<(n!=n) << std::endl;
}

#pragma GCC optimize ("fast-math")
void test2();
void test2() {
std::cout << std::isnan(n)<<__builtin_isnan(n)<<(n!=n) << std::endl;
}

int main(int argc, char** argv) {
test1(); test2(); return 0;
}

Output of 4.6.1-9ubuntu3 with -O3:
100
111

Expected output:
100
100

The two lines should be identical, yes?  It seems the attribute is applied to
test1, but the pragma isn't catching test2.  Apologies if I'm not using the
pragma correctly.

Also, I'm not really sure what to expect for the first two values of each line,
it depends on whether the inlining is done before or after optimization.  It
appears the built-in is expanded before optimization, but the isnan() is after
(I checked with nm, isnan is indeed inlined due to -O).  So up to you if that
is an issue.  Ironically, this is exactly the behavior I was looking for in bug
50724, but I wouldn't want to rely on this since you could decide to make this
attribute apply after inlining... however, if there is a definite behavior
regarding inlined function calls, you might want to document that?

Finally, this may be a tangent, but the implied finite-math-only is not setting
__FINITE_MATH_ONLY__==1.  That seems reasonable for the attribute, because
AFAIK this attribute processing runs after the preprocessor is done, right? 
But maybe the pragma could be setting it?  This might warrant a note in the
'optimize' attribute/pragma docs regarding the (in)ability of each to update
preprocessor flags.

Thanks!


[Bug middle-end/50724] cmath's floating-point classification implementations inconsistent with math.h

2011-10-18 Thread ejtttje at gmail dot com
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=50724

--- Comment #35 from Ethan Tira-Thompson  2011-10-18 
21:09:07 UTC ---
Thanks all for the info!

I should have realized there was literally an attribute/pragma called
'optimize' (duh), and it's already in the docs... for some reason I had gotten
the impression this was a brand new development (i.e. hadn't been released
yet), I should've checked.

FYI, the optimize attribute seems to work for fast-math, but interestingly, the
pragma doesn't.  I've created a new bug 50782 for this.

> change RTL optimizers to not do comparison code folding based on
> flag_finite_math_only (so you can expand isnan to !(x==x) even with
> -ffinite-math-only)

What would you say to a solution which allows finite math to optimize the
comparisons, but at the cost of explicit classification being full function
calls?  And of course when finite math is not in effect, everything is inlined
as normal.

This would allow core computations to be fully optimized and only explicit
classification calls would be affected.  This presumes the classification calls
are less common in order to be a good tradeoff, my intuition is that this is
the case.  It also allows those of you who want to optimize-away nan checks to
continue to do so, just use a (x!=x), and as a bonus this approach will also
work consistently between gcc variants.  What do you think?

This is also easy to implement without touching the compiler source, just apply
attributes in libstdc++ to keep the classification calls no-finite-math-only,
for example the isnan implementation would be:

#if defined(__FINITE_MATH_ONLY__) && __FINITE_MATH_ONLY__
// apply attributes to retain classification functionality
  template
inline typename __gnu_cxx::__enable_if<__is_arithmetic<_Tp>::__value,
   int>::__type
isnan(_Tp __f) __attribute__ ((optimize ("no-finite-math-only"),noinline));
#endif

  template
inline typename __gnu_cxx::__enable_if<__is_arithmetic<_Tp>::__value,
   int>::__type
isnan(_Tp __f)
{
return std::__is_integer<_Tp>::__value ? false : __builtin_isnan(__f);
}

(and obviously similar for fpclassify, isfinite, isinf, and isnormal)

I tweaked isnan to short circuit on __is_integer instead of a roundabout
promotion to double.  If you don't like that it can certainly go back to the
promotion style.

This works (tested with 4.6.1) because __builtin_isnan is expanded in the isnan
context, where the optimize attribute is in effect.  If you think that
expansion behavior is subject to change (see also bug 50782), we could bump
this up to apply to the builtin itself instead of the user function...?

As written, this relies on the noinline attribute trumping the inline keyword. 
We rewrite this to avoid that conflict if needed.  (Is the inline keyword
superfluous here anyway? Testing it appears so.)


[Bug rtl-optimization/50782] optimize pragma not applying fast-math

2011-10-18 Thread ejtttje at gmail dot com
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=50782

--- Comment #1 from Ethan Tira-Thompson  2011-10-18 
21:16:23 UTC ---
I'm sorry, apparently I messed something up in my testing.

The output of -O3 is actually:
000
111

The output of -O0 is:
100
111

So the optimize attribute is being applied after/including any inlined
functions.  Obviously, when the function is not inlined, it is not affected by
the attribute.

The primary bug of the two lines not being the same remains the same.


[Bug rtl-optimization/50782] optimize pragma not applying fast-math

2011-10-18 Thread ejtttje at gmail dot com
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=50782

--- Comment #2 from Ethan Tira-Thompson  2011-10-18 
21:28:42 UTC ---
Argh, sorry for the spastic updates, but I checked again and I definitely have
these lines in my console history:
$ g++ test.cc -o test -Wall -g -O3 && ./test
100
111

But now I'm getting the 000/111 output for the same build command... I don't
understand the inconsistency *shrug* see what you get O:-)


[Bug rtl-optimization/50782] optimize pragma not applying fast-math

2011-10-18 Thread ejtttje at gmail dot com
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=50782

--- Comment #3 from Ethan Tira-Thompson  2011-10-18 
23:55:47 UTC ---
I figured out what I did differently, I did some 'minor cleanup' and moved n
out of the function scope.  This actually changes the optimization results.

This is just for reference in case you are interested:

Looking at the assembly for the three tests below, I confirmed printf is being
passed a constant value in each of them.  My theory is that in test1 gcc does a
const-eval of the isnan outside of the test function scope, whereas in the
other two it inlined isnan first and then optimized the constants within the
scope of the attribute.  Anyway this is just an example that the relationship
between the optimize attribute and inlined functions may be hard to predict (at
least, for people who aren't gcc maintainers ;))

#include 
#include 
#include 

void test1() __attribute__((optimize("fast-math")));
void test1() {
const float n = std::numeric_limits::quiet_NaN();
printf("%d\n",std::isnan(n));
}

void test2() __attribute__((optimize("fast-math")));
void test2() {
static const float n = std::numeric_limits::quiet_NaN();
printf("%d\n",std::isnan(n));
}

const float n = std::numeric_limits::quiet_NaN();
void test3() __attribute__((optimize("fast-math")));
void test3() {
printf("%d\n",std::isnan(n));
}

int main(int argc, char** argv) {
test1(); test2(); test3(); return 0;
}

Output:
ejt@vbox-ubuntu-11:~$ g++ test.cc -o test -Wall -g -O3 && ./test
1
0
0
ejt@vbox-ubuntu-11:~$ nm test | c++filt | grep -i isnan
ejt@vbox-ubuntu-11:~$ g++ test.cc -o test -Wall -g -O0 && ./test
1
1
1
ejt@vbox-ubuntu-11:~$ nm test | c++filt | grep -i isnan
0040073a W __gnu_cxx::__enable_if::__value,
int>::__type std::isnan(float)