This is the mail archive of the
gcc@gcc.gnu.org
mailing list for the GCC project.
Blackfin eh broken with dataflow merge
- From: Bernd Schmidt <bernds_cb1 at t-online dot de>
- To: GCC List <gcc at gcc dot gnu dot org>
- Cc: Kenneth Zadeck <zadeck at naturalbridge dot com>
- Date: Wed, 13 Jun 2007 19:43:44 +0200
- Subject: Blackfin eh broken with dataflow merge
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 <bernd.schmidt@analog.com>
+
+ * 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 <ubizjak@gmail.com>
* 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))]