> On 15 Sep 2025, at 09:29, Jennifer Schmitz <[email protected]> wrote:
> 
> External email: Use caution opening links or attachments
> 
> 
>> On 28 Aug 2025, at 09:19, Jennifer Schmitz <[email protected]> wrote:
>> 
>> External email: Use caution opening links or attachments
>> 
>> 
>>> On 25 Aug 2025, at 15:40, Kyrylo Tkachov <[email protected]> wrote:
>>> 
>>> Hi Jennifer,
>>> 
>>>> On 25 Aug 2025, at 12:56, Jennifer Schmitz <[email protected]> wrote:
>>>> 
>>>> When op2 in SVE2 saturating add intrinsics (svuqadd, svsqadd) is a zero
>>>> vector and predication is _z, an ICE in vregs occurs, e.g. for
>>>> 
>>>> svuint8_t foo (svbool_t pg, svuint8_t op1)
>>>> {
>>>> return svsqadd_u8_z (pg, op1, svdup_s8 (0));
>>>> }
>>>> 
>>>> The insn failed to match the pattern (aarch64-sve2.md):
>>>> 
>>>> ;; Predicated binary operations with no reverse form, merging with zero.
>>>> ;; At present we don't generate these patterns via a cond_* optab,
>>>> ;; so there's no correctness requirement to handle merging with an
>>>> ;; independent value.
>>>> (define_insn_and_rewrite "*cond_<sve_int_op><mode>_z"
>>>> [(set (match_operand:SVE_FULL_I 0 "register_operand")
>>>> (unspec:SVE_FULL_I
>>>> [(match_operand:<VPRED> 1 "register_operand")
>>>> (unspec:SVE_FULL_I
>>>>  [(match_operand 5)
>>>>   (unspec:SVE_FULL_I
>>>> [(match_operand:SVE_FULL_I 2 "register_operand")
>>>> (match_operand:SVE_FULL_I 3 "register_operand")]
>>>> SVE2_COND_INT_BINARY_NOREV)]
>>>>  UNSPEC_PRED_X)
>>>> (match_operand:SVE_FULL_I 4 "aarch64_simd_imm_zero")]
>>>> UNSPEC_SEL))]
>>>> "TARGET_SVE2"
>>>> {@ [ cons: =0 , 1   , 2 , 3  ]
>>>>  [ &w       , Upl , 0 , w  ] movprfx\t%0.<Vetype>, %1/z, 
>>>> %0.<Vetype>\;<sve_int_op>\t%0.<Vetype>, %1/m, %0.<Vetype>, %3.<Vetype>
>>>>  [ &w       , Upl , w , w  ] movprfx\t%0.<Vetype>, %1/z, 
>>>> %2.<Vetype>\;<sve_int_op>\t%0.<Vetype>, %1/m, %0.<Vetype>, %3.<Vetype>
>>>> }
>>>> "&& !CONSTANT_P (operands[5])"
>>>> {
>>>> operands[5] = CONSTM1_RTX (<VPRED>mode);
>>>> }
>>>> [(set_attr "movprfx" "yes")]
>>>> )
>>>> 
>>>> because operands[3] and operands[4] were both expanded into the same 
>>>> register
>>>> operand containing a zero vector by
>>>> 
>>>> ;; Predicated binary arithmetic with merging.
>>>> (define_expand "@cond_<sve_int_op><mode>"
>>>> [(set (match_operand:SVE_FULL_I 0 "register_operand")
>>>> (unspec:SVE_FULL_I
>>>> [(match_operand:<VPRED> 1 "register_operand")
>>>> (unspec:SVE_FULL_I
>>>>  [(match_dup 5)
>>>>   (unspec:SVE_FULL_I
>>>> [(match_operand:SVE_FULL_I 2 "register_operand")
>>>> (match_operand:SVE_FULL_I 3 "register_operand")]
>>>> SVE2_COND_INT_BINARY)]
>>>>  UNSPEC_PRED_X)
>>>> (match_operand:SVE_FULL_I 4 "aarch64_simd_reg_or_zero")]
>>>> UNSPEC_SEL))]
>>>> "TARGET_SVE2"
>>>> {
>>>> operands[5] = CONSTM1_RTX (<MODE>mode);
>>>> }
>>>> )
>>>> 
>>>> This patch fixes the ICE by changing the predicate of operands[3]
>>>> in both patterns to aarch64_simd_reg_or_zero. It also adds tests
>>>> adjusted from the report in PR121599.
>>>> 
>>>> The patch was bootstrapped and tested on aarch64-linux-gnu, no regression.
>>>> OK for trunk?
>>>> 
>>>> Alex Coplan pointed out in the bugzilla ticket that this ICE goes back
>>>> to GCC 10. Shall we backport?
>>>> 
>>>> Signed-off-by: Jennifer Schmitz <[email protected]>
>>>> 
>>>> gcc/
>>>> PR target/121599
>>>> * config/aarch64/aarch64-sve2.md (@cond_<sve_int_op><mode>):
>>>> Set predicate for operand 3 to aarch64_simd_reg_or_zero.
>>>> (*cond_<sve_int_op><mode>_z): Likewise.
>>>> 
>>>> gcc/testsuite/
>>>> PR target/121599
>>>> * gcc.target/aarch64/sve2/pr121599.c: New test.
>>>> ---
>>>> gcc/config/aarch64/aarch64-sve2.md            |  4 +--
>>>> .../gcc.target/aarch64/sve2/pr121599.c        | 31 +++++++++++++++++++
>>>> 2 files changed, 33 insertions(+), 2 deletions(-)
>>>> create mode 100644 gcc/testsuite/gcc.target/aarch64/sve2/pr121599.c
>>>> 
>>>> diff --git a/gcc/config/aarch64/aarch64-sve2.md 
>>>> b/gcc/config/aarch64/aarch64-sve2.md
>>>> index a3cbbce8b31..c6a84fa7f3d 100644
>>>> --- a/gcc/config/aarch64/aarch64-sve2.md
>>>> +++ b/gcc/config/aarch64/aarch64-sve2.md
>>>> @@ -1021,7 +1021,7 @@
>>>>  [(match_dup 5)
>>>>   (unspec:SVE_FULL_I
>>>> [(match_operand:SVE_FULL_I 2 "register_operand")
>>>> - (match_operand:SVE_FULL_I 3 "register_operand")]
>>>> + (match_operand:SVE_FULL_I 3 "aarch64_simd_reg_or_zero")]
>>>> SVE2_COND_INT_BINARY)]
>>>>  UNSPEC_PRED_X)
>>>> (match_operand:SVE_FULL_I 4 "aarch64_simd_reg_or_zero")]
>>>> @@ -1136,7 +1136,7 @@
>>>>  [(match_operand 5)
>>>>   (unspec:SVE_FULL_I
>>>> [(match_operand:SVE_FULL_I 2 "register_operand")
>>>> - (match_operand:SVE_FULL_I 3 "register_operand")]
>>>> + (match_operand:SVE_FULL_I 3 "aarch64_simd_reg_or_zero")]
>>>> SVE2_COND_INT_BINARY_NOREV)]
>>>>  UNSPEC_PRED_X)
>>>> (match_operand:SVE_FULL_I 4 "aarch64_simd_imm_zero")]
>>> 
>>> I think the ICE happens because operands[4] ends up being a register which 
>>> the aarch64_simd_imm_zero can’t handle.
>>> The pattern *cond_<sve_int_op><mode>_z is also not supposed to be handling 
>>> register operands, it only expresses a merge with zero.
>>> Allowing a zero in operands[3] here is problematic as the output code 
>>> wouldn’t know how to print it if the midend used a zero vector for it.
>>> 
>>> I think the right solution is to adjust the @cond_<sve_int_op><mode> 
>>> expander to only allow aarch64_simd_imm_zero for operands[4] for the 
>>> SVE2_COND_INT_BINARY_NOREV subset of SVE2_COND_INT_BINARY.
>> Hi Kyrill,
>> Thanks for reviewing the patch.
>> I tried allowing only aarch64_simd_imm_zero for operands[4] for 
>> SVE2_COND_INT_BINARY_NOREV, but while that solved the ICE it caused all 
>> tests predication other than _z to fail.
>> I chose instead to add a pattern similar to the existing 
>> *cond_<sve_int_op><mode>_3 for SVE2_COND_INT_BINARY_NOREV that handles the 
>> case when operands[3] and operands[4] are the same register operand.
>> Thanks,
>> Jennifer
> Gentle ping.
> Thanks,
> Jennifer
Gentle ping.
Thanks,
Jennifer
>> 
>> When op2 in SVE2 saturating add intrinsics (svuqadd, svsqadd) is a zero
>> vector and predication is _z, an ICE in vregs occurs, e.g. for
>> 
>> svuint8_t foo (svbool_t pg, svuint8_t op1)
>> {
>>   return svsqadd_u8_z (pg, op1, svdup_s8 (0));
>> }
>> 
>> The insn failed to match the pattern (aarch64-sve2.md):
>> 
>> ;; Predicated binary operations with no reverse form, merging with zero.
>> ;; At present we don't generate these patterns via a cond_* optab,
>> ;; so there's no correctness requirement to handle merging with an
>> ;; independent value.
>> (define_insn_and_rewrite "*cond_<sve_int_op><mode>_z"
>> [(set (match_operand:SVE_FULL_I 0 "register_operand")
>>       (unspec:SVE_FULL_I
>>         [(match_operand:<VPRED> 1 "register_operand")
>>          (unspec:SVE_FULL_I
>>            [(match_operand 5)
>>             (unspec:SVE_FULL_I
>>               [(match_operand:SVE_FULL_I 2 "register_operand")
>>                (match_operand:SVE_FULL_I 3 "register_operand")]
>>               SVE2_COND_INT_BINARY_NOREV)]
>>            UNSPEC_PRED_X)
>>          (match_operand:SVE_FULL_I 4 "aarch64_simd_imm_zero")]
>>         UNSPEC_SEL))]
>> "TARGET_SVE2"
>> {@ [ cons: =0 , 1   , 2 , 3  ]
>>    [ &w       , Upl , 0 , w  ] movprfx\t%0.<Vetype>, %1/z, 
>> %0.<Vetype>\;<sve_int_op>\t%0.<Vetype>, %1/m, %0.<Vetype>, %3.<Vetype>
>>    [ &w       , Upl , w , w  ] movprfx\t%0.<Vetype>, %1/z, 
>> %2.<Vetype>\;<sve_int_op>\t%0.<Vetype>, %1/m, %0.<Vetype>, %3.<Vetype>
>> }
>> "&& !CONSTANT_P (operands[5])"
>> {
>>   operands[5] = CONSTM1_RTX (<VPRED>mode);
>> }
>> [(set_attr "movprfx" "yes")]
>> )
>> 
>> because operands[3] and operands[4] were both expanded into the same register
>> operand containing a zero vector by define_expand "@cond_<sve_int_op><mode>".
>> 
>> This patch fixes the ICE by adding the pattern
>> ;; Predicated binary operations with no reverse form, merging with
>> ;; the second input.
>> (define_insn_and_rewrite "*cond_<sve_int_op><mode>_3"
>> for SVE2_COND_INT_BINARY_NOREV that allows operands[4] to be a register 
>> operand
>> (equal to operands[3]). It adds a vcond_mask expression such that we end
>> up with an insn matched by
>> ;; Predicated binary arithmetic, merging with the first input.
>> (define_insn_and_rewrite "*cond_<sve_int_op><mode>_2"
>> 
>> The patch was bootstrapped and tested on aarch64-linux-gnu, no regression.
>> OK for trunk?
>> 
>> Alex Coplan pointed out in the bugzilla ticket that this ICE goes back
>> to GCC 10. Shall we backport?
>> 
>> Signed-off-by: Jennifer Schmitz <[email protected]>
>> 
>> gcc/
>>       PR target/121599
>>       * config/aarch64/aarch64-sve2.md (*cond_<sve_int_op><mode>_3):
>>       New pattern for SVE2_COND_INT_BINARY_NOREV.
>> 
>> gcc/testsuite/
>>       PR target/121599
>>       * gcc.target/aarch64/sve2/pr121599.c: New test.
>> ---
>> gcc/config/aarch64/aarch64-sve2.md            | 36 +++++++++++++++++++
>> .../gcc.target/aarch64/sve2/pr121599.c        | 31 ++++++++++++++++
>> 2 files changed, 67 insertions(+)
>> create mode 100644 gcc/testsuite/gcc.target/aarch64/sve2/pr121599.c
>> 
>> diff --git a/gcc/config/aarch64/aarch64-sve2.md 
>> b/gcc/config/aarch64/aarch64-sve2.md
>> index a3cbbce8b31..d82dc41df3e 100644
>> --- a/gcc/config/aarch64/aarch64-sve2.md
>> +++ b/gcc/config/aarch64/aarch64-sve2.md
>> @@ -1124,6 +1124,42 @@
>>  [(set_attr "movprfx" "yes")]
>> )
>> 
>> +;; Predicated binary operations with no reverse form, merging with
>> +;; the second input.
>> +(define_insn_and_rewrite "*cond_<sve_int_op><mode>_3"
>> +  [(set (match_operand:SVE_FULL_I 0 "register_operand")
>> +       (unspec:SVE_FULL_I
>> +         [(match_operand:<VPRED> 1 "register_operand")
>> +          (unspec:SVE_FULL_I
>> +            [(match_operand 5)
>> +             (unspec:SVE_FULL_I
>> +               [(match_operand:SVE_FULL_I 2 "register_operand")
>> +                (match_operand:SVE_FULL_I 3 "register_operand")]
>> +               SVE2_COND_INT_BINARY_NOREV)]
>> +            UNSPEC_PRED_X)
>> +          (match_operand:SVE_FULL_I 4 "register_operand")]
>> +         UNSPEC_SEL))]
>> +  "TARGET_SVE2
>> +   && rtx_equal_p (operands[3], operands[4])"
>> +  "#"
>> +  "&& 1"
>> +  {
>> +    if (reload_completed
>> +        && register_operand (operands[4], <MODE>mode)
>> +        && !rtx_equal_p (operands[0], operands[4]))
>> +      {
>> +       emit_insn (gen_vcond_mask_<mode><vpred> (operands[0], operands[2],
>> +                                                operands[4], operands[1]));
>> +       operands[4] = operands[2] = operands[0];
>> +      }
>> +    else if (!CONSTANT_P (operands[5]))
>> +      operands[5] = CONSTM1_RTX (<VPRED>mode);
>> +    else
>> +      FAIL;
>> +  }
>> +  [(set_attr "movprfx" "yes")]
>> +)
>> +
>> ;; Predicated binary operations with no reverse form, merging with zero.
>> ;; At present we don't generate these patterns via a cond_* optab,
>> ;; so there's no correctness requirement to handle merging with an
>> diff --git a/gcc/testsuite/gcc.target/aarch64/sve2/pr121599.c 
>> b/gcc/testsuite/gcc.target/aarch64/sve2/pr121599.c
>> new file mode 100644
>> index 00000000000..dbfa613649d
>> --- /dev/null
>> +++ b/gcc/testsuite/gcc.target/aarch64/sve2/pr121599.c
>> @@ -0,0 +1,31 @@
>> +/* PR target/121599.  */
>> +/* { dg-do compile } */
>> +/* { dg-options "-O2" } */
>> +/* { dg-final { check-function-bodies "**" "" "" } } */
>> +
>> +#include <arm_sve.h>
>> +
>> +/*
>> +** foo:
>> +**     movi    d([0-9]+), #0
>> +**     sel     z0\.b, p0, z0\.b, z\1\.b
>> +**     usqadd  z0\.b, p0/m, z0\.b, z\1\.b
>> +**     ret
>> +*/
>> +svuint8_t foo (svbool_t pg, svuint8_t op1)
>> +{
>> +    return svsqadd_u8_z (pg, op1, svdup_s8 (0));
>> +}
>> +
>> +/*
>> +** bar:
>> +**     movi    d([0-9]+), #0
>> +**     sel     z0\.b, p0, z0\.b, z\1\.b
>> +**     suqadd  z0\.b, p0/m, z0\.b, z\1\.b
>> +**     ret
>> +*/
>> +svint8_t bar (svbool_t pg, svint8_t op1)
>> +{
>> +    return svuqadd_n_s8_z (pg, op1, 0);
>> +}
>> +
>> --
>> 2.34.1
>>> 
>>> Thanks,
>>> Kyrill
>>> 
>>>> diff --git a/gcc/testsuite/gcc.target/aarch64/sve2/pr121599.c 
>>>> b/gcc/testsuite/gcc.target/aarch64/sve2/pr121599.c
>>>> new file mode 100644
>>>> index 00000000000..cd80ef9115c
>>>> --- /dev/null
>>>> +++ b/gcc/testsuite/gcc.target/aarch64/sve2/pr121599.c
>>>> @@ -0,0 +1,31 @@
>>>> +/* PR target/121599.  */
>>>> +/* { dg-do compile } */
>>>> +/* { dg-options "-O2" } */
>>>> +/* { dg-final { check-function-bodies "**" "" "" } } */
>>>> +
>>>> +#include <arm_sve.h>
>>>> +
>>>> +/*
>>>> +** foo:
>>>> +** movi d([0-9]+), #0
>>>> +** movprfx z0\.b, p0/z, z0\.b
>>>> +** usqadd z0\.b, p0/m, z0\.b, z\1\.b
>>>> +** ret
>>>> +*/
>>>> +svuint8_t foo (svbool_t pg, svuint8_t op1)
>>>> +{
>>>> +    return svsqadd_u8_z (pg, op1, svdup_s8 (0));
>>>> +}
>>>> +
>>>> +/*
>>>> +** bar:
>>>> +** movi d([0-9]+), #0
>>>> +** movprfx z0\.b, p0/z, z0\.b
>>>> +** suqadd z0\.b, p0/m, z0\.b, z\1\.b
>>>> +** ret
>>>> +*/
>>>> +svint8_t bar (svbool_t pg, svint8_t op1)
>>>> +{
>>>> +    return svuqadd_n_s8_z (pg, op1, 0);
>>>> +}
>>>> +
>>>> --
>>>> 2.34.1


Reply via email to