OSDN Git Service

Merge from transactional-memory branch.
authoraldyh <aldyh@138bc75d-0d04-0410-961f-82ee72b054a4>
Tue, 8 Nov 2011 11:13:41 +0000 (11:13 +0000)
committeraldyh <aldyh@138bc75d-0d04-0410-961f-82ee72b054a4>
Tue, 8 Nov 2011 11:13:41 +0000 (11:13 +0000)
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@181154 138bc75d-0d04-0410-961f-82ee72b054a4

304 files changed:
ChangeLog
Makefile.def
Makefile.in
config/mmap.m4 [new file with mode: 0644]
configure
configure.ac
contrib/ChangeLog
contrib/gcc_update
gcc/ChangeLog
gcc/Makefile.in
gcc/attribs.c
gcc/builtin-attrs.def
gcc/builtin-types.def
gcc/builtins.def
gcc/c-family/ChangeLog
gcc/c-family/c-common.c
gcc/c-family/c-common.h
gcc/c-parser.c
gcc/c-tree.h
gcc/c-typeck.c
gcc/calls.c
gcc/cfgbuild.c
gcc/cfgexpand.c
gcc/cfgrtl.c
gcc/cgraph.c
gcc/cgraph.h
gcc/cgraphunit.c
gcc/combine.c
gcc/common.opt
gcc/config/i386/i386-builtin-types.def
gcc/config/i386/i386.c
gcc/cp/ChangeLog
gcc/cp/call.c
gcc/cp/class.c
gcc/cp/cp-tree.h
gcc/cp/decl.c
gcc/cp/except.c
gcc/cp/parser.c
gcc/cp/parser.h
gcc/cp/pt.c
gcc/cp/semantics.c
gcc/doc/invoke.texi
gcc/doc/tm.texi
gcc/doc/tm.texi.in
gcc/emit-rtl.c
gcc/gimple-low.c
gcc/gimple-pretty-print.c
gcc/gimple.c
gcc/gimple.def
gcc/gimple.h
gcc/gimplify.c
gcc/gsstruct.def
gcc/gtm-builtins.def [new file with mode: 0644]
gcc/ipa-inline.c
gcc/omp-low.c
gcc/opts.c
gcc/output.h
gcc/params.def
gcc/passes.c
gcc/print-tree.c
gcc/recog.c
gcc/reg-notes.def
gcc/rtlanal.c
gcc/target.def
gcc/targhooks.c
gcc/targhooks.h
gcc/testsuite/ChangeLog
gcc/testsuite/c-c++-common/tm/20100127.c [new file with mode: 0644]
gcc/testsuite/c-c++-common/tm/abort-1.c [new file with mode: 0644]
gcc/testsuite/c-c++-common/tm/abort-2.c [new file with mode: 0644]
gcc/testsuite/c-c++-common/tm/abort-3.c [new file with mode: 0644]
gcc/testsuite/c-c++-common/tm/atomic-1.c [new file with mode: 0644]
gcc/testsuite/c-c++-common/tm/atomic-2.c [new file with mode: 0644]
gcc/testsuite/c-c++-common/tm/attrib-1.c [new file with mode: 0644]
gcc/testsuite/c-c++-common/tm/cancel-1.c [new file with mode: 0644]
gcc/testsuite/c-c++-common/tm/freq.c [new file with mode: 0644]
gcc/testsuite/c-c++-common/tm/inline-asm-2.c [new file with mode: 0644]
gcc/testsuite/c-c++-common/tm/inline-asm.c [new file with mode: 0644]
gcc/testsuite/c-c++-common/tm/ipa-1.c [new file with mode: 0644]
gcc/testsuite/c-c++-common/tm/malloc.c [new file with mode: 0644]
gcc/testsuite/c-c++-common/tm/memcpy-1.c [new file with mode: 0644]
gcc/testsuite/c-c++-common/tm/omp.c [new file with mode: 0644]
gcc/testsuite/c-c++-common/tm/outer-1.c [new file with mode: 0644]
gcc/testsuite/c-c++-common/tm/safe-1.c [new file with mode: 0644]
gcc/testsuite/c-c++-common/tm/safe-2.c [new file with mode: 0644]
gcc/testsuite/c-c++-common/tm/safe-3.c [new file with mode: 0644]
gcc/testsuite/c-c++-common/tm/trxn-expr-2.c [new file with mode: 0644]
gcc/testsuite/c-c++-common/tm/trxn-expr.c [new file with mode: 0644]
gcc/testsuite/c-c++-common/tm/wrap-1.c [new file with mode: 0644]
gcc/testsuite/g++.dg/dg.exp
gcc/testsuite/g++.dg/tm/20100429.C [new file with mode: 0644]
gcc/testsuite/g++.dg/tm/20100727.C [new file with mode: 0644]
gcc/testsuite/g++.dg/tm/alias.C [new file with mode: 0644]
gcc/testsuite/g++.dg/tm/attrib-2.C [new file with mode: 0644]
gcc/testsuite/g++.dg/tm/attrib-3.C [new file with mode: 0644]
gcc/testsuite/g++.dg/tm/attrib-4.C [new file with mode: 0644]
gcc/testsuite/g++.dg/tm/fatomic-1.C [new file with mode: 0644]
gcc/testsuite/g++.dg/tm/nested-1.C [new file with mode: 0644]
gcc/testsuite/g++.dg/tm/nested-2.C [new file with mode: 0644]
gcc/testsuite/g++.dg/tm/nested-3.C [new file with mode: 0644]
gcc/testsuite/g++.dg/tm/opt-1.C [new file with mode: 0644]
gcc/testsuite/g++.dg/tm/pr45940-2.C [new file with mode: 0644]
gcc/testsuite/g++.dg/tm/pr45940-3.C [new file with mode: 0644]
gcc/testsuite/g++.dg/tm/pr45940-4.C [new file with mode: 0644]
gcc/testsuite/g++.dg/tm/pr45940.C [new file with mode: 0644]
gcc/testsuite/g++.dg/tm/pr46269.C [new file with mode: 0644]
gcc/testsuite/g++.dg/tm/pr46270.C [new file with mode: 0644]
gcc/testsuite/g++.dg/tm/pr46300.C [new file with mode: 0644]
gcc/testsuite/g++.dg/tm/pr46567.C [new file with mode: 0644]
gcc/testsuite/g++.dg/tm/pr46646.C [new file with mode: 0644]
gcc/testsuite/g++.dg/tm/pr46653.C [new file with mode: 0644]
gcc/testsuite/g++.dg/tm/pr46714.C [new file with mode: 0644]
gcc/testsuite/g++.dg/tm/pr46941.C [new file with mode: 0644]
gcc/testsuite/g++.dg/tm/pr47340.C [new file with mode: 0644]
gcc/testsuite/g++.dg/tm/pr47530.C [new file with mode: 0644]
gcc/testsuite/g++.dg/tm/pr47554.C [new file with mode: 0644]
gcc/testsuite/g++.dg/tm/pr47573.C [new file with mode: 0644]
gcc/testsuite/g++.dg/tm/pr47746.C [new file with mode: 0644]
gcc/testsuite/g++.dg/tm/template-1.C [new file with mode: 0644]
gcc/testsuite/g++.dg/tm/tm.exp [new file with mode: 0644]
gcc/testsuite/g++.dg/tm/vector-1.C [new file with mode: 0644]
gcc/testsuite/g++.dg/tm/wrap-2.C [new file with mode: 0644]
gcc/testsuite/gcc.dg/tm/20091013.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/tm/20091221.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/tm/20100125.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/tm/20100519.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/tm/20100524-2.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/tm/20100603.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/tm/20100609.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/tm/20100610.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/tm/20100615-2.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/tm/20100615.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/tm/20110216.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/tm/alias-1.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/tm/alias-2.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/tm/data-1.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/tm/data-2.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/tm/debug-1.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/tm/indirect-1.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/tm/ipa-1.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/tm/ipa-2.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/tm/ipa-3.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/tm/irrevocable-1.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/tm/irrevocable-2.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/tm/irrevocable-3.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/tm/irrevocable-4.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/tm/irrevocable-5.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/tm/irrevocable-6.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/tm/irrevocable-7.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/tm/memopt-1.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/tm/memopt-10.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/tm/memopt-11.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/tm/memopt-12.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/tm/memopt-13.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/tm/memopt-15.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/tm/memopt-2.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/tm/memopt-3.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/tm/memopt-4.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/tm/memopt-5.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/tm/memopt-6.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/tm/memopt-7.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/tm/memopt-8.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/tm/memopt-9.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/tm/memset-2.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/tm/memset.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/tm/nested-1.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/tm/nested-2.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/tm/opt-1.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/tm/opt-2.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/tm/pr45985.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/tm/pr46567-2.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/tm/pr46567.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/tm/pr46654.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/tm/pr47520.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/tm/pr47690.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/tm/pr47905.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/tm/props-1.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/tm/props-2.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/tm/props-3.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/tm/props-4.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/tm/tm.exp [new file with mode: 0644]
gcc/testsuite/gcc.dg/tm/unsafe.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/tm/unused.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/tm/vector-1.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/tm/wrap-2.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/tm/wrap-3.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/tm/wrap-4.c [new file with mode: 0644]
gcc/timevar.def
gcc/toplev.c
gcc/trans-mem.c [new file with mode: 0644]
gcc/trans-mem.h [new file with mode: 0644]
gcc/tree-cfg.c
gcc/tree-eh.c
gcc/tree-flow.h
gcc/tree-inline.c
gcc/tree-inline.h
gcc/tree-pass.h
gcc/tree-pretty-print.c
gcc/tree-ssa-alias.c
gcc/tree-ssa-structalias.c
gcc/tree.c
gcc/tree.def
gcc/tree.h
gcc/varasm.c
include/ChangeLog
include/demangle.h
libiberty/ChangeLog
libiberty/cp-demangle.c
libitm/ChangeLog [new file with mode: 0644]
libitm/Makefile.am [new file with mode: 0644]
libitm/Makefile.in [new file with mode: 0644]
libitm/aatree.cc [new file with mode: 0644]
libitm/aatree.h [new file with mode: 0644]
libitm/acinclude.m4 [new file with mode: 0644]
libitm/aclocal.m4 [new file with mode: 0644]
libitm/alloc.cc [new file with mode: 0644]
libitm/alloc_c.cc [new file with mode: 0644]
libitm/alloc_cpp.cc [new file with mode: 0644]
libitm/barrier.cc [new file with mode: 0644]
libitm/barrier.tpl [new file with mode: 0644]
libitm/beginend.cc [new file with mode: 0644]
libitm/clone.cc [new file with mode: 0644]
libitm/common.h [new file with mode: 0644]
libitm/config.h.in [new file with mode: 0644]
libitm/config/alpha/cacheline.h [new file with mode: 0644]
libitm/config/alpha/sjlj.S [new file with mode: 0644]
libitm/config/alpha/target.h [new file with mode: 0644]
libitm/config/alpha/unaligned.h [new file with mode: 0644]
libitm/config/generic/cacheline.cc [new file with mode: 0644]
libitm/config/generic/cacheline.h [new file with mode: 0644]
libitm/config/generic/cachepage.h [new file with mode: 0644]
libitm/config/generic/tls.cc [new file with mode: 0644]
libitm/config/generic/tls.h [new file with mode: 0644]
libitm/config/generic/unaligned.h [new file with mode: 0644]
libitm/config/linux/alpha/futex_bits.h [new file with mode: 0644]
libitm/config/linux/futex.cc [new file with mode: 0644]
libitm/config/linux/futex.h [new file with mode: 0644]
libitm/config/linux/rwlock.cc [new file with mode: 0644]
libitm/config/linux/rwlock.h [new file with mode: 0644]
libitm/config/linux/x86/futex_bits.h [new file with mode: 0644]
libitm/config/linux/x86/tls.h [new file with mode: 0644]
libitm/config/posix/cachepage.cc [new file with mode: 0644]
libitm/config/posix/rwlock.cc [new file with mode: 0644]
libitm/config/posix/rwlock.h [new file with mode: 0644]
libitm/config/x86/cacheline.cc [new file with mode: 0644]
libitm/config/x86/cacheline.h [new file with mode: 0644]
libitm/config/x86/sjlj.S [new file with mode: 0644]
libitm/config/x86/target.h [new file with mode: 0644]
libitm/config/x86/unaligned.h [new file with mode: 0644]
libitm/config/x86/x86_avx.cc [new file with mode: 0644]
libitm/config/x86/x86_sse.cc [new file with mode: 0644]
libitm/configure [new file with mode: 0644]
libitm/configure.ac [new file with mode: 0644]
libitm/configure.tgt [new file with mode: 0644]
libitm/containers.h [new file with mode: 0644]
libitm/dispatch.h [new file with mode: 0644]
libitm/eh_cpp.cc [new file with mode: 0644]
libitm/libitm.h [new file with mode: 0644]
libitm/libitm.map [new file with mode: 0644]
libitm/libitm.spec.in [new file with mode: 0644]
libitm/libitm.texi [new file with mode: 0644]
libitm/libitm_i.h [new file with mode: 0644]
libitm/local.cc [new file with mode: 0644]
libitm/local_type_traits [new file with mode: 0644]
libitm/memcpy.cc [new file with mode: 0644]
libitm/memset.cc [new file with mode: 0644]
libitm/method-gl.cc [new file with mode: 0644]
libitm/method-serial.cc [new file with mode: 0644]
libitm/method-wbetl.cc [new file with mode: 0644]
libitm/query.cc [new file with mode: 0644]
libitm/retry.cc [new file with mode: 0644]
libitm/stmlock.h [new file with mode: 0644]
libitm/testsuite/Makefile.am [new file with mode: 0644]
libitm/testsuite/Makefile.in [new file with mode: 0644]
libitm/testsuite/config/default.exp [new file with mode: 0644]
libitm/testsuite/lib/libitm-dg.exp [new file with mode: 0644]
libitm/testsuite/lib/libitm.exp [new file with mode: 0644]
libitm/testsuite/libitm.c++/c++.exp [new file with mode: 0644]
libitm/testsuite/libitm.c++/dropref.C [new file with mode: 0644]
libitm/testsuite/libitm.c++/eh-1.C [new file with mode: 0644]
libitm/testsuite/libitm.c++/static_ctor.C [new file with mode: 0644]
libitm/testsuite/libitm.c++/throwdown.C [new file with mode: 0644]
libitm/testsuite/libitm.c/c.exp [new file with mode: 0644]
libitm/testsuite/libitm.c/cancel.c [new file with mode: 0644]
libitm/testsuite/libitm.c/clone-1.c [new file with mode: 0644]
libitm/testsuite/libitm.c/dropref-2.c [new file with mode: 0644]
libitm/testsuite/libitm.c/dropref.c [new file with mode: 0644]
libitm/testsuite/libitm.c/memcpy-1.c [new file with mode: 0644]
libitm/testsuite/libitm.c/memset-1.c [new file with mode: 0644]
libitm/testsuite/libitm.c/notx.c [new file with mode: 0644]
libitm/testsuite/libitm.c/reentrant.c [new file with mode: 0644]
libitm/testsuite/libitm.c/simple-1.c [new file with mode: 0644]
libitm/testsuite/libitm.c/simple-2.c [new file with mode: 0644]
libitm/testsuite/libitm.c/txrelease.c [new file with mode: 0644]
libitm/useraction.cc [new file with mode: 0644]
libitm/util.cc [new file with mode: 0644]
libstdc++-v3/ChangeLog
libstdc++-v3/config/abi/pre/gnu-versioned-namespace.ver
libstdc++-v3/config/abi/pre/gnu.ver
libstdc++-v3/libsupc++/Makefile.am
libstdc++-v3/libsupc++/Makefile.in
libstdc++-v3/libsupc++/eh_tm.cc [new file with mode: 0644]
libstdc++-v3/libsupc++/unwind-cxx.h
libstdc++-v3/testsuite/util/testsuite_abi.cc

index 49ba74f..d6ae1b1 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,15 @@
+2011-11-07  Aldy Hernandez  <aldyh@redhat.com>
+           Richard Henderson  <rth@redhat.com>
+
+       Merged from transactional-memory.
+
+       * Makefile.def (lang_env_dependencies): libitm is c++.
+       Add libitm target module.
+       * configure.ac: Likewise.
+       * config/mmap.m4: New file.
+       * contrib/gcc_update: Add libitm to touch data.
+       * Makefile.in, configure: Rebuild.
+
 2011-11-02  Rainer Orth  <ro@CeBiTec.Uni-Bielefeld.DE>
 
        * Makefile.tpl (EXTRA_GCC_FLAGS): Remove LIBGCC2_CFLAGS,
index 5116341..b94dabf 100644 (file)
@@ -139,6 +139,7 @@ target_modules = { module= boehm-gc; };
 target_modules = { module= rda; };
 target_modules = { module= libada; };
 target_modules = { module= libgomp; bootstrap= true; lib_path=.libs; };
+target_modules = { module= libitm; lib_path=.libs; };
 
 // These are (some of) the make targets to be done in each subdirectory.
 // Not all; these are the ones which don't have special options.
@@ -470,6 +471,7 @@ dependencies = { module=all-m4; on=all-build-texinfo; };
 // environment (e.g. on libstdc++).  By default target modules depend
 // on libgcc and newlib/libgloss.
 lang_env_dependencies = { module=libjava; cxx=true; };
+lang_env_dependencies = { module=libitm; cxx=true; };
 lang_env_dependencies = { module=newlib; no_c=true; };
 lang_env_dependencies = { module=libgloss; no_c=true; };
 lang_env_dependencies = { module=libgcc; no_gcc=true; no_c=true; };
index 821499d..900c325 100644 (file)
@@ -594,7 +594,7 @@ all:
 
 # This is the list of directories that may be needed in RPATH_ENVVAR
 # so that programs built for the target machine work.
-TARGET_LIB_PATH = $(TARGET_LIB_PATH_libstdc++-v3)$(TARGET_LIB_PATH_libmudflap)$(TARGET_LIB_PATH_libssp)$(TARGET_LIB_PATH_libgomp)$(HOST_LIB_PATH_gcc)
+TARGET_LIB_PATH = $(TARGET_LIB_PATH_libstdc++-v3)$(TARGET_LIB_PATH_libmudflap)$(TARGET_LIB_PATH_libssp)$(TARGET_LIB_PATH_libgomp)$(TARGET_LIB_PATH_libitm)$(HOST_LIB_PATH_gcc)
 
 @if target-libstdc++-v3
 TARGET_LIB_PATH_libstdc++-v3 = $$r/$(TARGET_SUBDIR)/libstdc++-v3/src/.libs:
@@ -612,6 +612,10 @@ TARGET_LIB_PATH_libssp = $$r/$(TARGET_SUBDIR)/libssp/.libs:
 TARGET_LIB_PATH_libgomp = $$r/$(TARGET_SUBDIR)/libgomp/.libs:
 @endif target-libgomp
 
+@if target-libitm
+TARGET_LIB_PATH_libitm = $$r/$(TARGET_SUBDIR)/libitm/.libs:
+@endif target-libitm
+
 
 
 # This is the list of directories that may be needed in RPATH_ENVVAR
@@ -947,7 +951,8 @@ configure-target:  \
     maybe-configure-target-boehm-gc \
     maybe-configure-target-rda \
     maybe-configure-target-libada \
-    maybe-configure-target-libgomp
+    maybe-configure-target-libgomp \
+    maybe-configure-target-libitm
 
 # The target built for a native non-bootstrap build.
 .PHONY: all
@@ -1094,6 +1099,7 @@ all-target: maybe-all-target-libada
 @if target-libgomp-no-bootstrap
 all-target: maybe-all-target-libgomp
 @endif target-libgomp-no-bootstrap
+all-target: maybe-all-target-libitm
 
 # Do a target for all the subdirectories.  A ``make do-X'' will do a
 # ``make X'' in all subdirectories (because, in general, there is a
@@ -1176,6 +1182,7 @@ info-target: maybe-info-target-boehm-gc
 info-target: maybe-info-target-rda
 info-target: maybe-info-target-libada
 info-target: maybe-info-target-libgomp
+info-target: maybe-info-target-libitm
 
 .PHONY: do-dvi
 do-dvi:
@@ -1253,6 +1260,7 @@ dvi-target: maybe-dvi-target-boehm-gc
 dvi-target: maybe-dvi-target-rda
 dvi-target: maybe-dvi-target-libada
 dvi-target: maybe-dvi-target-libgomp
+dvi-target: maybe-dvi-target-libitm
 
 .PHONY: do-pdf
 do-pdf:
@@ -1330,6 +1338,7 @@ pdf-target: maybe-pdf-target-boehm-gc
 pdf-target: maybe-pdf-target-rda
 pdf-target: maybe-pdf-target-libada
 pdf-target: maybe-pdf-target-libgomp
+pdf-target: maybe-pdf-target-libitm
 
 .PHONY: do-html
 do-html:
@@ -1407,6 +1416,7 @@ html-target: maybe-html-target-boehm-gc
 html-target: maybe-html-target-rda
 html-target: maybe-html-target-libada
 html-target: maybe-html-target-libgomp
+html-target: maybe-html-target-libitm
 
 .PHONY: do-TAGS
 do-TAGS:
@@ -1484,6 +1494,7 @@ TAGS-target: maybe-TAGS-target-boehm-gc
 TAGS-target: maybe-TAGS-target-rda
 TAGS-target: maybe-TAGS-target-libada
 TAGS-target: maybe-TAGS-target-libgomp
+TAGS-target: maybe-TAGS-target-libitm
 
 .PHONY: do-install-info
 do-install-info:
@@ -1561,6 +1572,7 @@ install-info-target: maybe-install-info-target-boehm-gc
 install-info-target: maybe-install-info-target-rda
 install-info-target: maybe-install-info-target-libada
 install-info-target: maybe-install-info-target-libgomp
+install-info-target: maybe-install-info-target-libitm
 
 .PHONY: do-install-pdf
 do-install-pdf:
@@ -1638,6 +1650,7 @@ install-pdf-target: maybe-install-pdf-target-boehm-gc
 install-pdf-target: maybe-install-pdf-target-rda
 install-pdf-target: maybe-install-pdf-target-libada
 install-pdf-target: maybe-install-pdf-target-libgomp
+install-pdf-target: maybe-install-pdf-target-libitm
 
 .PHONY: do-install-html
 do-install-html:
@@ -1715,6 +1728,7 @@ install-html-target: maybe-install-html-target-boehm-gc
 install-html-target: maybe-install-html-target-rda
 install-html-target: maybe-install-html-target-libada
 install-html-target: maybe-install-html-target-libgomp
+install-html-target: maybe-install-html-target-libitm
 
 .PHONY: do-installcheck
 do-installcheck:
@@ -1792,6 +1806,7 @@ installcheck-target: maybe-installcheck-target-boehm-gc
 installcheck-target: maybe-installcheck-target-rda
 installcheck-target: maybe-installcheck-target-libada
 installcheck-target: maybe-installcheck-target-libgomp
+installcheck-target: maybe-installcheck-target-libitm
 
 .PHONY: do-mostlyclean
 do-mostlyclean:
@@ -1869,6 +1884,7 @@ mostlyclean-target: maybe-mostlyclean-target-boehm-gc
 mostlyclean-target: maybe-mostlyclean-target-rda
 mostlyclean-target: maybe-mostlyclean-target-libada
 mostlyclean-target: maybe-mostlyclean-target-libgomp
+mostlyclean-target: maybe-mostlyclean-target-libitm
 
 .PHONY: do-clean
 do-clean:
@@ -1946,6 +1962,7 @@ clean-target: maybe-clean-target-boehm-gc
 clean-target: maybe-clean-target-rda
 clean-target: maybe-clean-target-libada
 clean-target: maybe-clean-target-libgomp
+clean-target: maybe-clean-target-libitm
 
 .PHONY: do-distclean
 do-distclean:
@@ -2023,6 +2040,7 @@ distclean-target: maybe-distclean-target-boehm-gc
 distclean-target: maybe-distclean-target-rda
 distclean-target: maybe-distclean-target-libada
 distclean-target: maybe-distclean-target-libgomp
+distclean-target: maybe-distclean-target-libitm
 
 .PHONY: do-maintainer-clean
 do-maintainer-clean:
@@ -2100,6 +2118,7 @@ maintainer-clean-target: maybe-maintainer-clean-target-boehm-gc
 maintainer-clean-target: maybe-maintainer-clean-target-rda
 maintainer-clean-target: maybe-maintainer-clean-target-libada
 maintainer-clean-target: maybe-maintainer-clean-target-libgomp
+maintainer-clean-target: maybe-maintainer-clean-target-libitm
 
 
 # Here are the targets which correspond to the do-X targets.
@@ -2231,7 +2250,8 @@ check-target:  \
     maybe-check-target-boehm-gc \
     maybe-check-target-rda \
     maybe-check-target-libada \
-    maybe-check-target-libgomp
+    maybe-check-target-libgomp \
+    maybe-check-target-libitm
 
 do-check:
        @: $(MAKE); $(unstage)
@@ -2380,7 +2400,8 @@ install-target:  \
     maybe-install-target-boehm-gc \
     maybe-install-target-rda \
     maybe-install-target-libada \
-    maybe-install-target-libgomp
+    maybe-install-target-libgomp \
+    maybe-install-target-libitm
 
 uninstall:
        @echo "the uninstall target is not supported in this tree"
@@ -2476,7 +2497,8 @@ install-strip-target:  \
     maybe-install-strip-target-boehm-gc \
     maybe-install-strip-target-rda \
     maybe-install-strip-target-libada \
-    maybe-install-strip-target-libgomp
+    maybe-install-strip-target-libgomp \
+    maybe-install-strip-target-libitm
 
 
 ### other supporting targets
@@ -40142,6 +40164,463 @@ maintainer-clean-target-libgomp:
 
 
 
+
+
+.PHONY: configure-target-libitm maybe-configure-target-libitm
+maybe-configure-target-libitm:
+@if gcc-bootstrap
+configure-target-libitm: stage_current
+@endif gcc-bootstrap
+@if target-libitm
+maybe-configure-target-libitm: configure-target-libitm
+configure-target-libitm: 
+       @: $(MAKE); $(unstage)
+       @r=`${PWD_COMMAND}`; export r; \
+       s=`cd $(srcdir); ${PWD_COMMAND}`; export s; \
+       echo "Checking multilib configuration for libitm..."; \
+       $(SHELL) $(srcdir)/mkinstalldirs $(TARGET_SUBDIR)/libitm ; \
+       $(CC_FOR_TARGET) --print-multi-lib > $(TARGET_SUBDIR)/libitm/multilib.tmp 2> /dev/null ; \
+       if test -r $(TARGET_SUBDIR)/libitm/multilib.out; then \
+         if cmp -s $(TARGET_SUBDIR)/libitm/multilib.tmp $(TARGET_SUBDIR)/libitm/multilib.out; then \
+           rm -f $(TARGET_SUBDIR)/libitm/multilib.tmp; \
+         else \
+           rm -f $(TARGET_SUBDIR)/libitm/Makefile; \
+           mv $(TARGET_SUBDIR)/libitm/multilib.tmp $(TARGET_SUBDIR)/libitm/multilib.out; \
+         fi; \
+       else \
+         mv $(TARGET_SUBDIR)/libitm/multilib.tmp $(TARGET_SUBDIR)/libitm/multilib.out; \
+       fi; \
+       test ! -f $(TARGET_SUBDIR)/libitm/Makefile || exit 0; \
+       $(SHELL) $(srcdir)/mkinstalldirs $(TARGET_SUBDIR)/libitm ; \
+       $(NORMAL_TARGET_EXPORTS)  \
+       echo Configuring in $(TARGET_SUBDIR)/libitm; \
+       cd "$(TARGET_SUBDIR)/libitm" || exit 1; \
+       case $(srcdir) in \
+         /* | [A-Za-z]:[\\/]*) topdir=$(srcdir) ;; \
+         *) topdir=`echo $(TARGET_SUBDIR)/libitm/ | \
+               sed -e 's,\./,,g' -e 's,[^/]*/,../,g' `$(srcdir) ;; \
+       esac; \
+       srcdiroption="--srcdir=$${topdir}/libitm"; \
+       libsrcdir="$$s/libitm"; \
+       rm -f no-such-file || : ; \
+       CONFIG_SITE=no-such-file $(SHELL) $${libsrcdir}/configure \
+         $(TARGET_CONFIGARGS) --build=${build_alias} --host=${target_alias} \
+         --target=${target_alias} $${srcdiroption}  \
+         || exit 1
+@endif target-libitm
+
+
+
+
+
+.PHONY: all-target-libitm maybe-all-target-libitm
+maybe-all-target-libitm:
+@if gcc-bootstrap
+all-target-libitm: stage_current
+@endif gcc-bootstrap
+@if target-libitm
+TARGET-target-libitm=all
+maybe-all-target-libitm: all-target-libitm
+all-target-libitm: configure-target-libitm
+       @: $(MAKE); $(unstage)
+       @r=`${PWD_COMMAND}`; export r; \
+       s=`cd $(srcdir); ${PWD_COMMAND}`; export s; \
+       $(NORMAL_TARGET_EXPORTS)  \
+       (cd $(TARGET_SUBDIR)/libitm && \
+         $(MAKE) $(BASE_FLAGS_TO_PASS) $(EXTRA_TARGET_FLAGS)  \
+               $(TARGET-target-libitm))
+@endif target-libitm
+
+
+
+
+
+.PHONY: check-target-libitm maybe-check-target-libitm
+maybe-check-target-libitm:
+@if target-libitm
+maybe-check-target-libitm: check-target-libitm
+
+check-target-libitm:
+       @: $(MAKE); $(unstage)
+       @r=`${PWD_COMMAND}`; export r; \
+       s=`cd $(srcdir); ${PWD_COMMAND}`; export s; \
+       $(NORMAL_TARGET_EXPORTS) \
+       (cd $(TARGET_SUBDIR)/libitm && \
+         $(MAKE) $(TARGET_FLAGS_TO_PASS)   check)
+
+@endif target-libitm
+
+.PHONY: install-target-libitm maybe-install-target-libitm
+maybe-install-target-libitm:
+@if target-libitm
+maybe-install-target-libitm: install-target-libitm
+
+install-target-libitm: installdirs
+       @: $(MAKE); $(unstage)
+       @r=`${PWD_COMMAND}`; export r; \
+       s=`cd $(srcdir); ${PWD_COMMAND}`; export s; \
+       $(NORMAL_TARGET_EXPORTS) \
+       (cd $(TARGET_SUBDIR)/libitm && \
+         $(MAKE) $(TARGET_FLAGS_TO_PASS)  install)
+
+@endif target-libitm
+
+.PHONY: install-strip-target-libitm maybe-install-strip-target-libitm
+maybe-install-strip-target-libitm:
+@if target-libitm
+maybe-install-strip-target-libitm: install-strip-target-libitm
+
+install-strip-target-libitm: installdirs
+       @: $(MAKE); $(unstage)
+       @r=`${PWD_COMMAND}`; export r; \
+       s=`cd $(srcdir); ${PWD_COMMAND}`; export s; \
+       $(NORMAL_TARGET_EXPORTS) \
+       (cd $(TARGET_SUBDIR)/libitm && \
+         $(MAKE) $(TARGET_FLAGS_TO_PASS)  install-strip)
+
+@endif target-libitm
+
+# Other targets (info, dvi, pdf, etc.)
+
+.PHONY: maybe-info-target-libitm info-target-libitm
+maybe-info-target-libitm:
+@if target-libitm
+maybe-info-target-libitm: info-target-libitm
+
+info-target-libitm: \
+    configure-target-libitm 
+       @: $(MAKE); $(unstage)
+       @[ -f $(TARGET_SUBDIR)/libitm/Makefile ] || exit 0 ; \
+       r=`${PWD_COMMAND}`; export r; \
+       s=`cd $(srcdir); ${PWD_COMMAND}`; export s; \
+       $(NORMAL_TARGET_EXPORTS) \
+       echo "Doing info in $(TARGET_SUBDIR)/libitm" ; \
+       for flag in $(EXTRA_TARGET_FLAGS); do \
+         eval `echo "$$flag" | sed -e "s|^\([^=]*\)=\(.*\)|\1='\2'; export \1|"`; \
+       done; \
+       (cd $(TARGET_SUBDIR)/libitm && \
+         $(MAKE) $(BASE_FLAGS_TO_PASS) "AR=$${AR}" "AS=$${AS}" \
+                 "CC=$${CC}" "CXX=$${CXX}" "LD=$${LD}" "NM=$${NM}" \
+                 "RANLIB=$${RANLIB}" \
+                 "DLLTOOL=$${DLLTOOL}" "WINDRES=$${WINDRES}" "WINDMC=$${WINDMC}" \
+                  info) \
+         || exit 1
+
+@endif target-libitm
+
+.PHONY: maybe-dvi-target-libitm dvi-target-libitm
+maybe-dvi-target-libitm:
+@if target-libitm
+maybe-dvi-target-libitm: dvi-target-libitm
+
+dvi-target-libitm: \
+    configure-target-libitm 
+       @: $(MAKE); $(unstage)
+       @[ -f $(TARGET_SUBDIR)/libitm/Makefile ] || exit 0 ; \
+       r=`${PWD_COMMAND}`; export r; \
+       s=`cd $(srcdir); ${PWD_COMMAND}`; export s; \
+       $(NORMAL_TARGET_EXPORTS) \
+       echo "Doing dvi in $(TARGET_SUBDIR)/libitm" ; \
+       for flag in $(EXTRA_TARGET_FLAGS); do \
+         eval `echo "$$flag" | sed -e "s|^\([^=]*\)=\(.*\)|\1='\2'; export \1|"`; \
+       done; \
+       (cd $(TARGET_SUBDIR)/libitm && \
+         $(MAKE) $(BASE_FLAGS_TO_PASS) "AR=$${AR}" "AS=$${AS}" \
+                 "CC=$${CC}" "CXX=$${CXX}" "LD=$${LD}" "NM=$${NM}" \
+                 "RANLIB=$${RANLIB}" \
+                 "DLLTOOL=$${DLLTOOL}" "WINDRES=$${WINDRES}" "WINDMC=$${WINDMC}" \
+                  dvi) \
+         || exit 1
+
+@endif target-libitm
+
+.PHONY: maybe-pdf-target-libitm pdf-target-libitm
+maybe-pdf-target-libitm:
+@if target-libitm
+maybe-pdf-target-libitm: pdf-target-libitm
+
+pdf-target-libitm: \
+    configure-target-libitm 
+       @: $(MAKE); $(unstage)
+       @[ -f $(TARGET_SUBDIR)/libitm/Makefile ] || exit 0 ; \
+       r=`${PWD_COMMAND}`; export r; \
+       s=`cd $(srcdir); ${PWD_COMMAND}`; export s; \
+       $(NORMAL_TARGET_EXPORTS) \
+       echo "Doing pdf in $(TARGET_SUBDIR)/libitm" ; \
+       for flag in $(EXTRA_TARGET_FLAGS); do \
+         eval `echo "$$flag" | sed -e "s|^\([^=]*\)=\(.*\)|\1='\2'; export \1|"`; \
+       done; \
+       (cd $(TARGET_SUBDIR)/libitm && \
+         $(MAKE) $(BASE_FLAGS_TO_PASS) "AR=$${AR}" "AS=$${AS}" \
+                 "CC=$${CC}" "CXX=$${CXX}" "LD=$${LD}" "NM=$${NM}" \
+                 "RANLIB=$${RANLIB}" \
+                 "DLLTOOL=$${DLLTOOL}" "WINDRES=$${WINDRES}" "WINDMC=$${WINDMC}" \
+                  pdf) \
+         || exit 1
+
+@endif target-libitm
+
+.PHONY: maybe-html-target-libitm html-target-libitm
+maybe-html-target-libitm:
+@if target-libitm
+maybe-html-target-libitm: html-target-libitm
+
+html-target-libitm: \
+    configure-target-libitm 
+       @: $(MAKE); $(unstage)
+       @[ -f $(TARGET_SUBDIR)/libitm/Makefile ] || exit 0 ; \
+       r=`${PWD_COMMAND}`; export r; \
+       s=`cd $(srcdir); ${PWD_COMMAND}`; export s; \
+       $(NORMAL_TARGET_EXPORTS) \
+       echo "Doing html in $(TARGET_SUBDIR)/libitm" ; \
+       for flag in $(EXTRA_TARGET_FLAGS); do \
+         eval `echo "$$flag" | sed -e "s|^\([^=]*\)=\(.*\)|\1='\2'; export \1|"`; \
+       done; \
+       (cd $(TARGET_SUBDIR)/libitm && \
+         $(MAKE) $(BASE_FLAGS_TO_PASS) "AR=$${AR}" "AS=$${AS}" \
+                 "CC=$${CC}" "CXX=$${CXX}" "LD=$${LD}" "NM=$${NM}" \
+                 "RANLIB=$${RANLIB}" \
+                 "DLLTOOL=$${DLLTOOL}" "WINDRES=$${WINDRES}" "WINDMC=$${WINDMC}" \
+                  html) \
+         || exit 1
+
+@endif target-libitm
+
+.PHONY: maybe-TAGS-target-libitm TAGS-target-libitm
+maybe-TAGS-target-libitm:
+@if target-libitm
+maybe-TAGS-target-libitm: TAGS-target-libitm
+
+TAGS-target-libitm: \
+    configure-target-libitm 
+       @: $(MAKE); $(unstage)
+       @[ -f $(TARGET_SUBDIR)/libitm/Makefile ] || exit 0 ; \
+       r=`${PWD_COMMAND}`; export r; \
+       s=`cd $(srcdir); ${PWD_COMMAND}`; export s; \
+       $(NORMAL_TARGET_EXPORTS) \
+       echo "Doing TAGS in $(TARGET_SUBDIR)/libitm" ; \
+       for flag in $(EXTRA_TARGET_FLAGS); do \
+         eval `echo "$$flag" | sed -e "s|^\([^=]*\)=\(.*\)|\1='\2'; export \1|"`; \
+       done; \
+       (cd $(TARGET_SUBDIR)/libitm && \
+         $(MAKE) $(BASE_FLAGS_TO_PASS) "AR=$${AR}" "AS=$${AS}" \
+                 "CC=$${CC}" "CXX=$${CXX}" "LD=$${LD}" "NM=$${NM}" \
+                 "RANLIB=$${RANLIB}" \
+                 "DLLTOOL=$${DLLTOOL}" "WINDRES=$${WINDRES}" "WINDMC=$${WINDMC}" \
+                  TAGS) \
+         || exit 1
+
+@endif target-libitm
+
+.PHONY: maybe-install-info-target-libitm install-info-target-libitm
+maybe-install-info-target-libitm:
+@if target-libitm
+maybe-install-info-target-libitm: install-info-target-libitm
+
+install-info-target-libitm: \
+    configure-target-libitm \
+    info-target-libitm 
+       @: $(MAKE); $(unstage)
+       @[ -f $(TARGET_SUBDIR)/libitm/Makefile ] || exit 0 ; \
+       r=`${PWD_COMMAND}`; export r; \
+       s=`cd $(srcdir); ${PWD_COMMAND}`; export s; \
+       $(NORMAL_TARGET_EXPORTS) \
+       echo "Doing install-info in $(TARGET_SUBDIR)/libitm" ; \
+       for flag in $(EXTRA_TARGET_FLAGS); do \
+         eval `echo "$$flag" | sed -e "s|^\([^=]*\)=\(.*\)|\1='\2'; export \1|"`; \
+       done; \
+       (cd $(TARGET_SUBDIR)/libitm && \
+         $(MAKE) $(BASE_FLAGS_TO_PASS) "AR=$${AR}" "AS=$${AS}" \
+                 "CC=$${CC}" "CXX=$${CXX}" "LD=$${LD}" "NM=$${NM}" \
+                 "RANLIB=$${RANLIB}" \
+                 "DLLTOOL=$${DLLTOOL}" "WINDRES=$${WINDRES}" "WINDMC=$${WINDMC}" \
+                  install-info) \
+         || exit 1
+
+@endif target-libitm
+
+.PHONY: maybe-install-pdf-target-libitm install-pdf-target-libitm
+maybe-install-pdf-target-libitm:
+@if target-libitm
+maybe-install-pdf-target-libitm: install-pdf-target-libitm
+
+install-pdf-target-libitm: \
+    configure-target-libitm \
+    pdf-target-libitm 
+       @: $(MAKE); $(unstage)
+       @[ -f $(TARGET_SUBDIR)/libitm/Makefile ] || exit 0 ; \
+       r=`${PWD_COMMAND}`; export r; \
+       s=`cd $(srcdir); ${PWD_COMMAND}`; export s; \
+       $(NORMAL_TARGET_EXPORTS) \
+       echo "Doing install-pdf in $(TARGET_SUBDIR)/libitm" ; \
+       for flag in $(EXTRA_TARGET_FLAGS); do \
+         eval `echo "$$flag" | sed -e "s|^\([^=]*\)=\(.*\)|\1='\2'; export \1|"`; \
+       done; \
+       (cd $(TARGET_SUBDIR)/libitm && \
+         $(MAKE) $(BASE_FLAGS_TO_PASS) "AR=$${AR}" "AS=$${AS}" \
+                 "CC=$${CC}" "CXX=$${CXX}" "LD=$${LD}" "NM=$${NM}" \
+                 "RANLIB=$${RANLIB}" \
+                 "DLLTOOL=$${DLLTOOL}" "WINDRES=$${WINDRES}" "WINDMC=$${WINDMC}" \
+                  install-pdf) \
+         || exit 1
+
+@endif target-libitm
+
+.PHONY: maybe-install-html-target-libitm install-html-target-libitm
+maybe-install-html-target-libitm:
+@if target-libitm
+maybe-install-html-target-libitm: install-html-target-libitm
+
+install-html-target-libitm: \
+    configure-target-libitm \
+    html-target-libitm 
+       @: $(MAKE); $(unstage)
+       @[ -f $(TARGET_SUBDIR)/libitm/Makefile ] || exit 0 ; \
+       r=`${PWD_COMMAND}`; export r; \
+       s=`cd $(srcdir); ${PWD_COMMAND}`; export s; \
+       $(NORMAL_TARGET_EXPORTS) \
+       echo "Doing install-html in $(TARGET_SUBDIR)/libitm" ; \
+       for flag in $(EXTRA_TARGET_FLAGS); do \
+         eval `echo "$$flag" | sed -e "s|^\([^=]*\)=\(.*\)|\1='\2'; export \1|"`; \
+       done; \
+       (cd $(TARGET_SUBDIR)/libitm && \
+         $(MAKE) $(BASE_FLAGS_TO_PASS) "AR=$${AR}" "AS=$${AS}" \
+                 "CC=$${CC}" "CXX=$${CXX}" "LD=$${LD}" "NM=$${NM}" \
+                 "RANLIB=$${RANLIB}" \
+                 "DLLTOOL=$${DLLTOOL}" "WINDRES=$${WINDRES}" "WINDMC=$${WINDMC}" \
+                  install-html) \
+         || exit 1
+
+@endif target-libitm
+
+.PHONY: maybe-installcheck-target-libitm installcheck-target-libitm
+maybe-installcheck-target-libitm:
+@if target-libitm
+maybe-installcheck-target-libitm: installcheck-target-libitm
+
+installcheck-target-libitm: \
+    configure-target-libitm 
+       @: $(MAKE); $(unstage)
+       @[ -f $(TARGET_SUBDIR)/libitm/Makefile ] || exit 0 ; \
+       r=`${PWD_COMMAND}`; export r; \
+       s=`cd $(srcdir); ${PWD_COMMAND}`; export s; \
+       $(NORMAL_TARGET_EXPORTS) \
+       echo "Doing installcheck in $(TARGET_SUBDIR)/libitm" ; \
+       for flag in $(EXTRA_TARGET_FLAGS); do \
+         eval `echo "$$flag" | sed -e "s|^\([^=]*\)=\(.*\)|\1='\2'; export \1|"`; \
+       done; \
+       (cd $(TARGET_SUBDIR)/libitm && \
+         $(MAKE) $(BASE_FLAGS_TO_PASS) "AR=$${AR}" "AS=$${AS}" \
+                 "CC=$${CC}" "CXX=$${CXX}" "LD=$${LD}" "NM=$${NM}" \
+                 "RANLIB=$${RANLIB}" \
+                 "DLLTOOL=$${DLLTOOL}" "WINDRES=$${WINDRES}" "WINDMC=$${WINDMC}" \
+                  installcheck) \
+         || exit 1
+
+@endif target-libitm
+
+.PHONY: maybe-mostlyclean-target-libitm mostlyclean-target-libitm
+maybe-mostlyclean-target-libitm:
+@if target-libitm
+maybe-mostlyclean-target-libitm: mostlyclean-target-libitm
+
+mostlyclean-target-libitm: 
+       @: $(MAKE); $(unstage)
+       @[ -f $(TARGET_SUBDIR)/libitm/Makefile ] || exit 0 ; \
+       r=`${PWD_COMMAND}`; export r; \
+       s=`cd $(srcdir); ${PWD_COMMAND}`; export s; \
+       $(NORMAL_TARGET_EXPORTS) \
+       echo "Doing mostlyclean in $(TARGET_SUBDIR)/libitm" ; \
+       for flag in $(EXTRA_TARGET_FLAGS); do \
+         eval `echo "$$flag" | sed -e "s|^\([^=]*\)=\(.*\)|\1='\2'; export \1|"`; \
+       done; \
+       (cd $(TARGET_SUBDIR)/libitm && \
+         $(MAKE) $(BASE_FLAGS_TO_PASS) "AR=$${AR}" "AS=$${AS}" \
+                 "CC=$${CC}" "CXX=$${CXX}" "LD=$${LD}" "NM=$${NM}" \
+                 "RANLIB=$${RANLIB}" \
+                 "DLLTOOL=$${DLLTOOL}" "WINDRES=$${WINDRES}" "WINDMC=$${WINDMC}" \
+                  mostlyclean) \
+         || exit 1
+
+@endif target-libitm
+
+.PHONY: maybe-clean-target-libitm clean-target-libitm
+maybe-clean-target-libitm:
+@if target-libitm
+maybe-clean-target-libitm: clean-target-libitm
+
+clean-target-libitm: 
+       @: $(MAKE); $(unstage)
+       @[ -f $(TARGET_SUBDIR)/libitm/Makefile ] || exit 0 ; \
+       r=`${PWD_COMMAND}`; export r; \
+       s=`cd $(srcdir); ${PWD_COMMAND}`; export s; \
+       $(NORMAL_TARGET_EXPORTS) \
+       echo "Doing clean in $(TARGET_SUBDIR)/libitm" ; \
+       for flag in $(EXTRA_TARGET_FLAGS); do \
+         eval `echo "$$flag" | sed -e "s|^\([^=]*\)=\(.*\)|\1='\2'; export \1|"`; \
+       done; \
+       (cd $(TARGET_SUBDIR)/libitm && \
+         $(MAKE) $(BASE_FLAGS_TO_PASS) "AR=$${AR}" "AS=$${AS}" \
+                 "CC=$${CC}" "CXX=$${CXX}" "LD=$${LD}" "NM=$${NM}" \
+                 "RANLIB=$${RANLIB}" \
+                 "DLLTOOL=$${DLLTOOL}" "WINDRES=$${WINDRES}" "WINDMC=$${WINDMC}" \
+                  clean) \
+         || exit 1
+
+@endif target-libitm
+
+.PHONY: maybe-distclean-target-libitm distclean-target-libitm
+maybe-distclean-target-libitm:
+@if target-libitm
+maybe-distclean-target-libitm: distclean-target-libitm
+
+distclean-target-libitm: 
+       @: $(MAKE); $(unstage)
+       @[ -f $(TARGET_SUBDIR)/libitm/Makefile ] || exit 0 ; \
+       r=`${PWD_COMMAND}`; export r; \
+       s=`cd $(srcdir); ${PWD_COMMAND}`; export s; \
+       $(NORMAL_TARGET_EXPORTS) \
+       echo "Doing distclean in $(TARGET_SUBDIR)/libitm" ; \
+       for flag in $(EXTRA_TARGET_FLAGS); do \
+         eval `echo "$$flag" | sed -e "s|^\([^=]*\)=\(.*\)|\1='\2'; export \1|"`; \
+       done; \
+       (cd $(TARGET_SUBDIR)/libitm && \
+         $(MAKE) $(BASE_FLAGS_TO_PASS) "AR=$${AR}" "AS=$${AS}" \
+                 "CC=$${CC}" "CXX=$${CXX}" "LD=$${LD}" "NM=$${NM}" \
+                 "RANLIB=$${RANLIB}" \
+                 "DLLTOOL=$${DLLTOOL}" "WINDRES=$${WINDRES}" "WINDMC=$${WINDMC}" \
+                  distclean) \
+         || exit 1
+
+@endif target-libitm
+
+.PHONY: maybe-maintainer-clean-target-libitm maintainer-clean-target-libitm
+maybe-maintainer-clean-target-libitm:
+@if target-libitm
+maybe-maintainer-clean-target-libitm: maintainer-clean-target-libitm
+
+maintainer-clean-target-libitm: 
+       @: $(MAKE); $(unstage)
+       @[ -f $(TARGET_SUBDIR)/libitm/Makefile ] || exit 0 ; \
+       r=`${PWD_COMMAND}`; export r; \
+       s=`cd $(srcdir); ${PWD_COMMAND}`; export s; \
+       $(NORMAL_TARGET_EXPORTS) \
+       echo "Doing maintainer-clean in $(TARGET_SUBDIR)/libitm" ; \
+       for flag in $(EXTRA_TARGET_FLAGS); do \
+         eval `echo "$$flag" | sed -e "s|^\([^=]*\)=\(.*\)|\1='\2'; export \1|"`; \
+       done; \
+       (cd $(TARGET_SUBDIR)/libitm && \
+         $(MAKE) $(BASE_FLAGS_TO_PASS) "AR=$${AR}" "AS=$${AS}" \
+                 "CC=$${CC}" "CXX=$${CXX}" "LD=$${LD}" "NM=$${NM}" \
+                 "RANLIB=$${RANLIB}" \
+                 "DLLTOOL=$${DLLTOOL}" "WINDRES=$${WINDRES}" "WINDMC=$${WINDMC}" \
+                  maintainer-clean) \
+         || exit 1
+
+@endif target-libitm
+
+
+
 @if target-libmudflap
 .PHONY: check-target-libmudflap-c++
 check-target-libmudflap-c++:
