summaryrefslogtreecommitdiff
path: root/gcc/config/s390/s390.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/config/s390/s390.c')
-rw-r--r--gcc/config/s390/s390.c123
1 files changed, 91 insertions, 32 deletions
diff --git a/gcc/config/s390/s390.c b/gcc/config/s390/s390.c
index 6517bce15e0..2edc8ab78f2 100644
--- a/gcc/config/s390/s390.c
+++ b/gcc/config/s390/s390.c
@@ -745,9 +745,13 @@ s390_select_ccmode (enum rtx_code code, rtx op0, rtx op1)
/* Replace the comparison OP0 CODE OP1 by a semantically equivalent one
that we can implement more efficiently. */
-void
-s390_canonicalize_comparison (enum rtx_code *code, rtx *op0, rtx *op1)
+static void
+s390_canonicalize_comparison (int *code, rtx *op0, rtx *op1,
+ bool op0_preserve_value)
{
+ if (op0_preserve_value)
+ return;
+
/* Convert ZERO_EXTRACT back to AND to enable TM patterns. */
if ((*code == EQ || *code == NE)
&& *op1 == const0_rtx
@@ -894,7 +898,7 @@ s390_canonicalize_comparison (enum rtx_code *code, rtx *op0, rtx *op1)
if (MEM_P (*op0) && REG_P (*op1))
{
rtx tem = *op0; *op0 = *op1; *op1 = tem;
- *code = swap_condition (*code);
+ *code = (int)swap_condition ((enum rtx_code)*code);
}
}
@@ -1343,6 +1347,24 @@ s390_contiguous_bitmask_p (unsigned HOST_WIDE_INT in, int size,
return true;
}
+/* Check whether a rotate of ROTL followed by an AND of CONTIG is
+ equivalent to a shift followed by the AND. In particular, CONTIG
+ should not overlap the (rotated) bit 0/bit 63 gap. Negative values
+ for ROTL indicate a rotate to the right. */
+
+bool
+s390_extzv_shift_ok (int bitsize, int rotl, unsigned HOST_WIDE_INT contig)
+{
+ int pos, len;
+ bool ok;
+
+ ok = s390_contiguous_bitmask_p (contig, bitsize, &pos, &len);
+ gcc_assert (ok);
+
+ return ((rotl >= 0 && rotl <= pos)
+ || (rotl < 0 && -rotl <= bitsize - len - pos));
+}
+
/* Check whether we can (and want to) split a double-word
move in mode MODE from SRC to DST into two single-word
moves, moving the subword FIRST_SUBWORD first. */
@@ -5364,28 +5386,35 @@ print_operand_address (FILE *file, rtx addr)
'C': print opcode suffix for branch condition.
'D': print opcode suffix for inverse branch condition.
'E': print opcode suffix for branch on index instruction.
- 'J': print tls_load/tls_gdcall/tls_ldcall suffix
'G': print the size of the operand in bytes.
+ 'J': print tls_load/tls_gdcall/tls_ldcall suffix
+ 'M': print the second word of a TImode operand.
+ 'N': print the second word of a DImode operand.
'O': print only the displacement of a memory reference.
'R': print only the base register of a memory reference.
'S': print S-type memory reference (base+displacement).
- 'N': print the second word of a DImode operand.
- 'M': print the second word of a TImode operand.
'Y': print shift count operand.
'b': print integer X as if it's an unsigned byte.
'c': print integer X as if it's an signed byte.
- 'x': print integer X as if it's an unsigned halfword.
+ 'e': "end" of DImode contiguous bitmask X.
+ 'f': "end" of SImode contiguous bitmask X.
'h': print integer X as if it's a signed halfword.
'i': print the first nonzero HImode part of X.
'j': print the first HImode part unequal to -1 of X.
'k': print the first nonzero SImode part of X.
'm': print the first SImode part unequal to -1 of X.
- 'o': print integer X as if it's an unsigned 32bit word. */
+ 'o': print integer X as if it's an unsigned 32bit word.
+ 's': "start" of DImode contiguous bitmask X.
+ 't': "start" of SImode contiguous bitmask X.
+ 'x': print integer X as if it's an unsigned halfword.
+*/
void
print_operand (FILE *file, rtx x, int code)
{
+ HOST_WIDE_INT ival;
+
switch (code)
{
case 'C':
@@ -5564,30 +5593,57 @@ print_operand (FILE *file, rtx x, int code)
break;
case CONST_INT:
- if (code == 'b')
- fprintf (file, HOST_WIDE_INT_PRINT_DEC, INTVAL (x) & 0xff);
- else if (code == 'c')
- fprintf (file, HOST_WIDE_INT_PRINT_DEC, ((INTVAL (x) & 0xff) ^ 0x80) - 0x80);
- else if (code == 'x')
- fprintf (file, HOST_WIDE_INT_PRINT_DEC, INTVAL (x) & 0xffff);
- else if (code == 'h')
- fprintf (file, HOST_WIDE_INT_PRINT_DEC, ((INTVAL (x) & 0xffff) ^ 0x8000) - 0x8000);
- else if (code == 'i')
- fprintf (file, HOST_WIDE_INT_PRINT_DEC,
- s390_extract_part (x, HImode, 0));
- else if (code == 'j')
- fprintf (file, HOST_WIDE_INT_PRINT_DEC,
- s390_extract_part (x, HImode, -1));
- else if (code == 'k')
- fprintf (file, HOST_WIDE_INT_PRINT_DEC,
- s390_extract_part (x, SImode, 0));
- else if (code == 'm')
- fprintf (file, HOST_WIDE_INT_PRINT_DEC,
- s390_extract_part (x, SImode, -1));
- else if (code == 'o')
- fprintf (file, HOST_WIDE_INT_PRINT_DEC, INTVAL (x) & 0xffffffff);
- else
- fprintf (file, HOST_WIDE_INT_PRINT_DEC, INTVAL (x));
+ ival = INTVAL (x);
+ switch (code)
+ {
+ case 0:
+ break;
+ case 'b':
+ ival &= 0xff;
+ break;
+ case 'c':
+ ival = ((ival & 0xff) ^ 0x80) - 0x80;
+ break;
+ case 'x':
+ ival &= 0xffff;
+ break;
+ case 'h':
+ ival = ((ival & 0xffff) ^ 0x8000) - 0x8000;
+ break;
+ case 'i':
+ ival = s390_extract_part (x, HImode, 0);
+ break;
+ case 'j':
+ ival = s390_extract_part (x, HImode, -1);
+ break;
+ case 'k':
+ ival = s390_extract_part (x, SImode, 0);
+ break;
+ case 'm':
+ ival = s390_extract_part (x, SImode, -1);
+ break;
+ case 'o':
+ ival &= 0xffffffff;
+ break;
+ case 'e': case 'f':
+ case 's': case 't':
+ {
+ int pos, len;
+ bool ok;
+
+ len = (code == 's' || code == 'e' ? 64 : 32);
+ ok = s390_contiguous_bitmask_p (ival, len, &pos, &len);
+ gcc_assert (ok);
+ if (code == 's' || code == 't')
+ ival = 64 - pos - len;
+ else
+ ival = 64 - 1 - pos;
+ }
+ break;
+ default:
+ output_operand_lossage ("invalid constant for output modifier '%c'", code);
+ }
+ fprintf (file, HOST_WIDE_INT_PRINT_DEC, ival);
break;
case CONST_DOUBLE:
@@ -11071,6 +11127,9 @@ s390_loop_unroll_adjust (unsigned nunroll, struct loop *loop)
#undef TARGET_UNWIND_WORD_MODE
#define TARGET_UNWIND_WORD_MODE s390_unwind_word_mode
+#undef TARGET_CANONICALIZE_COMPARISON
+#define TARGET_CANONICALIZE_COMPARISON s390_canonicalize_comparison
+
struct gcc_target targetm = TARGET_INITIALIZER;
#include "gt-s390.h"