This is the mail archive of the gcc-patches@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]

Re: post-reload register copy-propagation



Richard Henderson wrote:

>On Fri, Dec 14, 2001 at 11:35:31PM +0100, Ulrich Weigand wrote:
>> Thus, the subsequent copy-propagation pass doesn't know that the
>> eh registers are clobbered and incorrectly reuses one of them
>> inside the catch block to refer to a value from the main routine;
>> this causes another test case failure ...
>
>Test case and target tuple?

Well, on s390-ibm-linux this trivial test case
shows the problem (it's an extremely simplified
version of __cxa_vec_delete2, where I've noticed
the problem first ...):

extern "C" void dummy (void);

extern "C" void test (int a, int b, int c, int d,
                      void (*callback) (void))
{
  try
    {
      dummy ();
    }
  catch (...)
    {
      callback ();
    }
}


Note that 'callback' is passed in register 6 according
to the S/390 calling convention.  Register 6 at the same
time is the first EH_RETURN_DATA_REGNO, so it is clobbered
by exception handling.

Nevertheless, the code above compiled with -O2 results in:

test:
     stm  %r6,%r15,24(%r15)
     bras %r13,.LTN0_0
.LT0_0:
.LC0:
     .long     dummy
.LC1:
     .long     __cxa_begin_catch
.LC2:
     .long     __cxa_end_catch
.LC4:
     .long     _Unwind_Resume
.LTN0_0:
     lr   %r1,%r15
     ahi  %r15,-96
.LCFI1:
     st   %r1,0(%r15)
     l    %r1,.LC0-.LT0_0(%r13)    # 154      *movsi/3  [length = 4]
.LEHB0:
     basr %r14,%r1  # 30 basr_31   [length = 2]
.LEHE0:
     j    .L1  # 32 jump [length = 4]
.L10:
     l    %r1,.LC1-.LT0_0(%r13)    # 153      *movsi/3  [length = 4]
     lr   %r2,%r6   # 42 *movsi/1  [length = 2]
     basr %r14,%r1  # 45 basr_r_31 [length = 2]
.LEHB1:
     basr %r14,%r6  # 53 basr_31   [length = 2]
.LEHE1:
     l    %r1,.LC2-.LT0_0(%r13)    # 83  *movsi/3  [length = 4]
.LEHB2:
     basr %r14,%r1  # 84 basr_31   [length = 2]
.LEHE2:
     j    .L1  # 156     jump [length = 4]
.L9:
     l    %r1,.LC2-.LT0_0(%r13)    # 64  *movsi/3  [length = 4]
     basr %r14,%r1  # 65 basr_31   [length = 2]
     l    %r1,.LC4-.LT0_0(%r13)    # 112      *movsi/3  [length = 4]
     lr   %r2,%r6   # 110     *movsi/1   [length = 2]
.LEHB3:
     basr %r14,%r1  # 113     basr_31    [length = 2]
.LEHE3:
.L1:
     l    %r4,152(%r15)
     lm   %r6,%r15,120(%r15)
     br   %r4


Note the call to 'callback' in insn 53, where register
6 is used incorrectly.  (In insn 42, register 6 is used
correctly for exception handling logic.)

I've appended the flow2 and rnreg traces below for further
details; before the copy-prop pass, the initial value of
reg 6 had been correctly reloaded into reg 12.


>The copy-prop pass isn't supposed to traverse EH edges...

OK, now I see how this is supposed to work, thanks.

However, the following code doesn't seem to care about the
type of the edge:

      /* If a block has a single predecessor, that we've already
         processed, begin with the value data that was live at
         the end of the predecessor block.  */
      /* ??? Ought to use more intelligent queueing of blocks.  */
      if (bb->pred
          && ! bb->pred->pred_next
          && bb->pred->src->index != ENTRY_BLOCK
          && bb->pred->src->index < b)
        all_vd[b] = all_vd[bb->pred->src->index];
      else
        init_value_data (all_vd + b);

If I add a '&& ! (bb->pred->flags & EDGE_COMPLEX)' to the
condition, this test case works fine ...




;; Function void test(int, int, int, int, void (*)())



try_optimize_cfg iteration 1

Forwarding edge 0->1 to 6 failed.
Forwarding edge 2->3 to 5 failed.


try_optimize_cfg iteration 1

Forwarding edge 0->1 to 6 failed.
Forwarding edge 2->3 to 5 failed.
55 registers.

7 basic blocks, 9 edges.

Basic block 0: first insn 94, last 30, loop_depth 0, count 0, freq 10000.
Predecessors:  ENTRY [100.0%]  (fallthru)
Successors:  1 [50.0%]  (fallthru) 2 [50.0%]  (ab,abcall,eh)
Registers live at start: 6 [%r6] 15 [%r15]
Registers live at end: 6 [%r6] 12 [%r12] 15 [%r15]

Basic block 1: first insn 95, last 32, loop_depth 0, count 0, freq 5000.
Predecessors:  0 [50.0%]  (fallthru)
Successors:  6 [100.0%]
Registers live at start: 15 [%r15]
Registers live at end: 15 [%r15]

Basic block 2: first insn 131, last 53, loop_depth 0, count 0, freq 5000.
Predecessors:  0 [50.0%]  (ab,abcall,eh)
Successors:  3 [50.0%]  (fallthru) 4 [50.0%]  (ab,abcall,eh)
Registers live at start: 6 [%r6] 12 [%r12] 15 [%r15]
Registers live at end: 6 [%r6] 15 [%r15]

Basic block 3: first insn 97, last 55, loop_depth 0, count 0, freq 2500.
Predecessors:  2 [50.0%]  (fallthru)
Successors:  5 [100.0%]
Registers live at start: 15 [%r15]
Registers live at end: 15 [%r15]

Basic block 4: first insn 121, last 113, loop_depth 0, count 0, freq 2500.
Predecessors:  2 [50.0%]  (ab,abcall,eh)
Successors:
Registers live at start: 6 [%r6] 15 [%r15]
Registers live at end: 15 [%r15]

Basic block 5: first insn 81, last 84, loop_depth 0, count 0, freq 2500.
Predecessors:  3 [100.0%]
Successors:  6 [100.0%]  (fallthru)
Registers live at start: 15 [%r15]
Registers live at end: 15 [%r15]

Basic block 6: first insn 93, last 103, loop_depth 0, count 0, freq 7500.
Predecessors:  5 [100.0%]  (fallthru) 1 [100.0%]
Successors:  EXIT [100.0%]  (fallthru)
Registers live at start: 15 [%r15]
Registers live at end: 15 [%r15]

(note 2 0 94 NOTE_INSN_DELETED)

;; Start of basic block 0, registers live: 6 [%r6] 15 [%r15]
(note 94 2 15 [bb 0] NOTE_INSN_BASIC_BLOCK)

(note 15 94 17 NOTE_INSN_FUNCTION_BEG)

(note 17 15 19 0x401b94c0 NOTE_INSN_BLOCK_BEG)

(note 19 17 14 0x401b9480 NOTE_INSN_BLOCK_BEG)

(insn 14 19 154 (set (reg/v/f:SI 12 %r12 [43])
        (reg:SI 6 %r6)) 42 {*movsi} (nil)
    (nil))

(insn 154 14 30 (set (reg/f:SI 1 %r1 [44])
        (mem/u/f:SI (symbol_ref/u:SI ("*.LC0")) [2 S4 A32])) 42 {*movsi}
(nil)
    (expr_list:REG_EQUIV (symbol_ref:SI ("dummy"))
        (nil)))

(call_insn 30 154 95 (parallel[
            (call (mem:QI (reg/f:SI 1 %r1 [44]) [0 S1 A8])
                (const_int 0 [0x0]))
            (clobber (reg:SI 14 %r14))
        ] ) 216 {basr_31} (insn_list 154 (nil))
    (expr_list:REG_DEAD (reg/f:SI 1 %r1 [44])
        (expr_list:REG_UNUSED (reg:SI 14 %r14)
            (expr_list:REG_EH_REGION (const_int 1 [0x1])
                (nil))))
    (nil))
;; End of basic block 0, registers live:
 6 [%r6] 12 [%r12] 15 [%r15]

;; Start of basic block 1, registers live: 15 [%r15]
(note 95 30 32 [bb 1] NOTE_INSN_BASIC_BLOCK)

(jump_insn 32 95 33 (set (pc)
        (label_ref 93)) 209 {jump} (nil)
    (nil))
;; End of basic block 1, registers live:
 15 [%r15]

(barrier 33 32 131)

;; Start of basic block 2, registers live: 6 [%r6] 12 [%r12] 15 [%r15]
(code_label 131 33 141 10 "" "" [1 uses])

(note 141 131 136 [bb 2] NOTE_INSN_BASIC_BLOCK)

(insn 136 141 42 (asm_input ("")) -1 (nil)
    (nil))

(insn 42 136 153 (set (reg:SI 2 %r2)
        (reg:SI 6 %r6 [45])) 42 {*movsi} (nil)
    (nil))

(insn 153 42 45 (set (reg/f:SI 1 %r1 [46])
        (mem/u/f:SI (symbol_ref/u:SI ("*.LC1")) [2 S4 A32])) 42 {*movsi}
(nil)
    (expr_list:REG_EQUIV (symbol_ref:SI ("__cxa_begin_catch"))
        (nil)))

(call_insn 45 153 53 (parallel[
            (set (reg:SI 2 %r2)
                (call (mem:QI (reg/f:SI 1 %r1 [46]) [0 S1 A8])
                    (const_int 0 [0x0])))
            (clobber (reg:SI 14 %r14))
        ] ) 222 {basr_r_31} (insn_list 42 (insn_list 153 (nil)))
    (expr_list:REG_DEAD (reg/f:SI 1 %r1 [46])
        (expr_list:REG_UNUSED (reg:SI 2 %r2)
            (expr_list:REG_UNUSED (reg:SI 14 %r14)
                (expr_list:REG_EH_REGION (const_int 0 [0x0])
                    (nil)))))
    (expr_list (use (reg:SI 2 %r2))
        (nil)))

(call_insn 53 45 97 (parallel[
            (call (mem:QI (reg/v/f:SI 12 %r12 [43]) [0 S1 A8])
                (const_int 0 [0x0]))
            (clobber (reg:SI 14 %r14))
        ] ) 216 {basr_31} (nil)
    (expr_list:REG_DEAD (reg/v/f:SI 12 %r12 [43])
        (expr_list:REG_UNUSED (reg:SI 14 %r14)
            (expr_list:REG_EH_REGION (const_int 3 [0x3])
                (nil))))
    (nil))
;; End of basic block 2, registers live:
 6 [%r6] 15 [%r15]

;; Start of basic block 3, registers live: 15 [%r15]
(note 97 53 55 [bb 3] NOTE_INSN_BASIC_BLOCK)

(jump_insn 55 97 56 (set (pc)
        (label_ref 81)) 209 {jump} (nil)
    (nil))
;; End of basic block 3, registers live:
 15 [%r15]

(barrier 56 55 121)

;; Start of basic block 4, registers live: 6 [%r6] 15 [%r15]
(code_label 121 56 144 9 "" "" [1 uses])

(note 144 121 126 [bb 4] NOTE_INSN_BASIC_BLOCK)

(insn 126 144 64 (asm_input ("")) -1 (nil)
    (nil))

(insn 64 126 65 (set (reg/f:SI 1 %r1 [50])
        (mem/u/f:SI (symbol_ref/u:SI ("*.LC2")) [2 S4 A32])) 42 {*movsi}
(nil)
    (expr_list:REG_EQUIV (symbol_ref:SI ("__cxa_end_catch"))
        (nil)))

(call_insn 65 64 110 (parallel[
            (call (mem:QI (reg/f:SI 1 %r1 [50]) [0 S1 A8])
                (const_int 0 [0x0]))
            (clobber (reg:SI 14 %r14))
        ] ) 216 {basr_31} (insn_list 64 (nil))
    (expr_list:REG_DEAD (reg/f:SI 1 %r1 [50])
        (expr_list:REG_UNUSED (reg:SI 14 %r14)
            (expr_list:REG_EH_REGION (const_int 4 [0x4])
                (nil))))
    (nil))

(insn/s 110 65 112 (set (reg:SI 2 %r2)
        (reg:SI 6 %r6 [45])) 42 {*movsi} (nil)
    (expr_list:REG_DEAD (reg:SI 6 %r6 [45])
        (nil)))

(insn 112 110 113 (set (reg/f:SI 1 %r1 [53])
        (mem/u/f:SI (symbol_ref/u:SI ("*.LC4")) [2 S4 A32])) 42 {*movsi}
(nil)
    (expr_list:REG_EQUIV (symbol_ref:SI ("_Unwind_Resume"))
        (nil)))

(call_insn 113 112 114 (parallel[
            (call (mem:QI (reg/f:SI 1 %r1 [53]) [0 S1 A8])
                (const_int 0 [0x0]))
            (clobber (reg:SI 14 %r14))
        ] ) 216 {basr_31} (insn_list 110 (insn_list 112 (nil)))
    (expr_list:REG_DEAD (reg:SI 2 %r2)
        (expr_list:REG_DEAD (reg/f:SI 1 %r1 [53])
            (expr_list:REG_UNUSED (reg:SI 14 %r14)
                (expr_list:REG_NORETURN (const_int 0 [0x0])
                    (nil)))))
    (expr_list (use (reg:SI 2 %r2))
        (nil)))
;; End of basic block 4, registers live:
 15 [%r15]

(barrier 114 113 81)

;; Start of basic block 5, registers live: 15 [%r15]
(code_label 81 114 101 5 "" "" [1 uses])

(note 101 81 83 [bb 5] NOTE_INSN_BASIC_BLOCK)

(insn 83 101 84 (set (reg/f:SI 1 %r1 [52])
        (mem/u/f:SI (symbol_ref/u:SI ("*.LC2")) [2 S4 A32])) 42 {*movsi}
(nil)
    (expr_list:REG_EQUIV (symbol_ref:SI ("__cxa_end_catch"))
        (nil)))

(call_insn 84 83 89 (parallel[
            (call (mem:QI (reg/f:SI 1 %r1 [52]) [0 S1 A8])
                (const_int 0 [0x0]))
            (clobber (reg:SI 14 %r14))
        ] ) 216 {basr_31} (insn_list 83 (nil))
    (expr_list:REG_DEAD (reg/f:SI 1 %r1 [52])
        (expr_list:REG_UNUSED (reg:SI 14 %r14)
            (nil)))
    (nil))
;; End of basic block 5, registers live:
 15 [%r15]

(note 89 84 90 0x401b9480 NOTE_INSN_BLOCK_END)

(note 90 89 91 0x401b94c0 NOTE_INSN_BLOCK_END)

(note 91 90 93 NOTE_INSN_FUNCTION_END)

;; Start of basic block 6, registers live: 15 [%r15]
(code_label 93 91 103 1 "" "" [1 uses])

(note 103 93 152 [bb 6] NOTE_INSN_BASIC_BLOCK)
;; End of basic block 6, registers live:
 15 [%r15]

(note 152 103 155 NOTE_INSN_DELETED)

(note 155 152 0 NOTE_INSN_DELETED)





;; Function void test(int, int, int, int, void (*)())

insn 53: replaced reg 12 with 6


(note 2 0 94 NOTE_INSN_DELETED)

;; Start of basic block 0, registers live: 6 [%r6] 15 [%r15]
(note 94 2 15 [bb 0] NOTE_INSN_BASIC_BLOCK)

(note 15 94 17 NOTE_INSN_FUNCTION_BEG)

(note 17 15 19 0x401b94c0 NOTE_INSN_BLOCK_BEG)

(note 19 17 154 0x401b9480 NOTE_INSN_BLOCK_BEG)

(insn 154 19 30 (set (reg/f:SI 1 %r1 [44])
        (mem/u/f:SI (symbol_ref/u:SI ("*.LC0")) [2 S4 A32])) 42 {*movsi}
(nil)
    (expr_list:REG_EQUIV (symbol_ref:SI ("dummy"))
        (nil)))

(call_insn 30 154 95 (parallel[
            (call (mem:QI (reg/f:SI 1 %r1 [44]) [0 S1 A8])
                (const_int 0 [0x0]))
            (clobber (reg:SI 14 %r14))
        ] ) 216 {basr_31} (insn_list 154 (nil))
    (expr_list:REG_DEAD (reg/f:SI 1 %r1 [44])
        (expr_list:REG_UNUSED (reg:SI 14 %r14)
            (expr_list:REG_EH_REGION (const_int 1 [0x1])
                (nil))))
    (nil))
;; End of basic block 0, registers live:
 6 [%r6] 15 [%r15]

;; Start of basic block 1, registers live: 15 [%r15]
(note 95 30 32 [bb 1] NOTE_INSN_BASIC_BLOCK)

(jump_insn 32 95 33 (set (pc)
        (label_ref 93)) 209 {jump} (nil)
    (nil))
;; End of basic block 1, registers live:
 15 [%r15]

(barrier 33 32 131)

;; Start of basic block 2, registers live: 6 [%r6] 15 [%r15]
(code_label 131 33 141 10 "" "" [1 uses])

(note 141 131 136 [bb 2] NOTE_INSN_BASIC_BLOCK)

(insn 136 141 42 (asm_input ("")) -1 (nil)
    (nil))

(insn 42 136 153 (set (reg:SI 2 %r2)
        (reg:SI 6 %r6 [45])) 42 {*movsi} (nil)
    (nil))

(insn 153 42 45 (set (reg/f:SI 1 %r1 [46])
        (mem/u/f:SI (symbol_ref/u:SI ("*.LC1")) [2 S4 A32])) 42 {*movsi}
(nil)
    (expr_list:REG_EQUIV (symbol_ref:SI ("__cxa_begin_catch"))
        (nil)))

(call_insn 45 153 53 (parallel[
            (set (reg:SI 2 %r2)
                (call (mem:QI (reg/f:SI 1 %r1 [46]) [0 S1 A8])
                    (const_int 0 [0x0])))
            (clobber (reg:SI 14 %r14))
        ] ) 222 {basr_r_31} (insn_list 42 (insn_list 153 (nil)))
    (expr_list:REG_DEAD (reg/f:SI 1 %r1 [46])
        (expr_list:REG_UNUSED (reg:SI 2 %r2)
            (expr_list:REG_UNUSED (reg:SI 14 %r14)
                (expr_list:REG_EH_REGION (const_int 0 [0x0])
                    (nil)))))
    (expr_list (use (reg:SI 2 %r2))
        (nil)))

(call_insn 53 45 97 (parallel[
            (call (mem:QI (reg:SI 6 %r6) [0 S1 A8])
                (const_int 0 [0x0]))
            (clobber (reg:SI 14 %r14))
        ] ) 216 {basr_31} (nil)
    (expr_list:REG_UNUSED (reg:SI 14 %r14)
        (expr_list:REG_EH_REGION (const_int 3 [0x3])
            (nil)))
    (nil))
;; End of basic block 2, registers live:
 6 [%r6] 15 [%r15]

;; Start of basic block 3, registers live: 15 [%r15]
(note 97 53 55 [bb 3] NOTE_INSN_BASIC_BLOCK)

(jump_insn 55 97 56 (set (pc)
        (label_ref 81)) 209 {jump} (nil)
    (nil))
;; End of basic block 3, registers live:
 15 [%r15]

(barrier 56 55 121)

;; Start of basic block 4, registers live: 6 [%r6] 15 [%r15]
(code_label 121 56 144 9 "" "" [1 uses])

(note 144 121 126 [bb 4] NOTE_INSN_BASIC_BLOCK)

(insn 126 144 64 (asm_input ("")) -1 (nil)
    (nil))

(insn 64 126 65 (set (reg/f:SI 1 %r1 [50])
        (mem/u/f:SI (symbol_ref/u:SI ("*.LC2")) [2 S4 A32])) 42 {*movsi}
(nil)
    (expr_list:REG_EQUIV (symbol_ref:SI ("__cxa_end_catch"))
        (nil)))

