public inbox for gcc-help@gcc.gnu.org
 help / color / mirror / Atom feed
* Pure/const function not getting executed as the first operand to logical OR ( || ) (C++)
@ 2022-01-23  8:37 Vishal Subramanyam
  2022-01-23  9:12 ` Xi Ruoyao
  0 siblings, 1 reply; 7+ messages in thread
From: Vishal Subramanyam @ 2022-01-23  8:37 UTC (permalink / raw)
  To: gcc-help

When compiling the following C++ snippet with -O0, I'm getting a Floating Point Exception on my Ubuntu 21.10, g++ 11.2.0, x86-64.

#include <iostream>

int func(int n, int r)
{
    return n % r;
}
int main()
{
    const int n = 15, r = 0;
    if (r == 0 || func(n, r))
        std::cout << "YES" << std::endl;
    else
        std::cout << "NO" << std::endl;
    if (func(n, r) || r == 0)
        std::cout << "YES" << std::endl;
    else
        std::cout << "NO" << std::endl;
    return 0;
}

With -O0, I'm getting a Floating Point error in the second if condition since it involves executing the "func" function where division by zero occurs. 

YES
Floating point exception (core dumped)

Now, with -O1 optimization, this is the output.

YES
YES

The "func" call has been optimized away. I checked the assembly code output with -S and verified the same. Now, I would like to know what was the optimization (the optimization option) that led to this happening. When I tried compiling the same code with -O0 but with an additional "-fipa-pure-const", I'm getting the same output as the O1 program with two YESes. But when I try compiling with both the -O1 and -fno-ipa-pure-const, I am not getting the Floating Point Exception. If -fipa-pure-const is responsible for the optimization that removes the function call, shouldn't the function call occur with -fno-ipa-pure-const. I have tried various combinations of options related to dead code elimination and branch probabilities, but can't figure out what's happening?

Thanks,
Vishal

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

* Re: Pure/const function not getting executed as the first operand to logical OR ( || ) (C++)
  2022-01-23  8:37 Pure/const function not getting executed as the first operand to logical OR ( || ) (C++) Vishal Subramanyam
@ 2022-01-23  9:12 ` Xi Ruoyao
       [not found]   ` <MA1PR0101MB15596E34BCF3E684A1468974B55D9@MA1PR0101MB1559.INDPRD01.PROD.OUTLOOK.COM>
  0 siblings, 1 reply; 7+ messages in thread
From: Xi Ruoyao @ 2022-01-23  9:12 UTC (permalink / raw)
  To: Vishal Subramanyam, gcc-help

On Sun, 2022-01-23 at 08:37 +0000, Vishal Subramanyam via Gcc-help
wrote:
> When compiling the following C++ snippet with -O0, I'm getting a
> Floating Point Exception on my Ubuntu 21.10, g++ 11.2.0, x86-64.
> 
> #include <iostream>
> 
> int func(int n, int r)
> {
>     return n % r;
> }
> int main()
> {
>     const int n = 15, r = 0;
>     if (r == 0 || func(n, r))
>         std::cout << "YES" << std::endl;
>     else
>         std::cout << "NO" << std::endl;
>     if (func(n, r) || r == 0)
>         std::cout << "YES" << std::endl;
>     else
>         std::cout << "NO" << std::endl;
>     return 0;
> }
> 
> With -O0, I'm getting a Floating Point error in the second if
> condition since it involves executing the "func" function where
> division by zero occurs. 
> 
> YES
> Floating point exception (core dumped)
> 
> Now, with -O1 optimization, this is the output.
> 
> YES
> YES
> 
> The "func" call has been optimized away. I checked the assembly code
> output with -S and verified the same. Now, I would like to know what
> was the optimization (the optimization option) that led to this
> happening. When I tried compiling the same code with -O0 but with an
> additional "-fipa-pure-const", I'm getting the same output as the O1
> program with two YESes.

I can reproduce this behavior, but I have some doubt on this: I remember
someone told me that -f* options had no effect with -O0.

> But when I try compiling with both the -O1 and -fno-ipa-pure-const, I
> am not getting the Floating Point Exception. If -fipa-pure-const is
> responsible for the optimization that removes the function call,
> shouldn't the function call occur with -fno-ipa-pure-const. I have
> tried various combinations of options related to dead code elimination
> and branch probabilities, but can't figure out what's happening?

You need -fno-inline.  If the function call is inlined completely, then
the compiler can find and remove dead code without any inter-procedural
analysis.

> g++ t.cc -O1 -fno-inline -fno-ipa-pure-const && ./a.out 
> YES
> [1]    4151 floating point exception (core dumped)  ./a.out
-- 
Xi Ruoyao <xry111@mengyan1223.wang>
School of Aerospace Science and Technology, Xidian University

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

* Fw: Pure/const function not getting executed as the first operand to logical OR ( || ) (C++)
       [not found]   ` <MA1PR0101MB15596E34BCF3E684A1468974B55D9@MA1PR0101MB1559.INDPRD01.PROD.OUTLOOK.COM>