@@ -42233,6 +42712,7 @@ configure-stage3-target-libgomp: maybe-all-stage3-gcc
 configure-stage4-target-libgomp: maybe-all-stage4-gcc
 configure-stageprofile-target-libgomp: maybe-all-stageprofile-gcc
 configure-stagefeedback-target-libgomp: maybe-all-stagefeedback-gcc
+configure-target-libitm: stage_last
 @endif gcc-bootstrap
 
 @if gcc-no-bootstrap
@@ -42255,6 +42735,7 @@ configure-target-boehm-gc: maybe-all-gcc
 configure-target-rda: maybe-all-gcc
 configure-target-libada: maybe-all-gcc
 configure-target-libgomp: maybe-all-gcc
+configure-target-libitm: maybe-all-gcc
 @endif gcc-no-bootstrap
 
 
@@ -43028,6 +43509,7 @@ configure-target-boehm-gc: maybe-all-target-libgcc
 configure-target-rda: maybe-all-target-libgcc
 configure-target-libada: maybe-all-target-libgcc
 configure-target-libgomp: maybe-all-target-libgcc
+configure-target-libitm: maybe-all-target-libgcc
 @endif gcc-no-bootstrap
 
 
@@ -43067,6 +43549,9 @@ configure-target-libada: maybe-all-target-newlib maybe-all-target-libgloss
 
 configure-target-libgomp: maybe-all-target-newlib maybe-all-target-libgloss
 
+configure-target-libitm: maybe-all-target-newlib maybe-all-target-libgloss
+configure-target-libitm: maybe-all-target-libstdc++-v3
+
 
 CONFIGURE_GDB_TK = @CONFIGURE_GDB_TK@
 GDB_TK = @GDB_TK@
diff --git a/config/mmap.m4 b/config/mmap.m4
new file mode 100644 (file)
index 0000000..39d79af
--- /dev/null
@@ -0,0 +1,97 @@
+dnl ----------------------------------------------------------------------
+dnl This whole bit snagged from gcc
+
+dnl
+dnl mmap(2) blacklisting.  Some platforms provide the mmap library routine
+dnl but don't support all of the features we need from it.
+dnl
+AC_DEFUN([GCC_AC_FUNC_MMAP_BLACKLIST],
+[
+AC_CHECK_HEADER([sys/mman.h],
+               [gcc_header_sys_mman_h=yes], [gcc_header_sys_mman_h=no])
+AC_CHECK_FUNC([mmap], [gcc_func_mmap=yes], [gcc_func_mmap=no])
+if test "$gcc_header_sys_mman_h" != yes \
+ || test "$gcc_func_mmap" != yes; then
+   gcc_cv_func_mmap_file=no
+   gcc_cv_func_mmap_dev_zero=no
+   gcc_cv_func_mmap_anon=no
+else
+   AC_CACHE_CHECK([whether read-only mmap of a plain file works], 
+  gcc_cv_func_mmap_file,
+  [# Add a system to this blacklist if 
+   # mmap(0, stat_size, PROT_READ, MAP_PRIVATE, fd, 0) doesn't return a
+   # memory area containing the same data that you'd get if you applied
+   # read() to the same fd.  The only system known to have a problem here
+   # is VMS, where text files have record structure.
+   case "$host_os" in
+     vms* | ultrix*) 
+        gcc_cv_func_mmap_file=no ;;
+     *)
+        gcc_cv_func_mmap_file=yes;;
+   esac])
+   AC_CACHE_CHECK([whether mmap from /dev/zero works],
+  gcc_cv_func_mmap_dev_zero,
+  [# Add a system to this blacklist if it has mmap() but /dev/zero
+   # does not exist, or if mmapping /dev/zero does not give anonymous
+   # zeroed pages with both the following properties:
+   # 1. If you map N consecutive pages in with one call, and then
+   #    unmap any subset of those pages, the pages that were not
+   #    explicitly unmapped remain accessible.
+   # 2. If you map two adjacent blocks of memory and then unmap them
+   #    both at once, they must both go away.
+   # Systems known to be in this category are Windows (all variants),
+   # VMS, and Darwin.
+   case "$host_os" in
+     vms* | cygwin* | pe | mingw* | darwin* | ultrix* | hpux10* | hpux11.00)
+        gcc_cv_func_mmap_dev_zero=no ;;
+     *)
+        gcc_cv_func_mmap_dev_zero=yes;;
+   esac])
+
+   # Unlike /dev/zero, the MAP_ANON(YMOUS) defines can be probed for.
+   AC_CACHE_CHECK([for MAP_ANON(YMOUS)], gcc_cv_decl_map_anon,
+    [AC_COMPILE_IFELSE([AC_LANG_PROGRAM(
+[#include <sys/types.h>
+#include <sys/mman.h>
+#include <unistd.h>
+
+#ifndef MAP_ANONYMOUS
+#define MAP_ANONYMOUS MAP_ANON
+#endif
+],
+[int n = MAP_ANONYMOUS;])],
+    gcc_cv_decl_map_anon=yes,
+    gcc_cv_decl_map_anon=no)])
+
+   if test $gcc_cv_decl_map_anon = no; then
+     gcc_cv_func_mmap_anon=no
+   else
+     AC_CACHE_CHECK([whether mmap with MAP_ANON(YMOUS) works],
+     gcc_cv_func_mmap_anon,
+  [# Add a system to this blacklist if it has mmap() and MAP_ANON or
+   # MAP_ANONYMOUS, but using mmap(..., MAP_PRIVATE|MAP_ANONYMOUS, -1, 0)
+   # doesn't give anonymous zeroed pages with the same properties listed
+   # above for use of /dev/zero.
+   # Systems known to be in this category are Windows, VMS, and SCO Unix.
+   case "$host_os" in
+     vms* | cygwin* | pe | mingw* | sco* | udk* )
+        gcc_cv_func_mmap_anon=no ;;
+     *)
+        gcc_cv_func_mmap_anon=yes;;
+   esac])
+   fi
+fi
+
+if test $gcc_cv_func_mmap_file = yes; then
+  AC_DEFINE(HAVE_MMAP_FILE, 1,
+           [Define if read-only mmap of a plain file works.])
+fi
+if test $gcc_cv_func_mmap_dev_zero = yes; then
+  AC_DEFINE(HAVE_MMAP_DEV_ZERO, 1,
+           [Define if mmap of /dev/zero works.])
+fi
+if test $gcc_cv_func_mmap_anon = yes; then
+  AC_DEFINE(HAVE_MMAP_ANON, 1,
+           [Define if mmap with MAP_ANON(YMOUS) works.])
+fi
+])
index eb69f28..03d0048 100755 (executable)
--- a/configure
+++ b/configure
@@ -2681,6 +2681,7 @@ target_libraries="target-libgcc \
                target-libgloss \
                target-newlib \
                target-libgomp \
+               target-libitm \
                target-libstdc++-v3 \
                target-libmudflap \
                target-libssp \
@@ -3056,6 +3057,24 @@ if test x$enable_libgomp = x ; then
     esac
 fi
 
+# Disable libitm on non POSIX hosted systems.
+if test x$enable_libitm = x ; then
+    # Enable libitm by default on hosted POSIX systems.
+    case "${target}" in
+    *-*-linux* | *-*-gnu* | *-*-k*bsd*-gnu)
+       ;;
+    *-*-netbsd* | *-*-freebsd* | *-*-openbsd*)
+       ;;
+    *-*-solaris2* | *-*-sysv4* | *-*-irix6* | *-*-osf* | *-*-hpux11*)
+       ;;
+    *-*-darwin* | *-*-aix*)
+       ;;
+    *)
+       noconfigdirs="$noconfigdirs target-libitm"
+       ;;
+    esac
+fi
+
 # Disable libssp for some systems.
 case "${target}" in
   avr-*-*)
index 337e11d..4bca6d8 100644 (file)
@@ -154,6 +154,7 @@ target_libraries="target-libgcc \
                target-libgloss \
                target-newlib \
                target-libgomp \
+               target-libitm \
                target-libstdc++-v3 \
                target-libmudflap \
                target-libssp \
@@ -492,6 +493,24 @@ if test x$enable_libgomp = x ; then
     esac
 fi
 
+# Disable libitm on non POSIX hosted systems.
+if test x$enable_libitm = x ; then
+    # Enable libitm by default on hosted POSIX systems.
+    case "${target}" in
+    *-*-linux* | *-*-gnu* | *-*-k*bsd*-gnu)
+       ;;
+    *-*-netbsd* | *-*-freebsd* | *-*-openbsd*)
+       ;;
+    *-*-solaris2* | *-*-sysv4* | *-*-irix6* | *-*-osf* | *-*-hpux11*)
+       ;;
+    *-*-darwin* | *-*-aix*)
+       ;;
+    *)
+       noconfigdirs="$noconfigdirs target-libitm"
+       ;;
+    esac
+fi
+
 # Disable libssp for some systems.
 case "${target}" in
   avr-*-*)
index ed2ff36..b382897 100644 (file)
@@ -1,3 +1,9 @@
+2011-11-07  Richard Henderson  <rth@redhat.com>
+
+       Merged from transactional-memory.
+
+       * gcc_update: Add libitm to touch data.
+
 2011-11-07   Quentin Neill  <quentin.neill@amd.com>
 
        * compare_tests: Add ability to compare all .sum
index c719502..3612880 100755 (executable)
@@ -136,6 +136,11 @@ libgomp/Makefile.in: libgomp/Makefile.am libgomp/aclocal.m4
 libgomp/testsuite/Makefile.in: libgomp/Makefile.am libgomp/aclocal.m4
 libgomp/configure: libgomp/configure.ac libgomp/aclocal.m4
 libgomp/config.h.in: libgomp/configure.ac libgomp/aclocal.m4
+libitm/aclocal.m4: libitm/configure.ac libitm/acinclude.m4
+libitm/Makefile.in: libitm/Makefile.am libitm/aclocal.m4
+libitm/testsuite/Makefile.in: libitm/testsuite/Makefile.am libitm/aclocal.m4
+libitm/configure: libitm/configure.ac libitm/aclocal.m4
+libitm/config.h.in: libitm/configure.ac libitm/aclocal.m4
 # Top level
 Makefile.in: Makefile.tpl Makefile.def
 configure: configure.ac config/acx.m4
index cfde0b6..e6816e5 100644 (file)
@@ -1,4 +1,202 @@
 2011-11-07  Richard Henderson  <rth@redhat.com>
+           Aldy Hernandez  <aldyh@redhat.com>
+           Andrew MacLeod  <amacleod@redhat.com>
+           Torvald Riegel  <triegel@redhat.com>
+
+       Merged from transactional-memory.
+
+       * gtm-builtins.def: New file.
+       * trans-mem.c: New file.
+       * trans-mem.h: New file.
+
+       * opts.c (finish_options): Error out when using -flto and
+       -fgnu-tm.
+
+       * config/i386/i386.c: Define TARGET_VECTORIZE* transactional variants.
+       (ix86_handle_tm_regparm_attribute, struct bdesc_tm,
+       ix86_builtin_tm_load, ix86_builtin_tm_store,
+       ix86_init_tm_builtins): New.
+       (ix86_init_builtins): Initialize TM builtins.
+       (struct ix86_attribute_table): Add "*tm regparm".
+       * config/i386/i386-builtin-types.def (PV2SI): Define.
+       (PCV2SI): Define.
+       Define V2SI_FTYPE_PCV2SI.
+       Define V4SF_FTYPE_PCV4SF.
+       Define V8SF_FTYPE_PCV8SF.
+       Define VOID_PV2SI_V2SI.
+
+       * doc/invoke.texi (C Dialect Options): Document -fgnu-tm and
+       tm-max-aggregate-size.
+       * doc/tm.texi.in: Add TARGET_VECTORIZE_BUILTIN_TM_LOAD and
+       TARGET_VECTORIZE_BUILTIN_TM_STORE hooks.
+       * doc/tm.texi: Regenerate.
+
+       * attribs.c (apply_tm_attr): New.
+       (init_attributes): Allow '*' prefix for overrides.
+       (register_attribute): Likewise.
+       * builtin-attrs.def (ATTR_TM_TMPURE, ATTR_TM_REGPARM): New.
+       (ATTR_TM_NOTHROW_LIST, ATTR_TM_TMPURE_NOTHROW_LIST,
+       ATTR_TM_PURE_TMPURE_NOTHROW_LIST, ATTR_TM_NORETURN_NOTHROW_LIST,
+       ATTR_TM_CONST_NOTHROW_LIST, ATTR_TMPURE_MALLOC_NOTHROW_LIST,
+       ATTR_TMPURE_NOTHROW_LIST): New.
+       * builtin-types.def (BT_FN_I[1248]_VPTR, BT_FN_FLOAT_VPTR,
+       BT_FN_DOUBLE_VPTR, BT_FN_LDOUBLE_VPTR, BT_FN_VOID_VPTR_I[1248],
+       BT_FN_VOID_VPTR_FLOAT, BT_FN_VOID_VPTR_DOUBLE,
+       BT_FN_VOID_VPTR_LDOUBLE, BT_FN_VOID_VPTR_SIZE): New.
+       * builtins.def: Include gtm-builtins.def. Add comments regarding
+       transactional memory synchronization.
+       (DEF_TM_BUILTIN): New.
+       * c-parser.c (struct c_parser): Add in_transaction.
+       (c_parser_transaction, c_parser_transaction_expression,
+       c_parser_transaction_cancel, c_parser_transaction_attributes): New.
+       (c_parser_attribute_any_word): Split out from c_parser_attributes.
+       (c_parser_statement_after_labels): Handle RID_TRANSACTION*.
+       (c_parser_unary_expression): Same.
+       * c-tree.h (c_finish_transaction): Declare.
+       * c-typeck.c (c_finish_transaction): New.
+       (build_function_call_vec): Call tm_malloc_replacement.
+       * calls.c (is_tm_builtin): New.
+       (flags_from_decl_or_type): Add ECF_TM_BUILTIN and ECF_TM_PURE.
+       * cfgbuild.c (make_edges): Add edges for REG_TM notes.
+       * cfgexpand.c (expand_call_stmt): Call
+       mark_transaction_restart_calls.
+       (gimple_expand_cfg): Free the tm_restart map.
+       (mark_transaction_restart_calls): New.
+       * cfgrtl.c (purge_dead_edges): Look for REG_TM notes.
+       * cgraph.c (dump_cgraph_node): Handle tm_clone.
+       * cgraph.h (struct cgraph_node): Add tm_clone field.
+       (decl_is_tm_clone): New.
+       (struct cgraph_local_info): Add tm_may_enter_irr.
+       (cgraph_copy_node_for_versioning): Declare.
+       * cgraphunit.c (cgraph_copy_node_for_versioning): Export;
+       copy analyzed from old version.
+       * combine.c (distribute_notes): Handle REG_TM notes.
+       * common.opt: Add -fgnu-tm.
+       * crtstuff.c (__TMC_LIST__, __TMC_END__): New.
+       (__do_global_dtors_aux): Deregister clone table.
+       (frame_dummy): Register clone table.
+       * emit-rtl.c (try_split): Handle REG_TM. Early return if no function
+       body.
+       * gimple-low.c (lower_stmt): Handle GIMPLE_EH_ELSE and
+       GIMPLE_TRANSACTION.
+       (gimple_stmt_may_fallthru): Handle GIMPLE_EH_ELSE.
+       * gimple-pretty-print.c: Include trans-mem.h.
+       (dump_gimple_fmt): Add %x.
+       (dump_gimple_call): Dump arguments for calls to _ITM_beginTransaction.
+       (dump_gimple_eh_else, dump_gimple_transaction): New.
+       (dump_gimple_stmt): Handle GIMPLE_EH_ELSE and GIMPLE_TRANSACTION.
+       * gimple.c (gimple_build_eh_else, gimple_build_transaction): New.
+       (walk_gimple_seq): Honor removed_stmt. Document usage of removed_stmt
+       field.
+       (walk_gimple_op): Handle GIMPLE_TRANSACTION.
+       (walk_gimple_stmt): Initialize and honor removed_stmt.
+       Handle GIMPLE_EH_ELSE and GIMPLE_TRANSACTION.
+       (gimple_copy): Handle GIMPLE_EH_ELSE and GIMPLE_TRANSACTION.
+       * gimple.def (GIMPLE_TRANSACTION, GIMPLE_EH_ELSE): New.
+       * gimple.h (struct gimple_statement_eh_else,
+       gimple_statement_transaction, GTMA_*): New.
+       (gimple_statement_d): Add gimple_statement_eh_else and
+       gimple_transaction.
+       (gimple_build_eh_else, gimple_build_transaction,
+       gimple_fold_call, diagnose_tm_safe_errors): Declare.
+       (get_call_expr_in): Remove prototype.
+       (gimple_has_substatements): Add GIMPLE_EH_ELSE and GIMPLE_TRANSACTION.
+       (gimple_eh_else_n_body, gimple_eh_else_e_body,
+       gimple_eh_else_set_n_body, gimple_eh_else_set_e_body,
+       gimple_transaction_body, gimple_transaction_label,
+       gimple_transaction_label_ptr, gimple_transaction_subcode,
+       gimple_transaction_set_body, gimple_transaction_set_label,
+       gimple_transaction_set_subcode): New.
+       (struct walk_stmt_info): Use BOOL_BITFIELD; add removed_stmt.
+       * gimplify.c (create_tmp_var_name): Use clean_symbol_name.
+       (voidify_wrapper_expr): Handle TRANSACTION_EXPR.
+       (gimplify_transaction): New.
+       (gimplify_expr): Handle TRANSACTION_EXPR.
+       * gsstruct.def (GSS_EH_ELSE, GSS_TRANSACTION): New.
+       * ipa-inline.c (can_inline_edge_p): Do not inline TM safe calling
+       TM pure functions.
+       * Makefile.in: Add trans-mem.o and dependencies.
+       (BUILTINS_DEF): Add gtm-builtins.def.
+       (gimple-pretty-print.o): Depend on TRANS_MEM_H.
+       (GTFILES): Add trans-mem.c.
+       * omp-low.c (WALK_SUBSTMTS): Add GIMPLE_TRANSACTION.
+       * output.h (record_tm_clone_pair, finish_tm_clone_pairs,
+       get_tm_clone_pair): Declare.
+       * params.def (PARAM_TM_MAX_AGGREGATE_SIZE): New.
+       * passes.c (init_optimization_passes): Place transactional memory
+       passes.
+       * print-tree.c (print_node): Dump tm-clone.
+       * recog.c (peep2_attempt): Handle REG_TM.
+       * reg-notes.def (TM): New.
+       * rtlanal.c (alloc_reg_note): Handle REG_TM.
+       * target.def (builtin_tm_load, builtin_tm_store): New.
+       * targhooks.c (default_builtin_tm_load_store): New.
+       * targhooks.h (default_builtin_tm_load_store): Declare.
+       * timevar.def (TV_TRANS_MEM): New.
+       * toplev.c (compile_file): Call finish_tm_clone_pairs.
+       * tree-cfg.c (make_edges): Handle GIMPLE_TRANSACTION.
+       (cleanup_dead_labels): Handle GIMPLE_TRANSACTION. Avoid unnecessary
+       writes into the statements to update labels.
+       (is_ctrl_altering_stmt): Add TM ending statements. Handle
+       GIMPLE_TRANSACTION.
+       (verify_gimple_transaction): New.
+       (verify_gimple_stmt): Handle GIMPLE_TRANSACTION.
+       (verify_gimple_in_seq_2): Handle GIMPLE_EH_ELSE and GIMPLE_TRANSACTION.
+       (gimple_redirect_edge_and_branch): Handle TM_TRANSACTION.
+       (dump_function_to_file): Display [tm-clone] if applicable.
+       * tree-eh.c (struct_ptr_eq): Make inline and move to tree.h.
+       (struct_ptr_hash): Same.
+       (collect_finally_tree): Handle GIMPLE_EH_ELSE.
+       (replace_goto_queue_1): Likewise.
+       (get_eh_else): New.
+       (honor_protect_cleanup_actions): Handle GIMPLE_EH_ELSE.
+       (lower_try_finally_nofallthru): Likewise.
+       (lower_try_finally_onedest): Likewise.
+       (lower_try_finally_copy): Likewise.
+       (lower_try_finally_switch): Likewise.
+       (lower_try_finally): Likewise.
+       (decide_copy_try_finally): Likewise.
+       (lower_eh_constructs_2): Likewise.
+       (refactor_eh_r): Likewise.
+       * tree-flow.h (struct gimple_df): Add tm_restart field.
+       Define tm_restart_node.
+       * tree-inline.c (remap_gimple_stmt): Handle GIMPLE_TRANSACTION.
+       (estimate_num_insns): Likewise.
+       (init_inline_once): Init tm_cost.
+       * tree-inline.h (struct eni_weights_d): Add tm_cost.
+       * tree-pass.h (pass_diagnose_tm_blocks, pass_lower_tm, pass_tm_init,
+       pass_tm_mark, pass_tm_memopt, pass_tm_edges, pass_ipa_tm): Declare.
+       * tree-pretty-print.c (dump_generic_node): Handle TRANSACTION_EXPR.
+       * tree-ssa-alias.c (ref_maybe_used_by_call_p_1): Handle
+       BUILT_IN_TM_MEMSET, BUILT_IN_TM_MEMCPY, BUILT_IN_TM_MEMMOVE.
+       Add support for TM vector loads.  Add support for TM logging builtins.
+       (call_may_clobber_ref_p_1): Add support for vector stores.
+       * tree-ssa-structalias.c (find_func_aliases): Add support for TM
+       vector stores and loads. Handle BUILT_IN_TM_MEMSET,
+       BUILT_IN_TM_MEMCPY, BUILT_IN_TM_MEMMOVE.
+       * tree.c (strip_invariant_refs): Moved from gimple.c to here.
+       (local_define_builtin): Handle ECF_TM_PURE.
+       (build_common_builtin_nodes): Set __builtin_eh_pointer to ECF_TM_PURE.
+       * tree.def (TRANSACTION_EXPR): New.
+       * tree.h (strip_invariant_refs): Moved from gimple.h to here.
+       (TRANSACTION_EXPR_BODY, TRANSACTION_EXPR_CHECK,
+       TRANSACTION_EXPR_OUTER, TRANSACTION_EXPR_RELAXED,
+       BUILTIN_TM_LOAD_STORE_P, BUILTIN_TM_LOAD_P, BUILTIN_TM_STORE_P,
+       CASE_BUILT_IN_TM_LOAD, CASE_BUILT_IN_TM_STORE): New.
+       (ECF_TM_PURE, ECF_TM_BUILTIN): New.
+       (struct tree_function_decl): Add tm_clone_flag.
+       (struct_ptr_eq, struct_ptr_hash): New.
+       (apply_tm_attr): Declare.
+       (is_tm_safe_or_pure): New.
+       (build_tm_abort_call, is_tm_safe, is_tm_pure,
+       is_tm_may_cancel_outer, is_tm_ending_fndecl, record_tm_replacement,
+       tm_malloc_replacement): Declare.
+       * varasm.c (tm_clone_hash): New.
+       (record_tm_clone_pair, finish_tm_clone_pairs, get_tm_clone_pair,
+       dump_tm_clone_to_vec, dump_tm_clone_pairs, tm_alias_pair_cmp): New.
+       (struct tm_alias_pair): New.  Declare VEC types for object.
+
+2011-11-07  Richard Henderson  <rth@redhat.com>
 
        * optabs.h (OTI_sync_compare_and_swap, OTI_sync_lock_test_and_set,
        OTI_sync_old_add, OTI_sync_old_sub, OTI_sync_old_ior,
index 20bb98a..9ec2df1 100644 (file)
@@ -856,7 +856,8 @@ RTL_H = $(RTL_BASE_H) genrtl.h vecir.h
 RTL_ERROR_H = $(RTL_H) $(DIAGNOSTIC_CORE_H)
 READ_MD_H = $(OBSTACK_H) $(HASHTAB_H) read-md.h
 PARAMS_H = params.h params.def
-BUILTINS_DEF = builtins.def sync-builtins.def omp-builtins.def
+BUILTINS_DEF = builtins.def sync-builtins.def omp-builtins.def \
+       gtm-builtins.def
 INTERNAL_FN_DEF = internal-fn.def
 INTERNAL_FN_H = internal-fn.h $(INTERNAL_FN_DEF)
 TREE_H = tree.h all-tree.def tree.def c-family/c-common.def \
@@ -869,6 +870,7 @@ BASIC_BLOCK_H = basic-block.h $(PREDICT_H) $(VEC_H) $(FUNCTION_H) cfghooks.h
 GIMPLE_H = gimple.h gimple.def gsstruct.def pointer-set.h $(VEC_H) \
        vecir.h $(GGC_H) $(BASIC_BLOCK_H) $(TARGET_H) tree-ssa-operands.h \
        tree-ssa-alias.h $(INTERNAL_FN_H)
+TRANS_MEM_H = trans-mem.h
 GCOV_IO_H = gcov-io.h gcov-iov.h auto-host.h
 COVERAGE_H = coverage.h $(GCOV_IO_H)
 DEMANGLE_H = $(srcdir)/../include/demangle.h
@@ -1352,6 +1354,7 @@ OBJS = \
        timevar.o \
        toplev.o \
        tracer.o \
+       trans-mem.o \
        tree-affine.o \
        tree-call-cdce.o \
        tree-cfg.o \
@@ -2158,6 +2161,12 @@ gtype-desc.o: gtype-desc.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
        $(CFGLOOP_H) $(TARGET_H) $(IPA_PROP_H) $(LTO_STREAMER_H) \
        target-globals.h
 
+trans-mem.o : trans-mem.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
+       $(TREE_H) $(GIMPLE_H) $(TREE_FLOW_H) $(TREE_PASS_H) $(TREE_INLINE_H) \
+       $(DIAGNOSTIC_CORE_H) $(DEMANGLE_H) output.h $(TRANS_MEM_H) \
+       $(PARAMS_H) $(TARGET_H) langhooks.h \
+       tree-pretty-print.h gimple-pretty-print.h
+
 ggc-common.o: ggc-common.c $(CONFIG_H) $(SYSTEM_H) coretypes.h         \
        $(GGC_H) $(HASHTAB_H) $(DIAGNOSTIC_CORE_H) $(PARAMS_H) hosthooks.h      \
        $(HOSTHOOKS_DEF_H) $(VEC_H) $(PLUGIN_H) $(GGC_INTERNAL_H) $(TIMEVAR_H)
@@ -2684,6 +2693,7 @@ gimple.o : gimple.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TREE_H) \
 gimple-pretty-print.o : gimple-pretty-print.c $(CONFIG_H) $(SYSTEM_H) \
    $(TREE_H) $(DIAGNOSTIC_H) $(HASHTAB_H) $(TREE_FLOW_H) \
    $(TM_H) coretypes.h $(TREE_PASS_H) $(GIMPLE_H) value-prof.h \
