Hi! The following testcase results in an assembler warning on movb $700415, %ch The problem is that the *mov*_insv_1* patterns use SImode or DImode for the source operand, accept CONST_INTs in the constraints and nothing truncates the constants to QImode. While the b modifier in %b1 handles changing the printout of registers and memory (forcing it to be 8-bit low register or in Intel syntax 8-bit memory), it doesn't handle CONST_INTs this way. I've checked other such uses of b, w, k modifiers and usually they are used either in widening of the operand (which is fine), or with constraints not allowing integers.
Fixed thusly, bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk/4.7? 2012-09-01 Jakub Jelinek <ja...@redhat.com> PR target/54436 * config/i386/i386.md (*mov<mode>_insv_1_rex64, *movsi_insv_1): If operands[1] is CONST_INT_P, convert it to QImode before printing. * gcc.dg/torture/pr54436.c: New test. --- gcc/config/i386/i386.md.jj 2012-08-30 11:38:22.000000000 +0200 +++ gcc/config/i386/i386.md 2012-08-31 17:12:03.556906659 +0200 @@ -2690,7 +2690,11 @@ (define_insn "*mov<mode>_insv_1_rex64" (const_int 8)) (match_operand:SWI48x 1 "nonmemory_operand" "Qn"))] "TARGET_64BIT" - "mov{b}\t{%b1, %h0|%h0, %b1}" +{ + if (CONST_INT_P (operands[1])) + operands[1] = simplify_gen_subreg (QImode, operands[1], <MODE>mode, 0); + return "mov{b}\t{%b1, %h0|%h0, %b1}"; +} [(set_attr "type" "imov") (set_attr "mode" "QI")]) @@ -2700,7 +2704,11 @@ (define_insn "*movsi_insv_1" (const_int 8)) (match_operand:SI 1 "general_operand" "Qmn"))] "!TARGET_64BIT" - "mov{b}\t{%b1, %h0|%h0, %b1}" +{ + if (CONST_INT_P (operands[1])) + operands[1] = simplify_gen_subreg (QImode, operands[1], SImode, 0); + return "mov{b}\t{%b1, %h0|%h0, %b1}"; +} [(set_attr "type" "imov") (set_attr "mode" "QI")]) --- gcc/testsuite/gcc.dg/torture/pr54436.c.jj 2012-08-31 18:30:22.131777543 +0200 +++ gcc/testsuite/gcc.dg/torture/pr54436.c 2012-08-31 18:32:27.994169836 +0200 @@ -0,0 +1,38 @@ +/* PR target/54436 */ +/* { dg-do assemble } */ + +#if __SIZEOF_SHORT__ == 2 && __SIZEOF_LONG_LONG__ == 8 +static inline unsigned short +baz (unsigned short *x) +{ + union U { unsigned short a; unsigned char b[2]; } u = { *x }; + u.b[0] = ((u.b[0] * 0x0802ULL & 0x22110ULL) + | (u.b[0] * 0x8020ULL & 0x88440ULL)) * 0x10101ULL >> 16; + u.b[1] = ((u.b[1] * 0x0802ULL & 0x22110ULL) + | (u.b[1] * 0x8020ULL & 0x88440ULL)) * 0x10101ULL >> 16; + unsigned char t = u.b[0]; + u.b[0] = u.b[1]; + u.b[1] = t; + return u.a; +} + +static inline unsigned long long +bar (unsigned long long *x) +{ + union U { unsigned long long a; unsigned short b[4]; } u = { *x }; + u.b[0] = baz (&u.b[0]); + return u.a; +} + +void +foo (void) +{ + unsigned long long l = -1ULL; + __asm volatile ("" : : "r" (bar (&l))); +} +#else +void +foo (void) +{ +} +#endif Jakub