@ 2022-01-23  9:58     ` Vishal Subramanyam
  2022-01-23 10:02     ` Xi Ruoyao
  1 sibling, 0 replies; 7+ messages in thread
From: Vishal Subramanyam @ 2022-01-23  9:58 UTC (permalink / raw)
  To: gcc-help



________________________________________
From: Vishal Subramanyam <vishalsubramanyam@outlook.com>
Sent: Sunday, January 23, 2022 9:56 AM
To: Xi Ruoyao
Subject: Re: Pure/const function not getting executed as the first operand to logical OR ( || ) (C++)

This still doesn't explain why an O1 level optimization can violate the standard by not evaluating the first operand.
What optimization is my code triggering with -fno-inline? My function clearly has a return value, so how did the compiler
decide that the return value doesn't matter?

Thanks,
Vishal

________________________________________
From: Xi Ruoyao <xry111@mengyan1223.wang>
Sent: Sunday, January 23, 2022 9:12 AM
To: Vishal Subramanyam; gcc-help@gcc.gnu.org
Subject: Re: Pure/const function not getting executed as the first operand to logical OR ( || ) (C++)

On Sun, 2022-01-23 at 08:37 +0000, Vishal Subramanyam via Gcc-help
wrote:
> When compiling the following C++ snippet with -O0, I'm getting a
> Floating Point Exception on my Ubuntu 21.10, g++ 11.2.0, x86-64.
>
> #include <iostream>
>
> int func(int n, int r)
> {
>     return n % r;
> }
> int main()
> {
>     const int n = 15, r = 0;
>     if (r == 0 || func(n, r))
>         std::cout << "YES" << std::endl;
>     else
>         std::cout << "NO" << std::endl;
>     if (func(n, r) || r == 0)
>         std::cout << "YES" << std::endl;
>     else
>         std::cout << "NO" << std::endl;
>     return 0;
> }
>
> With -O0, I'm getting a Floating Point error in the second if
> condition since it involves executing the "func" function where
> division by zero occurs.
>
> YES
> Floating point exception (core dumped)
>
> Now, with -O1 optimization, this is the output.
>
> YES
> YES
>
> The "func" call has been optimized away. I checked the assembly code
> output with -S and verified the same. Now, I would like to know what
> was the optimization (the optimization option) that led to this
> happening. When I tried compiling the same code with -O0 but with an
> additional "-fipa-pure-const", I'm getting the same output as the O1
> program with two YESes.

I can reproduce this behavior, but I have some doubt on this: I remember
someone told me that -f* options had no effect with -O0.

> But when I try compiling with both the -O1 and -fno-ipa-pure-const, I
> am not getting the Floating Point Exception. If -fipa-pure-const is
> responsible for the optimization that removes the function call,
> shouldn't the function call occur with -fno-ipa-pure-const. I have
> tried various combinations of options related to dead code elimination
> and branch probabilities, but can't figure out what's happening?

You need -fno-inline.  If the function call is inlined completely, then
the compiler can find and remove dead code without any inter-procedural
analysis.

> g++ t.cc -O1 -fno-inline -fno-ipa-pure-const && ./a.out
> YES
> [1]    4151 floating point exception (core dumped)  ./a.out
--
Xi Ruoyao <xry111@mengyan1223.wang>
School of Aerospace Science and Technology, Xidian University

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

* Re: Pure/const function not getting executed as the first operand to logical OR ( || ) (C++)
       [not found]   ` <MA1PR0101MB15596E34BCF3E684A1468974B55D9@MA1PR0101MB1559.INDPRD01.PROD.OUTLOOK.COM>
  2022-01-23  9:58     ` Fw: " Vishal Subramanyam
@ 2022-01-23 10:02     ` Xi Ruoyao
  2022-01-23 10:50       ` Vishal Subramanyam
  1 sibling, 1 reply; 7+ messages in thread
From: Xi Ruoyao @ 2022-01-23 10:02 UTC (permalink / raw)
  To: Vishal Subramanyam; +Cc: gcc-help

On Sun, 2022-01-23 at 09:56 +0000, Vishal Subramanyam wrote:
> This still doesn't explain why an O1 level optimization can violate
> the standard by not evaluating the first operand.

It's not violating the standard.  The standard says division-by-zero is
an undefined behavior, so the compiler can do anything.

> What optimization is my code triggering with -fno-inline? My function
> clearly has a return value, so how did the compiler
> decide that the return value doesn't matter?

-- 
Xi Ruoyao <xry111@mengyan1223.wang>
School of Aerospace Science and Technology, Xidian University

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

