Hi Vladimir,
on 2024/8/10 01:47, Vladimir Makarov wrote:
>
> On 8/9/24 05:49, Kewen.Lin wrote:
>> Hi,
>>
>> Commit r15-2084 exposes one ICE in LRA. Firstly, before
>> r15-2084 KFmode has 126 bit precision while V1TImode has 128
>> bit precision, so the subreg (subreg:V1TI (reg:KF 131) 0) is
>> paradoxical_subreg_p, which stops some passes from doing
>> some optimization. After r15-2084, KFmode has the same mode
>> precision as V1TImode, passes are able to optimize more, but
>> it causes this ICE in LRA as described below:
>>
>> For insn 106 (set (mem:V1TI ...) (subreg:V1TI (reg:KF 133) 0)),
>> which matches pattern
>>
>> (define_insn "*vsx_le_perm_store_<mode>"
>> [(set (match_operand:VSX_LE_128 0 "memory_operand" "=Z,Q")
>> (match_operand:VSX_LE_128 1 "vsx_register_operand" "+wa,r"))]
>> "!BYTES_BIG_ENDIAN && TARGET_VSX && !TARGET_P9_VECTOR
>> && !altivec_indexed_or_indirect_operand (operands[0], <MODE>mode)"
>> "@
>> #
>> #"
>> [(set_attr "type" "vecstore,store")
>> (set_attr "length" "12,8")
>> (set_attr "isa" "<VSisa>,*")])
>> LRA makes equivalence substitution on r133 with const double
>> (const_double:KF 0.0), selects alternative 0 and fixes up
>> operand 1 for constraint "wa", because operand 1 is OP_INOUT,
>> so it considers assigning back to it as well, that is:
>>
>> lra_emit_move (type == OP_INOUT ? copy_rtx (old) : old, new_reg);
>>
>> But because old has been changed to const_double in equivalence
>> substitution, the move is actually assigning to const_double,
>> which is invalid and cause ICE.
>>
>> Considering reg:KF 133 is equivalent with (const_double:KF 0.0)
>> even though this operand is OP_INOUT, IMHO there should not be
>> any following uses of reg:KF 133, otherwise it doesn't have the
>> chance to be equivalent to (const_double:KF 0.0). From this
>> perspective, I think we can guard the lra_emit_move with
>> nonimmediate_operand to exclude such case.
>>
>> Does it sound reasonable?
> Yes.
>> btw, I also tried with disallowing equivalence substitution with
>> CONSTANT_P value if the corresponding operand is OP_INOUT or
>> OP_OUT, it can also fix this issue, but with more thinking it
>> seems not necessary to stop such substitution if we can handle it
>> later as above.
>>
>> Bootstrapped and regtested on x86_64-redhat-linux and
>> powerpc64{,le}-linux-gnu.
>>
> Thank you for the good explanation of the problem. The patch is ok for me.
> It would be nice to add a comment before `nonimmediate_operand` that `old`
> can be an equivalent constant and we chose insn alternative before the
> equivalent substitution.
Thanks for your comments!! If I read the code right, the function chooses
insn alternative after equivalence substitution, the related code is:
4207 if (lra_dump_file != NULL)
4208 {
4209 fprintf (lra_dump_file,
4210 "Changing pseudo %d in operand %i of insn %u on
equiv ",
4211 REGNO (old), i, INSN_UID (curr_insn));
4212 dump_value_slim (lra_dump_file, subst, 1);
4213 fprintf (lra_dump_file, "\n");
4214 }
4215 op_change_p = change_p = true;
4216 }
4217 if (simplify_operand_subreg (i, GET_MODE (old)) || op_change_p)
4218 {
4219 change_p = true;
4220 lra_update_dup (curr_id, i);
4221 }
4411 fprintf (lra_dump_file, " Choosing alt %d in insn %u:",
4412 goal_alt_number, INSN_UID (curr_insn));
4413 print_curr_insn_alt (goal_alt_number);
so I just added a comment as you suggested but stripping "and ...":
diff --git a/gcc/lra-constraints.cc b/gcc/lra-constraints.cc
index 92b343fa99a..f355c6c6168 100644
--- a/gcc/lra-constraints.cc
+++ b/gcc/lra-constraints.cc
@@ -4742,7 +4742,9 @@ curr_insn_transform (bool check_only_p)
}
*loc = new_reg;
if (type != OP_IN
- && find_reg_note (curr_insn, REG_UNUSED, old) == NULL_RTX)
+ && find_reg_note (curr_insn, REG_UNUSED, old) == NULL_RTX
+ /* OLD can be an equivalent constant here. */
+ && nonimmediate_operand (old, GET_MODE (old)))
{
start_sequence ();
lra_emit_move (type == OP_INOUT ? copy_rtx (old) : old, new_reg);
Does it look good to you? Or did I miss something here?
Thanks again!
BR,
Kewen
>
> Thank you for fixing the PR.
>
>> PR rtl-optimization/116170
>>
>> gcc/ChangeLog:
>>
>> * lra-constraints.cc (curr_insn_transform): Don't emit move back to
>> old operand if it's nonimmediate_operand.
>>
>> gcc/testsuite/ChangeLog:
>>
>> * gcc.target/powerpc/pr116170.c: New test.
>> ---
>> gcc/lra-constraints.cc | 3 ++-
>> gcc/testsuite/gcc.target/powerpc/pr116170.c | 18 ++++++++++++++++++
>> 2 files changed, 20 insertions(+), 1 deletion(-)
>> create mode 100644 gcc/testsuite/gcc.target/powerpc/pr116170.c
>>
>> diff --git a/gcc/lra-constraints.cc b/gcc/lra-constraints.cc
>> index 92b343fa99a..024c85c87d9 100644
>> --- a/gcc/lra-constraints.cc
>> +++ b/gcc/lra-constraints.cc
>> @@ -4742,7 +4742,8 @@ curr_insn_transform (bool check_only_p)
>> }
>> *loc = new_reg;
>> if (type != OP_IN
>> - && find_reg_note (curr_insn, REG_UNUSED, old) == NULL_RTX)
>> + && find_reg_note (curr_insn, REG_UNUSED, old) == NULL_RTX
>> + && nonimmediate_operand (old, GET_MODE (old)))
>> {
>> start_sequence ();
>> lra_emit_move (type == OP_INOUT ? copy_rtx (old) : old, new_reg);
>> diff --git a/gcc/testsuite/gcc.target/powerpc/pr116170.c
>> b/gcc/testsuite/gcc.target/powerpc/pr116170.c
>> new file mode 100644
>> index 00000000000..6f6ca0f1ae9
>> --- /dev/null
>> +++ b/gcc/testsuite/gcc.target/powerpc/pr116170.c
>> @@ -0,0 +1,18 @@
>> +/* { dg-do compile } */
>> +/* { dg-require-effective-target ppc_float128_sw } */
>> +/* { dg-options "-mdejagnu-cpu=power8 -O2 -fstack-protector-strong
>> -ffloat-store" } */
>> +
>> +/* Verify there is no ICE. */
>> +
>> +int a, d;
>> +_Float128 b, c;
>> +void
>> +e ()
>> +{
>> + int f = 0;
>> + if (a)
>> + if (b || c)
>> + f = 1;
>> + if (d)
>> + e (f ? 0 : b);
>> +}
>> --
>> 2.43.5
>>
>