From: Michael Meissner Date: Mon, 22 May 2017 22:44:45 +0000 (+0000) Subject: re PR target/80718 (GCC generates slow code for offsettable vec_duplicate) X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=d1f6caaee56f3eb3472899ed56396565c56e164c;p=gcc.git re PR target/80718 (GCC generates slow code for offsettable vec_duplicate) [gcc] 2017-05-22 Michael Meissner PR target/80718 * config/rs6000/vsx.md (vsx_splat_, VSX_D iterator): Split V2DF/V2DI splat into two separate patterns, one that handles registers, and the other that only handles memory. Drop support for splatting from a GPR on ISA 2.07 and then splitting the splat into direct move and splat. (vsx_splat__reg): Likewise. (vsx_splat__mem): Likewise. [gcc/testsuite] 2017-05-22 Michael Meissner PR target/80718 * gcc.target/powerpc/pr80718.c: New test. From-SVN: r248352 --- diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 713654d8031..6824450961b 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,14 @@ +2017-05-22 Michael Meissner + + PR target/80718 + * config/rs6000/vsx.md (vsx_splat_, VSX_D iterator): Split + V2DF/V2DI splat into two separate patterns, one that handles + registers, and the other that only handles memory. Drop support + for splatting from a GPR on ISA 2.07 and then splitting the + splat into direct move and splat. + (vsx_splat__reg): Likewise. + (vsx_splat__mem): Likewise. + 2017-05-22 Segher Boessenkool * cfgcleanup.c (bb_is_just_return): Allow CLOBBERs. diff --git a/gcc/config/rs6000/vsx.md b/gcc/config/rs6000/vsx.md index 28fc5b5f3cf..b669764ce8f 100644 --- a/gcc/config/rs6000/vsx.md +++ b/gcc/config/rs6000/vsx.md @@ -3066,29 +3066,41 @@ }) ;; V2DF/V2DI splat -(define_insn_and_split "vsx_splat_" - [(set (match_operand:VSX_D 0 "vsx_register_operand" - "=, ,we,") +;; We separate the register splat insn from the memory splat insn to force the +;; register allocator to generate the indexed form of the SPLAT when it is +;; given an offsettable memory reference. Otherwise, if the register and +;; memory insns were combined into a single insn, the register allocator will +;; load the value into a register, and then do a double word permute. +(define_expand "vsx_splat_" + [(set (match_operand:VSX_D 0 "vsx_register_operand") (vec_duplicate:VSX_D - (match_operand: 1 "splat_input_operand" - ",Z, b, wA")))] + (match_operand: 1 "input_operand")))] + "VECTOR_MEM_VSX_P (mode)" +{ + rtx op1 = operands[1]; + if (MEM_P (op1)) + operands[1] = rs6000_address_for_fpconvert (op1); + else if (!REG_P (op1)) + op1 = force_reg (mode, op1); +}) + +(define_insn "vsx_splat__reg" + [(set (match_operand:VSX_D 0 "vsx_register_operand" "=,?we") + (vec_duplicate:VSX_D + (match_operand: 1 "gpc_reg_operand" ",b")))] "VECTOR_MEM_VSX_P (mode)" "@ xxpermdi %x0,%x1,%x1,0 - lxvdsx %x0,%y1 - mtvsrdd %x0,%1,%1 - #" - "&& reload_completed && TARGET_POWERPC64 && !TARGET_P9_VECTOR - && int_reg_operand (operands[1], mode)" - [(set (match_dup 2) - (match_dup 1)) - (set (match_dup 0) - (vec_duplicate:VSX_D (match_dup 2)))] -{ - operands[2] = gen_rtx_REG (mode, reg_or_subregno (operands[0])); -} - [(set_attr "type" "vecperm,vecload,vecperm,vecperm") - (set_attr "length" "4,4,4,8")]) + mtvsrdd %x0,%1,%1" + [(set_attr "type" "vecperm")]) + +(define_insn "vsx_splat__mem" + [(set (match_operand:VSX_D 0 "vsx_register_operand" "=") + (vec_duplicate:VSX_D + (match_operand: 1 "memory_operand" "Z")))] + "VECTOR_MEM_VSX_P (mode)" + "lxvdsx %x0,%y1" + [(set_attr "type" "vecload")]) ;; V4SI splat support (define_insn "vsx_splat_v4si" diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index c55b0eef335..702940b67df 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2017-05-22 Michael Meissner + + PR target/80718 + * gcc.target/powerpc/pr80718.c: New test. + 2017-05-22 Segher Boessenkool * gcc.target/powerpc/conditional-return.c: New testcase. diff --git a/gcc/testsuite/gcc.target/powerpc/pr80718.c b/gcc/testsuite/gcc.target/powerpc/pr80718.c new file mode 100644 index 00000000000..9ac5b1b684f --- /dev/null +++ b/gcc/testsuite/gcc.target/powerpc/pr80718.c @@ -0,0 +1,298 @@ +/* { dg-do compile { target { powerpc*-*-* && lp64 } } } */ +/* { dg-skip-if "" { powerpc*-*-darwin* } { "*" } { "" } } */ +/* { dg-require-effective-target powerpc_p8vector_ok } */ +/* { dg-skip-if "do not override -mcpu" { powerpc*-*-* } { "-mcpu=*" } { "-mcpu=power8" } } */ +/* { dg-options "-mcpu=power8 -O3 -ffast-math" } */ + +/* Taken from the Spec 2006 milc brenchmark. Ultimately, GCC wants to generate + a DF splat from offsettable memory. The register allocator decided it was + better to do the load in the GPR registers and do a move direct, rather than + doing a load in the VSX register sets. */ + +typedef struct +{ + double real; + double imag; +} complex; + +typedef struct +{ + double real; + double imag; +} double_complex; + +complex cmplx (double x, double y); +complex cadd (complex * a, complex * b); +complex cmul (complex * a, complex * b); +complex csub (complex * a, complex * b); +complex cdiv (complex * a, complex * b); +complex conjg (complex * a); +complex ce_itheta (double theta); + +double_complex dcmplx (double x, double y); +double_complex dcadd (double_complex * a, double_complex * b); +double_complex dcmul (double_complex * a, double_complex * b); +double_complex dcsub (double_complex * a, double_complex * b); +double_complex dcdiv (double_complex * a, double_complex * b); +double_complex dconjg (double_complex * a); +double_complex dcexp (double_complex * a); +double_complex dclog (double_complex * a); +double_complex dcsqrt (double_complex * z); +double_complex dce_itheta (double theta); + +typedef struct +{ + unsigned long r0, r1, r2, r3, r4, r5, r6; + unsigned long multiplier, addend, ic_state; + double scale; +} double_prn; + +double myrand (double_prn * prn_pt); + +typedef struct +{ + complex e[3][3]; +} su3_matrix; + +typedef struct +{ + complex c[3]; +} su3_vector; + +typedef struct +{ + complex m01, m02, m12; + double m00im, m11im, m22im; + double space; +} anti_hermitmat; + +typedef struct +{ + complex e[2][2]; +} su2_matrix; +typedef struct +{ + su3_vector d[4]; +} wilson_vector; +typedef struct +{ + su3_vector h[2]; +} half_wilson_vector; +typedef struct +{ + wilson_vector c[3]; +} color_wilson_vector; +typedef struct +{ + wilson_vector d[4]; +} spin_wilson_vector; +typedef struct +{ + color_wilson_vector d[4]; +} wilson_matrix; +typedef struct +{ + spin_wilson_vector c[3]; +} wilson_propagator; + +void mult_su3_nn (su3_matrix * a, su3_matrix * b, su3_matrix * c); +void mult_su3_na (su3_matrix * a, su3_matrix * b, su3_matrix * c); +void mult_su3_an (su3_matrix * a, su3_matrix * b, su3_matrix * c); +double realtrace_su3 (su3_matrix * a, su3_matrix * b); +complex trace_su3 (su3_matrix * a); +complex complextrace_su3 (su3_matrix * a, su3_matrix * b); +complex det_su3 (su3_matrix * a); +void add_su3_matrix (su3_matrix * a, su3_matrix * b, su3_matrix * c); +void sub_su3_matrix (su3_matrix * a, su3_matrix * b, su3_matrix * c); +void scalar_mult_su3_matrix (su3_matrix * src, double scalar, + su3_matrix * dest); +void scalar_mult_add_su3_matrix (su3_matrix * src1, su3_matrix * src2, + double scalar, su3_matrix * dest); +void scalar_mult_sub_su3_matrix (su3_matrix * src1, su3_matrix * src2, + double scalar, su3_matrix * dest); +void c_scalar_mult_su3mat (su3_matrix * src, complex * scalar, + su3_matrix * dest); +void c_scalar_mult_add_su3mat (su3_matrix * src1, su3_matrix * src2, + complex * scalar, su3_matrix * dest); +void c_scalar_mult_sub_su3mat (su3_matrix * src1, su3_matrix * src2, + complex * scalar, su3_matrix * dest); +void su3_adjoint (su3_matrix * a, su3_matrix * b); +void make_anti_hermitian (su3_matrix * m3, anti_hermitmat * ah3); +void random_anti_hermitian (anti_hermitmat * mat_antihermit, + double_prn * prn_pt); +void uncompress_anti_hermitian (anti_hermitmat * mat_anti, su3_matrix * mat); +void compress_anti_hermitian (su3_matrix * mat, anti_hermitmat * mat_anti); +void clear_su3mat (su3_matrix * dest); +void su3mat_copy (su3_matrix * a, su3_matrix * b); +void dumpmat (su3_matrix * m); + +void su3_projector (su3_vector * a, su3_vector * b, su3_matrix * c); +complex su3_dot (su3_vector * a, su3_vector * b); +double su3_rdot (su3_vector * a, su3_vector * b); +double magsq_su3vec (su3_vector * a); +void su3vec_copy (su3_vector * a, su3_vector * b); +void dumpvec (su3_vector * v); +void clearvec (su3_vector * v); + +void mult_su3_mat_vec (su3_matrix * a, su3_vector * b, su3_vector * c); +void mult_su3_mat_vec_sum (su3_matrix * a, su3_vector * b, su3_vector * c); +void mult_su3_mat_vec_sum_4dir (su3_matrix * a, su3_vector * b0, + su3_vector * b1, su3_vector * b2, + su3_vector * b3, su3_vector * c); +void mult_su3_mat_vec_nsum (su3_matrix * a, su3_vector * b, su3_vector * c); +void mult_adj_su3_mat_vec (su3_matrix * a, su3_vector * b, su3_vector * c); +void mult_adj_su3_mat_vec_4dir (su3_matrix * a, su3_vector * b, + su3_vector * c); +void mult_adj_su3_mat_4vec (su3_matrix * mat, su3_vector * src, + su3_vector * dest0, su3_vector * dest1, + su3_vector * dest2, su3_vector * dest3); +void mult_adj_su3_mat_vec_sum (su3_matrix * a, su3_vector * b, + su3_vector * c); +void mult_adj_su3_mat_vec_nsum (su3_matrix * a, su3_vector * b, + su3_vector * c); + +void add_su3_vector (su3_vector * a, su3_vector * b, su3_vector * c); +void sub_su3_vector (su3_vector * a, su3_vector * b, su3_vector * c); +void sub_four_su3_vecs (su3_vector * a, su3_vector * b1, su3_vector * b2, + su3_vector * b3, su3_vector * b4); + +void scalar_mult_su3_vector (su3_vector * src, double scalar, + su3_vector * dest); +void scalar_mult_add_su3_vector (su3_vector * src1, su3_vector * src2, + double scalar, su3_vector * dest); +void scalar_mult_sum_su3_vector (su3_vector * src1, su3_vector * src2, + double scalar); +void scalar_mult_sub_su3_vector (su3_vector * src1, su3_vector * src2, + double scalar, su3_vector * dest); +void scalar_mult_wvec (wilson_vector * src, double s, wilson_vector * dest); +void scalar_mult_hwvec (half_wilson_vector * src, double s, + half_wilson_vector * dest); +void scalar_mult_add_wvec (wilson_vector * src1, wilson_vector * src2, + double scalar, wilson_vector * dest); +void scalar_mult_addtm_wvec (wilson_vector * src1, wilson_vector * src2, + double scalar, wilson_vector * dest); +void c_scalar_mult_wvec (wilson_vector * src1, complex * phase, + wilson_vector * dest); +void c_scalar_mult_add_wvec (wilson_vector * src1, wilson_vector * src2, + complex * phase, wilson_vector * dest); +void c_scalar_mult_add_wvec2 (wilson_vector * src1, wilson_vector * src2, + complex s, wilson_vector * dest); +void c_scalar_mult_su3vec (su3_vector * src, complex * phase, + su3_vector * dest); +void c_scalar_mult_add_su3vec (su3_vector * v1, complex * phase, + su3_vector * v2); +void c_scalar_mult_sub_su3vec (su3_vector * v1, complex * phase, + su3_vector * v2); + +void left_su2_hit_n (su2_matrix * u, int p, int q, su3_matrix * link); +void right_su2_hit_a (su2_matrix * u, int p, int q, su3_matrix * link); +void dumpsu2 (su2_matrix * u); +void mult_su2_mat_vec_elem_n (su2_matrix * u, complex * x0, complex * x1); +void mult_su2_mat_vec_elem_a (su2_matrix * u, complex * x0, complex * x1); + +void mult_mat_wilson_vec (su3_matrix * mat, wilson_vector * src, + wilson_vector * dest); +void mult_su3_mat_hwvec (su3_matrix * mat, half_wilson_vector * src, + half_wilson_vector * dest); +void mult_adj_mat_wilson_vec (su3_matrix * mat, wilson_vector * src, + wilson_vector * dest); +void mult_adj_su3_mat_hwvec (su3_matrix * mat, half_wilson_vector * src, + half_wilson_vector * dest); + +void add_wilson_vector (wilson_vector * src1, wilson_vector * src2, + wilson_vector * dest); +void sub_wilson_vector (wilson_vector * src1, wilson_vector * src2, + wilson_vector * dest); +double magsq_wvec (wilson_vector * src); +complex wvec_dot (wilson_vector * src1, wilson_vector * src2); +complex wvec2_dot (wilson_vector * src1, wilson_vector * src2); +double wvec_rdot (wilson_vector * a, wilson_vector * b); + +void wp_shrink (wilson_vector * src, half_wilson_vector * dest, + int dir, int sign); +void wp_shrink_4dir (wilson_vector * a, half_wilson_vector * b1, + half_wilson_vector * b2, half_wilson_vector * b3, + half_wilson_vector * b4, int sign); +void wp_grow (half_wilson_vector * src, wilson_vector * dest, + int dir, int sign); +void wp_grow_add (half_wilson_vector * src, wilson_vector * dest, + int dir, int sign); +void grow_add_four_wvecs (wilson_vector * a, half_wilson_vector * b1, + half_wilson_vector * b2, half_wilson_vector * b3, + half_wilson_vector * b4, int sign, int sum); +void mult_by_gamma (wilson_vector * src, wilson_vector * dest, int dir); +void mult_by_gamma_left (wilson_matrix * src, wilson_matrix * dest, int dir); +void mult_by_gamma_right (wilson_matrix * src, wilson_matrix * dest, int dir); +void mult_swv_by_gamma_l (spin_wilson_vector * src, spin_wilson_vector * dest, + int dir); +void mult_swv_by_gamma_r (spin_wilson_vector * src, spin_wilson_vector * dest, + int dir); +void su3_projector_w (wilson_vector * a, wilson_vector * b, su3_matrix * c); +void clear_wvec (wilson_vector * dest); +void copy_wvec (wilson_vector * src, wilson_vector * dest); +void dump_wilson_vec (wilson_vector * src); + +double gaussian_rand_no (double_prn * prn_pt); +typedef int int32type; +typedef unsigned int u_int32type; +void byterevn (int32type w[], int n); + +void +mult_adj_su3_mat_vec (su3_matrix * a, su3_vector * b, su3_vector * c) +{ + int i; + register double t, ar, ai, br, bi, cr, ci; + for (i = 0; i < 3; i++) + { + ar = a->e[0][i].real; + ai = a->e[0][i].imag; + + br = b->c[0].real; + bi = b->c[0].imag; + + cr = ar * br; + t = ai * bi; + cr += t; + + ci = ar * bi; + t = ai * br; + ci -= t; + + ar = a->e[1][i].real; + ai = a->e[1][i].imag; + + br = b->c[1].real; + bi = b->c[1].imag; + + t = ar * br; + cr += t; + t = ai * bi; + cr += t; + + t = ar * bi; + ci += t; + t = ai * br; + ci -= t; + + ar = a->e[2][i].real; + ai = a->e[2][i].imag; + + br = b->c[2].real; + bi = b->c[2].imag; + + t = ar * br; + cr += t; + t = ai * bi; + cr += t; + + t = ar * bi; + ci += t; + t = ai * br; + ci -= t; + + c->c[i].real = cr; + c->c[i].imag = ci; + } +} + +/* { dg-final { scan-assembler-not "mtvsrd" } } */