From: Matthew Malcomson <mmalcom...@nvidia.com>

Cc'ing in i386 maintainers.

-------------- >8 ------- 8< -----------
In ix86_atomic_assign_expand_fenv we generate some TREE to be expanded.
Originally this code used `MODIFY_EXPR`, but that caused some bugs due
to the use of `create_tmp_var_raw`.
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=94780
This was then fixed in revision 9b8e9006bb35 by using `TARGET_EXPR`
instead.

`MODIFY_EXPR` expressions are automatically marked with
`TREE_SIDE_EFFECTS`, while `TARGET_EXPR` expressions are not.
In most instances of this function this does not matter since the
expression used to initialise variables is a function call and `build4`
automatically sets the flag on the result anyway.

For `hold_assign_orig` that is not the case.  While it is initialised by
a function call that function call is marked as PURE.  Hence the
initialisation is marked as not having side-effects.  This variable
eventually gets put into a `COMPOUND_EXPR` as the first argument with
the second argument using the variable that has been added.  This
removal of the unused expression was not happening for the C frontend,
but I newly use it in the C++ frontend where we call `cp_fold_r` and
this exposes the latent bug.

Here marking `hold_assign_orig` as `TREE_SIDE_EFFECTS` in order to avoid
this problem.  It will mean that the `COMPOUND_EXPR` it is used in is
also marked as having side effects.  While that means nothing gets
optimised out in practice it still seems like good practice to mark
`hold_assign_mod` as having side effects to.  This assigns to
`mxcsr_mod_var` which is used in later expressions.

This commit fixes the below libstdc++ tests that fail with the previous
commits in this patch series applied:
- 29_atomics/atomic_float/1.cc
- 29_atomics/atomic_float/compare_exchange_padding.cc
- 29_atomics/atomic_ref/float.cc

Questions for reviewers:
- Is there any problem setting a `TARGET_EXPR` to have
  `TREE_SIDE_EFFECTS`?  When trying to interpret why this expression
  doesn't automatically get set as having side effects I get the
  impression it's to do with the possible cacheing of the expression in
  argument 3 (honestly not 100% confident on my interpretation of what
  happens with this argument).
  - I would also appreciate a little expansion on why a `TARGET_EXPR` is
    not automatically marked as having side-effects in `make_node`,
    while `INIT_EXPR` is.  I guess the operand 3 thing again?

gcc/ChangeLog:

        * config/i386/i386.cc (ix86_atomic_assign_expand_fenv): Set side
        effects flag on `hold_assign_orig` and `hold_assign_mod`.

Signed-off-by: Matthew Malcomson <mmalcom...@nvidia.com>
---
 gcc/config/i386/i386.cc | 17 +++++++++++++++++
 1 file changed, 17 insertions(+)

diff --git a/gcc/config/i386/i386.cc b/gcc/config/i386/i386.cc
index 613f2b2139d..7ea56cd8d76 100644
--- a/gcc/config/i386/i386.cc
+++ b/gcc/config/i386/i386.cc
@@ -26737,6 +26737,14 @@ ix86_atomic_assign_expand_fenv (tree *hold, tree 
*clear, tree *update)
       tree hold_assign_orig = build4 (TARGET_EXPR, unsigned_type_node,
                                      mxcsr_orig_var, stmxcsr_hold_call,
                                      NULL_TREE, NULL_TREE);
+      /* Ensure that this doesn't get optimised out of the COMPOUND_EXPR we
+       * define below.  It appears on first glance that the fact the
+       * initialisation argument is a function call would mean this
+       * automatically gets set, but that function call is marked as pure and
+       * so does not have the side-effects flag.
+       * This particular assignment needs to be marked as having side-effects
+       * because we use the value in the variable that gets assigned.  */
+      TREE_SIDE_EFFECTS (hold_assign_orig) = 1;
       tree hold_mod_val = build2 (BIT_IOR_EXPR, unsigned_type_node,
                                  mxcsr_orig_var,
                                  build_int_cst (unsigned_type_node, 0x1f80));
@@ -26745,6 +26753,15 @@ ix86_atomic_assign_expand_fenv (tree *hold, tree 
*clear, tree *update)
       tree hold_assign_mod = build4 (TARGET_EXPR, unsigned_type_node,
                                     mxcsr_mod_var, hold_mod_val,
                                     NULL_TREE, NULL_TREE);
+      /* Similar to above, ensure that this is marked as having side effects
+       * because we rely on the assignment to `mxcsr_mod_var` for later uses.
+       * While this expression is going in arg1 of a `COMPOUND_EXPR`, that
+       * `COMPOUND_EXPR` is going into arg0 of another one.  Since we've marked
+       * the initialisation above as having side effects the `COMPOUND_EXPR`
+       * will not be optimised away and we don't technically need this second
+       * marking, however it still seems like good practice to mark everything
+       * that has side effects we care about as having those side effects. */
+      TREE_SIDE_EFFECTS (hold_assign_mod) = 1;
       tree ldmxcsr_hold_call = build_call_expr (ldmxcsr, 1, mxcsr_mod_var);
       tree hold_all = build2 (COMPOUND_EXPR, unsigned_type_node,
                              hold_assign_orig, hold_assign_mod);
-- 
2.43.0

Reply via email to