diff --git a/gcc/ChangeLog b/gcc/ChangeLog index f0aecbd07df..7d518b8abce 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,8 @@ +2014-05-20 Bill Schmidt + + * simplify-rtx.c (simplify_binary_operation_1): Optimize case of + nested VEC_SELECTs that are inverses of each other. + 2014-05-20 Richard Biener * tree-ssa-sccvn.c (process_scc): Dump SCC here, when diff --git a/gcc/simplify-rtx.c b/gcc/simplify-rtx.c index 27e04f53439..181b56fb8c0 100644 --- a/gcc/simplify-rtx.c +++ b/gcc/simplify-rtx.c @@ -3419,6 +3419,31 @@ simplify_binary_operation_1 (enum rtx_code code, enum machine_mode mode, } } + /* If we have two nested selects that are inverses of each + other, replace them with the source operand. */ + if (GET_CODE (trueop0) == VEC_SELECT + && GET_MODE (XEXP (trueop0, 0)) == mode) + { + rtx op0_subop1 = XEXP (trueop0, 1); + gcc_assert (GET_CODE (op0_subop1) == PARALLEL); + gcc_assert (XVECLEN (trueop1, 0) == GET_MODE_NUNITS (mode)); + + /* Apply the outer ordering vector to the inner one. (The inner + ordering vector is expressly permitted to be of a different + length than the outer one.) If the result is { 0, 1, ..., n-1 } + then the two VEC_SELECTs cancel. */ + for (int i = 0; i < XVECLEN (trueop1, 0); ++i) + { + rtx x = XVECEXP (trueop1, 0, i); + if (!CONST_INT_P (x)) + return 0; + rtx y = XVECEXP (op0_subop1, 0, INTVAL (x)); + if (!CONST_INT_P (y) || i != INTVAL (y)) + return 0; + } + return XEXP (trueop0, 0); + } + return 0; case VEC_CONCAT: { diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 95ceb3927ca..1440e049912 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,7 @@ +2014-05-20 Bill Schmidt + + * gcc.target/powerpc/vsxcopy.c: New test. + 2014-05-20 Paolo Carlini PR c++/58664 diff --git a/gcc/testsuite/gcc.target/powerpc/vsxcopy.c b/gcc/testsuite/gcc.target/powerpc/vsxcopy.c new file mode 100644 index 00000000000..fc1f0bd387a --- /dev/null +++ b/gcc/testsuite/gcc.target/powerpc/vsxcopy.c @@ -0,0 +1,15 @@ +/* { dg-do compile { target { powerpc64*-*-* } } } */ +/* { dg-require-effective-target powerpc_vsx_ok } */ +/* { dg-options "-O1" } */ +/* { dg-final { scan-assembler "lxvd2x" } } */ +/* { dg-final { scan-assembler "stxvd2x" } } */ +/* { dg-final { scan-assembler-not "xxpermdi" } } */ + +typedef float vecf __attribute__ ((vector_size (16))); +extern vecf j, k; + +void fun (void) +{ + j = k; +} +