Here's two approaches to fix the regression in 89689. Note this only fixes the regression in the originally reported testcase. THe deeper issue Martin raises in C#1 is not addressed. Thus if we go forward with either patch ISTM that we would drop the regression markers, but keep the BZ open.
So the key blocks in question as we enter DSE1: > > ;; basic block 2, loop depth 0, maybe hot > ;; prev block 0, next block 3, flags: (NEW, REACHABLE, VISITED) > ;; pred: ENTRY (FALLTHRU,EXECUTABLE) > h = l; > h$data_33 = l.data; > if (h$data_33 != &__sb_slop) > goto <bb 3>; [70.00%] > else > goto <bb 4>; [30.00%] > ;; succ: 3 [70.0% (guessed)] (TRUE_VALUE,EXECUTABLE) > ;; 4 [30.0% (guessed)] (FALSE_VALUE,EXECUTABLE) > > ;; basic block 3, loop depth 0, maybe hot > ;; prev block 2, next block 4, flags: (NEW, REACHABLE, VISITED) > ;; pred: 2 [70.0% (guessed)] (TRUE_VALUE,EXECUTABLE) > *h$data_33 = 0; > ;; succ: 4 [always] (FALLTHRU,EXECUTABLE) > > ;; basic block 4, loop depth 0, maybe hot > ;; prev block 3, next block 5, flags: (NEW, REACHABLE, VISITED) > ;; pred: 3 [always] (FALLTHRU,EXECUTABLE) > ;; 2 [30.0% (guessed)] (FALSE_VALUE,EXECUTABLE) > _23 = __builtin_object_size (h$data_33, 0); > _25 = __builtin___memcpy_chk (h$data_33, "abcd", 4, _23); > __builtin_puts (h$data_33); > _6 = h$data_33 == &__sb_slop; > _7 = (int) _6; > printf ("%d\n", _7); > _9 = h$data_33 == &buf; > _10 = (int) _9; > printf ("%d\n", _10); > if (h$data_33 != &__sb_slop) > goto <bb 5>; [70.00%] > else > goto <bb 6>; [30.00%] > So vrp1 is going to want to thread the jump at the end of bb4 which requires duplicating bb4. One version of bb4 will only be reachable via the false edge from bb2. That in turn exposes a cprop opportunity to replace h$data_33 with &__sbloop and the type of &__sbloop is a char[1] array thus triggering the false positive warning. We can avoid all that by realizing the store in bb3 is dead. That in turn makes the conditional at the end of bb2 pointless as bb3 is empty and thus both arms ultimately transfer control to bb4 without any other side effects meaning we can eliminate that conditional which in turn eliminates the need for jump threading. Again, this only fixes the original testcase and if there were other statements in bb3 it wouldn't work and it won't work for the test in c#1. But the proposed changes are a general improvement. DSE misses this case because ref_maybe_used_by_stmt_p returns true for the virtual operand of the __builtin_object_size call. Opps! There's two easy ways to fix this, I've bootstrapped and regression tested both. First, the most conservative fix and perhaps the most appropriate for gcc-10 -- special casing __builtin_object_size in tree-ssa-dse.c. The second approach is more general and marks __builtin_object_size as const rather than just pure. Jakub and I kicked this around in IRC a bit. We've always marked __builtin_object_size as pure. It was never const. THere is some concern that code motion might cause _b_o_s to get different results, which would be particularly concerning for _b_o_s types #1 and #3 which do use some contextual information. However, ISTM that motion is still going to be limited by the SSA graph, though somewhat less because we wouldn't have a dependency on the virtual operands. So it *should* be safe, but there's some degree of hesitation to make this change at this point in gcc-10's lifecycle. Thoughts? If we go forward obviously I'd add a testcase and ChangeLog entries. Jeff
diff --git a/gcc/tree-ssa-dse.c b/gcc/tree-ssa-dse.c index 374143e5785..e88342f1b68 100644 --- a/gcc/tree-ssa-dse.c +++ b/gcc/tree-ssa-dse.c @@ -789,8 +789,13 @@ dse_classify_store (ao_ref *ref, gimple *stmt, phi_def = use_stmt; } } - /* If the statement is a use the store is not dead. */ - else if (ref_maybe_used_by_stmt_p (use_stmt, ref)) + /* If the statement is a use the store is not dead. Do not + consider calls to __builtin_object_size as a use. For gcc-11 + we plan mark __builtin_object_size as const. */ + else if ((!is_gimple_call (use_stmt) + || !gimple_call_builtin_p (as_a <gcall *> (use_stmt), + BUILT_IN_OBJECT_SIZE)) + && ref_maybe_used_by_stmt_p (use_stmt, ref)) { /* Handle common cases where we can easily build an ao_ref structure for USE_STMT and in doing so we find that the
commit f4e5d3f4755b6a5846ac20b53008b90131a8bb7c Author: Jeff Law <l...@torsion.usersys.redhat.com> Date: Tue Jan 28 18:16:09 2020 -0500 Mark _b_o_s as constant diff --git a/gcc/builtins.def b/gcc/builtins.def index 5ab842c34c2..fa8b0641ab1 100644 --- a/gcc/builtins.def +++ b/gcc/builtins.def @@ -972,7 +972,7 @@ DEF_BUILTIN_STUB (BUILT_IN_STRCMP_EQ, "__builtin_strcmp_eq") DEF_BUILTIN_STUB (BUILT_IN_STRNCMP_EQ, "__builtin_strncmp_eq") /* Object size checking builtins. */ -DEF_GCC_BUILTIN (BUILT_IN_OBJECT_SIZE, "object_size", BT_FN_SIZE_CONST_PTR_INT, ATTR_PURE_NOTHROW_LEAF_LIST) +DEF_GCC_BUILTIN (BUILT_IN_OBJECT_SIZE, "object_size", BT_FN_SIZE_CONST_PTR_INT, ATTR_CONST_NOTHROW_LEAF_LIST) DEF_EXT_LIB_BUILTIN (BUILT_IN_MEMCPY_CHK, "__memcpy_chk", BT_FN_PTR_PTR_CONST_PTR_SIZE_SIZE, ATTR_RET1_NOTHROW_NONNULL_LEAF) DEF_EXT_LIB_BUILTIN (BUILT_IN_MEMMOVE_CHK, "__memmove_chk", BT_FN_PTR_PTR_CONST_PTR_SIZE_SIZE, ATTR_RET1_NOTHROW_NONNULL_LEAF) DEF_EXT_LIB_BUILTIN (BUILT_IN_MEMPCPY_CHK, "__mempcpy_chk", BT_FN_PTR_PTR_CONST_PTR_SIZE_SIZE, ATTR_RETNONNULL_NOTHROW_LEAF)