+   $(TRANS_MEM_H) \
    tree-pretty-print.h gimple-pretty-print.h
 tree-mudflap.o : $(CONFIG_H) $(SYSTEM_H) $(TREE_H) $(TREE_INLINE_H) \
    $(GIMPLE_H) $(DIAGNOSTIC_H) $(DEMANGLE_H) $(HASHTAB_H) langhooks.h tree-mudflap.h \
@@ -3733,6 +3743,7 @@ GTFILES = $(CPP_ID_DATA_H) $(srcdir)/input.h $(srcdir)/coretypes.h \
   $(srcdir)/lto-symtab.c \
   $(srcdir)/tree-ssa-alias.h \
   $(srcdir)/ipa-prop.h \
+  $(srcdir)/trans-mem.c \
   $(srcdir)/lto-streamer.h \
   $(srcdir)/target-globals.h \
   $(srcdir)/ipa-inline.h \
index 9448c0c..0e94fd2 100644 (file)
@@ -166,7 +166,8 @@ init_attributes (void)
          gcc_assert (strcmp (attribute_tables[i][j].name,
                              attribute_tables[i][k].name));
     }
-  /* Check that no name occurs in more than one table.  */
+  /* Check that no name occurs in more than one table.  Names that
+     begin with '*' are exempt, and may be overridden.  */
   for (i = 0; i < ARRAY_SIZE (attribute_tables); i++)
     {
       size_t j, k, l;
@@ -174,8 +175,9 @@ init_attributes (void)
       for (j = i + 1; j < ARRAY_SIZE (attribute_tables); j++)
        for (k = 0; attribute_tables[i][k].name != NULL; k++)
          for (l = 0; attribute_tables[j][l].name != NULL; l++)
-           gcc_assert (strcmp (attribute_tables[i][k].name,
-                               attribute_tables[j][l].name));
+           gcc_assert (attribute_tables[i][k].name[0] == '*'
+                       || strcmp (attribute_tables[i][k].name,
+                                  attribute_tables[j][l].name));
     }
 #endif
 
@@ -207,7 +209,7 @@ register_attribute (const struct attribute_spec *attr)
   slot = htab_find_slot_with_hash (attribute_hash, &str,
                                   substring_hash (str.str, str.length),
                                   INSERT);
-  gcc_assert (!*slot);
+  gcc_assert (!*slot || attr->name[0] == '*');
   *slot = (void *) CONST_CAST (struct attribute_spec *, attr);
 }
 
@@ -484,3 +486,12 @@ decl_attributes (tree *node, tree attributes, int flags)
 
   return returned_attrs;
 }
+
+/* Subroutine of set_method_tm_attributes.  Apply TM attribute ATTR
+   to the method FNDECL.  */
+
+void
+apply_tm_attr (tree fndecl, tree attr)
+{
+  decl_attributes (&TREE_TYPE (fndecl), tree_cons (attr, NULL, NULL), 0);
+}
index d0c3d96..619794e 100644 (file)
@@ -96,6 +96,8 @@ DEF_ATTR_IDENT (ATTR_SENTINEL, "sentinel")
 DEF_ATTR_IDENT (ATTR_STRFMON, "strfmon")
 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_TREE_LIST (ATTR_NOVOPS_LIST, ATTR_NOVOPS, ATTR_NULL, ATTR_NULL)
 
@@ -227,6 +229,26 @@ DEF_FORMAT_ATTRIBUTE_NOTHROW(STRFMON,3,3_4)
 #undef DEF_FORMAT_ATTRIBUTE_NOTHROW
 #undef DEF_FORMAT_ATTRIBUTE_BOTH
 
+/* Transactional memory variants of the above.  */
+
+DEF_ATTR_TREE_LIST (ATTR_TM_NOTHROW_LIST,
+                   ATTR_TM_REGPARM, ATTR_NULL, ATTR_NOTHROW_LIST)
+DEF_ATTR_TREE_LIST (ATTR_TM_TMPURE_NOTHROW_LIST,
+                   ATTR_TM_TMPURE, ATTR_NULL, ATTR_TM_NOTHROW_LIST)
+DEF_ATTR_TREE_LIST (ATTR_TM_PURE_TMPURE_NOTHROW_LIST,
+                   ATTR_PURE, ATTR_NULL, ATTR_TM_TMPURE_NOTHROW_LIST)
+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)
+
+/* Same attributes used for BUILT_IN_MALLOC except with TM_PURE thrown in.  */
+DEF_ATTR_TREE_LIST (ATTR_TMPURE_MALLOC_NOTHROW_LIST,
+                  ATTR_TM_TMPURE, ATTR_NULL, ATTR_MALLOC_NOTHROW_LIST)
+/* Same attributes used for BUILT_IN_FREE except with TM_PURE thrown in.  */
+DEF_ATTR_TREE_LIST (ATTR_TMPURE_NOTHROW_LIST,
+                  ATTR_TM_TMPURE, ATTR_NULL, ATTR_NOTHROW_LIST)
+
 /* Construct a tree for a format_arg attribute.  */
 #define DEF_FORMAT_ARG_ATTRIBUTE(FA)                                   \
   DEF_ATTR_TREE_LIST (ATTR_FORMAT_ARG_##FA, ATTR_FORMAT_ARG,           \
index a6d0127..8edf744 100644 (file)
@@ -530,3 +530,24 @@ DEF_FUNCTION_TYPE_VAR_5 (BT_FN_INT_INT_INT_INT_INT_INT_VAR,
 DEF_POINTER_TYPE (BT_PTR_FN_VOID_VAR, BT_FN_VOID_VAR)
 DEF_FUNCTION_TYPE_3 (BT_FN_PTR_PTR_FN_VOID_VAR_PTR_SIZE,
                     BT_PTR, BT_PTR_FN_VOID_VAR, BT_PTR, BT_SIZE)
+
+
+DEF_FUNCTION_TYPE_1 (BT_FN_I1_VPTR, BT_I1, BT_VOLATILE_PTR)
+DEF_FUNCTION_TYPE_1 (BT_FN_I2_VPTR, BT_I2, BT_VOLATILE_PTR)
+DEF_FUNCTION_TYPE_1 (BT_FN_I4_VPTR, BT_I4, BT_VOLATILE_PTR)
+DEF_FUNCTION_TYPE_1 (BT_FN_I8_VPTR, BT_I8, BT_VOLATILE_PTR)
+DEF_FUNCTION_TYPE_1 (BT_FN_FLOAT_VPTR, BT_FLOAT, BT_VOLATILE_PTR)
+DEF_FUNCTION_TYPE_1 (BT_FN_DOUBLE_VPTR, BT_DOUBLE, BT_VOLATILE_PTR)
+DEF_FUNCTION_TYPE_1 (BT_FN_LDOUBLE_VPTR, BT_LONGDOUBLE, BT_VOLATILE_PTR)
+
+DEF_FUNCTION_TYPE_2 (BT_FN_VOID_VPTR_I1, BT_VOID, BT_VOLATILE_PTR, BT_I1)
+DEF_FUNCTION_TYPE_2 (BT_FN_VOID_VPTR_I2, BT_VOID, BT_VOLATILE_PTR, BT_I2)
+DEF_FUNCTION_TYPE_2 (BT_FN_VOID_VPTR_I4, BT_VOID, BT_VOLATILE_PTR, BT_I4)
+DEF_FUNCTION_TYPE_2 (BT_FN_VOID_VPTR_I8, BT_VOID, BT_VOLATILE_PTR, BT_I8)
+DEF_FUNCTION_TYPE_2 (BT_FN_VOID_VPTR_FLOAT, BT_VOID, BT_VOLATILE_PTR, BT_FLOAT)
+DEF_FUNCTION_TYPE_2 (BT_FN_VOID_VPTR_DOUBLE, BT_VOID,
+                    BT_VOLATILE_PTR, BT_DOUBLE)
+DEF_FUNCTION_TYPE_2 (BT_FN_VOID_VPTR_LDOUBLE, BT_VOID,
+                    BT_VOLATILE_PTR, BT_LONGDOUBLE)
+DEF_FUNCTION_TYPE_2 (BT_FN_VOID_VPTR_SIZE, BT_VOID,
+                    BT_VOLATILE_PTR, BT_SIZE)
index 0420b55..616fca7 100644 (file)
@@ -142,6 +142,13 @@ along with GCC; see the file COPYING3.  If not see
                false, true, true, ATTRS, false, \
               (flag_openmp || flag_tree_parallelize_loops))
 
+/* Builtin used by the implementation of GNU TM.  These
+   functions are mapped to the actual implementation of the STM library. */
+#undef DEF_TM_BUILTIN
+#define DEF_TM_BUILTIN(ENUM, NAME, TYPE, ATTRS) \
+  DEF_BUILTIN (ENUM, "__builtin_" NAME, BUILT_IN_NORMAL, TYPE, TYPE,    \
+              false, true, true, ATTRS, false, flag_tm)
+
 /* Define an attribute list for math functions that are normally
    "impure" because some of them may write into global memory for
    `errno'.  If !flag_errno_math they are instead "const".  */
@@ -624,6 +631,7 @@ DEF_GCC_BUILTIN        (BUILT_IN_APPLY_ARGS, "apply_args", BT_FN_PTR_VAR, ATTR_L
 DEF_GCC_BUILTIN        (BUILT_IN_BSWAP32, "bswap32", BT_FN_UINT32_UINT32, ATTR_CONST_NOTHROW_LEAF_LIST)
 DEF_GCC_BUILTIN        (BUILT_IN_BSWAP64, "bswap64", BT_FN_UINT64_UINT64, ATTR_CONST_NOTHROW_LEAF_LIST)
 DEF_EXT_LIB_BUILTIN    (BUILT_IN_CLEAR_CACHE, "__clear_cache", BT_FN_VOID_PTR_PTR, ATTR_NOTHROW_LEAF_LIST)
+/* [trans-mem]: Adjust BUILT_IN_TM_CALLOC if BUILT_IN_CALLOC is changed.  */
 DEF_LIB_BUILTIN        (BUILT_IN_CALLOC, "calloc", BT_FN_PTR_SIZE_SIZE, ATTR_MALLOC_NOTHROW_LEAF_LIST)
 DEF_GCC_BUILTIN        (BUILT_IN_CLASSIFY_TYPE, "classify_type", BT_FN_INT_VAR, ATTR_LEAF_LIST)
 DEF_GCC_BUILTIN        (BUILT_IN_CLZ, "clz", BT_FN_INT_UINT, ATTR_CONST_NOTHROW_LEAF_LIST)
@@ -662,6 +670,7 @@ DEF_EXT_LIB_BUILTIN    (BUILT_IN_FFSL, "ffsl", BT_FN_INT_LONG, ATTR_CONST_NOTHRO
 DEF_EXT_LIB_BUILTIN    (BUILT_IN_FFSLL, "ffsll", BT_FN_INT_LONGLONG, ATTR_CONST_NOTHROW_LEAF_LIST)
 DEF_EXT_LIB_BUILTIN        (BUILT_IN_FORK, "fork", BT_FN_PID, ATTR_NOTHROW_LIST)
 DEF_GCC_BUILTIN        (BUILT_IN_FRAME_ADDRESS, "frame_address", BT_FN_PTR_UINT, ATTR_NULL)
+/* [trans-mem]: Adjust BUILT_IN_TM_FREE if BUILT_IN_FREE is changed.  */
 DEF_LIB_BUILTIN        (BUILT_IN_FREE, "free", BT_FN_VOID_PTR, ATTR_NOTHROW_LIST)
 DEF_GCC_BUILTIN        (BUILT_IN_FROB_RETURN_ADDR, "frob_return_addr", BT_FN_PTR_PTR, ATTR_NULL)
 DEF_EXT_LIB_BUILTIN    (BUILT_IN_GETTEXT, "gettext", BT_FN_STRING_CONST_STRING, ATTR_FORMAT_ARG_1)
@@ -698,6 +707,7 @@ DEF_GCC_BUILTIN        (BUILT_IN_ISUNORDERED, "isunordered", BT_FN_INT_VAR, ATTR
 DEF_LIB_BUILTIN        (BUILT_IN_LABS, "labs", BT_FN_LONG_LONG, ATTR_CONST_NOTHROW_LEAF_LIST)
 DEF_C99_BUILTIN        (BUILT_IN_LLABS, "llabs", BT_FN_LONGLONG_LONGLONG, ATTR_CONST_NOTHROW_LEAF_LIST)
 DEF_GCC_BUILTIN        (BUILT_IN_LONGJMP, "longjmp", BT_FN_VOID_PTR_INT, ATTR_NORETURN_NOTHROW_LEAF_LIST)
+/* [trans-mem]: Adjust BUILT_IN_TM_MALLOC if BUILT_IN_MALLOC is changed.  */
 DEF_LIB_BUILTIN        (BUILT_IN_MALLOC, "malloc", BT_FN_PTR_SIZE, ATTR_MALLOC_NOTHROW_LEAF_LIST)
 DEF_GCC_BUILTIN        (BUILT_IN_NEXT_ARG, "next_arg", BT_FN_PTR_VAR, ATTR_LEAF_LIST)
 DEF_GCC_BUILTIN        (BUILT_IN_PARITY, "parity", BT_FN_INT_UINT, ATTR_CONST_NOTHROW_LEAF_LIST)
@@ -793,3 +803,6 @@ DEF_BUILTIN_STUB (BUILT_IN_EH_COPY_VALUES, "__builtin_eh_copy_values")
 
 /* OpenMP builtins.  */
 #include "omp-builtins.def"
+
+/* GTM builtins. */
+#include "gtm-builtins.def"
index 04134ec..914c916 100644 (file)
@@ -1,3 +1,19 @@
+2011-11-07  Richard Henderson  <rth@redhat.com>
+           Aldy Hernandez  <aldyh@redhat.com>
+           Torvald Riegel  <triegel@redhat.com>
+
+       Merged from transactional-memory.
+
+       * c-common.c (handle_tm_wrap_attribute,
+       handle_tm_attribute, ignore_attribute, parse_tm_stmt_attr): New.
+       (struct c_common_reswords): Added __transaction* keywords.
+       (struct c_common_attribute_table): Added transaction* and tm_regparm
+       attributes.
+       * c-common.h: Added RID_TRANSACTION*. Added TM_ATTR* and TM_STMT*
+       masks.
+       (parse_tm_stmt_attr, tm_attr_to_mask, tm_mask_to_attr,
+       find_tm_attribute): Declare.
+
 2011-11-07  Jason Merrill  <jason@redhat.com>
 
        PR c++/35688
index 0329bc7..a682331 100644 (file)
@@ -357,6 +357,8 @@ static tree handle_returns_twice_attribute (tree *, tree, tree, int, bool *);
 static tree handle_no_limit_stack_attribute (tree *, tree, tree, int,
                                             bool *);
 static tree handle_pure_attribute (tree *, tree, tree, int, bool *);
+static tree handle_tm_attribute (tree *, tree, tree, int, bool *);
+static tree handle_tm_wrap_attribute (tree *, tree, tree, int, bool *);
 static tree handle_novops_attribute (tree *, tree, tree, int, bool *);
 static tree handle_deprecated_attribute (tree *, tree, tree, int,
                                         bool *);
@@ -372,6 +374,7 @@ static tree handle_type_generic_attribute (tree *, tree, tree, int, bool *);
 static tree handle_alloc_size_attribute (tree *, tree, tree, int, bool *);
 static tree handle_target_attribute (tree *, tree, tree, int, bool *);
 static tree handle_optimize_attribute (tree *, tree, tree, int, bool *);
+static tree ignore_attribute (tree *, tree, tree, int, bool *);
 static tree handle_no_split_stack_attribute (tree *, tree, tree, int, bool *);
 static tree handle_fnspec_attribute (tree *, tree, tree, int, bool *);
 
@@ -474,6 +477,9 @@ const struct c_common_resword c_common_reswords[] =
   { "__signed",                RID_SIGNED,     0 },
   { "__signed__",      RID_SIGNED,     0 },
   { "__thread",                RID_THREAD,     0 },
+  { "__transaction_atomic", RID_TRANSACTION_ATOMIC, 0 },
+  { "__transaction_relaxed", RID_TRANSACTION_RELAXED, 0 },
+  { "__transaction_cancel", RID_TRANSACTION_CANCEL, 0 },
   { "__typeof",                RID_TYPEOF,     0 },
   { "__typeof__",      RID_TYPEOF,     0 },
   { "__underlying_type", RID_UNDERLYING_TYPE, D_CXXONLY },
@@ -666,6 +672,20 @@ const struct attribute_spec c_common_attribute_table[] =
                              handle_no_limit_stack_attribute, false },
   { "pure",                   0, 0, true,  false, false,
                              handle_pure_attribute, false },
+  { "transaction_callable",   0, 0, false, true,  false,
+                             handle_tm_attribute, false },
+  { "transaction_unsafe",     0, 0, false, true,  false,
+                             handle_tm_attribute, false },
+  { "transaction_safe",       0, 0, false, true,  false,
+                             handle_tm_attribute, false },
+  { "transaction_may_cancel_outer", 0, 0, false, true, false,
+                             handle_tm_attribute, false },
+  /* ??? These two attributes didn't make the transition from the
+     Intel language document to the multi-vendor language document.  */
+  { "transaction_pure",       0, 0, false, true,  false,
+                             handle_tm_attribute, false },
+  { "transaction_wrap",       1, 1, true,  false,  false,
+                            handle_tm_wrap_attribute, false },
   /* For internal use (marking of builtins) only.  The name contains space
      to prevent its usage in source code.  */
   { "no vops",                0, 0, true,  false, false,
@@ -707,6 +727,10 @@ const struct attribute_spec c_common_attribute_table[] =
                              handle_target_attribute, false },
   { "optimize",               1, -1, true, false, false,
                              handle_optimize_attribute, false },
+  /* For internal use only.  The leading '*' both prevents its usage in
+     source code and signals that it may be overridden by machine tables.  */
+  { "*tm regparm",            0, 0, false, true, true,
+                             ignore_attribute, false },
   { "no_split_stack",        0, 0, true,  false, false,
                              handle_no_split_stack_attribute, false },
   /* For internal use (marking of builtins and runtime functions) only.
@@ -7315,6 +7339,223 @@ handle_pure_attribute (tree *node, tree name, tree ARG_UNUSED (args),
   return NULL_TREE;
 }
 
+/* Digest an attribute list destined for a transactional memory statement.
+   ALLOWED is the set of attributes that are allowed for this statement;
+   return the attribute we parsed.  Multiple attributes are never allowed.  */
+
+int
+parse_tm_stmt_attr (tree attrs, int allowed)
+{
+  tree a_seen = NULL;
+  int m_seen = 0;
+
+  for ( ; attrs ; attrs = TREE_CHAIN (attrs))
+    {
+      tree a = TREE_PURPOSE (attrs);
+      int m = 0;
+
+      if (is_attribute_p ("outer", a))
+       m = TM_STMT_ATTR_OUTER;
+
+      if ((m & allowed) == 0)
+       {
+         warning (OPT_Wattributes, "%qE attribute directive ignored", a);
+         continue;
+       }
+
+      if (m_seen == 0)
+       {
+         a_seen = a;
+         m_seen = m;
+       }
+      else if (m_seen == m)
+       warning (OPT_Wattributes, "%qE attribute duplicated", a);
+      else
+       warning (OPT_Wattributes, "%qE attribute follows %qE", a, a_seen);
+    }
+
+  return m_seen;
+}
+
+/* Transform a TM attribute name into a maskable integer and back.
+   Note that NULL (i.e. no attribute) is mapped to UNKNOWN, corresponding
+   to how the lack of an attribute is treated.  */
+
+int
+tm_attr_to_mask (tree attr)
+{
+  if (attr == NULL)
+    return 0;
+  if (is_attribute_p ("transaction_safe", attr))
+    return TM_ATTR_SAFE;
+  if (is_attribute_p ("transaction_callable", attr))
+    return TM_ATTR_CALLABLE;
+  if (is_attribute_p ("transaction_pure", attr))
+    return TM_ATTR_PURE;
+  if (is_attribute_p ("transaction_unsafe", attr))
+    return TM_ATTR_IRREVOCABLE;
+  if (is_attribute_p ("transaction_may_cancel_outer", attr))
+    return TM_ATTR_MAY_CANCEL_OUTER;
+  return 0;
+}
+
+tree
+tm_mask_to_attr (int mask)
+{
+  const char *str;
+  switch (mask)
+    {
+    case TM_ATTR_SAFE:
+      str = "transaction_safe";
+      break;
+    case TM_ATTR_CALLABLE:
+      str = "transaction_callable";
+      break;
+    case TM_ATTR_PURE:
+      str = "transaction_pure";
+      break;
+    case TM_ATTR_IRREVOCABLE:
+      str = "transaction_unsafe";
+      break;
+    case TM_ATTR_MAY_CANCEL_OUTER:
+      str = "transaction_may_cancel_outer";
+      break;
+    default:
+      gcc_unreachable ();
+    }
+  return get_identifier (str);
+}
+
+/* Return the first TM attribute seen in LIST.  */
+
+tree
+find_tm_attribute (tree list)
+{
+  for (; list ; list = TREE_CHAIN (list))
+    {
+      tree name = TREE_PURPOSE (list);
+      if (tm_attr_to_mask (name) != 0)
+       return name;
+    }
+  return NULL_TREE;
+}
+
+/* Handle the TM attributes; arguments as in struct attribute_spec.handler.
+   Here we accept only function types, and verify that none of the other
+   function TM attributes are also applied.  */
+/* ??? We need to accept class types for C++, but not C.  This greatly
+   complicates this function, since we can no longer rely on the extra
+   processing given by function_type_required.  */
+
+static tree
+handle_tm_attribute (tree *node, tree name, tree args,
+                    int flags, bool *no_add_attrs)
+{
+  /* Only one path adds the attribute; others don't.  */
+  *no_add_attrs = true;
+
+  switch (TREE_CODE (*node))
+    {
+    case RECORD_TYPE:
+    case UNION_TYPE:
+      /* Only tm_callable and tm_safe apply to classes.  */
+      if (tm_attr_to_mask (name) & ~(TM_ATTR_SAFE | TM_ATTR_CALLABLE))
+       goto ignored;
+      /* FALLTHRU */
+
+    case FUNCTION_TYPE:
+    case METHOD_TYPE:
+      {
+       tree old_name = find_tm_attribute (TYPE_ATTRIBUTES (*node));
+       if (old_name == name)
+         ;
+       else if (old_name != NULL_TREE)
+         error ("type was previously declared %qE", old_name);
+       else
+         *no_add_attrs = false;
+      }
+      break;
+
+    case POINTER_TYPE:
+      {
+       enum tree_code subcode = TREE_CODE (TREE_TYPE (*node));
+       if (subcode == FUNCTION_TYPE || subcode == METHOD_TYPE)
+         {
+           tree fn_tmp = TREE_TYPE (*node);
+           decl_attributes (&fn_tmp, tree_cons (name, args, NULL), 0);
+           *node = build_pointer_type (fn_tmp);
+           break;
+         }
+      }
+      /* FALLTHRU */
+
+    default:
+      /* If a function is next, pass it on to be tried next.  */
+      if (flags & (int) ATTR_FLAG_FUNCTION_NEXT)
+       return tree_cons (name, args, NULL);
+
+    ignored:
+      warning (OPT_Wattributes, "%qE attribute ignored", name);
+      break;
+    }
+
+  return NULL_TREE;
+}
+
+/* Handle the TM_WRAP attribute; arguments as in
+   struct attribute_spec.handler.  */
+
+static tree
+handle_tm_wrap_attribute (tree *node, tree name, tree args,
+                         int ARG_UNUSED (flags), bool *no_add_attrs)
+{
+  tree decl = *node;
+
+  /* We don't need the attribute even on success, since we
+     record the entry in an external table.  */
+  *no_add_attrs = true;
+
+  if (TREE_CODE (decl) != FUNCTION_DECL)
+    warning (OPT_Wattributes, "%qE attribute ignored", name);
+  else
+    {
+      tree wrap_decl = TREE_VALUE (args);
+      if (TREE_CODE (wrap_decl) != IDENTIFIER_NODE
+         && TREE_CODE (wrap_decl) != VAR_DECL
+         && TREE_CODE (wrap_decl) != FUNCTION_DECL)
+       error ("%qE argument not an identifier", name);
+      else
+       {
+         if (TREE_CODE (wrap_decl) == IDENTIFIER_NODE)
+           wrap_decl = lookup_name (wrap_decl);
+         if (wrap_decl && TREE_CODE (wrap_decl) == FUNCTION_DECL)
+           {
+             if (lang_hooks.types_compatible_p (TREE_TYPE (decl),
+                                                TREE_TYPE (wrap_decl)))
+               record_tm_replacement (wrap_decl, decl);
+             else
+               error ("%qD is not compatible with %qD", wrap_decl, decl);
+           }
+         else
+           error ("transaction_wrap argument is not a function");
+       }
+    }
+
+  return NULL_TREE;
+}
+
+/* Ignore the given attribute.  Used when this attribute may be usefully
+   overridden by the target, but is not used generically.  */
+
+static tree
+ignore_attribute (tree * ARG_UNUSED (node), tree ARG_UNUSED (name),
+                 tree ARG_UNUSED (args), int ARG_UNUSED (flags),
+                 bool *no_add_attrs)
+{
+  *no_add_attrs = true;
+  return NULL_TREE;
+}
+
 /* Handle a "no vops" attribute; arguments as in
    struct attribute_spec.handler.  */
 
index bff6956..4d65dd1 100644 (file)
@@ -113,6 +113,9 @@ enum rid
      as a normal identifier.  */
   RID_CXX_COMPAT_WARN,
 
+  /* GNU transactional memory extension */
+  RID_TRANSACTION_ATOMIC, RID_TRANSACTION_RELAXED, RID_TRANSACTION_CANCEL,
+
   /* Too many ways of getting the name of a function as a string */
   RID_FUNCTION_NAME, RID_PRETTY_FUNCTION_NAME, RID_C99_FUNCTION_NAME,
 
@@ -1073,6 +1076,28 @@ c_tree_chain_next (tree t)
   return NULL;
 }
 
+/* Mask used by tm_stmt_attr.  */
+#define TM_STMT_ATTR_OUTER     2
+#define TM_STMT_ATTR_ATOMIC    4
+#define TM_STMT_ATTR_RELAXED   8
+
+extern int parse_tm_stmt_attr (tree, int);
+
+/* Mask used by tm_attr_to_mask and tm_mask_to_attr.  Note that these
+   are ordered specifically such that more restrictive attributes are
+   at lower bit positions.  This fact is known by the C++ tm attribute
+   inheritance code such that least bit extraction (mask & -mask) results
+   in the most restrictive attribute.  */
+#define TM_ATTR_SAFE                   1
+#define TM_ATTR_CALLABLE               2
+#define TM_ATTR_PURE                   4
+#define TM_ATTR_IRREVOCABLE            8
+#define TM_ATTR_MAY_CANCEL_OUTER       16
+
+extern int tm_attr_to_mask (tree);
+extern tree tm_mask_to_attr (int);
+extern tree find_tm_attribute (tree);
+
 /* A suffix-identifier value doublet that represents user-defined literals
    for C++-0x.  */
 struct GTY(()) tree_userdef_literal {
index 58bcb02..aed390f 100644 (file)
@@ -195,6 +195,9 @@ typedef struct GTY(()) c_parser {
      undesirable to bind an identifier to an Objective-C class, even
      if a class with that name exists.  */
   BOOL_BITFIELD objc_need_raw_identifier : 1;
+  /* Nonzero if we're processing a __transaction statement.  The value
+     is 1 | TM_STMT_ATTR_*.  */
+  unsigned int in_transaction : 4;
   /* True if we are in a context where the Objective-C "Property attribute"
      keywords are valid.  */
   BOOL_BITFIELD objc_property_attr_context : 1;
@@ -1171,6 +1174,9 @@ static struct c_expr c_parser_postfix_expression_after_paren_type (c_parser *,
 static struct c_expr c_parser_postfix_expression_after_primary (c_parser *,
                                                                location_t loc,
                                                                struct c_expr);
+static tree c_parser_transaction (c_parser *, enum rid);
+static struct c_expr c_parser_transaction_expression (c_parser *, enum rid);
+static tree c_parser_transaction_cancel (c_parser *);
 static struct c_expr c_parser_expression (c_parser *);
 static struct c_expr c_parser_expression_conv (c_parser *);
 static VEC(tree,gc) *c_parser_expr_list (c_parser *, bool, bool,
@@ -3413,6 +3419,66 @@ c_parser_simple_asm_expr (c_parser *parser)
   return str;
 }
 
+static tree
+c_parser_attribute_any_word (c_parser *parser)
+{
+  tree attr_name = NULL_TREE;
+
+  if (c_parser_next_token_is (parser, CPP_KEYWORD))
+    {
+      /* ??? See comment above about what keywords are accepted here.  */
+      bool ok;
+      switch (c_parser_peek_token (parser)->keyword)
+       {
+       case RID_STATIC:
+       case RID_UNSIGNED:
+       case RID_LONG:
+       case RID_INT128:
+       case RID_CONST:
+       case RID_EXTERN:
+       case RID_REGISTER:
+       case RID_TYPEDEF:
+       case RID_SHORT:
+       case RID_INLINE:
+       case RID_NORETURN:
+       case RID_VOLATILE:
+       case RID_SIGNED:
+       case RID_AUTO:
+       case RID_RESTRICT:
+       case RID_COMPLEX:
+       case RID_THREAD:
+       case RID_INT:
+       case RID_CHAR:
+       case RID_FLOAT:
+       case RID_DOUBLE:
+       case RID_VOID:
+       case RID_DFLOAT32:
+       case RID_DFLOAT64:
+       case RID_DFLOAT128:
+       case RID_BOOL:
+       case RID_FRACT:
+       case RID_ACCUM:
+       case RID_SAT:
+       case RID_TRANSACTION_ATOMIC:
+       case RID_TRANSACTION_CANCEL:
+         ok = true;
+         break;
+       default:
+         ok = false;
+         break;
+       }
+      if (!ok)
+       return NULL_TREE;
+
+      /* Accept __attribute__((__const)) as __attribute__((const)) etc.  */
+      attr_name = ridpointers[(int) c_parser_peek_token (parser)->keyword];
+    }
+  else if (c_parser_next_token_is (parser, CPP_NAME))
+    attr_name = c_parser_peek_token (parser)->value;
+
+  return attr_name;
+}
+
 /* Parse (possibly empty) attributes.  This is a GNU extension.
 
    attributes:
@@ -3473,57 +3539,10 @@ c_parser_attributes (c_parser *parser)
              c_parser_consume_token (parser);
              continue;
            }
-         if (c_parser_next_token_is (parser, CPP_KEYWORD))
-           {
-             /* ??? See comment above about what keywords are
-                accepted here.  */
-             bool ok;
-             switch (c_parser_peek_token (parser)->keyword)
-               {
-               case RID_STATIC:
-               case RID_UNSIGNED:
-               case RID_LONG:
-               case RID_INT128:
-               case RID_CONST:
-               case RID_EXTERN:
-               case RID_REGISTER:
-               case RID_TYPEDEF:
-               case RID_SHORT:
-               case RID_INLINE:
-               case RID_NORETURN:
-               case RID_VOLATILE:
-               case RID_SIGNED:
-               case RID_AUTO:
-               case RID_RESTRICT:
-               case RID_COMPLEX:
-               case RID_THREAD:
-               case RID_INT:
-               case RID_CHAR:
-               case RID_FLOAT:
-               case RID_DOUBLE:
-               case RID_VOID:
-               case RID_DFLOAT32:
-               case RID_DFLOAT64:
-               case RID_DFLOAT128:
-               case RID_BOOL:
-               case RID_FRACT:
-               case RID_ACCUM:
-               case RID_SAT:
-                 ok = true;
-                 break;
-               default:
-                 ok = false;
-                 break;
-               }
-             if (!ok)
-               break;
-             /* Accept __attribute__((__const)) as __attribute__((const))
-                etc.  */
-             attr_name
-               = ridpointers[(int) c_parser_peek_token (parser)->keyword];
-           }
-         else
-           attr_name = c_parser_peek_token (parser)->value;
+
+         attr_name = c_parser_attribute_any_word (parser);
+         if (attr_name == NULL)
+           break;
          c_parser_consume_token (parser);
          if (c_parser_next_token_is_not (parser, CPP_OPEN_PAREN))
            {
@@ -4394,7 +4413,14 @@ c_parser_label (c_parser *parser)
      atomic-directive expression-statement
 
    ordered-construct:
-     ordered-directive structured-block  */
+     ordered-directive structured-block
+
+   Transactional Memory:
+
+   statement:
+     transaction-statement
+     transaction-cancel-statement
+*/
 
 static void
 c_parser_statement (c_parser *parser)
@@ -4485,6 +4511,14 @@ c_parser_statement_after_labels (c_parser *parser)
        case RID_ASM:
          stmt = c_parser_asm_statement (parser);
          break;
+       case RID_TRANSACTION_ATOMIC:
+       case RID_TRANSACTION_RELAXED:
+         stmt = c_parser_transaction (parser,
+             c_parser_peek_token (parser)->keyword);
+         break;
+       case RID_TRANSACTION_CANCEL:
+         stmt = c_parser_transaction_cancel (parser);
+         goto expect_semicolon;
        case RID_AT_THROW:
          gcc_assert (c_dialect_objc ());
          c_parser_consume_token (parser);
@@ -5812,6 +5846,11 @@ c_parser_cast_expression (c_parser *parser, struct c_expr *after)
    unary-operator: one of
      __extension__ __real__ __imag__
 
+   Transactional Memory:
+
+   unary-expression:
+     transaction-expression
+
    In addition, the GNU syntax treats ++ and -- as unary operators, so
    they may be applied to cast expressions with errors for non-lvalues
    given later.  */
@@ -5919,6 +5958,10 @@ c_parser_unary_expression (c_parser *parser)
          op = c_parser_cast_expression (parser, NULL);
          op = default_function_array_conversion (exp_loc, op);
          return parser_build_unary_op (op_loc, IMAGPART_EXPR, op);
+       case RID_TRANSACTION_ATOMIC:
+       case RID_TRANSACTION_RELAXED:
+         return c_parser_transaction_expression (parser,
+             c_parser_peek_token (parser)->keyword);
        default:
          return c_parser_postfix_expression (parser);
        }
@@ -10535,6 +10578,212 @@ c_parser_omp_threadprivate (c_parser *parser)
   c_parser_skip_to_pragma_eol (parser);
 }
 
+/* Parse a transaction attribute (GCC Extension).
+
+   transaction-attribute:
+     attributes
+     [ [ any-word ] ]
+
+   The transactional memory language description is written for C++,
+   and uses the C++0x attribute syntax.  For compatibility, allow the
+   bracket style for transactions in C as well.  */
+
+static tree
+c_parser_transaction_attributes (c_parser *parser)
+{
+  tree attr_name, attr = NULL;
+
+  if (c_parser_next_token_is_keyword (parser, RID_ATTRIBUTE))
+    return c_parser_attributes (parser);
+
+  if (!c_parser_next_token_is (parser, CPP_OPEN_SQUARE))
+    return NULL_TREE;
+  c_parser_consume_token (parser);
+  if (!c_parser_require (parser, CPP_OPEN_SQUARE, "expected %<[%>"))
+    goto error1;
+
+  attr_name = c_parser_attribute_any_word (parser);
+  if (attr_name)
+    {
+      c_parser_consume_token (parser);
+      attr = build_tree_list (attr_name, NULL_TREE);
+    }
+  else
+    c_parser_error (parser, "expected identifier");
+
+  c_parser_skip_until_found (parser, CPP_CLOSE_SQUARE, "expected %<]%>");
+ error1:
+  c_parser_skip_until_found (parser, CPP_CLOSE_SQUARE, "expected %<]%>");
+  return attr;
+}
+
+/* Parse a __transaction_atomic or __transaction_relaxed statement
+   (GCC Extension).
+
+   transaction-statement:
+     __transaction_atomic transaction-attribute[opt] compound-statement
+     __transaction_relaxed compound-statement
+
+   Note that the only valid attribute is: "outer".
+*/
+
+static tree
+c_parser_transaction (c_parser *parser, enum rid keyword)
+{
+  unsigned int old_in = parser->in_transaction;
+  unsigned int this_in = 1, new_in;
+  location_t loc = c_parser_peek_token (parser)->location;
+  tree stmt, attrs;
+
+  gcc_assert ((keyword == RID_TRANSACTION_ATOMIC
+      || keyword == RID_TRANSACTION_RELAXED)
+      && c_parser_next_token_is_keyword (parser, keyword));
+  c_parser_consume_token (parser);
+
+  if (keyword == RID_TRANSACTION_RELAXED)
+    this_in |= TM_STMT_ATTR_RELAXED;
+  else
+    {
+      attrs = c_parser_transaction_attributes (parser);
+      if (attrs)
+       this_in |= parse_tm_stmt_attr (attrs, TM_STMT_ATTR_OUTER);
+    }
+
+  /* Keep track if we're in the lexical scope of an outer transaction.  */
+  new_in = this_in | (old_in & TM_STMT_ATTR_OUTER);
+
+  parser->in_transaction = new_in;
+  stmt = c_parser_compound_statement (parser);
+  parser->in_transaction = old_in;
+
+  if (flag_tm)
+    stmt = c_finish_transaction (loc, stmt, this_in);
+  else
+    error_at (loc, (keyword == RID_TRANSACTION_ATOMIC ?
+       "%<__transaction_atomic%> without transactional memory support enabled"
+       : "%<__transaction_relaxed %> "
+       "without transactional memory support enabled"));
+
+  return stmt;
+}
+
+/* Parse a __transaction_atomic or __transaction_relaxed expression
+   (GCC Extension).
+
+   transaction-expression:
+     __transaction_atomic ( expression )
+     __transaction_relaxed ( expression )
+*/
+
+static struct c_expr
+c_parser_transaction_expression (c_parser *parser, enum rid keyword)
+{
+  struct c_expr ret;
+  unsigned int old_in = parser->in_transaction;
+  unsigned int this_in = 1;
+  location_t loc = c_parser_peek_token (parser)->location;
+  tree attrs;
+
+  gcc_assert ((keyword == RID_TRANSACTION_ATOMIC
+      || keyword == RID_TRANSACTION_RELAXED)
+      && c_parser_next_token_is_keyword (parser, keyword));
+  c_parser_consume_token (parser);
+
+  if (keyword == RID_TRANSACTION_RELAXED)
+    this_in |= TM_STMT_ATTR_RELAXED;
+  else
+    {
+      attrs = c_parser_transaction_attributes (parser);
+      if (attrs)
+       this_in |= parse_tm_stmt_attr (attrs, 0);
+    }
+
+  parser->in_transaction = this_in;
+  if (c_parser_next_token_is (parser, CPP_OPEN_PAREN))
+    {
+      tree expr = c_parser_expression (parser).value;
+      ret.original_type = TREE_TYPE (expr);
+      ret.value = build1 (TRANSACTION_EXPR, ret.original_type, expr);
+      if (this_in & TM_STMT_ATTR_RELAXED)
+       TRANSACTION_EXPR_RELAXED (ret.value) = 1;
+      SET_EXPR_LOCATION (ret.value, loc);
+      ret.original_code = TRANSACTION_EXPR;
+    }
+  else
+    {
+      c_parser_error (parser, "expected %<(%>");
+      ret.value = error_mark_node;
+      ret.original_code = ERROR_MARK;
+      ret.original_type = NULL;
+    }
+  parser->in_transaction = old_in;
+
+  if (!flag_tm)
+    error_at (loc, (keyword == RID_TRANSACTION_ATOMIC ?
+       "%<__transaction_atomic%> without transactional memory support enabled"
+       : "%<__transaction_relaxed %> "
+       "without transactional memory support enabled"));
+
+  return ret;
+}
+
+/* Parse a __transaction_cancel statement (GCC Extension).
+
+   transaction-cancel-statement:
+     __transaction_cancel transaction-attribute[opt] ;
+
+   Note that the only valid attribute is "outer".
+*/
+
+static tree
+c_parser_transaction_cancel(c_parser *parser)
+{
+  location_t loc = c_parser_peek_token (parser)->location;
+  tree attrs;
+  bool is_outer = false;
+
+  gcc_assert (c_parser_next_token_is_keyword (parser, RID_TRANSACTION_CANCEL));
+  c_parser_consume_token (parser);
+
+  attrs = c_parser_transaction_attributes (parser);
+  if (attrs)
+    is_outer = (parse_tm_stmt_attr (attrs, TM_STMT_ATTR_OUTER) != 0);
+
+  if (!flag_tm)
+    {
+      error_at (loc, "%<__transaction_cancel%> without "
+               "transactional memory support enabled");
+      goto ret_error;
+    }
+  else if (parser->in_transaction & TM_STMT_ATTR_RELAXED)
+    {
+      error_at (loc, "%<__transaction_cancel%> within a "
+               "%<__transaction_relaxed%>");
+      goto ret_error;
+    }
+  else if (is_outer)
+    {
+      if ((parser->in_transaction & TM_STMT_ATTR_OUTER) == 0
+         && !is_tm_may_cancel_outer (current_function_decl))
+       {
+         error_at (loc, "outer %<__transaction_cancel%> not "
+                   "within outer %<__transaction_atomic%>");
+         error_at (loc, "  or a %<transaction_may_cancel_outer%> function");
+         goto ret_error;
+       }
+    }
+  else if (parser->in_transaction == 0)
+    {
+      error_at (loc, "%<__transaction_cancel%> not within "
+               "%<__transaction_atomic%>");
+      goto ret_error;
+    }
+
+  return add_stmt (build_tm_abort_call (loc, is_outer));
+
+ ret_error:
+  return build1 (NOP_EXPR, void_type_node, error_mark_node);
+}
 \f
 /* Parse a single source file.  */
 
index 6801db2..51c660c 100644 (file)
@@ -603,6 +603,7 @@ extern tree c_begin_omp_task (void);
 extern tree c_finish_omp_task (location_t, tree, tree);
 extern tree c_finish_omp_clauses (tree);
 extern tree c_build_va_arg (location_t, tree, tree);
+extern tree c_finish_transaction (location_t, tree, int);
 extern tree c_build_vec_perm_expr (location_t, tree, tree, tree);
 
 /* Set to 0 at beginning of a function definition, set to 1 if
index 392ac65..4a134b0 100644 (file)
@@ -2716,6 +2716,9 @@ build_function_call_vec (location_t loc, tree function, VEC(tree,gc) *params,
        return tem;
 
       name = DECL_NAME (function);
+
+      if (flag_tm)
+       tm_malloc_replacement (function);
       fundecl = function;
       /* Atomic functions have type checking/casting already done.  They are 
         often rewritten and don't match the original parameter list.  */
@@ -10922,6 +10925,19 @@ c_finish_omp_clauses (tree clauses)
   return clauses;
 }
 
+/* Create a transaction node.  */
+
+tree
+c_finish_transaction (location_t loc, tree block, int flags)
+{
+  tree stmt = build_stmt (loc, TRANSACTION_EXPR, block);
+  if (flags & TM_STMT_ATTR_OUTER)
+    TRANSACTION_EXPR_OUTER (stmt) = 1;
+  if (flags & TM_STMT_ATTR_RELAXED)
+    TRANSACTION_EXPR_RELAXED (stmt) = 1;
+  return add_stmt (stmt);
+}
+
 /* Make a variant type in the proper way for C/C++, propagating qualifiers
    down to the element type of an array.  */
 
index eeb6b2e..382de7f 100644 (file)
@@ -611,6 +611,69 @@ alloca_call_p (const_tree exp)
   return false;
 }
 
+/* Return TRUE if FNDECL is either a TM builtin or a TM cloned
+   function.  Return FALSE otherwise.  */
+
+static bool
+is_tm_builtin (const_tree fndecl)
+{
+  if (fndecl == NULL)
+    return false;
+
+  if (decl_is_tm_clone (fndecl))
+    return true;
+
+  if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL)
+    {
+      switch (DECL_FUNCTION_CODE (fndecl))
+       {
+       case BUILT_IN_TM_COMMIT:
+       case BUILT_IN_TM_COMMIT_EH:
+       case BUILT_IN_TM_ABORT:
+       case BUILT_IN_TM_IRREVOCABLE:
+       case BUILT_IN_TM_GETTMCLONE_IRR:
+       case BUILT_IN_TM_MEMCPY:
+       case BUILT_IN_TM_MEMMOVE:
+       case BUILT_IN_TM_MEMSET:
+       CASE_BUILT_IN_TM_STORE (1):
+       CASE_BUILT_IN_TM_STORE (2):
+       CASE_BUILT_IN_TM_STORE (4):
+       CASE_BUILT_IN_TM_STORE (8):
+       CASE_BUILT_IN_TM_STORE (FLOAT):
+       CASE_BUILT_IN_TM_STORE (DOUBLE):
+       CASE_BUILT_IN_TM_STORE (LDOUBLE):
+       CASE_BUILT_IN_TM_STORE (M64):
+       CASE_BUILT_IN_TM_STORE (M128):
+       CASE_BUILT_IN_TM_STORE (M256):
+       CASE_BUILT_IN_TM_LOAD (1):
+       CASE_BUILT_IN_TM_LOAD (2):
+       CASE_BUILT_IN_TM_LOAD (4):
+       CASE_BUILT_IN_TM_LOAD (8):
+       CASE_BUILT_IN_TM_LOAD (FLOAT):
+       CASE_BUILT_IN_TM_LOAD (DOUBLE):
+       CASE_BUILT_IN_TM_LOAD (LDOUBLE):
+       CASE_BUILT_IN_TM_LOAD (M64):
+       CASE_BUILT_IN_TM_LOAD (M128):
+       CASE_BUILT_IN_TM_LOAD (M256):
+       case BUILT_IN_TM_LOG:
+       case BUILT_IN_TM_LOG_1:
+       case BUILT_IN_TM_LOG_2:
+       case BUILT_IN_TM_LOG_4:
+       case BUILT_IN_TM_LOG_8:
+       case BUILT_IN_TM_LOG_FLOAT:
+       case BUILT_IN_TM_LOG_DOUBLE:
+       case BUILT_IN_TM_LOG_LDOUBLE:
+       case BUILT_IN_TM_LOG_M64:
+       case BUILT_IN_TM_LOG_M128:
+       case BUILT_IN_TM_LOG_M256:
+         return true;
+       default:
+         break;
+       }
+    }
+  return false;
+}
+
 /* Detect flags (function attributes) from the function decl or type node.  */
 
 int
