Hi,
Add support for early expansion of vector shifts. Including
vec_sl (shift left), vec_sr (shift right),
vec_sra (shift right algebraic), vec_rl (rotate left).
Part of this includes adding the vector shift right instructions to
the list of those instructions having an unsigned second argument.
The VSR (vector shift right) folding is a bit more complex than
the others. This is due to requiring arg0 be unsigned before the
gimple RSHIFT_EXPR assignment is built, which is required for an
algebraic shift.
[V2 update] Guard the folding of left shifts with TYPE_OVERFLOW_WRAPS.
Add -fwrapv test variations for the left shifts.
[V3 update] Rework the vector shift right folding logic to use the
gimple_build convenience routines. Add a #include of ssa-propagate.h
to get at the update_call_from_tree() function.
I sniff-tested the latest changes on Power8, with good results. Full
regtest running. OK for trunk?
[gcc]
2017-06-13 Will Schmidt
* config/rs6000/rs6000.c: Add include of ssa-propagate.h for
update_call_from_tree().
(rs6000_gimple_fold_builtin): Add handling
for early expansion of vector shifts (sl,sr,sra,rl).
(builtin_function_type): Add vector shift right instructions
to the unsigned argument list.
[gcc/testsuite]
2017-06-13 Will Schmidt
* testsuite/gcc.target/powerpc/fold-vec-shift-char.c: New.
* testsuite/gcc.target/powerpc/fold-vec-shift-int.c: New.
* testsuite/gcc.target/powerpc/fold-vec-shift-longlong.c: New.
* testsuite/gcc.target/powerpc/fold-vec-shift-short.c: New.
* testsuite/gcc.target/powerpc/fold-vec-shift-left.c: New.
* testsuite/gcc.target/powerpc/fold-vec-shift-left-fwrapv.c: New.
* testsuite/gcc.target/powerpc/fold-vec-shift-left-longlong-fwrapv.c:
New.
* testsuite/gcc.target/powerpc/fold-vec-shift-left-longlong.c: New.
diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c
index 63ca2d1..a88fc18 100644
--- a/gcc/config/rs6000/rs6000.c
+++ b/gcc/config/rs6000/rs6000.c
@@ -77,6 +77,7 @@
#endif
#include "case-cfn-macros.h"
#include "ppc-auxv.h"
+#include "tree-ssa-propagate.h"
/* This file should be included last. */
#include "target-def.h"
@@ -16588,6 +16589,76 @@ rs6000_gimple_fold_builtin (gimple_stmt_iterator *gsi)
gsi_replace (gsi, g, true);
return true;
}
+/* Flavors of vec_rotate_left. */
+case ALTIVEC_BUILTIN_VRLB:
+case ALTIVEC_BUILTIN_VRLH:
+case ALTIVEC_BUILTIN_VRLW:
+case P8V_BUILTIN_VRLD:
+ {
+ arg0 = gimple_call_arg (stmt, 0);
+ arg1 = gimple_call_arg (stmt, 1);
+ lhs = gimple_call_lhs (stmt);
+ gimple *g = gimple_build_assign (lhs, LROTATE_EXPR, arg0, arg1);
+ gimple_set_location (g, gimple_location (stmt));
+ gsi_replace (gsi, g, true);
+ return true;
+ }
+ /* Flavors of vector shift right algebraic.
+ * vec_sra{b,h,w} -> vsra{b,h,w}. */
+case ALTIVEC_BUILTIN_VSRAB:
+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);
+ gimple *g = gimple_build_assign (lhs, RSHIFT_EXPR, arg0, arg1);
+ gimple_set_location (g, gimple_location (stmt));
+ 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:
+case ALTIVEC_BUILTIN_VSLH:
+case ALTIVEC_BUILTIN_VSLW:
+case P8V_BUILTIN_VSLD:
+ {
+ arg0 = gimple_call_arg (stmt, 0);
+ if (INTEGRAL_TYPE_P (TREE_TYPE (TREE_TYPE (arg0)))
+ && !TYPE_OVERFLOW_WRAPS (TREE_TYPE (TREE_TYPE (arg0
+ return false;
+ arg1 = gimple_call_arg (stmt, 1);
+ lhs = gimple_call_lhs (stmt);
+ gimple *g = gimple_build_assign (lhs, LSHIFT_EXPR, arg0, arg1);
+ gimple_set_location (g, gimple_location (stmt));
+ gsi_replace (gsi, g, true);
+ return true;
+ }
+/* Flavors of vector shift right. */
+case ALTIVEC_BUILTIN_VSRB:
+case ALTIVEC_BUILTIN_VSRH:
+case ALTIVEC_BUILTIN_VSRW:
+case P8V_BUILTIN_VSRD:
+ {
+ arg0 = gimple_call_arg (stmt, 0);
+ arg1 = gimple_call_arg (stmt, 1);
+ lhs = gimple_call_lhs (stmt);
+ gimple_seq stmts = NULL;
+ /* convert arg0 to unsigned. */
+ tree arg0_unsigned
+ = gimple_build (, VIEW_CONVERT_EXPR,
+ unsigned_type_for (TREE_TYPE (arg0)), arg0);
+ tree res
+ = gimple_build (, RSHIFT_EXPR,
+ TREE_TYPE (arg0_unsigned), arg0_unsigned, arg1);
+ /* convert result back to the lhs type. */
+ res = gimple_build (, VIEW_CONVERT_EXPR, TREE_TYPE (lhs), res);
+