Richard Biener <rguent...@suse.de> writes:
>> @@ -812,33 +997,80 @@ split_constant_offset_1 (tree type, tree op0, enum 
>> tree_code code, tree op1,
>>      }
>>  }
>>  
>> -/* Expresses EXP as VAR + OFF, where off is a constant.  The type of OFF
>> -   will be ssizetype.  */
>> +/* If EXP has pointer type, try to express it as:
>> +
>> +     POINTER_PLUS <*VAR, (sizetype) *OFF>
>> +
>> +   where:
>> +
>> +   - *VAR has the same type as EXP
>> +   - *OFF is a constant of type ssizetype.
>> +
>> +   If EXP has an integral type, try to express (sizetype) EXP as:
>> +
>> +     *VAR + (sizetype) *OFF
>> +
>> +   where:
>> +
>> +   - *VAR has type sizetype
>> +   - *OFF is a constant of type ssizetype.
>> +
>> +   If EXP_RANGE is nonnull, set it to the range of EXP.
>> +
>> +   CACHE caches {*VAR, *OFF} pairs for SSA names that we've previously
>> +   visited.  LIMIT counts down the number of SSA names that we are
>> +   allowed to process before giving up.  */
>>  
>>  static void
>> -split_constant_offset (tree exp, tree *var, tree *off,
>> +split_constant_offset (tree exp, tree *var, tree *off, value_range 
>> *exp_range,
>>                     hash_map<tree, std::pair<tree, tree> > &cache,
>>                     unsigned *limit)
>>  {
>> -  tree type = TREE_TYPE (exp), op0, op1, e, o;
>> +  tree type = TREE_TYPE (exp), op0, op1;
>>    enum tree_code code;
>>  
>> -  *var = exp;
>> -  *off = ssize_int (0);
>> +  code = TREE_CODE (exp);
>> +  if (exp_range)
>> +    {
>> +      *exp_range = type;
>> +      if (code == SSA_NAME)
>> +    {
>> +      wide_int var_min, var_max;
>> +      value_range_kind vr_kind = get_range_info (exp, &var_min, &var_max);
>> +      wide_int var_nonzero = get_nonzero_bits (exp);
>> +      vr_kind = intersect_range_with_nonzero_bits (vr_kind,
>> +                                                   &var_min, &var_max,
>> +                                                   var_nonzero,
>> +                                                   TYPE_SIGN (type));
>> +      if (vr_kind == VR_RANGE)
>> +        *exp_range = value_range (type, var_min, var_max);
>> +    }
>> +    }
>>  
>> -  if (tree_is_chrec (exp)
>> -      || get_gimple_rhs_class (TREE_CODE (exp)) == GIMPLE_TERNARY_RHS)
>> -    return;
>> +  if (!tree_is_chrec (exp)
>> +      && get_gimple_rhs_class (TREE_CODE (exp)) != GIMPLE_TERNARY_RHS)
>> +    {
>> +      extract_ops_from_tree (exp, &code, &op0, &op1);
>> +      if (split_constant_offset_1 (type, op0, code, op1, var, off,
>> +                               exp_range, cache, limit))
>> +    return;
>> +    }
>>  
>> -  code = TREE_CODE (exp);
>> -  extract_ops_from_tree (exp, &code, &op0, &op1);
>> -  if (split_constant_offset_1 (type, op0, code, op1, &e, &o, cache, limit))
>> +  *var = exp;
>> +  if (INTEGRAL_TYPE_P (type))
>> +    *var = fold_convert (sizetype, *var);
>> +  *off = ssize_int (0);
>> +  if (exp_range && code != SSA_NAME)
>>      {
>> -      *var = e;
>> -      *off = o;
>> +      wide_int var_min, var_max;
>> +      if (determine_value_range (exp, &var_min, &var_max) == VR_RANGE)
>> +    *exp_range = value_range (type, var_min, var_max);
>
> So this call is only for the case the recursion failed, otherwise
> we build exp_range during the recursive call, correct?

Yeah, that's right.

> The patch is OK.

Thanks.  For the record, now also tested on x86_64-linux-gnu.

I'm not sure what to do about backports though.  It seems a bit
invasive for GCC 8 and 9 at least (PR95396).

Richard

Reply via email to