diff options
author | Bernd Schmidt <bernds@redhat.co.uk> | 2000-11-01 17:02:45 +0000 |
---|---|---|
committer | Bernd Schmidt <bernds@gcc.gnu.org> | 2000-11-01 17:02:45 +0000 |
commit | b0b3afb2f34492e2bf82b0bcad8d84d5c3a3a7f7 (patch) | |
tree | 134205e79f38779f813ba6a5e2125ad69cafdd53 /gcc | |
parent | f92351d76e07aa24c84fb6f3ce6b7cd97592c9f5 (diff) | |
download | gcc-b0b3afb2f34492e2bf82b0bcad8d84d5c3a3a7f7.zip gcc-b0b3afb2f34492e2bf82b0bcad8d84d5c3a3a7f7.tar.gz gcc-b0b3afb2f34492e2bf82b0bcad8d84d5c3a3a7f7.tar.bz2 |
Constant folding for builtins
From-SVN: r37191
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/ChangeLog | 11 | ||||
-rw-r--r-- | gcc/builtins.c | 122 | ||||
-rw-r--r-- | gcc/c-typeck.c | 3 | ||||
-rw-r--r-- | gcc/cp/ChangeLog | 4 | ||||
-rw-r--r-- | gcc/cp/call.c | 2 | ||||
-rw-r--r-- | gcc/expr.h | 1 | ||||
-rw-r--r-- | gcc/fold-const.c | 13 |
7 files changed, 116 insertions, 40 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index c8b0dff..13a6999 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,14 @@ +2000-11-01 Bernd Schmidt <bernds@redhat.co.uk> + + * builtins.c (fold_builtin_constant_p, fold_builtin): New functions. + (expand_builtin_constant_p): Move parts of the code into + fold_builtin_constant_p. + (expand_builtin_strlen): Move parts of the code into fold_builtin. + * expr.h (fold_builtin): Declare. + * fold-const.c (fold): Handle builtin calls. + + * c-typeck.c (build_function_call): Call fold on the CALL_EXPR. + 2000-11-01 Richard Henderson <rth@redhat.com> * stmt.c (expand_start_null_loop): New. diff --git a/gcc/builtins.c b/gcc/builtins.c index abb6747..7b08013 100644 --- a/gcc/builtins.c +++ b/gcc/builtins.c @@ -116,6 +116,7 @@ static rtx expand_builtin_frame_address PARAMS ((tree)); static rtx expand_builtin_fputs PARAMS ((tree, int)); static tree stabilize_va_list PARAMS ((tree, int)); static rtx expand_builtin_expect PARAMS ((tree, rtx)); +static tree fold_builtin_constant_p PARAMS ((tree)); /* Return the alignment in bits of EXP, a pointer valued expression. But don't return more than MAX_ALIGN no matter what. @@ -1161,44 +1162,19 @@ expand_builtin_constant_p (exp) { tree arglist = TREE_OPERAND (exp, 1); enum machine_mode value_mode = TYPE_MODE (TREE_TYPE (exp)); + rtx tmp; if (arglist == 0) return const0_rtx; - else - { - tree arg = TREE_VALUE (arglist); - rtx tmp; - - /* We return 1 for a numeric type that's known to be a constant - value at compile-time or for an aggregate type that's a - literal constant. */ - STRIP_NOPS (arg); - - /* If we know this is a constant, emit the constant of one. */ - if (TREE_CODE_CLASS (TREE_CODE (arg)) == 'c' - || (TREE_CODE (arg) == CONSTRUCTOR - && TREE_CONSTANT (arg)) - || (TREE_CODE (arg) == ADDR_EXPR - && TREE_CODE (TREE_OPERAND (arg, 0)) == STRING_CST)) - return const1_rtx; - - /* If we aren't going to be running CSE or this expression - has side effects, show we don't know it to be a constant. - Likewise if it's a pointer or aggregate type since in those - case we only want literals, since those are only optimized - when generating RTL, not later. */ - if (TREE_SIDE_EFFECTS (arg) || cse_not_expected - || AGGREGATE_TYPE_P (TREE_TYPE (arg)) - || POINTER_TYPE_P (TREE_TYPE (arg))) - return const0_rtx; + arglist = TREE_VALUE (arglist); - /* Otherwise, emit (constant_p_rtx (ARG)) and let CSE get a - chance to see if it can deduce whether ARG is constant. */ + /* We have taken care of the easy cases during constant folding. This + case is not obvious, so emit (constant_p_rtx (ARGLIST)) and let CSE get a + chance to see if it can deduce whether ARGLIST is constant. */ - tmp = expand_expr (arg, NULL_RTX, VOIDmode, 0); - tmp = gen_rtx_CONSTANT_P_RTX (value_mode, tmp); - return tmp; - } + tmp = expand_expr (arglist, NULL_RTX, VOIDmode, 0); + tmp = gen_rtx_CONSTANT_P_RTX (value_mode, tmp); + return tmp; } /* Expand a call to one of the builtin math functions (sin, cos, or sqrt). @@ -1342,7 +1318,6 @@ expand_builtin_strlen (exp, target, mode) { rtx pat; tree src = TREE_VALUE (arglist); - tree len = c_strlen (src); int align = get_pointer_alignment (src, BIGGEST_ALIGNMENT) / BITS_PER_UNIT; @@ -1351,10 +1326,6 @@ expand_builtin_strlen (exp, target, mode) enum machine_mode insn_mode = value_mode, char_mode; enum insn_code icode = CODE_FOR_nothing; - /* If the length is known, just return it. */ - if (len != 0) - return expand_expr (len, target, mode, EXPAND_MEMORY_USE_BAD); - /* If SRC is not a pointer type, don't do this operation inline. */ if (align == 0) return 0; @@ -2814,3 +2785,78 @@ expand_builtin (exp, target, subtarget, mode, ignore) to be called normally. */ return expand_call (exp, target, ignore); } + +/* Fold a call to __builtin_constant_p, if we know it will evaluate to a + constant. ARGLIST is the argument list of the call. */ + +static tree +fold_builtin_constant_p (arglist) + tree arglist; +{ + if (arglist == 0) + return 0; + + arglist = TREE_VALUE (arglist); + + /* We return 1 for a numeric type that's known to be a constant + value at compile-time or for an aggregate type that's a + literal constant. */ + STRIP_NOPS (arglist); + + /* If we know this is a constant, emit the constant of one. */ + if (TREE_CODE_CLASS (TREE_CODE (arglist)) == 'c' + || (TREE_CODE (arglist) == CONSTRUCTOR + && TREE_CONSTANT (arglist)) + || (TREE_CODE (arglist) == ADDR_EXPR + && TREE_CODE (TREE_OPERAND (arglist, 0)) == STRING_CST)) + return integer_one_node; + + /* If we aren't going to be running CSE or this expression + has side effects, show we don't know it to be a constant. + Likewise if it's a pointer or aggregate type since in those + case we only want literals, since those are only optimized + when generating RTL, not later. */ + if (TREE_SIDE_EFFECTS (arglist) || cse_not_expected + || AGGREGATE_TYPE_P (TREE_TYPE (arglist)) + || POINTER_TYPE_P (TREE_TYPE (arglist))) + return integer_zero_node; + + return 0; +} + +/* Used by constant folding to eliminate some builtin calls early. EXP is + the CALL_EXPR of a call to a builtin function. */ + +tree +fold_builtin (exp) + tree exp; +{ + tree fndecl = TREE_OPERAND (TREE_OPERAND (exp, 0), 0); + tree arglist = TREE_OPERAND (exp, 1); + enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl); + + if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_MD) + return 0; + + switch (fcode) + { + case BUILT_IN_CONSTANT_P: + return fold_builtin_constant_p (arglist); + + case BUILT_IN_STRLEN: + if (arglist != 0 + /* Arg could be non-pointer if user redeclared this fcn wrong. */ + && TREE_CODE (TREE_TYPE (TREE_VALUE (arglist))) == POINTER_TYPE) + { + tree len = c_strlen (TREE_VALUE (arglist)); + if (len != 0) + return len; + } + break; + + default: + break; + } + + return 0; +} diff --git a/gcc/c-typeck.c b/gcc/c-typeck.c index acc2840..16dbc34 100644 --- a/gcc/c-typeck.c +++ b/gcc/c-typeck.c @@ -1567,8 +1567,9 @@ build_function_call (function, params) result = build (CALL_EXPR, TREE_TYPE (fntype), function, coerced_params, NULL_TREE); - TREE_SIDE_EFFECTS (result) = 1; + result = fold (result); + if (VOID_TYPE_P (TREE_TYPE (result))) return result; return require_complete_type (result); diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 0907b04..9846778 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,7 @@ +2000-11-01 Bernd Schmidt <bernds@redhat.co.uk> + + * call.c (build_over_call): Call fold on the CALL_EXPR. + 2000-11-01 Gabriel Dos Reis <gdr@codesourcery.com> * error.c (dump_template_decl): Separate template hearders with diff --git a/gcc/cp/call.c b/gcc/cp/call.c index ba77b64..4d2e7a1 100644 --- a/gcc/cp/call.c +++ b/gcc/cp/call.c @@ -4188,7 +4188,7 @@ build_over_call (cand, args, flags) return exp; } - fn = build_call (fn, converted_args); + fn = fold (build_call (fn, converted_args)); if (TREE_CODE (TREE_TYPE (fn)) == VOID_TYPE) return fn; fn = require_complete_type (fn); @@ -918,6 +918,7 @@ extern rtx gen_cond_trap PARAMS ((enum rtx_code, rtx, rtx, rtx)); /* Functions from builtins.c: */ #ifdef TREE_CODE extern rtx expand_builtin PARAMS ((tree, rtx, rtx, enum machine_mode, int)); +extern tree fold_builtin PARAMS ((tree)); extern tree expand_tree_builtin PARAMS ((tree, tree, tree)); extern void std_expand_builtin_va_start PARAMS ((int, tree, rtx)); extern rtx std_expand_builtin_va_arg PARAMS ((tree, tree)); diff --git a/gcc/fold-const.c b/gcc/fold-const.c index c5b29a4..25fd496 100644 --- a/gcc/fold-const.c +++ b/gcc/fold-const.c @@ -7168,6 +7168,19 @@ fold (expr) return t; } + case CALL_EXPR: + /* Check for a built-in function. */ + if (TREE_CODE (TREE_OPERAND (expr, 0)) == ADDR_EXPR + && (TREE_CODE (TREE_OPERAND (TREE_OPERAND (expr, 0), 0)) + == FUNCTION_DECL) + && DECL_BUILT_IN (TREE_OPERAND (TREE_OPERAND (expr, 0), 0))) + { + tree tmp = fold_builtin (expr); + if (tmp) + return tmp; + } + return t; + default: return t; } /* switch (code) */ |