diff options
author | Roger Sayle <roger@eyesopen.com> | 2003-08-26 00:09:10 +0000 |
---|---|---|
committer | Roger Sayle <sayle@gcc.gnu.org> | 2003-08-26 00:09:10 +0000 |
commit | 8634629b6f3e9a316e4ef83685e3c36068d6a0c1 (patch) | |
tree | 267b0d3325e69e819d855522539d14770832fe00 | |
parent | 0961802f7eb8343c55cd29946985600f646879d3 (diff) | |
download | gcc-8634629b6f3e9a316e4ef83685e3c36068d6a0c1.zip gcc-8634629b6f3e9a316e4ef83685e3c36068d6a0c1.tar.gz gcc-8634629b6f3e9a316e4ef83685e3c36068d6a0c1.tar.bz2 |
builtins.c (expand_builtin_mathfn): Rearrange so that we only return 0 for invalid argument types.
* builtins.c (expand_builtin_mathfn): Rearrange so that we only
return 0 for invalid argument types. Instead drop through to a
call of expand_call at the bottom of function. If op is SQRT,
try attaching a SQRT rtx as the REQ_EQUAL note of the libcall.
From-SVN: r70792
-rw-r--r-- | gcc/ChangeLog | 7 | ||||
-rw-r--r-- | gcc/builtins.c | 108 |
2 files changed, 83 insertions, 32 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index f004265..24a3f58 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,10 @@ +2003-08-25 Roger Sayle <roger@eyesopen.com> + + * builtins.c (expand_builtin_mathfn): Rearrange so that we only + return 0 for invalid argument types. Instead drop through to a + call of expand_call at the bottom of function. If op is SQRT, + try attaching a SQRT rtx as the REQ_EQUAL note of the libcall. + 2003-08-25 Richard Henderson <rth@redhat.com> * config/ia64/ia64.c (ia64_expand_tls_address): Properly truncate diff --git a/gcc/builtins.c b/gcc/builtins.c index 10e9a2c..dc999f7 100644 --- a/gcc/builtins.c +++ b/gcc/builtins.c @@ -1565,7 +1565,7 @@ static rtx expand_builtin_mathfn (tree exp, rtx target, rtx subtarget) { optab builtin_optab; - rtx op0, insns; + rtx op0, insns, before_call; tree fndecl = get_callee_fndecl (exp); tree arglist = TREE_OPERAND (exp, 1); enum machine_mode mode; @@ -1636,49 +1636,93 @@ expand_builtin_mathfn (tree exp, rtx target, rtx subtarget) /* Make a suitable register to place result in. */ mode = TYPE_MODE (TREE_TYPE (exp)); - /* Before working hard, check whether the instruction is available. */ - if (builtin_optab->handlers[(int) mode].insn_code == CODE_FOR_nothing) - return 0; - target = gen_reg_rtx (mode); - if (! flag_errno_math || ! HONOR_NANS (mode)) errno_set = false; - /* Wrap the computation of the argument in a SAVE_EXPR, as we may - need to expand the argument again. This way, we will not perform - side-effects more the once. */ - narg = save_expr (arg); - if (narg != arg) + /* Before working hard, check whether the instruction is available. */ + if (builtin_optab->handlers[(int) mode].insn_code != CODE_FOR_nothing) { - arglist = build_tree_list (NULL_TREE, arg); - exp = build_function_call_expr (fndecl, arglist); - } + target = gen_reg_rtx (mode); - op0 = expand_expr (arg, subtarget, VOIDmode, 0); + /* Wrap the computation of the argument in a SAVE_EXPR, as we may + need to expand the argument again. This way, we will not perform + side-effects more the once. */ + narg = save_expr (arg); + if (narg != arg) + { + arglist = build_tree_list (NULL_TREE, arg); + exp = build_function_call_expr (fndecl, arglist); + } - emit_queue (); - start_sequence (); + op0 = expand_expr (arg, subtarget, VOIDmode, 0); - /* Compute into TARGET. - Set TARGET to wherever the result comes back. */ - target = expand_unop (mode, builtin_optab, op0, target, 0); + emit_queue (); + start_sequence (); - /* If we were unable to expand via the builtin, stop the sequence - (without outputting the insns) and call to the library function - with the stabilized argument list. */ - if (target == 0) - { + /* Compute into TARGET. + Set TARGET to wherever the result comes back. */ + target = expand_unop (mode, builtin_optab, op0, target, 0); + + if (target != 0) + { + if (errno_set) + expand_errno_check (exp, target); + + /* Output the entire sequence. */ + insns = get_insns (); + end_sequence (); + emit_insn (insns); + return target; + } + + /* If we were unable to expand via the builtin, stop the sequence + (without outputting the insns) and call to the library function + with the stabilized argument list. */ end_sequence (); - return expand_call (exp, target, target == const0_rtx); } - if (errno_set) - expand_errno_check (exp, target); + before_call = get_last_insn (); - /* Output the entire sequence. */ - insns = get_insns (); - end_sequence (); - emit_insn (insns); + target = expand_call (exp, target, target == const0_rtx); + + /* If this is a sqrt operation and we don't care about errno, try to + attach a REG_EQUAL note with a SQRT rtx to the emitted libcall. + This allows the semantics of the libcall to be visible to the RTL + optimizers. */ + if (builtin_optab == sqrt_optab && !errno_set) + { + /* Search backwards through the insns emitted by expand_call looking + for the instruction with the REG_RETVAL note. */ + rtx last = get_last_insn (); + while (last != before_call) + { + if (find_reg_note (last, REG_RETVAL, NULL)) + { + rtx note = find_reg_note (last, REG_EQUAL, NULL); + /* Check that the REQ_EQUAL note is an EXPR_LIST with + two elements, i.e. symbol_ref(sqrt) and the operand. */ + if (note + && GET_CODE (note) == EXPR_LIST + && GET_CODE (XEXP (note, 0)) == EXPR_LIST + && XEXP (XEXP (note, 0), 1) != NULL_RTX + && XEXP (XEXP (XEXP (note, 0), 1), 1) == NULL_RTX) + { + rtx operand = XEXP (XEXP (XEXP (note, 0), 1), 0); + /* Check operand is a register with expected mode. */ + if (operand + && GET_CODE (operand) == REG + && GET_MODE (operand) == mode) + { + /* Replace the REG_EQUAL note with a SQRT rtx. */ + rtx equiv = gen_rtx_SQRT (mode, operand); + set_unique_reg_note (last, REG_EQUAL, equiv); + } + } + break; + } + last = PREV_INSN (last); + } + } return target; } |