Commit 383d9c83 by Ira Rosen Committed by Ira Rosen

tree-vectorizer.h (vect_recog_func_ptr): Make last argument to be a pointer.


        * tree-vectorizer.h (vect_recog_func_ptr): Make last argument to
        be a pointer.
        * tree-vect-patterns.c (vect_recog_widen_sum_pattern,
        vect_recog_widen_mult_pattern, vect_recog_dot_prod_pattern,
        vect_recog_pow_pattern): Likewise.
        (vect_pattern_recog_1): Remove declaration.
        (widened_name_p): Remove declaration.  Add new argument to
        specify whether to check that both types are either signed or
        unsigned.
        (vect_recog_widen_mult_pattern): Update documentation.  Handle
        unsigned patterns and multiplication by constants.
        (vect_pattern_recog_1): Update vect_recog_func references.  Use
        statement information from the statement returned from pattern
        detection functions.
        (vect_pattern_recog): Update vect_recog_func reference.
        * tree-vect-stmts.c (vectorizable_type_promotion): For widening
        multiplication by a constant use the type of the other operand.

From-SVN: r174735
parent f527cc50
2011-06-07 Ira Rosen <ira.rosen@linaro.org>
* tree-vectorizer.h (vect_recog_func_ptr): Make last argument to be
a pointer.
* tree-vect-patterns.c (vect_recog_widen_sum_pattern,
vect_recog_widen_mult_pattern, vect_recog_dot_prod_pattern,
vect_recog_pow_pattern): Likewise.
(vect_pattern_recog_1): Remove declaration.
(widened_name_p): Remove declaration. Add new argument to specify
whether to check that both types are either signed or unsigned.
(vect_recog_widen_mult_pattern): Update documentation. Handle
unsigned patterns and multiplication by constants.
(vect_pattern_recog_1): Update vect_recog_func references. Use
statement information from the statement returned from pattern
detection functions.
(vect_pattern_recog): Update vect_recog_func reference.
* tree-vect-stmts.c (vectorizable_type_promotion): For widening
multiplication by a constant use the type of the other operand.
2011-06-06 Richard Sandiford <rdsandiford@googlemail.com> 2011-06-06 Richard Sandiford <rdsandiford@googlemail.com>
PR rtl-optimization/49145 PR rtl-optimization/49145
......
2011-06-07 Ira Rosen <ira.rosen@linaro.org>
* lib/target-supports.exp
(check_effective_target_vect_widen_mult_qi_to_hi):
Add NEON as supporting target.
(check_effective_target_vect_widen_mult_hi_to_si): Likewise.
(check_effective_target_vect_widen_mult_qi_to_hi_pattern): New.
(check_effective_target_vect_widen_mult_hi_to_si_pattern): New.
* gcc.dg/vect/vect-widen-mult-u8.c: Expect to be vectorized
using widening multiplication on targets that support it.
* gcc.dg/vect/vect-widen-mult-u16.c: Likewise.
* gcc.dg/vect/vect-widen-mult-const-s16.c: New test.
* gcc.dg/vect/vect-widen-mult-const-u16.c: New test.
2011-06-06 Nicola Pero <nicola.pero@meta-innovation.com> 2011-06-06 Nicola Pero <nicola.pero@meta-innovation.com>
Updated all testcases in the ObjC/ObjC++ testsuites to use the Updated all testcases in the ObjC/ObjC++ testsuites to use the
......
/* { dg-require-effective-target vect_int } */
#include "tree-vect.h"
#include <stdlib.h>
#define N 32
__attribute__ ((noinline)) void
foo (int *__restrict a,
short *__restrict b,
int n)
{
int i;
for (i = 0; i < n; i++)
a[i] = b[i] * 2333;
for (i = 0; i < n; i++)
if (a[i] != b[i] * 2333)
abort ();
}
__attribute__ ((noinline)) void
bar (int *__restrict a,
short *__restrict b,
int n)
{
int i;
for (i = 0; i < n; i++)
a[i] = b[i] * (short) 2333;
for (i = 0; i < n; i++)
if (a[i] != b[i] * (short) 2333)
abort ();
}
int main (void)
{
int i;
int a[N];
short b[N];
for (i = 0; i < N; i++)
{
a[i] = 0;
b[i] = i;
__asm__ volatile ("");
}
foo (a, b, N);
bar (a, b, N);
return 0;
}
/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 2 "vect" { target vect_widen_mult_hi_to_si } } } */
/* { dg-final { scan-tree-dump-times "vect_recog_widen_mult_pattern: detected" 2 "vect" { target vect_widen_mult_hi_to_si_pattern } } } */
/* { dg-final { scan-tree-dump-times "pattern recognized" 2 "vect" { target vect_widen_mult_hi_to_si_pattern } } } */
/* { dg-final { cleanup-tree-dump "vect" } } */
/* { dg-require-effective-target vect_int } */
#include "tree-vect.h"
#include <stdlib.h>
#define N 32
__attribute__ ((noinline)) void
foo (unsigned int *__restrict a,
unsigned short *__restrict b,
int n)
{
int i;
for (i = 0; i < n; i++)
a[i] = b[i] * 2333;
for (i = 0; i < n; i++)
if (a[i] != b[i] * 2333)
abort ();
}
__attribute__ ((noinline)) void
bar (unsigned int *__restrict a,
unsigned short *__restrict b,
int n)
{
int i;
for (i = 0; i < n; i++)
a[i] = (unsigned short) 2333 * b[i];
for (i = 0; i < n; i++)
if (a[i] != b[i] * (unsigned short) 2333)
abort ();
}
__attribute__ ((noinline)) void
baz (unsigned int *__restrict a,
unsigned short *__restrict b,
int n)
{
int i;
for (i = 0; i < n; i++)
a[i] = b[i] * 233333333;
for (i = 0; i < n; i++)
if (a[i] != b[i] * 233333333)
abort ();
}
int main (void)
{
int i;
unsigned int a[N];
unsigned short b[N];
for (i = 0; i < N; i++)
{
a[i] = 0;
b[i] = i;
__asm__ volatile ("");
}
foo (a, b, N);
bar (a, b, N);
baz (a, b, N);
return 0;
}
/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 3 "vect" { target vect_widen_mult_hi_to_si } } } */
/* { dg-final { scan-tree-dump-times "vect_recog_widen_mult_pattern: detected" 2 "vect" { target vect_widen_mult_hi_to_si_pattern } } } */
/* { dg-final { scan-tree-dump-times "pattern recognized" 2 "vect" { target vect_widen_mult_hi_to_si_pattern } } } */
/* { dg-final { cleanup-tree-dump "vect" } } */
...@@ -9,13 +9,11 @@ unsigned short X[N] __attribute__ ((__aligned__(__BIGGEST_ALIGNMENT__))); ...@@ -9,13 +9,11 @@ unsigned short X[N] __attribute__ ((__aligned__(__BIGGEST_ALIGNMENT__)));
unsigned short Y[N] __attribute__ ((__aligned__(__BIGGEST_ALIGNMENT__))); unsigned short Y[N] __attribute__ ((__aligned__(__BIGGEST_ALIGNMENT__)));
unsigned int result[N]; unsigned int result[N];
/* short->int widening-mult */ /* unsigned short->unsigned int widening-mult. */
__attribute__ ((noinline)) int __attribute__ ((noinline)) int
foo1(int len) { foo1(int len) {
int i; int i;
/* Not vectorized because X[i] and Y[i] are casted to 'int'
so the widening multiplication pattern is not recognized. */
for (i=0; i<len; i++) { for (i=0; i<len; i++) {
result[i] = (unsigned int)(X[i] * Y[i]); result[i] = (unsigned int)(X[i] * Y[i]);
} }
...@@ -43,8 +41,8 @@ int main (void) ...@@ -43,8 +41,8 @@ int main (void)
return 0; return 0;
} }
/*The induction loop is vectorized */ /* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" { target { vect_widen_mult_hi_to_si || vect_unpack } } } } */
/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 2 "vect" { xfail *-*-* } } } */ /* { dg-final { scan-tree-dump-times "vect_recog_widen_mult_pattern: detected" 1 "vect" { target vect_widen_mult_hi_to_si_pattern } } } */
/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" { target vect_pack_trunc } } } */ /* { dg-final { scan-tree-dump-times "pattern recognized" 1 "vect" { target vect_widen_mult_hi_to_si_pattern } } } */
/* { dg-final { cleanup-tree-dump "vect" } } */ /* { dg-final { cleanup-tree-dump "vect" } } */
...@@ -9,7 +9,7 @@ unsigned char X[N] __attribute__ ((__aligned__(__BIGGEST_ALIGNMENT__))); ...@@ -9,7 +9,7 @@ unsigned char X[N] __attribute__ ((__aligned__(__BIGGEST_ALIGNMENT__)));
unsigned char Y[N] __attribute__ ((__aligned__(__BIGGEST_ALIGNMENT__))); unsigned char Y[N] __attribute__ ((__aligned__(__BIGGEST_ALIGNMENT__)));
unsigned short result[N]; unsigned short result[N];
/* char->short widening-mult */ /* unsigned char-> unsigned short widening-mult. */
__attribute__ ((noinline)) int __attribute__ ((noinline)) int
foo1(int len) { foo1(int len) {
int i; int i;
...@@ -28,8 +28,7 @@ int main (void) ...@@ -28,8 +28,7 @@ int main (void)
for (i=0; i<N; i++) { for (i=0; i<N; i++) {
X[i] = i; X[i] = i;
Y[i] = 64-i; Y[i] = 64-i;
if (i%4 == 0) __asm__ volatile ("");
X[i] = 5;
} }
foo1 (N); foo1 (N);
...@@ -43,5 +42,7 @@ int main (void) ...@@ -43,5 +42,7 @@ int main (void)
} }
/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" { target { vect_widen_mult_qi_to_hi || vect_unpack } } } } */ /* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" { target { vect_widen_mult_qi_to_hi || vect_unpack } } } } */
/* { dg-final { scan-tree-dump-times "vect_recog_widen_mult_pattern: detected" 1 "vect" { target vect_widen_mult_qi_to_hi_pattern } } } */
/* { dg-final { scan-tree-dump-times "pattern recognized" 1 "vect" { target vect_widen_mult_qi_to_hi_pattern } } } */
/* { dg-final { cleanup-tree-dump "vect" } } */ /* { dg-final { cleanup-tree-dump "vect" } } */
...@@ -2668,7 +2668,8 @@ proc check_effective_target_vect_widen_mult_qi_to_hi { } { ...@@ -2668,7 +2668,8 @@ proc check_effective_target_vect_widen_mult_qi_to_hi { } {
} else { } else {
set et_vect_widen_mult_qi_to_hi_saved 0 set et_vect_widen_mult_qi_to_hi_saved 0
} }
if { [istarget powerpc*-*-*] } { if { [istarget powerpc*-*-*]
|| ([istarget arm*-*-*] && [check_effective_target_arm_neon]) } {
set et_vect_widen_mult_qi_to_hi_saved 1 set et_vect_widen_mult_qi_to_hi_saved 1
} }
} }
...@@ -2701,7 +2702,8 @@ proc check_effective_target_vect_widen_mult_hi_to_si { } { ...@@ -2701,7 +2702,8 @@ proc check_effective_target_vect_widen_mult_hi_to_si { } {
|| [istarget spu-*-*] || [istarget spu-*-*]
|| [istarget ia64-*-*] || [istarget ia64-*-*]
|| [istarget i?86-*-*] || [istarget i?86-*-*]
|| [istarget x86_64-*-*] } { || [istarget x86_64-*-*]
|| ([istarget arm*-*-*] && [check_effective_target_arm_neon]) } {
set et_vect_widen_mult_hi_to_si_saved 1 set et_vect_widen_mult_hi_to_si_saved 1
} }
} }
...@@ -2710,6 +2712,52 @@ proc check_effective_target_vect_widen_mult_hi_to_si { } { ...@@ -2710,6 +2712,52 @@ proc check_effective_target_vect_widen_mult_hi_to_si { } {
} }
# Return 1 if the target plus current options supports a vector # Return 1 if the target plus current options supports a vector
# widening multiplication of *char* args into *short* result, 0 otherwise.
#
# This won't change for different subtargets so cache the result.
proc check_effective_target_vect_widen_mult_qi_to_hi_pattern { } {
global et_vect_widen_mult_qi_to_hi_pattern
if [info exists et_vect_widen_mult_qi_to_hi_pattern_saved] {
verbose "check_effective_target_vect_widen_mult_qi_to_hi_pattern: using cached result" 2
} else {
set et_vect_widen_mult_qi_to_hi_pattern_saved 0
if { [istarget powerpc*-*-*]
|| ([istarget arm*-*-*] && [check_effective_target_arm_neon]) } {
set et_vect_widen_mult_qi_to_hi_pattern_saved 1
}
}
verbose "check_effective_target_vect_widen_mult_qi_to_hi_pattern: returning $et_vect_widen_mult_qi_to_hi_pattern_saved" 2
return $et_vect_widen_mult_qi_to_hi_pattern_saved
}
# Return 1 if the target plus current options supports a vector
# widening multiplication of *short* args into *int* result, 0 otherwise.
#
# This won't change for different subtargets so cache the result.
proc check_effective_target_vect_widen_mult_hi_to_si_pattern { } {
global et_vect_widen_mult_hi_to_si_pattern
if [info exists et_vect_widen_mult_hi_to_si_pattern_saved] {
verbose "check_effective_target_vect_widen_mult_hi_to_si_pattern: using cached result" 2
} else {
set et_vect_widen_mult_hi_to_si_pattern_saved 0
if { [istarget powerpc*-*-*]
|| [istarget spu-*-*]
|| [istarget ia64-*-*]
|| [istarget i?86-*-*]
|| [istarget x86_64-*-*]
|| ([istarget arm*-*-*] && [check_effective_target_arm_neon]) } {
set et_vect_widen_mult_hi_to_si_pattern_saved 1
}
}
verbose "check_effective_target_vect_widen_mult_hi_to_si_pattern: returning $et_vect_widen_mult_hi_to_si_pattern_saved" 2
return $et_vect_widen_mult_hi_to_si_pattern_saved
}
# Return 1 if the target plus current options supports a vector
# dot-product of signed chars, 0 otherwise. # dot-product of signed chars, 0 otherwise.
# #
# This won't change for different subtargets so cache the result. # This won't change for different subtargets so cache the result.
......
...@@ -3232,6 +3232,33 @@ vectorizable_type_promotion (gimple stmt, gimple_stmt_iterator *gsi, ...@@ -3232,6 +3232,33 @@ vectorizable_type_promotion (gimple stmt, gimple_stmt_iterator *gsi,
fprintf (vect_dump, "use not simple."); fprintf (vect_dump, "use not simple.");
return false; return false;
} }
op_type = TREE_CODE_LENGTH (code);
if (op_type == binary_op)
{
bool ok;
op1 = gimple_assign_rhs2 (stmt);
if (code == WIDEN_MULT_EXPR)
{
/* For WIDEN_MULT_EXPR, if OP0 is a constant, use the type of
OP1. */
if (CONSTANT_CLASS_P (op0))
ok = vect_is_simple_use_1 (op1, loop_vinfo, NULL,
&def_stmt, &def, &dt[1], &vectype_in);
else
ok = vect_is_simple_use (op1, loop_vinfo, NULL, &def_stmt, &def,
&dt[1]);
if (!ok)
{
if (vect_print_dump_info (REPORT_DETAILS))
fprintf (vect_dump, "use not simple.");
return false;
}
}
}
/* If op0 is an external or constant def use a vector type with /* If op0 is an external or constant def use a vector type with
the same size as the output vector type. */ the same size as the output vector type. */
if (!vectype_in) if (!vectype_in)
...@@ -3264,18 +3291,6 @@ vectorizable_type_promotion (gimple stmt, gimple_stmt_iterator *gsi, ...@@ -3264,18 +3291,6 @@ vectorizable_type_promotion (gimple stmt, gimple_stmt_iterator *gsi,
gcc_assert (ncopies >= 1); gcc_assert (ncopies >= 1);
op_type = TREE_CODE_LENGTH (code);
if (op_type == binary_op)
{
op1 = gimple_assign_rhs2 (stmt);
if (!vect_is_simple_use (op1, loop_vinfo, NULL, &def_stmt, &def, &dt[1]))
{
if (vect_print_dump_info (REPORT_DETAILS))
fprintf (vect_dump, "use not simple.");
return false;
}
}
/* Supportable by target? */ /* Supportable by target? */
if (!supportable_widening_operation (code, stmt, vectype_out, vectype_in, if (!supportable_widening_operation (code, stmt, vectype_out, vectype_in,
&decl1, &decl2, &code1, &code2, &decl1, &decl2, &code1, &code2,
...@@ -3301,6 +3316,14 @@ vectorizable_type_promotion (gimple stmt, gimple_stmt_iterator *gsi, ...@@ -3301,6 +3316,14 @@ vectorizable_type_promotion (gimple stmt, gimple_stmt_iterator *gsi,
fprintf (vect_dump, "transform type promotion operation. ncopies = %d.", fprintf (vect_dump, "transform type promotion operation. ncopies = %d.",
ncopies); ncopies);
if (code == WIDEN_MULT_EXPR)
{
if (CONSTANT_CLASS_P (op0))
op0 = fold_convert (TREE_TYPE (op1), op0);
else if (CONSTANT_CLASS_P (op1))
op1 = fold_convert (TREE_TYPE (op0), op1);
}
/* Handle def. */ /* Handle def. */
/* In case of multi-step promotion, we first generate promotion operations /* In case of multi-step promotion, we first generate promotion operations
to the intermediate types, and then from that types to the final one. to the intermediate types, and then from that types to the final one.
......
...@@ -896,7 +896,7 @@ extern void vect_slp_transform_bb (basic_block); ...@@ -896,7 +896,7 @@ extern void vect_slp_transform_bb (basic_block);
/* Pattern recognition functions. /* Pattern recognition functions.
Additional pattern recognition functions can (and will) be added Additional pattern recognition functions can (and will) be added
in the future. */ in the future. */
typedef gimple (* vect_recog_func_ptr) (gimple, tree *, tree *); typedef gimple (* vect_recog_func_ptr) (gimple *, tree *, tree *);
#define NUM_PATTERNS 4 #define NUM_PATTERNS 4
void vect_pattern_recog (loop_vec_info); void vect_pattern_recog (loop_vec_info);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment