diff options
author | Bill Schmidt <wschmidt@linux.vnet.ibm.com> | 2014-09-08 18:40:56 +0000 |
---|---|---|
committer | William Schmidt <wschmidt@gcc.gnu.org> | 2014-09-08 18:40:56 +0000 |
commit | db09274d918fc8e1411ad0ad60d1f0a6ec4eb9da (patch) | |
tree | 3ba75b651bf50bf18f714cbfb584f17bb3681990 /gcc/config | |
parent | 33d9078ac5134dce037632da60cde27145193f5a (diff) | |
download | gcc-db09274d918fc8e1411ad0ad60d1f0a6ec4eb9da.zip gcc-db09274d918fc8e1411ad0ad60d1f0a6ec4eb9da.tar.gz gcc-db09274d918fc8e1411ad0ad60d1f0a6ec4eb9da.tar.bz2 |
rs6000.c (special_handling_values): Add SH_SPLAT.
[gcc]
2014-09-08 Bill Schmidt <wschmidt@linux.vnet.ibm.com>
* config/rs6000/rs6000.c (special_handling_values): Add SH_SPLAT.
(rtx_is_swappable_p): Convert UNSPEC cascading ||s to a switch
statement; allow optimization of UNSPEC_VSPLT_DIRECT with special
handling SH_SPLAT.
(adjust_extract): Fix test for VEC_DUPLICATE case; fix adjustment
of extracted lane.
(adjust_splat): New function.
(handle_special_swappables): Call adjust_splat for SH_SPLAT.
(dump_swap_insn_table): Add case for SH_SPLAT.
[gcc/testsuite]
2014-09-08 Bill Schmidt <wschmidt@linux.vnet.ibm.com>
* gcc.target/powerpc/swaps-p8-16.c: New test.
From-SVN: r215019
Diffstat (limited to 'gcc/config')
-rw-r--r-- | gcc/config/rs6000/rs6000.c | 125 |
1 files changed, 79 insertions, 46 deletions
diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c index 6370304..fd91986 100644 --- a/gcc/config/rs6000/rs6000.c +++ b/gcc/config/rs6000/rs6000.c @@ -33524,7 +33524,8 @@ enum special_handling_values { SH_SUBREG, SH_NOSWAP_LD, SH_NOSWAP_ST, - SH_EXTRACT + SH_EXTRACT, + SH_SPLAT }; /* Union INSN with all insns containing definitions that reach USE. @@ -33735,43 +33736,50 @@ rtx_is_swappable_p (rtx op, unsigned int *special) vector splat are element-order sensitive. A few of these cases might be workable with special handling if required. */ int val = XINT (op, 1); - if (val == UNSPEC_VMRGH_DIRECT - || val == UNSPEC_VMRGL_DIRECT - || val == UNSPEC_VPACK_SIGN_SIGN_SAT - || val == UNSPEC_VPACK_SIGN_UNS_SAT - || val == UNSPEC_VPACK_UNS_UNS_MOD - || val == UNSPEC_VPACK_UNS_UNS_MOD_DIRECT - || val == UNSPEC_VPACK_UNS_UNS_SAT - || val == UNSPEC_VPERM - || val == UNSPEC_VPERM_UNS - || val == UNSPEC_VPERMHI - || val == UNSPEC_VPERMSI - || val == UNSPEC_VPKPX - || val == UNSPEC_VSLDOI - || val == UNSPEC_VSLO - || val == UNSPEC_VSPLT_DIRECT - || val == UNSPEC_VSRO - || val == UNSPEC_VSUM2SWS - || val == UNSPEC_VSUM4S - || val == UNSPEC_VSUM4UBS - || val == UNSPEC_VSUMSWS - || val == UNSPEC_VSUMSWS_DIRECT - || val == UNSPEC_VSX_CONCAT - || val == UNSPEC_VSX_CVSPDP - || val == UNSPEC_VSX_CVSPDPN - || val == UNSPEC_VSX_SET - || val == UNSPEC_VSX_SLDWI - || val == UNSPEC_VUNPACK_HI_SIGN - || val == UNSPEC_VUNPACK_HI_SIGN_DIRECT - || val == UNSPEC_VUNPACK_LO_SIGN - || val == UNSPEC_VUNPACK_LO_SIGN_DIRECT - || val == UNSPEC_VUPKHPX - || val == UNSPEC_VUPKHS_V4SF - || val == UNSPEC_VUPKHU_V4SF - || val == UNSPEC_VUPKLPX - || val == UNSPEC_VUPKLS_V4SF - || val == UNSPEC_VUPKHU_V4SF) - return 0; + switch (val) + { + default: + break; + case UNSPEC_VMRGH_DIRECT: + case UNSPEC_VMRGL_DIRECT: + case UNSPEC_VPACK_SIGN_SIGN_SAT: + case UNSPEC_VPACK_SIGN_UNS_SAT: + case UNSPEC_VPACK_UNS_UNS_MOD: + case UNSPEC_VPACK_UNS_UNS_MOD_DIRECT: + case UNSPEC_VPACK_UNS_UNS_SAT: + case UNSPEC_VPERM: + case UNSPEC_VPERM_UNS: + case UNSPEC_VPERMHI: + case UNSPEC_VPERMSI: + case UNSPEC_VPKPX: + case UNSPEC_VSLDOI: + case UNSPEC_VSLO: + case UNSPEC_VSRO: + case UNSPEC_VSUM2SWS: + case UNSPEC_VSUM4S: + case UNSPEC_VSUM4UBS: + case UNSPEC_VSUMSWS: + case UNSPEC_VSUMSWS_DIRECT: + case UNSPEC_VSX_CONCAT: + case UNSPEC_VSX_CVSPDP: + case UNSPEC_VSX_CVSPDPN: + case UNSPEC_VSX_SET: + case UNSPEC_VSX_SLDWI: + case UNSPEC_VUNPACK_HI_SIGN: + case UNSPEC_VUNPACK_HI_SIGN_DIRECT: + case UNSPEC_VUNPACK_LO_SIGN: + case UNSPEC_VUNPACK_LO_SIGN_DIRECT: + case UNSPEC_VUPKHPX: + case UNSPEC_VUPKHS_V4SF: + case UNSPEC_VUPKHU_V4SF: + case UNSPEC_VUPKLPX: + case UNSPEC_VUPKLS_V4SF: + case UNSPEC_VUPKLU_V4SF: + return 0; + case UNSPEC_VSPLT_DIRECT: + *special = SH_SPLAT; + return 1; + } } default: @@ -34098,20 +34106,20 @@ permute_store (rtx_insn *insn) INSN_UID (insn)); } -/* Given OP that contains a vector extract operation, change the index - of the extracted lane to count from the other side of the vector. */ +/* Given OP that contains a vector extract operation, adjust the index + of the extracted lane to account for the doubleword swap. */ static void adjust_extract (rtx_insn *insn) { - rtx body = PATTERN (insn); + rtx src = SET_SRC (PATTERN (insn)); /* The vec_select may be wrapped in a vec_duplicate for a splat, so account for that. */ - rtx sel = (GET_CODE (body) == VEC_DUPLICATE - ? XEXP (XEXP (body, 0), 1) - : XEXP (body, 1)); + rtx sel = GET_CODE (src) == VEC_DUPLICATE ? XEXP (src, 0) : src; rtx par = XEXP (sel, 1); - int nunits = GET_MODE_NUNITS (GET_MODE (XEXP (sel, 0))); - XVECEXP (par, 0, 0) = GEN_INT (nunits - 1 - INTVAL (XVECEXP (par, 0, 0))); + int half_elts = GET_MODE_NUNITS (GET_MODE (XEXP (sel, 0))) >> 1; + int lane = INTVAL (XVECEXP (par, 0, 0)); + lane = lane >= half_elts ? lane - half_elts : lane + half_elts; + XVECEXP (par, 0, 0) = GEN_INT (lane); INSN_CODE (insn) = -1; /* Force re-recognition. */ df_insn_rescan (insn); @@ -34119,6 +34127,24 @@ adjust_extract (rtx_insn *insn) fprintf (dump_file, "Changing lane for extract %d\n", INSN_UID (insn)); } +/* Given OP that contains a vector direct-splat operation, adjust the index + of the source lane to account for the doubleword swap. */ +static void +adjust_splat (rtx_insn *insn) +{ + rtx body = PATTERN (insn); + rtx unspec = XEXP (body, 1); + int half_elts = GET_MODE_NUNITS (GET_MODE (unspec)) >> 1; + int lane = INTVAL (XVECEXP (unspec, 0, 1)); + lane = lane >= half_elts ? lane - half_elts : lane + half_elts; + XVECEXP (unspec, 0, 1) = GEN_INT (lane); + INSN_CODE (insn) = -1; /* Force re-recognition. */ + df_insn_rescan (insn); + + if (dump_file) + fprintf (dump_file, "Changing lane for splat %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 @@ -34160,6 +34186,11 @@ handle_special_swappables (swap_web_entry *insn_entry, unsigned i) case SH_EXTRACT: /* Change the lane on an extract operation. */ adjust_extract (insn); + break; + case SH_SPLAT: + /* Change the lane on a direct-splat operation. */ + adjust_splat (insn); + break; } } @@ -34230,6 +34261,8 @@ dump_swap_insn_table (swap_web_entry *insn_entry) fputs ("special:store ", dump_file); else if (insn_entry[i].special_handling == SH_EXTRACT) fputs ("special:extract ", dump_file); + else if (insn_entry[i].special_handling == SH_SPLAT) + fputs ("special:splat ", dump_file); } if (insn_entry[i].web_not_optimizable) fputs ("unoptimizable ", dump_file); |