s390.c: Rename UNSPEC_CCU_TO_INT to UNSPEC_STRCMPCC_TO_INT and UNSPEC_CCZ_TO_INT to...

2013-06-27  Andreas Krebbel  <Andreas.Krebbel@de.ibm.com>

	* config/s390/s390.c: Rename UNSPEC_CCU_TO_INT to
	UNSPEC_STRCMPCC_TO_INT and UNSPEC_CCZ_TO_INT to UNSPEC_CC_TO_INT.
	(struct machine_function): Add tbegin_p.
	(s390_canonicalize_comparison): Fold CC mode compares to
	conditional jump if possible.
	(s390_emit_jump): Return the emitted jump.
	(s390_branch_condition_mask, s390_branch_condition_mnemonic):
	Handle CCRAWmode compares.
	(s390_option_override): Default to -mhtm if available.
	(s390_reg_clobbered_rtx): Handle floating point regs as well.
	(s390_regs_ever_clobbered): Use s390_regs_ever_clobbered also for
	FPRs instead of df_regs_ever_live_p.
	(s390_optimize_nonescaping_tx): New function.
	(s390_init_frame_layout): Extend clobbered_regs array to cover
	FPRs as well.
	(s390_emit_prologue): Call s390_optimize_nonescaping_tx.
	(s390_expand_tbegin): New function.
	(enum s390_builtin): New enum definition.
	(code_for_builtin): New array definition.
	(s390_init_builtins): New function.
	(s390_expand_builtin): New function.
	(TARGET_INIT_BUILTINS): Define.
	(TARGET_EXPAND_BUILTIN): Define.
	* common/config/s390/s390-common.c (processor_flags_table): Add
	PF_TX.
	* config/s390/predicates.md (s390_comparison): Handle CCRAWmode.
	(s390_alc_comparison): Likewise.
	* config/s390/s390-modes.def: Add CCRAWmode.
	* config/s390/s390.h (processor_flags): Add PF_TX.
	(TARGET_CPU_HTM): Define macro.
	(TARGET_HTM): Define macro.
	(TARGET_CPU_CPP_BUILTINS): Define __HTM__ for htm.
	* config/s390/s390.md: Rename UNSPEC_CCU_TO_INT to
	UNSPEC_STRCMPCC_TO_INT and UNSPEC_CCZ_TO_INT to UNSPEC_CC_TO_INT.
	(UNSPECV_TBEGIN, UNSPECV_TBEGINC, UNSPECV_TEND, UNSPECV_TABORT)
	(UNSPECV_ETND, UNSPECV_NTSTG, UNSPECV_PPA): New unspecv enum
	values.
	(TBEGIN_MASK, TBEGINC_MASK): New constants.
	("*cc_to_int"): Move up.
	("*mov<mode>cc", "*cjump_64", "*cjump_31"): Accept integer
	constants other than 0.
	("*ccraw_to_int"): New insn and splitter definition.
	("tbegin", "tbegin_nofloat", "tbegin_retry")
	("tbegin_retry_nofloat", "tbeginc", "tend", "tabort")
	("tx_assist"): New expander.
	("tbegin_1", "tbegin_nofloat_1", "*tbeginc_1", "*tend_1")
	("*tabort_1", "etnd", "ntstg", "*ppa"): New insn definition.
	* config/s390/s390.opt: Add -mhtm option.
	* config/s390/s390-protos.h (s390_emit_jump): Add return type.
	* config/s390/htmxlintrin.h: New file.
	* config/s390/htmintrin.h: New file.
	* config/s390/s390intrin.h: New file.
	* doc/extend.texi: Document htm builtins.
	* config.gcc: Add the new header files to extra_headers.

2013-06-27  Andreas Krebbel  <Andreas.Krebbel@de.ibm.com>

	* gcc.target/s390/htm-1.c: New file.
	* gcc.target/s390/htm-nofloat-1.c: New file.
	* gcc.target/s390/htm-xl-intrin-1.c: New file.

2013-06-27  Andreas Krebbel  <Andreas.Krebbel@de.ibm.com>

	* config/s390/target.h: Include htmintrin.h.
	(_HTM_ITM_RETRIES): New macro definition.
	(htm_available, htm_init, htm_begin, htm_begin_success)
	(htm_commit, htm_abort, htm_abort_should_retry): New functions.

From-SVN: r200454
This commit is contained in:
Andreas Krebbel 2013-06-27 07:44:11 +00:00 committed by Andreas Krebbel
parent b47a3fef9c
commit 5a3fe9b607
20 changed files with 1438 additions and 77 deletions

View File

@ -1,3 +1,60 @@
2013-06-27 Andreas Krebbel <Andreas.Krebbel@de.ibm.com>
* config/s390/s390.c: Rename UNSPEC_CCU_TO_INT to
UNSPEC_STRCMPCC_TO_INT and UNSPEC_CCZ_TO_INT to UNSPEC_CC_TO_INT.
(struct machine_function): Add tbegin_p.
(s390_canonicalize_comparison): Fold CC mode compares to
conditional jump if possible.
(s390_emit_jump): Return the emitted jump.
(s390_branch_condition_mask, s390_branch_condition_mnemonic):
Handle CCRAWmode compares.
(s390_option_override): Default to -mhtm if available.
(s390_reg_clobbered_rtx): Handle floating point regs as well.
(s390_regs_ever_clobbered): Use s390_regs_ever_clobbered also for
FPRs instead of df_regs_ever_live_p.
(s390_optimize_nonescaping_tx): New function.
(s390_init_frame_layout): Extend clobbered_regs array to cover
FPRs as well.
(s390_emit_prologue): Call s390_optimize_nonescaping_tx.
(s390_expand_tbegin): New function.
(enum s390_builtin): New enum definition.
(code_for_builtin): New array definition.
(s390_init_builtins): New function.
(s390_expand_builtin): New function.
(TARGET_INIT_BUILTINS): Define.
(TARGET_EXPAND_BUILTIN): Define.
* common/config/s390/s390-common.c (processor_flags_table): Add
PF_TX.
* config/s390/predicates.md (s390_comparison): Handle CCRAWmode.
(s390_alc_comparison): Likewise.
* config/s390/s390-modes.def: Add CCRAWmode.
* config/s390/s390.h (processor_flags): Add PF_TX.
(TARGET_CPU_HTM): Define macro.
(TARGET_HTM): Define macro.
(TARGET_CPU_CPP_BUILTINS): Define __HTM__ for htm.
* config/s390/s390.md: Rename UNSPEC_CCU_TO_INT to
UNSPEC_STRCMPCC_TO_INT and UNSPEC_CCZ_TO_INT to UNSPEC_CC_TO_INT.
(UNSPECV_TBEGIN, UNSPECV_TBEGINC, UNSPECV_TEND, UNSPECV_TABORT)
(UNSPECV_ETND, UNSPECV_NTSTG, UNSPECV_PPA): New unspecv enum
values.
(TBEGIN_MASK, TBEGINC_MASK): New constants.
("*cc_to_int"): Move up.
("*mov<mode>cc", "*cjump_64", "*cjump_31"): Accept integer
constants other than 0.
("*ccraw_to_int"): New insn and splitter definition.
("tbegin", "tbegin_nofloat", "tbegin_retry")
("tbegin_retry_nofloat", "tbeginc", "tend", "tabort")
("tx_assist"): New expander.
("tbegin_1", "tbegin_nofloat_1", "*tbeginc_1", "*tend_1")
("*tabort_1", "etnd", "ntstg", "*ppa"): New insn definition.
* config/s390/s390.opt: Add -mhtm option.
* config/s390/s390-protos.h (s390_emit_jump): Add return type.
* config/s390/htmxlintrin.h: New file.
* config/s390/htmintrin.h: New file.
* config/s390/s390intrin.h: New file.
* doc/extend.texi: Document htm builtins.
* config.gcc: Add the new header files to extra_headers.
2013-06-26 Thomas Schwinge <thomas@codesourcery.com>
* config/i386/gnu.h [TARGET_LIBC_PROVIDES_SSP]

View File

@ -42,7 +42,7 @@ EXPORTED_CONST int processor_flags_table[] =
/* z196 */ PF_IEEE_FLOAT | PF_ZARCH | PF_LONG_DISPLACEMENT
| PF_EXTIMM | PF_DFP | PF_Z10 | PF_Z196,
/* zEC12 */ PF_IEEE_FLOAT | PF_ZARCH | PF_LONG_DISPLACEMENT
| PF_EXTIMM | PF_DFP | PF_Z10 | PF_Z196 | PF_ZEC12
| PF_EXTIMM | PF_DFP | PF_Z10 | PF_Z196 | PF_ZEC12 | PF_TX
};
/* Change optimizations to be performed, depending on the

View File

@ -453,6 +453,7 @@ s390*-*-*)
cpu_type=s390
need_64bit_hwint=yes
extra_options="${extra_options} fused-madd.opt"
extra_headers="s390intrin.h htmintrin.h htmxlintrin.h"
;;
# Note the 'l'; we need to be able to match e.g. "shle" or "shl".
sh[123456789lbe]*-*-* | sh-*-*)

View File

@ -0,0 +1,57 @@
/* GNU compiler hardware transactional execution intrinsics
Copyright (C) 2013 Free Software Foundation, Inc.
Contributed by Andreas Krebbel (Andreas.Krebbel@de.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/>. */
#ifndef _HTMINTRIN_H
#define _HTMINTRIN_H
/* Condition codes generated by tbegin */
#define _HTM_TBEGIN_STARTED 0
#define _HTM_TBEGIN_INDETERMINATE 1
#define _HTM_TBEGIN_TRANSIENT 2
#define _HTM_TBEGIN_PERSISTENT 3
/* The abort codes below this threshold are reserved for machine
use. */
#define _HTM_FIRST_USER_ABORT_CODE 256
/* The transaction diagnostic block is it is defined in the Principles
of Operation chapter 5-91. */
struct __htm_tdb {
unsigned char format; /* 0 */
unsigned char flags;
unsigned char reserved1[4];
unsigned short nesting_depth;
unsigned long long abort_code; /* 8 */
unsigned long long conflict_token; /* 16 */
unsigned long long atia; /* 24 */
unsigned char eaid; /* 32 */
unsigned char dxc;
unsigned char reserved2[2];
unsigned int program_int_id;
unsigned long long exception_id; /* 40 */
unsigned long long bea; /* 48 */
unsigned char reserved3[72]; /* 56 */
unsigned long long gprs[16]; /* 128 */
} __attribute__((__packed__, __aligned__ (8)));
#endif /* _HTMINTRIN_H */

