aboutsummaryrefslogtreecommitdiffstats
path: root/toolchain-layer/recipes-devtools/gcc/gcc-4.6/linaro/gcc-4.6-linaro-r106834.patch
diff options
context:
space:
mode:
Diffstat (limited to 'toolchain-layer/recipes-devtools/gcc/gcc-4.6/linaro/gcc-4.6-linaro-r106834.patch')
-rw-r--r--toolchain-layer/recipes-devtools/gcc/gcc-4.6/linaro/gcc-4.6-linaro-r106834.patch1505
1 files changed, 0 insertions, 1505 deletions
diff --git a/toolchain-layer/recipes-devtools/gcc/gcc-4.6/linaro/gcc-4.6-linaro-r106834.patch b/toolchain-layer/recipes-devtools/gcc/gcc-4.6/linaro/gcc-4.6-linaro-r106834.patch
deleted file mode 100644
index 421a8fe3a9..0000000000
--- a/toolchain-layer/recipes-devtools/gcc/gcc-4.6/linaro/gcc-4.6-linaro-r106834.patch
+++ /dev/null
@@ -1,1505 +0,0 @@
- 2011-10-18 Ira Rosen <ira.rosen@linaro.org>
-
- gcc/
- * doc/md.texi (vec_widen_ushiftl_hi, vec_widen_ushiftl_lo,
- vec_widen_sshiftl_hi, vec_widen_sshiftl_lo): Document.
- * tree-pretty-print.c (dump_generic_node): Handle WIDEN_LSHIFT_EXPR,
- VEC_WIDEN_LSHIFT_HI_EXPR and VEC_WIDEN_LSHIFT_LO_EXPR.
- (op_code_prio): Likewise.
- (op_symbol_code): Handle WIDEN_LSHIFT_EXPR.
- * optabs.c (optab_for_tree_code): Handle
- VEC_WIDEN_LSHIFT_HI_EXPR and VEC_WIDEN_LSHIFT_LO_EXPR.
- (init-optabs): Initialize optab codes for vec_widen_u/sshiftl_hi/lo.
- * optabs.h (enum optab_index): Add OTI_vec_widen_u/sshiftl_hi/lo.
- * genopinit.c (optabs): Initialize the new optabs.
- * expr.c (expand_expr_real_2): Handle
- VEC_WIDEN_LSHIFT_HI_EXPR and VEC_WIDEN_LSHIFT_LO_EXPR.
- * gimple-pretty-print.c (dump_binary_rhs): Likewise.
- * tree-vectorizer.h (NUM_PATTERNS): Increase to 8.
- * tree.def (WIDEN_LSHIFT_EXPR, VEC_WIDEN_LSHIFT_HI_EXPR,
- VEC_WIDEN_LSHIFT_LO_EXPR): New.
- * cfgexpand.c (expand_debug_expr): Handle new tree codes.
- * tree-vect-patterns.c (vect_vect_recog_func_ptrs): Add
- vect_recog_widen_shift_pattern.
- (vect_handle_widen_mult_by_const): Rename...
- (vect_handle_widen_op_by_const): ...to this. Handle shifts.
- Add a new argument, update documentation.
- (vect_recog_widen_mult_pattern): Assume that only second
- operand can be constant. Update call to
- vect_handle_widen_op_by_const.
- (vect_recog_over_widening_pattern): Fix typo.
- (vect_recog_widen_shift_pattern): New.
- * tree-vect-stmts.c (vectorizable_type_promotion): Handle
- widening shifts.
- (supportable_widening_operation): Likewise.
- * tree-inline.c (estimate_operator_cost): Handle new tree codes.
- * tree-vect-generic.c (expand_vector_operations_1): Likewise.
- * tree-cfg.c (verify_gimple_assign_binary): Likewise.
- * config/arm/neon.md (neon_vec_<US>shiftl_<mode>): New.
- (vec_widen_<US>shiftl_lo_<mode>, neon_vec_<US>shiftl_hi_<mode>,
- vec_widen_<US>shiftl_hi_<mode>, neon_vec_<US>shift_left_<mode>):
- Likewise.
- * config/arm/predicates.md (const_neon_scalar_shift_amount_operand):
- New.
- * config/arm/iterators.md (V_innermode): New.
- * tree-vect-slp.c (vect_build_slp_tree): Require same shift operand
- for widening shift.
-
- gcc/testsuite
- * testsuite/lib/target-supports.exp
- (check_effective_target_vect_widen_shift): New.
- * gcc.dg/vect/vect-widen-shift-s16.c: New.
- * gcc.dg/vect/vect-widen-shift-s8.c: New.
- * gcc.dg/vect/vect-widen-shift-u16.c: New.
- * gcc.dg/vect/vect-widen-shift-u8.c: New.
-
- 2011-10-06 Jakub Jelinek <jakub@redhat.com>
-
- gcc/
- * tree-vect-patterns.c (vect_pattern_recog_1): Use
- vect_recog_func_ptr typedef for the first argument.
- (vect_pattern_recog): Rename vect_recog_func_ptr variable
- to vect_recog_func, use vect_recog_func_ptr typedef for it.
-
- 2011-10-16 Ira Rosen <ira.rosen@linaro.org>
-
- gcc/
- PR tree-optimization/50727
- * tree-vect-patterns.c (vect_operation_fits_smaller_type): Add
- DEF_STMT to the list of statements to be replaced by the
- pattern statements.
-
- 2011-10-09 Ira Rosen <ira.rosen@linaro.org>
-
- gcc/
- PR tree-optimization/50635
- * tree-vect-patterns.c (vect_handle_widen_mult_by_const): Add
- DEF_STMT to the list of statements to be replaced by the
- pattern statements.
- (vect_handle_widen_mult_by_const): Don't check TYPE_OUT.
-
-=== modified file 'gcc/cfgexpand.c'
---- old/gcc/cfgexpand.c 2011-07-01 09:19:21 +0000
-+++ new/gcc/cfgexpand.c 2011-10-23 13:33:07 +0000
-@@ -3215,6 +3215,8 @@
- case VEC_UNPACK_LO_EXPR:
- case VEC_WIDEN_MULT_HI_EXPR:
- case VEC_WIDEN_MULT_LO_EXPR:
-+ case VEC_WIDEN_LSHIFT_HI_EXPR:
-+ case VEC_WIDEN_LSHIFT_LO_EXPR:
- return NULL;
-
- /* Misc codes. */
-
-=== modified file 'gcc/config/arm/iterators.md'
---- old/gcc/config/arm/iterators.md 2011-09-06 14:29:24 +0000
-+++ new/gcc/config/arm/iterators.md 2011-10-23 13:33:07 +0000
-@@ -388,6 +388,9 @@
- (define_mode_attr qhs_extenddi_cstr [(SI "r") (HI "rm") (QI "rUq")])
- (define_mode_attr qhs_zextenddi_cstr [(SI "r") (HI "rm") (QI "rm")])
-
-+;; Mode attribute for vshll.
-+(define_mode_attr V_innermode [(V8QI "QI") (V4HI "HI") (V2SI "SI")])
-+
- ;;----------------------------------------------------------------------------
- ;; Code attributes
- ;;----------------------------------------------------------------------------
-
-=== modified file 'gcc/config/arm/neon.md'
---- old/gcc/config/arm/neon.md 2011-10-03 01:32:17 +0000
-+++ new/gcc/config/arm/neon.md 2011-10-23 13:33:07 +0000
-@@ -5316,6 +5316,44 @@
- }
- )
-
-+(define_insn "neon_vec_<US>shiftl_<mode>"
-+ [(set (match_operand:<V_widen> 0 "register_operand" "=w")
-+ (SE:<V_widen> (ashift:VW (match_operand:VW 1 "register_operand" "w")
-+ (match_operand:<V_innermode> 2 "const_neon_scalar_shift_amount_operand" ""))))]
-+ "TARGET_NEON"
-+{
-+ return "vshll.<US><V_sz_elem> %q0, %P1, %2";
-+}
-+ [(set_attr "neon_type" "neon_shift_1")]
-+)
-+
-+(define_expand "vec_widen_<US>shiftl_lo_<mode>"
-+ [(match_operand:<V_unpack> 0 "register_operand" "")
-+ (SE:<V_unpack> (match_operand:VU 1 "register_operand" ""))
-+ (match_operand:SI 2 "immediate_operand" "i")]
-+ "TARGET_NEON && !BYTES_BIG_ENDIAN"
-+ {
-+ emit_insn (gen_neon_vec_<US>shiftl_<V_half> (operands[0],
-+ simplify_gen_subreg (<V_HALF>mode, operands[1], <MODE>mode, 0),
-+ operands[2]));
-+ DONE;
-+ }
-+)
-+
-+(define_expand "vec_widen_<US>shiftl_hi_<mode>"
-+ [(match_operand:<V_unpack> 0 "register_operand" "")
-+ (SE:<V_unpack> (match_operand:VU 1 "register_operand" ""))
-+ (match_operand:SI 2 "immediate_operand" "i")]
-+ "TARGET_NEON && !BYTES_BIG_ENDIAN"
-+ {
-+ emit_insn (gen_neon_vec_<US>shiftl_<V_half> (operands[0],
-+ simplify_gen_subreg (<V_HALF>mode, operands[1], <MODE>mode,
-+ GET_MODE_SIZE (<V_HALF>mode)),
-+ operands[2]));
-+ DONE;
-+ }
-+)
-+
- ;; Vectorize for non-neon-quad case
- (define_insn "neon_unpack<US>_<mode>"
- [(set (match_operand:<V_widen> 0 "register_operand" "=w")
-@@ -5392,6 +5430,34 @@
- }
- )
-
-+(define_expand "vec_widen_<US>shiftl_hi_<mode>"
-+ [(match_operand:<V_double_width> 0 "register_operand" "")
-+ (SE:<V_double_width> (match_operand:VDI 1 "register_operand" ""))
-+ (match_operand:SI 2 "immediate_operand" "i")]
-+ "TARGET_NEON"
-+ {
-+ rtx tmpreg = gen_reg_rtx (<V_widen>mode);
-+ emit_insn (gen_neon_vec_<US>shiftl_<mode> (tmpreg, operands[1], operands[2]));
-+ emit_insn (gen_neon_vget_high<V_widen_l> (operands[0], tmpreg));
-+
-+ DONE;
-+ }
-+)
-+
-+(define_expand "vec_widen_<US>shiftl_lo_<mode>"
-+ [(match_operand:<V_double_width> 0 "register_operand" "")
-+ (SE:<V_double_width> (match_operand:VDI 1 "register_operand" ""))
-+ (match_operand:SI 2 "immediate_operand" "i")]
-+ "TARGET_NEON"
-+ {
-+ rtx tmpreg = gen_reg_rtx (<V_widen>mode);
-+ emit_insn (gen_neon_vec_<US>shiftl_<mode> (tmpreg, operands[1], operands[2]));
-+ emit_insn (gen_neon_vget_low<V_widen_l> (operands[0], tmpreg));
-+
-+ DONE;
-+ }
-+)
-+
- ;; The case when using all quad registers.
- (define_insn "vec_pack_trunc_<mode>"
- [(set (match_operand:<V_narrow_pack> 0 "register_operand" "=&w")
-
-=== modified file 'gcc/config/arm/predicates.md'
---- old/gcc/config/arm/predicates.md 2011-10-10 11:43:28 +0000
-+++ new/gcc/config/arm/predicates.md 2011-10-23 13:33:07 +0000
-@@ -136,6 +136,11 @@
- (match_operand 0 "s_register_operand"))
- (match_operand 0 "const_int_operand")))
-
-+(define_predicate "const_neon_scalar_shift_amount_operand"
-+ (and (match_code "const_int")
-+ (match_test "((unsigned HOST_WIDE_INT) INTVAL (op)) <= GET_MODE_BITSIZE (mode)
-+ && ((unsigned HOST_WIDE_INT) INTVAL (op)) > 0")))
-+
- (define_predicate "arm_add_operand"
- (ior (match_operand 0 "arm_rhs_operand")
- (match_operand 0 "arm_neg_immediate_operand")))
-
-=== modified file 'gcc/doc/md.texi'
---- old/gcc/doc/md.texi 2011-08-13 08:32:32 +0000
-+++ new/gcc/doc/md.texi 2011-10-23 13:33:07 +0000
-@@ -4230,6 +4230,17 @@
- elements of the two vectors, and put the N/2 products of size 2*S in the
- output vector (operand 0).
-
-+@cindex @code{vec_widen_ushiftl_hi_@var{m}} instruction pattern
-+@cindex @code{vec_widen_ushiftl_lo_@var{m}} instruction pattern
-+@cindex @code{vec_widen_sshiftl_hi_@var{m}} instruction pattern
-+@cindex @code{vec_widen_sshiftl_lo_@var{m}} instruction pattern
-+@item @samp{vec_widen_ushiftl_hi_@var{m}}, @samp{vec_widen_ushiftl_lo_@var{m}}
-+@itemx @samp{vec_widen_sshiftl_hi_@var{m}}, @samp{vec_widen_sshiftl_lo_@var{m}}
-+Signed/Unsigned widening shift left. The first input (operand 1) is a vector
-+with N signed/unsigned elements of size S@. Operand 2 is a constant. Shift
-+the high/low elements of operand 1, and put the N/2 results of size 2*S in the
-+output vector (operand 0).
-+
- @cindex @code{mulhisi3} instruction pattern
- @item @samp{mulhisi3}
- Multiply operands 1 and 2, which have mode @code{HImode}, and store
-
-=== modified file 'gcc/expr.c'
---- old/gcc/expr.c 2011-08-25 11:42:09 +0000
-+++ new/gcc/expr.c 2011-10-23 13:33:07 +0000
-@@ -8290,6 +8290,19 @@
- return target;
- }
-
-+ case VEC_WIDEN_LSHIFT_HI_EXPR:
-+ case VEC_WIDEN_LSHIFT_LO_EXPR:
-+ {
-+ tree oprnd0 = treeop0;
-+ tree oprnd1 = treeop1;
-+
-+ expand_operands (oprnd0, oprnd1, NULL_RTX, &op0, &op1, EXPAND_NORMAL);
-+ target = expand_widen_pattern_expr (ops, op0, op1, NULL_RTX,
-+ target, unsignedp);
-+ gcc_assert (target);
-+ return target;
-+ }
-+
- case VEC_PACK_TRUNC_EXPR:
- case VEC_PACK_SAT_EXPR:
- case VEC_PACK_FIX_TRUNC_EXPR:
-
-=== modified file 'gcc/genopinit.c'
---- old/gcc/genopinit.c 2011-07-15 13:06:31 +0000
-+++ new/gcc/genopinit.c 2011-10-23 13:33:07 +0000
-@@ -268,6 +268,10 @@
- "set_optab_handler (vec_widen_umult_lo_optab, $A, CODE_FOR_$(vec_widen_umult_lo_$a$))",
- "set_optab_handler (vec_widen_smult_hi_optab, $A, CODE_FOR_$(vec_widen_smult_hi_$a$))",
- "set_optab_handler (vec_widen_smult_lo_optab, $A, CODE_FOR_$(vec_widen_smult_lo_$a$))",
-+ "set_optab_handler (vec_widen_ushiftl_hi_optab, $A, CODE_FOR_$(vec_widen_ushiftl_hi_$a$))",
-+ "set_optab_handler (vec_widen_ushiftl_lo_optab, $A, CODE_FOR_$(vec_widen_ushiftl_lo_$a$))",
-+ "set_optab_handler (vec_widen_sshiftl_hi_optab, $A, CODE_FOR_$(vec_widen_sshiftl_hi_$a$))",
-+ "set_optab_handler (vec_widen_sshiftl_lo_optab, $A, CODE_FOR_$(vec_widen_sshiftl_lo_$a$))",
- "set_optab_handler (vec_unpacks_hi_optab, $A, CODE_FOR_$(vec_unpacks_hi_$a$))",
- "set_optab_handler (vec_unpacks_lo_optab, $A, CODE_FOR_$(vec_unpacks_lo_$a$))",
- "set_optab_handler (vec_unpacku_hi_optab, $A, CODE_FOR_$(vec_unpacku_hi_$a$))",
-
-=== modified file 'gcc/gimple-pretty-print.c'
---- old/gcc/gimple-pretty-print.c 2011-05-05 15:42:22 +0000
-+++ new/gcc/gimple-pretty-print.c 2011-10-23 13:33:07 +0000
-@@ -343,6 +343,8 @@
- case VEC_EXTRACT_ODD_EXPR:
- case VEC_INTERLEAVE_HIGH_EXPR:
- case VEC_INTERLEAVE_LOW_EXPR:
-+ case VEC_WIDEN_LSHIFT_HI_EXPR:
-+ case VEC_WIDEN_LSHIFT_LO_EXPR:
- for (p = tree_code_name [(int) code]; *p; p++)
- pp_character (buffer, TOUPPER (*p));
- pp_string (buffer, " <");
-
-=== modified file 'gcc/optabs.c'
---- old/gcc/optabs.c 2011-08-11 15:46:01 +0000
-+++ new/gcc/optabs.c 2011-10-23 13:33:07 +0000
-@@ -454,6 +454,14 @@
- return TYPE_UNSIGNED (type) ?
- vec_widen_umult_lo_optab : vec_widen_smult_lo_optab;
-
-+ case VEC_WIDEN_LSHIFT_HI_EXPR:
-+ return TYPE_UNSIGNED (type) ?
-+ vec_widen_ushiftl_hi_optab : vec_widen_sshiftl_hi_optab;
-+
-+ case VEC_WIDEN_LSHIFT_LO_EXPR:
-+ return TYPE_UNSIGNED (type) ?
-+ vec_widen_ushiftl_lo_optab : vec_widen_sshiftl_lo_optab;
-+
- case VEC_UNPACK_HI_EXPR:
- return TYPE_UNSIGNED (type) ?
- vec_unpacku_hi_optab : vec_unpacks_hi_optab;
-@@ -6351,6 +6359,10 @@
- init_optab (vec_widen_umult_lo_optab, UNKNOWN);
- init_optab (vec_widen_smult_hi_optab, UNKNOWN);
- init_optab (vec_widen_smult_lo_optab, UNKNOWN);
-+ init_optab (vec_widen_ushiftl_hi_optab, UNKNOWN);
-+ init_optab (vec_widen_ushiftl_lo_optab, UNKNOWN);
-+ init_optab (vec_widen_sshiftl_hi_optab, UNKNOWN);
-+ init_optab (vec_widen_sshiftl_lo_optab, UNKNOWN);
- init_optab (vec_unpacks_hi_optab, UNKNOWN);
- init_optab (vec_unpacks_lo_optab, UNKNOWN);
- init_optab (vec_unpacku_hi_optab, UNKNOWN);
-
-=== modified file 'gcc/optabs.h'
---- old/gcc/optabs.h 2011-07-27 14:12:45 +0000
-+++ new/gcc/optabs.h 2011-10-23 13:33:07 +0000
-@@ -350,6 +350,12 @@
- OTI_vec_widen_umult_lo,
- OTI_vec_widen_smult_hi,
- OTI_vec_widen_smult_lo,
-+ /* Widening shift left.
-+ The high/low part of the resulting vector is returned. */
-+ OTI_vec_widen_ushiftl_hi,
-+ OTI_vec_widen_ushiftl_lo,
-+ OTI_vec_widen_sshiftl_hi,
-+ OTI_vec_widen_sshiftl_lo,
- /* Extract and widen the high/low part of a vector of signed or
- floating point elements. */
- OTI_vec_unpacks_hi,
-@@ -542,6 +548,10 @@
- #define vec_widen_umult_lo_optab (&optab_table[OTI_vec_widen_umult_lo])
- #define vec_widen_smult_hi_optab (&optab_table[OTI_vec_widen_smult_hi])
- #define vec_widen_smult_lo_optab (&optab_table[OTI_vec_widen_smult_lo])
-+#define vec_widen_ushiftl_hi_optab (&optab_table[OTI_vec_widen_ushiftl_hi])
-+#define vec_widen_ushiftl_lo_optab (&optab_table[OTI_vec_widen_ushiftl_lo])
-+#define vec_widen_sshiftl_hi_optab (&optab_table[OTI_vec_widen_sshiftl_hi])
-+#define vec_widen_sshiftl_lo_optab (&optab_table[OTI_vec_widen_sshiftl_lo])
- #define vec_unpacks_hi_optab (&optab_table[OTI_vec_unpacks_hi])
- #define vec_unpacks_lo_optab (&optab_table[OTI_vec_unpacks_lo])
- #define vec_unpacku_hi_optab (&optab_table[OTI_vec_unpacku_hi])
-
-=== added file 'gcc/testsuite/gcc.dg/vect/vect-widen-shift-s16.c'
---- old/gcc/testsuite/gcc.dg/vect/vect-widen-shift-s16.c 1970-01-01 00:00:00 +0000
-+++ new/gcc/testsuite/gcc.dg/vect/vect-widen-shift-s16.c 2011-10-23 13:33:07 +0000
-@@ -0,0 +1,107 @@
-+/* { dg-require-effective-target vect_int } */
-+/* { dg-require-effective-target vect_shift } */
-+
-+#include <stdarg.h>
-+#include "tree-vect.h"
-+
-+#define N 64
-+#define C 16
-+
-+__attribute__ ((noinline)) void
-+foo (short *src, int *dst)
-+{
-+ int i;
-+ short b, b0, b1, b2, b3, *s = src;
-+ int *d = dst;
-+
-+ for (i = 0; i < N/4; i++)
-+ {
-+ b0 = *s++;
-+ b1 = *s++;
-+ b2 = *s++;
-+ b3 = *s++;
-+ *d = b0 << C;
-+ d++;
-+ *d = b1 << C;
-+ d++;
-+ *d = b2 << C;
-+ d++;
-+ *d = b3 << C;
-+ d++;
-+ }
-+
-+ s = src;
-+ d = dst;
-+ for (i = 0; i < N; i++)
-+ {
-+ b = *s++;
-+ if (*d != b << C)
-+ abort ();
-+ d++;
-+ }
-+
-+ s = src;
-+ d = dst;
-+ for (i = 0; i < N/4; i++)
-+ {
-+ b0 = *s++;
-+ b1 = *s++;
-+ b2 = *s++;
-+ b3 = *s++;
-+ *d = b0 << C;
-+ d++;
-+ *d = b1 << C;
-+ d++;
-+ *d = b2 << C;
-+ d++;
-+ *d = b3 << 6;
-+ d++;
-+ }
-+
-+ s = src;
-+ d = dst;
-+ for (i = 0; i < N/4; i++)
-+ {
-+ b = *s++;
-+ if (*d != b << C)
-+ abort ();
-+ d++;
-+ b = *s++;
-+ if (*d != b << C)
-+ abort ();
-+ d++;
-+ b = *s++;
-+ if (*d != b << C)
-+ abort ();
-+ d++;
-+ b = *s++;
-+ if (*d != b << 6)
-+ abort ();
-+ d++;
-+ }
-+}
-+
-+int main (void)
-+{
-+ int i;
-+ short in[N];
-+ int out[N];
-+
-+ check_vect ();
-+
-+ for (i = 0; i < N; i++)
-+ {
-+ in[i] = i;
-+ out[i] = 255;
-+ __asm__ volatile ("");
-+ }
-+
-+ foo (in, out);
-+
-+ return 0;
-+}
-+
-+/* { dg-final { scan-tree-dump-times "vect_recog_widen_shift_pattern: detected" 8 "vect" { target vect_widen_shift } } } */
-+/* { dg-final { scan-tree-dump-times "vectorized 2 loops" 1 "vect" } } */
-+/* { dg-final { cleanup-tree-dump "vect" } } */
-+
-
-=== added file 'gcc/testsuite/gcc.dg/vect/vect-widen-shift-s8.c'
---- old/gcc/testsuite/gcc.dg/vect/vect-widen-shift-s8.c 1970-01-01 00:00:00 +0000
-+++ new/gcc/testsuite/gcc.dg/vect/vect-widen-shift-s8.c 2011-10-23 13:33:07 +0000
-@@ -0,0 +1,58 @@
-+/* { dg-require-effective-target vect_int } */
-+/* { dg-require-effective-target vect_shift } */
-+
-+#include <stdarg.h>
-+#include "tree-vect.h"
-+
-+#define N 64
-+#define C 12
-+
-+__attribute__ ((noinline)) void
-+foo (char *src, int *dst)
-+{
-+ int i;
-+ char b, *s = src;
-+ int *d = dst;
-+
-+ for (i = 0; i < N; i++)
-+ {
-+ b = *s++;
-+ *d = b << C;
-+ d++;
-+ }
-+
-+ s = src;
-+ d = dst;
-+ for (i = 0; i < N; i++)
-+ {
-+ b = *s++;
-+ if (*d != b << C)
-+ abort ();
-+ d++;
-+ }
-+}
-+
-+int main (void)
-+{
-+ int i;
-+ char in[N];
-+ int out[N];
-+
-+ check_vect ();
-+
-+ for (i = 0; i < N; i++)
-+ {
-+ in[i] = i;
-+ out[i] = 255;
-+ __asm__ volatile ("");
-+ }
-+
-+ foo (in, out);
-+
-+ return 0;
-+}
-+
-+/* { dg-final { scan-tree-dump-times "vect_recog_widen_shift_pattern: detected" 1 "vect" { target vect_widen_shift } } } */
-+/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" } } */
-+/* { dg-final { cleanup-tree-dump "vect" } } */
-+
-
-=== added file 'gcc/testsuite/gcc.dg/vect/vect-widen-shift-u16.c'
---- old/gcc/testsuite/gcc.dg/vect/vect-widen-shift-u16.c 1970-01-01 00:00:00 +0000
-+++ new/gcc/testsuite/gcc.dg/vect/vect-widen-shift-u16.c 2011-10-23 13:33:07 +0000
-@@ -0,0 +1,58 @@
-+/* { dg-require-effective-target vect_int } */
-+/* { dg-require-effective-target vect_shift } */
-+
-+#include <stdarg.h>
-+#include "tree-vect.h"
-+
-+#define N 64
-+#define C 7
-+
-+__attribute__ ((noinline)) void
-+foo (unsigned short *src, unsigned int *dst)
-+{
-+ int i;
-+ unsigned short b, *s = src;
-+ unsigned int *d = dst;
-+
-+ for (i = 0; i < N; i++)
-+ {
-+ b = *s++;
-+ *d = b << C;
-+ d++;
-+ }
-+
-+ s = src;
-+ d = dst;
-+ for (i = 0; i < N; i++)
-+ {
-+ b = *s++;
-+ if (*d != b << C)
-+ abort ();
-+ d++;
-+ }
-+}
-+
-+int main (void)
-+{
-+ int i;
-+ unsigned short in[N];
-+ unsigned int out[N];
-+
-+ check_vect ();
-+
-+ for (i = 0; i < N; i++)
-+ {
-+ in[i] = i;
-+ out[i] = 255;
-+ __asm__ volatile ("");
-+ }
-+
-+ foo (in, out);
-+
-+ return 0;
-+}
-+
-+/* { dg-final { scan-tree-dump-times "vect_recog_widen_shift_pattern: detected" 1 "vect" { target vect_widen_shift } } } */
-+/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" } } */
-+/* { dg-final { cleanup-tree-dump "vect" } } */
-+
-
-=== added file 'gcc/testsuite/gcc.dg/vect/vect-widen-shift-u8.c'
---- old/gcc/testsuite/gcc.dg/vect/vect-widen-shift-u8.c 1970-01-01 00:00:00 +0000
-+++ new/gcc/testsuite/gcc.dg/vect/vect-widen-shift-u8.c 2011-10-23 13:33:07 +0000
-@@ -0,0 +1,65 @@
-+/* { dg-require-effective-target vect_int } */
-+/* { dg-require-effective-target vect_shift } */
-+
-+#include <stdarg.h>
-+#include "tree-vect.h"
-+
-+#define N 64
-+#define C1 10
-+#define C2 5
-+
-+__attribute__ ((noinline)) void
-+foo (unsigned char *src, unsigned int *dst1, unsigned int *dst2)
-+{
-+ int i;
-+ unsigned char b, *s = src;
-+ unsigned int *d1 = dst1, *d2 = dst2;
-+
-+ for (i = 0; i < N; i++)
-+ {
-+ b = *s++;
-+ *d1 = b << C1;
-+ d1++;
-+ *d2 = b << C2;
-+ d2++;
-+ }
-+
-+ s = src;
-+ d1 = dst1;
-+ d2 = dst2;
-+ for (i = 0; i < N; i++)
-+ {
-+ b = *s++;
-+ if (*d1 != b << C1 || *d2 != b << C2)
-+ abort ();
-+ d1++;
-+ d2++;
-+ }
-+}
-+
-+int main (void)
-+{
-+ int i;
-+ unsigned char in[N];
-+ unsigned int out1[N];
-+ unsigned int out2[N];
-+
-+ check_vect ();
-+
-+ for (i = 0; i < N; i++)
-+ {
-+ in[i] = i;
-+ out1[i] = 255;
-+ out2[i] = 255;
-+ __asm__ volatile ("");
-+ }
-+
-+ foo (in, out1, out2);
-+
-+ return 0;
-+}
-+
-+/* { dg-final { scan-tree-dump-times "vect_recog_widen_shift_pattern: detected" 1 "vect" { target vect_widen_shift } } } */
-+/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" } } */
-+/* { dg-final { cleanup-tree-dump "vect" } } */
-+
-
-=== modified file 'gcc/testsuite/lib/target-supports.exp'
---- old/gcc/testsuite/lib/target-supports.exp 2011-10-06 11:08:08 +0000
-+++ new/gcc/testsuite/lib/target-supports.exp 2011-10-23 13:33:07 +0000
-@@ -2783,6 +2783,26 @@
- }
-
- # Return 1 if the target plus current options supports a vector
-+# widening shift, 0 otherwise.
-+#
-+# This won't change for different subtargets so cache the result.
-+
-+proc check_effective_target_vect_widen_shift { } {
-+ global et_vect_widen_shift_saved
-+
-+ if [info exists et_vect_shift_saved] {
-+ verbose "check_effective_target_vect_widen_shift: using cached result" 2
-+ } else {
-+ set et_vect_widen_shift_saved 0
-+ if { ([istarget arm*-*-*] && [check_effective_target_arm_neon_ok]) } {
-+ set et_vect_widen_shift_saved 1
-+ }
-+ }
-+ verbose "check_effective_target_vect_widen_shift: returning $et_vect_widen_shift_saved" 2
-+ return $et_vect_widen_shift_saved
-+}
-+
-+# Return 1 if the target plus current options supports a vector
- # dot-product of signed chars, 0 otherwise.
- #
- # This won't change for different subtargets so cache the result.
-
-=== modified file 'gcc/tree-cfg.c'
---- old/gcc/tree-cfg.c 2011-07-15 13:44:50 +0000
-+++ new/gcc/tree-cfg.c 2011-10-23 13:33:07 +0000
-@@ -3473,6 +3473,44 @@
- return false;
- }
-
-+ case WIDEN_LSHIFT_EXPR:
-+ {
-+ if (!INTEGRAL_TYPE_P (lhs_type)
-+ || !INTEGRAL_TYPE_P (rhs1_type)
-+ || TREE_CODE (rhs2) != INTEGER_CST
-+ || (2 * TYPE_PRECISION (rhs1_type) > TYPE_PRECISION (lhs_type)))
-+ {
-+ error ("type mismatch in widening vector shift expression");
-+ debug_generic_expr (lhs_type);
-+ debug_generic_expr (rhs1_type);
-+ debug_generic_expr (rhs2_type);
-+ return true;
-+ }
-+
-+ return false;
-+ }
-+
-+ case VEC_WIDEN_LSHIFT_HI_EXPR:
-+ case VEC_WIDEN_LSHIFT_LO_EXPR:
-+ {
-+ if (TREE_CODE (rhs1_type) != VECTOR_TYPE
-+ || TREE_CODE (lhs_type) != VECTOR_TYPE
-+ || !INTEGRAL_TYPE_P (TREE_TYPE (rhs1_type))
-+ || !INTEGRAL_TYPE_P (TREE_TYPE (lhs_type))
-+ || TREE_CODE (rhs2) != INTEGER_CST
-+ || (2 * TYPE_PRECISION (TREE_TYPE (rhs1_type))
-+ > TYPE_PRECISION (TREE_TYPE (lhs_type))))
-+ {
-+ error ("type mismatch in widening vector shift expression");
-+ debug_generic_expr (lhs_type);
-+ debug_generic_expr (rhs1_type);
-+ debug_generic_expr (rhs2_type);
-+ return true;
-+ }
-+
-+ return false;
-+ }
-+
- case PLUS_EXPR:
- case MINUS_EXPR:
- {
-
-=== modified file 'gcc/tree-inline.c'
---- old/gcc/tree-inline.c 2011-08-13 08:32:32 +0000
-+++ new/gcc/tree-inline.c 2011-10-23 13:33:07 +0000
-@@ -3343,6 +3343,7 @@
- case DOT_PROD_EXPR:
- case WIDEN_MULT_PLUS_EXPR:
- case WIDEN_MULT_MINUS_EXPR:
-+ case WIDEN_LSHIFT_EXPR:
-
- case VEC_WIDEN_MULT_HI_EXPR:
- case VEC_WIDEN_MULT_LO_EXPR:
-@@ -3357,6 +3358,8 @@
- case VEC_EXTRACT_ODD_EXPR:
- case VEC_INTERLEAVE_HIGH_EXPR:
- case VEC_INTERLEAVE_LOW_EXPR:
-+ case VEC_WIDEN_LSHIFT_HI_EXPR:
-+ case VEC_WIDEN_LSHIFT_LO_EXPR:
-
- return 1;
-
-
-=== modified file 'gcc/tree-pretty-print.c'
---- old/gcc/tree-pretty-print.c 2010-11-05 09:00:50 +0000
-+++ new/gcc/tree-pretty-print.c 2011-10-23 13:33:07 +0000
-@@ -1539,6 +1539,7 @@
- case RROTATE_EXPR:
- case VEC_LSHIFT_EXPR:
- case VEC_RSHIFT_EXPR:
-+ case WIDEN_LSHIFT_EXPR:
- case BIT_IOR_EXPR:
- case BIT_XOR_EXPR:
- case BIT_AND_EXPR:
-@@ -2209,6 +2210,22 @@
- pp_string (buffer, " > ");
- break;
-
-+ case VEC_WIDEN_LSHIFT_HI_EXPR:
-+ pp_string (buffer, " VEC_WIDEN_LSHIFT_HI_EXPR < ");
-+ dump_generic_node (buffer, TREE_OPERAND (node, 0), spc, flags, false);
-+ pp_string (buffer, ", ");
-+ dump_generic_node (buffer, TREE_OPERAND (node, 1), spc, flags, false);
-+ pp_string (buffer, " > ");
-+ break;
-+
-+ case VEC_WIDEN_LSHIFT_LO_EXPR:
-+ pp_string (buffer, " VEC_WIDEN_LSHIFT_HI_EXPR < ");
-+ dump_generic_node (buffer, TREE_OPERAND (node, 0), spc, flags, false);
-+ pp_string (buffer, ", ");
-+ dump_generic_node (buffer, TREE_OPERAND (node, 1), spc, flags, false);
-+ pp_string (buffer, " > ");
-+ break;
-+
- case VEC_UNPACK_HI_EXPR:
- pp_string (buffer, " VEC_UNPACK_HI_EXPR < ");
- dump_generic_node (buffer, TREE_OPERAND (node, 0), spc, flags, false);
-@@ -2531,6 +2548,9 @@
- case RSHIFT_EXPR:
- case LROTATE_EXPR:
- case RROTATE_EXPR:
-+ case VEC_WIDEN_LSHIFT_HI_EXPR:
-+ case VEC_WIDEN_LSHIFT_LO_EXPR:
-+ case WIDEN_LSHIFT_EXPR:
- return 11;
-
- case WIDEN_SUM_EXPR:
-@@ -2706,6 +2726,9 @@
- case VEC_RSHIFT_EXPR:
- return "v>>";
-
-+ case WIDEN_LSHIFT_EXPR:
-+ return "w<<";
-+
- case POINTER_PLUS_EXPR:
- return "+";
-
-
-=== modified file 'gcc/tree-vect-generic.c'
---- old/gcc/tree-vect-generic.c 2011-02-08 14:16:50 +0000
-+++ new/gcc/tree-vect-generic.c 2011-10-23 13:33:07 +0000
-@@ -552,7 +552,9 @@
- || code == VEC_UNPACK_LO_EXPR
- || code == VEC_PACK_TRUNC_EXPR
- || code == VEC_PACK_SAT_EXPR
-- || code == VEC_PACK_FIX_TRUNC_EXPR)
-+ || code == VEC_PACK_FIX_TRUNC_EXPR
-+ || code == VEC_WIDEN_LSHIFT_HI_EXPR
-+ || code == VEC_WIDEN_LSHIFT_LO_EXPR)
- type = TREE_TYPE (rhs1);
-
- /* Optabs will try converting a negation into a subtraction, so
-
-=== modified file 'gcc/tree-vect-patterns.c'
---- old/gcc/tree-vect-patterns.c 2011-09-05 06:23:37 +0000
-+++ new/gcc/tree-vect-patterns.c 2011-10-23 13:33:07 +0000
-@@ -48,12 +48,15 @@
- static gimple vect_recog_pow_pattern (VEC (gimple, heap) **, tree *, tree *);
- static gimple vect_recog_over_widening_pattern (VEC (gimple, heap) **, tree *,
- tree *);
-+static gimple vect_recog_widen_shift_pattern (VEC (gimple, heap) **,
-+ tree *, tree *);
- static vect_recog_func_ptr vect_vect_recog_func_ptrs[NUM_PATTERNS] = {
- vect_recog_widen_mult_pattern,
- vect_recog_widen_sum_pattern,
- vect_recog_dot_prod_pattern,
- vect_recog_pow_pattern,
-- vect_recog_over_widening_pattern};
-+ vect_recog_over_widening_pattern,
-+ vect_recog_widen_shift_pattern};
-
-
- /* Function widened_name_p
-@@ -331,27 +334,38 @@
- return pattern_stmt;
- }
-
--/* Handle two cases of multiplication by a constant. The first one is when
-- the constant, CONST_OPRND, fits the type (HALF_TYPE) of the second
-- operand (OPRND). In that case, we can peform widen-mult from HALF_TYPE to
-- TYPE.
-+
-+/* Handle widening operation by a constant. At the moment we support MULT_EXPR
-+ and LSHIFT_EXPR.
-+
-+ For MULT_EXPR we check that CONST_OPRND fits HALF_TYPE, and for LSHIFT_EXPR
-+ we check that CONST_OPRND is less or equal to the size of HALF_TYPE.
-
- Otherwise, if the type of the result (TYPE) is at least 4 times bigger than
-- HALF_TYPE, and CONST_OPRND fits an intermediate type (2 times smaller than
-- TYPE), we can perform widen-mult from the intermediate type to TYPE and
-- replace a_T = (TYPE) a_t; with a_it - (interm_type) a_t; */
-+ HALF_TYPE, and there is an intermediate type (2 times smaller than TYPE)
-+ that satisfies the above restrictions, we can perform a widening opeartion
-+ from the intermediate type to TYPE and replace a_T = (TYPE) a_t;
-+ with a_it = (interm_type) a_t; */
-
- static bool
--vect_handle_widen_mult_by_const (gimple stmt, tree const_oprnd, tree *oprnd,
-- VEC (gimple, heap) **stmts, tree type,
-- tree *half_type, gimple def_stmt)
-+vect_handle_widen_op_by_const (gimple stmt, enum tree_code code,
-+ tree const_oprnd, tree *oprnd,
-+ VEC (gimple, heap) **stmts, tree type,
-+ tree *half_type, gimple def_stmt)
- {
- tree new_type, new_oprnd, tmp;
- gimple new_stmt;
- loop_vec_info loop_info = STMT_VINFO_LOOP_VINFO (vinfo_for_stmt (stmt));
- struct loop *loop = LOOP_VINFO_LOOP (loop_info);
-
-- if (int_fits_type_p (const_oprnd, *half_type))
-+ if (code != MULT_EXPR && code != LSHIFT_EXPR)
-+ return false;
-+
-+ if (((code == MULT_EXPR && int_fits_type_p (const_oprnd, *half_type))
-+ || (code == LSHIFT_EXPR
-+ && compare_tree_int (const_oprnd, TYPE_PRECISION (*half_type))
-+ != 1))
-+ && TYPE_PRECISION (type) == (TYPE_PRECISION (*half_type) * 2))
- {
- /* CONST_OPRND is a constant of HALF_TYPE. */
- *oprnd = gimple_assign_rhs1 (def_stmt);
-@@ -364,14 +378,16 @@
- || !vinfo_for_stmt (def_stmt))
- return false;
-
-- /* TYPE is 4 times bigger than HALF_TYPE, try widen-mult for
-+ /* TYPE is 4 times bigger than HALF_TYPE, try widening operation for
- a type 2 times bigger than HALF_TYPE. */
- new_type = build_nonstandard_integer_type (TYPE_PRECISION (type) / 2,
- TYPE_UNSIGNED (type));
-- if (!int_fits_type_p (const_oprnd, new_type))
-+ if ((code == MULT_EXPR && !int_fits_type_p (const_oprnd, new_type))
-+ || (code == LSHIFT_EXPR
-+ && compare_tree_int (const_oprnd, TYPE_PRECISION (new_type)) == 1))
- return false;
-
-- /* Use NEW_TYPE for widen_mult. */
-+ /* Use NEW_TYPE for widening operation. */
- if (STMT_VINFO_RELATED_STMT (vinfo_for_stmt (def_stmt)))
- {
- new_stmt = STMT_VINFO_RELATED_STMT (vinfo_for_stmt (def_stmt));
-@@ -381,6 +397,7 @@
- || TREE_TYPE (gimple_assign_lhs (new_stmt)) != new_type)
- return false;
-
-+ VEC_safe_push (gimple, heap, *stmts, def_stmt);
- *oprnd = gimple_assign_lhs (new_stmt);
- }
- else
-@@ -392,7 +409,6 @@
- new_oprnd = make_ssa_name (tmp, NULL);
- new_stmt = gimple_build_assign_with_ops (NOP_EXPR, new_oprnd, *oprnd,
- NULL_TREE);
-- SSA_NAME_DEF_STMT (new_oprnd) = new_stmt;
- STMT_VINFO_RELATED_STMT (vinfo_for_stmt (def_stmt)) = new_stmt;
- VEC_safe_push (gimple, heap, *stmts, def_stmt);
- *oprnd = new_oprnd;
-@@ -402,7 +418,6 @@
- return true;
- }
-
--
- /* Function vect_recog_widen_mult_pattern
-
- Try to find the following pattern:
-@@ -491,7 +506,7 @@
- enum tree_code dummy_code;
- int dummy_int;
- VEC (tree, heap) *dummy_vec;
-- bool op0_ok, op1_ok;
-+ bool op1_ok;
-
- if (!is_gimple_assign (last_stmt))
- return NULL;
-@@ -511,38 +526,23 @@
- return NULL;
-
- /* Check argument 0. */
-- op0_ok = widened_name_p (oprnd0, last_stmt, &half_type0, &def_stmt0, false);
-+ if (!widened_name_p (oprnd0, last_stmt, &half_type0, &def_stmt0, false))
-+ return NULL;
- /* Check argument 1. */
- op1_ok = widened_name_p (oprnd1, last_stmt, &half_type1, &def_stmt1, false);
-
-- /* In case of multiplication by a constant one of the operands may not match
-- the pattern, but not both. */
-- if (!op0_ok && !op1_ok)
-- return NULL;
--
-- if (op0_ok && op1_ok)
-+ if (op1_ok)
- {
- oprnd0 = gimple_assign_rhs1 (def_stmt0);
- oprnd1 = gimple_assign_rhs1 (def_stmt1);
- }
-- else if (!op0_ok)
-- {
-- if (TREE_CODE (oprnd0) == INTEGER_CST
-- && TREE_CODE (half_type1) == INTEGER_TYPE
-- && vect_handle_widen_mult_by_const (last_stmt, oprnd0, &oprnd1,
-- stmts, type,
-- &half_type1, def_stmt1))
-- half_type0 = half_type1;
-- else
-- return NULL;
-- }
-- else if (!op1_ok)
-+ else
- {
- if (TREE_CODE (oprnd1) == INTEGER_CST
- && TREE_CODE (half_type0) == INTEGER_TYPE
-- && vect_handle_widen_mult_by_const (last_stmt, oprnd1, &oprnd0,
-- stmts, type,
-- &half_type0, def_stmt0))
-+ && vect_handle_widen_op_by_const (last_stmt, MULT_EXPR, oprnd1,
-+ &oprnd0, stmts, type,
-+ &half_type0, def_stmt0))
- half_type1 = half_type0;
- else
- return NULL;
-@@ -998,6 +998,7 @@
- || TREE_TYPE (gimple_assign_lhs (new_stmt)) != interm_type)
- return false;
-
-+ VEC_safe_push (gimple, heap, *stmts, def_stmt);
- oprnd = gimple_assign_lhs (new_stmt);
- }
- else
-@@ -1128,7 +1129,7 @@
- statetments, except for the case when the last statement in the
- sequence doesn't have a corresponding pattern statement. In such
- case we associate the last pattern statement with the last statement
-- in the sequence. Therefore, we only add an original statetement to
-+ in the sequence. Therefore, we only add the original statement to
- the list if we know that it is not the last. */
- if (prev_stmt)
- VEC_safe_push (gimple, heap, *stmts, prev_stmt);
-@@ -1215,6 +1216,231 @@
- }
-
-
-+/* Detect widening shift pattern:
-+
-+ type a_t;
-+ TYPE a_T, res_T;
-+
-+ S1 a_t = ;
-+ S2 a_T = (TYPE) a_t;
-+ S3 res_T = a_T << CONST;
-+
-+ where type 'TYPE' is at least double the size of type 'type'.
-+
-+ Also detect unsigned cases:
-+
-+ unsigned type a_t;
-+ unsigned TYPE u_res_T;
-+ TYPE a_T, res_T;
-+
-+ S1 a_t = ;
-+ S2 a_T = (TYPE) a_t;
-+ S3 res_T = a_T << CONST;
-+ S4 u_res_T = (unsigned TYPE) res_T;
-+
-+ And a case when 'TYPE' is 4 times bigger than 'type'. In that case we
-+ create an additional pattern stmt for S2 to create a variable of an
-+ intermediate type, and perform widen-shift on the intermediate type:
-+
-+ type a_t;
-+ interm_type a_it;
-+ TYPE a_T, res_T, res_T';
-+
-+ S1 a_t = ;
-+ S2 a_T = (TYPE) a_t;
-+ '--> a_it = (interm_type) a_t;
-+ S3 res_T = a_T << CONST;
-+ '--> res_T' = a_it <<* CONST;
-+
-+ Input/Output:
-+
-+ * STMTS: Contains a stmt from which the pattern search begins.
-+ In case of unsigned widen-shift, the original stmt (S3) is replaced with S4
-+ in STMTS. When an intermediate type is used and a pattern statement is
-+ created for S2, we also put S2 here (before S3).
-+
-+ Output:
-+
-+ * TYPE_IN: The type of the input arguments to the pattern.
-+
-+ * TYPE_OUT: The type of the output of this pattern.
-+
-+ * Return value: A new stmt that will be used to replace the sequence of
-+ stmts that constitute the pattern. In this case it will be:
-+ WIDEN_LSHIFT_EXPR <a_t, CONST>. */
-+
-+static gimple
-+vect_recog_widen_shift_pattern (VEC (gimple, heap) **stmts,
-+ tree *type_in, tree *type_out)
-+{
-+ gimple last_stmt = VEC_pop (gimple, *stmts);
-+ gimple def_stmt0;
-+ tree oprnd0, oprnd1;
-+ tree type, half_type0;
-+ gimple pattern_stmt, orig_stmt = NULL;
-+ tree vectype, vectype_out = NULL_TREE;
-+ tree dummy;
-+ tree var;
-+ enum tree_code dummy_code;
-+ int dummy_int;
-+ VEC (tree, heap) * dummy_vec;
-+ gimple use_stmt = NULL;
-+ bool over_widen = false;
-+
-+ if (!is_gimple_assign (last_stmt) || !vinfo_for_stmt (last_stmt))
-+ return NULL;
-+
-+ orig_stmt = last_stmt;
-+ if (STMT_VINFO_IN_PATTERN_P (vinfo_for_stmt (last_stmt)))
-+ {
-+ /* This statement was also detected as over-widening operation (it can't
-+ be any other pattern, because only over-widening detects shifts).
-+ LAST_STMT is the final type demotion statement, but its related
-+ statement is shift. We analyze the related statement to catch cases:
-+
-+ orig code:
-+ type a_t;
-+ itype res;
-+ TYPE a_T, res_T;
-+
-+ S1 a_T = (TYPE) a_t;
-+ S2 res_T = a_T << CONST;
-+ S3 res = (itype)res_T;
-+
-+ (size of type * 2 <= size of itype
-+ and size of itype * 2 <= size of TYPE)
-+
-+ code after over-widening pattern detection:
-+
-+ S1 a_T = (TYPE) a_t;
-+ --> a_it = (itype) a_t;
-+ S2 res_T = a_T << CONST;
-+ S3 res = (itype)res_T; <--- LAST_STMT
-+ --> res = a_it << CONST;
-+
-+ after widen_shift:
-+
-+ S1 a_T = (TYPE) a_t;
-+ --> a_it = (itype) a_t; - redundant
-+ S2 res_T = a_T << CONST;
-+ S3 res = (itype)res_T;
-+ --> res = a_t w<< CONST;
-+
-+ i.e., we replace the three statements with res = a_t w<< CONST. */
-+ last_stmt = STMT_VINFO_RELATED_STMT (vinfo_for_stmt (last_stmt));
-+ over_widen = true;
-+ }
-+
-+ if (gimple_assign_rhs_code (last_stmt) != LSHIFT_EXPR)
-+ return NULL;
-+
-+ oprnd0 = gimple_assign_rhs1 (last_stmt);
-+ oprnd1 = gimple_assign_rhs2 (last_stmt);
-+ if (TREE_CODE (oprnd0) != SSA_NAME || TREE_CODE (oprnd1) != INTEGER_CST)
-+ return NULL;
-+
-+ /* Check operand 0: it has to be defined by a type promotion. */
-+ if (!widened_name_p (oprnd0, last_stmt, &half_type0, &def_stmt0, false))
-+ return NULL;
-+
-+ /* Check operand 1: has to be positive. We check that it fits the type
-+ in vect_handle_widen_op_by_const (). */
-+ if (tree_int_cst_compare (oprnd1, size_zero_node) <= 0)
-+ return NULL;
-+
-+ oprnd0 = gimple_assign_rhs1 (def_stmt0);
-+ type = gimple_expr_type (last_stmt);
-+
-+ /* Check if this a widening operation. */
-+ if (!vect_handle_widen_op_by_const (last_stmt, LSHIFT_EXPR, oprnd1,
-+ &oprnd0, stmts,
-+ type, &half_type0, def_stmt0))
-+ return NULL;
-+
-+ /* Handle unsigned case. Look for
-+ S4 u_res_T = (unsigned TYPE) res_T;
-+ Use unsigned TYPE as the type for WIDEN_LSHIFT_EXPR. */
-+ if (TYPE_UNSIGNED (type) != TYPE_UNSIGNED (half_type0))
-+ {
-+ tree lhs = gimple_assign_lhs (last_stmt), use_lhs;
-+ imm_use_iterator imm_iter;
-+ use_operand_p use_p;
-+ int nuses = 0;
-+ tree use_type;
-+
-+ if (over_widen)
-+ {
-+ /* In case of over-widening pattern, S4 should be ORIG_STMT itself.
-+ We check here that TYPE is the correct type for the operation,
-+ i.e., it's the type of the original result. */
-+ tree orig_type = gimple_expr_type (orig_stmt);
-+ if ((TYPE_UNSIGNED (type) != TYPE_UNSIGNED (orig_type))
-+ || (TYPE_PRECISION (type) != TYPE_PRECISION (orig_type)))
-+ return NULL;
-+ }
-+ else
-+ {
-+ FOR_EACH_IMM_USE_FAST (use_p, imm_iter, lhs)
-+ {
-+ if (is_gimple_debug (USE_STMT (use_p)))
-+ continue;
-+ use_stmt = USE_STMT (use_p);
-+ nuses++;
-+ }
-+
-+ if (nuses != 1 || !is_gimple_assign (use_stmt)
-+ || !CONVERT_EXPR_CODE_P (gimple_assign_rhs_code (use_stmt)))
-+ return NULL;
-+
-+ use_lhs = gimple_assign_lhs (use_stmt);
-+ use_type = TREE_TYPE (use_lhs);
-+
-+ if (!INTEGRAL_TYPE_P (use_type)
-+ || (TYPE_UNSIGNED (type) == TYPE_UNSIGNED (use_type))
-+ || (TYPE_PRECISION (type) != TYPE_PRECISION (use_type)))
-+ return NULL;
-+
-+ type = use_type;
-+ }
-+ }
-+
-+ /* Pattern detected. */
-+ if (vect_print_dump_info (REPORT_DETAILS))
-+ fprintf (vect_dump, "vect_recog_widen_shift_pattern: detected: ");
-+
-+ /* Check target support. */
-+ vectype = get_vectype_for_scalar_type (half_type0);
-+ vectype_out = get_vectype_for_scalar_type (type);
-+
-+ if (!vectype
-+ || !vectype_out
-+ || !supportable_widening_operation (WIDEN_LSHIFT_EXPR, last_stmt,
-+ vectype_out, vectype,
-+ &dummy, &dummy, &dummy_code,
-+ &dummy_code, &dummy_int,
-+ &dummy_vec))
-+ return NULL;
-+
-+ *type_in = vectype;
-+ *type_out = vectype_out;
-+
-+ /* Pattern supported. Create a stmt to be used to replace the pattern. */
-+ var = vect_recog_temp_ssa_var (type, NULL);
-+ pattern_stmt =
-+ gimple_build_assign_with_ops (WIDEN_LSHIFT_EXPR, var, oprnd0, oprnd1);
-+
-+ if (vect_print_dump_info (REPORT_DETAILS))
-+ print_gimple_stmt (vect_dump, pattern_stmt, 0, TDF_SLIM);
-+
-+ if (use_stmt)
-+ last_stmt = use_stmt;
-+ else
-+ last_stmt = orig_stmt;
-+
-+ VEC_safe_push (gimple, heap, *stmts, last_stmt);
-+ return pattern_stmt;
-+}
-+
- /* Mark statements that are involved in a pattern. */
-
- static inline void
-@@ -1278,7 +1504,8 @@
- static void
- vect_pattern_recog_1 (
- gimple (* vect_recog_func) (VEC (gimple, heap) **, tree *, tree *),
-- gimple_stmt_iterator si)
-+ gimple_stmt_iterator si,
-+ VEC (gimple, heap) **stmts_to_replace)
- {
- gimple stmt = gsi_stmt (si), pattern_stmt;
- stmt_vec_info stmt_info;
-@@ -1288,14 +1515,14 @@
- enum tree_code code;
- int i;
- gimple next;
-- VEC (gimple, heap) *stmts_to_replace = VEC_alloc (gimple, heap, 1);
-
-- VEC_quick_push (gimple, stmts_to_replace, stmt);
-- pattern_stmt = (* vect_recog_func) (&stmts_to_replace, &type_in, &type_out);
-+ VEC_truncate (gimple, *stmts_to_replace, 0);
-+ VEC_quick_push (gimple, *stmts_to_replace, stmt);
-+ pattern_stmt = (* vect_recog_func) (stmts_to_replace, &type_in, &type_out);
- if (!pattern_stmt)
- return;
-
-- stmt = VEC_last (gimple, stmts_to_replace);
-+ stmt = VEC_last (gimple, *stmts_to_replace);
- stmt_info = vinfo_for_stmt (stmt);
- loop_vinfo = STMT_VINFO_LOOP_VINFO (stmt_info);
-
-@@ -1303,8 +1530,6 @@
- {
- /* No need to check target support (already checked by the pattern
- recognition function). */
-- if (type_out)
-- gcc_assert (VECTOR_MODE_P (TYPE_MODE (type_out)));
- pattern_vectype = type_out ? type_out : type_in;
- }
- else
-@@ -1360,8 +1585,8 @@
- /* It is possible that additional pattern stmts are created and inserted in
- STMTS_TO_REPLACE. We create a stmt_info for each of them, and mark the
- relevant statements. */
-- for (i = 0; VEC_iterate (gimple, stmts_to_replace, i, stmt)
-- && (unsigned) i < (VEC_length (gimple, stmts_to_replace) - 1);
-+ for (i = 0; VEC_iterate (gimple, *stmts_to_replace, i, stmt)
-+ && (unsigned) i < (VEC_length (gimple, *stmts_to_replace) - 1);
- i++)
- {
- stmt_info = vinfo_for_stmt (stmt);
-@@ -1374,8 +1599,6 @@
-
- vect_mark_pattern_stmts (stmt, pattern_stmt, NULL_TREE);
- }
--
-- VEC_free (gimple, heap, stmts_to_replace);
- }
-
-
-@@ -1465,6 +1688,7 @@
- gimple_stmt_iterator si;
- unsigned int i, j;
- gimple (* vect_recog_func_ptr) (VEC (gimple, heap) **, tree *, tree *);
-+ VEC (gimple, heap) *stmts_to_replace = VEC_alloc (gimple, heap, 1);
-
- if (vect_print_dump_info (REPORT_DETAILS))
- fprintf (vect_dump, "=== vect_pattern_recog ===");
-@@ -1480,8 +1704,11 @@
- for (j = 0; j < NUM_PATTERNS; j++)
- {
- vect_recog_func_ptr = vect_vect_recog_func_ptrs[j];
-- vect_pattern_recog_1 (vect_recog_func_ptr, si);
-+ vect_pattern_recog_1 (vect_recog_func_ptr, si,
-+ &stmts_to_replace);
- }
- }
- }
-+
-+ VEC_free (gimple, heap, stmts_to_replace);
- }
-
-=== modified file 'gcc/tree-vect-slp.c'
---- old/gcc/tree-vect-slp.c 2011-10-23 11:29:25 +0000
-+++ new/gcc/tree-vect-slp.c 2011-10-27 11:27:59 +0000
-@@ -480,6 +480,11 @@
- }
- }
- }
-+ else if (rhs_code == WIDEN_LSHIFT_EXPR)
-+ {
-+ need_same_oprnds = true;
-+ first_op1 = gimple_assign_rhs2 (stmt);
-+ }
- }
- else
- {
-
-=== modified file 'gcc/tree-vect-stmts.c'
---- old/gcc/tree-vect-stmts.c 2011-10-23 11:29:25 +0000
-+++ new/gcc/tree-vect-stmts.c 2011-10-27 11:27:59 +0000
-@@ -3359,6 +3359,7 @@
- VEC (tree, heap) *vec_oprnds0 = NULL, *vec_oprnds1 = NULL;
- VEC (tree, heap) *vec_dsts = NULL, *interm_types = NULL, *tmp_vec_dsts = NULL;
- bb_vec_info bb_vinfo = STMT_VINFO_BB_VINFO (stmt_info);
-+ unsigned int k;
-
- if (!STMT_VINFO_RELEVANT_P (stmt_info) && !bb_vinfo)
- return false;
-@@ -3375,7 +3376,8 @@
-
- code = gimple_assign_rhs_code (stmt);
- if (!CONVERT_EXPR_CODE_P (code)
-- && code != WIDEN_MULT_EXPR)
-+ && code != WIDEN_MULT_EXPR
-+ && code != WIDEN_LSHIFT_EXPR)
- return false;
-
- scalar_dest = gimple_assign_lhs (stmt);
-@@ -3403,7 +3405,7 @@
- bool ok;
-
- op1 = gimple_assign_rhs2 (stmt);
-- if (code == WIDEN_MULT_EXPR)
-+ if (code == WIDEN_MULT_EXPR || code == WIDEN_LSHIFT_EXPR)
- {
- /* For WIDEN_MULT_EXPR, if OP0 is a constant, use the type of
- OP1. */
-@@ -3480,7 +3482,7 @@
- fprintf (vect_dump, "transform type promotion operation. ncopies = %d.",
- ncopies);
-
-- if (code == WIDEN_MULT_EXPR)
-+ if (code == WIDEN_MULT_EXPR || code == WIDEN_LSHIFT_EXPR)
- {
- if (CONSTANT_CLASS_P (op0))
- op0 = fold_convert (TREE_TYPE (op1), op0);
-@@ -3521,6 +3523,8 @@
- if (op_type == binary_op)
- vec_oprnds1 = VEC_alloc (tree, heap, 1);
- }
-+ else if (code == WIDEN_LSHIFT_EXPR)
-+ vec_oprnds1 = VEC_alloc (tree, heap, slp_node->vec_stmts_size);
-
- /* In case the vectorization factor (VF) is bigger than the number
- of elements that we can fit in a vectype (nunits), we have to generate
-@@ -3534,15 +3538,33 @@
- if (j == 0)
- {
- if (slp_node)
-- vect_get_slp_defs (op0, op1, slp_node, &vec_oprnds0,
-- &vec_oprnds1, -1);
-- else
-+ {
-+ if (code == WIDEN_LSHIFT_EXPR)
-+ {
-+ vec_oprnd1 = op1;
-+ /* Store vec_oprnd1 for every vector stmt to be created
-+ for SLP_NODE. We check during the analysis that all
-+ the shift arguments are the same. */
-+ for (k = 0; k < slp_node->vec_stmts_size - 1; k++)
-+ VEC_quick_push (tree, vec_oprnds1, vec_oprnd1);
-+
-+ vect_get_slp_defs (op0, NULL_TREE, slp_node, &vec_oprnds0, NULL,
-+ -1);
-+ }
-+ else
-+ vect_get_slp_defs (op0, op1, slp_node, &vec_oprnds0,
-+ &vec_oprnds1, -1);
-+ }
-+ else
- {
- vec_oprnd0 = vect_get_vec_def_for_operand (op0, stmt, NULL);
- VEC_quick_push (tree, vec_oprnds0, vec_oprnd0);
- if (op_type == binary_op)
- {
-- vec_oprnd1 = vect_get_vec_def_for_operand (op1, stmt, NULL);
-+ if (code == WIDEN_LSHIFT_EXPR)
-+ vec_oprnd1 = op1;
-+ else
-+ vec_oprnd1 = vect_get_vec_def_for_operand (op1, stmt, NULL);
- VEC_quick_push (tree, vec_oprnds1, vec_oprnd1);
- }
- }
-@@ -3553,7 +3575,10 @@
- VEC_replace (tree, vec_oprnds0, 0, vec_oprnd0);
- if (op_type == binary_op)
- {
-- vec_oprnd1 = vect_get_vec_def_for_stmt_copy (dt[1], vec_oprnd1);
-+ if (code == WIDEN_LSHIFT_EXPR)
-+ vec_oprnd1 = op1;
-+ else
-+ vec_oprnd1 = vect_get_vec_def_for_stmt_copy (dt[1], vec_oprnd1);
- VEC_replace (tree, vec_oprnds1, 0, vec_oprnd1);
- }
- }
-@@ -5853,6 +5878,19 @@
- }
- break;
-
-+ case WIDEN_LSHIFT_EXPR:
-+ if (BYTES_BIG_ENDIAN)
-+ {
-+ c1 = VEC_WIDEN_LSHIFT_HI_EXPR;
-+ c2 = VEC_WIDEN_LSHIFT_LO_EXPR;
-+ }
-+ else
-+ {
-+ c2 = VEC_WIDEN_LSHIFT_HI_EXPR;
-+ c1 = VEC_WIDEN_LSHIFT_LO_EXPR;
-+ }
-+ break;
-+
- CASE_CONVERT:
- if (BYTES_BIG_ENDIAN)
- {
-
-=== modified file 'gcc/tree-vectorizer.h'
---- old/gcc/tree-vectorizer.h 2011-09-05 06:23:37 +0000
-+++ new/gcc/tree-vectorizer.h 2011-10-23 13:33:07 +0000
-@@ -896,7 +896,7 @@
- Additional pattern recognition functions can (and will) be added
- in the future. */
- typedef gimple (* vect_recog_func_ptr) (VEC (gimple, heap) **, tree *, tree *);
--#define NUM_PATTERNS 5
-+#define NUM_PATTERNS 6
- void vect_pattern_recog (loop_vec_info);
-
- /* In tree-vectorizer.c. */
-
-=== modified file 'gcc/tree.def'
---- old/gcc/tree.def 2011-01-21 14:14:12 +0000
-+++ new/gcc/tree.def 2011-10-23 13:33:07 +0000
-@@ -1092,6 +1092,19 @@
- is subtracted from t3. */
- DEFTREECODE (WIDEN_MULT_MINUS_EXPR, "widen_mult_minus_expr", tcc_expression, 3)
-
-+/* Widening shift left.
-+ The first operand is of type t1.
-+ The second operand is the number of bits to shift by; it need not be the
-+ same type as the first operand and result.
-+ Note that the result is undefined if the second operand is larger
-+ than or equal to the first operand's type size.
-+ The type of the entire expression is t2, such that t2 is at least twice
-+ the size of t1.
-+ WIDEN_LSHIFT_EXPR is equivalent to first widening (promoting)
-+ the first argument from type t1 to type t2, and then shifting it
-+ by the second argument. */
-+DEFTREECODE (WIDEN_LSHIFT_EXPR, "widen_lshift_expr", tcc_binary, 2)
-+
- /* Fused multiply-add.
- All operands and the result are of the same type. No intermediate
- rounding is performed after multiplying operand one with operand two
-@@ -1147,6 +1160,16 @@
- DEFTREECODE (VEC_INTERLEAVE_HIGH_EXPR, "vec_interleavehigh_expr", tcc_binary, 2)
- DEFTREECODE (VEC_INTERLEAVE_LOW_EXPR, "vec_interleavelow_expr", tcc_binary, 2)
-
-+/* Widening vector shift left in bits.
-+ Operand 0 is a vector to be shifted with N elements of size S.
-+ Operand 1 is an integer shift amount in bits.
-+ The result of the operation is N elements of size 2*S.
-+ VEC_WIDEN_LSHIFT_HI_EXPR computes the N/2 high results.
-+ VEC_WIDEN_LSHIFT_LO_EXPR computes the N/2 low results.
-+ */
-+DEFTREECODE (VEC_WIDEN_LSHIFT_HI_EXPR, "widen_lshift_hi_expr", tcc_binary, 2)
-+DEFTREECODE (VEC_WIDEN_LSHIFT_LO_EXPR, "widen_lshift_lo_expr", tcc_binary, 2)
-+
- /* PREDICT_EXPR. Specify hint for branch prediction. The
- PREDICT_EXPR_PREDICTOR specify predictor and PREDICT_EXPR_OUTCOME the
- outcome (0 for not taken and 1 for taken). Once the profile is guessed
-