This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[PATCH] S/390: shifts and setmems with implicit ANDs
- From: Andreas Krebbel <krebbel1 at de dot ibm dot com>
- To: gcc-patches at gcc dot gnu dot org
- Date: Fri, 12 Aug 2005 12:30:12 +0200
- Subject: [PATCH] S/390: shifts and setmems with implicit ANDs
Hi,
shift instructions on s390 only use the 6 least significant bits
of the shift count operand. Hence we can skip pointless ANDs. After
an unsuccessful try using TARGET_SHIFT_TRUNCATION_MASK I've modified
the shift_count_operand predicate and the print_shift_count_operand
function to omit ANDs with constants which have set these 6 bits.
Almost the same applies to the padding byte operand of mvcle which is
always truncated to the 8 least significant bits.
Bootstrapped and testsuite run without regressions on s390 and s390x.
OK for mainline?
Bye,
-Andreas-
2005-08-11 Andreas Krebbel <krebbel1@de.ibm.com>
* config/s390/predicates.md (setmem_operand): New predicate.
(shift_count_operand): Accept ANDs with special constants as
operand.
(print_shift_count_operand): Skip ANDs with special constants.
* config/s390/s390.md ("setmem_long", "*setmem_long"): Replaced
shift_count_operand with setmem_operand.
Index: gcc-4.1/gcc/config/s390/predicates.md
===================================================================
--- gcc-4.1.orig/gcc/config/s390/predicates.md 2005-08-11 12:38:04.000000000 +0200
+++ gcc-4.1/gcc/config/s390/predicates.md 2005-08-11 12:38:21.000000000 +0200
@@ -75,13 +75,59 @@
(and (match_test "mode == Pmode")
(match_test "!legitimate_la_operand_p (op)"))))
+;; Return true if OP is a valid operand for setmem.
+
+(define_predicate "setmem_operand"
+ (match_code "reg, subreg, plus, const_int")
+{
+ HOST_WIDE_INT offset = 0;
+
+ /* The padding byte operand of the mvcle instruction is always truncated
+ to the 8 least significant bits. */
+ if (GET_CODE (op) == AND && GET_CODE (XEXP (op, 1)) == CONST_INT
+ && (INTVAL (XEXP (op, 1)) & 255) == 255)
+ op = XEXP (op, 0);
+
+ /* We can have an integer constant, an address register,
+ or a sum of the two. Note that reload already checks
+ that any register present is an address register, so
+ we just check for any register here. */
+ if (GET_CODE (op) == CONST_INT)
+ {
+ offset = INTVAL (op);
+ op = NULL_RTX;
+ }
+ if (op && GET_CODE (op) == PLUS && GET_CODE (XEXP (op, 1)) == CONST_INT)
+ {
+ offset = INTVAL (XEXP (op, 1));
+ op = XEXP (op, 0);
+ }
+ while (op && GET_CODE (op) == SUBREG)
+ op = SUBREG_REG (op);
+ if (op && GET_CODE (op) != REG)
+ return false;
+
+ /* Unfortunately we have to reject constants that are invalid
+ for an address, or else reload will get confused. */
+ if (!DISP_IN_RANGE (offset))
+ return false;
+
+ return true;
+})
+
;; Return true if OP is a valid shift count operand.
(define_predicate "shift_count_operand"
- (match_code "reg, subreg, plus, const_int")
+ (match_code "reg, subreg, plus, const_int, and")
{
HOST_WIDE_INT offset = 0;
+ /* Shift count operands are always truncated to the 6 least significant bits.
+ So we can accept pointless ANDs here. */
+ if (GET_CODE (op) == AND && GET_CODE (XEXP (op, 1)) == CONST_INT
+ && (INTVAL (XEXP (op, 1)) & 63) == 63)
+ op = XEXP (op, 0);
+
/* We can have an integer constant, an address register,
or a sum of the two. Note that reload already checks
that any register present is an address register, so
Index: gcc-4.1/gcc/config/s390/s390.c
===================================================================
--- gcc-4.1.orig/gcc/config/s390/s390.c 2005-08-11 12:38:21.000000000 +0200
+++ gcc-4.1/gcc/config/s390/s390.c 2005-08-11 13:29:12.000000000 +0200
@@ -3749,6 +3749,17 @@ print_shift_count_operand (FILE *file, r
{
HOST_WIDE_INT offset = 0;
+ /* Shift count operands are always truncated to the 6 least significant bits and
+ the setmem padding byte to the least 8 significant bits. Hence we can drop
+ pointless ANDs. */
+ if (GET_CODE (op) == AND && GET_CODE (XEXP (op, 1)) == CONST_INT)
+ {
+ if ((INTVAL (XEXP (op, 1)) & 63) != 63)
+ gcc_unreachable ();
+
+ op = XEXP (op, 0);
+ }
+
/* We can have an integer constant, an address register,
or a sum of the two. */
if (GET_CODE (op) == CONST_INT)
Index: gcc-4.1/gcc/config/s390/s390.md
===================================================================
--- gcc-4.1.orig/gcc/config/s390/s390.md 2005-08-11 12:38:04.000000000 +0200
+++ gcc-4.1/gcc/config/s390/s390.md 2005-08-11 13:29:12.000000000 +0200
@@ -2057,7 +2057,7 @@
[(parallel
[(clobber (match_dup 1))
(set (match_operand:BLK 0 "memory_operand" "")
- (match_operand 2 "shift_count_operand" ""))
+ (match_operand 2 "setmem_operand" ""))
(use (match_operand 1 "general_operand" ""))
(use (match_dup 3))
(clobber (reg:CC CC_REGNUM))])]
@@ -2083,7 +2083,7 @@
(define_insn "*setmem_long"
[(clobber (match_operand:<DBL> 0 "register_operand" "=d"))
(set (mem:BLK (subreg:P (match_operand:<DBL> 3 "register_operand" "0") 0))
- (match_operand 2 "shift_count_operand" "Y"))
+ (match_operand 2 "setmem_operand" "Y"))
(use (match_dup 3))
(use (match_operand:<DBL> 1 "register_operand" "d"))
(clobber (reg:CC CC_REGNUM))]