Hi,

"Kewen.Lin" <li...@linux.ibm.com> writes:

> Hi,
>
> on 2023/10/25 10:00, Jiufu Guo wrote:
>> Hi,
>> 
>> Trunk gcc supports more constants to be built via two instructions: e.g.
>> "li/lis; xori/xoris/rldicl/rldicr/rldic".
>> And then num_insns_constant should also be updated.
>> 
>
> Thanks for updating this.
>
>> Bootstrap & regtest pass ppc64{,le}.
>> Is this ok for trunk?
>> 
>> BR,
>> Jeff (Jiufu Guo)
>> 
>> gcc/ChangeLog:
>> 
>>      * config/rs6000/rs6000.cc (can_be_built_by_lilis_and_rldicX): New
>>      function.
>>      (num_insns_constant_gpr): Update to return 2 for more cases.
>>      (rs6000_emit_set_long_const): Update to use
>>      can_be_built_by_lilis_and_rldicX.
>> 
>> ---
>>  gcc/config/rs6000/rs6000.cc | 64 ++++++++++++++++++++++++-------------
>>  1 file changed, 41 insertions(+), 23 deletions(-)
>> 
>> diff --git a/gcc/config/rs6000/rs6000.cc b/gcc/config/rs6000/rs6000.cc
>> index cc24dd5301e..b23ff3d7917 100644
>> --- a/gcc/config/rs6000/rs6000.cc
>> +++ b/gcc/config/rs6000/rs6000.cc
>> @@ -6032,6 +6032,9 @@ direct_return (void)
>>    return 0;
>>  }
>>  
>> +static bool
>> +can_be_built_by_lilis_and_rldicX (HOST_WIDE_INT, int *, HOST_WIDE_INT *);
>> +
>>  /* Helper for num_insns_constant.  Calculate number of instructions to
>>     load VALUE to a single gpr using combinations of addi, addis, ori,
>>     oris, sldi and rldimi instructions.  */
>> @@ -6044,35 +6047,41 @@ num_insns_constant_gpr (HOST_WIDE_INT value)
>>      return 1;
>>  
>>    /* constant loadable with addis */
>> -  else if ((value & 0xffff) == 0
>> -       && (value >> 31 == -1 || value >> 31 == 0))
>> +  if ((value & 0xffff) == 0 && (value >> 31 == -1 || value >> 31 == 0))
>>      return 1;
>>  
>>    /* PADDI can support up to 34 bit signed integers.  */
>> -  else if (TARGET_PREFIXED && SIGNED_INTEGER_34BIT_P (value))
>> +  if (TARGET_PREFIXED && SIGNED_INTEGER_34BIT_P (value))
>>      return 1;
>>  
>> -  else if (TARGET_POWERPC64)
>> -    {
>> -      HOST_WIDE_INT low = sext_hwi (value, 32);
>> -      HOST_WIDE_INT high = value >> 31;
>> +  if (!TARGET_POWERPC64)
>> +    return 2;
>>  
>> -      if (high == 0 || high == -1)
>> -    return 2;
>> +  HOST_WIDE_INT low = sext_hwi (value, 32);
>> +  HOST_WIDE_INT high = value >> 31;
>>  
>> -      high >>= 1;
>> +  if (high == 0 || high == -1)
>> +    return 2;
>>  
>> -      if (low == 0 || low == high)
>> -    return num_insns_constant_gpr (high) + 1;
>> -      else if (high == 0)
>> -    return num_insns_constant_gpr (low) + 1;
>> -      else
>> -    return (num_insns_constant_gpr (high)
>> -            + num_insns_constant_gpr (low) + 1);
>> -    }
>> +  high >>= 1;
>>  
>> -  else
>> +  HOST_WIDE_INT ud2 = (low >> 16) & 0xffff;
>> +  HOST_WIDE_INT ud1 = low & 0xffff;
>> +  if (high == -1 && ((!(ud2 & 0x8000) && ud1 == 0) || (ud1 & 0x8000)))
>> +    return 2;
>> +  if (high == 0 && (ud1 == 0 || (!(ud1 & 0x8000))))
>>      return 2;
>
> I was thinking that instead of enumerating all the cases in function
> rs6000_emit_set_long_const, if we can add one optional argument like
> "int* num_insns=nullptr" to function rs6000_emit_set_long_const, and
> when it's not nullptr, not emitting anything but update the count in
> rs6000_emit_set_long_const.  It helps people remember to update
> num_insns when updating rs6000_emit_set_long_const in future, it's
> also more clear on how the number comes from.
>
> Does it sound good to you?

Thanks for your advice!  Yes, "rs6000_emit_set_long_const"  and
"num_insns_constant_gpr" should be aligned.  Using a same logic
(same code place) would make sense.


BR,
Jeff (Jiufu Guo)
>
> BR,
> Kewen
>
>> +
>> +  int shift;
>> +  HOST_WIDE_INT mask;
>> +  if (can_be_built_by_lilis_and_rldicX (value, &shift, &mask))
>> +    return 2;
>> +
>> +  if (low == 0 || low == high)
>> +    return num_insns_constant_gpr (high) + 1;
>> +  if (high == 0)
>> +    return num_insns_constant_gpr (low) + 1;
>> +  return (num_insns_constant_gpr (high) + num_insns_constant_gpr (low) + 1);
>>  }
>>  
>>  /* Helper for num_insns_constant.  Allow constants formed by the
>> @@ -10492,6 +10501,18 @@ can_be_built_by_li_and_rldic (HOST_WIDE_INT c, int 
>> *shift, HOST_WIDE_INT *mask)
>>    return false;
>>  }
>>  
>> +/* Combine the above checking functions for  li/lis;rldicX. */
>> +
>> +static bool
>> +can_be_built_by_lilis_and_rldicX (HOST_WIDE_INT c, int *shift,
>> +                              HOST_WIDE_INT *mask)
>> +{
>> +  return (can_be_built_by_li_lis_and_rotldi (c, shift, mask)
>> +      || can_be_built_by_li_lis_and_rldicl (c, shift, mask)
>> +      || can_be_built_by_li_lis_and_rldicr (c, shift, mask)
>> +      || can_be_built_by_li_and_rldic (c, shift, mask));
>> +}
>> +
>>  /* Subroutine of rs6000_emit_set_const, handling PowerPC64 DImode.
>>     Output insns to set DEST equal to the constant C as a series of
>>     lis, ori and shl instructions.  */
>> @@ -10538,10 +10559,7 @@ rs6000_emit_set_long_const (rtx dest, HOST_WIDE_INT 
>> c)
>>        emit_move_insn (dest, gen_rtx_XOR (DImode, temp,
>>                                       GEN_INT ((ud2 ^ 0xffff) << 16)));
>>      }
>> -  else if (can_be_built_by_li_lis_and_rotldi (c, &shift, &mask)
>> -       || can_be_built_by_li_lis_and_rldicl (c, &shift, &mask)
>> -       || can_be_built_by_li_lis_and_rldicr (c, &shift, &mask)
>> -       || can_be_built_by_li_and_rldic (c, &shift, &mask))
>> +  else if (can_be_built_by_lilis_and_rldicX (c, &shift, &mask))
>>      {
>>        temp = !can_create_pseudo_p () ? dest : gen_reg_rtx (DImode);
>>        unsigned HOST_WIDE_INT imm = (c | ~mask);

Reply via email to