473,386 Members | 1,736 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,386 software developers and data experts.

Question on gcc -O3 optimization (bug or feature)

Hi,

I have the following code that is compiled on gcc422 (linux) with -
O3 option. I see that one of the branch is discarded, even though it
is not a dead branch. Is this a bug or a feature?

#include <stdlib.h>
#include <stdio.h>

void show_issue(int number)
{
if( number < 0 ) {
printf("%d is a negative number \n", number);
number = - number;
printf("After conversion: %d\n", number);
if( number < 0 ) {
/* ################ with gcc422 -O3, this branch is
discarded ############ */
printf("Must be INT_MIN since negating has no effect\n");
}
}
else {
printf("%d is positive number\n", number);
}
}
int main()
{
int i;
for(i = 30; i < 32; i++ ) {
show_issue( 1 << i );
}
return 0;
}
Jun 27 '08 #1
10 1919
In article <66**********************************@y22g2000prd. googlegroups.com>,
compiler_newbie <bh****@gmail.comwrote:
I have the following code that is compiled on gcc422 (linux) with -
O3 option. I see that one of the branch is discarded, even though it
is not a dead branch. Is this a bug or a feature?
>#include <stdlib.h>
#include <stdio.h>

void show_issue(int number)
{
if( number < 0 ) {
printf("%d is a negative number \n", number);
number = - number;
printf("After conversion: %d\n", number);
if( number < 0 ) {
/* ################ with gcc422 -O3, this branch is
discarded ############ */
printf("Must be INT_MIN since negating has no effect\n");
}
}
else {
printf("%d is positive number\n", number);
}
}
The result of integer overflow with the unary negation operator
is undefined in the C standard, so the compiler is free to do whatever
it feels like for that case.
--
"The study of error is not only in the highest degree
prophylatic, but it serves as a stimulating introduction to the
study of truth." -- Walter Lipmann
Jun 27 '08 #2
compiler_newbie <bh****@gmail.comwrites:
void show_issue(int number)
{
if( number < 0 ) {
printf("%d is a negative number \n", number);
number = - number;
printf("After conversion: %d\n", number);
if( number < 0 ) {
/* ################ with gcc422 -O3, this branch is
discarded ############ */
It is discarded because signed arithmetic overflow yields
undefined behavior.

If you want to get the behavior that you expect, you can use the
-fwrapv option:

`-fwrapv'
This option instructs the compiler to assume that signed arithmetic
overflow of addition, subtraction and multiplication wraps around
using twos-complement representation. This flag enables some
optimizations and disables others. This option is enabled by
default for the Java front-end, as required by the Java language
specification.

printf("Must be INT_MIN since negating has no effect\n");
}
}
else {
printf("%d is positive number\n", number);
}
}
--
Ben Pfaff
http://benpfaff.org
Jun 27 '08 #3
On Jun 11, 10:27 am, Ben Pfaff <b...@cs.stanford.eduwrote:
>
It is discarded because signed arithmetic overflow yields
undefined behavior.

Thanks for your responses and the mention of the compiler flag that
supports the "classic" behaviour.
Jun 27 '08 #4
compiler_newbie wrote:
Ben Pfaff <b...@cs.stanford.eduwrote:
>It is discarded because signed arithmetic overflow yields
undefined behavior.

Thanks for your responses and the mention of the compiler flag
that supports the "classic" behaviour.
It's not classic behaviour, and that 'flag' is not generally
available. For portable code you have to assume that inverting
INT_MAX can cause overflow and undefined (or implementation
defined) behaviour.

The simplest thing is:

if (INT_MIN == n) ...

which is totally independent.

--
[mail]: Chuck F (cbfalconer at maineline dot net)
[page]: <http://cbfalconer.home.att.net>
Try the download section.
** Posted from http://www.teranews.com **
Jun 27 '08 #5

"compiler_newbie" <bh****@gmail.comschreef in bericht
news:f8**********************************@l28g2000 prd.googlegroups.com...
On Jun 11, 10:27 am, Ben Pfaff <b...@cs.stanford.eduwrote:
>>
It is discarded because signed arithmetic overflow yields
undefined behavior.


Thanks for your responses and the mention of the compiler flag that
supports the "classic" behaviour.
it looks strange to me to first do an operation and then after that check if
the operation should've been done.
Why not just check before and code the expected behaviour yourself??

Jun 27 '08 #6
compiler_newbie wrote:
void show_issue(int number)
{
if( number < 0 ) {
printf("%d is a negative number \n", number);
OK so number < 0
number = - number;
OK now number 0
printf("After conversion: %d\n", number);
if( number < 0 ) {
The compiler can guarantee that this condition is /never/ true.
/* ################ with gcc422 -O3, this branch is
discarded ############ */
printf("Must be INT_MIN since negating has no effect\n");
}
}
else {
printf("%d is positive number\n", number);
}
}
Jun 27 '08 #7
In article <66**********************************@y22g2000prd. googlegroups.comcompiler_newbie <bh****@gmail.comwrites:
....
void show_issue(int number)
{
if( number < 0 ) {
....
number = - number;
....
if( number < 0 ) {
/* ################ with gcc422 -O3, this branch is
discarded ############ */
printf("Must be INT_MIN since negating has no effect\n");
No. If number equals INT_MIN and -INT_MIN is not an integer it is
undefined behaviour (it might signal overflow).
--
dik t. winter, cwi, kruislaan 413, 1098 sj amsterdam, nederland, +31205924131
home: bovenover 215, 1025 jn amsterdam, nederland; http://www.cwi.nl/~dik/
Jun 27 '08 #8
"Serve Lau" <ni***@qinqin.comwrites:
"compiler_newbie" <bh****@gmail.comschreef in bericht
news:f8**********************************@l28g2000 prd.googlegroups.com...
>On Jun 11, 10:27 am, Ben Pfaff <b...@cs.stanford.eduwrote:
>>>
It is discarded because signed arithmetic overflow yields
undefined behavior.

Thanks for your responses and the mention of the compiler flag that
supports the "classic" behaviour.

it looks strange to me to first do an operation and then after that
check if the operation should've been done.
Why not just check before and code the expected behaviour yourself??
Really?

Consider this:

long long x = <some value>, y = <some other value>;
if (<multiplication would overflow>) {
printf("%lld * %lld would overflow\n");
}
else {
printf("%lld * %lld = %lld\n", x * y);
}

(I chose long long to preclude using a longer type to hold an
intermediate result.)

How would you complete the above code so its output is always correct?

I have no doubt that it's possible to do this, but it's going to take
at least several lines of code, and it's likely to be more expensive
than the multiplication itself. (And I'm too lazy to work it out
myself.) Imagine doing that for every arithmetic operation in your
program.

On the other hand, most CPUs provide a straightforward way to attempt
a multiplication and determine after the fact whether it overflowed.
Unfortunately, due to the variety of CPUs out there, it wasn't
practical for C to provide a standard way to do this.

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
Nokia
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
Jun 27 '08 #9

"Keith Thompson" <ks***@mib.orgschreef in bericht
news:ln************@nuthaus.mib.org...
"Serve Lau" <ni***@qinqin.comwrites:
>"compiler_newbie" <bh****@gmail.comschreef in bericht
news:f8**********************************@l28g200 0prd.googlegroups.com...
>>On Jun 11, 10:27 am, Ben Pfaff <b...@cs.stanford.eduwrote:

It is discarded because signed arithmetic overflow yields
undefined behavior.

Thanks for your responses and the mention of the compiler flag that
supports the "classic" behaviour.

it looks strange to me to first do an operation and then after that
check if the operation should've been done.
Why not just check before and code the expected behaviour yourself??

Really?

Consider this:

long long x = <some value>, y = <some other value>;
if (<multiplication would overflow>) {
printf("%lld * %lld would overflow\n");
}
else {
printf("%lld * %lld = %lld\n", x * y);
}
you're right, there are situations where it wouldnt make much sense however
in the case of x = -x its easy and cleaner to check before.

or take

x = x / y;

if (program_crashed())
{
printf("y was zero\n");
x = 0;
}

wouldnt make much sense either right.

Jun 27 '08 #10
"Serve Lau" <ni***@qinqin.comwrites:
"Keith Thompson" <ks***@mib.orgschreef in bericht
news:ln************@nuthaus.mib.org...
>"Serve Lau" <ni***@qinqin.comwrites:
>>"compiler_newbie" <bh****@gmail.comschreef in bericht
news:f8**********************************@l28g20 00prd.googlegroups.com...
On Jun 11, 10:27 am, Ben Pfaff <b...@cs.stanford.eduwrote:
>
It is discarded because signed arithmetic overflow yields
undefined behavior.

Thanks for your responses and the mention of the compiler flag that
supports the "classic" behaviour.

it looks strange to me to first do an operation and then after that
check if the operation should've been done.
Why not just check before and code the expected behaviour yourself??

Really?

Consider this:

long long x = <some value>, y = <some other value>;
if (<multiplication would overflow>) {
printf("%lld * %lld would overflow\n");
}
else {
printf("%lld * %lld = %lld\n", x * y);
}

you're right, there are situations where it wouldnt make much sense
however in the case of x = -x its easy and cleaner to check before.
Checking that with full portability is slightly trickier than what I'm
guessing you're thinking of. It overflows if and only if
(LLONG_MIN < -LLONG_MAX && x == LLONG_MIN)
and you have to adjust it depending on the type of x (with no help
from the compiler if you get it wrong).
or take

x = x / y;

if (program_crashed())
{
printf("y was zero\n");
x = 0;
}

wouldnt make much sense either right.
It would make a great deal of sense if, rather than program_crashed(),
the language provided a way to detect any kind of arithmetic error.
For example, in Ada:

begin
X := X / Y;
exception
when Constraint_Error =>
-- handle overflow
end;

And I think you're forgetting a possibility. Assuming, again,
that x and y are of type long long, the division can overflow on a
two's-complement system if x == LLONG_MIN and y == -1. That's just
the kind of thing that programmer's can easily forget, and that
compilers can't forget.

Of course floating-point division can easily overflow if the right
operand has a magnitude less than 1.0.

In practice, most programmers, most of the time, just don't bother
doing these checks. We instead use types that we *think* (or hope)
are big enough to hold whatever values we need. It's almost the
numeric equivalent of gets() with an array that we *think* is big
enough to hold whatever the user enters (except that we have a bit
more control over the input).

*If* C provided a way to detect numeric overflow after the fact
without invoking undefined behavior, it could be a lot easier to
write safer software in C -- and if the checks were built into the
language, the compiler could potentially eliminate a lot of them,
in cases where it can prove that a given expression can't overflow.
As programmers, we'd have to apply that reasoning to every expression
in a program, and most of us aren't compulsive enough to do this
and get it right every single time.

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
Nokia
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
Jun 27 '08 #11

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

3
by: Bryan Parkoff | last post by:
.....I try to reduce un-necessary temporal variables so it can be optimized for best performance. I try to assign only one register storage so two variables can access to only one register storage...
6
by: Thorsten Raasch | last post by:
Hi, the following C++ program seems to yield a segmentation fault in g++ 3.4 when compiled with any of the optimization options -O*, e.g. with "g++ -O2 bug.cpp -o bug". class TestClass {...
5
by: Carmine Cairo | last post by:
Hi, I'm working on a project and today I've note a little problem during the compile fase. Here a little piece of code: // 1st version welldone = 0; size = p->getSize(); backbone = new...
83
by: user | last post by:
Hello, Here is the program #include stdio int main(void) { const int num = 100; int *ip;
1
by: noleander | last post by:
Ive got Vis C++ 2003 standard edition. I want to optimize my application for speed (use the /O2 directive). The "optimization" field in my Project Properties window shows /O2 (in my Release...
11
by: jryden | last post by:
I wrote the following code into a console program in Visual C++6. If you build a release build and select custom optimizations and select 'general optimizations' as the only optimization then you...
3
by: Abhishek | last post by:
Recently i found that my C++ program was running fine with no optimization and giving segmentation fault with error code 139 when compiled with optimization level 2. I searched somewhat but never...
45
by: Robbie Hatley | last post by:
Hello, group. I've been doing too much C++ programming lately, and I'm starting to become rusty at some aspects of the C way of doing things, esp. efficient low-level data copies. ...
3
by: per9000 | last post by:
Hi, I've written a small app that I mostly want to run from the console. Sometimes I want the output in a GUI instead to facilitate a "Save As" feature etc. I created a nice form etc and the...
0
by: taylorcarr | last post by:
A Canon printer is a smart device known for being advanced, efficient, and reliable. It is designed for home, office, and hybrid workspace use and can also be used for a variety of purposes. However,...
0
by: aa123db | last post by:
Variable and constants Use var or let for variables and const fror constants. Var foo ='bar'; Let foo ='bar';const baz ='bar'; Functions function $name$ ($parameters$) { } ...
0
by: ryjfgjl | last post by:
If we have dozens or hundreds of excel to import into the database, if we use the excel import function provided by database editors such as navicat, it will be extremely tedious and time-consuming...
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...
0
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However,...
0
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...
0
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.