fix for spurious ppc cvs-1.c compile failures

Jeffrey A Law law@hurl.cygnus.com
Fri Feb 5 11:40:00 GMT 1999


The ppc port (and any other using the haifa scheduler) can perform an
uninitialized memory read if a CALL_INSN has a dependency on an insn
which is deleted during register allocation & reloading.

Consider:

(insn 9 12 10 (set (reg:DF 33 f1)
        (reg:DF 33 f1)) 560 {*movdf_hardfloat32} (nil)
    (insn_list:REG_LIBCALL 11 (nil)))

(insn 10 9 11 (use (reg:DF 33 f1)) -1 (insn_list 9 (nil))
    (expr_list:REG_DEAD (reg:DF 33 f1)
        (nil)))

(call_insn/s 11 10 14 (parallel[
            (set (reg:SI 3 r3)
                (call (mem:SI (symbol_ref:SI ("__itrunc")) 0)
                    (const_int 0)))
            (use (const_int 0))
            (clobber (scratch:SI))
        ] ) 649 {*ret_call_nonlocal_aix32} (insn_list 9 (insn_list:REG_DEP_ANTI
10 (nil)))
    (insn_list:REG_RETVAL 9 (expr_list:REG_UNUSED (scratch:SI)
            (nil)))
    (nil))

Note the dependency in insn 11 on insn 9.

Now this after reload has completed:

(note 9 12 10 "" NOTE_INSN_DELETED)

;; Start of basic block 0, registers live: 1 [1] 31 [31] 33 [1]
(insn 10 9 11 (use (reg:DF 33 f1)) -1 (insn_list 9 (nil))
    (expr_list:REG_DEAD (reg:DF 33 f1)
        (nil)))

(call_insn/s 11 10 14 (parallel[
            (set (reg:SI 3 r3)
                (call (mem:SI (symbol_ref:SI ("__itrunc")) 0)
                    (const_int 0)))
            (use (const_int 0))
            (clobber (reg:SI 65 lr))
        ] ) 649 {*ret_call_nonlocal_aix32} (insn_list 9 (insn_list:REG_DEP_ANTI
10 (nil)))
    (expr_list:REG_UNUSED (reg:SI 65 lr)
        (nil))
    (nil))

The nop move has been deleted, but the dependency is left on insn 11.  As best
as I can tell that is the expected behavior.

Anyway, haifa-sched.c::add_dependence has this code:

#ifdef INSN_SCHEDULING
  /* (This code is guarded by INSN_SCHEDULING, otherwise INSN_BB is undefined.)
     No need for interblock dependences with calls, since
     calls are not moved between blocks.   Note: the edge where
     elem is a CALL is still required.  */
  if (GET_CODE (insn) == CALL_INSN
      && (INSN_BB (elem) != INSN_BB (insn)))
    return;

#endif


INSN_BB is defined as:

#define INSN_BB(INSN) (BLOCK_TO_BB (INSN_BLOCK (INSN)))

INSN_BLOCK is defined as:

#define INSN_BLOCK(insn) (insn_orig_block[INSN_UID (insn)])

And insn_orig_block is initialized with:

  luid = 0;
  for (b = 0; b < n_basic_blocks; b++)
    for (insn = BLOCK_HEAD (b);; insn = NEXT_INSN (insn))
      {
        INSN_BLOCK (insn) = b;
        INSN_LUID (insn) = luid++;

        if (insn == BLOCK_END (b))
          break;
      }

Note that only insns which are inside a basic block are assigned a block or
or LUID number.

Thus if a CALL_INSN's dependency is on a NOTE which falls outside of the
boundaries of basic blocks, then we can perform an uninitialized read of
insn_orig_block.


Any dependency on a NOTE is useless and can/should be ignored.  The old
scheduler doesn't have this problem; it also ignores depedncies on notes,
but using other mechanisms.

	* haifa-sched.c (add_dependence): Do not add a dependency on a
	note.


Index: haifa-sched.c
===================================================================
RCS file: /cvs/cvsfiles/devo/gcc/haifa-sched.c,v
retrieving revision 1.105
diff -c -3 -p -r1.105 haifa-sched.c
*** haifa-sched.c	1999/02/03 05:49:09	1.105
--- haifa-sched.c	1999/02/05 19:20:54
*************** add_dependence (insn, elem, dep_type)
*** 861,866 ****
--- 861,872 ----
    if (insn == elem)
      return;
  
+   /* We can get a dependency on deleted insns due to optimizations in
+      the register allocation and reloading or due to splitting.  Any
+      such dependency is useless and can be ignored.  */
+   if (GET_CODE (elem) == NOTE)
+     return;
+ 	
    /* If elem is part of a sequence that must be scheduled together, then
       make the dependence point to the last insn of the sequence.
       When HAVE_cc0, it is possible for NOTEs to exist between users and


More information about the Gcc-patches mailing list