diff mbox

[rs6000,libitm] Enable Hardware Transactional Memory (HTM) support on Power

Message ID 1372734758.4736.149.camel@otta
State New
Headers show

Commit Message

Peter Bergner July 2, 2013, 3:12 a.m. UTC
On May 10th, the Power Architecture Advisory Council announced the public
availability of Power ISA 2.07.

  https://www.power.org/documentation/power-isa-version-2-07/

This patch adds support for Hardware Transactional Memory (HTM) builtins
as well as a header file that implements a set of builtin like functions
that provides compatibility with the IBM XL compiler on both Power and
S390.

The GCC builtins are used to implement the HTM fast path support within libitm.
All libitm test cases succeed with this patch applied.

This patch bootstraps and regtests with no regressions on powerpc64-linux
(running the testsuite in both 32-bit and 64-bit modes).

Is this ok for trunk?

Peter


libitm/
        * acinclude.m4 (LIBITM_CHECK_AS_HTM): New.
        * configure.ac: Use it.
	(AC_CHECK_HEADERS): Check for sys/auxv.h.
	(AC_CHECK_FUNCS): Check for getauxval.
        * config.h.in, configure: Rebuild.
	* configure.tgt (target_cpu): Add -mhtm to XCFLAGS.
	* config/powerpc/target.h: Include sys/auxv.h and htmintrin.h.
	(USE_HTM_FASTPATH): Define.
	(_TBEGIN_STARTED, _TBEGIN_INDETERMINATE, _TBEGIN_PERSISTENT,
	_HTM_RETRIES) New macros.
	(htm_abort, htm_abort_should_retry, htm_available, htm_begin, htm_init,
	htm_begin_success, htm_commit, htm_transaction_active): New functions.

gcc/
	* config.gcc (powerpc*-*-*): Install htmintrin.h and htmxlintrin.h.
	* config/rs6000/t-rs6000 (MD_INCLUDES): Add htm.md.
	* config/rs6000/rs6000.opt: Add -mhtm option.
	* config/rs6000/rs6000-cpus.def (POWERPC_MASKS): Add OPTION_MASK_HTM.
	(ISA_2_7_MASKS_SERVER): Add OPTION_MASK_HTM.
	* config/rs6000/rs6000-c.c (rs6000_target_modify_macros): Define
	__HTM__ if the HTM instructions are available.
	* config/rs6000/predicates.md (u3bit_cint_operand, u10bit_cint_operand,
	htm_spr_reg_operand): New define_predicates.
	* config/rs6000/rs6000.md (define_attr "type"): Add htm.
	(TFHAR_REGNO, TFIAR_REGNO, TEXASR_REGNO): New define_constants.
	Include htm.md.
	* config/rs6000/rs6000-builtin.def (BU_HTM_0, BU_HTM_1, BU_HTM_2,
	BU_HTM_3, BU_HTM_SPR0, BU_HTM_SPR1): Add support macros for defining
	HTM builtin functions.
	* config/rs6000/rs6000.c (RS6000_BUILTIN_H): New macro.
	(rs6000_reg_names, alt_reg_names): Add HTM SPR register names.
	(rs6000_init_hard_regno_mode_ok): Add support for HTM instructions.
	(rs6000_builtin_mask_calculate): Likewise.
	(rs6000_option_override_internal): Likewise.
	(bdesc_htm): Add new HTM builtin support.
	(htm_spr_num): New function.
	(htm_spr_regno): Likewise.
	(rs6000_htm_spr_icode): Likewise.
	(htm_expand_builtin): Likewise.
	(htm_init_builtins): Likewise.
	(rs6000_expand_builtin): Add support for HTM builtin functions.
	(rs6000_init_builtins): Likewise.
	(rs6000_invalid_builtin, rs6000_opt_mask): Add support for -mhtm option.
	* config/rs6000/rs6000.h (ASM_CPU_SPEC): Add support for -mhtm.
	(TARGET_HTM, MASK_HTM): Define macros.
	(FIRST_PSEUDO_REGISTER): Adjust for new HTM SPR registers.
	(FIXED_REGISTERS): Likewise.
	(CALL_USED_REGISTERS): Likewise.
	(CALL_REALLY_USED_REGISTERS): Likewise.
	(REG_ALLOC_ORDER): Likewise.
	(enum reg_class): Likewise.
	(REG_CLASS_NAMES): Likewise.
	(REG_CLASS_CONTENTS): Likewise.
	(REGISTER_NAMES): Likewise.
	(ADDITIONAL_REGISTER_NAMES): Likewise.
	(RS6000_BTC_SPR, RS6000_BTC_VOID, RS6000_BTC_32BIT, RS6000_BTC_64BIT,
	RS6000_BTC_MISC_MASK, RS6000_BTM_HTM): New macros.
	(RS6000_BTM_COMMON): Add RS6000_BTM_HTM.
	* config/rs6000/htm.md: New file.
	* config/rs6000/htmintrin.h: New file.
	* config/rs6000/htmxlintrin.h: New file.

gcc/testsuite/
        * lib/target-supports.exp (check_effective_target_powerpc_htm_ok): New
        function to test if HTM is available.
	* gcc.target/powerpc/htm-xl-intrin-1.c: New test.
	* gcc.target/powerpc/htm-builtin-1.c: New test.

Comments

Richard Henderson July 2, 2013, 2:31 p.m. UTC | #1
On 07/01/2013 08:12 PM, Peter Bergner wrote:
> libitm/
>         * acinclude.m4 (LIBITM_CHECK_AS_HTM): New.
>         * configure.ac: Use it.
> 	(AC_CHECK_HEADERS): Check for sys/auxv.h.
> 	(AC_CHECK_FUNCS): Check for getauxval.
>         * config.h.in, configure: Rebuild.
> 	* configure.tgt (target_cpu): Add -mhtm to XCFLAGS.
> 	* config/powerpc/target.h: Include sys/auxv.h and htmintrin.h.
> 	(USE_HTM_FASTPATH): Define.
> 	(_TBEGIN_STARTED, _TBEGIN_INDETERMINATE, _TBEGIN_PERSISTENT,
> 	_HTM_RETRIES) New macros.
> 	(htm_abort, htm_abort_should_retry, htm_available, htm_begin, htm_init,
> 	htm_begin_success, htm_commit, htm_transaction_active): New functions.

The libitm parts are ok.

I briefly looked over the rs6000 backend bits and didn't see anything
noticeably wrong, but I'll leave that for DJE to approve.


r~
David Edelsohn July 4, 2013, 4:02 p.m. UTC | #2
On Mon, Jul 1, 2013 at 11:12 PM, Peter Bergner <bergner@vnet.ibm.com> wrote:
> On May 10th, the Power Architecture Advisory Council announced the public
> availability of Power ISA 2.07.
>
>   https://www.power.org/documentation/power-isa-version-2-07/
>
> This patch adds support for Hardware Transactional Memory (HTM) builtins
> as well as a header file that implements a set of builtin like functions
> that provides compatibility with the IBM XL compiler on both Power and
> S390.
>
> The GCC builtins are used to implement the HTM fast path support within libitm.
> All libitm test cases succeed with this patch applied.
>
> This patch bootstraps and regtests with no regressions on powerpc64-linux
> (running the testsuite in both 32-bit and 64-bit modes).
>
> Is this ok for trunk?
>
> Peter
>
>
> libitm/
>         * acinclude.m4 (LIBITM_CHECK_AS_HTM): New.
>         * configure.ac: Use it.
>         (AC_CHECK_HEADERS): Check for sys/auxv.h.
>         (AC_CHECK_FUNCS): Check for getauxval.
>         * config.h.in, configure: Rebuild.
>         * configure.tgt (target_cpu): Add -mhtm to XCFLAGS.
>         * config/powerpc/target.h: Include sys/auxv.h and htmintrin.h.
>         (USE_HTM_FASTPATH): Define.
>         (_TBEGIN_STARTED, _TBEGIN_INDETERMINATE, _TBEGIN_PERSISTENT,
>         _HTM_RETRIES) New macros.
>         (htm_abort, htm_abort_should_retry, htm_available, htm_begin, htm_init,
>         htm_begin_success, htm_commit, htm_transaction_active): New functions.
>
> gcc/
>         * config.gcc (powerpc*-*-*): Install htmintrin.h and htmxlintrin.h.
>         * config/rs6000/t-rs6000 (MD_INCLUDES): Add htm.md.
>         * config/rs6000/rs6000.opt: Add -mhtm option.
>         * config/rs6000/rs6000-cpus.def (POWERPC_MASKS): Add OPTION_MASK_HTM.
>         (ISA_2_7_MASKS_SERVER): Add OPTION_MASK_HTM.
>         * config/rs6000/rs6000-c.c (rs6000_target_modify_macros): Define
>         __HTM__ if the HTM instructions are available.
>         * config/rs6000/predicates.md (u3bit_cint_operand, u10bit_cint_operand,
>         htm_spr_reg_operand): New define_predicates.
>         * config/rs6000/rs6000.md (define_attr "type"): Add htm.
>         (TFHAR_REGNO, TFIAR_REGNO, TEXASR_REGNO): New define_constants.
>         Include htm.md.
>         * config/rs6000/rs6000-builtin.def (BU_HTM_0, BU_HTM_1, BU_HTM_2,
>         BU_HTM_3, BU_HTM_SPR0, BU_HTM_SPR1): Add support macros for defining
>         HTM builtin functions.
>         * config/rs6000/rs6000.c (RS6000_BUILTIN_H): New macro.
>         (rs6000_reg_names, alt_reg_names): Add HTM SPR register names.
>         (rs6000_init_hard_regno_mode_ok): Add support for HTM instructions.
>         (rs6000_builtin_mask_calculate): Likewise.
>         (rs6000_option_override_internal): Likewise.
>         (bdesc_htm): Add new HTM builtin support.
>         (htm_spr_num): New function.
>         (htm_spr_regno): Likewise.
>         (rs6000_htm_spr_icode): Likewise.
>         (htm_expand_builtin): Likewise.
>         (htm_init_builtins): Likewise.
>         (rs6000_expand_builtin): Add support for HTM builtin functions.
>         (rs6000_init_builtins): Likewise.
>         (rs6000_invalid_builtin, rs6000_opt_mask): Add support for -mhtm option.
>         * config/rs6000/rs6000.h (ASM_CPU_SPEC): Add support for -mhtm.
>         (TARGET_HTM, MASK_HTM): Define macros.
>         (FIRST_PSEUDO_REGISTER): Adjust for new HTM SPR registers.
>         (FIXED_REGISTERS): Likewise.
>         (CALL_USED_REGISTERS): Likewise.
>         (CALL_REALLY_USED_REGISTERS): Likewise.
>         (REG_ALLOC_ORDER): Likewise.
>         (enum reg_class): Likewise.
>         (REG_CLASS_NAMES): Likewise.
>         (REG_CLASS_CONTENTS): Likewise.
>         (REGISTER_NAMES): Likewise.
>         (ADDITIONAL_REGISTER_NAMES): Likewise.
>         (RS6000_BTC_SPR, RS6000_BTC_VOID, RS6000_BTC_32BIT, RS6000_BTC_64BIT,
>         RS6000_BTC_MISC_MASK, RS6000_BTM_HTM): New macros.
>         (RS6000_BTM_COMMON): Add RS6000_BTM_HTM.
>         * config/rs6000/htm.md: New file.
>         * config/rs6000/htmintrin.h: New file.
>         * config/rs6000/htmxlintrin.h: New file.
>
> gcc/testsuite/
>         * lib/target-supports.exp (check_effective_target_powerpc_htm_ok): New
>         function to test if HTM is available.
>         * gcc.target/powerpc/htm-xl-intrin-1.c: New test.
>         * gcc.target/powerpc/htm-builtin-1.c: New test.

The rs6000 parts generally are okay.

The expanders in htm.md should not include constraint letters.

htm_mfpr / htm_mtspr seem half generalized, but I guess the
specialized interaction with the HTM SPR regnos requires that it be
specialized.

Thanks, David

P.S. For large patches, it is better to include the ChangeLog in the
body and attach the patch itself.
Peter Bergner July 15, 2013, 3:23 p.m. UTC | #3
On Thu, 2013-07-04 at 12:02 -0400, David Edelsohn wrote:
> The expanders in htm.md should not include constraint letters.

That's the way I had the code originally, since they're not
needed for expand, but I added them later to improve the
error message when someone uses a builtin that takes an
integer constant argument and uses a value out of range.
Specifically, it is used by this part of the patch:

+         if (!(*insn_op->predicate) (op[nopnds], insn_op->mode))
+           {
+             if (!strcmp (insn_op->constraint, "n"))
+               {
+                 int arg_num = (nonvoid) ? nopnds : nopnds + 1;
+                 if (!CONST_INT_P (op[nopnds]))
+                   error ("argument %d must be an unsigned literal", arg_num);
+                 else
+                   error ("argument %d is an unsigned literal that is "
+                          "out of range", arg_num);
+                 return const0_rtx;
+               }
+             op[nopnds] = copy_to_mode_reg (insn_op->mode, op[nopnds]);
+           }

If you want, I can remove the constraints and the extra error
message.  Just let me know what you want.

Peter
David Edelsohn July 15, 2013, 3:55 p.m. UTC | #4
On Mon, Jul 15, 2013 at 11:23 AM, Peter Bergner <bergner@vnet.ibm.com> wrote:
> On Thu, 2013-07-04 at 12:02 -0400, David Edelsohn wrote:
>> The expanders in htm.md should not include constraint letters.
>
> That's the way I had the code originally, since they're not
> needed for expand, but I added them later to improve the
> error message when someone uses a builtin that takes an
> integer constant argument and uses a value out of range.
> Specifically, it is used by this part of the patch:
>
> +         if (!(*insn_op->predicate) (op[nopnds], insn_op->mode))
> +           {
> +             if (!strcmp (insn_op->constraint, "n"))
> +               {
> +                 int arg_num = (nonvoid) ? nopnds : nopnds + 1;
> +                 if (!CONST_INT_P (op[nopnds]))
> +                   error ("argument %d must be an unsigned literal", arg_num);
> +                 else
> +                   error ("argument %d is an unsigned literal that is "
> +                          "out of range", arg_num);
> +                 return const0_rtx;
> +               }
> +             op[nopnds] = copy_to_mode_reg (insn_op->mode, op[nopnds]);
> +           }
>
> If you want, I can remove the constraints and the extra error
> message.  Just let me know what you want.

Thanks for the explanation.  Leave it in.

Jakub was asking about the status of the HTM patch and support, so
please check it in.

Thanks, David
Peter Bergner July 15, 2013, 5:25 p.m. UTC | #5
On Mon, 2013-07-15 at 11:55 -0400, David Edelsohn wrote:
> Thanks for the explanation.  Leave it in.
> 
> Jakub was asking about the status of the HTM patch and support, so
> please check it in.

Ok, committed to mainline (after another bootstrap) as revision 200960.
Thanks!

Peter
Jakub Jelinek July 15, 2013, 6:44 p.m. UTC | #6
On Mon, Jul 15, 2013 at 12:25:58PM -0500, Peter Bergner wrote:
> On Mon, 2013-07-15 at 11:55 -0400, David Edelsohn wrote:
> > Thanks for the explanation.  Leave it in.
> > 
> > Jakub was asking about the status of the HTM patch and support, so
> > please check it in.
> 
> Ok, committed to mainline (after another bootstrap) as revision 200960.
> Thanks!

Looking at the patch, you've changed FIRST_PSEUDO_REGISTER (internal gcc
thing, so fine), but that also changed DWARF_FRAME_REGISTER which was
computed based on FIRST_PSEUDO_REGISTER.  Isn't that an ABI break in the
unwinder (think about having parts of unwinder linked from different
versions of libgcc)?
Can't we just tweak DWARF_FRAME_REGISTER not to include those registers?

	Jakub
diff mbox

Patch

Index: libitm/configure
===================================================================
--- libitm/configure	(revision 200584)
+++ libitm/configure	(working copy)
@@ -15349,7 +15349,7 @@  $as_echo "#define STRING_WITH_STRINGS 1"
 
 fi
 
-for ac_header in unistd.h semaphore.h sys/time.h malloc.h
+for ac_header in unistd.h semaphore.h sys/time.h sys/auxv.h malloc.h
 do :
   as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh`
 ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default"
@@ -16184,7 +16184,7 @@  rm -f core conftest.err conftest.$ac_obj
     conftest$ac_exeext conftest.$ac_ext
 
 # Check for functions needed.
-for ac_func in strtoull memalign posix_memalign
+for ac_func in strtoull memalign posix_memalign getauxval
 do :
   as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
 ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"
@@ -17364,6 +17364,43 @@  $as_echo "#define HAVE_AS_RTM 1" >>confd
   ;;
 esac
 
+case "${target_cpu}" in
+powerpc*)
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking if the assembler supports HTM" >&5
+$as_echo_n "checking if the assembler supports HTM... " >&6; }
+if test "${libitm_cv_as_htm+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+
+    cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+asm("tbegin. 0; tend. 0");
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  libitm_cv_as_htm=yes
+else
+  libitm_cv_as_htm=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $libitm_cv_as_htm" >&5
+$as_echo "$libitm_cv_as_htm" >&6; }
+  if test x$libitm_cv_as_htm = xyes; then
+
+$as_echo "#define HAVE_AS_HTM 1" >>confdefs.h
+
+  fi
+  ;;
+esac
+
 
   { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether weak refs work like ELF" >&5
 $as_echo_n "checking whether weak refs work like ELF... " >&6; }
Index: libitm/configure.ac
===================================================================
--- libitm/configure.ac	(revision 200584)
+++ libitm/configure.ac	(working copy)
@@ -160,7 +160,7 @@  AC_SUBST(libtool_VERSION)
 AC_STDC_HEADERS
 AC_HEADER_TIME
 ACX_HEADER_STRING
-AC_CHECK_HEADERS(unistd.h semaphore.h sys/time.h malloc.h)
+AC_CHECK_HEADERS(unistd.h semaphore.h sys/time.h sys/auxv.h malloc.h)
 
 GCC_HEADER_STDINT(gstdint.h)
 
@@ -193,7 +193,7 @@  AC_LINK_IFELSE(
    [AC_MSG_ERROR([Pthreads are required to build libitm])])])
 
 # Check for functions needed.
-AC_CHECK_FUNCS(strtoull memalign posix_memalign)
+AC_CHECK_FUNCS(strtoull memalign posix_memalign getauxval)
 
 # Check for broken semaphore implementation on darwin.
 # sem_init returns: sem_init error: Function not implemented.
@@ -245,6 +245,7 @@  LIBITM_CHECK_SYNC_BUILTINS
 LIBITM_CHECK_64BIT_SYNC_BUILTINS
 LIBITM_CHECK_AS_AVX
 LIBITM_CHECK_AS_RTM
+LIBITM_CHECK_AS_HTM
 
 GCC_CHECK_ELF_STYLE_WEAKREF
 
Index: libitm/configure.tgt
===================================================================
--- libitm/configure.tgt	(revision 200584)
+++ libitm/configure.tgt	(working copy)
@@ -47,7 +47,10 @@  fi
 # work out any special compilation flags as necessary.
 case "${target_cpu}" in
   alpha*)		ARCH=alpha ;;
-  rs6000 | powerpc*)	ARCH=powerpc ;;
+  rs6000 | powerpc*)
+	XCFLAGS="${XCFLAGS} -mhtm"
+	ARCH=powerpc
+	;;
 
   arm*)		ARCH=arm ;;
 
Index: libitm/config.h.in
===================================================================
--- libitm/config.h.in	(revision 200584)
+++ libitm/config.h.in	(working copy)
@@ -12,6 +12,9 @@ 
 /* Define if your assembler supports .cfi_* directives. */
 #undef HAVE_AS_CFI_PSEUDO_OP
 
+/* Define to 1 if the assembler supports HTM. */
+#undef HAVE_AS_HTM
+
 /* Define to 1 if the assembler supports RTM. */
 #undef HAVE_AS_RTM
 
@@ -36,6 +39,9 @@ 
 /* Define to 1 if target has a weakref that works like the ELF one. */
 #undef HAVE_ELF_STYLE_WEAKREF
 
+/* Define to 1 if you have the `getauxval' function. */
+#undef HAVE_GETAUXVAL
+
 /* Define to 1 if you have the <inttypes.h> header file. */
 #undef HAVE_INTTYPES_H
 
@@ -81,6 +87,9 @@ 
 /* Define to 1 if the target supports __sync_*_compare_and_swap */
 #undef HAVE_SYNC_BUILTINS
 
+/* Define to 1 if you have the <sys/auxv.h> header file. */
+#undef HAVE_SYS_AUXV_H
+
 /* Define to 1 if you have the <sys/stat.h> header file. */
 #undef HAVE_SYS_STAT_H
 
Index: libitm/config/powerpc/target.h
===================================================================
--- libitm/config/powerpc/target.h	(revision 200584)
+++ libitm/config/powerpc/target.h	(working copy)
@@ -22,6 +22,10 @@ 
    see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
    <http://www.gnu.org/licenses/>.  */
 
+#ifdef HAVE_SYS_AUXV_H
+#include <sys/auxv.h>
+#endif
+
 namespace GTM HIDDEN {
 
 typedef int v128 __attribute__((vector_size(16), may_alias, aligned(16)));
@@ -55,4 +59,82 @@  cpu_relax (void)
   __asm volatile ("" : : : "memory");
 }
 
+// Use HTM if it is supported by the system.
+// See gtm_thread::begin_transaction for how these functions are used.
+#if defined (__linux__) \
+    && defined (HAVE_AS_HTM) \
+    && defined (HAVE_GETAUXVAL) \
+    && defined (AT_HWCAP2) \
+    && defined (PPC_FEATURE2_HAS_HTM)
+
+#include <htmintrin.h>
+
+#define USE_HTM_FASTPATH
+
+#define _TBEGIN_STARTED       0
+#define _TBEGIN_INDETERMINATE 1
+#define _TBEGIN_PERSISTENT    2
+
+/* Number of retries for transient failures.  */
+#define _HTM_RETRIES 10
+
+static inline bool
+htm_available (void)
+{
+  return (getauxval (AT_HWCAP2) & PPC_FEATURE2_HAS_HTM) ? true : false;
+}
+
+static inline uint32_t
+htm_init (void)
+{
+  // Maximum number of times we try to execute a transaction
+  // as a HW transaction.
+  return htm_available () ? _HTM_RETRIES : 0;
+}
+
+static inline uint32_t
+htm_begin (void)
+{
+  if (__builtin_expect (__builtin_tbegin (0), 1))
+    return _TBEGIN_STARTED;
+
+  if (_TEXASRU_FAILURE_PERSISTENT (__builtin_get_texasru ()))
+    return _TBEGIN_PERSISTENT;
+
+  return _TBEGIN_INDETERMINATE;
+}
+
+static inline bool
+htm_begin_success (uint32_t begin_ret)
+{
+  return begin_ret == _TBEGIN_STARTED;
+}
+
+static inline void
+htm_commit (void)
+{
+  __builtin_tend (0);
+}
+
+static inline void
+htm_abort (void)
+{
+  __builtin_tabort (0);
+}
+
+static inline bool
+htm_abort_should_retry (uint32_t begin_ret)
+{
+  return begin_ret != _TBEGIN_PERSISTENT;
+}
+
+/* Returns true iff a hardware transaction is currently being executed.  */
+static inline bool
+htm_transaction_active (void)
+{
+  return (_HTM_STATE (__builtin_ttest ()) == _HTM_TRANSACTIONAL);
+}
+
+#endif
+
 } // namespace GTM
Index: libitm/acinclude.m4
===================================================================
--- libitm/acinclude.m4	(revision 200584)
+++ libitm/acinclude.m4	(working copy)
@@ -123,6 +123,20 @@  i[[34567]]86 | x86_64)
   ;;
 esac])
 
+dnl Check if as supports HTM instructions.
+AC_DEFUN([LIBITM_CHECK_AS_HTM], [
+case "${target_cpu}" in
+powerpc*)
+  AC_CACHE_CHECK([if the assembler supports HTM], libitm_cv_as_htm, [
+    AC_TRY_COMPILE([], [asm("tbegin. 0; tend. 0");],
+		   [libitm_cv_as_htm=yes], [libitm_cv_as_htm=no])
+  ])
+  if test x$libitm_cv_as_htm = xyes; then
+    AC_DEFINE(HAVE_AS_HTM, 1, [Define to 1 if the assembler supports HTM.])
+  fi
+  ;;
+esac])
+
 sinclude(../libtool.m4)
 dnl The lines below arrange for aclocal not to bring an installed
 dnl libtool.m4 into aclocal.m4, while still arranging for automake to
Index: gcc/testsuite/gcc.target/powerpc/htm-xl-intrin-1.c
===================================================================
--- gcc/testsuite/gcc.target/powerpc/htm-xl-intrin-1.c	(revision 0)
+++ gcc/testsuite/gcc.target/powerpc/htm-xl-intrin-1.c	(revision 0)
@@ -0,0 +1,32 @@ 
+/* This checks the availability of the XL compiler intrinsics for
+   transactional execution with the expected prototypes.  */
+
+/* { dg-do compile { target { powerpc*-*-* } } } */
+/* { dg-skip-if "" { powerpc*-*-darwin* } { "*" } { "" } } */
+/* { dg-require-effective-target powerpc_htm_ok } */
+/* { dg-options "-O2 -mhtm" } */
+
+#include <htmxlintrin.h>
+
+void
+foo (void *TM_buff, long *result, unsigned char *code)
+{
+  *result++ = __TM_simple_begin ();
+  *result++ = __TM_begin (TM_buff);
+  *result++ = __TM_end ();
+  __TM_abort ();
+  __TM_named_abort (*code);
+  __TM_resume ();
+  __TM_suspend ();
+  *result++ = __TM_is_user_abort (TM_buff);
+  *result++ = __TM_is_named_user_abort (TM_buff, code);
+  *result++ = __TM_is_illegal (TM_buff);
+  *result++ = __TM_is_footprint_exceeded (TM_buff);
+  *result++ = __TM_nesting_depth (TM_buff);
+  *result++ = __TM_is_nested_too_deep (TM_buff);
+  *result++ = __TM_is_conflict (TM_buff);
+  *result++ = __TM_is_failure_persistent (TM_buff);
+  *result++ = __TM_failure_address (TM_buff);
+  *result++ = __TM_failure_code (TM_buff);
+}
+
Index: gcc/testsuite/gcc.target/powerpc/htm-builtin-1.c
===================================================================
--- gcc/testsuite/gcc.target/powerpc/htm-builtin-1.c	(revision 0)
+++ gcc/testsuite/gcc.target/powerpc/htm-builtin-1.c	(revision 0)
@@ -0,0 +1,51 @@ 
+/* { dg-do compile { target { powerpc*-*-* } } } */
+/* { dg-skip-if "" { powerpc*-*-darwin* } { "*" } { "" } } */
+/* { dg-require-effective-target powerpc_htm_ok } */
+/* { dg-options "-O2 -mhtm" } */
+
+/* { dg-final { scan-assembler-times "tbegin\\." 1 } } */
+/* { dg-final { scan-assembler-times "tend\\." 2 } } */
+/* { dg-final { scan-assembler-times "tabort\\." 2 } } */
+/* { dg-final { scan-assembler-times "tabortdc\\." 1 } } */
+/* { dg-final { scan-assembler-times "tabortdci\\." 1 } } */
+/* { dg-final { scan-assembler-times "tabortwc\\." 1 } } */
+/* { dg-final { scan-assembler-times "tabortwci\\." 2 } } */
+/* { dg-final { scan-assembler-times "tcheck\\." 1 } } */
+/* { dg-final { scan-assembler-times "trechkpt\\." 1 } } */
+/* { dg-final { scan-assembler-times "treclaim\\." 1 } } */
+/* { dg-final { scan-assembler-times "tsr\\." 3 } } */
+/* { dg-final { scan-assembler-times "mfspr" 4 } } */
+/* { dg-final { scan-assembler-times "mtspr" 4 } } */
+
+void use_builtins (long *p, char code, long *a, long *b)
+{
+  p[0] = __builtin_tbegin (0);
+  p[1] = __builtin_tend (0);
+  p[2] = __builtin_tendall ();
+  p[3] = __builtin_tabort (0);
+  p[4] = __builtin_tabort (code);
+
+  p[5] = __builtin_tabortdc (0xf, a[5], b[5]);
+  p[6] = __builtin_tabortdci (0xf, a[6], 13);
+  p[7] = __builtin_tabortwc (0xf, a[7], b[7]);
+  p[8] = __builtin_tabortwci (0xf, a[8], 13);
+
+  p[9] = __builtin_tcheck (5);
+  p[10] = __builtin_trechkpt ();
+  p[11] = __builtin_treclaim (0);
+  p[12] = __builtin_tresume ();
+  p[13] = __builtin_tsuspend ();
+  p[14] = __builtin_tsr (0);
+  p[15] = __builtin_ttest (); /* This expands to a tabortwci.  */
+
+
+  p[16] = __builtin_get_texasr ();
+  p[17] = __builtin_get_texasru ();
+  p[18] = __builtin_get_tfhar ();
+  p[19] = __builtin_get_tfiar ();
+
+  __builtin_set_texasr (a[20]);
+  __builtin_set_texasru (a[21]);
+  __builtin_set_tfhar (a[22]);
+  __builtin_set_tfiar (a[23]);
+}
Index: gcc/testsuite/lib/target-supports.exp
===================================================================
--- gcc/testsuite/lib/target-supports.exp	(revision 200584)
+++ gcc/testsuite/lib/target-supports.exp	(working copy)
@@ -2830,6 +2830,27 @@  proc check_effective_target_powerpc_vsx_
     }
 }
 
