diff mbox

-fuse-caller-save - Collect register usage information

Message ID 53C27913.8010602@mentor.com
State New
Headers show

Commit Message

Tom de Vries July 13, 2014, 12:18 p.m. UTC
On 19-06-14 21:45, Richard Henderson wrote:
> On 06/19/2014 12:36 PM, Jan Hubicka wrote:
>>> On 06/19/2014 09:06 AM, Tom de Vries wrote:
>>>>
>>>> 2014-06-19  Tom de Vries  <tom@codesourcery.com>
>>>>
>>>> 	* final.c (collect_fn_hard_reg_usage): Don't save function_used_regs if
>>>> 	it contains all call_used_regs.
>>>
>>> Ok.
>>
>> When we now have way to represent different reg usages for functions, what would be best
>> way to make local functions to default into saving some SSE registers on x86/x86-64?
>
> I wouldn't do that at all.  Leave all sse registers call-clobbered.  This way
> you don't need to have different entry points (or one possibly less efficient
> entry point) when a function is used both locally and globally.
>
> What I would investigate is how to use this hard reg usage data in the register
> allocator.  If we know that the callee only uses xmm0-xmm4, then we can keep
> xmm5-xmm15 live across the call.
>

AFAIU, what you describe here already works. This patch contains a version of 
the fuse-caller-save test with xmm registers. The callee bar only uses xmm0, and 
caller foo keeps xmm1 live across the call.

OK for trunk?

Thanks,
- Tom

Comments

Jan Hubicka July 13, 2014, 1:24 p.m. UTC | #1
> >>When we now have way to represent different reg usages for functions, what would be best
> >>way to make local functions to default into saving some SSE registers on x86/x86-64?
> >
> >I wouldn't do that at all.  Leave all sse registers call-clobbered.  This way
> >you don't need to have different entry points (or one possibly less efficient
> >entry point) when a function is used both locally and globally.
> >
> >What I would investigate is how to use this hard reg usage data in the register
> >allocator.  If we know that the callee only uses xmm0-xmm4, then we can keep
> >xmm5-xmm15 live across the call.

What I was shooting for whas to
  1) make it possible to declare by attribute that some registers are not call clobbered
  2) have more sane default when the call usage data are not available - either because of LTO partitioning
     or because the callee was not copmiled yet.
> >
> 
> AFAIU, what you describe here already works. This patch contains a
> version of the fuse-caller-save test with xmm registers. The callee
> bar only uses xmm0, and caller foo keeps xmm1 live across the call.
> 
> OK for trunk?
> 
> Thanks,
> - Tom
> 

> 2014-07-13  Tom de Vries  <tom@codesourcery.com>
> 
> 	* gcc.target/i386/fuse-caller-save-xmm-run.c: New test.
> 	* gcc.target/i386/fuse-caller-save-xmm.c: New test.

