Hi,

The GCC combine pass combines the insns even though they contain volatile
registers. This doesn't make sence.

The test case listed in https://gcc.gnu.org/bugzilla/show_bug.cgi?id=46164
shows the expected asm command "mov r1, r1" is not generated."r1" is defined
as a volatile register, and there are three insns related to r1:

    (insn 98 97 40 3 (set (reg/v:SI 1 r1 [ b ]) (reg:SI 154 [ b ])) 
    (insn 41 40 43 3 (set (reg/f:SI 148)        (reg/v:SI 1 r1 [ b ]))
    (insn 43 41 45 3 (parallel [
            (set (reg/v:SI 0 r0 [ ret ])
                (asm_operands/v:SI ("mov %2, %2  mov %3, %3  mov %4, %4")
("=r") 0 [
                        (reg/v:SI 0 r0 [ a ])
                        (reg/v:SI 1 r1 [ b ])
                        (reg/v:SI 2 r2 [ c ])
                        (mem/c:QI (reg/f:SI 148) [0 MEM[(char *)&temp]+0 S1
A8])
                        ....
The combine pass combine these insns:

    (note 98 97 40 3 NOTE_INSN_DELETED)
    (note 41 40 43 3 NOTE_INSN_DELETED)
    (insn 43 41 45 3 (parallel [
            (set (reg/v:SI 0 r0 [ ret ])
                (asm_operands/v:SI ("mov %2, %2  mov %3, %3  mov %4, %4")
("=r") 0 [
                        (reg/v:SI 0 r0 [ a ])
                        (reg:SI 154 [ b ])
                        (reg/v:SI 2 r2 [ c ])
                        (mem/c:QI (reg:SI 154 [ b ]) [0 MEM[(char *)&temp]+0
S1 A8])
                        ....
                        
The volatile register "r1" is totally disappeared in the asm_operands, and
the generated asm code is unexpected.

This patch is used to disable the combine operation if the insns contain
volatile registers. A new test case is also added in this patch.

Is it OK for trunk?

BR,
Hale Wang

ChangeLog:

2015-01-22  Hale Wang  <hale.w...@arm.com>

        PR middle-end/46164
        * combine.c (can_combine_p): Don't combine the insns if
        a volatile register is contained.

2015-01-22  Hale Wang  <hale.w...@arm.com>

        PR middle-end/46164
        * gcc.target/arm/pr46164.c: New test.


diff --git a/gcc/combine.c b/gcc/combine.c
index 5c763b4..cf48666 100644
--- a/gcc/combine.c
+++ b/gcc/combine.c
@@ -2004,6 +2004,13 @@ can_combine_p (rtx_insn *insn, rtx_insn *i3, rtx_insn
*pred ATTRIBUTE_UNUSED,
              return 0;
        }
 
+  /* If src contains a volatile register, reject, because the register may
+     possibly be used in a asm operand.  The combined insn may cause the
asm
+     operand to be generated unexpectly.  */
+
+  if (REG_P (src) && REG_USERVAR_P (src))
+    return 0;
+
   /* If INSN contains anything volatile, or is an `asm' (whether volatile
      or not), reject, unless nothing volatile comes between it and I3 */
 
diff --git a/gcc/testsuite/gcc.target/arm/pr46164.c
b/gcc/testsuite/gcc.target/arm/pr46164.c
new file mode 100644
index 0000000..ad3b7cb
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/pr46164.c
@@ -0,0 +1,26 @@
+/* { dg-do compile } */
+/* { dg-options "-mcpu=cortex-m3 -mthumb -O1" } */
+
+char temp[16];
+extern int foo1 (void);
+
+void foo (void)
+{
+  int i;
+  int len;
+
+  while (1)
+  {
+    len = foo1 ();
+    register char *a asm ("r1") = temp;
+    asm volatile ("mov %[r1], %[r1]\n " :: [r1]"r"(a), "m"(*a));
+
+    for (i = 0; i < len; i++)
+    {
+      if (temp[i] == 10)
+      return;
+    }
+  }
+}
+
+/* { dg-final { scan-assembler "\[\\t \]+mov\ r1,\ r1" } } */

Attachment: pr46164-combine-volatile-register.patch-3
Description: Binary data

Reply via email to