From 185ebd6c71d791ea2f333a23382589620e9bf848 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Tue, 29 Dec 1998 03:36:22 -0800 Subject: [PATCH] Richard Kenner : * rtl.def (CONSTANT_P_RTX): Clarify commentary. * expr.c (expand_builtin, case BUILT_IN_CONSTANT_P): Rework to consider constant CONSTRUCTOR constant and to defer some cases to cse. * cse.c (fold_rtx, case CONST): Add handling for CONSTANT_P_RTX. * regclass.c (reg_scan_mark_refs, case CONST): Likewise. Richard Henderson * expr.c (init_expr_once): Kill can_handle_constant_p recognition. * cse.c (fold_rtx, case 'x'): Remove standalone CONSTANT_P_RTX code. From-SVN: r24439 --- gcc/ChangeLog | 20 ++++++++++++++++ gcc/cse.c | 21 ++++++++++++----- gcc/expr.c | 63 ++++++++++++++++++++++--------------------------- gcc/extend.texi | 52 ++++++++++++++++++++++++++++++++++++++++ gcc/regclass.c | 6 ++++- gcc/rtl.def | 7 +++--- 6 files changed, 124 insertions(+), 45 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 2d742399aaa8..cb230d9c80e6 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,23 @@ +Tue Dec 29 11:32:54 1998 Richard Kenner : + + * rtl.def (CONSTANT_P_RTX): Clarify commentary. + * expr.c (expand_builtin, case BUILT_IN_CONSTANT_P): Rework to + consider constant CONSTRUCTOR constant and to defer some cases + to cse. + * cse.c (fold_rtx, case CONST): Add handling for CONSTANT_P_RTX. + * regclass.c (reg_scan_mark_refs, case CONST): Likewise. + +Tue Dec 29 11:30:10 1998 Richard Henderson + + * expr.c (init_expr_once): Kill can_handle_constant_p recognition. + * cse.c (fold_rtx, case 'x'): Remove standalone CONSTANT_P_RTX code. + + * alpha.c (reg_or_6bit_operand): Remove CONSTANT_P_RTX handling. + (reg_or_8bit_operand, cint8_operand, add_operand): Likewise. + (sext_add_operand, and_operand, or_operand): Likewise. + (reg_or_cint_operand, some_operand, input_operand): Likewise. + * alpha.h (PREDICATE_CODES): Likewise. + Sat Dec 26 23:26:26 PST 1998 Jeff Law (law@cygnus.com) * version.c: Bump for snapshot. diff --git a/gcc/cse.c b/gcc/cse.c index 2ef26a5e934d..9ca293185be3 100644 --- a/gcc/cse.c +++ b/gcc/cse.c @@ -4931,6 +4931,21 @@ fold_rtx (x, insn) switch (code) { case CONST: + /* If the operand is a CONSTANT_P_RTX, see if what's inside it + is known to be constant and replace the whole thing with a + CONST_INT of either zero or one. Note that this code assumes + that an insn that recognizes a CONST will also recognize a + CONST_INT, but that seems to be a safe assumption. */ + if (GET_CODE (XEXP (x, 0)) == CONSTANT_P_RTX) + { + x = equiv_constant (fold_rtx (XEXP (XEXP (x, 0), 0), 0)); + return (x != 0 && (GET_CODE (x) == CONST_INT + || GET_CODE (x) == CONST_DOUBLE) + ? const1_rtx : const0_rtx); + } + + /* ... fall through ... */ + case CONST_INT: case CONST_DOUBLE: case SYMBOL_REF: @@ -5850,12 +5865,6 @@ fold_rtx (x, insn) const_arg1 ? const_arg1 : folded_arg1, const_arg2 ? const_arg2 : XEXP (x, 2)); break; - - case 'x': - /* Always eliminate CONSTANT_P_RTX at this stage. */ - if (code == CONSTANT_P_RTX) - return (const_arg0 ? const1_rtx : const0_rtx); - break; } return new ? new : x; diff --git a/gcc/expr.c b/gcc/expr.c index e943e53463e9..09a7eb1f16ad 100644 --- a/gcc/expr.c +++ b/gcc/expr.c @@ -101,11 +101,6 @@ static rtx saveregs_value; /* Similarly for __builtin_apply_args. */ static rtx apply_args_value; -/* Nonzero if the machine description has been fixed to accept - CONSTANT_P_RTX patterns. We will emit a warning and continue - if we find we must actually use such a beast. */ -static int can_handle_constant_p; - /* Don't check memory usage, since code is being emitted to check a memory usage. Used when current_function_check_memory_usage is true, to avoid infinite recursion. */ @@ -309,14 +304,6 @@ init_expr_once () } } - /* Find out if CONSTANT_P_RTX is accepted. */ - SET_DEST (pat) = gen_rtx_REG (TYPE_MODE (integer_type_node), - FIRST_PSEUDO_REGISTER); - SET_SRC (pat) = gen_rtx_CONSTANT_P_RTX (TYPE_MODE (integer_type_node), - SET_DEST (pat)); - if (recog (pat, insn, &num_clobbers) >= 0) - can_handle_constant_p = 1; - end_sequence (); obfree (free_point); } @@ -9010,36 +8997,42 @@ expand_builtin (exp, target, subtarget, mode, ignore) 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 (really_constant_p (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; - /* Only emit CONSTANT_P_RTX if CSE will be run. - Moreover, we don't want to expand trees that have side effects, - as the original __builtin_constant_p did not evaluate its - argument at all, and we would break existing usage by changing - this. This quirk was generally useful, eliminating a bit of hair - in the writing of the macros that use this function. Now the - same thing can be better accomplished in an inline function. */ + /* 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; - if (! cse_not_expected && ! TREE_SIDE_EFFECTS (arg)) - { - /* Lazy fixup of old code: issue a warning and fail the test. */ - if (! can_handle_constant_p) - { - warning ("Delayed evaluation of __builtin_constant_p not supported on this target."); - warning ("Please report this as a bug to egcs-bugs@cygnus.com."); - return const0_rtx; - } - return gen_rtx_CONSTANT_P_RTX (TYPE_MODE (integer_type_node), - expand_expr (arg, NULL_RTX, - VOIDmode, 0)); - } + /* Otherwise, emit (const (constant_p_rtx (ARG))) and let CSE + get a chance to see if it can deduce whether ARG is constant. */ + /* ??? We always generate the CONST in ptr_mode since that's + certain to be valid on this machine, then convert it to + whatever we need. */ - return const0_rtx; + tmp = expand_expr (arg, NULL_RTX, VOIDmode, 0); + tmp = gen_rtx_CONSTANT_P_RTX (ptr_mode, tmp); + tmp = gen_rtx_CONST (ptr_mode, tmp); + tmp = convert_to_mode (mode, tmp, 0); + return tmp; } case BUILT_IN_FRAME_ADDRESS: diff --git a/gcc/extend.texi b/gcc/extend.texi index cde383c78222..4389bee45838 100644 --- a/gcc/extend.texi +++ b/gcc/extend.texi @@ -64,6 +64,7 @@ C++ Language}, for extensions that apply @emph{only} to C++. * Function Names:: Printable strings which are the name of the current function. * Return Address:: Getting the return or frame address of a function. +* Other Builtins:: Other built-in functions. @end menu @end ifset @ifclear INTERNALS @@ -2904,6 +2905,7 @@ These functions may be used to get information about the callers of a function. @table @code +@findex __builtin_return_address @item __builtin_return_address (@var{level}) This function returns the return address of the current function, or of one of its callers. The @var{level} argument is number of frames to @@ -2920,6 +2922,7 @@ of the stack has been reached, this function will return @code{0}. This function should only be used with a non-zero argument for debugging purposes. +@findex __builtin_frame_address @item __builtin_frame_address (@var{level}) This function is similar to @code{__builtin_return_address}, but it returns the address of the function frame rather than the return address @@ -2940,6 +2943,55 @@ The caveats that apply to @code{__builtin_return_address} apply to this function as well. @end table +@node Other Builtins +@section Other built-in functions provided by GNU CC + +GNU CC provides a large number of built-in functions other than the ones +mentioned above. Some of these are for internal use in the processing +of exceptions or variable-length argument lists and will not be +documented here because they may change from time to time; we do not +recommend general use of these functions. + +The remaining functions are provided for optimization purposes. + +GNU CC includes builtin versions of many of the functions in the +standard C library. These will always be treated as having the same +meaning as the C library function even if you specify the +@samp{-fno-builtin} (@pxref{C Dialect Options}) option. These functions +correspond to the C library functions @code{alloca}, @code{ffs}, +@code{abs}, @code{fabsf}, @code{fabs}, @code{fabsl}, @code{labs}, +@code{memcpy}, @code{memcmp}, @code{strcmp}, @code{strcpy}, +@code{strlen}, @code{sqrtf}, @code{sqrt}, @code{sqrtl}, @code{sinf}, +@code{sin}, @code{sinl}, @code{cosf}, @code{cos}, and @code{cosl}. + +@findex __builtin_constant_p +You can use the builtin function @code{__builtin_constant_p} to +determine if a value is known to be constant at compile-time and hence +that GNU CC can perform constant-folding on expressions involving that +value. The argument of the function is the value to test. The function +returns the integer 1 if the argument is known to be a compile-time +constant and 0 if it is not known to be a compile-time constant. A +return of 0 does not indicate that the value is @emph{not} a constant, +but merely that GNU CC cannot prove it is a constant with the specified +value of the @samp{-O} option. + +You would typically use this function in an embedded application where +memory was a critical resource. If you have some complex calculation, +you may want it to be folded if it involves constants, but need to call +a function if it does not. For example: + +#define Scale_Value(X) \ + (__builtin_constant_p (X) ? ((X) * SCALE + OFFSET) : Scale (X)) +@end smallexample + +You may use this builtin function in either a macro or an inline +function. However, if you use it in an inlined function and pass an +argument of the function as the argument to the builtin, GNU CC will +never return 1 when you call the inline function with a string constant +or constructor expression (@pxref{Constructors}) and will not return 1 +when you pass a constant numeric value to the inline function unless you +specify the @samp{-O} option. + @node C++ Extensions @chapter Extensions to the C++ Language @cindex extensions, C++ language diff --git a/gcc/regclass.c b/gcc/regclass.c index b442cc266be3..489f8240407d 100644 --- a/gcc/regclass.c +++ b/gcc/regclass.c @@ -2032,8 +2032,12 @@ reg_scan_mark_refs (x, insn, note_flag, min_regno) code = GET_CODE (x); switch (code) { - case CONST_INT: case CONST: + if (GET_CODE (XEXP (x, 0)) == CONSTANT_P_RTX) + reg_scan_mark_refs (XEXP (XEXP (x, 0), 0), insn, note_flag, min_regno); + return; + + case CONST_INT: case CONST_DOUBLE: case CC0: case PC: diff --git a/gcc/rtl.def b/gcc/rtl.def index 5273fdffa8c7..8f47d406412a 100644 --- a/gcc/rtl.def +++ b/gcc/rtl.def @@ -850,9 +850,10 @@ DEF_RTL_EXPR(RANGE_VAR, "range_var", "eti", 'x') 0 is the live bitmap. Operand 1 is the original block number. */ DEF_RTL_EXPR(RANGE_LIVE, "range_live", "bi", 'x') -/* A unary `__builtin_constant_p' expression. These are only emitted - during RTL generation, and then only if optimize > 0. They are - eliminated by the first CSE pass. */ +/* A unary `__builtin_constant_p' expression. This RTL code may only be used + as an operand of a CONST. This pattern is only emitted during RTL + generation and then only if optimize > 0. It is converted by the first + CSE pass into the appropriate CONST_INT. */ DEF_RTL_EXPR(CONSTANT_P_RTX, "constant_p_rtx", "e", 'x') /*