htm.md (UNSPEC_HTM_FENCE): New.

* config/rs6000/htm.md (UNSPEC_HTM_FENCE): New.
	(tabort, tabort<wd>c, tabort<wd>ci, tbegin, tcheck, tend,
	trechkpt, treclaim, tsr, ttest): Rename define_insns from this...
	(*tabort, *tabort<wd>c, *tabort<wd>ci, *tbegin, *tcheck, *tend,
	*trechkpt, *treclaim, *tsr, *ttest): ...to this.  Add memory barrier.
	(tabort, tabort<wd>c, tabort<wd>ci, tbegin, tcheck, tend,
	trechkpt, treclaim, tsr, ttest): New define_expands.
	* config/rs6000/rs6000-c.c (rs6000_target_modify_macros): Define
	__TM_FENCE__ for htm.
	* doc/extend.texi: Update documentation for htm builtins.

Co-Authored-By: Torvald Riegel <triegel@redhat.com>

From-SVN: r228827
This commit is contained in:
Peter Bergner 2015-10-14 16:28:06 -05:00 committed by Peter Bergner
parent a409ca75d6
commit 4c1f41e152
4 changed files with 199 additions and 24 deletions

View File

@ -1,3 +1,17 @@
2015-10-14 Peter Bergner <bergner@vnet.ibm.com>
Torvald Riegel <triegel@redhat.com>
* config/rs6000/htm.md (UNSPEC_HTM_FENCE): New.
(tabort, tabort<wd>c, tabort<wd>ci, tbegin, tcheck, tend,
trechkpt, treclaim, tsr, ttest): Rename define_insns from this...
(*tabort, *tabort<wd>c, *tabort<wd>ci, *tbegin, *tcheck, *tend,
*trechkpt, *treclaim, *tsr, *ttest): ...to this. Add memory barrier.
(tabort, tabort<wd>c, tabort<wd>ci, tbegin, tcheck, tend,
trechkpt, treclaim, tsr, ttest): New define_expands.
* config/rs6000/rs6000-c.c (rs6000_target_modify_macros): Define
__TM_FENCE__ for htm.
* doc/extend.texi: Update documentation for htm builtins.
2015-10-14 Uros Bizjak <ubizjak@gmail.com>
PR target/67967

View File

