Constant folding for builtins
From-SVN: r37191
This commit is contained in:
parent
f92351d76e
commit
b0b3afb2f3
@ -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.
|
||||
|
122
gcc/builtins.c
122
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;
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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));
|
||||
|
@ -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) */
|
||||
|
Loading…
Reference in New Issue
Block a user