OSDN Git Service

PR target/22362
authorjakub <jakub@138bc75d-0d04-0410-961f-82ee72b054a4>
Tue, 6 Sep 2005 19:57:57 +0000 (19:57 +0000)
committerjakub <jakub@138bc75d-0d04-0410-961f-82ee72b054a4>
Tue, 6 Sep 2005 19:57:57 +0000 (19:57 +0000)
* config/i386/i386.c (ix86_function_regparm): Make sure automatic regparm
for internal functions doesn't use registers used by global registers
variables.  Use fewer register parameters if there are global register
variables.

* gcc.target/i386/pr22362.c: New test.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@103964 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/ChangeLog
gcc/config/i386/i386.c
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.target/i386/pr22362.c [new file with mode: 0644]

index 1f93ae7..9c60317 100644 (file)
@@ -1,3 +1,11 @@
+2005-09-06  Jakub Jelinek  <jakub@redhat.com>
+
+       PR target/22362
+       * config/i386/i386.c (ix86_function_regparm): Make sure automatic regparm
+       for internal functions doesn't use registers used by global registers
+       variables.  Use fewer register parameters if there are global register
+       variables.
+
 2005-09-06  Olivier Hainque  <hainque@adacore.com>
             Eric Botcazou  <ebotcazou@adacore.com>
 
index 5d2db43..2325efd 100644 (file)
@@ -2148,12 +2148,29 @@ ix86_function_regparm (tree type, tree decl)
          struct cgraph_local_info *i = cgraph_local_info (decl);
          if (i && i->local)
            {
+             int local_regparm, globals = 0, regno;
+
+             /* Make sure no regparm register is taken by a global register
+                variable.  */
+             for (local_regparm = 0; local_regparm < 3; local_regparm++)
+               if (global_regs[local_regparm])
+                 break;
              /* We can't use regparm(3) for nested functions as these use
                 static chain pointer in third argument.  */
-             if (DECL_CONTEXT (decl) && !DECL_NO_STATIC_CHAIN (decl))
-               regparm = 2;
-             else
-               regparm = 3;
+             if (local_regparm == 3
+                 && DECL_CONTEXT (decl) && !DECL_NO_STATIC_CHAIN (decl))
+               local_regparm = 2;
+             /* Each global register variable increases register preassure,
+                so the more global reg vars there are, the smaller regparm
+                optimization use, unless requested by the user explicitly.  */
+             for (regno = 0; regno < 6; regno++)
+               if (global_regs[regno])
+                 globals++;
+             local_regparm
+               = globals < local_regparm ? local_regparm - globals : 0;
+
+             if (local_regparm > regparm)
+               regparm = local_regparm;
            }
        }
     }
index 31dfd85..b76b34b 100644 (file)
@@ -1,5 +1,8 @@
 2005-09-06  Jakub Jelinek  <jakub@redhat.com>
 
+       PR target/22362
+       * gcc.target/i386/pr22362.c: New test.
+
        PR rtl-optimization/23098
        * gcc.target/i386/pr23098.c: Add dg-require-effective-target ilp32.
 
diff --git a/gcc/testsuite/gcc.target/i386/pr22362.c b/gcc/testsuite/gcc.target/i386/pr22362.c
new file mode 100644 (file)
index 0000000..a7c78b1
--- /dev/null
@@ -0,0 +1,25 @@
+/* PR target/22362 */
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+/* { dg-require-effective-target ilp32 } */
+
+register unsigned int reg0 __asm__ ("esi");
+register unsigned int reg1 __asm__ ("edi");
+register unsigned int reg2 __asm__ ("ebx");
+
+static unsigned int
+__attribute__((noinline))
+foo (unsigned long *x, void *y, void *z)
+{
+  int i;
+
+  for (i = 5; i > 0; i--)
+    x[i] = (unsigned long) foo ((unsigned long *) x[i], y, z);
+  return 0;
+}
+
+unsigned int
+bar (void)
+{
+  return foo (0, 0, 0);
+}