On Sun, Jun 22, 2025 at 2:11 PM Mikael Morin <[email protected]> wrote:
>
> From: Mikael Morin <[email protected]>
>
> Changes v1 -> v2:
> - Also handle complex conjugate operator.
That's OK.
> - Don't create the NON_LVALUE_EXPR if there is a type conversion between the
> doubled operators.
We're not doing that elsewhere so I'd rather not do it here either.
Does it cause
actual problems?
> Regression tested on x86_64-linux. OK for master?
>
> -- 8< --
>
> gcc/ChangeLog:
>
> * match.pd (`-(-X)`, `~(~X)`, `conj(conj(X))`): Add a
> NON_LVALUE_EXPR wrapper to the simplification of doubled unary
> operators NEGATE_EXPR, BIT_NOT_EXPR and CONJ_EXPR.
>
> gcc/testsuite/ChangeLog:
>
> * gfortran.dg/non_lvalue_1.f90: New test.
> ---
> gcc/match.pd | 10 +++++--
> gcc/testsuite/gfortran.dg/non_lvalue_1.f90 | 32 ++++++++++++++++++++++
> 2 files changed, 39 insertions(+), 3 deletions(-)
> create mode 100644 gcc/testsuite/gfortran.dg/non_lvalue_1.f90
>
> diff --git a/gcc/match.pd b/gcc/match.pd
> index 0f53c162fce..372d4657baa 100644
> --- a/gcc/match.pd
> +++ b/gcc/match.pd
> @@ -2357,7 +2357,7 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
> /* ~~x -> x */
> (simplify
> (bit_not (bit_not @0))
> - @0)
> + (non_lvalue @0))
>
> /* zero_one_valued_p will match when a value is known to be either
> 0 or 1 including constants 0 or 1.
> @@ -4037,7 +4037,9 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
> (negate (nop_convert? (negate @1)))
> (if (!TYPE_OVERFLOW_SANITIZED (type)
> && !TYPE_OVERFLOW_SANITIZED (TREE_TYPE (@1)))
> - (view_convert @1)))
> + (if (GENERIC && type == TREE_TYPE (@1))
> + (non_lvalue @1)
> + (view_convert @1))))
>
> /* We can't reassociate floating-point unless -fassociative-math
> or fixed-point plus or minus because of saturation to +-Inf. */
> @@ -5767,7 +5769,9 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
> (simplify
> (conj (convert? (conj @0)))
> (if (tree_nop_conversion_p (TREE_TYPE (@0), type))
> - (convert @0)))
> + (if (GENERIC && type == TREE_TYPE (@0))
> + (non_lvalue @0)
> + (convert @0))))
>
> /* conj({x,y}) -> {x,-y} */
> (simplify
> diff --git a/gcc/testsuite/gfortran.dg/non_lvalue_1.f90
> b/gcc/testsuite/gfortran.dg/non_lvalue_1.f90
> new file mode 100644
> index 00000000000..61dad5a2ce1
> --- /dev/null
> +++ b/gcc/testsuite/gfortran.dg/non_lvalue_1.f90
> @@ -0,0 +1,32 @@
> +! { dg-do compile }
> +! { dg-additional-options "-fdump-tree-original" }
> +!
> +! Check the generation of NON_LVALUE_EXPR expressions in cases where a unary
> +! operator expression would simplify to a bare data reference.
> +
> +! A NON_LVALUE_EXPR is generated for a double negation that would simplify to
> +! a bare data reference.
> +function f1 (f1_arg1)
> + integer, value :: f1_arg1
> + integer :: f1
> + f1 = -(-f1_arg1)
> +end function
> +! { dg-final { scan-tree-dump "__result_f1 = NON_LVALUE_EXPR <f1_arg1>;"
> "original" } }
> +
> +! A NON_LVALUE_EXPR is generated for a double complement that would simplify
> to
> +! a bare data reference.
> +function f2 (f2_arg1)
> + integer, value :: f2_arg1
> + integer :: f2
> + f2 = not(not(f2_arg1))
> +end function
> +! { dg-final { scan-tree-dump "__result_f2 = NON_LVALUE_EXPR <f2_arg1>;"
> "original" } }
> +
> +! A NON_LVALUE_EXPR is generated for a double complex conjugate that would
> +! simplify to a bare data reference.
> +function f3 (f3_arg1)
> + complex, value :: f3_arg1
> + complex :: f3
> + f3 = conjg(conjg(f3_arg1))
> +end function
> +! { dg-final { scan-tree-dump "__result_f3 = NON_LVALUE_EXPR <f3_arg1>;"
> "original" } }
> --
> 2.47.2
>