From 09e0c98bc4d9b5a9d0b03d9aee14c2f3fb8135c5 Mon Sep 17 00:00:00 2001 From: Bill Schmidt Date: Mon, 11 Feb 2019 16:50:33 +0000 Subject: [PATCH] rs6000.c (rs6000_gimple_fold_builtin): Shift-right and shift-left vector built-ins need to include a TRUNC_MOD_EXPR... [gcc] 2019-02-11 Bill Schmidt * config/rs6000/rs6000.c (rs6000_gimple_fold_builtin): Shift-right and shift-left vector built-ins need to include a TRUNC_MOD_EXPR for correct semantics. [gcc/testsuite] 2019-02-11 Bill Schmidt * gcc.target/powerpc/vec-sld-modulo.c: New. * gcc.target/powerpc/vec-srad-modulo.c: New. * gcc.target/powerpc/vec-srd-modulo.c: New. From-SVN: r268771 --- gcc/ChangeLog | 6 ++ gcc/config/rs6000/rs6000.c | 60 ++++++++++++++++--- gcc/testsuite/ChangeLog | 6 ++ .../gcc.target/powerpc/vec-sld-modulo.c | 42 +++++++++++++ .../gcc.target/powerpc/vec-srad-modulo.c | 43 +++++++++++++ .../gcc.target/powerpc/vec-srd-modulo.c | 42 +++++++++++++ 6 files changed, 191 insertions(+), 8 deletions(-) create mode 100644 gcc/testsuite/gcc.target/powerpc/vec-sld-modulo.c create mode 100644 gcc/testsuite/gcc.target/powerpc/vec-srad-modulo.c create mode 100644 gcc/testsuite/gcc.target/powerpc/vec-srd-modulo.c diff --git a/gcc/ChangeLog b/gcc/ChangeLog index b43bf022066..4a66632e740 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,9 @@ +2019-02-11 Bill Schmidt + + * config/rs6000/rs6000.c (rs6000_gimple_fold_builtin): Shift-right + and shift-left vector built-ins need to include a TRUNC_MOD_EXPR + for correct semantics. + 2019-02-11 Alan Modra * doc/invoke.texi (man page RS/6000 and PowerPC Options): Mention diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c index b4db03203a2..ff51e48eae4 100644 --- a/gcc/config/rs6000/rs6000.c +++ b/gcc/config/rs6000/rs6000.c @@ -15735,13 +15735,37 @@ rs6000_gimple_fold_builtin (gimple_stmt_iterator *gsi) case ALTIVEC_BUILTIN_VSRAH: case ALTIVEC_BUILTIN_VSRAW: case P8V_BUILTIN_VSRAD: - arg0 = gimple_call_arg (stmt, 0); - arg1 = gimple_call_arg (stmt, 1); - lhs = gimple_call_lhs (stmt); - g = gimple_build_assign (lhs, RSHIFT_EXPR, arg0, arg1); - gimple_set_location (g, gimple_location (stmt)); - gsi_replace (gsi, g, true); - return true; + { + arg0 = gimple_call_arg (stmt, 0); + arg1 = gimple_call_arg (stmt, 1); + lhs = gimple_call_lhs (stmt); + tree arg1_type = TREE_TYPE (arg1); + tree unsigned_arg1_type = unsigned_type_for (TREE_TYPE (arg1)); + tree unsigned_element_type = unsigned_type_for (TREE_TYPE (arg1_type)); + location_t loc = gimple_location (stmt); + /* Force arg1 into the range valid matching the arg0 type. */ + /* Build a vector consisting of the max valid bit-size values. */ + int n_elts = VECTOR_CST_NELTS (arg1); + tree element_size = build_int_cst (unsigned_element_type, + 128 / n_elts); + tree_vector_builder elts (unsigned_arg1_type, n_elts, 1); + for (int i = 0; i < n_elts; i++) + elts.safe_push (element_size); + tree modulo_tree = elts.build (); + /* Modulo the provided shift value against that vector. */ + gimple_seq stmts = NULL; + tree unsigned_arg1 = gimple_build (&stmts, VIEW_CONVERT_EXPR, + unsigned_arg1_type, arg1); + tree new_arg1 = gimple_build (&stmts, loc, TRUNC_MOD_EXPR, + unsigned_arg1_type, unsigned_arg1, + modulo_tree); + gsi_insert_seq_before (gsi, stmts, GSI_SAME_STMT); + /* And finally, do the shift. */ + g = gimple_build_assign (lhs, RSHIFT_EXPR, arg0, new_arg1); + gimple_set_location (g, loc); + gsi_replace (gsi, g, true); + return true; + } /* Flavors of vector shift left. builtin_altivec_vsl{b,h,w} -> vsl{b,h,w}. */ case ALTIVEC_BUILTIN_VSLB: @@ -15795,14 +15819,34 @@ rs6000_gimple_fold_builtin (gimple_stmt_iterator *gsi) arg0 = gimple_call_arg (stmt, 0); arg1 = gimple_call_arg (stmt, 1); lhs = gimple_call_lhs (stmt); + tree arg1_type = TREE_TYPE (arg1); + tree unsigned_arg1_type = unsigned_type_for (TREE_TYPE (arg1)); + tree unsigned_element_type = unsigned_type_for (TREE_TYPE (arg1_type)); + location_t loc = gimple_location (stmt); gimple_seq stmts = NULL; /* Convert arg0 to unsigned. */ tree arg0_unsigned = gimple_build (&stmts, VIEW_CONVERT_EXPR, unsigned_type_for (TREE_TYPE (arg0)), arg0); + /* Force arg1 into the range valid matching the arg0 type. */ + /* Build a vector consisting of the max valid bit-size values. */ + int n_elts = VECTOR_CST_NELTS (arg1); + tree element_size = build_int_cst (unsigned_element_type, + 128 / n_elts); + tree_vector_builder elts (unsigned_arg1_type, n_elts, 1); + for (int i = 0; i < n_elts; i++) + elts.safe_push (element_size); + tree modulo_tree = elts.build (); + /* Modulo the provided shift value against that vector. */ + tree unsigned_arg1 = gimple_build (&stmts, VIEW_CONVERT_EXPR, + unsigned_arg1_type, arg1); + tree new_arg1 = gimple_build (&stmts, loc, TRUNC_MOD_EXPR, + unsigned_arg1_type, unsigned_arg1, + modulo_tree); + /* Do the shift. */ tree res = gimple_build (&stmts, RSHIFT_EXPR, - TREE_TYPE (arg0_unsigned), arg0_unsigned, arg1); + TREE_TYPE (arg0_unsigned), arg0_unsigned, new_arg1); /* Convert result back to the lhs type. */ res = gimple_build (&stmts, VIEW_CONVERT_EXPR, TREE_TYPE (lhs), res); gsi_insert_seq_before (gsi, stmts, GSI_SAME_STMT); diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 37af06ad0d9..78aa1bc3c4c 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,9 @@ +2019-02-11 Bill Schmidt + + * gcc.target/powerpc/vec-sld-modulo.c: New. + * gcc.target/powerpc/vec-srad-modulo.c: New. + * gcc.target/powerpc/vec-srd-modulo.c: New. + 2019-02-11 Martin Liska PR ipa/89009 diff --git a/gcc/testsuite/gcc.target/powerpc/vec-sld-modulo.c b/gcc/testsuite/gcc.target/powerpc/vec-sld-modulo.c new file mode 100644 index 00000000000..de7c04577ab --- /dev/null +++ b/gcc/testsuite/gcc.target/powerpc/vec-sld-modulo.c @@ -0,0 +1,42 @@ +/* Test that using a character splat to set up a shift-left + for a doubleword vector works correctly after gimple folding. */ + +/* { dg-do run { target { vsx_hw } } } */ +/* { dg-options "-O2 -mvsx" } */ + +#include + +typedef __vector unsigned long long vui64_t; + +static inline vui64_t +vec_sldi (vui64_t vra, const unsigned int shb) +{ + vui64_t lshift; + vui64_t result; + + /* Note legitimate use of wrong-type splat due to expectation that only + lower 6-bits are read. */ + lshift = (vui64_t) vec_splat_s8 (shb); + + /* Vector Shift Left Doublewords based on the lower 6-bits + of corresponding element of lshift. */ + result = vec_vsld (vra, lshift); + + return result; +} + +__attribute__ ((noinline)) vui64_t +test_sldi_4 (vui64_t a) +{ + return vec_sldi (a, 4); +} + +int +main () +{ + vui64_t x = {-256, 1025}; + x = test_sldi_4 (x); + if (x[0] != -4096 || x[1] != 16400) + __builtin_abort (); + return 0; +} diff --git a/gcc/testsuite/gcc.target/powerpc/vec-srad-modulo.c b/gcc/testsuite/gcc.target/powerpc/vec-srad-modulo.c new file mode 100644 index 00000000000..f18049c386f --- /dev/null +++ b/gcc/testsuite/gcc.target/powerpc/vec-srad-modulo.c @@ -0,0 +1,43 @@ +/* Test that using a character splat to set up a shift-right algebraic + for a doubleword vector works correctly after gimple folding. */ + +/* { dg-do run { target { vsx_hw } } } */ +/* { dg-options "-O2 -mvsx" } */ + +#include + +typedef __vector unsigned long long vui64_t; +typedef __vector long long vi64_t; + +static inline vi64_t +vec_sradi (vi64_t vra, const unsigned int shb) +{ + vui64_t rshift; + vi64_t result; + + /* Note legitimate use of wrong-type splat due to expectation that only + lower 6-bits are read. */ + rshift = (vui64_t) vec_splat_s8 (shb); + + /* Vector Shift Right Algebraic Doublewords based on the lower 6-bits + of corresponding element of rshift. */ + result = vec_vsrad (vra, rshift); + + return result; +} + +__attribute__ ((noinline)) vi64_t +test_sradi_4 (vi64_t a) +{ + return vec_sradi (a, 4); +} + +int +main () +{ + vi64_t x = {-256, 1025}; + x = test_sradi_4 (x); + if (x[0] != -16 || x[1] != 64) + __builtin_abort (); + return 0; +} diff --git a/gcc/testsuite/gcc.target/powerpc/vec-srd-modulo.c b/gcc/testsuite/gcc.target/powerpc/vec-srd-modulo.c new file mode 100644 index 00000000000..0370f1534b7 --- /dev/null +++ b/gcc/testsuite/gcc.target/powerpc/vec-srd-modulo.c @@ -0,0 +1,42 @@ +/* Test that using a character splat to set up a shift-right logical + for a doubleword vector works correctly after gimple folding. */ + +/* { dg-do run { target { vsx_hw } } } */ +/* { dg-options "-O2 -mvsx" } */ + +#include + +typedef __vector unsigned long long vui64_t; + +static inline vui64_t +vec_srdi (vui64_t vra, const unsigned int shb) +{ + vui64_t rshift; + vui64_t result; + + /* Note legitimate use of wrong-type splat due to expectation that only + lower 6-bits are read. */ + rshift = (vui64_t) vec_splat_s8 (shb); + + /* Vector Shift Right [Logical] Doublewords based on the lower 6-bits + of corresponding element of rshift. */ + result = vec_vsrd (vra, rshift); + + return result; +} + +__attribute__ ((noinline)) vui64_t +test_srdi_4 (vui64_t a) +{ + return vec_srdi (a, 4); +} + +int +main () +{ + vui64_t x = {1992357, 1025}; + x = test_srdi_4 (x); + if (x[0] != 124522 || x[1] != 64) + __builtin_abort (); + return 0; +} -- 2.30.2