https://gcc.gnu.org/bugzilla/show_bug.cgi?id=64722
--- Comment #10 from David Malcolm <dmalcolm at gcc dot gnu.org> ---
Notes to self on how I debugged this:
I added the following to harness.h:
gcc_jit_context_set_bool_option (
ctxt,
GCC_JIT_BOOL_OPTION_DUMP_EVERYTHING,
1);
gcc_jit_context_set_bool_option (
ctxt,
GCC_JIT_BOOL_OPTION_KEEP_INTERMEDIATES,
1);
thus populating each iteration's tempdir with logfiles (and turned off
optimizations).
Rename the tempdirs to iteration-1 and iteration-2 for the sake of sanity.
Diffing the logfiles:
(for f in $(ls /tmp/iteration-1); do
diff -up /tmp/iteration-1/$f /tmp/iteration-2/$f;
done) | less
showed the first significant difference appears
in fake.c.234r.pro_and_epilogue:
--- /tmp/iteration-1/fake.c.234r.pro_and_epilogue 2015-01-22
03:31:55.243746546 -0500
+++ /tmp/iteration-2/fake.c.234r.pro_and_epilogue 2015-01-22
03:31:55.315744888 -0500
@@ -28,11 +26,11 @@ Dataflow summary:
;; hardware regs used 7 [sp]
;; regular block artificial uses 6 [bp] 7 [sp]
;; eh block artificial uses 6 [bp] 7 [sp] 16 [argp] 20 [frame]
-;; entry block defs 0 [ax] 1 [dx] 2 [cx] 3 [bx] 6 [bp] 7 [sp] 20 [frame]
+;; entry block defs 0 [ax] 1 [dx] 2 [cx] 6 [bp] 7 [sp] 20 [frame]
i.e. "3 [bx]" no longer appears in entry block defs in iteration 2.
and it's in this dump that the RTL diverged; previous pass dumps show use a
use of bx in the call_insn, but this dump shows the save/restore
of ebx in iteration 1's code, and *not* in iteration 2's.
I put a breakpoint on emit_insn to find where the save insns are emitted:
Breakpoint 12, emit_insn (x=0xf653e900) at ../../src/gcc/emit-rtl.c:4922
4922 {
(gdb) call debug(x)
(set (mem:SI (pre_dec:SI (reg/f:SI 7 sp)) [0 S4 A8])
(reg:SI 3 bx))
(gdb) bt
#0 emit_insn (x=0xf653e900) at ../../src/gcc/emit-rtl.c:4922
#1 0xf74d2744 in ix86_emit_save_regs () at
../../src/gcc/config/i386/i386.c:10282
#2 ix86_expand_prologue () at ../../src/gcc/config/i386/i386.c:11398
#3 0xf75bd6fa in gen_prologue () at ../../src/gcc/config/i386/i386.md:12187
#4 0xf7027836 in thread_prologue_and_epilogue_insns () at
../../src/gcc/function.c:5929
#5 0xf70280a5 in rest_of_handle_thread_prologue_and_epilogue () at
../../src/gcc/function.c:6499
#6 (anonymous namespace)::pass_thread_prologue_and_epilogue::execute
(this=0x8074610) at ../../src/gcc/function.c:6537
#7 0xf71a6ac5 in execute_one_pass (pass=0x8074610) at
../../src/gcc/passes.c:2326
#8 0xf71a6f57 in execute_pass_list_1 (pass=0x8074610) at
../../src/gcc/passes.c:2378
#9 0xf71a6f6a in execute_pass_list_1 (pass=0x8074450) at
../../src/gcc/passes.c:2379
#10 0xf71a6f6a in execute_pass_list_1 (pass=0x8073910, pass@entry=0x80717d0) at
../../src/gcc/passes.c:2379
#11 0xf71a6fc3 in execute_pass_list (fn=0xf6527064, pass=0x80717d0) at
../../src/gcc/passes.c:2389
#12 0xf6f338e0 in cgraph_node::expand (this=0xf65261c8) at
../../src/gcc/cgraphunit.c:1804
#13 0xf6f34517 in output_in_order (no_reorder=no_reorder@entry=false) at
../../src/gcc/cgraphunit.c:2042
#14 0xf6f3491d in symbol_table::compile (this=0xf6527000) at
../../src/gcc/cgraphunit.c:2287
#15 0xf6f362d9 in symbol_table::finalize_compilation_unit (this=0xf6527000) at
../../src/gcc/cgraphunit.c:2370
#16 0xf6eadcad in jit_langhook_write_globals () at
../../src/gcc/jit/dummy-frontend.c:231
#17 0xf725c098 in compile_file () at ../../src/gcc/toplev.c:606
#18 0xf6eaa4ac in do_compile () at ../../src/gcc/toplev.c:2048
#19 toplev::main (this=0xffffd4c7, argc=12, argv=0x804e918) at
../../src/gcc/toplev.c:2145
#20 0xf6ec7c43 in gcc::jit::playback::context::compile (this=0xffffd52c) at
../../src/gcc/jit/jit-playback.c:1721
#21 0xf6ec03c1 in gcc::jit::recording::context::compile (this=0x804d008) at
../../src/gcc/jit/jit-recording.c:1175
#22 0xf6eb5d7c in gcc_jit_context_compile (ctxt=0x804d008) at
../../src/gcc/jit/libgccjit.c:2201
#23 0x08049bd0 in test_jit (argv0=0xffffd7ea
"/root/gcc-git-jit/build-jit/gcc/testsuite/jit/test-hello-world.c.exe",
user_data=0x0) at /root/gcc-git-jit/src/gcc/testsuite/jit.dg/harness.h:352
#24 0x08049cc8 in main (argc=1, argv=0xffffd6b4) at
/root/gcc-git-jit/src/gcc/testsuite/jit.dg/harness.h:397
This revealed that ix86_emit_save_regs is only being called on
iteration 1, not on iteration 2.
Debugging ix86_expand_prologue showed differences in "frame":
iter 1 iter 2
nregs = 1 0
reg_save_offset = 8 12
sse_reg_save_offset = 12 8
In particular, nregs = 1 on iter1, but is 0 on iter2
nregs is computed in ix86_nsaved_regs (void)
which loops over regno for real non-SSE registers calling:
ix86_save_reg (unsigned int regno, bool maybe_eh_return)
within ix86_expand_prologue:
On iteration 1:
(gdb) p this_target_hard_regs->x_call_used_regs[3]
$42 = 0 '\000'
(gdb) p this_target_hard_regs->x_fixed_regs[3]
$43 = 0 '\000'
(gdb) p regs_ever_live[3]
$44 = true
On iteration 2:
(gdb) p this_target_hard_regs->x_call_used_regs[3]
$46 = 1 '\001'
(gdb) p this_target_hard_regs->x_fixed_regs[3]
$47 = 1 '\001'
(gdb) p regs_ever_live[3]
$48 = true
which led to investigating this code in ix86_conditional_register_usage:
4394 j = PIC_OFFSET_TABLE_REGNUM;
4395 if (j != INVALID_REGNUM)
4396 fixed_regs[j] = call_used_regs[j] = 1;
and line 4396 is bizarrely only called on the 2nd iteration, not the 1st,
which led me to investigate "PIC_OFFSET_TABLE_REGNUM", and discover what
appears to be the root cause, as described in comment #1.