+# Return 1 if this is a PowerPC target supporting -mhtm
+
+proc check_effective_target_powerpc_htm_ok { } {
+    if { ([istarget powerpc*-*-*]
+         && ![istarget powerpc-*-linux*paired*])
+	 || [istarget rs6000-*-*] } {
+	# HTM is not supported on AIX yet.
+	if { [istarget powerpc*-*-aix*] } {
+	    return 0
+	}
+	return [check_no_compiler_messages powerpc_htm_ok object {
+	    int main (void) {
+		asm volatile ("tbegin. 0");
+		return 0;
+	    }
+	} "-mhtm"]
+    } else {
+	return 0
+    }
+}
+
 # Return 1 if this is a PowerPC target supporting -mcpu=cell.
 
 proc check_effective_target_powerpc_ppu_ok { } {
Index: gcc/config.gcc
===================================================================
--- gcc/config.gcc	(revision 200584)
+++ gcc/config.gcc	(working copy)
@@ -421,7 +421,7 @@  picochip-*-*)
         ;;
 powerpc*-*-*)
 	cpu_type=rs6000
-	extra_headers="ppc-asm.h altivec.h spe.h ppu_intrinsics.h paired.h spu2vmx.h vec_types.h si2vmx.h"
+	extra_headers="ppc-asm.h altivec.h spe.h ppu_intrinsics.h paired.h spu2vmx.h vec_types.h si2vmx.h htmintrin.h htmxlintrin.h"
 	need_64bit_hwint=yes
 	case x$with_cpu in
 	    xpowerpc64|xdefault64|x6[23]0|x970|xG5|xpower[345678]|xpower6x|xrs64a|xcell|xa2|xe500mc64|xe5500|Xe6500)
Index: gcc/config/rs6000/predicates.md
===================================================================
--- gcc/config/rs6000/predicates.md	(revision 200584)
+++ gcc/config/rs6000/predicates.md	(working copy)
@@ -124,6 +124,11 @@  (define_predicate "s5bit_cint_operand"
   (and (match_code "const_int")
        (match_test "INTVAL (op) >= -16 && INTVAL (op) <= 15")))
 
