> Am 24.06.2026 um 16:35 schrieb Andrew MacLeod <[email protected]>:
>
>
>> On 6/24/26 10:29, Andrew MacLeod wrote:
>>
>>> On 6/24/26 02:52, Richard Biener wrote:
>>> Vectorizer pattern recog eventually feeds range_of_expr with both
>>> pattern def expressions and pattern context stmts. While that's
>>> IMO not OK the ranger code has some existing defenses against
>>> defs that do not reside in the IL. Just those are incomplete.
>>>
>>> The following makes them more robust. I will cleanup the vectorizer
>>> side of things on trunk.
>>>
>>> I have documented gimple_ranger::range_of_expr as to how I understand
>>> it works (the different range_of_* APIs seem to behave slightly
>>> different - I find this confusing). Esp. range_of_expr requires
>>> a valid 'r' input range and the return value isn't always reflecting
>>> that something was done.
>>
>> range_of_expr does not require a valid input range.. none of them do. It
>> just requires R to be the right class of range to handle the expression
>> being passed in. They should all be more or less consistent.
>>
>
> It occurs to me perhaps you get confused by things like
>
> // If there is no global range for EXPR yet, try to evaluate it.
> // This call sets R to a global range regardless.
> if (!m_cache.get_global_range (r, expr))
> {
>
> Which *WILL* set R regardless of the return value. Its an internal API and
> the return value for it indicates whether there was an existing global value
> or not, and if there wasnt one, it sets a default and returns it.
Possibly. I will check in detail tomorrow. Is the non-comment part of the
patch ok?
Thanks,
Richard
>
>> The return value indicates whether the R passed in has had a value set or
>> not. This applies to all range_of_* routines. IF you get TRUE back, you
>> can use it.
>>
>> The only way something like range_of_expr can return false is if the
>> expression is not a supported by any of the range types, ie, like a vec or
>> complex.
>>
>>
>>
>>>
>>> Bootstrap and regtest running on x86_64-unknown-linux-gnu.
>>>
>>> OK for trunk and branches?
>>>
>>> The testcase (and the unreduced code) only ICEs on the 15 branch
>>> on aarch64 when building firefox.
>>>
>>> Thanks,
>>> Richard.
>>>
>>> PR tree-optimization/125953
>>> * gimple-range.cc (gimple_ranger::range_of_expr): Document.
>>> Fall back to global ranges if 'stmt' is not in the IL.
>>>
>>> * gcc.dg/torture/pr125953.c: New testcase.
>>> ---
>>> gcc/gimple-range.cc | 9 +++++++--
>>> gcc/testsuite/gcc.dg/torture/pr125953.c | 14 ++++++++++++++
>>> 2 files changed, 21 insertions(+), 2 deletions(-)
>>> create mode 100644 gcc/testsuite/gcc.dg/torture/pr125953.c
>>>
>>> diff --git a/gcc/gimple-range.cc b/gcc/gimple-range.cc
>>> index bc3eaf9efda..9aa281261a2 100644
>>> --- a/gcc/gimple-range.cc
>>> +++ b/gcc/gimple-range.cc
>>> @@ -78,6 +78,10 @@ gimple_ranger::const_query ()
>>> return m_cache.const_query ();
>>> }
>>> +// Calculate a range of EXPR on stmt STMT and improve R with it.
>>> +// If STMT is not specified fall back to use global ranges.
>>> +// Return false if R cannot be improved.
>>> +
>>> bool
>>> gimple_ranger::range_of_expr (vrange &r, tree expr, gimple *stmt)
>>> {
>>> @@ -98,8 +102,9 @@ gimple_ranger::range_of_expr (vrange &r, tree expr,
>>> gimple *stmt)
>>> fputs ("\n", dump_file);
>>> }
>>> - // If there is no statement, just get the global value.
>>> - if (!stmt)
>>> + // If there is no statement or stmt happens to be not in the IL,
>>> + // just get the global value.
>>> + if (!stmt || !gimple_bb (stmt))
>>> {
>>> value_range tmp (TREE_TYPE (expr));
>>> // If there is no global range for EXPR yet, try to evaluate it.
>>> diff --git a/gcc/testsuite/gcc.dg/torture/pr125953.c
>>> b/gcc/testsuite/gcc.dg/torture/pr125953.c
>>> new file mode 100644
>>> index 00000000000..3a34bc3d676
>>> --- /dev/null
>>> +++ b/gcc/testsuite/gcc.dg/torture/pr125953.c
>>> @@ -0,0 +1,14 @@
>>> +/* { dg-do compile } */
>>> +/* { dg-additional-options "-march=armv8.3-a+sve2" { target aarch64-*-* }
>>> } */
>>> +
>>> +unsigned char *begin(unsigned char *out)
>>> +{
>>> + int size_0_0_0;
>>> + unsigned char *kRow = begin(out);
>>> + unsigned char *currentRow = kRow;
>>> + for (int x = 0; x < size_0_0_0; ++x) {
>>> + char k = kRow ? kRow[x] : 5;
>>> + out[2] = currentRow[2] * k / 255;
>>> + }
>>> + return out;
>>> +}
>