View File

@ -0,0 +1,182 @@
/* XL compiler hardware transactional execution intrinsics
Copyright (C) 2013 Free Software Foundation, Inc.
Contributed by Andreas Krebbel (Andreas.Krebbel@de.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/>. */
#ifndef _HTMXLINTRIN_H
#define _HTMXLINTRIN_H
#include <stdint.h>
#include <htmintrin.h>
#ifdef __cplusplus
extern "C" {
#endif
/* These intrinsics are being made available for compatibility with
the IBM XL compiler. For documentation please see the "z/OS XL
C/C++ Programming Guide" publically available on the web. */
extern __inline long __attribute__((__gnu_inline__, __always_inline__, __artificial__))
__TM_simple_begin ()
{
return __builtin_tbegin_nofloat (0);
}
extern __inline long __attribute__((__gnu_inline__, __always_inline__, __artificial__))
__TM_begin (void* const tdb)
{
return __builtin_tbegin_nofloat (tdb);
}
extern __inline long __attribute__((__gnu_inline__, __always_inline__, __artificial__))
__TM_end ()
{
return __builtin_tend ();
}
extern __inline void __attribute__((__gnu_inline__, __always_inline__, __artificial__))
__TM_abort ()
{
return __builtin_tabort (_HTM_FIRST_USER_ABORT_CODE);
}
extern __inline void __attribute__((__gnu_inline__, __always_inline__, __artificial__))
__TM_named_abort (unsigned char const code)
{
return __builtin_tabort ((int)_HTM_FIRST_USER_ABORT_CODE + code);
}
extern __inline void __attribute__((__gnu_inline__, __always_inline__, __artificial__))
__TM_non_transactional_store (void* const addr, long long const value)
{
__builtin_non_tx_store ((uint64_t*)addr, (uint64_t)value);
}
extern __inline long __attribute__((__gnu_inline__, __always_inline__, __artificial__))
__TM_nesting_depth (void* const tdb_ptr)
{
int depth = __builtin_tx_nesting_depth ();
struct __htm_tdb *tdb = (struct __htm_tdb*)tdb_ptr;
if (depth != 0)
return depth;
if (tdb->format == 0)
return 0;
return tdb->nesting_depth;
}
/* Transaction failure diagnostics */
extern __inline long __attribute__((__gnu_inline__, __always_inline__, __artificial__))
__TM_is_user_abort (void* const tdb_ptr)
{
struct __htm_tdb *tdb = (struct __htm_tdb*)tdb_ptr;
if (tdb->format == 0)
return 0;
return !!(tdb->abort_code >= _HTM_FIRST_USER_ABORT_CODE);
}
extern __inline long __attribute__((__gnu_inline__, __always_inline__, __artificial__))
__TM_is_named_user_abort (void* const tdb_ptr, unsigned char* code)
{
struct __htm_tdb *tdb = (struct __htm_tdb*)tdb_ptr;
if (tdb->format == 0)
return 0;
if (tdb->abort_code >= _HTM_FIRST_USER_ABORT_CODE)
{
*code = tdb->abort_code - _HTM_FIRST_USER_ABORT_CODE;
return 1;
}
return 0;
}
extern __inline long __attribute__((__gnu_inline__, __always_inline__, __artificial__))
__TM_is_illegal (void* const tdb_ptr)
{
struct __htm_tdb *tdb = (struct __htm_tdb*)tdb_ptr;
return (tdb->format == 0
&& (tdb->abort_code == 4 /* unfiltered program interruption */
|| tdb->abort_code == 11 /* restricted instruction */));
}
extern __inline long __attribute__((__gnu_inline__, __always_inline__, __artificial__))
__TM_is_footprint_exceeded (void* const tdb_ptr)
{
struct __htm_tdb *tdb = (struct __htm_tdb*)tdb_ptr;
return (tdb->format == 0
&& (tdb->abort_code == 7 /* fetch overflow */
|| tdb->abort_code == 8 /* store overflow */));
}
extern __inline long __attribute__((__gnu_inline__, __always_inline__, __artificial__))
__TM_is_nested_too_deep (void* const tdb_ptr)
{
struct __htm_tdb *tdb = (struct __htm_tdb*)tdb_ptr;
return tdb->format == 0 && tdb->abort_code == 13; /* depth exceeded */
}
extern __inline long __attribute__((__gnu_inline__, __always_inline__, __artificial__))
__TM_is_conflict (void* const tdb_ptr)
{
struct __htm_tdb *tdb = (struct __htm_tdb*)tdb_ptr;
return (tdb->format == 0
&& (tdb->abort_code == 9 /* fetch conflict */
|| tdb->abort_code == 10 /* store conflict */));
}
extern __inline long __attribute__((__gnu_inline__, __always_inline__, __artificial__))
__TM_is_failure_persistent (long const result)
{
return result == _HTM_TBEGIN_PERSISTENT;
}
extern __inline long __attribute__((__gnu_inline__, __always_inline__, __artificial__))
__TM_failure_address (void* const tdb_ptr)
{
struct __htm_tdb *tdb = (struct __htm_tdb*)tdb_ptr;
#ifdef __s390x__
return tdb->atia;
#else
return tdb->atia & 0xffffffff;
#endif
}
extern __inline long __attribute__((__gnu_inline__, __always_inline__, __artificial__))
__TM_failure_code (void* const tdb_ptr)
{
struct __htm_tdb *tdb = (struct __htm_tdb*)tdb_ptr;
return tdb->abort_code;
}
#ifdef __cplusplus
}
#endif
#endif /* _HTMXLINTRIN_H */

View File

@ -176,7 +176,11 @@
{
if (GET_CODE (XEXP (op, 0)) != REG
|| REGNO (XEXP (op, 0)) != CC_REGNUM
|| XEXP (op, 1) != const0_rtx)
|| (XEXP (op, 1) != const0_rtx
&& !(CONST_INT_P (XEXP (op, 1))
&& GET_MODE (XEXP (op, 0)) == CCRAWmode
&& INTVAL (XEXP (op, 1)) >= 0
&& INTVAL (XEXP (op, 1)) <= 15)))
return false;
return (s390_branch_condition_mask (op) >= 0);
@ -224,7 +228,11 @@
if (GET_CODE (XEXP (op, 0)) != REG
|| REGNO (XEXP (op, 0)) != CC_REGNUM
|| XEXP (op, 1) != const0_rtx)
|| (XEXP (op, 1) != const0_rtx
&& !(CONST_INT_P (XEXP (op, 1))
&& GET_MODE (XEXP (op, 0)) == CCRAWmode
&& INTVAL (XEXP (op, 1)) >= 0
&& INTVAL (XEXP (op, 1)) <= 15)))
return false;
switch (GET_MODE (XEXP (op, 0)))

View File

@ -152,6 +152,14 @@ The compare and swap instructions sets the condition code to 0/1 if the
operands were equal/unequal. The CCZ1 mode ensures the result can be
effectively placed into a register.
CCRAW
The cc mode generated by a non-compare instruction. The condition
code mask for the CC consumer is determined by the comparison operator
(only EQ and NE allowed) and the immediate value given as second
operand to the operator. For the other CC modes this value used to be
0.
*/
@ -172,3 +180,4 @@ CC_MODE (CCT);
CC_MODE (CCT1);
CC_MODE (CCT2);
CC_MODE (CCT3);
CC_MODE (CCRAW);

View File

@ -58,7 +58,7 @@ extern bool s390_match_ccmode (rtx, enum machine_mode);
extern enum machine_mode s390_tm_ccmode (rtx, rtx, bool);
extern enum machine_mode s390_select_ccmode (enum rtx_code, rtx, rtx);
extern rtx s390_emit_compare (enum rtx_code, rtx, rtx);
extern void s390_emit_jump (rtx, rtx);
extern rtx s390_emit_jump (rtx, rtx);
extern bool symbolic_reference_mentioned_p (rtx);
extern bool tls_symbolic_reference_mentioned_p (rtx);
extern bool legitimate_la_operand_p (rtx);
@ -87,6 +87,7 @@ extern void s390_expand_cs_hqi (enum machine_mode, rtx, rtx, rtx,
rtx, rtx, bool);
extern void s390_expand_atomic (enum machine_mode, enum rtx_code,
rtx, rtx, rtx, bool);
extern void s390_expand_tbegin (rtx, rtx, rtx, bool);
extern rtx s390_return_addr_rtx (int, rtx);
extern rtx s390_back_chain_rtx (void);
extern rtx s390_emit_call (rtx, rtx, rtx, rtx);

