@@ -115,6 +115,31 @@
return true;
})
+; Accept single register and immediate operands usable as shift
+; counts.
+(define_predicate "addrreg_or_constint_operand"
+ (match_code "reg, subreg, const_int")
+{
+ if (GET_MODE (op) != VOIDmode
+ && GET_MODE_CLASS (GET_MODE (op)) != MODE_INT)
+ return false;
+
+ while (op && GET_CODE (op) == SUBREG)
+ op = SUBREG_REG (op);
+
+ if (REG_P (op)
+ && (REGNO (op) >= FIRST_PSEUDO_REGISTER || ADDR_REG_P (op)))
+ return true;
+
+ if (CONST_INT_P (op))
+ return true;
+
+ return false;
+})
+; An integer operand with the lowest order 6 bit all ones.
+(define_predicate "const_int_6bitset_operand"
+ (and (match_code "const_int")
+ (match_test "(INTVAL (op) & 63) == 63")))
(define_predicate "nonzero_shift_count_operand"
(and (match_code "const_int")
(match_test "IN_RANGE (INTVAL (op), 1, GET_MODE_BITSIZE (mode) - 1)")))
@@ -739,6 +739,8 @@
(define_mode_attr asm_fcmp [(CCVEQ "e") (CCVFH "h") (CCVFHE "he")])
(define_mode_attr insn_cmp [(CCVEQ "eq") (CCVH "h") (CCVHU "hl") (CCVFH "h") (CCVFHE "he")])
+;; Subst pattern definitions
+(include "subst.md")
(include "vector.md")
@@ -8350,28 +8352,26 @@
; rotl(di|si)3 instruction pattern(s).
;
-; rll, rllg
-(define_insn "rotl<mode>3"
- [(set (match_operand:GPR 0 "register_operand" "=d")
- (rotate:GPR (match_operand:GPR 1 "register_operand" "d")
- (match_operand:SI 2 "shift_count_or_setmem_operand" "Y")))]
+(define_expand "rotl<mode>3"
+ [(set (match_operand:GPR 0 "register_operand" "")
+ (rotate:GPR (match_operand:GPR 1 "register_operand" "")
+ (match_operand:SI 2 "shift_count_or_setmem_operand" "")))]
"TARGET_CPU_ZARCH"
- "rll<g>\t%0,%1,%Y2"
- [(set_attr "op_type" "RSE")
- (set_attr "atype" "reg")
- (set_attr "z10prop" "z10_super_E1")])
+ "")
; rll, rllg
-(define_insn "*rotl<mode>3_and"
- [(set (match_operand:GPR 0 "register_operand" "=d")
- (rotate:GPR (match_operand:GPR 1 "register_operand" "d")
- (and:SI (match_operand:SI 2 "shift_count_or_setmem_operand" "Y")
- (match_operand:SI 3 "const_int_operand" "n"))))]
- "TARGET_CPU_ZARCH && (INTVAL (operands[3]) & 63) == 63"
- "rll<g>\t%0,%1,%Y2"
+(define_insn "*rotl<mode>3<addr_style_op><masked_op>"
+ [(set (match_operand:GPR 0 "register_operand" "=d,d")
+ (rotate:GPR (match_operand:GPR 1 "register_operand" "d,d")
+ (match_operand:SI 2 "addrreg_or_constint_operand" "a,n")))]
+ "TARGET_CPU_ZARCH"
+ "@
+ rll<g>\t%0,%1,<addr_style_op_op3>(%2)
+ rll<g>\t%0,%1,%Y2"
[(set_attr "op_type" "RSE")
(set_attr "atype" "reg")
- (set_attr "z10prop" "z10_super_E1")])
+ (set_attr "disabled" "0,<addr_style_op_disable>")
+ (set_attr "z10prop" "z10_super_E1")])
;;
new file mode 100644
@@ -0,0 +1,66 @@
+;;- Machine description for GNU compiler -- S/390 / zSeries version.
+;; Subst patterns.
+;; Copyright (C) 2016 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/>.
+
+(define_code_iterator SUBST [ashift lshiftrt rotate])
+
+; This expands an register/immediate operand to a register+immediate
+; operand to draw advantage of the address style operand format
+; providing a addition for free.
+(define_subst "addr_style_op_subst"
+ [(set (match_operand:DSI 0 "" "")
+ (SUBST:DSI (match_operand:DSI 1 "" "")
+ (match_operand:SI 2 "" "")))]
+ "REG_P (operands[2])"
+ [(set (match_dup 0)
+ (SUBST:DSI (match_dup 1)
+ (plus:SI (match_dup 2)
+ (match_operand 3 "const_int_operand" "n"))))])
+
+; Use this in the insn name.
+(define_subst_attr "addr_style_op" "addr_style_op_subst" "" "_plus")
+
+; In the subst pattern the additional const int operand will be used
+; as displacement. In the normal version the displacements stays just
+; 0.
+(define_subst_attr "addr_style_op_op3" "addr_style_op_subst" "0" "%Y3")
+
+; In the subst pattern we have to disable the alternative where op2 is
+; already a constant. This attribute is supposed to be used in the
+; "disabled" insn attribute to achieve this.
+(define_subst_attr "addr_style_op_disable" "addr_style_op_subst" "0" "1")
+
+
+; This substitution adds an explicit AND operation to the second
+; operand. This way previous operations on the now masked out bits
+; might get optimized away.
+(define_subst "masked_op_subst"
+ [(set (match_operand:DSI 0 "" "")
+ (SUBST:DSI (match_operand:DSI 1 "" "")
+ (match_operand:SI 2 "" "")))]
+ ""
+ [(set (match_dup 0)
+ (SUBST:DSI (match_dup 1)
+ (and:SI (match_dup 2)
+ (match_operand:SI 3 "const_int_6bitset_operand" ""))))])
+
+; Use this in the insn name.
+(define_subst_attr "masked_op" "masked_op_subst" "" "_and")
+