@@ -644,10 +707,28 @@ flags_from_decl_or_type (const_tree exp)
       if (TREE_NOTHROW (exp))
        flags |= ECF_NOTHROW;
 
+      if (flag_tm)
+       {
+         if (is_tm_builtin (exp))
+           flags |= ECF_TM_BUILTIN;
+         else if ((flags & ECF_CONST) != 0
+                  || lookup_attribute ("transaction_pure",
+                                       TYPE_ATTRIBUTES (TREE_TYPE (exp))))
+           flags |= ECF_TM_PURE;
+       }
+
       flags = special_function_p (exp, flags);
     }
-  else if (TYPE_P (exp) && TYPE_READONLY (exp))
-    flags |= ECF_CONST;
+  else if (TYPE_P (exp))
+    {
+      if (TYPE_READONLY (exp))
+       flags |= ECF_CONST;
+
+      if (flag_tm
+         && ((flags & ECF_CONST) != 0
+             || lookup_attribute ("transaction_pure", TYPE_ATTRIBUTES (exp))))
+       flags |= ECF_TM_PURE;
+    }
 
   if (TREE_THIS_VOLATILE (exp))
     {
index 6f0d69e..692fea8 100644 (file)
@@ -338,18 +338,30 @@ make_edges (basic_block min, basic_block max, int update_p)
          /* Add any appropriate EH edges.  */
          rtl_make_eh_edge (edge_cache, bb, insn);
 
-         if (code == CALL_INSN && nonlocal_goto_handler_labels)
+         if (code == CALL_INSN)
            {
-             /* ??? This could be made smarter: in some cases it's possible
-                to tell that certain calls will not do a nonlocal goto.
-                For example, if the nested functions that do the nonlocal
-                gotos do not have their addresses taken, then only calls to
-                those functions or to other nested functions that use them
-                could possibly do nonlocal gotos.  */
              if (can_nonlocal_goto (insn))
-               for (x = nonlocal_goto_handler_labels; x; x = XEXP (x, 1))
-                 make_label_edge (edge_cache, bb, XEXP (x, 0),
-                                  EDGE_ABNORMAL | EDGE_ABNORMAL_CALL);
+               {
+                 /* ??? This could be made smarter: in some cases it's
+                    possible to tell that certain calls will not do a
+                    nonlocal goto.  For example, if the nested functions
+                    that do the nonlocal gotos do not have their addresses
+                    taken, then only calls to those functions or to other
+                    nested functions that use them could possibly do
+                    nonlocal gotos.  */
+                 for (x = nonlocal_goto_handler_labels; x; x = XEXP (x, 1))
+                   make_label_edge (edge_cache, bb, XEXP (x, 0),
+                                    EDGE_ABNORMAL | EDGE_ABNORMAL_CALL);
+               }
+
+             if (flag_tm)
+               {
+                 rtx note;
+                 for (note = REG_NOTES (insn); note; note = XEXP (note, 1))
+                   if (REG_NOTE_KIND (note) == REG_TM)
+                     make_label_edge (edge_cache, bb, XEXP (note, 0),
+                                      EDGE_ABNORMAL | EDGE_ABNORMAL_CALL);
+               }
            }
        }
 
index 6fb9ee0..3d73333 100644 (file)
@@ -1802,6 +1802,38 @@ expand_gimple_cond (basic_block bb, gimple stmt)
   return new_bb;
 }
 
+/* Mark all calls that can have a transaction restart.  */
+
+static void
+mark_transaction_restart_calls (gimple stmt)
+{
+  struct tm_restart_node dummy;
+  void **slot;
+
+  if (!cfun->gimple_df->tm_restart)
+    return;
+
+  dummy.stmt = stmt;
+  slot = htab_find_slot (cfun->gimple_df->tm_restart, &dummy, NO_INSERT);
+  if (slot)
+    {
+      struct tm_restart_node *n = (struct tm_restart_node *) *slot;
+      tree list = n->label_or_list;
+      rtx insn;
+
+      for (insn = next_real_insn (get_last_insn ());
+          !CALL_P (insn);
+          insn = next_real_insn (insn))
+       continue;
+
+      if (TREE_CODE (list) == LABEL_DECL)
+       add_reg_note (insn, REG_TM, label_rtx (list));
+      else
+       for (; list ; list = TREE_CHAIN (list))
+         add_reg_note (insn, REG_TM, label_rtx (TREE_VALUE (list)));
+    }
+}
+
 /* A subroutine of expand_gimple_stmt_1, expanding one GIMPLE_CALL
    statement STMT.  */
 
@@ -1888,6 +1920,8 @@ expand_call_stmt (gimple stmt)
     expand_assignment (lhs, exp, false);
   else
     expand_expr_real_1 (exp, const0_rtx, VOIDmode, EXPAND_NORMAL, NULL);
+
+  mark_transaction_restart_calls (stmt);
 }
 
 /* A subroutine of expand_gimple_stmt, expanding one gimple statement
@@ -4455,6 +4489,14 @@ gimple_expand_cfg (void)
   /* After expanding, the return labels are no longer needed. */
   return_label = NULL;
   naked_return_label = NULL;
+
+  /* After expanding, the tm_restart map is no longer needed.  */
+  if (cfun->gimple_df->tm_restart)
+    {
+      htab_delete (cfun->gimple_df->tm_restart);
+      cfun->gimple_df->tm_restart = NULL;
+    }
+
   /* Tag the blocks with a depth number so that change_scope can find
      the common parent easily.  */
   set_block_levels (DECL_INITIAL (cfun->decl), 0);
index f06dbc8..6e9f70e 100644 (file)
@@ -2246,6 +2246,8 @@ purge_dead_edges (basic_block bb)
            ;
          else if ((e->flags & EDGE_EH) && can_throw_internal (insn))
            ;
+         else if (flag_tm && find_reg_note (insn, REG_TM, NULL))
+           ;
          else
            remove = true;
        }
index f056d3d..2d226d4 100644 (file)
@@ -1840,6 +1840,8 @@ dump_cgraph_node (FILE *f, struct cgraph_node *node)
     fprintf (f, " only_called_at_exit");
   else if (node->alias)
     fprintf (f, " alias");
+  if (node->tm_clone)
+    fprintf (f, " tm_clone");
 
   fprintf (f, "\n");
 
index 294fb77..9e98ce9 100644 (file)
@@ -98,6 +98,9 @@ struct GTY(()) cgraph_local_info {
   /* True when the function has been originally extern inline, but it is
      redefined now.  */
   unsigned redefined_extern_inline : 1;
+
+  /* True if the function may enter serial irrevocable mode.  */
+  unsigned tm_may_enter_irr : 1;
 };
 
 /* Information about the function that needs to be computed globally
@@ -245,6 +248,11 @@ struct GTY((chain_next ("%h.next"), chain_prev ("%h.previous"))) cgraph_node {
   unsigned only_called_at_startup : 1;
   /* True when function can only be called at startup (from static dtor).  */
   unsigned only_called_at_exit : 1;
+  /* True when function is the transactional clone of a function which
+     is called only from inside transactions.  */
+  /* ?? We should be able to remove this.  We have enough bits in
+     cgraph to calculate it.  */
+  unsigned tm_clone : 1;
 };
 
 typedef struct cgraph_node *cgraph_node_ptr;
@@ -565,6 +573,8 @@ void verify_cgraph_node (struct cgraph_node *);
 void cgraph_build_static_cdtor (char which, tree body, int priority);
 void cgraph_reset_static_var_maps (void);
 void init_cgraph (void);
+struct cgraph_node * cgraph_copy_node_for_versioning (struct cgraph_node *,
+               tree, VEC(cgraph_edge_p,heap)*, bitmap);
 struct cgraph_node *cgraph_function_versioning (struct cgraph_node *,
                                                VEC(cgraph_edge_p,heap)*,
                                                VEC(ipa_replace_map_p,gc)*,
@@ -1082,4 +1092,14 @@ cgraph_edge_recursive_p (struct cgraph_edge *e)
   else
     return e->caller->decl == callee->decl;
 }
+
+/* Return true if the TM_CLONE bit is set for a given FNDECL.  */
+static inline bool
+decl_is_tm_clone (const_tree fndecl)
+{
+  struct cgraph_node *n = cgraph_get_node (fndecl);
+  if (n)
+    return n->tm_clone;
+  return false;
+}
 #endif  /* GCC_CGRAPH_H  */
index 83c47ab..e401b8f 100644 (file)
@@ -2272,7 +2272,7 @@ update_call_expr (struct cgraph_node *new_version)
    was copied to prevent duplications of calls that are dead
    in the clone.  */
 
-static struct cgraph_node *
+struct cgraph_node *
 cgraph_copy_node_for_versioning (struct cgraph_node *old_version,
                                 tree new_decl,
                                 VEC(cgraph_edge_p,heap) *redirect_callers,
@@ -2286,7 +2286,7 @@ cgraph_copy_node_for_versioning (struct cgraph_node *old_version,
 
    new_version = cgraph_create_node (new_decl);
 
-   new_version->analyzed = true;
+   new_version->analyzed = old_version->analyzed;
    new_version->local = old_version->local;
    new_version->local.externally_visible = false;
    new_version->local.local = true;
index 2941114..ad9aa38 100644 (file)
@@ -13286,6 +13286,7 @@ distribute_notes (rtx notes, rtx from_insn, rtx i3, rtx i2, rtx elim_i2,
 
        case REG_NORETURN:
        case REG_SETJMP:
+       case REG_TM:
          /* These notes must remain with the call.  It should not be
             possible for both I2 and I3 to be a call.  */
          if (CALL_P (i3))
index 1871054..4eb5b30 100644 (file)
@@ -1194,6 +1194,10 @@ floop-block
 Common Report Var(flag_loop_block) Optimization
 Enable Loop Blocking transformation
 
+fgnu-tm
+Common Report Var(flag_tm)
+Enable support for GNU transactional memory
+
 floop-flatten
 Common Report Var(flag_loop_flatten) Optimization
 Enable Loop Flattening transformation
index 5f64b08..5dcb68c 100644 (file)
@@ -114,6 +114,7 @@ DEF_POINTER_TYPE (PINT, INT)
 DEF_POINTER_TYPE (PULONGLONG, ULONGLONG)
 DEF_POINTER_TYPE (PUNSIGNED, UNSIGNED)
 
+DEF_POINTER_TYPE (PV2SI, V2SI)
 DEF_POINTER_TYPE (PV2DF, V2DF)
 DEF_POINTER_TYPE (PV2DI, V2DI)
 DEF_POINTER_TYPE (PV2SF, V2SF)
@@ -124,6 +125,7 @@ DEF_POINTER_TYPE (PV8SF, V8SF)
 DEF_POINTER_TYPE (PV4SI, V4SI)
 DEF_POINTER_TYPE (PV8SI, V8SI)
 
+DEF_POINTER_TYPE (PCV2SI, V2SI, CONST)
 DEF_POINTER_TYPE (PCV2DF, V2DF, CONST)
 DEF_POINTER_TYPE (PCV2SF, V2SF, CONST)
 DEF_POINTER_TYPE (PCV4DF, V4DF, CONST)
@@ -175,6 +177,7 @@ DEF_FUNCTION_TYPE (V2SF, V2SI)
 DEF_FUNCTION_TYPE (V2SI, V2DF)
 DEF_FUNCTION_TYPE (V2SI, V2SF)
 DEF_FUNCTION_TYPE (V2SI, V2SI)
+DEF_FUNCTION_TYPE (V2SI, PCV2SI)
 DEF_FUNCTION_TYPE (V2SI, V4SF)
 DEF_FUNCTION_TYPE (V32QI, PCCHAR)
 DEF_FUNCTION_TYPE (V4DF, PCDOUBLE)
@@ -188,6 +191,7 @@ DEF_FUNCTION_TYPE (V4SF, PCFLOAT)
 DEF_FUNCTION_TYPE (V4SF, V2DF)
 DEF_FUNCTION_TYPE (V4SF, V4DF)
 DEF_FUNCTION_TYPE (V4SF, V4SF)
+DEF_FUNCTION_TYPE (V4SF, PCV4SF)
 DEF_FUNCTION_TYPE (V4SF, V4SI)
 DEF_FUNCTION_TYPE (V4SF, V8SF)
 DEF_FUNCTION_TYPE (V4SF, V8HI)
@@ -203,6 +207,7 @@ DEF_FUNCTION_TYPE (V8HI, V8HI)
 DEF_FUNCTION_TYPE (V8QI, V8QI)
 DEF_FUNCTION_TYPE (V8SF, PCFLOAT)
 DEF_FUNCTION_TYPE (V8SF, PCV4SF)
+DEF_FUNCTION_TYPE (V8SF, PCV8SF)
 DEF_FUNCTION_TYPE (V8SF, V4SF)
 DEF_FUNCTION_TYPE (V8SF, V8SF)
 DEF_FUNCTION_TYPE (V8SF, V8SI)
@@ -353,9 +358,12 @@ DEF_FUNCTION_TYPE (VOID, PFLOAT, V4SF)
 DEF_FUNCTION_TYPE (VOID, PFLOAT, V8SF)
 DEF_FUNCTION_TYPE (VOID, PINT, INT)
 DEF_FUNCTION_TYPE (VOID, PULONGLONG, ULONGLONG)
+DEF_FUNCTION_TYPE (VOID, PV2SI, V2SI)
 DEF_FUNCTION_TYPE (VOID, PV2DI, V2DI)
 DEF_FUNCTION_TYPE (VOID, PV2SF, V4SF)
 DEF_FUNCTION_TYPE (VOID, PV4DI, V4DI)
+DEF_FUNCTION_TYPE (VOID, PV4SF, V4SF)
+DEF_FUNCTION_TYPE (VOID, PV8SF, V8SF)
 DEF_FUNCTION_TYPE (VOID, UNSIGNED, UNSIGNED)
 
 DEF_FUNCTION_TYPE (INT, V16QI, V16QI, INT)
index bce100a..799e12b 100644 (file)
@@ -5028,6 +5028,40 @@ ix86_handle_cconv_attribute (tree *node, tree name,
   return NULL_TREE;
 }
 
+/* The transactional memory builtins are implicitly regparm or fastcall
+   depending on the ABI.  Override the generic do-nothing attribute that
+   these builtins were declared with, and replace it with one of the two
+   attributes that we expect elsewhere.  */
+
+static tree
+ix86_handle_tm_regparm_attribute (tree *node, tree name ATTRIBUTE_UNUSED,
+                                 tree args ATTRIBUTE_UNUSED,
+                                 int flags ATTRIBUTE_UNUSED,
+                                 bool *no_add_attrs)
+{
+  tree alt;
+
+  /* In no case do we want to add the placeholder attribute.  */
+  *no_add_attrs = true;
+
+  /* The 64-bit ABI is unchanged for transactional memory.  */
+  if (TARGET_64BIT)
+    return NULL_TREE;
+
+  /* ??? Is there a better way to validate 32-bit windows?  We have
+     cfun->machine->call_abi, but that seems to be set only for 64-bit.  */
+  if (CHECK_STACK_LIMIT > 0)
+    alt = tree_cons (get_identifier ("fastcall"), NULL, NULL);
+  else
+    {
+      alt = tree_cons (NULL, build_int_cst (NULL, 2), NULL);
+      alt = tree_cons (get_identifier ("regparm"), alt, NULL);
+    }
+  decl_attributes (node, alt, flags);
+
+  return NULL_TREE;
+}
+
 /* This function determines from TYPE the calling-convention.  */
 
 unsigned int
@@ -26790,6 +26824,154 @@ static const struct builtin_description bdesc_multi_arg[] =
   { OPTION_MASK_ISA_XOP, CODE_FOR_xop_vpermil2v8sf3,     "__builtin_ia32_vpermil2ps256", IX86_BUILTIN_VPERMIL2PS256, UNKNOWN, (int)MULTI_ARG_4_SF2_SI_I1 },
 
 };
+\f
+/* TM vector builtins.  */
+
+/* Reuse the existing x86-specific `struct builtin_description' cause
+   we're lazy.  Add casts to make them fit.  */
+static const struct builtin_description bdesc_tm[] =
+{
+  { OPTION_MASK_ISA_MMX, CODE_FOR_nothing, "__builtin__ITM_WM64", (enum ix86_builtins) BUILT_IN_TM_STORE_M64, UNKNOWN, VOID_FTYPE_PV2SI_V2SI },
+  { OPTION_MASK_ISA_MMX, CODE_FOR_nothing, "__builtin__ITM_WaRM64", (enum ix86_builtins) BUILT_IN_TM_STORE_WAR_M64, UNKNOWN, VOID_FTYPE_PV2SI_V2SI },
+  { OPTION_MASK_ISA_MMX, CODE_FOR_nothing, "__builtin__ITM_WaWM64", (enum ix86_builtins) BUILT_IN_TM_STORE_WAW_M64, UNKNOWN, VOID_FTYPE_PV2SI_V2SI },
+  { OPTION_MASK_ISA_MMX, CODE_FOR_nothing, "__builtin__ITM_RM64", (enum ix86_builtins) BUILT_IN_TM_LOAD_M64, UNKNOWN, V2SI_FTYPE_PCV2SI },
+  { OPTION_MASK_ISA_MMX, CODE_FOR_nothing, "__builtin__ITM_RaRM64", (enum ix86_builtins) BUILT_IN_TM_LOAD_RAR_M64, UNKNOWN, V2SI_FTYPE_PCV2SI },
+  { OPTION_MASK_ISA_MMX, CODE_FOR_nothing, "__builtin__ITM_RaWM64", (enum ix86_builtins) BUILT_IN_TM_LOAD_RAW_M64, UNKNOWN, V2SI_FTYPE_PCV2SI },
+  { OPTION_MASK_ISA_MMX, CODE_FOR_nothing, "__builtin__ITM_RfWM64", (enum ix86_builtins) BUILT_IN_TM_LOAD_RFW_M64, UNKNOWN, V2SI_FTYPE_PCV2SI },
+
+  { OPTION_MASK_ISA_SSE, CODE_FOR_nothing, "__builtin__ITM_WM128", (enum ix86_builtins) BUILT_IN_TM_STORE_M128, UNKNOWN, VOID_FTYPE_PV4SF_V4SF },
+  { OPTION_MASK_ISA_SSE, CODE_FOR_nothing, "__builtin__ITM_WaRM128", (enum ix86_builtins) BUILT_IN_TM_STORE_WAR_M128, UNKNOWN, VOID_FTYPE_PV4SF_V4SF },
+  { OPTION_MASK_ISA_SSE, CODE_FOR_nothing, "__builtin__ITM_WaWM128", (enum ix86_builtins) BUILT_IN_TM_STORE_WAW_M128, UNKNOWN, VOID_FTYPE_PV4SF_V4SF },
+  { OPTION_MASK_ISA_SSE, CODE_FOR_nothing, "__builtin__ITM_RM128", (enum ix86_builtins) BUILT_IN_TM_LOAD_M128, UNKNOWN, V4SF_FTYPE_PCV4SF },
+  { OPTION_MASK_ISA_SSE, CODE_FOR_nothing, "__builtin__ITM_RaRM128", (enum ix86_builtins) BUILT_IN_TM_LOAD_RAR_M128, UNKNOWN, V4SF_FTYPE_PCV4SF },
+  { OPTION_MASK_ISA_SSE, CODE_FOR_nothing, "__builtin__ITM_RaWM128", (enum ix86_builtins) BUILT_IN_TM_LOAD_RAW_M128, UNKNOWN, V4SF_FTYPE_PCV4SF },
+  { OPTION_MASK_ISA_SSE, CODE_FOR_nothing, "__builtin__ITM_RfWM128", (enum ix86_builtins) BUILT_IN_TM_LOAD_RFW_M128, UNKNOWN, V4SF_FTYPE_PCV4SF },
+
+  { OPTION_MASK_ISA_AVX, CODE_FOR_nothing, "__builtin__ITM_WM256", (enum ix86_builtins) BUILT_IN_TM_STORE_M256, UNKNOWN, VOID_FTYPE_PV8SF_V8SF },
+  { OPTION_MASK_ISA_AVX, CODE_FOR_nothing, "__builtin__ITM_WaRM256", (enum ix86_builtins) BUILT_IN_TM_STORE_WAR_M256, UNKNOWN, VOID_FTYPE_PV8SF_V8SF },
+  { OPTION_MASK_ISA_AVX, CODE_FOR_nothing, "__builtin__ITM_WaWM256", (enum ix86_builtins) BUILT_IN_TM_STORE_WAW_M256, UNKNOWN, VOID_FTYPE_PV8SF_V8SF },
+  { OPTION_MASK_ISA_AVX, CODE_FOR_nothing, "__builtin__ITM_RM256", (enum ix86_builtins) BUILT_IN_TM_LOAD_M256, UNKNOWN, V8SF_FTYPE_PCV8SF },
+  { OPTION_MASK_ISA_AVX, CODE_FOR_nothing, "__builtin__ITM_RaRM256", (enum ix86_builtins) BUILT_IN_TM_LOAD_RAR_M256, UNKNOWN, V8SF_FTYPE_PCV8SF },
+  { OPTION_MASK_ISA_AVX, CODE_FOR_nothing, "__builtin__ITM_RaWM256", (enum ix86_builtins) BUILT_IN_TM_LOAD_RAW_M256, UNKNOWN, V8SF_FTYPE_PCV8SF },
+  { OPTION_MASK_ISA_AVX, CODE_FOR_nothing, "__builtin__ITM_RfWM256", (enum ix86_builtins) BUILT_IN_TM_LOAD_RFW_M256, UNKNOWN, V8SF_FTYPE_PCV8SF },
+
+  { OPTION_MASK_ISA_MMX, CODE_FOR_nothing, "__builtin__ITM_LM64", (enum ix86_builtins) BUILT_IN_TM_LOG_M64, UNKNOWN, VOID_FTYPE_PCVOID },
+  { OPTION_MASK_ISA_SSE, CODE_FOR_nothing, "__builtin__ITM_LM128", (enum ix86_builtins) BUILT_IN_TM_LOG_M128, UNKNOWN, VOID_FTYPE_PCVOID },
+  { OPTION_MASK_ISA_AVX, CODE_FOR_nothing, "__builtin__ITM_LM256", (enum ix86_builtins) BUILT_IN_TM_LOG_M256, UNKNOWN, VOID_FTYPE_PCVOID },
+};
+
+/* TM callbacks.  */
+
+/* Return the builtin decl needed to load a vector of TYPE.  */
+
+static tree
+ix86_builtin_tm_load (tree type)
+{
+  if (TREE_CODE (type) == VECTOR_TYPE)
+    {
+      switch (tree_low_cst (TYPE_SIZE (type), 1))
+       {
+       case 64:
+         return builtin_decl_explicit (BUILT_IN_TM_LOAD_M64);
+       case 128:
+         return builtin_decl_explicit (BUILT_IN_TM_LOAD_M128);
+       case 256:
+         return builtin_decl_explicit (BUILT_IN_TM_LOAD_M256);
+       }
+    }
+  return NULL_TREE;
+}
+
+/* Return the builtin decl needed to store a vector of TYPE.  */
+
+static tree
+ix86_builtin_tm_store (tree type)
+{
+  if (TREE_CODE (type) == VECTOR_TYPE)
+    {
+      switch (tree_low_cst (TYPE_SIZE (type), 1))
+       {
+       case 64:
+         return builtin_decl_explicit (BUILT_IN_TM_STORE_M64);
+       case 128:
+         return builtin_decl_explicit (BUILT_IN_TM_STORE_M128);
+       case 256:
+         return builtin_decl_explicit (BUILT_IN_TM_STORE_M256);
+       }
+    }
+  return NULL_TREE;
+}
+\f
+/* Initialize the transactional memory vector load/store builtins.  */
+
+static void
+ix86_init_tm_builtins (void)
+{
+  enum ix86_builtin_func_type ftype;
+  const struct builtin_description *d;
+  size_t i;
+  tree decl;
+  tree attrs_load, attrs_type_load, attrs_store, attrs_type_store;
+  tree attrs_log, attrs_type_log;
+
+  if (!flag_tm)
+    return;
+
+  /* Use whatever attributes a normal TM load has.  */
+  decl = builtin_decl_explicit (BUILT_IN_TM_LOAD_1);
+  attrs_load = DECL_ATTRIBUTES (decl);
+  attrs_type_load = TYPE_ATTRIBUTES (TREE_TYPE (decl));
+  /* Use whatever attributes a normal TM store has.  */
+  decl = builtin_decl_explicit (BUILT_IN_TM_STORE_1);
+  attrs_store = DECL_ATTRIBUTES (decl);
+  attrs_type_store = TYPE_ATTRIBUTES (TREE_TYPE (decl));
+  /* Use whatever attributes a normal TM log has.  */
+  decl = builtin_decl_explicit (BUILT_IN_TM_LOG);
+  attrs_log = DECL_ATTRIBUTES (decl);
+  attrs_type_log = TYPE_ATTRIBUTES (TREE_TYPE (decl));
+
+  for (i = 0, d = bdesc_tm;
+       i < ARRAY_SIZE (bdesc_tm);
+       i++, d++)
+    {
+      if ((d->mask & ix86_isa_flags) != 0
+         || (lang_hooks.builtin_function
+             == lang_hooks.builtin_function_ext_scope))
+       {
+         tree type, attrs, attrs_type;
+         enum built_in_function code = (enum built_in_function) d->code;
+
+         ftype = (enum ix86_builtin_func_type) d->flag;
+         type = ix86_get_builtin_func_type (ftype);
+
+         if (BUILTIN_TM_LOAD_P (code))
+           {
+             attrs = attrs_load;
+             attrs_type = attrs_type_load;
+           }
+         else if (BUILTIN_TM_STORE_P (code))
+           {
+             attrs = attrs_store;
+             attrs_type = attrs_type_store;
+           }
+         else
+           {
+             attrs = attrs_log;
+             attrs_type = attrs_type_log;
+           }
+         decl = add_builtin_function (d->name, type, code, BUILT_IN_NORMAL,
+                                      /* The builtin without the prefix for
+                                         calling it directly.  */
+                                      d->name + strlen ("__builtin_"),
+                                      attrs);
+         /* add_builtin_function() will set the DECL_ATTRIBUTES, now
+            set the TYPE_ATTRIBUTES.  */
+         decl_attributes (&TREE_TYPE (decl), attrs_type, ATTR_FLAG_BUILT_IN);
+
+         set_builtin_decl (code, decl, false);
+       }
+    }
+}
 
 /* Set up all the MMX/SSE builtins, even builtins for instructions that are not
    in the current target ISA to allow the user to compile particular modules
@@ -27163,6 +27345,7 @@ ix86_init_builtins (void)
   TREE_READONLY (t) = 1;
   ix86_builtins[(int) IX86_BUILTIN_COPYSIGNQ] = t;
 
+  ix86_init_tm_builtins ();
   ix86_init_mmx_sse_builtins ();
 
   if (TARGET_LP64)
@@ -29921,7 +30104,6 @@ avx_vperm2f128_parallel (rtx par, enum machine_mode mode)
   return mask + 1;
 }
 \f
-
 /* Store OPERAND to the memory after reload is completed.  This means
    that we can't easily use assign_stack_local.  */
 rtx
@@ -34784,6 +34966,11 @@ static const struct attribute_spec ix86_attribute_table[] =
      for FP arguments.  */
   { "sseregparm", 0, 0, false, true, true, ix86_handle_cconv_attribute,
     true },
+  /* The transactional memory builtins are implicitly regparm or fastcall
+     depending on the ABI.  Override the generic do-nothing attribute that
+     these builtins were declared with.  */
+  { "*tm regparm", 0, 0, false, true, true, ix86_handle_tm_regparm_attribute,
+    true },
   /* force_align_arg_pointer says this function realigns the stack at entry.  */
   { (const char *)&ix86_force_align_arg_pointer_string, 0, 0,
     false, true,  true, ix86_handle_cconv_attribute, false },
@@ -37954,6 +38141,12 @@ ix86_autovectorize_vector_sizes (void)
 #define TARGET_VECTORIZE_BUILTIN_VECTORIZED_FUNCTION \
   ix86_builtin_vectorized_function
 
+#undef TARGET_VECTORIZE_BUILTIN_TM_LOAD
+#define TARGET_VECTORIZE_BUILTIN_TM_LOAD ix86_builtin_tm_load
+
+#undef TARGET_VECTORIZE_BUILTIN_TM_STORE
+#define TARGET_VECTORIZE_BUILTIN_TM_STORE ix86_builtin_tm_store
+
 #undef TARGET_VECTORIZE_BUILTIN_GATHER
 #define TARGET_VECTORIZE_BUILTIN_GATHER ix86_vectorize_builtin_gather
 
index bcdecdf..15b44b5 100644 (file)
@@ -1,3 +1,40 @@
+2011-11-07  Richard Henderson  <rth@redhat.com>
+           Aldy Hernandez  <aldyh@redhat.com>
+           Torvald Riegel  <triegel@redhat.com>
+
+       Merged from transactional-memory.
+
+       * call.c (build_new_function_call): Call tm_malloc_replacement.
+       * class.c (check_bases): Compute transaction attributes for the
+       class based on its base classes.
+       (look_for_tm_attr_overrides, set_one_vmethod_tm_attributes,
+       set_method_tm_attributes): New.
+       (finish_struct_1): Call set_method_tm_attributes.
+       * cp-tree.h (begin_transaction_stmt, finish_transaction_stmt,
+       build_transaction_expr): Declare.
+       (TRANSACTION_EXPR_IS_STMT): New.
+       * decl.c (push_cp_library_fn): Set attribute to transaction_safe.
+       * except.c (do_get_exception_ptr): Apply transaction_pure.
+       (do_begin_catch): Mark _ITM_cxa_begin_catch transaction_pure and
+       record as transactional-memory wrapper.
+       (do_end_catch): Similarly for _ITM_cxa_end_catch.
+       (do_allocate_exception): Similarly for _ITM_cxa_allocate_exception.
+       (build_throw): Similarly for _ITM_cxa_throw. Make __cxa_rethrow pure.
+       * parser.h (struct cp_parser): Add in_transaction flag.
+       * parser.c (enum non_integral_constant): Add NIC_TRANSACTION.
+       (cp_parser_non_integral_constant_expression): Handle NIC_TRANSACTION.
+       (enum required_token): Add transaction tokens.
+       (cp_parser_transaction, cp_parser_transaction_expression,
+       cp_parser_function_transaction, cp_parser_transaction_cancel,
+       cp_parser_txn_attribute_opt): New.
+       (cp_parser_unary_expression): Handle RID_TRANSACTION*.
+       (cp_parser_statement, cp_parser_function_definition_after_declarator,
+       cp_parser_token_starts_function_definition_p): Same.
+       (cp_parser_required_error): Handle RT_TRANSACTION*.
+       * pt.c (tsubst_expr): Handle TRANSACTION_EXPR.
+       * semantics.c (begin_transaction_stmt, finish_transaction_stmt,
+       build_transaction_expr): New.
+
 2011-11-08  Dodji Seketeli  <dodji@redhat.com>
 
        Fix context handling of alias-declaration
index 2bf22f9..578905e 100644 (file)
@@ -3826,6 +3826,9 @@ build_new_function_call (tree fn, VEC(tree,gc) **args, bool koenig_p,
        return error_mark_node;
     }
 
+  if (flag_tm)
+    tm_malloc_replacement (fn);
+
   /* If this function was found without using argument dependent
      lookup, then we want to ignore any undeclared friend
      functions.  */
index 1775868..be632be 100644 (file)
@@ -1227,13 +1227,12 @@ check_bases (tree t,
             int* no_const_asn_ref_p)
 {
   int i;
-  int seen_non_virtual_nearly_empty_base_p;
+  bool seen_non_virtual_nearly_empty_base_p = 0;
+  int seen_tm_mask = 0;
   tree base_binfo;
   tree binfo;
   tree field = NULL_TREE;
 
-  seen_non_virtual_nearly_empty_base_p = 0;
-
   if (!CLASSTYPE_NON_STD_LAYOUT (t))
     for (field = TYPE_FIELDS (t); field; field = DECL_CHAIN (field))
       if (TREE_CODE (field) == FIELD_DECL)
@@ -1338,6 +1337,23 @@ check_bases (tree t,
                  break;
                }
        }
+
+      /* Don't bother collecting tm attributes if transactional memory
+        support is not enabled.  */
+      if (flag_tm)
+       {
+         tree tm_attr = find_tm_attribute (TYPE_ATTRIBUTES (basetype));
+         if (tm_attr)
+           seen_tm_mask |= tm_attr_to_mask (tm_attr);
+       }
+    }
+
+  /* If one of the base classes had TM attributes, and the current class
+     doesn't define its own, then the current class inherits one.  */
+  if (seen_tm_mask && !find_tm_attribute (TYPE_ATTRIBUTES (t)))
+    {
+      tree tm_attr = tm_mask_to_attr (seen_tm_mask & -seen_tm_mask);
+      TYPE_ATTRIBUTES (t) = tree_cons (tm_attr, NULL, TYPE_ATTRIBUTES (t));
     }
 }
 
