@@ -1719,7 +1719,8 @@ replace_uses_by (tree name, tree val)
if (gimple_code (stmt) == GIMPLE_PHI)
{
e = gimple_phi_arg_edge (stmt, PHI_ARG_INDEX_FROM_USE (use));
- if (e->flags & EDGE_ABNORMAL)
+ if (e->flags & EDGE_ABNORMAL
+ && !SSA_NAME_OCCURS_IN_ABNORMAL_PHI (val))
{
/* This can only occur for virtual operands, since
for the real ones SSA_NAME_OCCURS_IN_ABNORMAL_PHI (name))
@@ -0,0 +1,42 @@
+// { dg-do compile }
+
+class A
+{
+public:
+ A ();
+};
+class B
+{
+public:
+ B (int);
+ operator void *() { return m_fn1 () ? 0 : this; }
+ int m_fn1 ();
+};
+typedef int jmp_buf[];
+struct C
+{
+ jmp_buf cond_;
+};
+class F
+{
+ C what_;
+ bool m_fn2 ();
+};
+int _setjmp (int[]);
+void longjmp ();
+class D
+{
+public:
+ D () { longjmp (); }
+};
+bool
+F::m_fn2 ()
+{
+ B a (0);
+ if (a)
+ if (_setjmp (what_.cond_))
+ return 0;
+ else
+ D ();
+ A b;
+}
Hi! I've bootstrapped/regtested on x86_64-linux and i686-linux and committed following backports from gcc-5-branch and trunk to gcc-4_9-branch: Jakub 2016-07-07 Jakub Jelinek <jakub@redhat.com> Backported from mainline 2014-12-12 Richard Biener <rguenther@suse.de> PR middle-end/64280 * tree-cfg.c (replace_uses_by): Guard assert properly. * g++.dg/torture/pr64280.C: New testcase. 2016-07-07 Jakub Jelinek <jakub@redhat.com> Backported from mainline 2016-03-02 Jakub Jelinek <jakub@redhat.com> PR middle-end/70022 * gcc.dg/pr70022.c: Add -w -Wno-psabi to dg-options. --- gcc/testsuite/gcc.dg/pr70022.c (revision 233904) +++ gcc/testsuite/gcc.dg/pr70022.c (revision 233905) @@ -1,4 +1,5 @@ /* { dg-do compile } */ +/* { dg-options "-w -Wno-psabi" } */ typedef int v4si __attribute__ ((vector_size (16))); 2016-07-07 Jakub Jelinek <jakub@redhat.com> Backported from mainline 2016-02-15 Jakub Jelinek <jakub@redhat.com> PR c++/69797 * c-common.c (sync_resolve_size): Diagnose too few arguments even when params is non-NULL empty vector. * c-c++-common/pr69797.c: New test. --- gcc/c-family/c-common.c (revision 234548) +++ gcc/c-family/c-common.c (revision 234549) @@ -10511,7 +10511,7 @@ sync_resolve_size (tree function, vec<tr tree type; int size; - if (!params) + if (vec_safe_is_empty (params)) { error ("too few arguments to function %qE", function); return 0; --- gcc/testsuite/c-c++-common/pr69797.c (revision 0) +++ gcc/testsuite/c-c++-common/pr69797.c (revision 234549) @@ -0,0 +1,8 @@ +/* PR c++/69797 */ +/* { dg-do compile } */ + +void +foo () +{ + __atomic_fetch_add (); /* { dg-error "too few arguments to function" } */ +} 2016-07-07 Jakub Jelinek <jakub@redhat.com> Backported from mainline 2016-02-16 Jakub Jelinek <jakub@redhat.com> PR tree-optimization/69802 * tree-ssa-reassoc.c (update_range_test): If op is SSA_NAME_IS_DEFAULT_DEF, give up unless tem is a positive op == 1 test of precision 1 integral op, otherwise handle that case as op itself. Fix up formatting. (optimize_range_tests_to_bit_test, optimize_range_tests): Fix up formatting. * gcc.dg/pr69802.c: New test. --- gcc/tree-ssa-reassoc.c (revision 234549) +++ gcc/tree-ssa-reassoc.c (revision 234550) @@ -2091,10 +2091,33 @@ update_range_test (struct range_entry *r tree tem = build_range_check (loc, optype, exp, in_p, low, high); enum warn_strict_overflow_code wc = WARN_STRICT_OVERFLOW_COMPARISON; gimple_stmt_iterator gsi; + unsigned int uid; if (tem == NULL_TREE) return false; + /* If op is default def SSA_NAME, there is no place to insert the + new comparison. Give up, unless we can use OP itself as the + range test. */ + if (op && SSA_NAME_IS_DEFAULT_DEF (op)) + { + if (op == range->exp + && ((TYPE_PRECISION (optype) == 1 && TYPE_UNSIGNED (optype)) + || TREE_CODE (optype) == BOOLEAN_TYPE) + && (op == tem + || (TREE_CODE (tem) == EQ_EXPR + && TREE_OPERAND (tem, 0) == op + && integer_onep (TREE_OPERAND (tem, 1)))) + && opcode != BIT_IOR_EXPR + && (opcode != ERROR_MARK || oe->rank != BIT_IOR_EXPR)) + { + stmt = NULL; + tem = op; + } + else + return false; + } + if (strict_overflow_p && issue_strict_overflow_warning (wc)) warning_at (loc, OPT_Wstrict_overflow, "assuming signed overflow does not occur " @@ -2128,11 +2151,22 @@ update_range_test (struct range_entry *r tem = invert_truthvalue_loc (loc, tem); tem = fold_convert_loc (loc, optype, tem); - gsi = gsi_for_stmt (stmt); + if (stmt) + { + gsi = gsi_for_stmt (stmt); + uid = gimple_uid (stmt); + } + else + { + gsi = gsi_none (); + uid = 0; + } + if (stmt == NULL) + gcc_checking_assert (tem == op); /* In rare cases range->exp can be equal to lhs of stmt. In that case we have to insert after the stmt rather then before it. */ - if (op == range->exp) + else if (op == range->exp) tem = force_gimple_operand_gsi (&gsi, tem, true, NULL_TREE, false, GSI_CONTINUE_LINKING); else @@ -2145,7 +2179,7 @@ update_range_test (struct range_entry *r if (gimple_uid (gsi_stmt (gsi))) break; else - gimple_set_uid (gsi_stmt (gsi), gimple_uid (stmt)); + gimple_set_uid (gsi_stmt (gsi), uid); oe->op = tem; range->exp = exp; --- gcc/testsuite/gcc.dg/pr69802.c (revision 0) +++ gcc/testsuite/gcc.dg/pr69802.c (revision 234550) @@ -0,0 +1,23 @@ +/* PR tree-optimization/69802 */ +/* { dg-do compile } */ +/* { dg-options "-O2 -Wall" } */ + +struct S { unsigned f : 1; }; +int a, d; + +int +foo (void) +{ + unsigned b = 0; + struct S c; + d = ((1 && b) < c.f) & c.f; /* { dg-warning "is used uninitialized" } */ + return a; +} + +int +bar (_Bool c) +{ + unsigned b = 0; + d = ((1 && b) < c) & c; + return a; +} 2016-07-07 Jakub Jelinek <jakub@redhat.com> Backported from mainline 2016-02-19 Jakub Jelinek <jakub@redhat.com> PR c++/67767 * parser.c (cp_parser_std_attribute_spec_seq): Don't assume attr_spec is always single element chain, chain all the attributes properly together in the right order. * g++.dg/cpp0x/pr67767.C: New test. --- gcc/cp/parser.c (revision 234550) +++ gcc/cp/parser.c (revision 234551) @@ -22645,7 +22645,8 @@ cp_parser_std_attribute_spec (cp_parser static tree cp_parser_std_attribute_spec_seq (cp_parser *parser) { - tree attr_specs = NULL; + tree attr_specs = NULL_TREE; + tree attr_last = NULL_TREE; while (true) { @@ -22655,11 +22656,13 @@ cp_parser_std_attribute_spec_seq (cp_par if (attr_spec == error_mark_node) return error_mark_node; - TREE_CHAIN (attr_spec) = attr_specs; - attr_specs = attr_spec; + if (attr_last) + TREE_CHAIN (attr_last) = attr_spec; + else + attr_specs = attr_last = attr_spec; + attr_last = tree_last (attr_last); } - attr_specs = nreverse (attr_specs); return attr_specs; } --- gcc/testsuite/g++.dg/cpp0x/pr67767.C (revision 0) +++ gcc/testsuite/g++.dg/cpp0x/pr67767.C (revision 234551) @@ -0,0 +1,10 @@ +// PR c++/67767 +// { dg-do compile { target c++11 } } +// { dg-options "-Wsuggest-attribute=noreturn" } + +void foo [[gnu::cold, gnu::noreturn]] (); + +void foo () // { dg-bogus "function might be candidate for attribute" } +{ + throw 1; +} 2016-07-07 Jakub Jelinek <jakub@redhat.com> Backported from mainline 2016-02-26 Jakub Jelinek <jakub@redhat.com> Eric Botcazou <ebotcazou@adacore.com> PR rtl-optimization/69891 * dse.c (scan_insn): If we can't figure out memset arguments or they are non-constant, call clear_rhs_from_active_local_stores. * gcc.target/i386/pr69891.c: New test. --- gcc/dse.c (revision 234554) +++ gcc/dse.c (revision 234555) @@ -2582,6 +2582,8 @@ scan_insn (bb_info_t bb_info, rtx insn) active_local_stores = insn_info; } } + else + clear_rhs_from_active_local_stores (); } } --- gcc/testsuite/gcc.target/i386/pr69891.c (revision 0) +++ gcc/testsuite/gcc.target/i386/pr69891.c (revision 234555) @@ -0,0 +1,30 @@ +/* PR rtl-optimization/69891 */ +/* { dg-do run } */ +/* { dg-options "-O -fno-tree-fre -mstringop-strategy=libcall -Wno-psabi" } */ +/* { dg-additional-options "-mno-sse" { target ia32 } } */ + +typedef unsigned short A; +typedef unsigned short B __attribute__ ((vector_size (32))); +typedef unsigned int C; +typedef unsigned int D __attribute__ ((vector_size (32))); +typedef unsigned long long E; +typedef unsigned long long F __attribute__ ((vector_size (32))); + +__attribute__((noinline, noclone)) unsigned +foo(D a, B b, D c, F d) +{ + b /= (B) {1, -c[0]} | 1; + c[0] |= 7; + a %= c | 1; + c ^= c; + return a[0] + b[15] + c[0] + d[3]; +} + +int +main () +{ + unsigned x = foo ((D) {}, (B) {}, (D) {}, (F) {}); + if (x != 0) + __builtin_abort (); + return 0; +} 2016-07-07 Jakub Jelinek <jakub@redhat.com> Backported from mainline 2016-03-09 Jakub Jelinek <jakub@redhat.com> PR tree-optimization/70152 * tree-sra.c (replace_removed_params_ssa_names): Copy over SSA_NAME_OCCURS_IN_ABNORMAL_PHI from old_name to new_name. * gcc.dg/pr70152.c: New test. --- gcc/tree-sra.c (revision 234560) +++ gcc/tree-sra.c (revision 234561) @@ -4609,6 +4609,8 @@ replace_removed_params_ssa_names (tree o repl = get_replaced_param_substitute (adj); new_name = make_ssa_name (repl, stmt); + SSA_NAME_OCCURS_IN_ABNORMAL_PHI (new_name) + = SSA_NAME_OCCURS_IN_ABNORMAL_PHI (old_name); if (dump_file) { --- gcc/testsuite/gcc.dg/pr70152.c (revision 0) +++ gcc/testsuite/gcc.dg/pr70152.c (revision 234561) @@ -0,0 +1,27 @@ +/* PR tree-optimization/70152 */ +/* { dg-do compile } */ +/* { dg-options "-O2" } */ + +int a; +int foo (void); +int setjmp (char *); +char buf[64]; + +static int +bar (int x) +{ + x = 0; + setjmp (buf); + for (;;) + { + switch (x) + case 5: + x = foo (); + } +} + +void +baz (void) +{ + bar (a); +} 2016-07-07 Jakub Jelinek <jakub@redhat.com> Backported from mainline 2016-03-11 Jakub Jelinek <jakub@redhat.com> PR tree-optimization/70169 * tree-ssa-loop.c (gen_lsm_tmp_name): Handle FUNCTION_DECL and LABEL_DECL like VAR_DECL. Emit nothing instead of gcc_unreachable for unknown codes. * gcc.dg/pr70169.c: New test. --- gcc/tree-ssa-loop.c (revision 234561) +++ gcc/tree-ssa-loop.c (revision 234562) @@ -698,6 +698,8 @@ gen_lsm_tmp_name (tree ref) case SSA_NAME: case VAR_DECL: case PARM_DECL: + case FUNCTION_DECL: + case LABEL_DECL: name = get_name (ref); if (!name) name = "D"; @@ -713,11 +715,9 @@ gen_lsm_tmp_name (tree ref) break; case INTEGER_CST: + default: /* Nothing. */ break; - - default: - gcc_unreachable (); } } --- gcc/testsuite/gcc.dg/pr70169.c (revision 0) +++ gcc/testsuite/gcc.dg/pr70169.c (revision 234562) @@ -0,0 +1,40 @@ +/* PR tree-optimization/70169 */ +/* { dg-do compile } */ +/* { dg-options "-O2 -fno-strict-aliasing -fno-tree-dce" } */ + +int printf (const char *, ...); + +void +foo () +{ + unsigned char *p = (unsigned char *) &printf; + for (;;) + (*p)++; +} + +void +bar (int x) +{ + unsigned char *p = (unsigned char *) &printf; + int i; + for (i = 0; i < x; i++) + (*p)++; +} + +void +baz (int x, int y) +{ + unsigned char *p = (unsigned char *) &&lab; + int i; + if (y) + { + for (i = 0; i < x; i++) + (*p)++; + } + else + { + lab: + asm volatile (""); + foo (); + } +} 2016-07-07 Jakub Jelinek <jakub@redhat.com> Backported from mainline 2016-03-15 Jakub Jelinek <jakub@redhat.com> PR rtl-optimization/70222 * combine.c (simplify_shift_const_1): For A >> B >> C LSHIFTRT optimization if mode is different from result_mode, queue up masking of the result in outer_op. Formatting fix. * gcc.c-torture/execute/pr70222-1.c: New test. * gcc.c-torture/execute/pr70222-2.c: New test. --- gcc/combine.c (revision 234562) +++ gcc/combine.c (revision 234563) @@ -10476,9 +10476,19 @@ simplify_shift_const_1 (enum rtx_code co && CONST_INT_P (XEXP (varop, 0)) && !CONST_INT_P (XEXP (varop, 1))) { + /* For ((unsigned) (cstULL >> count)) >> cst2 we have to make + sure the result will be masked. See PR70222. */ + if (code == LSHIFTRT + && mode != result_mode + && !merge_outer_ops (&outer_op, &outer_const, AND, + GET_MODE_MASK (result_mode) + >> orig_count, result_mode, + &complement_p)) + break; + rtx new_rtx = simplify_const_binary_operation (code, mode, - XEXP (varop, 0), - GEN_INT (count)); + XEXP (varop, 0), + GEN_INT (count)); varop = gen_rtx_fmt_ee (code, mode, new_rtx, XEXP (varop, 1)); count = 0; continue; --- gcc/testsuite/gcc.c-torture/execute/pr70222-1.c (revision 0) +++ gcc/testsuite/gcc.c-torture/execute/pr70222-1.c (revision 234563) @@ -0,0 +1,30 @@ +/* PR rtl-optimization/70222 */ + +int a = 1; +unsigned int b = 2; +int c = 0; +int d = 0; + +void +foo () +{ + int e = ((-(c >= c)) < b) > ((int) (-1ULL >> ((a / a) * 15))); + d = -e; +} + +__attribute__((noinline, noclone)) void +bar (int x) +{ + if (x != -1) + __builtin_abort (); +} + +int +main () +{ +#if __CHAR_BIT__ == 8 && __SIZEOF_INT__ == 4 && __SIZEOF_LONG_LONG__ == 8 + foo (); + bar (d); +#endif + return 0; +} --- gcc/testsuite/gcc.c-torture/execute/pr70222-2.c (revision 0) +++ gcc/testsuite/gcc.c-torture/execute/pr70222-2.c (revision 234563) @@ -0,0 +1,20 @@ +/* PR rtl-optimization/70222 */ + +#if __CHAR_BIT__ == 8 && __SIZEOF_INT__ == 4 && __SIZEOF_LONG_LONG__ == 8 +__attribute__((noinline, noclone)) unsigned int +foo (int x) +{ + unsigned long long y = -1ULL >> x; + return (unsigned int) y >> 31; +} +#endif + +int +main () +{ +#if __CHAR_BIT__ == 8 && __SIZEOF_INT__ == 4 && __SIZEOF_LONG_LONG__ == 8 + if (foo (15) != 1 || foo (32) != 1 || foo (33) != 0) + __builtin_abort (); +#endif + return 0; +} 2016-07-07 Jakub Jelinek <jakub@redhat.com> Backported from mainline 2016-03-29 Jakub Jelinek <jakub@redhat.com> PR rtl-optimization/70429 * combine.c (simplify_shift_const_1): For ASHIFTRT don't optimize (cst1 >> count) >> cst2 into (cst1 >> cst2) >> count if mode != result_mode. * gcc.c-torture/execute/pr70429.c: New test. --- gcc/combine.c (revision 234566) +++ gcc/combine.c (revision 234567) @@ -10485,6 +10485,11 @@ simplify_shift_const_1 (enum rtx_code co >> orig_count, result_mode, &complement_p)) break; + /* For ((int) (cstLL >> count)) >> cst2 just give up. Queuing + up outer sign extension (often left and right shift) is + hardly more efficient than the original. See PR70429. */ + if (code == ASHIFTRT && mode != result_mode) + break; rtx new_rtx = simplify_const_binary_operation (code, mode, XEXP (varop, 0), --- gcc/testsuite/gcc.c-torture/execute/pr70429.c (revision 0) +++ gcc/testsuite/gcc.c-torture/execute/pr70429.c (revision 234567) @@ -0,0 +1,17 @@ +/* PR rtl-optimization/70429 */ + +__attribute__((noinline, noclone)) int +foo (int a) +{ + return (int) (0x14ff6e2207db5d1fLL >> a) >> 4; +} + +int +main () +{ + if (sizeof (int) != 4 || sizeof (long long) != 8 || __CHAR_BIT__ != 8) + return 0; + if (foo (1) != 0x3edae8 || foo (2) != -132158092) + __builtin_abort (); + return 0; +} 2016-07-07 Jakub Jelinek <jakub@redhat.com> Backported from mainline 2016-05-17 Jakub Jelinek <jakub@redhat.com> PR sanitizer/71160 * asan/asan_malloc_linux.cc: Cherry pick upstream r254395 and r269633. --- libsanitizer/asan/asan_malloc_linux.cc (revision 236432) +++ libsanitizer/asan/asan_malloc_linux.cc (revision 236433) @@ -58,39 +58,62 @@ void ReplaceSystemMalloc() { // ---------------------- Replacement functions ---------------- {{{1 using namespace __asan; // NOLINT +static uptr allocated_for_dlsym; +static const uptr kDlsymAllocPoolSize = 1024; +static uptr alloc_memory_for_dlsym[kDlsymAllocPoolSize]; + +static bool IsInDlsymAllocPool(const void *ptr) { + uptr off = (uptr)ptr - (uptr)alloc_memory_for_dlsym; + return off < sizeof(alloc_memory_for_dlsym); +} + +static void *AllocateFromLocalPool(uptr size_in_bytes) { + uptr size_in_words = RoundUpTo(size_in_bytes, kWordSize) / kWordSize; + void *mem = (void*)&alloc_memory_for_dlsym[allocated_for_dlsym]; + allocated_for_dlsym += size_in_words; + CHECK_LT(allocated_for_dlsym, kDlsymAllocPoolSize); + return mem; +} + INTERCEPTOR(void, free, void *ptr) { GET_STACK_TRACE_FREE; + if (UNLIKELY(IsInDlsymAllocPool(ptr))) + return; asan_free(ptr, &stack, FROM_MALLOC); } INTERCEPTOR(void, cfree, void *ptr) { GET_STACK_TRACE_FREE; + if (UNLIKELY(IsInDlsymAllocPool(ptr))) + return; asan_free(ptr, &stack, FROM_MALLOC); } INTERCEPTOR(void*, malloc, uptr size) { + if (UNLIKELY(!asan_inited)) + // Hack: dlsym calls malloc before REAL(malloc) is retrieved from dlsym. + return AllocateFromLocalPool(size); GET_STACK_TRACE_MALLOC; return asan_malloc(size, &stack); } INTERCEPTOR(void*, calloc, uptr nmemb, uptr size) { - if (!asan_inited) { + if (UNLIKELY(!asan_inited)) // Hack: dlsym calls calloc before REAL(calloc) is retrieved from dlsym. - const uptr kCallocPoolSize = 1024; - static uptr calloc_memory_for_dlsym[kCallocPoolSize]; - static uptr allocated; - uptr size_in_words = ((nmemb * size) + kWordSize - 1) / kWordSize; - void *mem = (void*)&calloc_memory_for_dlsym[allocated]; - allocated += size_in_words; - CHECK(allocated < kCallocPoolSize); - return mem; - } + return AllocateFromLocalPool(nmemb * size); GET_STACK_TRACE_MALLOC; return asan_calloc(nmemb, size, &stack); } INTERCEPTOR(void*, realloc, void *ptr, uptr size) { GET_STACK_TRACE_MALLOC; + if (UNLIKELY(IsInDlsymAllocPool(ptr))) { + uptr offset = (uptr)ptr - (uptr)alloc_memory_for_dlsym; + uptr copy_size = Min(size, kDlsymAllocPoolSize - offset); + void *new_ptr = asan_malloc(size, &stack); + internal_memcpy(new_ptr, ptr, copy_size); + return new_ptr; + } return asan_realloc(ptr, size, &stack); } 2016-07-07 Jakub Jelinek <jakub@redhat.com> Backported from mainline 2016-06-10 Jakub Jelinek <jakub@redhat.com> PR middle-end/71494 * tree-nested.c (convert_nonlocal_reference_stmt): For GIMPLE_GOTO without LABEL_DECL, set *handled_ops_p to false instead of true. * gcc.c-torture/execute/pr71494.c: New test. --- gcc/tree-nested.c (revision 237448) +++ gcc/tree-nested.c (revision 237449) @@ -1348,7 +1348,7 @@ convert_nonlocal_reference_stmt (gimple_ { wi->val_only = true; wi->is_lhs = false; - *handled_ops_p = true; + *handled_ops_p = false; return NULL_TREE; } break; --- gcc/testsuite/gcc.c-torture/execute/pr71494.c (revision 0) +++ gcc/testsuite/gcc.c-torture/execute/pr71494.c (revision 237449) @@ -0,0 +1,22 @@ +/* PR middle-end/71494 */ + +int +main () +{ + void *label = &&out; + int i = 0; + void test (void) + { + label = &&out2; + goto *label; + out2:; + i++; + } + goto *label; + out: + i += 2; + test (); + if (i != 3) + __builtin_abort (); + return 0; +} 2016-07-07 Jakub Jelinek <jakub@redhat.com> Backported from mainline 2016-06-21 Jakub Jelinek <jakub@redhat.com> PR tree-optimization/71588 * tree-ssa-strlen.c (valid_builtin_call): New function. (adjust_last_stmt, strlen_optimize_stmt): Use it. * gcc.dg/pr71558.c: New test. --- gcc/tree-ssa-strlen.c (revision 237632) +++ gcc/tree-ssa-strlen.c (revision 237633) @@ -768,6 +768,49 @@ find_equal_ptrs (tree ptr, int idx) } } +/* Return true if STMT is a call to a builtin function with the right + arguments and attributes that should be considered for optimization + by this pass. */ + +static bool +valid_builtin_call (gimple stmt) +{ + if (!gimple_call_builtin_p (stmt, BUILT_IN_NORMAL)) + return false; + + tree callee = gimple_call_fndecl (stmt); + switch (DECL_FUNCTION_CODE (callee)) + { + case BUILT_IN_STRCHR: + case BUILT_IN_STRLEN: + /* The above functions should be pure. Punt if they aren't. */ + if (gimple_vdef (stmt) || gimple_vuse (stmt) == NULL_TREE) + return false; + break; + + case BUILT_IN_MEMCPY: + case BUILT_IN_MEMCPY_CHK: + case BUILT_IN_MEMPCPY: + case BUILT_IN_MEMPCPY_CHK: + case BUILT_IN_STPCPY: + case BUILT_IN_STPCPY_CHK: + case BUILT_IN_STRCAT: + case BUILT_IN_STRCAT_CHK: + case BUILT_IN_STRCPY: + case BUILT_IN_STRCPY_CHK: + /* The above functions should be neither const nor pure. Punt if they + aren't. */ + if (gimple_vdef (stmt) == NULL_TREE || gimple_vuse (stmt) == NULL_TREE) + return false; + break; + + default: + break; + } + + return true; +} + /* If the last .MEM setter statement before STMT is memcpy (x, y, strlen (y) + 1), the only .MEM use of it is STMT and STMT is known to overwrite x[strlen (x)], adjust the last memcpy to @@ -842,7 +885,7 @@ adjust_last_stmt (strinfo si, gimple stm return; } - if (!gimple_call_builtin_p (last.stmt, BUILT_IN_NORMAL)) + if (!valid_builtin_call (last.stmt)) return; callee = gimple_call_fndecl (last.stmt); @@ -1827,7 +1870,7 @@ strlen_optimize_stmt (gimple_stmt_iterat if (is_gimple_call (stmt)) { tree callee = gimple_call_fndecl (stmt); - if (gimple_call_builtin_p (stmt, BUILT_IN_NORMAL)) + if (valid_builtin_call (stmt)) switch (DECL_FUNCTION_CODE (callee)) { case BUILT_IN_STRLEN: --- gcc/testsuite/gcc.dg/pr71558.c (revision 0) +++ gcc/testsuite/gcc.dg/pr71558.c (revision 237633) @@ -0,0 +1,17 @@ +/* PR tree-optimization/71588 */ + +/* strcpy must not be pure, but make sure we don't ICE even when + it is declared incorrectly. */ +char *strcpy (char *, const char *) __attribute__ ((__pure__)); +__SIZE_TYPE__ strlen (const char *); +void *malloc (__SIZE_TYPE__); + +char a[20]; + +char * +foo (void) +{ + __SIZE_TYPE__ b = strlen (a); + char *c = malloc (b); + return strcpy (c, a); +} 2016-07-07 Jakub Jelinek <jakub@redhat.com> Backported from mainline 2016-06-28 Jakub Jelinek <jakub@redhat.com> PR middle-end/71626 * config/i386/i386.c (ix86_expand_vector_move): For SUBREG of a constant, force its SUBREG_REG into memory or register instead of whole op1. * gcc.c-torture/execute/pr71626-1.c: New test. * gcc.c-torture/execute/pr71626-2.c: New test. --- gcc/config/i386/i386.c (revision 237938) +++ gcc/config/i386/i386.c (revision 237939) @@ -16918,12 +16918,29 @@ ix86_expand_vector_move (enum machine_mo of the register, once we have that information we may be able to handle some of them more efficiently. */ if (can_create_pseudo_p () - && register_operand (op0, mode) && (CONSTANT_P (op1) || (GET_CODE (op1) == SUBREG && CONSTANT_P (SUBREG_REG (op1)))) - && !standard_sse_constant_p (op1)) - op1 = validize_mem (force_const_mem (mode, op1)); + && ((register_operand (op0, mode) + && !standard_sse_constant_p (op1)) + /* ix86_expand_vector_move_misalign() does not like constants. */ + || (SSE_REG_MODE_P (mode) + && MEM_P (op0) + && MEM_ALIGN (op0) < align))) + { + if (GET_CODE (op1) == SUBREG) + { + machine_mode imode = GET_MODE (SUBREG_REG (op1)); + rtx r = force_const_mem (imode, SUBREG_REG (op1)); + if (r) + r = validize_mem (r); + else + r = force_reg (imode, SUBREG_REG (op1)); + op1 = simplify_gen_subreg (mode, r, imode, SUBREG_BYTE (op1)); + } + else + op1 = validize_mem (force_const_mem (mode, op1)); + } /* We need to check memory alignment for SSE mode since attribute can make operands unaligned. */ @@ -16934,13 +16951,8 @@ ix86_expand_vector_move (enum machine_mo { rtx tmp[2]; - /* ix86_expand_vector_move_misalign() does not like constants ... */ - if (CONSTANT_P (op1) - || (GET_CODE (op1) == SUBREG - && CONSTANT_P (SUBREG_REG (op1)))) - op1 = validize_mem (force_const_mem (mode, op1)); - - /* ... nor both arguments in memory. */ + /* ix86_expand_vector_move_misalign() does not like both + arguments in memory. */ if (!register_operand (op0, mode) && !register_operand (op1, mode)) op1 = force_reg (mode, op1); --- gcc/testsuite/gcc.c-torture/execute/pr71626-1.c (revision 0) +++ gcc/testsuite/gcc.c-torture/execute/pr71626-1.c (revision 237939) @@ -0,0 +1,19 @@ +/* PR middle-end/71626 */ + +typedef __INTPTR_TYPE__ V __attribute__((__vector_size__(sizeof (__INTPTR_TYPE__)))); + +__attribute__((noinline, noclone)) V +foo () +{ + V v = { (__INTPTR_TYPE__) foo }; + return v; +} + +int +main () +{ + V v = foo (); + if (v[0] != (__INTPTR_TYPE__) foo) + __builtin_abort (); + return 0; +} --- gcc/testsuite/gcc.c-torture/execute/pr71626-2.c (revision 0) +++ gcc/testsuite/gcc.c-torture/execute/pr71626-2.c (revision 237939) @@ -0,0 +1,4 @@ +/* PR middle-end/71626 */ +/* { dg-additional-options "-fpic" { target fpic } } */ + +#include "pr71626-1.c" 2016-07-07 Jakub Jelinek <jakub@redhat.com> Backported from mainline 2016-06-30 Jakub Jelinek <jakub@redhat.com> PR fortran/71705 * trans-openmp.c (gfc_trans_omp_clauses): Set TREE_ADDRESSABLE on decls in to/from clauses. * gfortran.dg/gomp/pr71705.f90: New test. --- gcc/fortran/trans-openmp.c (revision 237940) +++ gcc/fortran/trans-openmp.c (revision 237941) @@ -2180,6 +2180,8 @@ gfc_trans_omp_clauses (stmtblock_t *bloc tree decl = gfc_get_symbol_decl (n->sym); if (gfc_omp_privatize_by_reference (decl)) decl = build_fold_indirect_ref (decl); + else if (DECL_P (decl)) + TREE_ADDRESSABLE (decl) = 1; if (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (decl))) { tree type = TREE_TYPE (decl); --- gcc/testsuite/gfortran.dg/gomp/pr71705.f90 (revision 0) +++ gcc/testsuite/gfortran.dg/gomp/pr71705.f90 (revision 237941) @@ -0,0 +1,7 @@ +! PR fortran/71705 +! { dg-do compile } + + real :: x + x = 0.0 + !$omp target update to(x) +end 2016-07-07 Jakub Jelinek <jakub@redhat.com> Backported from mainline 2016-06-30 Jakub Jelinek <jakub@redhat.com> PR fortran/71704 * parse.c (matchs, matcho): If spec_only, only gfc_match the keyword and if successful, goto do_spec_only. (matchds, matchdo): Define. (decode_omp_directive): Add spec_only local var and set it. Use matchds or matchdo macros instead of matchs or matcho for declare target, declare simd, declare reduction and threadprivate directives. Return ST_GET_FCN_CHARACTERISTICS if a non-declarative directive could be matched. (next_statement): For ST_GET_FCN_CHARACTERISTICS restore gfc_current_locus from old_locus even if there is no label. * gfortran.dg/gomp/pr71704.f90: New test. --- gcc/fortran/parse.c (revision 237941) +++ gcc/fortran/parse.c (revision 237942) @@ -559,9 +559,12 @@ decode_statement (void) return ST_NONE; } -/* Like match, but set a flag simd_matched if keyword matched. */ +/* Like match, but set a flag simd_matched if keyword matched + and if spec_only, goto do_spec_only without actually matching. */ #define matchs(keyword, subr, st) \ do { \ + if (spec_only && gfc_match (keyword) == MATCH_YES) \ + goto do_spec_only; \ if (match_word_omp_simd (keyword, subr, &old_locus, \ &simd_matched) == MATCH_YES) \ return st; \ @@ -569,11 +572,36 @@ decode_statement (void) undo_new_statement (); \ } while (0); -/* Like match, but don't match anything if not -fopenmp. */ +/* Like match, but don't match anything if not -fopenmp + and if spec_only, goto do_spec_only without actually matching. */ #define matcho(keyword, subr, st) \ do { \ if (!gfc_option.gfc_flag_openmp) \ ; \ + else if (spec_only && gfc_match (keyword) == MATCH_YES) \ + goto do_spec_only; \ + else if (match_word (keyword, subr, &old_locus) \ + == MATCH_YES) \ + return st; \ + else \ + undo_new_statement (); \ + } while (0); + +/* Like match, but set a flag simd_matched if keyword matched. */ +#define matchds(keyword, subr, st) \ + do { \ + if (match_word_omp_simd (keyword, subr, &old_locus, \ + &simd_matched) == MATCH_YES) \ + return st; \ + else \ + undo_new_statement (); \ + } while (0); + +/* Like match, but don't match anything if not -fopenmp. */ +#define matchdo(keyword, subr, st) \ + do { \ + if (!gfc_option.gfc_flag_openmp) \ + ; \ else if (match_word (keyword, subr, &old_locus) \ == MATCH_YES) \ return st; \ @@ -587,6 +615,7 @@ decode_omp_directive (void) locus old_locus; char c; bool simd_matched = false; + bool spec_only = false; gfc_enforce_clean_symbol_state (); @@ -601,6 +630,10 @@ decode_omp_directive (void) return ST_NONE; } + if (gfc_current_state () == COMP_FUNCTION + && gfc_current_block ()->result->ts.kind == -1) + spec_only = true; + gfc_unset_implicit_pure (NULL); old_locus = gfc_current_locus; @@ -629,12 +662,12 @@ decode_omp_directive (void) matcho ("critical", gfc_match_omp_critical, ST_OMP_CRITICAL); break; case 'd': - matchs ("declare reduction", gfc_match_omp_declare_reduction, - ST_OMP_DECLARE_REDUCTION); - matchs ("declare simd", gfc_match_omp_declare_simd, - ST_OMP_DECLARE_SIMD); - matcho ("declare target", gfc_match_omp_declare_target, - ST_OMP_DECLARE_TARGET); + matchds ("declare reduction", gfc_match_omp_declare_reduction, + ST_OMP_DECLARE_REDUCTION); + matchds ("declare simd", gfc_match_omp_declare_simd, + ST_OMP_DECLARE_SIMD); + matchdo ("declare target", gfc_match_omp_declare_target, + ST_OMP_DECLARE_TARGET); matchs ("distribute parallel do simd", gfc_match_omp_distribute_parallel_do_simd, ST_OMP_DISTRIBUTE_PARALLEL_DO_SIMD); @@ -754,8 +787,8 @@ decode_omp_directive (void) matcho ("teams distribute", gfc_match_omp_teams_distribute, ST_OMP_TEAMS_DISTRIBUTE); matcho ("teams", gfc_match_omp_teams, ST_OMP_TEAMS); - matcho ("threadprivate", gfc_match_omp_threadprivate, - ST_OMP_THREADPRIVATE); + matchdo ("threadprivate", gfc_match_omp_threadprivate, + ST_OMP_THREADPRIVATE); break; case 'w': matcho ("workshare", gfc_match_omp_workshare, ST_OMP_WORKSHARE); @@ -778,6 +811,13 @@ decode_omp_directive (void) gfc_error_recovery (); return ST_NONE; + + do_spec_only: + reject_statement (); + gfc_clear_error (); + gfc_buffer_error (false); + gfc_current_locus = old_locus; + return ST_GET_FCN_CHARACTERISTICS; } static gfc_statement @@ -1126,10 +1166,13 @@ next_statement (void) gfc_buffer_error (0); - if (st == ST_GET_FCN_CHARACTERISTICS && gfc_statement_label != NULL) + if (st == ST_GET_FCN_CHARACTERISTICS) { - gfc_free_st_label (gfc_statement_label); - gfc_statement_label = NULL; + if (gfc_statement_label != NULL) + { + gfc_free_st_label (gfc_statement_label); + gfc_statement_label = NULL; + } gfc_current_locus = old_locus; } --- gcc/testsuite/gfortran.dg/gomp/pr71704.f90 (revision 0) +++ gcc/testsuite/gfortran.dg/gomp/pr71704.f90 (revision 237942) @@ -0,0 +1,58 @@ +! PR fortran/71704 +! { dg-do compile } + +real function f0 () +!$omp declare simd (f0) + f0 = 1 +end + +real function f1 () +!$omp declare target (f1) + f1 = 1 +end + +real function f2 () +!$omp declare reduction (foo : integer : omp_out = omp_out + omp_in) & +!$omp & initializer (omp_priv = 0) + f2 = 1 +end + +real function f3 () + real, save :: t +!$omp threadprivate (t) + f3 = 1 +end + +real function f4 () +!$omp taskwait + f4 = 1 +end + +real function f5 () +!$omp barrier + f5 = 1 +end + +real function f6 () +!$omp parallel +!$omp end parallel + f6 = 1 +end + +real function f7 () +!$omp single +!$omp end single + f7 = 1 +end + +real function f8 () +!$omp critical +!$omp end critical + f8 = 1 +end + +real function f9 () +!$omp critical +!$omp end critical + f9 = 1 +end 2016-07-07 Jakub Jelinek <jakub@redhat.com> Backported from mainline 2016-07-01 Jakub Jelinek <jakub@redhat.com> PR fortran/71717 * trans-openmp.c (gfc_omp_privatize_by_reference): Return false for GFC_DECL_ASSOCIATE_VAR_P with POINTER_TYPE. * testsuite/libgomp.fortran/associate3.f90: New test. --- gcc/fortran/trans-openmp.c (revision 237942) +++ gcc/fortran/trans-openmp.c (revision 237943) @@ -61,6 +61,7 @@ gfc_omp_privatize_by_reference (const_tr if (GFC_DECL_GET_SCALAR_POINTER (decl) || GFC_DECL_GET_SCALAR_ALLOCATABLE (decl) || GFC_DECL_CRAY_POINTEE (decl) + || GFC_DECL_ASSOCIATE_VAR_P (decl) || VOID_TYPE_P (TREE_TYPE (TREE_TYPE (decl)))) return false; --- libgomp/testsuite/libgomp.fortran/associate3.f90 (revision 0) +++ libgomp/testsuite/libgomp.fortran/associate3.f90 (revision 237943) @@ -0,0 +1,20 @@ +! PR fortran/71717 +! { dg-do run } + + type t + real, allocatable :: f(:) + end type + type (t) :: v + integer :: i, j + allocate (v%f(4)) + v%f = 19. + i = 5 + associate (u => v, k => i) + !$omp parallel do + do j = 1, 4 + u%f(j) = 21. + if (j.eq.1) k = 7 + end do + end associate + if (any (v%f(:).ne.21.) .or. i.ne.7) call abort +end