Prevent GCC from folding inline test functions
authorLuis Machado <lgustavo@codesourcery.com>
Mon, 24 Aug 2015 15:33:21 +0000 (12:33 -0300)
committerLuis Machado <lgustavo@codesourcery.com>
Mon, 24 Aug 2015 15:33:21 +0000 (12:33 -0300)
While doing some powerpc Linux tests on a ppc 476 board using GCC 5.2, i
noticed inline-bt.exp, inline-cmds.exp and inline-locals.exp failing.

FAIL: gdb.opt/inline-bt.exp: continue to bar (1)
FAIL: gdb.opt/inline-bt.exp: backtrace from bar (1)
FAIL: gdb.opt/inline-bt.exp: continue to bar (2)
FAIL: gdb.opt/inline-bt.exp: backtrace from bar (2)
FAIL: gdb.opt/inline-bt.exp: continue to bar (3)
FAIL: gdb.opt/inline-bt.exp: backtrace from bar (3)
FAIL: gdb.opt/inline-cmds.exp: continue to bar (1)
FAIL: gdb.opt/inline-cmds.exp: backtrace from bar (1)
FAIL: gdb.opt/inline-cmds.exp: continue to bar (2)
FAIL: gdb.opt/inline-cmds.exp: backtrace from bar (2)
FAIL: gdb.opt/inline-cmds.exp: continue to marker
FAIL: gdb.opt/inline-cmds.exp: backtrace from marker
FAIL: gdb.opt/inline-cmds.exp: step into finish marker
FAIL: gdb.opt/inline-locals.exp: continue to bar (1)
FAIL: gdb.opt/inline-locals.exp: continue to bar (2)
FAIL: gdb.opt/inline-locals.exp: backtrace from bar (2)
FAIL: gdb.opt/inline-locals.exp: continue to bar (3)
FAIL: gdb.opt/inline-locals.exp: backtrace from bar (3)

They failed because the breakpoint supposedly inserted at bar was actually
inserted at noinline.

(gdb) break inline-markers.c:20^M
Breakpoint 2 at 0x1000079c: file gdb/testsuite/gdb.opt/inline-markers.c, line 20.^M
(gdb) continue^M
Continuing.^M
^M
Breakpoint 2, noinline () at gdb/testsuite/gdb.opt/inline-markers.c:35^M
35        inlined_fn (); /* inlined */^M

As we can see, line 20 is really inside bar, not noinline:

18 void bar(void)
19 {
20   x += y; /* set breakpoint 1 here */
21 }

Further investigation shows that this is really due to GCC 5's new
ICF pass (-fipa-icf), now enabled by default at -O2, which folds bar
and marker into noinline, where the call to inlined_fn was inlined.

This breaks the testcase since it expects to stop at specific spots.

I thought about two possible fixes for this issue.

- Disable the ICF pass manually when building the binary (-fno-ipa-icf).

This has the advantage of not having to touch the testcase sources themselves,
but the disadvantage of having to add conditional blocks to test the GCC
version. If we ever change GCC's default, we will have to adjust the
conditional block again to match GCC's behavior.

- Modify the testcase sources to make the identical functions unique.

This solution doesn't touch the testcase itself, but changes the source
code slightly in order to make bar, marker and inlined_fn unique. This
causes GCC's ICF pass to ignore these functions and not fold them into
a common identical function.

I'm good with either of them, but i'm more inclined to go with the second
one.

The attached patch implements this by adding the new global variable z, set
to 0, that gets added in different ways to marker and inlined_fn. Since it
is 0, it doesn't affect any possible value checks that we may wish to do
in the future (we currently only check for values changed by bar).

Ok?

ps: I also noticed GDB doesn't do a great job at stating that the breakpoint
was actually inserted at a different source line than previously requested,
so this sounds like a bug that should be fixed, if it is not just wrong
DWARF information (did not investigate it further).

gdb/testsuite/ChangeLog:

2015-08-24  Luis Machado  <lgustavo@codesourcery.com>

* gdb.opt/inline-bt.c: New volatile global z.
* gdb.opt/inline-cmds.c: Likewise.
* gdb.opt/inline-locals.c: Likewise.
* gdb.opt/inline-markers.c: New extern global z.
(marker): Use z.
(inline_fn): Likewise.

gdb/testsuite/ChangeLog
gdb/testsuite/gdb.opt/inline-bt.c
gdb/testsuite/gdb.opt/inline-cmds.c
gdb/testsuite/gdb.opt/inline-locals.c
gdb/testsuite/gdb.opt/inline-markers.c

index c3d5182d1e58d099f502452b838161bcc787a442..b788c0f8eca4d859433a6aba5b03bf5036b2c883 100644 (file)
@@ -1,3 +1,12 @@
+2015-08-24  Luis Machado  <lgustavo@codesourcery.com>
+
+       * gdb.opt/inline-bt.c: New volatile global z.
+       * gdb.opt/inline-cmds.c: Likewise.
+       * gdb.opt/inline-locals.c: Likewise.
+       * gdb.opt/inline-markers.c: New extern global z.
+       (marker): Use z.
+       (inline_fn): Likewise.
+
 2015-08-24  Pedro Alves  <palves@redhat.com>
 
        * config/m32r-stub.exp: Remove file.
index dc2bd45c37f8cd611464337381d4e41b6fac4249..a47d16e6afde7724dfbdc58f956e53d374c74490 100644 (file)
@@ -23,6 +23,7 @@
 #endif
 
 int x, y;
+volatile int z = 0;
 volatile int result;
 
 void bar(void);
index 9955720c9128a6fd7f5694e4eaf8fcf39debe015..cc43b57b68987098d2857e38fe6ae162b585fa79 100644 (file)
@@ -23,6 +23,7 @@
 #endif
 
 int x, y;
+volatile int z = 0;
 volatile int result;
 
 void bar(void);
index fc018bfa960d0fc600db120f786d28a7ed45cb5d..fa5cd137b114abe9df133bcb238cfebca8430176 100644 (file)
@@ -23,6 +23,7 @@
 #endif
 
 int x, y;
+volatile int z = 0;
 volatile int result;
 volatile int *array_p;
 
index 46c68ae9d8eda520adbbf28ac4bc2e02902bf9a5..5d5503331d4e3858e254959b01cad3c4b4f0ecc2 100644 (file)
@@ -13,7 +13,7 @@
    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
 
-extern int x, y;
+extern int x, y, z;
 
 void bar(void)
 {
@@ -22,12 +22,12 @@ void bar(void)
 
 void marker(void)
 {
-  x += y; /* set breakpoint 2 here */
+  x += y - z; /* set breakpoint 2 here */
 }
 
 inline void inlined_fn(void)
 {
-  x += y;
+  x += y + z;
 }
 
 void noinline(void)