rs6000.c (swap_web_entry): Enlarge special_handling bitfield.

[gcc]

2015-08-30  Bill Schmidt  <wschmidt@linux.vnet.ibm.com>

	* config/rs6000/rs6000.c (swap_web_entry): Enlarge
	special_handling bitfield.
	(special_handling_values): Add SH_XXPERMDI and SH_CONCAT.
	(rtx_is_swappable_p): Add handling for vec_select/vec_concat form
	that represents a general xxpermdi.
	(insn_is_swappable_p): Add handling for vec_concat of two
	doublewords, which maps to a specific xxpermdi.
	(adjust_xxpermdi): New function.
	(adjust_concat): Likewise.
	(handle_special_swappables): Call adjust_xxpermdi and
	adjust_concat.
	(dump_swap_insn_table): Handle SH_XXPERMDI and SH_CONCAT.

[gcc/testsuite]

2015-08-30  Bill Schmidt  <wschmidt@linux.vnet.ibm.com>

	* gcc.target/powerpc/swaps-p8-19.c: New test.

From-SVN: r227331
This commit is contained in:
Bill Schmidt 2015-08-31 01:02:47 +00:00 committed by William Schmidt
parent 5ba02681ad
commit babb13f5cc
4 changed files with 123 additions and 2 deletions

View File

@ -1,3 +1,18 @@
2015-08-30 Bill Schmidt <wschmidt@linux.vnet.ibm.com>
* config/rs6000/rs6000.c (swap_web_entry): Enlarge
special_handling bitfield.
(special_handling_values): Add SH_XXPERMDI and SH_CONCAT.
(rtx_is_swappable_p): Add handling for vec_select/vec_concat form
that represents a general xxpermdi.
(insn_is_swappable_p): Add handling for vec_concat of two
doublewords, which maps to a specific xxpermdi.
(adjust_xxpermdi): New function.
(adjust_concat): Likewise.
(handle_special_swappables): Call adjust_xxpermdi and
adjust_concat.
(dump_swap_insn_table): Handle SH_XXPERMDI and SH_CONCAT.
2015-08-30 Rich Felker <dalias@libc.org>
* config.gcc (supported_defaults): Handle sh[123456ble]*-*-*

View File

