This is the mail archive of the
gcc@gcc.gnu.org
mailing list for the GCC project.
instrumentation between call and GP restore
- From: Janis Johnson <janis187 at us dot ibm dot com>
- To: gcc at gcc dot gnu dot org
- Date: Wed, 19 Dec 2001 10:07:55 -0800
- Subject: instrumentation between call and GP restore
I'm stuck and would appreciate a hint or two on how to fix this.
Loads and stores on IA-64 are all done through addresses in registers.
Data that is not on the stack is addressed through the GP, which is a
caller-save register. Arc profiling is inserting instrumentation code
between a call and the restore of the GP, causing it to sometimes use
the wrong GP value to find the address of the profile block count.
Here's a simple test case that aborts at run-time when compiled with
"-ftest-coverage -fprofile-arcs" on ia64-linux:
extern void srand (int);
int main ()
{
srand (2);
exit (0);
}
On entry to branch_prob, the RTL for the call to srand and the
save/restore of the GP is:
(insn 11 9 12 (set (reg:DI 32 loc0)
(reg:DI 1 r1)) -1 (nil)
(nil))
(call_insn 12 11 14 (parallel[
(call (mem:DI (symbol_ref/v:DI ("srand")) [0 S8 A64])
(const_int 1 [0x1]))
(use (unspec[
(reg:DI 1 r1)
] 9))
(clobber (reg:DI 320 b0))
] ) -1 (nil)
(nil)
(expr_list (use (reg:SI 120 out0))
(nil)))
(insn 14 12 15 (set (reg:DI 1 r1)
(reg:DI 32 loc0)) -1 (nil)
(nil))
The call to flow_call_edges_add from branch_prob splits the block after
the CALL_INSN and arc-profiling instrumentation is inserted at the
beginning of the new block, resulting in:
(insn 11 9 12 (set (reg:DI 32 loc0)
(reg:DI 1 r1)) -1 (nil)
(nil))
(call_insn 12 11 44 (parallel[
(call (mem:DI (symbol_ref/v:DI ("srand")) [0 S8 A64])
(const_int 1 [0x1]))
(use (unspec[
(reg:DI 1 r1)
] 9))
(clobber (reg:DI 320 b0))
] ) -1 (nil)
(nil)
(expr_list (use (reg:SI 120 out0))
(nil)))
(insn 44 12 45 (set (reg:DI 346)
(plus:DI (reg:DI 1 r1) <--- use the GP
(symbol_ref:DI ("*.LPBX2")))) -1 (nil)
(nil))
(insn 45 44 47 (set (reg:DI 345)
(mem/u:DI (reg:DI 346) [0 S8 A64])) -1 (nil)
(expr_list:REG_EQUAL (symbol_ref:DI ("*.LPBX2"))
(nil)))
(insn 47 45 48 (set (reg:DI 347)
(reg:DI 345)) -1 (nil)
(nil))
(insn 48 47 50 (set (reg/f:DI 348)
(plus:DI (reg:DI 345)
(const_int 8 [0x8]))) -1 (nil)
(nil))
(insn 50 48 51 (set (reg:DI 349)
(mem:DI (reg/f:DI 348) [0 S8 A64])) -1 (nil)
(nil))
(insn 51 50 53 (set (reg:DI 350)
(plus:DI (reg:DI 349)
(const_int 1 [0x1]))) -1 (nil)
(nil))
(insn 53 51 14 (set (mem:DI (reg/f:DI 348) [0 S8 A64])
(reg:DI 350)) -1 (nil)
(nil))
(insn 14 53 15 (set (reg:DI 1 r1) <--- restore GP
(reg:DI 32 loc0)) -1 (nil)
(nil))
Is there a mechanism to keep the GP restore in the same block as the
call, or to recognize that the instrumentation code uses the GP that was
clobbered in the call?
Janis