Hi! The various blendm expanders look like: (define_insn "<avx512>_blendm<mode>" [(set (match_operand:V48_AVX512VL 0 "register_operand" "=v") (vec_merge:V48_AVX512VL (match_operand:V48_AVX512VL 2 "nonimmediate_operand" "vm") (match_operand:V48_AVX512VL 1 "register_operand" "v") (match_operand:<avx512fmaskmode> 3 "register_operand" "Yk")))] "TARGET_AVX512F" "vblendm<ssemodesuffix>\t{%2, %1, %0%{%3%}|%0%{%3%}, %1, %2}" [(set_attr "type" "ssemov") (set_attr "prefix" "evex") (set_attr "mode" "<sseinsnmode>")]) (i.e. their operands[1] is the second argument of VEC_MERGE (aka the value to take elements from for bits cleared in the mask), while operands[2] is the first argument of VEC_MERGE (aka the value to take elements from for bits set in the mask)), so the call to gen_blendm which want to insert a single element (with index elt) into target by broadcasting val into a temporary and using mask of 1 << elt uses wrong order of arguments.
Fixed thusly, bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk? 2016-03-27 Jakub Jelinek <ja...@redhat.com> PR target/70421 * config/i386/i386.c (ix86_expand_vector_set): Fix up argument order in gen_blendm expander. * gcc.dg/torture/pr70421.c: New test. * gcc.target/i386/avx512f-pr70421.c: New test. --- gcc/config/i386/i386.c.jj 2016-03-23 10:41:12.000000000 +0100 +++ gcc/config/i386/i386.c 2016-03-27 22:32:51.748280358 +0200 @@ -46930,7 +46930,7 @@ half: { tmp = gen_reg_rtx (mode); emit_insn (gen_rtx_SET (tmp, gen_rtx_VEC_DUPLICATE (mode, val))); - emit_insn (gen_blendm (target, tmp, target, + emit_insn (gen_blendm (target, target, tmp, force_reg (mmode, gen_int_mode (1 << elt, mmode)))); } --- gcc/testsuite/gcc.dg/torture/pr70421.c.jj 2016-03-29 09:25:37.015469084 +0200 +++ gcc/testsuite/gcc.dg/torture/pr70421.c 2016-03-29 09:25:13.000000000 +0200 @@ -0,0 +1,22 @@ +/* PR target/70421 */ +/* { dg-do run } */ +/* { dg-additional-options "-Wno-psabi -w" } */ + +typedef unsigned V __attribute__ ((vector_size (64))); + +unsigned __attribute__ ((noinline, noclone)) +foo (unsigned x, V u, V v) +{ + v[1] ^= v[2]; + x ^= ((V) v)[u[0]]; + return x; +} + +int +main () +{ + unsigned x = foo (0x10, (V) { 1 }, (V) { 0x100, 0x1000, 0x10000 }); + if (x != 0x11010) + __builtin_abort (); + return 0; +} --- gcc/testsuite/gcc.target/i386/avx512f-pr70421.c.jj 2016-03-29 09:26:23.380837148 +0200 +++ gcc/testsuite/gcc.target/i386/avx512f-pr70421.c 2016-03-29 09:27:37.066832846 +0200 @@ -0,0 +1,15 @@ +/* PR target/70421 */ +/* { dg-do run } */ +/* { dg-require-effective-target avx512f } */ +/* { dg-options "-O2 -mavx512f" } */ + +#include "avx512f-check.h" + +#define main() do_main() +#include "../../gcc.dg/torture/pr70421.c" + +static void +avx512f_test (void) +{ + do_main (); +} Jakub