Mercurial > hg > CbC > CbC_gcc
diff gcc/cfgexpand.c @ 132:d34655255c78
update gcc-8.2
author | mir3636 |
---|---|
date | Thu, 25 Oct 2018 10:21:07 +0900 |
parents | f81c5aa9f14f 84e7813d76e9 |
children | 4e440907fcbf |
line wrap: on
line diff
--- a/gcc/cfgexpand.c Thu Oct 25 08:08:40 2018 +0900 +++ b/gcc/cfgexpand.c Thu Oct 25 10:21:07 2018 +0900 @@ -1,5 +1,5 @@ /* A pass for lowering trees to RTL. - Copyright (C) 2004-2017 Free Software Foundation, Inc. + Copyright (C) 2004-2018 Free Software Foundation, Inc. This file is part of GCC. @@ -77,8 +77,6 @@ #include "tree-ssa-address.h" #include "output.h" #include "builtins.h" -#include "tree-chkp.h" -#include "rtl-chkp.h" /* Some systems use __main in a way incompatible with its use in gcc, in these cases use the macros NAME__MAIN to give a quoted symbol and SYMBOL__MAIN to @@ -317,7 +315,7 @@ /* Initially, the size of the variable. Later, the size of the partition, if this variable becomes it's partition's representative. */ - HOST_WIDE_INT size; + poly_uint64 size; /* The *byte* alignment required for this variable. Or as, with the size, the alignment for this partition. */ @@ -392,22 +390,23 @@ /* Allocate SIZE bytes at byte alignment ALIGN from the stack frame. Return the frame offset. */ -static HOST_WIDE_INT -alloc_stack_frame_space (HOST_WIDE_INT size, unsigned HOST_WIDE_INT align) +static poly_int64 +alloc_stack_frame_space (poly_int64 size, unsigned HOST_WIDE_INT align) { - HOST_WIDE_INT offset, new_frame_offset; + poly_int64 offset, new_frame_offset; if (FRAME_GROWS_DOWNWARD) { new_frame_offset - = align_base (frame_offset - frame_phase - size, - align, false) + frame_phase; + = aligned_lower_bound (frame_offset - frame_phase - size, + align) + frame_phase; offset = new_frame_offset; } else { new_frame_offset - = align_base (frame_offset - frame_phase, align, true) + frame_phase; + = aligned_upper_bound (frame_offset - frame_phase, + align) + frame_phase; offset = new_frame_offset; new_frame_offset += size; } @@ -445,10 +444,10 @@ tree size = TREE_CODE (decl) == SSA_NAME ? TYPE_SIZE_UNIT (TREE_TYPE (decl)) : DECL_SIZE_UNIT (decl); - v->size = tree_to_uhwi (size); + v->size = tree_to_poly_uint64 (size); /* Ensure that all variables have size, so that &a != &b for any two variables that are simultaneously live. */ - if (v->size == 0) + if (known_eq (v->size, 0U)) v->size = 1; v->alignb = align_local_variable (decl); /* An alignment of zero can mightily confuse us later. */ @@ -678,8 +677,8 @@ size_t ib = *(const size_t *)b; unsigned int aligna = stack_vars[ia].alignb; unsigned int alignb = stack_vars[ib].alignb; - HOST_WIDE_INT sizea = stack_vars[ia].size; - HOST_WIDE_INT sizeb = stack_vars[ib].size; + poly_int64 sizea = stack_vars[ia].size; + poly_int64 sizeb = stack_vars[ib].size; tree decla = stack_vars[ia].decl; tree declb = stack_vars[ib].decl; bool largea, largeb; @@ -692,10 +691,9 @@ return (int)largeb - (int)largea; /* Secondary compare on size, decreasing */ - if (sizea > sizeb) - return -1; - if (sizea < sizeb) - return 1; + int diff = compare_sizes_for_sort (sizeb, sizea); + if (diff != 0) + return diff; /* Tertiary compare on true alignment, decreasing. */ if (aligna < alignb) @@ -906,7 +904,7 @@ { size_t i = stack_vars_sorted[si]; unsigned int ialign = stack_vars[i].alignb; - HOST_WIDE_INT isize = stack_vars[i].size; + poly_int64 isize = stack_vars[i].size; /* Ignore objects that aren't partition representatives. If we see a var that is not a partition representative, it must @@ -918,7 +916,7 @@ { size_t j = stack_vars_sorted[sj]; unsigned int jalign = stack_vars[j].alignb; - HOST_WIDE_INT jsize = stack_vars[j].size; + poly_int64 jsize = stack_vars[j].size; /* Ignore objects that aren't partition representatives. */ if (stack_vars[j].representative != j) @@ -934,8 +932,8 @@ sizes, as the shorter vars wouldn't be adequately protected. Don't do that for "large" (unsupported) alignment objects, those aren't protected anyway. */ - if ((asan_sanitize_stack_p ()) - && isize != jsize + if (asan_sanitize_stack_p () + && maybe_ne (isize, jsize) && ialign * BITS_PER_UNIT <= MAX_SUPPORTED_STACK_ALIGNMENT) break; @@ -966,9 +964,9 @@ if (stack_vars[i].representative != i) continue; - fprintf (dump_file, "Partition %lu: size " HOST_WIDE_INT_PRINT_DEC - " align %u\n", (unsigned long) i, stack_vars[i].size, - stack_vars[i].alignb); + fprintf (dump_file, "Partition %lu: size ", (unsigned long) i); + print_dec (stack_vars[i].size, dump_file); + fprintf (dump_file, " align %u\n", stack_vars[i].alignb); for (j = i; j != EOC; j = stack_vars[j].next) { @@ -983,13 +981,13 @@ static void expand_one_stack_var_at (tree decl, rtx base, unsigned base_align, - HOST_WIDE_INT offset) + poly_int64 offset) { unsigned align; rtx x; /* If this fails, we've overflowed the stack frame. Error nicely? */ - gcc_assert (offset == trunc_int_for_mode (offset, Pmode)); + gcc_assert (known_eq (offset, trunc_int_for_mode (offset, Pmode))); x = plus_constant (Pmode, base, offset); x = gen_rtx_MEM (TREE_CODE (decl) == SSA_NAME @@ -1003,7 +1001,7 @@ important, we'll simply use the alignment that is already set. */ if (base == virtual_stack_vars_rtx) offset -= frame_phase; - align = least_bit_hwi (offset); + align = known_alignment (offset); align *= BITS_PER_UNIT; if (align == 0 || align > base_align) align = base_align; @@ -1044,7 +1042,7 @@ expand_stack_vars (bool (*pred) (size_t), struct stack_vars_data *data) { size_t si, i, j, n = stack_vars_num; - HOST_WIDE_INT large_size = 0, large_alloc = 0; + poly_uint64 large_size = 0, large_alloc = 0; rtx large_base = NULL; unsigned large_align = 0; bool large_allocation_done = false; @@ -1087,8 +1085,7 @@ : DECL_RTL (decl) != pc_rtx) continue; - large_size += alignb - 1; - large_size &= -(HOST_WIDE_INT)alignb; + large_size = aligned_upper_bound (large_size, alignb); large_size += stack_vars[i].size; } } @@ -1097,7 +1094,7 @@ { rtx base; unsigned base_align, alignb; - HOST_WIDE_INT offset; + poly_int64 offset; i = stack_vars_sorted[si]; @@ -1122,13 +1119,17 @@ if (alignb * BITS_PER_UNIT <= MAX_SUPPORTED_STACK_ALIGNMENT) { base = virtual_stack_vars_rtx; - if ((asan_sanitize_stack_p ()) - && pred) + /* ASAN description strings don't yet have a syntax for expressing + polynomial offsets. */ + HOST_WIDE_INT prev_offset; + if (asan_sanitize_stack_p () + && pred + && frame_offset.is_constant (&prev_offset) + && stack_vars[i].size.is_constant ()) { - HOST_WIDE_INT prev_offset - = align_base (frame_offset, - MAX (alignb, ASAN_RED_ZONE_SIZE), - !FRAME_GROWS_DOWNWARD); + prev_offset = align_base (prev_offset, + MAX (alignb, ASAN_RED_ZONE_SIZE), + !FRAME_GROWS_DOWNWARD); tree repr_decl = NULL_TREE; offset = alloc_stack_frame_space (stack_vars[i].size @@ -1136,7 +1137,10 @@ MAX (alignb, ASAN_RED_ZONE_SIZE)); data->asan_vec.safe_push (prev_offset); - data->asan_vec.safe_push (offset + stack_vars[i].size); + /* Allocating a constant amount of space from a constant + starting offset must give a constant result. */ + data->asan_vec.safe_push ((offset + stack_vars[i].size) + .to_constant ()); /* Find best representative of the partition. Prefer those with DECL_NAME, even better satisfying asan_protect_stack_decl predicate. */ @@ -1154,6 +1158,20 @@ if (repr_decl == NULL_TREE) repr_decl = stack_vars[i].decl; data->asan_decl_vec.safe_push (repr_decl); + + /* Make sure a representative is unpoison if another + variable in the partition is handled by + use-after-scope sanitization. */ + if (asan_handled_variables != NULL + && !asan_handled_variables->contains (repr_decl)) + { + for (j = i; j != EOC; j = stack_vars[j].next) + if (asan_handled_variables->contains (stack_vars[j].decl)) + break; + if (j != EOC) + asan_handled_variables->add (repr_decl); + } + data->asan_alignb = MAX (data->asan_alignb, alignb); if (data->asan_base == NULL) data->asan_base = gen_reg_rtx (Pmode); @@ -1180,23 +1198,22 @@ /* If there were any variables requiring "large" alignment, allocate space. */ - if (large_size > 0 && ! large_allocation_done) + if (maybe_ne (large_size, 0U) && ! large_allocation_done) { - HOST_WIDE_INT loffset; + poly_int64 loffset; rtx large_allocsize; - large_allocsize = GEN_INT (large_size); + large_allocsize = gen_int_mode (large_size, Pmode); get_dynamic_stack_size (&large_allocsize, 0, large_align, NULL); loffset = alloc_stack_frame_space - (INTVAL (large_allocsize), + (rtx_to_poly_int64 (large_allocsize), PREFERRED_STACK_BOUNDARY / BITS_PER_UNIT); large_base = get_dynamic_stack_base (loffset, large_align); large_allocation_done = true; } gcc_assert (large_base != NULL); - large_alloc += alignb - 1; - large_alloc &= -(HOST_WIDE_INT)alignb; + large_alloc = aligned_upper_bound (large_alloc, alignb); offset = large_alloc; large_alloc += stack_vars[i].size; @@ -1214,15 +1231,15 @@ } } - gcc_assert (large_alloc == large_size); + gcc_assert (known_eq (large_alloc, large_size)); } /* Take into account all sizes of partitions and reset DECL_RTLs. */ -static HOST_WIDE_INT +static poly_uint64 account_stack_vars (void) { size_t si, j, i, n = stack_vars_num; - HOST_WIDE_INT size = 0; + poly_uint64 size = 0; for (si = 0; si < n; ++si) { @@ -1257,10 +1274,10 @@ allocate it, which means that in-frame portion is just a pointer. ??? We've got a pseudo for sure here, do we actually dynamically allocate its spilling area if needed? - ??? Isn't it a problem when POINTER_SIZE also exceeds - MAX_SUPPORTED_STACK_ALIGNMENT, as on cris and lm32? */ + ??? Isn't it a problem when Pmode alignment also exceeds + MAX_SUPPORTED_STACK_ALIGNMENT, as can happen on cris and lm32? */ if (align > MAX_SUPPORTED_STACK_ALIGNMENT) - align = POINTER_SIZE; + align = GET_MODE_ALIGNMENT (Pmode); record_alignment_for_reg_var (align); } @@ -1285,18 +1302,19 @@ static void expand_one_stack_var_1 (tree var) { - HOST_WIDE_INT size, offset; + poly_uint64 size; + poly_int64 offset; unsigned byte_align; if (TREE_CODE (var) == SSA_NAME) { tree type = TREE_TYPE (var); - size = tree_to_uhwi (TYPE_SIZE_UNIT (type)); + size = tree_to_poly_uint64 (TYPE_SIZE_UNIT (type)); byte_align = TYPE_ALIGN_UNIT (type); } else { - size = tree_to_uhwi (DECL_SIZE_UNIT (var)); + size = tree_to_poly_uint64 (DECL_SIZE_UNIT (var)); byte_align = align_local_variable (var); } @@ -1380,7 +1398,7 @@ /* If the variable alignment is very large we'll dynamicaly allocate it, which means that in-frame portion is just a pointer. */ if (align > MAX_SUPPORTED_STACK_ALIGNMENT) - align = POINTER_SIZE; + align = GET_MODE_ALIGNMENT (Pmode); record_alignment_for_reg_var (align); @@ -1508,12 +1526,14 @@ tree size_unit = TREE_CODE (var) == SSA_NAME ? TYPE_SIZE_UNIT (TREE_TYPE (var)) : DECL_SIZE_UNIT (var); + poly_uint64 size; /* Whether the variable is small enough for immediate allocation not to be a problem with regard to the frame size. */ bool smallish - = ((HOST_WIDE_INT) tree_to_uhwi (size_unit) - < PARAM_VALUE (PARAM_MIN_SIZE_FOR_STACK_SHARING)); + = (poly_int_tree_p (size_unit, &size) + && (estimated_poly_value (size) + < PARAM_VALUE (PARAM_MIN_SIZE_FOR_STACK_SHARING))); /* If stack protection is enabled, *all* stack variables must be deferred, so that we can re-order the strings to the top of the frame. @@ -1567,7 +1587,7 @@ Return stack usage this variable is supposed to take. */ -static HOST_WIDE_INT +static poly_uint64 expand_one_var (tree var, bool toplevel, bool really_expand) { unsigned int align = BITS_PER_UNIT; @@ -1605,11 +1625,12 @@ /* If the variable alignment is very large we'll dynamicaly allocate it, which means that in-frame portion is just a pointer. */ if (align > MAX_SUPPORTED_STACK_ALIGNMENT) - align = POINTER_SIZE; + align = GET_MODE_ALIGNMENT (Pmode); } record_alignment_for_reg_var (align); + poly_uint64 size; if (TREE_CODE (origvar) == SSA_NAME) { gcc_assert (!VAR_P (var) @@ -1650,12 +1671,18 @@ if (really_expand) expand_one_register_var (origvar); } - else if (! valid_constant_size_p (DECL_SIZE_UNIT (var))) + else if (!poly_int_tree_p (DECL_SIZE_UNIT (var), &size) + || !valid_constant_size_p (DECL_SIZE_UNIT (var))) { /* Reject variables which cover more than half of the address-space. */ if (really_expand) { - error ("size of variable %q+D is too large", var); + if (DECL_NONLOCAL_FRAME (var)) + error_at (DECL_SOURCE_LOCATION (current_function_decl), + "total size of local objects is too large"); + else + error_at (DECL_SOURCE_LOCATION (var), + "size of variable %q+D is too large", var); expand_one_error_var (var); } } @@ -1672,9 +1699,7 @@ expand_one_stack_var (origvar); } - - - return tree_to_uhwi (DECL_SIZE_UNIT (var)); + return size; } return 0; } @@ -1927,7 +1952,7 @@ HOST_WIDE_INT estimated_stack_frame_size (struct cgraph_node *node) { - HOST_WIDE_INT size = 0; + poly_int64 size = 0; size_t i; tree var; struct function *fn = DECL_STRUCT_FUNCTION (node->decl); @@ -1951,7 +1976,7 @@ fini_vars_expansion (); pop_cfun (); - return size; + return estimated_poly_value (size); } /* Helper routine to check if a record or union contains an array field. */ @@ -2221,9 +2246,12 @@ in addition to phase 1 and 2. */ expand_stack_vars (asan_decl_phase_3, &data); - if (!data.asan_vec.is_empty ()) + /* ASAN description strings don't yet have a syntax for expressing + polynomial offsets. */ + HOST_WIDE_INT prev_offset; + if (!data.asan_vec.is_empty () + && frame_offset.is_constant (&prev_offset)) { - HOST_WIDE_INT prev_offset = frame_offset; HOST_WIDE_INT offset, sz, redzonesz; redzonesz = ASAN_RED_ZONE_SIZE; sz = data.asan_vec[0] - prev_offset; @@ -2232,8 +2260,10 @@ && sz + ASAN_RED_ZONE_SIZE >= (int) data.asan_alignb) redzonesz = ((sz + ASAN_RED_ZONE_SIZE + data.asan_alignb - 1) & ~(data.asan_alignb - HOST_WIDE_INT_1)) - sz; - offset - = alloc_stack_frame_space (redzonesz, ASAN_RED_ZONE_SIZE); + /* Allocating a constant amount of space from a constant + starting offset must give a constant result. */ + offset = (alloc_stack_frame_space (redzonesz, ASAN_RED_ZONE_SIZE) + .to_constant ()); data.asan_vec.safe_push (prev_offset); data.asan_vec.safe_push (offset); /* Leave space for alignment if STRICT_ALIGNMENT. */ @@ -2278,9 +2308,10 @@ if (STACK_ALIGNMENT_NEEDED) { HOST_WIDE_INT align = PREFERRED_STACK_BOUNDARY / BITS_PER_UNIT; - if (!FRAME_GROWS_DOWNWARD) - frame_offset += align - 1; - frame_offset &= -align; + if (FRAME_GROWS_DOWNWARD) + frame_offset = aligned_lower_bound (frame_offset, align); + else + frame_offset = aligned_upper_bound (frame_offset, align); } return var_end_seq; @@ -2468,6 +2499,13 @@ } } + /* Optimize (x % C1) == C2 or (x % C1) != C2 if it is beneficial + into (x - C2) * C3 < C4. */ + if ((code == EQ_EXPR || code == NE_EXPR) + && TREE_CODE (op0) == SSA_NAME + && TREE_CODE (op1) == INTEGER_CST) + code = maybe_optimize_mod_cmp (code, &op0, &op1); + last2 = last = get_last_insn (); extract_true_false_edges_from_block (bb, &true_edge, &false_edge); @@ -2519,7 +2557,6 @@ redirect_edge_succ (false_edge, new_bb); false_edge->flags |= EDGE_FALLTHRU; new_bb->count = false_edge->count (); - new_bb->frequency = EDGE_FREQUENCY (false_edge); loop_p loop = find_common_loop (bb->loop_father, dest->loop_father); add_bb_to_loop (new_bb, loop); if (loop->latch == bb @@ -2608,7 +2645,7 @@ exp = build_vl_exp (CALL_EXPR, gimple_call_num_args (stmt) + 3); CALL_EXPR_FN (exp) = gimple_call_fn (stmt); - builtin_p = decl && DECL_BUILT_IN (decl); + builtin_p = decl && fndecl_built_in_p (decl); /* If this is not a builtin function, the function type through which the call is made may be different from the type of the function. */ @@ -2640,11 +2677,14 @@ if (gimple_call_nothrow_p (stmt)) TREE_NOTHROW (exp) = 1; + if (gimple_no_warning_p (stmt)) + TREE_NO_WARNING (exp) = 1; + CALL_EXPR_TAILCALL (exp) = gimple_call_tail_p (stmt); CALL_EXPR_MUST_TAIL_CALL (exp) = gimple_call_must_tail_p (stmt); CALL_EXPR_RETURN_SLOT_OPT (exp) = gimple_call_return_slot_opt_p (stmt); if (decl - && DECL_BUILT_IN_CLASS (decl) == BUILT_IN_NORMAL + && fndecl_built_in_p (decl, BUILT_IN_NORMAL) && ALLOCA_FUNCTION_CODE_P (DECL_FUNCTION_CODE (decl))) CALL_ALLOCA_FOR_VAR_P (exp) = gimple_call_alloca_for_var_p (stmt); else @@ -2652,7 +2692,6 @@ CALL_EXPR_VA_ARG_PACK (exp) = gimple_call_va_arg_pack_p (stmt); CALL_EXPR_BY_DESCRIPTOR (exp) = gimple_call_by_descriptor_p (stmt); SET_EXPR_LOCATION (exp, gimple_location (stmt)); - CALL_WITH_BOUNDS_P (exp) = gimple_call_with_bounds_p (stmt); /* Ensure RTL is created for debug args. */ if (decl && DECL_HAS_DEBUG_ARGS_P (decl)) @@ -3031,14 +3070,14 @@ generating_concat_p = 0; - if ((TREE_CODE (val) == INDIRECT_REF - && allows_mem) + if ((TREE_CODE (val) == INDIRECT_REF && allows_mem) || (DECL_P (val) && (allows_mem || REG_P (DECL_RTL (val))) && ! (REG_P (DECL_RTL (val)) && GET_MODE (DECL_RTL (val)) != TYPE_MODE (type))) || ! allows_reg - || is_inout) + || is_inout + || TREE_ADDRESSABLE (type)) { op = expand_expr (val, NULL_RTX, VOIDmode, !allows_reg ? EXPAND_MEMORY : EXPAND_WRITE); @@ -3047,7 +3086,7 @@ if (! allows_reg && !MEM_P (op)) error ("output number %d not directly addressable", i); - if ((! allows_mem && MEM_P (op)) + if ((! allows_mem && MEM_P (op) && GET_MODE (op) != BLKmode) || GET_CODE (op) == CONCAT) { rtx old_op = op; @@ -3229,7 +3268,7 @@ may insert further instructions into the same basic block after asm goto and if we don't do this, insertion of instructions on the fallthru edge might misbehave. See PR58670. */ - if (fallthru_bb && label_to_block_fn (cfun, label) == fallthru_bb) + if (fallthru_bb && label_to_block (cfun, label) == fallthru_bb) { if (fallthru_label == NULL_RTX) fallthru_label = gen_label_rtx (); @@ -3431,12 +3470,11 @@ from the current function. */ static void -expand_return (tree retval, tree bounds) +expand_return (tree retval) { rtx result_rtl; rtx val = 0; tree retval_rhs; - rtx bounds_rtl; /* If function wants no value, give it none. */ if (TREE_CODE (TREE_TYPE (TREE_TYPE (current_function_decl))) == VOID_TYPE) @@ -3462,71 +3500,6 @@ result_rtl = DECL_RTL (DECL_RESULT (current_function_decl)); - /* Put returned bounds to the right place. */ - bounds_rtl = DECL_BOUNDS_RTL (DECL_RESULT (current_function_decl)); - if (bounds_rtl) - { - rtx addr = NULL; - rtx bnd = NULL; - - if (bounds && bounds != error_mark_node) - { - bnd = expand_normal (bounds); - targetm.calls.store_returned_bounds (bounds_rtl, bnd); - } - else if (REG_P (bounds_rtl)) - { - if (bounds) - bnd = chkp_expand_zero_bounds (); - else - { - addr = expand_normal (build_fold_addr_expr (retval_rhs)); - addr = gen_rtx_MEM (Pmode, addr); - bnd = targetm.calls.load_bounds_for_arg (addr, NULL, NULL); - } - - targetm.calls.store_returned_bounds (bounds_rtl, bnd); - } - else - { - int n; - - gcc_assert (GET_CODE (bounds_rtl) == PARALLEL); - - if (bounds) - bnd = chkp_expand_zero_bounds (); - else - { - addr = expand_normal (build_fold_addr_expr (retval_rhs)); - addr = gen_rtx_MEM (Pmode, addr); - } - - for (n = 0; n < XVECLEN (bounds_rtl, 0); n++) - { - rtx slot = XEXP (XVECEXP (bounds_rtl, 0, n), 0); - if (!bounds) - { - rtx offs = XEXP (XVECEXP (bounds_rtl, 0, n), 1); - rtx from = adjust_address (addr, Pmode, INTVAL (offs)); - bnd = targetm.calls.load_bounds_for_arg (from, NULL, NULL); - } - targetm.calls.store_returned_bounds (slot, bnd); - } - } - } - else if (chkp_function_instrumented_p (current_function_decl) - && !BOUNDED_P (retval_rhs) - && chkp_type_has_pointer (TREE_TYPE (retval_rhs)) - && TREE_CODE (retval_rhs) != RESULT_DECL) - { - rtx addr = expand_normal (build_fold_addr_expr (retval_rhs)); - addr = gen_rtx_MEM (Pmode, addr); - - gcc_assert (MEM_P (result_rtl)); - - chkp_copy_bounds_for_stack_parm (result_rtl, addr, TREE_TYPE (retval_rhs)); - } - /* If we are returning the RESULT_DECL, then the value has already been stored into it, so we don't have to do anything special. */ if (TREE_CODE (retval_rhs) == RESULT_DECL) @@ -3569,6 +3542,26 @@ } } +/* Expand a clobber of LHS. If LHS is stored it in a multi-part + register, tell the rtl optimizers that its value is no longer + needed. */ + +static void +expand_clobber (tree lhs) +{ + if (DECL_P (lhs)) + { + rtx decl_rtl = DECL_RTL_IF_SET (lhs); + if (decl_rtl && REG_P (decl_rtl)) + { + machine_mode decl_mode = GET_MODE (decl_rtl); + if (maybe_gt (GET_MODE_SIZE (decl_mode), + REGMODE_NATURAL_SIZE (decl_mode))) + emit_clobber (decl_rtl); + } + } +} + /* A subroutine of expand_gimple_stmt, expanding one gimple statement STMT that doesn't require special handling for outgoing edges. That is no tailcalls and no GIMPLE_COND. */ @@ -3613,19 +3606,12 @@ case GIMPLE_RETURN: { - tree bnd = gimple_return_retbnd (as_a <greturn *> (stmt)); op0 = gimple_return_retval (as_a <greturn *> (stmt)); if (op0 && op0 != error_mark_node) { tree result = DECL_RESULT (current_function_decl); - /* Mark we have return statement with missing bounds. */ - if (!bnd - && chkp_function_instrumented_p (cfun->decl) - && !DECL_P (op0)) - bnd = error_mark_node; - /* If we are not returning the current function's RESULT_DECL, build an assignment to it. */ if (op0 != result) @@ -3647,7 +3633,7 @@ if (!op0) expand_null_return (); else - expand_return (op0, bnd); + expand_return (op0); } break; @@ -3674,7 +3660,7 @@ if (TREE_CLOBBER_P (rhs)) /* This is a clobber to mark the going out of scope for this LHS. */ - ; + expand_clobber (lhs); else expand_assignment (lhs, rhs, gimple_assign_nontemporal_move_p ( @@ -3793,6 +3779,7 @@ /* If we want exceptions for non-call insns, any may_trap_p instruction may throw. */ && GET_CODE (PATTERN (insn)) != CLOBBER + && GET_CODE (PATTERN (insn)) != CLOBBER_HIGH && GET_CODE (PATTERN (insn)) != USE && insn_could_throw_p (insn)) make_reg_eh_region_note (insn, 0, lp_nr); @@ -3850,11 +3837,7 @@ if (!(e->flags & (EDGE_ABNORMAL | EDGE_EH))) { if (e->dest != EXIT_BLOCK_PTR_FOR_FN (cfun)) - { - e->dest->frequency -= EDGE_FREQUENCY (e); - if (e->dest->frequency < 0) - e->dest->frequency = 0; - } + e->dest->count -= e->count (); probability += e->probability; remove_edge (e); } @@ -4173,7 +4156,6 @@ case SAD_EXPR: case WIDEN_MULT_PLUS_EXPR: case WIDEN_MULT_MINUS_EXPR: - case FMA_EXPR: goto ternary; case TRUTH_ANDIF_EXPR: @@ -4199,6 +4181,8 @@ binary: case tcc_binary: + if (mode == BLKmode) + return NULL_RTX; op1 = expand_debug_expr (TREE_OPERAND (exp, 1)); if (!op1) return NULL_RTX; @@ -4223,6 +4207,8 @@ unary: case tcc_unary: + if (mode == BLKmode) + return NULL_RTX; inner_mode = TYPE_MODE (TREE_TYPE (TREE_OPERAND (exp, 0))); op0 = expand_debug_expr (TREE_OPERAND (exp, 0)); if (!op0) @@ -4266,6 +4252,9 @@ op0 = expand_expr (exp, NULL_RTX, mode, EXPAND_INITIALIZER); return op0; + case POLY_INT_CST: + return immed_wide_int_const (poly_int_cst_value (exp), mode); + case COMPLEX_CST: gcc_assert (COMPLEX_MODE_P (mode)); op0 = expand_debug_expr (TREE_REALPART (exp)); @@ -4414,10 +4403,11 @@ goto component_ref; op1 = expand_debug_expr (TREE_OPERAND (exp, 1)); - if (!op1 || !CONST_INT_P (op1)) + poly_int64 offset; + if (!op1 || !poly_int_rtx_p (op1, &offset)) return NULL; - op0 = plus_constant (inner_mode, op0, INTVAL (op1)); + op0 = plus_constant (inner_mode, op0, offset); } as = TYPE_ADDR_SPACE (TREE_TYPE (TREE_TYPE (TREE_OPERAND (exp, 0)))); @@ -4469,7 +4459,7 @@ case VIEW_CONVERT_EXPR: { machine_mode mode1; - HOST_WIDE_INT bitsize, bitpos; + poly_int64 bitsize, bitpos; tree offset; int reversep, volatilep = 0; tree tem @@ -4477,7 +4467,7 @@ &unsignedp, &reversep, &volatilep); rtx orig_op0; - if (bitsize == 0) + if (known_eq (bitsize, 0)) return NULL; orig_op0 = op0 = expand_debug_expr (tem); @@ -4518,21 +4508,20 @@ if (MEM_P (op0)) { if (mode1 == VOIDmode) - /* Bitfield. */ - mode1 = smallest_int_mode_for_size (bitsize); - if (bitpos >= BITS_PER_UNIT) { - op0 = adjust_address_nv (op0, mode1, bitpos / BITS_PER_UNIT); - bitpos %= BITS_PER_UNIT; + if (maybe_gt (bitsize, MAX_BITSIZE_MODE_ANY_INT)) + return NULL; + /* Bitfield. */ + mode1 = smallest_int_mode_for_size (bitsize); } - else if (bitpos < 0) + poly_int64 bytepos = bits_to_bytes_round_down (bitpos); + if (maybe_ne (bytepos, 0)) { - HOST_WIDE_INT units - = (-bitpos + BITS_PER_UNIT - 1) / BITS_PER_UNIT; - op0 = adjust_address_nv (op0, mode1, -units); - bitpos += units * BITS_PER_UNIT; + op0 = adjust_address_nv (op0, mode1, bytepos); + bitpos = num_trailing_bits (bitpos); } - else if (bitpos == 0 && bitsize == GET_MODE_BITSIZE (mode)) + else if (known_eq (bitpos, 0) + && known_eq (bitsize, GET_MODE_BITSIZE (mode))) op0 = adjust_address_nv (op0, mode, 0); else if (GET_MODE (op0) != mode1) op0 = adjust_address_nv (op0, mode1, 0); @@ -4543,17 +4532,18 @@ set_mem_attributes (op0, exp, 0); } - if (bitpos == 0 && mode == GET_MODE (op0)) + if (known_eq (bitpos, 0) && mode == GET_MODE (op0)) return op0; - if (bitpos < 0) + if (maybe_lt (bitpos, 0)) return NULL; - if (GET_MODE (op0) == BLKmode) + if (GET_MODE (op0) == BLKmode || mode == BLKmode) return NULL; - if ((bitpos % BITS_PER_UNIT) == 0 - && bitsize == GET_MODE_BITSIZE (mode1)) + poly_int64 bytepos; + if (multiple_p (bitpos, BITS_PER_UNIT, &bytepos) + && known_eq (bitsize, GET_MODE_BITSIZE (mode1))) { machine_mode opmode = GET_MODE (op0); @@ -4566,12 +4556,11 @@ debug stmts). The gen_subreg below would rightfully crash, and the address doesn't really exist, so just drop it. */ - if (bitpos >= GET_MODE_BITSIZE (opmode)) + if (known_ge (bitpos, GET_MODE_BITSIZE (opmode))) return NULL; - if ((bitpos % GET_MODE_BITSIZE (mode)) == 0) - return simplify_gen_subreg (mode, op0, opmode, - bitpos / BITS_PER_UNIT); + if (multiple_p (bitpos, GET_MODE_BITSIZE (mode))) + return simplify_gen_subreg (mode, op0, opmode, bytepos); } return simplify_gen_ternary (SCALAR_INT_MODE_P (GET_MODE (op0)) @@ -4581,10 +4570,12 @@ GET_MODE (op0) != VOIDmode ? GET_MODE (op0) : TYPE_MODE (TREE_TYPE (tem)), - op0, GEN_INT (bitsize), GEN_INT (bitpos)); + op0, gen_int_mode (bitsize, word_mode), + gen_int_mode (bitpos, word_mode)); } case ABS_EXPR: + case ABSU_EXPR: return simplify_gen_unary (ABS, mode, op0, mode); case NEGATE_EXPR: @@ -4631,6 +4622,7 @@ return simplify_gen_binary (PLUS, mode, op0, op1); case MINUS_EXPR: + case POINTER_DIFF_EXPR: return simplify_gen_binary (MINUS, mode, op0, op1); case MULT_EXPR: @@ -4897,7 +4889,7 @@ if (handled_component_p (TREE_OPERAND (exp, 0))) { - HOST_WIDE_INT bitoffset, bitsize, maxsize; + poly_int64 bitoffset, bitsize, maxsize, byteoffset; bool reverse; tree decl = get_ref_base_and_extent (TREE_OPERAND (exp, 0), &bitoffset, @@ -4907,12 +4899,12 @@ || TREE_CODE (decl) == RESULT_DECL) && (!TREE_ADDRESSABLE (decl) || target_for_debug_bind (decl)) - && (bitoffset % BITS_PER_UNIT) == 0 - && bitsize > 0 - && bitsize == maxsize) + && multiple_p (bitoffset, BITS_PER_UNIT, &byteoffset) + && known_gt (bitsize, 0) + && known_eq (bitsize, maxsize)) { rtx base = gen_rtx_DEBUG_IMPLICIT_PTR (mode, decl); - return plus_constant (mode, base, bitoffset / BITS_PER_UNIT); + return plus_constant (mode, base, byteoffset); } } @@ -4930,10 +4922,11 @@ { op1 = expand_debug_expr (TREE_OPERAND (TREE_OPERAND (exp, 0), 1)); - if (!op1 || !CONST_INT_P (op1)) + poly_int64 offset; + if (!op1 || !poly_int_rtx_p (op1, &offset)) return NULL; - return plus_constant (mode, op0, INTVAL (op1)); + return plus_constant (mode, op0, offset); } } @@ -4948,9 +4941,11 @@ case VECTOR_CST: { - unsigned i, nelts; - - nelts = VECTOR_CST_NELTS (exp); + unsigned HOST_WIDE_INT i, nelts; + + if (!VECTOR_CST_NELTS (exp).is_constant (&nelts)) + return NULL; + op0 = gen_rtx_CONCATN (mode, rtvec_alloc (nelts)); for (i = 0; i < nelts; ++i) @@ -4970,10 +4965,13 @@ else if (TREE_CODE (TREE_TYPE (exp)) == VECTOR_TYPE) { unsigned i; + unsigned HOST_WIDE_INT nelts; tree val; - op0 = gen_rtx_CONCATN - (mode, rtvec_alloc (TYPE_VECTOR_SUBPARTS (TREE_TYPE (exp)))); + if (!TYPE_VECTOR_SUBPARTS (TREE_TYPE (exp)).is_constant (&nelts)) + goto flag_unsupported; + + op0 = gen_rtx_CONCATN (mode, rtvec_alloc (nelts)); FOR_EACH_CONSTRUCTOR_VALUE (CONSTRUCTOR_ELTS (exp), i, val) { @@ -4983,7 +4981,7 @@ XVECEXP (op0, 0, i) = op1; } - if (i < TYPE_VECTOR_SUBPARTS (TREE_TYPE (exp))) + if (i < nelts) { op1 = expand_debug_expr (build_zero_cst (TREE_TYPE (TREE_TYPE (exp)))); @@ -4991,7 +4989,7 @@ if (!op1) return NULL; - for (; i < TYPE_VECTOR_SUBPARTS (TREE_TYPE (exp)); i++) + for (; i < nelts; i++) XVECEXP (op0, 0, i) = op1; } @@ -5058,13 +5056,13 @@ /* Vector stuff. For most of the codes we don't have rtl codes. */ case REALIGN_LOAD_EXPR: - case REDUC_MAX_EXPR: - case REDUC_MIN_EXPR: - case REDUC_PLUS_EXPR: case VEC_COND_EXPR: case VEC_PACK_FIX_TRUNC_EXPR: + case VEC_PACK_FLOAT_EXPR: case VEC_PACK_SAT_EXPR: case VEC_PACK_TRUNC_EXPR: + case VEC_UNPACK_FIX_TRUNC_HI_EXPR: + case VEC_UNPACK_FIX_TRUNC_LO_EXPR: case VEC_UNPACK_FLOAT_HI_EXPR: case VEC_UNPACK_FLOAT_LO_EXPR: case VEC_UNPACK_HI_EXPR: @@ -5076,6 +5074,8 @@ case VEC_WIDEN_LSHIFT_HI_EXPR: case VEC_WIDEN_LSHIFT_LO_EXPR: case VEC_PERM_EXPR: + case VEC_DUPLICATE_EXPR: + case VEC_SERIES_EXPR: return NULL; /* Misc codes. */ @@ -5149,9 +5149,6 @@ } return NULL; - case FMA_EXPR: - return simplify_gen_ternary (FMA, mode, inner_mode, op0, op1, op2); - default: flag_unsupported: if (flag_checking) @@ -5174,6 +5171,10 @@ switch (TREE_CODE (exp)) { + case VAR_DECL: + if (DECL_ABSTRACT_ORIGIN (exp)) + return expand_debug_source_expr (DECL_ABSTRACT_ORIGIN (exp)); + break; case PARM_DECL: { mode = DECL_MODE (exp); @@ -5317,7 +5318,7 @@ flag_strict_aliasing = 0; for (insn = get_insns (); insn; insn = NEXT_INSN (insn)) - if (DEBUG_INSN_P (insn)) + if (DEBUG_BIND_INSN_P (insn)) { tree value = (tree)INSN_VAR_LOCATION_LOC (insn); rtx val; @@ -5464,7 +5465,7 @@ gimple_stmt_iterator gsi; gimple_seq stmts; gimple *stmt = NULL; - rtx_note *note; + rtx_note *note = NULL; rtx_insn *last; edge e; edge_iterator ei; @@ -5517,6 +5518,7 @@ if (stmt || elt) { + gcc_checking_assert (!note); last = get_last_insn (); if (stmt) @@ -5531,6 +5533,7 @@ BB_HEAD (bb) = NEXT_INSN (last); if (NOTE_P (BB_HEAD (bb))) BB_HEAD (bb) = NEXT_INSN (BB_HEAD (bb)); + gcc_assert (LABEL_P (BB_HEAD (bb))); note = emit_note_after (NOTE_INSN_BASIC_BLOCK, BB_HEAD (bb)); maybe_dump_rtl_for_gimple_stmt (stmt, last); @@ -5538,7 +5541,8 @@ else BB_HEAD (bb) = note = emit_note (NOTE_INSN_BASIC_BLOCK); - NOTE_BASIC_BLOCK (note) = bb; + if (note) + NOTE_BASIC_BLOCK (note) = bb; for (; !gsi_end_p (gsi); gsi_next (&gsi)) { @@ -5570,7 +5574,7 @@ a_2 = ... #DEBUG ... => #D1 */ - if (MAY_HAVE_DEBUG_INSNS + if (MAY_HAVE_DEBUG_BIND_INSNS && SA.values && !is_gimple_debug (stmt)) { @@ -5651,49 +5655,92 @@ if (new_bb) return new_bb; } - else if (gimple_debug_bind_p (stmt)) + else if (is_gimple_debug (stmt)) { location_t sloc = curr_insn_location (); gimple_stmt_iterator nsi = gsi; for (;;) { - tree var = gimple_debug_bind_get_var (stmt); - tree value; - rtx val; + tree var; + tree value = NULL_TREE; + rtx val = NULL_RTX; machine_mode mode; - if (TREE_CODE (var) != DEBUG_EXPR_DECL - && TREE_CODE (var) != LABEL_DECL - && !target_for_debug_bind (var)) + if (!gimple_debug_nonbind_marker_p (stmt)) + { + if (gimple_debug_bind_p (stmt)) + { + var = gimple_debug_bind_get_var (stmt); + + if (TREE_CODE (var) != DEBUG_EXPR_DECL + && TREE_CODE (var) != LABEL_DECL + && !target_for_debug_bind (var)) + goto delink_debug_stmt; + + if (DECL_P (var)) + mode = DECL_MODE (var); + else + mode = TYPE_MODE (TREE_TYPE (var)); + + if (gimple_debug_bind_has_value_p (stmt)) + value = gimple_debug_bind_get_value (stmt); + + val = gen_rtx_VAR_LOCATION + (mode, var, (rtx)value, VAR_INIT_STATUS_INITIALIZED); + } + else if (gimple_debug_source_bind_p (stmt)) + { + var = gimple_debug_source_bind_get_var (stmt); + + value = gimple_debug_source_bind_get_value (stmt); + + mode = DECL_MODE (var); + + val = gen_rtx_VAR_LOCATION (mode, var, (rtx)value, + VAR_INIT_STATUS_UNINITIALIZED); + } + else + gcc_unreachable (); + } + /* If this function was first compiled with markers + enabled, but they're now disable (e.g. LTO), drop + them on the floor. */ + else if (gimple_debug_nonbind_marker_p (stmt) + && !MAY_HAVE_DEBUG_MARKER_INSNS) goto delink_debug_stmt; - - if (gimple_debug_bind_has_value_p (stmt)) - value = gimple_debug_bind_get_value (stmt); + else if (gimple_debug_begin_stmt_p (stmt)) + val = GEN_RTX_DEBUG_MARKER_BEGIN_STMT_PAT (); + else if (gimple_debug_inline_entry_p (stmt)) + { + tree block = gimple_block (stmt); + + if (block) + val = GEN_RTX_DEBUG_MARKER_INLINE_ENTRY_PAT (); + else + goto delink_debug_stmt; + } else - value = NULL_TREE; + gcc_unreachable (); last = get_last_insn (); set_curr_insn_location (gimple_location (stmt)); - if (DECL_P (var)) - mode = DECL_MODE (var); - else - mode = TYPE_MODE (TREE_TYPE (var)); - - val = gen_rtx_VAR_LOCATION - (mode, var, (rtx)value, VAR_INIT_STATUS_INITIALIZED); - emit_debug_insn (val); if (dump_file && (dump_flags & TDF_DETAILS)) { /* We can't dump the insn with a TREE where an RTX is expected. */ - PAT_VAR_LOCATION_LOC (val) = const0_rtx; + if (GET_CODE (val) == VAR_LOCATION) + { + gcc_checking_assert (PAT_VAR_LOCATION_LOC (val) == (rtx)value); + PAT_VAR_LOCATION_LOC (val) = const0_rtx; + } maybe_dump_rtl_for_gimple_stmt (stmt, last); - PAT_VAR_LOCATION_LOC (val) = (rtx)value; + if (GET_CODE (val) == VAR_LOCATION) + PAT_VAR_LOCATION_LOC (val) = (rtx)value; } delink_debug_stmt: @@ -5709,42 +5756,12 @@ if (gsi_end_p (nsi)) break; stmt = gsi_stmt (nsi); - if (!gimple_debug_bind_p (stmt)) + if (!is_gimple_debug (stmt)) break; } set_curr_insn_location (sloc); } - else if (gimple_debug_source_bind_p (stmt)) - { - location_t sloc = curr_insn_location (); - tree var = gimple_debug_source_bind_get_var (stmt); - tree value = gimple_debug_source_bind_get_value (stmt); - rtx val; - machine_mode mode; - - last = get_last_insn (); - - set_curr_insn_location (gimple_location (stmt)); - - mode = DECL_MODE (var); - - val = gen_rtx_VAR_LOCATION (mode, var, (rtx)value, - VAR_INIT_STATUS_UNINITIALIZED); - - emit_debug_insn (val); - - if (dump_file && (dump_flags & TDF_DETAILS)) - { - /* We can't dump the insn with a TREE where an RTX - is expected. */ - PAT_VAR_LOCATION_LOC (val) = const0_rtx; - maybe_dump_rtl_for_gimple_stmt (stmt, last); - PAT_VAR_LOCATION_LOC (val) = (rtx)value; - } - - set_curr_insn_location (sloc); - } else { gcall *call_stmt = dyn_cast <gcall *> (stmt); @@ -5822,6 +5839,8 @@ last = PREV_INSN (last); if (JUMP_TABLE_DATA_P (last)) last = PREV_INSN (PREV_INSN (last)); + if (BARRIER_P (last)) + last = PREV_INSN (last); BB_END (bb) = last; update_bb_for_insn (bb); @@ -5863,7 +5882,6 @@ init_block = create_basic_block (NEXT_INSN (get_insns ()), get_last_insn (), ENTRY_BLOCK_PTR_FOR_FN (cfun)); - init_block->frequency = ENTRY_BLOCK_PTR_FOR_FN (cfun)->frequency; init_block->count = ENTRY_BLOCK_PTR_FOR_FN (cfun)->count; add_bb_to_loop (init_block, ENTRY_BLOCK_PTR_FOR_FN (cfun)->loop_father); if (e) @@ -5927,7 +5945,7 @@ while (NEXT_INSN (head) && NOTE_P (NEXT_INSN (head))) head = NEXT_INSN (head); /* But make sure exit_block starts with RETURN_LABEL, otherwise the - bb frequency counting will be confused. Any instructions before that + bb count counting will be confused. Any instructions before that label are emitted for the case where PREV_BB falls through into the exit block, so append those instructions to prev_bb in that case. */ if (NEXT_INSN (head) != return_label) @@ -5940,7 +5958,6 @@ } } exit_block = create_basic_block (NEXT_INSN (head), end, prev_bb); - exit_block->frequency = EXIT_BLOCK_PTR_FOR_FN (cfun)->frequency; exit_block->count = EXIT_BLOCK_PTR_FOR_FN (cfun)->count; add_bb_to_loop (exit_block, EXIT_BLOCK_PTR_FOR_FN (cfun)->loop_father); @@ -5960,10 +5977,7 @@ if (e2 != e) { exit_block->count -= e2->count (); - exit_block->frequency -= EDGE_FREQUENCY (e2); } - if (exit_block->frequency < 0) - exit_block->frequency = 0; update_bb_for_insn (exit_block); } @@ -6092,7 +6106,7 @@ gcc_assert ((stack_realign_drap != 0) == (drap_rtx != NULL)); /* Do nothing if NULL is returned, which means DRAP is not needed. */ - if (NULL != drap_rtx) + if (drap_rtx != NULL) { crtl->args.internal_arg_pointer = drap_rtx; @@ -6196,7 +6210,7 @@ timevar_pop (TV_OUT_OF_SSA); SA.partition_to_pseudo = XCNEWVEC (rtx, SA.map->num_partitions); - if (MAY_HAVE_DEBUG_STMTS && flag_tree_ter) + if (MAY_HAVE_DEBUG_BIND_STMTS && flag_tree_ter) { gimple_stmt_iterator gsi; FOR_EACH_BB_FN (bb, cfun) @@ -6216,9 +6230,6 @@ rtl_profile_for_bb (ENTRY_BLOCK_PTR_FOR_FN (fun)); - if (chkp_function_instrumented_p (current_function_decl)) - chkp_reset_rtl_bounds (); - insn_locations_init (); if (!DECL_IS_BUILTIN (current_function_decl)) { @@ -6382,12 +6393,17 @@ FOR_EACH_EDGE (e, ei, ENTRY_BLOCK_PTR_FOR_FN (fun)->succs) e->flags &= ~EDGE_EXECUTABLE; + /* If the function has too many markers, drop them while expanding. */ + if (cfun->debug_marker_count + >= PARAM_VALUE (PARAM_MAX_DEBUG_MARKER_COUNT)) + cfun->debug_nonbind_markers = false; + lab_rtx_for_bb = new hash_map<basic_block, rtx_code_label *>; FOR_BB_BETWEEN (bb, init_block->next_bb, EXIT_BLOCK_PTR_FOR_FN (fun), next_bb) bb = expand_gimple_basic_block (bb, var_ret_seq != NULL_RTX); - if (MAY_HAVE_DEBUG_INSNS) + if (MAY_HAVE_DEBUG_BIND_INSNS) expand_debug_locations (); if (deep_ter_debug_map)