This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: Remove host_integerp tests with variable signedness


On Fri, Nov 15, 2013 at 11:48 AM, Richard Sandiford
<rdsandiford@googlemail.com> wrote:
> Richard Biener <richard.guenther@gmail.com> writes:
>> On Thu, Nov 14, 2013 at 10:04 PM, Richard Sandiford
>> <rdsandiford@googlemail.com> wrote:
>>> Apart from the case in the C front end, there are 4 calls to host_integerp
>>> with a variable "pos" argument.  These "pos" arguments are all taken from
>>> TYPE_UNSIGNED.  In the dwarf2out.c case we go on to require:
>>>
>>>   simple_type_size_in_bits (TREE_TYPE (value)) <= HOST_BITS_PER_WIDE_INT
>>>   || host_integerp (value, 0)
>>>
>>> The host_integerp (value, 0) makes the first host_integerp trivially
>>> redundant for !TYPE_UNSIGNED.  Checking that the precision is
>>> <= HOST_BITS_PER_WIDE_INT makes the first host_integerp redundant
>>> for TYPE_UNSIGNED too, since all unsigned types of those precisions
>>> will fit in an unsigned HWI.  We already know that we're dealing with
>>> an INTEGER_CST, so there's no need for a code check either.
>>>
>>> vect_recog_divmod_pattern is similar in the sense that we already know
>>> that we have an INTEGER_CST and that we specifically check for precisions
>>> <= HOST_BITS_PER_WIDE_INT.
>>>
>>> In the other two cases we don't know whether we're dealing with an
>>> INTEGER_CST but we do check for precisions <= HOST_BITS_PER_WIDE_INT.
>>> So these host_integerps reduce to code tests.  (The precision check
>>> for expand_vector_divmod doesn't show up in the context but is at
>>> the top of the function:
>>>
>>>   if (prec > HOST_BITS_PER_WIDE_INT)
>>>     return NULL_TREE;
>>> )
>>>
>>> I also replaced the associated tree_low_csts with TREE_INT_CST_LOWs.
>>>
>>> Tested on x86_64-linux-gnu.  OK to install?
>>
>> Note that host_integerp "conveniently" also makes sure the argument
>> is not NULL and of INTEGER_CST kind, so without more context ....
>
> Right, which is why I was trying to list out the reasons why the
> INTEGER_CST check isn't needed in the first two cases.  None of the
> cases can be null AFAIK.
>
>>> Index: gcc/dwarf2out.c
>>> ===================================================================
>>> --- gcc/dwarf2out.c     2013-11-14 20:21:27.183058648 +0000
>>> +++ gcc/dwarf2out.c     2013-11-14 20:22:18.128829681 +0000
>>> @@ -17321,9 +17321,8 @@ gen_enumeration_type_die (tree type, dw_
>>>           if (TREE_CODE (value) == CONST_DECL)
>>>             value = DECL_INITIAL (value);
>>>
>>> -         if (host_integerp (value, TYPE_UNSIGNED (TREE_TYPE (value)))
>>> -             && (simple_type_size_in_bits (TREE_TYPE (value))
>>> -                 <= HOST_BITS_PER_WIDE_INT || host_integerp (value, 0)))
>>> +         if (simple_type_size_in_bits (TREE_TYPE (value))
>>> +             <= HOST_BITS_PER_WIDE_INT || host_integerp (value, 0))
>>
>> ... this isn't a 1:1 tranform
>
> The full context is:
>
>           if (simple_type_size_in_bits (TREE_TYPE (value))
>               <= HOST_BITS_PER_WIDE_INT || host_integerp (value, 0))
>             /* DWARF2 does not provide a way of indicating whether or
>                not enumeration constants are signed or unsigned.  GDB
>                always assumes the values are signed, so we output all
>                values as if they were signed.  That means that
>                enumeration constants with very large unsigned values
>                will appear to have negative values in the debugger.
>
>                TODO: the above comment is wrong, DWARF2 does provide
>                DW_FORM_sdata/DW_FORM_udata to represent signed/unsigned data.
>                This should be re-worked to use correct signed/unsigned
>                int/double tags for all cases, instead of always treating as
>                signed.  */
>             add_AT_int (enum_die, DW_AT_const_value, TREE_INT_CST_LOW (value));
>           else
>             /* Enumeration constants may be wider than HOST_WIDE_INT.  Handle
>                that here.  */
>             add_AT_double (enum_die, DW_AT_const_value,
>                            TREE_INT_CST_HIGH (value), TREE_INT_CST_LOW (value));
>
> We're dealing with a nonnull INTEGER_CST whatever happens.
>
>>> Index: gcc/tree-vect-patterns.c
>>> ===================================================================
>>> --- gcc/tree-vect-patterns.c    2013-11-14 20:21:27.183058648 +0000
>>> +++ gcc/tree-vect-patterns.c    2013-11-14 20:22:18.129829676 +0000
>>> @@ -2064,9 +2064,8 @@ vect_recog_divmod_pattern (vec<gimple> *
>>>        return pattern_stmt;
>>>      }
>>>
>>> -  if (!host_integerp (oprnd1, TYPE_UNSIGNED (itype))
>>> -      || integer_zerop (oprnd1)
>>> -      || prec > HOST_BITS_PER_WIDE_INT)
>>> +  if (prec > HOST_BITS_PER_WIDE_INT
>>> +      || integer_zerop (oprnd1))
>>
>> likewise.
>
> This is midway through a function that has already checked:
>
>   if (TREE_CODE (oprnd0) != SSA_NAME
>       || TREE_CODE (oprnd1) != INTEGER_CST
>       || TREE_CODE (itype) != INTEGER_TYPE
>       || TYPE_PRECISION (itype) != GET_MODE_PRECISION (TYPE_MODE (itype)))
>     return NULL;
>
> and where:
>
>   prec = TYPE_PRECISION (itype);
>
> So even without the host_integerp test, the code in the patch only fails
> to exit if we have an INTEGER_CST whose precision is <= HOST_BITS_PER_WIDE_INT.
> In that case the host_integerp test is redundant, because a unsigned constant
> will fit in an unsigned HWI and a signed constant will fit in a signed HWI.
>
>>> @@ -2078,8 +2077,8 @@ vect_recog_divmod_pattern (vec<gimple> *
>>>      {
>>>        unsigned HOST_WIDE_INT mh, ml;
>>>        int pre_shift, post_shift;
>>> -      unsigned HOST_WIDE_INT d = tree_low_cst (oprnd1, 1)
>>> -                                & GET_MODE_MASK (TYPE_MODE (itype));
>>
>> This ensures the value is positive ...
>
> This is in a:
>
>   if (TYPE_UNSIGNED (itype))
>     {
>
> block that is only reached if the conditions above are met.
>
>>> +      unsigned HOST_WIDE_INT d = (TREE_INT_CST_LOW (oprnd1)
>>> +                                 & GET_MODE_MASK (TYPE_MODE (itype)));
>>>        tree t1, t2, t3, t4;
>>>
>>>        if (d >= ((unsigned HOST_WIDE_INT) 1 << (prec - 1)))
>>> @@ -2195,7 +2194,7 @@ vect_recog_divmod_pattern (vec<gimple> *
>>>      {
>>>        unsigned HOST_WIDE_INT ml;
>>>        int post_shift;
>>> -      HOST_WIDE_INT d = tree_low_cst (oprnd1, 0);
>>> +      HOST_WIDE_INT d = TREE_INT_CST_LOW (oprnd1);
>>
>> While this also allows negatives.
>
> This is in the else (!TYPE_UNSIGNED) arm.
>
>>> Index: gcc/fold-const.c
>>> ===================================================================
>>> --- gcc/fold-const.c    2013-11-14 20:21:27.183058648 +0000
>>> +++ gcc/fold-const.c    2013-11-14 20:22:18.124829699 +0000
>>> @@ -12032,16 +12032,15 @@ fold_binary_loc (location_t loc,
>>>          if the new mask might be further optimized.  */
>>>        if ((TREE_CODE (arg0) == LSHIFT_EXPR
>>>            || TREE_CODE (arg0) == RSHIFT_EXPR)
>>> -         && host_integerp (TREE_OPERAND (arg0, 1), 1)
>>> -         && host_integerp (arg1, TYPE_UNSIGNED (TREE_TYPE (arg1)))
>>> -         && tree_low_cst (TREE_OPERAND (arg0, 1), 1)
>>> -            < TYPE_PRECISION (TREE_TYPE (arg0))
>>>           && TYPE_PRECISION (TREE_TYPE (arg0)) <= HOST_BITS_PER_WIDE_INT
>>> -         && tree_low_cst (TREE_OPERAND (arg0, 1), 1) > 0)
>>> +         && TREE_CODE (arg1) == INTEGER_CST
>>> +         && host_integerp (TREE_OPERAND (arg0, 1), 1)
>>> +         && tree_low_cst (TREE_OPERAND (arg0, 1), 1) > 0
>>> +         && (tree_low_cst (TREE_OPERAND (arg0, 1), 1)
>>> +             < TYPE_PRECISION (TREE_TYPE (arg0))))
>>>         {
>>>           unsigned int shiftc = tree_low_cst (TREE_OPERAND (arg0, 1), 1);
>>> -         unsigned HOST_WIDE_INT mask
>>> -           = tree_low_cst (arg1, TYPE_UNSIGNED (TREE_TYPE (arg1)));
>>> +         unsigned HOST_WIDE_INT mask = TREE_INT_CST_LOW (arg1);
>>
>> Where's the size test on arg1 gone?  IMHO this whole code should
>> just use double-ints ...
>
> Not sure which test you mean.  The only arg1 test is the host_integerp one,
> which I'm trying to get rid of.  The precision of arg0 is the same as
> the precision of arg1 in this context, so the same reasoning as above
> applies: once we've established the TYPE_PRECISION condition, we already
> know that an unsigned arg1 constant will fit in an unsigned HWI and
> that a signed arg1 constant will fit in a HWI.  So just checking the
> code is enough.

Ah, indeed.

The patch is ok - thanks for the explanations.

Richard.

> Thanks,
> Richard


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]