Re: Ping : [PATCH] [gcc, combine] PR46164: Don't combine the insns if a volatile register is contained.

2015-02-26 Thread Terry Guo
On Thu, Feb 26, 2015 at 1:55 PM, Segher Boessenkool
seg...@kernel.crashing.org wrote:
 On Tue, Feb 17, 2015 at 11:39:34AM +0800, Terry Guo wrote:
 On Sun, Feb 15, 2015 at 7:35 PM, Segher Boessenkool
 seg...@kernel.crashing.org wrote:
  Hi Terry,
 
  I still think this is stage1 material.
 
  +  /* Don't combine if dest contains a user specified register and i3 
  contains
  + ASM_OPERANDS, because the user specified register (same with dest) 
  in i3
  + would be replaced by the src of insn which might be different with
  + the user's expectation.  */
 
  Do not eliminate a register asm in an asm input or similar?  Text
  explaining why REG_USERVAR_P  HARD_REGISTER_P works here would be
  good to have, too.

 diff --git a/gcc/combine.c b/gcc/combine.c
 index f779117..aeb2854 100644
 --- a/gcc/combine.c
 +++ b/gcc/combine.c
 @@ -1779,7 +1779,7 @@ can_combine_p (rtx_insn *insn, rtx_insn *i3, rtx_insn 
 *pred ATTRIBUTE_UNUSED,
  {
int i;
const_rtx set = 0;
 -  rtx src, dest;
 +  rtx src, dest, asm_op;
rtx_insn *p;
  #ifdef AUTO_INC_DEC
rtx link;
 @@ -1914,6 +1914,14 @@ can_combine_p (rtx_insn *insn, rtx_insn *i3, rtx_insn 
 *pred ATTRIBUTE_UNUSED,
set = expand_field_assignment (set);
src = SET_SRC (set), dest = SET_DEST (set);

 +  /* Use REG_USERVAR_P and HARD_REGISTER_P to check whether DEST is a user
 + specified register, and do not eliminate such register if it is in an
 + asm input because we may end up with something different with user's
 + expectation.  */

 That doesn't explain why this will hit (almost) only on register asms.
 The user's expectation doesn't matter that much either: GCC would violate
 its own documentation / promises, that matters more ;-)

 +  if (REG_P (dest)  REG_USERVAR_P (dest)  HARD_REGISTER_P (dest)
 +   ((asm_op = extract_asm_operands (PATTERN (i3))) != NULL))

 You do not need the temporary variable, nor the != 0 or the extra parens;
 just write

   extract_asm_operands (PATTERN (i3))

 Cheers,


 Segher

Thanks for comments. Patch is updated now. Please review again.

BR,
Terry


pr64818-combine-user-specified-register.patch-5
Description: Binary data


Re: Ping : [PATCH] [gcc, combine] PR46164: Don't combine the insns if a volatile register is contained.

2015-02-25 Thread Segher Boessenkool
On Tue, Feb 17, 2015 at 11:39:34AM +0800, Terry Guo wrote:
 On Sun, Feb 15, 2015 at 7:35 PM, Segher Boessenkool
 seg...@kernel.crashing.org wrote:
  Hi Terry,
 
  I still think this is stage1 material.
 
  +  /* Don't combine if dest contains a user specified register and i3 
  contains
  + ASM_OPERANDS, because the user specified register (same with dest) 
  in i3
  + would be replaced by the src of insn which might be different with
  + the user's expectation.  */
 
  Do not eliminate a register asm in an asm input or similar?  Text
  explaining why REG_USERVAR_P  HARD_REGISTER_P works here would be
  good to have, too.

 diff --git a/gcc/combine.c b/gcc/combine.c
 index f779117..aeb2854 100644
 --- a/gcc/combine.c
 +++ b/gcc/combine.c
 @@ -1779,7 +1779,7 @@ can_combine_p (rtx_insn *insn, rtx_insn *i3, rtx_insn 
 *pred ATTRIBUTE_UNUSED,
  {
int i;
const_rtx set = 0;
 -  rtx src, dest;
 +  rtx src, dest, asm_op;
rtx_insn *p;
  #ifdef AUTO_INC_DEC
rtx link;
 @@ -1914,6 +1914,14 @@ can_combine_p (rtx_insn *insn, rtx_insn *i3, rtx_insn 
 *pred ATTRIBUTE_UNUSED,
set = expand_field_assignment (set);
src = SET_SRC (set), dest = SET_DEST (set);
  
 +  /* Use REG_USERVAR_P and HARD_REGISTER_P to check whether DEST is a user
 + specified register, and do not eliminate such register if it is in an
 + asm input because we may end up with something different with user's
 + expectation.  */

That doesn't explain why this will hit (almost) only on register asms.
The user's expectation doesn't matter that much either: GCC would violate
its own documentation / promises, that matters more ;-)

 +  if (REG_P (dest)  REG_USERVAR_P (dest)  HARD_REGISTER_P (dest)
 +   ((asm_op = extract_asm_operands (PATTERN (i3))) != NULL))

You do not need the temporary variable, nor the != 0 or the extra parens;
just write

  extract_asm_operands (PATTERN (i3))

Cheers,


Segher


Re: Ping : [PATCH] [gcc, combine] PR46164: Don't combine the insns if a volatile register is contained.

2015-02-16 Thread Terry Guo
On Sun, Feb 15, 2015 at 7:35 PM, Segher Boessenkool
seg...@kernel.crashing.org wrote:
 Hi Terry,

 I still think this is stage1 material.

 +  /* Don't combine if dest contains a user specified register and i3 
 contains
 + ASM_OPERANDS, because the user specified register (same with dest) in 
 i3
 + would be replaced by the src of insn which might be different with
 + the user's expectation.  */

 Do not eliminate a register asm in an asm input or similar?  Text
 explaining why REG_USERVAR_P  HARD_REGISTER_P works here would be
 good to have, too.

 +  if (REG_P (dest)  REG_USERVAR_P (dest)  HARD_REGISTER_P (dest)
 +   (GET_CODE (PATTERN (i3)) == SET
 +GET_CODE (SET_SRC (PATTERN (i3))) == ASM_OPERANDS))
 +return 0;

 That works only for asms with exactly one output.  You want
 extract_asm_operands.


 Segher

Thanks Segher. Patch is updated per you suggestion. Is this one ok for stage 1?

BR,
Terry


pr64818-combine-user-specified-register.patch-4
Description: Binary data


Re: Ping : [PATCH] [gcc, combine] PR46164: Don't combine the insns if a volatile register is contained.

2015-02-15 Thread Terry Guo
On Fri, Feb 13, 2015 at 5:06 PM, Richard Sandiford
rdsandif...@googlemail.com wrote:
 Segher Boessenkool seg...@kernel.crashing.org writes:
 On Thu, Feb 12, 2015 at 03:54:21PM +, Richard Sandiford wrote:
 Hale Wang hale.w...@arm.com writes:
  Ping?

 It's not a regression (or is it?), so it is not appropriate for stage4.


  diff --git a/gcc/combine.c b/gcc/combine.c index 5c763b4..6901ac2 100644
  --- a/gcc/combine.c
  +++ b/gcc/combine.c
  @@ -1904,6 +1904,12 @@ can_combine_p (rtx_insn *insn, rtx_insn *i3,
  rtx_insn *pred ATTRIBUTE_UNUSED,
 set = expand_field_assignment (set);
 src = SET_SRC (set), dest = SET_DEST (set);
 
  +  /* Don't combine if dest contains a user specified register, because
  the
  + user specified register (same with dest) in i3 would be replaced by
  the
  + src of insn which might be different with the user's expectation.
  + */  if (REG_P (dest)  REG_USERVAR_P (dest)  HARD_REGISTER_P
  (dest))
  +return 0;

 I suppose this is similar to Andrew's comment, but I think the rule
 is that it's invalid to replace a REG_USERVAR_P operand in an inline asm.

 Why not?  You probably mean register asm, not all user variables?

 Yeah, meant hard REG_USERVAR_P, sorry, as for the patch.

 Outside of an inline asm we make no guarantee about whether something is
 stored in a particular register or not.

 So IMO we should be checking whether either INSN or I3 is an asm as well
 as the above.

 [ INSN can never be an asm, that is already refused by can_combine_p. ]

 We do not guarantee things will end up in the specified reg (except for asm),
 but will it hurt to leave things in the reg the user said it should be in, 
 even
 if we do not guarantee this behaviour?

 Whether it does not, making the test unnecessarily wide is at best only
 going to paper over problems elsewhere.  I really think we should test
 for i3 being an asm.

 Thanks,
 Richard

Thanks for reviewing. Hale wants me to continue his work because he
will be in holiday in next ten days. The check of asm is added. Is
this one OK?

BR,
Terry


pr64818-combine-user-specified-register.patch-3
Description: Binary data


Re: Ping : [PATCH] [gcc, combine] PR46164: Don't combine the insns if a volatile register is contained.

2015-02-15 Thread Segher Boessenkool
Hi Terry,

I still think this is stage1 material.

 +  /* Don't combine if dest contains a user specified register and i3 contains
 + ASM_OPERANDS, because the user specified register (same with dest) in i3
 + would be replaced by the src of insn which might be different with
 + the user's expectation.  */

Do not eliminate a register asm in an asm input or similar?  Text
explaining why REG_USERVAR_P  HARD_REGISTER_P works here would be
good to have, too.

 +  if (REG_P (dest)  REG_USERVAR_P (dest)  HARD_REGISTER_P (dest)
 +   (GET_CODE (PATTERN (i3)) == SET
 +GET_CODE (SET_SRC (PATTERN (i3))) == ASM_OPERANDS))
 +return 0;

That works only for asms with exactly one output.  You want
extract_asm_operands.


Segher


Re: Ping : [PATCH] [gcc, combine] PR46164: Don't combine the insns if a volatile register is contained.

2015-02-13 Thread Richard Sandiford
Segher Boessenkool seg...@kernel.crashing.org writes:
 On Thu, Feb 12, 2015 at 03:54:21PM +, Richard Sandiford wrote:
 Hale Wang hale.w...@arm.com writes:
  Ping?

 It's not a regression (or is it?), so it is not appropriate for stage4.


  diff --git a/gcc/combine.c b/gcc/combine.c index 5c763b4..6901ac2 100644
  --- a/gcc/combine.c
  +++ b/gcc/combine.c
  @@ -1904,6 +1904,12 @@ can_combine_p (rtx_insn *insn, rtx_insn *i3,
  rtx_insn *pred ATTRIBUTE_UNUSED,
 set = expand_field_assignment (set);
 src = SET_SRC (set), dest = SET_DEST (set);
  
  +  /* Don't combine if dest contains a user specified register, because
  the
  + user specified register (same with dest) in i3 would be replaced by
  the
  + src of insn which might be different with the user's expectation.
  + */  if (REG_P (dest)  REG_USERVAR_P (dest)  HARD_REGISTER_P
  (dest))
  +return 0;
 
 I suppose this is similar to Andrew's comment, but I think the rule
 is that it's invalid to replace a REG_USERVAR_P operand in an inline asm.

 Why not?  You probably mean register asm, not all user variables?

Yeah, meant hard REG_USERVAR_P, sorry, as for the patch.

 Outside of an inline asm we make no guarantee about whether something is
 stored in a particular register or not.
 
 So IMO we should be checking whether either INSN or I3 is an asm as well
 as the above.

 [ INSN can never be an asm, that is already refused by can_combine_p. ]

 We do not guarantee things will end up in the specified reg (except for asm),
 but will it hurt to leave things in the reg the user said it should be in, 
 even
 if we do not guarantee this behaviour?

Whether it does not, making the test unnecessarily wide is at best only
going to paper over problems elsewhere.  I really think we should test
for i3 being an asm.

Thanks,
Richard


Re: Ping : [PATCH] [gcc, combine] PR46164: Don't combine the insns if a volatile register is contained.

2015-02-12 Thread Segher Boessenkool
On Thu, Feb 12, 2015 at 03:54:21PM +, Richard Sandiford wrote:
 Hale Wang hale.w...@arm.com writes:
  Ping?

It's not a regression (or is it?), so it is not appropriate for stage4.


  diff --git a/gcc/combine.c b/gcc/combine.c index 5c763b4..6901ac2 100644
  --- a/gcc/combine.c
  +++ b/gcc/combine.c
  @@ -1904,6 +1904,12 @@ can_combine_p (rtx_insn *insn, rtx_insn *i3,
  rtx_insn *pred ATTRIBUTE_UNUSED,
 set = expand_field_assignment (set);
 src = SET_SRC (set), dest = SET_DEST (set);
  
  +  /* Don't combine if dest contains a user specified register, because
  the
  + user specified register (same with dest) in i3 would be replaced by
  the
  + src of insn which might be different with the user's expectation.
  + */  if (REG_P (dest)  REG_USERVAR_P (dest)  HARD_REGISTER_P
  (dest))
  +return 0;
 
 I suppose this is similar to Andrew's comment, but I think the rule
 is that it's invalid to replace a REG_USERVAR_P operand in an inline asm.

Why not?  You probably mean register asm, not all user variables?

 Outside of an inline asm we make no guarantee about whether something is
 stored in a particular register or not.
 
 So IMO we should be checking whether either INSN or I3 is an asm as well
 as the above.

[ INSN can never be an asm, that is already refused by can_combine_p. ]

We do not guarantee things will end up in the specified reg (except for asm),
but will it hurt to leave things in the reg the user said it should be in, even
if we do not guarantee this behaviour?


Segher


Re: Ping : [PATCH] [gcc, combine] PR46164: Don't combine the insns if a volatile register is contained.

2015-02-12 Thread Jeff Law

On 02/12/15 15:15, Segher Boessenkool wrote:

On Thu, Feb 12, 2015 at 03:54:21PM +, Richard Sandiford wrote:

Hale Wang hale.w...@arm.com writes:

Ping?


It's not a regression (or is it?), so it is not appropriate for stage4.

That's the big question, of course.


[ INSN can never be an asm, that is already refused by can_combine_p. ]

We do not guarantee things will end up in the specified reg (except for asm),
but will it hurt to leave things in the reg the user said it should be in, even
if we do not guarantee this behaviour?
I doubt it could hurt except in extreme corner cases where the value 
gets used later in some insn where the user register was inappropriate. 
 That will cause a spill to copy from the user register to a scratch of 
the appropriate type.


That's, of course, if I'm reading this correctly...

jeff




RE: Ping : [PATCH] [gcc, combine] PR46164: Don't combine the insns if a volatile register is contained.

2015-02-12 Thread Hale Wang
 -Original Message-
 From: Segher Boessenkool [mailto:seg...@kernel.crashing.org]
 Sent: Friday, February 13, 2015 6:16 AM
 To: Hale Wang; 'GCC Patches'; Richard Sandiford
 Subject: Re: Ping : [PATCH] [gcc, combine] PR46164: Don't combine the
insns
 if a volatile register is contained.
 
 On Thu, Feb 12, 2015 at 03:54:21PM +, Richard Sandiford wrote:
  Hale Wang hale.w...@arm.com writes:
   Ping?
 
 It's not a regression (or is it?), so it is not appropriate for stage4.
 
 
   diff --git a/gcc/combine.c b/gcc/combine.c index 5c763b4..6901ac2
   100644
   --- a/gcc/combine.c
   +++ b/gcc/combine.c
   @@ -1904,6 +1904,12 @@ can_combine_p (rtx_insn *insn, rtx_insn *i3,
   rtx_insn *pred ATTRIBUTE_UNUSED,
  set = expand_field_assignment (set);
  src = SET_SRC (set), dest = SET_DEST (set);
  
   +  /* Don't combine if dest contains a user specified register,
   + because
   the
   + user specified register (same with dest) in i3 would be
   + replaced by
   the
   + src of insn which might be different with the user's
expectation.
   + */  if (REG_P (dest)  REG_USERVAR_P (dest) 
 HARD_REGISTER_P
   (dest))
   +return 0;
 
  I suppose this is similar to Andrew's comment, but I think the rule is
  that it's invalid to replace a REG_USERVAR_P operand in an inline asm.
 
 Why not?  You probably mean register asm, not all user variables?
 
  Outside of an inline asm we make no guarantee about whether something
  is stored in a particular register or not.
 
  So IMO we should be checking whether either INSN or I3 is an asm as
  well as the above.
 
 [ INSN can never be an asm, that is already refused by can_combine_p. ]
 

Indeed. If INSN is an asm operand, it's already refused by can_combine_p.

Hale.

 We do not guarantee things will end up in the specified reg (except for
asm),
 but will it hurt to leave things in the reg the user said it should be in,
even if
 we do not guarantee this behaviour?
 
 
 Segher






Re: Ping : [PATCH] [gcc, combine] PR46164: Don't combine the insns if a volatile register is contained.

2015-02-12 Thread Richard Sandiford
Hale Wang hale.w...@arm.com writes:
 Ping?

 -Original Message-
 From: Hale Wang [mailto:hale.w...@arm.com]
 Sent: Thursday, January 29, 2015 9:58 AM
 To: Hale Wang; 'Segher Boessenkool'
 Cc: GCC Patches
 Subject: RE: [PATCH] [gcc, combine] PR46164: Don't combine the insns if a
 volatile register is contained.
 
 Hi Segher,
 
 I have updated the patch as you suggested. Both the patch and the
 changelog are attached.
 
 By the way, the test case provided by Tim Pambor in PR46164 was a
 different
 bug with PR46164. So I resubmitted the bug in
 https://gcc.gnu.org/bugzilla/show_bug.cgi?id=64818.
 And this patch is just used to fix this bug. Is it OK for you?
 
 Thanks,
 Hale
 
 gcc/ChangeLog:
 2015-01-27  Segher Boessenkool  seg...@kernel.crashing.org
  Hale Wang  hale.w...@arm.com
 
  PR rtl-optimization/64818
  * combine.c (can_combine_p): Don't combine the insn if
  the dest of insn is a user specified register.
 
 gcc/testsuit/ChangeLog:
 2015-01-27  Segher Boessenkool  seg...@kernel.crashing.org
  Hale Wang  hale.w...@arm.com
 
  PR rtl-optimization/64818
  * gcc.target/arm/pr64818.c: New test.
 
 
 diff --git a/gcc/combine.c b/gcc/combine.c index 5c763b4..6901ac2 100644
 --- a/gcc/combine.c
 +++ b/gcc/combine.c
 @@ -1904,6 +1904,12 @@ can_combine_p (rtx_insn *insn, rtx_insn *i3,
 rtx_insn *pred ATTRIBUTE_UNUSED,
set = expand_field_assignment (set);
src = SET_SRC (set), dest = SET_DEST (set);
 
 +  /* Don't combine if dest contains a user specified register, because
 the
 + user specified register (same with dest) in i3 would be replaced by
 the
 + src of insn which might be different with the user's expectation.
 + */  if (REG_P (dest)  REG_USERVAR_P (dest)  HARD_REGISTER_P
 (dest))
 +return 0;

I suppose this is similar to Andrew's comment, but I think the rule
is that it's invalid to replace a REG_USERVAR_P operand in an inline asm.
Outside of an inline asm we make no guarantee about whether something is
stored in a particular register or not.

So IMO we should be checking whether either INSN or I3 is an asm as well
as the above.

Thanks,
Richard



Ping : [PATCH] [gcc, combine] PR46164: Don't combine the insns if a volatile register is contained.

2015-02-08 Thread Hale Wang
Ping?

 -Original Message-
 From: Hale Wang [mailto:hale.w...@arm.com]
 Sent: Thursday, January 29, 2015 9:58 AM
 To: Hale Wang; 'Segher Boessenkool'
 Cc: GCC Patches
 Subject: RE: [PATCH] [gcc, combine] PR46164: Don't combine the insns if a
 volatile register is contained.
 
 Hi Segher,
 
 I have updated the patch as you suggested. Both the patch and the
 changelog are attached.
 
 By the way, the test case provided by Tim Pambor in PR46164 was a
different
 bug with PR46164. So I resubmitted the bug in
 https://gcc.gnu.org/bugzilla/show_bug.cgi?id=64818.
 And this patch is just used to fix this bug. Is it OK for you?
 
 Thanks,
 Hale
 
 gcc/ChangeLog:
 2015-01-27  Segher Boessenkool  seg...@kernel.crashing.org
   Hale Wang  hale.w...@arm.com
 
   PR rtl-optimization/64818
   * combine.c (can_combine_p): Don't combine the insn if
   the dest of insn is a user specified register.
 
 gcc/testsuit/ChangeLog:
 2015-01-27  Segher Boessenkool  seg...@kernel.crashing.org
   Hale Wang  hale.w...@arm.com
 
   PR rtl-optimization/64818
   * gcc.target/arm/pr64818.c: New test.
 
 
 diff --git a/gcc/combine.c b/gcc/combine.c index 5c763b4..6901ac2 100644
 --- a/gcc/combine.c
 +++ b/gcc/combine.c
 @@ -1904,6 +1904,12 @@ can_combine_p (rtx_insn *insn, rtx_insn *i3,
 rtx_insn *pred ATTRIBUTE_UNUSED,
set = expand_field_assignment (set);
src = SET_SRC (set), dest = SET_DEST (set);
 
 +  /* Don't combine if dest contains a user specified register, because
the
 + user specified register (same with dest) in i3 would be replaced by
the
 + src of insn which might be different with the user's expectation.
 + */  if (REG_P (dest)  REG_USERVAR_P (dest)  HARD_REGISTER_P
 (dest))
 +return 0;
 +
/* Don't eliminate a store in the stack pointer.  */
if (dest == stack_pointer_rtx
/* Don't combine with an insn that sets a register to itself if it
has diff --git
 a/gcc/testsuite/gcc.target/arm/pr64818.c
 b/gcc/testsuite/gcc.target/arm/pr64818.c
 new file mode 100644
 index 000..bddd846
 --- /dev/null
 +++ b/gcc/testsuite/gcc.target/arm/pr64818.c
 @@ -0,0 +1,30 @@
 +/* { dg-do compile } */
 +/* { dg-options -O1 } */
 +
 +char temp[16];
 +extern int foo1 (void);
 +
 +void foo (void)
 +{
 +  int i;
 +  int len;
 +
 +  while (1)
 +  {
 +len = foo1 ();
 +register int a asm (r0) = 5;
 +register char *b asm (r1) = temp;
 +register int c asm (r2) = len;
 +asm volatile (mov %[r0], %[r0]\n  mov %[r1], %[r1]\n
 mov %[r2], %[r2]\n
 +: +m(*b)
 +: [r0]r(a), [r1]r(b), [r2]r(c));
 +
 +for (i = 0; i  len; i++)
 +{
 +  if (temp[i] == 10)
 +  return;
 +}
 +  }
 +}
 +
 +/* { dg-final { scan-assembler \[\\t \]+mov\ r1,\ r1 } } */
 
 
   On Tue, Jan 27, 2015 at 11:49:55AM +0800, Hale Wang wrote:
  
   Hi Hale,
You are correct. Just -O1 reproduces this problem.
However it's a combine bug which is related to the combing user
specified register into inline-asm.
  
   Yes, it is.  But the registers the testcase uses exist on any ARM
   version
  there
   is as far as I know, so not specifying specific model and ABI should
   give
  wider
   test coverage (if anyone actually builds and/or tests more than the
  default,
   of course :-) )
  
 Could you try this patch please?
   
Your patch rejected the combine 98+43, that's correct.
  
   Excellent, thanks for testing.
  
However, Jakub
pointed out that preventing that to be combined would be a serious
regression on code quality.
  
   I know; I needed to think of some good way to detect register
   variables
  (they
   aren't marked specially in RTL).  I think I found one, for combine
   that
  is; if we
   need to detect it in other passes too, we probably need to put
   another
  flag
   on it, or something.
  
Andrew Pinski suggested: can_combine_p would reject combing into
an inline-asm to prevent this issue. And I have updated the patch.
What do you think about this change?
  
   That will regress combining anything else into an asm.  It will
   disallow combining asms _at all_, if we really wanted that we should
   simply not
  build
   LOG_LINKS for them.  But it hurts optimisation (for simple r
   constraints
  it is
   not a real problem, RA should take care of it, but for anything else
   it
  is).
  
   Updated patch below.  A user variable that is also a hard register
   can
  only
   happen in a few cases: 1) a register variable, the case we are
   after;
   2)
  an
   argument for the current function that was propagated into a user
   variable (something combine should not do at all, it hinders good
   register
  allocation,
   but it does anyway on most targets).
  
   Do you want to take this or shall I?  This is not a regression, so
   it
  probably
   should wait for stage1 :-(
  
 
  Your solution is very good. I will test this patch locally and send
  out the result ASAP.
  Thanks,
 
  Hale