@@ -115,6 +115,10 @@
return true;
})
+; 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)")))
@@ -2994,18 +2994,18 @@ s390_decompose_address (rtx addr, struct s390_address *out)
bool
s390_decompose_shift_count (rtx op, rtx *base, HOST_WIDE_INT *offset)
{
- HOST_WIDE_INT off = 0;
+ rtx off = NULL_RTX;
/* We can have an integer constant, an address register,
or a sum of the two. */
- if (GET_CODE (op) == CONST_INT)
+ if (CONST_SCALAR_INT_P (op))
{
- off = INTVAL (op);
+ off = op;
op = NULL_RTX;
}
- if (op && GET_CODE (op) == PLUS && GET_CODE (XEXP (op, 1)) == CONST_INT)
+ if (op && GET_CODE (op) == PLUS && CONST_SCALAR_INT_P (XEXP (op, 1)))
{
- off = INTVAL (XEXP (op, 1));
+ off = XEXP (op, 1);
op = XEXP (op, 0);
}
while (op && GET_CODE (op) == SUBREG)
@@ -3015,7 +3015,18 @@ s390_decompose_shift_count (rtx op, rtx *base, HOST_WIDE_INT *offset)
return false;
if (offset)
- *offset = off;
+ {
+ if (off == NULL_RTX)
+ *offset = 0;
+ else if (CONST_INT_P (off))
+ *offset = INTVAL (off);
+ else if (CONST_WIDE_INT_P (off))
+ /* The offset will anyway be cut down to 12 bits so take just
+ the lowest order chunk of the wide int. */
+ *offset = CONST_WIDE_INT_ELT (off, 0);
+ else
+ gcc_unreachable ();
+ }
if (base)
*base = op;
@@ -741,6 +741,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")
@@ -8360,28 +8362,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 "nonmemory_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 "nonmemory_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 "enabled" "*,<addr_style_op_enabled>")
+ (set_attr "z10prop" "z10_super_E1")])
;;
new file mode 100644
@@ -0,0 +1,67 @@
+;;- 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 "" "")))]
+ ""
+ [(set (match_dup 0)
+ (SUBST:DSI (match_dup 1)
+ (plus:SI (match_operand:SI 2 "register_operand" "a")
+ (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")
+
+; The constraints for the second alternative are ok. However, the
+; output template is not. We simply disable the alternative.
+; Alternatively we could also adjust the output template with a
+; subst_attr.
+(define_subst_attr "addr_style_op_enabled" "addr_style_op_subst" "*" "0")
+
+
+; 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")
+