"Kewen.Lin" <li...@linux.ibm.com> writes:
> 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"))]

Is it well-formed to have "+" on an operand that is only semantically
an input?  df and most passes would consider it to be a pure input
and so would disregard any write that is intended to take place.

E.g. if we have:

  (set (reg:M R2) (reg:M R1)) ;; R1 dead
  (set (reg:M R3) (reg:M R2))

then it would be valid to change that to:

  (set (reg:M R2) (reg:M R1))
  (set (reg:M R3) (reg:M R1))

without considering the "+" on the input to the first instruction.

But if we do stick with the patch...

>   "!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?
>
> 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.
>
> BR,
> Kewen
> -----
>       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)))

...IMO it would be better to use CONSTANT_P instead.  It's sometimes
useful to accept constants in specific instructions only, meaning that
they aren't general enough to be immediate_operands.

Thanks,
Richard

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

Reply via email to