Backports to 6.x
Jakub Jelinek
jakub@redhat.com
Fri Sep 16 09:53:00 GMT 2016
Hi!
I've backported a bunch of patches to 6.x, after bootstrapping/regtesting
them on x86_64-linux and i686-linux:
Jakub
-------------- next part --------------
2016-09-16 Jakub Jelinek <jakub@redhat.com>
Backported from mainline
2016-09-05 Jakub Jelinek <jakub@redhat.com>
PR sanitizer/77396
* asan/asan_globals.cc: Cherry-pick upstream r280657.
* g++.dg/asan/pr77396-2.C: New test.
2016-09-02 Jakub Jelinek <jakub@redhat.com>
PR sanitizer/77396
* g++.dg/asan/pr77396.C: New test.
--- libsanitizer/asan/asan_globals.cc (revision 239997)
+++ libsanitizer/asan/asan_globals.cc (revision 239998)
@@ -248,10 +248,10 @@ void __asan_unregister_globals(__asan_gl
// initializer can only touch global variables in the same TU.
void __asan_before_dynamic_init(const char *module_name) {
if (!flags()->check_initialization_order ||
- !CanPoisonMemory())
+ !CanPoisonMemory() ||
+ !dynamic_init_globals)
return;
bool strict_init_order = flags()->strict_init_order;
- CHECK(dynamic_init_globals);
CHECK(module_name);
CHECK(asan_inited);
BlockingMutexLock lock(&mu_for_globals);
@@ -274,7 +274,8 @@ void __asan_before_dynamic_init(const ch
// TU are poisoned. It simply unpoisons all dynamically initialized globals.
void __asan_after_dynamic_init() {
if (!flags()->check_initialization_order ||
- !CanPoisonMemory())
+ !CanPoisonMemory() ||
+ !dynamic_init_globals)
return;
CHECK(asan_inited);
BlockingMutexLock lock(&mu_for_globals);
--- gcc/testsuite/g++.dg/asan/pr77396.C (revision 0)
+++ gcc/testsuite/g++.dg/asan/pr77396.C (revision 239961)
@@ -0,0 +1,12 @@
+// PR sanitizer/77396
+// { dg-do run }
+// { dg-set-target-env-var ASAN_OPTIONS "check_initialization_order=true" }
+
+static int a = 0;
+static int b = a;
+
+int
+main ()
+{
+ return 0;
+}
--- gcc/testsuite/g++.dg/asan/pr77396-2.C (revision 0)
+++ gcc/testsuite/g++.dg/asan/pr77396-2.C (revision 239998)
@@ -0,0 +1,12 @@
+// PR sanitizer/77396
+// { dg-do run }
+// { dg-set-target-env-var ASAN_OPTIONS "check_initialization_order=true" }
+
+struct S { S () { asm volatile ("" : : : "memory"); } };
+static S c;
+
+int
+main ()
+{
+ return 0;
+}
-------------- next part --------------
2016-09-16 Jakub Jelinek <jakub@redhat.com>
Backported from mainline
2016-09-06 Jakub Jelinek <jakub@redhat.com>
PR target/69255
* config/i386/i386.c (ix86_expand_builtin): For builtin with
unsupported or unknown ISA, use expand_call.
* gcc.target/i386/pr69255-1.c: New test.
* gcc.target/i386/pr69255-2.c: New test.
* gcc.target/i386/pr69255-3.c: New test.
--- gcc/config/i386/i386.c (revision 240013)
+++ gcc/config/i386/i386.c (revision 240014)
@@ -36107,7 +36107,7 @@ ix86_expand_builtin (tree exp, rtx targe
error ("%qE needs isa option %s", fndecl, opts);
free (opts);
}
- return const0_rtx;
+ return expand_call (exp, target, ignore);
}
switch (fcode)
--- gcc/testsuite/gcc.target/i386/pr69255-1.c (revision 0)
+++ gcc/testsuite/gcc.target/i386/pr69255-1.c (revision 240014)
@@ -0,0 +1,17 @@
+/* PR target/69255 */
+/* { dg-do compile } */
+/* { dg-options "-msse4 -mno-avx" } */
+
+#pragma GCC target "avx512vl"
+#pragma GCC target "no-avx512vl"
+__attribute__ ((__vector_size__ (32))) long long a;
+__attribute__ ((__vector_size__ (16))) int b;
+
+void
+foo (const long long *p)
+{
+ a = __builtin_ia32_gather3siv4di (a, p, b, 1, 1); /* { dg-error "needs isa option -m32 -mavx512vl" } */
+}
+
+/* { dg-warning "AVX vector return without AVX enabled changes the ABI" "" { target *-*-* } 13 } */
+/* { dg-warning "AVX vector argument without AVX enabled changes the ABI" "" { target *-*-* } 13 } */
--- gcc/testsuite/gcc.target/i386/pr69255-2.c (revision 0)
+++ gcc/testsuite/gcc.target/i386/pr69255-2.c (revision 240014)
@@ -0,0 +1,17 @@
+/* PR target/69255 */
+/* { dg-do compile } */
+/* { dg-options "-msse4 -mno-avx" } */
+
+#pragma GCC target "avx512vl"
+#pragma GCC target ""
+__attribute__ ((__vector_size__ (32))) long long a;
+__attribute__ ((__vector_size__ (16))) int b;
+
+void
+foo (const long long *p)
+{
+ __builtin_ia32_gather3siv4di (a, p, b, 1, 1); /* { dg-error "needs isa option -m32 -mavx512vl" } */
+}
+
+/* { dg-warning "AVX vector return without AVX enabled changes the ABI" "" { target *-*-* } 13 } */
+/* { dg-warning "AVX vector argument without AVX enabled changes the ABI" "" { target *-*-* } 13 } */
--- gcc/testsuite/gcc.target/i386/pr69255-3.c (revision 0)
+++ gcc/testsuite/gcc.target/i386/pr69255-3.c (revision 240014)
@@ -0,0 +1,17 @@
+/* PR target/69255 */
+/* { dg-do compile } */
+/* { dg-options "-msse4 -mno-avx" } */
+
+#pragma GCC target "avx512vl"
+#pragma GCC target ""
+__attribute__ ((__vector_size__ (32))) long long a;
+__attribute__ ((__vector_size__ (16))) int b;
+
+void
+foo (const long long *p, __attribute__ ((__vector_size__ (32))) long long *q)
+{
+ *q = __builtin_ia32_gather3siv4di (a, p, b, 1, 1); /* { dg-error "needs isa option -m32 -mavx512vl" } */
+}
+
+/* { dg-warning "AVX vector return without AVX enabled changes the ABI" "" { target *-*-* } 13 } */
+/* { dg-warning "AVX vector argument without AVX enabled changes the ABI" "" { target *-*-* } 13 } */
-------------- next part --------------
2016-09-16 Jakub Jelinek <jakub@redhat.com>
Backported from mainline
2016-09-08 Jakub Jelinek <jakub@redhat.com>
PR fortran/77516
* omp-low.c (lower_rec_simd_input_clauses): Use max_vf for non-positive
OMP_CLAUSE_SAFELEN_EXPR.
* gfortran.dg/gomp/pr77516.f90: New test.
--- gcc/omp-low.c (revision 240036)
+++ gcc/omp-low.c (revision 240037)
@@ -4302,7 +4302,9 @@ lower_rec_simd_input_clauses (tree new_v
{
tree c = find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
OMP_CLAUSE_SAFELEN);
- if (c && TREE_CODE (OMP_CLAUSE_SAFELEN_EXPR (c)) != INTEGER_CST)
+ if (c
+ && (TREE_CODE (OMP_CLAUSE_SAFELEN_EXPR (c)) != INTEGER_CST
+ || tree_int_cst_sgn (OMP_CLAUSE_SAFELEN_EXPR (c)) != 1))
max_vf = 1;
else if (c && compare_tree_int (OMP_CLAUSE_SAFELEN_EXPR (c),
max_vf) == -1)
--- gcc/testsuite/gfortran.dg/gomp/pr77516.f90 (revision 0)
+++ gcc/testsuite/gfortran.dg/gomp/pr77516.f90 (revision 240037)
@@ -0,0 +1,12 @@
+! PR fortran/77516
+! { dg-do compile }
+
+program pr77516
+ integer :: i, x
+ x = 0
+!$omp simd safelen(0) reduction(+:x)
+ do i = 1, 8
+ x = x + 1
+ end do
+ print *, x
+end
-------------- next part --------------
2016-09-16 Jakub Jelinek <jakub@redhat.com>
Backported from mainline
2016-09-08 Jakub Jelinek <jakub@redhat.com>
PR fortran/77500
* trans-openmp.c (gfc_trans_omp_atomic): For atomic write or
swap, don't try to look through GFC_ISYM_CONVERSION. In other cases,
check that value.function.isym is non-NULL before dereferencing it.
* gfortran.dg/gomp/pr77500.f90: New test.
--- gcc/fortran/trans-openmp.c (revision 240037)
+++ gcc/fortran/trans-openmp.c (revision 240038)
@@ -2818,7 +2818,11 @@ gfc_trans_omp_atomic (gfc_code *code)
gfc_start_block (&block);
expr2 = code->expr2;
- if (expr2->expr_type == EXPR_FUNCTION
+ if (((atomic_code->ext.omp_atomic & GFC_OMP_ATOMIC_MASK)
+ != GFC_OMP_ATOMIC_WRITE)
+ && (atomic_code->ext.omp_atomic & GFC_OMP_ATOMIC_SWAP) == 0
+ && expr2->expr_type == EXPR_FUNCTION
+ && expr2->value.function.isym
&& expr2->value.function.isym->id == GFC_ISYM_CONVERSION)
expr2 = expr2->value.function.actual->expr;
@@ -2857,6 +2861,7 @@ gfc_trans_omp_atomic (gfc_code *code)
var = code->expr1->symtree->n.sym;
expr2 = code->expr2;
if (expr2->expr_type == EXPR_FUNCTION
+ && expr2->value.function.isym
&& expr2->value.function.isym->id == GFC_ISYM_CONVERSION)
expr2 = expr2->value.function.actual->expr;
}
@@ -2914,6 +2919,7 @@ gfc_trans_omp_atomic (gfc_code *code)
}
e = expr2->value.op.op1;
if (e->expr_type == EXPR_FUNCTION
+ && e->value.function.isym
&& e->value.function.isym->id == GFC_ISYM_CONVERSION)
e = e->value.function.actual->expr;
if (e->expr_type == EXPR_VARIABLE
@@ -2927,6 +2933,7 @@ gfc_trans_omp_atomic (gfc_code *code)
{
e = expr2->value.op.op2;
if (e->expr_type == EXPR_FUNCTION
+ && e->value.function.isym
&& e->value.function.isym->id == GFC_ISYM_CONVERSION)
e = e->value.function.actual->expr;
gcc_assert (e->expr_type == EXPR_VARIABLE
@@ -3041,6 +3048,7 @@ gfc_trans_omp_atomic (gfc_code *code)
code = code->next;
expr2 = code->expr2;
if (expr2->expr_type == EXPR_FUNCTION
+ && expr2->value.function.isym
&& expr2->value.function.isym->id == GFC_ISYM_CONVERSION)
expr2 = expr2->value.function.actual->expr;
--- gcc/testsuite/gfortran.dg/gomp/pr77500.f90 (revision 0)
+++ gcc/testsuite/gfortran.dg/gomp/pr77500.f90 (revision 240038)
@@ -0,0 +1,9 @@
+! PR fortran/77500
+! { dg-do compile }
+
+program pr77500
+ real :: x
+!$omp atomic write
+ x = f()
+!$omp end atomic
+end
-------------- next part --------------
2016-09-16 Jakub Jelinek <jakub@redhat.com>
Backported from mainline
2016-09-13 Jakub Jelinek <jakub@redhat.com>
PR c++/77553
* constexpr.c (cxx_fold_pointer_plus_expression): New function.
(cxx_eval_binary_expression): Use it for POINTER_PLUS_EXPR.
(cxx_eval_pointer_plus_expression): Remove.
(cxx_eval_constant_expression) <case POINTER_PLUS_EXPR>: Don't
call cxx_eval_pointer_plus_expression.
* g++.dg/cpp1y/constexpr-77553.C: New test.
--- gcc/cp/constexpr.c (revision 240118)
+++ gcc/cp/constexpr.c (revision 240119)
@@ -1745,6 +1745,63 @@ cxx_eval_unary_expression (const constex
return r;
}
+/* Helper function for cxx_eval_binary_expression. Try to optimize
+ original POINTER_PLUS_EXPR T, LHS p+ RHS, return NULL_TREE if the
+ generic folding should be used. */
+
+static tree
+cxx_fold_pointer_plus_expression (const constexpr_ctx *ctx, tree t,
+ tree lhs, tree rhs, bool *non_constant_p,
+ bool *overflow_p)
+{
+ STRIP_NOPS (lhs);
+ if (TREE_CODE (lhs) != ADDR_EXPR)
+ return NULL_TREE;
+
+ lhs = TREE_OPERAND (lhs, 0);
+
+ /* &A[i] p+ j => &A[i + j] */
+ if (TREE_CODE (lhs) == ARRAY_REF
+ && TREE_CODE (TREE_OPERAND (lhs, 1)) == INTEGER_CST
+ && TREE_CODE (rhs) == INTEGER_CST
+ && TYPE_SIZE_UNIT (TREE_TYPE (lhs))
+ && TREE_CODE (TYPE_SIZE_UNIT (TREE_TYPE (lhs))) == INTEGER_CST)
+ {
+ tree orig_type = TREE_TYPE (t);
+ location_t loc = EXPR_LOCATION (t);
+ tree type = TREE_TYPE (lhs);
+
+ t = fold_convert_loc (loc, ssizetype, TREE_OPERAND (lhs, 1));
+ tree nelts = array_type_nelts_top (TREE_TYPE (TREE_OPERAND (lhs, 0)));
+ nelts = cxx_eval_constant_expression (ctx, nelts, false, non_constant_p,
+ overflow_p);
+ if (*non_constant_p)
+ return NULL_TREE;
+ /* Don't fold an out-of-bound access. */
+ if (!tree_int_cst_le (t, nelts))
+ return NULL_TREE;
+ rhs = cp_fold_convert (ssizetype, rhs);
+ /* Don't fold if rhs can't be divided exactly by TYPE_SIZE_UNIT.
+ constexpr int A[1]; ... (char *)&A[0] + 1 */
+ if (!integer_zerop (fold_build2_loc (loc, TRUNC_MOD_EXPR, sizetype,
+ rhs, TYPE_SIZE_UNIT (type))))
+ return NULL_TREE;
+ /* Make sure to treat the second operand of POINTER_PLUS_EXPR
+ as signed. */
+ rhs = fold_build2_loc (loc, EXACT_DIV_EXPR, ssizetype, rhs,
+ TYPE_SIZE_UNIT (type));
+ t = size_binop_loc (loc, PLUS_EXPR, rhs, t);
+ t = build4_loc (loc, ARRAY_REF, type, TREE_OPERAND (lhs, 0),
+ t, NULL_TREE, NULL_TREE);
+ t = cp_build_addr_expr (t, tf_warning_or_error);
+ t = cp_fold_convert (orig_type, t);
+ return cxx_eval_constant_expression (ctx, t, /*lval*/false,
+ non_constant_p, overflow_p);
+ }
+
+ return NULL_TREE;
+}
+
/* Subroutine of cxx_eval_constant_expression.
Like cxx_eval_unary_expression, except for binary expressions. */
@@ -1790,6 +1847,9 @@ cxx_eval_binary_expression (const conste
else if (TREE_CODE (rhs) == PTRMEM_CST)
rhs = cplus_expand_constant (rhs);
}
+ else if (code == POINTER_PLUS_EXPR)
+ r = cxx_fold_pointer_plus_expression (ctx, t, lhs, rhs, non_constant_p,
+ overflow_p);
if (r == NULL_TREE)
r = fold_binary_loc (loc, code, type, lhs, rhs);
@@ -3448,65 +3508,6 @@ cxx_eval_switch_expr (const constexpr_ct
return NULL_TREE;
}
-/* Subroutine of cxx_eval_constant_expression.
- Attempt to reduce a POINTER_PLUS_EXPR expression T. */
-
-static tree
-cxx_eval_pointer_plus_expression (const constexpr_ctx *ctx, tree t,
- bool lval, bool *non_constant_p,
- bool *overflow_p)
-{
- tree orig_type = TREE_TYPE (t);
- tree op00 = TREE_OPERAND (t, 0);
- tree op01 = TREE_OPERAND (t, 1);
- location_t loc = EXPR_LOCATION (t);
-
- op00 = cxx_eval_constant_expression (ctx, op00, lval,
- non_constant_p, overflow_p);
-
- STRIP_NOPS (op00);
- if (TREE_CODE (op00) != ADDR_EXPR)
- return NULL_TREE;
-
- op01 = cxx_eval_constant_expression (ctx, op01, lval,
- non_constant_p, overflow_p);
- op00 = TREE_OPERAND (op00, 0);
-
- /* &A[i] p+ j => &A[i + j] */
- if (TREE_CODE (op00) == ARRAY_REF
- && TREE_CODE (TREE_OPERAND (op00, 1)) == INTEGER_CST
- && TREE_CODE (op01) == INTEGER_CST
- && TYPE_SIZE_UNIT (TREE_TYPE (op00))
- && TREE_CODE (TYPE_SIZE_UNIT (TREE_TYPE (op00))) == INTEGER_CST)
- {
- tree type = TREE_TYPE (op00);
- t = fold_convert_loc (loc, ssizetype, TREE_OPERAND (op00, 1));
- tree nelts = array_type_nelts_top (TREE_TYPE (TREE_OPERAND (op00, 0)));
- /* Don't fold an out-of-bound access. */
- if (!tree_int_cst_le (t, nelts))
- return NULL_TREE;
- op01 = cp_fold_convert (ssizetype, op01);
- /* Don't fold if op01 can't be divided exactly by TYPE_SIZE_UNIT.
- constexpr int A[1]; ... (char *)&A[0] + 1 */
- if (!integer_zerop (fold_build2_loc (loc, TRUNC_MOD_EXPR, sizetype,
- op01, TYPE_SIZE_UNIT (type))))
- return NULL_TREE;
- /* Make sure to treat the second operand of POINTER_PLUS_EXPR
- as signed. */
- op01 = fold_build2_loc (loc, EXACT_DIV_EXPR, ssizetype, op01,
- TYPE_SIZE_UNIT (type));
- t = size_binop_loc (loc, PLUS_EXPR, op01, t);
- t = build4_loc (loc, ARRAY_REF, type, TREE_OPERAND (op00, 0),
- t, NULL_TREE, NULL_TREE);
- t = cp_build_addr_expr (t, tf_warning_or_error);
- t = cp_fold_convert (orig_type, t);
- return cxx_eval_constant_expression (ctx, t, lval, non_constant_p,
- overflow_p);
- }
-
- return NULL_TREE;
-}
-
/* Attempt to reduce the expression T to a constant value.
On failure, issue diagnostic and return error_mark_node. */
/* FIXME unify with c_fully_fold */
@@ -3824,12 +3825,6 @@ cxx_eval_constant_expression (const cons
break;
case POINTER_PLUS_EXPR:
- r = cxx_eval_pointer_plus_expression (ctx, t, lval, non_constant_p,
- overflow_p);
- if (r)
- break;
- /* else fall through */
-
case PLUS_EXPR:
case MINUS_EXPR:
case MULT_EXPR:
--- gcc/testsuite/g++.dg/cpp1y/constexpr-77553.C (revision 0)
+++ gcc/testsuite/g++.dg/cpp1y/constexpr-77553.C (revision 240119)
@@ -0,0 +1,29 @@
+// PR c++/77553
+// { dg-do compile { target c++14 } }
+
+constexpr void
+bar (int *x)
+{
+ int i = 0;
+ x[i++] = 1;
+ x[3] = i;
+}
+
+constexpr int
+foo ()
+{
+ int a[] = { 0, 0, 0, 0 };
+ bar (a);
+
+ return a[0] + 8 * a[1] + 64 * a[2] + 512 * a[3];
+}
+
+constexpr int b = foo ();
+
+int
+main ()
+{
+ static_assert (b == 513, "");
+ if (foo () != 513)
+ __builtin_abort ();
+}
-------------- next part --------------
2016-09-16 Jakub Jelinek <jakub@redhat.com>
Backported from mainline
2016-09-14 Jakub Jelinek <jakub@redhat.com>
PR sanitizer/68260
* tsan.c: Include target.h.
(enum tsan_atomic_action): Add bool_clear and bool_test_and_set.
(BOOL_CLEAR, BOOL_TEST_AND_SET): Define.
(tsan_atomic_table): Add BUILT_IN_ATOMIC_CLEAR and
BUILT_IN_ATOMIC_TEST_AND_SET entries.
(instrument_builtin_call): Handle bool_clear and bool_test_and_set.
* c-c++-common/tsan/pr68260.c: New test.
--- gcc/tsan.c (revision 240128)
+++ gcc/tsan.c (revision 240129)
@@ -40,6 +40,7 @@ along with GCC; see the file COPYING3.
#include "tsan.h"
#include "asan.h"
#include "builtins.h"
+#include "target.h"
/* Number of instrumented memory accesses in the current function. */
@@ -240,7 +241,8 @@ instrument_expr (gimple_stmt_iterator gs
enum tsan_atomic_action
{
check_last, add_seq_cst, add_acquire, weak_cas, strong_cas,
- bool_cas, val_cas, lock_release, fetch_op, fetch_op_seq_cst
+ bool_cas, val_cas, lock_release, fetch_op, fetch_op_seq_cst,
+ bool_clear, bool_test_and_set
};
/* Table how to map sync/atomic builtins to their corresponding
@@ -274,6 +276,10 @@ static const struct tsan_map_atomic
TRANSFORM (fcode, tsan_fcode, fetch_op, code)
#define FETCH_OPS(fcode, tsan_fcode, code) \
TRANSFORM (fcode, tsan_fcode, fetch_op_seq_cst, code)
+#define BOOL_CLEAR(fcode, tsan_fcode) \
+ TRANSFORM (fcode, tsan_fcode, bool_clear, ERROR_MARK)
+#define BOOL_TEST_AND_SET(fcode, tsan_fcode) \
+ TRANSFORM (fcode, tsan_fcode, bool_test_and_set, ERROR_MARK)
CHECK_LAST (ATOMIC_LOAD_1, TSAN_ATOMIC8_LOAD),
CHECK_LAST (ATOMIC_LOAD_2, TSAN_ATOMIC16_LOAD),
@@ -463,7 +469,11 @@ static const struct tsan_map_atomic
LOCK_RELEASE (SYNC_LOCK_RELEASE_2, TSAN_ATOMIC16_STORE),
LOCK_RELEASE (SYNC_LOCK_RELEASE_4, TSAN_ATOMIC32_STORE),
LOCK_RELEASE (SYNC_LOCK_RELEASE_8, TSAN_ATOMIC64_STORE),
- LOCK_RELEASE (SYNC_LOCK_RELEASE_16, TSAN_ATOMIC128_STORE)
+ LOCK_RELEASE (SYNC_LOCK_RELEASE_16, TSAN_ATOMIC128_STORE),
+
+ BOOL_CLEAR (ATOMIC_CLEAR, TSAN_ATOMIC8_STORE),
+
+ BOOL_TEST_AND_SET (ATOMIC_TEST_AND_SET, TSAN_ATOMIC8_EXCHANGE)
};
/* Instrument an atomic builtin. */
@@ -615,6 +625,57 @@ instrument_builtin_call (gimple_stmt_ite
build_int_cst (NULL_TREE,
MEMMODEL_RELEASE));
return;
+ case bool_clear:
+ case bool_test_and_set:
+ if (BOOL_TYPE_SIZE != 8)
+ {
+ decl = NULL_TREE;
+ for (j = 1; j < 5; j++)
+ if (BOOL_TYPE_SIZE == (8 << j))
+ {
+ enum built_in_function tsan_fcode
+ = (enum built_in_function)
+ (tsan_atomic_table[i].tsan_fcode + j);
+ decl = builtin_decl_implicit (tsan_fcode);
+ break;
+ }
+ if (decl == NULL_TREE)
+ return;
+ }
+ last_arg = gimple_call_arg (stmt, num - 1);
+ if (!tree_fits_uhwi_p (last_arg)
+ || memmodel_base (tree_to_uhwi (last_arg)) >= MEMMODEL_LAST)
+ return;
+ t = TYPE_ARG_TYPES (TREE_TYPE (decl));
+ t = TREE_VALUE (TREE_CHAIN (t));
+ if (tsan_atomic_table[i].action == bool_clear)
+ {
+ update_gimple_call (gsi, decl, 3, gimple_call_arg (stmt, 0),
+ build_int_cst (t, 0), last_arg);
+ return;
+ }
+ t = build_int_cst (t, targetm.atomic_test_and_set_trueval);
+ update_gimple_call (gsi, decl, 3, gimple_call_arg (stmt, 0),
+ t, last_arg);
+ stmt = gsi_stmt (*gsi);
+ lhs = gimple_call_lhs (stmt);
+ if (lhs == NULL_TREE)
+ return;
+ if (targetm.atomic_test_and_set_trueval != 1
+ || !useless_type_conversion_p (TREE_TYPE (lhs),
+ TREE_TYPE (t)))
+ {
+ tree new_lhs = make_ssa_name (TREE_TYPE (t));
+ gimple_call_set_lhs (stmt, new_lhs);
+ if (targetm.atomic_test_and_set_trueval != 1)
+ g = gimple_build_assign (lhs, NE_EXPR, new_lhs,
+ build_int_cst (TREE_TYPE (t), 0));
+ else
+ g = gimple_build_assign (lhs, NOP_EXPR, new_lhs);
+ gsi_insert_after (gsi, g, GSI_NEW_STMT);
+ update_stmt (stmt);
+ }
+ return;
default:
continue;
}
--- gcc/testsuite/c-c++-common/tsan/pr68260.c (revision 0)
+++ gcc/testsuite/c-c++-common/tsan/pr68260.c (revision 240129)
@@ -0,0 +1,28 @@
+/* PR sanitizer/68260 */
+
+#include <pthread.h>
+#include <stdbool.h>
+
+bool lock;
+int counter;
+
+void *
+tf (void *arg)
+{
+ (void) arg;
+ while (__atomic_test_and_set (&lock, __ATOMIC_ACQUIRE))
+ ;
+ ++counter;
+ __atomic_clear (&lock, __ATOMIC_RELEASE);
+ return (void *) 0;
+}
+
+int
+main ()
+{
+ pthread_t thr;
+ pthread_create (&thr, 0, tf, 0);
+ tf ((void *) 0);
+ pthread_join (thr, 0);
+ return 0;
+}
-------------- next part --------------
2016-09-16 Jakub Jelinek <jakub@redhat.com>
Eric Botcazou <ebotcazou@adacore.com>
PR middle-end/77594
* internal-fn.c (expand_arith_overflow) <case MINUS_EXPR>: Don't fall
through into expand_addsub_overflow after expand_neg_overflow.
* gcc.target/i386/pr77594.c: New test.
--- gcc/internal-fn.c (revision 240172)
+++ gcc/internal-fn.c (revision 240173)
@@ -1833,7 +1833,10 @@ expand_arith_overflow (enum tree_code co
{
case MINUS_EXPR:
if (integer_zerop (arg0) && !unsr_p)
- expand_neg_overflow (loc, lhs, arg1, false);
+ {
+ expand_neg_overflow (loc, lhs, arg1, false);
+ return;
+ }
/* FALLTHRU */
case PLUS_EXPR:
expand_addsub_overflow (loc, code, lhs, arg0, arg1,
--- gcc/testsuite/gcc.target/i386/pr77594.c (revision 0)
+++ gcc/testsuite/gcc.target/i386/pr77594.c (revision 240173)
@@ -0,0 +1,11 @@
+/* PR middle-end/77594 */
+/* { dg-do compile } */
+/* { dg-options "-O0" } */
+
+int
+foo (int a, int *b)
+{
+ return __builtin_sub_overflow (0, a, b);
+}
+
+/* { dg-final { scan-assembler-times "\tjn?o\t" 1 } } */
More information about the Gcc-patches
mailing list