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

Reply via email to