+;; Return 1 if op is a unsigned 3-bit constant integer.
+(define_predicate "u3bit_cint_operand"
+  (and (match_code "const_int")
+       (match_test "INTVAL (op) >= 0 && INTVAL (op) <= 7")))
+
 ;; Return 1 if op is a unsigned 5-bit constant integer.
 (define_predicate "u5bit_cint_operand"
   (and (match_code "const_int")
@@ -135,6 +140,11 @@  (define_predicate "s8bit_cint_operand"
   (and (match_code "const_int")
        (match_test "INTVAL (op) >= -128 && INTVAL (op) <= 127")))
 
+;; Return 1 if op is a unsigned 10-bit constant integer.
+(define_predicate "u10bit_cint_operand"
+  (and (match_code "const_int")
+       (match_test "INTVAL (op) >= 0 && INTVAL (op) <= 1023")))
+
 ;; Return 1 if op is a constant integer that can fit in a D field.
 (define_predicate "short_cint_operand"
   (and (match_code "const_int")
@@ -226,6 +236,33 @@  (define_predicate "base_reg_operand"
   return (REGNO (op) != FIRST_GPR_REGNO);
 })
 
+;; Return 1 if op is a HTM specific SPR register.
+(define_predicate "htm_spr_reg_operand"
+  (match_operand 0 "register_operand")
+{
+  if (!TARGET_HTM)
+    return 0;
+
+  if (GET_CODE (op) == SUBREG)
+    op = SUBREG_REG (op);
+
+  if (!REG_P (op))
+    return 0;
+
+  switch (REGNO (op))
+    {
+      case TFHAR_REGNO:
+      case TFIAR_REGNO:
+      case TEXASR_REGNO:
+	return 1;
+      default:
+	break;
+    }
+  
+  /* Unknown SPR.  */
+  return 0;
+})
+
 ;; Return 1 if op is a general purpose register that is an even register
 ;; which suitable for a load/store quad operation
 (define_predicate "quad_int_reg_operand"
Index: gcc/config/rs6000/htm.md
===================================================================
--- gcc/config/rs6000/htm.md	(revision 0)
+++ gcc/config/rs6000/htm.md	(revision 0)
@@ -0,0 +1,366 @@ 
+;; Hardware Transactional Memory (HTM) patterns.
+;; Copyright (C) 2013 Free Software Foundation, Inc.
+;; Contributed by Peter Bergner <bergner@vnet.ibm.com>.
+
+;; This file is part of GCC.
+
+;; GCC is free software; you can redistribute it and/or modify it
+;; under the terms of the GNU General Public License as published
+;; by the Free Software Foundation; either version 3, or (at your
+;; option) any later version.
+
+;; GCC is distributed in the hope that it will be useful, but WITHOUT
+;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+;; or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
+;; License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GCC; see the file COPYING3.  If not see
+;; <http://www.gnu.org/licenses/>.
+
+(define_constants
+  [(TFHAR_SPR		128)
+   (TFIAR_SPR		129)
+   (TEXASR_SPR		130)
+   (TEXASRU_SPR		131)
+   (MAX_HTM_OPERANDS	4)
+  ])
+
+;;
+;; UNSPEC_VOLATILE usage
+;;
+
+(define_c_enum "unspecv"
+  [UNSPECV_HTM_TABORT
+   UNSPECV_HTM_TABORTDC
+   UNSPECV_HTM_TABORTDCI
+   UNSPECV_HTM_TABORTWC
+   UNSPECV_HTM_TABORTWCI
+   UNSPECV_HTM_TBEGIN
+   UNSPECV_HTM_TCHECK
+   UNSPECV_HTM_TEND
+   UNSPECV_HTM_TRECHKPT
+   UNSPECV_HTM_TRECLAIM
+   UNSPECV_HTM_TSR
+   UNSPECV_HTM_MFSPR
+   UNSPECV_HTM_MTSPR
+  ])
+
+
+(define_expand "tabort"
+  [(set (match_dup 2)
+	(unspec_volatile:CC [(match_operand:SI 1 "int_reg_operand" "")]
+			    UNSPECV_HTM_TABORT))
+   (set (match_dup 3)
+	(eq:SI (match_dup 2)
+	       (const_int 0)))
+   (set (match_operand:SI 0 "int_reg_operand" "")
+	(minus:SI (const_int 1) (match_dup 3)))]
+  "TARGET_HTM"
+{
+  operands[2] = gen_rtx_REG (CCmode, CR0_REGNO);
+  operands[3] = gen_reg_rtx (SImode);
+})
+
+(define_insn "*tabort_internal"
+  [(set (match_operand:CC 1 "cc_reg_operand" "=x")
+	(unspec_volatile:CC [(match_operand:SI 0 "int_reg_operand" "r")]
+			    UNSPECV_HTM_TABORT))]
+  "TARGET_HTM"
+  "tabort. %0"
+  [(set_attr "type" "htm")
+   (set_attr "length" "4")])
+
+(define_expand "tabortdc"
+  [(set (match_dup 4)
+	(unspec_volatile:CC [(match_operand 1 "u5bit_cint_operand" "n")
+			     (match_operand:SI 2 "gpc_reg_operand" "r")
+			     (match_operand:SI 3 "gpc_reg_operand" "r")]
+			    UNSPECV_HTM_TABORTDC))
+   (set (match_dup 5)
+	(eq:SI (match_dup 4)
+	       (const_int 0)))
+   (set (match_operand:SI 0 "int_reg_operand" "")
+	(minus:SI (const_int 1) (match_dup 5)))]
+  "TARGET_HTM"
+{
+  operands[4] = gen_rtx_REG (CCmode, CR0_REGNO);
+  operands[5] = gen_reg_rtx (SImode);
+})
+
+(define_insn "*tabortdc_internal"
+  [(set (match_operand:CC 3 "cc_reg_operand" "=x")
+	(unspec_volatile:CC [(match_operand 0 "u5bit_cint_operand" "n")
+			     (match_operand:SI 1 "gpc_reg_operand" "r")
+			     (match_operand:SI 2 "gpc_reg_operand" "r")]
+			    UNSPECV_HTM_TABORTDC))]
+  "TARGET_HTM"
+  "tabortdc. %0,%1,%2"
+  [(set_attr "type" "htm")
+   (set_attr "length" "4")])
+
+(define_expand "tabortdci"
+  [(set (match_dup 4)
+	(unspec_volatile:CC [(match_operand 1 "u5bit_cint_operand" "n")
+			     (match_operand:SI 2 "gpc_reg_operand" "r")
+			     (match_operand 3 "s5bit_cint_operand" "n")]
+			    UNSPECV_HTM_TABORTDCI))
+   (set (match_dup 5)
+	(eq:SI (match_dup 4)
+	       (const_int 0)))
+   (set (match_operand:SI 0 "int_reg_operand" "")
+	(minus:SI (const_int 1) (match_dup 5)))]
+  "TARGET_HTM"
+{
+  operands[4] = gen_rtx_REG (CCmode, CR0_REGNO);
+  operands[5] = gen_reg_rtx (SImode);
+})
+
+(define_insn "*tabortdci_internal"
+  [(set (match_operand:CC 3 "cc_reg_operand" "=x")
+	(unspec_volatile:CC [(match_operand 0 "u5bit_cint_operand" "n")
+			     (match_operand:SI 1 "gpc_reg_operand" "r")
+			     (match_operand 2 "s5bit_cint_operand" "n")]
+			    UNSPECV_HTM_TABORTDCI))]
+  "TARGET_HTM"
+  "tabortdci. %0,%1,%2"
+  [(set_attr "type" "htm")
+   (set_attr "length" "4")])
+
+(define_expand "tabortwc"
+  [(set (match_dup 4)
+	(unspec_volatile:CC [(match_operand 1 "u5bit_cint_operand" "n")
+			     (match_operand:SI 2 "gpc_reg_operand" "r")
+			     (match_operand:SI 3 "gpc_reg_operand" "r")]
+			    UNSPECV_HTM_TABORTWC))
+   (set (match_dup 5)
+	(eq:SI (match_dup 4)
+	       (const_int 0)))
+   (set (match_operand:SI 0 "int_reg_operand" "")
+	(minus:SI (const_int 1) (match_dup 5)))]
+  "TARGET_HTM"
+{
+  operands[4] = gen_rtx_REG (CCmode, CR0_REGNO);
+  operands[5] = gen_reg_rtx (SImode);
+})
+
+(define_insn "*tabortwc_internal"
+  [(set (match_operand:CC 3 "cc_reg_operand" "=x")
+	(unspec_volatile:CC [(match_operand 0 "u5bit_cint_operand" "n")
+			     (match_operand:SI 1 "gpc_reg_operand" "r")
+			     (match_operand:SI 2 "gpc_reg_operand" "r")]
+			    UNSPECV_HTM_TABORTWC))]
+  "TARGET_HTM"
+  "tabortwc. %0,%1,%2"
+  [(set_attr "type" "htm")
+   (set_attr "length" "4")])
+
+(define_expand "tabortwci"
+  [(set (match_dup 4)
+	(unspec_volatile:CC [(match_operand 1 "u5bit_cint_operand" "n")
+			     (match_operand:SI 2 "gpc_reg_operand" "r")
+			     (match_operand 3 "s5bit_cint_operand" "n")]
+			    UNSPECV_HTM_TABORTWCI))
+   (set (match_dup 5)
+	(eq:SI (match_dup 4)
+	       (const_int 0)))
+   (set (match_operand:SI 0 "int_reg_operand" "")
+	(minus:SI (const_int 1) (match_dup 5)))]
+  "TARGET_HTM"
+{
+  operands[4] = gen_rtx_REG (CCmode, CR0_REGNO);
+  operands[5] = gen_reg_rtx (SImode);
+})
+
+(define_expand "ttest"
+  [(set (match_dup 1)
+	(unspec_volatile:CC [(const_int 0)
+			     (reg:SI 0)
+			     (const_int 0)]
+			    UNSPECV_HTM_TABORTWCI))
+   (set (subreg:CC (match_dup 2) 0) (match_dup 1))
+   (set (match_dup 3) (lshiftrt:SI (match_dup 2) (const_int 24)))
+   (parallel [(set (match_operand:SI 0 "int_reg_operand" "")
+		   (and:SI (match_dup 3) (const_int 15)))
+              (clobber (scratch:CC))])]
+  "TARGET_HTM"
+{
+  operands[1] = gen_rtx_REG (CCmode, CR0_REGNO);
+  operands[2] = gen_reg_rtx (SImode);
+  operands[3] = gen_reg_rtx (SImode);
+})
+
+(define_insn "*tabortwci_internal"
+  [(set (match_operand:CC 3 "cc_reg_operand" "=x")
+	(unspec_volatile:CC [(match_operand 0 "u5bit_cint_operand" "n")
+			     (match_operand:SI 1 "gpc_reg_operand" "r")
+			     (match_operand 2 "s5bit_cint_operand" "n")]
+			    UNSPECV_HTM_TABORTWCI))]
+  "TARGET_HTM"
+  "tabortwci. %0,%1,%2"
+  [(set_attr "type" "htm")
+   (set_attr "length" "4")])
+
+(define_expand "tbegin"
+  [(set (match_dup 2)
+	(unspec_volatile:CC [(match_operand 1 "const_0_to_1_operand" "n")]
+			    UNSPECV_HTM_TBEGIN))
+   (set (match_dup 3)
+	(eq:SI (match_dup 2)
+	       (const_int 0)))
+   (set (match_operand:SI 0 "int_reg_operand" "")
+	(minus:SI (const_int 1) (match_dup 3)))]
+  "TARGET_HTM"
+{
+  operands[2] = gen_rtx_REG (CCmode, CR0_REGNO);
+  operands[3] = gen_reg_rtx (SImode);
+})
+
+(define_insn "*tbegin_internal"
+  [(set (match_operand:CC 1 "cc_reg_operand" "=x")
+	(unspec_volatile:CC [(match_operand 0 "const_0_to_1_operand" "n")]
+			    UNSPECV_HTM_TBEGIN))]
+  "TARGET_HTM"
+  "tbegin. %0"
+  [(set_attr "type" "htm")
+   (set_attr "length" "4")])
+
+(define_expand "tcheck"
+  [(set (match_dup 2)
+	(unspec_volatile:CC [(match_operand 1 "u3bit_cint_operand" "n")]
+			    UNSPECV_HTM_TCHECK))
+   (set (match_dup 3)
+	(eq:SI (match_dup 2)
+	       (const_int 0)))
+   (set (match_operand:SI 0 "int_reg_operand" "")
+	(minus:SI (const_int 1) (match_dup 3)))]
+  "TARGET_HTM"
+{
+  operands[2] = gen_rtx_REG (CCmode, CR0_REGNO);
+  operands[3] = gen_reg_rtx (SImode);
+})
+
+(define_insn "*tcheck_internal"
+  [(set (match_operand:CC 1 "cc_reg_operand" "=x")
+	(unspec_volatile:CC [(match_operand 0 "u3bit_cint_operand" "n")]
+			    UNSPECV_HTM_TCHECK))]
+  "TARGET_HTM"
+  "tcheck. %0"
+  [(set_attr "type" "htm")
+   (set_attr "length" "4")])
+
+(define_expand "tend"
+  [(set (match_dup 2)
+	(unspec_volatile:CC [(match_operand 1 "const_0_to_1_operand" "n")]
+			    UNSPECV_HTM_TEND))
+   (set (match_dup 3)
+	(eq:SI (match_dup 2)
+	       (const_int 0)))
+   (set (match_operand:SI 0 "int_reg_operand" "")
+	(minus:SI (const_int 1) (match_dup 3)))]
+  "TARGET_HTM"
+{
+  operands[2] = gen_rtx_REG (CCmode, CR0_REGNO);
+  operands[3] = gen_reg_rtx (SImode);
+})
+
+(define_insn "*tend_internal"
+  [(set (match_operand:CC 1 "cc_reg_operand" "=x")
+	(unspec_volatile:CC [(match_operand 0 "const_0_to_1_operand" "n")]
+			    UNSPECV_HTM_TEND))]
+  "TARGET_HTM"
+  "tend. %0"
+  [(set_attr "type" "htm")
+   (set_attr "length" "4")])
+
+(define_expand "trechkpt"
+  [(set (match_dup 1)
+	(unspec_volatile:CC [(const_int 0)]
+			    UNSPECV_HTM_TRECHKPT))
+   (set (match_dup 2)
+	(eq:SI (match_dup 1)
+	       (const_int 0)))
+   (set (match_operand:SI 0 "int_reg_operand" "")
+	(minus:SI (const_int 1) (match_dup 2)))]
+  "TARGET_HTM"
+{
+  operands[1] = gen_rtx_REG (CCmode, CR0_REGNO);
+  operands[2] = gen_reg_rtx (SImode);
+})
+
+(define_insn "*trechkpt_internal"
+  [(set (match_operand:CC 0 "cc_reg_operand" "=x")
+	(unspec_volatile:CC [(const_int 0)]
+			    UNSPECV_HTM_TRECHKPT))]
+  "TARGET_HTM"
+  "trechkpt."
+  [(set_attr "type" "htm")
+   (set_attr "length" "4")])
+
+(define_expand "treclaim"
+  [(set (match_dup 2)
+	(unspec_volatile:CC [(match_operand:SI 1 "gpc_reg_operand" "r")]
+			    UNSPECV_HTM_TRECLAIM))
+   (set (match_dup 3)
+	(eq:SI (match_dup 2)
+	       (const_int 0)))
+   (set (match_operand:SI 0 "int_reg_operand" "")
+	(minus:SI (const_int 1) (match_dup 3)))]
+  "TARGET_HTM"
+{
+  operands[2] = gen_rtx_REG (CCmode, CR0_REGNO);
+  operands[3] = gen_reg_rtx (SImode);
+})
+
+(define_insn "*treclaim_internal"
+  [(set (match_operand:CC 1 "cc_reg_operand" "=x")
+	(unspec_volatile:CC [(match_operand:SI 0 "gpc_reg_operand" "r")]
+			    UNSPECV_HTM_TRECLAIM))]
+  "TARGET_HTM"
+  "treclaim. %0"
+  [(set_attr "type" "htm")
+   (set_attr "length" "4")])
+
+(define_expand "tsr"
+  [(set (match_dup 2)
+	(unspec_volatile:CC [(match_operand 1 "const_0_to_1_operand" "n")]
+			    UNSPECV_HTM_TSR))
+   (set (match_dup 3)
+	(eq:SI (match_dup 2)
+	       (const_int 0)))
+   (set (match_operand:SI 0 "int_reg_operand" "")
+	(minus:SI (const_int 1) (match_dup 3)))]
+  "TARGET_HTM"
+{
+  operands[2] = gen_rtx_REG (CCmode, CR0_REGNO);
+  operands[3] = gen_reg_rtx (SImode);
+})
+
+(define_insn "*tsr_internal"
+  [(set (match_operand:CC 1 "cc_reg_operand" "=x")
+	(unspec_volatile:CC [(match_operand 0 "const_0_to_1_operand" "n")]
+			    UNSPECV_HTM_TSR))]
+  "TARGET_HTM"
+  "tsr. %0"
+  [(set_attr "type" "htm")
+   (set_attr "length" "4")])
+
+(define_insn "htm_mfspr_<mode>"
+  [(set (match_operand:P 0 "gpc_reg_operand" "=r")
+        (unspec_volatile:P [(match_operand 1 "u10bit_cint_operand" "n")
+			    (match_operand:P 2 "htm_spr_reg_operand" "")]
+			   UNSPECV_HTM_MFSPR))]
+  "TARGET_HTM"
+  "mfspr %0,%1";
+  [(set_attr "type" "htm")
+   (set_attr "length" "4")])
+
+(define_insn "htm_mtspr_<mode>"
+  [(set (match_operand:P 2 "htm_spr_reg_operand" "")
+        (unspec_volatile:P [(match_operand:P 0 "gpc_reg_operand" "r")
+			    (match_operand 1 "u10bit_cint_operand" "n")]
+                           UNSPECV_HTM_MTSPR))]
+  "TARGET_HTM"
+  "mtspr %1,%0";
+  [(set_attr "type" "htm")
+   (set_attr "length" "4")])
Index: gcc/config/rs6000/rs6000-cpus.def
===================================================================
--- gcc/config/rs6000/rs6000-cpus.def	(revision 200584)
+++ gcc/config/rs6000/rs6000-cpus.def	(working copy)
@@ -51,6 +51,7 @@ 
 				 | OPTION_MASK_P8_VECTOR		\
 				 | OPTION_MASK_CRYPTO			\
 				 | OPTION_MASK_DIRECT_MOVE		\
+				 | OPTION_MASK_HTM			\
 				 | OPTION_MASK_QUAD_MEMORY)
 
 #define POWERPC_7400_MASK	(OPTION_MASK_PPC_GFXOPT | OPTION_MASK_ALTIVEC)
@@ -74,6 +75,7 @@ 
 				 | OPTION_MASK_DIRECT_MOVE		\
 				 | OPTION_MASK_DLMZB			\
 				 | OPTION_MASK_FPRND			\
+				 | OPTION_MASK_HTM			\
 				 | OPTION_MASK_ISEL			\
 				 | OPTION_MASK_MFCRF			\
 				 | OPTION_MASK_MFPGPR			\
Index: gcc/config/rs6000/htmintrin.h
===================================================================
--- gcc/config/rs6000/htmintrin.h	(revision 0)
+++ gcc/config/rs6000/htmintrin.h	(revision 0)
@@ -0,0 +1,131 @@ 
+/* Hardware Transactional Memory (HTM) intrinsics.
+   Copyright (C) 2013 Free Software Foundation, Inc.
+   Contributed by Peter Bergner <bergner@vnet.ibm.com>.
+
+   This file is free software; you can redistribute it and/or modify it under
+   the terms of the GNU General Public License as published by the Free
+   Software Foundation; either version 3 of the License, or (at your option)
+   any later version.
+
+   This file is distributed in the hope that it will be useful, but WITHOUT
+   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+   FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+   for more details.
+
+   Under Section 7 of GPL version 3, you are granted additional
+   permissions described in the GCC Runtime Library Exception, version
+   3.1, as published by the Free Software Foundation.
+
+   You should have received a copy of the GNU General Public License and
+   a copy of the GCC Runtime Library Exception along with this program;
+   see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#ifndef __HTM__
+# error "HTM instruction set not enabled"
+#endif /* __HTM__ */
+
+#ifndef _HTMINTRIN_H
+#define _HTMINTRIN_H
+
+#include <stdint.h>
+
+typedef uint64_t texasr_t;
+typedef uint32_t texasru_t;
+typedef uint32_t texasrl_t;
+typedef uintptr_t tfiar_t;
+typedef uintptr_t tfhar_t;
+
+#define _HTM_STATE(CR0) ((CR0 >> 1) & 0x3)
+#define _HTM_NONTRANSACTIONAL 0x0
+#define _HTM_SUSPENDED        0x1
+#define _HTM_TRANSACTIONAL    0x2
+
+/* The following macros use the IBM bit numbering for BITNUM
+   as used in the ISA documentation.  */
+
+#define _TEXASR_EXTRACT_BITS(TEXASR,BITNUM,SIZE) \
+  (((TEXASR) >> (63-(BITNUM))) & ((1<<(SIZE))-1))
+#define _TEXASRU_EXTRACT_BITS(TEXASR,BITNUM,SIZE) \
+  (((TEXASR) >> (31-(BITNUM))) & ((1<<(SIZE))-1))
+
+#define _TEXASR_FAILURE_CODE(TEXASR) \
+  _TEXASR_EXTRACT_BITS(TEXASR, 7, 8)
+#define _TEXASRU_FAILURE_CODE(TEXASRU) \
+  _TEXASRU_EXTRACT_BITS(TEXASRU, 7, 8)
+
+#define _TEXASR_FAILURE_PERSISTENT(TEXASR) \
+  _TEXASR_EXTRACT_BITS(TEXASR, 7, 1)
+#define _TEXASRU_FAILURE_PERSISTENT(TEXASRU) \
+  _TEXASRU_EXTRACT_BITS(TEXASRU, 7, 1)
+
+#define _TEXASR_DISALLOWED(TEXASR) \
+  _TEXASR_EXTRACT_BITS(TEXASR, 8, 1)
+#define _TEXASRU_DISALLOWED(TEXASRU) \
+  _TEXASRU_EXTRACT_BITS(TEXASRU, 8, 1)
+
+#define _TEXASR_NESTING_OVERFLOW(TEXASR) \
+  _TEXASR_EXTRACT_BITS(TEXASR, 9, 1)
+#define _TEXASRU_NESTING_OVERFLOW(TEXASRU) \
+  _TEXASRU_EXTRACT_BITS(TEXASRU, 9, 1)
+
+#define _TEXASR_FOOTPRINT_OVERFLOW(TEXASR) \
+  _TEXASR_EXTRACT_BITS(TEXASR, 10, 1)
+#define _TEXASRU_FOOTPRINT_OVERFLOW(TEXASRU) \
+  _TEXASRU_EXTRACT_BITS(TEXASRU, 10, 1)
+
+#define _TEXASR_SELF_INDUCED_CONFLICT(TEXASR) \
+  _TEXASR_EXTRACT_BITS(TEXASR, 11, 1)
+#define _TEXASRU_SELF_INDUCED_CONFLICT(TEXASRU) \
+  _TEXASRU_EXTRACT_BITS(TEXASRU, 11, 1)
+
+#define _TEXASR_NON_TRANSACTIONAL_CONFLICT(TEXASR) \
+  _TEXASR_EXTRACT_BITS(TEXASR, 12, 1)
+#define _TEXASRU_NON_TRANSACTIONAL_CONFLICT(TEXASRU) \
+  _TEXASRU_EXTRACT_BITS(TEXASRU, 12, 1)
+
+#define _TEXASR_TRANSACTION_CONFLICT(TEXASR) \
+  _TEXASR_EXTRACT_BITS(TEXASR, 13, 1)
+#define _TEXASRU_TRANSACTION_CONFLICT(TEXASRU) \
+  _TEXASRU_EXTRACT_BITS(TEXASRU, 13, 1)
+
+#define _TEXASR_TRANSLATION_INVALIDATION_CONFLICT(TEXASR) \
+  _TEXASR_EXTRACT_BITS(TEXASR, 14, 1)
+#define _TEXASRU_TRANSLATION_INVALIDATION_CONFLICT(TEXASRU) \
+  _TEXASRU_EXTRACT_BITS(TEXASRU, 14, 1)
+
+#define _TEXASR_IMPLEMENTAION_SPECIFIC(TEXASR) \
+  _TEXASR_EXTRACT_BITS(TEXASR, 15, 1)
+#define _TEXASRU_IMPLEMENTAION_SPECIFIC(TEXASRU) \
+  _TEXASRU_EXTRACT_BITS(TEXASRU, 15, 1)
+
+#define _TEXASR_INSRUCTION_FETCH_CONFLICT(TEXASR) \
+  _TEXASR_EXTRACT_BITS(TEXASR, 16, 1)
+#define _TEXASRU_INSRUCTION_FETCH_CONFLICT(TEXASRU) \
+  _TEXASRU_EXTRACT_BITS(TEXASRU, 16, 1)
+
+#define _TEXASR_ABORT(TEXASR) \
+  _TEXASR_EXTRACT_BITS(TEXASR, 31, 1)
+#define _TEXASRU_ABORT(TEXASRU) \
+  _TEXASRU_EXTRACT_BITS(TEXASRU, 31, 1)
+
+
+#define _TEXASR_SUSPENDED(TEXASR) \
+  _TEXASR_EXTRACT_BITS(TEXASR, 32, 1)
+
+#define _TEXASR_PRIVILEGE(TEXASR) \
+  _TEXASR_EXTRACT_BITS(TEXASR, 35, 2)
+
+#define _TEXASR_FAILURE_SUMMARY(TEXASR) \
+  _TEXASR_EXTRACT_BITS(TEXASR, 36, 1)
+
+#define _TEXASR_TFIAR_EXACT(TEXASR) \
+  _TEXASR_EXTRACT_BITS(TEXASR, 37, 1)
+
+#define _TEXASR_ROT(TEXASR) \
+  _TEXASR_EXTRACT_BITS(TEXASR, 38, 1)
+
+#define _TEXASR_TRANSACTION_LEVEL(TEXASR) \
+  _TEXASR_EXTRACT_BITS(TEXASR, 63, 12)
+
+#endif /* _HTMINTRIN_H */
Index: gcc/config/rs6000/t-rs6000
===================================================================
--- gcc/config/rs6000/t-rs6000	(revision 200584)
+++ gcc/config/rs6000/t-rs6000	(working copy)
@@ -72,6 +72,7 @@  MD_INCLUDES = $(srcdir)/config/rs6000/rs
 	$(srcdir)/config/rs6000/vsx.md \
 	$(srcdir)/config/rs6000/altivec.md \
 	$(srcdir)/config/rs6000/crypto.md \
+	$(srcdir)/config/rs6000/htm.md \
 	$(srcdir)/config/rs6000/spe.md \
 	$(srcdir)/config/rs6000/dfp.md \
 	$(srcdir)/config/rs6000/paired.md
Index: gcc/config/rs6000/htmxlintrin.h
===================================================================
--- gcc/config/rs6000/htmxlintrin.h	(revision 0)
+++ gcc/config/rs6000/htmxlintrin.h	(revision 0)
@@ -0,0 +1,210 @@ 
+/* XL compiler Hardware Transactional Memory (HTM) execution intrinsics.
+   Copyright (C) 2013 Free Software Foundation, Inc.
+   Contributed by Peter Bergner <bergner@vnet.ibm.com>.
+
+   This file is free software; you can redistribute it and/or modify it under
+   the terms of the GNU General Public License as published by the Free
+   Software Foundation; either version 3 of the License, or (at your option)
+   any later version.
+
+   This file is distributed in the hope that it will be useful, but WITHOUT
+   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+   FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+   for more details.
+
+   Under Section 7 of GPL version 3, you are granted additional
+   permissions described in the GCC Runtime Library Exception, version
+   3.1, as published by the Free Software Foundation.
+
+   You should have received a copy of the GNU General Public License and
+   a copy of the GCC Runtime Library Exception along with this program;
+   see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#ifndef __HTM__
+# error "HTM instruction set not enabled"
+#endif /* __HTM__ */
+
+#ifndef _HTMXLINTRIN_H
+#define _HTMXLINTRIN_H
+
+#include <stdint.h>
+#include <htmintrin.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define _TEXASR_PTR(TM_BUF) \
+  ((texasr_t *)((TM_BUF)+0))
+#define _TEXASRU_PTR(TM_BUF) \
+  ((texasru_t *)((TM_BUF)+0))
+#define _TEXASRL_PTR(TM_BUF) \
+  ((texasrl_t *)((TM_BUF)+4))
+#define _TFIAR_PTR(TM_BUF) \
+  ((tfiar_t *)((TM_BUF)+8))
+
+typedef char TM_buff_type[16];
+
+extern __inline long
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+__TM_simple_begin (void)
+{
+  if (__builtin_expect (__builtin_tbegin (0), 1))
+    return 1;
+  return 0;
+}
+
+extern __inline long
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+__TM_begin (void* const TM_buff)
+{
+  if (__builtin_expect (__builtin_tbegin (0), 1))
+    {
+      *_TEXASRL_PTR (TM_buff) = 0;
+      return 1;
+    }
+#ifdef __powerpc64__
+  *_TEXASR_PTR (TM_buff) = __builtin_get_texasr ();
+#else
+  *_TEXASRU_PTR (TM_buff) = __builtin_get_texasru ();
+  *_TEXASRL_PTR (TM_buff) = __builtin_get_texasr ();
+#endif
+  *_TFIAR_PTR (TM_buff) = __builtin_get_tfiar ();
+  return 0;
+}
+
+extern __inline long
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+__TM_end (void)
+{
+  if (__builtin_expect (__builtin_tend (0), 1))
+    return 1;
+  return 0;
+}
+
+extern __inline void
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+__TM_abort (void)
+{
+  __builtin_tabort (0);
+}
+
+extern __inline void
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+__TM_named_abort (unsigned char const code)
+{
+  __builtin_tabort (code);
+}
+
+extern __inline void
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+__TM_resume (void)
+{
+  __builtin_tresume ();
+}
+
+extern __inline void
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+__TM_suspend (void)
+{
+  __builtin_tsuspend ();
+}
+
+extern __inline long
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+__TM_is_user_abort (void* const TM_buff)
+{
+  texasru_t texasru = *_TEXASRU_PTR (TM_buff);
+  return _TEXASRU_ABORT (texasru);
+}
+
+extern __inline long
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+__TM_is_named_user_abort (void* const TM_buff, unsigned char *code)
+{
+  texasru_t texasru = *_TEXASRU_PTR (TM_buff);
+
+  *code = _TEXASRU_FAILURE_CODE (texasru);
+  return _TEXASRU_ABORT (texasru);
+}
+
+extern __inline long
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+__TM_is_illegal (void* const TM_buff)
+{
+  texasru_t texasru = *_TEXASRU_PTR (TM_buff);
+  return _TEXASRU_DISALLOWED (texasru);
+}
+
+extern __inline long
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+__TM_is_footprint_exceeded (void* const TM_buff)
+{
+  texasru_t texasru = *_TEXASRU_PTR (TM_buff);
+  return _TEXASRU_FOOTPRINT_OVERFLOW (texasru);
+}
+
+extern __inline long
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+__TM_nesting_depth (void* const TM_buff)
+{
+  texasrl_t texasrl;
+
+  if (_HTM_STATE (__builtin_ttest ()) == _HTM_NONTRANSACTIONAL)
+    {
+      texasrl = *_TEXASRL_PTR (TM_buff);
+      if (!_TEXASR_FAILURE_SUMMARY (texasrl))
+        texasrl = 0;
+    }
+  else
+    texasrl = (texasrl_t) __builtin_get_texasr ();
+
+  return _TEXASR_TRANSACTION_LEVEL (texasrl);
+}
+
+extern __inline long
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+__TM_is_nested_too_deep(void* const TM_buff)
+{
+  texasru_t texasru = *_TEXASRU_PTR (TM_buff);
+  return _TEXASRU_NESTING_OVERFLOW (texasru);
+}
+
+extern __inline long
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+__TM_is_conflict(void* const TM_buff)
+{
+  texasru_t texasru = *_TEXASRU_PTR (TM_buff);
+  /* Return TEXASR bits 11 (Self-Induced Conflict) through
+     14 (Translation Invalidation Conflict).  */
+  return (_TEXASRU_EXTRACT_BITS (texasru, 14, 4)) ? 1 : 0;
+}
+
+extern __inline long
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+__TM_is_failure_persistent(void* const TM_buff)
+{
+  texasru_t texasru = *_TEXASRU_PTR (TM_buff);
+  return _TEXASRU_FAILURE_PERSISTENT (texasru);
+}
+
+extern __inline long
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+__TM_failure_address(void* const TM_buff)
+{
+  return *_TFIAR_PTR (TM_buff);
+}
+
+extern __inline long long
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+__TM_failure_code(void* const TM_buff)
+{
+  return *_TEXASR_PTR (TM_buff);
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _HTMXLINTRIN_H */
Index: gcc/config/rs6000/rs6000.opt
===================================================================
--- gcc/config/rs6000/rs6000.opt	(revision 200584)
+++ gcc/config/rs6000/rs6000.opt	(working copy)
@@ -539,6 +539,10 @@  mdirect-move
 Target Report Mask(DIRECT_MOVE) Var(rs6000_isa_flags)
 Use ISA 2.07 direct move between GPR & VSX register instructions
 
+mhtm
+Target Report Mask(HTM) Var(rs6000_isa_flags)
+Use ISA 2.07 transactional memory (HTM) instructions
+
 mquad-memory
 Target Report Mask(QUAD_MEMORY) Var(rs6000_isa_flags)
 Generate the quad word memory instructions (lq/stq/lqarx/stqcx).
Index: gcc/config/rs6000/rs6000-c.c
===================================================================
--- gcc/config/rs6000/rs6000-c.c	(revision 200584)
+++ gcc/config/rs6000/rs6000-c.c	(working copy)
@@ -333,6 +333,8 @@  rs6000_target_modify_macros (bool define
     }
   if ((flags & OPTION_MASK_VSX) != 0)
     rs6000_define_or_undefine_macro (define_p, "__VSX__");
+  if ((flags & OPTION_MASK_HTM) != 0)
+    rs6000_define_or_undefine_macro (define_p, "__HTM__");
   if ((flags & OPTION_MASK_P8_VECTOR) != 0)
     rs6000_define_or_undefine_macro (define_p, "__POWER8_VECTOR__");
   if ((flags & OPTION_MASK_CRYPTO) != 0)
Index: gcc/config/rs6000/rs6000-builtin.def
===================================================================
--- gcc/config/rs6000/rs6000-builtin.def	(revision 200584)
+++ gcc/config/rs6000/rs6000-builtin.def	(working copy)
@@ -30,6 +30,7 @@ 
    RS6000_BUILTIN_A -- ABS builtins
    RS6000_BUILTIN_D -- DST builtins
    RS6000_BUILTIN_E -- SPE EVSEL builtins.
+   RS6000_BUILTIN_H -- HTM builtins
    RS6000_BUILTIN_P -- Altivec, VSX, ISA 2.07 vector predicate builtins
    RS6000_BUILTIN_Q -- Paired floating point VSX predicate builtins
    RS6000_BUILTIN_S -- SPE predicate builtins
@@ -66,6 +67,10 @@ 
   #error "RS6000_BUILTIN_E is not defined."
 #endif
 
+#ifndef RS6000_BUILTIN_H
+  #error "RS6000_BUILTIN_H is not defined."
+#endif
+
 #ifndef RS6000_BUILTIN_P
   #error "RS6000_BUILTIN_P is not defined."
 #endif
@@ -403,6 +408,56 @@ 
 		     | RS6000_BTC_TERNARY),				\
 		    CODE_FOR_nothing)			/* ICODE */
 
+/* HTM convenience macros.  */
+#define BU_HTM_0(ENUM, NAME, ATTR, ICODE)				\
+  RS6000_BUILTIN_H (HTM_BUILTIN_ ## ENUM,		/* ENUM */	\
+		    "__builtin_" NAME,			/* NAME */	\
+		    RS6000_BTM_HTM,			/* MASK */	\
+		    RS6000_BTC_ ## ATTR,		/* ATTR */	\
+		    CODE_FOR_ ## ICODE)			/* ICODE */
+
+#define BU_HTM_1(ENUM, NAME, ATTR, ICODE)				\
+  RS6000_BUILTIN_H (HTM_BUILTIN_ ## ENUM,		/* ENUM */	\
+		    "__builtin_" NAME,			/* NAME */	\
+		    RS6000_BTM_HTM,			/* MASK */	\
+		    (RS6000_BTC_ ## ATTR		/* ATTR */	\
+		     | RS6000_BTC_UNARY),				\
+		    CODE_FOR_ ## ICODE)			/* ICODE */
+
+#define BU_HTM_2(ENUM, NAME, ATTR, ICODE)				\
+  RS6000_BUILTIN_H (HTM_BUILTIN_ ## ENUM,		/* ENUM */	\
+		    "__builtin_" NAME,			/* NAME */	\
+		    RS6000_BTM_HTM,			/* MASK */	\
+		    (RS6000_BTC_ ## ATTR		/* ATTR */	\
+		     | RS6000_BTC_BINARY),				\
+		    CODE_FOR_ ## ICODE)			/* ICODE */
+
+#define BU_HTM_3(ENUM, NAME, ATTR, ICODE)				\
+  RS6000_BUILTIN_H (HTM_BUILTIN_ ## ENUM,		/* ENUM */	\
+		    "__builtin_" NAME,			/* NAME */	\
+		    RS6000_BTM_HTM,			/* MASK */	\
+		    (RS6000_BTC_ ## ATTR		/* ATTR */	\
+		     | RS6000_BTC_TERNARY),				\
+		    CODE_FOR_ ## ICODE)			/* ICODE */
+
+#define BU_HTM_SPR0(ENUM, NAME, ATTR, ICODE)				\
+  RS6000_BUILTIN_H (HTM_BUILTIN_ ## ENUM,		/* ENUM */	\
+		    "__builtin_" NAME,			/* NAME */	\
+		    RS6000_BTM_HTM,			/* MASK */	\
+		    (RS6000_BTC_ ## ATTR		/* ATTR */	\
+		     | RS6000_BTC_SPR),					\
+		    CODE_FOR_ ## ICODE)			/* ICODE */
+
+#define BU_HTM_SPR1(ENUM, NAME, ATTR, ICODE)				\
+  RS6000_BUILTIN_H (HTM_BUILTIN_ ## ENUM,		/* ENUM */	\
+		    "__builtin_" NAME,			/* NAME */	\
+		    RS6000_BTM_HTM,			/* MASK */	\
+		    (RS6000_BTC_ ## ATTR		/* ATTR */	\
+		     | RS6000_BTC_UNARY					\
+		     | RS6000_BTC_SPR					\
+		     | RS6000_BTC_VOID),				\
+		    CODE_FOR_ ## ICODE)			/* ICODE */
+
 /* SPE convenience macros.  */
 #define BU_SPE_1(ENUM, NAME, ATTR, ICODE)				\
   RS6000_BUILTIN_1 (SPE_BUILTIN_ ## ENUM,		/* ENUM */	\
@@ -1367,6 +1422,33 @@  BU_CRYPTO_OVERLOAD_3 (VPERMXOR,	 "vpermx
 BU_CRYPTO_OVERLOAD_3 (VSHASIGMA, "vshasigma")
 
 
+/* HTM functions.  */
+BU_HTM_1  (TABORT,	"tabort",	MISC,	tabort)
+BU_HTM_3  (TABORTDC,	"tabortdc",	MISC,	tabortdc)
+BU_HTM_3  (TABORTDCI,	"tabortdci",	MISC,	tabortdci)
+BU_HTM_3  (TABORTWC,	"tabortwc",	MISC,	tabortwc)
+BU_HTM_3  (TABORTWCI,	"tabortwci",	MISC,	tabortwci)
+BU_HTM_1  (TBEGIN,	"tbegin",	MISC,	tbegin)
+BU_HTM_1  (TCHECK,	"tcheck",	MISC,	tcheck)
+BU_HTM_1  (TEND,	"tend",		MISC,	tend)
+BU_HTM_0  (TENDALL,	"tendall",	MISC,	tend)
+BU_HTM_0  (TRECHKPT,	"trechkpt",	MISC,	trechkpt)
+BU_HTM_1  (TRECLAIM,	"treclaim",	MISC,	treclaim)
+BU_HTM_0  (TRESUME,	"tresume",	MISC,	tsr)
+BU_HTM_0  (TSUSPEND,	"tsuspend",	MISC,	tsr)
+BU_HTM_1  (TSR,		"tsr",		MISC,	tsr)
+BU_HTM_0  (TTEST,	"ttest",	MISC,	ttest)
+
+BU_HTM_SPR0 (GET_TFHAR,		"get_tfhar",	MISC,	nothing)
+BU_HTM_SPR1 (SET_TFHAR,		"set_tfhar",	MISC,	nothing)
+BU_HTM_SPR0 (GET_TFIAR,		"get_tfiar",	MISC,	nothing)
+BU_HTM_SPR1 (SET_TFIAR,		"set_tfiar",	MISC,	nothing)
+BU_HTM_SPR0 (GET_TEXASR,	"get_texasr",	MISC,	nothing)
+BU_HTM_SPR1 (SET_TEXASR,	"set_texasr",	MISC,	nothing)
+BU_HTM_SPR0 (GET_TEXASRU,	"get_texasru",	MISC,	nothing)
+BU_HTM_SPR1 (SET_TEXASRU,	"set_texasru",	MISC,	nothing)
+
+
 /* 3 argument paired floating point builtins.  */
 BU_PAIRED_3 (MSUB,            "msub",           FP, 	fmsv2sf4)
 BU_PAIRED_3 (MADD,            "madd",           FP, 	fmav2sf4)
@@ -1665,10 +1747,10 @@  BU_SPECIAL_X (RS6000_BUILTIN_RSQRTF, "__
 	      RS6000_BTC_FP)
 
 BU_SPECIAL_X (RS6000_BUILTIN_GET_TB, "__builtin_ppc_get_timebase",
-	     RS6000_BTM_ALWAYS, RS6000_BTC_MISC)
+	      RS6000_BTM_ALWAYS, RS6000_BTC_MISC)
 
 BU_SPECIAL_X (RS6000_BUILTIN_MFTB, "__builtin_ppc_mftb",
-	     RS6000_BTM_ALWAYS, RS6000_BTC_MISC)
+	      RS6000_BTM_ALWAYS, RS6000_BTC_MISC)
 
 /* Darwin CfString builtin.  */
 BU_SPECIAL_X (RS6000_BUILTIN_CFSTRING, "__builtin_cfstring", RS6000_BTM_ALWAYS,
Index: gcc/config/rs6000/rs6000.c
===================================================================
--- gcc/config/rs6000/rs6000.c	(revision 200584)
+++ gcc/config/rs6000/rs6000.c	(working copy)
@@ -910,6 +910,7 @@  struct processor_costs ppca2_cost = {
 #undef RS6000_BUILTIN_A
 #undef RS6000_BUILTIN_D
 #undef RS6000_BUILTIN_E
+#undef RS6000_BUILTIN_H
 #undef RS6000_BUILTIN_P
 #undef RS6000_BUILTIN_Q
 #undef RS6000_BUILTIN_S
@@ -933,6 +934,9 @@  struct processor_costs ppca2_cost = {
 #define RS6000_BUILTIN_E(ENUM, NAME, MASK, ATTR, ICODE)  \
   { NAME, ICODE, MASK, ATTR },
 
+#define RS6000_BUILTIN_H(ENUM, NAME, MASK, ATTR, ICODE)  \
+  { NAME, ICODE, MASK, ATTR },
+
 #define RS6000_BUILTIN_P(ENUM, NAME, MASK, ATTR, ICODE)  \
   { NAME, ICODE, MASK, ATTR },
 
@@ -963,6 +967,7 @@  static const struct rs6000_builtin_info_
 #undef RS6000_BUILTIN_A
 #undef RS6000_BUILTIN_D
 #undef RS6000_BUILTIN_E
+#undef RS6000_BUILTIN_H
 #undef RS6000_BUILTIN_P
 #undef RS6000_BUILTIN_Q
 #undef RS6000_BUILTIN_S
@@ -1003,6 +1008,7 @@  static void rs6000_common_init_builtins 
 static void paired_init_builtins (void);
 static rtx paired_expand_predicate_builtin (enum insn_code, tree, rtx);
 static void spe_init_builtins (void);
+static void htm_init_builtins (void);
 static rtx spe_expand_predicate_builtin (enum insn_code, tree, rtx);
 static rtx spe_expand_evsel_builtin (enum insn_code, tree, rtx);
 static int rs6000_emit_int_cmove (rtx, rtx, rtx, rtx);
@@ -1130,7 +1136,9 @@  char rs6000_reg_names[][8] =
       /* SPE registers.  */
       "spe_acc", "spefscr",
       /* Soft frame pointer.  */
-      "sfp"
+      "sfp",
+      /* HTM SPR registers.  */
+      "tfhar", "tfiar", "texasr"
 };
 
 #ifdef TARGET_REGNAMES
@@ -1156,7 +1164,9 @@  static const char alt_reg_names[][8] =
   /* SPE registers.  */
   "spe_acc", "spefscr",
   /* Soft frame pointer.  */
-  "sfp"
+  "sfp",
+  /* HTM SPR registers.  */
+  "tfhar", "tfiar", "texasr"
 };
 #endif
 
@@ -2190,6 +2200,9 @@  rs6000_init_hard_regno_mode_ok (bool glo
   rs6000_regno_regclass[VSCR_REGNO] = VRSAVE_REGS;
   rs6000_regno_regclass[SPE_ACC_REGNO] = SPE_ACC_REGS;
   rs6000_regno_regclass[SPEFSCR_REGNO] = SPEFSCR_REGS;
+  rs6000_regno_regclass[TFHAR_REGNO] = SPR_REGS;
+  rs6000_regno_regclass[TFIAR_REGNO] = SPR_REGS;
+  rs6000_regno_regclass[TEXASR_REGNO] = SPR_REGS;
   rs6000_regno_regclass[ARG_POINTER_REGNUM] = BASE_REGS;
   rs6000_regno_regclass[FRAME_POINTER_REGNUM] = BASE_REGS;
 
@@ -2710,7 +2723,8 @@  rs6000_builtin_mask_calculate (void)
 	  | ((TARGET_POPCNTD)		    ? RS6000_BTM_POPCNTD   : 0)
 	  | ((rs6000_cpu == PROCESSOR_CELL) ? RS6000_BTM_CELL      : 0)
 	  | ((TARGET_P8_VECTOR)		    ? RS6000_BTM_P8_VECTOR : 0)
-	  | ((TARGET_CRYPTO)		    ? RS6000_BTM_CRYPTO	   : 0));
+	  | ((TARGET_CRYPTO)		    ? RS6000_BTM_CRYPTO	   : 0)
+	  | ((TARGET_HTM)		    ? RS6000_BTM_HTM	   : 0));
 }
 
 /* Override command line options.  Mostly we process the processor type and
@@ -2984,7 +2998,7 @@  rs6000_option_override_internal (bool gl
 
   /* For the newer switches (vsx, dfp, etc.) set some of the older options,
      unless the user explicitly used the -mno-<option> to disable the code.  */
-  if (TARGET_P8_VECTOR || TARGET_DIRECT_MOVE || TARGET_CRYPTO)
+  if (TARGET_P8_VECTOR || TARGET_DIRECT_MOVE || TARGET_CRYPTO || TARGET_HTM)
     rs6000_isa_flags |= (ISA_2_7_MASKS_SERVER & ~rs6000_isa_flags_explicit);
   else if (TARGET_VSX)
     rs6000_isa_flags |= (ISA_2_6_MASKS_SERVER & ~rs6000_isa_flags_explicit);
@@ -10143,6 +10157,7 @@  def_builtin (const char *name, tree type
 #undef RS6000_BUILTIN_A
 #undef RS6000_BUILTIN_D
 #undef RS6000_BUILTIN_E
+#undef RS6000_BUILTIN_H
 #undef RS6000_BUILTIN_P
 #undef RS6000_BUILTIN_Q
 #undef RS6000_BUILTIN_S
@@ -10156,6 +10171,7 @@  def_builtin (const char *name, tree type
 #define RS6000_BUILTIN_A(ENUM, NAME, MASK, ATTR, ICODE)
 #define RS6000_BUILTIN_D(ENUM, NAME, MASK, ATTR, ICODE)
 #define RS6000_BUILTIN_E(ENUM, NAME, MASK, ATTR, ICODE)
+#define RS6000_BUILTIN_H(ENUM, NAME, MASK, ATTR, ICODE)
 #define RS6000_BUILTIN_P(ENUM, NAME, MASK, ATTR, ICODE)
 #define RS6000_BUILTIN_Q(ENUM, NAME, MASK, ATTR, ICODE)
 #define RS6000_BUILTIN_S(ENUM, NAME, MASK, ATTR, ICODE)
@@ -10174,6 +10190,7 @@  static const struct builtin_description 
 #undef RS6000_BUILTIN_A
 #undef RS6000_BUILTIN_D
 #undef RS6000_BUILTIN_E
+#undef RS6000_BUILTIN_H
 #undef RS6000_BUILTIN_P
 #undef RS6000_BUILTIN_Q
 #undef RS6000_BUILTIN_S
@@ -10187,6 +10204,7 @@  static const struct builtin_description 
   { MASK, ICODE, NAME, ENUM },
 
 #define RS6000_BUILTIN_E(ENUM, NAME, MASK, ATTR, ICODE)
+#define RS6000_BUILTIN_H(ENUM, NAME, MASK, ATTR, ICODE)
 #define RS6000_BUILTIN_P(ENUM, NAME, MASK, ATTR, ICODE)
 #define RS6000_BUILTIN_Q(ENUM, NAME, MASK, ATTR, ICODE)
 #define RS6000_BUILTIN_S(ENUM, NAME, MASK, ATTR, ICODE)
@@ -10205,6 +10223,7 @@  static const struct builtin_description 
 #undef RS6000_BUILTIN_A
 #undef RS6000_BUILTIN_D
 #undef RS6000_BUILTIN_E
+#undef RS6000_BUILTIN_H
 #undef RS6000_BUILTIN_P
 #undef RS6000_BUILTIN_Q
 #undef RS6000_BUILTIN_S
@@ -10218,6 +10237,7 @@  static const struct builtin_description 
 #define RS6000_BUILTIN_A(ENUM, NAME, MASK, ATTR, ICODE)
 #define RS6000_BUILTIN_D(ENUM, NAME, MASK, ATTR, ICODE)
 #define RS6000_BUILTIN_E(ENUM, NAME, MASK, ATTR, ICODE)
+#define RS6000_BUILTIN_H(ENUM, NAME, MASK, ATTR, ICODE)
 #define RS6000_BUILTIN_P(ENUM, NAME, MASK, ATTR, ICODE)
 #define RS6000_BUILTIN_Q(ENUM, NAME, MASK, ATTR, ICODE)
 #define RS6000_BUILTIN_S(ENUM, NAME, MASK, ATTR, ICODE)
@@ -10234,6 +10254,7 @@  static const struct builtin_description 
 #undef RS6000_BUILTIN_A
 #undef RS6000_BUILTIN_D
 #undef RS6000_BUILTIN_E
+#undef RS6000_BUILTIN_H
 #undef RS6000_BUILTIN_P
 #undef RS6000_BUILTIN_Q
 #undef RS6000_BUILTIN_S
@@ -10245,6 +10266,7 @@  static const struct builtin_description 
 #define RS6000_BUILTIN_A(ENUM, NAME, MASK, ATTR, ICODE)
 #define RS6000_BUILTIN_D(ENUM, NAME, MASK, ATTR, ICODE)
 #define RS6000_BUILTIN_E(ENUM, NAME, MASK, ATTR, ICODE)
+#define RS6000_BUILTIN_H(ENUM, NAME, MASK, ATTR, ICODE)
 #define RS6000_BUILTIN_P(ENUM, NAME, MASK, ATTR, ICODE) \
   { MASK, ICODE, NAME, ENUM },
 
@@ -10266,6 +10288,7 @@  static const struct builtin_description 
 #undef RS6000_BUILTIN_A
 #undef RS6000_BUILTIN_D
 #undef RS6000_BUILTIN_E
+#undef RS6000_BUILTIN_H
 #undef RS6000_BUILTIN_P
 #undef RS6000_BUILTIN_Q
 #undef RS6000_BUILTIN_S
@@ -10277,6 +10300,7 @@  static const struct builtin_description 
 #define RS6000_BUILTIN_A(ENUM, NAME, MASK, ATTR, ICODE)
 #define RS6000_BUILTIN_D(ENUM, NAME, MASK, ATTR, ICODE)
 #define RS6000_BUILTIN_E(ENUM, NAME, MASK, ATTR, ICODE)
+#define RS6000_BUILTIN_H(ENUM, NAME, MASK, ATTR, ICODE)
 #define RS6000_BUILTIN_P(ENUM, NAME, MASK, ATTR, ICODE)
 #define RS6000_BUILTIN_Q(ENUM, NAME, MASK, ATTR, ICODE)
 #define RS6000_BUILTIN_S(ENUM, NAME, MASK, ATTR, ICODE) \
@@ -10296,6 +10320,7 @@  static const struct builtin_description 
 #undef RS6000_BUILTIN_A
 #undef RS6000_BUILTIN_D
 #undef RS6000_BUILTIN_E
+#undef RS6000_BUILTIN_H
 #undef RS6000_BUILTIN_P
 #undef RS6000_BUILTIN_Q
 #undef RS6000_BUILTIN_S
@@ -10309,6 +10334,7 @@  static const struct builtin_description 
 #define RS6000_BUILTIN_E(ENUM, NAME, MASK, ATTR, ICODE) \
   { MASK, ICODE, NAME, ENUM },
 
+#define RS6000_BUILTIN_H(ENUM, NAME, MASK, ATTR, ICODE)
 #define RS6000_BUILTIN_P(ENUM, NAME, MASK, ATTR, ICODE)
 #define RS6000_BUILTIN_Q(ENUM, NAME, MASK, ATTR, ICODE)
 #define RS6000_BUILTIN_S(ENUM, NAME, MASK, ATTR, ICODE)
@@ -10326,6 +10352,7 @@  static const struct builtin_description 
 #undef RS6000_BUILTIN_A
 #undef RS6000_BUILTIN_D
 #undef RS6000_BUILTIN_E
+#undef RS6000_BUILTIN_H
 #undef RS6000_BUILTIN_P
 #undef RS6000_BUILTIN_Q
 #undef RS6000_BUILTIN_S
@@ -10337,6 +10364,7 @@  static const struct builtin_description 
 #define RS6000_BUILTIN_A(ENUM, NAME, MASK, ATTR, ICODE)
 #define RS6000_BUILTIN_D(ENUM, NAME, MASK, ATTR, ICODE)
 #define RS6000_BUILTIN_E(ENUM, NAME, MASK, ATTR, ICODE)
+#define RS6000_BUILTIN_H(ENUM, NAME, MASK, ATTR, ICODE)
 #define RS6000_BUILTIN_P(ENUM, NAME, MASK, ATTR, ICODE)
 #define RS6000_BUILTIN_Q(ENUM, NAME, MASK, ATTR, ICODE) \
   { MASK, ICODE, NAME, ENUM },
@@ -10357,6 +10385,7 @@  static const struct builtin_description 
 #undef RS6000_BUILTIN_A
 #undef RS6000_BUILTIN_D
 #undef RS6000_BUILTIN_E
+#undef RS6000_BUILTIN_H
 #undef RS6000_BUILTIN_P
 #undef RS6000_BUILTIN_Q
 #undef RS6000_BUILTIN_S
@@ -10370,6 +10399,7 @@  static const struct builtin_description 
 
 #define RS6000_BUILTIN_D(ENUM, NAME, MASK, ATTR, ICODE)
 #define RS6000_BUILTIN_E(ENUM, NAME, MASK, ATTR, ICODE)
+#define RS6000_BUILTIN_H(ENUM, NAME, MASK, ATTR, ICODE)
 #define RS6000_BUILTIN_P(ENUM, NAME, MASK, ATTR, ICODE)
 #define RS6000_BUILTIN_Q(ENUM, NAME, MASK, ATTR, ICODE)
 #define RS6000_BUILTIN_S(ENUM, NAME, MASK, ATTR, ICODE)
@@ -10387,8 +10417,9 @@  static const struct builtin_description 
 #undef RS6000_BUILTIN_2
 #undef RS6000_BUILTIN_3
 #undef RS6000_BUILTIN_A
-#undef RS6000_BUILTIN_E
 #undef RS6000_BUILTIN_D
+#undef RS6000_BUILTIN_E
+#undef RS6000_BUILTIN_H
 #undef RS6000_BUILTIN_P
 #undef RS6000_BUILTIN_Q
 #undef RS6000_BUILTIN_S
@@ -10402,6 +10433,7 @@  static const struct builtin_description 
 #define RS6000_BUILTIN_A(ENUM, NAME, MASK, ATTR, ICODE)
 #define RS6000_BUILTIN_D(ENUM, NAME, MASK, ATTR, ICODE)
 #define RS6000_BUILTIN_E(ENUM, NAME, MASK, ATTR, ICODE)
+#define RS6000_BUILTIN_H(ENUM, NAME, MASK, ATTR, ICODE)
 #define RS6000_BUILTIN_P(ENUM, NAME, MASK, ATTR, ICODE)
 #define RS6000_BUILTIN_Q(ENUM, NAME, MASK, ATTR, ICODE)
 #define RS6000_BUILTIN_S(ENUM, NAME, MASK, ATTR, ICODE)
@@ -10412,17 +10444,49 @@  static const struct builtin_description 
 #include "rs6000-builtin.def"
 };
 
+/* HTM builtins.  */
 #undef RS6000_BUILTIN_1
 #undef RS6000_BUILTIN_2
 #undef RS6000_BUILTIN_3
 #undef RS6000_BUILTIN_A
 #undef RS6000_BUILTIN_D
 #undef RS6000_BUILTIN_E
+#undef RS6000_BUILTIN_H
 #undef RS6000_BUILTIN_P
 #undef RS6000_BUILTIN_Q
 #undef RS6000_BUILTIN_S
 #undef RS6000_BUILTIN_X
 
+#define RS6000_BUILTIN_1(ENUM, NAME, MASK, ATTR, ICODE)
+#define RS6000_BUILTIN_2(ENUM, NAME, MASK, ATTR, ICODE)
+#define RS6000_BUILTIN_3(ENUM, NAME, MASK, ATTR, ICODE)
+#define RS6000_BUILTIN_A(ENUM, NAME, MASK, ATTR, ICODE)
+#define RS6000_BUILTIN_D(ENUM, NAME, MASK, ATTR, ICODE)
+#define RS6000_BUILTIN_E(ENUM, NAME, MASK, ATTR, ICODE)
+#define RS6000_BUILTIN_H(ENUM, NAME, MASK, ATTR, ICODE) \
+  { MASK, ICODE, NAME, ENUM },
+
+#define RS6000_BUILTIN_P(ENUM, NAME, MASK, ATTR, ICODE)
+#define RS6000_BUILTIN_Q(ENUM, NAME, MASK, ATTR, ICODE)
+#define RS6000_BUILTIN_S(ENUM, NAME, MASK, ATTR, ICODE)
+#define RS6000_BUILTIN_X(ENUM, NAME, MASK, ATTR, ICODE)
+
+static const struct builtin_description bdesc_htm[] =
+{
+#include "rs6000-builtin.def"
+};
+
+#undef RS6000_BUILTIN_1
+#undef RS6000_BUILTIN_2
+#undef RS6000_BUILTIN_3
+#undef RS6000_BUILTIN_A
+#undef RS6000_BUILTIN_D
+#undef RS6000_BUILTIN_E
+#undef RS6000_BUILTIN_H
+#undef RS6000_BUILTIN_P
+#undef RS6000_BUILTIN_Q
+#undef RS6000_BUILTIN_S
+
 /* Return true if a builtin function is overloaded.  */
 bool
 rs6000_overloaded_builtin_p (enum rs6000_builtins fncode)
@@ -10892,6 +10956,197 @@  altivec_expand_stv_builtin (enum insn_co
   return NULL_RTX;
 }
 
+/* Return the appropriate SPR number associated with the given builtin.  */
+static inline HOST_WIDE_INT
+htm_spr_num (enum rs6000_builtins code)
+{
+  if (code == HTM_BUILTIN_GET_TFHAR
+      || code == HTM_BUILTIN_SET_TFHAR)
+    return TFHAR_SPR;
+  else if (code == HTM_BUILTIN_GET_TFIAR
+	   || code == HTM_BUILTIN_SET_TFIAR)
+    return TFIAR_SPR;
+  else if (code == HTM_BUILTIN_GET_TEXASR
+	   || code == HTM_BUILTIN_SET_TEXASR)
+    return TEXASR_SPR;
+  gcc_assert (code == HTM_BUILTIN_GET_TEXASRU
+	      || code == HTM_BUILTIN_SET_TEXASRU);
+  return TEXASRU_SPR;
+}
+
+/* Return the appropriate SPR regno associated with the given builtin.  */
+static inline HOST_WIDE_INT
+htm_spr_regno (enum rs6000_builtins code)
+{
+  if (code == HTM_BUILTIN_GET_TFHAR
+      || code == HTM_BUILTIN_SET_TFHAR)
+    return TFHAR_REGNO;
+  else if (code == HTM_BUILTIN_GET_TFIAR
+	   || code == HTM_BUILTIN_SET_TFIAR)
+    return TFIAR_REGNO;
+  gcc_assert (code == HTM_BUILTIN_GET_TEXASR
+	      || code == HTM_BUILTIN_SET_TEXASR
+	      || code == HTM_BUILTIN_GET_TEXASRU
+	      || code == HTM_BUILTIN_SET_TEXASRU);
+  return TEXASR_REGNO;
+}
+
+/* Return the correct ICODE value depending on whether we are
+   setting or reading the HTM SPRs.  */
+static inline enum insn_code
+rs6000_htm_spr_icode (bool nonvoid)
+{
+  if (nonvoid)
+    return (TARGET_64BIT) ? CODE_FOR_htm_mfspr_di : CODE_FOR_htm_mfspr_si;
+  else
+    return (TARGET_64BIT) ? CODE_FOR_htm_mtspr_di : CODE_FOR_htm_mtspr_si;
+}
+
+/* Expand the HTM builtin in EXP and store the result in TARGET.
+   Store true in *EXPANDEDP if we found a builtin to expand.  */
+static rtx
+htm_expand_builtin (tree exp, rtx target, bool * expandedp)
+{
+  tree fndecl = TREE_OPERAND (CALL_EXPR_FN (exp), 0);
+  bool nonvoid = TREE_TYPE (TREE_TYPE (fndecl)) != void_type_node;
+  enum rs6000_builtins fcode = (enum rs6000_builtins) DECL_FUNCTION_CODE (fndecl);
+  const struct builtin_description *d;
+  size_t i;
+
+  *expandedp = false;
+
+  /* Expand the HTM builtins.  */
+  d = bdesc_htm;
+  for (i = 0; i < ARRAY_SIZE (bdesc_htm); i++, d++)
+    if (d->code == fcode)
+      {
+	rtx op[MAX_HTM_OPERANDS], pat;
+	int nopnds = 0;
+	tree arg;
+	call_expr_arg_iterator iter;
+	unsigned attr = rs6000_builtin_info[fcode].attr;
+	enum insn_code icode = d->icode;
+
+	if (attr & RS6000_BTC_SPR)
+	  icode = rs6000_htm_spr_icode (nonvoid);
+
+	if (nonvoid)
+	  {
+	    enum machine_mode tmode = insn_data[icode].operand[0].mode;
+	    if (!target
+		|| GET_MODE (target) != tmode
+		|| !(*insn_data[icode].operand[0].predicate) (target, tmode))
+	      target = gen_reg_rtx (tmode);
+	    op[nopnds++] = target;
+	  }
+
+	FOR_EACH_CALL_EXPR_ARG (arg, iter, exp)
+	{
+	  const struct insn_operand_data *insn_op;
+
+	  if (arg == error_mark_node || nopnds >= MAX_HTM_OPERANDS)
+	    return NULL_RTX;
+
+	  insn_op = &insn_data[icode].operand[nopnds];
+
+	  op[nopnds] = expand_normal (arg);
+
+	  if (!(*insn_op->predicate) (op[nopnds], insn_op->mode))
+	    {
+	      if (!strcmp (insn_op->constraint, "n"))
+		{
+		  int arg_num = (nonvoid) ? nopnds : nopnds + 1;
+		  if (!CONST_INT_P (op[nopnds]))
+		    error ("argument %d must be an unsigned literal", arg_num);
+		  else
+		    error ("argument %d is an unsigned literal that is "
+			   "out of range", arg_num);
+		  return const0_rtx;
+		}
+	      op[nopnds] = copy_to_mode_reg (insn_op->mode, op[nopnds]);
+	    }
+
+	  nopnds++;
+	}
+
+	/* Handle the builtins for extended mnemonics.  These accept
+	   no arguments, but map to builtins that take arguments.  */
+	switch (fcode)
+	  {
+	  case HTM_BUILTIN_TENDALL:  /* Alias for: tend. 1  */
+	  case HTM_BUILTIN_TRESUME:  /* Alias for: tsr. 1  */
+	    op[nopnds++] = GEN_INT (1);
+#ifdef ENABLE_CHECKING
+	    attr |= RS6000_BTC_UNARY;
+#endif
+	    break;
+	  case HTM_BUILTIN_TSUSPEND: /* Alias for: tsr. 0  */
+	    op[nopnds++] = GEN_INT (0);
+#ifdef ENABLE_CHECKING
+	    attr |= RS6000_BTC_UNARY;
+#endif
+	    break;
+	  default:
+	    break;
+	  }
+
+	/* If this builtin accesses SPRs, then pass in the appropriate
+	   SPR number and SPR regno as the last two operands.  */
+	if (attr & RS6000_BTC_SPR)
+	  {
+	    op[nopnds++] = gen_rtx_CONST_INT (Pmode, htm_spr_num (fcode));
+	    op[nopnds++] = gen_rtx_REG (Pmode, htm_spr_regno (fcode));
+	  }
+
+#ifdef ENABLE_CHECKING
+	int expected_nopnds = 0;
+	if ((attr & RS6000_BTC_TYPE_MASK) == RS6000_BTC_UNARY)
+	  expected_nopnds = 1;
+	else if ((attr & RS6000_BTC_TYPE_MASK) == RS6000_BTC_BINARY)
+	  expected_nopnds = 2;
+	else if ((attr & RS6000_BTC_TYPE_MASK) == RS6000_BTC_TERNARY)
+	  expected_nopnds = 3;
+	if (!(attr & RS6000_BTC_VOID))
+	  expected_nopnds += 1;
+	if (attr & RS6000_BTC_SPR)
+	  expected_nopnds += 2;
+
+	gcc_assert (nopnds == expected_nopnds && nopnds <= MAX_HTM_OPERANDS);
+#endif
+
+	switch (nopnds)
+	  {
+	  case 0:
+	    pat = GEN_FCN (icode) (NULL_RTX);
+	    break;
+	  case 1:
+	    pat = GEN_FCN (icode) (op[0]);
+	    break;
+	  case 2:
+	    pat = GEN_FCN (icode) (op[0], op[1]);
+	    break;
+	  case 3:
+	    pat = GEN_FCN (icode) (op[0], op[1], op[2]);
+	    break;
+	  case 4:
+	    pat = GEN_FCN (icode) (op[0], op[1], op[2], op[3]);
+	    break;
+	  default:
+	    gcc_unreachable ();
+	  }
+	if (!pat)
+	  return NULL_RTX;
+	emit_insn (pat);
+
+	*expandedp = true;
+	if (nonvoid)
+	  return target;
+	return const0_rtx;
+      }
+
+  return NULL_RTX;
+}
+
 static rtx
 rs6000_expand_ternop_builtin (enum insn_code icode, tree exp, rtx target)
 {
@@ -11973,6 +12228,8 @@  rs6000_invalid_builtin (enum rs6000_buil
     error ("Builtin function %s is only valid for the cell processor", name);
   else if ((fnmask & RS6000_BTM_VSX) != 0)
     error ("Builtin function %s requires the -mvsx option", name);
+  else if ((fnmask & RS6000_BTM_HTM) != 0)
+    error ("Builtin function %s requires the -mhtm option", name);
   else if ((fnmask & RS6000_BTM_ALTIVEC) != 0)
     error ("Builtin function %s requires the -maltivec option", name);
   else if ((fnmask & RS6000_BTM_PAIRED) != 0)
@@ -12152,6 +12409,13 @@  rs6000_expand_builtin (tree exp, rtx tar
       if (success)
 	return ret;
     }  
+  if (TARGET_HTM)
+    {
+      ret = htm_expand_builtin (exp, target, &success);
+
+      if (success)
+	return ret;
+    }  
 
   gcc_assert (TARGET_ALTIVEC || TARGET_VSX || TARGET_SPE || TARGET_PAIRED_FLOAT);
 
@@ -12334,6 +12598,9 @@  rs6000_init_builtins (void)
     spe_init_builtins ();
   if (TARGET_EXTRA_BUILTINS)
     altivec_init_builtins ();
+  if (TARGET_HTM)
+    htm_init_builtins ();
+
   if (TARGET_EXTRA_BUILTINS || TARGET_SPE || TARGET_PAIRED_FLOAT)
     rs6000_common_init_builtins ();
 
@@ -13073,6 +13340,79 @@  altivec_init_builtins (void)
   def_builtin ("__builtin_vec_ext_v2di", ftype, VSX_BUILTIN_VEC_EXT_V2DI);
 }
 
+static void
+htm_init_builtins (void)
+{
+  HOST_WIDE_INT builtin_mask = rs6000_builtin_mask;
+  const struct builtin_description *d;
+  size_t i;
+
+  d = bdesc_htm;
+  for (i = 0; i < ARRAY_SIZE (bdesc_htm); i++, d++)
+    {
+      tree op[MAX_HTM_OPERANDS], type;
+      HOST_WIDE_INT mask = d->mask;
+      unsigned attr = rs6000_builtin_info[d->code].attr;
+      bool void_func = (attr & RS6000_BTC_VOID);
+      int attr_args = (attr & RS6000_BTC_TYPE_MASK);
+      int nopnds = 0;
+      tree argtype = (attr & RS6000_BTC_SPR) ? long_unsigned_type_node
+					     : unsigned_type_node;
+
+      if ((mask & builtin_mask) != mask)
+	{
+	  if (TARGET_DEBUG_BUILTIN)
+	    fprintf (stderr, "htm_builtin, skip binary %s\n", d->name);
+	  continue;
+	}
+
+      if (d->name == 0)
+	{
+	  if (TARGET_DEBUG_BUILTIN)
+	    fprintf (stderr, "htm_builtin, bdesc_htm[%ld] no name\n",
+		     (long unsigned) i);
+	  continue;
+	}
+
+      op[nopnds++] = (void_func) ? void_type_node : argtype;
+
+      if (attr_args == RS6000_BTC_UNARY)
+	op[nopnds++] = argtype;
+      else if (attr_args == RS6000_BTC_BINARY)
+	{
+	  op[nopnds++] = argtype;
+	  op[nopnds++] = argtype;
+	}
+      else if (attr_args == RS6000_BTC_TERNARY)
+	{
+	  op[nopnds++] = argtype;
+	  op[nopnds++] = argtype;
+	  op[nopnds++] = argtype;
+	}
+
+      switch (nopnds)
+	{
+	case 1:
+	  type = build_function_type_list (op[0], NULL_TREE);
+	  break;
+	case 2:
+	  type = build_function_type_list (op[0], op[1], NULL_TREE);
+	  break;
+	case 3:
+	  type = build_function_type_list (op[0], op[1], op[2], NULL_TREE);
+	  break;
+	case 4:
+	  type = build_function_type_list (op[0], op[1], op[2], op[3],
+					   NULL_TREE);
+	  break;
+	default:
+	  gcc_unreachable ();
+	}
+
+      def_builtin (d->name, type, d->code);
+    }
+}
+
 /* Hash function for builtin functions with up to 3 arguments and a return
    type.  */
 static unsigned
@@ -28776,6 +29116,7 @@  static struct rs6000_opt_mask const rs60
   { "dlmzb",			OPTION_MASK_DLMZB,		false, true  },
   { "fprnd",			OPTION_MASK_FPRND,		false, true  },
   { "hard-dfp",			OPTION_MASK_DFP,		false, true  },
+  { "htm",			OPTION_MASK_HTM,		false, true  },
   { "isel",			OPTION_MASK_ISEL,		false, true  },
   { "mfcrf",			OPTION_MASK_MFCRF,		false, true  },
   { "mfpgpr",			OPTION_MASK_MFPGPR,		false, true  },
@@ -28835,6 +29176,7 @@  static struct rs6000_opt_mask const rs60
   { "cell",		 RS6000_BTM_CELL,	false, false },
   { "power8-vector",	 RS6000_BTM_P8_VECTOR,	false, false },
   { "crypto",		 RS6000_BTM_CRYPTO,	false, false },
+  { "htm",		 RS6000_BTM_HTM,	false, false },
 };
 
 /* Option variables that we want to support inside attribute((target)) and
Index: gcc/config/rs6000/rs6000.h
===================================================================
--- gcc/config/rs6000/rs6000.h	(revision 200584)
+++ gcc/config/rs6000/rs6000.h	(working copy)
@@ -164,7 +164,7 @@ 
 %{mcpu=e6500: -me6500} \
 %{maltivec: -maltivec} \
 %{mvsx: -mvsx %{!maltivec: -maltivec} %{!mcpu*: %(asm_cpu_power7)}} \
-%{mpower8-vector|mcrypto|mdirect-move: %{!mcpu*: %(asm_cpu_power8)}} \
+%{mpower8-vector|mcrypto|mdirect-move|mhtm: %{!mcpu*: %(asm_cpu_power8)}} \
 -many"
 
 #define CPP_DEFAULT_SPEC ""
@@ -285,9 +285,11 @@  extern const char *host_detect_local_cpu
 #ifndef HAVE_AS_POWER8
 #undef  TARGET_DIRECT_MOVE
 #undef  TARGET_CRYPTO
+#undef  TARGET_HTM
 #undef  TARGET_P8_VECTOR
 #define TARGET_DIRECT_MOVE 0
 #define TARGET_CRYPTO 0
+#define TARGET_HTM 0
 #define TARGET_P8_VECTOR 0
 #endif
 
@@ -543,6 +545,7 @@  extern int rs6000_vector_align[];
 #define MASK_FPRND			OPTION_MASK_FPRND
 #define MASK_P8_FUSION			OPTION_MASK_P8_FUSION
 #define MASK_HARD_FLOAT			OPTION_MASK_HARD_FLOAT
+#define MASK_HTM			OPTION_MASK_HTM
 #define MASK_ISEL			OPTION_MASK_ISEL
 #define MASK_MFCRF			OPTION_MASK_MFCRF
 #define MASK_MFPGPR			OPTION_MASK_MFPGPR
@@ -891,7 +894,7 @@  enum data_align { align_abi, align_opt, 
    Another pseudo (not included in DWARF_FRAME_REGISTERS) is soft frame
    pointer, which is eventually eliminated in favor of SP or FP.  */
 
-#define FIRST_PSEUDO_REGISTER 114
+#define FIRST_PSEUDO_REGISTER 117
 
 /* This must be included for pre gcc 3.0 glibc compatibility.  */
 #define PRE_GCC3_DWARF_FRAME_REGISTERS 77
@@ -953,7 +956,7 @@  enum data_align { align_abi, align_opt, 
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
    1, 1						   \
-   , 1, 1, 1                                       \
+   , 1, 1, 1, 1, 1, 1				   \
 }
 
 /* 1 for registers not available across function calls.
@@ -973,7 +976,7 @@  enum data_align { align_abi, align_opt, 
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
    1, 1						   \
-   , 1, 1, 1                                       \
+   , 1, 1, 1, 1, 1, 1				   \
 }
 
 /* Like `CALL_USED_REGISTERS' except this macro doesn't require that
@@ -992,7 +995,7 @@  enum data_align { align_abi, align_opt, 
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
    0, 0						   \
-   , 0, 0, 0                                       \
+   , 0, 0, 0, 0, 0, 0				   \
 }
 
 #define TOTAL_ALTIVEC_REGS	(LAST_ALTIVEC_REGNO - FIRST_ALTIVEC_REGNO + 1)
@@ -1031,6 +1034,9 @@  enum data_align { align_abi, align_opt, 
 	vrsave, vscr	(fixed)
 	spe_acc, spefscr (fixed)
 	sfp		(fixed)
+	tfhar		(fixed)
+	tfiar		(fixed)
+	texasr		(fixed)
 */
 
 #if FIXED_R2 == 1
@@ -1072,7 +1078,7 @@  enum data_align { align_abi, align_opt, 
    96, 95, 94, 93, 92, 91,					\
    108, 107, 106, 105, 104, 103, 102, 101, 100, 99, 98, 97,	\
    109, 110,							\
-   111, 112, 113						\
+   111, 112, 113, 114, 115, 116					\
 }
 
 /* True if register is floating-point.  */
@@ -1299,6 +1305,7 @@  enum reg_class
   VSCR_REGS,
   SPE_ACC_REGS,
   SPEFSCR_REGS,
+  SPR_REGS,
   NON_SPECIAL_REGS,
   LINK_REGS,
   CTR_REGS,
@@ -1329,6 +1336,7 @@  enum reg_class
   "VSCR_REGS",								\
   "SPE_ACC_REGS",                                                       \
   "SPEFSCR_REGS",                                                       \
+  "SPR_REGS",								\
   "NON_SPECIAL_REGS",							\
   "LINK_REGS",								\
   "CTR_REGS",								\
@@ -1358,6 +1366,7 @@  enum reg_class
   { 0x00000000, 0x00000000, 0x00000000, 0x00004000 }, /* VSCR_REGS */	     \
   { 0x00000000, 0x00000000, 0x00000000, 0x00008000 }, /* SPE_ACC_REGS */     \
   { 0x00000000, 0x00000000, 0x00000000, 0x00010000 }, /* SPEFSCR_REGS */     \
+  { 0x00000000, 0x00000000, 0x00000000, 0x00040000 }, /* SPR_REGS */     \
   { 0xffffffff, 0xffffffff, 0x00000008, 0x00020000 }, /* NON_SPECIAL_REGS */ \
   { 0x00000000, 0x00000000, 0x00000002, 0x00000000 }, /* LINK_REGS */	     \
   { 0x00000000, 0x00000000, 0x00000004, 0x00000000 }, /* CTR_REGS */	     \
@@ -1368,7 +1377,7 @@  enum reg_class
   { 0x00000000, 0x00000000, 0x00000ff0, 0x00000000 }, /* CR_REGS */	     \
   { 0xffffffff, 0x00000000, 0x00000ffe, 0x00020000 }, /* NON_FLOAT_REGS */   \
   { 0x00000000, 0x00000000, 0x00001000, 0x00000000 }, /* CA_REGS */	     \
-  { 0xffffffff, 0xffffffff, 0xfffffffe, 0x0003ffff }  /* ALL_REGS */	     \
+  { 0xffffffff, 0xffffffff, 0xfffffffe, 0x0007ffff }  /* ALL_REGS */	     \
 }
 
 /* The same information, inverted:
@@ -2282,6 +2291,9 @@  extern char rs6000_reg_names[][8];	/* re
   &rs6000_reg_names[111][0],	/* spe_acc */				\
   &rs6000_reg_names[112][0],	/* spefscr */				\
   &rs6000_reg_names[113][0],	/* sfp  */				\
+  &rs6000_reg_names[114][0],	/* tfhar  */				\
+  &rs6000_reg_names[115][0],	/* tfiar  */				\
+  &rs6000_reg_names[116][0],	/* texasr  */				\
 }
 
 /* Table of additional register names to use in user input.  */
@@ -2335,7 +2347,9 @@  extern char rs6000_reg_names[][8];	/* re
   {"vs48", 93}, {"vs49", 94}, {"vs50", 95}, {"vs51", 96},       \
   {"vs52", 97}, {"vs53", 98}, {"vs54", 99}, {"vs55", 100},	\
   {"vs56", 101},{"vs57", 102},{"vs58", 103},{"vs59", 104},      \
-  {"vs60", 105},{"vs61", 106},{"vs62", 107},{"vs63", 108} }
+  {"vs60", 105},{"vs61", 106},{"vs62", 107},{"vs63", 108},	\
+  /* Transactional Memory Facility (HTM) Registers.  */		\
+  {"tfhar",  114}, {"tfiar",  115}, {"texasr",  116} }
 
 /* This is how to output an element of a case-vector that is relative.  */
 
@@ -2424,7 +2438,12 @@  extern int frame_pointer_needed;
 #define RS6000_BTC_ATTR_MASK	0x00000700	/* Mask of the attributes.  */
 
 /* Miscellaneous information.  */
-#define RS6000_BTC_OVERLOADED	0x4000000	/* function is overloaded.  */
+#define RS6000_BTC_SPR		0x01000000	/* function references SPRs.  */
+#define RS6000_BTC_VOID		0x02000000	/* function has no return value.  */
+#define RS6000_BTC_OVERLOADED	0x04000000	/* function is overloaded.  */
+#define RS6000_BTC_32BIT	0x08000000	/* function references SPRs.  */
+#define RS6000_BTC_64BIT	0x10000000	/* function references SPRs.  */
+#define RS6000_BTC_MISC_MASK	0x1f000000	/* Mask of the misc info.  */
 
 /* Convenience macros to document the instruction type.  */
 #define RS6000_BTC_MEM		RS6000_BTC_MISC	/* load/store touches mem.  */
@@ -2438,6 +2457,7 @@  extern int frame_pointer_needed;
 #define RS6000_BTM_VSX		MASK_VSX	/* VSX (vector/scalar).  */
 #define RS6000_BTM_P8_VECTOR	MASK_P8_VECTOR	/* ISA 2.07 vector.  */
 #define RS6000_BTM_CRYPTO	MASK_CRYPTO	/* crypto funcs.  */
+#define RS6000_BTM_HTM		MASK_HTM	/* hardware TM funcs.  */
 #define RS6000_BTM_SPE		MASK_STRING	/* E500 */
 #define RS6000_BTM_PAIRED	MASK_MULHW	/* 750CL paired insns.  */
 #define RS6000_BTM_FRE		MASK_POPCNTB	/* FRE instruction.  */
@@ -2455,6 +2475,7 @@  extern int frame_pointer_needed;
 				 | RS6000_BTM_FRES			\
 				 | RS6000_BTM_FRSQRTE			\
 				 | RS6000_BTM_FRSQRTES			\
+				 | RS6000_BTM_HTM			\
 				 | RS6000_BTM_POPCNTD			\
 				 | RS6000_BTM_CELL)
 
@@ -2466,6 +2487,7 @@  extern int frame_pointer_needed;
 #undef RS6000_BUILTIN_A
 #undef RS6000_BUILTIN_D
 #undef RS6000_BUILTIN_E
+#undef RS6000_BUILTIN_H
 #undef RS6000_BUILTIN_P
 #undef RS6000_BUILTIN_Q
 #undef RS6000_BUILTIN_S
@@ -2477,6 +2499,7 @@  extern int frame_pointer_needed;
 #define RS6000_BUILTIN_A(ENUM, NAME, MASK, ATTR, ICODE) ENUM,
 #define RS6000_BUILTIN_D(ENUM, NAME, MASK, ATTR, ICODE) ENUM,
 #define RS6000_BUILTIN_E(ENUM, NAME, MASK, ATTR, ICODE) ENUM,
+#define RS6000_BUILTIN_H(ENUM, NAME, MASK, ATTR, ICODE) ENUM,
 #define RS6000_BUILTIN_P(ENUM, NAME, MASK, ATTR, ICODE) ENUM,
 #define RS6000_BUILTIN_Q(ENUM, NAME, MASK, ATTR, ICODE) ENUM,
 #define RS6000_BUILTIN_S(ENUM, NAME, MASK, ATTR, ICODE) ENUM,
@@ -2495,6 +2518,7 @@  enum rs6000_builtins
 #undef RS6000_BUILTIN_A
 #undef RS6000_BUILTIN_D
 #undef RS6000_BUILTIN_E
+#undef RS6000_BUILTIN_H
 #undef RS6000_BUILTIN_P
 #undef RS6000_BUILTIN_Q
 #undef RS6000_BUILTIN_S
Index: gcc/config/rs6000/rs6000.md
===================================================================
--- gcc/config/rs6000/rs6000.md	(revision 200584)
+++ gcc/config/rs6000/rs6000.md	(working copy)
@@ -53,6 +53,9 @@  (define_constants
    (SPE_ACC_REGNO		111)
    (SPEFSCR_REGNO		112)
    (FRAME_POINTER_REGNUM	113)
+   (TFHAR_REGNO			114)
+   (TFIAR_REGNO			115)
+   (TEXASR_REGNO		116)
 
    ; ABI defined stack offsets for storing the TOC pointer with AIX calls.
    (TOC_SAVE_OFFSET_32BIT	20)
@@ -153,7 +156,7 @@  (define_c_enum "unspecv"
 
 ;; Define an insn type attribute.  This is used in function unit delay
 ;; computations.
-(define_attr "type" "integer,two,three,load,load_ext,load_ext_u,load_ext_ux,load_ux,load_u,store,store_ux,store_u,fpload,fpload_ux,fpload_u,fpstore,fpstore_ux,fpstore_u,vecload,vecstore,imul,imul2,imul3,lmul,idiv,ldiv,insert_word,branch,cmp,fast_compare,compare,var_delayed_compare,delayed_compare,imul_compare,lmul_compare,fpcompare,cr_logical,delayed_cr,mfcr,mfcrf,mtcr,mfjmpr,mtjmpr,fp,fpsimple,dmul,sdiv,ddiv,ssqrt,dsqrt,jmpreg,brinc,vecsimple,veccomplex,vecdiv,veccmp,veccmpsimple,vecperm,vecfloat,vecfdiv,vecdouble,isync,sync,load_l,store_c,shift,trap,insert_dword,var_shift_rotate,cntlz,exts,mffgpr,mftgpr,isel,popcnt,crypto"
+(define_attr "type" "integer,two,three,load,load_ext,load_ext_u,load_ext_ux,load_ux,load_u,store,store_ux,store_u,fpload,fpload_ux,fpload_u,fpstore,fpstore_ux,fpstore_u,vecload,vecstore,imul,imul2,imul3,lmul,idiv,ldiv,insert_word,branch,cmp,fast_compare,compare,var_delayed_compare,delayed_compare,imul_compare,lmul_compare,fpcompare,cr_logical,delayed_cr,mfcr,mfcrf,mtcr,mfjmpr,mtjmpr,fp,fpsimple,dmul,sdiv,ddiv,ssqrt,dsqrt,jmpreg,brinc,vecsimple,veccomplex,vecdiv,veccmp,veccmpsimple,vecperm,vecfloat,vecfdiv,vecdouble,isync,sync,load_l,store_c,shift,trap,insert_dword,var_shift_rotate,cntlz,exts,mffgpr,mftgpr,isel,popcnt,crypto,htm"
   (const_string "integer"))
 
 ;; Define floating point instruction sub-types for use with Xfpu.md
@@ -15302,3 +15305,4 @@  (define_insn "rs6000_mftb_<mode>"
 (include "dfp.md")
 (include "paired.md")
 (include "crypto.md")
+(include "htm.md")