OK
Honza
> 
> diff --git a/gcc/testsuite/gcc.target/i386/fuse-caller-save-xmm-run.c b/gcc/testsuite/gcc.target/i386/fuse-caller-save-xmm-run.c
> new file mode 100644
> index 0000000..17385fa
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/i386/fuse-caller-save-xmm-run.c
> @@ -0,0 +1,34 @@
> +/* { dg-do run } */
> +/* { dg-options "-O2 -msse -fuse-caller-save" } */
> +
> +typedef double v2df __attribute__((vector_size (16)));
> +
> +static v2df __attribute__((noinline))
> +bar (v2df a)
> +{ 
> +  return a + (v2df){ 3.0, 3.0 };
> +}
> +
> +v2df __attribute__((noinline))
> +foo (v2df y)
> +{
> +  return y + bar (y);
> +}
> +
> +int
> +main (void)
> +{
> +  int success;
> +  union {
> +    v2df v;
> +    double d[2];
> +  } u;
> +
> +  u.v = foo ((v2df){ 5.0, 5.0});
> +  success = (u.d[0] == 13.0
> +	     && u.d[1] == 13.0);
> +
> +  return !success;
> +}
> +
> +
> diff --git a/gcc/testsuite/gcc.target/i386/fuse-caller-save-xmm.c b/gcc/testsuite/gcc.target/i386/fuse-caller-save-xmm.c
> new file mode 100644
> index 0000000..de1ca63
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/i386/fuse-caller-save-xmm.c
> @@ -0,0 +1,38 @@
> +/* { dg-do compile } */
> +/* { dg-options "-O2 -msse -fuse-caller-save" } */
> +
> +typedef double v2df __attribute__((vector_size (16)));
> +
> +static v2df __attribute__((noinline))
> +bar (v2df a)
> +{ 
> +  return a + (v2df){ 3.0, 3.0 };
> +}
> +
> +v2df __attribute__((noinline))
> +foo (v2df y)
> +{
> +  return y + bar (y);
> +}
> +
> +int
> +main (void)
> +{
> +  int success;
> +  union {
> +    v2df v;
> +    double d[2];
> +  } u;
> +
> +  u.v = foo ((v2df){ 5.0, 5.0});
> +  success = (u.d[0] == 13.0
> +	     && u.d[1] == 13.0);
> +
> +  return !success;
> +}
> +
> +/* { dg-final { scan-assembler-not "movaps\t%xmm1, \\(%rsp\\)" } } */
> +/* { dg-final { scan-assembler-not "movapd\t\\(%rsp\\), %xmm1" } } */
> +/* { dg-final { scan-assembler-times ".cfi_def_cfa_offset 16" 1 } } */
> +/* { dg-final { scan-assembler-times ".cfi_def_cfa_offset 32" 1 } } */
> +
diff mbox

Patch

2014-07-13  Tom de Vries  <tom@codesourcery.com>

	* gcc.target/i386/fuse-caller-save-xmm-run.c: New test.
	* gcc.target/i386/fuse-caller-save-xmm.c: New test.

diff --git a/gcc/testsuite/gcc.target/i386/fuse-caller-save-xmm-run.c b/gcc/testsuite/gcc.target/i386/fuse-caller-save-xmm-run.c
new file mode 100644
index 0000000..17385fa
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/fuse-caller-save-xmm-run.c
@@ -0,0 +1,34 @@ 
+/* { dg-do run } */
+/* { dg-options "-O2 -msse -fuse-caller-save" } */
+
+typedef double v2df __attribute__((vector_size (16)));
+
+static v2df __attribute__((noinline))
+bar (v2df a)
+{ 
+  return a + (v2df){ 3.0, 3.0 };
+}
+
+v2df __attribute__((noinline))
+foo (v2df y)
+{
+  return y + bar (y);
+}
+
+int
+main (void)
+{
+  int success;
+  union {
+    v2df v;
+    double d[2];
+  } u;
+
+  u.v = foo ((v2df){ 5.0, 5.0});
+  success = (u.d[0] == 13.0
+	     && u.d[1] == 13.0);
+
+  return !success;
+}
+
+
diff --git a/gcc/testsuite/gcc.target/i386/fuse-caller-save-xmm.c b/gcc/testsuite/gcc.target/i386/fuse-caller-save-xmm.c
new file mode 100644
index 0000000..de1ca63
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/fuse-caller-save-xmm.c
@@ -0,0 +1,38 @@ 
+/* { dg-do compile } */
+/* { dg-options "-O2 -msse -fuse-caller-save" } */
+
+typedef double v2df __attribute__((vector_size (16)));
+
+static v2df __attribute__((noinline))
+bar (v2df a)
+{ 
+  return a + (v2df){ 3.0, 3.0 };
+}
+
+v2df __attribute__((noinline))
+foo (v2df y)
+{
+  return y + bar (y);
+}
+
+int
+main (void)
+{
+  int success;
+  union {
+    v2df v;
+    double d[2];
+  } u;
+
+  u.v = foo ((v2df){ 5.0, 5.0});
+  success = (u.d[0] == 13.0
+	     && u.d[1] == 13.0);
+
+  return !success;
+}
+
+/* { dg-final { scan-assembler-not "movaps\t%xmm1, \\(%rsp\\)" } } */
+/* { dg-final { scan-assembler-not "movapd\t\\(%rsp\\), %xmm1" } } */
+/* { dg-final { scan-assembler-times ".cfi_def_cfa_offset 16" 1 } } */
+/* { dg-final { scan-assembler-times ".cfi_def_cfa_offset 32" 1 } } */
+