aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorBernd Schmidt <bernds@redhat.co.uk>2000-11-01 17:02:45 +0000
committerBernd Schmidt <bernds@gcc.gnu.org>2000-11-01 17:02:45 +0000
commitb0b3afb2f34492e2bf82b0bcad8d84d5c3a3a7f7 (patch)
tree134205e79f38779f813ba6a5e2125ad69cafdd53 /gcc
parentf92351d76e07aa24c84fb6f3ce6b7cd97592c9f5 (diff)
downloadgcc-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/ChangeLog11
-rw-r--r--gcc/builtins.c122
-rw-r--r--gcc/c-typeck.c3
-rw-r--r--gcc/cp/ChangeLog4
-rw-r--r--gcc/cp/call.c2
-rw-r--r--gcc/expr.h1
-rw-r--r--gcc/fold-const.c13
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);
diff --git a/gcc/expr.h b/gcc/expr.h
index 8cb2836..d4256c2 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 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) */