[Patch] 1/2 Expand sync_sub as sync_add if predicates don't match.

David Daney ddaney@avtrex.com
Fri Aug 24 00:41:00 GMT 2007


David Daney wrote:
> Richard Sandiford wrote:
>> David Daney <ddaney@avtrex.com> writes:
>>  
>>> While implementing the atomic memory operations for MIPS, I came 
>>> across a problem where immediate operands were forced into a register 
>>> when sync_sub* insns were expanded.  On MIPS there is no minus 
>>> instruction for immediate operands, instead this should be expanded 
>>> as plus with the negative value of the immediate operand.
>>>
>>> In expand_sync_operation() and expand_sync_fetch_operation() there is 
>>> code to handle conversion to plus if the minus insn does not exits.  
>>> I enhanced this slightly so that it also does the conversion if the 
>>> predicate for sync_sub* does not match, but it does match for the 
>>> corresponding sync_add*.  This allows me to write sync_sub* insns 
>>> with a register predicate and have them used for non-immediate 
>>> operands, but an immediate operand results in conversion to sync_add*.
>>>
>>> Tested on x86_64-pc-linux-gnu all default languages both native and 
>>> -m32 with no regressions.  Also tested mips64-linux C only.
>>>
>>> :ADDPATCH middle-end:
>>>
>>> OK to commit?
>>>     
>>
>> FWIW, with (minus ... (const_int ...)) not being canonical rtl, I think
>> we should always use PLUS rather than MINUS if the operand is a 
>> CONST_INT.
>> E.g. the first thing expand_binop does is:
>>
>>   /* If subtracting an integer constant, convert this into an addition of
>>      the negated constant.  */
>>   if (binoptab == sub_optab && GET_CODE (op1) == CONST_INT)
>>     {
>>       op1 = negate_rtx (mode, op1);
>>       binoptab = add_optab;
>>     }
>>
>> and I think we should have a similar thing in expand_sync_operation
>> and expand_sync_fetch_operation.  As well as avoiding invalid
>> expressions, it has the advantage of folding the negation at
>> generation time, which I don't think the current version would.
>> (Sorry if that's wrong.)
>>   
> 
> The attached new revision of the patch does it this way now.  Light 
> testing on MIPS shows that it has the same effect as the first version.  
> Which from the point of view of my mips atomic memory operations patch 
> is sufficient.
> 
> I was a little hesitant to do it this way the first time because it has 
> the potential of adversely impacting a (hypothetical) port where
> 
> sync_sub<mode> is more efficient than sync_add<mode> the only place I 
> could think of where this would be plausible is for cases where negating 
> the value would cause it to no longer fit in the same number of bits as 
> the original value (-0x8000 on mips assuming there were a subiu 
> instruction).
> 
> If deemed better than the previous version, I will fully test this.  It 
> would however be nice to get feedback that this is really better before 
> exerting a lot more effort in testing.

Now tested on both i686-pc-linux-gnu and x86_64-pc-linux-gnu all default 
languages with no regressions found.

OK to commit?


> 
> 2007-08-21  David Daney  <ddaney@avtrex.com>
> 
>    * optabs.c (expand_sync_operation):  Use plus insn if minus
>    CONST_INT_P(val).
>    (expand_sync_fetch_operation):  Ditto.
> 
> 
> ------------------------------------------------------------------------
> 
> Index: optabs.c
> ===================================================================
> --- optabs.c	(revision 127356)
> +++ optabs.c	(working copy)
> @@ -6444,7 +6444,7 @@ expand_sync_operation (rtx mem, rtx val,
>  
>      case MINUS:
>        icode = sync_sub_optab[mode];
> -      if (icode == CODE_FOR_nothing)
> +      if (icode == CODE_FOR_nothing || CONST_INT_P (val))
>  	{
>  	  icode = sync_add_optab[mode];
>  	  if (icode != CODE_FOR_nothing)
> @@ -6544,7 +6544,8 @@ expand_sync_fetch_operation (rtx mem, rt
>      case MINUS:
>        old_code = sync_old_sub_optab[mode];
>        new_code = sync_new_sub_optab[mode];
> -      if (old_code == CODE_FOR_nothing && new_code == CODE_FOR_nothing)
> +      if ((old_code == CODE_FOR_nothing && new_code == CODE_FOR_nothing)
> +          || CONST_INT_P (val))
>  	{
>  	  old_code = sync_old_add_optab[mode];
>  	  new_code = sync_new_add_optab[mode];



More information about the Gcc-patches mailing list