re PR target/66144 (vector element operator produces very bad code)
[gcc] 2017-02-06 Michael Meissner <meissner@linux.vnet.ibm.com> PR target/66144 * config/rs6000/vector.md (vcond<mode><mode>): Allow the true and false values to be constant vectors with all 0 or all 1 bits set. (vcondu<mode><mode>): Likewise. * config/rs6000/predicates.md (vector_int_reg_or_same_bit): New predicate. (fpmask_comparison_operator): Update comment. (vecint_comparison_operator): New predicate. * config/rs6000/rs6000.c (rs6000_emit_vector_cond_expr): Optimize vector conditionals when the true and false values are constant vectors with all 0 bits or all 1 bits set. [gcc/testsuite] 2017-02-06 Michael Meissner <meissner@linux.vnet.ibm.com> PR target/66144 * gcc.target/powerpc/pr66144-1.c: New test. * gcc.target/powerpc/pr66144-2.c: Likewise. * gcc.target/powerpc/pr66144-3.c: Likewise. From-SVN: r245222
This commit is contained in:
parent
e495e31a20
commit
391675acd2
8 changed files with 156 additions and 16 deletions
|
@ -1,3 +1,17 @@
|
|||
2017-02-06 Michael Meissner <meissner@linux.vnet.ibm.com>
|
||||
|
||||
PR target/66144
|
||||
* config/rs6000/vector.md (vcond<mode><mode>): Allow the true and
|
||||
false values to be constant vectors with all 0 or all 1 bits set.
|
||||
(vcondu<mode><mode>): Likewise.
|
||||
* config/rs6000/predicates.md (vector_int_reg_or_same_bit): New
|
||||
predicate.
|
||||
(fpmask_comparison_operator): Update comment.
|
||||
(vecint_comparison_operator): New predicate.
|
||||
* config/rs6000/rs6000.c (rs6000_emit_vector_cond_expr): Optimize
|
||||
vector conditionals when the true and false values are constant
|
||||
vectors with all 0 bits or all 1 bits set.
|
||||
|
||||
2017-02-06 Martin Sebor <msebor@redhat.com>
|
||||
|
||||
PR tree-optimization/79376
|
||||
|
|
|
@ -808,6 +808,21 @@
|
|||
(and (match_code "const_int,const_double,const_wide_int,const_vector")
|
||||
(match_test "op == CONSTM1_RTX (mode) && !FLOAT_MODE_P (mode)")))
|
||||
|
||||
;; Return 1 if operand is a vector int register or is either a vector constant
|
||||
;; of all 0 bits of a vector constant of all 1 bits.
|
||||
(define_predicate "vector_int_reg_or_same_bit"
|
||||
(match_code "reg,subreg,const_vector")
|
||||
{
|
||||
if (GET_MODE_CLASS (mode) != MODE_VECTOR_INT)
|
||||
return 0;
|
||||
|
||||
else if (REG_P (op) || SUBREG_P (op))
|
||||
return vint_operand (op, mode);
|
||||
|
||||
else
|
||||
return op == CONST0_RTX (mode) || op == CONSTM1_RTX (mode);
|
||||
})
|
||||
|
||||
;; Return 1 if operand is 0.0.
|
||||
(define_predicate "zero_fp_constant"
|
||||
(and (match_code "const_double")
|
||||
|
@ -1260,8 +1275,8 @@
|
|||
(and (match_operand 0 "branch_comparison_operator")
|
||||
(match_code "ne,le,ge,leu,geu,ordered")))
|
||||
|
||||
;; Return 1 if OP is a comparison operator suitable for vector/scalar
|
||||
;; comparisons that generate a -1/0 mask.
|
||||
;; Return 1 if OP is a comparison operator suitable for floating point
|
||||
;; vector/scalar comparisons that generate a -1/0 mask.
|
||||
(define_predicate "fpmask_comparison_operator"
|
||||
(match_code "eq,gt,ge"))
|
||||
|
||||
|
@ -1271,6 +1286,11 @@
|
|||
(define_predicate "invert_fpmask_comparison_operator"
|
||||
(match_code "ne,unlt,unle"))
|
||||
|
||||
;; Return 1 if OP is a comparison operation suitable for integer vector/scalar
|
||||
;; comparisons that generate a -1/0 mask.
|
||||
(define_predicate "vecint_comparison_operator"
|
||||
(match_code "eq,gt,gtu"))
|
||||
|
||||
;; Return 1 if OP is a comparison operation that is valid for a branch
|
||||
;; insn, which is true if the corresponding bit in the CC register is set.
|
||||
(define_predicate "branch_positive_comparison_operator"
|
||||
|
|
|
@ -25125,7 +25125,6 @@ rs6000_emit_vector_cond_expr (rtx dest, rtx op_true, rtx op_false,
|
|||
machine_mode cc_mode = CCmode;
|
||||
rtx mask;
|
||||
rtx cond2;
|
||||
rtx tmp;
|
||||
bool invert_move = false;
|
||||
|
||||
if (VECTOR_UNIT_NONE_P (dest_mode))
|
||||
|
@ -25170,12 +25169,44 @@ rs6000_emit_vector_cond_expr (rtx dest, rtx op_true, rtx op_false,
|
|||
return 0;
|
||||
|
||||
if (invert_move)
|
||||
std::swap (op_true, op_false);
|
||||
|
||||
/* Optimize vec1 == vec2, to know the mask generates -1/0. */
|
||||
if (GET_MODE_CLASS (dest_mode) == MODE_VECTOR_INT
|
||||
&& (GET_CODE (op_true) == CONST_VECTOR
|
||||
|| GET_CODE (op_false) == CONST_VECTOR))
|
||||
{
|
||||
tmp = op_true;
|
||||
op_true = op_false;
|
||||
op_false = tmp;
|
||||
rtx constant_0 = CONST0_RTX (dest_mode);
|
||||
rtx constant_m1 = CONSTM1_RTX (dest_mode);
|
||||
|
||||
if (op_true == constant_m1 && op_false == constant_0)
|
||||
{
|
||||
emit_move_insn (dest, mask);
|
||||
return 1;
|
||||
}
|
||||
|
||||
else if (op_true == constant_0 && op_false == constant_m1)
|
||||
{
|
||||
emit_insn (gen_rtx_SET (dest, gen_rtx_NOT (dest_mode, mask)));
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* If we can't use the vector comparison directly, perhaps we can use
|
||||
the mask for the true or false fields, instead of loading up a
|
||||
constant. */
|
||||
if (op_true == constant_m1)
|
||||
op_true = mask;
|
||||
|
||||
if (op_false == constant_0)
|
||||
op_false = mask;
|
||||
}
|
||||
|
||||
if (!REG_P (op_true) && !SUBREG_P (op_true))
|
||||
op_true = force_reg (dest_mode, op_true);
|
||||
|
||||
if (!REG_P (op_false) && !SUBREG_P (op_false))
|
||||
op_false = force_reg (dest_mode, op_false);
|
||||
|
||||
cond2 = gen_rtx_fmt_ee (NE, cc_mode, gen_lowpart (dest_mode, mask),
|
||||
CONST0_RTX (dest_mode));
|
||||
emit_insn (gen_rtx_SET (dest,
|
||||
|
|
|
@ -390,13 +390,13 @@
|
|||
}")
|
||||
|
||||
(define_expand "vcond<mode><mode>"
|
||||
[(set (match_operand:VEC_I 0 "vint_operand" "")
|
||||
[(set (match_operand:VEC_I 0 "vint_operand")
|
||||
(if_then_else:VEC_I
|
||||
(match_operator 3 "comparison_operator"
|
||||
[(match_operand:VEC_I 4 "vint_operand" "")
|
||||
(match_operand:VEC_I 5 "vint_operand" "")])
|
||||
(match_operand:VEC_I 1 "vint_operand" "")
|
||||
(match_operand:VEC_I 2 "vint_operand" "")))]
|
||||
[(match_operand:VEC_I 4 "vint_operand")
|
||||
(match_operand:VEC_I 5 "vint_operand")])
|
||||
(match_operand:VEC_I 1 "vector_int_reg_or_same_bit")
|
||||
(match_operand:VEC_I 2 "vector_int_reg_or_same_bit")))]
|
||||
"VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)"
|
||||
"
|
||||
{
|
||||
|
@ -446,13 +446,13 @@
|
|||
}")
|
||||
|
||||
(define_expand "vcondu<mode><mode>"
|
||||
[(set (match_operand:VEC_I 0 "vint_operand" "")
|
||||
[(set (match_operand:VEC_I 0 "vint_operand")
|
||||
(if_then_else:VEC_I
|
||||
(match_operator 3 "comparison_operator"
|
||||
[(match_operand:VEC_I 4 "vint_operand" "")
|
||||
(match_operand:VEC_I 5 "vint_operand" "")])
|
||||
(match_operand:VEC_I 1 "vint_operand" "")
|
||||
(match_operand:VEC_I 2 "vint_operand" "")))]
|
||||
[(match_operand:VEC_I 4 "vint_operand")
|
||||
(match_operand:VEC_I 5 "vint_operand")])
|
||||
(match_operand:VEC_I 1 "vector_int_reg_or_same_bit")
|
||||
(match_operand:VEC_I 2 "vector_int_reg_or_same_bit")))]
|
||||
"VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)"
|
||||
"
|
||||
{
|
||||
|
|
|
@ -1,3 +1,10 @@
|
|||
2017-02-06 Michael Meissner <meissner@linux.vnet.ibm.com>
|
||||
|
||||
PR target/66144
|
||||
* gcc.target/powerpc/pr66144-1.c: New test.
|
||||
* gcc.target/powerpc/pr66144-2.c: Likewise.
|
||||
* gcc.target/powerpc/pr66144-3.c: Likewise.
|
||||
|
||||
2017-02-06 Martin Sebor <msebor@redhat.com>
|
||||
|
||||
PR tree-optimization/79376
|
||||
|
|
20
gcc/testsuite/gcc.target/powerpc/pr66144-1.c
Normal file
20
gcc/testsuite/gcc.target/powerpc/pr66144-1.c
Normal file
|
@ -0,0 +1,20 @@
|
|||
/* { dg-do compile { target { powerpc64*-*-* } } } */
|
||||
/* { dg-skip-if "do not override -mcpu" { powerpc*-*-* } { "-mcpu=*" } { "-mcpu=power9" } } */
|
||||
/* { dg-require-effective-target powerpc_p9vector_ok } */
|
||||
/* { dg-options "-mcpu=power9 -O2" } */
|
||||
|
||||
/* Verify that we optimize vector1 = (vector2 == vector3) by not loading up
|
||||
0/-1. */
|
||||
|
||||
vector int
|
||||
test (vector int a, vector int b)
|
||||
{
|
||||
return a == b;
|
||||
}
|
||||
|
||||
/* { dg-final { scan-assembler {\mvcmpequw\M} } } */
|
||||
/* { dg-final { scan-assembler-not {\mxxspltib\M} } } */
|
||||
/* { dg-final { scan-assembler-not {\mvspltisw\M} } } */
|
||||
/* { dg-final { scan-assembler-not {\mxxlxor\M} } } */
|
||||
/* { dg-final { scan-assembler-not {\mxxlxorc\M} } } */
|
||||
/* { dg-final { scan-assembler-not {\mxxsel\M} } } */
|
21
gcc/testsuite/gcc.target/powerpc/pr66144-2.c
Normal file
21
gcc/testsuite/gcc.target/powerpc/pr66144-2.c
Normal file
|
@ -0,0 +1,21 @@
|
|||
/* { dg-do compile { target { powerpc64*-*-* } } } */
|
||||
/* { dg-skip-if "do not override -mcpu" { powerpc*-*-* } { "-mcpu=*" } { "-mcpu=power8" } } */
|
||||
/* { dg-require-effective-target powerpc_p8vector_ok } */
|
||||
/* { dg-options "-mcpu=power8 -O2" } */
|
||||
|
||||
/* Verify that we optimize vector1 = (vector2 != vector3) by not loading up
|
||||
0/-1. */
|
||||
|
||||
vector unsigned char
|
||||
test (vector unsigned char a, vector unsigned char b)
|
||||
{
|
||||
return a != b;
|
||||
}
|
||||
|
||||
/* { dg-final { scan-assembler {\mvcmpequb\M} } } */
|
||||
/* { dg-final { scan-assembler {\mxxlnor\M} } } */
|
||||
/* { dg-final { scan-assembler-not {\mxxspltib\M} } } */
|
||||
/* { dg-final { scan-assembler-not {\mvspltisw\M} } } */
|
||||
/* { dg-final { scan-assembler-not {\mxxlxor\M} } } */
|
||||
/* { dg-final { scan-assembler-not {\mxxlxorc\M} } } */
|
||||
/* { dg-final { scan-assembler-not {\mxxsel\M} } } */
|
27
gcc/testsuite/gcc.target/powerpc/pr66144-3.c
Normal file
27
gcc/testsuite/gcc.target/powerpc/pr66144-3.c
Normal file
|
@ -0,0 +1,27 @@
|
|||
/* { dg-do compile { target { powerpc64*-*-* } } } */
|
||||
/* { dg-skip-if "do not override -mcpu" { powerpc*-*-* } { "-mcpu=*" } { "-mcpu=power8" } } */
|
||||
/* { dg-require-effective-target powerpc_p8vector_ok } */
|
||||
/* { dg-options "-mcpu=power8 -O2 -ftree-vectorize" } */
|
||||
|
||||
/* Verify that we can optimize a vector conditional move, where one of the arms
|
||||
is all 1's into using the mask as one of the inputs to XXSEL. */
|
||||
|
||||
#include <altivec.h>
|
||||
|
||||
static int a[1024], b[1024], c[1024];
|
||||
|
||||
int *p_a = a, *p_b = b, *p_c = c;
|
||||
|
||||
void
|
||||
test (void)
|
||||
{
|
||||
unsigned long i;
|
||||
|
||||
for (i = 0; i < 1024; i++)
|
||||
a[i] = (b[i] == c[i]) ? -1 : a[i];
|
||||
}
|
||||
|
||||
/* { dg-final { scan-assembler {\mvcmpequw\M} } } */
|
||||
/* { dg-final { scan-assembler {\mxxsel\M} } } */
|
||||
/* { dg-final { scan-assembler-not {\mvspltisw\M} } } */
|
||||
/* { dg-final { scan-assembler-not {\mxxlorc\M} } } */
|
Loading…
Add table
Reference in a new issue