@ -34986,7 +34986,7 @@ class swap_web_entry : public web_entry_base
/* A nonzero value indicates what kind of special handling for this
insn is required if doublewords are swapped. Undefined if
is_swappable is not set. */
unsigned int special_handling : 3;
unsigned int special_handling : 4;
/* Set if the web represented by this entry cannot be optimized. */
unsigned int web_not_optimizable : 1;
/* Set if this insn should be deleted. */
@ -35000,7 +35000,9 @@ enum special_handling_values {
SH_NOSWAP_LD,
SH_NOSWAP_ST,
SH_EXTRACT,
SH_SPLAT
SH_SPLAT,
SH_XXPERMDI,
SH_CONCAT
};
/* Union INSN with all insns containing definitions that reach USE.
@ -35192,6 +35194,20 @@ rtx_is_swappable_p (rtx op, unsigned int *special)
*special = SH_EXTRACT;
return 1;
}
/* An XXPERMDI is ok if we adjust the lanes. Note that if the
XXPERMDI is a swap operation, it will be identified by
insn_is_swap_p and therefore we won't get here. */
else if (GET_CODE (XEXP (op, 0)) == VEC_CONCAT
&& (GET_MODE (XEXP (op, 0)) == V4DFmode
|| GET_MODE (XEXP (op, 0)) == V4DImode)
&& GET_CODE ((parallel = XEXP (op, 1))) == PARALLEL
&& XVECLEN (parallel, 0) == 2
&& GET_CODE (XVECEXP (parallel, 0, 0)) == CONST_INT
&& GET_CODE (XVECEXP (parallel, 0, 1)) == CONST_INT)
{
*special = SH_XXPERMDI;
return 1;
}
else
return 0;
@ -35369,6 +35385,17 @@ insn_is_swappable_p (swap_web_entry *insn_entry, rtx insn,
return 1;
}
/* A concatenation of two doublewords is ok if we reverse the
order of the inputs. */
if (GET_CODE (body) == SET
&& GET_CODE (SET_SRC (body)) == VEC_CONCAT
&& (GET_MODE (SET_SRC (body)) == V2DFmode
|| GET_MODE (SET_SRC (body)) == V2DImode))
{
*special = SH_CONCAT;
return 1;
}
/* Otherwise check the operands for vector lane violations. */
return rtx_is_swappable_p (body, special);
}
@ -35658,6 +35685,49 @@ adjust_splat (rtx_insn *insn)
fprintf (dump_file, "Changing lane for splat %d\n", INSN_UID (insn));
}
/* Given OP that contains an XXPERMDI operation (that is not a doubleword
swap), reverse the order of the source operands and adjust the indices
of the source lanes to account for doubleword reversal. */
static void
adjust_xxpermdi (rtx_insn *insn)
{
rtx set = PATTERN (insn);
rtx select = XEXP (set, 1);
rtx concat = XEXP (select, 0);
rtx src0 = XEXP (concat, 0);
XEXP (concat, 0) = XEXP (concat, 1);
XEXP (concat, 1) = src0;
rtx parallel = XEXP (select, 1);
int lane0 = INTVAL (XVECEXP (parallel, 0, 0));
int lane1 = INTVAL (XVECEXP (parallel, 0, 1));
int new_lane0 = 3 - lane1;
int new_lane1 = 3 - lane0;
XVECEXP (parallel, 0, 0) = GEN_INT (new_lane0);
XVECEXP (parallel, 0, 1) = GEN_INT (new_lane1);
INSN_CODE (insn) = -1; /* Force re-recognition. */
df_insn_rescan (insn);
if (dump_file)
fprintf (dump_file, "Changing lanes for xxpermdi %d\n", INSN_UID (insn));
}
/* Given OP that contains a VEC_CONCAT operation of two doublewords,
reverse the order of those inputs. */
static void
adjust_concat (rtx_insn *insn)
{
rtx set = PATTERN (insn);
rtx concat = XEXP (set, 1);
rtx src0 = XEXP (concat, 0);
XEXP (concat, 0) = XEXP (concat, 1);
XEXP (concat, 1) = src0;
INSN_CODE (insn) = -1; /* Force re-recognition. */
df_insn_rescan (insn);
if (dump_file)
fprintf (dump_file, "Reversing inputs for concat %d\n", INSN_UID (insn));
}
/* The insn described by INSN_ENTRY[I] can be swapped, but only
with special handling. Take care of that here. */
static void
@ -35704,6 +35774,14 @@ handle_special_swappables (swap_web_entry *insn_entry, unsigned i)
/* Change the lane on a direct-splat operation. */
adjust_splat (insn);
break;
case SH_XXPERMDI:
/* Change the lanes on an XXPERMDI operation. */
adjust_xxpermdi (insn);
break;
case SH_CONCAT:
/* Reverse the order of a concatenation operation. */
adjust_concat (insn);
break;
}
}
@ -35776,6 +35854,10 @@ dump_swap_insn_table (swap_web_entry *insn_entry)
fputs ("special:extract ", dump_file);
else if (insn_entry[i].special_handling == SH_SPLAT)
fputs ("special:splat ", dump_file);
else if (insn_entry[i].special_handling == SH_XXPERMDI)
fputs ("special:xxpermdi ", dump_file);
else if (insn_entry[i].special_handling == SH_CONCAT)
fputs ("special:concat ", dump_file);
}
if (insn_entry[i].web_not_optimizable)
fputs ("unoptimizable ", dump_file);

View File

@ -1,3 +1,7 @@
2015-08-30 Bill Schmidt <wschmidt@linux.vnet.ibm.com>
* gcc.target/powerpc/swaps-p8-19.c: New test.
2015-08-29 Jerry DeLisle <jvdelisle@gcc.gnu.org>
PR fortran/67367

View File

@ -0,0 +1,20 @@
/* { dg-do compile { target { powerpc64le-*-* } } } */
/* { dg-skip-if "do not override -mcpu" { powerpc*-*-* } { "-mcpu=*" } { "-mcpu=power8" } } */
/* { dg-options "-O2 -ftree-vectorize -mcpu=power8 -ffast-math -fvect-cost-model=unlimited" } */
/* This tests special handling for various uses of xxpermdi, other than
to perform doubleword swaps. */
void foo (_Complex double *self, _Complex double *a, _Complex double *b,
int a1, int a2)
{
int i, j;
for (i = 0; i < a1; ++i)
for (j = 0; j < a2; ++j)
self[i] = self[i] + a[i,j] * b[j];
}
/* { dg-final { scan-assembler-times "xxpermdi .*,.*,.*,0" 1 } } */
/* { dg-final { scan-assembler-times "xxpermdi .*,.*,.*,1" 1 } } */
/* { dg-final { scan-assembler-times "xxpermdi .*,.*,.*,2" 1 } } */
/* { dg-final { scan-assembler-times "xxpermdi .*,.*,.*,3" 1 } } */