From: Bill Schmidt Date: Mon, 31 Aug 2015 01:02:47 +0000 (+0000) Subject: rs6000.c (swap_web_entry): Enlarge special_handling bitfield. X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=babb13f5cc83ae685fdea4824a51f6de5345b2aa;p=gcc.git rs6000.c (swap_web_entry): Enlarge special_handling bitfield. [gcc] 2015-08-30 Bill Schmidt * 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 * gcc.target/powerpc/swaps-p8-19.c: New test. From-SVN: r227331 --- diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 9150a6e7692..f91964d1221 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,18 @@ +2015-08-30 Bill Schmidt + + * 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 * config.gcc (supported_defaults): Handle sh[123456ble]*-*-* diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c index 93fdece9a32..500effa7331 100644 --- a/gcc/config/rs6000/rs6000.c +++ b/gcc/config/rs6000/rs6000.c @@ -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); diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 1d8373d7876..8869251bb14 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,7 @@ +2015-08-30 Bill Schmidt + + * gcc.target/powerpc/swaps-p8-19.c: New test. + 2015-08-29 Jerry DeLisle PR fortran/67367 diff --git a/gcc/testsuite/gcc.target/powerpc/swaps-p8-19.c b/gcc/testsuite/gcc.target/powerpc/swaps-p8-19.c new file mode 100644 index 00000000000..6dffbb9b892 --- /dev/null +++ b/gcc/testsuite/gcc.target/powerpc/swaps-p8-19.c @@ -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 } } */