Hello! Again the case of pushing an out-of-range constant to a mode register.
2015-10-03 Uros Bizjak <ubiz...@gmail.com> PR target/66473 * config/i386/i386.c (ix86_expand_vector_set): Use gen_int_mode to prepare mask operand for AVX512 modes. testsuite/ChangeLog: 2015-10-03 Uros Bizjak <ubiz...@gmail.com> PR target/66473 * gcc.target/i386/pr66473.c: New test. Bootstrapped and regression tested on x86_64-linux-gnu {,-m32}. Committed to mainline and gcc-5 branch. Uros.
Index: config/i386/i386.c =================================================================== --- config/i386/i386.c (revision 224330) +++ config/i386/i386.c (working copy) @@ -44720,6 +44720,8 @@ ix86_expand_vector_set (bool mmx_ok, rtx target, r { gen_vec_set_lo_v4df, gen_vec_set_hi_v4df } }; int i, j, n; + machine_mode mmode = VOIDmode; + rtx (*gen_blendm) (rtx, rtx, rtx, rtx); switch (mode) { @@ -44936,76 +44938,65 @@ half: case V8DFmode: if (TARGET_AVX512F) { - tmp = gen_reg_rtx (mode); - emit_insn (gen_rtx_SET (tmp, gen_rtx_VEC_DUPLICATE (mode, val))); - emit_insn (gen_avx512f_blendmv8df (target, tmp, target, - force_reg (QImode, GEN_INT (1 << elt)))); - return; + mmode = QImode; + gen_blendm = gen_avx512f_blendmv8df; } - else - break; + break; + case V8DImode: if (TARGET_AVX512F) { - tmp = gen_reg_rtx (mode); - emit_insn (gen_rtx_SET (tmp, gen_rtx_VEC_DUPLICATE (mode, val))); - emit_insn (gen_avx512f_blendmv8di (target, tmp, target, - force_reg (QImode, GEN_INT (1 << elt)))); - return; + mmode = QImode; + gen_blendm = gen_avx512f_blendmv8di; } - else - break; + break; + case V16SFmode: if (TARGET_AVX512F) { - tmp = gen_reg_rtx (mode); - emit_insn (gen_rtx_SET (tmp, gen_rtx_VEC_DUPLICATE (mode, val))); - emit_insn (gen_avx512f_blendmv16sf (target, tmp, target, - force_reg (HImode, GEN_INT (1 << elt)))); - return; + mmode = HImode; + gen_blendm = gen_avx512f_blendmv16sf; } - else - break; + break; + case V16SImode: if (TARGET_AVX512F) { - tmp = gen_reg_rtx (mode); - emit_insn (gen_rtx_SET (tmp, gen_rtx_VEC_DUPLICATE (mode, val))); - emit_insn (gen_avx512f_blendmv16si (target, tmp, target, - force_reg (HImode, GEN_INT (1 << elt)))); - return; + mmode = HImode; + gen_blendm = gen_avx512f_blendmv16si; } - else - break; + break; + case V32HImode: if (TARGET_AVX512F && TARGET_AVX512BW) { - tmp = gen_reg_rtx (mode); - emit_insn (gen_rtx_SET (tmp, gen_rtx_VEC_DUPLICATE (mode, val))); - emit_insn (gen_avx512bw_blendmv32hi (target, tmp, target, - force_reg (SImode, GEN_INT (1 << elt)))); - return; + mmode = SImode; + gen_blendm = gen_avx512bw_blendmv32hi; } - else - break; + break; + case V64QImode: if (TARGET_AVX512F && TARGET_AVX512BW) { - tmp = gen_reg_rtx (mode); - emit_insn (gen_rtx_SET (tmp, gen_rtx_VEC_DUPLICATE (mode, val))); - emit_insn (gen_avx512bw_blendmv64qi (target, tmp, target, - force_reg (DImode, GEN_INT (1 << elt)))); - return; + mmode = DImode; + gen_blendm = gen_avx512bw_blendmv64qi; } - else - break; + break; default: break; } - if (use_vec_merge) + if (mmode != VOIDmode) { + tmp = gen_reg_rtx (mode); + emit_insn (gen_rtx_SET (tmp, gen_rtx_VEC_DUPLICATE (mode, val))); + emit_insn (gen_blendm (target, tmp, target, + force_reg (mmode, + gen_int_mode (1 << elt, mmode)))); + } + else if (use_vec_merge) + { tmp = gen_rtx_VEC_DUPLICATE (mode, val); tmp = gen_rtx_VEC_MERGE (mode, tmp, target, GEN_INT (1 << elt)); emit_insn (gen_rtx_SET (target, tmp)); Index: testsuite/gcc.target/i386/pr66473.c =================================================================== --- testsuite/gcc.target/i386/pr66473.c (revision 0) +++ testsuite/gcc.target/i386/pr66473.c (working copy) @@ -0,0 +1,17 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -mavx512f" } */ + +typedef double __m512d __attribute__ ((__vector_size__ (64))); + +extern __m512d _ZGVeN8v_func (__m512d); + +double +func_vlen8 (double x) +{ + __m512d mx, mr; + + mx[0] = mx[1] = mx[2] = mx[3] = mx[4] = mx[5] = mx[6] = mx[7] = x; + mr = _ZGVeN8v_func (mx); + + return (double) mr[0]; +}