* [PATCH] PR target/66819: Allow indirect sibcall with register arguments @ 2015-07-09 10:54 H.J. Lu 2015-07-09 11:04 ` Uros Bizjak 2015-07-10 16:30 ` Uros Bizjak 0 siblings, 2 replies; 8+ messages in thread From: H.J. Lu @ 2015-07-09 10:54 UTC (permalink / raw) To: gcc-patches; +Cc: Uros Bizjak Indirect sibcall with register arguments is OK when there is register available for argument passing. OK for trunk if there is no regression? H.J. --- gcc/ PR target/66819 * config/i386/i386.c (ix86_function_ok_for_sibcall): Allow indirect sibcall with register arguments if register available for argument passing. (init_cumulative_args): Set cfun->machine->arg_reg_available_p to cum->nregs != 0. (function_arg_advance_32): Set cfun->machine->arg_reg_available_p to 0 when setting cum->nregs = 0. * config/i386/i386.h (machine_function): Add arg_reg_available_p. gcc/testsuite/ PR target/66819 * gcc.target/i386/pr66819-1.c: New test. * gcc.target/i386/pr66819-2.c: Likewise. * gcc.target/i386/pr66819-3.c: Likewise. * gcc.target/i386/pr66819-4.c: Likewise. * gcc.target/i386/pr66819-5.c: Likewise. --- gcc/config/i386/i386.c | 15 +++++++++------ gcc/config/i386/i386.h | 3 +++ gcc/testsuite/gcc.target/i386/pr66819-1.c | 8 ++++++++ gcc/testsuite/gcc.target/i386/pr66819-2.c | 8 ++++++++ gcc/testsuite/gcc.target/i386/pr66819-3.c | 10 ++++++++++ gcc/testsuite/gcc.target/i386/pr66819-4.c | 12 ++++++++++++ gcc/testsuite/gcc.target/i386/pr66819-5.c | 10 ++++++++++ 7 files changed, 60 insertions(+), 6 deletions(-) create mode 100644 gcc/testsuite/gcc.target/i386/pr66819-1.c create mode 100644 gcc/testsuite/gcc.target/i386/pr66819-2.c create mode 100644 gcc/testsuite/gcc.target/i386/pr66819-3.c create mode 100644 gcc/testsuite/gcc.target/i386/pr66819-4.c create mode 100644 gcc/testsuite/gcc.target/i386/pr66819-5.c diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c index 54ee6f3..85e59a8 100644 --- a/gcc/config/i386/i386.c +++ b/gcc/config/i386/i386.c @@ -5628,12 +5628,12 @@ ix86_function_ok_for_sibcall (tree decl, tree exp) if (!decl || (TARGET_DLLIMPORT_DECL_ATTRIBUTES && DECL_DLLIMPORT_P (decl))) { - if (ix86_function_regparm (type, NULL) >= 3) - { - /* ??? Need to count the actual number of registers to be used, - not the possible number of registers. Fix later. */ - return false; - } + /* FIXME: The symbol indirect call doesn't need a + call-clobbered register. But we don't know if + this is a symbol indirect call or not here. */ + if (ix86_function_regparm (type, NULL) >= 3 + && !cfun->machine->arg_reg_available_p) + return false; } } @@ -6567,6 +6567,7 @@ init_cumulative_args (CUMULATIVE_ARGS *cum, /* Argument info to initialize */ ? X86_64_REGPARM_MAX : X86_64_MS_REGPARM_MAX); } + cfun->machine->arg_reg_available_p = cum->nregs != 0; if (TARGET_SSE) { cum->sse_nregs = SSE_REGPARM_MAX; @@ -6636,6 +6637,7 @@ init_cumulative_args (CUMULATIVE_ARGS *cum, /* Argument info to initialize */ else cum->nregs = ix86_function_regparm (fntype, fndecl); } + cfun->machine->arg_reg_available_p = cum->nregs != 0; /* Set up the number of SSE registers used for passing SFmode and DFmode arguments. Warn for mismatching ABI. */ @@ -7584,6 +7586,7 @@ pass_in_reg: { cum->nregs = 0; cum->regno = 0; + cfun->machine->arg_reg_available_p = 0; } break; diff --git a/gcc/config/i386/i386.h b/gcc/config/i386/i386.h index 74334ff..0b6e304 100644 --- a/gcc/config/i386/i386.h +++ b/gcc/config/i386/i386.h @@ -2479,6 +2479,9 @@ struct GTY(()) machine_function { /* If true, it is safe to not save/restore DRAP register. */ BOOL_BITFIELD no_drap_save_restore : 1; + /* If true, there is register available for argument passing. */ + BOOL_BITFIELD arg_reg_available_p : 1; + /* During prologue/epilogue generation, the current frame state. Otherwise, the frame state at the end of the prologue. */ struct machine_frame_state fs; diff --git a/gcc/testsuite/gcc.target/i386/pr66819-1.c b/gcc/testsuite/gcc.target/i386/pr66819-1.c new file mode 100644 index 0000000..7c8a1ab --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr66819-1.c @@ -0,0 +1,8 @@ +/* { dg-do compile { target ia32 } } */ +/* { dg-options "-O2 -mregparm=3" } */ +/* { dg-final { scan-assembler-not "call" } } */ + +void foo(void (*bar)(void)) +{ + bar(); +} diff --git a/gcc/testsuite/gcc.target/i386/pr66819-2.c b/gcc/testsuite/gcc.target/i386/pr66819-2.c new file mode 100644 index 0000000..9de4f97 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr66819-2.c @@ -0,0 +1,8 @@ +/* { dg-do compile { target ia32 } } */ +/* { dg-options "-fPIC -O2 -mregparm=3" } */ +/* { dg-final { scan-assembler-not "call" } } */ + +void foo(void (*bar)(void)) +{ + bar(); +} diff --git a/gcc/testsuite/gcc.target/i386/pr66819-3.c b/gcc/testsuite/gcc.target/i386/pr66819-3.c new file mode 100644 index 0000000..3bc5a34 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr66819-3.c @@ -0,0 +1,10 @@ +/* { dg-do compile { target ia32 } } */ +/* { dg-options "-O2 -mregparm=3" } */ +/* { dg-final { scan-assembler-not "call" } } */ + +void (*bar)(int, int); + +void foo(int i, int j) +{ + bar(i, j); +} diff --git a/gcc/testsuite/gcc.target/i386/pr66819-4.c b/gcc/testsuite/gcc.target/i386/pr66819-4.c new file mode 100644 index 0000000..18b2ccf --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr66819-4.c @@ -0,0 +1,12 @@ +/* { dg-do compile { target ia32 } } */ +/* { dg-options "-O2 -mregparm=3" } */ +/* { dg-final { scan-assembler-not "call" } } */ + +#include <stdarg.h> + +void (*bar)(int, va_list); + +void foo(int i, va_list args) +{ + bar(i, args); +} diff --git a/gcc/testsuite/gcc.target/i386/pr66819-5.c b/gcc/testsuite/gcc.target/i386/pr66819-5.c new file mode 100644 index 0000000..6b019d1 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr66819-5.c @@ -0,0 +1,10 @@ +/* { dg-do compile { target ia32 } } */ +/* { dg-options "-O2 -mregparm=3" } */ +/* { dg-final { scan-assembler "call" } } */ + +void (*bar)(int, int, int); + +void foo(int i, int j, int k) +{ + bar(i, j, k); +} -- 2.4.3 ^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH] PR target/66819: Allow indirect sibcall with register arguments 2015-07-09 10:54 [PATCH] PR target/66819: Allow indirect sibcall with register arguments H.J. Lu @ 2015-07-09 11:04 ` Uros Bizjak 2015-07-09 11:12 ` H.J. Lu 2015-07-10 16:30 ` Uros Bizjak 1 sibling, 1 reply; 8+ messages in thread From: Uros Bizjak @ 2015-07-09 11:04 UTC (permalink / raw) To: H.J. Lu; +Cc: gcc-patches On Thu, Jul 9, 2015 at 12:54 PM, H.J. Lu <hjl.tools@gmail.com> wrote: > Indirect sibcall with register arguments is OK when there is register > available for argument passing. > > OK for trunk if there is no regression? > > > H.J. > --- > gcc/ > > PR target/66819 > * config/i386/i386.c (ix86_function_ok_for_sibcall): Allow > indirect sibcall with register arguments if register available > for argument passing. > (init_cumulative_args): Set cfun->machine->arg_reg_available_p > to cum->nregs != 0. > (function_arg_advance_32): Set cfun->machine->arg_reg_available_p > to 0 when setting cum->nregs = 0. > * config/i386/i386.h (machine_function): Add arg_reg_available_p. > > gcc/testsuite/ > > PR target/66819 > * gcc.target/i386/pr66819-1.c: New test. > * gcc.target/i386/pr66819-2.c: Likewise. > * gcc.target/i386/pr66819-3.c: Likewise. > * gcc.target/i386/pr66819-4.c: Likewise. > * gcc.target/i386/pr66819-5.c: Likewise. > --- > gcc/config/i386/i386.c | 15 +++++++++------ > gcc/config/i386/i386.h | 3 +++ > gcc/testsuite/gcc.target/i386/pr66819-1.c | 8 ++++++++ > gcc/testsuite/gcc.target/i386/pr66819-2.c | 8 ++++++++ > gcc/testsuite/gcc.target/i386/pr66819-3.c | 10 ++++++++++ > gcc/testsuite/gcc.target/i386/pr66819-4.c | 12 ++++++++++++ > gcc/testsuite/gcc.target/i386/pr66819-5.c | 10 ++++++++++ > 7 files changed, 60 insertions(+), 6 deletions(-) > create mode 100644 gcc/testsuite/gcc.target/i386/pr66819-1.c > create mode 100644 gcc/testsuite/gcc.target/i386/pr66819-2.c > create mode 100644 gcc/testsuite/gcc.target/i386/pr66819-3.c > create mode 100644 gcc/testsuite/gcc.target/i386/pr66819-4.c > create mode 100644 gcc/testsuite/gcc.target/i386/pr66819-5.c > > diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c > index 54ee6f3..85e59a8 100644 > --- a/gcc/config/i386/i386.c > +++ b/gcc/config/i386/i386.c > @@ -5628,12 +5628,12 @@ ix86_function_ok_for_sibcall (tree decl, tree exp) > if (!decl > || (TARGET_DLLIMPORT_DECL_ATTRIBUTES && DECL_DLLIMPORT_P (decl))) > { > - if (ix86_function_regparm (type, NULL) >= 3) > - { > - /* ??? Need to count the actual number of registers to be used, > - not the possible number of registers. Fix later. */ > - return false; > - } > + /* FIXME: The symbol indirect call doesn't need a > + call-clobbered register. But we don't know if > + this is a symbol indirect call or not here. */ > + if (ix86_function_regparm (type, NULL) >= 3 > + && !cfun->machine->arg_reg_available_p) > + return false; > } > } Why can't we directly look at nregs != 0 in the above code? AFAICS, nregs accurately tracks number of available argument registers. Uros. > @@ -6567,6 +6567,7 @@ init_cumulative_args (CUMULATIVE_ARGS *cum, /* Argument info to initialize */ > ? X86_64_REGPARM_MAX > : X86_64_MS_REGPARM_MAX); > } > + cfun->machine->arg_reg_available_p = cum->nregs != 0; > if (TARGET_SSE) > { > cum->sse_nregs = SSE_REGPARM_MAX; > @@ -6636,6 +6637,7 @@ init_cumulative_args (CUMULATIVE_ARGS *cum, /* Argument info to initialize */ > else > cum->nregs = ix86_function_regparm (fntype, fndecl); > } > + cfun->machine->arg_reg_available_p = cum->nregs != 0; > > /* Set up the number of SSE registers used for passing SFmode > and DFmode arguments. Warn for mismatching ABI. */ > @@ -7584,6 +7586,7 @@ pass_in_reg: > { > cum->nregs = 0; > cum->regno = 0; > + cfun->machine->arg_reg_available_p = 0; > } > break; > > diff --git a/gcc/config/i386/i386.h b/gcc/config/i386/i386.h > index 74334ff..0b6e304 100644 > --- a/gcc/config/i386/i386.h > +++ b/gcc/config/i386/i386.h > @@ -2479,6 +2479,9 @@ struct GTY(()) machine_function { > /* If true, it is safe to not save/restore DRAP register. */ > BOOL_BITFIELD no_drap_save_restore : 1; > > + /* If true, there is register available for argument passing. */ > + BOOL_BITFIELD arg_reg_available_p : 1; > + > /* During prologue/epilogue generation, the current frame state. > Otherwise, the frame state at the end of the prologue. */ > struct machine_frame_state fs; > diff --git a/gcc/testsuite/gcc.target/i386/pr66819-1.c b/gcc/testsuite/gcc.target/i386/pr66819-1.c > new file mode 100644 > index 0000000..7c8a1ab > --- /dev/null > +++ b/gcc/testsuite/gcc.target/i386/pr66819-1.c > @@ -0,0 +1,8 @@ > +/* { dg-do compile { target ia32 } } */ > +/* { dg-options "-O2 -mregparm=3" } */ > +/* { dg-final { scan-assembler-not "call" } } */ > + > +void foo(void (*bar)(void)) > +{ > + bar(); > +} > diff --git a/gcc/testsuite/gcc.target/i386/pr66819-2.c b/gcc/testsuite/gcc.target/i386/pr66819-2.c > new file mode 100644 > index 0000000..9de4f97 > --- /dev/null > +++ b/gcc/testsuite/gcc.target/i386/pr66819-2.c > @@ -0,0 +1,8 @@ > +/* { dg-do compile { target ia32 } } */ > +/* { dg-options "-fPIC -O2 -mregparm=3" } */ > +/* { dg-final { scan-assembler-not "call" } } */ > + > +void foo(void (*bar)(void)) > +{ > + bar(); > +} > diff --git a/gcc/testsuite/gcc.target/i386/pr66819-3.c b/gcc/testsuite/gcc.target/i386/pr66819-3.c > new file mode 100644 > index 0000000..3bc5a34 > --- /dev/null > +++ b/gcc/testsuite/gcc.target/i386/pr66819-3.c > @@ -0,0 +1,10 @@ > +/* { dg-do compile { target ia32 } } */ > +/* { dg-options "-O2 -mregparm=3" } */ > +/* { dg-final { scan-assembler-not "call" } } */ > + > +void (*bar)(int, int); > + > +void foo(int i, int j) > +{ > + bar(i, j); > +} > diff --git a/gcc/testsuite/gcc.target/i386/pr66819-4.c b/gcc/testsuite/gcc.target/i386/pr66819-4.c > new file mode 100644 > index 0000000..18b2ccf > --- /dev/null > +++ b/gcc/testsuite/gcc.target/i386/pr66819-4.c > @@ -0,0 +1,12 @@ > +/* { dg-do compile { target ia32 } } */ > +/* { dg-options "-O2 -mregparm=3" } */ > +/* { dg-final { scan-assembler-not "call" } } */ > + > +#include <stdarg.h> > + > +void (*bar)(int, va_list); > + > +void foo(int i, va_list args) > +{ > + bar(i, args); > +} > diff --git a/gcc/testsuite/gcc.target/i386/pr66819-5.c b/gcc/testsuite/gcc.target/i386/pr66819-5.c > new file mode 100644 > index 0000000..6b019d1 > --- /dev/null > +++ b/gcc/testsuite/gcc.target/i386/pr66819-5.c > @@ -0,0 +1,10 @@ > +/* { dg-do compile { target ia32 } } */ > +/* { dg-options "-O2 -mregparm=3" } */ > +/* { dg-final { scan-assembler "call" } } */ > + > +void (*bar)(int, int, int); > + > +void foo(int i, int j, int k) > +{ > + bar(i, j, k); > +} > -- > 2.4.3 > ^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH] PR target/66819: Allow indirect sibcall with register arguments 2015-07-09 11:04 ` Uros Bizjak @ 2015-07-09 11:12 ` H.J. Lu 0 siblings, 0 replies; 8+ messages in thread From: H.J. Lu @ 2015-07-09 11:12 UTC (permalink / raw) To: Uros Bizjak; +Cc: gcc-patches On Thu, Jul 9, 2015 at 4:04 AM, Uros Bizjak <ubizjak@gmail.com> wrote: > On Thu, Jul 9, 2015 at 12:54 PM, H.J. Lu <hjl.tools@gmail.com> wrote: >> Indirect sibcall with register arguments is OK when there is register >> available for argument passing. >> >> OK for trunk if there is no regression? >> >> >> H.J. >> --- >> gcc/ >> >> PR target/66819 >> * config/i386/i386.c (ix86_function_ok_for_sibcall): Allow >> indirect sibcall with register arguments if register available >> for argument passing. >> (init_cumulative_args): Set cfun->machine->arg_reg_available_p >> to cum->nregs != 0. >> (function_arg_advance_32): Set cfun->machine->arg_reg_available_p >> to 0 when setting cum->nregs = 0. >> * config/i386/i386.h (machine_function): Add arg_reg_available_p. >> >> gcc/testsuite/ >> >> PR target/66819 >> * gcc.target/i386/pr66819-1.c: New test. >> * gcc.target/i386/pr66819-2.c: Likewise. >> * gcc.target/i386/pr66819-3.c: Likewise. >> * gcc.target/i386/pr66819-4.c: Likewise. >> * gcc.target/i386/pr66819-5.c: Likewise. >> --- >> gcc/config/i386/i386.c | 15 +++++++++------ >> gcc/config/i386/i386.h | 3 +++ >> gcc/testsuite/gcc.target/i386/pr66819-1.c | 8 ++++++++ >> gcc/testsuite/gcc.target/i386/pr66819-2.c | 8 ++++++++ >> gcc/testsuite/gcc.target/i386/pr66819-3.c | 10 ++++++++++ >> gcc/testsuite/gcc.target/i386/pr66819-4.c | 12 ++++++++++++ >> gcc/testsuite/gcc.target/i386/pr66819-5.c | 10 ++++++++++ >> 7 files changed, 60 insertions(+), 6 deletions(-) >> create mode 100644 gcc/testsuite/gcc.target/i386/pr66819-1.c >> create mode 100644 gcc/testsuite/gcc.target/i386/pr66819-2.c >> create mode 100644 gcc/testsuite/gcc.target/i386/pr66819-3.c >> create mode 100644 gcc/testsuite/gcc.target/i386/pr66819-4.c >> create mode 100644 gcc/testsuite/gcc.target/i386/pr66819-5.c >> >> diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c >> index 54ee6f3..85e59a8 100644 >> --- a/gcc/config/i386/i386.c >> +++ b/gcc/config/i386/i386.c >> @@ -5628,12 +5628,12 @@ ix86_function_ok_for_sibcall (tree decl, tree exp) >> if (!decl >> || (TARGET_DLLIMPORT_DECL_ATTRIBUTES && DECL_DLLIMPORT_P (decl))) >> { >> - if (ix86_function_regparm (type, NULL) >= 3) >> - { >> - /* ??? Need to count the actual number of registers to be used, >> - not the possible number of registers. Fix later. */ >> - return false; >> - } >> + /* FIXME: The symbol indirect call doesn't need a >> + call-clobbered register. But we don't know if >> + this is a symbol indirect call or not here. */ >> + if (ix86_function_regparm (type, NULL) >= 3 >> + && !cfun->machine->arg_reg_available_p) >> + return false; >> } >> } > > Why can't we directly look at nregs != 0 in the above code? AFAICS, > nregs accurately tracks number of available argument registers. > I tried it first. But nregs isn't accessible from ix86_function_ok_for_sibcall. -- H.J. ^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH] PR target/66819: Allow indirect sibcall with register arguments 2015-07-09 10:54 [PATCH] PR target/66819: Allow indirect sibcall with register arguments H.J. Lu 2015-07-09 11:04 ` Uros Bizjak @ 2015-07-10 16:30 ` Uros Bizjak 2015-07-10 17:10 ` H.J. Lu 1 sibling, 1 reply; 8+ messages in thread From: Uros Bizjak @ 2015-07-10 16:30 UTC (permalink / raw) To: H.J. Lu; +Cc: gcc-patches On Thu, Jul 9, 2015 at 12:54 PM, H.J. Lu <hjl.tools@gmail.com> wrote: > Indirect sibcall with register arguments is OK when there is register > available for argument passing. > > OK for trunk if there is no regression? > > > H.J. > --- > gcc/ > > PR target/66819 > * config/i386/i386.c (ix86_function_ok_for_sibcall): Allow > indirect sibcall with register arguments if register available > for argument passing. > (init_cumulative_args): Set cfun->machine->arg_reg_available_p > to cum->nregs != 0. > (function_arg_advance_32): Set cfun->machine->arg_reg_available_p > to 0 when setting cum->nregs = 0. Do we also need similar functionality for 64bit ABIs? What happens if we are out of argument regs there? > * config/i386/i386.h (machine_function): Add arg_reg_available_p. > > gcc/testsuite/ > > PR target/66819 > * gcc.target/i386/pr66819-1.c: New test. > * gcc.target/i386/pr66819-2.c: Likewise. > * gcc.target/i386/pr66819-3.c: Likewise. > * gcc.target/i386/pr66819-4.c: Likewise. > * gcc.target/i386/pr66819-5.c: Likewise. > --- > gcc/config/i386/i386.c | 15 +++++++++------ > gcc/config/i386/i386.h | 3 +++ > gcc/testsuite/gcc.target/i386/pr66819-1.c | 8 ++++++++ > gcc/testsuite/gcc.target/i386/pr66819-2.c | 8 ++++++++ > gcc/testsuite/gcc.target/i386/pr66819-3.c | 10 ++++++++++ > gcc/testsuite/gcc.target/i386/pr66819-4.c | 12 ++++++++++++ > gcc/testsuite/gcc.target/i386/pr66819-5.c | 10 ++++++++++ > 7 files changed, 60 insertions(+), 6 deletions(-) > create mode 100644 gcc/testsuite/gcc.target/i386/pr66819-1.c > create mode 100644 gcc/testsuite/gcc.target/i386/pr66819-2.c > create mode 100644 gcc/testsuite/gcc.target/i386/pr66819-3.c > create mode 100644 gcc/testsuite/gcc.target/i386/pr66819-4.c > create mode 100644 gcc/testsuite/gcc.target/i386/pr66819-5.c > > diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c > index 54ee6f3..85e59a8 100644 > --- a/gcc/config/i386/i386.c > +++ b/gcc/config/i386/i386.c > @@ -5628,12 +5628,12 @@ ix86_function_ok_for_sibcall (tree decl, tree exp) > if (!decl > || (TARGET_DLLIMPORT_DECL_ATTRIBUTES && DECL_DLLIMPORT_P (decl))) > { > - if (ix86_function_regparm (type, NULL) >= 3) > - { > - /* ??? Need to count the actual number of registers to be used, > - not the possible number of registers. Fix later. */ > - return false; > - } > + /* FIXME: The symbol indirect call doesn't need a > + call-clobbered register. But we don't know if > + this is a symbol indirect call or not here. */ > + if (ix86_function_regparm (type, NULL) >= 3 > + && !cfun->machine->arg_reg_available_p) Isn't enough to look at arg_reg_available here? > + return false; > } > } > > @@ -6567,6 +6567,7 @@ init_cumulative_args (CUMULATIVE_ARGS *cum, /* Argument info to initialize */ > ? X86_64_REGPARM_MAX > : X86_64_MS_REGPARM_MAX); > } > + cfun->machine->arg_reg_available_p = cum->nregs != 0; false instead of 0. This is a boolean. > if (TARGET_SSE) > { > cum->sse_nregs = SSE_REGPARM_MAX; > @@ -6636,6 +6637,7 @@ init_cumulative_args (CUMULATIVE_ARGS *cum, /* Argument info to initialize */ > else > cum->nregs = ix86_function_regparm (fntype, fndecl); > } > + cfun->machine->arg_reg_available_p = cum->nregs != 0; IMO, cum->nregs > 0 would be more descriptive. > /* Set up the number of SSE registers used for passing SFmode > and DFmode arguments. Warn for mismatching ABI. */ > @@ -7584,6 +7586,7 @@ pass_in_reg: > { > cum->nregs = 0; > cum->regno = 0; > + cfun->machine->arg_reg_available_p = 0; > } > break; > > diff --git a/gcc/config/i386/i386.h b/gcc/config/i386/i386.h > index 74334ff..0b6e304 100644 > --- a/gcc/config/i386/i386.h > +++ b/gcc/config/i386/i386.h > @@ -2479,6 +2479,9 @@ struct GTY(()) machine_function { > /* If true, it is safe to not save/restore DRAP register. */ > BOOL_BITFIELD no_drap_save_restore : 1; > > + /* If true, there is register available for argument passing. */ > + BOOL_BITFIELD arg_reg_available_p : 1; This is not a predicate, but a boolean flag. Please remove _p from the name. > + > /* During prologue/epilogue generation, the current frame state. > Otherwise, the frame state at the end of the prologue. */ > struct machine_frame_state fs; > diff --git a/gcc/testsuite/gcc.target/i386/pr66819-1.c b/gcc/testsuite/gcc.target/i386/pr66819-1.c > new file mode 100644 > index 0000000..7c8a1ab > --- /dev/null > +++ b/gcc/testsuite/gcc.target/i386/pr66819-1.c > @@ -0,0 +1,8 @@ > +/* { dg-do compile { target ia32 } } */ > +/* { dg-options "-O2 -mregparm=3" } */ > +/* { dg-final { scan-assembler-not "call" } } */ > + > +void foo(void (*bar)(void)) > +{ > + bar(); > +} > diff --git a/gcc/testsuite/gcc.target/i386/pr66819-2.c b/gcc/testsuite/gcc.target/i386/pr66819-2.c > new file mode 100644 > index 0000000..9de4f97 > --- /dev/null > +++ b/gcc/testsuite/gcc.target/i386/pr66819-2.c > @@ -0,0 +1,8 @@ > +/* { dg-do compile { target ia32 } } */ > +/* { dg-options "-fPIC -O2 -mregparm=3" } */ > +/* { dg-final { scan-assembler-not "call" } } */ > + > +void foo(void (*bar)(void)) > +{ > + bar(); > +} > diff --git a/gcc/testsuite/gcc.target/i386/pr66819-3.c b/gcc/testsuite/gcc.target/i386/pr66819-3.c > new file mode 100644 > index 0000000..3bc5a34 > --- /dev/null > +++ b/gcc/testsuite/gcc.target/i386/pr66819-3.c > @@ -0,0 +1,10 @@ > +/* { dg-do compile { target ia32 } } */ > +/* { dg-options "-O2 -mregparm=3" } */ > +/* { dg-final { scan-assembler-not "call" } } */ > + > +void (*bar)(int, int); > + > +void foo(int i, int j) > +{ > + bar(i, j); > +} > diff --git a/gcc/testsuite/gcc.target/i386/pr66819-4.c b/gcc/testsuite/gcc.target/i386/pr66819-4.c > new file mode 100644 > index 0000000..18b2ccf > --- /dev/null > +++ b/gcc/testsuite/gcc.target/i386/pr66819-4.c > @@ -0,0 +1,12 @@ > +/* { dg-do compile { target ia32 } } */ > +/* { dg-options "-O2 -mregparm=3" } */ > +/* { dg-final { scan-assembler-not "call" } } */ > + > +#include <stdarg.h> > + > +void (*bar)(int, va_list); > + > +void foo(int i, va_list args) > +{ > + bar(i, args); > +} > diff --git a/gcc/testsuite/gcc.target/i386/pr66819-5.c b/gcc/testsuite/gcc.target/i386/pr66819-5.c > new file mode 100644 > index 0000000..6b019d1 > --- /dev/null > +++ b/gcc/testsuite/gcc.target/i386/pr66819-5.c > @@ -0,0 +1,10 @@ > +/* { dg-do compile { target ia32 } } */ > +/* { dg-options "-O2 -mregparm=3" } */ > +/* { dg-final { scan-assembler "call" } } */ > + > +void (*bar)(int, int, int); > + > +void foo(int i, int j, int k) > +{ > + bar(i, j, k); > +} > -- > 2.4.3 > ^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH] PR target/66819: Allow indirect sibcall with register arguments 2015-07-10 16:30 ` Uros Bizjak @ 2015-07-10 17:10 ` H.J. Lu 2015-07-10 17:21 ` Uros Bizjak 0 siblings, 1 reply; 8+ messages in thread From: H.J. Lu @ 2015-07-10 17:10 UTC (permalink / raw) To: Uros Bizjak; +Cc: gcc-patches [-- Attachment #1: Type: text/plain, Size: 4998 bytes --] On Fri, Jul 10, 2015 at 9:30 AM, Uros Bizjak <ubizjak@gmail.com> wrote: > On Thu, Jul 9, 2015 at 12:54 PM, H.J. Lu <hjl.tools@gmail.com> wrote: >> Indirect sibcall with register arguments is OK when there is register >> available for argument passing. >> >> OK for trunk if there is no regression? >> >> >> H.J. >> --- >> gcc/ >> >> PR target/66819 >> * config/i386/i386.c (ix86_function_ok_for_sibcall): Allow >> indirect sibcall with register arguments if register available >> for argument passing. >> (init_cumulative_args): Set cfun->machine->arg_reg_available_p >> to cum->nregs != 0. >> (function_arg_advance_32): Set cfun->machine->arg_reg_available_p >> to 0 when setting cum->nregs = 0. > > Do we also need similar functionality for 64bit ABIs? What happens if > we are out of argument regs there? 64-bit is OK since we have rax, r10 and r11 as scratch registers which aren't used to pass arguments. >> * config/i386/i386.h (machine_function): Add arg_reg_available_p. >> >> gcc/testsuite/ >> >> PR target/66819 >> * gcc.target/i386/pr66819-1.c: New test. >> * gcc.target/i386/pr66819-2.c: Likewise. >> * gcc.target/i386/pr66819-3.c: Likewise. >> * gcc.target/i386/pr66819-4.c: Likewise. >> * gcc.target/i386/pr66819-5.c: Likewise. >> --- >> gcc/config/i386/i386.c | 15 +++++++++------ >> gcc/config/i386/i386.h | 3 +++ >> gcc/testsuite/gcc.target/i386/pr66819-1.c | 8 ++++++++ >> gcc/testsuite/gcc.target/i386/pr66819-2.c | 8 ++++++++ >> gcc/testsuite/gcc.target/i386/pr66819-3.c | 10 ++++++++++ >> gcc/testsuite/gcc.target/i386/pr66819-4.c | 12 ++++++++++++ >> gcc/testsuite/gcc.target/i386/pr66819-5.c | 10 ++++++++++ >> 7 files changed, 60 insertions(+), 6 deletions(-) >> create mode 100644 gcc/testsuite/gcc.target/i386/pr66819-1.c >> create mode 100644 gcc/testsuite/gcc.target/i386/pr66819-2.c >> create mode 100644 gcc/testsuite/gcc.target/i386/pr66819-3.c >> create mode 100644 gcc/testsuite/gcc.target/i386/pr66819-4.c >> create mode 100644 gcc/testsuite/gcc.target/i386/pr66819-5.c >> >> diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c >> index 54ee6f3..85e59a8 100644 >> --- a/gcc/config/i386/i386.c >> +++ b/gcc/config/i386/i386.c >> @@ -5628,12 +5628,12 @@ ix86_function_ok_for_sibcall (tree decl, tree exp) >> if (!decl >> || (TARGET_DLLIMPORT_DECL_ATTRIBUTES && DECL_DLLIMPORT_P (decl))) >> { >> - if (ix86_function_regparm (type, NULL) >= 3) >> - { >> - /* ??? Need to count the actual number of registers to be used, >> - not the possible number of registers. Fix later. */ >> - return false; >> - } >> + /* FIXME: The symbol indirect call doesn't need a >> + call-clobbered register. But we don't know if >> + this is a symbol indirect call or not here. */ >> + if (ix86_function_regparm (type, NULL) >= 3 >> + && !cfun->machine->arg_reg_available_p) > > Isn't enough to look at arg_reg_available here? We need to check ix86_function_regparm since nregs is 0 if -mregparm=N isn't used and pr65753.c will fail. >> + return false; >> } >> } >> >> @@ -6567,6 +6567,7 @@ init_cumulative_args (CUMULATIVE_ARGS *cum, /* Argument info to initialize */ >> ? X86_64_REGPARM_MAX >> : X86_64_MS_REGPARM_MAX); >> } >> + cfun->machine->arg_reg_available_p = cum->nregs != 0; > > false instead of 0. This is a boolean. Updated. >> if (TARGET_SSE) >> { >> cum->sse_nregs = SSE_REGPARM_MAX; >> @@ -6636,6 +6637,7 @@ init_cumulative_args (CUMULATIVE_ARGS *cum, /* Argument info to initialize */ >> else >> cum->nregs = ix86_function_regparm (fntype, fndecl); >> } >> + cfun->machine->arg_reg_available_p = cum->nregs != 0; > > IMO, cum->nregs > 0 would be more descriptive. Updated. >> /* Set up the number of SSE registers used for passing SFmode >> and DFmode arguments. Warn for mismatching ABI. */ >> @@ -7584,6 +7586,7 @@ pass_in_reg: >> { >> cum->nregs = 0; >> cum->regno = 0; >> + cfun->machine->arg_reg_available_p = 0; >> } >> break; >> >> diff --git a/gcc/config/i386/i386.h b/gcc/config/i386/i386.h >> index 74334ff..0b6e304 100644 >> --- a/gcc/config/i386/i386.h >> +++ b/gcc/config/i386/i386.h >> @@ -2479,6 +2479,9 @@ struct GTY(()) machine_function { >> /* If true, it is safe to not save/restore DRAP register. */ >> BOOL_BITFIELD no_drap_save_restore : 1; >> >> + /* If true, there is register available for argument passing. */ >> + BOOL_BITFIELD arg_reg_available_p : 1; > > This is not a predicate, but a boolean flag. Please remove _p from the name. Updated. Here is the updated patch. OK for trunk? Thanks. -- H.J. [-- Attachment #2: 0001-Allow-indirect-sibcall-with-register-arguments.patch --] [-- Type: text/x-patch, Size: 6137 bytes --] From 3bcd6c122684d896840b2feb756e9b9ab8723ecc Mon Sep 17 00:00:00 2001 From: "H.J. Lu" <hjl.tools@gmail.com> Date: Wed, 8 Jul 2015 21:10:25 -0700 Subject: [PATCH] Allow indirect sibcall with register arguments Indirect sibcall with register arguments is OK when there is register available for argument passing. gcc/ PR target/66819 * config/i386/i386.c (ix86_function_ok_for_sibcall): Allow indirect sibcall with register arguments if register available for argument passing. (init_cumulative_args): Set cfun->machine->arg_reg_available to cum->nregs != 0. (function_arg_advance_32): Set cfun->machine->arg_reg_available to 0 when setting cum->nregs = 0. * config/i386/i386.h (machine_function): Add arg_reg_available. gcc/testsuite/ PR target/66819 * gcc.target/i386/pr66819-1.c: New test. * gcc.target/i386/pr66819-2.c: Likewise. * gcc.target/i386/pr66819-3.c: Likewise. * gcc.target/i386/pr66819-4.c: Likewise. * gcc.target/i386/pr66819-5.c: Likewise. --- gcc/config/i386/i386.c | 16 ++++++++++------ gcc/config/i386/i386.h | 3 +++ gcc/testsuite/gcc.target/i386/pr66819-1.c | 8 ++++++++ gcc/testsuite/gcc.target/i386/pr66819-2.c | 8 ++++++++ gcc/testsuite/gcc.target/i386/pr66819-3.c | 10 ++++++++++ gcc/testsuite/gcc.target/i386/pr66819-4.c | 12 ++++++++++++ gcc/testsuite/gcc.target/i386/pr66819-5.c | 10 ++++++++++ 7 files changed, 61 insertions(+), 6 deletions(-) create mode 100644 gcc/testsuite/gcc.target/i386/pr66819-1.c create mode 100644 gcc/testsuite/gcc.target/i386/pr66819-2.c create mode 100644 gcc/testsuite/gcc.target/i386/pr66819-3.c create mode 100644 gcc/testsuite/gcc.target/i386/pr66819-4.c create mode 100644 gcc/testsuite/gcc.target/i386/pr66819-5.c diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c index 57b8acc..c0a1993 100644 --- a/gcc/config/i386/i386.c +++ b/gcc/config/i386/i386.c @@ -5629,12 +5629,12 @@ ix86_function_ok_for_sibcall (tree decl, tree exp) if (!decl || (TARGET_DLLIMPORT_DECL_ATTRIBUTES && DECL_DLLIMPORT_P (decl))) { - if (ix86_function_regparm (type, NULL) >= 3) - { - /* ??? Need to count the actual number of registers to be used, - not the possible number of registers. Fix later. */ - return false; - } + /* ??? The symbol indirect call doesn't need a + call-clobbered register. But we don't know if + this is a symbol indirect call or not here. */ + if (ix86_function_regparm (type, NULL) >= 3 + && !cfun->machine->arg_reg_available) + return false; } } @@ -6610,6 +6610,7 @@ init_cumulative_args (CUMULATIVE_ARGS *cum, /* Argument info to initialize */ if (stdarg_p (fntype)) { cum->nregs = 0; + cfun->machine->arg_reg_available = false; cum->sse_nregs = 0; cum->mmx_nregs = 0; cum->warn_avx512f = false; @@ -6642,6 +6643,8 @@ init_cumulative_args (CUMULATIVE_ARGS *cum, /* Argument info to initialize */ and DFmode arguments. Warn for mismatching ABI. */ cum->float_in_sse = ix86_function_sseregparm (fntype, fndecl, true); } + + cfun->machine->arg_reg_available = (cum->nregs > 0); } /* Return the "natural" mode for TYPE. In most cases, this is just TYPE_MODE. @@ -7584,6 +7587,7 @@ pass_in_reg: if (cum->nregs <= 0) { cum->nregs = 0; + cfun->machine->arg_reg_available = false; cum->regno = 0; } break; diff --git a/gcc/config/i386/i386.h b/gcc/config/i386/i386.h index 74334ff..14006c8 100644 --- a/gcc/config/i386/i386.h +++ b/gcc/config/i386/i386.h @@ -2479,6 +2479,9 @@ struct GTY(()) machine_function { /* If true, it is safe to not save/restore DRAP register. */ BOOL_BITFIELD no_drap_save_restore : 1; + /* If true, there is register available for argument passing. */ + BOOL_BITFIELD arg_reg_available : 1; + /* During prologue/epilogue generation, the current frame state. Otherwise, the frame state at the end of the prologue. */ struct machine_frame_state fs; diff --git a/gcc/testsuite/gcc.target/i386/pr66819-1.c b/gcc/testsuite/gcc.target/i386/pr66819-1.c new file mode 100644 index 0000000..7c8a1ab --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr66819-1.c @@ -0,0 +1,8 @@ +/* { dg-do compile { target ia32 } } */ +/* { dg-options "-O2 -mregparm=3" } */ +/* { dg-final { scan-assembler-not "call" } } */ + +void foo(void (*bar)(void)) +{ + bar(); +} diff --git a/gcc/testsuite/gcc.target/i386/pr66819-2.c b/gcc/testsuite/gcc.target/i386/pr66819-2.c new file mode 100644 index 0000000..9de4f97 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr66819-2.c @@ -0,0 +1,8 @@ +/* { dg-do compile { target ia32 } } */ +/* { dg-options "-fPIC -O2 -mregparm=3" } */ +/* { dg-final { scan-assembler-not "call" } } */ + +void foo(void (*bar)(void)) +{ + bar(); +} diff --git a/gcc/testsuite/gcc.target/i386/pr66819-3.c b/gcc/testsuite/gcc.target/i386/pr66819-3.c new file mode 100644 index 0000000..3bc5a34 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr66819-3.c @@ -0,0 +1,10 @@ +/* { dg-do compile { target ia32 } } */ +/* { dg-options "-O2 -mregparm=3" } */ +/* { dg-final { scan-assembler-not "call" } } */ + +void (*bar)(int, int); + +void foo(int i, int j) +{ + bar(i, j); +} diff --git a/gcc/testsuite/gcc.target/i386/pr66819-4.c b/gcc/testsuite/gcc.target/i386/pr66819-4.c new file mode 100644 index 0000000..18b2ccf --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr66819-4.c @@ -0,0 +1,12 @@ +/* { dg-do compile { target ia32 } } */ +/* { dg-options "-O2 -mregparm=3" } */ +/* { dg-final { scan-assembler-not "call" } } */ + +#include <stdarg.h> + +void (*bar)(int, va_list); + +void foo(int i, va_list args) +{ + bar(i, args); +} diff --git a/gcc/testsuite/gcc.target/i386/pr66819-5.c b/gcc/testsuite/gcc.target/i386/pr66819-5.c new file mode 100644 index 0000000..6b019d1 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr66819-5.c @@ -0,0 +1,10 @@ +/* { dg-do compile { target ia32 } } */ +/* { dg-options "-O2 -mregparm=3" } */ +/* { dg-final { scan-assembler "call" } } */ + +void (*bar)(int, int, int); + +void foo(int i, int j, int k) +{ + bar(i, j, k); +} -- 2.4.3 ^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH] PR target/66819: Allow indirect sibcall with register arguments 2015-07-10 17:10 ` H.J. Lu @ 2015-07-10 17:21 ` Uros Bizjak 2015-07-10 17:58 ` H.J. Lu 0 siblings, 1 reply; 8+ messages in thread From: Uros Bizjak @ 2015-07-10 17:21 UTC (permalink / raw) To: H.J. Lu; +Cc: gcc-patches On Fri, Jul 10, 2015 at 7:10 PM, H.J. Lu <hjl.tools@gmail.com> wrote: > On Fri, Jul 10, 2015 at 9:30 AM, Uros Bizjak <ubizjak@gmail.com> wrote: >> On Thu, Jul 9, 2015 at 12:54 PM, H.J. Lu <hjl.tools@gmail.com> wrote: >>> Indirect sibcall with register arguments is OK when there is register >>> available for argument passing. >>> >>> OK for trunk if there is no regression? >>> >>> >>> H.J. >>> --- >>> gcc/ >>> >>> PR target/66819 >>> * config/i386/i386.c (ix86_function_ok_for_sibcall): Allow >>> indirect sibcall with register arguments if register available >>> for argument passing. >>> (init_cumulative_args): Set cfun->machine->arg_reg_available_p >>> to cum->nregs != 0. Please update the above entry for nregs > 0. >>> (function_arg_advance_32): Set cfun->machine->arg_reg_available_p >>> to 0 when setting cum->nregs = 0. >> >> Do we also need similar functionality for 64bit ABIs? What happens if >> we are out of argument regs there? > > 64-bit is OK since we have rax, r10 and r11 as scratch registers which > aren't used to pass arguments. Maybe this fact should be added as a comment in some appropriate place. >>> * config/i386/i386.h (machine_function): Add arg_reg_available_p. >>> >>> gcc/testsuite/ >>> >>> PR target/66819 >>> * gcc.target/i386/pr66819-1.c: New test. >>> * gcc.target/i386/pr66819-2.c: Likewise. >>> * gcc.target/i386/pr66819-3.c: Likewise. >>> * gcc.target/i386/pr66819-4.c: Likewise. >>> * gcc.target/i386/pr66819-5.c: Likewise. >>> --- >>> gcc/config/i386/i386.c | 15 +++++++++------ >>> gcc/config/i386/i386.h | 3 +++ >>> gcc/testsuite/gcc.target/i386/pr66819-1.c | 8 ++++++++ >>> gcc/testsuite/gcc.target/i386/pr66819-2.c | 8 ++++++++ >>> gcc/testsuite/gcc.target/i386/pr66819-3.c | 10 ++++++++++ >>> gcc/testsuite/gcc.target/i386/pr66819-4.c | 12 ++++++++++++ >>> gcc/testsuite/gcc.target/i386/pr66819-5.c | 10 ++++++++++ >>> 7 files changed, 60 insertions(+), 6 deletions(-) >>> create mode 100644 gcc/testsuite/gcc.target/i386/pr66819-1.c >>> create mode 100644 gcc/testsuite/gcc.target/i386/pr66819-2.c >>> create mode 100644 gcc/testsuite/gcc.target/i386/pr66819-3.c >>> create mode 100644 gcc/testsuite/gcc.target/i386/pr66819-4.c >>> create mode 100644 gcc/testsuite/gcc.target/i386/pr66819-5.c >>> >>> diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c >>> index 54ee6f3..85e59a8 100644 >>> --- a/gcc/config/i386/i386.c >>> +++ b/gcc/config/i386/i386.c >>> @@ -5628,12 +5628,12 @@ ix86_function_ok_for_sibcall (tree decl, tree exp) >>> if (!decl >>> || (TARGET_DLLIMPORT_DECL_ATTRIBUTES && DECL_DLLIMPORT_P (decl))) >>> { >>> - if (ix86_function_regparm (type, NULL) >= 3) >>> - { >>> - /* ??? Need to count the actual number of registers to be used, >>> - not the possible number of registers. Fix later. */ >>> - return false; >>> - } >>> + /* FIXME: The symbol indirect call doesn't need a >>> + call-clobbered register. But we don't know if >>> + this is a symbol indirect call or not here. */ >>> + if (ix86_function_regparm (type, NULL) >= 3 >>> + && !cfun->machine->arg_reg_available_p) >> >> Isn't enough to look at arg_reg_available here? > > We need to check ix86_function_regparm since nregs is 0 if > -mregparm=N isn't used and pr65753.c will fail. OK. Please add this comment, is not that obvious. > >>> + return false; >>> } >>> } >>> >>> @@ -6567,6 +6567,7 @@ init_cumulative_args (CUMULATIVE_ARGS *cum, /* Argument info to initialize */ >>> ? X86_64_REGPARM_MAX >>> : X86_64_MS_REGPARM_MAX); >>> } >>> + cfun->machine->arg_reg_available_p = cum->nregs != 0; >> >> false instead of 0. This is a boolean. > > Updated. > >>> if (TARGET_SSE) >>> { >>> cum->sse_nregs = SSE_REGPARM_MAX; >>> @@ -6636,6 +6637,7 @@ init_cumulative_args (CUMULATIVE_ARGS *cum, /* Argument info to initialize */ >>> else >>> cum->nregs = ix86_function_regparm (fntype, fndecl); >>> } >>> + cfun->machine->arg_reg_available_p = cum->nregs != 0; >> >> IMO, cum->nregs > 0 would be more descriptive. > > Updated. > >>> /* Set up the number of SSE registers used for passing SFmode >>> and DFmode arguments. Warn for mismatching ABI. */ >>> @@ -7584,6 +7586,7 @@ pass_in_reg: >>> { >>> cum->nregs = 0; >>> cum->regno = 0; >>> + cfun->machine->arg_reg_available_p = 0; >>> } >>> break; >>> >>> diff --git a/gcc/config/i386/i386.h b/gcc/config/i386/i386.h >>> index 74334ff..0b6e304 100644 >>> --- a/gcc/config/i386/i386.h >>> +++ b/gcc/config/i386/i386.h >>> @@ -2479,6 +2479,9 @@ struct GTY(()) machine_function { >>> /* If true, it is safe to not save/restore DRAP register. */ >>> BOOL_BITFIELD no_drap_save_restore : 1; >>> >>> + /* If true, there is register available for argument passing. */ >>> + BOOL_BITFIELD arg_reg_available_p : 1; >> >> This is not a predicate, but a boolean flag. Please remove _p from the name. > > Updated. > > Here is the updated patch. OK for trunk? OK with a small comment additions. + /* If true, there is register available for argument passing. */ + BOOL_BITFIELD arg_reg_available : 1; + Please mention here that this is for 32bit targets only. Thanks, Uros. ^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH] PR target/66819: Allow indirect sibcall with register arguments 2015-07-10 17:21 ` Uros Bizjak @ 2015-07-10 17:58 ` H.J. Lu 2015-07-10 19:54 ` Uros Bizjak 0 siblings, 1 reply; 8+ messages in thread From: H.J. Lu @ 2015-07-10 17:58 UTC (permalink / raw) To: Uros Bizjak; +Cc: gcc-patches [-- Attachment #1: Type: text/plain, Size: 5842 bytes --] On Fri, Jul 10, 2015 at 10:21 AM, Uros Bizjak <ubizjak@gmail.com> wrote: > On Fri, Jul 10, 2015 at 7:10 PM, H.J. Lu <hjl.tools@gmail.com> wrote: >> On Fri, Jul 10, 2015 at 9:30 AM, Uros Bizjak <ubizjak@gmail.com> wrote: >>> On Thu, Jul 9, 2015 at 12:54 PM, H.J. Lu <hjl.tools@gmail.com> wrote: >>>> Indirect sibcall with register arguments is OK when there is register >>>> available for argument passing. >>>> >>>> OK for trunk if there is no regression? >>>> >>>> >>>> H.J. >>>> --- >>>> gcc/ >>>> >>>> PR target/66819 >>>> * config/i386/i386.c (ix86_function_ok_for_sibcall): Allow >>>> indirect sibcall with register arguments if register available >>>> for argument passing. >>>> (init_cumulative_args): Set cfun->machine->arg_reg_available_p >>>> to cum->nregs != 0. > > Please update the above entry for nregs > 0. > >>>> (function_arg_advance_32): Set cfun->machine->arg_reg_available_p >>>> to 0 when setting cum->nregs = 0. >>> >>> Do we also need similar functionality for 64bit ABIs? What happens if >>> we are out of argument regs there? >> >> 64-bit is OK since we have rax, r10 and r11 as scratch registers which >> aren't used to pass arguments. > > Maybe this fact should be added as a comment in some appropriate place. > >>>> * config/i386/i386.h (machine_function): Add arg_reg_available_p. >>>> >>>> gcc/testsuite/ >>>> >>>> PR target/66819 >>>> * gcc.target/i386/pr66819-1.c: New test. >>>> * gcc.target/i386/pr66819-2.c: Likewise. >>>> * gcc.target/i386/pr66819-3.c: Likewise. >>>> * gcc.target/i386/pr66819-4.c: Likewise. >>>> * gcc.target/i386/pr66819-5.c: Likewise. >>>> --- >>>> gcc/config/i386/i386.c | 15 +++++++++------ >>>> gcc/config/i386/i386.h | 3 +++ >>>> gcc/testsuite/gcc.target/i386/pr66819-1.c | 8 ++++++++ >>>> gcc/testsuite/gcc.target/i386/pr66819-2.c | 8 ++++++++ >>>> gcc/testsuite/gcc.target/i386/pr66819-3.c | 10 ++++++++++ >>>> gcc/testsuite/gcc.target/i386/pr66819-4.c | 12 ++++++++++++ >>>> gcc/testsuite/gcc.target/i386/pr66819-5.c | 10 ++++++++++ >>>> 7 files changed, 60 insertions(+), 6 deletions(-) >>>> create mode 100644 gcc/testsuite/gcc.target/i386/pr66819-1.c >>>> create mode 100644 gcc/testsuite/gcc.target/i386/pr66819-2.c >>>> create mode 100644 gcc/testsuite/gcc.target/i386/pr66819-3.c >>>> create mode 100644 gcc/testsuite/gcc.target/i386/pr66819-4.c >>>> create mode 100644 gcc/testsuite/gcc.target/i386/pr66819-5.c >>>> >>>> diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c >>>> index 54ee6f3..85e59a8 100644 >>>> --- a/gcc/config/i386/i386.c >>>> +++ b/gcc/config/i386/i386.c >>>> @@ -5628,12 +5628,12 @@ ix86_function_ok_for_sibcall (tree decl, tree exp) >>>> if (!decl >>>> || (TARGET_DLLIMPORT_DECL_ATTRIBUTES && DECL_DLLIMPORT_P (decl))) >>>> { >>>> - if (ix86_function_regparm (type, NULL) >= 3) >>>> - { >>>> - /* ??? Need to count the actual number of registers to be used, >>>> - not the possible number of registers. Fix later. */ >>>> - return false; >>>> - } >>>> + /* FIXME: The symbol indirect call doesn't need a >>>> + call-clobbered register. But we don't know if >>>> + this is a symbol indirect call or not here. */ >>>> + if (ix86_function_regparm (type, NULL) >= 3 >>>> + && !cfun->machine->arg_reg_available_p) >>> >>> Isn't enough to look at arg_reg_available here? >> >> We need to check ix86_function_regparm since nregs is 0 if >> -mregparm=N isn't used and pr65753.c will fail. > > OK. Please add this comment, is not that obvious. > >> >>>> + return false; >>>> } >>>> } >>>> >>>> @@ -6567,6 +6567,7 @@ init_cumulative_args (CUMULATIVE_ARGS *cum, /* Argument info to initialize */ >>>> ? X86_64_REGPARM_MAX >>>> : X86_64_MS_REGPARM_MAX); >>>> } >>>> + cfun->machine->arg_reg_available_p = cum->nregs != 0; >>> >>> false instead of 0. This is a boolean. >> >> Updated. >> >>>> if (TARGET_SSE) >>>> { >>>> cum->sse_nregs = SSE_REGPARM_MAX; >>>> @@ -6636,6 +6637,7 @@ init_cumulative_args (CUMULATIVE_ARGS *cum, /* Argument info to initialize */ >>>> else >>>> cum->nregs = ix86_function_regparm (fntype, fndecl); >>>> } >>>> + cfun->machine->arg_reg_available_p = cum->nregs != 0; >>> >>> IMO, cum->nregs > 0 would be more descriptive. >> >> Updated. >> >>>> /* Set up the number of SSE registers used for passing SFmode >>>> and DFmode arguments. Warn for mismatching ABI. */ >>>> @@ -7584,6 +7586,7 @@ pass_in_reg: >>>> { >>>> cum->nregs = 0; >>>> cum->regno = 0; >>>> + cfun->machine->arg_reg_available_p = 0; >>>> } >>>> break; >>>> >>>> diff --git a/gcc/config/i386/i386.h b/gcc/config/i386/i386.h >>>> index 74334ff..0b6e304 100644 >>>> --- a/gcc/config/i386/i386.h >>>> +++ b/gcc/config/i386/i386.h >>>> @@ -2479,6 +2479,9 @@ struct GTY(()) machine_function { >>>> /* If true, it is safe to not save/restore DRAP register. */ >>>> BOOL_BITFIELD no_drap_save_restore : 1; >>>> >>>> + /* If true, there is register available for argument passing. */ >>>> + BOOL_BITFIELD arg_reg_available_p : 1; >>> >>> This is not a predicate, but a boolean flag. Please remove _p from the name. >> >> Updated. >> >> Here is the updated patch. OK for trunk? > > OK with a small comment additions. > > + /* If true, there is register available for argument passing. */ > + BOOL_BITFIELD arg_reg_available : 1; > + > > Please mention here that this is for 32bit targets only. > Updated. Is this one OK? Thanks. -- H.J. [-- Attachment #2: 0001-Allow-indirect-sibcall-with-register-arguments.patch --] [-- Type: text/x-patch, Size: 6807 bytes --] From 528ddcbfa2d66c6b34dea88d9ad64593be89159e Mon Sep 17 00:00:00 2001 From: "H.J. Lu" <hjl.tools@gmail.com> Date: Wed, 8 Jul 2015 21:10:25 -0700 Subject: [PATCH] Allow indirect sibcall with register arguments Indirect sibcall with register arguments is OK when there is register available for argument passing. gcc/ PR target/66819 * config/i386/i386.c (ix86_function_ok_for_sibcall): Allow indirect sibcall with register arguments if register available for argument passing. (init_cumulative_args): Set cfun->machine->arg_reg_available to (cum->nregs > 0) or to true if function has a variable argument list. (function_arg_advance_32): Set cfun->machine->arg_reg_available to false if cum->nregs <= 0. * config/i386/i386.h (machine_function): Add arg_reg_available. gcc/testsuite/ PR target/66819 * gcc.target/i386/pr66819-1.c: New test. * gcc.target/i386/pr66819-2.c: Likewise. * gcc.target/i386/pr66819-3.c: Likewise. * gcc.target/i386/pr66819-4.c: Likewise. * gcc.target/i386/pr66819-5.c: Likewise. --- gcc/config/i386/i386.c | 23 +++++++++++++++++------ gcc/config/i386/i386.h | 7 +++++++ gcc/testsuite/gcc.target/i386/pr66819-1.c | 8 ++++++++ gcc/testsuite/gcc.target/i386/pr66819-2.c | 8 ++++++++ gcc/testsuite/gcc.target/i386/pr66819-3.c | 10 ++++++++++ gcc/testsuite/gcc.target/i386/pr66819-4.c | 12 ++++++++++++ gcc/testsuite/gcc.target/i386/pr66819-5.c | 10 ++++++++++ 7 files changed, 72 insertions(+), 6 deletions(-) create mode 100644 gcc/testsuite/gcc.target/i386/pr66819-1.c create mode 100644 gcc/testsuite/gcc.target/i386/pr66819-2.c create mode 100644 gcc/testsuite/gcc.target/i386/pr66819-3.c create mode 100644 gcc/testsuite/gcc.target/i386/pr66819-4.c create mode 100644 gcc/testsuite/gcc.target/i386/pr66819-5.c diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c index 6929caf..0f96452 100644 --- a/gcc/config/i386/i386.c +++ b/gcc/config/i386/i386.c @@ -5629,12 +5629,16 @@ ix86_function_ok_for_sibcall (tree decl, tree exp) if (!decl || (TARGET_DLLIMPORT_DECL_ATTRIBUTES && DECL_DLLIMPORT_P (decl))) { - if (ix86_function_regparm (type, NULL) >= 3) - { - /* ??? Need to count the actual number of registers to be used, - not the possible number of registers. Fix later. */ - return false; - } + /* Check if regparm >= 3 since arg_reg_available is set to + false if regparm == 0. If regparm is 1 or 2, there is + always a call-clobbered register available. + + ??? The symbol indirect call doesn't need a call-clobbered + register. But we don't know if this is a symbol indirect + call or not here. */ + if (ix86_function_regparm (type, NULL) >= 3 + && !cfun->machine->arg_reg_available) + return false; } } @@ -6610,6 +6614,10 @@ init_cumulative_args (CUMULATIVE_ARGS *cum, /* Argument info to initialize */ if (stdarg_p (fntype)) { cum->nregs = 0; + /* Since in 32-bit, variable arguments are always passed on + stack, there is scratch register available for indirect + sibcall. */ + cfun->machine->arg_reg_available = true; cum->sse_nregs = 0; cum->mmx_nregs = 0; cum->warn_avx512f = false; @@ -6642,6 +6650,8 @@ init_cumulative_args (CUMULATIVE_ARGS *cum, /* Argument info to initialize */ and DFmode arguments. Warn for mismatching ABI. */ cum->float_in_sse = ix86_function_sseregparm (fntype, fndecl, true); } + + cfun->machine->arg_reg_available = (cum->nregs > 0); } /* Return the "natural" mode for TYPE. In most cases, this is just TYPE_MODE. @@ -7584,6 +7594,7 @@ pass_in_reg: if (cum->nregs <= 0) { cum->nregs = 0; + cfun->machine->arg_reg_available = false; cum->regno = 0; } break; diff --git a/gcc/config/i386/i386.h b/gcc/config/i386/i386.h index 74334ff..0fcf391 100644 --- a/gcc/config/i386/i386.h +++ b/gcc/config/i386/i386.h @@ -2479,6 +2479,13 @@ struct GTY(()) machine_function { /* If true, it is safe to not save/restore DRAP register. */ BOOL_BITFIELD no_drap_save_restore : 1; + /* If true, there is register available for argument passing. This + is used only in ix86_function_ok_for_sibcall by 32-bit to determine + if there is scratch register available for indirect sibcall. In + 64-bit, rax, r10 and r11 are scratch registers which aren't used to + pass arguments and can be used for indirect sibcall. */ + BOOL_BITFIELD arg_reg_available : 1; + /* During prologue/epilogue generation, the current frame state. Otherwise, the frame state at the end of the prologue. */ struct machine_frame_state fs; diff --git a/gcc/testsuite/gcc.target/i386/pr66819-1.c b/gcc/testsuite/gcc.target/i386/pr66819-1.c new file mode 100644 index 0000000..7c8a1ab --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr66819-1.c @@ -0,0 +1,8 @@ +/* { dg-do compile { target ia32 } } */ +/* { dg-options "-O2 -mregparm=3" } */ +/* { dg-final { scan-assembler-not "call" } } */ + +void foo(void (*bar)(void)) +{ + bar(); +} diff --git a/gcc/testsuite/gcc.target/i386/pr66819-2.c b/gcc/testsuite/gcc.target/i386/pr66819-2.c new file mode 100644 index 0000000..9de4f97 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr66819-2.c @@ -0,0 +1,8 @@ +/* { dg-do compile { target ia32 } } */ +/* { dg-options "-fPIC -O2 -mregparm=3" } */ +/* { dg-final { scan-assembler-not "call" } } */ + +void foo(void (*bar)(void)) +{ + bar(); +} diff --git a/gcc/testsuite/gcc.target/i386/pr66819-3.c b/gcc/testsuite/gcc.target/i386/pr66819-3.c new file mode 100644 index 0000000..3bc5a34 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr66819-3.c @@ -0,0 +1,10 @@ +/* { dg-do compile { target ia32 } } */ +/* { dg-options "-O2 -mregparm=3" } */ +/* { dg-final { scan-assembler-not "call" } } */ + +void (*bar)(int, int); + +void foo(int i, int j) +{ + bar(i, j); +} diff --git a/gcc/testsuite/gcc.target/i386/pr66819-4.c b/gcc/testsuite/gcc.target/i386/pr66819-4.c new file mode 100644 index 0000000..18b2ccf --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr66819-4.c @@ -0,0 +1,12 @@ +/* { dg-do compile { target ia32 } } */ +/* { dg-options "-O2 -mregparm=3" } */ +/* { dg-final { scan-assembler-not "call" } } */ + +#include <stdarg.h> + +void (*bar)(int, va_list); + +void foo(int i, va_list args) +{ + bar(i, args); +} diff --git a/gcc/testsuite/gcc.target/i386/pr66819-5.c b/gcc/testsuite/gcc.target/i386/pr66819-5.c new file mode 100644 index 0000000..6b019d1 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr66819-5.c @@ -0,0 +1,10 @@ +/* { dg-do compile { target ia32 } } */ +/* { dg-options "-O2 -mregparm=3" } */ +/* { dg-final { scan-assembler "call" } } */ + +void (*bar)(int, int, int); + +void foo(int i, int j, int k) +{ + bar(i, j, k); +} -- 2.4.3 ^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH] PR target/66819: Allow indirect sibcall with register arguments 2015-07-10 17:58 ` H.J. Lu @ 2015-07-10 19:54 ` Uros Bizjak 0 siblings, 0 replies; 8+ messages in thread From: Uros Bizjak @ 2015-07-10 19:54 UTC (permalink / raw) To: H.J. Lu; +Cc: gcc-patches On Fri, Jul 10, 2015 at 7:58 PM, H.J. Lu <hjl.tools@gmail.com> wrote: > On Fri, Jul 10, 2015 at 10:21 AM, Uros Bizjak <ubizjak@gmail.com> wrote: >> On Fri, Jul 10, 2015 at 7:10 PM, H.J. Lu <hjl.tools@gmail.com> wrote: >>> On Fri, Jul 10, 2015 at 9:30 AM, Uros Bizjak <ubizjak@gmail.com> wrote: >>>> On Thu, Jul 9, 2015 at 12:54 PM, H.J. Lu <hjl.tools@gmail.com> wrote: >>>>> Indirect sibcall with register arguments is OK when there is register >>>>> available for argument passing. >>>>> >>>>> OK for trunk if there is no regression? >>>>> >>>>> >>>>> H.J. >>>>> --- >>>>> gcc/ >>>>> >>>>> PR target/66819 >>>>> * config/i386/i386.c (ix86_function_ok_for_sibcall): Allow >>>>> indirect sibcall with register arguments if register available >>>>> for argument passing. >>>>> (init_cumulative_args): Set cfun->machine->arg_reg_available_p >>>>> to cum->nregs != 0. >> >> Please update the above entry for nregs > 0. >> >>>>> (function_arg_advance_32): Set cfun->machine->arg_reg_available_p >>>>> to 0 when setting cum->nregs = 0. >>>> >>>> Do we also need similar functionality for 64bit ABIs? What happens if >>>> we are out of argument regs there? >>> >>> 64-bit is OK since we have rax, r10 and r11 as scratch registers which >>> aren't used to pass arguments. >> >> Maybe this fact should be added as a comment in some appropriate place. >> >>>>> * config/i386/i386.h (machine_function): Add arg_reg_available_p. >>>>> >>>>> gcc/testsuite/ >>>>> >>>>> PR target/66819 >>>>> * gcc.target/i386/pr66819-1.c: New test. >>>>> * gcc.target/i386/pr66819-2.c: Likewise. >>>>> * gcc.target/i386/pr66819-3.c: Likewise. >>>>> * gcc.target/i386/pr66819-4.c: Likewise. >>>>> * gcc.target/i386/pr66819-5.c: Likewise. >>>>> --- >>>>> gcc/config/i386/i386.c | 15 +++++++++------ >>>>> gcc/config/i386/i386.h | 3 +++ >>>>> gcc/testsuite/gcc.target/i386/pr66819-1.c | 8 ++++++++ >>>>> gcc/testsuite/gcc.target/i386/pr66819-2.c | 8 ++++++++ >>>>> gcc/testsuite/gcc.target/i386/pr66819-3.c | 10 ++++++++++ >>>>> gcc/testsuite/gcc.target/i386/pr66819-4.c | 12 ++++++++++++ >>>>> gcc/testsuite/gcc.target/i386/pr66819-5.c | 10 ++++++++++ >>>>> 7 files changed, 60 insertions(+), 6 deletions(-) >>>>> create mode 100644 gcc/testsuite/gcc.target/i386/pr66819-1.c >>>>> create mode 100644 gcc/testsuite/gcc.target/i386/pr66819-2.c >>>>> create mode 100644 gcc/testsuite/gcc.target/i386/pr66819-3.c >>>>> create mode 100644 gcc/testsuite/gcc.target/i386/pr66819-4.c >>>>> create mode 100644 gcc/testsuite/gcc.target/i386/pr66819-5.c >>>>> >>>>> diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c >>>>> index 54ee6f3..85e59a8 100644 >>>>> --- a/gcc/config/i386/i386.c >>>>> +++ b/gcc/config/i386/i386.c >>>>> @@ -5628,12 +5628,12 @@ ix86_function_ok_for_sibcall (tree decl, tree exp) >>>>> if (!decl >>>>> || (TARGET_DLLIMPORT_DECL_ATTRIBUTES && DECL_DLLIMPORT_P (decl))) >>>>> { >>>>> - if (ix86_function_regparm (type, NULL) >= 3) >>>>> - { >>>>> - /* ??? Need to count the actual number of registers to be used, >>>>> - not the possible number of registers. Fix later. */ >>>>> - return false; >>>>> - } >>>>> + /* FIXME: The symbol indirect call doesn't need a >>>>> + call-clobbered register. But we don't know if >>>>> + this is a symbol indirect call or not here. */ >>>>> + if (ix86_function_regparm (type, NULL) >= 3 >>>>> + && !cfun->machine->arg_reg_available_p) >>>> >>>> Isn't enough to look at arg_reg_available here? >>> >>> We need to check ix86_function_regparm since nregs is 0 if >>> -mregparm=N isn't used and pr65753.c will fail. >> >> OK. Please add this comment, is not that obvious. >> >>> >>>>> + return false; >>>>> } >>>>> } >>>>> >>>>> @@ -6567,6 +6567,7 @@ init_cumulative_args (CUMULATIVE_ARGS *cum, /* Argument info to initialize */ >>>>> ? X86_64_REGPARM_MAX >>>>> : X86_64_MS_REGPARM_MAX); >>>>> } >>>>> + cfun->machine->arg_reg_available_p = cum->nregs != 0; >>>> >>>> false instead of 0. This is a boolean. >>> >>> Updated. >>> >>>>> if (TARGET_SSE) >>>>> { >>>>> cum->sse_nregs = SSE_REGPARM_MAX; >>>>> @@ -6636,6 +6637,7 @@ init_cumulative_args (CUMULATIVE_ARGS *cum, /* Argument info to initialize */ >>>>> else >>>>> cum->nregs = ix86_function_regparm (fntype, fndecl); >>>>> } >>>>> + cfun->machine->arg_reg_available_p = cum->nregs != 0; >>>> >>>> IMO, cum->nregs > 0 would be more descriptive. >>> >>> Updated. >>> >>>>> /* Set up the number of SSE registers used for passing SFmode >>>>> and DFmode arguments. Warn for mismatching ABI. */ >>>>> @@ -7584,6 +7586,7 @@ pass_in_reg: >>>>> { >>>>> cum->nregs = 0; >>>>> cum->regno = 0; >>>>> + cfun->machine->arg_reg_available_p = 0; >>>>> } >>>>> break; >>>>> >>>>> diff --git a/gcc/config/i386/i386.h b/gcc/config/i386/i386.h >>>>> index 74334ff..0b6e304 100644 >>>>> --- a/gcc/config/i386/i386.h >>>>> +++ b/gcc/config/i386/i386.h >>>>> @@ -2479,6 +2479,9 @@ struct GTY(()) machine_function { >>>>> /* If true, it is safe to not save/restore DRAP register. */ >>>>> BOOL_BITFIELD no_drap_save_restore : 1; >>>>> >>>>> + /* If true, there is register available for argument passing. */ >>>>> + BOOL_BITFIELD arg_reg_available_p : 1; >>>> >>>> This is not a predicate, but a boolean flag. Please remove _p from the name. >>> >>> Updated. >>> >>> Here is the updated patch. OK for trunk? >> >> OK with a small comment additions. >> >> + /* If true, there is register available for argument passing. */ >> + BOOL_BITFIELD arg_reg_available : 1; >> + >> >> Please mention here that this is for 32bit targets only. >> > > Updated. Is this one OK? LGTM. OK for mainline. Thanks, Uros. ^ permalink raw reply [flat|nested] 8+ messages in thread
end of thread, other threads:[~2015-07-10 19:54 UTC | newest] Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2015-07-09 10:54 [PATCH] PR target/66819: Allow indirect sibcall with register arguments H.J. Lu 2015-07-09 11:04 ` Uros Bizjak 2015-07-09 11:12 ` H.J. Lu 2015-07-10 16:30 ` Uros Bizjak 2015-07-10 17:10 ` H.J. Lu 2015-07-10 17:21 ` Uros Bizjak 2015-07-10 17:58 ` H.J. Lu 2015-07-10 19:54 ` Uros Bizjak
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).