gcc-patches@gcc.gnu.org
[Top] [All Lists]

[patch] current_insn_predicate vs. inline asm

Subject: [patch] current_insn_predicate vs. inline asm
From: Paul Brook
Date: Wed, 9 Aug 2006 17:22:34 +0100
The Arm port uses %? in format strings to generate mnemonic suffixes for 
conditionally executed instructions. These expand to different things 
depending on the value of current_insn_predicate.

It turns out that there's a fair amount of kernel code that includes %? in 
inline assembly fragments. This is arguably a bug in the kernel. However, 
given gcc never conditionaly executes inline asm it's not entirely 
unreasonable to expect this to "work". i.e. should expand to the 
unconditional form.

Currently final_scan_insn doesn't set current_insn_predicate until after asm 
fragments have been output. This means inline asm incorrectly inherits its 
conditionalness from the previous insn.

The attached patch resets current_insn_predicate earlier, so inline asm output 
is unconditional. It fixes an arm-linux kernel miscompilation.

Tested with cross to arm-none-eabi.
Ok for mainline and 4.1?

Paul

2006-08-09  Paul Brook  <paul@xxxxxxxxxxxxxxxx>

        gcc/
        * final.c (final_scan_insn): Clear current_insn_predicate before
        outputting inline asm.

        gcc/testsuite/
        * gcc.target/arm/cond-asm.c: New test.
Index: gcc/final.c
===================================================================
--- gcc/final.c (revision 116034)
+++ gcc/final.c (working copy)
@@ -1985,6 +1985,10 @@ final_scan_insn (rtx insn, FILE *file, i
        int insn_code_number;
        const char *template;
 
+#ifdef HAVE_conditional_execution
+       /* Reset this early so it is correct for ASM statements.  */
+       current_insn_predicate = NULL_RTX;
+#endif
        /* An INSN, JUMP_INSN or CALL_INSN.
           First check for special kinds that recog doesn't recognize.  */
 
@@ -2419,8 +2423,6 @@ final_scan_insn (rtx insn, FILE *file, i
 #ifdef HAVE_conditional_execution
        if (GET_CODE (PATTERN (insn)) == COND_EXEC)
          current_insn_predicate = COND_EXEC_TEST (PATTERN (insn));
-       else
-         current_insn_predicate = NULL_RTX;
 #endif
 
 #ifdef HAVE_cc0
Index: gcc/testsuite/gcc.target/arm/cond-asm.c
===================================================================
--- gcc/testsuite/gcc.target/arm/cond-asm.c     (revision 0)
+++ gcc/testsuite/gcc.target/arm/cond-asm.c     (revision 0)
@@ -0,0 +1,13 @@
+/* Check that %? in inline asm expands to nothing.  */
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+/* { dg-require-effective-target arm32 } */
+int b;
+int foo(int a)
+{
+  if (a)
+    b = 42;
+  asm ("test%?me":"=r"(a):"0"(a));
+  return a;
+}
+/* { dg-final { scan-assembler "testme" } } */
<Prev in Thread] Current Thread [Next in Thread>