Commit c2699190 by Xinliang David Li Committed by Xinliang David Li

tree-call-cdce.c: New file.

2008-06-04  Xinliang David Li  <davidxl@google.com>

	* tree-call-cdce.c: New file. 
	(cond_dead_built_in_calls): New static variable.
	(input_domain): New struct.
	(check_pow): New function.
	(check_builtin_call): Ditto.
	(check_target_format): Ditto.
	(is_call_dce_candidate): Ditto.
	(gen_one_condition): Ditto.
	(gen_conditions_for_domain): Ditto.
	(get_domain): Ditto.
	(gen_conditions_for_pow_cst_base): Ditto.
	(gen_conditions_for_pow_int_base): Ditto.
	(gen_conditions_for_pow): Ditto.
	(get_no_error_domain): Ditto.
	(gen_shrink_wrap_conditions): Ditto.
	(shrink_wrap_one_built_in_call): Ditto.
	(shink_wrap_conditional_dead_built_in_calls): Ditto.
	(tree_call_cdce): Ditto.
	(gate_call_cdce): Ditto.
	(pass_call_cdce): New gimple pass.
	* passes.c: (init_optimization_passes): New pass.
	* tree-pass.h: New pass declaration.
	* opts.c (decode_options): New flag setting.
	* common.opt: Add -ftree-builtin-call-dce flag.
	* Makefile.in: Add new source file.
	* tempvar.def: New tv_id.
	* doc/invoke.texi (-ftree-builtin-call-dce): New flag.

2008-06-04  Xinliang David Li  <davidxl@google.com>
	* gcc.dg/cdce1.c: New test.
	* gcc.dg/cdce2.c: Ditto.
	* g++.dg/cdce3.C: Ditto.

