https://gcc.gnu.org/g:b3cc0b4da1b94e3b3c2895011ab8d19d1268c34b
commit b3cc0b4da1b94e3b3c2895011ab8d19d1268c34b Author: Mikael Morin <mik...@gcc.gnu.org> Date: Thu Jul 4 15:24:36 2024 +0200 match: Unwrap non-lvalue as unary or binary operand gcc/ChangeLog: * match.pd: Unwrap NON_LVALUE_EXPR trees when they are used as operand of a unary or binary operator. gcc/testsuite/ChangeLog: * gfortran.dg/non_lvalue_2.f90: New test. Diff: --- gcc/match.pd | 12 ++++++++ gcc/testsuite/gfortran.dg/non_lvalue_2.f90 | 44 ++++++++++++++++++++++++++++++ 2 files changed, 56 insertions(+) diff --git a/gcc/match.pd b/gcc/match.pd index d0859545ada..513df562fd7 100644 --- a/gcc/match.pd +++ b/gcc/match.pd @@ -280,6 +280,18 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT) (outer_op @0 @2) @3)))))) +/* Remove superfluous NON_LVALUE_EXPR in unary operators. */ +(for op (UNCOND_UNARY) + (simplify (op (non_lvalue @0)) + (op @0))) + +/* Remove superfluous NON_LVALUE_EXPR in binary operators. */ +(for op (UNCOND_BINARY tcc_comparison) + (simplify (op (non_lvalue @0) @1) + (op @0 @1)) + (simplify (op @0 (non_lvalue @1)) + (op @0 @1))) + /* Simplify x - x. This is unsafe for certain floats even in non-IEEE formats. In IEEE, it is unsafe because it does wrong for NaNs. diff --git a/gcc/testsuite/gfortran.dg/non_lvalue_2.f90 b/gcc/testsuite/gfortran.dg/non_lvalue_2.f90 new file mode 100644 index 00000000000..8c3197eab1f --- /dev/null +++ b/gcc/testsuite/gfortran.dg/non_lvalue_2.f90 @@ -0,0 +1,44 @@ +! { dg-do compile } +! { dg-additional-options "-fdump-tree-original" } +! +! Check the removal of NON_LVALUE_EXPR if they are used in a non-lvalue context + +! The NON_LVALUE_EXPR is dropped if it's part (left operand) of a bigger expression +function f1 (f1_arg1, f1_arg2) + integer, value :: f1_arg1, f1_arg2 + integer :: f1 + f1 = (f1_arg1 + 0) + f1_arg2 +end function +! { dg-final { scan-tree-dump "__result_f1 = f1_arg1 \\+ f1_arg2;" "original" } } + +! The NON_LVALUE_EXPR is dropped if it's part (right operand) of a bigger expression +function f2 (f2_arg1, f2_arg2) + integer, value :: f2_arg1, f2_arg2 + integer :: f2 + f2 = f2_arg1 + (f2_arg2 + 0) +end function +! { dg-final { scan-tree-dump "__result_f2 = f2_arg1 \\+ f2_arg2;" "original" } } + +! The NON_LVALUE_EXPR is dropped if it's part (left operand) of a binary logical operator +function f3 (f3_arg1) + integer, value :: f3_arg1 + logical :: f3 + f3 = (f3_arg1 + 0) > 0 +end function +! { dg-final { scan-tree-dump "__result_f3 = f3_arg1 > 0;" "original" } } + +! The NON_LVALUE_EXPR is dropped if it's part (right operand) of a binary logical operator +function f4 (f4_arg1, f4_arg2) + integer, value :: f4_arg1, f4_arg2 + logical :: f4 + f4 = f4_arg1 > (f4_arg2 + 0) +end function +! { dg-final { scan-tree-dump "__result_f4 = f4_arg1 > f4_arg2;" "original" } } + +! The NON_LVALUE_EXPR is dropped if it's part of a unary operator +function f5 (f5_arg1) + integer, value :: f5_arg1 + integer :: f5 + f5 = -(not(not(f5_arg1))) +end function +! { dg-final { scan-tree-dump "__result_f5 = -f5_arg1;" "original" } }