The move to the output operand should use high register input operand. PR target/113044
gcc/ChangeLog: * config/i386/i386.md (*ashlqi_ext<mode>_1): Move from the high register of the input operand. (*<insn>qi_ext<mode>_1): Ditto. gcc/testsuite/ChangeLog: * gcc.target/i386/pr113044.c: New test. Bootstrapped and regression tested on x86_64-linux-gnu {,-m32}. Uros,
diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md index 710068e9093..4c6368bf3b7 100644 --- a/gcc/config/i386/i386.md +++ b/gcc/config/i386/i386.md @@ -15527,7 +15527,8 @@ (define_insn_and_split "*ashlqi_ext<mode>_1" && !(rtx_equal_p (operands[0], operands[1]))" [(set (zero_extract:SWI248 (match_dup 0) (const_int 8) (const_int 8)) - (match_dup 1)) + (zero_extract:SWI248 + (match_dup 1) (const_int 8) (const_int 8))) (parallel [(set (zero_extract:SWI248 (match_dup 0) (const_int 8) (const_int 8)) @@ -16689,7 +16690,8 @@ (define_insn_and_split "*<insn>qi_ext<mode>_1" && !(rtx_equal_p (operands[0], operands[1]))" [(set (zero_extract:SWI248 (match_dup 0) (const_int 8) (const_int 8)) - (match_dup 1)) + (zero_extract:SWI248 + (match_dup 1) (const_int 8) (const_int 8))) (parallel [(set (zero_extract:SWI248 (match_dup 0) (const_int 8) (const_int 8)) diff --git a/gcc/testsuite/gcc.target/i386/pr113044.c b/gcc/testsuite/gcc.target/i386/pr113044.c new file mode 100644 index 00000000000..923e7f48299 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr113044.c @@ -0,0 +1,24 @@ +/* PR target/113044 */ +/* { dg-do run } */ +/* { dg-options "-O" } */ + +typedef unsigned char __attribute__((__vector_size__ (2))) V; + +V +foo (char c, V v) +{ + V x = v >> (v & 8); + volatile char d = c; + if (!d) + __builtin_abort(); + return x; +} + +int +main (void) +{ + V x = foo (10, (V){3}); + if (x[0] != 3 || x[1]) + __builtin_abort(); + return 0; +}