@ -26,6 +26,14 @@
(MAX_HTM_OPERANDS 4)
])
;;
;; UNSPEC usage
;;
(define_c_enum "unspec"
[UNSPEC_HTM_FENCE
])
;;
;; UNSPEC_VOLATILE usage
;;
@ -45,96 +53,223 @@
UNSPECV_HTM_MTSPR
])
(define_expand "tabort"
[(parallel
[(set (match_operand:CC 1 "cc_reg_operand" "=x")
(unspec_volatile:CC [(match_operand:SI 0 "base_reg_operand" "b")]
UNSPECV_HTM_TABORT))
(set (match_dup 2) (unspec:BLK [(match_dup 2)] UNSPEC_HTM_FENCE))])]
"TARGET_HTM"
{
operands[2] = gen_rtx_MEM (BLKmode, gen_rtx_SCRATCH (Pmode));
MEM_VOLATILE_P (operands[2]) = 1;
})
(define_insn "tabort"
(define_insn "*tabort"
[(set (match_operand:CC 1 "cc_reg_operand" "=x")
(unspec_volatile:CC [(match_operand:SI 0 "base_reg_operand" "b")]
UNSPECV_HTM_TABORT))]
UNSPECV_HTM_TABORT))
(set (match_operand:BLK 2) (unspec:BLK [(match_dup 2)] UNSPEC_HTM_FENCE))]
"TARGET_HTM"
"tabort. %0"
[(set_attr "type" "htm")
(set_attr "length" "4")])
(define_insn "tabort<wd>c"
(define_expand "tabort<wd>c"
[(parallel
[(set (match_operand:CC 3 "cc_reg_operand" "=x")
(unspec_volatile:CC [(match_operand 0 "u5bit_cint_operand" "n")
(match_operand:GPR 1 "gpc_reg_operand" "r")
(match_operand:GPR 2 "gpc_reg_operand" "r")]
UNSPECV_HTM_TABORTXC))
(set (match_dup 4) (unspec:BLK [(match_dup 4)] UNSPEC_HTM_FENCE))])]
"TARGET_HTM"
{
operands[4] = gen_rtx_MEM (BLKmode, gen_rtx_SCRATCH (Pmode));
MEM_VOLATILE_P (operands[4]) = 1;
})
(define_insn "*tabort<wd>c"
[(set (match_operand:CC 3 "cc_reg_operand" "=x")
(unspec_volatile:CC [(match_operand 0 "u5bit_cint_operand" "n")
(match_operand:GPR 1 "gpc_reg_operand" "r")
(match_operand:GPR 2 "gpc_reg_operand" "r")]
UNSPECV_HTM_TABORTXC))]
UNSPECV_HTM_TABORTXC))
(set (match_operand:BLK 4) (unspec:BLK [(match_dup 4)] UNSPEC_HTM_FENCE))]
"TARGET_HTM"
"tabort<wd>c. %0,%1,%2"
[(set_attr "type" "htm")
(set_attr "length" "4")])
(define_insn "tabort<wd>ci"
(define_expand "tabort<wd>ci"
[(parallel
[(set (match_operand:CC 3 "cc_reg_operand" "=x")
(unspec_volatile:CC [(match_operand 0 "u5bit_cint_operand" "n")
(match_operand:GPR 1 "gpc_reg_operand" "r")
(match_operand 2 "s5bit_cint_operand" "n")]
UNSPECV_HTM_TABORTXCI))
(set (match_dup 4) (unspec:BLK [(match_dup 4)] UNSPEC_HTM_FENCE))])]
"TARGET_HTM"
{
operands[4] = gen_rtx_MEM (BLKmode, gen_rtx_SCRATCH (Pmode));
MEM_VOLATILE_P (operands[4]) = 1;
})
(define_insn "*tabort<wd>ci"
[(set (match_operand:CC 3 "cc_reg_operand" "=x")
(unspec_volatile:CC [(match_operand 0 "u5bit_cint_operand" "n")
(match_operand:GPR 1 "gpc_reg_operand" "r")
(match_operand 2 "s5bit_cint_operand" "n")]
UNSPECV_HTM_TABORTXCI))]
UNSPECV_HTM_TABORTXCI))
(set (match_operand:BLK 4) (unspec:BLK [(match_dup 4)] UNSPEC_HTM_FENCE))]
"TARGET_HTM"
"tabort<wd>ci. %0,%1,%2"
[(set_attr "type" "htm")
(set_attr "length" "4")])
(define_insn "tbegin"
(define_expand "tbegin"
[(parallel
[(set (match_operand:CC 1 "cc_reg_operand" "=x")
(unspec_volatile:CC [(match_operand 0 "const_0_to_1_operand" "n")]
UNSPECV_HTM_TBEGIN))
(set (match_dup 2) (unspec:BLK [(match_dup 2)] UNSPEC_HTM_FENCE))])]
"TARGET_HTM"
{
operands[2] = gen_rtx_MEM (BLKmode, gen_rtx_SCRATCH (Pmode));
MEM_VOLATILE_P (operands[2]) = 1;
})
(define_insn "*tbegin"
[(set (match_operand:CC 1 "cc_reg_operand" "=x")
(unspec_volatile:CC [(match_operand 0 "const_0_to_1_operand" "n")]
UNSPECV_HTM_TBEGIN))]
UNSPECV_HTM_TBEGIN))
(set (match_operand:BLK 2) (unspec:BLK [(match_dup 2)] UNSPEC_HTM_FENCE))]
"TARGET_HTM"
"tbegin. %0"
[(set_attr "type" "htm")
(set_attr "length" "4")])
(define_insn "tcheck"
(define_expand "tcheck"
[(parallel
[(set (match_operand:CC 0 "cc_reg_operand" "=y")
(unspec_volatile:CC [(const_int 0)] UNSPECV_HTM_TCHECK))
(set (match_dup 1) (unspec:BLK [(match_dup 1)] UNSPEC_HTM_FENCE))])]
"TARGET_HTM"
{
operands[1] = gen_rtx_MEM (BLKmode, gen_rtx_SCRATCH (Pmode));
MEM_VOLATILE_P (operands[1]) = 1;
})
(define_insn "*tcheck"
[(set (match_operand:CC 0 "cc_reg_operand" "=y")
(unspec_volatile:CC [(const_int 0)]
UNSPECV_HTM_TCHECK))]
(unspec_volatile:CC [(const_int 0)] UNSPECV_HTM_TCHECK))
(set (match_operand:BLK 1) (unspec:BLK [(match_dup 1)] UNSPEC_HTM_FENCE))]
"TARGET_HTM"
"tcheck %0"
[(set_attr "type" "htm")
(set_attr "length" "4")])
(define_insn "tend"
(define_expand "tend"
[(parallel
[(set (match_operand:CC 1 "cc_reg_operand" "=x")
(unspec_volatile:CC [(match_operand 0 "const_0_to_1_operand" "n")]
UNSPECV_HTM_TEND))
(set (match_dup 2) (unspec:BLK [(match_dup 2)] UNSPEC_HTM_FENCE))])]
"TARGET_HTM"
{
operands[2] = gen_rtx_MEM (BLKmode, gen_rtx_SCRATCH (Pmode));
MEM_VOLATILE_P (operands[2]) = 1;
})
(define_insn "*tend"
[(set (match_operand:CC 1 "cc_reg_operand" "=x")
(unspec_volatile:CC [(match_operand 0 "const_0_to_1_operand" "n")]
UNSPECV_HTM_TEND))]
UNSPECV_HTM_TEND))
(set (match_operand:BLK 2) (unspec:BLK [(match_dup 2)] UNSPEC_HTM_FENCE))]
"TARGET_HTM"
"tend. %0"
[(set_attr "type" "htm")
(set_attr "length" "4")])
(define_insn "trechkpt"
(define_expand "trechkpt"
[(parallel
[(set (match_operand:CC 0 "cc_reg_operand" "=x")
(unspec_volatile:CC [(const_int 0)] UNSPECV_HTM_TRECHKPT))
(set (match_dup 1) (unspec:BLK [(match_dup 1)] UNSPEC_HTM_FENCE))])]
"TARGET_HTM"
{
operands[1] = gen_rtx_MEM (BLKmode, gen_rtx_SCRATCH (Pmode));
MEM_VOLATILE_P (operands[1]) = 1;
})
(define_insn "*trechkpt"
[(set (match_operand:CC 0 "cc_reg_operand" "=x")
(unspec_volatile:CC [(const_int 0)]
UNSPECV_HTM_TRECHKPT))]
(unspec_volatile:CC [(const_int 0)] UNSPECV_HTM_TRECHKPT))
(set (match_operand:BLK 1) (unspec:BLK [(match_dup 1)] UNSPEC_HTM_FENCE))]
"TARGET_HTM"
"trechkpt."
[(set_attr "type" "htm")
(set_attr "length" "4")])
(define_insn "treclaim"
(define_expand "treclaim"
[(parallel
[(set (match_operand:CC 1 "cc_reg_operand" "=x")
(unspec_volatile:CC [(match_operand:SI 0 "gpc_reg_operand" "r")]
UNSPECV_HTM_TRECLAIM))
(set (match_dup 2) (unspec:BLK [(match_dup 2)] UNSPEC_HTM_FENCE))])]
"TARGET_HTM"
{
operands[2] = gen_rtx_MEM (BLKmode, gen_rtx_SCRATCH (Pmode));
MEM_VOLATILE_P (operands[2]) = 1;
})
(define_insn "*treclaim"
[(set (match_operand:CC 1 "cc_reg_operand" "=x")
(unspec_volatile:CC [(match_operand:SI 0 "gpc_reg_operand" "r")]
UNSPECV_HTM_TRECLAIM))]
UNSPECV_HTM_TRECLAIM))
(set (match_operand:BLK 2) (unspec:BLK [(match_dup 2)] UNSPEC_HTM_FENCE))]
"TARGET_HTM"
"treclaim. %0"
[(set_attr "type" "htm")
(set_attr "length" "4")])
(define_insn "tsr"
(define_expand "tsr"
[(parallel
[(set (match_operand:CC 1 "cc_reg_operand" "=x")
(unspec_volatile:CC [(match_operand 0 "const_0_to_1_operand" "n")]
UNSPECV_HTM_TSR))
(set (match_dup 2) (unspec:BLK [(match_dup 2)] UNSPEC_HTM_FENCE))])]
"TARGET_HTM"
{
operands[2] = gen_rtx_MEM (BLKmode, gen_rtx_SCRATCH (Pmode));
MEM_VOLATILE_P (operands[2]) = 1;
})
(define_insn "*tsr"
[(set (match_operand:CC 1 "cc_reg_operand" "=x")
(unspec_volatile:CC [(match_operand 0 "const_0_to_1_operand" "n")]
UNSPECV_HTM_TSR))]
UNSPECV_HTM_TSR))
(set (match_operand:BLK 2) (unspec:BLK [(match_dup 2)] UNSPEC_HTM_FENCE))]
"TARGET_HTM"
"tsr. %0"
[(set_attr "type" "htm")
(set_attr "length" "4")])
(define_insn "ttest"
(define_expand "ttest"
[(parallel
[(set (match_operand:CC 0 "cc_reg_operand" "=x")
(unspec_volatile:CC [(const_int 0)] UNSPECV_HTM_TTEST))
(set (match_dup 1) (unspec:BLK [(match_dup 1)] UNSPEC_HTM_FENCE))])]
"TARGET_HTM"
{
operands[1] = gen_rtx_MEM (BLKmode, gen_rtx_SCRATCH (Pmode));
MEM_VOLATILE_P (operands[1]) = 1;
})
(define_insn "*ttest"
[(set (match_operand:CC 0 "cc_reg_operand" "=x")
(unspec_volatile:CC [(const_int 0)]
UNSPECV_HTM_TTEST))]
(unspec_volatile:CC [(const_int 0)] UNSPECV_HTM_TTEST))
(set (match_operand:BLK 1) (unspec:BLK [(match_dup 1)] UNSPEC_HTM_FENCE))]
"TARGET_HTM"
"tabortwci. 0,1,0"
[(set_attr "type" "htm")

View File

@ -372,7 +372,11 @@ rs6000_target_modify_macros (bool define_p, HOST_WIDE_INT flags,
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__");
{
rs6000_define_or_undefine_macro (define_p, "__HTM__");
/* Tell the user that our HTM insn patterns act as memory barriers. */
rs6000_define_or_undefine_macro (define_p, "__TM_FENCE__");
}
if ((flags & OPTION_MASK_P8_VECTOR) != 0)
rs6000_define_or_undefine_macro (define_p, "__POWER8_VECTOR__");
if ((flags & OPTION_MASK_QUAD_MEMORY) != 0)

View File

@ -16092,6 +16092,28 @@ unsigned int __builtin_tresume (void)
unsigned int __builtin_tsuspend (void)
@end smallexample
Note that the semantics of the above HTM builtins are required to mimic
the locking semantics used for critical sections. Builtins that are used
to create a new transaction or restart a suspended transaction must have
lock acquisition like semantics while those builtins that end or suspend a
transaction must have lock release like semantics. Specifically, this must
mimic lock semantics as specified by C++11, for example: Lock acquisition is
as-if an execution of __atomic_exchange_n(&globallock,1,__ATOMIC_ACQUIRE)
that returns 0, and lock release is as-if an execution of
__atomic_store(&globallock,0,__ATOMIC_RELEASE), with globallock being an
implicit implementation-defined lock used for all transactions. The HTM
instructions associated with with the builtins inherently provide the
correct acquisition and release hardware barriers required. However,
the compiler must also be prohibited from moving loads and stores across
the builtins in a way that would violate their semantics. This has been
accomplished by adding memory barriers to the associated HTM instructions
(which is a conservative approach to provide acquire and release semantics).
Earlier versions of the compiler did not treat the HTM instructions as
memory barriers. A @code{__TM_FENCE__} macro has been added, which can
be used to determine whether the current compiler treats HTM instructions
as memory barriers or not. This allows the user to explicitly add memory
barriers to their code when using an older version of the compiler.
The following set of built-in functions are available to gain access
to the HTM specific special purpose registers.