mirror of
git://gcc.gnu.org/git/gcc.git
synced 2025-04-20 02:00:48 +08:00
fold-const.c (fold_mathfn_compare): New function to simplify comparisons against built-in math functions.
* fold-const.c (fold_mathfn_compare): New function to simplify comparisons against built-in math functions. Fold comparisons of sqrt against constants. (fold): Call fold_mathfn_compare when appropriate. * gcc.dg/builtins-6.c: New test case. From-SVN: r64619
This commit is contained in:
parent
952a6df761
commit
c876997fea
@ -1,3 +1,10 @@
|
||||
2003-03-20 Roger Sayle <roger@eyesopen.com>
|
||||
|
||||
* fold-const.c (fold_mathfn_compare): New function to simplify
|
||||
comparisons against built-in math functions. Fold comparisons
|
||||
of sqrt against constants.
|
||||
(fold): Call fold_mathfn_compare when appropriate.
|
||||
|
||||
2003-03-20 Richard Earnshaw <rearnsha@arm.com>
|
||||
|
||||
* ifcvt.c (find_if_case_1): If we add a new bb, update the dominance
|
||||
@ -1542,24 +1549,24 @@ Sat Mar 8 14:13:35 CET 2003 Jan Hubicka <jh@suse.cz>
|
||||
MEM, try loading the MEM into a register and taking the low-part
|
||||
of that, to help CSE see the use of the MEM in its true mode.
|
||||
|
||||
2002-03-05 Tom Tromey <tromey@redhat.com>
|
||||
2003-03-05 Tom Tromey <tromey@redhat.com>
|
||||
|
||||
* config/stormy16/stormy16.h (DWARF_LINE_MIN_INSTR_LENGTH):
|
||||
Define.
|
||||
|
||||
2002-03-05 Nick Clifton <nickc@cambridge.redhat.com>
|
||||
2003-03-05 Nick Clifton <nickc@cambridge.redhat.com>
|
||||
|
||||
* config/stormy16/stormy16.md ("*eqbranchsi"): Remove '+' on
|
||||
operand 2.
|
||||
("*ineqbranchsi"): Likewise.
|
||||
|
||||
2002-03-05 Andrew Haley <aph@cambridge.redhat.com>
|
||||
2003-03-05 Andrew Haley <aph@cambridge.redhat.com>
|
||||
|
||||
* config/stormy16/stormy16.c (xstormy16_expand_prologue): Delete
|
||||
mem_fake_push_rtx. Instead construct a SEQUENCE to show the
|
||||
register store followed by a stack increment.
|
||||
|
||||
2002-03-05 Chris Moller <cmoller@redhat.com>
|
||||
2003-03-05 Chris Moller <cmoller@redhat.com>
|
||||
|
||||
* config/stormy16/stormy16.c (REG_NEEDS_SAVE): added a term
|
||||
to inhibit saving CARRY_REGS.
|
||||
@ -2328,7 +2335,7 @@ Mon Mar 3 19:07:21 CET 2003 Jan Hubicka <jh@suse.cz>
|
||||
(*tst_extzv_memqi_1_n): Likewise.
|
||||
(a peephole2): New.
|
||||
|
||||
2002-02-28 Richard Sandiford <rsandifo@redhat.com>
|
||||
2003-02-28 Richard Sandiford <rsandifo@redhat.com>
|
||||
|
||||
* config/mips/mips.h (CRT_CALL_STATIC_FUNCTION): Wrap in
|
||||
#ifndef __mips16.
|
||||
@ -4123,7 +4130,7 @@ Sun Feb 9 23:54:59 CET 2003 Jan Hubicka <jh@suse.cz>
|
||||
simplify_binary_operation): Deal with vector modes
|
||||
(simplify_ternary_operation): Deal with no-op VEC_MERGE.
|
||||
|
||||
2002-02-09 Richard Sandiford <rsandifo@redhat.com>
|
||||
2003-02-09 Richard Sandiford <rsandifo@redhat.com>
|
||||
|
||||
* toplev.c (rest_of_compilation): Recompute register usage after
|
||||
split_all_insns.
|
||||
@ -4489,7 +4496,7 @@ Wed Feb 5 23:12:57 CET 2003 Jan Hubicka <jh@suse.cz>
|
||||
* config/ia64/unwind-ia64.c: include coretypes.h, tm.h to get
|
||||
config/ia64/linux.h
|
||||
|
||||
2002-02-05 Roger Sayle <roger@eyesopen.com>
|
||||
2003-02-05 Roger Sayle <roger@eyesopen.com>
|
||||
|
||||
* cfgloop.h (flow_bb_inside_loop_p): Correct prototype again.
|
||||
|
||||
@ -4605,7 +4612,7 @@ Mon Feb 3 21:19:11 CET 2003 Jan Hubicka <jh@suse.cz>
|
||||
(movups/movupd/movdqu patterns): Force one of operands to not be
|
||||
memory.
|
||||
|
||||
2002-02-03 Roger Sayle <roger@eyesopen.com>
|
||||
2003-02-03 Roger Sayle <roger@eyesopen.com>
|
||||
|
||||
* hooks.c (hook_rtx_rtx_identity): Generic hook function that
|
||||
takes a single rtx and returns it unmodified.
|
||||
@ -5624,11 +5631,11 @@ Sat Jan 25 21:04:33 CET 2003 Jan Hubicka <jh@suse.cz>
|
||||
* config/h8300/h8300.c (h8300_shift_needs_scratch_p): Update a
|
||||
comment.
|
||||
|
||||
2002-01-25 Richard Henderson <rth@redhat.com>
|
||||
2003-01-25 Richard Henderson <rth@redhat.com>
|
||||
|
||||
* config/m68k/m68k-none.h (ASM_SPEC): Adjust inter-option spacing.
|
||||
|
||||
2002-01-25 Kelley Cook <kelleycook@comcast.net>
|
||||
2003-01-25 Kelley Cook <kelleycook@comcast.net>
|
||||
|
||||
* ggc-simple.c (debug_ggc_tree): Add PTR cast.
|
||||
|
||||
@ -5646,7 +5653,7 @@ Sat Jan 25 21:04:33 CET 2003 Jan Hubicka <jh@suse.cz>
|
||||
2002-02-19 Robert Lipe <robertlipe@usa.net>
|
||||
* config/i386/t-sco5gas: (CRTSTUFF_T_CFLAGS_S): Delete -mcoff.
|
||||
|
||||
2002-01-25 Roger Sayle <roger@eyesopen.com>
|
||||
2003-01-25 Roger Sayle <roger@eyesopen.com>
|
||||
|
||||
* builtins.c (purge_builtin_constant_p): Scan insn stream
|
||||
sequentially rather than by basic block.
|
||||
@ -5656,7 +5663,7 @@ Sat Jan 25 21:04:33 CET 2003 Jan Hubicka <jh@suse.cz>
|
||||
|
||||
* combine.c (simplify_comparison, case AND): Remove a redundant test.
|
||||
|
||||
2002-01-25 Roger Sayle <roger@eyesopen.com>
|
||||
2003-01-25 Roger Sayle <roger@eyesopen.com>
|
||||
|
||||
* function.h (struct function): New field calls_constant_p.
|
||||
(current_function_calls_constant_p): New macro for above.
|
||||
@ -5668,7 +5675,7 @@ Sat Jan 25 21:04:33 CET 2003 Jan Hubicka <jh@suse.cz>
|
||||
* integrate.c (expand_inline_function): Set calls_constant_p if
|
||||
the function being inlined has calls_constant_p set.
|
||||
|
||||
2002-01-25 Roger Sayle <roger@eyesopen.com>
|
||||
2003-01-25 Roger Sayle <roger@eyesopen.com>
|
||||
|
||||
* cse.c (fold_rtx): Instantiate CONSTANT_P_RTX to 0 when not
|
||||
optimizing, even if flag_gcse is true.
|
||||
@ -5728,7 +5735,7 @@ Sat Jan 25 11:10:03 CET 2003 Jan Hubicka <jh@suse.cz>
|
||||
|
||||
* builtins.c (fold_trunc_transparent_mathfn): Undo accidental commit.
|
||||
|
||||
2002-01-24 Stuart Hastings <stuart@apple.com>
|
||||
2003-01-24 Stuart Hastings <stuart@apple.com>
|
||||
|
||||
* config/i386/i386.c (x86_output_mi_thunk): Add Darwin/x86 support.
|
||||
|
||||
|
155
gcc/fold-const.c
155
gcc/fold-const.c
@ -112,6 +112,8 @@ static int count_cond PARAMS ((tree, int));
|
||||
static tree fold_binary_op_with_conditional_arg
|
||||
PARAMS ((enum tree_code, tree, tree, tree, int));
|
||||
static bool fold_real_zero_addition_p PARAMS ((tree, tree, int));
|
||||
static tree fold_mathfn_compare PARAMS ((enum built_in_function,
|
||||
enum tree_code, tree, tree, tree));
|
||||
|
||||
/* The following constants represent a bit based encoding of GCC's
|
||||
comparison operators. This encoding simplifies transformations
|
||||
@ -4661,6 +4663,144 @@ fold_real_zero_addition_p (type, addend, negate)
|
||||
return negate && !HONOR_SIGN_DEPENDENT_ROUNDING (TYPE_MODE (type));
|
||||
}
|
||||
|
||||
/* Subroutine of fold() that checks comparisons of built-in math
|
||||
functions against real constants.
|
||||
|
||||
FCODE is the DECL_FUNCTION_CODE of the built-in, CODE is the comparison
|
||||
operator: EQ_EXPR, NE_EXPR, GT_EXPR, LT_EXPR, GE_EXPR or LE_EXPR. TYPE
|
||||
is the type of the result and ARG0 and ARG1 are the operands of the
|
||||
comparison. ARG1 must be a TREE_REAL_CST.
|
||||
|
||||
The function returns the constant folded tree if a simplification
|
||||
can be made, and NULL_TREE otherwise. */
|
||||
|
||||
static tree
|
||||
fold_mathfn_compare (fcode, code, type, arg0, arg1)
|
||||
enum built_in_function fcode;
|
||||
enum tree_code code;
|
||||
tree type, arg0, arg1;
|
||||
{
|
||||
REAL_VALUE_TYPE c;
|
||||
|
||||
if (fcode == BUILT_IN_SQRT
|
||||
|| fcode == BUILT_IN_SQRTF
|
||||
|| fcode == BUILT_IN_SQRTL)
|
||||
{
|
||||
tree arg = TREE_VALUE (TREE_OPERAND (arg0, 1));
|
||||
enum machine_mode mode = TYPE_MODE (TREE_TYPE (arg0));
|
||||
|
||||
c = TREE_REAL_CST (arg1);
|
||||
if (REAL_VALUE_NEGATIVE (c))
|
||||
{
|
||||
/* sqrt(x) < y is always false, if y is negative. */
|
||||
if (code == EQ_EXPR || code == LT_EXPR || code == LE_EXPR)
|
||||
return omit_one_operand (type,
|
||||
convert (type, integer_zero_node),
|
||||
arg);
|
||||
|
||||
/* sqrt(x) > y is always true, if y is negative and we
|
||||
don't care about NaNs, i.e. negative values of x. */
|
||||
if (code == NE_EXPR || !HONOR_NANS (mode))
|
||||
return omit_one_operand (type,
|
||||
convert (type, integer_one_node),
|
||||
arg);
|
||||
|
||||
/* sqrt(x) > y is the same as x >= 0, if y is negative. */
|
||||
return fold (build (GE_EXPR, type, arg,
|
||||
build_real (TREE_TYPE (arg), dconst0)));
|
||||
}
|
||||
else if (code == GT_EXPR || code == GE_EXPR)
|
||||
{
|
||||
REAL_VALUE_TYPE c2;
|
||||
|
||||
REAL_ARITHMETIC (c2, MULT_EXPR, c, c);
|
||||
real_convert (&c2, mode, &c2);
|
||||
|
||||
if (REAL_VALUE_ISINF (c2))
|
||||
{
|
||||
/* sqrt(x) > y is x == +Inf, when y is very large. */
|
||||
if (HONOR_INFINITIES (mode))
|
||||
return fold (build (EQ_EXPR, type, arg,
|
||||
build_real (TREE_TYPE (arg), c2)));
|
||||
|
||||
/* sqrt(x) > y is always false, when y is very large
|
||||
and we don't care about infinities. */
|
||||
return omit_one_operand (type,
|
||||
convert (type, integer_zero_node),
|
||||
arg);
|
||||
}
|
||||
|
||||
/* sqrt(x) > c is the same as x > c*c. */
|
||||
return fold (build (code, type, arg,
|
||||
build_real (TREE_TYPE (arg), c2)));
|
||||
}
|
||||
else if (code == LT_EXPR || code == LE_EXPR)
|
||||
{
|
||||
REAL_VALUE_TYPE c2;
|
||||
|
||||
REAL_ARITHMETIC (c2, MULT_EXPR, c, c);
|
||||
real_convert (&c2, mode, &c2);
|
||||
|
||||
if (REAL_VALUE_ISINF (c2))
|
||||
{
|
||||
/* sqrt(x) < y is always true, when y is a very large
|
||||
value and we don't care about NaNs or Infinities. */
|
||||
if (! HONOR_NANS (mode) && ! HONOR_INFINITIES (mode))
|
||||
return omit_one_operand (type,
|
||||
convert (type, integer_one_node),
|
||||
arg);
|
||||
|
||||
/* sqrt(x) < y is x != +Inf when y is very large and we
|
||||
don't care about NaNs. */
|
||||
if (! HONOR_NANS (mode))
|
||||
return fold (build (NE_EXPR, type, arg,
|
||||
build_real (TREE_TYPE (arg), c2)));
|
||||
|
||||
/* sqrt(x) < y is x >= 0 when y is very large and we
|
||||
don't care about Infinities. */
|
||||
if (! HONOR_INFINITIES (mode))
|
||||
return fold (build (GE_EXPR, type, arg,
|
||||
build_real (TREE_TYPE (arg), dconst0)));
|
||||
|
||||
/* sqrt(x) < y is x >= 0 && x != +Inf, when y is large. */
|
||||
if ((*lang_hooks.decls.global_bindings_p) () != 0
|
||||
|| contains_placeholder_p (arg))
|
||||
return NULL_TREE;
|
||||
|
||||
arg = save_expr (arg);
|
||||
return fold (build (TRUTH_ANDIF_EXPR, type,
|
||||
fold (build (GE_EXPR, type, arg,
|
||||
build_real (TREE_TYPE (arg),
|
||||
dconst0))),
|
||||
fold (build (NE_EXPR, type, arg,
|
||||
build_real (TREE_TYPE (arg),
|
||||
c2)))));
|
||||
}
|
||||
|
||||
/* sqrt(x) < c is the same as x < c*c, if we ignore NaNs. */
|
||||
if (! HONOR_NANS (mode))
|
||||
return fold (build (code, type, arg,
|
||||
build_real (TREE_TYPE (arg), c2)));
|
||||
|
||||
/* sqrt(x) < c is the same as x >= 0 && x < c*c. */
|
||||
if ((*lang_hooks.decls.global_bindings_p) () == 0
|
||||
&& ! contains_placeholder_p (arg))
|
||||
{
|
||||
arg = save_expr (arg);
|
||||
return fold (build (TRUTH_ANDIF_EXPR, type,
|
||||
fold (build (GE_EXPR, type, arg,
|
||||
build_real (TREE_TYPE (arg),
|
||||
dconst0))),
|
||||
fold (build (code, type, arg,
|
||||
build_real (TREE_TYPE (arg),
|
||||
c2)))));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return NULL_TREE;
|
||||
}
|
||||
|
||||
|
||||
/* Perform constant folding and related simplification of EXPR.
|
||||
The related simplifications include x*1 => x, x*0 => 0, etc.,
|
||||
@ -6209,6 +6349,21 @@ fold (expr)
|
||||
arg1, TREE_OPERAND (arg0, 1), 0))
|
||||
&& ! TREE_CONSTANT_OVERFLOW (tem))
|
||||
return fold (build (code, type, TREE_OPERAND (arg0, 0), tem));
|
||||
|
||||
/* Fold comparisons against built-in math functions. */
|
||||
if (TREE_CODE (arg1) == REAL_CST
|
||||
&& flag_unsafe_math_optimizations
|
||||
&& ! flag_errno_math)
|
||||
{
|
||||
enum built_in_function fcode = builtin_mathfn_code (arg0);
|
||||
|
||||
if (fcode != END_BUILTINS)
|
||||
{
|
||||
tem = fold_mathfn_compare (fcode, code, type, arg0, arg1);
|
||||
if (tem != NULL_TREE)
|
||||
return tem;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Convert foo++ == CONST into ++foo == CONST + INCR.
|
||||
|
@ -1,3 +1,7 @@
|
||||
2003-03-20 Roger Sayle <roger@eyesopen.com>
|
||||
|
||||
* gcc.dg/builtins-6.c: New test case.
|
||||
|
||||
2003-03-19 Alan Modra <amodra@bigpond.net.au>
|
||||
|
||||
PR target/10073
|
||||
|
80
gcc/testsuite/gcc.dg/builtins-6.c
Normal file
80
gcc/testsuite/gcc.dg/builtins-6.c
Normal file
@ -0,0 +1,80 @@
|
||||
/* Copyright (C) 2003 Free Software Foundation.
|
||||
|
||||
Verify that constant folding comparisons against built-in math functions
|
||||
don't cause any problems for the compiler, and produce expected results.
|
||||
|
||||
Written by Roger Sayle, 15th March 2003. */
|
||||
|
||||
/* { dg-do run } */
|
||||
/* { dg-options "-O2 -ffast-math" } */
|
||||
|
||||
#include <float.h>
|
||||
|
||||
extern void abort (void);
|
||||
extern double sqrt (double);
|
||||
|
||||
int test1(double x)
|
||||
{
|
||||
return sqrt(x) < -9.0;
|
||||
}
|
||||
|
||||
int test2(double x)
|
||||
{
|
||||
return sqrt(x) > -9.0;
|
||||
}
|
||||
|
||||
int test3(double x)
|
||||
{
|
||||
return sqrt(x) < 9.0;
|
||||
}
|
||||
|
||||
int test4(double x)
|
||||
{
|
||||
return sqrt(x) > 9.0;
|
||||
}
|
||||
|
||||
int test5(double x)
|
||||
{
|
||||
return sqrt(x) < DBL_MAX;
|
||||
}
|
||||
|
||||
int test6(double x)
|
||||
{
|
||||
return sqrt(x) > DBL_MAX;
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
double x;
|
||||
|
||||
x = 80.0;
|
||||
if (test1 (x))
|
||||
abort ();
|
||||
if (! test2 (x))
|
||||
abort ();
|
||||
if (! test3 (x))
|
||||
abort ();
|
||||
if (test4 (x))
|
||||
abort ();
|
||||
if (! test5 (x))
|
||||
abort ();
|
||||
if (test6 (x))
|
||||
abort ();
|
||||
|
||||
x = 100.0;
|
||||
if (test1 (x))
|
||||
abort ();
|
||||
if (! test2 (x))
|
||||
abort ();
|
||||
if (test3 (x))
|
||||
abort ();
|
||||
if (! test4 (x))
|
||||
abort ();
|
||||
if (! test5 (x))
|
||||
abort ();
|
||||
if (test6 (x))
|
||||
abort ();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user