[RFC][patch] trans-mem: mark transaction begins as returns-twice
Torvald Riegel
triegel@redhat.com
Mon Jan 2 18:10:00 GMT 2012
Attached is Richard Henderson's patch that marks calls that start a
transaction as returns-twice. In turn, these calls will be treated like
a call to setjmp.
This was motivated by the miscompilation of one of the STAMP
applications (Genome), where a stack slot was used as temp storage for a
CPU register but not restored when the transaction got aborted and
restarted (then, after restart, the program crashed because it used
inconsistent data). With the attached patch and in this particular
example, the stack slots that are written to in the transaction do not
get read during the transaction. (-fno-caller-saves was not a
sufficient solution, BTW.)
AFAICT, we previously wanted to handle "restart safety" by adding
abnormal edges to all calls to the TM runtime library (which could in
turn call the libitm longjmp that actually restarts a transaction).
Richard mentioned that we could drop this code (I think he meant this,
and others pieces perhaps) if the returns-twice approach works. BTW,
did we also add abnormal edges to any call to transactional clones,
which could in turn call the TM runtime library?
Conceptually, what we would need to enforce is that all stack slots that
are live-in into a transaction (i.e., the live range crosses a call to
_ITM_beginTransaction) do not get reused until the matching call to
_ITM_commitTransaction. Alternatively, we can reuse those, but need to
save and restore them after aborts.
As Richard suggested, I looked at the handling of REG_SETJMP (see the
summary below). This looks like a sufficient solution to me (eg, don't
share stack slots if regs cross a setjmp) but I don't know nearly enough
about this to really understand whether it is. Can somebody else have a
look please? In particular:
- Is it really sufficient?
- Is this too conservative (e.g., no CSE at all)? If so, we should look
at this again for 4.8 I guess, otherwise every function that uses a
transaction will be slower, and slowing down nontransactional code
isn't nice. Or won't that be much of a slowdown?
- Do we potentially get unnecessary warnings (if vars are live across
a transaction begin)? I didn't get such warnings in the STAMP app
that wasn't working though. Does anyone has suggestions for a test
case?
- For the long-term, should we try to limit the setjmp effects to the
TM region? Contrary to standard setjmp/longjmp, we know about the
regions and where the longjmps matching a setjmp are. Any thoughts
on how much this might matter performance-wise?
Overall, I think we should still use it, unless we can come up with
another fix in time for 4.7.
Opinions?
Torvald
Summary:
- cprop.c: constant propagation only runs if !cfun->calls_setjmp
- gcse.c: Same.
- cse.c: we don't CSE over a call to setjmp. But comment associates this
just with some weird longjmp on VAX and other systems.
- cselib.c (cselib_process_insn): Forget everything at a setjmp.
- callers of this function are: dse_step1(), local_cprop_pass(),
reload_cse_regs(), thread_jump(), vt_initialize()
- ira-lives.c (process_bb_node_lives): ??? Don't allocate allocnos
that cross setjmps.
- regstat.c (regstat_bb_compute_ri): Marks all pseudo(?) regs that
cross a setjmp. Clients of this information:
- (regstat_compute_ri): ??? REG_LIVE_LENGTH(regno) = -1;
REG_BASIC_BLOCK(regno) = REG_BLOCK_UNKNOWN;
- function.c (generate_setjmp_warnings): Warnings if vars are live
across setjmp.
- ira-color.c (coalesce_spill_slots): ??? Don't share stack slots if
one of the regs crosses a setjmp?
- reload1.c (reload_as_needed): Don't reuse any reload reg contents
across a setjmp.
- reload.c (find_equiv_reg): Don't reuse register contents from before
a setjmp-type function call.
- resource.c (mark_referenced_resources, mark_set_resources): setjmp
uses all registers.
- sched-deps.c: setjmp acts as a MOVE_BARRIER. What does this barrier
do precisely?
-------------- next part --------------
commit 53e0ab5b86ca38d55e4c4fd927be33143586ad15
Author: Torvald Riegel <triegel@redhat.com>
Date: Mon Dec 19 23:36:45 2011 +0100
rth's returns-twice fix
diff --git a/gcc/builtin-attrs.def b/gcc/builtin-attrs.def
index 619794e..c3132cc 100644
--- a/gcc/builtin-attrs.def
+++ b/gcc/builtin-attrs.def
@@ -98,6 +98,7 @@ DEF_ATTR_IDENT (ATTR_STRFTIME, "strftime")
DEF_ATTR_IDENT (ATTR_TYPEGENERIC, "type generic")
DEF_ATTR_IDENT (ATTR_TM_REGPARM, "*tm regparm")
DEF_ATTR_IDENT (ATTR_TM_TMPURE, "transaction_pure")
+DEF_ATTR_IDENT (ATTR_RETURNS_TWICE, "returns_twice")
DEF_ATTR_TREE_LIST (ATTR_NOVOPS_LIST, ATTR_NOVOPS, ATTR_NULL, ATTR_NULL)
@@ -241,6 +242,8 @@ DEF_ATTR_TREE_LIST (ATTR_TM_NORETURN_NOTHROW_LIST,
ATTR_TM_REGPARM, ATTR_NULL, ATTR_NORETURN_NOTHROW_LIST)
DEF_ATTR_TREE_LIST (ATTR_TM_CONST_NOTHROW_LIST,
ATTR_TM_REGPARM, ATTR_NULL, ATTR_CONST_NOTHROW_LIST)
+DEF_ATTR_TREE_LIST (ATTR_TM_NOTHROW_RT_LIST,
+ ATTR_RETURNS_TWICE, ATTR_NULL, ATTR_TM_NOTHROW_LIST)
/* Same attributes used for BUILT_IN_MALLOC except with TM_PURE thrown in. */
DEF_ATTR_TREE_LIST (ATTR_TMPURE_MALLOC_NOTHROW_LIST,
diff --git a/gcc/gtm-builtins.def b/gcc/gtm-builtins.def
index 9fcbdb0..1630a0e 100644
--- a/gcc/gtm-builtins.def
+++ b/gcc/gtm-builtins.def
@@ -1,5 +1,5 @@
DEF_TM_BUILTIN (BUILT_IN_TM_START, "_ITM_beginTransaction",
- BT_FN_UINT_UINT, ATTR_TM_NOTHROW_LIST)
+ BT_FN_UINT_UINT, ATTR_TM_NOTHROW_RT_LIST)
DEF_TM_BUILTIN (BUILT_IN_TM_COMMIT, "_ITM_commitTransaction",
BT_FN_VOID, ATTR_TM_NOTHROW_LIST)
More information about the Gcc-patches
mailing list