diff options
Diffstat (limited to 'gcc/stmt.c')
-rw-r--r-- | gcc/stmt.c | 150 |
1 files changed, 95 insertions, 55 deletions
diff --git a/gcc/stmt.c b/gcc/stmt.c index f283b7590c6..9800ee8306b 100644 --- a/gcc/stmt.c +++ b/gcc/stmt.c @@ -541,10 +541,23 @@ expand_computed_goto (exp) #endif emit_queue (); - do_pending_stack_adjust (); - emit_indirect_jump (x); - current_function_has_computed_jump = 1; + if (! cfun->computed_goto_common_label) + { + cfun->computed_goto_common_reg = copy_to_mode_reg (Pmode, x); + cfun->computed_goto_common_label = gen_label_rtx (); + emit_label (cfun->computed_goto_common_label); + + do_pending_stack_adjust (); + emit_indirect_jump (cfun->computed_goto_common_reg); + + current_function_has_computed_jump = 1; + } + else + { + emit_move_insn (cfun->computed_goto_common_reg, x); + emit_jump (cfun->computed_goto_common_label); + } } /* Handle goto statements and the labels that they can go to. */ @@ -1107,18 +1120,26 @@ n_occurrences (c, s) } /* Generate RTL for an asm statement (explicit assembler code). - BODY is a STRING_CST node containing the assembler code text, - or an ADDR_EXPR containing a STRING_CST. */ + STRING is a STRING_CST node containing the assembler code text, + or an ADDR_EXPR containing a STRING_CST. VOL nonzero means the + insn is volatile; don't optimize it. */ void -expand_asm (body) - tree body; +expand_asm (string, vol) + tree string; + int vol; { - if (TREE_CODE (body) == ADDR_EXPR) - body = TREE_OPERAND (body, 0); + rtx body; + + if (TREE_CODE (string) == ADDR_EXPR) + string = TREE_OPERAND (string, 0); - emit_insn (gen_rtx_ASM_INPUT (VOIDmode, - TREE_STRING_POINTER (body))); + body = gen_rtx_ASM_INPUT (VOIDmode, TREE_STRING_POINTER (string)); + + MEM_VOLATILE_P (body) = vol; + + emit_insn (body); + clear_last_expr (); } @@ -1597,6 +1618,7 @@ expand_asm_operands (string, outputs, inputs, clobbers, vol, filename, line) bool is_inout; bool allows_reg; bool allows_mem; + rtx op; if (!parse_output_constraint (&constraints[i], i, ninputs, noutputs, &allows_mem, &allows_reg, @@ -1620,24 +1642,28 @@ expand_asm_operands (string, outputs, inputs, clobbers, vol, filename, line) || ! allows_reg || is_inout) { - output_rtx[i] = expand_expr (val, NULL_RTX, VOIDmode, EXPAND_WRITE); + op = expand_expr (val, NULL_RTX, VOIDmode, EXPAND_WRITE); + if (GET_CODE (op) == MEM) + op = validize_mem (op); - if (! allows_reg && GET_CODE (output_rtx[i]) != MEM) + if (! allows_reg && GET_CODE (op) != MEM) error ("output number %d not directly addressable", i); - if ((! allows_mem && GET_CODE (output_rtx[i]) == MEM) - || GET_CODE (output_rtx[i]) == CONCAT) + if ((! allows_mem && GET_CODE (op) == MEM) + || GET_CODE (op) == CONCAT) { - real_output_rtx[i] = protect_from_queue (output_rtx[i], 1); - output_rtx[i] = gen_reg_rtx (GET_MODE (output_rtx[i])); + real_output_rtx[i] = protect_from_queue (op, 1); + op = gen_reg_rtx (GET_MODE (op)); if (is_inout) - emit_move_insn (output_rtx[i], real_output_rtx[i]); + emit_move_insn (op, real_output_rtx[i]); } } else { - output_rtx[i] = assign_temp (type, 0, 0, 1); - TREE_VALUE (tail) = make_tree (type, output_rtx[i]); + op = assign_temp (type, 0, 0, 1); + op = validize_mem (op); + TREE_VALUE (tail) = make_tree (type, op); } + output_rtx[i] = op; generating_concat_p = old_generating_concat_p; @@ -1684,11 +1710,15 @@ expand_asm_operands (string, outputs, inputs, clobbers, vol, filename, line) val = TREE_VALUE (tail); type = TREE_TYPE (val); - op = expand_expr (val, NULL_RTX, VOIDmode, 0); + op = expand_expr (val, NULL_RTX, VOIDmode, + (allows_mem && !allows_reg + ? EXPAND_MEMORY : EXPAND_NORMAL)); /* Never pass a CONCAT to an ASM. */ if (GET_CODE (op) == CONCAT) op = force_reg (GET_MODE (op), op); + else if (GET_CODE (op) == MEM) + op = validize_mem (op); if (asm_operand_ok (op, constraint) <= 0) { @@ -1697,35 +1727,36 @@ expand_asm_operands (string, outputs, inputs, clobbers, vol, filename, line) else if (!allows_mem) warning ("asm operand %d probably doesn't match constraints", i + noutputs); - else if (CONSTANT_P (op)) - op = force_const_mem (TYPE_MODE (type), op); - else if (GET_CODE (op) == REG - || GET_CODE (op) == SUBREG - || GET_CODE (op) == ADDRESSOF - || GET_CODE (op) == CONCAT) + else if (GET_CODE (op) == MEM) { - tree qual_type = build_qualified_type (type, - (TYPE_QUALS (type) - | TYPE_QUAL_CONST)); - rtx memloc = assign_temp (qual_type, 1, 1, 1); - - emit_move_insn (memloc, op); - op = memloc; + /* We won't recognize either volatile memory or memory + with a queued address as available a memory_operand + at this point. Ignore it: clearly this *is* a memory. */ } - - else if (GET_CODE (op) == MEM && MEM_VOLATILE_P (op)) + else { - /* We won't recognize volatile memory as available a - memory_operand at this point. Ignore it. */ + warning ("use of memory input without lvalue in " + "asm operand %d is deprecated", i + noutputs); + + if (CONSTANT_P (op)) + { + op = force_const_mem (TYPE_MODE (type), op); + op = validize_mem (op); + } + else if (GET_CODE (op) == REG + || GET_CODE (op) == SUBREG + || GET_CODE (op) == ADDRESSOF + || GET_CODE (op) == CONCAT) + { + tree qual_type = build_qualified_type (type, + (TYPE_QUALS (type) + | TYPE_QUAL_CONST)); + rtx memloc = assign_temp (qual_type, 1, 1, 1); + memloc = validize_mem (memloc); + emit_move_insn (memloc, op); + op = memloc; + } } - else if (queued_subexp_p (op)) - ; - else - /* ??? Leave this only until we have experience with what - happens in combine and elsewhere when constraints are - not satisfied. */ - warning ("asm operand %d probably doesn't match constraints", - i + noutputs); } generating_concat_p = old_generating_concat_p; @@ -2735,8 +2766,11 @@ expand_continue_loop (whichloop) /* Emit information for branch prediction. */ rtx note; - note = emit_note (NULL, NOTE_INSN_PREDICTION); - NOTE_PREDICTION (note) = NOTE_PREDICT (PRED_CONTINUE, IS_TAKEN); + if (flag_guess_branch_prob) + { + note = emit_note (NULL, NOTE_INSN_PREDICTION); + NOTE_PREDICTION (note) = NOTE_PREDICT (PRED_CONTINUE, IS_TAKEN); + } clear_last_expr (); if (whichloop == 0) whichloop = loop_stack; @@ -2929,7 +2963,8 @@ expand_value_return (val) rtx return_reg; enum br_predictor pred; - if ((pred = return_prediction (val)) != PRED_NO_PREDICTION) + if (flag_guess_branch_prob + && (pred = return_prediction (val)) != PRED_NO_PREDICTION) { /* Emit information for branch prediction. */ rtx note; @@ -3312,15 +3347,15 @@ tail_recursion_args (actuals, formals) else { rtx tmp = argvec[i]; - + int unsignedp = TREE_UNSIGNED (TREE_TYPE (TREE_VALUE (a))); + promote_mode(TREE_TYPE (TREE_VALUE (a)), GET_MODE (tmp), + &unsignedp, 0); if (DECL_MODE (f) != GET_MODE (DECL_RTL (f))) { tmp = gen_reg_rtx (DECL_MODE (f)); - convert_move (tmp, argvec[i], - TREE_UNSIGNED (TREE_TYPE (TREE_VALUE (a)))); + convert_move (tmp, argvec[i], unsignedp); } - convert_move (DECL_RTL (f), tmp, - TREE_UNSIGNED (TREE_TYPE (TREE_VALUE (a)))); + convert_move (DECL_RTL (f), tmp, unsignedp); } } @@ -3887,6 +3922,7 @@ expand_decl (decl) && !(flag_float_store && TREE_CODE (type) == REAL_TYPE) && ! TREE_THIS_VOLATILE (decl) + && ! DECL_NONLOCAL (decl) && (DECL_REGISTER (decl) || optimize)) { /* Automatic variable that can go in a register. */ @@ -3914,7 +3950,7 @@ expand_decl (decl) /* If something wants our address, try to use ADDRESSOF. */ if (TREE_ADDRESSABLE (decl)) - put_var_into_stack (decl); + put_var_into_stack (decl, /*rescan=*/false); } else if (TREE_CODE (DECL_SIZE_UNIT (decl)) == INTEGER_CST @@ -4014,6 +4050,8 @@ expand_decl_init (decl) /* Compute and store the initial value now. */ + push_temp_slots (); + if (DECL_INITIAL (decl) == error_mark_node) { enum tree_code code = TREE_CODE (TREE_TYPE (decl)); @@ -4037,6 +4075,7 @@ expand_decl_init (decl) /* Free any temporaries we made while initializing the decl. */ preserve_temp_slots (NULL_RTX); free_temp_slots (); + pop_temp_slots (); } /* CLEANUP is an expression to be executed at exit from this binding contour; @@ -4417,6 +4456,7 @@ expand_start_case (exit_flag, expr, type, printname) nesting_stack = thiscase; do_pending_stack_adjust (); + emit_queue (); /* Make sure case_stmt.start points to something that won't need any transformation before expand_end_case. */ |