* Re: Pure/const function not getting executed as the first operand to logical OR ( || ) (C++)
  2022-01-23 10:02     ` Xi Ruoyao
@ 2022-01-23 10:50       ` Vishal Subramanyam
  2022-01-23 11:25         ` Marc Glisse
  0 siblings, 1 reply; 7+ messages in thread
From: Vishal Subramanyam @ 2022-01-23 10:50 UTC (permalink / raw)
  To: Xi Ruoyao; +Cc: gcc-help

So I took a look at the x86 assembly with O1 just -fno-inline. So interprocedural analysis still happens. Now,
is there a specific name for the type of optimization where the compiler simply decides to drop the return value.
Is this related to return value optimization (though RVO usually discusses objects and explicit copy constructors)?

________________________________________
From: Xi Ruoyao <xry111@mengyan1223.wang>
Sent: Sunday, January 23, 2022 10:02 AM
To: Vishal Subramanyam
Cc: gcc-help@gcc.gnu.org
Subject: Re: Pure/const function not getting executed as the first operand to logical OR ( || ) (C++)

On Sun, 2022-01-23 at 09:56 +0000, Vishal Subramanyam wrote:
> This still doesn't explain why an O1 level optimization can violate
> the standard by not evaluating the first operand.

It's not violating the standard.  The standard says division-by-zero is
an undefined behavior, so the compiler can do anything.

> What optimization is my code triggering with -fno-inline? My function
> clearly has a return value, so how did the compiler
> decide that the return value doesn't matter?

--
Xi Ruoyao <xry111@mengyan1223.wang>
School of Aerospace Science and Technology, Xidian University

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

* Re: Pure/const function not getting executed as the first operand to logical OR ( || ) (C++)
  2022-01-23 10:50       ` Vishal Subramanyam
@ 2022-01-23 11:25         ` Marc Glisse
  2022-01-23 12:24           ` Vishal Subramanyam
  0 siblings, 1 reply; 7+ messages in thread
From: Marc Glisse @ 2022-01-23 11:25 UTC (permalink / raw)
  To: Vishal Subramanyam; +Cc: gcc-help

On Sun, 23 Jan 2022, Vishal Subramanyam via Gcc-help wrote:

> is there a specific name for the type of optimization where the compiler simply decides to drop the return value.

Gcc handles this as part of dead code elimination (among others). A 
simpler example would be

int main(){ 1/0; }

which does not crash either.

If you want to make your function func opaque to the optimizers, you may 
be interested in __attribute__((noipa)). Using volatile would also avoid 
some optimizations.

-- 
Marc Glisse

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

* Re: Pure/const function not getting executed as the first operand to logical OR ( || ) (C++)
  2022-01-23 11:25         ` Marc Glisse
@ 2022-01-23 12:24           ` Vishal Subramanyam
  0 siblings, 0 replies; 7+ messages in thread
From: Vishal Subramanyam @ 2022-01-23 12:24 UTC (permalink / raw)
  To: gcc-help

One last question. Since labelling the variables as volatile has the effect of turning off optimizations related to them,
I tried using __attribute__((const)) on the function to ensure IPA, but the function call still happened. Why couldn't the compiler
optimize these calls away since anyway the function doesn't cause any external effect?
________________________________________
From: Marc Glisse <marc.glisse@inria.fr>
Sent: Sunday, January 23, 2022 11:25 AM
To: Vishal Subramanyam
Cc: gcc-help@gcc.gnu.org
Subject: Re: Pure/const function not getting executed as the first operand to logical OR ( || ) (C++)

On Sun, 23 Jan 2022, Vishal Subramanyam via Gcc-help wrote:

> is there a specific name for the type of optimization where the compiler simply decides to drop the return value.

Gcc handles this as part of dead code elimination (among others). A
simpler example would be

int main(){ 1/0; }

which does not crash either.

If you want to make your function func opaque to the optimizers, you may
be interested in __attribute__((noipa)). Using volatile would also avoid
some optimizations.

--
Marc Glisse

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

end of thread, other threads:[~2022-01-23 12:24 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-01-23  8:37 Pure/const function not getting executed as the first operand to logical OR ( || ) (C++) Vishal Subramanyam
2022-01-23  9:12 ` Xi Ruoyao
     [not found]   ` <MA1PR0101MB15596E34BCF3E684A1468974B55D9@MA1PR0101MB1559.INDPRD01.PROD.OUTLOOK.COM>
2022-01-23  9:58     ` Fw: " Vishal Subramanyam
2022-01-23 10:02     ` Xi Ruoyao
2022-01-23 10:50       ` Vishal Subramanyam
2022-01-23 11:25         ` Marc Glisse
2022-01-23 12:24           ` Vishal Subramanyam

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