aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRoger Sayle <roger@eyesopen.com>2003-08-26 00:09:10 +0000
committerRoger Sayle <sayle@gcc.gnu.org>2003-08-26 00:09:10 +0000
commit8634629b6f3e9a316e4ef83685e3c36068d6a0c1 (patch)
tree267b0d3325e69e819d855522539d14770832fe00
parent0961802f7eb8343c55cd29946985600f646879d3 (diff)
downloadgcc-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/ChangeLog7
-rw-r--r--gcc/builtins.c108
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;
}