Mercurial > hg > CbC > CbC_gcc
diff gcc/explow.c @ 131:84e7813d76e9
gcc-8.2
author | mir3636 |
---|---|
date | Thu, 25 Oct 2018 07:37:49 +0900 |
parents | 04ced10e8804 |
children | 1830386684a0 |
line wrap: on
line diff
--- a/gcc/explow.c Fri Oct 27 22:46:09 2017 +0900 +++ b/gcc/explow.c Thu Oct 25 07:37:49 2018 +0900 @@ -1,5 +1,5 @@ /* Subroutines for manipulating rtx's in semantically interesting ways. - Copyright (C) 1987-2017 Free Software Foundation, Inc. + Copyright (C) 1987-2018 Free Software Foundation, Inc. This file is part of GCC. @@ -56,8 +56,7 @@ int width = GET_MODE_PRECISION (smode); /* You want to truncate to a _what_? */ - gcc_assert (SCALAR_INT_MODE_P (mode) - || POINTER_BOUNDS_MODE_P (mode)); + gcc_assert (SCALAR_INT_MODE_P (mode)); /* Canonicalize BImode to 0 and STORE_FLAG_VALUE. */ if (smode == BImode) @@ -77,13 +76,23 @@ return c; } +/* Likewise for polynomial values, using the sign-extended representation + for each individual coefficient. */ + +poly_int64 +trunc_int_for_mode (poly_int64 x, machine_mode mode) +{ + for (unsigned int i = 0; i < NUM_POLY_INT_COEFFS; ++i) + x.coeffs[i] = trunc_int_for_mode (x.coeffs[i], mode); + return x; +} + /* Return an rtx for the sum of X and the integer C, given that X has mode MODE. INPLACE is true if X can be modified inplace or false if it must be treated as immutable. */ rtx -plus_constant (machine_mode mode, rtx x, HOST_WIDE_INT c, - bool inplace) +plus_constant (machine_mode mode, rtx x, poly_int64 c, bool inplace) { RTX_CODE code; rtx y; @@ -92,7 +101,7 @@ gcc_assert (GET_MODE (x) == VOIDmode || GET_MODE (x) == mode); - if (c == 0) + if (known_eq (c, 0)) return x; restart: @@ -180,10 +189,12 @@ break; default: + if (CONST_POLY_INT_P (x)) + return immed_wide_int_const (const_poly_int_value (x) + c, mode); break; } - if (c != 0) + if (maybe_ne (c, 0)) x = gen_rtx_PLUS (mode, x, gen_int_mode (c, mode)); if (GET_CODE (x) == SYMBOL_REF || GET_CODE (x) == LABEL_REF) @@ -210,8 +221,8 @@ /* First handle constants appearing at this level explicitly. */ if (CONST_INT_P (XEXP (x, 1)) - && 0 != (tem = simplify_binary_operation (PLUS, GET_MODE (x), *constptr, - XEXP (x, 1))) + && (tem = simplify_binary_operation (PLUS, GET_MODE (x), *constptr, + XEXP (x, 1))) != 0 && CONST_INT_P (tem)) { *constptr = tem; @@ -222,8 +233,8 @@ x0 = eliminate_constant_term (XEXP (x, 0), &tem); x1 = eliminate_constant_term (XEXP (x, 1), &tem); if ((x1 != XEXP (x, 1) || x0 != XEXP (x, 0)) - && 0 != (tem = simplify_binary_operation (PLUS, GET_MODE (x), - *constptr, tem)) + && (tem = simplify_binary_operation (PLUS, GET_MODE (x), + *constptr, tem)) != 0 && CONST_INT_P (tem)) { *constptr = tem; @@ -929,7 +940,7 @@ } if (!suppress_reg_args_size) - add_reg_note (insn, REG_ARGS_SIZE, GEN_INT (stack_pointer_delta)); + add_args_size_note (insn, stack_pointer_delta); } /* Adjust the stack pointer by ADJUST (an rtx for a number of bytes). @@ -943,8 +954,9 @@ /* We expect all variable sized adjustments to be multiple of PREFERRED_STACK_BOUNDARY. */ - if (CONST_INT_P (adjust)) - stack_pointer_delta -= INTVAL (adjust); + poly_int64 const_adjust; + if (poly_int_rtx_p (adjust, &const_adjust)) + stack_pointer_delta -= const_adjust; adjust_stack_1 (adjust, false); } @@ -960,8 +972,9 @@ /* We expect all variable sized adjustments to be multiple of PREFERRED_STACK_BOUNDARY. */ - if (CONST_INT_P (adjust)) - stack_pointer_delta += INTVAL (adjust); + poly_int64 const_adjust; + if (poly_int_rtx_p (adjust, &const_adjust)) + stack_pointer_delta += const_adjust; adjust_stack_1 (adjust, true); } @@ -1206,7 +1219,6 @@ unsigned required_align, HOST_WIDE_INT *pstack_usage_size) { - unsigned extra = 0; rtx size = *psize; /* Ensure the size is in the proper mode. */ @@ -1242,16 +1254,16 @@ example), so we must preventively align the value. We leave space in SIZE for the hole that might result from the alignment operation. */ - /* Since the stack is presumed to be aligned before this allocation, - we only need to increase the size of the allocation if the required - alignment is more than the stack alignment. */ - if (required_align > STACK_BOUNDARY) + unsigned known_align = REGNO_POINTER_ALIGN (VIRTUAL_STACK_DYNAMIC_REGNUM); + if (known_align == 0) + known_align = BITS_PER_UNIT; + if (required_align > known_align) { - extra = (required_align - STACK_BOUNDARY) / BITS_PER_UNIT; + unsigned extra = (required_align - known_align) / BITS_PER_UNIT; size = plus_constant (Pmode, size, extra); size = force_operand (size, NULL_RTX); - if (size_align > STACK_BOUNDARY) - size_align = STACK_BOUNDARY; + if (size_align > known_align) + size_align = known_align; if (flag_stack_usage_info && pstack_usage_size) *pstack_usage_size += extra; @@ -1464,8 +1476,8 @@ /* We ought to be called always on the toplevel and stack ought to be aligned properly. */ - gcc_assert (!(stack_pointer_delta - % (PREFERRED_STACK_BOUNDARY / BITS_PER_UNIT))); + gcc_assert (multiple_p (stack_pointer_delta, + PREFERRED_STACK_BOUNDARY / BITS_PER_UNIT)); /* If needed, check that we have the required amount of stack. Take into account what has already been checked. */ @@ -1495,7 +1507,7 @@ } else { - int saved_stack_pointer_delta; + poly_int64 saved_stack_pointer_delta; if (!STACK_GROWS_DOWNWARD) emit_move_insn (target, virtual_stack_dynamic_rtx); @@ -1576,7 +1588,7 @@ of memory. */ rtx -get_dynamic_stack_base (HOST_WIDE_INT offset, unsigned required_align) +get_dynamic_stack_base (poly_int64 offset, unsigned required_align) { rtx target; @@ -1615,18 +1627,25 @@ emit_stack_probe (rtx address) { if (targetm.have_probe_stack_address ()) - emit_insn (targetm.gen_probe_stack_address (address)); + { + struct expand_operand ops[1]; + insn_code icode = targetm.code_for_probe_stack_address; + create_address_operand (ops, address); + maybe_legitimize_operands (icode, 0, 1, ops); + expand_insn (icode, 1, ops); + } else { rtx memref = gen_rtx_MEM (word_mode, address); MEM_VOLATILE_P (memref) = 1; + memref = validize_mem (memref); /* See if we have an insn to probe the stack. */ if (targetm.have_probe_stack ()) - emit_insn (targetm.gen_probe_stack (memref)); + emit_insn (targetm.gen_probe_stack (memref)); else - emit_move_insn (memref, const0_rtx); + emit_move_insn (memref, const0_rtx); } } @@ -1939,10 +1958,21 @@ /* We can get here with a constant size on some targets. */ rtx rounded_size, last_addr, residual; - HOST_WIDE_INT probe_interval; + HOST_WIDE_INT probe_interval, probe_range; + bool target_probe_range_p = false; compute_stack_clash_protection_loop_data (&rounded_size, &last_addr, &residual, &probe_interval, size); + /* Get the back-end specific probe ranges. */ + probe_range = targetm.stack_clash_protection_alloca_probe_range (); + target_probe_range_p = probe_range != 0; + gcc_assert (probe_range >= 0); + + /* If no back-end specific range defined, default to the top of the newly + allocated range. */ + if (probe_range == 0) + probe_range = probe_interval - GET_MODE_SIZE (word_mode); + if (rounded_size != CONST0_RTX (Pmode)) { if (CONST_INT_P (rounded_size) @@ -1953,13 +1983,12 @@ i += probe_interval) { anti_adjust_stack (GEN_INT (probe_interval)); - /* The prologue does not probe residuals. Thus the offset here to probe just beyond what the prologue had already allocated. */ emit_stack_probe (plus_constant (Pmode, stack_pointer_rtx, - (probe_interval - - GET_MODE_SIZE (word_mode)))); + probe_range)); + emit_insn (gen_blockage ()); } } @@ -1973,10 +2002,10 @@ anti_adjust_stack (GEN_INT (probe_interval)); /* The prologue does not probe residuals. Thus the offset here - to probe just beyond what the prologue had already allocated. */ + to probe just beyond what the prologue had already + allocated. */ emit_stack_probe (plus_constant (Pmode, stack_pointer_rtx, - (probe_interval - - GET_MODE_SIZE (word_mode)))); + probe_range)); emit_stack_clash_protection_probe_loop_end (loop_lab, end_loop, last_addr, rotate_loop); @@ -1986,35 +2015,60 @@ if (residual != CONST0_RTX (Pmode)) { - rtx x = force_reg (Pmode, plus_constant (Pmode, residual, - -GET_MODE_SIZE (word_mode))); + rtx label = NULL_RTX; + /* RESIDUAL could be zero at runtime and in that case *sp could + hold live data. Furthermore, we do not want to probe into the + red zone. + + If TARGET_PROBE_RANGE_P then the target has promised it's safe to + probe at offset 0. In which case we no longer have to check for + RESIDUAL == 0. However we still need to probe at the right offset + when RESIDUAL > PROBE_RANGE, in which case we probe at PROBE_RANGE. + + If !TARGET_PROBE_RANGE_P then go ahead and just guard the probe at *sp + on RESIDUAL != 0 at runtime if RESIDUAL is not a compile time constant. + */ anti_adjust_stack (residual); - emit_stack_probe (gen_rtx_PLUS (Pmode, stack_pointer_rtx, x)); - emit_insn (gen_blockage ()); - } - /* Some targets make optimistic assumptions in their prologues about - how the caller may have probed the stack. Make sure we honor - those assumptions when needed. */ - if (size != CONST0_RTX (Pmode) - && targetm.stack_clash_protection_final_dynamic_probe (residual)) - { - /* Ideally we would just probe at *sp. However, if SIZE is not - a compile-time constant, but is zero at runtime, then *sp - might hold live data. So probe at *sp if we know that - an allocation was made, otherwise probe into the red zone - which is obviously undesirable. */ - if (CONST_INT_P (size)) + if (!CONST_INT_P (residual)) { - emit_stack_probe (stack_pointer_rtx); - emit_insn (gen_blockage ()); + label = gen_label_rtx (); + rtx_code op = target_probe_range_p ? LT : EQ; + rtx probe_cmp_value = target_probe_range_p + ? gen_rtx_CONST_INT (GET_MODE (residual), probe_range) + : CONST0_RTX (GET_MODE (residual)); + + if (target_probe_range_p) + emit_stack_probe (stack_pointer_rtx); + + emit_cmp_and_jump_insns (residual, probe_cmp_value, + op, NULL_RTX, Pmode, 1, label); + } + + rtx x = NULL_RTX; + + /* If RESIDUAL isn't a constant and TARGET_PROBE_RANGE_P then we probe up + by the ABI defined safe value. */ + if (!CONST_INT_P (residual) && target_probe_range_p) + x = GEN_INT (probe_range); + /* If RESIDUAL is a constant but smaller than the ABI defined safe value, + we still want to probe up, but the safest amount if a word. */ + else if (target_probe_range_p) + { + if (INTVAL (residual) <= probe_range) + x = GEN_INT (GET_MODE_SIZE (word_mode)); + else + x = GEN_INT (probe_range); } else - { - emit_stack_probe (plus_constant (Pmode, stack_pointer_rtx, - -GET_MODE_SIZE (word_mode))); - emit_insn (gen_blockage ()); - } + /* If nothing else, probe at the top of the new allocation. */ + x = plus_constant (Pmode, residual, -GET_MODE_SIZE (word_mode)); + + emit_stack_probe (gen_rtx_PLUS (Pmode, stack_pointer_rtx, x)); + + emit_insn (gen_blockage ()); + if (!CONST_INT_P (residual)) + emit_label (label); } } @@ -2166,7 +2220,7 @@ if (REG_P (val) && GET_MODE (val) == BLKmode) { - unsigned HOST_WIDE_INT bytes = int_size_in_bytes (valtype); + unsigned HOST_WIDE_INT bytes = arg_int_size_in_bytes (valtype); opt_scalar_int_mode tmpmode; /* int_size_in_bytes can return -1. We don't need a check here