summaryrefslogtreecommitdiff
path: root/gcc/config/s390/s390.md
diff options
context:
space:
mode:
authorkrebbel <krebbel@138bc75d-0d04-0410-961f-82ee72b054a4>2013-06-27 07:44:11 +0000
committerkrebbel <krebbel@138bc75d-0d04-0410-961f-82ee72b054a4>2013-06-27 07:44:11 +0000
commit5ada7a142c1df1fad051c42f408d84df72a06b4c (patch)
tree9714280940ee187c9f5b17b68759e4465c6c3296 /gcc/config/s390/s390.md
parentdd2f8b8cc6e4bfcf12a484c55e5d289e9c218862 (diff)
downloadgcc-5ada7a142c1df1fad051c42f408d84df72a06b4c.tar.gz
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. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@200454 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/config/s390/s390.md')
-rw-r--r--gcc/config/s390/s390.md281
1 files changed, 258 insertions, 23 deletions
diff --git a/gcc/config/s390/s390.md b/gcc/config/s390/s390.md
index 0141b9813ef..e12d1538a50 100644
--- a/gcc/config/s390/s390.md
+++ b/gcc/config/s390/s390.md
@@ -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")])