Commit c876997f by Roger Sayle

fold-const.c (fold_mathfn_compare): New function to simplify comparisons against…

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
parent 952a6df7
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> 2003-03-20 Richard Earnshaw <rearnsha@arm.com>
* ifcvt.c (find_if_case_1): If we add a new bb, update the dominance * 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> ...@@ -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 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. 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): * config/stormy16/stormy16.h (DWARF_LINE_MIN_INSTR_LENGTH):
Define. 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 * config/stormy16/stormy16.md ("*eqbranchsi"): Remove '+' on
operand 2. operand 2.
("*ineqbranchsi"): Likewise. ("*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 * config/stormy16/stormy16.c (xstormy16_expand_prologue): Delete
mem_fake_push_rtx. Instead construct a SEQUENCE to show the mem_fake_push_rtx. Instead construct a SEQUENCE to show the
register store followed by a stack increment. 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 * config/stormy16/stormy16.c (REG_NEEDS_SAVE): added a term
to inhibit saving CARRY_REGS. to inhibit saving CARRY_REGS.
...@@ -2328,7 +2335,7 @@ Mon Mar 3 19:07:21 CET 2003 Jan Hubicka <jh@suse.cz> ...@@ -2328,7 +2335,7 @@ Mon Mar 3 19:07:21 CET 2003 Jan Hubicka <jh@suse.cz>
(*tst_extzv_memqi_1_n): Likewise. (*tst_extzv_memqi_1_n): Likewise.
(a peephole2): New. (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 * config/mips/mips.h (CRT_CALL_STATIC_FUNCTION): Wrap in
#ifndef __mips16. #ifndef __mips16.
...@@ -4123,7 +4130,7 @@ Sun Feb 9 23:54:59 CET 2003 Jan Hubicka <jh@suse.cz> ...@@ -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_binary_operation): Deal with vector modes
(simplify_ternary_operation): Deal with no-op VEC_MERGE. (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 * toplev.c (rest_of_compilation): Recompute register usage after
split_all_insns. split_all_insns.
...@@ -4489,7 +4496,7 @@ Wed Feb 5 23:12:57 CET 2003 Jan Hubicka <jh@suse.cz> ...@@ -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/unwind-ia64.c: include coretypes.h, tm.h to get
config/ia64/linux.h 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. * 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> ...@@ -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 (movups/movupd/movdqu patterns): Force one of operands to not be
memory. 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 * hooks.c (hook_rtx_rtx_identity): Generic hook function that
takes a single rtx and returns it unmodified. 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> ...@@ -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 * config/h8300/h8300.c (h8300_shift_needs_scratch_p): Update a
comment. 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. * 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. * 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> ...@@ -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> 2002-02-19 Robert Lipe <robertlipe@usa.net>
* config/i386/t-sco5gas: (CRTSTUFF_T_CFLAGS_S): Delete -mcoff. * 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 * builtins.c (purge_builtin_constant_p): Scan insn stream
sequentially rather than by basic block. sequentially rather than by basic block.
...@@ -5656,7 +5663,7 @@ Sat Jan 25 21:04:33 CET 2003 Jan Hubicka <jh@suse.cz> ...@@ -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. * 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. * function.h (struct function): New field calls_constant_p.
(current_function_calls_constant_p): New macro for above. (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> ...@@ -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 * integrate.c (expand_inline_function): Set calls_constant_p if
the function being inlined has calls_constant_p set. 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 * cse.c (fold_rtx): Instantiate CONSTANT_P_RTX to 0 when not
optimizing, even if flag_gcse is true. optimizing, even if flag_gcse is true.
...@@ -5728,7 +5735,7 @@ Sat Jan 25 11:10:03 CET 2003 Jan Hubicka <jh@suse.cz> ...@@ -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. * 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. * config/i386/i386.c (x86_output_mi_thunk): Add Darwin/x86 support.
......
...@@ -112,6 +112,8 @@ static int count_cond PARAMS ((tree, int)); ...@@ -112,6 +112,8 @@ static int count_cond PARAMS ((tree, int));
static tree fold_binary_op_with_conditional_arg static tree fold_binary_op_with_conditional_arg
PARAMS ((enum tree_code, tree, tree, tree, int)); PARAMS ((enum tree_code, tree, tree, tree, int));
static bool fold_real_zero_addition_p PARAMS ((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 /* The following constants represent a bit based encoding of GCC's
comparison operators. This encoding simplifies transformations comparison operators. This encoding simplifies transformations
...@@ -4661,6 +4663,144 @@ fold_real_zero_addition_p (type, addend, negate) ...@@ -4661,6 +4663,144 @@ fold_real_zero_addition_p (type, addend, negate)
return negate && !HONOR_SIGN_DEPENDENT_ROUNDING (TYPE_MODE (type)); 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. /* Perform constant folding and related simplification of EXPR.
The related simplifications include x*1 => x, x*0 => 0, etc., The related simplifications include x*1 => x, x*0 => 0, etc.,
...@@ -6209,6 +6349,21 @@ fold (expr) ...@@ -6209,6 +6349,21 @@ fold (expr)
arg1, TREE_OPERAND (arg0, 1), 0)) arg1, TREE_OPERAND (arg0, 1), 0))
&& ! TREE_CONSTANT_OVERFLOW (tem)) && ! TREE_CONSTANT_OVERFLOW (tem))
return fold (build (code, type, TREE_OPERAND (arg0, 0), 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. /* Convert foo++ == CONST into ++foo == CONST + INCR.
......
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> 2003-03-19 Alan Modra <amodra@bigpond.net.au>
PR target/10073 PR target/10073
......
/* 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;
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment