Exception handling on the Blackfin was broken by the dataflow merge.
Inspecting the differences in the generated code, it appears that when
compiling functions like _Unwind_Resume in unwind-dw2.c, the dse pass
deletes necessary instructions.

Before:
(insn 56 55 57 7 (set (reg/v:SI 56 [ offset ])
        (reg:SI 0 R0)) 14 {*movsi_insn} (expr_list:REG_DEAD (reg:SI 0 R0)
        (nil)))

(insn 57 56 67 7 (set (reg/v/f:SI 55 [ handler ])
        (mem/s/f/c:SI (plus:SI (reg/f:SI 15 FP)
                (const_int -376 [0xfffffe88])) [12 cur_context.ra+0 S4
A32])) 14 {*movsi_insn} (nil))

(insn 67 57 68 7 (set (reg:SI 10 P2 [ offset ])
        (reg/v:SI 56 [ offset ])) 14 {*movsi_insn} (expr_list:REG_DEAD
(reg/v:SI 56 [ offset ])
        (nil)))

(insn 68 67 69 7 (set (mem:SI (plus:SI (reg/f:SI 15 FP)
                (const_int 4 [0x4])) [0 S4 A32])
        (reg/v/f:SI 55 [ handler ])) 14 {*movsi_insn}
(expr_list:REG_DEAD (reg/v/f:SI 55 [ handler ])
        (nil)))

(jump_insn 69 68 0 7 (set (pc)
        (unspec_volatile [
                (reg:SI 10 P2)
            ] 0)) 126 {eh_return_internal} (expr_list:REG_DEAD (reg:SI
10 P2)
        (expr_list:REG_EQUAL (unspec_volatile [
                    (reg:SI 10 P2)
                ] 0)
            (nil))))

After:
(insn 56 55 67 7 (set (reg/v:SI 56 [ offset ])
        (reg:SI 0 R0)) 14 {*movsi_insn} (expr_list:REG_DEAD (reg:SI 0 R0)
        (nil)))

(insn 67 56 69 7 (set (reg:SI 10 P2 [ offset ])
        (reg/v:SI 56 [ offset ])) 14 {*movsi_insn} (expr_list:REG_DEAD
(reg/v:SI 56 [ offset ])
        (nil)))

(jump_insn 69 67 0 7 (set (pc)
        (unspec_volatile [
                (reg:SI 10 P2)
            ] 0)) 126 {eh_return_internal} (expr_list:REG_DEAD (reg:SI
10 P2)
        (expr_list:REG_EQUAL (unspec_volatile [
                    (reg:SI 10 P2)
                ] 0)
            (nil))))

[FP + 4] is part of the register save area.  Insn 68, which stores a
value into it, gets deleted.

There is a reference to current_function_uses_eh_return in dse.c, but
it's not clear to me what it's trying to achieve.  Anyway, turning the
store into an unspec_volatile solves the problem.  I've committed the
following.


Bernd
-- 
This footer brought to you by insane German lawmakers.
Analog Devices GmbH      Wilhelm-Wagenfeld-Str. 6      80807 Muenchen
Sitz der Gesellschaft Muenchen, Registergericht Muenchen HRB 40368
Geschaeftsfuehrer Thomas Wessel, William A. Martin, Margaret Seif
Index: ChangeLog
===================================================================
--- ChangeLog   (revision 125680)
+++ ChangeLog   (working copy)
@@ -1,3 +1,10 @@
+2007-06-13  Bernd Schmidt  <[EMAIL PROTECTED]>
+
+       * config/bfin/bfin.h (EH_RETURN_HANDLER_RTX): Use gen_frame_mem.
+       * config/bfin/bfin.md (UNSPEC_VOLATILE_STORE_EH_HANDLER): New constant.
+       (eh_store_handler): New pattern.
+       (eh_return): Emit it instead of a plain move.
+
 2007-06-13  Uros Bizjak  <[EMAIL PROTECTED]>
 
        * config/i386/i386.c (ix86_init_mmx_sse_builtins)
Index: config/bfin/bfin.h
===================================================================
--- config/bfin/bfin.h  (revision 125641)
+++ config/bfin/bfin.h  (working copy)
@@ -813,7 +813,7 @@ typedef struct {
 #define EH_RETURN_DATA_REGNO(N)        ((N) < 2 ? (N) : INVALID_REGNUM)
 #define EH_RETURN_STACKADJ_RTX gen_rtx_REG (Pmode, REG_P2)
 #define EH_RETURN_HANDLER_RTX \
-    gen_rtx_MEM (Pmode, plus_constant (frame_pointer_rtx, UNITS_PER_WORD))
+    gen_frame_mem (Pmode, plus_constant (frame_pointer_rtx, UNITS_PER_WORD))
 
 /* Addressing Modes */
 
Index: config/bfin/bfin.md
===================================================================
--- config/bfin/bfin.md (revision 125648)
+++ config/bfin/bfin.md (working copy)
@@ -144,7 +144,8 @@ (define_constants
   [(UNSPEC_VOLATILE_EH_RETURN 0)
    (UNSPEC_VOLATILE_CSYNC 1)
    (UNSPEC_VOLATILE_SSYNC 2)
-   (UNSPEC_VOLATILE_LOAD_FUNCDESC 3)])
+   (UNSPEC_VOLATILE_LOAD_FUNCDESC 3)
+   (UNSPEC_VOLATILE_STORE_EH_HANDLER 4)])
 
 (define_constants
   [(MACFLAG_NONE 0)
@@ -2687,12 +2688,20 @@ (define_expand "eh_return"
                    UNSPEC_VOLATILE_EH_RETURN)]
   ""
 {
-  emit_move_insn (EH_RETURN_HANDLER_RTX, operands[0]);
+  emit_insn (gen_eh_store_handler (EH_RETURN_HANDLER_RTX, operands[0]));
   emit_jump_insn (gen_eh_return_internal ());
   emit_barrier ();
   DONE;
 })
 
+(define_insn "eh_store_handler"
+  [(unspec_volatile [(match_operand:SI 1 "register_operand" "da")]
+                   UNSPEC_VOLATILE_STORE_EH_HANDLER)
+   (clobber (match_operand:SI 0 "memory_operand" "=m"))]
+  ""
+  "%0 = %1%!"
+  [(set_attr "type" "mcst")])
+
 (define_insn_and_split "eh_return_internal"
   [(set (pc)
        (unspec_volatile [(reg:SI REG_P2)] UNSPEC_VOLATILE_EH_RETURN))]

Reply via email to