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 >> >