View File

@ -367,6 +367,10 @@ struct GTY(()) machine_function
const char *some_ld_name;
bool has_landing_pad_p;
/* True if the current function may contain a tbegin clobbering
FPRs. */
bool tbegin_p;
};
/* Few accessor macros for struct cfun->machine->s390_frame_layout. */
@ -824,9 +828,9 @@ s390_canonicalize_comparison (int *code, rtx *op0, rtx *op1,
*op1 = constm1_rtx;
}
/* Remove redundant UNSPEC_CCU_TO_INT conversions if possible. */
/* Remove redundant UNSPEC_STRCMPCC_TO_INT conversions if possible. */
if (GET_CODE (*op0) == UNSPEC
&& XINT (*op0, 1) == UNSPEC_CCU_TO_INT
&& XINT (*op0, 1) == UNSPEC_STRCMPCC_TO_INT
&& XVECLEN (*op0, 0) == 1
&& GET_MODE (XVECEXP (*op0, 0, 0)) == CCUmode
&& GET_CODE (XVECEXP (*op0, 0, 0)) == REG
@ -852,25 +856,35 @@ s390_canonicalize_comparison (int *code, rtx *op0, rtx *op1,
}
}
/* Remove redundant UNSPEC_CCZ_TO_INT conversions if possible. */
/* Remove redundant UNSPEC_CC_TO_INT conversions if possible. */
if (GET_CODE (*op0) == UNSPEC
&& XINT (*op0, 1) == UNSPEC_CCZ_TO_INT
&& XINT (*op0, 1) == UNSPEC_CC_TO_INT
&& XVECLEN (*op0, 0) == 1
&& GET_MODE (XVECEXP (*op0, 0, 0)) == CCZmode
&& GET_CODE (XVECEXP (*op0, 0, 0)) == REG
&& REGNO (XVECEXP (*op0, 0, 0)) == CC_REGNUM
&& *op1 == const0_rtx)
&& CONST_INT_P (*op1))
{
enum rtx_code new_code = UNKNOWN;
switch (*code)
switch (GET_MODE (XVECEXP (*op0, 0, 0)))
{
case EQ: new_code = EQ; break;
case NE: new_code = NE; break;
default: break;
case CCZmode:
case CCRAWmode:
switch (*code)
{
case EQ: new_code = EQ; break;
case NE: new_code = NE; break;
default: break;
}
break;
default: break;
}
if (new_code != UNKNOWN)
{
/* For CCRAWmode put the required cc mask into the second
operand. */
if (GET_MODE (XVECEXP (*op0, 0, 0)) == CCRAWmode)
*op1 = gen_rtx_CONST_INT (VOIDmode, 1 << (3 - INTVAL (*op1)));
*op0 = XVECEXP (*op0, 0, 0);
*code = new_code;
}
@ -942,10 +956,11 @@ s390_emit_compare_and_swap (enum rtx_code code, rtx old, rtx mem,
const0_rtx);
}
/* Emit a jump instruction to TARGET. If COND is NULL_RTX, emit an
unconditional jump, else a conditional jump under condition COND. */
/* Emit a jump instruction to TARGET and return it. If COND is
NULL_RTX, emit an unconditional jump, else a conditional jump under
condition COND. */
void
rtx
s390_emit_jump (rtx target, rtx cond)
{
rtx insn;
@ -955,7 +970,7 @@ s390_emit_jump (rtx target, rtx cond)
target = gen_rtx_IF_THEN_ELSE (VOIDmode, cond, target, pc_rtx);
insn = gen_rtx_SET (VOIDmode, pc_rtx, target);
emit_jump_insn (insn);
return emit_jump_insn (insn);
}
/* Return branch condition mask to implement a branch
@ -971,7 +986,10 @@ s390_branch_condition_mask (rtx code)
gcc_assert (GET_CODE (XEXP (code, 0)) == REG);
gcc_assert (REGNO (XEXP (code, 0)) == CC_REGNUM);
gcc_assert (XEXP (code, 1) == const0_rtx);
gcc_assert (XEXP (code, 1) == const0_rtx
|| (GET_MODE (XEXP (code, 0)) == CCRAWmode
&& CONST_INT_P (XEXP (code, 1))));
switch (GET_MODE (XEXP (code, 0)))
{
@ -1145,6 +1163,17 @@ s390_branch_condition_mask (rtx code)
}
break;
case CCRAWmode:
switch (GET_CODE (code))
{
case EQ:
return INTVAL (XEXP (code, 1));
case NE:
return (INTVAL (XEXP (code, 1))) ^ 0xf;
default:
gcc_unreachable ();
}
default:
return -1;
}
@ -1204,7 +1233,9 @@ s390_branch_condition_mnemonic (rtx code, int inv)
if (GET_CODE (XEXP (code, 0)) == REG
&& REGNO (XEXP (code, 0)) == CC_REGNUM
&& XEXP (code, 1) == const0_rtx)
&& (XEXP (code, 1) == const0_rtx
|| (GET_MODE (XEXP (code, 0)) == CCRAWmode
&& CONST_INT_P (XEXP (code, 1)))))
mask = s390_branch_condition_mask (code);
else
mask = s390_compare_and_branch_condition_mask (code);
@ -1602,6 +1633,11 @@ s390_option_override (void)
if (!(target_flags_explicit & MASK_HARD_DFP) && TARGET_DFP)
target_flags |= MASK_HARD_DFP;
/* Enable hardware transactions if available and not explicitly
disabled by user. E.g. with -m31 -march=zEC12 -mzarch */
if (!(target_flags_explicit & MASK_OPT_HTM) && TARGET_CPU_HTM && TARGET_ZARCH)
target_flags |= MASK_OPT_HTM;
if (TARGET_HARD_DFP && !TARGET_DFP)
{
if (target_flags_explicit & MASK_HARD_DFP)
@ -7334,11 +7370,11 @@ s390_reg_clobbered_rtx (rtx setreg, const_rtx set_insn ATTRIBUTE_UNUSED, void *d
if (GET_CODE (setreg) == SUBREG)
{
rtx inner = SUBREG_REG (setreg);
if (!GENERAL_REG_P (inner))
if (!GENERAL_REG_P (inner) && !FP_REG_P (inner))
return;
regno = subreg_regno (setreg);
}
else if (GENERAL_REG_P (setreg))
else if (GENERAL_REG_P (setreg) || FP_REG_P (setreg))
regno = REGNO (setreg);
else
return;
@ -7361,13 +7397,13 @@ s390_regs_ever_clobbered (int *regs_ever_clobbered)
rtx cur_insn;
unsigned int i;
memset (regs_ever_clobbered, 0, 16 * sizeof (int));
memset (regs_ever_clobbered, 0, 32 * sizeof (int));
/* For non-leaf functions we have to consider all call clobbered regs to be
clobbered. */
if (!crtl->is_leaf)
{
for (i = 0; i < 16; i++)
for (i = 0; i < 32; i++)
regs_ever_clobbered[i] = call_really_used_regs[i];
}
@ -7389,7 +7425,7 @@ s390_regs_ever_clobbered (int *regs_ever_clobbered)
See expand_builtin_unwind_init. For regs_ever_live this is done by
reload. */
if (cfun->has_nonlocal_label)
for (i = 0; i < 16; i++)
for (i = 0; i < 32; i++)
if (!call_really_used_regs[i])
regs_ever_clobbered[i] = 1;
@ -7455,17 +7491,6 @@ s390_register_info (int clobbered_regs[])
{
int i, j;
/* fprs 8 - 15 are call saved for 64 Bit ABI. */
cfun_frame_layout.fpr_bitmap = 0;
cfun_frame_layout.high_fprs = 0;
if (TARGET_64BIT)
for (i = 24; i < 32; i++)
if (df_regs_ever_live_p (i) && !global_regs[i])
{
cfun_set_fpr_bit (i - 16);
cfun_frame_layout.high_fprs++;
}
/* Find first and last gpr to be saved. We trust regs_ever_live
data, except that we don't save and restore global registers.
@ -7474,6 +7499,29 @@ s390_register_info (int clobbered_regs[])
s390_regs_ever_clobbered (clobbered_regs);
/* fprs 8 - 15 are call saved for 64 Bit ABI. */
if (!epilogue_completed)
{
cfun_frame_layout.fpr_bitmap = 0;
cfun_frame_layout.high_fprs = 0;
if (TARGET_64BIT)
for (i = 24; i < 32; i++)
/* During reload we have to use the df_regs_ever_live infos
since reload is marking FPRs used as spill slots there as
live before actually making the code changes. Without
this we fail during elimination offset verification. */
if ((clobbered_regs[i]
|| (df_regs_ever_live_p (i)
&& (lra_in_progress
|| reload_in_progress
|| crtl->saves_all_registers)))
&& !global_regs[i])
{
cfun_set_fpr_bit (i - 16);
cfun_frame_layout.high_fprs++;
}
}
for (i = 0; i < 16; i++)
clobbered_regs[i] = clobbered_regs[i] && !global_regs[i] && !fixed_regs[i];
@ -7724,7 +7772,7 @@ s390_init_frame_layout (void)
{
HOST_WIDE_INT frame_size;
int base_used;
int clobbered_regs[16];
int clobbered_regs[32];
/* On S/390 machines, we may need to perform branch splitting, which
will require both base and return address register. We have no
@ -7759,6 +7807,157 @@ s390_init_frame_layout (void)
while (frame_size != cfun_frame_layout.frame_size);
}
/* Remove the FPR clobbers from a tbegin insn if it can be proven that
the TX is nonescaping. A transaction is considered escaping if
there is at least one path from tbegin returning CC0 to the
function exit block without an tend.
The check so far has some limitations:
- only single tbegin/tend BBs are supported
- the first cond jump after tbegin must separate the CC0 path from ~CC0
- when CC is copied to a GPR and the CC0 check is done with the GPR
this is not supported
*/
static void
s390_optimize_nonescaping_tx (void)
{
const unsigned int CC0 = 1 << 3;
basic_block tbegin_bb = NULL;
basic_block tend_bb = NULL;
basic_block bb;
rtx insn;
bool result = true;
int bb_index;
rtx tbegin_insn = NULL_RTX;
if (!cfun->machine->tbegin_p)
return;
for (bb_index = 0; bb_index < n_basic_blocks; bb_index++)
{
bb = BASIC_BLOCK (bb_index);
FOR_BB_INSNS (bb, insn)
{
rtx ite, cc, pat, target;
unsigned HOST_WIDE_INT mask;
if (!INSN_P (insn) || INSN_CODE (insn) <= 0)
continue;
pat = PATTERN (insn);
if (GET_CODE (pat) == PARALLEL)
pat = XVECEXP (pat, 0, 0);
if (GET_CODE (pat) != SET
|| GET_CODE (SET_SRC (pat)) != UNSPEC_VOLATILE)
continue;
if (XINT (SET_SRC (pat), 1) == UNSPECV_TBEGIN)
{
rtx tmp;
tbegin_insn = insn;
/* Just return if the tbegin doesn't have clobbers. */
if (GET_CODE (PATTERN (insn)) != PARALLEL)
return;
if (tbegin_bb != NULL)
return;
/* Find the next conditional jump. */
for (tmp = NEXT_INSN (insn);
tmp != NULL_RTX;
tmp = NEXT_INSN (tmp))
{
if (reg_set_p (gen_rtx_REG (CCmode, CC_REGNUM), tmp))
return;
if (!JUMP_P (tmp))
continue;
ite = SET_SRC (PATTERN (tmp));
if (GET_CODE (ite) != IF_THEN_ELSE)
continue;
cc = XEXP (XEXP (ite, 0), 0);
if (!REG_P (cc) || !CC_REGNO_P (REGNO (cc))
|| GET_MODE (cc) != CCRAWmode
|| GET_CODE (XEXP (XEXP (ite, 0), 1)) != CONST_INT)
return;
if (bb->succs->length () != 2)
return;
mask = INTVAL (XEXP (XEXP (ite, 0), 1));
if (GET_CODE (XEXP (ite, 0)) == NE)
mask ^= 0xf;
if (mask == CC0)
target = XEXP (ite, 1);
else if (mask == (CC0 ^ 0xf))
target = XEXP (ite, 2);
else
return;
{
edge_iterator ei;
edge e1, e2;
ei = ei_start (bb->succs);
e1 = ei_safe_edge (ei);
ei_next (&ei);
e2 = ei_safe_edge (ei);
if (e2->flags & EDGE_FALLTHRU)
{
e2 = e1;
e1 = ei_safe_edge (ei);
}
if (!(e1->flags & EDGE_FALLTHRU))
return;
tbegin_bb = (target == pc_rtx) ? e1->dest : e2->dest;
}
if (tmp == BB_END (bb))
break;
}
}
if (XINT (SET_SRC (pat), 1) == UNSPECV_TEND)
{
if (tend_bb != NULL)
return;
tend_bb = bb;
}
}
}
/* Either we successfully remove the FPR clobbers here or we are not
able to do anything for this TX. Both cases don't qualify for
another look. */
cfun->machine->tbegin_p = false;
if (tbegin_bb == NULL || tend_bb == NULL)
return;
calculate_dominance_info (CDI_POST_DOMINATORS);
result = dominated_by_p (CDI_POST_DOMINATORS, tbegin_bb, tend_bb);
free_dominance_info (CDI_POST_DOMINATORS);
if (!result)
return;
PATTERN (tbegin_insn) = XVECEXP (PATTERN (tbegin_insn), 0, 0);
INSN_CODE (tbegin_insn) = -1;
df_insn_rescan (tbegin_insn);
return;
}
/* Update frame layout. Recompute actual register save data based on
current info and update regs_ever_live for the special registers.
May be called multiple times, but may never cause *more* registers
@ -7767,7 +7966,7 @@ s390_init_frame_layout (void)
static void
s390_update_frame_layout (void)
{
int clobbered_regs[16];
int clobbered_regs[32];
s390_register_info (clobbered_regs);
@ -8204,8 +8403,10 @@ s390_emit_prologue (void)
int offset;
int next_fpr = 0;
/* Complete frame layout. */
/* Try to get rid of the FPR clobbers. */
s390_optimize_nonescaping_tx ();
/* Complete frame layout. */
s390_update_frame_layout ();
/* Annotate all constant pool references to let the scheduler know
@ -9353,6 +9554,294 @@ s390_gimplify_va_arg (tree valist, tree type, gimple_seq *pre_p,
return build_va_arg_indirect_ref (addr);
}
/* Emit rtl for the tbegin or tbegin_retry (RETRY != NULL_RTX)
expanders.
DEST - Register location where CC will be stored.
TDB - Pointer to a 256 byte area where to store the transaction.
diagnostic block. NULL if TDB is not needed.
RETRY - Retry count value. If non-NULL a retry loop for CC2
is emitted
CLOBBER_FPRS_P - If true clobbers for all FPRs are emitted as part
of the tbegin instruction pattern. */
void
s390_expand_tbegin (rtx dest, rtx tdb, rtx retry, bool clobber_fprs_p)
{
const int CC0 = 1 << 3;
const int CC1 = 1 << 2;
const int CC3 = 1 << 0;
rtx abort_label = gen_label_rtx ();
rtx leave_label = gen_label_rtx ();
rtx retry_reg = gen_reg_rtx (SImode);
rtx retry_label = NULL_RTX;
rtx jump;
rtx very_unlikely = GEN_INT (REG_BR_PROB_BASE / 100 - 1);
if (retry != NULL_RTX)
{
emit_move_insn (retry_reg, retry);
retry_label = gen_label_rtx ();
emit_label (retry_label);
}
if (clobber_fprs_p)
emit_insn (gen_tbegin_1 (tdb,
gen_rtx_CONST_INT (VOIDmode, TBEGIN_MASK)));
else
emit_insn (gen_tbegin_nofloat_1 (tdb,
gen_rtx_CONST_INT (VOIDmode, TBEGIN_MASK)));
jump = s390_emit_jump (abort_label,
gen_rtx_NE (VOIDmode,
gen_rtx_REG (CCRAWmode, CC_REGNUM),
gen_rtx_CONST_INT (VOIDmode, CC0)));
JUMP_LABEL (jump) = abort_label;
LABEL_NUSES (abort_label) = 1;
add_reg_note (jump, REG_BR_PROB, very_unlikely);
/* Initialize CC return value. */
emit_move_insn (dest, const0_rtx);
s390_emit_jump (leave_label, NULL_RTX);
LABEL_NUSES (leave_label) = 1;
emit_barrier ();
/* Abort handler code. */
emit_label (abort_label);
if (retry != NULL_RTX)
{
rtx count = gen_reg_rtx (SImode);
jump = s390_emit_jump (leave_label,
gen_rtx_EQ (VOIDmode,
gen_rtx_REG (CCRAWmode, CC_REGNUM),
gen_rtx_CONST_INT (VOIDmode, CC1 | CC3)));
LABEL_NUSES (leave_label) = 2;
add_reg_note (jump, REG_BR_PROB, very_unlikely);
/* CC2 - transient failure. Perform retry with ppa. */
emit_move_insn (count, retry);
emit_insn (gen_subsi3 (count, count, retry_reg));
emit_insn (gen_tx_assist (count));
jump = emit_jump_insn (gen_doloop_si64 (retry_label,
retry_reg,
retry_reg));
JUMP_LABEL (jump) = retry_label;
LABEL_NUSES (retry_label) = 1;
}
emit_move_insn (dest, gen_rtx_UNSPEC (SImode,
gen_rtvec (1, gen_rtx_REG (CCRAWmode,
CC_REGNUM)),
UNSPEC_CC_TO_INT));
emit_label (leave_label);
}
/* Builtins. */
enum s390_builtin
{
S390_BUILTIN_TBEGIN,
S390_BUILTIN_TBEGIN_NOFLOAT,
S390_BUILTIN_TBEGIN_RETRY,
S390_BUILTIN_TBEGIN_RETRY_NOFLOAT,
S390_BUILTIN_TBEGINC,
S390_BUILTIN_TEND,
S390_BUILTIN_TABORT,
S390_BUILTIN_NON_TX_STORE,
S390_BUILTIN_TX_NESTING_DEPTH,
S390_BUILTIN_TX_ASSIST,
S390_BUILTIN_max
};
static enum insn_code const code_for_builtin[S390_BUILTIN_max] = {
CODE_FOR_tbegin,
CODE_FOR_tbegin_nofloat,
CODE_FOR_tbegin_retry,
CODE_FOR_tbegin_retry_nofloat,
CODE_FOR_tbeginc,
CODE_FOR_tend,
CODE_FOR_tabort,
CODE_FOR_ntstg,
CODE_FOR_etnd,
CODE_FOR_tx_assist
};
static void
s390_init_builtins (void)
{
tree ftype, uint64_type;
/* void foo (void) */
ftype = build_function_type_list (void_type_node, NULL_TREE);
add_builtin_function ("__builtin_tbeginc", ftype, S390_BUILTIN_TBEGINC,
BUILT_IN_MD, NULL, NULL_TREE);
/* void foo (int) */
ftype = build_function_type_list (void_type_node, integer_type_node,
NULL_TREE);
add_builtin_function ("__builtin_tabort", ftype,
S390_BUILTIN_TABORT, BUILT_IN_MD, NULL, NULL_TREE);
add_builtin_function ("__builtin_tx_assist", ftype,
S390_BUILTIN_TX_ASSIST, BUILT_IN_MD, NULL, NULL_TREE);
/* int foo (void *) */
ftype = build_function_type_list (integer_type_node, ptr_type_node, NULL_TREE);
add_builtin_function ("__builtin_tbegin", ftype, S390_BUILTIN_TBEGIN,
BUILT_IN_MD, NULL, NULL_TREE);
add_builtin_function ("__builtin_tbegin_nofloat", ftype,
S390_BUILTIN_TBEGIN_NOFLOAT,
BUILT_IN_MD, NULL, NULL_TREE);
/* int foo (void *, int) */
ftype = build_function_type_list (integer_type_node, ptr_type_node,
integer_type_node, NULL_TREE);
add_builtin_function ("__builtin_tbegin_retry", ftype,
S390_BUILTIN_TBEGIN_RETRY,
BUILT_IN_MD,
NULL, NULL_TREE);
add_builtin_function ("__builtin_tbegin_retry_nofloat", ftype,
S390_BUILTIN_TBEGIN_RETRY_NOFLOAT,
BUILT_IN_MD,
NULL, NULL_TREE);
/* int foo (void) */
ftype = build_function_type_list (integer_type_node, NULL_TREE);
add_builtin_function ("__builtin_tx_nesting_depth", ftype,
S390_BUILTIN_TX_NESTING_DEPTH,
BUILT_IN_MD, NULL, NULL_TREE);
add_builtin_function ("__builtin_tend", ftype,
S390_BUILTIN_TEND, BUILT_IN_MD, NULL, NULL_TREE);
/* void foo (uint64_t *, uint64_t) */
if (TARGET_64BIT)
uint64_type = long_unsigned_type_node;
else
uint64_type = long_long_unsigned_type_node;
ftype = build_function_type_list (void_type_node,
build_pointer_type (uint64_type),
uint64_type, NULL_TREE);
add_builtin_function ("__builtin_non_tx_store", ftype,
S390_BUILTIN_NON_TX_STORE,
BUILT_IN_MD, NULL, NULL_TREE);
}
/* Expand an expression EXP that calls a built-in function,
with result going to TARGET if that's convenient
(and in mode MODE if that's convenient).
SUBTARGET may be used as the target for computing one of EXP's operands.
IGNORE is nonzero if the value is to be ignored. */
static rtx
s390_expand_builtin (tree exp, rtx target, rtx subtarget ATTRIBUTE_UNUSED,
enum machine_mode mode ATTRIBUTE_UNUSED,
int ignore ATTRIBUTE_UNUSED)
{
#define MAX_ARGS 2
tree fndecl = TREE_OPERAND (CALL_EXPR_FN (exp), 0);
unsigned int fcode = DECL_FUNCTION_CODE (fndecl);
enum insn_code icode;
rtx op[MAX_ARGS], pat;
int arity;
bool nonvoid;
tree arg;
call_expr_arg_iterator iter;
if (fcode >= S390_BUILTIN_max)
internal_error ("bad builtin fcode");
icode = code_for_builtin[fcode];
if (icode == 0)
internal_error ("bad builtin fcode");
if (!TARGET_ZEC12)
error ("Transactional execution builtins require zEC12 or later\n");
if (!TARGET_HTM && TARGET_ZEC12)
error ("Transactional execution builtins not enabled (-mtx)\n");
/* Set a flag in the machine specific cfun part in order to support
saving/restoring of FPRs. */
if (fcode == S390_BUILTIN_TBEGIN || fcode == S390_BUILTIN_TBEGIN_RETRY)
cfun->machine->tbegin_p = true;
nonvoid = TREE_TYPE (TREE_TYPE (fndecl)) != void_type_node;
arity = 0;
FOR_EACH_CALL_EXPR_ARG (arg, iter, exp)
{
const struct insn_operand_data *insn_op;
if (arg == error_mark_node)
return NULL_RTX;
if (arity >= MAX_ARGS)
return NULL_RTX;
insn_op = &insn_data[icode].operand[arity + nonvoid];
op[arity] = expand_expr (arg, NULL_RTX, insn_op->mode, EXPAND_NORMAL);
if (!(*insn_op->predicate) (op[arity], insn_op->mode))
{
if (insn_op->predicate == memory_operand)
{
/* Don't move a NULL pointer into a register. Otherwise
we have to rely on combine being able to move it back
in order to get an immediate 0 in the instruction. */
if (op[arity] != const0_rtx)
op[arity] = copy_to_mode_reg (Pmode, op[arity]);
op[arity] = gen_rtx_MEM (insn_op->mode, op[arity]);
}
else
op[arity] = copy_to_mode_reg (insn_op->mode, op[arity]);
}
arity++;
}
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);
}
switch (arity)
{
case 0:
pat = GEN_FCN (icode) (target);
break;
case 1:
if (nonvoid)
pat = GEN_FCN (icode) (target, op[0]);
else
pat = GEN_FCN (icode) (op[0]);
break;
case 2:
if (nonvoid)
pat = GEN_FCN (icode) (target, op[0], op[1]);
else
pat = GEN_FCN (icode) (op[0], op[1]);
break;
default:
gcc_unreachable ();
}
if (!pat)
return NULL_RTX;
emit_insn (pat);
if (nonvoid)
return target;
else
return const0_rtx;
}
/* Output assembly code for the trampoline template to
stdio stream FILE.
@ -11008,6 +11497,11 @@ s390_loop_unroll_adjust (unsigned nunroll, struct loop *loop)
#undef TARGET_RETURN_IN_MEMORY
#define TARGET_RETURN_IN_MEMORY s390_return_in_memory
#undef TARGET_INIT_BUILTINS
#define TARGET_INIT_BUILTINS s390_init_builtins
#undef TARGET_EXPAND_BUILTIN
#define TARGET_EXPAND_BUILTIN s390_expand_builtin
#undef TARGET_ASM_OUTPUT_ADDR_CONST_EXTRA
#define TARGET_ASM_OUTPUT_ADDR_CONST_EXTRA s390_output_addr_const_extra

View File

@ -34,7 +34,8 @@ enum processor_flags
PF_DFP = 16,
PF_Z10 = 32,
PF_Z196 = 64,
PF_ZEC12 = 128
PF_ZEC12 = 128,
PF_TX = 256
};
/* This is necessary to avoid a warning about comparing different enum
@ -61,6 +62,8 @@ enum processor_flags
(s390_arch_flags & PF_Z196)
#define TARGET_CPU_ZEC12 \
(s390_arch_flags & PF_ZEC12)
#define TARGET_CPU_HTM \
(s390_arch_flags & PF_TX)
/* These flags indicate that the generated code should run on a cpu
providing the respective hardware facility when run in
@ -78,6 +81,8 @@ enum processor_flags
(TARGET_ZARCH && TARGET_CPU_Z196)
#define TARGET_ZEC12 \
(TARGET_ZARCH && TARGET_CPU_ZEC12)
#define TARGET_HTM \
(TARGET_ZARCH && TARGET_CPU_HTM && TARGET_OPT_HTM)
#define TARGET_AVOID_CMP_AND_BRANCH (s390_tune == PROCESSOR_2817_Z196)
@ -93,23 +98,25 @@ enum processor_flags
#define TARGET_TPF 0
/* Target CPU builtins. */
#define TARGET_CPU_CPP_BUILTINS() \
do \
{ \
builtin_assert ("cpu=s390"); \
builtin_assert ("machine=s390"); \
builtin_define ("__s390__"); \
if (TARGET_ZARCH) \
builtin_define ("__zarch__"); \
if (TARGET_64BIT) \
builtin_define ("__s390x__"); \
if (TARGET_LONG_DOUBLE_128) \
builtin_define ("__LONG_DOUBLE_128__"); \
} \
#define TARGET_CPU_CPP_BUILTINS() \
do \
{ \
builtin_assert ("cpu=s390"); \
builtin_assert ("machine=s390"); \
builtin_define ("__s390__"); \
if (TARGET_ZARCH) \
builtin_define ("__zarch__"); \
if (TARGET_64BIT) \
builtin_define ("__s390x__"); \
if (TARGET_LONG_DOUBLE_128) \
builtin_define ("__LONG_DOUBLE_128__"); \
if (TARGET_HTM) \
builtin_define ("__HTM__"); \
} \
while (0)
#ifdef DEFAULT_TARGET_64BIT
#define TARGET_DEFAULT (MASK_64BIT | MASK_ZARCH | MASK_HARD_DFP)
#define TARGET_DEFAULT (MASK_64BIT | MASK_ZARCH | MASK_HARD_DFP | MASK_OPT_HTM)
#else
#define TARGET_DEFAULT 0
#endif

View File

@ -59,11 +59,17 @@
(define_c_enum "unspec" [
; Miscellaneous
UNSPEC_ROUND
UNSPEC_CCU_TO_INT
UNSPEC_CCZ_TO_INT
UNSPEC_ICM
UNSPEC_TIE
; Convert CC into a str comparison result and copy it into an
; integer register
; cc0->0, cc1->1, cc2->-1, (cc3->-1)
UNSPEC_STRCMPCC_TO_INT
; Copy CC as is into the lower 2 bits of an integer register
UNSPEC_CC_TO_INT
; GOT/PLT and lt-relative accesses
UNSPEC_LTREL_OFFSET
UNSPEC_LTREL_BASE
@ -138,6 +144,15 @@
; Atomic Support
UNSPECV_CAS
UNSPECV_ATOMIC_OP
; Transactional Execution support
UNSPECV_TBEGIN
UNSPECV_TBEGINC
UNSPECV_TEND
UNSPECV_TABORT
UNSPECV_ETND
UNSPECV_NTSTG
UNSPECV_PPA
])
;;
@ -191,6 +206,9 @@
(PFPO_OP1_TYPE_SHIFT 8)
])
; Immediate operands for tbegin and tbeginc
(define_constants [(TBEGIN_MASK 65292)]) ; 0xff0c
(define_constants [(TBEGINC_MASK 65288)]) ; 0xff08
;; Instruction operand type as used in the Principles of Operation.
;; Used to determine defaults for length and other attribute values.
@ -2251,7 +2269,7 @@
(define_insn "movcc"
[(set (match_operand:CC 0 "nonimmediate_operand" "=d,c,d,d,d,R,T")
(match_operand:CC 1 "nonimmediate_operand" "d,d,c,R,T,d,d"))]
(match_operand:CC 1 "nonimmediate_operand" " d,d,c,R,T,d,d"))]
""
"@
lr\t%0,%1
@ -2583,7 +2601,7 @@
(use (reg:SI 0))])
(parallel
[(set (match_operand:SI 0 "register_operand" "=d")
(unspec:SI [(reg:CCU CC_REGNUM)] UNSPEC_CCU_TO_INT))
(unspec:SI [(reg:CCU CC_REGNUM)] UNSPEC_STRCMPCC_TO_INT))
(clobber (reg:CC CC_REGNUM))])]
""
{
@ -2825,7 +2843,7 @@
(match_dup 2)]
UNSPEC_TDC_INSN))
(set (match_operand:SI 0 "register_operand" "=d")
(unspec:SI [(reg:CCZ CC_REGNUM)] UNSPEC_CCZ_TO_INT))]
(unspec:SI [(reg:CCZ CC_REGNUM)] UNSPEC_CC_TO_INT))]
"TARGET_HARD_FLOAT"
{
operands[2] = GEN_INT (S390_TDC_SIGNBIT_SET);
@ -2837,12 +2855,21 @@
(match_dup 2)]
UNSPEC_TDC_INSN))
(set (match_operand:SI 0 "register_operand" "=d")
(unspec:SI [(reg:CCZ CC_REGNUM)] UNSPEC_CCZ_TO_INT))]
(unspec:SI [(reg:CCZ CC_REGNUM)] UNSPEC_CC_TO_INT))]
"TARGET_HARD_FLOAT"
{
operands[2] = GEN_INT (S390_TDC_INFINITY);
})
(define_insn_and_split "*cc_to_int"
[(set (match_operand:SI 0 "register_operand" "=d")
(unspec:SI [(match_operand 1 "register_operand" "0")]
UNSPEC_CC_TO_INT))]
"operands != NULL"
"#"
"reload_completed"
[(set (match_dup 0) (lshiftrt:SI (match_dup 0) (const_int 28)))])
; This insn is used to generate all variants of the Test Data Class
; instruction, namely tcxb, tcdb, and tceb. The insn's first operand
; is the register to be tested and the second one is the bit mask
@ -2858,14 +2885,6 @@
[(set_attr "op_type" "RXE")
(set_attr "type" "fsimp<mode>")])
(define_insn_and_split "*ccz_to_int"
[(set (match_operand:SI 0 "register_operand" "=d")
(unspec:SI [(match_operand:CCZ 1 "register_operand" "0")]
UNSPEC_CCZ_TO_INT))]
""
"#"
"reload_completed"
[(set (match_dup 0) (lshiftrt:SI (match_dup 0) (const_int 28)))])
;
@ -3210,7 +3229,7 @@
(define_insn_and_split "cmpint"
[(set (match_operand:SI 0 "register_operand" "=d")
(unspec:SI [(match_operand:CCU 1 "register_operand" "0")]
UNSPEC_CCU_TO_INT))
UNSPEC_STRCMPCC_TO_INT))
(clobber (reg:CC CC_REGNUM))]
""
"#"
@ -3223,10 +3242,10 @@
(define_insn_and_split "*cmpint_cc"
[(set (reg CC_REGNUM)
(compare (unspec:SI [(match_operand:CCU 1 "register_operand" "0")]
UNSPEC_CCU_TO_INT)
UNSPEC_STRCMPCC_TO_INT)
(const_int 0)))
(set (match_operand:SI 0 "register_operand" "=d")
(unspec:SI [(match_dup 1)] UNSPEC_CCU_TO_INT))]
(unspec:SI [(match_dup 1)] UNSPEC_STRCMPCC_TO_INT))]
"s390_match_ccmode (insn, CCSmode)"
"#"
"&& reload_completed"
@ -3243,7 +3262,7 @@
(define_insn_and_split "*cmpint_sign"
[(set (match_operand:DI 0 "register_operand" "=d")
(sign_extend:DI (unspec:SI [(match_operand:CCU 1 "register_operand" "0")]
UNSPEC_CCU_TO_INT)))
UNSPEC_STRCMPCC_TO_INT)))
(clobber (reg:CC CC_REGNUM))]
"TARGET_ZARCH"
"#"
@ -3257,11 +3276,11 @@
[(set (reg CC_REGNUM)
(compare (ashiftrt:DI (ashift:DI (subreg:DI
(unspec:SI [(match_operand:CCU 1 "register_operand" "0")]
UNSPEC_CCU_TO_INT) 0)
UNSPEC_STRCMPCC_TO_INT) 0)
(const_int 32)) (const_int 32))
(const_int 0)))
(set (match_operand:DI 0 "register_operand" "=d")
(sign_extend:DI (unspec:SI [(match_dup 1)] UNSPEC_CCU_TO_INT)))]
(sign_extend:DI (unspec:SI [(match_dup 1)] UNSPEC_STRCMPCC_TO_INT)))]
"s390_match_ccmode (insn, CCSmode) && TARGET_ZARCH"
"#"
"&& reload_completed"
@ -5512,7 +5531,7 @@
(if_then_else:GPR
(match_operator 1 "s390_comparison"
[(match_operand 2 "cc_reg_operand" " c,c, c, c, c, c, c")
(const_int 0)])
(match_operand 5 "const_int_operand" "")])
(match_operand:GPR 3 "nonimmediate_operand" " d,0,QS, 0, d, 0,QS")
(match_operand:GPR 4 "nonimmediate_operand" " 0,d, 0,QS, 0, d,QS")))]
"TARGET_Z196"
@ -7912,7 +7931,8 @@
(define_insn "*cjump_64"
[(set (pc)
(if_then_else
(match_operator 1 "s390_comparison" [(reg CC_REGNUM) (const_int 0)])
(match_operator 1 "s390_comparison" [(reg CC_REGNUM)
(match_operand 2 "const_int_operand" "")])
(label_ref (match_operand 0 "" ""))
(pc)))]
"TARGET_CPU_ZARCH"
@ -7931,7 +7951,8 @@
(define_insn "*cjump_31"
[(set (pc)
(if_then_else
(match_operator 1 "s390_comparison" [(reg CC_REGNUM) (const_int 0)])
(match_operator 1 "s390_comparison" [(reg CC_REGNUM)
(match_operand 2 "const_int_operand" "")])
(label_ref (match_operand 0 "" ""))
(pc)))]
"!TARGET_CPU_ZARCH"
@ -9800,3 +9821,217 @@
"cpsdr\t%0,%2,%1"
[(set_attr "op_type" "RRF")
(set_attr "type" "fsimp<mode>")])
;;
;;- Transactional execution instructions
;;
; This splitter helps combine to make use of CC directly when
; comparing the integer result of a tbegin builtin with a constant.
; The unspec is already removed by canonicalize_comparison. So this
; splitters only job is to turn the PARALLEL into separate insns
; again. Unfortunately this only works with the very first cc/int
; compare since combine is not able to deal with data flow across
; basic block boundaries.
; It needs to be an insn pattern as well since combine does not apply
; the splitter directly. Combine would only use it if it actually
; would reduce the number of instructions.
(define_insn_and_split "*ccraw_to_int"
[(set (pc)
(if_then_else
(match_operator 0 "s390_eqne_operator"
[(reg:CCRAW CC_REGNUM)
(match_operand 1 "const_int_operand" "")])
(label_ref (match_operand 2 "" ""))
(pc)))
(set (match_operand:SI 3 "register_operand" "=d")
(unspec:SI [(reg:CCRAW CC_REGNUM)] UNSPEC_CC_TO_INT))]
""
"#"
""
[(set (match_dup 3)
(unspec:SI [(reg:CCRAW CC_REGNUM)] UNSPEC_CC_TO_INT))
(set (pc)
(if_then_else (match_op_dup 0 [(reg:CCRAW CC_REGNUM) (match_dup 1)])
(label_ref (match_dup 2))
(pc)))]
"")
; Non-constrained transaction begin
(define_expand "tbegin"
[(match_operand:SI 0 "register_operand" "=d")
(match_operand:BLK 1 "memory_operand" "=Q")]
"TARGET_HTM"
{
s390_expand_tbegin (operands[0], operands[1], NULL_RTX, true);
DONE;
})
(define_expand "tbegin_nofloat"
[(match_operand:SI 0 "register_operand" "=d")
(match_operand:BLK 1 "memory_operand" "=Q")]
"TARGET_HTM"
{
s390_expand_tbegin (operands[0], operands[1], NULL_RTX, false);
DONE;
})
(define_expand "tbegin_retry"
[(match_operand:SI 0 "register_operand" "=d")
(match_operand:BLK 1 "memory_operand" "=Q")
(match_operand 2 "const_int_operand")]
"TARGET_HTM"
{
s390_expand_tbegin (operands[0], operands[1], operands[2], true);
DONE;
})
(define_expand "tbegin_retry_nofloat"
[(match_operand:SI 0 "register_operand" "=d")
(match_operand:BLK 1 "memory_operand" "=Q")
(match_operand 2 "const_int_operand")]
"TARGET_HTM"
{
s390_expand_tbegin (operands[0], operands[1], operands[2], false);
DONE;
})
(define_insn "tbegin_1"
[(set (reg:CCRAW CC_REGNUM)
(unspec_volatile:CCRAW [(match_operand:BLK 0 "memory_operand" "=Q")
(match_operand 1 "const_int_operand" " D")]
UNSPECV_TBEGIN))
(clobber (reg:DF 16))
(clobber (reg:DF 17))
(clobber (reg:DF 18))
(clobber (reg:DF 19))
(clobber (reg:DF 20))
(clobber (reg:DF 21))
(clobber (reg:DF 22))
(clobber (reg:DF 23))
(clobber (reg:DF 24))
(clobber (reg:DF 25))
(clobber (reg:DF 26))
(clobber (reg:DF 27))
(clobber (reg:DF 28))
(clobber (reg:DF 29))
(clobber (reg:DF 30))
(clobber (reg:DF 31))]
; CONST_OK_FOR_CONSTRAINT_P does not work with D constraint since D is
; not supposed to be used for immediates (see genpreds.c).
"TARGET_HTM && INTVAL (operands[1]) >= 0 && INTVAL (operands[1]) <= 0xffff"
"tbegin\t%0,%x1"
[(set_attr "op_type" "SIL")])
; Same as above but without the FPR clobbers
(define_insn "tbegin_nofloat_1"
[(set (reg:CCRAW CC_REGNUM)
(unspec_volatile:CCRAW [(match_operand:BLK 0 "memory_operand" "=Q")
(match_operand 1 "const_int_operand" " D")]
UNSPECV_TBEGIN))]
"TARGET_HTM && INTVAL (operands[1]) >= 0 && INTVAL (operands[1]) <= 0xffff"
"tbegin\t%0,%x1"
[(set_attr "op_type" "SIL")])
; Constrained transaction begin
(define_expand "tbeginc"
[(set (reg:CCRAW CC_REGNUM)
(unspec_volatile:CCRAW [(const_int TBEGINC_MASK)]
UNSPECV_TBEGINC))]
"TARGET_HTM"
"")
(define_insn "*tbeginc_1"
[(set (reg:CCRAW CC_REGNUM)
(unspec_volatile:CCRAW [(match_operand 0 "const_int_operand" " D")]
UNSPECV_TBEGINC))]
"TARGET_HTM && INTVAL (operands[0]) >= 0 && INTVAL (operands[0]) <= 0xffff"
"tbeginc\t0,%x0"
[(set_attr "op_type" "SIL")])
; Transaction end
(define_expand "tend"
[(set (reg:CCRAW CC_REGNUM)
(unspec_volatile:CCRAW [(const_int 0)] UNSPECV_TEND))
(set (match_operand:SI 0 "register_operand" "=d")
(unspec:SI [(reg:CCRAW CC_REGNUM)] UNSPEC_CC_TO_INT))]
"TARGET_HTM"
"")
(define_insn "*tend_1"
[(set (reg:CCRAW CC_REGNUM)
(unspec_volatile:CCRAW [(const_int 0)] UNSPECV_TEND))]
"TARGET_HTM"
"tend"
[(set_attr "op_type" "S")])
; Transaction abort
(define_expand "tabort"
[(unspec_volatile [(match_operand 0 "shift_count_or_setmem_operand" "")]
UNSPECV_TABORT)]
"TARGET_HTM && operands != NULL"
{
if (CONST_INT_P (operands[0])
&& INTVAL (operands[0]) >= 0 && INTVAL (operands[0]) <= 255)
{
error ("Invalid transaction abort code: " HOST_WIDE_INT_PRINT_DEC
". Values in range 0 through 255 are reserved.",
INTVAL (operands[0]));
FAIL;
}
})
(define_insn "*tabort_1"
[(unspec_volatile [(match_operand 0 "shift_count_or_setmem_operand" "")]
UNSPECV_TABORT)]
"TARGET_HTM && operands != NULL"
"tabort\t%Y0"
[(set_attr "op_type" "S")])
; Transaction extract nesting depth
(define_insn "etnd"
[(set (match_operand:SI 0 "register_operand" "=d")
(unspec_volatile:SI [(const_int 0)] UNSPECV_ETND))]
"TARGET_HTM"
"etnd\t%0"
[(set_attr "op_type" "RRE")])
; Non-transactional store
(define_insn "ntstg"
[(set (match_operand:DI 0 "memory_operand" "=RT")
(unspec_volatile:DI [(match_operand:DI 1 "register_operand" "d")]
UNSPECV_NTSTG))]
"TARGET_HTM"
"ntstg\t%1,%0"
[(set_attr "op_type" "RXY")])
; Transaction perform processor assist
(define_expand "tx_assist"
[(set (match_dup 1) (const_int 0))
(unspec_volatile [(match_operand:SI 0 "register_operand" "d")
(match_dup 1)
(const_int 1)]
UNSPECV_PPA)]
"TARGET_HTM"
{
operands[1] = gen_reg_rtx (SImode);
})
(define_insn "*ppa"
[(unspec_volatile [(match_operand:SI 0 "register_operand" "d")
(match_operand:SI 1 "register_operand" "d")
(match_operand 2 "const_int_operand" "I")]
UNSPECV_PPA)]
"TARGET_HTM && INTVAL (operands[2]) < 16"
"ppa\t%0,%1,1"
[(set_attr "op_type" "RRF")])

View File

@ -104,6 +104,10 @@ mlong-double-64
Target Report RejectNegative Negative(mlong-double-128) InverseMask(LONG_DOUBLE_128)
Use 64-bit long double
mhtm
Target Report Mask(OPT_HTM)
Use hardware transactional execution instructions
mpacked-stack
Target Report Mask(PACKED_STACK)
Use packed stack layout

View File

@ -0,0 +1,33 @@
/* S/390 System z specific intrinsics
Copyright (C) 2013 Free Software Foundation, Inc.
Contributed by Andreas Krebbel (Andreas.Krebbel@de.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/>. */
#ifndef _S390INTRIN_H
#define _S390INTRIN_H
#ifndef __s390__
#error s390intrin.h included on wrong platform/compiler
#endif
#ifdef __HTM__
#include <htmintrin.h>
#endif
#endif /* _S390INTRIN_H*/

View File

@ -8847,6 +8847,7 @@ instructions, but allow the compiler to schedule those calls.
* PowerPC Built-in Functions::
* PowerPC AltiVec/VSX Built-in Functions::
* RX Built-in Functions::
* S/390 System z Built-in Functions::
* SH Built-in Functions::
* SPARC VIS Built-in Functions::
* SPU Built-in Functions::
@ -14422,6 +14423,120 @@ bit in the processor status word.
Generates the @code{wait} machine instruction.
@end deftypefn
@node S/390 System z Built-in Functions
@subsection S/390 System z Built-in Functions
@deftypefn {Built-in Function} int __builtin_tbegin (void*)
Generates the @code{tbegin} machine instruction starting a
non-constraint hardware transaction. If the parameter is non-NULL the
memory area is used to store the transaction diagnostic buffer and
will be passed as first operand to @code{tbegin}. This buffer can be
defined using the @code{struct __htm_tdb} C struct defined in
@code{htmintrin.h} and must reside on a double-word boundary. The
second tbegin operand is set to @code{0xff0c}. This enables
save/restore of all GPRs and disables aborts for FPR and AR
manipulations inside the transaction body. The condition code set by
the tbegin instruction is returned as integer value. The tbegin
instruction by definition overwrites the content of all FPRs. The
compiler will generate code which saves and restores the FPRs. For
soft-float code it is recommended to used the @code{*_nofloat}
variant. In order to prevent a TDB from being written it is required
to pass an constant zero value as parameter. Passing the zero value
through a variable is not sufficient. Although modifications of
access registers inside the transaction will not trigger an
transaction abort it is not supported to actually modify them. Access
registers do not get saved when entering a transaction. They will have
undefined state when reaching the abort code.
@end deftypefn
Macros for the possible return codes of tbegin are defined in the
@code{htmintrin.h} header file:
@table @code
@item _HTM_TBEGIN_STARTED
@code{tbegin} has been executed as part of normal processing. The
transaction body is supposed to be executed.
@item _HTM_TBEGIN_INDETERMINATE
The transaction was aborted due to an indeterminate condition which
might be persistent.
@item _HTM_TBEGIN_TRANSIENT
The transaction aborted due to a transient failure. The transaction
should be re-executed in that case.
@item _HTM_TBEGIN_PERSISTENT
The transaction aborted due to a persistent failure. Re-execution
under same circumstances will not be productive.
@end table
@defmac _HTM_FIRST_USER_ABORT_CODE
The @code{_HTM_FIRST_USER_ABORT_CODE} defined in @code{htmintrin.h}
specifies the first abort code which can be used for
@code{__builtin_tabort}. Values below this threshold are reserved for
machine use.
@end defmac
@deftp {Data type} {struct __htm_tdb}
The @code{struct __htm_tdb} defined in @code{htmintrin.h} describes
the structure of the transaction diagnostic block as specified in the
Principles of Operation manual chapter 5-91.
@end deftp
@deftypefn {Built-in Function} int __builtin_tbegin_nofloat (void*)
Same as @code{__builtin_tbegin} but without FPR saves and restores.
Using this variant in code making use of FPRs will leave the FPRs in
undefined state when entering the transaction abort handler code.
@end deftypefn
@deftypefn {Built-in Function} int __builtin_tbegin_retry (void*, int)
In addition to @code{__builtin_tbegin} a loop for transient failures
is generated. If tbegin returns a condition code of 2 the transaction
will be retried as often as specified in the second argument. The
perform processor assist instruction is used to tell the CPU about the
number of fails so far.
@end deftypefn
@deftypefn {Built-in Function} int __builtin_tbegin_retry_nofloat (void*, int)
Same as @code{__builtin_tbegin_retry} but without FPR saves and
restores. Using this variant in code making use of FPRs will leave
the FPRs in undefined state when entering the transaction abort
handler code.
@end deftypefn
@deftypefn {Built-in Function} void __builtin_tbeginc (void)
Generates the @code{tbeginc} machine instruction starting a constraint
hardware transaction. The second operand is set to @code{0xff08}.
@end deftypefn
@deftypefn {Built-in Function} int __builtin_tend (void)
Generates the @code{tend} machine instruction finishing a transaction
and making the changes visible to other threads. The condition code
generated by tend is returned as integer value.
@end deftypefn
@deftypefn {Built-in Function} void __builtin_tabort (int)
Generates the @code{tabort} machine instruction with the specified
abort code. Abort codes from 0 through 255 are reserved and will
result in an error message.
@end deftypefn
@deftypefn {Built-in Function} void __builtin_tx_assist (int)
Generates the @code{ppa rX,rY,1} machine instruction. Where the
integer parameter is loaded into rX and a value of zero is loaded into
rY. The integer parameter specifies the number of times the
transaction repeatedly aborted.
@end deftypefn
@deftypefn {Built-in Function} int __builtin_tx_nesting_depth (void)
Generates the @code{etnd} machine instruction. The current nesting
depth is returned as integer value. For a nesting depth of 0 the code
is not executed as part of an transaction.
@end deftypefn
@deftypefn {Built-in Function} void __builtin_non_tx_store (unsigned long long *, unsigned long long)
Generates the @code{ntstg} machine instruction. The second argument
is written to the first arguments location. The store operation will
not be rolled-back in case of an transaction abort.
@end deftypefn
@node SH Built-in Functions
@subsection SH Built-in Functions
The following built-in functions are supported on the SH1, SH2, SH3 and SH4

View File

@ -1,3 +1,9 @@
2013-06-27 Andreas Krebbel <Andreas.Krebbel@de.ibm.com>
* gcc.target/s390/htm-1.c: New file.
* gcc.target/s390/htm-nofloat-1.c: New file.
* gcc.target/s390/htm-xl-intrin-1.c: New file.
2013-06-26 Tobias Burnus <burnus@net-b.de>
PR fortran/29800

View File

@ -0,0 +1,37 @@
/* This checks the availability of the low-level builtins introduced
for transactional execution. */
/* { dg-do compile } */
/* { dg-options "-O3 -march=zEC12 -mzarch" } */
#include <stdint.h>
#include <htmintrin.h>
int a = 0;
uint64_t g;
int
foo (struct __htm_tdb* tdb)
{
int cc;
int n;
cc = __builtin_tbegin (0);
cc = __builtin_tbegin (tdb);
cc = __builtin_tbegin_nofloat (0);
cc = __builtin_tbegin_nofloat (tdb);
cc = __builtin_tbegin_retry (0, 42);
cc = __builtin_tbegin_retry (tdb, 42);
cc = __builtin_tbegin_retry_nofloat (0, 42);
cc = __builtin_tbegin_retry_nofloat (tdb, 42);
__builtin_tbeginc ();
n = __builtin_tx_nesting_depth();
__builtin_non_tx_store(&g, n);
__builtin_tabort (42 + 255);
__builtin_tend();
__builtin_tx_assist (23);
}
/* Make sure the tdb NULL argument ends up as immediate value in the
instruction. */
/* { dg-final { scan-assembler-times "tbegin\t0," 4 } } */

View File

@ -0,0 +1,12 @@
/* { dg-do compile } */
/* { dg-options "-O3 -march=zEC12 -mzarch" } */
int
foo ()
{
__builtin_tbegin_nofloat (0);
__builtin_tbegin_retry_nofloat (0, 42);
}
/* Make sure no FPR saves/restores are emitted. */
/* { dg-final { scan-assembler-not "std" } } */
/* { dg-final { scan-assembler-not "ld" } } */

View File

@ -0,0 +1,37 @@
/* This checks the availability of the XL compiler intrinsics for
transactional execution with the expected prototypes. */
/* { dg-do compile } */
/* { dg-options "-O3 -march=zEC12 -mzarch" } */
#include <htmxlintrin.h>
int a = 0;
unsigned long g;
int
foo ()
{
struct __htm_tdb *tdb_struct;
void * const tdb = tdb_struct;
long result;
unsigned char code;
result = __TM_simple_begin ();
result = __TM_begin (tdb);
result = __TM_end ();
__TM_abort ();
__TM_named_abort (42);
__TM_non_transactional_store (&g, 42);
result = __TM_nesting_depth (tdb);
result = __TM_is_user_abort (tdb);
result = __TM_is_named_user_abort (tdb, &code);
result = __TM_is_illegal (tdb);
result = __TM_is_footprint_exceeded (tdb);
result = __TM_is_nested_too_deep (tdb);
result = __TM_is_conflict (tdb);
result = __TM_is_failure_persistent (result);
result = __TM_failure_address (tdb);
result = __TM_failure_code (tdb);
}

View File

@ -1,3 +1,10 @@
2013-06-27 Andreas Krebbel <Andreas.Krebbel@de.ibm.com>
* config/s390/target.h: Include htmintrin.h.
(_HTM_ITM_RETRIES): New macro definition.
(htm_available, htm_init, htm_begin, htm_begin_success)
(htm_commit, htm_abort, htm_abort_should_retry): New functions.
2013-06-20 Iain Sandoe <iain@codesourcery.com>
Cesar Philippidis <cesar@codesourcery.com>

View File

@ -22,6 +22,12 @@
see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
<http://www.gnu.org/licenses/>. */
#include <htmintrin.h>
/* Number of retries for transient failures. */
#define _HTM_ITM_RETRIES 10
namespace GTM HIDDEN {
#define HW_CACHELINE_SIZE 256
@ -52,4 +58,57 @@ cpu_relax (void)
__asm volatile ("" : : : "memory");
}
#ifdef __HTM__
#define USE_HTM_FASTPATH
static inline bool
htm_available ()
{
return true;
}
static inline uint32_t
htm_init ()
{
return htm_available () ? _HTM_ITM_RETRIES : 0;
}
static inline uint32_t
htm_begin ()
{
return __builtin_tbegin_nofloat (NULL);
}
static inline bool
htm_begin_success (uint32_t begin_ret)
{
return begin_ret == _HTM_TBEGIN_STARTED;
}
static inline void
htm_commit ()
{
__builtin_tend ();
}
static inline void
htm_abort ()
{
__builtin_tabort (_HTM_FIRST_USER_ABORT_CODE);
}
static inline bool
htm_abort_should_retry (uint32_t begin_ret)
{
return begin_ret == _HTM_TBEGIN_TRANSIENT;
}
static inline bool
htm_transaction_active ()
{
return __builtin_tx_nesting_depth() != 0;
}
#endif
} // namespace GTM