[PATCH] Fix hangs with long double atomics (PR middle-end/71716)

Jakub Jelinek jakub@redhat.com
Fri Jul 1 15:07:00 GMT 2016


Hi!

As mentioned in the PR, atomics on types that contain some inner padding
(e.g. long double type on x86_64) have various issues.
Before my ATOMIC_COMPARE_EXCHANGE internal-fn addition, unless the user
uses atomic_compare_exchange* APIs and changes (e.g. copies elsewhere) the
expected variable, what can worst case happen is that atomic_load (done
using integral type covering all the bits) reads a value, then it is VCEd to
long double and stored as long double into the "expected" variable and
during this store, we can end up with random padding bits in the "expected"
variable and the first CAS can fail because of that.  But, with the RTL
store of the new "expected" value which is done using the integral type
the padding bits will have all proper values in the second iteration
already.
While with ATOMIC_COMPARE_EXCHANGE, the VIEW_CONVERT_EXPRs are visible in
GIMPLE and it is possible that all iterations have some issues in the
padding bits.

Thus, the following patch just disables the optimization for floating point
types (float/double perhaps might be fine, but I'm worried about sNaNs),
and also any other types that can contain some padding.

Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?

2016-07-01  Jakub Jelinek  <jakub@redhat.com>

	PR middle-end/71716
	* gimple-fold.c (optimize_atomic_compare_exchange_p): Return false
	for SCALAR_FLOAT_TYPE_P type of expected var, or if TYPE_PRECISION
	is different from mode's bitsize.  Small cleanup.

--- gcc/gimple-fold.c.jj	2016-06-28 10:26:52.000000000 +0200
+++ gcc/gimple-fold.c	2016-07-01 11:29:57.700252754 +0200
@@ -2984,12 +2984,19 @@ optimize_atomic_compare_exchange_p (gimp
 
   tree expected = gimple_call_arg (stmt, 1);
   if (TREE_CODE (expected) != ADDR_EXPR
-      || !SSA_VAR_P (TREE_OPERAND (expected, 0))
-      || !is_gimple_reg_type (TREE_TYPE (TREE_OPERAND (expected, 0)))
+      || !SSA_VAR_P (TREE_OPERAND (expected, 0)))
+    return false;
+
+  tree etype = TREE_TYPE (TREE_OPERAND (expected, 0));
+  if (!is_gimple_reg_type (etype)
       || !auto_var_in_fn_p (TREE_OPERAND (expected, 0), current_function_decl)
-      || TREE_THIS_VOLATILE (TREE_TYPE (TREE_OPERAND (expected, 0)))
-      || TREE_CODE (TREE_TYPE (TREE_OPERAND (expected, 0))) == VECTOR_TYPE
-      || TREE_CODE (TREE_TYPE (TREE_OPERAND (expected, 0))) == COMPLEX_TYPE)
+      || TREE_THIS_VOLATILE (etype)
+      || VECTOR_TYPE_P (etype)
+      || TREE_CODE (etype) == COMPLEX_TYPE
+      /* Don't optimize floating point expected vars, VIEW_CONVERT_EXPRs
+	 might not preserve all the bits.  See PR71716.  */
+      || SCALAR_FLOAT_TYPE_P (etype)
+      || TYPE_PRECISION (etype) != GET_MODE_BITSIZE (TYPE_MODE (etype)))
     return false;
 
   tree weak = gimple_call_arg (stmt, 3);
@@ -3005,8 +3012,7 @@ optimize_atomic_compare_exchange_p (gimp
       && optab_handler (sync_compare_and_swap_optab, mode) == CODE_FOR_nothing)
     return false;
 
-  if (int_size_in_bytes (TREE_TYPE (TREE_OPERAND (expected, 0)))
-      != GET_MODE_SIZE (mode))
+  if (int_size_in_bytes (etype) != GET_MODE_SIZE (mode))
     return false;
 
   return true;

	Jakub



More information about the Gcc-patches mailing list