@@ -4258,6 +4274,137 @@ clone_constructors_and_destructors (tree t)
     clone_function_decl (OVL_CURRENT (fns), /*update_method_vec_p=*/1);
 }
 
+/* Subroutine of set_one_vmethod_tm_attributes.  Search base classes
+   of TYPE for virtual functions which FNDECL overrides.  Return a
+   mask of the tm attributes found therein.  */
+
+static int
+look_for_tm_attr_overrides (tree type, tree fndecl)
+{
+  tree binfo = TYPE_BINFO (type);
+  tree base_binfo;
+  int ix, found = 0;
+
+  for (ix = 0; BINFO_BASE_ITERATE (binfo, ix, base_binfo); ++ix)
+    {
+      tree o, basetype = BINFO_TYPE (base_binfo);
+
+      if (!TYPE_POLYMORPHIC_P (basetype))
+       continue;
+
+      o = look_for_overrides_here (basetype, fndecl);
+      if (o)
+       found |= tm_attr_to_mask (find_tm_attribute
+                                 (TYPE_ATTRIBUTES (TREE_TYPE (o))));
+      else
+       found |= look_for_tm_attr_overrides (basetype, fndecl);
+    }
+
+  return found;
+}
+
+/* Subroutine of set_method_tm_attributes.  Handle the checks and
+   inheritance for one virtual method FNDECL.  */
+
+static void
+set_one_vmethod_tm_attributes (tree type, tree fndecl)
+{
+  tree tm_attr;
+  int found, have;
+
+  found = look_for_tm_attr_overrides (type, fndecl);
+
+  /* If FNDECL doesn't actually override anything (i.e. T is the
+     class that first declares FNDECL virtual), then we're done.  */
+  if (found == 0)
+    return;
+
+  tm_attr = find_tm_attribute (TYPE_ATTRIBUTES (TREE_TYPE (fndecl)));
+  have = tm_attr_to_mask (tm_attr);
+
+  /* Intel STM Language Extension 3.0, Section 4.2 table 4:
+     tm_pure must match exactly, otherwise no weakening of
+     tm_safe > tm_callable > nothing.  */
+  /* ??? The tm_pure attribute didn't make the transition to the
+     multivendor language spec.  */
+  if (have == TM_ATTR_PURE)
+    {
+      if (found != TM_ATTR_PURE)
+       {
+         found &= -found;
+         goto err_override;
+       }
+    }
+  /* If the overridden function is tm_pure, then FNDECL must be.  */
+  else if (found == TM_ATTR_PURE && tm_attr)
+    goto err_override;
+  /* Look for base class combinations that cannot be satisfied.  */
+  else if (found != TM_ATTR_PURE && (found & TM_ATTR_PURE))
+    {
+      found &= ~TM_ATTR_PURE;
+      found &= -found;
+      error_at (DECL_SOURCE_LOCATION (fndecl),
+               "method overrides both %<transaction_pure%> and %qE methods",
+               tm_mask_to_attr (found));
+    }
+  /* If FNDECL did not declare an attribute, then inherit the most
+     restrictive one.  */
+  else if (tm_attr == NULL)
+    {
+      apply_tm_attr (fndecl, tm_mask_to_attr (found & -found));
+    }
+  /* Otherwise validate that we're not weaker than a function
+     that is being overridden.  */
+  else
+    {
+      found &= -found;
+      if (found <= TM_ATTR_CALLABLE && have > found)
+       goto err_override;
+    }
+  return;
+
+ err_override:
+  error_at (DECL_SOURCE_LOCATION (fndecl),
+           "method declared %qE overriding %qE method",
+           tm_attr, tm_mask_to_attr (found));
+}
+
+/* For each of the methods in T, propagate a class-level tm attribute.  */
+
+static void
+set_method_tm_attributes (tree t)
+{
+  tree class_tm_attr, fndecl;
+
+  /* Don't bother collecting tm attributes if transactional memory
+     support is not enabled.  */
+  if (!flag_tm)
+    return;
+
+  /* Process virtual methods first, as they inherit directly from the
+     base virtual function and also require validation of new attributes.  */
+  if (TYPE_CONTAINS_VPTR_P (t))
+    {
+      tree vchain;
+      for (vchain = BINFO_VIRTUALS (TYPE_BINFO (t)); vchain;
+          vchain = TREE_CHAIN (vchain))
+       set_one_vmethod_tm_attributes (t, BV_FN (vchain));
+    }
+
+  /* If the class doesn't have an attribute, nothing more to do.  */
+  class_tm_attr = find_tm_attribute (TYPE_ATTRIBUTES (t));
+  if (class_tm_attr == NULL)
+    return;
+
+  /* Any method that does not yet have a tm attribute inherits
+     the one from the class.  */
+  for (fndecl = TYPE_METHODS (t); fndecl; fndecl = TREE_CHAIN (fndecl))
+    {
+      if (!find_tm_attribute (TYPE_ATTRIBUTES (TREE_TYPE (fndecl))))
+       apply_tm_attr (fndecl, class_tm_attr);
+    }
+}
+
 /* Returns true iff class T has a user-defined constructor other than
    the default constructor.  */
 
@@ -5841,6 +5988,7 @@ finish_struct_1 (tree t)
     }
 
   finish_struct_bits (t);
+  set_method_tm_attributes (t);
 
   /* Complete the rtl for any static member objects of the type we're
      working on.  */
index 177f100..32d08ca 100644 (file)
@@ -73,6 +73,7 @@ c-common.h, not after.
       VEC_INIT_EXPR_IS_CONSTEXPR (in VEC_INIT_EXPR)
       DECL_OVERRIDE_P (in FUNCTION_DECL)
       IMPLICIT_CONV_EXPR_DIRECT_INIT (in IMPLICIT_CONV_EXPR)
+      TRANSACTION_EXPR_IS_STMT (in TRANSACTION_EXPR)
    1: IDENTIFIER_VIRTUAL_P (in IDENTIFIER_NODE)
       TI_PENDING_TEMPLATE_FLAG.
       TEMPLATE_PARMS_FOR_INLINE.
@@ -3890,6 +3891,10 @@ more_aggr_init_expr_args_p (const aggr_init_expr_arg_iterator *iter)
   TREE_TYPE (OMP_CLAUSE_RANGE_CHECK (NODE, OMP_CLAUSE_PRIVATE, \
                                     OMP_CLAUSE_COPYPRIVATE))
 
+/* Nonzero if this transaction expression's body contains statements.  */
+#define TRANSACTION_EXPR_IS_STMT(NODE) \
+   TREE_LANG_FLAG_0 (TRANSACTION_EXPR_CHECK (NODE))
+
 /* These macros provide convenient access to the various _STMT nodes
    created when parsing template declarations.  */
 #define TRY_STMTS(NODE)                TREE_OPERAND (TRY_BLOCK_CHECK (NODE), 0)
@@ -5556,6 +5561,9 @@ extern void finish_omp_atomic                     (enum tree_code, enum tree_code,
 extern void finish_omp_barrier                 (void);
 extern void finish_omp_flush                   (void);
 extern void finish_omp_taskwait                        (void);
+extern tree begin_transaction_stmt             (location_t, tree *, int);
+extern void finish_transaction_stmt            (tree, tree, int);
+extern tree build_transaction_expr             (location_t, tree, int);
 extern void finish_omp_taskyield               (void);
 extern bool cxx_omp_create_clause_info         (tree, tree, bool, bool, bool);
 extern tree baselink_for_fns                    (tree);
index 1c33776..1c46adf 100644 (file)
@@ -4001,6 +4001,8 @@ push_cp_library_fn (enum tree_code operator_code, tree type)
                                 operator_code,
                                 type);
   pushdecl (fn);
+  if (flag_tm)
+    apply_tm_attr (fn, get_identifier ("transaction_safe"));
   return fn;
 }
 
index e529685..670a66f 100644 (file)
@@ -173,6 +173,9 @@ do_get_exception_ptr (void)
     {
       /* Declare void* __cxa_get_exception_ptr (void *) throw().  */
       fn = declare_nothrow_library_fn (fn, ptr_type_node, ptr_type_node);
+
+      if (flag_tm)
+       apply_tm_attr (fn, get_identifier ("transaction_pure"));
     }
 
   return cp_build_function_call_nary (fn, tf_warning_or_error,
@@ -192,6 +195,17 @@ do_begin_catch (void)
     {
       /* Declare void* __cxa_begin_catch (void *) throw().  */
       fn = declare_nothrow_library_fn (fn, ptr_type_node, ptr_type_node);
+
+      /* Create its transactional-memory equivalent.  */
+      if (flag_tm)
+       {
+         tree fn2 = get_identifier ("_ITM_cxa_begin_catch");
+         if (!get_global_value_if_present (fn2, &fn2))
+           fn2 = declare_nothrow_library_fn (fn2, ptr_type_node,
+                                             ptr_type_node);
+         apply_tm_attr (fn2, get_identifier ("transaction_pure"));
+         record_tm_replacement (fn, fn2);
+       }
     }
 
   return cp_build_function_call_nary (fn, tf_warning_or_error,
@@ -231,6 +245,19 @@ do_end_catch (tree type)
       fn = push_void_library_fn (fn, void_list_node);
       /* This can throw if the destructor for the exception throws.  */
       TREE_NOTHROW (fn) = 0;
+
+      /* Create its transactional-memory equivalent.  */
+      if (flag_tm)
+       {
+         tree fn2 = get_identifier ("_ITM_cxa_end_catch");
+         if (!get_global_value_if_present (fn2, &fn2))
+           {
+             fn2 = push_void_library_fn (fn2, void_list_node);
+             TREE_NOTHROW (fn2) = 0;
+           }
+         apply_tm_attr (fn2, get_identifier ("transaction_pure"));
+         record_tm_replacement (fn, fn2);
+       }
     }
 
   cleanup = cp_build_function_call_vec (fn, NULL, tf_warning_or_error);
@@ -581,6 +608,16 @@ do_allocate_exception (tree type)
     {
       /* Declare void *__cxa_allocate_exception(size_t) throw().  */
       fn = declare_nothrow_library_fn (fn, ptr_type_node, size_type_node);
+
+      if (flag_tm)
+       {
+         tree fn2 = get_identifier ("_ITM_cxa_allocate_exception");
+         if (!get_global_value_if_present (fn2, &fn2))
+           fn2 = declare_nothrow_library_fn (fn2, ptr_type_node,
+                                             size_type_node);
+         apply_tm_attr (fn2, get_identifier ("transaction_pure"));
+         record_tm_replacement (fn, fn2);
+       }
     }
 
   return cp_build_function_call_nary (fn, tf_warning_or_error,
@@ -712,6 +749,15 @@ build_throw (tree exp)
                                          ptr_type_node, ptr_type_node,
                                          cleanup_type, NULL_TREE);
          fn = push_throw_library_fn (fn, tmp);
+
+         if (flag_tm)
+           {
+             tree fn2 = get_identifier ("_ITM_cxa_throw");
+             if (!get_global_value_if_present (fn2, &fn2))
+               fn2 = push_throw_library_fn (fn2, tmp);
+             apply_tm_attr (fn2, get_identifier ("transaction_pure"));
+             record_tm_replacement (fn, fn2);
+           }
        }
 
       /* [except.throw]
@@ -831,6 +877,9 @@ build_throw (tree exp)
            (fn, build_function_type_list (void_type_node, NULL_TREE));
        }
 
+      if (flag_tm)
+       apply_tm_attr (fn, get_identifier ("transaction_pure"));
+
       /* ??? Indicate that this function call allows exceptions of the type
         of the enclosing catch block (if known).  */
       exp = cp_build_function_call_vec (fn, NULL, tf_warning_or_error);
index 3d35877..12f3c40 100644 (file)
@@ -106,7 +106,9 @@ typedef enum non_integral_constant {
   /* a comma operator */
   NIC_COMMA,
   /* a call to a constructor */
-  NIC_CONSTRUCTOR
+  NIC_CONSTRUCTOR,
+  /* a transaction expression */
+  NIC_TRANSACTION
 } non_integral_constant;
 
 /* The various kinds of errors about name-lookup failing. */
@@ -171,7 +173,10 @@ typedef enum required_token {
   RT_INTERATION, /* iteration-statement */
   RT_JUMP, /* jump-statement */
   RT_CLASS_KEY, /* class-key */
-  RT_CLASS_TYPENAME_TEMPLATE /* class, typename, or template */
+  RT_CLASS_TYPENAME_TEMPLATE, /* class, typename, or template */
+  RT_TRANSACTION_ATOMIC, /* __transaction_atomic */
+  RT_TRANSACTION_RELAXED, /* __transaction_relaxed */
+  RT_TRANSACTION_CANCEL /* __transaction_cancel */
 } required_token;
 
 /* Prototypes.  */
@@ -2106,6 +2111,17 @@ static bool cp_parser_extension_opt
 static void cp_parser_label_declaration
   (cp_parser *);
 
+/* Transactional Memory Extensions */
+
+static tree cp_parser_transaction
+  (cp_parser *, enum rid);
+static tree cp_parser_transaction_expression
+  (cp_parser *, enum rid);
+static bool cp_parser_function_transaction
+  (cp_parser *, enum rid);
+static tree cp_parser_transaction_cancel
+  (cp_parser *);
+
 enum pragma_context { pragma_external, pragma_stmt, pragma_compound };
 static bool cp_parser_pragma
   (cp_parser *, enum pragma_context);
@@ -2671,6 +2687,10 @@ cp_parser_non_integral_constant_expression (cp_parser  *parser,
                error ("a call to a constructor "
                       "cannot appear in a constant-expression");
                return true;
+             case NIC_TRANSACTION:
+               error ("a transaction expression "
+                      "cannot appear in a constant-expression");
+               return true;
              case NIC_THIS:
                msg = "this";
                break;
@@ -6372,6 +6392,10 @@ cp_parser_unary_expression (cp_parser *parser, bool address_p, bool cast_p,
          }
          break;
 
+       case RID_TRANSACTION_ATOMIC:
+       case RID_TRANSACTION_RELAXED:
+         return cp_parser_transaction_expression (parser, keyword);
+
        case RID_NOEXCEPT:
          {
            tree expr;
@@ -8506,6 +8530,11 @@ cp_parser_lambda_body (cp_parser* parser, tree lambda_expr)
      declaration-statement
      try-block
 
+  TM Extension:
+
+   statement:
+     atomic-statement
+
   IN_COMPOUND is true when the statement is nested inside a
   cp_parser_compound_statement; this matters for certain pragmas.
 
@@ -8582,6 +8611,14 @@ cp_parser_statement (cp_parser* parser, tree in_statement_expr,
          cp_parser_declaration_statement (parser);
          return;
          
+       case RID_TRANSACTION_ATOMIC:
+       case RID_TRANSACTION_RELAXED:
+         statement = cp_parser_transaction (parser, keyword);
+         break;
+       case RID_TRANSACTION_CANCEL:
+         statement = cp_parser_transaction_cancel (parser);
+         break;
+
        default:
          /* It might be a keyword like `int' that can start a
             declaration-statement.  */
@@ -15194,6 +15231,11 @@ cp_parser_asm_definition (cp_parser* parser)
    function-definition:
      __extension__ function-definition
 
+   TM Extension:
+
+   function-definition:
+     decl-specifier-seq [opt] declarator function-transaction-block
+
    The DECL_SPECIFIERS apply to this declarator.  Returns a
    representation of the entity declared.  If MEMBER_P is TRUE, then
    this declarator appears in a class scope.  The new DECL created by
@@ -20911,12 +20953,19 @@ cp_parser_function_definition_after_declarator (cp_parser* parser,
 
   start_lambda_scope (current_function_decl);
 
-  /* If the next token is `try', then we are looking at a
-     function-try-block.  */
-  if (cp_lexer_next_token_is_keyword (parser->lexer, RID_TRY))
+  /* If the next token is `try', `__transaction_atomic', or
+     `__transaction_relaxed`, then we are looking at either function-try-block
+     or function-transaction-block.  Note that all of these include the
+     function-body.  */
+  if (cp_lexer_next_token_is_keyword (parser->lexer, RID_TRANSACTION_ATOMIC))
+    ctor_initializer_p = cp_parser_function_transaction (parser,
+       RID_TRANSACTION_ATOMIC);
+  else if (cp_lexer_next_token_is_keyword (parser->lexer,
+      RID_TRANSACTION_RELAXED))
+    ctor_initializer_p = cp_parser_function_transaction (parser,
+       RID_TRANSACTION_RELAXED);
+  else if (cp_lexer_next_token_is_keyword (parser->lexer, RID_TRY))
     ctor_initializer_p = cp_parser_function_try_block (parser);
-  /* A function-try-block includes the function-body, so we only do
-     this next part if we're not processing a function-try-block.  */
   else
     ctor_initializer_p
       = cp_parser_ctor_initializer_opt_and_function_body (parser);
@@ -22073,6 +22122,12 @@ cp_parser_required_error (cp_parser *parser,
       case RT_AT_THROW:
        cp_parser_error (parser, "expected %<@throw%>");
        return;
+      case RT_TRANSACTION_ATOMIC:
+       cp_parser_error (parser, "expected %<__transaction_atomic%>");
+       return;
+      case RT_TRANSACTION_RELAXED:
+       cp_parser_error (parser, "expected %<__transaction_relaxed%>");
+       return;
       default:
        break;
     }
@@ -22303,6 +22358,10 @@ cp_parser_token_starts_function_definition_p (cp_token* token)
          || token->type == CPP_COLON
          /* A function-try-block begins with `try'.  */
          || token->keyword == RID_TRY
+         /* A function-transaction-block begins with `__transaction_atomic'
+            or `__transaction_relaxed'.  */
+         || token->keyword == RID_TRANSACTION_ATOMIC
+         || token->keyword == RID_TRANSACTION_RELAXED
          /* The named return value extension begins with `return'.  */
          || token->keyword == RID_RETURN);
 }
@@ -26623,6 +26682,272 @@ cp_parser_omp_construct (cp_parser *parser, cp_token *pragma_tok)
     SET_EXPR_LOCATION (stmt, pragma_tok->location);
 }
 \f
+/* Transactional Memory parsing routines.  */
+
+/* Parse a transaction attribute.
+
+   txn-attribute:
+       attribute
+       [ [ identifier ] ]
+
+   ??? Simplify this when C++0x bracket attributes are
+   implemented properly.  */
+
+static tree
+cp_parser_txn_attribute_opt (cp_parser *parser)
+{
+  cp_token *token;
+  tree attr_name, attr = NULL;
+
+  if (cp_lexer_next_token_is_keyword (parser->lexer, RID_ATTRIBUTE))
+    return cp_parser_attributes_opt (parser);
+
+  if (cp_lexer_next_token_is_not (parser->lexer, CPP_OPEN_SQUARE))
+    return NULL_TREE;
+  cp_lexer_consume_token (parser->lexer);
+  if (!cp_parser_require (parser, CPP_OPEN_SQUARE, RT_OPEN_SQUARE))
+    goto error1;
+
+  token = cp_lexer_peek_token (parser->lexer);
+  if (token->type == CPP_NAME || token->type == CPP_KEYWORD)
+    {
+      token = cp_lexer_consume_token (parser->lexer);
+
+      attr_name = (token->type == CPP_KEYWORD
+                  /* For keywords, use the canonical spelling,
+                     not the parsed identifier.  */
+                  ? ridpointers[(int) token->keyword]
+                  : token->u.value);
+      attr = build_tree_list (attr_name, NULL_TREE);
+    }
+  else
+    cp_parser_error (parser, "expected identifier");
+
+  cp_parser_require (parser, CPP_CLOSE_SQUARE, RT_CLOSE_SQUARE);
+ error1:
+  cp_parser_require (parser, CPP_CLOSE_SQUARE, RT_CLOSE_SQUARE);
+  return attr;
+}
+
+/* Parse a __transaction_atomic or __transaction_relaxed statement.
+
+   transaction-statement:
+     __transaction_atomic txn-attribute[opt] txn-exception-spec[opt]
+       compound-statement
+     __transaction_relaxed txn-exception-spec[opt] compound-statement
+
+   ??? The exception specification is not yet implemented.
+*/
+
+static tree
+cp_parser_transaction (cp_parser *parser, enum rid keyword)
+{
+  unsigned char old_in = parser->in_transaction;
+  unsigned char this_in = 1, new_in;
+  cp_token *token;
+  tree stmt, attrs;
+
+  gcc_assert (keyword == RID_TRANSACTION_ATOMIC
+      || keyword == RID_TRANSACTION_RELAXED);
+  token = cp_parser_require_keyword (parser, keyword,
+      (keyword == RID_TRANSACTION_ATOMIC ? RT_TRANSACTION_ATOMIC
+         : RT_TRANSACTION_RELAXED));
+  gcc_assert (token != NULL);
+
+  if (keyword == RID_TRANSACTION_RELAXED)
+    this_in |= TM_STMT_ATTR_RELAXED;
+  else
+    {
+      attrs = cp_parser_txn_attribute_opt (parser);
+      if (attrs)
+       this_in |= parse_tm_stmt_attr (attrs, TM_STMT_ATTR_OUTER);
+    }
+
+  /* Keep track if we're in the lexical scope of an outer transaction.  */
+  new_in = this_in | (old_in & TM_STMT_ATTR_OUTER);
+
+  stmt = begin_transaction_stmt (token->location, NULL, this_in);
+
+  parser->in_transaction = new_in;
+  cp_parser_compound_statement (parser, NULL, false, false);
+  parser->in_transaction = old_in;
+
+  finish_transaction_stmt (stmt, NULL, this_in);
+
+  return stmt;
+}
+
+/* Parse a __transaction_atomic or __transaction_relaxed expression.
+
+   transaction-expression:
+     __transaction_atomic txn-exception-spec[opt] ( expression )
+     __transaction_relaxed txn-exception-spec[opt] ( expression )
+
+   ??? The exception specification is not yet implemented.
+*/
+
+static tree
+cp_parser_transaction_expression (cp_parser *parser, enum rid keyword)
+{
+  unsigned char old_in = parser->in_transaction;
+  unsigned char this_in = 1;
+  cp_token *token;
+  tree ret;
+
+  gcc_assert (keyword == RID_TRANSACTION_ATOMIC
+      || keyword == RID_TRANSACTION_RELAXED);
+
+  if (!flag_tm)
+    error (keyword == RID_TRANSACTION_RELAXED
+          ? G_("%<__transaction_relaxed%> without transactional memory "
+               "support enabled")
+          : G_("%<__transaction_atomic%> without transactional memory "
+               "support enabled"));
+
+  token = cp_parser_require_keyword (parser, keyword,
+      (keyword == RID_TRANSACTION_ATOMIC ? RT_TRANSACTION_ATOMIC
+         : RT_TRANSACTION_RELAXED));
+  gcc_assert (token != NULL);
+
+  if (keyword == RID_TRANSACTION_RELAXED)
+    this_in |= TM_STMT_ATTR_RELAXED;
+
+  parser->in_transaction = this_in;
+  if (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_PAREN))
+    {
+      tree expr = cp_parser_expression (parser, /*cast_p=*/false, NULL);
+      ret = build_transaction_expr (token->location, expr, this_in);
+    }
+  else
+    {
+      cp_parser_error (parser, "expected %<(%>");
+      ret = error_mark_node;
+    }
+  parser->in_transaction = old_in;
+
+  if (cp_parser_non_integral_constant_expression (parser, NIC_TRANSACTION))
+    return error_mark_node;
+
+  return (flag_tm ? ret : error_mark_node);
+}
+
+/* Parse a function-transaction-block.
+
+   function-transaction-block:
+     __transaction_atomic txn-attribute[opt] ctor-initializer[opt]
+        function-body
+     __transaction_atomic txn-attribute[opt] function-try-block
+     __transaction_relaxed ctor-initializer[opt] function-body
+     __transaction_relaxed function-try-block
+*/
+
+static bool
+cp_parser_function_transaction (cp_parser *parser, enum rid keyword)
+{
+  unsigned char old_in = parser->in_transaction;
+  unsigned char new_in = 1;
+  tree compound_stmt, stmt, attrs;
+  bool ctor_initializer_p;
+  cp_token *token;
+
+  gcc_assert (keyword == RID_TRANSACTION_ATOMIC
+      || keyword == RID_TRANSACTION_RELAXED);
+  token = cp_parser_require_keyword (parser, keyword,
+      (keyword == RID_TRANSACTION_ATOMIC ? RT_TRANSACTION_ATOMIC
+         : RT_TRANSACTION_RELAXED));
+  gcc_assert (token != NULL);
+
+  if (keyword == RID_TRANSACTION_RELAXED)
+    new_in |= TM_STMT_ATTR_RELAXED;
+  else
+    {
+      attrs = cp_parser_txn_attribute_opt (parser);
+      if (attrs)
+       new_in |= parse_tm_stmt_attr (attrs, TM_STMT_ATTR_OUTER);
+    }
+
+  stmt = begin_transaction_stmt (token->location, &compound_stmt, new_in);
+
+  parser->in_transaction = new_in;
+
+  if (cp_lexer_next_token_is_keyword (parser->lexer, RID_TRY))
+    ctor_initializer_p = cp_parser_function_try_block (parser);
+  else
+    ctor_initializer_p
+      = cp_parser_ctor_initializer_opt_and_function_body (parser);
+
+  parser->in_transaction = old_in;
+
+  finish_transaction_stmt (stmt, compound_stmt, new_in);
+
+  return ctor_initializer_p;
+}
+
+/* Parse a __transaction_cancel statement.
+
+   cancel-statement:
+     __transaction_cancel txn-attribute[opt] ;
+     __transaction_cancel txn-attribute[opt] throw-expression ;
+
+   ??? Cancel and throw is not yet implemented.  */
+
+static tree
+cp_parser_transaction_cancel (cp_parser *parser)
+{
+  cp_token *token;
+  bool is_outer = false;
+  tree stmt, attrs;
+
+  token = cp_parser_require_keyword (parser, RID_TRANSACTION_CANCEL,
+                                    RT_TRANSACTION_CANCEL);
+  gcc_assert (token != NULL);
+
+  attrs = cp_parser_txn_attribute_opt (parser);
+  if (attrs)
+    is_outer = (parse_tm_stmt_attr (attrs, TM_STMT_ATTR_OUTER) != 0);
+
+  /* ??? Parse cancel-and-throw here.  */
+
+  cp_parser_require (parser, CPP_SEMICOLON, RT_SEMICOLON);
+
+  if (!flag_tm)
+    {
+      error_at (token->location, "%<__transaction_cancel%> without "
+               "transactional memory support enabled");
+      return error_mark_node;
+    }
+  else if (parser->in_transaction & TM_STMT_ATTR_RELAXED)
+    {
+      error_at (token->location, "%<__transaction_cancel%> within a "
+               "%<__transaction_relaxed%>");
+      return error_mark_node;
+    }
+  else if (is_outer)
+    {
+      if ((parser->in_transaction & TM_STMT_ATTR_OUTER) == 0
+         && !is_tm_may_cancel_outer (current_function_decl))
+       {
+         error_at (token->location, "outer %<__transaction_cancel%> not "
+                   "within outer %<__transaction_atomic%>");
+         error_at (token->location,
+                   "  or a %<transaction_may_cancel_outer%> function");
+         return error_mark_node;
+       }
+    }
+  else if (parser->in_transaction == 0)
+    {
+      error_at (token->location, "%<__transaction_cancel%> not within "
+               "%<__transaction_atomic%>");
+      return error_mark_node;
+    }
+
+  stmt = build_tm_abort_call (token->location, is_outer);
+  add_stmt (stmt);
+  finish_stmt ();
+
+  return stmt;
+}
+\f
 /* The parser.  */
 
 static GTY (()) cp_parser *the_parser;
index b44d23c..5b95f08 100644 (file)
@@ -329,6 +329,10 @@ typedef struct GTY(()) cp_parser {
      a local class.  */
   bool in_function_body;
 
+  /* Nonzero if we're processing a __transaction_atomic or
+     __transaction_relaxed statement.  */
+  unsigned char in_transaction;
+
   /* TRUE if we can auto-correct a colon to a scope operator.  */
   bool colon_corrects_to_scope_p;
 
index bf2a2c6..8c91a9e 100644 (file)
@@ -13108,6 +13108,28 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl,
        }
       break;
 
+    case TRANSACTION_EXPR:
+      {
+       int flags = 0;
+       flags |= (TRANSACTION_EXPR_OUTER (t) ? TM_STMT_ATTR_OUTER : 0);
+       flags |= (TRANSACTION_EXPR_RELAXED (t) ? TM_STMT_ATTR_RELAXED : 0);
+
+        if (TRANSACTION_EXPR_IS_STMT (t))
+          {
+            stmt = begin_transaction_stmt (input_location, NULL, flags);
+            RECUR (TRANSACTION_EXPR_BODY (t));
+            finish_transaction_stmt (stmt, NULL, flags);
+          }
+        else
+          {
+            stmt = build_transaction_expr (EXPR_LOCATION (t),
+                                          RECUR (TRANSACTION_EXPR_BODY (t)),
+                                          flags);
+            return stmt;
+          }
+      }
+      break;
+
     case EXPR_PACK_EXPANSION:
       error ("invalid use of pack expansion expression");
       return error_mark_node;
index 9d6bd31..508e252 100644 (file)
@@ -4968,6 +4968,64 @@ finish_omp_taskyield (void)
   finish_expr_stmt (stmt);
 }
 \f
