From b0b3afb2f34492e2bf82b0bcad8d84d5c3a3a7f7 Mon Sep 17 00:00:00 2001 From: Bernd Schmidt Date: Wed, 1 Nov 2000 17:02:45 +0000 Subject: [PATCH] Constant folding for builtins From-SVN: r37191 --- gcc/ChangeLog | 11 +++++ gcc/builtins.c | 122 ++++++++++++++++++++++++++++++++--------------- gcc/c-typeck.c | 3 +- gcc/cp/ChangeLog | 4 ++ gcc/cp/call.c | 2 +- gcc/expr.h | 1 + gcc/fold-const.c | 13 +++++ 7 files changed, 116 insertions(+), 40 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index c8b0dff26d3..13a6999054f 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,14 @@ +2000-11-01 Bernd Schmidt + + * 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 * stmt.c (expand_start_null_loop): New. diff --git a/gcc/builtins.c b/gcc/builtins.c index abb67476cd6..7b080134d75 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; + 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 (arg); + /* 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. */ - /* 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; - - /* Otherwise, emit (constant_p_rtx (ARG)) and let CSE get a - chance to see if it can deduce whether ARG 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 acc2840ee73..16dbc34363b 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 0907b04dbd3..9846778eff8 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,7 @@ +2000-11-01 Bernd Schmidt + + * call.c (build_over_call): Call fold on the CALL_EXPR. + 2000-11-01 Gabriel Dos Reis * error.c (dump_template_decl): Separate template hearders with diff --git a/gcc/cp/call.c b/gcc/cp/call.c index ba77b6490dd..4d2e7a14bbc 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); diff --git a/gcc/expr.h b/gcc/expr.h index 8cb28361038..d4256c2b63f 100644 --- a/gcc/expr.h +++ b/gcc/expr.h @@ -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 c5b29a47242..25fd4964519 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) */