Patchwork Fix i?86 *mov*insv_1* patterns (PR target/54436)

login
register
mail settings
Submitter Jakub Jelinek
Date Sept. 1, 2012, 6:32 a.m.
Message ID <20120901063236.GT1999@tucnak.redhat.com>
Download mbox | patch
Permalink /patch/181107/
State New
Headers show

Comments

Jakub Jelinek - Sept. 1, 2012, 6:32 a.m.
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  <jakub@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.


	Jakub
Uros Bizjak - Sept. 1, 2012, 7:22 a.m.
On Sat, Sep 1, 2012 at 8:32 AM, Jakub Jelinek <jakub@redhat.com> wrote:

> 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  <jakub@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.

OK.

Thanks,
Uros.

Patch

--- 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