(call_insn 65 64 110 (parallel[
            (call (mem:QI (reg/f:SI 1 %r1 [50]) [0 S1 A8])
                (const_int 0 [0x0]))
            (clobber (reg:SI 14 %r14))
        ] ) 216 {basr_31} (insn_list 64 (nil))
    (expr_list:REG_DEAD (reg/f:SI 1 %r1 [50])
        (expr_list:REG_UNUSED (reg:SI 14 %r14)
            (expr_list:REG_EH_REGION (const_int 4 [0x4])
                (nil))))
    (nil))

(insn/s 110 65 112 (set (reg:SI 2 %r2)
        (reg:SI 6 %r6 [45])) 42 {*movsi} (nil)
    (expr_list:REG_DEAD (reg:SI 6 %r6 [45])
        (nil)))

(insn 112 110 113 (set (reg/f:SI 1 %r1 [53])
        (mem/u/f:SI (symbol_ref/u:SI ("*.LC4")) [2 S4 A32])) 42 {*movsi}
(nil)
    (expr_list:REG_EQUIV (symbol_ref:SI ("_Unwind_Resume"))
        (nil)))

(call_insn 113 112 114 (parallel[
            (call (mem:QI (reg/f:SI 1 %r1 [53]) [0 S1 A8])
                (const_int 0 [0x0]))
            (clobber (reg:SI 14 %r14))
        ] ) 216 {basr_31} (insn_list 110 (insn_list 112 (nil)))
    (expr_list:REG_DEAD (reg:SI 2 %r2)
        (expr_list:REG_DEAD (reg/f:SI 1 %r1 [53])
            (expr_list:REG_UNUSED (reg:SI 14 %r14)
                (expr_list:REG_NORETURN (const_int 0 [0x0])
                    (nil)))))
    (expr_list (use (reg:SI 2 %r2))
        (nil)))
;; End of basic block 4, registers live:
 15 [%r15]

(barrier 114 113 81)

;; Start of basic block 5, registers live: 15 [%r15]
(code_label 81 114 101 5 "" "" [1 uses])

(note 101 81 83 [bb 5] NOTE_INSN_BASIC_BLOCK)

(insn 83 101 84 (set (reg/f:SI 1 %r1 [52])
        (mem/u/f:SI (symbol_ref/u:SI ("*.LC2")) [2 S4 A32])) 42 {*movsi}
(nil)
    (expr_list:REG_EQUIV (symbol_ref:SI ("__cxa_end_catch"))
        (nil)))

(call_insn 84 83 89 (parallel[
            (call (mem:QI (reg/f:SI 1 %r1 [52]) [0 S1 A8])
                (const_int 0 [0x0]))
            (clobber (reg:SI 14 %r14))
        ] ) 216 {basr_31} (insn_list 83 (nil))
    (expr_list:REG_DEAD (reg/f:SI 1 %r1 [52])
        (expr_list:REG_UNUSED (reg:SI 14 %r14)
            (nil)))
    (nil))
;; End of basic block 5, registers live:
 15 [%r15]

(note 89 84 90 0x401b9480 NOTE_INSN_BLOCK_END)

(note 90 89 91 0x401b94c0 NOTE_INSN_BLOCK_END)

(note 91 90 93 NOTE_INSN_FUNCTION_END)

;; Start of basic block 6, registers live: 15 [%r15]
(code_label 93 91 103 1 "" "" [1 uses])

(note 103 93 152 [bb 6] NOTE_INSN_BASIC_BLOCK)
;; End of basic block 6, registers live:
 15 [%r15]

(note 152 103 155 NOTE_INSN_DELETED)

(note 155 152 0 NOTE_INSN_DELETED)



Mit freundlichen Gruessen / Best Regards

Ulrich Weigand

--
  Dr. Ulrich Weigand
  Linux for S/390 Design & Development
  IBM Deutschland Entwicklung GmbH, Schoenaicher Str. 220, 71032 Boeblingen
  Phone: +49-7031/16-3727   ---   Email: Ulrich.Weigand@de.ibm.com


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