diff options
Diffstat (limited to 'gcc/calls.c')
-rw-r--r-- | gcc/calls.c | 71 |
1 files changed, 58 insertions, 13 deletions
diff --git a/gcc/calls.c b/gcc/calls.c index 7186611..2163e51 100644 --- a/gcc/calls.c +++ b/gcc/calls.c @@ -219,7 +219,8 @@ static rtx rtx_for_function_call PARAMS ((tree, tree)); static void load_register_parameters PARAMS ((struct arg_data *, int, rtx *, int)); static int libfunc_nothrow PARAMS ((rtx)); -static rtx emit_library_call_value_1 PARAMS ((int, rtx, rtx, int, +static rtx emit_library_call_value_1 PARAMS ((int, rtx, rtx, + enum libcall_type, enum machine_mode, int, va_list)); static int special_function_p PARAMS ((tree, int)); @@ -1678,9 +1679,8 @@ rtx_for_function_call (fndecl, exp) that this seems safer. */ funaddr = convert_memory_address (Pmode, funexp); #endif - emit_library_call (chkr_check_exec_libfunc, 1, - VOIDmode, 1, - funaddr, Pmode); + emit_library_call (chkr_check_exec_libfunc, LCT_CONST_MAKE_BLOCK, + VOIDmode, 1, funaddr, Pmode); } emit_queue (); } @@ -3026,7 +3026,7 @@ expand_call (exp, target, ignore) /* Mark the memory for the aggregate as write-only. */ if (current_function_check_memory_usage) - emit_library_call (chkr_set_right_libfunc, 1, + emit_library_call (chkr_set_right_libfunc, LCT_CONST_MAKE_BLOCK, VOIDmode, 3, structure_value_addr, ptr_mode, GEN_INT (struct_value_size), @@ -3465,7 +3465,7 @@ emit_library_call_value_1 (retval, orgfun, value, fn_type, outmode, nargs, p) int retval; rtx orgfun; rtx value; - int fn_type; + enum libcall_type fn_type; enum machine_mode outmode; int nargs; va_list p; @@ -3521,9 +3521,9 @@ emit_library_call_value_1 (retval, orgfun, value, fn_type, outmode, nargs, p) #endif #endif - if (fn_type == 1) + if (fn_type == LCT_CONST_MAKE_BLOCK) flags |= ECF_CONST; - else if (fn_type == 2) + else if (fn_type == LCT_PURE_MAKE_BLOCK) flags |= ECF_PURE; fun = orgfun; @@ -3580,6 +3580,11 @@ emit_library_call_value_1 (retval, orgfun, value, fn_type, outmode, nargs, p) count = 0; + /* Now we are about to start emitting insns that can be deleted + if a libcall is deleted. */ + if (flags & (ECF_CONST | ECF_PURE)) + start_sequence (); + push_temp_slots (); /* If there's a structure value address to be passed, @@ -4017,6 +4022,45 @@ emit_library_call_value_1 (retval, orgfun, value, fn_type, outmode, nargs, p) /* Now restore inhibit_defer_pop to its actual original value. */ OK_DEFER_POP; + /* If call is cse'able, make appropriate pair of reg-notes around it. + Test valreg so we don't crash; may safely ignore `const' + if return type is void. Disable for PARALLEL return values, because + we have no way to move such values into a pseudo register. */ + if ((flags & (ECF_CONST | ECF_PURE)) + && valreg != 0 && GET_CODE (valreg) != PARALLEL) + { + rtx note = 0; + rtx temp = gen_reg_rtx (GET_MODE (valreg)); + rtx insns; + int i; + + /* Construct an "equal form" for the value which mentions all the + arguments in order as well as the function name. */ + for (i = 0; i < nargs; i++) + note = gen_rtx_EXPR_LIST (VOIDmode, argvec[i].value, note); + note = gen_rtx_EXPR_LIST (VOIDmode, fun, note); + + insns = get_insns (); + end_sequence (); + + if (flags & ECF_PURE) + note = gen_rtx_EXPR_LIST (VOIDmode, + gen_rtx_USE (VOIDmode, + gen_rtx_MEM (BLKmode, + gen_rtx_SCRATCH (VOIDmode))), note); + + emit_libcall_block (insns, temp, valreg, note); + + valreg = temp; + } + else if (flags & (ECF_CONST | ECF_PURE)) + { + /* Otherwise, just write out the sequence without a note. */ + rtx insns = get_insns (); + + end_sequence (); + emit_insns (insns); + } pop_temp_slots (); /* Copy the value to the right place. */ @@ -4098,8 +4142,8 @@ emit_library_call_value_1 (retval, orgfun, value, fn_type, outmode, nargs, p) (use (memory (scratch)). */ void -emit_library_call VPARAMS((rtx orgfun, int fn_type, enum machine_mode outmode, - int nargs, ...)) +emit_library_call VPARAMS((rtx orgfun, enum libcall_type fn_type, + enum machine_mode outmode, int nargs, ...)) { #ifndef ANSI_PROTOTYPES rtx orgfun; @@ -4132,7 +4176,8 @@ emit_library_call VPARAMS((rtx orgfun, int fn_type, enum machine_mode outmode, If VALUE is nonzero, VALUE is returned. */ rtx -emit_library_call_value VPARAMS((rtx orgfun, rtx value, int fn_type, +emit_library_call_value VPARAMS((rtx orgfun, rtx value, + enum libcall_type fn_type, enum machine_mode outmode, int nargs, ...)) { #ifndef ANSI_PROTOTYPES @@ -4376,8 +4421,8 @@ store_one_arg (arg, argblock, flags, variable_size, reg_parm_stack_space) /* If the value is already in the stack slot, we are done. */ if (current_function_check_memory_usage && GET_CODE (arg->stack) == MEM) { - emit_library_call (chkr_set_right_libfunc, 1, VOIDmode, 3, - XEXP (arg->stack, 0), Pmode, + emit_library_call (chkr_set_right_libfunc, LCT_CONST_MAKE_BLOCK, + VOIDmode, 3, XEXP (arg->stack, 0), Pmode, ARGS_SIZE_RTX (arg->size), TYPE_MODE (sizetype), GEN_INT (MEMORY_USE_RW), |