> On 15 Jan 2025, at 08:38, Richard Biener <richard.guent...@gmail.com> wrote:
> 
> External email: Use caution opening links or attachments
> 
> 
> On Tue, Jan 14, 2025 at 4:35 PM Jennifer Schmitz via Gcc
> <gcc@gcc.gnu.org> wrote:
>> 
>> We are working on improving codegen for the following test cases (for all 
>> integer types T):
>> 
>> T foo (T x, T y)
>> {
>>  T diff = x - y;
>>  return x > y ? diff : -diff;
>> }
>> 
>> T bar (T x, T y)
>> {
>>  T diff1 = x - y;
>>  T diff2 = y - x;
>>  return x > y ? diff1 : diff2;
>> }
>> 
>> For signed integers, we already proposed a patch (attached to [1]) that 
>> amends existing match.pd
>> patterns in order to produce an ABS_EXPR (x - y).
>> 
>> Now, we want to implement the optimization for unsigned integers for 
>> AArch64. For example,
>> GCC compiles the function bar for uint8_t to (-O3 -fwrapv)
>> bar_u8:
>>        and     w3, w0, 255
>>        and     w1, w1, 255
>>        sub     w2, w3, w1
>>        sub     w0, w1, w3
>>        and     w2, w2, 255
>>        cmp     w3, w1
>>        and     w0, w0, 255
>>        csel    w0, w0, w2, ls
>>        ret
>> 
>> whereas clang produces the desired sequence
>> bar_u8:
>>        and     w8, w0, #0xff
>>        sub     w8, w8, w1, uxtb
>>        cmp     w8, #0
>>        cneg    w0, w8, mi
>>        ret
>> 
>> We would like to ask for guidance on where to best implement this 
>> optimization for unsigned
>> integers. We have considered the following approaches:
>> - also in match.pd as for the signed integers. However, the existing rule 
>> ABS (A) -> A for
>>  unsigned integers would fold ABS_EXPR (x - y) to (x - y), which is 
>> incorrect if x < y.
>>  Are there other ways to express absolute differences for unsigned types on 
>> gimple level?
> 
> Well, iff x > y ? x - y : y - x -> abs ((signed)(x - y)) == abs
> ((signed)(y - x)) then I'd suggest
> to instead of ABS_EXPR (x - y) use ABSU_EXPR ((signed)(x - y)).
> 
> But I'm not sure that's OK when the difference cannot be represented
> in a signed integer, like
> for x == UINT_MAX and y == 0.  The desired assembly uses conditional
> negation (foo), so
> why not use that form as target?  IIRC value-numbering will already
> try to CSE y - x as -T
> when there's a T == x - y.
Hi Richard,
thanks for responding to my email.
I tried using ABSU_EXPR ((signed)(x - y)), but as you expected it yields 
incorrect results
for some corner cases (if the top bit is set in x - y). So, I’m not sure if 
there is a
good way to fold it on gimple level that also gives correct results in all 
cases.
That points to doing it on RTL level...
Thanks,
Jennifer
> 
> Richard.
> 
>> - in the aarch64 backend on RTL level: create an if_then_else RTX with 
>> (zero-extended) minus expressions
>>  in both arms. However, the combine-pass dump shows that we are also lacking 
>> an instruction pattern
>>  matching each arm:
>>    Failed to match this instruction:
>>    (set (reg:SI 108)
>>        (zero_extend:SI (minus:QI (subreg:QI (reg/v:SI 103 [ x ]) 0)
>>                (subreg:QI (reg/v:SI 104 [ y ]) 0))))
>>  which we would want to map to the following split of 3 instructions:
>>    and r103, r103, 255
>>    sub r108, r103, r104, uxtb
>>    and r108, r108, 255
>>  Do we want to add both those patterns?
>> 
>> Any advice would be appreciated.
>> Thanks,
>> Jennifer
>> 
>> [1] https://gcc.gnu.org/bugzilla/show_bug.cgi?id=114999


Attachment: smime.p7s
Description: S/MIME cryptographic signature

Reply via email to