diff options
-rw-r--r-- | gcc/config/i386/i386-features.cc | 50 | ||||
-rw-r--r-- | gcc/testsuite/gcc.target/i386/pr107548-1.c | 25 | ||||
-rw-r--r-- | gcc/testsuite/gcc.target/i386/pr107548-2.c | 13 |
3 files changed, 88 insertions, 0 deletions
diff --git a/gcc/config/i386/i386-features.cc b/gcc/config/i386/i386-features.cc index 4bf8bb3..0f59be0 100644 --- a/gcc/config/i386/i386-features.cc +++ b/gcc/config/i386/i386-features.cc @@ -429,6 +429,11 @@ scalar_chain::add_insn (bitmap candidates, unsigned int insn_uid) for (ref = DF_INSN_UID_DEFS (insn_uid); ref; ref = DF_REF_NEXT_LOC (ref)) if (!HARD_REGISTER_P (DF_REF_REG (ref))) analyze_register_chain (candidates, ref); + + /* The operand(s) of VEC_SELECT don't need to be converted/convertible. */ + if (def_set && GET_CODE (SET_SRC (def_set)) == VEC_SELECT) + return; + for (ref = DF_INSN_UID_USES (insn_uid); ref; ref = DF_REF_NEXT_LOC (ref)) if (!DF_REF_REG_MEM_P (ref)) analyze_register_chain (candidates, ref); @@ -629,6 +634,23 @@ general_scalar_chain::compute_convert_gain () } break; + case VEC_SELECT: + if (XVECEXP (XEXP (src, 1), 0, 0) == const0_rtx) + { + // movd (4 bytes) replaced with movdqa (4 bytes). + if (!optimize_insn_for_size_p ()) + igain += ix86_cost->sse_to_integer - ix86_cost->xmm_move; + } + else + { + // pshufd; movd replaced with pshufd. + if (optimize_insn_for_size_p ()) + igain += COSTS_N_BYTES (4); + else + igain += ix86_cost->sse_to_integer; + } + break; + default: gcc_unreachable (); } @@ -1167,6 +1189,24 @@ general_scalar_chain::convert_insn (rtx_insn *insn) convert_op (&src, insn); break; + case VEC_SELECT: + if (XVECEXP (XEXP (src, 1), 0, 0) == const0_rtx) + src = XEXP (src, 0); + else if (smode == DImode) + { + rtx tmp = gen_lowpart (V1TImode, XEXP (src, 0)); + dst = gen_lowpart (V1TImode, dst); + src = gen_rtx_LSHIFTRT (V1TImode, tmp, GEN_INT (64)); + } + else + { + rtx tmp = XVECEXP (XEXP (src, 1), 0, 0); + rtvec vec = gen_rtvec (4, tmp, tmp, tmp, tmp); + rtx par = gen_rtx_PARALLEL (VOIDmode, vec); + src = gen_rtx_VEC_SELECT (vmode, XEXP (src, 0), par); + } + break; + default: gcc_unreachable (); } @@ -1930,6 +1970,16 @@ general_scalar_to_vector_candidate_p (rtx_insn *insn, enum machine_mode mode) case CONST_INT: return REG_P (dst); + case VEC_SELECT: + /* Excluding MEM_P (dst) avoids intefering with vpextr[dq]. */ + return REG_P (dst) + && REG_P (XEXP (src, 0)) + && GET_MODE (XEXP (src, 0)) == (mode == DImode ? V2DImode + : V4SImode) + && GET_CODE (XEXP (src, 1)) == PARALLEL + && XVECLEN (XEXP (src, 1), 0) == 1 + && CONST_INT_P (XVECEXP (XEXP (src, 1), 0, 0)); + default: return false; } diff --git a/gcc/testsuite/gcc.target/i386/pr107548-1.c b/gcc/testsuite/gcc.target/i386/pr107548-1.c new file mode 100644 index 0000000..da78f75 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr107548-1.c @@ -0,0 +1,25 @@ +/* { dg-do compile { target { ! ia32 } } } */ +/* { dg-options "-O2 -mstv -mno-stackrealign" } */ +typedef unsigned int v4si __attribute__((vector_size(16))); + +unsigned int foo1 (v4si a, v4si b) +{ + a[0] += b[0]; + return a[0] + a[1]; +} + +unsigned int foo2 (v4si a, v4si b) +{ + a[0] += b[0]; + return a[0] + a[2]; +} + +unsigned int foo3 (v4si a, v4si b) +{ + a[0] += b[0]; + return a[0] + a[3]; +} + +/* { dg-final { scan-assembler-times "\tmovd\t" 3 } } */ +/* { dg-final { scan-assembler-times "paddd" 6 } } */ +/* { dg-final { scan-assembler-not "addl" } } */ diff --git a/gcc/testsuite/gcc.target/i386/pr107548-2.c b/gcc/testsuite/gcc.target/i386/pr107548-2.c new file mode 100644 index 0000000..b57594e --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr107548-2.c @@ -0,0 +1,13 @@ +/* { dg-do compile { target { ! ia32 } } } */ +/* { dg-options "-O2 -mstv -mno-stackrealign" } */ +typedef unsigned long long v2di __attribute__((vector_size(16))); + +unsigned long long foo(v2di a, v2di b) +{ + a[0] += b[0]; + return a[0] + a[1]; +} + +/* { dg-final { scan-assembler-not "\taddq\t" } } */ +/* { dg-final { scan-assembler-times "paddq" 2 } } */ +/* { dg-final { scan-assembler "psrldq" } } */ |