+/* Begin a __transaction_atomic or __transaction_relaxed statement.
+   If PCOMPOUND is non-null, this is for a function-transaction-block, and we
+   should create an extra compound stmt.  */
+
+tree
+begin_transaction_stmt (location_t loc, tree *pcompound, int flags)
+{
+  tree r;
+
+  if (pcompound)
+    *pcompound = begin_compound_stmt (0);
+
+  r = build_stmt (loc, TRANSACTION_EXPR, NULL_TREE);
+
+  /* Only add the statement to the function if support enabled.  */
+  if (flag_tm)
+    add_stmt (r);
+  else
+    error_at (loc, ((flags & TM_STMT_ATTR_RELAXED) != 0
+                   ? G_("%<__transaction_relaxed%> without "
+                        "transactional memory support enabled")
+                   : G_("%<__transaction_atomic%> without "
+                        "transactional memory support enabled")));
+
+  TRANSACTION_EXPR_BODY (r) = push_stmt_list ();
+  return r;
+}
+
+/* End a __transaction_atomic or __transaction_relaxed statement.
+   If COMPOUND_STMT is non-null, this is for a function-transaction-block,
+   and we should end the compound.  */
+
+void
+finish_transaction_stmt (tree stmt, tree compound_stmt, int flags)
+{
+  TRANSACTION_EXPR_BODY (stmt) = pop_stmt_list (TRANSACTION_EXPR_BODY (stmt));
+  TRANSACTION_EXPR_OUTER (stmt) = (flags & TM_STMT_ATTR_OUTER) != 0;
+  TRANSACTION_EXPR_RELAXED (stmt) = (flags & TM_STMT_ATTR_RELAXED) != 0;
+  TRANSACTION_EXPR_IS_STMT (stmt) = 1;
+
+  if (compound_stmt)
+    finish_compound_stmt (compound_stmt);
+  finish_stmt ();
+}
+
+/* Build a __transaction_atomic or __transaction_relaxed expression.  */
+
+tree
+build_transaction_expr (location_t loc, tree expr, int flags)
+{
+  tree ret;
+  ret = build1 (TRANSACTION_EXPR, TREE_TYPE (expr), expr);
+  if (flags & TM_STMT_ATTR_RELAXED)
+       TRANSACTION_EXPR_RELAXED (ret) = 1;
+  SET_EXPR_LOCATION (ret, loc);
+  return ret;
+}
+\f
 void
 init_cp_semantics (void)
 {
@@ -8099,6 +8157,7 @@ potential_constant_expression_1 (tree t, bool want_rval, tsubst_flags_t flags)
     case STMT_EXPR:
     case EXPR_STMT:
     case BIND_EXPR:
+    case TRANSACTION_EXPR:
       if (flags & tf_error)
         error ("expression %qE is not a constant-expression", t);
       return false;
index e3fb21b..3a5a341 100644 (file)
@@ -1723,6 +1723,19 @@ Program Interface v3.0 @w{@uref{http://www.openmp.org/}}.  This option
 implies @option{-pthread}, and thus is only supported on targets that
 have support for @option{-pthread}.
 
+@item -fgnu-tm
+@opindex fgnu-tm
+When the option @option{-fgnu-tm} is specified, the compiler will
+generate code for the Linux variant of Intel's current Transactional
+Memory ABI specification document (Revision 1.1, May 6 2009).  This is
+an experimental feature whose interface may change in future versions
+of GCC, as the official specification changes.  Please note that not
+all architectures are supported for this feature.
+
+For more information on GCC's support for transactional memory,
+@xref{Enabling libitm,,The GNU Transactional Memory Library,libitm,GNU
+Transactional Memory Library}.
+
 @item -fms-extensions
 @opindex fms-extensions
 Accept some non-standard constructs used in Microsoft header files.
@@ -9113,6 +9126,13 @@ parameters only when their cumulative size is less or equal to
 @option{ipa-sra-ptr-growth-factor} times the size of the original
 pointer parameter.
 
+@item tm-max-aggregate-size
+When making copies of thread-local variables in a transaction, this
+parameter specifies the size in bytes after which variables will be
+saved with the logging functions as opposed to save/restore code
+sequence pairs.  This option only applies when using
+@option{-fgnu-tm}.
+
 @item graphite-max-nb-scop-params
 To avoid exponential effects in the Graphite loop transforms, the
 number of parameters in a Static Control Part (SCoP) is bounded.  The
index fed7702..d96932b 100644 (file)
@@ -5758,6 +5758,14 @@ mode returned by @code{TARGET_VECTORIZE_PREFERRED_SIMD_MODE}.
 The default is zero which means to not iterate over other vector sizes.
 @end deftypefn
 
+@deftypefn {Target Hook} tree TARGET_VECTORIZE_BUILTIN_TM_LOAD (tree)
+This hook should return the built-in decl needed to load a vector of the given type within a transaction.
+@end deftypefn
+
+@deftypefn {Target Hook} tree TARGET_VECTORIZE_BUILTIN_TM_STORE (tree)
+This hook should return the built-in decl needed to store a vector of the given type within a transaction.
+@end deftypefn
+
 @deftypefn {Target Hook} tree TARGET_VECTORIZE_BUILTIN_GATHER (const_tree @var{mem_vectype}, const_tree @var{index_type}, int @var{scale})
 Target builtin that implements vector gather operation.  @var{mem_vectype}
 is the vector type of the load and @var{index_type} is scalar type of
index f0c6ce0..146e38a 100644 (file)
@@ -5696,6 +5696,10 @@ mode returned by @code{TARGET_VECTORIZE_PREFERRED_SIMD_MODE}.
 The default is zero which means to not iterate over other vector sizes.
 @end deftypefn
 
+@hook TARGET_VECTORIZE_BUILTIN_TM_LOAD
+
+@hook TARGET_VECTORIZE_BUILTIN_TM_STORE
+
 @hook TARGET_VECTORIZE_BUILTIN_GATHER
 Target builtin that implements vector gather operation.  @var{mem_vectype}
 is the vector type of the load and @var{index_type} is scalar type of
index c2bc56b..4a27a05 100644 (file)
@@ -3595,6 +3595,7 @@ try_split (rtx pat, rtx trial, int last)
 
        case REG_NORETURN:
        case REG_SETJMP:
+       case REG_TM:
          for (insn = insn_last; insn != NULL_RTX; insn = PREV_INSN (insn))
            {
              if (CALL_P (insn))
index fd03ba4..f6deba1 100644 (file)
@@ -396,6 +396,11 @@ lower_stmt (gimple_stmt_iterator *gsi, struct lower_data *data)
       lower_sequence (gimple_eh_filter_failure (stmt), data);
       break;
 
+    case GIMPLE_EH_ELSE:
+      lower_sequence (gimple_eh_else_n_body (stmt), data);
+      lower_sequence (gimple_eh_else_e_body (stmt), data);
+      break;
+
     case GIMPLE_NOP:
     case GIMPLE_ASM:
     case GIMPLE_ASSIGN:
@@ -446,6 +451,10 @@ lower_stmt (gimple_stmt_iterator *gsi, struct lower_data *data)
       data->cannot_fallthru = false;
       return;
 
+    case GIMPLE_TRANSACTION:
+      lower_sequence (gimple_transaction_body (stmt), data);
+      break;
+
     default:
       gcc_unreachable ();
     }
@@ -727,6 +736,10 @@ gimple_stmt_may_fallthru (gimple stmt)
       return (gimple_seq_may_fallthru (gimple_try_eval (stmt))
              && gimple_seq_may_fallthru (gimple_try_cleanup (stmt)));
 
+    case GIMPLE_EH_ELSE:
+      return (gimple_seq_may_fallthru (gimple_eh_else_n_body (stmt))
+             || gimple_seq_may_fallthru (gimple_eh_else_e_body (stmt)));
+
     case GIMPLE_CALL:
       /* Functions that do not return do not fall through.  */
       return (gimple_call_flags (stmt) & ECF_NORETURN) == 0;
index 981d5b0..df703b4 100644 (file)
@@ -33,6 +33,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "tree-pass.h"
 #include "gimple.h"
 #include "value-prof.h"
+#include "trans-mem.h"
 
 #define INDENT(SPACE)                                                  \
   do { int i; for (i = 0; i < SPACE; i++) pp_space (buffer); } while (0)
@@ -162,6 +163,7 @@ debug_gimple_seq (gimple_seq seq)
      'd' - outputs an int as a decimal,
      's' - outputs a string,
      'n' - outputs a newline,
+     'x' - outputs an int as hexadecimal,
      '+' - increases indent by 2 then outputs a newline,
      '-' - decreases indent by 2 then outputs a newline.   */
 
@@ -216,6 +218,10 @@ dump_gimple_fmt (pretty_printer *buffer, int spc, int flags,
                 newline_and_indent (buffer, spc);
                 break;
 
+             case 'x':
+               pp_scalar (buffer, "%x", va_arg (args, int));
+               break;
+
               case '+':
                 spc += 2;
                 newline_and_indent (buffer, spc);
@@ -622,6 +628,7 @@ static void
 dump_gimple_call (pretty_printer *buffer, gimple gs, int spc, int flags)
 {
   tree lhs = gimple_call_lhs (gs);
+  tree fn = gimple_call_fn (gs);
 
   if (flags & TDF_ALIAS)
     {
@@ -648,8 +655,7 @@ dump_gimple_call (pretty_printer *buffer, gimple gs, int spc, int flags)
        dump_gimple_fmt (buffer, spc, flags, "%G <%s, %T", gs,
                         internal_fn_name (gimple_call_internal_fn (gs)), lhs);
       else
-       dump_gimple_fmt (buffer, spc, flags, "%G <%T, %T",
-                        gs, gimple_call_fn (gs), lhs);
+       dump_gimple_fmt (buffer, spc, flags, "%G <%T, %T", gs, fn, lhs);
       if (gimple_call_num_args (gs) > 0)
         {
           pp_string (buffer, ", ");
@@ -672,7 +678,7 @@ dump_gimple_call (pretty_printer *buffer, gimple gs, int spc, int flags)
       if (gimple_call_internal_p (gs))
        pp_string (buffer, internal_fn_name (gimple_call_internal_fn (gs)));
       else
-       print_call_name (buffer, gimple_call_fn (gs), flags);
+       print_call_name (buffer, fn, flags);
       pp_string (buffer, " (");
       dump_gimple_call_args (buffer, gs, flags);
       pp_character (buffer, ')');
@@ -689,9 +695,59 @@ dump_gimple_call (pretty_printer *buffer, gimple gs, int spc, int flags)
 
   if (gimple_call_return_slot_opt_p (gs))
     pp_string (buffer, " [return slot optimization]");
-
   if (gimple_call_tail_p (gs))
     pp_string (buffer, " [tail call]");
+
+  /* Dump the arguments of _ITM_beginTransaction sanely.  */
+  if (TREE_CODE (fn) == ADDR_EXPR)
+    fn = TREE_OPERAND (fn, 0);
+  if (TREE_CODE (fn) == FUNCTION_DECL && decl_is_tm_clone (fn))
+    pp_string (buffer, " [tm-clone]");
+  if (TREE_CODE (fn) == FUNCTION_DECL
+      && DECL_BUILT_IN_CLASS (fn) == BUILT_IN_NORMAL
+      && DECL_FUNCTION_CODE (fn) == BUILT_IN_TM_START
+      && gimple_call_num_args (gs) > 0)
+    {
+      tree t = gimple_call_arg (gs, 0);
+      unsigned HOST_WIDE_INT props;
+      gcc_assert (TREE_CODE (t) == INTEGER_CST);
+
+      pp_string (buffer, " [ ");
+
+      /* Get the transaction code properties.  */
+      props = TREE_INT_CST_LOW (t);
+
+      if (props & PR_INSTRUMENTEDCODE)
+       pp_string (buffer, "instrumentedCode ");
+      if (props & PR_UNINSTRUMENTEDCODE)
+       pp_string (buffer, "uninstrumentedCode ");
+      if (props & PR_HASNOXMMUPDATE)
+       pp_string (buffer, "hasNoXMMUpdate ");
+      if (props & PR_HASNOABORT)
+       pp_string (buffer, "hasNoAbort ");
+      if (props & PR_HASNOIRREVOCABLE)
+       pp_string (buffer, "hasNoIrrevocable ");
+      if (props & PR_DOESGOIRREVOCABLE)
+       pp_string (buffer, "doesGoIrrevocable ");
+      if (props & PR_HASNOSIMPLEREADS)
+       pp_string (buffer, "hasNoSimpleReads ");
+      if (props & PR_AWBARRIERSOMITTED)
+       pp_string (buffer, "awBarriersOmitted ");
+      if (props & PR_RARBARRIERSOMITTED)
+       pp_string (buffer, "RaRBarriersOmitted ");
+      if (props & PR_UNDOLOGCODE)
+       pp_string (buffer, "undoLogCode ");
+      if (props & PR_PREFERUNINSTRUMENTED)
+       pp_string (buffer, "preferUninstrumented ");
+      if (props & PR_EXCEPTIONBLOCK)
+       pp_string (buffer, "exceptionBlock ");
+      if (props & PR_HASELSE)
+       pp_string (buffer, "hasElse ");
+      if (props & PR_READONLY)
+       pp_string (buffer, "readOnly ");
+
+      pp_string (buffer, "]");
+    }
 }
 
 
@@ -947,6 +1003,24 @@ dump_gimple_eh_must_not_throw (pretty_printer *buffer, gimple gs,
 }
 
 
+/* Dump a GIMPLE_EH_ELSE tuple on the pretty_printer BUFFER, SPC spaces of
+   indent.  FLAGS specifies details to show in the dump (see TDF_* in
+   tree-pass.h).  */
+
+static void
+dump_gimple_eh_else (pretty_printer *buffer, gimple gs, int spc, int flags)
+{
+  if (flags & TDF_RAW)
+    dump_gimple_fmt (buffer, spc, flags,
+                    "%G <%+N_BODY <%S>%nE_BODY <%S>%->", gs,
+                    gimple_eh_else_n_body (gs), gimple_eh_else_e_body (gs));
+  else
+    dump_gimple_fmt (buffer, spc, flags,
+                   "<<<if_normal_exit>>>%+{%S}%-<<<else_eh_exit>>>%+{%S}",
+                    gimple_eh_else_n_body (gs), gimple_eh_else_e_body (gs));
+}
+
+
 /* Dump a GIMPLE_RESX tuple on the pretty_printer BUFFER, SPC spaces of
    indent.  FLAGS specifies details to show in the dump (see TDF_* in
    tree-pass.h).  */
@@ -1269,6 +1343,86 @@ dump_gimple_omp_return (pretty_printer *buffer, gimple gs, int spc, int flags)
     }
 }
 
+/* Dump a GIMPLE_TRANSACTION tuple on the pretty_printer BUFFER.  */
+
+static void
+dump_gimple_transaction (pretty_printer *buffer, gimple gs, int spc, int flags)
+{
+  unsigned subcode = gimple_transaction_subcode (gs);
+
+  if (flags & TDF_RAW)
+    {
+      dump_gimple_fmt (buffer, spc, flags,
+                      "%G [SUBCODE=%x,LABEL=%T] <%+BODY <%S> >",
+                      gs, subcode, gimple_transaction_label (gs),
+                      gimple_transaction_body (gs));
+    }
+  else
+    {
+      if (subcode & GTMA_IS_OUTER)
+       pp_string (buffer, "__transaction_atomic [[outer]]");
+      else if (subcode & GTMA_IS_RELAXED)
+       pp_string (buffer, "__transaction_relaxed");
+      else
+       pp_string (buffer, "__transaction_atomic");
+      subcode &= ~GTMA_DECLARATION_MASK;
+
+      if (subcode || gimple_transaction_label (gs))
+       {
+         pp_string (buffer, "  //");
+         if (gimple_transaction_label (gs))
+           {
+             pp_string (buffer, " LABEL=");
+             dump_generic_node (buffer, gimple_transaction_label (gs),
+                                spc, flags, false);
+           }
+         if (subcode)
+           {
+             pp_string (buffer, " SUBCODE=[ ");
+             if (subcode & GTMA_HAVE_ABORT)
+               {
+                 pp_string (buffer, "GTMA_HAVE_ABORT ");
+                 subcode &= ~GTMA_HAVE_ABORT;
+               }
+             if (subcode & GTMA_HAVE_LOAD)
+               {
+                 pp_string (buffer, "GTMA_HAVE_LOAD ");
+                 subcode &= ~GTMA_HAVE_LOAD;
+               }
+             if (subcode & GTMA_HAVE_STORE)
+               {
+                 pp_string (buffer, "GTMA_HAVE_STORE ");
+                 subcode &= ~GTMA_HAVE_STORE;
+               }
+             if (subcode & GTMA_MAY_ENTER_IRREVOCABLE)
+               {
+                 pp_string (buffer, "GTMA_MAY_ENTER_IRREVOCABLE ");
+                 subcode &= ~GTMA_MAY_ENTER_IRREVOCABLE;
+               }
+             if (subcode & GTMA_DOES_GO_IRREVOCABLE)
+               {
+                 pp_string (buffer, "GTMA_DOES_GO_IRREVOCABLE ");
+                 subcode &= ~GTMA_DOES_GO_IRREVOCABLE;
+               }
+             if (subcode)
+               pp_printf (buffer, "0x%x ", subcode);
+             pp_string (buffer, "]");
+           }
+       }
+
+      if (!gimple_seq_empty_p (gimple_transaction_body (gs)))
+       {
+         newline_and_indent (buffer, spc + 2);
+         pp_character (buffer, '{');
+         pp_newline (buffer);
+         dump_gimple_seq (buffer, gimple_transaction_body (gs),
+                          spc + 4, flags);
+         newline_and_indent (buffer, spc + 2);
+         pp_character (buffer, '}');
+       }
+    }
+}
+
 /* Dump a GIMPLE_ASM tuple on the pretty_printer BUFFER, SPC spaces of
    indent.  FLAGS specifies details to show in the dump (see TDF_* in
    tree-pass.h).  */
@@ -1855,6 +2009,10 @@ dump_gimple_stmt (pretty_printer *buffer, gimple gs, int spc, int flags)
       dump_gimple_eh_must_not_throw (buffer, gs, spc, flags);
       break;
 
+    case GIMPLE_EH_ELSE:
+      dump_gimple_eh_else (buffer, gs, spc, flags);
+      break;
+
     case GIMPLE_RESX:
       dump_gimple_resx (buffer, gs, spc, flags);
       break;
@@ -1877,6 +2035,10 @@ dump_gimple_stmt (pretty_printer *buffer, gimple gs, int spc, int flags)
       pp_string (buffer, " predictor.");
       break;
 
+    case GIMPLE_TRANSACTION:
+      dump_gimple_transaction (buffer, gs, spc, flags);
+      break;
+
     default:
       GIMPLE_NIY;
     }
index b2874bb..e803f56 100644 (file)
@@ -743,6 +743,17 @@ gimple_build_eh_must_not_throw (tree decl)
   return p;
 }
 
+/* Build a GIMPLE_EH_ELSE statement.  */
+
+gimple
+gimple_build_eh_else (gimple_seq n_body, gimple_seq e_body)
+{
+  gimple p = gimple_alloc (GIMPLE_EH_ELSE, 0);
+  gimple_eh_else_set_n_body (p, n_body);
+  gimple_eh_else_set_e_body (p, e_body);
+  return p;
+}
+
 /* Build a GIMPLE_TRY statement.
 
    EVAL is the expression to evaluate.
@@ -1146,6 +1157,17 @@ gimple_build_omp_atomic_store (tree val)
   return p;
 }
 
+/* Build a GIMPLE_TRANSACTION statement.  */
+
+gimple
+gimple_build_transaction (gimple_seq body, tree label)
+{
+  gimple p = gimple_alloc (GIMPLE_TRANSACTION, 0);
+  gimple_transaction_set_body (p, body);
+  gimple_transaction_set_label (p, label);
+  return p;
+}
+
 /* Build a GIMPLE_PREDICT statement.  PREDICT is one of the predictors from
    predict.def, OUTCOME is NOT_TAKEN or TAKEN.  */
 
@@ -1319,9 +1341,11 @@ gimple_seq_copy (gimple_seq src)
 /* Walk all the statements in the sequence SEQ calling walk_gimple_stmt
    on each one.  WI is as in walk_gimple_stmt.
 
-   If walk_gimple_stmt returns non-NULL, the walk is stopped, the
-   value is stored in WI->CALLBACK_RESULT and the statement that
-   produced the value is returned.
+   If walk_gimple_stmt returns non-NULL, the walk is stopped, and the
+   value is stored in WI->CALLBACK_RESULT.  Also, the statement that
+   produced the value is returned if this statement has not been
+   removed by a callback (wi->removed_stmt).  If the statement has
+   been removed, NULL is returned.
 
    Otherwise, all the statements are walked and NULL returned.  */
 
@@ -1331,7 +1355,7 @@ walk_gimple_seq (gimple_seq seq, walk_stmt_fn callback_stmt,
 {
   gimple_stmt_iterator gsi;
 
-  for (gsi = gsi_start (seq); !gsi_end_p (gsi); gsi_next (&gsi))
+  for (gsi = gsi_start (seq); !gsi_end_p (gsi); )
     {
       tree ret = walk_gimple_stmt (&gsi, callback_stmt, callback_op, wi);
       if (ret)
@@ -1340,8 +1364,12 @@ walk_gimple_seq (gimple_seq seq, walk_stmt_fn callback_stmt,
             to hold it.  */
          gcc_assert (wi);
          wi->callback_result = ret;
-         return gsi_stmt (gsi);
+
+         return wi->removed_stmt ? NULL : gsi_stmt (gsi);
        }
+
+      if (!wi->removed_stmt)
+       gsi_next (&gsi);
     }
 
   if (wi)
@@ -1680,6 +1708,13 @@ walk_gimple_op (gimple stmt, walk_tree_fn callback_op,
        return ret;
       break;
 
+    case GIMPLE_TRANSACTION:
+      ret = walk_tree (gimple_transaction_label_ptr (stmt), callback_op,
+                      wi, pset);
+      if (ret)
+       return ret;
+      break;
+
       /* Tuples that do not have operands.  */
     case GIMPLE_NOP:
     case GIMPLE_RESX:
@@ -1730,10 +1765,13 @@ walk_gimple_stmt (gimple_stmt_iterator *gsi, walk_stmt_fn callback_stmt,
   gimple stmt = gsi_stmt (*gsi);
 
   if (wi)
-    wi->gsi = *gsi;
+    {
+      wi->gsi = *gsi;
+      wi->removed_stmt = false;
 
-  if (wi && wi->want_locations && gimple_has_location (stmt))
-    input_location = gimple_location (stmt);
+      if (wi->want_locations && gimple_has_location (stmt))
+       input_location = gimple_location (stmt);
+    }
 
   ret = NULL;
 
@@ -1750,6 +1788,9 @@ walk_gimple_stmt (gimple_stmt_iterator *gsi, walk_stmt_fn callback_stmt,
         a value to return.  */
       gcc_assert (tree_ret == NULL);
 
+      if (wi && wi->removed_stmt)
+       return NULL;
+
       /* Re-read stmt in case the callback changed it.  */
       stmt = gsi_stmt (*gsi);
     }
@@ -1786,6 +1827,17 @@ walk_gimple_stmt (gimple_stmt_iterator *gsi, walk_stmt_fn callback_stmt,
        return wi->callback_result;
       break;
 
+    case GIMPLE_EH_ELSE:
+      ret = walk_gimple_seq (gimple_eh_else_n_body (stmt),
+                            callback_stmt, callback_op, wi);
+      if (ret)
+       return wi->callback_result;
+      ret = walk_gimple_seq (gimple_eh_else_e_body (stmt),
+                            callback_stmt, callback_op, wi);
+      if (ret)
+       return wi->callback_result;
+      break;
+
     case GIMPLE_TRY:
       ret = walk_gimple_seq (gimple_try_eval (stmt), callback_stmt, callback_op,
                             wi);
@@ -1813,8 +1865,8 @@ walk_gimple_stmt (gimple_stmt_iterator *gsi, walk_stmt_fn callback_stmt,
     case GIMPLE_OMP_TASK:
     case GIMPLE_OMP_SECTIONS:
     case GIMPLE_OMP_SINGLE:
-      ret = walk_gimple_seq (gimple_omp_body (stmt), callback_stmt, callback_op,
-                            wi);
+      ret = walk_gimple_seq (gimple_omp_body (stmt), callback_stmt,
+                            callback_op, wi);
       if (ret)
        return wi->callback_result;
       break;
@@ -1826,6 +1878,13 @@ walk_gimple_stmt (gimple_stmt_iterator *gsi, walk_stmt_fn callback_stmt,
        return wi->callback_result;
       break;
 
+    case GIMPLE_TRANSACTION:
+      ret = walk_gimple_seq (gimple_transaction_body (stmt),
+                            callback_stmt, callback_op, wi);
+      if (ret)
+       return wi->callback_result;
+      break;
+
     default:
       gcc_assert (!gimple_has_substatements (stmt));
       break;
@@ -2252,6 +2311,13 @@ gimple_copy (gimple stmt)
          gimple_eh_filter_set_types (copy, t);
          break;
 
+       case GIMPLE_EH_ELSE:
+         new_seq = gimple_seq_copy (gimple_eh_else_n_body (stmt));
+         gimple_eh_else_set_n_body (copy, new_seq);
+         new_seq = gimple_seq_copy (gimple_eh_else_e_body (stmt));
+         gimple_eh_else_set_e_body (copy, new_seq);
+         break;
+
        case GIMPLE_TRY:
          new_seq = gimple_seq_copy (gimple_try_eval (stmt));
          gimple_try_set_eval (copy, new_seq);
@@ -2327,6 +2393,11 @@ gimple_copy (gimple stmt)
          gimple_omp_set_body (copy, new_seq);
          break;
 
+       case GIMPLE_TRANSACTION:
+         new_seq = gimple_seq_copy (gimple_transaction_body (stmt));
+         gimple_transaction_set_body (copy, new_seq);
+         break;
+
        case GIMPLE_WITH_CLEANUP_EXPR:
          new_seq = gimple_seq_copy (gimple_wce_cleanup (stmt));
          gimple_wce_set_cleanup (copy, new_seq);
@@ -2782,37 +2853,6 @@ is_gimple_address (const_tree t)
     }
 }
 
-/* Strip out all handled components that produce invariant
-   offsets.  */
-
-static const_tree
-strip_invariant_refs (const_tree op)
-{
-  while (handled_component_p (op))
-    {
-      switch (TREE_CODE (op))
-       {
-       case ARRAY_REF:
-       case ARRAY_RANGE_REF:
-         if (!is_gimple_constant (TREE_OPERAND (op, 1))
-             || TREE_OPERAND (op, 2) != NULL_TREE
-             || TREE_OPERAND (op, 3) != NULL_TREE)
-           return NULL;
-         break;
-
-       case COMPONENT_REF:
-         if (TREE_OPERAND (op, 2) != NULL_TREE)
-           return NULL;
-         break;
-
-       default:;
-       }
-      op = TREE_OPERAND (op, 0);
-    }
-
-  return op;
-}
-
 /* Return true if T is a gimple invariant address.  */
 
 bool
@@ -3075,21 +3115,6 @@ is_gimple_mem_ref_addr (tree t)
                  || decl_address_invariant_p (TREE_OPERAND (t, 0)))));
 }
 
-/* If T makes a function call, return the corresponding CALL_EXPR operand.
-   Otherwise, return NULL_TREE.  */
-
-tree
-get_call_expr_in (tree t)
-{
-  if (TREE_CODE (t) == MODIFY_EXPR)
-    t = TREE_OPERAND (t, 1);
-  if (TREE_CODE (t) == WITH_SIZE_EXPR)
-    t = TREE_OPERAND (t, 0);
-  if (TREE_CODE (t) == CALL_EXPR)
-    return t;
-  return NULL_TREE;
-}
-
 
 /* Given a memory reference expression T, return its base address.
    The base address of a memory reference expression is the main
index 2b5488a..5ae9702 100644 (file)
@@ -124,6 +124,14 @@ DEFGSCODE(GIMPLE_ASM, "gimple_asm", GSS_ASM)
     CHAIN is the optional static chain link for nested functions.  */
 DEFGSCODE(GIMPLE_CALL, "gimple_call", GSS_CALL)
 
+/* GIMPLE_TRANSACTION <BODY, LABEL> represents __transaction_atomic and
+   __transaction_relaxed blocks.
+   BODY is the sequence of statements inside the transaction.
+   LABEL is a label for the statement immediately following the
+   transaction.  This is before RETURN so that it has MEM_OPS,
+   so that it can clobber global memory.  */
+DEFGSCODE(GIMPLE_TRANSACTION, "gimple_transaction", GSS_TRANSACTION)
+
 /* GIMPLE_RETURN <RETVAL> represents return statements.
 
    RETVAL is the value to return or NULL.  If a value is returned it
@@ -151,6 +159,12 @@ DEFGSCODE(GIMPLE_EH_FILTER, "gimple_eh_filter", GSS_EH_FILTER)
    be invoked if an exception propagates to this point.  */
 DEFGSCODE(GIMPLE_EH_MUST_NOT_THROW, "gimple_eh_must_not_throw", GSS_EH_MNT)
 
+/* GIMPLE_EH_ELSE <N_BODY, E_BODY> must be the sole contents of
+   a GIMPLE_TRY_FINALLY node.  For all normal exits from the try block,
+   N_BODY is run; for all exception exits from the try block,
+   E_BODY is run.  */
+DEFGSCODE(GIMPLE_EH_ELSE, "gimple_eh_else", GSS_EH_ELSE)
+
 /* GIMPLE_RESX resumes execution after an exception.  */
 DEFGSCODE(GIMPLE_RESX, "gimple_resx", GSS_EH_CTRL)
 
index 666c44c..ffecc26 100644 (file)
@@ -487,6 +487,15 @@ struct GTY(()) gimple_statement_eh_filter {
   gimple_seq failure;
 };
 
+/* GIMPLE_EH_ELSE */
+
+struct GTY(()) gimple_statement_eh_else {
+  /* [ WORD 1-4 ]  */
+  struct gimple_statement_base gsbase;
+
+  /* [ WORD 5,6 ] */
+  gimple_seq n_body, e_body;
+};
 
 /* GIMPLE_EH_MUST_NOT_THROW */
 
@@ -757,6 +766,43 @@ struct GTY(()) gimple_statement_omp_atomic_store {
   tree val;
 };
 
+/* GIMPLE_TRANSACTION.  */
+
+/* Bits to be stored in the GIMPLE_TRANSACTION subcode.  */
+
+/* The __transaction_atomic was declared [[outer]] or it is
+   __transaction_relaxed.  */
+#define GTMA_IS_OUTER                  (1u << 0)
+#define GTMA_IS_RELAXED                        (1u << 1)
+#define GTMA_DECLARATION_MASK          (GTMA_IS_OUTER | GTMA_IS_RELAXED)
+
+/* The transaction is seen to not have an abort.  */
+#define GTMA_HAVE_ABORT                        (1u << 2)
+/* The transaction is seen to have loads or stores.  */
+#define GTMA_HAVE_LOAD                 (1u << 3)
+#define GTMA_HAVE_STORE                        (1u << 4)
+/* The transaction MAY enter serial irrevocable mode in its dynamic scope.  */
+#define GTMA_MAY_ENTER_IRREVOCABLE     (1u << 5)
+/* The transaction WILL enter serial irrevocable mode.
+   An irrevocable block post-dominates the entire transaction, such
+   that all invocations of the transaction will go serial-irrevocable.
+   In such case, we don't bother instrumenting the transaction, and
+   tell the runtime that it should begin the transaction in
+   serial-irrevocable mode.  */
+#define GTMA_DOES_GO_IRREVOCABLE       (1u << 6)
+
+struct GTY(()) gimple_statement_transaction
+{
+  /* [ WORD 1-10 ]  */
+  struct gimple_statement_with_memory_ops_base gsbase;
+
+  /* [ WORD 11 ] */
+  gimple_seq body;
+
+  /* [ WORD 12 ] */
+  tree label;
+};
+
 #define DEFGSSTRUCT(SYM, STRUCT, HAS_TREE_OP)  SYM,
 enum gimple_statement_structure_enum {
 #include "gsstruct.def"
@@ -779,6 +825,7 @@ union GTY ((desc ("gimple_statement_structure (&%h)"), variable_size)) gimple_st
   struct gimple_statement_catch GTY ((tag ("GSS_CATCH"))) gimple_catch;
   struct gimple_statement_eh_filter GTY ((tag ("GSS_EH_FILTER"))) gimple_eh_filter;
   struct gimple_statement_eh_mnt GTY ((tag ("GSS_EH_MNT"))) gimple_eh_mnt;
+  struct gimple_statement_eh_else GTY ((tag ("GSS_EH_ELSE"))) gimple_eh_else;
   struct gimple_statement_phi GTY ((tag ("GSS_PHI"))) gimple_phi;
   struct gimple_statement_eh_ctrl GTY ((tag ("GSS_EH_CTRL"))) gimple_eh_ctrl;
   struct gimple_statement_try GTY ((tag ("GSS_TRY"))) gimple_try;
@@ -793,6 +840,7 @@ union GTY ((desc ("gimple_statement_structure (&%h)"), variable_size)) gimple_st
   struct gimple_statement_omp_continue GTY ((tag ("GSS_OMP_CONTINUE"))) gimple_omp_continue;
   struct gimple_statement_omp_atomic_load GTY ((tag ("GSS_OMP_ATOMIC_LOAD"))) gimple_omp_atomic_load;
   struct gimple_statement_omp_atomic_store GTY ((tag ("GSS_OMP_ATOMIC_STORE"))) gimple_omp_atomic_store;
+  struct gimple_statement_transaction GTY((tag ("GSS_TRANSACTION"))) gimple_transaction;
 };
 
 /* In gimple.c.  */
@@ -846,6 +894,7 @@ gimple gimple_build_asm_vec (const char *, VEC(tree,gc) *, VEC(tree,gc) *,
 gimple gimple_build_catch (tree, gimple_seq);
 gimple gimple_build_eh_filter (tree, gimple_seq);
 gimple gimple_build_eh_must_not_throw (tree);
+gimple gimple_build_eh_else (gimple_seq, gimple_seq);
 gimple gimple_build_try (gimple_seq, gimple_seq, enum gimple_try_flags);
 gimple gimple_build_wce (gimple_seq);
 gimple gimple_build_resx (int);
@@ -868,6 +917,7 @@ gimple gimple_build_omp_single (gimple_seq, tree);
 gimple gimple_build_cdt (tree, tree);
 gimple gimple_build_omp_atomic_load (tree, tree);
 gimple gimple_build_omp_atomic_store (tree);
+gimple gimple_build_transaction (gimple_seq, tree);
 gimple gimple_build_predict (enum br_predictor, enum prediction);
 enum gimple_statement_structure_enum gss_for_assign (enum tree_code);
 void sort_case_labels (VEC(tree,heap) *);
@@ -963,8 +1013,6 @@ extern bool is_gimple_non_addressable (tree t);
 
 /* Returns true iff T is a valid call address expression.  */
 extern bool is_gimple_call_addr (tree);
-/* If T makes a function call, returns the CALL_EXPR operand.  */
-extern tree get_call_expr_in (tree t);
 
 extern void recalculate_side_effects (tree);
 extern bool gimple_compare_field_offset (tree, tree);
@@ -1076,6 +1124,9 @@ extern tree canonicalize_cond_expr_cond (tree);
 /* In omp-low.c.  */
 extern tree omp_reduction_init (tree, tree);
 
+/* In trans-mem.c.  */
+extern void diagnose_tm_safe_errors (tree);
+
 /* In tree-nested.c.  */
 extern void lower_nested_functions (tree);
 extern void insert_field_into_struct (tree, tree);
@@ -1134,6 +1185,7 @@ gimple_has_substatements (gimple g)
     case GIMPLE_BIND:
     case GIMPLE_CATCH:
     case GIMPLE_EH_FILTER:
+    case GIMPLE_EH_ELSE:
     case GIMPLE_TRY:
     case GIMPLE_OMP_FOR:
     case GIMPLE_OMP_MASTER:
@@ -1145,6 +1197,7 @@ gimple_has_substatements (gimple g)
     case GIMPLE_OMP_SINGLE:
     case GIMPLE_OMP_CRITICAL:
     case GIMPLE_WITH_CLEANUP_EXPR:
+    case GIMPLE_TRANSACTION:
       return true;
 
     default:
@@ -3177,6 +3230,35 @@ gimple_eh_must_not_throw_set_fndecl (gimple gs, tree decl)
   gs->gimple_eh_mnt.fndecl = decl;
 }
 
+/* GIMPLE_EH_ELSE accessors.  */
+
+static inline gimple_seq
+gimple_eh_else_n_body (gimple gs)
+{
+  GIMPLE_CHECK (gs, GIMPLE_EH_ELSE);
+  return gs->gimple_eh_else.n_body;
+}
+
+static inline gimple_seq
+gimple_eh_else_e_body (gimple gs)
+{
+  GIMPLE_CHECK (gs, GIMPLE_EH_ELSE);
+  return gs->gimple_eh_else.e_body;
+}
+
+static inline void
+gimple_eh_else_set_n_body (gimple gs, gimple_seq seq)
+{
+  GIMPLE_CHECK (gs, GIMPLE_EH_ELSE);
+  gs->gimple_eh_else.n_body = seq;
+}
+
+static inline void
+gimple_eh_else_set_e_body (gimple gs, gimple_seq seq)
+{
+  GIMPLE_CHECK (gs, GIMPLE_EH_ELSE);
+  gs->gimple_eh_else.e_body = seq;
+}
 
 /* GIMPLE_TRY accessors. */
 
@@ -4555,6 +4637,67 @@ gimple_omp_continue_set_control_use (gimple g, tree use)
   g->gimple_omp_continue.control_use = use;
 }
 
+/* Return the body for the GIMPLE_TRANSACTION statement GS.  */
+
+static inline gimple_seq
+gimple_transaction_body (gimple gs)
+{
+  GIMPLE_CHECK (gs, GIMPLE_TRANSACTION);
+  return gs->gimple_transaction.body;
+}
+
+/* Return the label associated with a GIMPLE_TRANSACTION.  */
+
+static inline tree
+gimple_transaction_label (const_gimple gs)
+{
+  GIMPLE_CHECK (gs, GIMPLE_TRANSACTION);
+  return gs->gimple_transaction.label;
+}
+
+static inline tree *
+gimple_transaction_label_ptr (gimple gs)
+{
+  GIMPLE_CHECK (gs, GIMPLE_TRANSACTION);
+  return &gs->gimple_transaction.label;
+}
+
+/* Return the subcode associated with a GIMPLE_TRANSACTION.  */
+
+static inline unsigned int
+gimple_transaction_subcode (const_gimple gs)
+{
+  GIMPLE_CHECK (gs, GIMPLE_TRANSACTION);
+  return gs->gsbase.subcode;
+}
+
+/* Set BODY to be the body for the GIMPLE_TRANSACTION statement GS.  */
+
+static inline void
+gimple_transaction_set_body (gimple gs, gimple_seq body)
+{
+  GIMPLE_CHECK (gs, GIMPLE_TRANSACTION);
+  gs->gimple_transaction.body = body;
+}
+
+/* Set the label associated with a GIMPLE_TRANSACTION.  */
+
+static inline void
+gimple_transaction_set_label (gimple gs, tree label)
+{
+  GIMPLE_CHECK (gs, GIMPLE_TRANSACTION);
+  gs->gimple_transaction.label = label;
+}
+
+/* Set the subcode associated with a GIMPLE_TRANSACTION.  */
+
+static inline void
+gimple_transaction_set_subcode (gimple gs, unsigned int subcode)
+{
+  GIMPLE_CHECK (gs, GIMPLE_TRANSACTION);
+  gs->gsbase.subcode = subcode;
+}
+
 
 /* Return a pointer to the return value for GIMPLE_RETURN GS.  */
 
@@ -4981,6 +5124,12 @@ struct walk_stmt_info
      will be visited more than once.  */
   struct pointer_set_t *pset;
 
+  /* Operand returned by the callbacks.  This is set when calling
+     walk_gimple_seq.  If the walk_stmt_fn or walk_tree_fn callback
+     returns non-NULL, this field will contain the tree returned by
+     the last callback.  */
+  tree callback_result;
+
   /* Indicates whether the operand being examined may be replaced
      with something that matches is_gimple_val (if true) or something
      slightly more complicated (if false).  "Something" technically
@@ -4993,23 +5142,20 @@ struct walk_stmt_info
      statement 'foo (&var)', the flag VAL_ONLY will initially be set
      to true, however, when walking &var, the operand of that
      ADDR_EXPR does not need to be a GIMPLE value.  */
-  bool val_only;
+  BOOL_BITFIELD val_only : 1;
 
   /* True if we are currently walking the LHS of an assignment.  */
-  bool is_lhs;
+  BOOL_BITFIELD is_lhs : 1;
 
   /* Optional.  Set to true by the callback functions if they made any
      changes.  */
-  bool changed;
+  BOOL_BITFIELD changed : 1;
 
   /* True if we're interested in location information.  */
-  bool want_locations;
+  BOOL_BITFIELD want_locations : 1;
 
-  /* Operand returned by the callbacks.  This is set when calling
-     walk_gimple_seq.  If the walk_stmt_fn or walk_tree_fn callback
-     returns non-NULL, this field will contain the tree returned by
-     the last callback.  */
-  tree callback_result;
+  /* True if we've removed the statement that was processed.  */
+  BOOL_BITFIELD removed_stmt : 1;
 };
 
 /* Callback for walk_gimple_stmt.  Called for every statement found
index 8c2c5ac..99e0d0d 100644 (file)
@@ -413,6 +413,8 @@ create_tmp_var_name (const char *prefix)
       char *preftmp = ASTRDUP (prefix);
 
       remove_suffix (preftmp, strlen (preftmp));
+      clean_symbol_name (preftmp);
+
       prefix = preftmp;
     }
 
@@ -1072,6 +1074,12 @@ voidify_wrapper_expr (tree wrapper, tree temp)
                }
              break;
 
+           case TRANSACTION_EXPR:
+             TREE_SIDE_EFFECTS (*p) = 1;
+             TREE_TYPE (*p) = void_type_node;
+             p = &TRANSACTION_EXPR_BODY (*p);
+             break;
+
            default:
              goto out;
            }
@@ -6527,6 +6535,53 @@ gimplify_omp_atomic (tree *expr_p, gimple_seq *pre_p)
    return GS_ALL_DONE;
 }
 
+/* Gimplify a TRANSACTION_EXPR.  This involves gimplification of the
+   body, and adding some EH bits.  */
+
+static enum gimplify_status
+gimplify_transaction (tree *expr_p, gimple_seq *pre_p)
+{
+  tree expr = *expr_p, temp, tbody = TRANSACTION_EXPR_BODY (expr);
+  gimple g;
+  gimple_seq body = NULL;
+  struct gimplify_ctx gctx;
+  int subcode = 0;
+
+  /* Wrap the transaction body in a BIND_EXPR so we have a context
+     where to put decls for OpenMP.  */
+  if (TREE_CODE (tbody) != BIND_EXPR)
+    {
+      tree bind = build3 (BIND_EXPR, void_type_node, NULL, tbody, NULL);
+      TREE_SIDE_EFFECTS (bind) = 1;
+      SET_EXPR_LOCATION (bind, EXPR_LOCATION (tbody));
+      TRANSACTION_EXPR_BODY (expr) = bind;
+    }
+
+  push_gimplify_context (&gctx);
+  temp = voidify_wrapper_expr (*expr_p, NULL);
+
+  g = gimplify_and_return_first (TRANSACTION_EXPR_BODY (expr), &body);
+  pop_gimplify_context (g);
+
+  g = gimple_build_transaction (body, NULL);
+  if (TRANSACTION_EXPR_OUTER (expr))
+    subcode = GTMA_IS_OUTER;
+  else if (TRANSACTION_EXPR_RELAXED (expr))
+    subcode = GTMA_IS_RELAXED;
+  gimple_transaction_set_subcode (g, subcode);
+
+  gimplify_seq_add_stmt (pre_p, g);
+
+  if (temp)
+    {
+      *expr_p = temp;
+      return GS_OK;
+    }
+
+  *expr_p = NULL_TREE;
+  return GS_ALL_DONE;
+}
+
 /* Convert the GENERIC expression tree *EXPR_P to GIMPLE.  If the
    expression produces a value to be used as an operand inside a GIMPLE
    statement, the value will be stored back in *EXPR_P.  This value will
@@ -7251,6 +7306,10 @@ gimplify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p,
          ret = gimplify_omp_atomic (expr_p, pre_p);
          break;
 
+       case TRANSACTION_EXPR:
+         ret = gimplify_transaction (expr_p, pre_p);
+         break;
+
        case TRUTH_AND_EXPR:
        case TRUTH_OR_EXPR:
        case TRUTH_XOR_EXPR:
index 0b6531e..0e5727f 100644 (file)
@@ -38,6 +38,7 @@ DEFGSSTRUCT(GSS_CATCH, gimple_statement_catch, false)
 DEFGSSTRUCT(GSS_EH_FILTER, gimple_statement_eh_filter, false)
 DEFGSSTRUCT(GSS_EH_MNT, gimple_statement_eh_mnt, false)
 DEFGSSTRUCT(GSS_EH_CTRL, gimple_statement_eh_ctrl, false)
+DEFGSSTRUCT(GSS_EH_ELSE, gimple_statement_eh_else, false)
 DEFGSSTRUCT(GSS_WCE, gimple_statement_wce, false)
 DEFGSSTRUCT(GSS_OMP, gimple_statement_omp, false)
 DEFGSSTRUCT(GSS_OMP_CRITICAL, gimple_statement_omp_critical, false)
@@ -49,3 +50,4 @@ DEFGSSTRUCT(GSS_OMP_SINGLE, gimple_statement_omp_single, false)
 DEFGSSTRUCT(GSS_OMP_CONTINUE, gimple_statement_omp_continue, false)
 DEFGSSTRUCT(GSS_OMP_ATOMIC_LOAD, gimple_statement_omp_atomic_load, false)
 DEFGSSTRUCT(GSS_OMP_ATOMIC_STORE, gimple_statement_omp_atomic_store, false)
+DEFGSSTRUCT(GSS_TRANSACTION, gimple_statement_transaction, false)
diff --git a/gcc/gtm-builtins.def b/gcc/gtm-builtins.def
new file mode 100644 (file)
index 0000000..9fcbdb0
--- /dev/null
@@ -0,0 +1,208 @@
+DEF_TM_BUILTIN (BUILT_IN_TM_START, "_ITM_beginTransaction",
+               BT_FN_UINT_UINT, ATTR_TM_NOTHROW_LIST)
+
+DEF_TM_BUILTIN (BUILT_IN_TM_COMMIT, "_ITM_commitTransaction",
+               BT_FN_VOID, ATTR_TM_NOTHROW_LIST)
+DEF_TM_BUILTIN (BUILT_IN_TM_COMMIT_EH, "_ITM_commitTransactionEH",
+               BT_FN_VOID_PTR, ATTR_TM_NOTHROW_LIST)
+DEF_TM_BUILTIN (BUILT_IN_TM_ABORT, "_ITM_abortTransaction",
+               BT_FN_INT, ATTR_TM_NORETURN_NOTHROW_LIST)
+DEF_TM_BUILTIN (BUILT_IN_TM_IRREVOCABLE, "_ITM_changeTransactionMode",
+               BT_FN_INT_INT, ATTR_TM_NOTHROW_LIST)
+
+DEF_TM_BUILTIN (BUILT_IN_TM_MEMCPY, "_ITM_memcpyRtWt",
+               BT_FN_PTR_PTR_CONST_PTR_SIZE, ATTR_TM_TMPURE_NOTHROW_LIST)
+DEF_TM_BUILTIN (BUILT_IN_TM_MEMMOVE, "_ITM_memmoveRtWt",
+               BT_FN_PTR_PTR_CONST_PTR_SIZE, ATTR_TM_TMPURE_NOTHROW_LIST)
+DEF_TM_BUILTIN (BUILT_IN_TM_MEMSET, "_ITM_memsetW",
+               BT_FN_PTR_PTR_INT_SIZE, ATTR_TM_TMPURE_NOTHROW_LIST)
+
+DEF_TM_BUILTIN (BUILT_IN_TM_GETTMCLONE_IRR, "_ITM_getTMCloneOrIrrevocable",
+               BT_FN_PTR_PTR, ATTR_TM_CONST_NOTHROW_LIST)
+DEF_TM_BUILTIN (BUILT_IN_TM_GETTMCLONE_SAFE, "_ITM_getTMCloneSafe",
+               BT_FN_PTR_PTR, ATTR_TM_CONST_NOTHROW_LIST)
+
+/* Memory allocation builtins.  */
+DEF_TM_BUILTIN (BUILT_IN_TM_MALLOC, "_ITM_malloc",
+               BT_FN_PTR_SIZE, ATTR_TMPURE_MALLOC_NOTHROW_LIST)
+DEF_TM_BUILTIN (BUILT_IN_TM_CALLOC, "_ITM_calloc",
+               BT_FN_PTR_SIZE_SIZE, ATTR_TMPURE_MALLOC_NOTHROW_LIST)
+DEF_TM_BUILTIN (BUILT_IN_TM_FREE, "_ITM_free",
+               BT_FN_VOID_PTR, ATTR_TMPURE_NOTHROW_LIST)
+
+/* Logging builtins.  */
+DEF_TM_BUILTIN (BUILT_IN_TM_LOG_1, "_ITM_LU1",
+               BT_FN_VOID_VPTR, ATTR_TM_TMPURE_NOTHROW_LIST)
+DEF_TM_BUILTIN (BUILT_IN_TM_LOG_2, "_ITM_LU2",
+               BT_FN_VOID_VPTR, ATTR_TM_TMPURE_NOTHROW_LIST)
+DEF_TM_BUILTIN (BUILT_IN_TM_LOG_4, "_ITM_LU4",
+               BT_FN_VOID_VPTR, ATTR_TM_TMPURE_NOTHROW_LIST)
+DEF_TM_BUILTIN (BUILT_IN_TM_LOG_8, "_ITM_LU8",
+               BT_FN_VOID_VPTR, ATTR_TM_TMPURE_NOTHROW_LIST)
+DEF_TM_BUILTIN (BUILT_IN_TM_LOG_FLOAT, "_ITM_LF",
+               BT_FN_VOID_VPTR, ATTR_TM_TMPURE_NOTHROW_LIST)
+DEF_TM_BUILTIN (BUILT_IN_TM_LOG_DOUBLE, "_ITM_LD",
+               BT_FN_VOID_VPTR, ATTR_TM_TMPURE_NOTHROW_LIST)
+DEF_TM_BUILTIN (BUILT_IN_TM_LOG_LDOUBLE, "_ITM_LE",
+               BT_FN_VOID_VPTR, ATTR_TM_TMPURE_NOTHROW_LIST)
+DEF_TM_BUILTIN (BUILT_IN_TM_LOG, "_ITM_LB",
+               BT_FN_VOID_VPTR_SIZE, ATTR_TM_TMPURE_NOTHROW_LIST)
+
+/* These stubs should get defined in the backend if applicable.  */
+DEF_BUILTIN_STUB (BUILT_IN_TM_LOG_M64, "__builtin__ITM_LM64")
+DEF_BUILTIN_STUB (BUILT_IN_TM_LOG_M128, "__builtin__ITM_LM128")
+DEF_BUILTIN_STUB (BUILT_IN_TM_LOG_M256, "__builtin__ITM_LM256")
+
+/* Writes.
+
+   Note: The writes must follow the following order: STORE, WAR, WAW.
+   The TM optimizations depend on this order.
+
+   BUILT_IN_TM_STORE_1 must be the first builtin.
+   BUILTIN_TM_LOAD_STORE_P depends on this.  */
+DEF_TM_BUILTIN (BUILT_IN_TM_STORE_1, "_ITM_WU1",
+               BT_FN_VOID_VPTR_I1, ATTR_TM_NOTHROW_LIST)
+DEF_TM_BUILTIN (BUILT_IN_TM_STORE_WAR_1, "_ITM_WaRU1",
+               BT_FN_VOID_VPTR_I1, ATTR_TM_NOTHROW_LIST)
+DEF_TM_BUILTIN (BUILT_IN_TM_STORE_WAW_1, "_ITM_WaWU1",
+               BT_FN_VOID_VPTR_I1, ATTR_TM_NOTHROW_LIST)
+
+DEF_TM_BUILTIN (BUILT_IN_TM_STORE_2, "_ITM_WU2",
+               BT_FN_VOID_VPTR_I2, ATTR_TM_NOTHROW_LIST)
+DEF_TM_BUILTIN (BUILT_IN_TM_STORE_WAR_2, "_ITM_WaRU2",
+               BT_FN_VOID_VPTR_I2, ATTR_TM_NOTHROW_LIST)
+DEF_TM_BUILTIN (BUILT_IN_TM_STORE_WAW_2, "_ITM_WaWU2",
+               BT_FN_VOID_VPTR_I2, ATTR_TM_NOTHROW_LIST)
+
+DEF_TM_BUILTIN (BUILT_IN_TM_STORE_4, "_ITM_WU4",
+               BT_FN_VOID_VPTR_I4, ATTR_TM_NOTHROW_LIST)
+DEF_TM_BUILTIN (BUILT_IN_TM_STORE_WAR_4, "_ITM_WaRU4",
+               BT_FN_VOID_VPTR_I4, ATTR_TM_NOTHROW_LIST)
+DEF_TM_BUILTIN (BUILT_IN_TM_STORE_WAW_4, "_ITM_WaWU4",
+               BT_FN_VOID_VPTR_I4, ATTR_TM_NOTHROW_LIST)
+
+DEF_TM_BUILTIN (BUILT_IN_TM_STORE_8, "_ITM_WU8",
+               BT_FN_VOID_VPTR_I8, ATTR_TM_NOTHROW_LIST)
+DEF_TM_BUILTIN (BUILT_IN_TM_STORE_WAR_8, "_ITM_WaRU8",
+               BT_FN_VOID_VPTR_I8, ATTR_TM_NOTHROW_LIST)
+DEF_TM_BUILTIN (BUILT_IN_TM_STORE_WAW_8, "_ITM_WaWU8",
+               BT_FN_VOID_VPTR_I8, ATTR_TM_NOTHROW_LIST)
+
+DEF_TM_BUILTIN (BUILT_IN_TM_STORE_FLOAT, "_ITM_WF",
+               BT_FN_VOID_VPTR_FLOAT, ATTR_TM_NOTHROW_LIST)
+DEF_TM_BUILTIN (BUILT_IN_TM_STORE_WAR_FLOAT, "_ITM_WaRF",
+               BT_FN_VOID_VPTR_FLOAT, ATTR_TM_NOTHROW_LIST)
+DEF_TM_BUILTIN (BUILT_IN_TM_STORE_WAW_FLOAT, "_ITM_WaWF",
+               BT_FN_VOID_VPTR_FLOAT, ATTR_TM_NOTHROW_LIST)
+
+DEF_TM_BUILTIN (BUILT_IN_TM_STORE_DOUBLE, "_ITM_WD",
+               BT_FN_VOID_VPTR_DOUBLE, ATTR_TM_NOTHROW_LIST)
+DEF_TM_BUILTIN (BUILT_IN_TM_STORE_WAR_DOUBLE, "_ITM_WaRD",
+               BT_FN_VOID_VPTR_DOUBLE, ATTR_TM_NOTHROW_LIST)
+DEF_TM_BUILTIN (BUILT_IN_TM_STORE_WAW_DOUBLE, "_ITM_WaWD",
+               BT_FN_VOID_VPTR_DOUBLE, ATTR_TM_NOTHROW_LIST)
+
+/* These stubs should get defined in the backend if applicable.  */
+DEF_BUILTIN_STUB (BUILT_IN_TM_STORE_M64, "__builtin__ITM_WM64")
+DEF_BUILTIN_STUB (BUILT_IN_TM_STORE_WAR_M64, "__builtin__ITM_WaRM64")
+DEF_BUILTIN_STUB (BUILT_IN_TM_STORE_WAW_M64, "__builtin__ITM_WaWM64")
+DEF_BUILTIN_STUB (BUILT_IN_TM_STORE_M128, "__builtin__ITM_WM128")
+DEF_BUILTIN_STUB (BUILT_IN_TM_STORE_WAR_M128, "__builtin__ITM_WaRM128")
+DEF_BUILTIN_STUB (BUILT_IN_TM_STORE_WAW_M128, "__builtin__ITM_WaWM128")
+DEF_BUILTIN_STUB (BUILT_IN_TM_STORE_M256, "__builtin__ITM_WM256")
+DEF_BUILTIN_STUB (BUILT_IN_TM_STORE_WAR_M256, "__builtin__ITM_WaRM256")
+DEF_BUILTIN_STUB (BUILT_IN_TM_STORE_WAW_M256, "__builtin__ITM_WaWM256")
+
+DEF_TM_BUILTIN (BUILT_IN_TM_STORE_LDOUBLE, "_ITM_WE",
+               BT_FN_VOID_VPTR_LDOUBLE, ATTR_TM_NOTHROW_LIST)
+DEF_TM_BUILTIN (BUILT_IN_TM_STORE_WAR_LDOUBLE, "_ITM_WaRE",
+               BT_FN_VOID_VPTR_LDOUBLE, ATTR_TM_NOTHROW_LIST)
+DEF_TM_BUILTIN (BUILT_IN_TM_STORE_WAW_LDOUBLE, "_ITM_WaWE",
+               BT_FN_VOID_VPTR_LDOUBLE, ATTR_TM_NOTHROW_LIST)
+/* Note: BUILT_IN_TM_STORE_WAW_LDOUBLE must be the last TM store.
+   BUILTIN_TM_STORE_P depends on this.  */
+
+/* Reads.
+
+   Note: The reads must follow the following order: LOAD, RAR, RAW, RFW.
+   The TM optimizations depend on this order.  */
+DEF_TM_BUILTIN (BUILT_IN_TM_LOAD_1, "_ITM_RU1",
+               BT_FN_I1_VPTR, ATTR_TM_PURE_TMPURE_NOTHROW_LIST)
+DEF_TM_BUILTIN (BUILT_IN_TM_LOAD_RAR_1, "_ITM_RaRU1",
+               BT_FN_I1_VPTR, ATTR_TM_PURE_TMPURE_NOTHROW_LIST)
+DEF_TM_BUILTIN (BUILT_IN_TM_LOAD_RAW_1, "_ITM_RaWU1",
+               BT_FN_I1_VPTR, ATTR_TM_PURE_TMPURE_NOTHROW_LIST)
+DEF_TM_BUILTIN (BUILT_IN_TM_LOAD_RFW_1, "_ITM_RfWU1",
+               BT_FN_I1_VPTR, ATTR_TM_PURE_TMPURE_NOTHROW_LIST)
+
+DEF_TM_BUILTIN (BUILT_IN_TM_LOAD_2, "_ITM_RU2",
+               BT_FN_I2_VPTR, ATTR_TM_PURE_TMPURE_NOTHROW_LIST)
+DEF_TM_BUILTIN (BUILT_IN_TM_LOAD_RAR_2, "_ITM_RaRU2",
+               BT_FN_I2_VPTR, ATTR_TM_PURE_TMPURE_NOTHROW_LIST)
+DEF_TM_BUILTIN (BUILT_IN_TM_LOAD_RAW_2, "_ITM_RaWU2",
+               BT_FN_I2_VPTR, ATTR_TM_PURE_TMPURE_NOTHROW_LIST)
+DEF_TM_BUILTIN (BUILT_IN_TM_LOAD_RFW_2, "_ITM_RfWU2",
+               BT_FN_I2_VPTR, ATTR_TM_PURE_TMPURE_NOTHROW_LIST)
+
+DEF_TM_BUILTIN (BUILT_IN_TM_LOAD_4, "_ITM_RU4",
+               BT_FN_I4_VPTR, ATTR_TM_PURE_TMPURE_NOTHROW_LIST)
+DEF_TM_BUILTIN (BUILT_IN_TM_LOAD_RAR_4, "_ITM_RaRU4",
+               BT_FN_I4_VPTR, ATTR_TM_PURE_TMPURE_NOTHROW_LIST)
+DEF_TM_BUILTIN (BUILT_IN_TM_LOAD_RAW_4, "_ITM_RaWU4",
+               BT_FN_I4_VPTR, ATTR_TM_PURE_TMPURE_NOTHROW_LIST)
+DEF_TM_BUILTIN (BUILT_IN_TM_LOAD_RFW_4, "_ITM_RfWU4",
+               BT_FN_I4_VPTR, ATTR_TM_PURE_TMPURE_NOTHROW_LIST)
+
+DEF_TM_BUILTIN (BUILT_IN_TM_LOAD_8, "_ITM_RU8",
+               BT_FN_I8_VPTR, ATTR_TM_PURE_TMPURE_NOTHROW_LIST)
+DEF_TM_BUILTIN (BUILT_IN_TM_LOAD_RAR_8, "_ITM_RaRU8",
+               BT_FN_I8_VPTR, ATTR_TM_PURE_TMPURE_NOTHROW_LIST)
+DEF_TM_BUILTIN (BUILT_IN_TM_LOAD_RAW_8, "_ITM_RaWU8",
+               BT_FN_I8_VPTR, ATTR_TM_PURE_TMPURE_NOTHROW_LIST)
+DEF_TM_BUILTIN (BUILT_IN_TM_LOAD_RFW_8, "_ITM_RfWU8",
+               BT_FN_I8_VPTR, ATTR_TM_PURE_TMPURE_NOTHROW_LIST)
+
+DEF_TM_BUILTIN (BUILT_IN_TM_LOAD_FLOAT, "_ITM_RF",
+               BT_FN_FLOAT_VPTR, ATTR_TM_PURE_TMPURE_NOTHROW_LIST)
+DEF_TM_BUILTIN (BUILT_IN_TM_LOAD_RAR_FLOAT, "_ITM_RaRF",
+               BT_FN_FLOAT_VPTR, ATTR_TM_PURE_TMPURE_NOTHROW_LIST)
+DEF_TM_BUILTIN (BUILT_IN_TM_LOAD_RAW_FLOAT, "_ITM_RaWF",
+               BT_FN_FLOAT_VPTR, ATTR_TM_PURE_TMPURE_NOTHROW_LIST)
+DEF_TM_BUILTIN (BUILT_IN_TM_LOAD_RFW_FLOAT, "_ITM_RfWF",
+               BT_FN_FLOAT_VPTR, ATTR_TM_PURE_TMPURE_NOTHROW_LIST)
+
+DEF_TM_BUILTIN (BUILT_IN_TM_LOAD_DOUBLE, "_ITM_RD",
+               BT_FN_DOUBLE_VPTR, ATTR_TM_PURE_TMPURE_NOTHROW_LIST)
+DEF_TM_BUILTIN (BUILT_IN_TM_LOAD_RAR_DOUBLE, "_ITM_RaRD",
+               BT_FN_FLOAT_VPTR, ATTR_TM_PURE_TMPURE_NOTHROW_LIST)
+DEF_TM_BUILTIN (BUILT_IN_TM_LOAD_RAW_DOUBLE, "_ITM_RaWD",
+               BT_FN_FLOAT_VPTR, ATTR_TM_PURE_TMPURE_NOTHROW_LIST)
+DEF_TM_BUILTIN (BUILT_IN_TM_LOAD_RFW_DOUBLE, "_ITM_RfWD",
+               BT_FN_FLOAT_VPTR, ATTR_TM_PURE_TMPURE_NOTHROW_LIST)
+
+/* These stubs should get defined in the backend if applicable.  */
+DEF_BUILTIN_STUB (BUILT_IN_TM_LOAD_M64, "__builtin__ITM_RM64")
+DEF_BUILTIN_STUB (BUILT_IN_TM_LOAD_RAR_M64, "__builtin__ITM_RaRM64")
+DEF_BUILTIN_STUB (BUILT_IN_TM_LOAD_RAW_M64, "__builtin__ITM_RaRM64")
+DEF_BUILTIN_STUB (BUILT_IN_TM_LOAD_RFW_M64, "__builtin__ITM_RfWM64")
+DEF_BUILTIN_STUB (BUILT_IN_TM_LOAD_M128, "__builtin__ITM_RM128")
+DEF_BUILTIN_STUB (BUILT_IN_TM_LOAD_RAR_M128, "__builtin__ITM_RaRM128")
+DEF_BUILTIN_STUB (BUILT_IN_TM_LOAD_RAW_M128, "__builtin__ITM_RaRM128")
+DEF_BUILTIN_STUB (BUILT_IN_TM_LOAD_RFW_M128, "__builtin__ITM_RfWM128")
+DEF_BUILTIN_STUB (BUILT_IN_TM_LOAD_M256, "__builtin__ITM_RM256")
+DEF_BUILTIN_STUB (BUILT_IN_TM_LOAD_RAR_M256, "__builtin__ITM_RaRM256")
+DEF_BUILTIN_STUB (BUILT_IN_TM_LOAD_RAW_M256, "__builtin__ITM_RaRM256")
+DEF_BUILTIN_STUB (BUILT_IN_TM_LOAD_RFW_M256, "__builtin__ITM_RfWM256")
+
+DEF_TM_BUILTIN (BUILT_IN_TM_LOAD_LDOUBLE, "_ITM_RE",
+               BT_FN_LDOUBLE_VPTR, ATTR_TM_PURE_TMPURE_NOTHROW_LIST)
+DEF_TM_BUILTIN (BUILT_IN_TM_LOAD_RAR_LDOUBLE, "_ITM_RaRE",
+               BT_FN_LDOUBLE_VPTR, ATTR_TM_PURE_TMPURE_NOTHROW_LIST)
+DEF_TM_BUILTIN (BUILT_IN_TM_LOAD_RAW_LDOUBLE, "_ITM_RaWE",
+               BT_FN_LDOUBLE_VPTR, ATTR_TM_PURE_TMPURE_NOTHROW_LIST)
+DEF_TM_BUILTIN (BUILT_IN_TM_LOAD_RFW_LDOUBLE, "_ITM_RfWE",
+               BT_FN_LDOUBLE_VPTR, ATTR_TM_PURE_TMPURE_NOTHROW_LIST)
+
+/* Note: BUILT_IN_TM_LOAD_RFW_LDOUBLE must be the last TM load as well
+   as the last builtin.  BUILTIN_TM_LOAD_STORE_P and BUILTIN_TM_LOAD_P
+   depend on this.  */
index 31c88e5..3dadf8d 100644 (file)
@@ -284,6 +284,14 @@ can_inline_edge_p (struct cgraph_edge *e, bool report)
       e->inline_failed = CIF_EH_PERSONALITY;
       inlinable = false;
     }
+  /* TM pure functions should not get inlined if the outer function is
+     a TM safe function.  */
+  else if (is_tm_pure (callee->decl)
+          && is_tm_safe (e->caller->decl))
+    {
+      e->inline_failed = CIF_UNSPECIFIED;
+      inlinable = false;
+    }
   /* Don't inline if the callee can throw non-call exceptions but the
      caller cannot.
      FIXME: this is obviously wrong for LTO where STRUCT_FUNCTION is missing.
index 8145957..dc61c0b 100644 (file)
@@ -139,6 +139,7 @@ static tree scan_omp_1_op (tree *, int *, void *);
     case GIMPLE_TRY: \
     case GIMPLE_CATCH: \
     case GIMPLE_EH_FILTER: \
+    case GIMPLE_TRANSACTION: \
       /* The sub-statements for these should be walked.  */ \
       *handled_ops_p = false; \
       break;
index 3153fe5..9fdb226 100644 (file)
@@ -784,6 +784,8 @@ finish_options (struct gcc_options *opts, struct gcc_options *opts_set,
 #endif
       if (!opts->x_flag_fat_lto_objects && !HAVE_LTO_PLUGIN)
         error_at (loc, "-fno-fat-lto-objects are supported only with linker plugin.");
+      if (opts->x_flag_tm)
+       error_at (loc, "LTO is currently not supported with transactional memory");
 }
   if ((opts->x_flag_lto_partition_balanced != 0) + (opts->x_flag_lto_partition_1to1 != 0)
        + (opts->x_flag_lto_partition_none != 0) >= 1)
index 661b623..e47eddf 100644 (file)
@@ -606,6 +606,10 @@ extern bool unlikely_text_section_p (section *);
 extern void switch_to_section (section *);
 extern void output_section_asm_op (const void *);
 
+extern void record_tm_clone_pair (tree, tree);
+extern void finish_tm_clone_pairs (void);
+extern tree get_tm_clone_pair (tree);
+
 extern void default_asm_output_source_filename (FILE *, const char *);
 extern void output_file_directive (FILE *, const char *);
 
index a7ae091..239b684 100644 (file)
@@ -872,6 +872,13 @@ DEFPARAM (PARAM_IPA_SRA_PTR_GROWTH_FACTOR,
          "a pointer to an aggregate with",
          2, 0, 0)
 
+DEFPARAM (PARAM_TM_MAX_AGGREGATE_SIZE,
+         "tm-max-aggregate-size",
+         "Size in bytes after which thread-local aggregates should be "
+         "instrumented with the logging functions instead of save/restore "
+         "pairs",
+         9, 0, 0)
+
 DEFPARAM (PARAM_IPA_CP_VALUE_LIST_SIZE,
          "ipa-cp-value-list-size",
          "Maximum size of a list of values associated with each parameter for "
index 887007f..a351241 100644 (file)
@@ -1174,9 +1174,11 @@ init_optimization_passes (void)
   p = &all_lowering_passes;
   NEXT_PASS (pass_warn_unused_result);
   NEXT_PASS (pass_diagnose_omp_blocks);
+  NEXT_PASS (pass_diagnose_tm_blocks);
   NEXT_PASS (pass_mudflap_1);
   NEXT_PASS (pass_lower_omp);
   NEXT_PASS (pass_lower_cf);
+  NEXT_PASS (pass_lower_tm);
   NEXT_PASS (pass_refactor_eh);
   NEXT_PASS (pass_lower_eh);
   NEXT_PASS (pass_build_cfg);
@@ -1241,6 +1243,7 @@ init_optimization_passes (void)
     }
   NEXT_PASS (pass_ipa_increase_alignment);
   NEXT_PASS (pass_ipa_matrix_reorg);
+  NEXT_PASS (pass_ipa_tm);
   NEXT_PASS (pass_ipa_lower_emutls);
   *p = NULL;
 
@@ -1400,6 +1403,13 @@ init_optimization_passes (void)
       NEXT_PASS (pass_uncprop);
       NEXT_PASS (pass_local_pure_const);
     }
+  NEXT_PASS (pass_tm_init);
+    {
+      struct opt_pass **p = &pass_tm_init.pass.sub;
+      NEXT_PASS (pass_tm_mark);
+      NEXT_PASS (pass_tm_memopt);
+      NEXT_PASS (pass_tm_edges);
+    }
   NEXT_PASS (pass_lower_complex_O0);
   NEXT_PASS (pass_cleanup_eh);
   NEXT_PASS (pass_lower_resx);
index 1a1e33f..7fb71d0 100644 (file)
@@ -424,6 +424,8 @@ print_node (FILE *file, const char *prefix, tree node, int indent)
        fputs (" built-in", file);
       if (code == FUNCTION_DECL && DECL_STATIC_CHAIN (node))
        fputs (" static-chain", file);
+      if (TREE_CODE (node) == FUNCTION_DECL && decl_is_tm_clone (node))
+       fputs (" tm-clone", file);
 
       if (code == FIELD_DECL && DECL_PACKED (node))
        fputs (" packed", file);
index d3ecb73..ae05204 100644 (file)
@@ -3287,6 +3287,7 @@ peep2_attempt (basic_block bb, rtx insn, int match_len, rtx attempt)
          {
          case REG_NORETURN:
          case REG_SETJMP:
+         case REG_TM:
            add_reg_note (new_insn, REG_NOTE_KIND (note),
                          XEXP (note, 0));
            break;
index d103afe..f2f0973 100644 (file)
@@ -203,6 +203,11 @@ REG_NOTE (CROSSING_JUMP)
    functions that can return twice.  */
 REG_NOTE (SETJMP)
 
+/* This kind of note is generated at each transactional memory
+   builtin, to indicate we need to generate transaction restart
+   edges for this insn.  */
+REG_NOTE (TM)
+
 /* Indicates the cumulative offset of the stack pointer accounting
    for pushed arguments.  This will only be generated when
    ACCUMULATE_OUTGOING_ARGS is false.  */
index 54d9eb1..7c4a49b 100644 (file)
@@ -1918,6 +1918,7 @@ alloc_reg_note (enum reg_note kind, rtx datum, rtx list)
     case REG_CC_USER:
     case REG_LABEL_TARGET:
     case REG_LABEL_OPERAND:
+    case REG_TM:
       /* These types of register notes use an INSN_LIST rather than an
         EXPR_LIST, so that copying is done right and dumps look
         better.  */
index a83088d..62bd06e 100644 (file)
@@ -1003,6 +1003,24 @@ DEFHOOK
  (enum machine_mode mode, const_tree type, int misalignment, bool is_packed),
  default_builtin_support_vector_misalignment)
 
+/* Return the builtin decl needed to load a vector of TYPE.  */
+DEFHOOK
+(builtin_tm_load,
+ "This hook should return the built-in decl needed to load a vector of the "
+ "given type within a transaction.",
+ tree,
+ (tree),
+ default_builtin_tm_load_store)
+
+/* Return the builtin decl needed to store a vector of TYPE.  */
+DEFHOOK
+(builtin_tm_store,
+ "This hook should return the built-in decl needed to store a vector of the "
+ "given type within a transaction.",
+ tree,
+ (tree),
+ default_builtin_tm_load_store)
+
 /* Returns the preferred mode for SIMD operations for the specified
    scalar mode.  */
 DEFHOOK
index 81fd12f..2b4fd27 100644 (file)
@@ -1214,6 +1214,12 @@ default_have_conditional_execution (void)
 #endif
 }
 
+tree
+default_builtin_tm_load_store (tree ARG_UNUSED (type))
+{
+  return NULL_TREE;
+}
+
 /* Compute cost of moving registers to/from memory.  */
 
 int
index f19fb50..8618115 100644 (file)
@@ -152,6 +152,9 @@ extern bool default_addr_space_subset_p (addr_space_t, addr_space_t);
 extern rtx default_addr_space_convert (rtx, tree, tree);
 extern unsigned int default_case_values_threshold (void);
 extern bool default_have_conditional_execution (void);
+
+extern tree default_builtin_tm_load_store (tree);
+
 extern int default_memory_move_cost (enum machine_mode, reg_class_t, bool);
 extern int default_register_move_cost (enum machine_mode, reg_class_t,
                                       reg_class_t);
index a62b11c..c095293 100644 (file)
@@ -1,3 +1,14 @@
+2011-11-07  Richard Henderson  <rth@redhat.com>
+           Aldy Hernandez  <aldyh@redhat.com>
+           Torvald Riegel  <triegel@redhat.com>
+
+       Merged from transactional-memory.
+
+       * g++.dg/dg.exp: Run transactional memory tests.
+       * g++.dg/tm: New directory with new tests.
+       * gcc.dg/tm: New directory with new tests.
+       * c-c++-common/tm: New directory with new tests.
+
 2011-11-08  Dodji Seketeli  <dodji@redhat.com>
 
        Fix context handling of alias-declaration
