This is the mail archive of the gcc@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

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


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]