From-SVN: r136374
parent 7db5da56
2008-06-04 Xinliang David Li <davidxl@google.com>
* tree-call-cdce.c: New file.
(cond_dead_built_in_calls): New static variable.
(input_domain): New struct.
(check_pow): New function.
(check_builtin_call): Ditto.
(check_target_format): Ditto.
(is_call_dce_candidate): Ditto.
(gen_one_condition): Ditto.
(gen_conditions_for_domain): Ditto.
(get_domain): Ditto.
(gen_conditions_for_pow_cst_base): Ditto.
(gen_conditions_for_pow_int_base): Ditto.
(gen_conditions_for_pow): Ditto.
(get_no_error_domain): Ditto.
(gen_shrink_wrap_conditions): Ditto.
(shrink_wrap_one_built_in_call): Ditto.
(shink_wrap_conditional_dead_built_in_calls): Ditto.
(tree_call_cdce): Ditto.
(gate_call_cdce): Ditto.
(pass_call_cdce): New gimple pass.
* passes.c: (init_optimization_passes): New pass.
* tree-pass.h: New pass declaration.
* opts.c (decode_options): New flag setting.
* common.opt: Add -ftree-builtin-call-dce flag.
* Makefile.in: Add new source file.
* tempvar.def: New tv_id.
* doc/invoke.texi (-ftree-builtin-call-dce): New flag.
2008-06-04 Richard Guenther <rguenther@suse.de>
* tree-flow-inline.h (is_global_var): Do not check TREE_STATIC
......
......@@ -1143,6 +1143,7 @@ OBJS-common = \
toplev.o \
tracer.o \
tree-affine.o \
tree-call-cdce.o \
tree-cfg.o \
tree-cfgcleanup.o \
tree-chrec.o \
......@@ -2603,6 +2604,10 @@ tree-ssa-dce.o : tree-ssa-dce.c $(CONFIG_H) $(SYSTEM_H) $(TREE_H) \
coretypes.h $(TREE_DUMP_H) tree-pass.h $(FLAGS_H) $(BASIC_BLOCK_H) \
$(GGC_H) hard-reg-set.h $(OBSTACK_H) $(TREE_GIMPLE_H) $(CFGLOOP_H) \
$(SCEV_H)
tree-call-cdce.o : tree-call-cdce.c $(CONFIG_H) $(SYSTEM_H) $(TREE_H) \
$(RTL_H) $(TM_P_H) $(TREE_FLOW_H) $(DIAGNOSTIC_H) $(TIMEVAR_H) $(TM_H) \
coretypes.h $(TREE_DUMP_H) tree-pass.h $(FLAGS_H) $(BASIC_BLOCK_H) \
$(GGC_H) hard-reg-set.h $(OBSTACK_H) $(TREE_GIMPLE_H)
tree-ssa-ccp.o : tree-ssa-ccp.c $(TREE_FLOW_H) $(CONFIG_H) \
$(SYSTEM_H) $(RTL_H) $(TREE_H) $(TM_P_H) $(EXPR_H) $(GGC_H) output.h \
$(DIAGNOSTIC_H) $(FUNCTION_H) $(TIMEVAR_H) $(TM_H) coretypes.h \
......
......@@ -1255,6 +1255,10 @@ fweb
Common Report Var(flag_web) Init(2) Optimization
Construct webs and split unrelated uses of single variable
ftree-builtin-call-dce
Common Report Var(flag_tree_builtin_call_dce) Init(0) Optimization
Enable conditional dead code elimination for builtin calls
fwhole-program
Common Report Var(flag_whole_program) Init(0) Optimization
Perform whole program optimizations
......
......@@ -352,8 +352,9 @@ Objective-C and Objective-C++ Dialects}.
-fschedule-insns -fschedule-insns2 -fsection-anchors -fsee @gol
-fsignaling-nans -fsingle-precision-constant -fsplit-ivs-in-unroller @gol
-fsplit-wide-types -fstack-protector -fstack-protector-all @gol
-fstrict-aliasing -fstrict-overflow -fthread-jumps -ftracer -ftree-ccp @gol
-ftree-ch -ftree-copy-prop -ftree-copyrename -ftree-dce @gol
-fstrict-aliasing -fstrict-overflow -fthread-jumps -ftracer @gol
-ftree-builtin-call-dce -ftree-ccp -ftree-ch -ftree-copy-prop @gol
-ftree-copyrename -ftree-dce @gol
-ftree-dominator-opts -ftree-dse -ftree-fre -ftree-loop-im @gol
-ftree-loop-distribution @gol
-ftree-loop-ivcanon -ftree-loop-linear -ftree-loop-optimize @gol
......@@ -5154,6 +5155,7 @@ compilation time.
-fipa-reference @gol
-fmerge-constants
-fsplit-wide-types @gol
-ftree-builtin-call-dce @gol
-ftree-ccp @gol
-ftree-ch @gol
-ftree-copyrename @gol
......@@ -5874,6 +5876,13 @@ enabled by default at @option{-O2} and higher.
Perform dead code elimination (DCE) on trees. This flag is enabled by
default at @option{-O} and higher.
@item -ftree-builtin-call-dce
@opindex ftree-builtin-call-dce
Perform conditional dead code elimination (DCE) for calls to builtin functions
that may set @code{errno} but are otherwise side-effect free. This flag is
enabled by default at @option{-O2} and higher if @option{-Os} is not also
specified.
@item -ftree-dominator-opts
@opindex ftree-dominator-opts
Perform a variety of simple scalar cleanups (constant/copy
......
......@@ -889,6 +889,8 @@ decode_options (unsigned int argc, const char **argv)
if (!optimize_size)
{
/* Conditional DCE generates bigger code. */
flag_tree_builtin_call_dce = 1;
/* PRE tends to generate bigger code. */
flag_tree_pre = 1;
}
......
......@@ -561,6 +561,14 @@ init_optimization_passes (void)
NEXT_PASS (pass_copy_prop);
NEXT_PASS (pass_merge_phi);
NEXT_PASS (pass_dce);
/* Ideally the function call conditional
dead code elimination phase can be delayed
till later where potentially more opportunities
can be found. Due to lack of good ways to
update VDEFs associated with the shrink-wrapped
calls, it is better to do the transformation
here where memory SSA is not built yet. */
NEXT_PASS (pass_call_cdce);
NEXT_PASS (pass_update_address_taken);
NEXT_PASS (pass_simple_dse);
NEXT_PASS (pass_tail_recursion);
......
2008-06-04 Xinliang David Li <davidxl@google.com>
* gcc.dg/cdce1.c: New test.
* gcc.dg/cdce2.c: Ditto.
* g++.dg/cdce3.C: Ditto.
2008-06-04 Janus Weil <janus@gcc.gnu.org>
PR fortran/36322
......
/* { dg-do run { target { ! "*-*-darwin" } } } */
/* { dg-options "-O2 -fmath-errno -fdump-tree-cdce-details -lm" } */
/* { dg-final { scan-tree-dump "cdce3.C:68: note: function call is shrink-wrapped into error conditions\." "cdce" } }*/
/* { dg-final { scan-tree-dump "cdce3.C:69: note: function call is shrink-wrapped into error conditions\." "cdce" } }*/
/* { dg-final { scan-tree-dump "cdce3.C:70: note: function call is shrink-wrapped into error conditions\." "cdce" } }*/
/* { dg-final { scan-tree-dump "cdce3.C:71: note: function call is shrink-wrapped into error conditions\." "cdce" } }*/
/* { dg-final { scan-tree-dump "cdce3.C:72: note: function call is shrink-wrapped into error conditions\." "cdce" } }*/
/* { dg-final { scan-tree-dump "cdce3.C:73: note: function call is shrink-wrapped into error conditions\." "cdce" } }*/
/* { dg-final { scan-tree-dump "cdce3.C:74: note: function call is shrink-wrapped into error conditions\." "cdce" } }*/
/* { dg-final { scan-tree-dump "cdce3.C:75: note: function call is shrink-wrapped into error conditions\." "cdce" } }*/
/* { dg-final { scan-tree-dump "cdce3.C:76: note: function call is shrink-wrapped into error conditions\." "cdce" } }*/
/* { dg-final { scan-tree-dump "cdce3.C:77: note: function call is shrink-wrapped into error conditions\." "cdce" } }*/
/* { dg-final { scan-tree-dump "cdce3.C:78: note: function call is shrink-wrapped into error conditions\." "cdce" } }*/
/* { dg-final { scan-tree-dump "cdce3.C:79: note: function call is shrink-wrapped into error conditions\." "cdce" } }*/
/* { dg-final { scan-tree-dump "cdce3.C:80: note: function call is shrink-wrapped into error conditions\." "cdce" } }*/
/* { dg-final { scan-tree-dump "cdce3.C:81: note: function call is shrink-wrapped into error conditions\." "cdce" } }*/
/* { dg-final { scan-tree-dump "cdce3.C:82: note: function call is shrink-wrapped into error conditions\." "cdce" } }*/
/* { dg-final { scan-tree-dump "cdce3.C:83: note: function call is shrink-wrapped into error conditions\." "cdce" } }*/
/* { dg-final { cleanup-tree-dump "cdce" } } */
#include <stdlib.h>
#include <math.h>
#ifdef DEBUG
#include <stdio.h>
#endif
#include <errno.h>
typedef long double ldouble;
typedef void (*FP) (int xp);
#define NI __attribute__((noinline))
ldouble result;
#define DEF_MATH_FUNC(prefix, name) NI void prefix##name##f (int x) \
{ \
float yy = name##f ((float) x); \
STORE_RESULT; \
} \
NI void prefix##name (int x) \
{ \
double yy = name ((double)x); \
STORE_RESULT; \
} \
NI void prefix##name##l (int x) \
{ \
ldouble yy = name##l ((ldouble)x); \
STORE_RESULT; \
}
#undef STORE_RESULT
#define STORE_RESULT result = yy
DEF_MATH_FUNC (m,pow10)
DEF_MATH_FUNC (m,exp10)
DEF_MATH_FUNC (m,exp2)
DEF_MATH_FUNC (m,exp)
DEF_MATH_FUNC (m,expm1)
DEF_MATH_FUNC (m,cosh)
DEF_MATH_FUNC (m,sinh)
DEF_MATH_FUNC (m,acos)
DEF_MATH_FUNC (m,asin)
DEF_MATH_FUNC (m,acosh)
DEF_MATH_FUNC (m,atanh)
DEF_MATH_FUNC (m,log)
DEF_MATH_FUNC (m,log2)
DEF_MATH_FUNC (m,log10)
DEF_MATH_FUNC (m,log1p)
DEF_MATH_FUNC (m,sqrt)
#undef STORE_RESULT
#define STORE_RESULT
DEF_MATH_FUNC (o,pow10)
DEF_MATH_FUNC (o,exp10)
DEF_MATH_FUNC (o,exp2)
DEF_MATH_FUNC (o,exp)
DEF_MATH_FUNC (o,expm1)
DEF_MATH_FUNC (o,cosh)
DEF_MATH_FUNC (o,sinh)
DEF_MATH_FUNC (o,acos)
DEF_MATH_FUNC (o,asin)
DEF_MATH_FUNC (o,acosh)
DEF_MATH_FUNC (o,atanh)
DEF_MATH_FUNC (o,log)
DEF_MATH_FUNC (o,log2)
DEF_MATH_FUNC (o,log10)
DEF_MATH_FUNC (o,log1p)
DEF_MATH_FUNC (o,sqrt)
#define INIT_MATH_FUNC(prefix, name, lb, ub) { prefix##name##f, #name "f", 0, 0, lb, ub }, \
{ prefix##name, #name, 0, 0, lb, ub }, \
{ prefix##name##l, #name "l" , 0, 0, lb, ub },
struct MathFuncInfo
{
FP math_func;
const char* name;
int lb;
int ub;
bool has_lb;
bool has_ub;
} math_func_arr[] = {
INIT_MATH_FUNC (m,pow10, false, true)
INIT_MATH_FUNC (m,exp10, false, true)
INIT_MATH_FUNC (m,exp2, false, true)
INIT_MATH_FUNC (m,expm1, false, true)
INIT_MATH_FUNC (m,exp, false, true)
INIT_MATH_FUNC (m,cosh, true, true)
INIT_MATH_FUNC (m,sinh, true, true)
INIT_MATH_FUNC (m,acos, true, true)
INIT_MATH_FUNC (m,asin, true, true)
INIT_MATH_FUNC (m,acosh, true, false)
INIT_MATH_FUNC (m,atanh, true, true)
INIT_MATH_FUNC (m,log10, true, false)
INIT_MATH_FUNC (m,log, true, false)
INIT_MATH_FUNC (m,log2, true, false)
INIT_MATH_FUNC (m,log1p, true, false)
INIT_MATH_FUNC (m,sqrt, true, false)
{ 0, 0, 0, 0, 0, 0} };
MathFuncInfo opt_math_func_arr[] =
{ INIT_MATH_FUNC (o,pow10, false, true)
INIT_MATH_FUNC (o,exp10, false, true)
INIT_MATH_FUNC (o,exp2, false, true)
INIT_MATH_FUNC (o,expm1, false, true)
INIT_MATH_FUNC (o,exp, false, true)
INIT_MATH_FUNC (o,cosh, true, true)
INIT_MATH_FUNC (o,sinh, true, true)
INIT_MATH_FUNC (o,acos, true, true)
INIT_MATH_FUNC (o,asin, true, true)
INIT_MATH_FUNC (o,acosh, true, false)
INIT_MATH_FUNC (o,atanh, true, true)
INIT_MATH_FUNC (o,log10, true, false)
INIT_MATH_FUNC (o,log, true, false)
INIT_MATH_FUNC (o,log2, true, false)
INIT_MATH_FUNC (o,log1p, true, false)
INIT_MATH_FUNC (o,sqrt, true, false)
{ 0, 0, 0, 0, 0, 0} };
int test (MathFuncInfo* math_func_infos)
{
int i = 0;
int te = 0;
for (i = 0; math_func_infos[i].math_func; i++)
{
MathFuncInfo& info = math_func_infos[i];
int j;
if (info.has_lb)
{
for (j = 0; j > -500000; j--)
{
errno = 0;
info.math_func (j);
if (errno != 0)
{
te++;
info.lb = j ;
break;
}
}
}
if (info.has_ub)
{
for (j = 0; j < 500000; j++)
{
errno = 0;
info.math_func (j);
if (errno != 0)
{
te++;
info.ub = j ;
break;
}
}
}
}
return te;
}
int main()
{
int te1, te2;
te1 = test (&math_func_arr[0]);
te2 = test (&opt_math_func_arr[0]);
// Now examine the result
int i = 0;
int errcnt = 0;
for (i = 0; math_func_arr[i].math_func; i++)
{
MathFuncInfo& info = math_func_arr[i];
MathFuncInfo& opt_info = opt_math_func_arr[i];
#ifdef DEBUG
fprintf (stderr," %s: lb = %d, ub = %d: lb_opt = %d, ub_opt = %d\n",
info.name, info.lb, info.ub, opt_info.lb, opt_info.ub);
#endif
if (info.lb != opt_info.lb) errcnt ++;
if (info.ub != opt_info.ub) errcnt ++;
}
if (errcnt) abort();
return 0;
}
/* { dg-do run { target { ! "*-*-darwin" } } } */
/* { dg-options "-O2 -fmath-errno -fdump-tree-cdce-details -lm" } */
/* { dg-final { scan-tree-dump "cdce1.c:16: note: function call is shrink-wrapped into error conditions\." "cdce" } } */
/* { dg-final { cleanup-tree-dump "cdce" } } */
#include <stdlib.h>
#include <math.h>
#include <errno.h>
int total_err_count = 0;
double foo_opt (int x, double y) __attribute__((noinline));
double foo_opt (int x, double y)
{
double yy = 0;
errno = 0;
yy = pow (x, y * y);
return 0;
}
double foo (int x, double y) __attribute__((noinline));
double foo (int x, double y)
{
double yy = 0;
errno = 0;
yy = pow (x, y * y);
return yy;
}
int test (double (*fp)(int x, double y))
{
int i,x;
x = 127;
for (i = 30; i < 300; i++)
{
fp (x, i);
if (errno)
total_err_count ++;
}
x = -300;
for (i = 100; i < 300; i++)
{
fp (x, i);
if (errno)
total_err_count ++;
}
x = 65577;
for (i = 60; i < 200; i++)
{
fp (x, i);
if (errno)
total_err_count ++;
}
x = 65577 * 127;
for (i = 1; i < 100; i++)
{
fp (x, i);
if (errno)
total_err_count ++;
}
return total_err_count;
}
int main ()
{
int en1, en2;
total_err_count = 0;
en1 = test (foo_opt);
total_err_count = 0;
en2 = test (foo);
if (en1 != en2)
abort ();
return 0;
}
/* { dg-do run { target { ! "*-*-darwin" } } } */
/* { dg-options "-O2 -fmath-errno -fdump-tree-cdce-details -lm" } */
/* { dg-final { scan-tree-dump "cdce2.c:16: note: function call is shrink-wrapped into error conditions\." "cdce" } }*/
/* { dg-final { cleanup-tree-dump "cdce" } } */
#include <stdlib.h>
#include <math.h>
#include <errno.h>
int total_err_count = 0;
double foo_opt (double y) __attribute__((noinline));
double foo_opt (double y)
{
double yy = 0;
errno = 0;
yy = log (y);
return 0;
}
double foo (double y) __attribute__((noinline));
double foo (double y)
{
double yy = 0;
errno = 0;
yy = log (y);
return yy;
}
int test (double (*fp) (double y))
{
int i,x;
for (i = -100; i < 100; i++)
{
fp (i);
if (errno)
total_err_count ++;
}
return total_err_count;
}
int main ()
{
int en1, en2;
double yy;
total_err_count = 0;
en1 = test (foo_opt);
total_err_count = 0;
en2 = test (foo);
if (en1 != en2)
abort();
return 0;
}
......@@ -113,6 +113,7 @@ DEFTIMEVAR (TV_TREE_FORWPROP , "tree forward propagate")
DEFTIMEVAR (TV_TREE_PHIPROP , "tree phiprop")
DEFTIMEVAR (TV_TREE_DCE , "tree conservative DCE")
DEFTIMEVAR (TV_TREE_CD_DCE , "tree aggressive DCE")
DEFTIMEVAR (TV_TREE_CALL_CDCE , "tree buildin call DCE")
DEFTIMEVAR (TV_TREE_DSE , "tree DSE")
DEFTIMEVAR (TV_TREE_MERGE_PHI , "PHI merge")
DEFTIMEVAR (TV_TREE_LOOP , "tree loop optimization")
......
......@@ -337,6 +337,7 @@ extern struct gimple_opt_pass pass_dominator;
extern struct gimple_opt_pass pass_dce;
extern struct gimple_opt_pass pass_dce_loop;
extern struct gimple_opt_pass pass_cd_dce;
extern struct gimple_opt_pass pass_call_cdce;
extern struct gimple_opt_pass pass_merge_phi;
extern struct gimple_opt_pass pass_split_crit_edges;
extern struct gimple_opt_pass pass_pre;
......
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