diff --git a/gcc/testsuite/c-c++-common/tm/20100127.c b/gcc/testsuite/c-c++-common/tm/20100127.c
new file mode 100644 (file)
index 0000000..c25336d
--- /dev/null
@@ -0,0 +1,36 @@
+/* { dg-do compile } */
+/* { dg-options "-fgnu-tm -O -fdump-tree-tmmark" } */
+
+/* Test that `nontrxn' doesn't end up inside the transaction.  */
+
+typedef struct node {
+  int * val;
+  struct node *next;
+} node_t;
+
+node_t *next;
+int nontrxn1, nontrxn;
+
+static int set_remove(int * val)
+{
+  int result;
+  int * v;
+  __transaction_relaxed {
+    v = next->val;
+    result = (v == val);
+    if (result)
+      result = 2;
+  }
+  return result;
+}
+
+void test(void *data)
+{
+  extern void bark(void);
+  if (set_remove(0))
+    bark();
+  nontrxn = 99;                        /* Should be outside transaction.  */
+}
+
+/* { dg-final { scan-tree-dump-times "_ITM_W.*nontrxn" 0 "tmmark" } } */
+/* { dg-final { cleanup-tree-dump "tmmark" } } */
diff --git a/gcc/testsuite/c-c++-common/tm/abort-1.c b/gcc/testsuite/c-c++-common/tm/abort-1.c
new file mode 100644 (file)
index 0000000..90830f4
--- /dev/null
@@ -0,0 +1,6 @@
+/* { dg-do compile } */
+
+void f(void)
+{
+  __transaction_cancel;                /* { dg-error "without transactional" } */
+}
diff --git a/gcc/testsuite/c-c++-common/tm/abort-2.c b/gcc/testsuite/c-c++-common/tm/abort-2.c
new file mode 100644 (file)
index 0000000..727c634
--- /dev/null
@@ -0,0 +1,11 @@
+/* { dg-do compile } */
+/* { dg-options "-fgnu-tm" } */
+
+int g;
+void f(void)
+{
+  __transaction_atomic {
+    if (g == 0)
+      __transaction_cancel;
+  }
+}
diff --git a/gcc/testsuite/c-c++-common/tm/abort-3.c b/gcc/testsuite/c-c++-common/tm/abort-3.c
new file mode 100644 (file)
index 0000000..f2cf5b5
--- /dev/null
@@ -0,0 +1,8 @@
+/* { dg-do compile } */
+
+void f(void)
+{
+  __transaction_atomic {   /* { dg-error "__transaction_atomic. without trans" } */
+    __transaction_cancel;  /* { dg-error "_cancel. without trans" } */
+  }
+}
diff --git a/gcc/testsuite/c-c++-common/tm/atomic-1.c b/gcc/testsuite/c-c++-common/tm/atomic-1.c
new file mode 100644 (file)
index 0000000..e301f1f
--- /dev/null
@@ -0,0 +1,9 @@
+/* { dg-do compile } */
+
+int g;
+void f(void)
+{
+  __transaction_atomic {       /* { dg-error "without transactional memory" } */
+    g++;
+  }
+}
diff --git a/gcc/testsuite/c-c++-common/tm/atomic-2.c b/gcc/testsuite/c-c++-common/tm/atomic-2.c
new file mode 100644 (file)
index 0000000..f232766
--- /dev/null
@@ -0,0 +1,10 @@
+/* { dg-do compile } */
+/* { dg-options "-fgnu-tm" } */
+
+int g;
+void f(void)
+{
+  __transaction_atomic {
+    g++;
+  }
+}
diff --git a/gcc/testsuite/c-c++-common/tm/attrib-1.c b/gcc/testsuite/c-c++-common/tm/attrib-1.c
new file mode 100644 (file)
index 0000000..536aeb3
--- /dev/null
@@ -0,0 +1,25 @@
+/* { dg-do compile } */
+/* { dg-options "-fgnu-tm" } */
+
+#define TC     __attribute__((transaction_callable))
+#define TU     __attribute__((transaction_unsafe))
+#define TP     __attribute__((transaction_pure))
+#define TS     __attribute__((transaction_safe))
+extern void f1(void) TC;
+extern void f2(void) TU;
+extern void f3(void) TP;
+extern void f4(void) TS;
+
+extern void g1(void) TC TS;    /* { dg-error "previously declared" } */
+
+extern int v1 TP;              /* { dg-warning "ignored" } */
+
+typedef void t1(void) TC;
+typedef void (*t2)(void) TC;
+typedef int t3 TC;             /* { dg-warning "ignored" } */
+
+typedef void u0(void);
+typedef u0 u1 TC;
+typedef u1 u2 TP;              /* { dg-error "previously declared" } */
+typedef u0 *u3 TS;
+typedef u3 u4 TU;              /* { dg-error "previously declared" } */
diff --git a/gcc/testsuite/c-c++-common/tm/cancel-1.c b/gcc/testsuite/c-c++-common/tm/cancel-1.c
new file mode 100644 (file)
index 0000000..6d60f26
--- /dev/null
@@ -0,0 +1,17 @@
+/* { dg-do compile } */
+/* { dg-options "-fgnu-tm" } */
+
+void unsafe(void) __attribute__((transaction_unsafe));
+
+void
+f(void)
+{
+  int a;
+  __transaction_atomic {
+    a = 1;
+    __transaction_atomic {
+      __transaction_cancel;
+    }
+  }
+  unsafe();
+}
diff --git a/gcc/testsuite/c-c++-common/tm/freq.c b/gcc/testsuite/c-c++-common/tm/freq.c
new file mode 100644 (file)
index 0000000..31df167
--- /dev/null
@@ -0,0 +1,14 @@
+/* { dg-do compile } */
+/* { dg-options "-fgnu-tm -O" } */
+
+extern __attribute__((transaction_safe)) void TMreleaseNode ();
+
+int global;
+
+__attribute__((transaction_safe))
+void
+TMrbtree_insert ()
+{
+  if (global)
+    TMreleaseNode();
+}
diff --git a/gcc/testsuite/c-c++-common/tm/inline-asm-2.c b/gcc/testsuite/c-c++-common/tm/inline-asm-2.c
new file mode 100644 (file)
index 0000000..7d429fb
--- /dev/null
@@ -0,0 +1,8 @@
+// { dg-do compile }
+// { dg-options "-fgnu-tm" }
+
+__attribute__((transaction_callable))
+void func()
+{
+  __asm__ ("");
+}
diff --git a/gcc/testsuite/c-c++-common/tm/inline-asm.c b/gcc/testsuite/c-c++-common/tm/inline-asm.c
new file mode 100644 (file)
index 0000000..eefd347
--- /dev/null
@@ -0,0 +1,17 @@
+/* { dg-do compile } */
+/* { dg-options "-fgnu-tm -O1" } */
+
+static inline void
+inline_death ()
+{
+  __asm__ ("");                        /* { dg-error "asm not allowed" } */
+}
+
+void
+tranfunction ()
+{
+  __transaction_atomic
+    {
+      inline_death ();
+    }
+}
diff --git a/gcc/testsuite/c-c++-common/tm/ipa-1.c b/gcc/testsuite/c-c++-common/tm/ipa-1.c
new file mode 100644 (file)
index 0000000..961f7fe
--- /dev/null
@@ -0,0 +1,23 @@
+/* { dg-do compile } */
+/* { dg-options "-fgnu-tm -O -fdump-ipa-tmipa" } */
+
+int val, george;
+
+extern void func();
+
+int set_remove(void)
+{
+  int result = 8;
+  __transaction_atomic  {
+    result = george;
+    if (val)
+      goto out;
+  }
+ out:
+  func();
+  return result;
+}
+
+
+/* { dg-final { scan-ipa-dump-not "getTMCloneOrIrrevocable" "tmipa" } } */
+/* { dg-final { cleanup-ipa-dump "tmipa" } } */
diff --git a/gcc/testsuite/c-c++-common/tm/malloc.c b/gcc/testsuite/c-c++-common/tm/malloc.c
new file mode 100644 (file)
index 0000000..de7a766
--- /dev/null
@@ -0,0 +1,24 @@
+/* { dg-do compile } */
+/* { dg-options "-fgnu-tm -fdump-tree-tmmark" } */
+
+#include <stdlib.h>
+
+char *z;
+
+void foobar(void)
+{
+    char *p, *q;
+    __transaction_atomic {
+       p = (char *)malloc(123);
+       q = (char *)calloc(555,1);
+       free(q);
+       free(p);
+    }
+    z = (char *)malloc (666);
+}
+
+/* { dg-final { scan-tree-dump-times " malloc .666" 1 "tmmark" } } */
+/* { dg-final { scan-tree-dump-times "__builtin__ITM_malloc" 1 "tmmark" } } */
+/* { dg-final { scan-tree-dump-times "__builtin__ITM_calloc" 1 "tmmark" } } */
+/* { dg-final { scan-tree-dump-times "__builtin__ITM_free" 2 "tmmark" } } */
+/* { dg-final { cleanup-tree-dump "tmmark" } } */
diff --git a/gcc/testsuite/c-c++-common/tm/memcpy-1.c b/gcc/testsuite/c-c++-common/tm/memcpy-1.c
new file mode 100644 (file)
index 0000000..fa841b2
--- /dev/null
@@ -0,0 +1,9 @@
+/* { dg-do compile } */
+/* { dg-options "-fgnu-tm" } */
+#include <string.h>
+
+__attribute__((transaction_safe))
+void *wmemcpy(void *dest, const void *src, size_t n)
+{
+    return memcpy(dest, src, n);
+}
diff --git a/gcc/testsuite/c-c++-common/tm/omp.c b/gcc/testsuite/c-c++-common/tm/omp.c
new file mode 100644 (file)
index 0000000..b9fcc76
--- /dev/null
@@ -0,0 +1,22 @@
+/* { dg-do compile } */
+/* { dg-options "-fgnu-tm -fopenmp" } */
+
+__attribute__ ((transaction_pure))
+unsigned long rdtsc();
+
+typedef struct ENTER_EXIT_TIMES
+{
+  unsigned long enter;
+} times_t;
+
+void ParClassify()
+{
+  void * Parent;
+#pragma omp parallel private(Parent)
+  {
+    times_t inside;
+    __transaction_atomic {
+       inside.enter = rdtsc();
+    }
+  }
+}
diff --git a/gcc/testsuite/c-c++-common/tm/outer-1.c b/gcc/testsuite/c-c++-common/tm/outer-1.c
new file mode 100644 (file)
index 0000000..7dbf2e8
--- /dev/null
@@ -0,0 +1,31 @@
+/* { dg-do compile } */
+/* { dg-options "-fgnu-tm" } */
+
+void mco(void) __attribute__((transaction_may_cancel_outer));
+
+void
+f(void)
+{
+  mco();                       /* { dg-error "" } */
+  __transaction_atomic {
+    mco();                     /* { dg-error "" } */
+  }
+  __transaction_relaxed {
+    mco();                     /* { dg-error "" } */
+  }
+  __transaction_atomic [[outer]] {
+    mco();
+  }
+}
+
+void __attribute__((transaction_may_cancel_outer))
+g(void)
+{
+  mco();
+  __transaction_atomic {
+    mco();
+  }
+  __transaction_atomic [[outer]] {     /* { dg-error "" } */
+    mco();
+  }
+}
diff --git a/gcc/testsuite/c-c++-common/tm/safe-1.c b/gcc/testsuite/c-c++-common/tm/safe-1.c
new file mode 100644 (file)
index 0000000..b2a4353
--- /dev/null
@@ -0,0 +1,69 @@
+/* { dg-do compile } */
+/* { dg-options "-fgnu-tm" } */
+
+void ts(void) __attribute__((transaction_safe));
+void tp(void) __attribute__((transaction_pure));
+void tc(void) __attribute__((transaction_callable));
+void ti(void) __attribute__((transaction_unsafe));
+void tm(void) __attribute__((transaction_may_cancel_outer));
+void tu(void);
+int fc(int) __attribute__((const));
+
+typedef void (*Fs) (void) __attribute__((transaction_safe));
+typedef void (*Fc) (void) __attribute__((transaction_callable));
+typedef void (*Fi) (void) __attribute__((transaction_unsafe));
+typedef void (*Fm) (void) __attribute__((transaction_may_cancel_outer));
+extern Fs ps;
+extern Fc pc;
+extern Fi pi;
+extern Fm pm;
+extern void (*pu)(void);
+
+int __attribute__((transaction_safe))
+foo(void)
+{
+  int i;
+
+  ts();
+  tp();
+  tc();                        /* { dg-error "unsafe function call" } */
+  ti();                        /* { dg-error "unsafe function call" } */
+
+  /* ??? Direct function calls without markups are handled later
+     than pass_diagnose_tm_blocks, which means we'll exit with
+     errors before getting there.  This test moved to safe-3.c.  */
+  /* tu(); */
+
+  (*ps)();
+  (*pc)();             /* { dg-error "unsafe function call" } */
+  (*pi)();             /* { dg-error "unsafe function call" } */
+  (*pu)();             /* { dg-error "unsafe function call" } */
+
+  asm("");             /* { dg-error "asm not allowed" } */
+  asm("" : "=g"(i));   /* { dg-error "asm not allowed" } */
+
+  return fc(i);
+}
+
+int __attribute__((transaction_may_cancel_outer))
+bar(void)
+{
+  int i;
+
+  ts();
+  tp();
+  tc();                        /* { dg-error "unsafe function call" } */
+  ti();                        /* { dg-error "unsafe function call" } */
+  tm();
+
+  (*ps)();
+  (*pc)();             /* { dg-error "unsafe function call" } */
+  (*pi)();             /* { dg-error "unsafe function call" } */
+  (*pm)();
+  (*pu)();             /* { dg-error "unsafe function call" } */
+
+  asm("");             /* { dg-error "asm not allowed" } */
+  asm("" : "=g"(i));   /* { dg-error "asm not allowed" } */
+
+  return fc(i);
+}
diff --git a/gcc/testsuite/c-c++-common/tm/safe-2.c b/gcc/testsuite/c-c++-common/tm/safe-2.c
new file mode 100644 (file)
index 0000000..a6729ba
--- /dev/null
@@ -0,0 +1,43 @@
+/* { dg-do compile } */
+/* { dg-options "-fgnu-tm" } */
+
+void mco(void) __attribute__((transaction_may_cancel_outer));
+
+void
+f(void)
+{
+  mco();                       /* { dg-error "" } */
+  __transaction_atomic {
+    mco();                     /* { dg-error "" } */
+  }
+  __transaction_relaxed {
+    mco();                     /* { dg-error "" } */
+  }
+  __transaction_atomic [[outer]] {
+    mco();
+  }
+  __transaction_atomic [[outer]] {
+    __transaction_atomic {
+      __transaction_atomic {
+       __transaction_atomic {
+         mco();
+       }
+      }
+    }
+  }
+}
+
+void __attribute__((transaction_may_cancel_outer))
+g(void)
+{
+  mco();
+  __transaction_atomic {
+    __transaction_atomic {
+      __transaction_atomic {
+       __transaction_atomic {
+         mco();
+       }
+      }
+    }
+  }
+}
diff --git a/gcc/testsuite/c-c++-common/tm/safe-3.c b/gcc/testsuite/c-c++-common/tm/safe-3.c
new file mode 100644 (file)
index 0000000..8a883db
--- /dev/null
@@ -0,0 +1,48 @@
+/* { dg-do compile } */
+/* { dg-options "-fgnu-tm" } */
+
+void f_extern (void);
+void f_first (void);
+void f_later (void);
+
+extern int x;
+
+void f_first (void) { x++; }
+
+void __attribute__((transaction_safe))
+test_safe (void)
+{
+  f_extern ();         /* { dg-error "unsafe function call" } */
+  f_first ();
+  f_later ();
+}
+
+void __attribute__((transaction_may_cancel_outer))
+test_mco (void)
+{
+  f_extern ();         /* { dg-error "unsafe function call" } */
+  f_first ();
+  f_later ();
+}
+
+void
+test_atomic (void)
+{
+  __transaction_atomic {
+    f_extern ();       /* { dg-error "unsafe function call" } */
+    f_first ();
+    f_later ();
+  }
+  __transaction_relaxed {
+    f_extern ();
+    f_first ();
+    f_later ();
+  }
+  __transaction_atomic [[outer]] {
+    f_extern ();       /* { dg-error "unsafe function call" } */
+    f_first ();
+    f_later ();
+  }
+}
+
+void f_later () { f_first(); test_safe(); }
diff --git a/gcc/testsuite/c-c++-common/tm/trxn-expr-2.c b/gcc/testsuite/c-c++-common/tm/trxn-expr-2.c
new file mode 100644 (file)
index 0000000..0ef6526
--- /dev/null
@@ -0,0 +1,15 @@
+/* { dg-do compile } */
+/* Make sure that we don't just crash without -fgnu-tm enabled.  */
+/* { dg-options "" } */
+
+int x;
+
+int foo(void)
+{
+  return __transaction_atomic (x + 1);         /* { dg-error "" } */
+}
+
+int bar(void)
+{
+  return __transaction_relaxed (x + 1);                /* { dg-error "" } */
+}
diff --git a/gcc/testsuite/c-c++-common/tm/trxn-expr.c b/gcc/testsuite/c-c++-common/tm/trxn-expr.c
new file mode 100644 (file)
index 0000000..53d4677
--- /dev/null
@@ -0,0 +1,13 @@
+/* { dg-do compile } */
+/* { dg-options "-fgnu-tm -fdump-tree-tmmark" } */
+
+int y, x, york;
+
+void foobar(void)
+{
+  x = y + __transaction_atomic (york);
+}
+
+/* { dg-final { scan-tree-dump-times "_ITM_RU.*york" 1 "tmmark" } } */
+/* { dg-final { scan-tree-dump-times "_ITM_RU" 1 "tmmark" } } */
+/* { dg-final { cleanup-tree-dump "tmmark" } } */
diff --git a/gcc/testsuite/c-c++-common/tm/wrap-1.c b/gcc/testsuite/c-c++-common/tm/wrap-1.c
new file mode 100644 (file)
index 0000000..04b5b6f
--- /dev/null
@@ -0,0 +1,10 @@
+/* { dg-do compile } */
+/* { dg-options "-fgnu-tm -fdump-tree-optimized" } */
+
+void orig(void);
+void xyzzy(void) __attribute__((transaction_wrap (orig)));
+
+void foo() { __transaction_relaxed { orig (); } }
+
+/* { dg-final { scan-tree-dump-times "xyzzy" 1 "optimized" } } */
+/* { dg-final { cleanup-tree-dump "optimized" } } */
index cee19d6..ad1f7e2 100644 (file)
@@ -47,6 +47,7 @@ set tests [prune $tests $srcdir/$subdir/gomp/*]
 set tests [prune $tests $srcdir/$subdir/tree-prof/*]
 set tests [prune $tests $srcdir/$subdir/torture/*]
 set tests [prune $tests $srcdir/$subdir/graphite/*]
+set tests [prune $tests $srcdir/$subdir/tm/*]
 set tests [prune $tests $srcdir/$subdir/guality/*]
 set tests [prune $tests $srcdir/$subdir/simulate-thread/*]
 
diff --git a/gcc/testsuite/g++.dg/tm/20100429.C b/gcc/testsuite/g++.dg/tm/20100429.C
new file mode 100644 (file)
index 0000000..087ce32
--- /dev/null
@@ -0,0 +1,15 @@
+// { dg-do compile }
+// { dg-options "-fgnu-tm" }
+
+int foo(int a);
+int foo(float a);
+int
+bar(int a)
+{
+  int r;
+  __transaction_atomic
+    {
+      r = foo(a); // { dg-error "unsafe function call 'int foo\\(int\\)'" }
+    }
+  return r;
+}
diff --git a/gcc/testsuite/g++.dg/tm/20100727.C b/gcc/testsuite/g++.dg/tm/20100727.C
new file mode 100644 (file)
index 0000000..bda2df0
--- /dev/null
@@ -0,0 +1,796 @@
+// { dg-do compile }
+// { dg-options "-fgnu-tm" }
+
+typedef long int ptrdiff_t;
+typedef long unsigned int size_t;
+namespace std __attribute__ ((__visibility__ ("default")))
+{
+  using::ptrdiff_t;
+  using::size_t;
+}
+
+namespace std __attribute__ ((__visibility__ ("default")))
+{
+  struct input_iterator_tag
+  {
+  };
+  struct output_iterator_tag
+  {
+  };
+  struct forward_iterator_tag:public input_iterator_tag
+  {
+  };
+  struct bidirectional_iterator_tag:public forward_iterator_tag
+  {
+  };
+  struct random_access_iterator_tag:public bidirectional_iterator_tag
+  {
+  };
+  template < typename _Category, typename _Tp, typename _Distance =
+    ptrdiff_t, typename _Pointer = _Tp *, typename _Reference =
+    _Tp & >struct iterator
+  {
+    typedef _Category iterator_category;
+    typedef _Tp value_type;
+    typedef _Distance difference_type;
+    typedef _Pointer pointer;
+    typedef _Reference reference;
+  };
+  template < typename _Iterator > struct iterator_traits
+  {
+    typedef typename _Iterator::iterator_category iterator_category;
+    typedef typename _Iterator::value_type value_type;
+    typedef typename _Iterator::difference_type difference_type;
+    typedef typename _Iterator::pointer pointer;
+    typedef typename _Iterator::reference reference;
+  };
+  template < typename _Tp > struct iterator_traits <_Tp * >
+  {
+    typedef random_access_iterator_tag iterator_category;
+    typedef _Tp value_type;
+    typedef ptrdiff_t difference_type;
+    typedef _Tp *pointer;
+    typedef _Tp & reference;
+  };
+  template < typename _Tp > struct iterator_traits <const _Tp *>
+  {
+    typedef random_access_iterator_tag iterator_category;
+    typedef _Tp value_type;
+    typedef ptrdiff_t difference_type;
+    typedef const _Tp *pointer;
+    typedef const _Tp & reference;
+  };
+  template < typename _Iter > inline typename iterator_traits <
+    _Iter >::iterator_category __iterator_category (const _Iter &)
+  {
+    return typename iterator_traits < _Iter >::iterator_category ();
+  }
+}
+
+namespace std __attribute__ ((__visibility__ ("default")))
+{
+template < typename _Iterator > class reverse_iterator:public iterator < typename iterator_traits < _Iterator >::iterator_category,
+    typename iterator_traits < _Iterator >::value_type,
+    typename iterator_traits < _Iterator >::difference_type,
+    typename iterator_traits < _Iterator >::pointer,
+    typename iterator_traits < _Iterator >::reference >
+  {
+  protected:_Iterator current;
+    typedef iterator_traits < _Iterator > __traits_type;
+  public:typedef _Iterator iterator_type;
+    typedef typename __traits_type::difference_type difference_type;
+    typedef typename __traits_type::pointer pointer;
+    typedef typename __traits_type::reference reference;
+  reverse_iterator ():current ()
+    {
+    } explicit reverse_iterator (iterator_type __x):current (__x)
+    {
+    } reverse_iterator (const reverse_iterator & __x):current (__x.current)
+    {
+    } template < typename _Iter > reverse_iterator (const reverse_iterator <
+                                                   _Iter >
+                                                   &__x):current (__x.
+                                                                  base ())
+    {
+    } iterator_type base () const
+    {
+      return current;
+    }
+    reference operator* () const
+    {
+      _Iterator __tmp = current;
+       return *--__tmp;
+    }
+    pointer operator-> () const
+    {
+      return &(operator* ());
+    }
+    reverse_iterator & operator++ ()
+    {
+      --current;
+      return *this;
+    }
+    reverse_iterator operator++ (int)
+    {
+      reverse_iterator __tmp = *this;
+      --current;
+      return __tmp;
+    }
+    reverse_iterator & operator-- ()
+    {
+      ++current;
+      return *this;
+    }
+    reverse_iterator operator-- (int)
+    {
+      reverse_iterator __tmp = *this;
+      ++current;
+      return __tmp;
+    }
+    reverse_iterator operator+ (difference_type __n) const
+    {
+      return reverse_iterator (current - __n);
+    }
+    reverse_iterator & operator+= (difference_type __n)
+    {
+      current -= __n;
+      return *this;
+    }
+    reverse_iterator operator- (difference_type __n) const
+    {
+      return reverse_iterator (current + __n);
+    }
+    reverse_iterator & operator-= (difference_type __n)
+    {
+      current += __n;
+      return *this;
+    }
+    reference operator[] (difference_type __n) const
+    {
+      return *(*this + __n);
+    }
+  };
+  template < typename _Iterator >
+    inline bool operator== (const reverse_iterator < _Iterator > &__x,
+                           const reverse_iterator < _Iterator > &__y)
+  {
+    return __x.base () == __y.base ();
+  }
+  template < typename _Iterator >
+    inline bool operator< (const reverse_iterator < _Iterator > &__x,
+                          const reverse_iterator < _Iterator > &__y)
+  {
+    return __y.base () < __x.base ();
+  }
+  template < typename _Iterator >
+    inline bool operator!= (const reverse_iterator < _Iterator > &__x,
+                           const reverse_iterator < _Iterator > &__y)
+  {
+    return !(__x == __y);
+  }
+  template < typename _Iterator >
+    inline bool operator> (const reverse_iterator < _Iterator > &__x,
+                          const reverse_iterator < _Iterator > &__y)
+  {
+    return __y < __x;
+  }
+  template < typename _Iterator >
+    inline bool operator<= (const reverse_iterator < _Iterator > &__x,
+                           const reverse_iterator < _Iterator > &__y)
+  {
+    return !(__y < __x);
+  }
+  template < typename _Iterator >
+    inline bool operator>= (const reverse_iterator < _Iterator > &__x,
+                           const reverse_iterator < _Iterator > &__y)
+  {
+    return !(__x < __y);
+  }
+  template < typename _Iterator > inline typename reverse_iterator <
+    _Iterator >::difference_type operator- (const reverse_iterator <
+                                           _Iterator > &__x,
+                                           const reverse_iterator <
+                                           _Iterator > &__y)
+  {
+    return __y.base () - __x.base ();
+  }
+  template < typename _Iterator > inline reverse_iterator < _Iterator >
+    operator+ (typename reverse_iterator < _Iterator >::difference_type __n,
+              const reverse_iterator < _Iterator > &__x)
+  {
+    return reverse_iterator < _Iterator > (__x.base () - __n);
+  }
+  template < typename _IteratorL,
+    typename _IteratorR > inline bool operator== (const reverse_iterator <
+                                                 _IteratorL > &__x,
+                                                 const reverse_iterator <
+                                                 _IteratorR > &__y)
+  {
+    return __x.base () == __y.base ();
+  }
+  template < typename _IteratorL,
+    typename _IteratorR > inline bool operator< (const reverse_iterator <
+                                                _IteratorL > &__x,
+                                                const reverse_iterator <
+                                                _IteratorR > &__y)
+  {
+    return __y.base () < __x.base ();
+  }
+  template < typename _IteratorL,
+    typename _IteratorR > inline bool operator!= (const reverse_iterator <
+                                                 _IteratorL > &__x,
+                                                 const reverse_iterator <
+                                                 _IteratorR > &__y)
+  {
+    return !(__x == __y);
+  }
+  template < typename _IteratorL,
+    typename _IteratorR > inline bool operator> (const reverse_iterator <
+                                                _IteratorL > &__x,
+                                                const reverse_iterator <
+                                                _IteratorR > &__y)
+  {
+    return __y < __x;
+  }
+  template < typename _IteratorL,
+    typename _IteratorR > inline bool operator<= (const reverse_iterator <
+                                                 _IteratorL > &__x,
+                                                 const reverse_iterator <
+                                                 _IteratorR > &__y)
+  {
+    return !(__y < __x);
+  }
+  template < typename _IteratorL,
+    typename _IteratorR > inline bool operator>= (const reverse_iterator <
+                                                 _IteratorL > &__x,
+                                                 const reverse_iterator <
+                                                 _IteratorR > &__y)
+  {
+    return !(__x < __y);
+  }
+  template < typename _IteratorL,
+    typename _IteratorR > inline typename reverse_iterator <
+    _IteratorL >::difference_type operator- (const reverse_iterator <
+                                            _IteratorL > &__x,
+                                            const reverse_iterator <
+                                            _IteratorR > &__y)
+  {
+    return __y.base () - __x.base ();
+  }
+template < typename _Container > class back_insert_iterator:public iterator < output_iterator_tag, void, void, void,
+    void >
+  {
+  protected:_Container * container;
+  public:typedef _Container container_type;
+    explicit back_insert_iterator (_Container & __x):container (&__x)
+    {
+    } back_insert_iterator & operator= (typename _Container::
+                                       const_reference __value)
+    {
+      container->push_back (__value);
+      return *this;
+    }
+    back_insert_iterator & operator* ()
+    {
+      return *this;
+    }
+    back_insert_iterator & operator++ ()
+    {
+      return *this;
+    }
+    back_insert_iterator operator++ (int)
+    {
+      return *this;
+    }
+  };
+  template < typename _Container > inline back_insert_iterator < _Container >
+    back_inserter (_Container & __x)
+  {
+    return back_insert_iterator < _Container > (__x);
+  }
+template < typename _Container > class front_insert_iterator:public iterator < output_iterator_tag, void, void, void,
+    void >
+  {
+  protected:_Container * container;
+  public:typedef _Container container_type;
+    explicit front_insert_iterator (_Container & __x):container (&__x)
+    {
+    } front_insert_iterator & operator= (typename _Container::
+                                        const_reference __value)
+    {
+      container->push_front (__value);
+      return *this;
+    }
+    front_insert_iterator & operator* ()
+    {
+      return *this;
+    }
+    front_insert_iterator & operator++ ()
+    {
+      return *this;
+    }
+    front_insert_iterator operator++ (int)
+    {
+      return *this;
+    }
+  };
+  template < typename _Container > inline front_insert_iterator < _Container >
+    front_inserter (_Container & __x)
+  {
+    return front_insert_iterator < _Container > (__x);
+  }
+template < typename _Container > class insert_iterator:public iterator < output_iterator_tag, void, void, void,
+    void >
+  {
+  protected:_Container * container;
+    typename _Container::iterator iter;
+  public:typedef _Container container_type;
+      insert_iterator (_Container & __x,
+                      typename _Container::iterator __i):container (&__x),
+      iter (__i)
+    {
+    } insert_iterator & operator= (typename _Container::
+                                  const_reference __value)
+    {
+      iter = container->insert (iter, __value);
+      ++iter;
+      return *this;
+    }
+    insert_iterator & operator* ()
+    {
+      return *this;
+    }
+    insert_iterator & operator++ ()
+    {
+      return *this;
+    }
+    insert_iterator & operator++ (int)
+    {
+      return *this;
+    }
+  };
+  template < typename _Container,
+    typename _Iterator > inline insert_iterator < _Container >
+    inserter (_Container & __x, _Iterator __i)
+  {
+    return insert_iterator < _Container > (__x,
+                                          typename _Container::
+                                          iterator (__i));
+  }
+}
+
+namespace __gnu_cxx __attribute__ ((__visibility__ ("default")))
+{
+  using std::size_t;
+  using std::ptrdiff_t;
+  template < typename _Tp > class new_allocator
+  {
+  public:typedef size_t size_type;
+    typedef ptrdiff_t difference_type;
+    typedef _Tp *pointer;
+    typedef const _Tp *const_pointer;
+    typedef _Tp & reference;
+    typedef const _Tp & const_reference;
+    typedef _Tp value_type;
+    template < typename _Tp1 > struct rebind
+    {
+      typedef new_allocator < _Tp1 > other;
+    };
+    new_allocator ()throw ()
+    {
+    } new_allocator (const new_allocator &) throw ()
+    {
+    } template < typename _Tp1 > new_allocator (const new_allocator < _Tp1 >
+                                               &) throw ()
+    {
+    } ~new_allocator ()throw ()
+    {
+    } pointer address (reference __x) const
+    {
+      return &__x;
+    }
+    const_pointer address (const_reference __x) const
+    {
+      return &__x;
+    }
+    pointer allocate (size_type __n, const void * = 0)
+    {
+      return static_cast < _Tp * >(::operator  new (__n * sizeof (_Tp)));
+    }
+    void deallocate (pointer __p, size_type)
+    {
+      ::operator  delete (__p);
+    } size_type max_size () const throw ()
+    {
+      return size_t (-1) / sizeof (_Tp);
+    }
+    void construct (pointer __p, const _Tp & __val)
+    {
+      ::new ((void *) __p) _Tp (__val);
+    } void destroy (pointer __p)
+    {
+      __p->~_Tp ();
+  }};
+  template < typename _Tp > inline bool operator== (const new_allocator <
+                                                   _Tp > &,
+                                                   const new_allocator <
+                                                   _Tp > &)
+  {
+    return true;
+  }
+  template < typename _Tp > inline bool operator!= (const new_allocator <
+                                                   _Tp > &,
+                                                   const new_allocator <
+                                                   _Tp > &)
+  {
+    return false;
+  }
+}
+
+namespace std __attribute__ ((__visibility__ ("default")))
+{
+  template < typename _Tp > class allocator;
+  template <> class allocator < void >
+  {
+  public:typedef size_t size_type;
+    typedef ptrdiff_t difference_type;
+    typedef void *pointer;
+    typedef const void *const_pointer;
+    typedef void value_type;
+      template < typename _Tp1 > struct rebind
+    {
+      typedef allocator < _Tp1 > other;
+    };
+  };
+template < typename _Tp > class allocator:public __gnu_cxx::new_allocator <
+    _Tp >
+  {
+  public:typedef size_t size_type;
+    typedef ptrdiff_t difference_type;
+    typedef _Tp *pointer;
+    typedef const _Tp *const_pointer;
+    typedef _Tp & reference;
+    typedef const _Tp & const_reference;
+    typedef _Tp value_type;
+    template < typename _Tp1 > struct rebind
+    {
+      typedef allocator < _Tp1 > other;
+    };
+    allocator ()throw ()
+    {
+    } allocator (const allocator & __a) throw ():__gnu_cxx::new_allocator <
+      _Tp > (__a)
+    {
+    } template < typename _Tp1 > allocator (const allocator < _Tp1 >
+                                           &) throw ()
+    {
+    } ~allocator ()throw ()
+    {
+  }};
+  template < typename _T1,
+    typename _T2 > inline bool operator== (const allocator < _T1 > &,
+                                          const allocator < _T2 > &)
+  {
+    return true;
+  }
+  template < typename _Tp > inline bool operator== (const allocator < _Tp > &,
+                                                   const allocator < _Tp > &)
+  {
+    return true;
+  }
+  template < typename _T1,
+    typename _T2 > inline bool operator!= (const allocator < _T1 > &,
+                                          const allocator < _T2 > &)
+  {
+    return false;
+  }
+  template < typename _Tp > inline bool operator!= (const allocator < _Tp > &,
+                                                   const allocator < _Tp > &)
+  {
+    return false;
+  }
+  template < typename _Alloc, bool = __is_empty (_Alloc) > struct __alloc_swap
+  {
+    static void _S_do_it (_Alloc &, _Alloc &)
+    {
+  }};
+  template < typename _Alloc > struct __alloc_swap <_Alloc, false >
+  {
+    static void _S_do_it (_Alloc & __one, _Alloc & __two)
+    {
+      if (__one != __two)
+       swap (__one, __two);
+    }
+  };
+  template < typename _Alloc, bool = __is_empty (_Alloc) > struct __alloc_neq
+  {
+    static bool _S_do_it (const _Alloc &, const _Alloc &)
+    {
+      return false;
+    }
+  };
+  template < typename _Alloc > struct __alloc_neq <_Alloc, false >
+  {
+    static bool _S_do_it (const _Alloc & __one, const _Alloc & __two)
+    {
+      return __one != __two;
+    }
+  };
+}
+
+namespace std __attribute__ ((__visibility__ ("default")))
+{
+  struct _List_node_base
+  {
+    _List_node_base *_M_next;
+    _List_node_base *_M_prev;
+    static void swap (_List_node_base & __x, _List_node_base & __y) throw ();
+    void _M_transfer (_List_node_base * const __first,
+                     _List_node_base * const __last) throw ();
+    void _M_reverse () throw ();
+    void _M_hook (_List_node_base * const __position) throw ();
+    void _M_unhook () throw ();
+  };
+  template < typename _Tp > struct _List_node:public _List_node_base
+  {
+    _Tp _M_data;
+  };
+  template < typename _Tp > struct _List_iterator
+  {
+    typedef _List_iterator < _Tp > _Self;
+    typedef _List_node < _Tp > _Node;
+    typedef ptrdiff_t difference_type;
+    typedef std::bidirectional_iterator_tag iterator_category;
+    typedef _Tp value_type;
+    typedef _Tp *pointer;
+    typedef _Tp & reference;
+      _List_iterator ():_M_node ()
+    {
+    } explicit _List_iterator (_List_node_base * __x):_M_node (__x)
+    {
+    } reference operator* () const
+    {
+      return static_cast < _Node * >(_M_node)->_M_data;
+    }
+    pointer operator-> () const
+    {
+      return &static_cast < _Node * >(_M_node)->_M_data;
+    }
+    _Self & operator++ ()
+    {
+      _M_node = _M_node->_M_next;
+      return *this;
+    }
+    _Self operator++ (int)
+    {
+      _Self __tmp = *this;
+      _M_node = _M_node->_M_next;
+      return __tmp;
+    }
+    _Self & operator-- ()
+    {
+      _M_node = _M_node->_M_prev;
+      return *this;
+    }
+    _Self operator-- (int)
+    {
+      _Self __tmp = *this;
+      _M_node = _M_node->_M_prev;
+      return __tmp;
+    }
+    bool operator== (const _Self & __x) const
+    {
+      return _M_node == __x._M_node;
+    }
+    bool operator!= (const _Self & __x) const
+    {
+      return _M_node != __x._M_node;
+    }
+    _List_node_base *_M_node;
+  };
+  template < typename _Tp > struct _List_const_iterator
+  {
+    typedef _List_const_iterator < _Tp > _Self;
+    typedef const _List_node < _Tp > _Node;
+    typedef _List_iterator < _Tp > iterator;
+    typedef ptrdiff_t difference_type;
+    typedef std::bidirectional_iterator_tag iterator_category;
+    typedef _Tp value_type;
+    typedef const _Tp *pointer;
+    typedef const _Tp & reference;
+      _List_const_iterator ():_M_node ()
+    {
+    } explicit _List_const_iterator (const _List_node_base *
+                                    __x):_M_node (__x)
+    {
+    } _List_const_iterator (const iterator & __x):_M_node (__x._M_node)
+    {
+    } reference operator* () const
+    {
+      return static_cast < _Node * >(_M_node)->_M_data;
+    }
+    pointer operator-> () const
+    {
+      return &static_cast < _Node * >(_M_node)->_M_data;
+    }
+    _Self & operator++ ()
+    {
+      _M_node = _M_node->_M_next;
+      return *this;
+    }
+    _Self operator++ (int)
+    {
+      _Self __tmp = *this;
+      _M_node = _M_node->_M_next;
+      return __tmp;
+    }
+    _Self & operator-- ()
+    {
+      _M_node = _M_node->_M_prev;
+      return *this;
+    }
+    _Self operator-- (int)
+    {
+      _Self __tmp = *this;
+      _M_node = _M_node->_M_prev;
+      return __tmp;
+    }
+    bool operator== (const _Self & __x) const
+    {
+      return _M_node == __x._M_node;
+    }
+    bool operator!= (const _Self & __x) const
+    {
+      return _M_node != __x._M_node;
+    }
+    const _List_node_base *_M_node;
+  };
+  template < typename _Tp, typename _Alloc > class _List_base
+  {
+  protected:typedef typename _Alloc::template rebind < _List_node < _Tp >
+      >::other _Node_alloc_type;
+    typedef typename _Alloc::template rebind < _Tp >::other _Tp_alloc_type;
+    struct _List_impl:public _Node_alloc_type
+    {
+      _List_node_base _M_node;
+       _List_impl ():_Node_alloc_type (), _M_node ()
+      {
+      } _List_impl (const _Node_alloc_type & __a):_Node_alloc_type (__a),
+       _M_node ()
+      {
+    }};
+    _List_impl _M_impl;
+    _List_node < _Tp > *_M_get_node ()
+    {
+      return _M_impl._Node_alloc_type::allocate (1);
+    }
+    void _M_put_node (_List_node < _Tp > *__p)
+    {
+      _M_impl._Node_alloc_type::deallocate (__p, 1);
+  } public:typedef _Alloc allocator_type;
+    _Node_alloc_type & _M_get_Node_allocator ()
+    {
+      return *static_cast < _Node_alloc_type * >(&this->_M_impl);
+    }
+    const _Node_alloc_type & _M_get_Node_allocator () const
+    {
+      return *static_cast < const _Node_alloc_type *>(&this->_M_impl);
+    } _Tp_alloc_type _M_get_Tp_allocator () const
+    {
+      return _Tp_alloc_type (_M_get_Node_allocator ());
+    }
+    allocator_type get_allocator () const
+    {
+      return allocator_type (_M_get_Node_allocator ());
+    }
+    _List_base ():_M_impl ()
+    {
+      _M_init ();
+    }
+  _List_base (const allocator_type & __a):_M_impl (__a)
+    {
+      _M_init ();
+    } ~_List_base ()
+    {
+      _M_clear ();
+    } void _M_clear ();
+    void _M_init ()
+    {
+      this->_M_impl._M_node._M_next = &this->_M_impl._M_node;
+      this->_M_impl._M_node._M_prev = &this->_M_impl._M_node;
+  }};
+template < typename _Tp, typename _Alloc = std::allocator < _Tp > >class list:protected _List_base < _Tp,
+    _Alloc
+    >
+  {
+    typedef typename _Alloc::value_type _Alloc_value_type;
+    typedef _List_base < _Tp, _Alloc > _Base;
+    typedef typename _Base::_Tp_alloc_type _Tp_alloc_type;
+  public:typedef _Tp value_type;
+    typedef typename _Tp_alloc_type::pointer pointer;
+    typedef typename _Tp_alloc_type::const_pointer const_pointer;
+    typedef typename _Tp_alloc_type::reference reference;
+    typedef typename _Tp_alloc_type::const_reference const_reference;
+    typedef _List_iterator < _Tp > iterator;
+    typedef _List_const_iterator < _Tp > const_iterator;
+    typedef std::reverse_iterator < const_iterator > const_reverse_iterator;
+    typedef std::reverse_iterator < iterator > reverse_iterator;
+    typedef size_t size_type;
+    typedef ptrdiff_t difference_type;
+    typedef _Alloc allocator_type;
+  protected:typedef _List_node < _Tp > _Node;
+    using _Base::_M_impl;
+    using _Base::_M_put_node;
+    using _Base::_M_get_node;
+    using _Base::_M_get_Tp_allocator;
+    using _Base::_M_get_Node_allocator;
+  public:iterator begin ()
+    {
+      return iterator (this->_M_impl._M_node._M_next);
+    }
+    const_iterator begin () const
+    {
+      return const_iterator (this->_M_impl._M_node._M_next);
+    }
+    iterator end ()
+    {
+      return iterator (&this->_M_impl._M_node);
+    }
+    void remove (const _Tp & __value);
+    template < typename _Predicate > void remove_if (_Predicate);
+    void _M_erase (iterator __position)
+    {
+      __position._M_node->_M_unhook ();
+      _Node *__n = static_cast < _Node * >(__position._M_node);
+      _M_get_Tp_allocator ().destroy (&__n->_M_data);
+      _M_put_node (__n);
+    } void _M_check_equal_allocators (list & __x)
+    {
+      if (std::__alloc_neq <
+         typename _Base::_Node_alloc_type >::
+         _S_do_it (_M_get_Node_allocator (), __x._M_get_Node_allocator ()));
+    }
+  };
+}
+
+namespace std __attribute__ ((__visibility__ ("default")))
+{
+  template < typename _Tp, typename _Alloc > void list < _Tp,
+    _Alloc >::remove (const value_type & __value)
+  {
+    iterator __first = begin ();
+    iterator __last = end ();
+    iterator __extra = __last;
+    while (__first != __last)
+      {
+       iterator __next = __first;
+       ++__next;
+       if (*__first == __value)
+         {
+           if (&*__first != &__value)
+             _M_erase (__first);
+           else
+             __extra = __first;
+         }
+       __first = __next;
+      }
+    if (__extra != __last)
+      _M_erase (__extra);
+  }
+}
+
+class Unit
+{
+public:int dummy;
+};
+class Building
+{
+public:__attribute__ ((transaction_callable)) void removeUnitFromInside (Unit *
+                                                                   unit);
+    std::list < Unit * >unitsInside;
+};
+void
+Building::removeUnitFromInside (Unit * unit)
+{
+  unitsInside.remove (unit);
+}
diff --git a/gcc/testsuite/g++.dg/tm/alias.C b/gcc/testsuite/g++.dg/tm/alias.C
new file mode 100644 (file)
index 0000000..4459c70
--- /dev/null
@@ -0,0 +1,20 @@
+// { dg-do compile }
+// { dg-options "-fgnu-tm -O0" }
+
+/* Test that we generate transactional clones for both the base and
+   the complete dtor for class Itemset.  */
+
+class Itemset {
+public:
+   __attribute__((transaction_safe)) ~Itemset();
+  __attribute__((transaction_safe)) void operator delete(void *);
+private:
+};
+
+__attribute__((transaction_safe))
+Itemset::~Itemset()
+{
+}
+
+// { dg-final { scan-assembler "_ZGTtN7ItemsetD1Ev" } }
+// { dg-final { scan-assembler "_ZGTtN7ItemsetD2Ev" } }
diff --git a/gcc/testsuite/g++.dg/tm/attrib-2.C b/gcc/testsuite/g++.dg/tm/attrib-2.C
new file mode 100644 (file)
index 0000000..6a418e5
--- /dev/null
@@ -0,0 +1,22 @@
+// { dg-do compile }
+// { dg-options "-fgnu-tm -fdump-tree-optimized-asmname" }
+
+struct __attribute__((transaction_safe)) Tsafe
+{
+  void f();
+};
+
+void Tsafe::f() { }
+
+struct __attribute__((transaction_callable)) Tcall
+{
+  void f();
+};
+
+void Tcall::f() { }
+
+// { dg-final { scan-tree-dump-times "_ZN5Tsafe1fEv" 1 "optimized" } }
+// { dg-final { scan-tree-dump-times "_ZN5Tcall1fEv" 1 "optimized" } }
+// { dg-final { scan-tree-dump-times "_ZGTtN5Tsafe1fEv" 1 "optimized" } }
+// { dg-final { scan-tree-dump-times "_ZGTtN5Tcall1fEv" 1 "optimized" } }
+// { dg-final { cleanup-tree-dump "optimized" } }
diff --git a/gcc/testsuite/g++.dg/tm/attrib-3.C b/gcc/testsuite/g++.dg/tm/attrib-3.C
new file mode 100644 (file)
index 0000000..a2c9718
--- /dev/null
@@ -0,0 +1,33 @@
+// { dg-do compile }
+// { dg-options "-fgnu-tm -fdump-tree-optimized-asmname" }