1991-11-27 15:45:36 +01:00
|
|
|
|
/* Subroutines used by or related to instruction recognition.
|
2000-02-26 15:26:24 +01:00
|
|
|
|
Copyright (C) 1987, 1988, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998
|
|
|
|
|
1999, 2000 Free Software Foundation, Inc.
|
1991-11-27 15:45:36 +01:00
|
|
|
|
|
|
|
|
|
This file is part of GNU CC.
|
|
|
|
|
|
|
|
|
|
GNU CC is free software; you can redistribute it and/or modify
|
|
|
|
|
it under the terms of the GNU General Public License as published by
|
|
|
|
|
the Free Software Foundation; either version 2, or (at your option)
|
|
|
|
|
any later version.
|
|
|
|
|
|
|
|
|
|
GNU CC is distributed in the hope that it will be useful,
|
|
|
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
|
GNU General Public License for more details.
|
|
|
|
|
|
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
|
|
|
along with GNU CC; see the file COPYING. If not, write to
|
1995-06-15 14:04:37 +02:00
|
|
|
|
the Free Software Foundation, 59 Temple Place - Suite 330,
|
|
|
|
|
Boston, MA 02111-1307, USA. */
|
1991-11-27 15:45:36 +01:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#include "config.h"
|
Major cutover to using system.h:
* Makefile.in (alias.o, bitmap.o, c-aux-info.o, c-common.o,
c-decl.o, c-iterate.o, c-lang.o, c-lex.o, c-pragma.o, c-typeck.o,
caller-save.o, calls.o, collect2.o, combine.o, cse.o, dbxout.o,
dwarf2out.o, dwarfout.o, emit-rtl.o, except.o, explow.o, expmed.o,
expr.o, final.o, flow.o, function.o, getpwd.o, global.o,
integrate.o, jump.o, local-alloc.o, loop.o, optabs.o, pexecute.o,
prefix.o, print-rtl.o, print-tree.o, profile.o, real.o, recog.o,
reg-stack.o, regclass.o, regmove.o, reload.o, reload1.o, reorg.o,
rtl.o, rtlanal.o, sdbout.o, stmt.o, stor-layout.o, stupid.o,
tlink.o, toplev.o, tree.o, unroll.o, varasm.o, xcoffout.o): Depend
on system.h.
* alias.c, bitmap.c, c-aux-info.c, c-common.c, c-decl.c,
c-iterate.c, c-lang.c, c-lex.c, c-pragma.c, c-typeck.c,
caller-save.c, calls.c, collect2.c, combine.c, cse.c, dbxout.c,
dwarf2out.c, dwarfout.c, emit-rtl.c, except.c, explow.c, expmed.c,
expr.c, final.c, flow.c, function.c, gcc.c, getpwd.c, global.c,
integrate.c, jump.c, local-alloc.c, loop.c, optabs.c, pexecute.c,
prefix.c, print-rtl.c, print-tree.c, profile.c, real.c, recog.c,
reg-stack.c, regclass.c, regmove.c, reload.c, reload1.c, reorg.c,
rtl.c, rtlanal.c, sched.c, sdbout.c, stmt.c, stor-layout.c,
stupid.c, tlink.c, toplev.c, tree.c, unroll.c, varasm.c,
xcoffout.c: Include system.h. Organize include ordering so
that stdarg/varargs comes before other system headers. Remove
spurious casts of functions assured of a prototype in system.h.
From-SVN: r18726
1998-03-20 15:58:42 +01:00
|
|
|
|
#include "system.h"
|
alias.c: Change all uses of gen_rtx(FOO...) to gen_rtx_FOO...
* alias.c: Change all uses of gen_rtx(FOO...) to gen_rtx_FOO;
change gen_rtx(expr...) to gen_rtx_fmt_foo(expr...).
* caller-save.c, calls.c, combine.c, cse.c: Likewise.
* dwarf2out.c, except.c, explow.c, expmed.c, expr.c: Likewise.
* final.c, flow.c, function.c, genpeep.c, haifa-sched.c: Likewise.
* halfpic.c, integrate.c, jump.c, local-alloc.c, loop.c: Likewise.
* profile.c, recog.c, reg-stack.c, regclass.c, regmove.c: Likewise.
* reload.c, reload1.c, reorg.c, sched.c, stmt.c, stupid.c: Likewise.
* unroll.c, varasm.c: Likewise.
* config/alpha/alpha.c, config/alpha/alpha.md: Likewise.
From-SVN: r17357
1998-01-15 00:10:50 +01:00
|
|
|
|
#include "rtl.h"
|
1999-09-20 12:00:03 +02:00
|
|
|
|
#include "tm_p.h"
|
1991-11-27 15:45:36 +01:00
|
|
|
|
#include "insn-config.h"
|
|
|
|
|
#include "insn-attr.h"
|
|
|
|
|
#include "insn-flags.h"
|
|
|
|
|
#include "insn-codes.h"
|
2000-05-28 04:17:59 +02:00
|
|
|
|
#include "hard-reg-set.h"
|
1991-11-27 15:45:36 +01:00
|
|
|
|
#include "recog.h"
|
|
|
|
|
#include "regs.h"
|
1999-08-09 16:00:21 +02:00
|
|
|
|
#include "function.h"
|
1991-11-27 15:45:36 +01:00
|
|
|
|
#include "flags.h"
|
|
|
|
|
#include "real.h"
|
1998-10-25 13:56:39 +01:00
|
|
|
|
#include "toplev.h"
|
1999-02-02 22:22:52 +01:00
|
|
|
|
#include "basic-block.h"
|
1999-08-31 22:37:09 +02:00
|
|
|
|
#include "output.h"
|
1991-11-27 15:45:36 +01:00
|
|
|
|
|
|
|
|
|
#ifndef STACK_PUSH_CODE
|
|
|
|
|
#ifdef STACK_GROWS_DOWNWARD
|
|
|
|
|
#define STACK_PUSH_CODE PRE_DEC
|
|
|
|
|
#else
|
|
|
|
|
#define STACK_PUSH_CODE PRE_INC
|
|
|
|
|
#endif
|
|
|
|
|
#endif
|
|
|
|
|
|
1999-01-19 22:55:35 +01:00
|
|
|
|
#ifndef STACK_POP_CODE
|
|
|
|
|
#ifdef STACK_GROWS_DOWNWARD
|
|
|
|
|
#define STACK_POP_CODE POST_INC
|
|
|
|
|
#else
|
|
|
|
|
#define STACK_POP_CODE POST_DEC
|
|
|
|
|
#endif
|
|
|
|
|
#endif
|
|
|
|
|
|
2000-01-17 16:37:04 +01:00
|
|
|
|
static void validate_replace_rtx_1 PARAMS ((rtx *, rtx, rtx, rtx));
|
|
|
|
|
static rtx *find_single_use_1 PARAMS ((rtx, rtx *));
|
|
|
|
|
static rtx *find_constant_term_loc PARAMS ((rtx *));
|
|
|
|
|
static int insn_invalid_p PARAMS ((rtx));
|
1991-11-27 15:45:36 +01:00
|
|
|
|
|
|
|
|
|
/* Nonzero means allow operands to be volatile.
|
|
|
|
|
This should be 0 if you are generating rtl, such as if you are calling
|
|
|
|
|
the functions in optabs.c and expmed.c (most of the time).
|
|
|
|
|
This should be 1 if all valid insns need to be recognized,
|
|
|
|
|
such as in regclass.c and final.c and reload.c.
|
|
|
|
|
|
|
|
|
|
init_recog and init_recog_no_volatile are responsible for setting this. */
|
|
|
|
|
|
|
|
|
|
int volatile_ok;
|
|
|
|
|
|
1999-09-12 03:51:28 +02:00
|
|
|
|
struct recog_data recog_data;
|
Makefile.in (insn-extract.o): Fix dependencies.
* Makefile.in (insn-extract.o): Fix dependencies.
* genextract.c (main): Generate includes for insn-config.h and
recog.h.
Delete generation of declarations which are now in recog.h.
* genrecog.c (main): Delete generation of definitions which are
now in recog.c.
* local-alloc.c (block_alloc): Use extract_insn and the variables
it sets up instead of looking up values by insn_code.
* recog.c (recog_operand, recog_operand_loc, recog_dup_loc,
recog_dup_num): Define here instead of generating the definition in
genrecog.c.
(recog_n_operands, recog_n_dups, recog_n_alternatives,
recog_operand_mode, recog_constraints, recog_operand_address_p):
New variables.
(extract_insn): New function.
* recog.h (extract_insn): Declare function.
(which_alternative, recog_n_operands, recog_n_dups,
recog_n_alternatives, recog_operand_mode, recog_constraints,
recog_operand_address_p): Declare variables.
* regclass.c (n_occurrences): New static function.
* reload.c (n_occurrences): Delete function.
(find_reloads): Use extract_insn.
* reload.h (n_occurrences): Delete declaration.
From-SVN: r23147
1998-10-17 03:28:57 +02:00
|
|
|
|
|
1998-12-04 13:55:59 +01:00
|
|
|
|
/* Contains a vector of operand_alternative structures for every operand.
|
|
|
|
|
Set up by preprocess_constraints. */
|
|
|
|
|
struct operand_alternative recog_op_alt[MAX_RECOG_OPERANDS][MAX_RECOG_ALTERNATIVES];
|
|
|
|
|
|
1991-11-27 15:45:36 +01:00
|
|
|
|
/* On return from `constrain_operands', indicate which alternative
|
|
|
|
|
was satisfied. */
|
|
|
|
|
|
|
|
|
|
int which_alternative;
|
|
|
|
|
|
|
|
|
|
/* Nonzero after end of reload pass.
|
|
|
|
|
Set to 1 or 0 by toplev.c.
|
|
|
|
|
Controls the significance of (SUBREG (MEM)). */
|
|
|
|
|
|
|
|
|
|
int reload_completed;
|
|
|
|
|
|
|
|
|
|
/* Initialize data used by the function `recog'.
|
|
|
|
|
This must be called once in the compilation of a function
|
|
|
|
|
before any insn recognition may be done in the function. */
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
init_recog_no_volatile ()
|
|
|
|
|
{
|
|
|
|
|
volatile_ok = 0;
|
|
|
|
|
}
|
|
|
|
|
|
1991-12-24 03:03:33 +01:00
|
|
|
|
void
|
1991-11-27 15:45:36 +01:00
|
|
|
|
init_recog ()
|
|
|
|
|
{
|
|
|
|
|
volatile_ok = 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Try recognizing the instruction INSN,
|
|
|
|
|
and return the code number that results.
|
1995-05-16 14:39:54 +02:00
|
|
|
|
Remember the code so that repeated calls do not
|
1991-11-27 15:45:36 +01:00
|
|
|
|
need to spend the time for actual rerecognition.
|
|
|
|
|
|
|
|
|
|
This function is the normal interface to instruction recognition.
|
|
|
|
|
The automatically-generated function `recog' is normally called
|
|
|
|
|
through this one. (The only exception is in combine.c.) */
|
|
|
|
|
|
|
|
|
|
int
|
|
|
|
|
recog_memoized (insn)
|
|
|
|
|
rtx insn;
|
|
|
|
|
{
|
|
|
|
|
if (INSN_CODE (insn) < 0)
|
1992-07-07 00:16:17 +02:00
|
|
|
|
INSN_CODE (insn) = recog (PATTERN (insn), insn, NULL_PTR);
|
1991-11-27 15:45:36 +01:00
|
|
|
|
return INSN_CODE (insn);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Check that X is an insn-body for an `asm' with operands
|
|
|
|
|
and that the operands mentioned in it are legitimate. */
|
|
|
|
|
|
|
|
|
|
int
|
|
|
|
|
check_asm_operands (x)
|
|
|
|
|
rtx x;
|
|
|
|
|
{
|
1999-01-15 19:43:47 +01:00
|
|
|
|
int noperands;
|
1991-11-27 15:45:36 +01:00
|
|
|
|
rtx *operands;
|
final.c (bb_str): Qualify a char* with the keyword `const'.
* final.c (bb_str): Qualify a char* with the keyword `const'.
(add_bb_string, final_scan_insn, output_asm_insn): Likewise.
* fix-header.c (read_scan_file): Likewise.
* genoutput.c (output_epilogue, process_template): Likewise.
* local-alloc.c (requires_inout, block_alloc): Likewise.
* output.h (output_asm_insn, assemble_string): Likewise.
* recog.c (recog_constraints, check_asm_operands,
decode_asm_operands, extract_insn, preprocess_constraints,
constrain_operands): Likewise.
* recog.h (operand_alternative, recog_constraints, insn_template,
insn_outfun, insn_operand_constraint, insn_name): Likewise.
* regclass.c (record_reg_classes, scan_one_insn): Likewise.
* regmove.c (find_matches): Likewise.
* reload.c (alternative_allows_memconst): Likewise.
* reload1.c (constraint_accepts_reg_p,
reload_cse_simplify_operands): Likewise.
* rtl.h (decode_asm_operands): Likewise.
* scan.h (fn_decl): Likewise.
* varasm.c (assemble_string): Likewise.
From-SVN: r24834
1999-01-23 20:45:50 +01:00
|
|
|
|
const char **constraints;
|
1991-11-27 15:45:36 +01:00
|
|
|
|
int i;
|
|
|
|
|
|
1999-01-15 19:43:47 +01:00
|
|
|
|
/* Post-reload, be more strict with things. */
|
|
|
|
|
if (reload_completed)
|
|
|
|
|
{
|
|
|
|
|
/* ??? Doh! We've not got the wrapping insn. Cook one up. */
|
|
|
|
|
extract_insn (make_insn_raw (x));
|
|
|
|
|
constrain_operands (1);
|
|
|
|
|
return which_alternative >= 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
noperands = asm_noperands (x);
|
1991-11-27 15:45:36 +01:00
|
|
|
|
if (noperands < 0)
|
|
|
|
|
return 0;
|
|
|
|
|
if (noperands == 0)
|
|
|
|
|
return 1;
|
|
|
|
|
|
|
|
|
|
operands = (rtx *) alloca (noperands * sizeof (rtx));
|
final.c (bb_str): Qualify a char* with the keyword `const'.
* final.c (bb_str): Qualify a char* with the keyword `const'.
(add_bb_string, final_scan_insn, output_asm_insn): Likewise.
* fix-header.c (read_scan_file): Likewise.
* genoutput.c (output_epilogue, process_template): Likewise.
* local-alloc.c (requires_inout, block_alloc): Likewise.
* output.h (output_asm_insn, assemble_string): Likewise.
* recog.c (recog_constraints, check_asm_operands,
decode_asm_operands, extract_insn, preprocess_constraints,
constrain_operands): Likewise.
* recog.h (operand_alternative, recog_constraints, insn_template,
insn_outfun, insn_operand_constraint, insn_name): Likewise.
* regclass.c (record_reg_classes, scan_one_insn): Likewise.
* regmove.c (find_matches): Likewise.
* reload.c (alternative_allows_memconst): Likewise.
* reload1.c (constraint_accepts_reg_p,
reload_cse_simplify_operands): Likewise.
* rtl.h (decode_asm_operands): Likewise.
* scan.h (fn_decl): Likewise.
* varasm.c (assemble_string): Likewise.
From-SVN: r24834
1999-01-23 20:45:50 +01:00
|
|
|
|
constraints = (const char **) alloca (noperands * sizeof (char *));
|
1999-01-15 19:43:47 +01:00
|
|
|
|
|
|
|
|
|
decode_asm_operands (x, operands, NULL_PTR, constraints, NULL_PTR);
|
1991-11-27 15:45:36 +01:00
|
|
|
|
|
|
|
|
|
for (i = 0; i < noperands; i++)
|
1999-01-15 19:43:47 +01:00
|
|
|
|
{
|
final.c (bb_str): Qualify a char* with the keyword `const'.
* final.c (bb_str): Qualify a char* with the keyword `const'.
(add_bb_string, final_scan_insn, output_asm_insn): Likewise.
* fix-header.c (read_scan_file): Likewise.
* genoutput.c (output_epilogue, process_template): Likewise.
* local-alloc.c (requires_inout, block_alloc): Likewise.
* output.h (output_asm_insn, assemble_string): Likewise.
* recog.c (recog_constraints, check_asm_operands,
decode_asm_operands, extract_insn, preprocess_constraints,
constrain_operands): Likewise.
* recog.h (operand_alternative, recog_constraints, insn_template,
insn_outfun, insn_operand_constraint, insn_name): Likewise.
* regclass.c (record_reg_classes, scan_one_insn): Likewise.
* regmove.c (find_matches): Likewise.
* reload.c (alternative_allows_memconst): Likewise.
* reload1.c (constraint_accepts_reg_p,
reload_cse_simplify_operands): Likewise.
* rtl.h (decode_asm_operands): Likewise.
* scan.h (fn_decl): Likewise.
* varasm.c (assemble_string): Likewise.
From-SVN: r24834
1999-01-23 20:45:50 +01:00
|
|
|
|
const char *c = constraints[i];
|
1999-02-01 21:03:23 +01:00
|
|
|
|
if (c[0] == '%')
|
|
|
|
|
c++;
|
|
|
|
|
if (ISDIGIT ((unsigned char)c[0]) && c[1] == '\0')
|
1999-01-15 19:43:47 +01:00
|
|
|
|
c = constraints[c[0] - '0'];
|
|
|
|
|
|
|
|
|
|
if (! asm_operand_ok (operands[i], c))
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
1991-11-27 15:45:36 +01:00
|
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
|
1998-08-19 14:30:47 +02:00
|
|
|
|
/* Static data for the next two routines. */
|
1991-11-27 15:45:36 +01:00
|
|
|
|
|
1998-08-19 14:30:47 +02:00
|
|
|
|
typedef struct change_t
|
|
|
|
|
{
|
|
|
|
|
rtx object;
|
|
|
|
|
int old_code;
|
|
|
|
|
rtx *loc;
|
|
|
|
|
rtx old;
|
|
|
|
|
} change_t;
|
1991-11-27 15:45:36 +01:00
|
|
|
|
|
1998-08-19 14:30:47 +02:00
|
|
|
|
static change_t *changes;
|
|
|
|
|
static int changes_allocated;
|
1991-11-27 15:45:36 +01:00
|
|
|
|
|
|
|
|
|
static int num_changes = 0;
|
|
|
|
|
|
|
|
|
|
/* Validate a proposed change to OBJECT. LOC is the location in the rtl for
|
|
|
|
|
at which NEW will be placed. If OBJECT is zero, no validation is done,
|
|
|
|
|
the change is simply made.
|
|
|
|
|
|
|
|
|
|
Two types of objects are supported: If OBJECT is a MEM, memory_address_p
|
|
|
|
|
will be called with the address and mode as parameters. If OBJECT is
|
|
|
|
|
an INSN, CALL_INSN, or JUMP_INSN, the insn will be re-recognized with
|
|
|
|
|
the change in place.
|
|
|
|
|
|
|
|
|
|
IN_GROUP is non-zero if this is part of a group of changes that must be
|
|
|
|
|
performed as a group. In that case, the changes will be stored. The
|
|
|
|
|
function `apply_change_group' will validate and apply the changes.
|
|
|
|
|
|
|
|
|
|
If IN_GROUP is zero, this is a single change. Try to recognize the insn
|
|
|
|
|
or validate the memory reference with the change applied. If the result
|
|
|
|
|
is not valid for the machine, suppress the change and return zero.
|
|
|
|
|
Otherwise, perform the change and return 1. */
|
|
|
|
|
|
|
|
|
|
int
|
|
|
|
|
validate_change (object, loc, new, in_group)
|
|
|
|
|
rtx object;
|
|
|
|
|
rtx *loc;
|
|
|
|
|
rtx new;
|
|
|
|
|
int in_group;
|
|
|
|
|
{
|
|
|
|
|
rtx old = *loc;
|
|
|
|
|
|
|
|
|
|
if (old == new || rtx_equal_p (old, new))
|
|
|
|
|
return 1;
|
|
|
|
|
|
1998-08-19 14:30:47 +02:00
|
|
|
|
if (in_group == 0 && num_changes != 0)
|
1991-11-27 15:45:36 +01:00
|
|
|
|
abort ();
|
|
|
|
|
|
|
|
|
|
*loc = new;
|
|
|
|
|
|
|
|
|
|
/* Save the information describing this change. */
|
1998-08-19 14:30:47 +02:00
|
|
|
|
if (num_changes >= changes_allocated)
|
|
|
|
|
{
|
|
|
|
|
if (changes_allocated == 0)
|
|
|
|
|
/* This value allows for repeated substitutions inside complex
|
|
|
|
|
indexed addresses, or changes in up to 5 insns. */
|
|
|
|
|
changes_allocated = MAX_RECOG_OPERANDS * 5;
|
|
|
|
|
else
|
|
|
|
|
changes_allocated *= 2;
|
|
|
|
|
|
|
|
|
|
changes =
|
|
|
|
|
(change_t*) xrealloc (changes,
|
|
|
|
|
sizeof (change_t) * changes_allocated);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
changes[num_changes].object = object;
|
|
|
|
|
changes[num_changes].loc = loc;
|
|
|
|
|
changes[num_changes].old = old;
|
1991-11-27 15:45:36 +01:00
|
|
|
|
|
|
|
|
|
if (object && GET_CODE (object) != MEM)
|
|
|
|
|
{
|
|
|
|
|
/* Set INSN_CODE to force rerecognition of insn. Save old code in
|
|
|
|
|
case invalid. */
|
1998-08-19 14:30:47 +02:00
|
|
|
|
changes[num_changes].old_code = INSN_CODE (object);
|
1991-11-27 15:45:36 +01:00
|
|
|
|
INSN_CODE (object) = -1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
num_changes++;
|
|
|
|
|
|
|
|
|
|
/* If we are making a group of changes, return 1. Otherwise, validate the
|
|
|
|
|
change group we made. */
|
|
|
|
|
|
|
|
|
|
if (in_group)
|
|
|
|
|
return 1;
|
|
|
|
|
else
|
|
|
|
|
return apply_change_group ();
|
|
|
|
|
}
|
|
|
|
|
|
1998-10-23 01:08:26 +02:00
|
|
|
|
/* This subroutine of apply_change_group verifies whether the changes to INSN
|
|
|
|
|
were valid; i.e. whether INSN can still be recognized. */
|
|
|
|
|
|
|
|
|
|
static int
|
|
|
|
|
insn_invalid_p (insn)
|
|
|
|
|
rtx insn;
|
|
|
|
|
{
|
|
|
|
|
int icode = recog_memoized (insn);
|
|
|
|
|
int is_asm = icode < 0 && asm_noperands (PATTERN (insn)) >= 0;
|
|
|
|
|
|
1998-11-04 22:25:00 +01:00
|
|
|
|
if (is_asm && ! check_asm_operands (PATTERN (insn)))
|
|
|
|
|
return 1;
|
|
|
|
|
if (! is_asm && icode < 0)
|
1998-10-23 01:08:26 +02:00
|
|
|
|
return 1;
|
|
|
|
|
|
|
|
|
|
/* After reload, verify that all constraints are satisfied. */
|
|
|
|
|
if (reload_completed)
|
|
|
|
|
{
|
1998-11-04 22:25:00 +01:00
|
|
|
|
extract_insn (insn);
|
1998-10-23 01:08:26 +02:00
|
|
|
|
|
1998-11-04 22:25:00 +01:00
|
|
|
|
if (! constrain_operands (1))
|
1998-10-23 01:08:26 +02:00
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
1991-11-27 15:45:36 +01:00
|
|
|
|
/* Apply a group of changes previously issued with `validate_change'.
|
|
|
|
|
Return 1 if all changes are valid, zero otherwise. */
|
|
|
|
|
|
|
|
|
|
int
|
|
|
|
|
apply_change_group ()
|
|
|
|
|
{
|
|
|
|
|
int i;
|
|
|
|
|
|
|
|
|
|
/* The changes have been applied and all INSN_CODEs have been reset to force
|
|
|
|
|
rerecognition.
|
|
|
|
|
|
|
|
|
|
The changes are valid if we aren't given an object, or if we are
|
|
|
|
|
given a MEM and it still is a valid address, or if this is in insn
|
|
|
|
|
and it is recognized. In the latter case, if reload has completed,
|
|
|
|
|
we also require that the operands meet the constraints for
|
1998-11-04 22:25:00 +01:00
|
|
|
|
the insn. */
|
1991-11-27 15:45:36 +01:00
|
|
|
|
|
|
|
|
|
for (i = 0; i < num_changes; i++)
|
|
|
|
|
{
|
1998-08-19 14:30:47 +02:00
|
|
|
|
rtx object = changes[i].object;
|
1991-11-27 15:45:36 +01:00
|
|
|
|
|
|
|
|
|
if (object == 0)
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
if (GET_CODE (object) == MEM)
|
|
|
|
|
{
|
|
|
|
|
if (! memory_address_p (GET_MODE (object), XEXP (object, 0)))
|
|
|
|
|
break;
|
|
|
|
|
}
|
1998-10-23 01:08:26 +02:00
|
|
|
|
else if (insn_invalid_p (object))
|
1991-11-27 15:45:36 +01:00
|
|
|
|
{
|
|
|
|
|
rtx pat = PATTERN (object);
|
|
|
|
|
|
|
|
|
|
/* Perhaps we couldn't recognize the insn because there were
|
|
|
|
|
extra CLOBBERs at the end. If so, try to re-recognize
|
|
|
|
|
without the last CLOBBER (later iterations will cause each of
|
|
|
|
|
them to be eliminated, in turn). But don't do this if we
|
|
|
|
|
have an ASM_OPERAND. */
|
|
|
|
|
if (GET_CODE (pat) == PARALLEL
|
|
|
|
|
&& GET_CODE (XVECEXP (pat, 0, XVECLEN (pat, 0) - 1)) == CLOBBER
|
|
|
|
|
&& asm_noperands (PATTERN (object)) < 0)
|
|
|
|
|
{
|
|
|
|
|
rtx newpat;
|
|
|
|
|
|
|
|
|
|
if (XVECLEN (pat, 0) == 2)
|
|
|
|
|
newpat = XVECEXP (pat, 0, 0);
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
int j;
|
|
|
|
|
|
1999-09-07 07:49:18 +02:00
|
|
|
|
newpat
|
|
|
|
|
= gen_rtx_PARALLEL (VOIDmode,
|
|
|
|
|
gen_rtvec (XVECLEN (pat, 0) - 1));
|
1991-11-27 15:45:36 +01:00
|
|
|
|
for (j = 0; j < XVECLEN (newpat, 0); j++)
|
|
|
|
|
XVECEXP (newpat, 0, j) = XVECEXP (pat, 0, j);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Add a new change to this group to replace the pattern
|
|
|
|
|
with this new pattern. Then consider this change
|
|
|
|
|
as having succeeded. The change we added will
|
|
|
|
|
cause the entire call to fail if things remain invalid.
|
|
|
|
|
|
|
|
|
|
Note that this can lose if a later change than the one
|
|
|
|
|
we are processing specified &XVECEXP (PATTERN (object), 0, X)
|
|
|
|
|
but this shouldn't occur. */
|
|
|
|
|
|
|
|
|
|
validate_change (object, &PATTERN (object), newpat, 1);
|
|
|
|
|
}
|
|
|
|
|
else if (GET_CODE (pat) == USE || GET_CODE (pat) == CLOBBER)
|
|
|
|
|
/* If this insn is a CLOBBER or USE, it is always valid, but is
|
|
|
|
|
never recognized. */
|
|
|
|
|
continue;
|
|
|
|
|
else
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (i == num_changes)
|
|
|
|
|
{
|
|
|
|
|
num_changes = 0;
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
cancel_changes (0);
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Return the number of changes so far in the current group. */
|
|
|
|
|
|
|
|
|
|
int
|
|
|
|
|
num_validated_changes ()
|
|
|
|
|
{
|
|
|
|
|
return num_changes;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Retract the changes numbered NUM and up. */
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
cancel_changes (num)
|
|
|
|
|
int num;
|
|
|
|
|
{
|
|
|
|
|
int i;
|
|
|
|
|
|
|
|
|
|
/* Back out all the changes. Do this in the opposite order in which
|
|
|
|
|
they were made. */
|
|
|
|
|
for (i = num_changes - 1; i >= num; i--)
|
|
|
|
|
{
|
1998-08-19 14:30:47 +02:00
|
|
|
|
*changes[i].loc = changes[i].old;
|
|
|
|
|
if (changes[i].object && GET_CODE (changes[i].object) != MEM)
|
|
|
|
|
INSN_CODE (changes[i].object) = changes[i].old_code;
|
1991-11-27 15:45:36 +01:00
|
|
|
|
}
|
|
|
|
|
num_changes = num;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Replace every occurrence of FROM in X with TO. Mark each change with
|
|
|
|
|
validate_change passing OBJECT. */
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
validate_replace_rtx_1 (loc, from, to, object)
|
|
|
|
|
rtx *loc;
|
|
|
|
|
rtx from, to, object;
|
|
|
|
|
{
|
|
|
|
|
register int i, j;
|
rtl.h (rtx_format): Constify a char*.
* rtl.h (rtx_format): Constify a char*.
* rtl.c (rtx_format): Likewise.
(copy_rtx, copy_most_rtx, read_rtx): Likewise.
(init_rtl): Use accessor macro, not `rtx_format'.
* alias.c (rtx_equal_for_memref_p, find_symbolic_term): Constify a
char*.
* caller-save.c (mark_referenced_regs): Likewise.
* combine.c (subst, make_compound_operation, known_cond,
gen_rtx_combine, update_table_tick, get_last_value_validate,
use_crosses_set_p, mark_used_regs_combine, move_deaths): Likewise.
* cse.c (rtx_cost, mention_regs, canon_hash, exp_equiv_p,
refers_to_p, canon_reg, fold_rtx, cse_process_notes,
count_reg_usage): Likewise.
* emit-rtl.c (gen_rtx, copy_rtx_if_shared, reset_used_flags):
Likewise.
* final.c (leaf_renumber_regs_insn): Likewise.
* flow.c (mark_used_regs, find_use_as_address, dump_flow_info,
dump_edge_info, count_reg_references): Likewise.
* function.c (fixup_var_refs_1, walk_fixup_memory_subreg,
fixup_stack_1, purge_addressof_1, instantiate_virtual_regs_1):
Likewise.
* gcse.c (oprs_unchanged_p, hash_expr_1, expr_equiv_p,
oprs_not_set_p, expr_killed_p, compute_transp, find_used_regs,
add_label_notes): Likewise.
* genattrtab.c (attr_rtx, attr_copy_rtx, encode_units_mask,
clear_struct_flag, count_sub_rtxs, count_alternatives,
compares_alternatives_p, contained_in_p, walk_attr_value,
write_expr_attr_cache): Likewise.
* genconfig.c (walk_insn_part): Likewise.
* genemit.c (max_operand_1, gen_exp): Likewise.
* genextract.c (walk_rtx): Likewise.
* genflags.c (num_operands): Likewise.
* genoutput.c (scan_operands): Likewise.
* genpeep.c (match_rtx): Likewise.
* genrecog.c (add_to_sequence): Likewise.
* haifa-sched.c (may_trap_exp, sched_analyze_2, attach_deaths):
Likewise.
* integrate.c (save_constants, copy_for_inline,
copy_rtx_and_substitute, subst_constants, restore_constants):
Likewise.
* jump.c (mark_jump_label, invert_exp, redirect_exp,
rtx_renumbered_equal_p, rtx_equal_for_thread_p): Likewise.
* local-alloc.c (contains_replace_regs, memref_referenced_p):
Likewise.
* loop.c (record_excess_regs, rtx_equal_for_loop_p,
add_label_notes, replace_call_address, count_nonfixed_reads,
invariant_p, find_single_use_in_loop, find_mem_givs,
find_life_end, maybe_eliminate_biv_1, update_reg_last_use):
Likewise.
* print-rtl.c (reg_names, print_rtx): Likewise.
* recog.c (validate_replace_rtx_1, find_single_use_1): Likewise.
* reg-stack.c (stack_regs_mentioned_p, record_label_references,
record_reg_life_pat, swap_rtx_condition, goto_block_pat,
print_blocks): Likewise.
* regclass.c (fix_register, record_address_regs,
reg_scan_mark_refs): Likewise.
* regmove.c (stable_but_for_p): Likewise.
* reload.c (loc_mentioned_in_p, operands_match_p,
find_reloads_toplevsubst_reg_equivs, find_reloads_address_1,
copy_replacements, refers_to_regno_for_reload_p,
refers_to_mem_for_reload_p, find_inc_amount, regno_clobbered_p,
reload_when_needed_name, reg_class_names, debug_reload_to_stream):
Likewise.
* reload1.c (eliminate_regs, scan_paradoxical_subregs,
delete_address_reloads_1, count_occurrences,
reload_cse_mem_conflict_p, reload_combine_note_use,
add_auto_inc_notes): Likewise.
* resource.c (mark_referenced_resources, mark_set_resources):
Likewise.
* rtlanal.c (rtx_unstable_p, rtx_varies_p, rtx_addr_varies_p,
reg_mentioned_p, regs_set_between_p, modified_between_p,
modified_in_p, refers_to_regno_p, reg_overlap_mentioned_p,
rtx_equal_p, volatile_insn_p, volatile_refs_p, side_effects_p,
may_trap_p, inequality_comparisons_p, replace_rtx, replace_regs,
jmp_uses_reg_or_mem, for_each_rtx, regno_use_in): Likewise.
* sched.c (sched_analyze_2, attach_deaths): Likewise.
* stupid.c (stupid_mark_refs): Likewise.
* unroll.c (remap_split_bivs): Likewise.
* varasm.c (mark_constants): Likewise.
* a29k/a29k.c (uses_local_reg_p): Likewise.
* alpha/alpha.c (summarize_insn): Likewise.
* arm/arm.c (symbol_mentioned_p, label_mentioned_p,
eliminate_lr2ip): Likewise.
* arm/thumb.c (symbol_mentioned_p, label_mentioned_p): Likewise.
* i386/i386.c (symbolic_reference_mentioned_p, copy_all_rtx,
reg_mentioned_in_mem): Likewise.
* ns32k/ns32k.c (global_symbolic_reference_mentioned_p,
symbolic_reference_mentioned_p): Likewise.
* romp/romp.c (unsigned_comparisons_p, hash_rtx): Likewise.
* sh/sh.c (regs_used, mark_use): Likewise.
* vax/vax.c (vax_rtx_cost): Likewise.
From-SVN: r28784
1999-08-21 01:05:25 +02:00
|
|
|
|
register const char *fmt;
|
1991-11-27 15:45:36 +01:00
|
|
|
|
register rtx x = *loc;
|
|
|
|
|
enum rtx_code code = GET_CODE (x);
|
|
|
|
|
|
|
|
|
|
/* X matches FROM if it is the same rtx or they are both referring to the
|
|
|
|
|
same register in the same mode. Avoid calling rtx_equal_p unless the
|
|
|
|
|
operands look similar. */
|
|
|
|
|
|
|
|
|
|
if (x == from
|
|
|
|
|
|| (GET_CODE (x) == REG && GET_CODE (from) == REG
|
|
|
|
|
&& GET_MODE (x) == GET_MODE (from)
|
|
|
|
|
&& REGNO (x) == REGNO (from))
|
|
|
|
|
|| (GET_CODE (x) == GET_CODE (from) && GET_MODE (x) == GET_MODE (from)
|
|
|
|
|
&& rtx_equal_p (x, from)))
|
|
|
|
|
{
|
|
|
|
|
validate_change (object, loc, to, 1);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* For commutative or comparison operations, try replacing each argument
|
|
|
|
|
separately and seeing if we made any changes. If so, put a constant
|
|
|
|
|
argument last.*/
|
|
|
|
|
if (GET_RTX_CLASS (code) == '<' || GET_RTX_CLASS (code) == 'c')
|
|
|
|
|
{
|
|
|
|
|
int prev_changes = num_changes;
|
|
|
|
|
|
|
|
|
|
validate_replace_rtx_1 (&XEXP (x, 0), from, to, object);
|
|
|
|
|
validate_replace_rtx_1 (&XEXP (x, 1), from, to, object);
|
|
|
|
|
if (prev_changes != num_changes && CONSTANT_P (XEXP (x, 0)))
|
|
|
|
|
{
|
|
|
|
|
validate_change (object, loc,
|
alias.c: Change all uses of gen_rtx(FOO...) to gen_rtx_FOO...
* alias.c: Change all uses of gen_rtx(FOO...) to gen_rtx_FOO;
change gen_rtx(expr...) to gen_rtx_fmt_foo(expr...).
* caller-save.c, calls.c, combine.c, cse.c: Likewise.
* dwarf2out.c, except.c, explow.c, expmed.c, expr.c: Likewise.
* final.c, flow.c, function.c, genpeep.c, haifa-sched.c: Likewise.
* halfpic.c, integrate.c, jump.c, local-alloc.c, loop.c: Likewise.
* profile.c, recog.c, reg-stack.c, regclass.c, regmove.c: Likewise.
* reload.c, reload1.c, reorg.c, sched.c, stmt.c, stupid.c: Likewise.
* unroll.c, varasm.c: Likewise.
* config/alpha/alpha.c, config/alpha/alpha.md: Likewise.
From-SVN: r17357
1998-01-15 00:10:50 +01:00
|
|
|
|
gen_rtx_fmt_ee (GET_RTX_CLASS (code) == 'c' ? code
|
|
|
|
|
: swap_condition (code),
|
|
|
|
|
GET_MODE (x), XEXP (x, 1),
|
|
|
|
|
XEXP (x, 0)),
|
1991-11-27 15:45:36 +01:00
|
|
|
|
1);
|
|
|
|
|
x = *loc;
|
|
|
|
|
code = GET_CODE (x);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
1997-04-13 15:48:25 +02:00
|
|
|
|
/* Note that if CODE's RTX_CLASS is "c" or "<" we will have already
|
|
|
|
|
done the substitution, otherwise we won't. */
|
|
|
|
|
|
1991-11-27 15:45:36 +01:00
|
|
|
|
switch (code)
|
|
|
|
|
{
|
|
|
|
|
case PLUS:
|
1998-05-06 23:09:07 +02:00
|
|
|
|
/* If we have a PLUS whose second operand is now a CONST_INT, use
|
1991-11-27 15:45:36 +01:00
|
|
|
|
plus_constant to try to simplify it. */
|
|
|
|
|
if (GET_CODE (XEXP (x, 1)) == CONST_INT && XEXP (x, 1) == to)
|
1997-04-13 15:48:25 +02:00
|
|
|
|
validate_change (object, loc, plus_constant (XEXP (x, 0), INTVAL (to)),
|
|
|
|
|
1);
|
1991-11-27 15:45:36 +01:00
|
|
|
|
return;
|
1997-04-13 15:48:25 +02:00
|
|
|
|
|
|
|
|
|
case MINUS:
|
|
|
|
|
if (GET_CODE (to) == CONST_INT && XEXP (x, 1) == from)
|
|
|
|
|
{
|
|
|
|
|
validate_change (object, loc,
|
|
|
|
|
plus_constant (XEXP (x, 0), - INTVAL (to)),
|
|
|
|
|
1);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
break;
|
1991-11-27 15:45:36 +01:00
|
|
|
|
|
|
|
|
|
case ZERO_EXTEND:
|
|
|
|
|
case SIGN_EXTEND:
|
|
|
|
|
/* In these cases, the operation to be performed depends on the mode
|
|
|
|
|
of the operand. If we are replacing the operand with a VOIDmode
|
|
|
|
|
constant, we lose the information. So try to simplify the operation
|
|
|
|
|
in that case. If it fails, substitute in something that we know
|
1992-05-07 08:41:23 +02:00
|
|
|
|
won't be recognized. */
|
1991-11-27 15:45:36 +01:00
|
|
|
|
if (GET_MODE (to) == VOIDmode
|
|
|
|
|
&& (XEXP (x, 0) == from
|
|
|
|
|
|| (GET_CODE (XEXP (x, 0)) == REG && GET_CODE (from) == REG
|
|
|
|
|
&& GET_MODE (XEXP (x, 0)) == GET_MODE (from)
|
|
|
|
|
&& REGNO (XEXP (x, 0)) == REGNO (from))))
|
|
|
|
|
{
|
|
|
|
|
rtx new = simplify_unary_operation (code, GET_MODE (x), to,
|
|
|
|
|
GET_MODE (from));
|
|
|
|
|
if (new == 0)
|
alias.c: Change all uses of gen_rtx(FOO...) to gen_rtx_FOO...
* alias.c: Change all uses of gen_rtx(FOO...) to gen_rtx_FOO;
change gen_rtx(expr...) to gen_rtx_fmt_foo(expr...).
* caller-save.c, calls.c, combine.c, cse.c: Likewise.
* dwarf2out.c, except.c, explow.c, expmed.c, expr.c: Likewise.
* final.c, flow.c, function.c, genpeep.c, haifa-sched.c: Likewise.
* halfpic.c, integrate.c, jump.c, local-alloc.c, loop.c: Likewise.
* profile.c, recog.c, reg-stack.c, regclass.c, regmove.c: Likewise.
* reload.c, reload1.c, reorg.c, sched.c, stmt.c, stupid.c: Likewise.
* unroll.c, varasm.c: Likewise.
* config/alpha/alpha.c, config/alpha/alpha.md: Likewise.
From-SVN: r17357
1998-01-15 00:10:50 +01:00
|
|
|
|
new = gen_rtx_CLOBBER (GET_MODE (x), const0_rtx);
|
1991-11-27 15:45:36 +01:00
|
|
|
|
|
|
|
|
|
validate_change (object, loc, new, 1);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case SUBREG:
|
|
|
|
|
/* If we have a SUBREG of a register that we are replacing and we are
|
|
|
|
|
replacing it with a MEM, make a new MEM and try replacing the
|
|
|
|
|
SUBREG with it. Don't do this if the MEM has a mode-dependent address
|
|
|
|
|
or if we would be widening it. */
|
|
|
|
|
|
|
|
|
|
if (SUBREG_REG (x) == from
|
|
|
|
|
&& GET_CODE (from) == REG
|
|
|
|
|
&& GET_CODE (to) == MEM
|
|
|
|
|
&& ! mode_dependent_address_p (XEXP (to, 0))
|
|
|
|
|
&& ! MEM_VOLATILE_P (to)
|
|
|
|
|
&& GET_MODE_SIZE (GET_MODE (x)) <= GET_MODE_SIZE (GET_MODE (to)))
|
|
|
|
|
{
|
|
|
|
|
int offset = SUBREG_WORD (x) * UNITS_PER_WORD;
|
|
|
|
|
enum machine_mode mode = GET_MODE (x);
|
|
|
|
|
rtx new;
|
|
|
|
|
|
1994-11-16 22:10:09 +01:00
|
|
|
|
if (BYTES_BIG_ENDIAN)
|
|
|
|
|
offset += (MIN (UNITS_PER_WORD,
|
|
|
|
|
GET_MODE_SIZE (GET_MODE (SUBREG_REG (x))))
|
|
|
|
|
- MIN (UNITS_PER_WORD, GET_MODE_SIZE (mode)));
|
1991-11-27 15:45:36 +01:00
|
|
|
|
|
alias.c: Change all uses of gen_rtx(FOO...) to gen_rtx_FOO...
* alias.c: Change all uses of gen_rtx(FOO...) to gen_rtx_FOO;
change gen_rtx(expr...) to gen_rtx_fmt_foo(expr...).
* caller-save.c, calls.c, combine.c, cse.c: Likewise.
* dwarf2out.c, except.c, explow.c, expmed.c, expr.c: Likewise.
* final.c, flow.c, function.c, genpeep.c, haifa-sched.c: Likewise.
* halfpic.c, integrate.c, jump.c, local-alloc.c, loop.c: Likewise.
* profile.c, recog.c, reg-stack.c, regclass.c, regmove.c: Likewise.
* reload.c, reload1.c, reorg.c, sched.c, stmt.c, stupid.c: Likewise.
* unroll.c, varasm.c: Likewise.
* config/alpha/alpha.c, config/alpha/alpha.md: Likewise.
From-SVN: r17357
1998-01-15 00:10:50 +01:00
|
|
|
|
new = gen_rtx_MEM (mode, plus_constant (XEXP (to, 0), offset));
|
1999-01-19 11:32:33 +01:00
|
|
|
|
MEM_COPY_ATTRIBUTES (new, to);
|
1991-11-27 15:45:36 +01:00
|
|
|
|
validate_change (object, loc, new, 1);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case ZERO_EXTRACT:
|
|
|
|
|
case SIGN_EXTRACT:
|
|
|
|
|
/* If we are replacing a register with memory, try to change the memory
|
|
|
|
|
to be the mode required for memory in extract operations (this isn't
|
|
|
|
|
likely to be an insertion operation; if it was, nothing bad will
|
|
|
|
|
happen, we might just fail in some cases). */
|
|
|
|
|
|
|
|
|
|
if (XEXP (x, 0) == from && GET_CODE (from) == REG && GET_CODE (to) == MEM
|
|
|
|
|
&& GET_CODE (XEXP (x, 1)) == CONST_INT
|
|
|
|
|
&& GET_CODE (XEXP (x, 2)) == CONST_INT
|
|
|
|
|
&& ! mode_dependent_address_p (XEXP (to, 0))
|
|
|
|
|
&& ! MEM_VOLATILE_P (to))
|
|
|
|
|
{
|
|
|
|
|
enum machine_mode wanted_mode = VOIDmode;
|
|
|
|
|
enum machine_mode is_mode = GET_MODE (to);
|
|
|
|
|
int pos = INTVAL (XEXP (x, 2));
|
|
|
|
|
|
|
|
|
|
#ifdef HAVE_extzv
|
|
|
|
|
if (code == ZERO_EXTRACT)
|
1998-09-16 00:47:10 +02:00
|
|
|
|
{
|
1999-09-12 14:46:08 +02:00
|
|
|
|
wanted_mode = insn_data[(int) CODE_FOR_extzv].operand[1].mode;
|
1998-09-16 00:47:10 +02:00
|
|
|
|
if (wanted_mode == VOIDmode)
|
|
|
|
|
wanted_mode = word_mode;
|
|
|
|
|
}
|
1991-11-27 15:45:36 +01:00
|
|
|
|
#endif
|
|
|
|
|
#ifdef HAVE_extv
|
|
|
|
|
if (code == SIGN_EXTRACT)
|
1998-09-16 00:47:10 +02:00
|
|
|
|
{
|
1999-09-12 14:46:08 +02:00
|
|
|
|
wanted_mode = insn_data[(int) CODE_FOR_extv].operand[1].mode;
|
1998-09-16 00:47:10 +02:00
|
|
|
|
if (wanted_mode == VOIDmode)
|
|
|
|
|
wanted_mode = word_mode;
|
|
|
|
|
}
|
1991-11-27 15:45:36 +01:00
|
|
|
|
#endif
|
|
|
|
|
|
1992-05-07 08:41:23 +02:00
|
|
|
|
/* If we have a narrower mode, we can do something. */
|
1991-11-27 15:45:36 +01:00
|
|
|
|
if (wanted_mode != VOIDmode
|
|
|
|
|
&& GET_MODE_SIZE (wanted_mode) < GET_MODE_SIZE (is_mode))
|
|
|
|
|
{
|
|
|
|
|
int offset = pos / BITS_PER_UNIT;
|
|
|
|
|
rtx newmem;
|
|
|
|
|
|
|
|
|
|
/* If the bytes and bits are counted differently, we
|
|
|
|
|
must adjust the offset. */
|
1994-11-16 22:10:09 +01:00
|
|
|
|
if (BYTES_BIG_ENDIAN != BITS_BIG_ENDIAN)
|
|
|
|
|
offset = (GET_MODE_SIZE (is_mode) - GET_MODE_SIZE (wanted_mode)
|
|
|
|
|
- offset);
|
1991-11-27 15:45:36 +01:00
|
|
|
|
|
|
|
|
|
pos %= GET_MODE_BITSIZE (wanted_mode);
|
|
|
|
|
|
alias.c: Change all uses of gen_rtx(FOO...) to gen_rtx_FOO...
* alias.c: Change all uses of gen_rtx(FOO...) to gen_rtx_FOO;
change gen_rtx(expr...) to gen_rtx_fmt_foo(expr...).
* caller-save.c, calls.c, combine.c, cse.c: Likewise.
* dwarf2out.c, except.c, explow.c, expmed.c, expr.c: Likewise.
* final.c, flow.c, function.c, genpeep.c, haifa-sched.c: Likewise.
* halfpic.c, integrate.c, jump.c, local-alloc.c, loop.c: Likewise.
* profile.c, recog.c, reg-stack.c, regclass.c, regmove.c: Likewise.
* reload.c, reload1.c, reorg.c, sched.c, stmt.c, stupid.c: Likewise.
* unroll.c, varasm.c: Likewise.
* config/alpha/alpha.c, config/alpha/alpha.md: Likewise.
From-SVN: r17357
1998-01-15 00:10:50 +01:00
|
|
|
|
newmem = gen_rtx_MEM (wanted_mode,
|
|
|
|
|
plus_constant (XEXP (to, 0), offset));
|
1999-01-19 11:32:33 +01:00
|
|
|
|
MEM_COPY_ATTRIBUTES (newmem, to);
|
1991-11-27 15:45:36 +01:00
|
|
|
|
|
1992-07-07 00:16:17 +02:00
|
|
|
|
validate_change (object, &XEXP (x, 2), GEN_INT (pos), 1);
|
1991-11-27 15:45:36 +01:00
|
|
|
|
validate_change (object, &XEXP (x, 0), newmem, 1);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
break;
|
alias.c: Change all uses of gen_rtx(FOO...) to gen_rtx_FOO...
* alias.c: Change all uses of gen_rtx(FOO...) to gen_rtx_FOO;
change gen_rtx(expr...) to gen_rtx_fmt_foo(expr...).
* caller-save.c, calls.c, combine.c, cse.c: Likewise.
* dwarf2out.c, except.c, explow.c, expmed.c, expr.c: Likewise.
* final.c, flow.c, function.c, genpeep.c, haifa-sched.c: Likewise.
* halfpic.c, integrate.c, jump.c, local-alloc.c, loop.c: Likewise.
* profile.c, recog.c, reg-stack.c, regclass.c, regmove.c: Likewise.
* reload.c, reload1.c, reorg.c, sched.c, stmt.c, stupid.c: Likewise.
* unroll.c, varasm.c: Likewise.
* config/alpha/alpha.c, config/alpha/alpha.md: Likewise.
From-SVN: r17357
1998-01-15 00:10:50 +01:00
|
|
|
|
|
|
|
|
|
default:
|
|
|
|
|
break;
|
1991-11-27 15:45:36 +01:00
|
|
|
|
}
|
|
|
|
|
|
1998-01-25 22:00:42 +01:00
|
|
|
|
/* For commutative or comparison operations we've already performed
|
|
|
|
|
replacements. Don't try to perform them again. */
|
|
|
|
|
if (GET_RTX_CLASS (code) != '<' && GET_RTX_CLASS (code) != 'c')
|
1991-11-27 15:45:36 +01:00
|
|
|
|
{
|
1998-01-25 22:00:42 +01:00
|
|
|
|
fmt = GET_RTX_FORMAT (code);
|
|
|
|
|
for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
|
|
|
|
|
{
|
|
|
|
|
if (fmt[i] == 'e')
|
|
|
|
|
validate_replace_rtx_1 (&XEXP (x, i), from, to, object);
|
|
|
|
|
else if (fmt[i] == 'E')
|
|
|
|
|
for (j = XVECLEN (x, i) - 1; j >= 0; j--)
|
|
|
|
|
validate_replace_rtx_1 (&XVECEXP (x, i, j), from, to, object);
|
|
|
|
|
}
|
1991-11-27 15:45:36 +01:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Try replacing every occurrence of FROM in INSN with TO. After all
|
|
|
|
|
changes have been made, validate by seeing if INSN is still valid. */
|
|
|
|
|
|
|
|
|
|
int
|
|
|
|
|
validate_replace_rtx (from, to, insn)
|
|
|
|
|
rtx from, to, insn;
|
|
|
|
|
{
|
|
|
|
|
validate_replace_rtx_1 (&PATTERN (insn), from, to, insn);
|
|
|
|
|
return apply_change_group ();
|
|
|
|
|
}
|
1998-05-20 02:24:32 +02:00
|
|
|
|
|
1998-08-23 01:21:23 +02:00
|
|
|
|
/* Try replacing every occurrence of FROM in INSN with TO. After all
|
|
|
|
|
changes have been made, validate by seeing if INSN is still valid. */
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
validate_replace_rtx_group (from, to, insn)
|
|
|
|
|
rtx from, to, insn;
|
|
|
|
|
{
|
|
|
|
|
validate_replace_rtx_1 (&PATTERN (insn), from, to, insn);
|
|
|
|
|
}
|
|
|
|
|
|
1998-05-20 02:24:32 +02:00
|
|
|
|
/* Try replacing every occurrence of FROM in INSN with TO, avoiding
|
|
|
|
|
SET_DESTs. After all changes have been made, validate by seeing if
|
|
|
|
|
INSN is still valid. */
|
|
|
|
|
|
|
|
|
|
int
|
|
|
|
|
validate_replace_src (from, to, insn)
|
|
|
|
|
rtx from, to, insn;
|
|
|
|
|
{
|
|
|
|
|
if ((GET_CODE (insn) != INSN && GET_CODE (insn) != JUMP_INSN)
|
|
|
|
|
|| GET_CODE (PATTERN (insn)) != SET)
|
|
|
|
|
abort ();
|
|
|
|
|
|
|
|
|
|
validate_replace_rtx_1 (&SET_SRC (PATTERN (insn)), from, to, insn);
|
|
|
|
|
if (GET_CODE (SET_DEST (PATTERN (insn))) == MEM)
|
|
|
|
|
validate_replace_rtx_1 (&XEXP (SET_DEST (PATTERN (insn)), 0),
|
|
|
|
|
from, to, insn);
|
|
|
|
|
return apply_change_group ();
|
|
|
|
|
}
|
1991-11-27 15:45:36 +01:00
|
|
|
|
|
|
|
|
|
#ifdef HAVE_cc0
|
|
|
|
|
/* Return 1 if the insn using CC0 set by INSN does not contain
|
|
|
|
|
any ordered tests applied to the condition codes.
|
|
|
|
|
EQ and NE tests do not count. */
|
|
|
|
|
|
|
|
|
|
int
|
|
|
|
|
next_insn_tests_no_inequality (insn)
|
|
|
|
|
rtx insn;
|
|
|
|
|
{
|
|
|
|
|
register rtx next = next_cc0_user (insn);
|
|
|
|
|
|
|
|
|
|
/* If there is no next insn, we have to take the conservative choice. */
|
|
|
|
|
if (next == 0)
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
|
|
return ((GET_CODE (next) == JUMP_INSN
|
|
|
|
|
|| GET_CODE (next) == INSN
|
|
|
|
|
|| GET_CODE (next) == CALL_INSN)
|
|
|
|
|
&& ! inequality_comparisons_p (PATTERN (next)));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#if 0 /* This is useless since the insn that sets the cc's
|
|
|
|
|
must be followed immediately by the use of them. */
|
|
|
|
|
/* Return 1 if the CC value set up by INSN is not used. */
|
|
|
|
|
|
|
|
|
|
int
|
|
|
|
|
next_insns_test_no_inequality (insn)
|
|
|
|
|
rtx insn;
|
|
|
|
|
{
|
|
|
|
|
register rtx next = NEXT_INSN (insn);
|
|
|
|
|
|
|
|
|
|
for (; next != 0; next = NEXT_INSN (next))
|
|
|
|
|
{
|
|
|
|
|
if (GET_CODE (next) == CODE_LABEL
|
|
|
|
|
|| GET_CODE (next) == BARRIER)
|
|
|
|
|
return 1;
|
|
|
|
|
if (GET_CODE (next) == NOTE)
|
|
|
|
|
continue;
|
|
|
|
|
if (inequality_comparisons_p (PATTERN (next)))
|
|
|
|
|
return 0;
|
|
|
|
|
if (sets_cc0_p (PATTERN (next)) == 1)
|
|
|
|
|
return 1;
|
|
|
|
|
if (! reg_mentioned_p (cc0_rtx, PATTERN (next)))
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
/* This is used by find_single_use to locate an rtx that contains exactly one
|
|
|
|
|
use of DEST, which is typically either a REG or CC0. It returns a
|
|
|
|
|
pointer to the innermost rtx expression containing DEST. Appearances of
|
|
|
|
|
DEST that are being used to totally replace it are not counted. */
|
|
|
|
|
|
|
|
|
|
static rtx *
|
|
|
|
|
find_single_use_1 (dest, loc)
|
|
|
|
|
rtx dest;
|
|
|
|
|
rtx *loc;
|
|
|
|
|
{
|
|
|
|
|
rtx x = *loc;
|
|
|
|
|
enum rtx_code code = GET_CODE (x);
|
|
|
|
|
rtx *result = 0;
|
|
|
|
|
rtx *this_result;
|
|
|
|
|
int i;
|
rtl.h (rtx_format): Constify a char*.
* rtl.h (rtx_format): Constify a char*.
* rtl.c (rtx_format): Likewise.
(copy_rtx, copy_most_rtx, read_rtx): Likewise.
(init_rtl): Use accessor macro, not `rtx_format'.
* alias.c (rtx_equal_for_memref_p, find_symbolic_term): Constify a
char*.
* caller-save.c (mark_referenced_regs): Likewise.
* combine.c (subst, make_compound_operation, known_cond,
gen_rtx_combine, update_table_tick, get_last_value_validate,
use_crosses_set_p, mark_used_regs_combine, move_deaths): Likewise.
* cse.c (rtx_cost, mention_regs, canon_hash, exp_equiv_p,
refers_to_p, canon_reg, fold_rtx, cse_process_notes,
count_reg_usage): Likewise.
* emit-rtl.c (gen_rtx, copy_rtx_if_shared, reset_used_flags):
Likewise.
* final.c (leaf_renumber_regs_insn): Likewise.
* flow.c (mark_used_regs, find_use_as_address, dump_flow_info,
dump_edge_info, count_reg_references): Likewise.
* function.c (fixup_var_refs_1, walk_fixup_memory_subreg,
fixup_stack_1, purge_addressof_1, instantiate_virtual_regs_1):
Likewise.
* gcse.c (oprs_unchanged_p, hash_expr_1, expr_equiv_p,
oprs_not_set_p, expr_killed_p, compute_transp, find_used_regs,
add_label_notes): Likewise.
* genattrtab.c (attr_rtx, attr_copy_rtx, encode_units_mask,
clear_struct_flag, count_sub_rtxs, count_alternatives,
compares_alternatives_p, contained_in_p, walk_attr_value,
write_expr_attr_cache): Likewise.
* genconfig.c (walk_insn_part): Likewise.
* genemit.c (max_operand_1, gen_exp): Likewise.
* genextract.c (walk_rtx): Likewise.
* genflags.c (num_operands): Likewise.
* genoutput.c (scan_operands): Likewise.
* genpeep.c (match_rtx): Likewise.
* genrecog.c (add_to_sequence): Likewise.
* haifa-sched.c (may_trap_exp, sched_analyze_2, attach_deaths):
Likewise.
* integrate.c (save_constants, copy_for_inline,
copy_rtx_and_substitute, subst_constants, restore_constants):
Likewise.
* jump.c (mark_jump_label, invert_exp, redirect_exp,
rtx_renumbered_equal_p, rtx_equal_for_thread_p): Likewise.
* local-alloc.c (contains_replace_regs, memref_referenced_p):
Likewise.
* loop.c (record_excess_regs, rtx_equal_for_loop_p,
add_label_notes, replace_call_address, count_nonfixed_reads,
invariant_p, find_single_use_in_loop, find_mem_givs,
find_life_end, maybe_eliminate_biv_1, update_reg_last_use):
Likewise.
* print-rtl.c (reg_names, print_rtx): Likewise.
* recog.c (validate_replace_rtx_1, find_single_use_1): Likewise.
* reg-stack.c (stack_regs_mentioned_p, record_label_references,
record_reg_life_pat, swap_rtx_condition, goto_block_pat,
print_blocks): Likewise.
* regclass.c (fix_register, record_address_regs,
reg_scan_mark_refs): Likewise.
* regmove.c (stable_but_for_p): Likewise.
* reload.c (loc_mentioned_in_p, operands_match_p,
find_reloads_toplevsubst_reg_equivs, find_reloads_address_1,
copy_replacements, refers_to_regno_for_reload_p,
refers_to_mem_for_reload_p, find_inc_amount, regno_clobbered_p,
reload_when_needed_name, reg_class_names, debug_reload_to_stream):
Likewise.
* reload1.c (eliminate_regs, scan_paradoxical_subregs,
delete_address_reloads_1, count_occurrences,
reload_cse_mem_conflict_p, reload_combine_note_use,
add_auto_inc_notes): Likewise.
* resource.c (mark_referenced_resources, mark_set_resources):
Likewise.
* rtlanal.c (rtx_unstable_p, rtx_varies_p, rtx_addr_varies_p,
reg_mentioned_p, regs_set_between_p, modified_between_p,
modified_in_p, refers_to_regno_p, reg_overlap_mentioned_p,
rtx_equal_p, volatile_insn_p, volatile_refs_p, side_effects_p,
may_trap_p, inequality_comparisons_p, replace_rtx, replace_regs,
jmp_uses_reg_or_mem, for_each_rtx, regno_use_in): Likewise.
* sched.c (sched_analyze_2, attach_deaths): Likewise.
* stupid.c (stupid_mark_refs): Likewise.
* unroll.c (remap_split_bivs): Likewise.
* varasm.c (mark_constants): Likewise.
* a29k/a29k.c (uses_local_reg_p): Likewise.
* alpha/alpha.c (summarize_insn): Likewise.
* arm/arm.c (symbol_mentioned_p, label_mentioned_p,
eliminate_lr2ip): Likewise.
* arm/thumb.c (symbol_mentioned_p, label_mentioned_p): Likewise.
* i386/i386.c (symbolic_reference_mentioned_p, copy_all_rtx,
reg_mentioned_in_mem): Likewise.
* ns32k/ns32k.c (global_symbolic_reference_mentioned_p,
symbolic_reference_mentioned_p): Likewise.
* romp/romp.c (unsigned_comparisons_p, hash_rtx): Likewise.
* sh/sh.c (regs_used, mark_use): Likewise.
* vax/vax.c (vax_rtx_cost): Likewise.
From-SVN: r28784
1999-08-21 01:05:25 +02:00
|
|
|
|
const char *fmt;
|
1991-11-27 15:45:36 +01:00
|
|
|
|
|
|
|
|
|
switch (code)
|
|
|
|
|
{
|
|
|
|
|
case CONST_INT:
|
|
|
|
|
case CONST:
|
|
|
|
|
case LABEL_REF:
|
|
|
|
|
case SYMBOL_REF:
|
|
|
|
|
case CONST_DOUBLE:
|
|
|
|
|
case CLOBBER:
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
|
|
case SET:
|
|
|
|
|
/* If the destination is anything other than CC0, PC, a REG or a SUBREG
|
|
|
|
|
of a REG that occupies all of the REG, the insn uses DEST if
|
|
|
|
|
it is mentioned in the destination or the source. Otherwise, we
|
|
|
|
|
need just check the source. */
|
|
|
|
|
if (GET_CODE (SET_DEST (x)) != CC0
|
|
|
|
|
&& GET_CODE (SET_DEST (x)) != PC
|
|
|
|
|
&& GET_CODE (SET_DEST (x)) != REG
|
|
|
|
|
&& ! (GET_CODE (SET_DEST (x)) == SUBREG
|
|
|
|
|
&& GET_CODE (SUBREG_REG (SET_DEST (x))) == REG
|
|
|
|
|
&& (((GET_MODE_SIZE (GET_MODE (SUBREG_REG (SET_DEST (x))))
|
|
|
|
|
+ (UNITS_PER_WORD - 1)) / UNITS_PER_WORD)
|
|
|
|
|
== ((GET_MODE_SIZE (GET_MODE (SET_DEST (x)))
|
|
|
|
|
+ (UNITS_PER_WORD - 1)) / UNITS_PER_WORD))))
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
return find_single_use_1 (dest, &SET_SRC (x));
|
|
|
|
|
|
|
|
|
|
case MEM:
|
|
|
|
|
case SUBREG:
|
|
|
|
|
return find_single_use_1 (dest, &XEXP (x, 0));
|
alias.c: Change all uses of gen_rtx(FOO...) to gen_rtx_FOO...
* alias.c: Change all uses of gen_rtx(FOO...) to gen_rtx_FOO;
change gen_rtx(expr...) to gen_rtx_fmt_foo(expr...).
* caller-save.c, calls.c, combine.c, cse.c: Likewise.
* dwarf2out.c, except.c, explow.c, expmed.c, expr.c: Likewise.
* final.c, flow.c, function.c, genpeep.c, haifa-sched.c: Likewise.
* halfpic.c, integrate.c, jump.c, local-alloc.c, loop.c: Likewise.
* profile.c, recog.c, reg-stack.c, regclass.c, regmove.c: Likewise.
* reload.c, reload1.c, reorg.c, sched.c, stmt.c, stupid.c: Likewise.
* unroll.c, varasm.c: Likewise.
* config/alpha/alpha.c, config/alpha/alpha.md: Likewise.
From-SVN: r17357
1998-01-15 00:10:50 +01:00
|
|
|
|
|
|
|
|
|
default:
|
|
|
|
|
break;
|
1991-11-27 15:45:36 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* If it wasn't one of the common cases above, check each expression and
|
|
|
|
|
vector of this code. Look for a unique usage of DEST. */
|
|
|
|
|
|
|
|
|
|
fmt = GET_RTX_FORMAT (code);
|
|
|
|
|
for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
|
|
|
|
|
{
|
|
|
|
|
if (fmt[i] == 'e')
|
|
|
|
|
{
|
|
|
|
|
if (dest == XEXP (x, i)
|
|
|
|
|
|| (GET_CODE (dest) == REG && GET_CODE (XEXP (x, i)) == REG
|
|
|
|
|
&& REGNO (dest) == REGNO (XEXP (x, i))))
|
|
|
|
|
this_result = loc;
|
|
|
|
|
else
|
|
|
|
|
this_result = find_single_use_1 (dest, &XEXP (x, i));
|
|
|
|
|
|
|
|
|
|
if (result == 0)
|
|
|
|
|
result = this_result;
|
|
|
|
|
else if (this_result)
|
|
|
|
|
/* Duplicate usage. */
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
else if (fmt[i] == 'E')
|
|
|
|
|
{
|
|
|
|
|
int j;
|
|
|
|
|
|
|
|
|
|
for (j = XVECLEN (x, i) - 1; j >= 0; j--)
|
|
|
|
|
{
|
|
|
|
|
if (XVECEXP (x, i, j) == dest
|
|
|
|
|
|| (GET_CODE (dest) == REG
|
|
|
|
|
&& GET_CODE (XVECEXP (x, i, j)) == REG
|
|
|
|
|
&& REGNO (XVECEXP (x, i, j)) == REGNO (dest)))
|
|
|
|
|
this_result = loc;
|
|
|
|
|
else
|
|
|
|
|
this_result = find_single_use_1 (dest, &XVECEXP (x, i, j));
|
|
|
|
|
|
|
|
|
|
if (result == 0)
|
|
|
|
|
result = this_result;
|
|
|
|
|
else if (this_result)
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* See if DEST, produced in INSN, is used only a single time in the
|
|
|
|
|
sequel. If so, return a pointer to the innermost rtx expression in which
|
|
|
|
|
it is used.
|
|
|
|
|
|
|
|
|
|
If PLOC is non-zero, *PLOC is set to the insn containing the single use.
|
|
|
|
|
|
|
|
|
|
This routine will return usually zero either before flow is called (because
|
|
|
|
|
there will be no LOG_LINKS notes) or after reload (because the REG_DEAD
|
|
|
|
|
note can't be trusted).
|
|
|
|
|
|
|
|
|
|
If DEST is cc0_rtx, we look only at the next insn. In that case, we don't
|
|
|
|
|
care about REG_DEAD notes or LOG_LINKS.
|
|
|
|
|
|
|
|
|
|
Otherwise, we find the single use by finding an insn that has a
|
|
|
|
|
LOG_LINKS pointing at INSN and has a REG_DEAD note for DEST. If DEST is
|
|
|
|
|
only referenced once in that insn, we know that it must be the first
|
|
|
|
|
and last insn referencing DEST. */
|
|
|
|
|
|
|
|
|
|
rtx *
|
|
|
|
|
find_single_use (dest, insn, ploc)
|
|
|
|
|
rtx dest;
|
|
|
|
|
rtx insn;
|
|
|
|
|
rtx *ploc;
|
|
|
|
|
{
|
|
|
|
|
rtx next;
|
|
|
|
|
rtx *result;
|
|
|
|
|
rtx link;
|
|
|
|
|
|
|
|
|
|
#ifdef HAVE_cc0
|
|
|
|
|
if (dest == cc0_rtx)
|
|
|
|
|
{
|
|
|
|
|
next = NEXT_INSN (insn);
|
|
|
|
|
if (next == 0
|
|
|
|
|
|| (GET_CODE (next) != INSN && GET_CODE (next) != JUMP_INSN))
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
|
|
result = find_single_use_1 (dest, &PATTERN (next));
|
|
|
|
|
if (result && ploc)
|
|
|
|
|
*ploc = next;
|
|
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
if (reload_completed || reload_in_progress || GET_CODE (dest) != REG)
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
|
|
for (next = next_nonnote_insn (insn);
|
|
|
|
|
next != 0 && GET_CODE (next) != CODE_LABEL;
|
|
|
|
|
next = next_nonnote_insn (next))
|
|
|
|
|
if (GET_RTX_CLASS (GET_CODE (next)) == 'i' && dead_or_set_p (next, dest))
|
|
|
|
|
{
|
|
|
|
|
for (link = LOG_LINKS (next); link; link = XEXP (link, 1))
|
|
|
|
|
if (XEXP (link, 0) == insn)
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
if (link)
|
|
|
|
|
{
|
|
|
|
|
result = find_single_use_1 (dest, &PATTERN (next));
|
|
|
|
|
if (ploc)
|
|
|
|
|
*ploc = next;
|
|
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Return 1 if OP is a valid general operand for machine mode MODE.
|
|
|
|
|
This is either a register reference, a memory reference,
|
|
|
|
|
or a constant. In the case of a memory reference, the address
|
|
|
|
|
is checked for general validity for the target machine.
|
|
|
|
|
|
|
|
|
|
Register and memory references must have mode MODE in order to be valid,
|
|
|
|
|
but some constants have no machine mode and are valid for any mode.
|
|
|
|
|
|
|
|
|
|
If MODE is VOIDmode, OP is checked for validity for whatever mode
|
|
|
|
|
it has.
|
|
|
|
|
|
|
|
|
|
The main use of this function is as a predicate in match_operand
|
|
|
|
|
expressions in the machine description.
|
|
|
|
|
|
1992-05-07 08:41:23 +02:00
|
|
|
|
For an explanation of this function's behavior for registers of
|
1991-11-27 15:45:36 +01:00
|
|
|
|
class NO_REGS, see the comment for `register_operand'. */
|
|
|
|
|
|
|
|
|
|
int
|
|
|
|
|
general_operand (op, mode)
|
|
|
|
|
register rtx op;
|
|
|
|
|
enum machine_mode mode;
|
|
|
|
|
{
|
|
|
|
|
register enum rtx_code code = GET_CODE (op);
|
|
|
|
|
int mode_altering_drug = 0;
|
|
|
|
|
|
|
|
|
|
if (mode == VOIDmode)
|
|
|
|
|
mode = GET_MODE (op);
|
|
|
|
|
|
|
|
|
|
/* Don't accept CONST_INT or anything similar
|
|
|
|
|
if the caller wants something floating. */
|
|
|
|
|
if (GET_MODE (op) == VOIDmode && mode != VOIDmode
|
1992-10-11 21:27:23 +01:00
|
|
|
|
&& GET_MODE_CLASS (mode) != MODE_INT
|
|
|
|
|
&& GET_MODE_CLASS (mode) != MODE_PARTIAL_INT)
|
1991-11-27 15:45:36 +01:00
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
|
|
if (CONSTANT_P (op))
|
|
|
|
|
return ((GET_MODE (op) == VOIDmode || GET_MODE (op) == mode)
|
|
|
|
|
#ifdef LEGITIMATE_PIC_OPERAND_P
|
|
|
|
|
&& (! flag_pic || LEGITIMATE_PIC_OPERAND_P (op))
|
|
|
|
|
#endif
|
|
|
|
|
&& LEGITIMATE_CONSTANT_P (op));
|
|
|
|
|
|
|
|
|
|
/* Except for certain constants with VOIDmode, already checked for,
|
|
|
|
|
OP's mode must match MODE if MODE specifies a mode. */
|
|
|
|
|
|
|
|
|
|
if (GET_MODE (op) != mode)
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
|
|
if (code == SUBREG)
|
|
|
|
|
{
|
|
|
|
|
#ifdef INSN_SCHEDULING
|
|
|
|
|
/* On machines that have insn scheduling, we want all memory
|
|
|
|
|
reference to be explicit, so outlaw paradoxical SUBREGs. */
|
|
|
|
|
if (GET_CODE (SUBREG_REG (op)) == MEM
|
|
|
|
|
&& GET_MODE_SIZE (mode) > GET_MODE_SIZE (GET_MODE (SUBREG_REG (op))))
|
|
|
|
|
return 0;
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
op = SUBREG_REG (op);
|
|
|
|
|
code = GET_CODE (op);
|
|
|
|
|
#if 0
|
|
|
|
|
/* No longer needed, since (SUBREG (MEM...))
|
|
|
|
|
will load the MEM into a reload reg in the MEM's own mode. */
|
|
|
|
|
mode_altering_drug = 1;
|
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (code == REG)
|
|
|
|
|
/* A register whose class is NO_REGS is not a general operand. */
|
|
|
|
|
return (REGNO (op) >= FIRST_PSEUDO_REGISTER
|
|
|
|
|
|| REGNO_REG_CLASS (REGNO (op)) != NO_REGS);
|
|
|
|
|
|
|
|
|
|
if (code == MEM)
|
|
|
|
|
{
|
|
|
|
|
register rtx y = XEXP (op, 0);
|
2000-07-23 19:17:37 +02:00
|
|
|
|
|
1991-11-27 15:45:36 +01:00
|
|
|
|
if (! volatile_ok && MEM_VOLATILE_P (op))
|
|
|
|
|
return 0;
|
2000-07-23 19:17:37 +02:00
|
|
|
|
|
alias.c: Change all uses of gen_rtx(FOO...) to gen_rtx_FOO...
* alias.c: Change all uses of gen_rtx(FOO...) to gen_rtx_FOO;
change gen_rtx(expr...) to gen_rtx_fmt_foo(expr...).
* caller-save.c, calls.c, combine.c, cse.c: Likewise.
* dwarf2out.c, except.c, explow.c, expmed.c, expr.c: Likewise.
* final.c, flow.c, function.c, genpeep.c, haifa-sched.c: Likewise.
* halfpic.c, integrate.c, jump.c, local-alloc.c, loop.c: Likewise.
* profile.c, recog.c, reg-stack.c, regclass.c, regmove.c: Likewise.
* reload.c, reload1.c, reorg.c, sched.c, stmt.c, stupid.c: Likewise.
* unroll.c, varasm.c: Likewise.
* config/alpha/alpha.c, config/alpha/alpha.md: Likewise.
From-SVN: r17357
1998-01-15 00:10:50 +01:00
|
|
|
|
if (GET_CODE (y) == ADDRESSOF)
|
|
|
|
|
return 1;
|
2000-07-23 19:17:37 +02:00
|
|
|
|
|
1991-11-27 15:45:36 +01:00
|
|
|
|
/* Use the mem's mode, since it will be reloaded thus. */
|
|
|
|
|
mode = GET_MODE (op);
|
|
|
|
|
GO_IF_LEGITIMATE_ADDRESS (mode, y, win);
|
|
|
|
|
}
|
alias.c: Change all uses of gen_rtx(FOO...) to gen_rtx_FOO...
* alias.c: Change all uses of gen_rtx(FOO...) to gen_rtx_FOO;
change gen_rtx(expr...) to gen_rtx_fmt_foo(expr...).
* caller-save.c, calls.c, combine.c, cse.c: Likewise.
* dwarf2out.c, except.c, explow.c, expmed.c, expr.c: Likewise.
* final.c, flow.c, function.c, genpeep.c, haifa-sched.c: Likewise.
* halfpic.c, integrate.c, jump.c, local-alloc.c, loop.c: Likewise.
* profile.c, recog.c, reg-stack.c, regclass.c, regmove.c: Likewise.
* reload.c, reload1.c, reorg.c, sched.c, stmt.c, stupid.c: Likewise.
* unroll.c, varasm.c: Likewise.
* config/alpha/alpha.c, config/alpha/alpha.md: Likewise.
From-SVN: r17357
1998-01-15 00:10:50 +01:00
|
|
|
|
|
|
|
|
|
/* Pretend this is an operand for now; we'll run force_operand
|
|
|
|
|
on its replacement in fixup_var_refs_1. */
|
|
|
|
|
if (code == ADDRESSOF)
|
|
|
|
|
return 1;
|
|
|
|
|
|
1991-11-27 15:45:36 +01:00
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
|
|
win:
|
|
|
|
|
if (mode_altering_drug)
|
|
|
|
|
return ! mode_dependent_address_p (XEXP (op, 0));
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Return 1 if OP is a valid memory address for a memory reference
|
|
|
|
|
of mode MODE.
|
|
|
|
|
|
|
|
|
|
The main use of this function is as a predicate in match_operand
|
|
|
|
|
expressions in the machine description. */
|
|
|
|
|
|
|
|
|
|
int
|
|
|
|
|
address_operand (op, mode)
|
|
|
|
|
register rtx op;
|
|
|
|
|
enum machine_mode mode;
|
|
|
|
|
{
|
|
|
|
|
return memory_address_p (mode, op);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Return 1 if OP is a register reference of mode MODE.
|
|
|
|
|
If MODE is VOIDmode, accept a register in any mode.
|
|
|
|
|
|
|
|
|
|
The main use of this function is as a predicate in match_operand
|
|
|
|
|
expressions in the machine description.
|
|
|
|
|
|
|
|
|
|
As a special exception, registers whose class is NO_REGS are
|
|
|
|
|
not accepted by `register_operand'. The reason for this change
|
|
|
|
|
is to allow the representation of special architecture artifacts
|
|
|
|
|
(such as a condition code register) without extending the rtl
|
|
|
|
|
definitions. Since registers of class NO_REGS cannot be used
|
|
|
|
|
as registers in any case where register classes are examined,
|
|
|
|
|
it is most consistent to keep this function from accepting them. */
|
|
|
|
|
|
|
|
|
|
int
|
|
|
|
|
register_operand (op, mode)
|
|
|
|
|
register rtx op;
|
|
|
|
|
enum machine_mode mode;
|
|
|
|
|
{
|
|
|
|
|
if (GET_MODE (op) != mode && mode != VOIDmode)
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
|
|
if (GET_CODE (op) == SUBREG)
|
|
|
|
|
{
|
|
|
|
|
/* Before reload, we can allow (SUBREG (MEM...)) as a register operand
|
|
|
|
|
because it is guaranteed to be reloaded into one.
|
|
|
|
|
Just make sure the MEM is valid in itself.
|
|
|
|
|
(Ideally, (SUBREG (MEM)...) should not exist after reload,
|
|
|
|
|
but currently it does result from (SUBREG (REG)...) where the
|
|
|
|
|
reg went on the stack.) */
|
|
|
|
|
if (! reload_completed && GET_CODE (SUBREG_REG (op)) == MEM)
|
|
|
|
|
return general_operand (op, mode);
|
1995-07-01 12:55:03 +02:00
|
|
|
|
|
2000-06-13 23:47:44 +02:00
|
|
|
|
#ifdef CLASS_CANNOT_CHANGE_MODE
|
1995-07-01 12:55:03 +02:00
|
|
|
|
if (GET_CODE (SUBREG_REG (op)) == REG
|
|
|
|
|
&& REGNO (SUBREG_REG (op)) < FIRST_PSEUDO_REGISTER
|
2000-06-13 23:47:44 +02:00
|
|
|
|
&& (TEST_HARD_REG_BIT
|
|
|
|
|
(reg_class_contents[(int) CLASS_CANNOT_CHANGE_MODE],
|
|
|
|
|
REGNO (SUBREG_REG (op))))
|
|
|
|
|
&& CLASS_CANNOT_CHANGE_MODE_P (mode, GET_MODE (SUBREG_REG (op)))
|
1996-09-30 01:05:22 +02:00
|
|
|
|
&& GET_MODE_CLASS (GET_MODE (SUBREG_REG (op))) != MODE_COMPLEX_INT
|
|
|
|
|
&& GET_MODE_CLASS (GET_MODE (SUBREG_REG (op))) != MODE_COMPLEX_FLOAT)
|
1995-07-01 12:55:03 +02:00
|
|
|
|
return 0;
|
|
|
|
|
#endif
|
|
|
|
|
|
1991-11-27 15:45:36 +01:00
|
|
|
|
op = SUBREG_REG (op);
|
|
|
|
|
}
|
|
|
|
|
|
[multiple changes]
Fri Oct 29 15:25:07 1999 Arnaud Charlet <charlet@ACT-Europe.FR>
* gcov.c (DIR_SEPARATOR): Provide default.
(output_data): Add test for MS-DOS format absolute filename.
(fancy_abort): Correct program name.
(open_files): Open all files in binary mode.
* libgcc2.c (__bb_exit_func): Likewise.
* profile.c (init_branch_prob): Specify binary when opening files.
* flags.h (flag_unwind_tables): New decl.
* toplev.c (flag_unwind_table): New definition.
(f_options): Add -funwind-tables.
(decode_g_option): Clarify warning when unknown -g option is given.
(rest_of_compilation): If inside an inlined external function,
pretend we are just being declared.
* dwarf2out.c (dwarf2out_do_frame): Check -funwind_tables.
(dwarf2out_frame_finish): Likewise.
Fri Oct 29 06:32:44 1999 Geoffrey Keating <geoffk@cygnus.com>
* flow.c (propagate_block): When the last reference to a label
before an ADDR_VEC is deleted because the reference is a dead
store, delete the ADDR_VEC.
Fri Oct 29 07:44:26 1999 Vasco Pedro <vp@di.fct.unl.pt>
* fold-const.c (merge_ranges): In not in0, but in1, handle
upper bounds equal like subset case.
Thu Oct 28 19:22:24 1999 Douglas Rupp <rupp@gnat.com>
* dbxout.c (dbxout_parms): Generate a second stabs line for parameters
passed in a register but moved to the stack.
Thu Oct 28 19:12:57 1999 Sam Tardieu <tardieu@act-europe.fr>
* gcc.c (pass_exit_codes, greatest_status): New variables.
(struct option_map): Add entry for "--pass-exit-codes".
(execute): Update greatest_status if error.
(display_help): Add documentation for -pass-exit-codes.
(process_command): Handle -pass-exit-codes.
(main): Look at pass_exit_codes and greatest_status on call to exit.
Thu Oct 28 18:06:50 1999 Richard Kenner <kenner@vlsi1.ultra.nyu.edu>
* reload.c (find_reloads): Refine test for no input reload
case to not includes reloads emitted after insn.
* function.c (find_temp_slots_from_address): Handle sum involving
a register that points to a temp slot.
(update_temp_slot_address): Make recursive call if both old and
new are PLUS with a common operand.
* calls.c (expand_call): Mark temp slot for result as having
address taken.
* rtlanal.c (reg_referenced_p, case IF_THEN_ELSE): New case.
* gcc.c (process_command): Add standard_exec_prefix with "GCC"
component as well as "BINUTILS".
* integrate.h (copy_rtx_and_substitute): New arg, FOR_LHS.
* integrate.c (copy_rtx_and_substitute): Likewise.
(expand_inline_function, integrate_parm_decls, integrate_decl_tree):
All callers changed.
* unroll.c (inital_reg_note_copy, copy_loop_body): Likewise.
* dbxout.c (dbxout_type, case INTEGER_TYPE_NODE): If can use
gdb extensions, write size of type; also be more consistent
in using references when this is a subtype.
* pa.md (extv, extzv, insv): Use define_expand to reject constant
that is out of range.
* loop.c (unknown_constant_address_altered): New variable.
(prescan_loop): Initialize it.
(note_addr_stored): Set it for RTX_UNCHANGING_P MEM.
(invariant_p, case MEM): Remove handling for volatile and readony;
check new variable if readonly.
(check_dbra_loop): Chdeck unknown_constant_address_altered.
* cse.c (canon_hash, case MEM): Do not record if BLKmode.
(addr_affects_sp_p): Removed from note_mem_written and only
define #ifdef AUTO_INC_DEC.
* alpha.c (input_operand, case ADDRESSOF): Treat as REG.
* regclass.c (record_reg_classes): Properly handle register move
directions.
* varasm.c (initializer_constant_valid_p, case MINUS_EXPR):
Don't think valid if both operands are invalid.
(struct constant_descriptor): New field RTL.
(mark_const_hash_entry): Mark it.
(record_constant{,_rtx}): Initialize it.
(output_constant_def): Allocate RTL in permanent obstack and
save in table.
({record,compare}_constant_1): Modes must match for
CONSTRUCTOR of ARRAY_TYPE.
* c-common.h (initializer_constant_valid_p): Delete decl from here.
* output.h (initializer_constant_valid_p): Move decl to here.
* c-common.c (initializer_constant_valid_p): Delete function from here.
* varasm.c (initializer_constant_valid_p): Move function to here.
* tree.h (STRIP_SIGN_NOPS): New macro.
* fold-const.c (optimize_minmax_comparison): New function.
(invert_truthvalue, case WITH_RECORD_EXPR): New case.
(fold): Use STRIP_SIGN_NOPS instead of STRIP_TYPE_NOPS.
(fold, case EQ_EXPR): Call optimize_minmax_comparison and add
cases with ABS_EXPR, NEGATE_EXPR, PLUS_EXPR, MINUS_EXPR, and
widening conversions.
(fold, case LE_EXPR): Rework changing unsigned to signed comparisons
to look at size of mode, not precision of type; also add missing cases.
(optimize_bit_field_compare, decode_field_reference): Don't try to
optimize COMPONENT_REF of a PLACEHOLDER_EXPR.
* dwarf2out.c (ctype.h): Include.
(dwarf2out_set_demangle_name_func): New function.
(size_of_line_info): Deleted.
(output_line_info): Compute size of line info table from difference
of labels.
(base_type_die, add_name_attribute): Call demangle function, if any.
(field_byte_offset): Use bits per word for variable length fields.
(gen_array_type_die): Add array name.
(gen_subprogram_die): Ignore DECL_INLINE if -fno-inline.
(dwarf2out_add_library_unit_info): New function.
* explow.c (set_stack_check_libfunc): New function.
(stack_check_libfunc): New static variable.
(probe_stack_range): Allow front-end to set up a libfunc to call.
* combine.c (simplify_comparison): When making comparison in wider
mode, check for having commuted an AND and a SUBREG.
(contains_muldiv): New function.
(try_combine): Call it when dividing a PARALLEL.
(simplify_rtx, case TRUNCATE): Don't remove for umulsi3_highpart.
(simplify_comparison, case ASHIFTRT): Recognize sign-extension of
a PLUS.
(record_value_for_reg): If TEM is a binary operation with two CLOBBERs,
use one of the CLOBBERs instead.
(if_then_else_cond): If comparing against zero, just return thing
being compared.
* optabs.c (expand_abs): If machine has MAX, ABS (x) is MAX (x, -x).
Don't generate shifts and subtract if have conditional arithmetic.
* rtl.h (delete_barrier): New declaration.
* jump.c (jump_optimize): Set up to handle conditional call.
In conditional arithmetic case, handle CALL_INSN followed by a BARRIER.
(delete_barrier): New function.
* rtl.c (read_rtx): Call fatal if bad RTL code; check for bad mode.
* recog.c (nonmemory_operand): Accept ADDRESSOF.
* tree.c (build_type_attribute_variant): Push to obstack of
ttype around type_hash_canon call.
* expr.c (placeholder_list): Move decl to file scope.
(expand_expr): Don't force access to volatile just because its
address is taken.
If ignoring reference operations, just expand the operands.
(expand_expr, case COMPONENT_REF): Propagate
EXPAND_CONST_ADDRESS to recursive call when expanding inner.
Refine test for using bitfield operations vs pointer punning.
(expand_expr, case CONVERT_EXPR): If converting to
BLKmode UNION_TYPE from BLKmode, just return inner object.
Use proper mode in store_field call.
Properly set sizes of object to store and total size in store_field
call for convert to union.
(expand_expr, case ARRAY_REF): If OP0 is in a register, put it in
memory (like for ADDR_EXPR). Also, don't put constant in register if
we'll want it in memory.
(readonly_fields_p): New function.
(expand_expr, case INDIRECT_REF): Call it if LHS.
(expand_assignment): Handle a RESULT_DECL where
DECL_RTL is a PARALLEL.
(do_jump, case WITH_RECORD_EXPR): New case.
(get_inner_reference): Always go inside a CONVERT_EXPR
and NOP_EXPR if both modes are the same.
(store_field): Use bitfield operations if size of bitsize is not same
as size of RHS's type.
Check for bitpos not a multiple of alignment in BLKmode case.
Do block move in largest possible alignment.
(store_constructor): Set BITSIZE to -1 for variable size and properly
in case of array of BLKmode.
(expand_expr_unaligned): New function.
(do_compare_and_jump): Call it.
* mips/iris5.h (SWITCHES_NEED_SPACES): New macro.
* collect2.c (main): Only allow -ofoo if SWITCHES_NEED_SPACES
does not include 'o'.
* function.c (instantiate_virtual_regs_1, case SET): Handle case where
both SET_DEST and SET_SRC reference a virtual register.
(gen_mem_addressof): Copy RTX_UNCHANGING_P from new REG to old REG.
* integrate.c (expand_inline_function): Handle case of setting
virtual stack vars register (from built in setjmp); when parameter
lives in memory, expand virtual_{stack_vars,incoming_args}_rtx early.
(subst_constant): Add new parm, MEMONLY.
(expand_inline_function, integrate_parm_decls): Pass new parm.
(integrate_decl_tree): Likewise.
(copy_rtx_and_substitute, case MEM): Do copy RTX_UNCHANGING_P.
(try_constants): Call subst_constants twice, with MEMONLY 0 and 1.
(copy_rtx_and_substitute, case SET): Add explicit calls to
copy_rtx_and_substitute for both sides.
* stmt.c (expand_asm_operands): Don't use TREE_STRING_LENGTH for
constraints.
(pushcase{,_range}): Convert to NOMINAL_TYPE after checking for
within INDEX_TYPE, instead of before.
(fixup_gotos): Use f->target_rtl, not the next insn,
since latter may be from a later fixup.
(expand_value_return): Correctly convert VAL when promoting function
return; support RETURN_REG being a PARALLEL.
(expand_return): When checking for result in regs and having
cleanup, consider PARALLEL in DECL_RTL as being in regs.
From-SVN: r30299
1999-11-01 02:11:22 +01:00
|
|
|
|
/* If we have an ADDRESSOF, consider it valid since it will be
|
|
|
|
|
converted into something that will not be a MEM. */
|
|
|
|
|
if (GET_CODE (op) == ADDRESSOF)
|
|
|
|
|
return 1;
|
|
|
|
|
|
1991-11-27 15:45:36 +01:00
|
|
|
|
/* We don't consider registers whose class is NO_REGS
|
|
|
|
|
to be a register operand. */
|
|
|
|
|
return (GET_CODE (op) == REG
|
|
|
|
|
&& (REGNO (op) >= FIRST_PSEUDO_REGISTER
|
|
|
|
|
|| REGNO_REG_CLASS (REGNO (op)) != NO_REGS));
|
|
|
|
|
}
|
|
|
|
|
|
1999-10-15 03:52:29 +02:00
|
|
|
|
/* Return 1 for a register in Pmode; ignore the tested mode. */
|
|
|
|
|
|
|
|
|
|
int
|
|
|
|
|
pmode_register_operand (op, mode)
|
|
|
|
|
rtx op;
|
|
|
|
|
enum machine_mode mode ATTRIBUTE_UNUSED;
|
|
|
|
|
{
|
|
|
|
|
return register_operand (op, Pmode);
|
|
|
|
|
}
|
|
|
|
|
|
1991-11-27 15:45:36 +01:00
|
|
|
|
/* Return 1 if OP should match a MATCH_SCRATCH, i.e., if it is a SCRATCH
|
|
|
|
|
or a hard register. */
|
|
|
|
|
|
|
|
|
|
int
|
|
|
|
|
scratch_operand (op, mode)
|
|
|
|
|
register rtx op;
|
|
|
|
|
enum machine_mode mode;
|
|
|
|
|
{
|
1999-10-27 03:25:13 +02:00
|
|
|
|
if (GET_MODE (op) != mode && mode != VOIDmode)
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
|
|
return (GET_CODE (op) == SCRATCH
|
|
|
|
|
|| (GET_CODE (op) == REG
|
|
|
|
|
&& REGNO (op) < FIRST_PSEUDO_REGISTER));
|
1991-11-27 15:45:36 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Return 1 if OP is a valid immediate operand for mode MODE.
|
|
|
|
|
|
|
|
|
|
The main use of this function is as a predicate in match_operand
|
|
|
|
|
expressions in the machine description. */
|
|
|
|
|
|
|
|
|
|
int
|
|
|
|
|
immediate_operand (op, mode)
|
|
|
|
|
register rtx op;
|
|
|
|
|
enum machine_mode mode;
|
|
|
|
|
{
|
|
|
|
|
/* Don't accept CONST_INT or anything similar
|
|
|
|
|
if the caller wants something floating. */
|
|
|
|
|
if (GET_MODE (op) == VOIDmode && mode != VOIDmode
|
1992-10-11 21:27:23 +01:00
|
|
|
|
&& GET_MODE_CLASS (mode) != MODE_INT
|
|
|
|
|
&& GET_MODE_CLASS (mode) != MODE_PARTIAL_INT)
|
1991-11-27 15:45:36 +01:00
|
|
|
|
return 0;
|
|
|
|
|
|
1999-01-21 03:21:28 +01:00
|
|
|
|
/* Accept CONSTANT_P_RTX, since it will be gone by CSE1 and
|
|
|
|
|
result in 0/1. It seems a safe assumption that this is
|
|
|
|
|
in range for everyone. */
|
|
|
|
|
if (GET_CODE (op) == CONSTANT_P_RTX)
|
|
|
|
|
return 1;
|
|
|
|
|
|
1991-11-27 15:45:36 +01:00
|
|
|
|
return (CONSTANT_P (op)
|
|
|
|
|
&& (GET_MODE (op) == mode || mode == VOIDmode
|
|
|
|
|
|| GET_MODE (op) == VOIDmode)
|
|
|
|
|
#ifdef LEGITIMATE_PIC_OPERAND_P
|
|
|
|
|
&& (! flag_pic || LEGITIMATE_PIC_OPERAND_P (op))
|
|
|
|
|
#endif
|
|
|
|
|
&& LEGITIMATE_CONSTANT_P (op));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Returns 1 if OP is an operand that is a CONST_INT. */
|
|
|
|
|
|
|
|
|
|
int
|
|
|
|
|
const_int_operand (op, mode)
|
|
|
|
|
register rtx op;
|
1998-10-14 11:02:55 +02:00
|
|
|
|
enum machine_mode mode ATTRIBUTE_UNUSED;
|
1991-11-27 15:45:36 +01:00
|
|
|
|
{
|
|
|
|
|
return GET_CODE (op) == CONST_INT;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Returns 1 if OP is an operand that is a constant integer or constant
|
|
|
|
|
floating-point number. */
|
|
|
|
|
|
|
|
|
|
int
|
|
|
|
|
const_double_operand (op, mode)
|
|
|
|
|
register rtx op;
|
|
|
|
|
enum machine_mode mode;
|
|
|
|
|
{
|
|
|
|
|
/* Don't accept CONST_INT or anything similar
|
|
|
|
|
if the caller wants something floating. */
|
|
|
|
|
if (GET_MODE (op) == VOIDmode && mode != VOIDmode
|
1992-10-11 21:27:23 +01:00
|
|
|
|
&& GET_MODE_CLASS (mode) != MODE_INT
|
|
|
|
|
&& GET_MODE_CLASS (mode) != MODE_PARTIAL_INT)
|
1991-11-27 15:45:36 +01:00
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
|
|
return ((GET_CODE (op) == CONST_DOUBLE || GET_CODE (op) == CONST_INT)
|
|
|
|
|
&& (mode == VOIDmode || GET_MODE (op) == mode
|
|
|
|
|
|| GET_MODE (op) == VOIDmode));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Return 1 if OP is a general operand that is not an immediate operand. */
|
|
|
|
|
|
|
|
|
|
int
|
|
|
|
|
nonimmediate_operand (op, mode)
|
|
|
|
|
register rtx op;
|
|
|
|
|
enum machine_mode mode;
|
|
|
|
|
{
|
|
|
|
|
return (general_operand (op, mode) && ! CONSTANT_P (op));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Return 1 if OP is a register reference or immediate value of mode MODE. */
|
|
|
|
|
|
|
|
|
|
int
|
|
|
|
|
nonmemory_operand (op, mode)
|
|
|
|
|
register rtx op;
|
|
|
|
|
enum machine_mode mode;
|
|
|
|
|
{
|
|
|
|
|
if (CONSTANT_P (op))
|
|
|
|
|
{
|
|
|
|
|
/* Don't accept CONST_INT or anything similar
|
|
|
|
|
if the caller wants something floating. */
|
|
|
|
|
if (GET_MODE (op) == VOIDmode && mode != VOIDmode
|
1992-10-11 21:27:23 +01:00
|
|
|
|
&& GET_MODE_CLASS (mode) != MODE_INT
|
|
|
|
|
&& GET_MODE_CLASS (mode) != MODE_PARTIAL_INT)
|
1991-11-27 15:45:36 +01:00
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
|
|
return ((GET_MODE (op) == VOIDmode || GET_MODE (op) == mode)
|
|
|
|
|
#ifdef LEGITIMATE_PIC_OPERAND_P
|
|
|
|
|
&& (! flag_pic || LEGITIMATE_PIC_OPERAND_P (op))
|
|
|
|
|
#endif
|
|
|
|
|
&& LEGITIMATE_CONSTANT_P (op));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (GET_MODE (op) != mode && mode != VOIDmode)
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
|
|
if (GET_CODE (op) == SUBREG)
|
|
|
|
|
{
|
|
|
|
|
/* Before reload, we can allow (SUBREG (MEM...)) as a register operand
|
|
|
|
|
because it is guaranteed to be reloaded into one.
|
|
|
|
|
Just make sure the MEM is valid in itself.
|
|
|
|
|
(Ideally, (SUBREG (MEM)...) should not exist after reload,
|
|
|
|
|
but currently it does result from (SUBREG (REG)...) where the
|
|
|
|
|
reg went on the stack.) */
|
|
|
|
|
if (! reload_completed && GET_CODE (SUBREG_REG (op)) == MEM)
|
|
|
|
|
return general_operand (op, mode);
|
|
|
|
|
op = SUBREG_REG (op);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* We don't consider registers whose class is NO_REGS
|
|
|
|
|
to be a register operand. */
|
|
|
|
|
return (GET_CODE (op) == REG
|
|
|
|
|
&& (REGNO (op) >= FIRST_PSEUDO_REGISTER
|
|
|
|
|
|| REGNO_REG_CLASS (REGNO (op)) != NO_REGS));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Return 1 if OP is a valid operand that stands for pushing a
|
|
|
|
|
value of mode MODE onto the stack.
|
|
|
|
|
|
|
|
|
|
The main use of this function is as a predicate in match_operand
|
|
|
|
|
expressions in the machine description. */
|
|
|
|
|
|
|
|
|
|
int
|
|
|
|
|
push_operand (op, mode)
|
|
|
|
|
rtx op;
|
|
|
|
|
enum machine_mode mode;
|
|
|
|
|
{
|
|
|
|
|
if (GET_CODE (op) != MEM)
|
|
|
|
|
return 0;
|
|
|
|
|
|
1999-03-07 03:45:29 +01:00
|
|
|
|
if (mode != VOIDmode && GET_MODE (op) != mode)
|
1991-11-27 15:45:36 +01:00
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
|
|
op = XEXP (op, 0);
|
|
|
|
|
|
|
|
|
|
if (GET_CODE (op) != STACK_PUSH_CODE)
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
|
|
return XEXP (op, 0) == stack_pointer_rtx;
|
|
|
|
|
}
|
|
|
|
|
|
1999-01-19 22:55:35 +01:00
|
|
|
|
/* Return 1 if OP is a valid operand that stands for popping a
|
|
|
|
|
value of mode MODE off the stack.
|
|
|
|
|
|
|
|
|
|
The main use of this function is as a predicate in match_operand
|
|
|
|
|
expressions in the machine description. */
|
|
|
|
|
|
|
|
|
|
int
|
|
|
|
|
pop_operand (op, mode)
|
|
|
|
|
rtx op;
|
|
|
|
|
enum machine_mode mode;
|
|
|
|
|
{
|
|
|
|
|
if (GET_CODE (op) != MEM)
|
|
|
|
|
return 0;
|
|
|
|
|
|
1999-03-07 03:45:29 +01:00
|
|
|
|
if (mode != VOIDmode && GET_MODE (op) != mode)
|
1999-01-19 22:55:35 +01:00
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
|
|
op = XEXP (op, 0);
|
|
|
|
|
|
|
|
|
|
if (GET_CODE (op) != STACK_POP_CODE)
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
|
|
return XEXP (op, 0) == stack_pointer_rtx;
|
|
|
|
|
}
|
|
|
|
|
|
1991-11-27 15:45:36 +01:00
|
|
|
|
/* Return 1 if ADDR is a valid memory address for mode MODE. */
|
|
|
|
|
|
|
|
|
|
int
|
|
|
|
|
memory_address_p (mode, addr)
|
2000-01-13 01:17:33 +01:00
|
|
|
|
enum machine_mode mode ATTRIBUTE_UNUSED;
|
1991-11-27 15:45:36 +01:00
|
|
|
|
register rtx addr;
|
|
|
|
|
{
|
alias.c: Change all uses of gen_rtx(FOO...) to gen_rtx_FOO...
* alias.c: Change all uses of gen_rtx(FOO...) to gen_rtx_FOO;
change gen_rtx(expr...) to gen_rtx_fmt_foo(expr...).
* caller-save.c, calls.c, combine.c, cse.c: Likewise.
* dwarf2out.c, except.c, explow.c, expmed.c, expr.c: Likewise.
* final.c, flow.c, function.c, genpeep.c, haifa-sched.c: Likewise.
* halfpic.c, integrate.c, jump.c, local-alloc.c, loop.c: Likewise.
* profile.c, recog.c, reg-stack.c, regclass.c, regmove.c: Likewise.
* reload.c, reload1.c, reorg.c, sched.c, stmt.c, stupid.c: Likewise.
* unroll.c, varasm.c: Likewise.
* config/alpha/alpha.c, config/alpha/alpha.md: Likewise.
From-SVN: r17357
1998-01-15 00:10:50 +01:00
|
|
|
|
if (GET_CODE (addr) == ADDRESSOF)
|
|
|
|
|
return 1;
|
|
|
|
|
|
1991-11-27 15:45:36 +01:00
|
|
|
|
GO_IF_LEGITIMATE_ADDRESS (mode, addr, win);
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
|
|
win:
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Return 1 if OP is a valid memory reference with mode MODE,
|
|
|
|
|
including a valid address.
|
|
|
|
|
|
|
|
|
|
The main use of this function is as a predicate in match_operand
|
|
|
|
|
expressions in the machine description. */
|
|
|
|
|
|
|
|
|
|
int
|
|
|
|
|
memory_operand (op, mode)
|
|
|
|
|
register rtx op;
|
|
|
|
|
enum machine_mode mode;
|
|
|
|
|
{
|
|
|
|
|
rtx inner;
|
|
|
|
|
|
|
|
|
|
if (! reload_completed)
|
|
|
|
|
/* Note that no SUBREG is a memory operand before end of reload pass,
|
|
|
|
|
because (SUBREG (MEM...)) forces reloading into a register. */
|
|
|
|
|
return GET_CODE (op) == MEM && general_operand (op, mode);
|
|
|
|
|
|
|
|
|
|
if (mode != VOIDmode && GET_MODE (op) != mode)
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
|
|
inner = op;
|
|
|
|
|
if (GET_CODE (inner) == SUBREG)
|
|
|
|
|
inner = SUBREG_REG (inner);
|
|
|
|
|
|
|
|
|
|
return (GET_CODE (inner) == MEM && general_operand (op, mode));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Return 1 if OP is a valid indirect memory reference with mode MODE;
|
|
|
|
|
that is, a memory reference whose address is a general_operand. */
|
|
|
|
|
|
|
|
|
|
int
|
|
|
|
|
indirect_operand (op, mode)
|
|
|
|
|
register rtx op;
|
|
|
|
|
enum machine_mode mode;
|
|
|
|
|
{
|
|
|
|
|
/* Before reload, a SUBREG isn't in memory (see memory_operand, above). */
|
|
|
|
|
if (! reload_completed
|
|
|
|
|
&& GET_CODE (op) == SUBREG && GET_CODE (SUBREG_REG (op)) == MEM)
|
|
|
|
|
{
|
|
|
|
|
register int offset = SUBREG_WORD (op) * UNITS_PER_WORD;
|
|
|
|
|
rtx inner = SUBREG_REG (op);
|
|
|
|
|
|
1994-11-16 22:10:09 +01:00
|
|
|
|
if (BYTES_BIG_ENDIAN)
|
|
|
|
|
offset -= (MIN (UNITS_PER_WORD, GET_MODE_SIZE (GET_MODE (op)))
|
|
|
|
|
- MIN (UNITS_PER_WORD, GET_MODE_SIZE (GET_MODE (inner))));
|
1991-11-27 15:45:36 +01:00
|
|
|
|
|
1993-12-12 14:01:09 +01:00
|
|
|
|
if (mode != VOIDmode && GET_MODE (op) != mode)
|
|
|
|
|
return 0;
|
|
|
|
|
|
1991-11-27 15:45:36 +01:00
|
|
|
|
/* The only way that we can have a general_operand as the resulting
|
|
|
|
|
address is if OFFSET is zero and the address already is an operand
|
|
|
|
|
or if the address is (plus Y (const_int -OFFSET)) and Y is an
|
|
|
|
|
operand. */
|
|
|
|
|
|
|
|
|
|
return ((offset == 0 && general_operand (XEXP (inner, 0), Pmode))
|
|
|
|
|
|| (GET_CODE (XEXP (inner, 0)) == PLUS
|
|
|
|
|
&& GET_CODE (XEXP (XEXP (inner, 0), 1)) == CONST_INT
|
|
|
|
|
&& INTVAL (XEXP (XEXP (inner, 0), 1)) == -offset
|
|
|
|
|
&& general_operand (XEXP (XEXP (inner, 0), 0), Pmode)));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return (GET_CODE (op) == MEM
|
|
|
|
|
&& memory_operand (op, mode)
|
|
|
|
|
&& general_operand (XEXP (op, 0), Pmode));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Return 1 if this is a comparison operator. This allows the use of
|
|
|
|
|
MATCH_OPERATOR to recognize all the branch insns. */
|
|
|
|
|
|
|
|
|
|
int
|
|
|
|
|
comparison_operator (op, mode)
|
|
|
|
|
register rtx op;
|
|
|
|
|
enum machine_mode mode;
|
|
|
|
|
{
|
|
|
|
|
return ((mode == VOIDmode || GET_MODE (op) == mode)
|
|
|
|
|
&& GET_RTX_CLASS (GET_CODE (op)) == '<');
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* If BODY is an insn body that uses ASM_OPERANDS,
|
|
|
|
|
return the number of operands (both input and output) in the insn.
|
|
|
|
|
Otherwise return -1. */
|
|
|
|
|
|
|
|
|
|
int
|
|
|
|
|
asm_noperands (body)
|
|
|
|
|
rtx body;
|
|
|
|
|
{
|
|
|
|
|
if (GET_CODE (body) == ASM_OPERANDS)
|
|
|
|
|
/* No output operands: return number of input operands. */
|
|
|
|
|
return ASM_OPERANDS_INPUT_LENGTH (body);
|
|
|
|
|
if (GET_CODE (body) == SET && GET_CODE (SET_SRC (body)) == ASM_OPERANDS)
|
|
|
|
|
/* Single output operand: BODY is (set OUTPUT (asm_operands ...)). */
|
|
|
|
|
return ASM_OPERANDS_INPUT_LENGTH (SET_SRC (body)) + 1;
|
|
|
|
|
else if (GET_CODE (body) == PARALLEL
|
|
|
|
|
&& GET_CODE (XVECEXP (body, 0, 0)) == SET
|
|
|
|
|
&& GET_CODE (SET_SRC (XVECEXP (body, 0, 0))) == ASM_OPERANDS)
|
|
|
|
|
{
|
|
|
|
|
/* Multiple output operands, or 1 output plus some clobbers:
|
|
|
|
|
body is [(set OUTPUT (asm_operands ...))... (clobber (reg ...))...]. */
|
|
|
|
|
int i;
|
|
|
|
|
int n_sets;
|
|
|
|
|
|
|
|
|
|
/* Count backwards through CLOBBERs to determine number of SETs. */
|
|
|
|
|
for (i = XVECLEN (body, 0); i > 0; i--)
|
|
|
|
|
{
|
|
|
|
|
if (GET_CODE (XVECEXP (body, 0, i - 1)) == SET)
|
|
|
|
|
break;
|
|
|
|
|
if (GET_CODE (XVECEXP (body, 0, i - 1)) != CLOBBER)
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* N_SETS is now number of output operands. */
|
|
|
|
|
n_sets = i;
|
|
|
|
|
|
|
|
|
|
/* Verify that all the SETs we have
|
|
|
|
|
came from a single original asm_operands insn
|
|
|
|
|
(so that invalid combinations are blocked). */
|
|
|
|
|
for (i = 0; i < n_sets; i++)
|
|
|
|
|
{
|
|
|
|
|
rtx elt = XVECEXP (body, 0, i);
|
|
|
|
|
if (GET_CODE (elt) != SET)
|
|
|
|
|
return -1;
|
|
|
|
|
if (GET_CODE (SET_SRC (elt)) != ASM_OPERANDS)
|
|
|
|
|
return -1;
|
|
|
|
|
/* If these ASM_OPERANDS rtx's came from different original insns
|
|
|
|
|
then they aren't allowed together. */
|
|
|
|
|
if (ASM_OPERANDS_INPUT_VEC (SET_SRC (elt))
|
|
|
|
|
!= ASM_OPERANDS_INPUT_VEC (SET_SRC (XVECEXP (body, 0, 0))))
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
return (ASM_OPERANDS_INPUT_LENGTH (SET_SRC (XVECEXP (body, 0, 0)))
|
|
|
|
|
+ n_sets);
|
|
|
|
|
}
|
|
|
|
|
else if (GET_CODE (body) == PARALLEL
|
|
|
|
|
&& GET_CODE (XVECEXP (body, 0, 0)) == ASM_OPERANDS)
|
|
|
|
|
{
|
|
|
|
|
/* 0 outputs, but some clobbers:
|
|
|
|
|
body is [(asm_operands ...) (clobber (reg ...))...]. */
|
|
|
|
|
int i;
|
|
|
|
|
|
|
|
|
|
/* Make sure all the other parallel things really are clobbers. */
|
|
|
|
|
for (i = XVECLEN (body, 0) - 1; i > 0; i--)
|
|
|
|
|
if (GET_CODE (XVECEXP (body, 0, i)) != CLOBBER)
|
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
|
|
return ASM_OPERANDS_INPUT_LENGTH (XVECEXP (body, 0, 0));
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Assuming BODY is an insn body that uses ASM_OPERANDS,
|
|
|
|
|
copy its operands (both input and output) into the vector OPERANDS,
|
|
|
|
|
the locations of the operands within the insn into the vector OPERAND_LOCS,
|
|
|
|
|
and the constraints for the operands into CONSTRAINTS.
|
|
|
|
|
Write the modes of the operands into MODES.
|
|
|
|
|
Return the assembler-template.
|
|
|
|
|
|
|
|
|
|
If MODES, OPERAND_LOCS, CONSTRAINTS or OPERANDS is 0,
|
|
|
|
|
we don't store that info. */
|
|
|
|
|
|
rtl.h (rtunion_def): Constify member `rtstr'.
* rtl.h (rtunion_def): Constify member `rtstr'.
(emit_line_note_after, emit_line_note, emit_line_note_force,
emit_note, decode_asm_operands): Constify.
* cse.c (canon_hash): Likewise.
* dbxout.c (dbxout_block): Likewise.
* diagnostic.c (file_and_line_for_asm, v_error_for_asm,
v_warning_for_asm): Likewise.
* dwarfout.c (function_start_label): Likewise.
* emit-rtl.c (emit_line_note_after, emit_line_note, emit_note,
emit_line_note_force): Likewise.
* final.c (last_filename, asm_insn_count, final_scan_insn,
output_source_line): Likewise.
* function.h (struct emit_status): Likewise.
* gcse.c (hash_expr_1): Likewise.
* genattr.c (gen_attr, main): Likewise.
* genattrtab.c (struct function_unit, current_alternative_string,
write_attr_valueq, n_comma_elts, next_comma_elt, attr_eq,
attr_numeral, check_attr_test, check_attr_value,
convert_set_attr_alternative, convert_set_attr,
compute_alternative_mask, simplify_by_exploding, gen_attr,
gen_unit): Likewise.
* genflags.c (gen_insn): Likewise.
* gengenrtl.c (type_from_format): Likewise.
* genopinit.c (gen_insn): Likewise.
* genoutput.c (n_occurrences, process_template, process_template):
Likewise.
* ggc-page.c (ggc_set_mark, ggc_mark_if_gcable, ggc_get_size):
Likewise.
* ggc-simple.c (ggc_set_mark, ggc_mark_if_gcable, ggc_get_size):
Likewise.
* ggc.h (ggc_mark_string, ggc_mark, ggc_mark_if_gcable,
ggc_set_mark, ggc_get_size): Likewise.
* objc/objc-act.c (build_module_descriptor, finish_objc): Likewise.
* optabs.c (init_one_libfunc): Likewise.
* output.h (assemble_start_function): Likewise.
* recog.c (decode_asm_operands): Likewise.
* toplev.c (rest_of_compilation): Likewise.
* tree.h (emit_line_note_after, emit_line_note,
emit_line_note_force): Likewise.
* varasm.c (asm_output_bss, asm_output_aligned_bss,
asm_emit_uninitialised, assemble_start_function,
assemble_variable, const_hash, compare_constant_1,
find_pool_constant, mark_constant_pool, assemble_alias): Likewise.
* xcoffout.h (DBX_FINISH_SYMBOL): Likewise.
* alpha/alpha.md (call_vms, call_value_vms): Likewise.
* arm/aof.h (ASM_OUTPUT_ASCII): Likewise.
* arm/aout.h (ASM_OUTPUT_ASCII): Likewise.
* arm/arm-protos.h (output_ascii_pseudo_op, arm_dllexport_name_p,
arm_dllimport_name_p): Likewise.
* arm/arm.c (arm_encode_call_attribute, output_ascii_pseudo_op):
Likewise.
* arm/arm.h (ASM_OUTPUT_MI_THUNK): Likewise.
* arm/elf.h (ASM_FINISH_DECLARE_OBJECT): Likewise.
* arm/pe.c (arm_dllexport_name_p, arm_dllimport_name_p,
arm_mark_dllexport, arm_mark_dllimport,
arm_pe_encode_section_info): Likewise.
* arm/telf.h (ASM_OUTPUT_DEF_FROM_DECLS,
ASM_FINISH_DECLARE_OBJECT): Likewise.
* arm/thumb.c (thumb_function_prologue): Likewise.
* arm/thumb.h (ASM_OUTPUT_ASCII): Likewise.
* avr/avr.h (ASM_FINISH_DECLARE_OBJECT): Likewise.
* clipper/clix.h (ASM_OUTPUT_ASCII): Likewise.
* fx80/fx80.h (ASM_OUTPUT_ASCII): Likewise.
* i386/cygwin.h (ASM_OUTPUT_SECTION_NAME): Likewise.
* i386/freebsd.h (ASM_FINISH_DECLARE_OBJECT): Likewise.
* i386/i386-interix.h (ASM_OUTPUT_LIMITED_STRING,
ASM_OUTPUT_ASCII, ASM_OUTPUT_SECTION_NAME): Likewise.
* i386/i386-protos.h (asm_output_function_prefix): Likewise.
* i386/i386.c (asm_output_function_prefix): Likewise.
* i386/i386elf.h (ASM_OUTPUT_ASCII): Likewise.
* i386/osfrose.h (ASM_FINISH_DECLARE_OBJECT): Likewise.
* i386/ptx4-i.h (ASM_OUTPUT_ASCII): Likewise.
* i386/sco5.h (ASM_FINISH_DECLARE_OBJECT,
ASM_OUTPUT_LIMITED_STRING, ASM_OUTPUT_ASCII,
ASM_OUTPUT_SECTION_NAME): Likewise.
* i386/sysv4.h (ASM_OUTPUT_ASCII): Likewise.
* i860/paragon.h (ASM_OUTPUT_ASCII): Likewise.
* i860/sysv3.h (ASM_OUTPUT_ASCII): Likewise.
* m32r/m32r.c (m32r_encode_section_info): Likewise.
* mcore-elf.h (ASM_FINISH_DECLARE_OBJECT): Likewise.
* mcore/mcore.c (mcore_encode_section_info): Likewise.
* mips/elf.h (ASM_FINISH_DECLARE_OBJECT): Likewise.
* mips/elf64.h (ASM_FINISH_DECLARE_OBJECT): Likewise.
* mips/iris6.h (ASM_FINISH_DECLARE_OBJECT): Likewise.
* mips/mips.h (ASM_OUTPUT_IDENT): Likewise.
* mips/mips.md (movdi, movsi): Likewise.
* mips/netbsd.h (ASM_FINISH_DECLARE_OBJECT): Likewise.
* netbsd.h (ASM_FINISH_DECLARE_OBJECT): Likewise.
* openbsd.h (ASM_FINISH_DECLARE_OBJECT): Likewise.
* ptx4.h (ASM_FINISH_DECLARE_OBJECT, ASM_OUTPUT_LIMITED_STRING,
ASM_OUTPUT_ASCII): Likewise.
* rs6000/rs6000.c (rs6000_allocate_stack_space, output_epilog,
output_mi_thunk, output_toc): Likewise.
* rs6000/rs6000.md (movsi): Likewise.
* rs6000/sysv4.h (ASM_OUTPUT_INT, ASM_OUTPUT_SECTION_NAME): Likewise.
* tahoe/harris.h (ASM_OUTPUT_ASCII): Likewise.
* v850/v850.c (print_operand, print_operand_address,
v850_encode_data_area): Likewise.
ch:
* grant.c (globalize_decl): Constify a char*.
cp:
* decl2.c (finish_objects): Constify a char*.
* method.c (emit_thunk): Likewise.
From-SVN: r32388
2000-03-07 21:39:10 +01:00
|
|
|
|
const char *
|
1991-11-27 15:45:36 +01:00
|
|
|
|
decode_asm_operands (body, operands, operand_locs, constraints, modes)
|
|
|
|
|
rtx body;
|
|
|
|
|
rtx *operands;
|
|
|
|
|
rtx **operand_locs;
|
final.c (bb_str): Qualify a char* with the keyword `const'.
* final.c (bb_str): Qualify a char* with the keyword `const'.
(add_bb_string, final_scan_insn, output_asm_insn): Likewise.
* fix-header.c (read_scan_file): Likewise.
* genoutput.c (output_epilogue, process_template): Likewise.
* local-alloc.c (requires_inout, block_alloc): Likewise.
* output.h (output_asm_insn, assemble_string): Likewise.
* recog.c (recog_constraints, check_asm_operands,
decode_asm_operands, extract_insn, preprocess_constraints,
constrain_operands): Likewise.
* recog.h (operand_alternative, recog_constraints, insn_template,
insn_outfun, insn_operand_constraint, insn_name): Likewise.
* regclass.c (record_reg_classes, scan_one_insn): Likewise.
* regmove.c (find_matches): Likewise.
* reload.c (alternative_allows_memconst): Likewise.
* reload1.c (constraint_accepts_reg_p,
reload_cse_simplify_operands): Likewise.
* rtl.h (decode_asm_operands): Likewise.
* scan.h (fn_decl): Likewise.
* varasm.c (assemble_string): Likewise.
From-SVN: r24834
1999-01-23 20:45:50 +01:00
|
|
|
|
const char **constraints;
|
1991-11-27 15:45:36 +01:00
|
|
|
|
enum machine_mode *modes;
|
|
|
|
|
{
|
|
|
|
|
register int i;
|
|
|
|
|
int noperands;
|
rtl.h (rtunion_def): Constify member `rtstr'.
* rtl.h (rtunion_def): Constify member `rtstr'.
(emit_line_note_after, emit_line_note, emit_line_note_force,
emit_note, decode_asm_operands): Constify.
* cse.c (canon_hash): Likewise.
* dbxout.c (dbxout_block): Likewise.
* diagnostic.c (file_and_line_for_asm, v_error_for_asm,
v_warning_for_asm): Likewise.
* dwarfout.c (function_start_label): Likewise.
* emit-rtl.c (emit_line_note_after, emit_line_note, emit_note,
emit_line_note_force): Likewise.
* final.c (last_filename, asm_insn_count, final_scan_insn,
output_source_line): Likewise.
* function.h (struct emit_status): Likewise.
* gcse.c (hash_expr_1): Likewise.
* genattr.c (gen_attr, main): Likewise.
* genattrtab.c (struct function_unit, current_alternative_string,
write_attr_valueq, n_comma_elts, next_comma_elt, attr_eq,
attr_numeral, check_attr_test, check_attr_value,
convert_set_attr_alternative, convert_set_attr,
compute_alternative_mask, simplify_by_exploding, gen_attr,
gen_unit): Likewise.
* genflags.c (gen_insn): Likewise.
* gengenrtl.c (type_from_format): Likewise.
* genopinit.c (gen_insn): Likewise.
* genoutput.c (n_occurrences, process_template, process_template):
Likewise.
* ggc-page.c (ggc_set_mark, ggc_mark_if_gcable, ggc_get_size):
Likewise.
* ggc-simple.c (ggc_set_mark, ggc_mark_if_gcable, ggc_get_size):
Likewise.
* ggc.h (ggc_mark_string, ggc_mark, ggc_mark_if_gcable,
ggc_set_mark, ggc_get_size): Likewise.
* objc/objc-act.c (build_module_descriptor, finish_objc): Likewise.
* optabs.c (init_one_libfunc): Likewise.
* output.h (assemble_start_function): Likewise.
* recog.c (decode_asm_operands): Likewise.
* toplev.c (rest_of_compilation): Likewise.
* tree.h (emit_line_note_after, emit_line_note,
emit_line_note_force): Likewise.
* varasm.c (asm_output_bss, asm_output_aligned_bss,
asm_emit_uninitialised, assemble_start_function,
assemble_variable, const_hash, compare_constant_1,
find_pool_constant, mark_constant_pool, assemble_alias): Likewise.
* xcoffout.h (DBX_FINISH_SYMBOL): Likewise.
* alpha/alpha.md (call_vms, call_value_vms): Likewise.
* arm/aof.h (ASM_OUTPUT_ASCII): Likewise.
* arm/aout.h (ASM_OUTPUT_ASCII): Likewise.
* arm/arm-protos.h (output_ascii_pseudo_op, arm_dllexport_name_p,
arm_dllimport_name_p): Likewise.
* arm/arm.c (arm_encode_call_attribute, output_ascii_pseudo_op):
Likewise.
* arm/arm.h (ASM_OUTPUT_MI_THUNK): Likewise.
* arm/elf.h (ASM_FINISH_DECLARE_OBJECT): Likewise.
* arm/pe.c (arm_dllexport_name_p, arm_dllimport_name_p,
arm_mark_dllexport, arm_mark_dllimport,
arm_pe_encode_section_info): Likewise.
* arm/telf.h (ASM_OUTPUT_DEF_FROM_DECLS,
ASM_FINISH_DECLARE_OBJECT): Likewise.
* arm/thumb.c (thumb_function_prologue): Likewise.
* arm/thumb.h (ASM_OUTPUT_ASCII): Likewise.
* avr/avr.h (ASM_FINISH_DECLARE_OBJECT): Likewise.
* clipper/clix.h (ASM_OUTPUT_ASCII): Likewise.
* fx80/fx80.h (ASM_OUTPUT_ASCII): Likewise.
* i386/cygwin.h (ASM_OUTPUT_SECTION_NAME): Likewise.
* i386/freebsd.h (ASM_FINISH_DECLARE_OBJECT): Likewise.
* i386/i386-interix.h (ASM_OUTPUT_LIMITED_STRING,
ASM_OUTPUT_ASCII, ASM_OUTPUT_SECTION_NAME): Likewise.
* i386/i386-protos.h (asm_output_function_prefix): Likewise.
* i386/i386.c (asm_output_function_prefix): Likewise.
* i386/i386elf.h (ASM_OUTPUT_ASCII): Likewise.
* i386/osfrose.h (ASM_FINISH_DECLARE_OBJECT): Likewise.
* i386/ptx4-i.h (ASM_OUTPUT_ASCII): Likewise.
* i386/sco5.h (ASM_FINISH_DECLARE_OBJECT,
ASM_OUTPUT_LIMITED_STRING, ASM_OUTPUT_ASCII,
ASM_OUTPUT_SECTION_NAME): Likewise.
* i386/sysv4.h (ASM_OUTPUT_ASCII): Likewise.
* i860/paragon.h (ASM_OUTPUT_ASCII): Likewise.
* i860/sysv3.h (ASM_OUTPUT_ASCII): Likewise.
* m32r/m32r.c (m32r_encode_section_info): Likewise.
* mcore-elf.h (ASM_FINISH_DECLARE_OBJECT): Likewise.
* mcore/mcore.c (mcore_encode_section_info): Likewise.
* mips/elf.h (ASM_FINISH_DECLARE_OBJECT): Likewise.
* mips/elf64.h (ASM_FINISH_DECLARE_OBJECT): Likewise.
* mips/iris6.h (ASM_FINISH_DECLARE_OBJECT): Likewise.
* mips/mips.h (ASM_OUTPUT_IDENT): Likewise.
* mips/mips.md (movdi, movsi): Likewise.
* mips/netbsd.h (ASM_FINISH_DECLARE_OBJECT): Likewise.
* netbsd.h (ASM_FINISH_DECLARE_OBJECT): Likewise.
* openbsd.h (ASM_FINISH_DECLARE_OBJECT): Likewise.
* ptx4.h (ASM_FINISH_DECLARE_OBJECT, ASM_OUTPUT_LIMITED_STRING,
ASM_OUTPUT_ASCII): Likewise.
* rs6000/rs6000.c (rs6000_allocate_stack_space, output_epilog,
output_mi_thunk, output_toc): Likewise.
* rs6000/rs6000.md (movsi): Likewise.
* rs6000/sysv4.h (ASM_OUTPUT_INT, ASM_OUTPUT_SECTION_NAME): Likewise.
* tahoe/harris.h (ASM_OUTPUT_ASCII): Likewise.
* v850/v850.c (print_operand, print_operand_address,
v850_encode_data_area): Likewise.
ch:
* grant.c (globalize_decl): Constify a char*.
cp:
* decl2.c (finish_objects): Constify a char*.
* method.c (emit_thunk): Likewise.
From-SVN: r32388
2000-03-07 21:39:10 +01:00
|
|
|
|
const char *template = 0;
|
1991-11-27 15:45:36 +01:00
|
|
|
|
|
|
|
|
|
if (GET_CODE (body) == SET && GET_CODE (SET_SRC (body)) == ASM_OPERANDS)
|
|
|
|
|
{
|
|
|
|
|
rtx asmop = SET_SRC (body);
|
|
|
|
|
/* Single output operand: BODY is (set OUTPUT (asm_operands ....)). */
|
|
|
|
|
|
|
|
|
|
noperands = ASM_OPERANDS_INPUT_LENGTH (asmop) + 1;
|
|
|
|
|
|
|
|
|
|
for (i = 1; i < noperands; i++)
|
|
|
|
|
{
|
|
|
|
|
if (operand_locs)
|
|
|
|
|
operand_locs[i] = &ASM_OPERANDS_INPUT (asmop, i - 1);
|
|
|
|
|
if (operands)
|
|
|
|
|
operands[i] = ASM_OPERANDS_INPUT (asmop, i - 1);
|
|
|
|
|
if (constraints)
|
|
|
|
|
constraints[i] = ASM_OPERANDS_INPUT_CONSTRAINT (asmop, i - 1);
|
|
|
|
|
if (modes)
|
|
|
|
|
modes[i] = ASM_OPERANDS_INPUT_MODE (asmop, i - 1);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* The output is in the SET.
|
|
|
|
|
Its constraint is in the ASM_OPERANDS itself. */
|
|
|
|
|
if (operands)
|
|
|
|
|
operands[0] = SET_DEST (body);
|
|
|
|
|
if (operand_locs)
|
|
|
|
|
operand_locs[0] = &SET_DEST (body);
|
|
|
|
|
if (constraints)
|
|
|
|
|
constraints[0] = ASM_OPERANDS_OUTPUT_CONSTRAINT (asmop);
|
|
|
|
|
if (modes)
|
|
|
|
|
modes[0] = GET_MODE (SET_DEST (body));
|
|
|
|
|
template = ASM_OPERANDS_TEMPLATE (asmop);
|
|
|
|
|
}
|
|
|
|
|
else if (GET_CODE (body) == ASM_OPERANDS)
|
|
|
|
|
{
|
|
|
|
|
rtx asmop = body;
|
|
|
|
|
/* No output operands: BODY is (asm_operands ....). */
|
|
|
|
|
|
|
|
|
|
noperands = ASM_OPERANDS_INPUT_LENGTH (asmop);
|
|
|
|
|
|
|
|
|
|
/* The input operands are found in the 1st element vector. */
|
|
|
|
|
/* Constraints for inputs are in the 2nd element vector. */
|
|
|
|
|
for (i = 0; i < noperands; i++)
|
|
|
|
|
{
|
|
|
|
|
if (operand_locs)
|
|
|
|
|
operand_locs[i] = &ASM_OPERANDS_INPUT (asmop, i);
|
|
|
|
|
if (operands)
|
|
|
|
|
operands[i] = ASM_OPERANDS_INPUT (asmop, i);
|
|
|
|
|
if (constraints)
|
|
|
|
|
constraints[i] = ASM_OPERANDS_INPUT_CONSTRAINT (asmop, i);
|
|
|
|
|
if (modes)
|
|
|
|
|
modes[i] = ASM_OPERANDS_INPUT_MODE (asmop, i);
|
|
|
|
|
}
|
|
|
|
|
template = ASM_OPERANDS_TEMPLATE (asmop);
|
|
|
|
|
}
|
|
|
|
|
else if (GET_CODE (body) == PARALLEL
|
|
|
|
|
&& GET_CODE (XVECEXP (body, 0, 0)) == SET)
|
|
|
|
|
{
|
|
|
|
|
rtx asmop = SET_SRC (XVECEXP (body, 0, 0));
|
|
|
|
|
int nparallel = XVECLEN (body, 0); /* Includes CLOBBERs. */
|
|
|
|
|
int nin = ASM_OPERANDS_INPUT_LENGTH (asmop);
|
|
|
|
|
int nout = 0; /* Does not include CLOBBERs. */
|
|
|
|
|
|
|
|
|
|
/* At least one output, plus some CLOBBERs. */
|
|
|
|
|
|
|
|
|
|
/* The outputs are in the SETs.
|
|
|
|
|
Their constraints are in the ASM_OPERANDS itself. */
|
|
|
|
|
for (i = 0; i < nparallel; i++)
|
|
|
|
|
{
|
|
|
|
|
if (GET_CODE (XVECEXP (body, 0, i)) == CLOBBER)
|
|
|
|
|
break; /* Past last SET */
|
|
|
|
|
|
|
|
|
|
if (operands)
|
|
|
|
|
operands[i] = SET_DEST (XVECEXP (body, 0, i));
|
|
|
|
|
if (operand_locs)
|
|
|
|
|
operand_locs[i] = &SET_DEST (XVECEXP (body, 0, i));
|
|
|
|
|
if (constraints)
|
|
|
|
|
constraints[i] = XSTR (SET_SRC (XVECEXP (body, 0, i)), 1);
|
|
|
|
|
if (modes)
|
|
|
|
|
modes[i] = GET_MODE (SET_DEST (XVECEXP (body, 0, i)));
|
|
|
|
|
nout++;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (i = 0; i < nin; i++)
|
|
|
|
|
{
|
|
|
|
|
if (operand_locs)
|
|
|
|
|
operand_locs[i + nout] = &ASM_OPERANDS_INPUT (asmop, i);
|
|
|
|
|
if (operands)
|
|
|
|
|
operands[i + nout] = ASM_OPERANDS_INPUT (asmop, i);
|
|
|
|
|
if (constraints)
|
|
|
|
|
constraints[i + nout] = ASM_OPERANDS_INPUT_CONSTRAINT (asmop, i);
|
|
|
|
|
if (modes)
|
|
|
|
|
modes[i + nout] = ASM_OPERANDS_INPUT_MODE (asmop, i);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
template = ASM_OPERANDS_TEMPLATE (asmop);
|
|
|
|
|
}
|
|
|
|
|
else if (GET_CODE (body) == PARALLEL
|
|
|
|
|
&& GET_CODE (XVECEXP (body, 0, 0)) == ASM_OPERANDS)
|
|
|
|
|
{
|
|
|
|
|
/* No outputs, but some CLOBBERs. */
|
|
|
|
|
|
|
|
|
|
rtx asmop = XVECEXP (body, 0, 0);
|
|
|
|
|
int nin = ASM_OPERANDS_INPUT_LENGTH (asmop);
|
|
|
|
|
|
|
|
|
|
for (i = 0; i < nin; i++)
|
|
|
|
|
{
|
|
|
|
|
if (operand_locs)
|
|
|
|
|
operand_locs[i] = &ASM_OPERANDS_INPUT (asmop, i);
|
|
|
|
|
if (operands)
|
|
|
|
|
operands[i] = ASM_OPERANDS_INPUT (asmop, i);
|
|
|
|
|
if (constraints)
|
|
|
|
|
constraints[i] = ASM_OPERANDS_INPUT_CONSTRAINT (asmop, i);
|
|
|
|
|
if (modes)
|
|
|
|
|
modes[i] = ASM_OPERANDS_INPUT_MODE (asmop, i);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
template = ASM_OPERANDS_TEMPLATE (asmop);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return template;
|
|
|
|
|
}
|
1999-01-15 19:43:47 +01:00
|
|
|
|
|
1999-02-01 21:03:23 +01:00
|
|
|
|
/* Check if an asm_operand matches it's constraints.
|
|
|
|
|
Return > 0 if ok, = 0 if bad, < 0 if inconclusive. */
|
1999-01-15 19:43:47 +01:00
|
|
|
|
|
|
|
|
|
int
|
|
|
|
|
asm_operand_ok (op, constraint)
|
|
|
|
|
rtx op;
|
|
|
|
|
const char *constraint;
|
|
|
|
|
{
|
1999-02-01 21:03:23 +01:00
|
|
|
|
int result = 0;
|
|
|
|
|
|
1999-01-15 19:43:47 +01:00
|
|
|
|
/* Use constrain_operands after reload. */
|
|
|
|
|
if (reload_completed)
|
|
|
|
|
abort ();
|
|
|
|
|
|
|
|
|
|
while (*constraint)
|
|
|
|
|
{
|
|
|
|
|
switch (*constraint++)
|
|
|
|
|
{
|
|
|
|
|
case '=':
|
|
|
|
|
case '+':
|
|
|
|
|
case '*':
|
|
|
|
|
case '%':
|
|
|
|
|
case '?':
|
|
|
|
|
case '!':
|
|
|
|
|
case '#':
|
|
|
|
|
case '&':
|
|
|
|
|
case ',':
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case '0': case '1': case '2': case '3': case '4':
|
|
|
|
|
case '5': case '6': case '7': case '8': case '9':
|
1999-02-01 21:03:23 +01:00
|
|
|
|
/* For best results, our caller should have given us the
|
|
|
|
|
proper matching constraint, but we can't actually fail
|
|
|
|
|
the check if they didn't. Indicate that results are
|
|
|
|
|
inconclusive. */
|
|
|
|
|
result = -1;
|
1999-01-15 19:43:47 +01:00
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case 'p':
|
|
|
|
|
if (address_operand (op, VOIDmode))
|
|
|
|
|
return 1;
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case 'm':
|
|
|
|
|
case 'V': /* non-offsettable */
|
|
|
|
|
if (memory_operand (op, VOIDmode))
|
|
|
|
|
return 1;
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case 'o': /* offsettable */
|
|
|
|
|
if (offsettable_nonstrict_memref_p (op))
|
|
|
|
|
return 1;
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case '<':
|
1999-02-01 21:03:23 +01:00
|
|
|
|
/* ??? Before flow, auto inc/dec insns are not supposed to exist,
|
|
|
|
|
excepting those that expand_call created. Further, on some
|
|
|
|
|
machines which do not have generalized auto inc/dec, an inc/dec
|
|
|
|
|
is not a memory_operand.
|
|
|
|
|
|
|
|
|
|
Match any memory and hope things are resolved after reload. */
|
|
|
|
|
|
1999-01-15 19:43:47 +01:00
|
|
|
|
if (GET_CODE (op) == MEM
|
1999-02-01 21:03:23 +01:00
|
|
|
|
&& (1
|
|
|
|
|
|| GET_CODE (XEXP (op, 0)) == PRE_DEC
|
1999-01-15 19:43:47 +01:00
|
|
|
|
|| GET_CODE (XEXP (op, 0)) == POST_DEC))
|
|
|
|
|
return 1;
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case '>':
|
|
|
|
|
if (GET_CODE (op) == MEM
|
1999-02-01 21:03:23 +01:00
|
|
|
|
&& (1
|
|
|
|
|
|| GET_CODE (XEXP (op, 0)) == PRE_INC
|
1999-01-15 19:43:47 +01:00
|
|
|
|
|| GET_CODE (XEXP (op, 0)) == POST_INC))
|
|
|
|
|
return 1;
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case 'E':
|
|
|
|
|
#ifndef REAL_ARITHMETIC
|
|
|
|
|
/* Match any floating double constant, but only if
|
|
|
|
|
we can examine the bits of it reliably. */
|
|
|
|
|
if ((HOST_FLOAT_FORMAT != TARGET_FLOAT_FORMAT
|
|
|
|
|
|| HOST_BITS_PER_WIDE_INT != BITS_PER_WORD)
|
|
|
|
|
&& GET_MODE (op) != VOIDmode && ! flag_pretend_float)
|
|
|
|
|
break;
|
|
|
|
|
#endif
|
|
|
|
|
/* FALLTHRU */
|
|
|
|
|
|
|
|
|
|
case 'F':
|
|
|
|
|
if (GET_CODE (op) == CONST_DOUBLE)
|
|
|
|
|
return 1;
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case 'G':
|
|
|
|
|
if (GET_CODE (op) == CONST_DOUBLE
|
|
|
|
|
&& CONST_DOUBLE_OK_FOR_LETTER_P (op, 'G'))
|
|
|
|
|
return 1;
|
|
|
|
|
break;
|
|
|
|
|
case 'H':
|
|
|
|
|
if (GET_CODE (op) == CONST_DOUBLE
|
|
|
|
|
&& CONST_DOUBLE_OK_FOR_LETTER_P (op, 'H'))
|
|
|
|
|
return 1;
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case 's':
|
|
|
|
|
if (GET_CODE (op) == CONST_INT
|
|
|
|
|
|| (GET_CODE (op) == CONST_DOUBLE
|
|
|
|
|
&& GET_MODE (op) == VOIDmode))
|
|
|
|
|
break;
|
|
|
|
|
/* FALLTHRU */
|
|
|
|
|
|
|
|
|
|
case 'i':
|
|
|
|
|
if (CONSTANT_P (op)
|
|
|
|
|
#ifdef LEGITIMATE_PIC_OPERAND_P
|
|
|
|
|
&& (! flag_pic || LEGITIMATE_PIC_OPERAND_P (op))
|
|
|
|
|
#endif
|
|
|
|
|
)
|
|
|
|
|
return 1;
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case 'n':
|
|
|
|
|
if (GET_CODE (op) == CONST_INT
|
|
|
|
|
|| (GET_CODE (op) == CONST_DOUBLE
|
|
|
|
|
&& GET_MODE (op) == VOIDmode))
|
|
|
|
|
return 1;
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case 'I':
|
|
|
|
|
if (GET_CODE (op) == CONST_INT
|
|
|
|
|
&& CONST_OK_FOR_LETTER_P (INTVAL (op), 'I'))
|
|
|
|
|
return 1;
|
|
|
|
|
break;
|
|
|
|
|
case 'J':
|
|
|
|
|
if (GET_CODE (op) == CONST_INT
|
|
|
|
|
&& CONST_OK_FOR_LETTER_P (INTVAL (op), 'J'))
|
|
|
|
|
return 1;
|
|
|
|
|
break;
|
|
|
|
|
case 'K':
|
|
|
|
|
if (GET_CODE (op) == CONST_INT
|
|
|
|
|
&& CONST_OK_FOR_LETTER_P (INTVAL (op), 'K'))
|
|
|
|
|
return 1;
|
|
|
|
|
break;
|
|
|
|
|
case 'L':
|
|
|
|
|
if (GET_CODE (op) == CONST_INT
|
|
|
|
|
&& CONST_OK_FOR_LETTER_P (INTVAL (op), 'L'))
|
|
|
|
|
return 1;
|
|
|
|
|
break;
|
|
|
|
|
case 'M':
|
|
|
|
|
if (GET_CODE (op) == CONST_INT
|
|
|
|
|
&& CONST_OK_FOR_LETTER_P (INTVAL (op), 'M'))
|
|
|
|
|
return 1;
|
|
|
|
|
break;
|
|
|
|
|
case 'N':
|
|
|
|
|
if (GET_CODE (op) == CONST_INT
|
|
|
|
|
&& CONST_OK_FOR_LETTER_P (INTVAL (op), 'N'))
|
|
|
|
|
return 1;
|
|
|
|
|
break;
|
|
|
|
|
case 'O':
|
|
|
|
|
if (GET_CODE (op) == CONST_INT
|
|
|
|
|
&& CONST_OK_FOR_LETTER_P (INTVAL (op), 'O'))
|
|
|
|
|
return 1;
|
|
|
|
|
break;
|
|
|
|
|
case 'P':
|
|
|
|
|
if (GET_CODE (op) == CONST_INT
|
|
|
|
|
&& CONST_OK_FOR_LETTER_P (INTVAL (op), 'P'))
|
|
|
|
|
return 1;
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case 'X':
|
|
|
|
|
return 1;
|
|
|
|
|
|
|
|
|
|
case 'g':
|
|
|
|
|
if (general_operand (op, VOIDmode))
|
|
|
|
|
return 1;
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
#ifdef EXTRA_CONSTRAINT
|
|
|
|
|
case 'Q':
|
|
|
|
|
if (EXTRA_CONSTRAINT (op, 'Q'))
|
|
|
|
|
return 1;
|
|
|
|
|
break;
|
|
|
|
|
case 'R':
|
|
|
|
|
if (EXTRA_CONSTRAINT (op, 'R'))
|
|
|
|
|
return 1;
|
|
|
|
|
break;
|
|
|
|
|
case 'S':
|
|
|
|
|
if (EXTRA_CONSTRAINT (op, 'S'))
|
|
|
|
|
return 1;
|
|
|
|
|
break;
|
|
|
|
|
case 'T':
|
|
|
|
|
if (EXTRA_CONSTRAINT (op, 'T'))
|
|
|
|
|
return 1;
|
|
|
|
|
break;
|
|
|
|
|
case 'U':
|
|
|
|
|
if (EXTRA_CONSTRAINT (op, 'U'))
|
|
|
|
|
return 1;
|
|
|
|
|
break;
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
case 'r':
|
|
|
|
|
default:
|
|
|
|
|
if (GET_MODE (op) == BLKmode)
|
|
|
|
|
break;
|
|
|
|
|
if (register_operand (op, VOIDmode))
|
|
|
|
|
return 1;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
1999-02-01 21:03:23 +01:00
|
|
|
|
return result;
|
1999-01-15 19:43:47 +01:00
|
|
|
|
}
|
1991-11-27 15:45:36 +01:00
|
|
|
|
|
|
|
|
|
/* Given an rtx *P, if it is a sum containing an integer constant term,
|
|
|
|
|
return the location (type rtx *) of the pointer to that constant term.
|
|
|
|
|
Otherwise, return a null pointer. */
|
|
|
|
|
|
|
|
|
|
static rtx *
|
|
|
|
|
find_constant_term_loc (p)
|
|
|
|
|
rtx *p;
|
|
|
|
|
{
|
|
|
|
|
register rtx *tem;
|
|
|
|
|
register enum rtx_code code = GET_CODE (*p);
|
|
|
|
|
|
|
|
|
|
/* If *P IS such a constant term, P is its location. */
|
|
|
|
|
|
|
|
|
|
if (code == CONST_INT || code == SYMBOL_REF || code == LABEL_REF
|
|
|
|
|
|| code == CONST)
|
|
|
|
|
return p;
|
|
|
|
|
|
|
|
|
|
/* Otherwise, if not a sum, it has no constant term. */
|
|
|
|
|
|
|
|
|
|
if (GET_CODE (*p) != PLUS)
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
|
|
/* If one of the summands is constant, return its location. */
|
|
|
|
|
|
|
|
|
|
if (XEXP (*p, 0) && CONSTANT_P (XEXP (*p, 0))
|
|
|
|
|
&& XEXP (*p, 1) && CONSTANT_P (XEXP (*p, 1)))
|
|
|
|
|
return p;
|
|
|
|
|
|
|
|
|
|
/* Otherwise, check each summand for containing a constant term. */
|
|
|
|
|
|
|
|
|
|
if (XEXP (*p, 0) != 0)
|
|
|
|
|
{
|
|
|
|
|
tem = find_constant_term_loc (&XEXP (*p, 0));
|
|
|
|
|
if (tem != 0)
|
|
|
|
|
return tem;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (XEXP (*p, 1) != 0)
|
|
|
|
|
{
|
|
|
|
|
tem = find_constant_term_loc (&XEXP (*p, 1));
|
|
|
|
|
if (tem != 0)
|
|
|
|
|
return tem;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Return 1 if OP is a memory reference
|
|
|
|
|
whose address contains no side effects
|
|
|
|
|
and remains valid after the addition
|
|
|
|
|
of a positive integer less than the
|
|
|
|
|
size of the object being referenced.
|
|
|
|
|
|
|
|
|
|
We assume that the original address is valid and do not check it.
|
|
|
|
|
|
|
|
|
|
This uses strict_memory_address_p as a subroutine, so
|
|
|
|
|
don't use it before reload. */
|
|
|
|
|
|
|
|
|
|
int
|
|
|
|
|
offsettable_memref_p (op)
|
|
|
|
|
rtx op;
|
|
|
|
|
{
|
|
|
|
|
return ((GET_CODE (op) == MEM)
|
|
|
|
|
&& offsettable_address_p (1, GET_MODE (op), XEXP (op, 0)));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Similar, but don't require a strictly valid mem ref:
|
|
|
|
|
consider pseudo-regs valid as index or base regs. */
|
|
|
|
|
|
|
|
|
|
int
|
|
|
|
|
offsettable_nonstrict_memref_p (op)
|
|
|
|
|
rtx op;
|
|
|
|
|
{
|
|
|
|
|
return ((GET_CODE (op) == MEM)
|
|
|
|
|
&& offsettable_address_p (0, GET_MODE (op), XEXP (op, 0)));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Return 1 if Y is a memory address which contains no side effects
|
|
|
|
|
and would remain valid after the addition of a positive integer
|
|
|
|
|
less than the size of that mode.
|
|
|
|
|
|
|
|
|
|
We assume that the original address is valid and do not check it.
|
|
|
|
|
We do check that it is valid for narrower modes.
|
|
|
|
|
|
|
|
|
|
If STRICTP is nonzero, we require a strictly valid address,
|
|
|
|
|
for the sake of use in reload.c. */
|
|
|
|
|
|
|
|
|
|
int
|
|
|
|
|
offsettable_address_p (strictp, mode, y)
|
|
|
|
|
int strictp;
|
|
|
|
|
enum machine_mode mode;
|
|
|
|
|
register rtx y;
|
|
|
|
|
{
|
|
|
|
|
register enum rtx_code ycode = GET_CODE (y);
|
|
|
|
|
register rtx z;
|
|
|
|
|
rtx y1 = y;
|
|
|
|
|
rtx *y2;
|
2000-01-17 16:37:04 +01:00
|
|
|
|
int (*addressp) PARAMS ((enum machine_mode, rtx)) =
|
1999-09-14 20:19:09 +02:00
|
|
|
|
(strictp ? strict_memory_address_p : memory_address_p);
|
2000-05-25 08:17:05 +02:00
|
|
|
|
unsigned int mode_sz = GET_MODE_SIZE (mode);
|
1991-11-27 15:45:36 +01:00
|
|
|
|
|
|
|
|
|
if (CONSTANT_ADDRESS_P (y))
|
|
|
|
|
return 1;
|
|
|
|
|
|
|
|
|
|
/* Adjusting an offsettable address involves changing to a narrower mode.
|
|
|
|
|
Make sure that's OK. */
|
|
|
|
|
|
|
|
|
|
if (mode_dependent_address_p (y))
|
|
|
|
|
return 0;
|
|
|
|
|
|
2000-05-25 08:17:05 +02:00
|
|
|
|
/* ??? How much offset does an offsettable BLKmode reference need?
|
|
|
|
|
Clearly that depends on the situation in which it's being used.
|
|
|
|
|
However, the current situation in which we test 0xffffffff is
|
|
|
|
|
less than ideal. Caveat user. */
|
|
|
|
|
if (mode_sz == 0)
|
|
|
|
|
mode_sz = BIGGEST_ALIGNMENT / BITS_PER_UNIT;
|
|
|
|
|
|
1991-11-27 15:45:36 +01:00
|
|
|
|
/* If the expression contains a constant term,
|
|
|
|
|
see if it remains valid when max possible offset is added. */
|
|
|
|
|
|
|
|
|
|
if ((ycode == PLUS) && (y2 = find_constant_term_loc (&y1)))
|
|
|
|
|
{
|
|
|
|
|
int good;
|
|
|
|
|
|
|
|
|
|
y1 = *y2;
|
2000-05-25 08:17:05 +02:00
|
|
|
|
*y2 = plus_constant (*y2, mode_sz - 1);
|
1991-11-27 15:45:36 +01:00
|
|
|
|
/* Use QImode because an odd displacement may be automatically invalid
|
|
|
|
|
for any wider mode. But it should be valid for a single byte. */
|
|
|
|
|
good = (*addressp) (QImode, y);
|
|
|
|
|
|
|
|
|
|
/* In any case, restore old contents of memory. */
|
|
|
|
|
*y2 = y1;
|
|
|
|
|
return good;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (ycode == PRE_DEC || ycode == PRE_INC
|
|
|
|
|
|| ycode == POST_DEC || ycode == POST_INC)
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
|
|
/* The offset added here is chosen as the maximum offset that
|
|
|
|
|
any instruction could need to add when operating on something
|
|
|
|
|
of the specified mode. We assume that if Y and Y+c are
|
|
|
|
|
valid addresses then so is Y+d for all 0<d<c. */
|
|
|
|
|
|
2000-05-25 08:17:05 +02:00
|
|
|
|
z = plus_constant_for_output (y, mode_sz - 1);
|
1991-11-27 15:45:36 +01:00
|
|
|
|
|
|
|
|
|
/* Use QImode because an odd displacement may be automatically invalid
|
|
|
|
|
for any wider mode. But it should be valid for a single byte. */
|
|
|
|
|
return (*addressp) (QImode, z);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Return 1 if ADDR is an address-expression whose effect depends
|
|
|
|
|
on the mode of the memory reference it is used in.
|
|
|
|
|
|
|
|
|
|
Autoincrement addressing is a typical example of mode-dependence
|
|
|
|
|
because the amount of the increment depends on the mode. */
|
|
|
|
|
|
|
|
|
|
int
|
|
|
|
|
mode_dependent_address_p (addr)
|
1999-01-18 07:17:31 +01:00
|
|
|
|
rtx addr ATTRIBUTE_UNUSED; /* Maybe used in GO_IF_MODE_DEPENDENT_ADDRESS. */
|
1991-11-27 15:45:36 +01:00
|
|
|
|
{
|
|
|
|
|
GO_IF_MODE_DEPENDENT_ADDRESS (addr, win);
|
|
|
|
|
return 0;
|
1999-01-18 07:17:31 +01:00
|
|
|
|
/* Label `win' might (not) be used via GO_IF_MODE_DEPENDENT_ADDRESS. */
|
|
|
|
|
win: ATTRIBUTE_UNUSED_LABEL
|
1991-11-27 15:45:36 +01:00
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Return 1 if OP is a general operand
|
|
|
|
|
other than a memory ref with a mode dependent address. */
|
|
|
|
|
|
|
|
|
|
int
|
|
|
|
|
mode_independent_operand (op, mode)
|
|
|
|
|
enum machine_mode mode;
|
|
|
|
|
rtx op;
|
|
|
|
|
{
|
|
|
|
|
rtx addr;
|
|
|
|
|
|
|
|
|
|
if (! general_operand (op, mode))
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
|
|
if (GET_CODE (op) != MEM)
|
|
|
|
|
return 1;
|
|
|
|
|
|
|
|
|
|
addr = XEXP (op, 0);
|
|
|
|
|
GO_IF_MODE_DEPENDENT_ADDRESS (addr, lose);
|
|
|
|
|
return 1;
|
1999-01-18 07:17:31 +01:00
|
|
|
|
/* Label `lose' might (not) be used via GO_IF_MODE_DEPENDENT_ADDRESS. */
|
|
|
|
|
lose: ATTRIBUTE_UNUSED_LABEL
|
1991-11-27 15:45:36 +01:00
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
Makefile.in (c-decl.o): Depend on rtl.h and expr.h.
* Makefile.in (c-decl.o): Depend on rtl.h and expr.h.
* alias.c (struct alias_entry): alias_set is HOST_WIDE_INT.
(REG_BASE_VALUE): Remove unneeded cast to unsigned.
(get_alias_set_entry): ALIAS_SET arg is HOST_WIDE_INT.
(find_base_decl): New function, from c_find_base_decl in c-common.c.
(new_alias_set): Moved from tree.c; return is HOST_WIDE_INT.
(get_alias_set): Likewise.
Major rework to do more things and allow language-specific code
to just handle special-cases.
(record_alias_subset): Args are HOST_WIDE_INT.
(record_component_alias): Local vars are HOST_WIDE_INT.
Don't handle COMPLEX_EXPR.
(get_varargs_alias_set): Moved from builtins.c.
(get_frame_alias_set): New function.
* builtins.c (expand_builtin_return_address): Use frame alias set.
(expand_builtin_setjmp, expand_builtin_longjmp): Use alias set
for setjmp buffer.
(get_memory_rtx): Rework to use set_mem_attributes.
(get_varargs_alias_set): Deleted from here.
* c-common.c (c_apply_type_quals_to_decl): Alias sets now HOST_WIDE_INT.
(c_find_base_decl): Deleted from here.
(c_get_alias_set): Remove many cases and rework to just handle
C-specific cases.
* c-common.h (c_get_alias_set): Returns HOST_WIDE_INT.
* c-decl.c (rtl.h, expr.h): Now included.
(init_decl_processing): Call record_component_aliases on array types.
(grokdeclarator): Likewise.
Set TREE_ADDRESSABLE for all fields that are not bitfields.
* c-typeck.c (common_type): Call record_component_aliases for array.
* caller-save.c (setup_save_areas): Rework register loop for unsigned.
Set all save areas to the frame alias set.
* calls.c (initialie_argument_information): Call set_mem_attributes.
(compute_argument_addresses, expand_call): Likewise.
* explow.c (set_mem_attributes): New function.
(stabilize): Use MEM_COPY_ATTRIBUTES and force_reg.
* expr.c (struct move_by_pieces): Remove {to,from}_{struct,readonly}.
LEN and OFFSET now HOST_WIDE_INT.
(clear_by_pieces): Similar changes.
(move_by_pieces): LEN now HOST_WIDE_INT; don't set deleted fields.
(move_by_pieces_ninsns): Now returns unsigned HOST_WIDE_INT.
(move_by_pieces_1): Don't use deleted fields, use MEM_COPY_ATTRIBUTES.
(clear_by_pieces_1): Likewise.
(emit_push_insn): Call set_mem_attributes.
(expand_expr, case INDIRECT_REF): Likewise.
(expand_expr, case VAR_DECL): Call change_address.
* expr.h (ADD_PARM_SIZE, SUB_PARM_SIZE): Use host_integerp and
tree_low_cst.
(get_varargs_alias_set, get_frame_alias_set): New decls.
(record_base_value, record_alias_subset, lang_get_alias_set): Likewise.
(new_alias_set, set_mem_attributes): Likewse.
* function.c (struct temp_slot): ALIAS_SET is HOST_WIDE_INT.
(assign_stack_temp_for_type): Likewise.
Can split slot even if alias set since can copy.
Set MEM_ALIAS_SET and MEM_SET_IN_STRUCT_P.
(assign_temp): Use host_integerp and tree_low_cst.
(put_var_into_stack): Properly handle SAVE_EXPR.
(put_addressof_into_stack): Likewise.
(assign_parms): Call set_mem_attributes.
Delete #if 0 code.
(fix_lexical_address): Put reference to chain into frame alias set.
(expand_function_start): Call set_mem_attributes.
* integrate.c (expand_inline_function): Likewise.
* recog.c (adj_offsettable_operand): Use MEM_COPY_ATTRIBUTES.
* regmove.c (try_apply_stack_adjustment): Likewise.
* reload.c (push_reload, make_memloc): Likewise.
* reload1.c (alter_reg): Make alias sets for spilled pseudos.
* rtl.def (MEM): Update comment.
* rtl.h (MEM_ALIAS_SET): Now uses XCWINT.
(move_by_pieces): Change length to HOST_WIDE_INT.
(record_base_value, record_alias_subset): Delete from here.
* stmt.c (expand_decl): Call set_mem_attributes.
* stor-layout.c (finish_record_layout): Call record_component_aliases.i
* toplev.c (compile_file): Call init_alias_once earlier.
* tree.c (lang_get_alias_set, get_alias_set, new_alias_set): Deleted
from here: now in alias.c.
* tree.h (struct tree_type): alias_set is HOST_WIDE_INT.
(struct tree_decl): Likewise.
(get_alias_set, new_alias_set, lang_get_alias_set): Deleted from here.
* varasm.c (make_function_rtl, make_decl_rtl): Call set_mem_attributes.
(output_constant_def, force_const_mem): Likewise.
* cp/Makefile.in (decl.o): Include ../expr.h.
* cp/decl.c (expr.h): Include.
(init_decl_processing): Call record_component_aliases for arrays.
(grokdeclarator): Likewise.
Set TREE_ADDRESSABLE for fields that aren't bitfields.
* cp/tree.c (build_cplus_array_type_1): Call record_component_aliases.
From-SVN: r34305
2000-05-31 20:37:31 +02:00
|
|
|
|
/* Given an operand OP that is a valid memory reference which
|
|
|
|
|
satisfies offsettable_memref_p, return a new memory reference whose
|
|
|
|
|
address has been adjusted by OFFSET. OFFSET should be positive and
|
|
|
|
|
less than the size of the object referenced. */
|
1991-11-27 15:45:36 +01:00
|
|
|
|
|
|
|
|
|
rtx
|
|
|
|
|
adj_offsettable_operand (op, offset)
|
|
|
|
|
rtx op;
|
|
|
|
|
int offset;
|
|
|
|
|
{
|
|
|
|
|
register enum rtx_code code = GET_CODE (op);
|
|
|
|
|
|
|
|
|
|
if (code == MEM)
|
|
|
|
|
{
|
|
|
|
|
register rtx y = XEXP (op, 0);
|
|
|
|
|
register rtx new;
|
|
|
|
|
|
|
|
|
|
if (CONSTANT_ADDRESS_P (y))
|
|
|
|
|
{
|
1999-09-07 07:49:18 +02:00
|
|
|
|
new = gen_rtx_MEM (GET_MODE (op),
|
|
|
|
|
plus_constant_for_output (y, offset));
|
Makefile.in (c-decl.o): Depend on rtl.h and expr.h.
* Makefile.in (c-decl.o): Depend on rtl.h and expr.h.
* alias.c (struct alias_entry): alias_set is HOST_WIDE_INT.
(REG_BASE_VALUE): Remove unneeded cast to unsigned.
(get_alias_set_entry): ALIAS_SET arg is HOST_WIDE_INT.
(find_base_decl): New function, from c_find_base_decl in c-common.c.
(new_alias_set): Moved from tree.c; return is HOST_WIDE_INT.
(get_alias_set): Likewise.
Major rework to do more things and allow language-specific code
to just handle special-cases.
(record_alias_subset): Args are HOST_WIDE_INT.
(record_component_alias): Local vars are HOST_WIDE_INT.
Don't handle COMPLEX_EXPR.
(get_varargs_alias_set): Moved from builtins.c.
(get_frame_alias_set): New function.
* builtins.c (expand_builtin_return_address): Use frame alias set.
(expand_builtin_setjmp, expand_builtin_longjmp): Use alias set
for setjmp buffer.
(get_memory_rtx): Rework to use set_mem_attributes.
(get_varargs_alias_set): Deleted from here.
* c-common.c (c_apply_type_quals_to_decl): Alias sets now HOST_WIDE_INT.
(c_find_base_decl): Deleted from here.
(c_get_alias_set): Remove many cases and rework to just handle
C-specific cases.
* c-common.h (c_get_alias_set): Returns HOST_WIDE_INT.
* c-decl.c (rtl.h, expr.h): Now included.
(init_decl_processing): Call record_component_aliases on array types.
(grokdeclarator): Likewise.
Set TREE_ADDRESSABLE for all fields that are not bitfields.
* c-typeck.c (common_type): Call record_component_aliases for array.
* caller-save.c (setup_save_areas): Rework register loop for unsigned.
Set all save areas to the frame alias set.
* calls.c (initialie_argument_information): Call set_mem_attributes.
(compute_argument_addresses, expand_call): Likewise.
* explow.c (set_mem_attributes): New function.
(stabilize): Use MEM_COPY_ATTRIBUTES and force_reg.
* expr.c (struct move_by_pieces): Remove {to,from}_{struct,readonly}.
LEN and OFFSET now HOST_WIDE_INT.
(clear_by_pieces): Similar changes.
(move_by_pieces): LEN now HOST_WIDE_INT; don't set deleted fields.
(move_by_pieces_ninsns): Now returns unsigned HOST_WIDE_INT.
(move_by_pieces_1): Don't use deleted fields, use MEM_COPY_ATTRIBUTES.
(clear_by_pieces_1): Likewise.
(emit_push_insn): Call set_mem_attributes.
(expand_expr, case INDIRECT_REF): Likewise.
(expand_expr, case VAR_DECL): Call change_address.
* expr.h (ADD_PARM_SIZE, SUB_PARM_SIZE): Use host_integerp and
tree_low_cst.
(get_varargs_alias_set, get_frame_alias_set): New decls.
(record_base_value, record_alias_subset, lang_get_alias_set): Likewise.
(new_alias_set, set_mem_attributes): Likewse.
* function.c (struct temp_slot): ALIAS_SET is HOST_WIDE_INT.
(assign_stack_temp_for_type): Likewise.
Can split slot even if alias set since can copy.
Set MEM_ALIAS_SET and MEM_SET_IN_STRUCT_P.
(assign_temp): Use host_integerp and tree_low_cst.
(put_var_into_stack): Properly handle SAVE_EXPR.
(put_addressof_into_stack): Likewise.
(assign_parms): Call set_mem_attributes.
Delete #if 0 code.
(fix_lexical_address): Put reference to chain into frame alias set.
(expand_function_start): Call set_mem_attributes.
* integrate.c (expand_inline_function): Likewise.
* recog.c (adj_offsettable_operand): Use MEM_COPY_ATTRIBUTES.
* regmove.c (try_apply_stack_adjustment): Likewise.
* reload.c (push_reload, make_memloc): Likewise.
* reload1.c (alter_reg): Make alias sets for spilled pseudos.
* rtl.def (MEM): Update comment.
* rtl.h (MEM_ALIAS_SET): Now uses XCWINT.
(move_by_pieces): Change length to HOST_WIDE_INT.
(record_base_value, record_alias_subset): Delete from here.
* stmt.c (expand_decl): Call set_mem_attributes.
* stor-layout.c (finish_record_layout): Call record_component_aliases.i
* toplev.c (compile_file): Call init_alias_once earlier.
* tree.c (lang_get_alias_set, get_alias_set, new_alias_set): Deleted
from here: now in alias.c.
* tree.h (struct tree_type): alias_set is HOST_WIDE_INT.
(struct tree_decl): Likewise.
(get_alias_set, new_alias_set, lang_get_alias_set): Deleted from here.
* varasm.c (make_function_rtl, make_decl_rtl): Call set_mem_attributes.
(output_constant_def, force_const_mem): Likewise.
* cp/Makefile.in (decl.o): Include ../expr.h.
* cp/decl.c (expr.h): Include.
(init_decl_processing): Call record_component_aliases for arrays.
(grokdeclarator): Likewise.
Set TREE_ADDRESSABLE for fields that aren't bitfields.
* cp/tree.c (build_cplus_array_type_1): Call record_component_aliases.
From-SVN: r34305
2000-05-31 20:37:31 +02:00
|
|
|
|
MEM_COPY_ATTRIBUTES (new, op);
|
1991-11-27 15:45:36 +01:00
|
|
|
|
return new;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (GET_CODE (y) == PLUS)
|
|
|
|
|
{
|
|
|
|
|
rtx z = y;
|
|
|
|
|
register rtx *const_loc;
|
|
|
|
|
|
|
|
|
|
op = copy_rtx (op);
|
|
|
|
|
z = XEXP (op, 0);
|
|
|
|
|
const_loc = find_constant_term_loc (&z);
|
|
|
|
|
if (const_loc)
|
|
|
|
|
{
|
|
|
|
|
*const_loc = plus_constant_for_output (*const_loc, offset);
|
|
|
|
|
return op;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
alias.c: Change all uses of gen_rtx(FOO...) to gen_rtx_FOO...
* alias.c: Change all uses of gen_rtx(FOO...) to gen_rtx_FOO;
change gen_rtx(expr...) to gen_rtx_fmt_foo(expr...).
* caller-save.c, calls.c, combine.c, cse.c: Likewise.
* dwarf2out.c, except.c, explow.c, expmed.c, expr.c: Likewise.
* final.c, flow.c, function.c, genpeep.c, haifa-sched.c: Likewise.
* halfpic.c, integrate.c, jump.c, local-alloc.c, loop.c: Likewise.
* profile.c, recog.c, reg-stack.c, regclass.c, regmove.c: Likewise.
* reload.c, reload1.c, reorg.c, sched.c, stmt.c, stupid.c: Likewise.
* unroll.c, varasm.c: Likewise.
* config/alpha/alpha.c, config/alpha/alpha.md: Likewise.
From-SVN: r17357
1998-01-15 00:10:50 +01:00
|
|
|
|
new = gen_rtx_MEM (GET_MODE (op), plus_constant_for_output (y, offset));
|
Makefile.in (c-decl.o): Depend on rtl.h and expr.h.
* Makefile.in (c-decl.o): Depend on rtl.h and expr.h.
* alias.c (struct alias_entry): alias_set is HOST_WIDE_INT.
(REG_BASE_VALUE): Remove unneeded cast to unsigned.
(get_alias_set_entry): ALIAS_SET arg is HOST_WIDE_INT.
(find_base_decl): New function, from c_find_base_decl in c-common.c.
(new_alias_set): Moved from tree.c; return is HOST_WIDE_INT.
(get_alias_set): Likewise.
Major rework to do more things and allow language-specific code
to just handle special-cases.
(record_alias_subset): Args are HOST_WIDE_INT.
(record_component_alias): Local vars are HOST_WIDE_INT.
Don't handle COMPLEX_EXPR.
(get_varargs_alias_set): Moved from builtins.c.
(get_frame_alias_set): New function.
* builtins.c (expand_builtin_return_address): Use frame alias set.
(expand_builtin_setjmp, expand_builtin_longjmp): Use alias set
for setjmp buffer.
(get_memory_rtx): Rework to use set_mem_attributes.
(get_varargs_alias_set): Deleted from here.
* c-common.c (c_apply_type_quals_to_decl): Alias sets now HOST_WIDE_INT.
(c_find_base_decl): Deleted from here.
(c_get_alias_set): Remove many cases and rework to just handle
C-specific cases.
* c-common.h (c_get_alias_set): Returns HOST_WIDE_INT.
* c-decl.c (rtl.h, expr.h): Now included.
(init_decl_processing): Call record_component_aliases on array types.
(grokdeclarator): Likewise.
Set TREE_ADDRESSABLE for all fields that are not bitfields.
* c-typeck.c (common_type): Call record_component_aliases for array.
* caller-save.c (setup_save_areas): Rework register loop for unsigned.
Set all save areas to the frame alias set.
* calls.c (initialie_argument_information): Call set_mem_attributes.
(compute_argument_addresses, expand_call): Likewise.
* explow.c (set_mem_attributes): New function.
(stabilize): Use MEM_COPY_ATTRIBUTES and force_reg.
* expr.c (struct move_by_pieces): Remove {to,from}_{struct,readonly}.
LEN and OFFSET now HOST_WIDE_INT.
(clear_by_pieces): Similar changes.
(move_by_pieces): LEN now HOST_WIDE_INT; don't set deleted fields.
(move_by_pieces_ninsns): Now returns unsigned HOST_WIDE_INT.
(move_by_pieces_1): Don't use deleted fields, use MEM_COPY_ATTRIBUTES.
(clear_by_pieces_1): Likewise.
(emit_push_insn): Call set_mem_attributes.
(expand_expr, case INDIRECT_REF): Likewise.
(expand_expr, case VAR_DECL): Call change_address.
* expr.h (ADD_PARM_SIZE, SUB_PARM_SIZE): Use host_integerp and
tree_low_cst.
(get_varargs_alias_set, get_frame_alias_set): New decls.
(record_base_value, record_alias_subset, lang_get_alias_set): Likewise.
(new_alias_set, set_mem_attributes): Likewse.
* function.c (struct temp_slot): ALIAS_SET is HOST_WIDE_INT.
(assign_stack_temp_for_type): Likewise.
Can split slot even if alias set since can copy.
Set MEM_ALIAS_SET and MEM_SET_IN_STRUCT_P.
(assign_temp): Use host_integerp and tree_low_cst.
(put_var_into_stack): Properly handle SAVE_EXPR.
(put_addressof_into_stack): Likewise.
(assign_parms): Call set_mem_attributes.
Delete #if 0 code.
(fix_lexical_address): Put reference to chain into frame alias set.
(expand_function_start): Call set_mem_attributes.
* integrate.c (expand_inline_function): Likewise.
* recog.c (adj_offsettable_operand): Use MEM_COPY_ATTRIBUTES.
* regmove.c (try_apply_stack_adjustment): Likewise.
* reload.c (push_reload, make_memloc): Likewise.
* reload1.c (alter_reg): Make alias sets for spilled pseudos.
* rtl.def (MEM): Update comment.
* rtl.h (MEM_ALIAS_SET): Now uses XCWINT.
(move_by_pieces): Change length to HOST_WIDE_INT.
(record_base_value, record_alias_subset): Delete from here.
* stmt.c (expand_decl): Call set_mem_attributes.
* stor-layout.c (finish_record_layout): Call record_component_aliases.i
* toplev.c (compile_file): Call init_alias_once earlier.
* tree.c (lang_get_alias_set, get_alias_set, new_alias_set): Deleted
from here: now in alias.c.
* tree.h (struct tree_type): alias_set is HOST_WIDE_INT.
(struct tree_decl): Likewise.
(get_alias_set, new_alias_set, lang_get_alias_set): Deleted from here.
* varasm.c (make_function_rtl, make_decl_rtl): Call set_mem_attributes.
(output_constant_def, force_const_mem): Likewise.
* cp/Makefile.in (decl.o): Include ../expr.h.
* cp/decl.c (expr.h): Include.
(init_decl_processing): Call record_component_aliases for arrays.
(grokdeclarator): Likewise.
Set TREE_ADDRESSABLE for fields that aren't bitfields.
* cp/tree.c (build_cplus_array_type_1): Call record_component_aliases.
From-SVN: r34305
2000-05-31 20:37:31 +02:00
|
|
|
|
MEM_COPY_ATTRIBUTES (new, op);
|
1991-11-27 15:45:36 +01:00
|
|
|
|
return new;
|
|
|
|
|
}
|
|
|
|
|
abort ();
|
|
|
|
|
}
|
|
|
|
|
|
1999-09-12 03:51:28 +02:00
|
|
|
|
/* Analyze INSN and fill in recog_data. */
|
|
|
|
|
|
Makefile.in (insn-extract.o): Fix dependencies.
* Makefile.in (insn-extract.o): Fix dependencies.
* genextract.c (main): Generate includes for insn-config.h and
recog.h.
Delete generation of declarations which are now in recog.h.
* genrecog.c (main): Delete generation of definitions which are
now in recog.c.
* local-alloc.c (block_alloc): Use extract_insn and the variables
it sets up instead of looking up values by insn_code.
* recog.c (recog_operand, recog_operand_loc, recog_dup_loc,
recog_dup_num): Define here instead of generating the definition in
genrecog.c.
(recog_n_operands, recog_n_dups, recog_n_alternatives,
recog_operand_mode, recog_constraints, recog_operand_address_p):
New variables.
(extract_insn): New function.
* recog.h (extract_insn): Declare function.
(which_alternative, recog_n_operands, recog_n_dups,
recog_n_alternatives, recog_operand_mode, recog_constraints,
recog_operand_address_p): Declare variables.
* regclass.c (n_occurrences): New static function.
* reload.c (n_occurrences): Delete function.
(find_reloads): Use extract_insn.
* reload.h (n_occurrences): Delete declaration.
From-SVN: r23147
1998-10-17 03:28:57 +02:00
|
|
|
|
void
|
|
|
|
|
extract_insn (insn)
|
|
|
|
|
rtx insn;
|
|
|
|
|
{
|
|
|
|
|
int i;
|
|
|
|
|
int icode;
|
|
|
|
|
int noperands;
|
|
|
|
|
rtx body = PATTERN (insn);
|
|
|
|
|
|
1999-09-12 03:51:28 +02:00
|
|
|
|
recog_data.n_operands = 0;
|
|
|
|
|
recog_data.n_alternatives = 0;
|
|
|
|
|
recog_data.n_dups = 0;
|
Makefile.in (insn-extract.o): Fix dependencies.
* Makefile.in (insn-extract.o): Fix dependencies.
* genextract.c (main): Generate includes for insn-config.h and
recog.h.
Delete generation of declarations which are now in recog.h.
* genrecog.c (main): Delete generation of definitions which are
now in recog.c.
* local-alloc.c (block_alloc): Use extract_insn and the variables
it sets up instead of looking up values by insn_code.
* recog.c (recog_operand, recog_operand_loc, recog_dup_loc,
recog_dup_num): Define here instead of generating the definition in
genrecog.c.
(recog_n_operands, recog_n_dups, recog_n_alternatives,
recog_operand_mode, recog_constraints, recog_operand_address_p):
New variables.
(extract_insn): New function.
* recog.h (extract_insn): Declare function.
(which_alternative, recog_n_operands, recog_n_dups,
recog_n_alternatives, recog_operand_mode, recog_constraints,
recog_operand_address_p): Declare variables.
* regclass.c (n_occurrences): New static function.
* reload.c (n_occurrences): Delete function.
(find_reloads): Use extract_insn.
* reload.h (n_occurrences): Delete declaration.
From-SVN: r23147
1998-10-17 03:28:57 +02:00
|
|
|
|
|
|
|
|
|
switch (GET_CODE (body))
|
|
|
|
|
{
|
|
|
|
|
case USE:
|
|
|
|
|
case CLOBBER:
|
|
|
|
|
case ASM_INPUT:
|
|
|
|
|
case ADDR_VEC:
|
|
|
|
|
case ADDR_DIFF_VEC:
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
case SET:
|
|
|
|
|
case PARALLEL:
|
|
|
|
|
case ASM_OPERANDS:
|
1999-09-12 03:51:28 +02:00
|
|
|
|
recog_data.n_operands = noperands = asm_noperands (body);
|
Makefile.in (insn-extract.o): Fix dependencies.
* Makefile.in (insn-extract.o): Fix dependencies.
* genextract.c (main): Generate includes for insn-config.h and
recog.h.
Delete generation of declarations which are now in recog.h.
* genrecog.c (main): Delete generation of definitions which are
now in recog.c.
* local-alloc.c (block_alloc): Use extract_insn and the variables
it sets up instead of looking up values by insn_code.
* recog.c (recog_operand, recog_operand_loc, recog_dup_loc,
recog_dup_num): Define here instead of generating the definition in
genrecog.c.
(recog_n_operands, recog_n_dups, recog_n_alternatives,
recog_operand_mode, recog_constraints, recog_operand_address_p):
New variables.
(extract_insn): New function.
* recog.h (extract_insn): Declare function.
(which_alternative, recog_n_operands, recog_n_dups,
recog_n_alternatives, recog_operand_mode, recog_constraints,
recog_operand_address_p): Declare variables.
* regclass.c (n_occurrences): New static function.
* reload.c (n_occurrences): Delete function.
(find_reloads): Use extract_insn.
* reload.h (n_occurrences): Delete declaration.
From-SVN: r23147
1998-10-17 03:28:57 +02:00
|
|
|
|
if (noperands >= 0)
|
|
|
|
|
{
|
|
|
|
|
/* This insn is an `asm' with operands. */
|
|
|
|
|
|
|
|
|
|
/* expand_asm_operands makes sure there aren't too many operands. */
|
|
|
|
|
if (noperands > MAX_RECOG_OPERANDS)
|
|
|
|
|
abort ();
|
|
|
|
|
|
|
|
|
|
/* Now get the operand values and constraints out of the insn. */
|
1999-09-12 03:51:28 +02:00
|
|
|
|
decode_asm_operands (body, recog_data.operand,
|
|
|
|
|
recog_data.operand_loc,
|
|
|
|
|
recog_data.constraints,
|
|
|
|
|
recog_data.operand_mode);
|
Makefile.in (insn-extract.o): Fix dependencies.
* Makefile.in (insn-extract.o): Fix dependencies.
* genextract.c (main): Generate includes for insn-config.h and
recog.h.
Delete generation of declarations which are now in recog.h.
* genrecog.c (main): Delete generation of definitions which are
now in recog.c.
* local-alloc.c (block_alloc): Use extract_insn and the variables
it sets up instead of looking up values by insn_code.
* recog.c (recog_operand, recog_operand_loc, recog_dup_loc,
recog_dup_num): Define here instead of generating the definition in
genrecog.c.
(recog_n_operands, recog_n_dups, recog_n_alternatives,
recog_operand_mode, recog_constraints, recog_operand_address_p):
New variables.
(extract_insn): New function.
* recog.h (extract_insn): Declare function.
(which_alternative, recog_n_operands, recog_n_dups,
recog_n_alternatives, recog_operand_mode, recog_constraints,
recog_operand_address_p): Declare variables.
* regclass.c (n_occurrences): New static function.
* reload.c (n_occurrences): Delete function.
(find_reloads): Use extract_insn.
* reload.h (n_occurrences): Delete declaration.
From-SVN: r23147
1998-10-17 03:28:57 +02:00
|
|
|
|
if (noperands > 0)
|
|
|
|
|
{
|
1999-09-12 03:51:28 +02:00
|
|
|
|
const char *p = recog_data.constraints[0];
|
|
|
|
|
recog_data.n_alternatives = 1;
|
Makefile.in (insn-extract.o): Fix dependencies.
* Makefile.in (insn-extract.o): Fix dependencies.
* genextract.c (main): Generate includes for insn-config.h and
recog.h.
Delete generation of declarations which are now in recog.h.
* genrecog.c (main): Delete generation of definitions which are
now in recog.c.
* local-alloc.c (block_alloc): Use extract_insn and the variables
it sets up instead of looking up values by insn_code.
* recog.c (recog_operand, recog_operand_loc, recog_dup_loc,
recog_dup_num): Define here instead of generating the definition in
genrecog.c.
(recog_n_operands, recog_n_dups, recog_n_alternatives,
recog_operand_mode, recog_constraints, recog_operand_address_p):
New variables.
(extract_insn): New function.
* recog.h (extract_insn): Declare function.
(which_alternative, recog_n_operands, recog_n_dups,
recog_n_alternatives, recog_operand_mode, recog_constraints,
recog_operand_address_p): Declare variables.
* regclass.c (n_occurrences): New static function.
* reload.c (n_occurrences): Delete function.
(find_reloads): Use extract_insn.
* reload.h (n_occurrences): Delete declaration.
From-SVN: r23147
1998-10-17 03:28:57 +02:00
|
|
|
|
while (*p)
|
1999-09-12 03:51:28 +02:00
|
|
|
|
recog_data.n_alternatives += (*p++ == ',');
|
Makefile.in (insn-extract.o): Fix dependencies.
* Makefile.in (insn-extract.o): Fix dependencies.
* genextract.c (main): Generate includes for insn-config.h and
recog.h.
Delete generation of declarations which are now in recog.h.
* genrecog.c (main): Delete generation of definitions which are
now in recog.c.
* local-alloc.c (block_alloc): Use extract_insn and the variables
it sets up instead of looking up values by insn_code.
* recog.c (recog_operand, recog_operand_loc, recog_dup_loc,
recog_dup_num): Define here instead of generating the definition in
genrecog.c.
(recog_n_operands, recog_n_dups, recog_n_alternatives,
recog_operand_mode, recog_constraints, recog_operand_address_p):
New variables.
(extract_insn): New function.
* recog.h (extract_insn): Declare function.
(which_alternative, recog_n_operands, recog_n_dups,
recog_n_alternatives, recog_operand_mode, recog_constraints,
recog_operand_address_p): Declare variables.
* regclass.c (n_occurrences): New static function.
* reload.c (n_occurrences): Delete function.
(find_reloads): Use extract_insn.
* reload.h (n_occurrences): Delete declaration.
From-SVN: r23147
1998-10-17 03:28:57 +02:00
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* FALLTHROUGH */
|
|
|
|
|
|
|
|
|
|
default:
|
|
|
|
|
/* Ordinary insn: recognize it, get the operands via insn_extract
|
|
|
|
|
and get the constraints. */
|
|
|
|
|
|
|
|
|
|
icode = recog_memoized (insn);
|
|
|
|
|
if (icode < 0)
|
|
|
|
|
fatal_insn_not_found (insn);
|
|
|
|
|
|
1999-09-12 14:46:08 +02:00
|
|
|
|
recog_data.n_operands = noperands = insn_data[icode].n_operands;
|
|
|
|
|
recog_data.n_alternatives = insn_data[icode].n_alternatives;
|
|
|
|
|
recog_data.n_dups = insn_data[icode].n_dups;
|
Makefile.in (insn-extract.o): Fix dependencies.
* Makefile.in (insn-extract.o): Fix dependencies.
* genextract.c (main): Generate includes for insn-config.h and
recog.h.
Delete generation of declarations which are now in recog.h.
* genrecog.c (main): Delete generation of definitions which are
now in recog.c.
* local-alloc.c (block_alloc): Use extract_insn and the variables
it sets up instead of looking up values by insn_code.
* recog.c (recog_operand, recog_operand_loc, recog_dup_loc,
recog_dup_num): Define here instead of generating the definition in
genrecog.c.
(recog_n_operands, recog_n_dups, recog_n_alternatives,
recog_operand_mode, recog_constraints, recog_operand_address_p):
New variables.
(extract_insn): New function.
* recog.h (extract_insn): Declare function.
(which_alternative, recog_n_operands, recog_n_dups,
recog_n_alternatives, recog_operand_mode, recog_constraints,
recog_operand_address_p): Declare variables.
* regclass.c (n_occurrences): New static function.
* reload.c (n_occurrences): Delete function.
(find_reloads): Use extract_insn.
* reload.h (n_occurrences): Delete declaration.
From-SVN: r23147
1998-10-17 03:28:57 +02:00
|
|
|
|
|
|
|
|
|
insn_extract (insn);
|
|
|
|
|
|
|
|
|
|
for (i = 0; i < noperands; i++)
|
|
|
|
|
{
|
1999-09-12 14:46:08 +02:00
|
|
|
|
recog_data.constraints[i] = insn_data[icode].operand[i].constraint;
|
|
|
|
|
recog_data.operand_mode[i] = insn_data[icode].operand[i].mode;
|
Makefile.in (insn-extract.o): Fix dependencies.
* Makefile.in (insn-extract.o): Fix dependencies.
* genextract.c (main): Generate includes for insn-config.h and
recog.h.
Delete generation of declarations which are now in recog.h.
* genrecog.c (main): Delete generation of definitions which are
now in recog.c.
* local-alloc.c (block_alloc): Use extract_insn and the variables
it sets up instead of looking up values by insn_code.
* recog.c (recog_operand, recog_operand_loc, recog_dup_loc,
recog_dup_num): Define here instead of generating the definition in
genrecog.c.
(recog_n_operands, recog_n_dups, recog_n_alternatives,
recog_operand_mode, recog_constraints, recog_operand_address_p):
New variables.
(extract_insn): New function.
* recog.h (extract_insn): Declare function.
(which_alternative, recog_n_operands, recog_n_dups,
recog_n_alternatives, recog_operand_mode, recog_constraints,
recog_operand_address_p): Declare variables.
* regclass.c (n_occurrences): New static function.
* reload.c (n_occurrences): Delete function.
(find_reloads): Use extract_insn.
* reload.h (n_occurrences): Delete declaration.
From-SVN: r23147
1998-10-17 03:28:57 +02:00
|
|
|
|
}
|
|
|
|
|
}
|
1998-11-04 22:25:00 +01:00
|
|
|
|
for (i = 0; i < noperands; i++)
|
1999-09-12 03:51:28 +02:00
|
|
|
|
recog_data.operand_type[i]
|
|
|
|
|
= (recog_data.constraints[i][0] == '=' ? OP_OUT
|
|
|
|
|
: recog_data.constraints[i][0] == '+' ? OP_INOUT
|
|
|
|
|
: OP_IN);
|
1998-12-04 13:55:59 +01:00
|
|
|
|
|
1999-09-12 03:51:28 +02:00
|
|
|
|
if (recog_data.n_alternatives > MAX_RECOG_ALTERNATIVES)
|
1998-12-04 13:55:59 +01:00
|
|
|
|
abort ();
|
Makefile.in (insn-extract.o): Fix dependencies.
* Makefile.in (insn-extract.o): Fix dependencies.
* genextract.c (main): Generate includes for insn-config.h and
recog.h.
Delete generation of declarations which are now in recog.h.
* genrecog.c (main): Delete generation of definitions which are
now in recog.c.
* local-alloc.c (block_alloc): Use extract_insn and the variables
it sets up instead of looking up values by insn_code.
* recog.c (recog_operand, recog_operand_loc, recog_dup_loc,
recog_dup_num): Define here instead of generating the definition in
genrecog.c.
(recog_n_operands, recog_n_dups, recog_n_alternatives,
recog_operand_mode, recog_constraints, recog_operand_address_p):
New variables.
(extract_insn): New function.
* recog.h (extract_insn): Declare function.
(which_alternative, recog_n_operands, recog_n_dups,
recog_n_alternatives, recog_operand_mode, recog_constraints,
recog_operand_address_p): Declare variables.
* regclass.c (n_occurrences): New static function.
* reload.c (n_occurrences): Delete function.
(find_reloads): Use extract_insn.
* reload.h (n_occurrences): Delete declaration.
From-SVN: r23147
1998-10-17 03:28:57 +02:00
|
|
|
|
}
|
|
|
|
|
|
1998-12-04 13:55:59 +01:00
|
|
|
|
/* After calling extract_insn, you can use this function to extract some
|
|
|
|
|
information from the constraint strings into a more usable form.
|
|
|
|
|
The collected data is stored in recog_op_alt. */
|
|
|
|
|
void
|
|
|
|
|
preprocess_constraints ()
|
|
|
|
|
{
|
|
|
|
|
int i;
|
|
|
|
|
|
1999-09-14 20:19:09 +02:00
|
|
|
|
memset (recog_op_alt, 0, sizeof recog_op_alt);
|
1999-09-12 03:51:28 +02:00
|
|
|
|
for (i = 0; i < recog_data.n_operands; i++)
|
1998-12-04 13:55:59 +01:00
|
|
|
|
{
|
|
|
|
|
int j;
|
|
|
|
|
struct operand_alternative *op_alt;
|
1999-09-12 03:51:28 +02:00
|
|
|
|
const char *p = recog_data.constraints[i];
|
1998-12-04 13:55:59 +01:00
|
|
|
|
|
|
|
|
|
op_alt = recog_op_alt[i];
|
|
|
|
|
|
1999-09-12 03:51:28 +02:00
|
|
|
|
for (j = 0; j < recog_data.n_alternatives; j++)
|
1998-12-04 13:55:59 +01:00
|
|
|
|
{
|
|
|
|
|
op_alt[j].class = NO_REGS;
|
|
|
|
|
op_alt[j].constraint = p;
|
|
|
|
|
op_alt[j].matches = -1;
|
|
|
|
|
op_alt[j].matched = -1;
|
|
|
|
|
|
|
|
|
|
if (*p == '\0' || *p == ',')
|
|
|
|
|
{
|
|
|
|
|
op_alt[j].anything_ok = 1;
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (;;)
|
|
|
|
|
{
|
|
|
|
|
char c = *p++;
|
|
|
|
|
if (c == '#')
|
|
|
|
|
do
|
|
|
|
|
c = *p++;
|
|
|
|
|
while (c != ',' && c != '\0');
|
|
|
|
|
if (c == ',' || c == '\0')
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
switch (c)
|
|
|
|
|
{
|
|
|
|
|
case '=': case '+': case '*': case '%':
|
|
|
|
|
case 'E': case 'F': case 'G': case 'H':
|
|
|
|
|
case 's': case 'i': case 'n':
|
|
|
|
|
case 'I': case 'J': case 'K': case 'L':
|
|
|
|
|
case 'M': case 'N': case 'O': case 'P':
|
|
|
|
|
#ifdef EXTRA_CONSTRAINT
|
|
|
|
|
case 'Q': case 'R': case 'S': case 'T': case 'U':
|
|
|
|
|
#endif
|
|
|
|
|
/* These don't say anything we care about. */
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case '?':
|
|
|
|
|
op_alt[j].reject += 6;
|
|
|
|
|
break;
|
|
|
|
|
case '!':
|
|
|
|
|
op_alt[j].reject += 600;
|
|
|
|
|
break;
|
|
|
|
|
case '&':
|
|
|
|
|
op_alt[j].earlyclobber = 1;
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case '0': case '1': case '2': case '3': case '4':
|
|
|
|
|
case '5': case '6': case '7': case '8': case '9':
|
|
|
|
|
op_alt[j].matches = c - '0';
|
2000-03-09 17:07:33 +01:00
|
|
|
|
recog_op_alt[op_alt[j].matches][j].matched = i;
|
1998-12-04 13:55:59 +01:00
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case 'm':
|
|
|
|
|
op_alt[j].memory_ok = 1;
|
|
|
|
|
break;
|
|
|
|
|
case '<':
|
|
|
|
|
op_alt[j].decmem_ok = 1;
|
|
|
|
|
break;
|
|
|
|
|
case '>':
|
|
|
|
|
op_alt[j].incmem_ok = 1;
|
|
|
|
|
break;
|
|
|
|
|
case 'V':
|
|
|
|
|
op_alt[j].nonoffmem_ok = 1;
|
|
|
|
|
break;
|
|
|
|
|
case 'o':
|
|
|
|
|
op_alt[j].offmem_ok = 1;
|
|
|
|
|
break;
|
|
|
|
|
case 'X':
|
|
|
|
|
op_alt[j].anything_ok = 1;
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case 'p':
|
|
|
|
|
op_alt[j].class = reg_class_subunion[(int) op_alt[j].class][(int) BASE_REG_CLASS];
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case 'g': case 'r':
|
|
|
|
|
op_alt[j].class = reg_class_subunion[(int) op_alt[j].class][(int) GENERAL_REGS];
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
default:
|
1998-12-23 08:09:01 +01:00
|
|
|
|
op_alt[j].class = reg_class_subunion[(int) op_alt[j].class][(int) REG_CLASS_FROM_LETTER ((unsigned char)c)];
|
1998-12-04 13:55:59 +01:00
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
1998-11-04 22:25:00 +01:00
|
|
|
|
/* Check the operands of an insn against the insn's operand constraints
|
1991-11-27 15:45:36 +01:00
|
|
|
|
and return 1 if they are valid.
|
1998-11-04 22:25:00 +01:00
|
|
|
|
The information about the insn's operands, constraints, operand modes
|
|
|
|
|
etc. is obtained from the global variables set up by extract_insn.
|
1991-11-27 15:45:36 +01:00
|
|
|
|
|
|
|
|
|
WHICH_ALTERNATIVE is set to a number which indicates which
|
|
|
|
|
alternative of constraints was matched: 0 for the first alternative,
|
|
|
|
|
1 for the next, etc.
|
|
|
|
|
|
|
|
|
|
In addition, when two operands are match
|
|
|
|
|
and it happens that the output operand is (reg) while the
|
|
|
|
|
input operand is --(reg) or ++(reg) (a pre-inc or pre-dec),
|
|
|
|
|
make the output operand look like the input.
|
|
|
|
|
This is because the output operand is the one the template will print.
|
|
|
|
|
|
|
|
|
|
This is used in final, just before printing the assembler code and by
|
|
|
|
|
the routines that determine an insn's attribute.
|
|
|
|
|
|
|
|
|
|
If STRICT is a positive non-zero value, it means that we have been
|
|
|
|
|
called after reload has been completed. In that case, we must
|
|
|
|
|
do all checks strictly. If it is zero, it means that we have been called
|
|
|
|
|
before reload has completed. In that case, we first try to see if we can
|
|
|
|
|
find an alternative that matches strictly. If not, we try again, this
|
|
|
|
|
time assuming that reload will fix up the insn. This provides a "best
|
|
|
|
|
guess" for the alternative and is used to compute attributes of insns prior
|
|
|
|
|
to reload. A negative value of STRICT is used for this internal call. */
|
|
|
|
|
|
|
|
|
|
struct funny_match
|
|
|
|
|
{
|
|
|
|
|
int this, other;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
int
|
1998-11-04 22:25:00 +01:00
|
|
|
|
constrain_operands (strict)
|
1991-11-27 15:45:36 +01:00
|
|
|
|
int strict;
|
|
|
|
|
{
|
final.c (bb_str): Qualify a char* with the keyword `const'.
* final.c (bb_str): Qualify a char* with the keyword `const'.
(add_bb_string, final_scan_insn, output_asm_insn): Likewise.
* fix-header.c (read_scan_file): Likewise.
* genoutput.c (output_epilogue, process_template): Likewise.
* local-alloc.c (requires_inout, block_alloc): Likewise.
* output.h (output_asm_insn, assemble_string): Likewise.
* recog.c (recog_constraints, check_asm_operands,
decode_asm_operands, extract_insn, preprocess_constraints,
constrain_operands): Likewise.
* recog.h (operand_alternative, recog_constraints, insn_template,
insn_outfun, insn_operand_constraint, insn_name): Likewise.
* regclass.c (record_reg_classes, scan_one_insn): Likewise.
* regmove.c (find_matches): Likewise.
* reload.c (alternative_allows_memconst): Likewise.
* reload1.c (constraint_accepts_reg_p,
reload_cse_simplify_operands): Likewise.
* rtl.h (decode_asm_operands): Likewise.
* scan.h (fn_decl): Likewise.
* varasm.c (assemble_string): Likewise.
From-SVN: r24834
1999-01-23 20:45:50 +01:00
|
|
|
|
const char *constraints[MAX_RECOG_OPERANDS];
|
1992-04-18 00:42:49 +02:00
|
|
|
|
int matching_operands[MAX_RECOG_OPERANDS];
|
|
|
|
|
int earlyclobber[MAX_RECOG_OPERANDS];
|
1991-11-27 15:45:36 +01:00
|
|
|
|
register int c;
|
|
|
|
|
|
|
|
|
|
struct funny_match funny_match[MAX_RECOG_OPERANDS];
|
|
|
|
|
int funny_match_index;
|
|
|
|
|
|
1999-09-12 03:51:28 +02:00
|
|
|
|
if (recog_data.n_operands == 0 || recog_data.n_alternatives == 0)
|
1991-11-27 15:45:36 +01:00
|
|
|
|
return 1;
|
|
|
|
|
|
1999-09-12 03:51:28 +02:00
|
|
|
|
for (c = 0; c < recog_data.n_operands; c++)
|
1992-04-18 00:42:49 +02:00
|
|
|
|
{
|
1999-09-12 03:51:28 +02:00
|
|
|
|
constraints[c] = recog_data.constraints[c];
|
1992-04-18 00:42:49 +02:00
|
|
|
|
matching_operands[c] = -1;
|
|
|
|
|
}
|
1991-11-27 15:45:36 +01:00
|
|
|
|
|
|
|
|
|
which_alternative = 0;
|
|
|
|
|
|
1999-09-12 03:51:28 +02:00
|
|
|
|
while (which_alternative < recog_data.n_alternatives)
|
1991-11-27 15:45:36 +01:00
|
|
|
|
{
|
|
|
|
|
register int opno;
|
|
|
|
|
int lose = 0;
|
|
|
|
|
funny_match_index = 0;
|
|
|
|
|
|
1999-09-12 03:51:28 +02:00
|
|
|
|
for (opno = 0; opno < recog_data.n_operands; opno++)
|
1991-11-27 15:45:36 +01:00
|
|
|
|
{
|
1999-09-12 03:51:28 +02:00
|
|
|
|
register rtx op = recog_data.operand[opno];
|
1991-11-27 15:45:36 +01:00
|
|
|
|
enum machine_mode mode = GET_MODE (op);
|
final.c (bb_str): Qualify a char* with the keyword `const'.
* final.c (bb_str): Qualify a char* with the keyword `const'.
(add_bb_string, final_scan_insn, output_asm_insn): Likewise.
* fix-header.c (read_scan_file): Likewise.
* genoutput.c (output_epilogue, process_template): Likewise.
* local-alloc.c (requires_inout, block_alloc): Likewise.
* output.h (output_asm_insn, assemble_string): Likewise.
* recog.c (recog_constraints, check_asm_operands,
decode_asm_operands, extract_insn, preprocess_constraints,
constrain_operands): Likewise.
* recog.h (operand_alternative, recog_constraints, insn_template,
insn_outfun, insn_operand_constraint, insn_name): Likewise.
* regclass.c (record_reg_classes, scan_one_insn): Likewise.
* regmove.c (find_matches): Likewise.
* reload.c (alternative_allows_memconst): Likewise.
* reload1.c (constraint_accepts_reg_p,
reload_cse_simplify_operands): Likewise.
* rtl.h (decode_asm_operands): Likewise.
* scan.h (fn_decl): Likewise.
* varasm.c (assemble_string): Likewise.
From-SVN: r24834
1999-01-23 20:45:50 +01:00
|
|
|
|
register const char *p = constraints[opno];
|
1991-11-27 15:45:36 +01:00
|
|
|
|
int offset = 0;
|
|
|
|
|
int win = 0;
|
|
|
|
|
int val;
|
|
|
|
|
|
1992-04-18 00:42:49 +02:00
|
|
|
|
earlyclobber[opno] = 0;
|
|
|
|
|
|
1996-10-24 00:02:32 +02:00
|
|
|
|
/* A unary operator may be accepted by the predicate, but it
|
alias.c: Change all uses of gen_rtx(FOO...) to gen_rtx_FOO...
* alias.c: Change all uses of gen_rtx(FOO...) to gen_rtx_FOO;
change gen_rtx(expr...) to gen_rtx_fmt_foo(expr...).
* caller-save.c, calls.c, combine.c, cse.c: Likewise.
* dwarf2out.c, except.c, explow.c, expmed.c, expr.c: Likewise.
* final.c, flow.c, function.c, genpeep.c, haifa-sched.c: Likewise.
* halfpic.c, integrate.c, jump.c, local-alloc.c, loop.c: Likewise.
* profile.c, recog.c, reg-stack.c, regclass.c, regmove.c: Likewise.
* reload.c, reload1.c, reorg.c, sched.c, stmt.c, stupid.c: Likewise.
* unroll.c, varasm.c: Likewise.
* config/alpha/alpha.c, config/alpha/alpha.md: Likewise.
From-SVN: r17357
1998-01-15 00:10:50 +01:00
|
|
|
|
is irrelevant for matching constraints. */
|
1996-10-24 00:02:32 +02:00
|
|
|
|
if (GET_RTX_CLASS (GET_CODE (op)) == '1')
|
|
|
|
|
op = XEXP (op, 0);
|
|
|
|
|
|
1991-11-27 15:45:36 +01:00
|
|
|
|
if (GET_CODE (op) == SUBREG)
|
|
|
|
|
{
|
|
|
|
|
if (GET_CODE (SUBREG_REG (op)) == REG
|
|
|
|
|
&& REGNO (SUBREG_REG (op)) < FIRST_PSEUDO_REGISTER)
|
|
|
|
|
offset = SUBREG_WORD (op);
|
|
|
|
|
op = SUBREG_REG (op);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* An empty constraint or empty alternative
|
|
|
|
|
allows anything which matched the pattern. */
|
|
|
|
|
if (*p == 0 || *p == ',')
|
|
|
|
|
win = 1;
|
|
|
|
|
|
|
|
|
|
while (*p && (c = *p++) != ',')
|
|
|
|
|
switch (c)
|
|
|
|
|
{
|
1999-09-07 07:49:18 +02:00
|
|
|
|
case '?': case '!': case '*': case '%':
|
|
|
|
|
case '=': case '+':
|
1991-11-27 15:45:36 +01:00
|
|
|
|
break;
|
|
|
|
|
|
1994-03-06 21:17:55 +01:00
|
|
|
|
case '#':
|
|
|
|
|
/* Ignore rest of this alternative as far as
|
|
|
|
|
constraint checking is concerned. */
|
|
|
|
|
while (*p && *p != ',')
|
|
|
|
|
p++;
|
|
|
|
|
break;
|
|
|
|
|
|
1992-04-18 00:42:49 +02:00
|
|
|
|
case '&':
|
|
|
|
|
earlyclobber[opno] = 1;
|
|
|
|
|
break;
|
|
|
|
|
|
1999-09-07 07:49:18 +02:00
|
|
|
|
case '0': case '1': case '2': case '3': case '4':
|
|
|
|
|
case '5': case '6': case '7': case '8': case '9':
|
|
|
|
|
|
1991-11-27 15:45:36 +01:00
|
|
|
|
/* This operand must be the same as a previous one.
|
|
|
|
|
This kind of constraint is used for instructions such
|
|
|
|
|
as add when they take only two operands.
|
|
|
|
|
|
|
|
|
|
Note that the lower-numbered operand is passed first.
|
|
|
|
|
|
|
|
|
|
If we are not testing strictly, assume that this constraint
|
|
|
|
|
will be satisfied. */
|
|
|
|
|
if (strict < 0)
|
|
|
|
|
val = 1;
|
|
|
|
|
else
|
1999-04-11 00:16:29 +02:00
|
|
|
|
{
|
1999-09-12 03:51:28 +02:00
|
|
|
|
rtx op1 = recog_data.operand[c - '0'];
|
|
|
|
|
rtx op2 = recog_data.operand[opno];
|
1999-04-11 00:16:29 +02:00
|
|
|
|
|
|
|
|
|
/* A unary operator may be accepted by the predicate,
|
|
|
|
|
but it is irrelevant for matching constraints. */
|
|
|
|
|
if (GET_RTX_CLASS (GET_CODE (op1)) == '1')
|
|
|
|
|
op1 = XEXP (op1, 0);
|
|
|
|
|
if (GET_RTX_CLASS (GET_CODE (op2)) == '1')
|
|
|
|
|
op2 = XEXP (op2, 0);
|
|
|
|
|
|
|
|
|
|
val = operands_match_p (op1, op2);
|
|
|
|
|
}
|
1991-11-27 15:45:36 +01:00
|
|
|
|
|
1992-04-18 00:42:49 +02:00
|
|
|
|
matching_operands[opno] = c - '0';
|
|
|
|
|
matching_operands[c - '0'] = opno;
|
|
|
|
|
|
1991-11-27 15:45:36 +01:00
|
|
|
|
if (val != 0)
|
|
|
|
|
win = 1;
|
|
|
|
|
/* If output is *x and input is *--x,
|
|
|
|
|
arrange later to change the output to *--x as well,
|
|
|
|
|
since the output op is the one that will be printed. */
|
|
|
|
|
if (val == 2 && strict > 0)
|
|
|
|
|
{
|
|
|
|
|
funny_match[funny_match_index].this = opno;
|
|
|
|
|
funny_match[funny_match_index++].other = c - '0';
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case 'p':
|
|
|
|
|
/* p is used for address_operands. When we are called by
|
1994-10-17 16:30:22 +01:00
|
|
|
|
gen_reload, no one will have checked that the address is
|
|
|
|
|
strictly valid, i.e., that all pseudos requiring hard regs
|
|
|
|
|
have gotten them. */
|
1991-11-27 15:45:36 +01:00
|
|
|
|
if (strict <= 0
|
1999-09-12 03:51:28 +02:00
|
|
|
|
|| (strict_memory_address_p (recog_data.operand_mode[opno],
|
1998-11-04 22:25:00 +01:00
|
|
|
|
op)))
|
1991-11-27 15:45:36 +01:00
|
|
|
|
win = 1;
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
/* No need to check general_operand again;
|
|
|
|
|
it was done in insn-recog.c. */
|
|
|
|
|
case 'g':
|
|
|
|
|
/* Anything goes unless it is a REG and really has a hard reg
|
|
|
|
|
but the hard reg is not in the class GENERAL_REGS. */
|
|
|
|
|
if (strict < 0
|
|
|
|
|
|| GENERAL_REGS == ALL_REGS
|
|
|
|
|
|| GET_CODE (op) != REG
|
1992-05-27 12:21:59 +02:00
|
|
|
|
|| (reload_in_progress
|
|
|
|
|
&& REGNO (op) >= FIRST_PSEUDO_REGISTER)
|
1991-11-27 15:45:36 +01:00
|
|
|
|
|| reg_fits_class_p (op, GENERAL_REGS, offset, mode))
|
|
|
|
|
win = 1;
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case 'r':
|
|
|
|
|
if (strict < 0
|
|
|
|
|
|| (strict == 0
|
|
|
|
|
&& GET_CODE (op) == REG
|
|
|
|
|
&& REGNO (op) >= FIRST_PSEUDO_REGISTER)
|
|
|
|
|
|| (strict == 0 && GET_CODE (op) == SCRATCH)
|
|
|
|
|
|| (GET_CODE (op) == REG
|
1993-02-26 21:12:16 +01:00
|
|
|
|
&& ((GENERAL_REGS == ALL_REGS
|
|
|
|
|
&& REGNO (op) < FIRST_PSEUDO_REGISTER)
|
1991-11-27 15:45:36 +01:00
|
|
|
|
|| reg_fits_class_p (op, GENERAL_REGS,
|
|
|
|
|
offset, mode))))
|
|
|
|
|
win = 1;
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case 'X':
|
1996-07-04 00:07:53 +02:00
|
|
|
|
/* This is used for a MATCH_SCRATCH in the cases when
|
|
|
|
|
we don't actually need anything. So anything goes
|
|
|
|
|
any time. */
|
1991-11-27 15:45:36 +01:00
|
|
|
|
win = 1;
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case 'm':
|
|
|
|
|
if (GET_CODE (op) == MEM
|
|
|
|
|
/* Before reload, accept what reload can turn into mem. */
|
1992-05-27 12:21:59 +02:00
|
|
|
|
|| (strict < 0 && CONSTANT_P (op))
|
|
|
|
|
/* During reload, accept a pseudo */
|
|
|
|
|
|| (reload_in_progress && GET_CODE (op) == REG
|
|
|
|
|
&& REGNO (op) >= FIRST_PSEUDO_REGISTER))
|
1991-11-27 15:45:36 +01:00
|
|
|
|
win = 1;
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case '<':
|
|
|
|
|
if (GET_CODE (op) == MEM
|
|
|
|
|
&& (GET_CODE (XEXP (op, 0)) == PRE_DEC
|
|
|
|
|
|| GET_CODE (XEXP (op, 0)) == POST_DEC))
|
|
|
|
|
win = 1;
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case '>':
|
|
|
|
|
if (GET_CODE (op) == MEM
|
|
|
|
|
&& (GET_CODE (XEXP (op, 0)) == PRE_INC
|
|
|
|
|
|| GET_CODE (XEXP (op, 0)) == POST_INC))
|
|
|
|
|
win = 1;
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case 'E':
|
1995-04-10 23:39:56 +02:00
|
|
|
|
#ifndef REAL_ARITHMETIC
|
1991-11-27 15:45:36 +01:00
|
|
|
|
/* Match any CONST_DOUBLE, but only if
|
|
|
|
|
we can examine the bits of it reliably. */
|
|
|
|
|
if ((HOST_FLOAT_FORMAT != TARGET_FLOAT_FORMAT
|
1992-07-07 00:16:17 +02:00
|
|
|
|
|| HOST_BITS_PER_WIDE_INT != BITS_PER_WORD)
|
1992-03-11 03:37:38 +01:00
|
|
|
|
&& GET_MODE (op) != VOIDmode && ! flag_pretend_float)
|
1991-11-27 15:45:36 +01:00
|
|
|
|
break;
|
1995-04-10 23:39:56 +02:00
|
|
|
|
#endif
|
1991-11-27 15:45:36 +01:00
|
|
|
|
if (GET_CODE (op) == CONST_DOUBLE)
|
|
|
|
|
win = 1;
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case 'F':
|
|
|
|
|
if (GET_CODE (op) == CONST_DOUBLE)
|
|
|
|
|
win = 1;
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case 'G':
|
|
|
|
|
case 'H':
|
|
|
|
|
if (GET_CODE (op) == CONST_DOUBLE
|
|
|
|
|
&& CONST_DOUBLE_OK_FOR_LETTER_P (op, c))
|
|
|
|
|
win = 1;
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case 's':
|
|
|
|
|
if (GET_CODE (op) == CONST_INT
|
|
|
|
|
|| (GET_CODE (op) == CONST_DOUBLE
|
|
|
|
|
&& GET_MODE (op) == VOIDmode))
|
|
|
|
|
break;
|
|
|
|
|
case 'i':
|
|
|
|
|
if (CONSTANT_P (op))
|
|
|
|
|
win = 1;
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case 'n':
|
|
|
|
|
if (GET_CODE (op) == CONST_INT
|
|
|
|
|
|| (GET_CODE (op) == CONST_DOUBLE
|
|
|
|
|
&& GET_MODE (op) == VOIDmode))
|
|
|
|
|
win = 1;
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case 'I':
|
|
|
|
|
case 'J':
|
|
|
|
|
case 'K':
|
|
|
|
|
case 'L':
|
|
|
|
|
case 'M':
|
|
|
|
|
case 'N':
|
|
|
|
|
case 'O':
|
|
|
|
|
case 'P':
|
|
|
|
|
if (GET_CODE (op) == CONST_INT
|
|
|
|
|
&& CONST_OK_FOR_LETTER_P (INTVAL (op), c))
|
|
|
|
|
win = 1;
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
#ifdef EXTRA_CONSTRAINT
|
|
|
|
|
case 'Q':
|
|
|
|
|
case 'R':
|
|
|
|
|
case 'S':
|
|
|
|
|
case 'T':
|
|
|
|
|
case 'U':
|
|
|
|
|
if (EXTRA_CONSTRAINT (op, c))
|
|
|
|
|
win = 1;
|
|
|
|
|
break;
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
case 'V':
|
|
|
|
|
if (GET_CODE (op) == MEM
|
1996-03-12 01:08:58 +01:00
|
|
|
|
&& ((strict > 0 && ! offsettable_memref_p (op))
|
|
|
|
|
|| (strict < 0
|
|
|
|
|
&& !(CONSTANT_P (op) || GET_CODE (op) == MEM))
|
|
|
|
|
|| (reload_in_progress
|
|
|
|
|
&& !(GET_CODE (op) == REG
|
|
|
|
|
&& REGNO (op) >= FIRST_PSEUDO_REGISTER))))
|
1991-11-27 15:45:36 +01:00
|
|
|
|
win = 1;
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case 'o':
|
|
|
|
|
if ((strict > 0 && offsettable_memref_p (op))
|
|
|
|
|
|| (strict == 0 && offsettable_nonstrict_memref_p (op))
|
|
|
|
|
/* Before reload, accept what reload can handle. */
|
|
|
|
|
|| (strict < 0
|
1992-05-27 12:21:59 +02:00
|
|
|
|
&& (CONSTANT_P (op) || GET_CODE (op) == MEM))
|
|
|
|
|
/* During reload, accept a pseudo */
|
|
|
|
|
|| (reload_in_progress && GET_CODE (op) == REG
|
|
|
|
|
&& REGNO (op) >= FIRST_PSEUDO_REGISTER))
|
1991-11-27 15:45:36 +01:00
|
|
|
|
win = 1;
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
default:
|
|
|
|
|
if (strict < 0
|
|
|
|
|
|| (strict == 0
|
|
|
|
|
&& GET_CODE (op) == REG
|
|
|
|
|
&& REGNO (op) >= FIRST_PSEUDO_REGISTER)
|
|
|
|
|
|| (strict == 0 && GET_CODE (op) == SCRATCH)
|
|
|
|
|
|| (GET_CODE (op) == REG
|
|
|
|
|
&& reg_fits_class_p (op, REG_CLASS_FROM_LETTER (c),
|
|
|
|
|
offset, mode)))
|
|
|
|
|
win = 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
constraints[opno] = p;
|
|
|
|
|
/* If this operand did not win somehow,
|
|
|
|
|
this alternative loses. */
|
|
|
|
|
if (! win)
|
|
|
|
|
lose = 1;
|
|
|
|
|
}
|
|
|
|
|
/* This alternative won; the operands are ok.
|
|
|
|
|
Change whichever operands this alternative says to change. */
|
|
|
|
|
if (! lose)
|
|
|
|
|
{
|
1992-04-18 00:42:49 +02:00
|
|
|
|
int opno, eopno;
|
|
|
|
|
|
|
|
|
|
/* See if any earlyclobber operand conflicts with some other
|
|
|
|
|
operand. */
|
|
|
|
|
|
|
|
|
|
if (strict > 0)
|
1999-09-12 03:51:28 +02:00
|
|
|
|
for (eopno = 0; eopno < recog_data.n_operands; eopno++)
|
1992-04-19 22:00:41 +02:00
|
|
|
|
/* Ignore earlyclobber operands now in memory,
|
|
|
|
|
because we would often report failure when we have
|
|
|
|
|
two memory operands, one of which was formerly a REG. */
|
|
|
|
|
if (earlyclobber[eopno]
|
1999-09-12 03:51:28 +02:00
|
|
|
|
&& GET_CODE (recog_data.operand[eopno]) == REG)
|
|
|
|
|
for (opno = 0; opno < recog_data.n_operands; opno++)
|
|
|
|
|
if ((GET_CODE (recog_data.operand[opno]) == MEM
|
|
|
|
|
|| recog_data.operand_type[opno] != OP_OUT)
|
1992-04-18 00:42:49 +02:00
|
|
|
|
&& opno != eopno
|
1996-07-04 00:07:53 +02:00
|
|
|
|
/* Ignore things like match_operator operands. */
|
1999-09-12 03:51:28 +02:00
|
|
|
|
&& *recog_data.constraints[opno] != 0
|
1992-04-18 00:42:49 +02:00
|
|
|
|
&& ! (matching_operands[opno] == eopno
|
1999-09-12 03:51:28 +02:00
|
|
|
|
&& operands_match_p (recog_data.operand[opno],
|
|
|
|
|
recog_data.operand[eopno]))
|
|
|
|
|
&& ! safe_from_earlyclobber (recog_data.operand[opno],
|
|
|
|
|
recog_data.operand[eopno]))
|
1992-04-18 00:42:49 +02:00
|
|
|
|
lose = 1;
|
|
|
|
|
|
|
|
|
|
if (! lose)
|
1991-11-27 15:45:36 +01:00
|
|
|
|
{
|
1992-04-18 00:42:49 +02:00
|
|
|
|
while (--funny_match_index >= 0)
|
|
|
|
|
{
|
1999-09-12 03:51:28 +02:00
|
|
|
|
recog_data.operand[funny_match[funny_match_index].other]
|
|
|
|
|
= recog_data.operand[funny_match[funny_match_index].this];
|
1992-04-18 00:42:49 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return 1;
|
1991-11-27 15:45:36 +01:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
which_alternative++;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* If we are about to reject this, but we are not to test strictly,
|
|
|
|
|
try a very loose test. Only return failure if it fails also. */
|
|
|
|
|
if (strict == 0)
|
1998-11-04 22:25:00 +01:00
|
|
|
|
return constrain_operands (-1);
|
1991-11-27 15:45:36 +01:00
|
|
|
|
else
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Return 1 iff OPERAND (assumed to be a REG rtx)
|
alias.c: Change all uses of gen_rtx(FOO...) to gen_rtx_FOO...
* alias.c: Change all uses of gen_rtx(FOO...) to gen_rtx_FOO;
change gen_rtx(expr...) to gen_rtx_fmt_foo(expr...).
* caller-save.c, calls.c, combine.c, cse.c: Likewise.
* dwarf2out.c, except.c, explow.c, expmed.c, expr.c: Likewise.
* final.c, flow.c, function.c, genpeep.c, haifa-sched.c: Likewise.
* halfpic.c, integrate.c, jump.c, local-alloc.c, loop.c: Likewise.
* profile.c, recog.c, reg-stack.c, regclass.c, regmove.c: Likewise.
* reload.c, reload1.c, reorg.c, sched.c, stmt.c, stupid.c: Likewise.
* unroll.c, varasm.c: Likewise.
* config/alpha/alpha.c, config/alpha/alpha.md: Likewise.
From-SVN: r17357
1998-01-15 00:10:50 +01:00
|
|
|
|
is a hard reg in class CLASS when its regno is offset by OFFSET
|
1991-11-27 15:45:36 +01:00
|
|
|
|
and changed to mode MODE.
|
|
|
|
|
If REG occupies multiple hard regs, all of them must be in CLASS. */
|
|
|
|
|
|
|
|
|
|
int
|
|
|
|
|
reg_fits_class_p (operand, class, offset, mode)
|
|
|
|
|
rtx operand;
|
|
|
|
|
register enum reg_class class;
|
|
|
|
|
int offset;
|
|
|
|
|
enum machine_mode mode;
|
|
|
|
|
{
|
|
|
|
|
register int regno = REGNO (operand);
|
|
|
|
|
if (regno < FIRST_PSEUDO_REGISTER
|
|
|
|
|
&& TEST_HARD_REG_BIT (reg_class_contents[(int) class],
|
|
|
|
|
regno + offset))
|
|
|
|
|
{
|
|
|
|
|
register int sr;
|
|
|
|
|
regno += offset;
|
|
|
|
|
for (sr = HARD_REGNO_NREGS (regno, mode) - 1;
|
|
|
|
|
sr > 0; sr--)
|
|
|
|
|
if (! TEST_HARD_REG_BIT (reg_class_contents[(int) class],
|
|
|
|
|
regno + sr))
|
|
|
|
|
break;
|
|
|
|
|
return sr == 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
1999-02-02 22:22:52 +01:00
|
|
|
|
|
Makefile.in (flow.o): Depend on TREE_H.
* Makefile.in (flow.o): Depend on TREE_H.
* basic-block.h (REG_SET_EQUAL_P): New.
(XOR_REG_SET): New.
(n_edges): Declare.
(free_regset_vector): Remove declaration.
(flow_delete_insn_chain): Declare.
(enum update_life_extent): New.
(update_life_info, count_or_remove_death_notes): Declare.
* combine.c (distribute_notes) [REG_DEAD]: Stop search at bb->head.
Verify register live at bb->global_live_at_start before adding USE.
* flow.c (HAVE_epilogue, HAVE_prologue): Provide default.
(CLEAN_ALLOCA): New.
(n_edges): New.
(PROP_*): New flags.
(find_basic_blocks_1): Use alloc_EXPR_LIST.
(clear_edges): Zero n_edges.
(make_edge): Increment n_edges.
(split_edge): Don't allocate bb->local_set. Increment n_edges.
(flow_delete_insn_chain): Export.
(delete_block): Decrement n_edges.
(merge_blocks_nomove): Likewise.
(life_analysis): Give life_analysis_1 PROP flags.
(verify_wide_reg_1, verify_wide_reg): New.
(verify_local_live_at_start): New.
(update_life_info): Rewrite to call into propogate_block.
(mark_reg): New.
(mark_regs_live_at_end): After reload, if epilogue as rtl,
always mark stack pointer. Conditionally mark PIC register.
After reload, mark call-saved registers, return regsiters.
(life_analysis_1): Accept PROP flags not remove_dead_code.
Call mark_regs_live_at_end before zeroing regs_ever_live.
Use calculate_global_regs_live. Copy global_live_at_end before
calling final propagate_block. Zero reg_next_use on exit.
(calculate_global_regs_live): New.
(allocate_bb_life_data): Don't allocate bb->local_set.
(init_regset_vector, free_regset_vector): Remove.
(propagate_block): Accept FLAGS not FINAL or REMOVE_DEAD_CODE.
Test flags before every operation. Warn if prologue/epilogue insn
would have been deleted.
(mark_set_regs, mark_set_1): Accept and use FLAGS.
Use alloc_EXPR_LIST.
(mark_used_regs): Accept and use FLAGS, not FINAL.
Remove special handling for RETURN.
(try_pre_increment): Use alloc_EXPR_LIST.
(dump_flow_info): Dump n_edges.
(unlink_insn_chain, split_hard_reg_notes): Remove.
(maybe_add_dead_note, maybe_add_dead_note_use): Remove.
(find_insn_with_note, new_insn_dead_notes): Remove.
(update_n_sets, sets_reg_or_subreg_1, sets_reg_or_subreg): Remove.
(maybe_remove_dead_notes, prepend_reg_notes): Remove.
(replace_insns): Remove.
(count_or_remove_death_notes): New.
(verify_flow_info): Abort on error after all checks.
(remove_edge): Decrement n_edges.
(remove_fake_edges): Tweek format.
* haifa-sched.c (schedule_insns): Use split_all_insns.
* output.h (update_life_info): Remove declaration.
* recog.c (split_all_insns): From the corpse of split_block_insns,
do the whole function block by block. Use update_life_info.
(recog_last_allowed_insn): New.
(recog_next_insn): Mind it.
(peephole2_optimize): Set it. Walk backwards through blocks.
Use update_life_info.
* rtl.h (update_flow_info, replace_insns): Remove declarations.
(split_all_insns): Declare.
* toplev.c (rest_of_compilation): Thread prologue before flow2.
Use split_all_insns.
* i386.md (or -1 peep2s): Disable.
From-SVN: r29877
1999-10-09 21:47:18 +02:00
|
|
|
|
/* Split all insns in the function. If UPD_LIFE, update life info after. */
|
1999-02-02 22:22:52 +01:00
|
|
|
|
|
|
|
|
|
void
|
Makefile.in (flow.o): Depend on TREE_H.
* Makefile.in (flow.o): Depend on TREE_H.
* basic-block.h (REG_SET_EQUAL_P): New.
(XOR_REG_SET): New.
(n_edges): Declare.
(free_regset_vector): Remove declaration.
(flow_delete_insn_chain): Declare.
(enum update_life_extent): New.
(update_life_info, count_or_remove_death_notes): Declare.
* combine.c (distribute_notes) [REG_DEAD]: Stop search at bb->head.
Verify register live at bb->global_live_at_start before adding USE.
* flow.c (HAVE_epilogue, HAVE_prologue): Provide default.
(CLEAN_ALLOCA): New.
(n_edges): New.
(PROP_*): New flags.
(find_basic_blocks_1): Use alloc_EXPR_LIST.
(clear_edges): Zero n_edges.
(make_edge): Increment n_edges.
(split_edge): Don't allocate bb->local_set. Increment n_edges.
(flow_delete_insn_chain): Export.
(delete_block): Decrement n_edges.
(merge_blocks_nomove): Likewise.
(life_analysis): Give life_analysis_1 PROP flags.
(verify_wide_reg_1, verify_wide_reg): New.
(verify_local_live_at_start): New.
(update_life_info): Rewrite to call into propogate_block.
(mark_reg): New.
(mark_regs_live_at_end): After reload, if epilogue as rtl,
always mark stack pointer. Conditionally mark PIC register.
After reload, mark call-saved registers, return regsiters.
(life_analysis_1): Accept PROP flags not remove_dead_code.
Call mark_regs_live_at_end before zeroing regs_ever_live.
Use calculate_global_regs_live. Copy global_live_at_end before
calling final propagate_block. Zero reg_next_use on exit.
(calculate_global_regs_live): New.
(allocate_bb_life_data): Don't allocate bb->local_set.
(init_regset_vector, free_regset_vector): Remove.
(propagate_block): Accept FLAGS not FINAL or REMOVE_DEAD_CODE.
Test flags before every operation. Warn if prologue/epilogue insn
would have been deleted.
(mark_set_regs, mark_set_1): Accept and use FLAGS.
Use alloc_EXPR_LIST.
(mark_used_regs): Accept and use FLAGS, not FINAL.
Remove special handling for RETURN.
(try_pre_increment): Use alloc_EXPR_LIST.
(dump_flow_info): Dump n_edges.
(unlink_insn_chain, split_hard_reg_notes): Remove.
(maybe_add_dead_note, maybe_add_dead_note_use): Remove.
(find_insn_with_note, new_insn_dead_notes): Remove.
(update_n_sets, sets_reg_or_subreg_1, sets_reg_or_subreg): Remove.
(maybe_remove_dead_notes, prepend_reg_notes): Remove.
(replace_insns): Remove.
(count_or_remove_death_notes): New.
(verify_flow_info): Abort on error after all checks.
(remove_edge): Decrement n_edges.
(remove_fake_edges): Tweek format.
* haifa-sched.c (schedule_insns): Use split_all_insns.
* output.h (update_life_info): Remove declaration.
* recog.c (split_all_insns): From the corpse of split_block_insns,
do the whole function block by block. Use update_life_info.
(recog_last_allowed_insn): New.
(recog_next_insn): Mind it.
(peephole2_optimize): Set it. Walk backwards through blocks.
Use update_life_info.
* rtl.h (update_flow_info, replace_insns): Remove declarations.
(split_all_insns): Declare.
* toplev.c (rest_of_compilation): Thread prologue before flow2.
Use split_all_insns.
* i386.md (or -1 peep2s): Disable.
From-SVN: r29877
1999-10-09 21:47:18 +02:00
|
|
|
|
split_all_insns (upd_life)
|
|
|
|
|
int upd_life;
|
1999-02-02 22:22:52 +01:00
|
|
|
|
{
|
Makefile.in (flow.o): Depend on TREE_H.
* Makefile.in (flow.o): Depend on TREE_H.
* basic-block.h (REG_SET_EQUAL_P): New.
(XOR_REG_SET): New.
(n_edges): Declare.
(free_regset_vector): Remove declaration.
(flow_delete_insn_chain): Declare.
(enum update_life_extent): New.
(update_life_info, count_or_remove_death_notes): Declare.
* combine.c (distribute_notes) [REG_DEAD]: Stop search at bb->head.
Verify register live at bb->global_live_at_start before adding USE.
* flow.c (HAVE_epilogue, HAVE_prologue): Provide default.
(CLEAN_ALLOCA): New.
(n_edges): New.
(PROP_*): New flags.
(find_basic_blocks_1): Use alloc_EXPR_LIST.
(clear_edges): Zero n_edges.
(make_edge): Increment n_edges.
(split_edge): Don't allocate bb->local_set. Increment n_edges.
(flow_delete_insn_chain): Export.
(delete_block): Decrement n_edges.
(merge_blocks_nomove): Likewise.
(life_analysis): Give life_analysis_1 PROP flags.
(verify_wide_reg_1, verify_wide_reg): New.
(verify_local_live_at_start): New.
(update_life_info): Rewrite to call into propogate_block.
(mark_reg): New.
(mark_regs_live_at_end): After reload, if epilogue as rtl,
always mark stack pointer. Conditionally mark PIC register.
After reload, mark call-saved registers, return regsiters.
(life_analysis_1): Accept PROP flags not remove_dead_code.
Call mark_regs_live_at_end before zeroing regs_ever_live.
Use calculate_global_regs_live. Copy global_live_at_end before
calling final propagate_block. Zero reg_next_use on exit.
(calculate_global_regs_live): New.
(allocate_bb_life_data): Don't allocate bb->local_set.
(init_regset_vector, free_regset_vector): Remove.
(propagate_block): Accept FLAGS not FINAL or REMOVE_DEAD_CODE.
Test flags before every operation. Warn if prologue/epilogue insn
would have been deleted.
(mark_set_regs, mark_set_1): Accept and use FLAGS.
Use alloc_EXPR_LIST.
(mark_used_regs): Accept and use FLAGS, not FINAL.
Remove special handling for RETURN.
(try_pre_increment): Use alloc_EXPR_LIST.
(dump_flow_info): Dump n_edges.
(unlink_insn_chain, split_hard_reg_notes): Remove.
(maybe_add_dead_note, maybe_add_dead_note_use): Remove.
(find_insn_with_note, new_insn_dead_notes): Remove.
(update_n_sets, sets_reg_or_subreg_1, sets_reg_or_subreg): Remove.
(maybe_remove_dead_notes, prepend_reg_notes): Remove.
(replace_insns): Remove.
(count_or_remove_death_notes): New.
(verify_flow_info): Abort on error after all checks.
(remove_edge): Decrement n_edges.
(remove_fake_edges): Tweek format.
* haifa-sched.c (schedule_insns): Use split_all_insns.
* output.h (update_life_info): Remove declaration.
* recog.c (split_all_insns): From the corpse of split_block_insns,
do the whole function block by block. Use update_life_info.
(recog_last_allowed_insn): New.
(recog_next_insn): Mind it.
(peephole2_optimize): Set it. Walk backwards through blocks.
Use update_life_info.
* rtl.h (update_flow_info, replace_insns): Remove declarations.
(split_all_insns): Declare.
* toplev.c (rest_of_compilation): Thread prologue before flow2.
Use split_all_insns.
* i386.md (or -1 peep2s): Disable.
From-SVN: r29877
1999-10-09 21:47:18 +02:00
|
|
|
|
sbitmap blocks;
|
|
|
|
|
int changed;
|
|
|
|
|
int i;
|
|
|
|
|
|
|
|
|
|
blocks = sbitmap_alloc (n_basic_blocks);
|
|
|
|
|
sbitmap_zero (blocks);
|
|
|
|
|
changed = 0;
|
1999-02-02 22:22:52 +01:00
|
|
|
|
|
Makefile.in (flow.o): Depend on TREE_H.
* Makefile.in (flow.o): Depend on TREE_H.
* basic-block.h (REG_SET_EQUAL_P): New.
(XOR_REG_SET): New.
(n_edges): Declare.
(free_regset_vector): Remove declaration.
(flow_delete_insn_chain): Declare.
(enum update_life_extent): New.
(update_life_info, count_or_remove_death_notes): Declare.
* combine.c (distribute_notes) [REG_DEAD]: Stop search at bb->head.
Verify register live at bb->global_live_at_start before adding USE.
* flow.c (HAVE_epilogue, HAVE_prologue): Provide default.
(CLEAN_ALLOCA): New.
(n_edges): New.
(PROP_*): New flags.
(find_basic_blocks_1): Use alloc_EXPR_LIST.
(clear_edges): Zero n_edges.
(make_edge): Increment n_edges.
(split_edge): Don't allocate bb->local_set. Increment n_edges.
(flow_delete_insn_chain): Export.
(delete_block): Decrement n_edges.
(merge_blocks_nomove): Likewise.
(life_analysis): Give life_analysis_1 PROP flags.
(verify_wide_reg_1, verify_wide_reg): New.
(verify_local_live_at_start): New.
(update_life_info): Rewrite to call into propogate_block.
(mark_reg): New.
(mark_regs_live_at_end): After reload, if epilogue as rtl,
always mark stack pointer. Conditionally mark PIC register.
After reload, mark call-saved registers, return regsiters.
(life_analysis_1): Accept PROP flags not remove_dead_code.
Call mark_regs_live_at_end before zeroing regs_ever_live.
Use calculate_global_regs_live. Copy global_live_at_end before
calling final propagate_block. Zero reg_next_use on exit.
(calculate_global_regs_live): New.
(allocate_bb_life_data): Don't allocate bb->local_set.
(init_regset_vector, free_regset_vector): Remove.
(propagate_block): Accept FLAGS not FINAL or REMOVE_DEAD_CODE.
Test flags before every operation. Warn if prologue/epilogue insn
would have been deleted.
(mark_set_regs, mark_set_1): Accept and use FLAGS.
Use alloc_EXPR_LIST.
(mark_used_regs): Accept and use FLAGS, not FINAL.
Remove special handling for RETURN.
(try_pre_increment): Use alloc_EXPR_LIST.
(dump_flow_info): Dump n_edges.
(unlink_insn_chain, split_hard_reg_notes): Remove.
(maybe_add_dead_note, maybe_add_dead_note_use): Remove.
(find_insn_with_note, new_insn_dead_notes): Remove.
(update_n_sets, sets_reg_or_subreg_1, sets_reg_or_subreg): Remove.
(maybe_remove_dead_notes, prepend_reg_notes): Remove.
(replace_insns): Remove.
(count_or_remove_death_notes): New.
(verify_flow_info): Abort on error after all checks.
(remove_edge): Decrement n_edges.
(remove_fake_edges): Tweek format.
* haifa-sched.c (schedule_insns): Use split_all_insns.
* output.h (update_life_info): Remove declaration.
* recog.c (split_all_insns): From the corpse of split_block_insns,
do the whole function block by block. Use update_life_info.
(recog_last_allowed_insn): New.
(recog_next_insn): Mind it.
(peephole2_optimize): Set it. Walk backwards through blocks.
Use update_life_info.
* rtl.h (update_flow_info, replace_insns): Remove declarations.
(split_all_insns): Declare.
* toplev.c (rest_of_compilation): Thread prologue before flow2.
Use split_all_insns.
* i386.md (or -1 peep2s): Disable.
From-SVN: r29877
1999-10-09 21:47:18 +02:00
|
|
|
|
for (i = n_basic_blocks - 1; i >= 0; --i)
|
1999-02-02 22:22:52 +01:00
|
|
|
|
{
|
Makefile.in (flow.o): Depend on TREE_H.
* Makefile.in (flow.o): Depend on TREE_H.
* basic-block.h (REG_SET_EQUAL_P): New.
(XOR_REG_SET): New.
(n_edges): Declare.
(free_regset_vector): Remove declaration.
(flow_delete_insn_chain): Declare.
(enum update_life_extent): New.
(update_life_info, count_or_remove_death_notes): Declare.
* combine.c (distribute_notes) [REG_DEAD]: Stop search at bb->head.
Verify register live at bb->global_live_at_start before adding USE.
* flow.c (HAVE_epilogue, HAVE_prologue): Provide default.
(CLEAN_ALLOCA): New.
(n_edges): New.
(PROP_*): New flags.
(find_basic_blocks_1): Use alloc_EXPR_LIST.
(clear_edges): Zero n_edges.
(make_edge): Increment n_edges.
(split_edge): Don't allocate bb->local_set. Increment n_edges.
(flow_delete_insn_chain): Export.
(delete_block): Decrement n_edges.
(merge_blocks_nomove): Likewise.
(life_analysis): Give life_analysis_1 PROP flags.
(verify_wide_reg_1, verify_wide_reg): New.
(verify_local_live_at_start): New.
(update_life_info): Rewrite to call into propogate_block.
(mark_reg): New.
(mark_regs_live_at_end): After reload, if epilogue as rtl,
always mark stack pointer. Conditionally mark PIC register.
After reload, mark call-saved registers, return regsiters.
(life_analysis_1): Accept PROP flags not remove_dead_code.
Call mark_regs_live_at_end before zeroing regs_ever_live.
Use calculate_global_regs_live. Copy global_live_at_end before
calling final propagate_block. Zero reg_next_use on exit.
(calculate_global_regs_live): New.
(allocate_bb_life_data): Don't allocate bb->local_set.
(init_regset_vector, free_regset_vector): Remove.
(propagate_block): Accept FLAGS not FINAL or REMOVE_DEAD_CODE.
Test flags before every operation. Warn if prologue/epilogue insn
would have been deleted.
(mark_set_regs, mark_set_1): Accept and use FLAGS.
Use alloc_EXPR_LIST.
(mark_used_regs): Accept and use FLAGS, not FINAL.
Remove special handling for RETURN.
(try_pre_increment): Use alloc_EXPR_LIST.
(dump_flow_info): Dump n_edges.
(unlink_insn_chain, split_hard_reg_notes): Remove.
(maybe_add_dead_note, maybe_add_dead_note_use): Remove.
(find_insn_with_note, new_insn_dead_notes): Remove.
(update_n_sets, sets_reg_or_subreg_1, sets_reg_or_subreg): Remove.
(maybe_remove_dead_notes, prepend_reg_notes): Remove.
(replace_insns): Remove.
(count_or_remove_death_notes): New.
(verify_flow_info): Abort on error after all checks.
(remove_edge): Decrement n_edges.
(remove_fake_edges): Tweek format.
* haifa-sched.c (schedule_insns): Use split_all_insns.
* output.h (update_life_info): Remove declaration.
* recog.c (split_all_insns): From the corpse of split_block_insns,
do the whole function block by block. Use update_life_info.
(recog_last_allowed_insn): New.
(recog_next_insn): Mind it.
(peephole2_optimize): Set it. Walk backwards through blocks.
Use update_life_info.
* rtl.h (update_flow_info, replace_insns): Remove declarations.
(split_all_insns): Declare.
* toplev.c (rest_of_compilation): Thread prologue before flow2.
Use split_all_insns.
* i386.md (or -1 peep2s): Disable.
From-SVN: r29877
1999-10-09 21:47:18 +02:00
|
|
|
|
basic_block bb = BASIC_BLOCK (i);
|
|
|
|
|
rtx insn, next;
|
1999-02-02 22:22:52 +01:00
|
|
|
|
|
Makefile.in (flow.o): Depend on TREE_H.
* Makefile.in (flow.o): Depend on TREE_H.
* basic-block.h (REG_SET_EQUAL_P): New.
(XOR_REG_SET): New.
(n_edges): Declare.
(free_regset_vector): Remove declaration.
(flow_delete_insn_chain): Declare.
(enum update_life_extent): New.
(update_life_info, count_or_remove_death_notes): Declare.
* combine.c (distribute_notes) [REG_DEAD]: Stop search at bb->head.
Verify register live at bb->global_live_at_start before adding USE.
* flow.c (HAVE_epilogue, HAVE_prologue): Provide default.
(CLEAN_ALLOCA): New.
(n_edges): New.
(PROP_*): New flags.
(find_basic_blocks_1): Use alloc_EXPR_LIST.
(clear_edges): Zero n_edges.
(make_edge): Increment n_edges.
(split_edge): Don't allocate bb->local_set. Increment n_edges.
(flow_delete_insn_chain): Export.
(delete_block): Decrement n_edges.
(merge_blocks_nomove): Likewise.
(life_analysis): Give life_analysis_1 PROP flags.
(verify_wide_reg_1, verify_wide_reg): New.
(verify_local_live_at_start): New.
(update_life_info): Rewrite to call into propogate_block.
(mark_reg): New.
(mark_regs_live_at_end): After reload, if epilogue as rtl,
always mark stack pointer. Conditionally mark PIC register.
After reload, mark call-saved registers, return regsiters.
(life_analysis_1): Accept PROP flags not remove_dead_code.
Call mark_regs_live_at_end before zeroing regs_ever_live.
Use calculate_global_regs_live. Copy global_live_at_end before
calling final propagate_block. Zero reg_next_use on exit.
(calculate_global_regs_live): New.
(allocate_bb_life_data): Don't allocate bb->local_set.
(init_regset_vector, free_regset_vector): Remove.
(propagate_block): Accept FLAGS not FINAL or REMOVE_DEAD_CODE.
Test flags before every operation. Warn if prologue/epilogue insn
would have been deleted.
(mark_set_regs, mark_set_1): Accept and use FLAGS.
Use alloc_EXPR_LIST.
(mark_used_regs): Accept and use FLAGS, not FINAL.
Remove special handling for RETURN.
(try_pre_increment): Use alloc_EXPR_LIST.
(dump_flow_info): Dump n_edges.
(unlink_insn_chain, split_hard_reg_notes): Remove.
(maybe_add_dead_note, maybe_add_dead_note_use): Remove.
(find_insn_with_note, new_insn_dead_notes): Remove.
(update_n_sets, sets_reg_or_subreg_1, sets_reg_or_subreg): Remove.
(maybe_remove_dead_notes, prepend_reg_notes): Remove.
(replace_insns): Remove.
(count_or_remove_death_notes): New.
(verify_flow_info): Abort on error after all checks.
(remove_edge): Decrement n_edges.
(remove_fake_edges): Tweek format.
* haifa-sched.c (schedule_insns): Use split_all_insns.
* output.h (update_life_info): Remove declaration.
* recog.c (split_all_insns): From the corpse of split_block_insns,
do the whole function block by block. Use update_life_info.
(recog_last_allowed_insn): New.
(recog_next_insn): Mind it.
(peephole2_optimize): Set it. Walk backwards through blocks.
Use update_life_info.
* rtl.h (update_flow_info, replace_insns): Remove declarations.
(split_all_insns): Declare.
* toplev.c (rest_of_compilation): Thread prologue before flow2.
Use split_all_insns.
* i386.md (or -1 peep2s): Disable.
From-SVN: r29877
1999-10-09 21:47:18 +02:00
|
|
|
|
for (insn = bb->head; insn ; insn = next)
|
1999-02-02 22:22:52 +01:00
|
|
|
|
{
|
Makefile.in (flow.o): Depend on TREE_H.
* Makefile.in (flow.o): Depend on TREE_H.
* basic-block.h (REG_SET_EQUAL_P): New.
(XOR_REG_SET): New.
(n_edges): Declare.
(free_regset_vector): Remove declaration.
(flow_delete_insn_chain): Declare.
(enum update_life_extent): New.
(update_life_info, count_or_remove_death_notes): Declare.
* combine.c (distribute_notes) [REG_DEAD]: Stop search at bb->head.
Verify register live at bb->global_live_at_start before adding USE.
* flow.c (HAVE_epilogue, HAVE_prologue): Provide default.
(CLEAN_ALLOCA): New.
(n_edges): New.
(PROP_*): New flags.
(find_basic_blocks_1): Use alloc_EXPR_LIST.
(clear_edges): Zero n_edges.
(make_edge): Increment n_edges.
(split_edge): Don't allocate bb->local_set. Increment n_edges.
(flow_delete_insn_chain): Export.
(delete_block): Decrement n_edges.
(merge_blocks_nomove): Likewise.
(life_analysis): Give life_analysis_1 PROP flags.
(verify_wide_reg_1, verify_wide_reg): New.
(verify_local_live_at_start): New.
(update_life_info): Rewrite to call into propogate_block.
(mark_reg): New.
(mark_regs_live_at_end): After reload, if epilogue as rtl,
always mark stack pointer. Conditionally mark PIC register.
After reload, mark call-saved registers, return regsiters.
(life_analysis_1): Accept PROP flags not remove_dead_code.
Call mark_regs_live_at_end before zeroing regs_ever_live.
Use calculate_global_regs_live. Copy global_live_at_end before
calling final propagate_block. Zero reg_next_use on exit.
(calculate_global_regs_live): New.
(allocate_bb_life_data): Don't allocate bb->local_set.
(init_regset_vector, free_regset_vector): Remove.
(propagate_block): Accept FLAGS not FINAL or REMOVE_DEAD_CODE.
Test flags before every operation. Warn if prologue/epilogue insn
would have been deleted.
(mark_set_regs, mark_set_1): Accept and use FLAGS.
Use alloc_EXPR_LIST.
(mark_used_regs): Accept and use FLAGS, not FINAL.
Remove special handling for RETURN.
(try_pre_increment): Use alloc_EXPR_LIST.
(dump_flow_info): Dump n_edges.
(unlink_insn_chain, split_hard_reg_notes): Remove.
(maybe_add_dead_note, maybe_add_dead_note_use): Remove.
(find_insn_with_note, new_insn_dead_notes): Remove.
(update_n_sets, sets_reg_or_subreg_1, sets_reg_or_subreg): Remove.
(maybe_remove_dead_notes, prepend_reg_notes): Remove.
(replace_insns): Remove.
(count_or_remove_death_notes): New.
(verify_flow_info): Abort on error after all checks.
(remove_edge): Decrement n_edges.
(remove_fake_edges): Tweek format.
* haifa-sched.c (schedule_insns): Use split_all_insns.
* output.h (update_life_info): Remove declaration.
* recog.c (split_all_insns): From the corpse of split_block_insns,
do the whole function block by block. Use update_life_info.
(recog_last_allowed_insn): New.
(recog_next_insn): Mind it.
(peephole2_optimize): Set it. Walk backwards through blocks.
Use update_life_info.
* rtl.h (update_flow_info, replace_insns): Remove declarations.
(split_all_insns): Declare.
* toplev.c (rest_of_compilation): Thread prologue before flow2.
Use split_all_insns.
* i386.md (or -1 peep2s): Disable.
From-SVN: r29877
1999-10-09 21:47:18 +02:00
|
|
|
|
rtx set;
|
1999-02-02 22:22:52 +01:00
|
|
|
|
|
Makefile.in (flow.o): Depend on TREE_H.
* Makefile.in (flow.o): Depend on TREE_H.
* basic-block.h (REG_SET_EQUAL_P): New.
(XOR_REG_SET): New.
(n_edges): Declare.
(free_regset_vector): Remove declaration.
(flow_delete_insn_chain): Declare.
(enum update_life_extent): New.
(update_life_info, count_or_remove_death_notes): Declare.
* combine.c (distribute_notes) [REG_DEAD]: Stop search at bb->head.
Verify register live at bb->global_live_at_start before adding USE.
* flow.c (HAVE_epilogue, HAVE_prologue): Provide default.
(CLEAN_ALLOCA): New.
(n_edges): New.
(PROP_*): New flags.
(find_basic_blocks_1): Use alloc_EXPR_LIST.
(clear_edges): Zero n_edges.
(make_edge): Increment n_edges.
(split_edge): Don't allocate bb->local_set. Increment n_edges.
(flow_delete_insn_chain): Export.
(delete_block): Decrement n_edges.
(merge_blocks_nomove): Likewise.
(life_analysis): Give life_analysis_1 PROP flags.
(verify_wide_reg_1, verify_wide_reg): New.
(verify_local_live_at_start): New.
(update_life_info): Rewrite to call into propogate_block.
(mark_reg): New.
(mark_regs_live_at_end): After reload, if epilogue as rtl,
always mark stack pointer. Conditionally mark PIC register.
After reload, mark call-saved registers, return regsiters.
(life_analysis_1): Accept PROP flags not remove_dead_code.
Call mark_regs_live_at_end before zeroing regs_ever_live.
Use calculate_global_regs_live. Copy global_live_at_end before
calling final propagate_block. Zero reg_next_use on exit.
(calculate_global_regs_live): New.
(allocate_bb_life_data): Don't allocate bb->local_set.
(init_regset_vector, free_regset_vector): Remove.
(propagate_block): Accept FLAGS not FINAL or REMOVE_DEAD_CODE.
Test flags before every operation. Warn if prologue/epilogue insn
would have been deleted.
(mark_set_regs, mark_set_1): Accept and use FLAGS.
Use alloc_EXPR_LIST.
(mark_used_regs): Accept and use FLAGS, not FINAL.
Remove special handling for RETURN.
(try_pre_increment): Use alloc_EXPR_LIST.
(dump_flow_info): Dump n_edges.
(unlink_insn_chain, split_hard_reg_notes): Remove.
(maybe_add_dead_note, maybe_add_dead_note_use): Remove.
(find_insn_with_note, new_insn_dead_notes): Remove.
(update_n_sets, sets_reg_or_subreg_1, sets_reg_or_subreg): Remove.
(maybe_remove_dead_notes, prepend_reg_notes): Remove.
(replace_insns): Remove.
(count_or_remove_death_notes): New.
(verify_flow_info): Abort on error after all checks.
(remove_edge): Decrement n_edges.
(remove_fake_edges): Tweek format.
* haifa-sched.c (schedule_insns): Use split_all_insns.
* output.h (update_life_info): Remove declaration.
* recog.c (split_all_insns): From the corpse of split_block_insns,
do the whole function block by block. Use update_life_info.
(recog_last_allowed_insn): New.
(recog_next_insn): Mind it.
(peephole2_optimize): Set it. Walk backwards through blocks.
Use update_life_info.
* rtl.h (update_flow_info, replace_insns): Remove declarations.
(split_all_insns): Declare.
* toplev.c (rest_of_compilation): Thread prologue before flow2.
Use split_all_insns.
* i386.md (or -1 peep2s): Disable.
From-SVN: r29877
1999-10-09 21:47:18 +02:00
|
|
|
|
/* Can't use `next_real_insn' because that might go across
|
|
|
|
|
CODE_LABELS and short-out basic blocks. */
|
|
|
|
|
next = NEXT_INSN (insn);
|
|
|
|
|
if (GET_CODE (insn) != INSN)
|
|
|
|
|
;
|
1999-02-02 22:22:52 +01:00
|
|
|
|
|
Makefile.in (flow.o): Depend on TREE_H.
* Makefile.in (flow.o): Depend on TREE_H.
* basic-block.h (REG_SET_EQUAL_P): New.
(XOR_REG_SET): New.
(n_edges): Declare.
(free_regset_vector): Remove declaration.
(flow_delete_insn_chain): Declare.
(enum update_life_extent): New.
(update_life_info, count_or_remove_death_notes): Declare.
* combine.c (distribute_notes) [REG_DEAD]: Stop search at bb->head.
Verify register live at bb->global_live_at_start before adding USE.
* flow.c (HAVE_epilogue, HAVE_prologue): Provide default.
(CLEAN_ALLOCA): New.
(n_edges): New.
(PROP_*): New flags.
(find_basic_blocks_1): Use alloc_EXPR_LIST.
(clear_edges): Zero n_edges.
(make_edge): Increment n_edges.
(split_edge): Don't allocate bb->local_set. Increment n_edges.
(flow_delete_insn_chain): Export.
(delete_block): Decrement n_edges.
(merge_blocks_nomove): Likewise.
(life_analysis): Give life_analysis_1 PROP flags.
(verify_wide_reg_1, verify_wide_reg): New.
(verify_local_live_at_start): New.
(update_life_info): Rewrite to call into propogate_block.
(mark_reg): New.
(mark_regs_live_at_end): After reload, if epilogue as rtl,
always mark stack pointer. Conditionally mark PIC register.
After reload, mark call-saved registers, return regsiters.
(life_analysis_1): Accept PROP flags not remove_dead_code.
Call mark_regs_live_at_end before zeroing regs_ever_live.
Use calculate_global_regs_live. Copy global_live_at_end before
calling final propagate_block. Zero reg_next_use on exit.
(calculate_global_regs_live): New.
(allocate_bb_life_data): Don't allocate bb->local_set.
(init_regset_vector, free_regset_vector): Remove.
(propagate_block): Accept FLAGS not FINAL or REMOVE_DEAD_CODE.
Test flags before every operation. Warn if prologue/epilogue insn
would have been deleted.
(mark_set_regs, mark_set_1): Accept and use FLAGS.
Use alloc_EXPR_LIST.
(mark_used_regs): Accept and use FLAGS, not FINAL.
Remove special handling for RETURN.
(try_pre_increment): Use alloc_EXPR_LIST.
(dump_flow_info): Dump n_edges.
(unlink_insn_chain, split_hard_reg_notes): Remove.
(maybe_add_dead_note, maybe_add_dead_note_use): Remove.
(find_insn_with_note, new_insn_dead_notes): Remove.
(update_n_sets, sets_reg_or_subreg_1, sets_reg_or_subreg): Remove.
(maybe_remove_dead_notes, prepend_reg_notes): Remove.
(replace_insns): Remove.
(count_or_remove_death_notes): New.
(verify_flow_info): Abort on error after all checks.
(remove_edge): Decrement n_edges.
(remove_fake_edges): Tweek format.
* haifa-sched.c (schedule_insns): Use split_all_insns.
* output.h (update_life_info): Remove declaration.
* recog.c (split_all_insns): From the corpse of split_block_insns,
do the whole function block by block. Use update_life_info.
(recog_last_allowed_insn): New.
(recog_next_insn): Mind it.
(peephole2_optimize): Set it. Walk backwards through blocks.
Use update_life_info.
* rtl.h (update_flow_info, replace_insns): Remove declarations.
(split_all_insns): Declare.
* toplev.c (rest_of_compilation): Thread prologue before flow2.
Use split_all_insns.
* i386.md (or -1 peep2s): Disable.
From-SVN: r29877
1999-10-09 21:47:18 +02:00
|
|
|
|
/* Don't split no-op move insns. These should silently
|
|
|
|
|
disappear later in final. Splitting such insns would
|
|
|
|
|
break the code that handles REG_NO_CONFLICT blocks. */
|
1999-02-02 22:22:52 +01:00
|
|
|
|
|
Makefile.in (flow.o): Depend on TREE_H.
* Makefile.in (flow.o): Depend on TREE_H.
* basic-block.h (REG_SET_EQUAL_P): New.
(XOR_REG_SET): New.
(n_edges): Declare.
(free_regset_vector): Remove declaration.
(flow_delete_insn_chain): Declare.
(enum update_life_extent): New.
(update_life_info, count_or_remove_death_notes): Declare.
* combine.c (distribute_notes) [REG_DEAD]: Stop search at bb->head.
Verify register live at bb->global_live_at_start before adding USE.
* flow.c (HAVE_epilogue, HAVE_prologue): Provide default.
(CLEAN_ALLOCA): New.
(n_edges): New.
(PROP_*): New flags.
(find_basic_blocks_1): Use alloc_EXPR_LIST.
(clear_edges): Zero n_edges.
(make_edge): Increment n_edges.
(split_edge): Don't allocate bb->local_set. Increment n_edges.
(flow_delete_insn_chain): Export.
(delete_block): Decrement n_edges.
(merge_blocks_nomove): Likewise.
(life_analysis): Give life_analysis_1 PROP flags.
(verify_wide_reg_1, verify_wide_reg): New.
(verify_local_live_at_start): New.
(update_life_info): Rewrite to call into propogate_block.
(mark_reg): New.
(mark_regs_live_at_end): After reload, if epilogue as rtl,
always mark stack pointer. Conditionally mark PIC register.
After reload, mark call-saved registers, return regsiters.
(life_analysis_1): Accept PROP flags not remove_dead_code.
Call mark_regs_live_at_end before zeroing regs_ever_live.
Use calculate_global_regs_live. Copy global_live_at_end before
calling final propagate_block. Zero reg_next_use on exit.
(calculate_global_regs_live): New.
(allocate_bb_life_data): Don't allocate bb->local_set.
(init_regset_vector, free_regset_vector): Remove.
(propagate_block): Accept FLAGS not FINAL or REMOVE_DEAD_CODE.
Test flags before every operation. Warn if prologue/epilogue insn
would have been deleted.
(mark_set_regs, mark_set_1): Accept and use FLAGS.
Use alloc_EXPR_LIST.
(mark_used_regs): Accept and use FLAGS, not FINAL.
Remove special handling for RETURN.
(try_pre_increment): Use alloc_EXPR_LIST.
(dump_flow_info): Dump n_edges.
(unlink_insn_chain, split_hard_reg_notes): Remove.
(maybe_add_dead_note, maybe_add_dead_note_use): Remove.
(find_insn_with_note, new_insn_dead_notes): Remove.
(update_n_sets, sets_reg_or_subreg_1, sets_reg_or_subreg): Remove.
(maybe_remove_dead_notes, prepend_reg_notes): Remove.
(replace_insns): Remove.
(count_or_remove_death_notes): New.
(verify_flow_info): Abort on error after all checks.
(remove_edge): Decrement n_edges.
(remove_fake_edges): Tweek format.
* haifa-sched.c (schedule_insns): Use split_all_insns.
* output.h (update_life_info): Remove declaration.
* recog.c (split_all_insns): From the corpse of split_block_insns,
do the whole function block by block. Use update_life_info.
(recog_last_allowed_insn): New.
(recog_next_insn): Mind it.
(peephole2_optimize): Set it. Walk backwards through blocks.
Use update_life_info.
* rtl.h (update_flow_info, replace_insns): Remove declarations.
(split_all_insns): Declare.
* toplev.c (rest_of_compilation): Thread prologue before flow2.
Use split_all_insns.
* i386.md (or -1 peep2s): Disable.
From-SVN: r29877
1999-10-09 21:47:18 +02:00
|
|
|
|
else if ((set = single_set (insn)) != NULL
|
|
|
|
|
&& rtx_equal_p (SET_SRC (set), SET_DEST (set)))
|
1999-02-02 22:22:52 +01:00
|
|
|
|
{
|
Makefile.in (flow.o): Depend on TREE_H.
* Makefile.in (flow.o): Depend on TREE_H.
* basic-block.h (REG_SET_EQUAL_P): New.
(XOR_REG_SET): New.
(n_edges): Declare.
(free_regset_vector): Remove declaration.
(flow_delete_insn_chain): Declare.
(enum update_life_extent): New.
(update_life_info, count_or_remove_death_notes): Declare.
* combine.c (distribute_notes) [REG_DEAD]: Stop search at bb->head.
Verify register live at bb->global_live_at_start before adding USE.
* flow.c (HAVE_epilogue, HAVE_prologue): Provide default.
(CLEAN_ALLOCA): New.
(n_edges): New.
(PROP_*): New flags.
(find_basic_blocks_1): Use alloc_EXPR_LIST.
(clear_edges): Zero n_edges.
(make_edge): Increment n_edges.
(split_edge): Don't allocate bb->local_set. Increment n_edges.
(flow_delete_insn_chain): Export.
(delete_block): Decrement n_edges.
(merge_blocks_nomove): Likewise.
(life_analysis): Give life_analysis_1 PROP flags.
(verify_wide_reg_1, verify_wide_reg): New.
(verify_local_live_at_start): New.
(update_life_info): Rewrite to call into propogate_block.
(mark_reg): New.
(mark_regs_live_at_end): After reload, if epilogue as rtl,
always mark stack pointer. Conditionally mark PIC register.
After reload, mark call-saved registers, return regsiters.
(life_analysis_1): Accept PROP flags not remove_dead_code.
Call mark_regs_live_at_end before zeroing regs_ever_live.
Use calculate_global_regs_live. Copy global_live_at_end before
calling final propagate_block. Zero reg_next_use on exit.
(calculate_global_regs_live): New.
(allocate_bb_life_data): Don't allocate bb->local_set.
(init_regset_vector, free_regset_vector): Remove.
(propagate_block): Accept FLAGS not FINAL or REMOVE_DEAD_CODE.
Test flags before every operation. Warn if prologue/epilogue insn
would have been deleted.
(mark_set_regs, mark_set_1): Accept and use FLAGS.
Use alloc_EXPR_LIST.
(mark_used_regs): Accept and use FLAGS, not FINAL.
Remove special handling for RETURN.
(try_pre_increment): Use alloc_EXPR_LIST.
(dump_flow_info): Dump n_edges.
(unlink_insn_chain, split_hard_reg_notes): Remove.
(maybe_add_dead_note, maybe_add_dead_note_use): Remove.
(find_insn_with_note, new_insn_dead_notes): Remove.
(update_n_sets, sets_reg_or_subreg_1, sets_reg_or_subreg): Remove.
(maybe_remove_dead_notes, prepend_reg_notes): Remove.
(replace_insns): Remove.
(count_or_remove_death_notes): New.
(verify_flow_info): Abort on error after all checks.
(remove_edge): Decrement n_edges.
(remove_fake_edges): Tweek format.
* haifa-sched.c (schedule_insns): Use split_all_insns.
* output.h (update_life_info): Remove declaration.
* recog.c (split_all_insns): From the corpse of split_block_insns,
do the whole function block by block. Use update_life_info.
(recog_last_allowed_insn): New.
(recog_next_insn): Mind it.
(peephole2_optimize): Set it. Walk backwards through blocks.
Use update_life_info.
* rtl.h (update_flow_info, replace_insns): Remove declarations.
(split_all_insns): Declare.
* toplev.c (rest_of_compilation): Thread prologue before flow2.
Use split_all_insns.
* i386.md (or -1 peep2s): Disable.
From-SVN: r29877
1999-10-09 21:47:18 +02:00
|
|
|
|
/* Nops get in the way while scheduling, so delete them
|
|
|
|
|
now if register allocation has already been done. It
|
|
|
|
|
is too risky to try to do this before register
|
|
|
|
|
allocation, and there are unlikely to be very many
|
|
|
|
|
nops then anyways. */
|
|
|
|
|
if (reload_completed)
|
|
|
|
|
{
|
|
|
|
|
PUT_CODE (insn, NOTE);
|
|
|
|
|
NOTE_LINE_NUMBER (insn) = NOTE_INSN_DELETED;
|
|
|
|
|
NOTE_SOURCE_FILE (insn) = 0;
|
|
|
|
|
}
|
1999-02-02 22:22:52 +01:00
|
|
|
|
}
|
Makefile.in (flow.o): Depend on TREE_H.
* Makefile.in (flow.o): Depend on TREE_H.
* basic-block.h (REG_SET_EQUAL_P): New.
(XOR_REG_SET): New.
(n_edges): Declare.
(free_regset_vector): Remove declaration.
(flow_delete_insn_chain): Declare.
(enum update_life_extent): New.
(update_life_info, count_or_remove_death_notes): Declare.
* combine.c (distribute_notes) [REG_DEAD]: Stop search at bb->head.
Verify register live at bb->global_live_at_start before adding USE.
* flow.c (HAVE_epilogue, HAVE_prologue): Provide default.
(CLEAN_ALLOCA): New.
(n_edges): New.
(PROP_*): New flags.
(find_basic_blocks_1): Use alloc_EXPR_LIST.
(clear_edges): Zero n_edges.
(make_edge): Increment n_edges.
(split_edge): Don't allocate bb->local_set. Increment n_edges.
(flow_delete_insn_chain): Export.
(delete_block): Decrement n_edges.
(merge_blocks_nomove): Likewise.
(life_analysis): Give life_analysis_1 PROP flags.
(verify_wide_reg_1, verify_wide_reg): New.
(verify_local_live_at_start): New.
(update_life_info): Rewrite to call into propogate_block.
(mark_reg): New.
(mark_regs_live_at_end): After reload, if epilogue as rtl,
always mark stack pointer. Conditionally mark PIC register.
After reload, mark call-saved registers, return regsiters.
(life_analysis_1): Accept PROP flags not remove_dead_code.
Call mark_regs_live_at_end before zeroing regs_ever_live.
Use calculate_global_regs_live. Copy global_live_at_end before
calling final propagate_block. Zero reg_next_use on exit.
(calculate_global_regs_live): New.
(allocate_bb_life_data): Don't allocate bb->local_set.
(init_regset_vector, free_regset_vector): Remove.
(propagate_block): Accept FLAGS not FINAL or REMOVE_DEAD_CODE.
Test flags before every operation. Warn if prologue/epilogue insn
would have been deleted.
(mark_set_regs, mark_set_1): Accept and use FLAGS.
Use alloc_EXPR_LIST.
(mark_used_regs): Accept and use FLAGS, not FINAL.
Remove special handling for RETURN.
(try_pre_increment): Use alloc_EXPR_LIST.
(dump_flow_info): Dump n_edges.
(unlink_insn_chain, split_hard_reg_notes): Remove.
(maybe_add_dead_note, maybe_add_dead_note_use): Remove.
(find_insn_with_note, new_insn_dead_notes): Remove.
(update_n_sets, sets_reg_or_subreg_1, sets_reg_or_subreg): Remove.
(maybe_remove_dead_notes, prepend_reg_notes): Remove.
(replace_insns): Remove.
(count_or_remove_death_notes): New.
(verify_flow_info): Abort on error after all checks.
(remove_edge): Decrement n_edges.
(remove_fake_edges): Tweek format.
* haifa-sched.c (schedule_insns): Use split_all_insns.
* output.h (update_life_info): Remove declaration.
* recog.c (split_all_insns): From the corpse of split_block_insns,
do the whole function block by block. Use update_life_info.
(recog_last_allowed_insn): New.
(recog_next_insn): Mind it.
(peephole2_optimize): Set it. Walk backwards through blocks.
Use update_life_info.
* rtl.h (update_flow_info, replace_insns): Remove declarations.
(split_all_insns): Declare.
* toplev.c (rest_of_compilation): Thread prologue before flow2.
Use split_all_insns.
* i386.md (or -1 peep2s): Disable.
From-SVN: r29877
1999-10-09 21:47:18 +02:00
|
|
|
|
else
|
1999-02-02 22:22:52 +01:00
|
|
|
|
{
|
Makefile.in (flow.o): Depend on TREE_H.
* Makefile.in (flow.o): Depend on TREE_H.
* basic-block.h (REG_SET_EQUAL_P): New.
(XOR_REG_SET): New.
(n_edges): Declare.
(free_regset_vector): Remove declaration.
(flow_delete_insn_chain): Declare.
(enum update_life_extent): New.
(update_life_info, count_or_remove_death_notes): Declare.
* combine.c (distribute_notes) [REG_DEAD]: Stop search at bb->head.
Verify register live at bb->global_live_at_start before adding USE.
* flow.c (HAVE_epilogue, HAVE_prologue): Provide default.
(CLEAN_ALLOCA): New.
(n_edges): New.
(PROP_*): New flags.
(find_basic_blocks_1): Use alloc_EXPR_LIST.
(clear_edges): Zero n_edges.
(make_edge): Increment n_edges.
(split_edge): Don't allocate bb->local_set. Increment n_edges.
(flow_delete_insn_chain): Export.
(delete_block): Decrement n_edges.
(merge_blocks_nomove): Likewise.
(life_analysis): Give life_analysis_1 PROP flags.
(verify_wide_reg_1, verify_wide_reg): New.
(verify_local_live_at_start): New.
(update_life_info): Rewrite to call into propogate_block.
(mark_reg): New.
(mark_regs_live_at_end): After reload, if epilogue as rtl,
always mark stack pointer. Conditionally mark PIC register.
After reload, mark call-saved registers, return regsiters.
(life_analysis_1): Accept PROP flags not remove_dead_code.
Call mark_regs_live_at_end before zeroing regs_ever_live.
Use calculate_global_regs_live. Copy global_live_at_end before
calling final propagate_block. Zero reg_next_use on exit.
(calculate_global_regs_live): New.
(allocate_bb_life_data): Don't allocate bb->local_set.
(init_regset_vector, free_regset_vector): Remove.
(propagate_block): Accept FLAGS not FINAL or REMOVE_DEAD_CODE.
Test flags before every operation. Warn if prologue/epilogue insn
would have been deleted.
(mark_set_regs, mark_set_1): Accept and use FLAGS.
Use alloc_EXPR_LIST.
(mark_used_regs): Accept and use FLAGS, not FINAL.
Remove special handling for RETURN.
(try_pre_increment): Use alloc_EXPR_LIST.
(dump_flow_info): Dump n_edges.
(unlink_insn_chain, split_hard_reg_notes): Remove.
(maybe_add_dead_note, maybe_add_dead_note_use): Remove.
(find_insn_with_note, new_insn_dead_notes): Remove.
(update_n_sets, sets_reg_or_subreg_1, sets_reg_or_subreg): Remove.
(maybe_remove_dead_notes, prepend_reg_notes): Remove.
(replace_insns): Remove.
(count_or_remove_death_notes): New.
(verify_flow_info): Abort on error after all checks.
(remove_edge): Decrement n_edges.
(remove_fake_edges): Tweek format.
* haifa-sched.c (schedule_insns): Use split_all_insns.
* output.h (update_life_info): Remove declaration.
* recog.c (split_all_insns): From the corpse of split_block_insns,
do the whole function block by block. Use update_life_info.
(recog_last_allowed_insn): New.
(recog_next_insn): Mind it.
(peephole2_optimize): Set it. Walk backwards through blocks.
Use update_life_info.
* rtl.h (update_flow_info, replace_insns): Remove declarations.
(split_all_insns): Declare.
* toplev.c (rest_of_compilation): Thread prologue before flow2.
Use split_all_insns.
* i386.md (or -1 peep2s): Disable.
From-SVN: r29877
1999-10-09 21:47:18 +02:00
|
|
|
|
/* Split insns here to get max fine-grain parallelism. */
|
|
|
|
|
rtx first = PREV_INSN (insn);
|
|
|
|
|
rtx last = try_split (PATTERN (insn), insn, 1);
|
|
|
|
|
|
|
|
|
|
if (last != insn)
|
1999-02-02 22:22:52 +01:00
|
|
|
|
{
|
Makefile.in (flow.o): Depend on TREE_H.
* Makefile.in (flow.o): Depend on TREE_H.
* basic-block.h (REG_SET_EQUAL_P): New.
(XOR_REG_SET): New.
(n_edges): Declare.
(free_regset_vector): Remove declaration.
(flow_delete_insn_chain): Declare.
(enum update_life_extent): New.
(update_life_info, count_or_remove_death_notes): Declare.
* combine.c (distribute_notes) [REG_DEAD]: Stop search at bb->head.
Verify register live at bb->global_live_at_start before adding USE.
* flow.c (HAVE_epilogue, HAVE_prologue): Provide default.
(CLEAN_ALLOCA): New.
(n_edges): New.
(PROP_*): New flags.
(find_basic_blocks_1): Use alloc_EXPR_LIST.
(clear_edges): Zero n_edges.
(make_edge): Increment n_edges.
(split_edge): Don't allocate bb->local_set. Increment n_edges.
(flow_delete_insn_chain): Export.
(delete_block): Decrement n_edges.
(merge_blocks_nomove): Likewise.
(life_analysis): Give life_analysis_1 PROP flags.
(verify_wide_reg_1, verify_wide_reg): New.
(verify_local_live_at_start): New.
(update_life_info): Rewrite to call into propogate_block.
(mark_reg): New.
(mark_regs_live_at_end): After reload, if epilogue as rtl,
always mark stack pointer. Conditionally mark PIC register.
After reload, mark call-saved registers, return regsiters.
(life_analysis_1): Accept PROP flags not remove_dead_code.
Call mark_regs_live_at_end before zeroing regs_ever_live.
Use calculate_global_regs_live. Copy global_live_at_end before
calling final propagate_block. Zero reg_next_use on exit.
(calculate_global_regs_live): New.
(allocate_bb_life_data): Don't allocate bb->local_set.
(init_regset_vector, free_regset_vector): Remove.
(propagate_block): Accept FLAGS not FINAL or REMOVE_DEAD_CODE.
Test flags before every operation. Warn if prologue/epilogue insn
would have been deleted.
(mark_set_regs, mark_set_1): Accept and use FLAGS.
Use alloc_EXPR_LIST.
(mark_used_regs): Accept and use FLAGS, not FINAL.
Remove special handling for RETURN.
(try_pre_increment): Use alloc_EXPR_LIST.
(dump_flow_info): Dump n_edges.
(unlink_insn_chain, split_hard_reg_notes): Remove.
(maybe_add_dead_note, maybe_add_dead_note_use): Remove.
(find_insn_with_note, new_insn_dead_notes): Remove.
(update_n_sets, sets_reg_or_subreg_1, sets_reg_or_subreg): Remove.
(maybe_remove_dead_notes, prepend_reg_notes): Remove.
(replace_insns): Remove.
(count_or_remove_death_notes): New.
(verify_flow_info): Abort on error after all checks.
(remove_edge): Decrement n_edges.
(remove_fake_edges): Tweek format.
* haifa-sched.c (schedule_insns): Use split_all_insns.
* output.h (update_life_info): Remove declaration.
* recog.c (split_all_insns): From the corpse of split_block_insns,
do the whole function block by block. Use update_life_info.
(recog_last_allowed_insn): New.
(recog_next_insn): Mind it.
(peephole2_optimize): Set it. Walk backwards through blocks.
Use update_life_info.
* rtl.h (update_flow_info, replace_insns): Remove declarations.
(split_all_insns): Declare.
* toplev.c (rest_of_compilation): Thread prologue before flow2.
Use split_all_insns.
* i386.md (or -1 peep2s): Disable.
From-SVN: r29877
1999-10-09 21:47:18 +02:00
|
|
|
|
SET_BIT (blocks, i);
|
|
|
|
|
changed = 1;
|
|
|
|
|
|
|
|
|
|
/* try_split returns the NOTE that INSN became. */
|
|
|
|
|
first = NEXT_INSN (first);
|
|
|
|
|
PUT_CODE (insn, NOTE);
|
|
|
|
|
NOTE_SOURCE_FILE (insn) = 0;
|
|
|
|
|
NOTE_LINE_NUMBER (insn) = NOTE_INSN_DELETED;
|
|
|
|
|
|
|
|
|
|
if (insn == bb->end)
|
|
|
|
|
{
|
|
|
|
|
bb->end = last;
|
|
|
|
|
break;
|
|
|
|
|
}
|
1999-02-02 22:22:52 +01:00
|
|
|
|
}
|
|
|
|
|
}
|
Makefile.in (flow.o): Depend on TREE_H.
* Makefile.in (flow.o): Depend on TREE_H.
* basic-block.h (REG_SET_EQUAL_P): New.
(XOR_REG_SET): New.
(n_edges): Declare.
(free_regset_vector): Remove declaration.
(flow_delete_insn_chain): Declare.
(enum update_life_extent): New.
(update_life_info, count_or_remove_death_notes): Declare.
* combine.c (distribute_notes) [REG_DEAD]: Stop search at bb->head.
Verify register live at bb->global_live_at_start before adding USE.
* flow.c (HAVE_epilogue, HAVE_prologue): Provide default.
(CLEAN_ALLOCA): New.
(n_edges): New.
(PROP_*): New flags.
(find_basic_blocks_1): Use alloc_EXPR_LIST.
(clear_edges): Zero n_edges.
(make_edge): Increment n_edges.
(split_edge): Don't allocate bb->local_set. Increment n_edges.
(flow_delete_insn_chain): Export.
(delete_block): Decrement n_edges.
(merge_blocks_nomove): Likewise.
(life_analysis): Give life_analysis_1 PROP flags.
(verify_wide_reg_1, verify_wide_reg): New.
(verify_local_live_at_start): New.
(update_life_info): Rewrite to call into propogate_block.
(mark_reg): New.
(mark_regs_live_at_end): After reload, if epilogue as rtl,
always mark stack pointer. Conditionally mark PIC register.
After reload, mark call-saved registers, return regsiters.
(life_analysis_1): Accept PROP flags not remove_dead_code.
Call mark_regs_live_at_end before zeroing regs_ever_live.
Use calculate_global_regs_live. Copy global_live_at_end before
calling final propagate_block. Zero reg_next_use on exit.
(calculate_global_regs_live): New.
(allocate_bb_life_data): Don't allocate bb->local_set.
(init_regset_vector, free_regset_vector): Remove.
(propagate_block): Accept FLAGS not FINAL or REMOVE_DEAD_CODE.
Test flags before every operation. Warn if prologue/epilogue insn
would have been deleted.
(mark_set_regs, mark_set_1): Accept and use FLAGS.
Use alloc_EXPR_LIST.
(mark_used_regs): Accept and use FLAGS, not FINAL.
Remove special handling for RETURN.
(try_pre_increment): Use alloc_EXPR_LIST.
(dump_flow_info): Dump n_edges.
(unlink_insn_chain, split_hard_reg_notes): Remove.
(maybe_add_dead_note, maybe_add_dead_note_use): Remove.
(find_insn_with_note, new_insn_dead_notes): Remove.
(update_n_sets, sets_reg_or_subreg_1, sets_reg_or_subreg): Remove.
(maybe_remove_dead_notes, prepend_reg_notes): Remove.
(replace_insns): Remove.
(count_or_remove_death_notes): New.
(verify_flow_info): Abort on error after all checks.
(remove_edge): Decrement n_edges.
(remove_fake_edges): Tweek format.
* haifa-sched.c (schedule_insns): Use split_all_insns.
* output.h (update_life_info): Remove declaration.
* recog.c (split_all_insns): From the corpse of split_block_insns,
do the whole function block by block. Use update_life_info.
(recog_last_allowed_insn): New.
(recog_next_insn): Mind it.
(peephole2_optimize): Set it. Walk backwards through blocks.
Use update_life_info.
* rtl.h (update_flow_info, replace_insns): Remove declarations.
(split_all_insns): Declare.
* toplev.c (rest_of_compilation): Thread prologue before flow2.
Use split_all_insns.
* i386.md (or -1 peep2s): Disable.
From-SVN: r29877
1999-10-09 21:47:18 +02:00
|
|
|
|
|
|
|
|
|
if (insn == bb->end)
|
|
|
|
|
break;
|
1999-02-02 22:22:52 +01:00
|
|
|
|
}
|
|
|
|
|
|
Makefile.in (flow.o): Depend on TREE_H.
* Makefile.in (flow.o): Depend on TREE_H.
* basic-block.h (REG_SET_EQUAL_P): New.
(XOR_REG_SET): New.
(n_edges): Declare.
(free_regset_vector): Remove declaration.
(flow_delete_insn_chain): Declare.
(enum update_life_extent): New.
(update_life_info, count_or_remove_death_notes): Declare.
* combine.c (distribute_notes) [REG_DEAD]: Stop search at bb->head.
Verify register live at bb->global_live_at_start before adding USE.
* flow.c (HAVE_epilogue, HAVE_prologue): Provide default.
(CLEAN_ALLOCA): New.
(n_edges): New.
(PROP_*): New flags.
(find_basic_blocks_1): Use alloc_EXPR_LIST.
(clear_edges): Zero n_edges.
(make_edge): Increment n_edges.
(split_edge): Don't allocate bb->local_set. Increment n_edges.
(flow_delete_insn_chain): Export.
(delete_block): Decrement n_edges.
(merge_blocks_nomove): Likewise.
(life_analysis): Give life_analysis_1 PROP flags.
(verify_wide_reg_1, verify_wide_reg): New.
(verify_local_live_at_start): New.
(update_life_info): Rewrite to call into propogate_block.
(mark_reg): New.
(mark_regs_live_at_end): After reload, if epilogue as rtl,
always mark stack pointer. Conditionally mark PIC register.
After reload, mark call-saved registers, return regsiters.
(life_analysis_1): Accept PROP flags not remove_dead_code.
Call mark_regs_live_at_end before zeroing regs_ever_live.
Use calculate_global_regs_live. Copy global_live_at_end before
calling final propagate_block. Zero reg_next_use on exit.
(calculate_global_regs_live): New.
(allocate_bb_life_data): Don't allocate bb->local_set.
(init_regset_vector, free_regset_vector): Remove.
(propagate_block): Accept FLAGS not FINAL or REMOVE_DEAD_CODE.
Test flags before every operation. Warn if prologue/epilogue insn
would have been deleted.
(mark_set_regs, mark_set_1): Accept and use FLAGS.
Use alloc_EXPR_LIST.
(mark_used_regs): Accept and use FLAGS, not FINAL.
Remove special handling for RETURN.
(try_pre_increment): Use alloc_EXPR_LIST.
(dump_flow_info): Dump n_edges.
(unlink_insn_chain, split_hard_reg_notes): Remove.
(maybe_add_dead_note, maybe_add_dead_note_use): Remove.
(find_insn_with_note, new_insn_dead_notes): Remove.
(update_n_sets, sets_reg_or_subreg_1, sets_reg_or_subreg): Remove.
(maybe_remove_dead_notes, prepend_reg_notes): Remove.
(replace_insns): Remove.
(count_or_remove_death_notes): New.
(verify_flow_info): Abort on error after all checks.
(remove_edge): Decrement n_edges.
(remove_fake_edges): Tweek format.
* haifa-sched.c (schedule_insns): Use split_all_insns.
* output.h (update_life_info): Remove declaration.
* recog.c (split_all_insns): From the corpse of split_block_insns,
do the whole function block by block. Use update_life_info.
(recog_last_allowed_insn): New.
(recog_next_insn): Mind it.
(peephole2_optimize): Set it. Walk backwards through blocks.
Use update_life_info.
* rtl.h (update_flow_info, replace_insns): Remove declarations.
(split_all_insns): Declare.
* toplev.c (rest_of_compilation): Thread prologue before flow2.
Use split_all_insns.
* i386.md (or -1 peep2s): Disable.
From-SVN: r29877
1999-10-09 21:47:18 +02:00
|
|
|
|
/* ??? When we're called from just after reload, the CFG is in bad
|
|
|
|
|
shape, and we may have fallen off the end. This could be fixed
|
|
|
|
|
by having reload not try to delete unreachable code. Otherwise
|
|
|
|
|
assert we found the end insn. */
|
|
|
|
|
if (insn == NULL && upd_life)
|
|
|
|
|
abort ();
|
1999-02-02 22:22:52 +01:00
|
|
|
|
}
|
Makefile.in (flow.o): Depend on TREE_H.
* Makefile.in (flow.o): Depend on TREE_H.
* basic-block.h (REG_SET_EQUAL_P): New.
(XOR_REG_SET): New.
(n_edges): Declare.
(free_regset_vector): Remove declaration.
(flow_delete_insn_chain): Declare.
(enum update_life_extent): New.
(update_life_info, count_or_remove_death_notes): Declare.
* combine.c (distribute_notes) [REG_DEAD]: Stop search at bb->head.
Verify register live at bb->global_live_at_start before adding USE.
* flow.c (HAVE_epilogue, HAVE_prologue): Provide default.
(CLEAN_ALLOCA): New.
(n_edges): New.
(PROP_*): New flags.
(find_basic_blocks_1): Use alloc_EXPR_LIST.
(clear_edges): Zero n_edges.
(make_edge): Increment n_edges.
(split_edge): Don't allocate bb->local_set. Increment n_edges.
(flow_delete_insn_chain): Export.
(delete_block): Decrement n_edges.
(merge_blocks_nomove): Likewise.
(life_analysis): Give life_analysis_1 PROP flags.
(verify_wide_reg_1, verify_wide_reg): New.
(verify_local_live_at_start): New.
(update_life_info): Rewrite to call into propogate_block.
(mark_reg): New.
(mark_regs_live_at_end): After reload, if epilogue as rtl,
always mark stack pointer. Conditionally mark PIC register.
After reload, mark call-saved registers, return regsiters.
(life_analysis_1): Accept PROP flags not remove_dead_code.
Call mark_regs_live_at_end before zeroing regs_ever_live.
Use calculate_global_regs_live. Copy global_live_at_end before
calling final propagate_block. Zero reg_next_use on exit.
(calculate_global_regs_live): New.
(allocate_bb_life_data): Don't allocate bb->local_set.
(init_regset_vector, free_regset_vector): Remove.
(propagate_block): Accept FLAGS not FINAL or REMOVE_DEAD_CODE.
Test flags before every operation. Warn if prologue/epilogue insn
would have been deleted.
(mark_set_regs, mark_set_1): Accept and use FLAGS.
Use alloc_EXPR_LIST.
(mark_used_regs): Accept and use FLAGS, not FINAL.
Remove special handling for RETURN.
(try_pre_increment): Use alloc_EXPR_LIST.
(dump_flow_info): Dump n_edges.
(unlink_insn_chain, split_hard_reg_notes): Remove.
(maybe_add_dead_note, maybe_add_dead_note_use): Remove.
(find_insn_with_note, new_insn_dead_notes): Remove.
(update_n_sets, sets_reg_or_subreg_1, sets_reg_or_subreg): Remove.
(maybe_remove_dead_notes, prepend_reg_notes): Remove.
(replace_insns): Remove.
(count_or_remove_death_notes): New.
(verify_flow_info): Abort on error after all checks.
(remove_edge): Decrement n_edges.
(remove_fake_edges): Tweek format.
* haifa-sched.c (schedule_insns): Use split_all_insns.
* output.h (update_life_info): Remove declaration.
* recog.c (split_all_insns): From the corpse of split_block_insns,
do the whole function block by block. Use update_life_info.
(recog_last_allowed_insn): New.
(recog_next_insn): Mind it.
(peephole2_optimize): Set it. Walk backwards through blocks.
Use update_life_info.
* rtl.h (update_flow_info, replace_insns): Remove declarations.
(split_all_insns): Declare.
* toplev.c (rest_of_compilation): Thread prologue before flow2.
Use split_all_insns.
* i386.md (or -1 peep2s): Disable.
From-SVN: r29877
1999-10-09 21:47:18 +02:00
|
|
|
|
|
|
|
|
|
if (changed && upd_life)
|
|
|
|
|
{
|
1999-10-19 00:20:27 +02:00
|
|
|
|
compute_bb_for_insn (get_max_uid ());
|
Makefile.in (flow.o): Depend on TREE_H.
* Makefile.in (flow.o): Depend on TREE_H.
* basic-block.h (REG_SET_EQUAL_P): New.
(XOR_REG_SET): New.
(n_edges): Declare.
(free_regset_vector): Remove declaration.
(flow_delete_insn_chain): Declare.
(enum update_life_extent): New.
(update_life_info, count_or_remove_death_notes): Declare.
* combine.c (distribute_notes) [REG_DEAD]: Stop search at bb->head.
Verify register live at bb->global_live_at_start before adding USE.
* flow.c (HAVE_epilogue, HAVE_prologue): Provide default.
(CLEAN_ALLOCA): New.
(n_edges): New.
(PROP_*): New flags.
(find_basic_blocks_1): Use alloc_EXPR_LIST.
(clear_edges): Zero n_edges.
(make_edge): Increment n_edges.
(split_edge): Don't allocate bb->local_set. Increment n_edges.
(flow_delete_insn_chain): Export.
(delete_block): Decrement n_edges.
(merge_blocks_nomove): Likewise.
(life_analysis): Give life_analysis_1 PROP flags.
(verify_wide_reg_1, verify_wide_reg): New.
(verify_local_live_at_start): New.
(update_life_info): Rewrite to call into propogate_block.
(mark_reg): New.
(mark_regs_live_at_end): After reload, if epilogue as rtl,
always mark stack pointer. Conditionally mark PIC register.
After reload, mark call-saved registers, return regsiters.
(life_analysis_1): Accept PROP flags not remove_dead_code.
Call mark_regs_live_at_end before zeroing regs_ever_live.
Use calculate_global_regs_live. Copy global_live_at_end before
calling final propagate_block. Zero reg_next_use on exit.
(calculate_global_regs_live): New.
(allocate_bb_life_data): Don't allocate bb->local_set.
(init_regset_vector, free_regset_vector): Remove.
(propagate_block): Accept FLAGS not FINAL or REMOVE_DEAD_CODE.
Test flags before every operation. Warn if prologue/epilogue insn
would have been deleted.
(mark_set_regs, mark_set_1): Accept and use FLAGS.
Use alloc_EXPR_LIST.
(mark_used_regs): Accept and use FLAGS, not FINAL.
Remove special handling for RETURN.
(try_pre_increment): Use alloc_EXPR_LIST.
(dump_flow_info): Dump n_edges.
(unlink_insn_chain, split_hard_reg_notes): Remove.
(maybe_add_dead_note, maybe_add_dead_note_use): Remove.
(find_insn_with_note, new_insn_dead_notes): Remove.
(update_n_sets, sets_reg_or_subreg_1, sets_reg_or_subreg): Remove.
(maybe_remove_dead_notes, prepend_reg_notes): Remove.
(replace_insns): Remove.
(count_or_remove_death_notes): New.
(verify_flow_info): Abort on error after all checks.
(remove_edge): Decrement n_edges.
(remove_fake_edges): Tweek format.
* haifa-sched.c (schedule_insns): Use split_all_insns.
* output.h (update_life_info): Remove declaration.
* recog.c (split_all_insns): From the corpse of split_block_insns,
do the whole function block by block. Use update_life_info.
(recog_last_allowed_insn): New.
(recog_next_insn): Mind it.
(peephole2_optimize): Set it. Walk backwards through blocks.
Use update_life_info.
* rtl.h (update_flow_info, replace_insns): Remove declarations.
(split_all_insns): Declare.
* toplev.c (rest_of_compilation): Thread prologue before flow2.
Use split_all_insns.
* i386.md (or -1 peep2s): Disable.
From-SVN: r29877
1999-10-09 21:47:18 +02:00
|
|
|
|
count_or_remove_death_notes (blocks, 1);
|
1999-10-20 16:04:12 +02:00
|
|
|
|
update_life_info (blocks, UPDATE_LIFE_LOCAL, PROP_DEATH_NOTES);
|
Makefile.in (flow.o): Depend on TREE_H.
* Makefile.in (flow.o): Depend on TREE_H.
* basic-block.h (REG_SET_EQUAL_P): New.
(XOR_REG_SET): New.
(n_edges): Declare.
(free_regset_vector): Remove declaration.
(flow_delete_insn_chain): Declare.
(enum update_life_extent): New.
(update_life_info, count_or_remove_death_notes): Declare.
* combine.c (distribute_notes) [REG_DEAD]: Stop search at bb->head.
Verify register live at bb->global_live_at_start before adding USE.
* flow.c (HAVE_epilogue, HAVE_prologue): Provide default.
(CLEAN_ALLOCA): New.
(n_edges): New.
(PROP_*): New flags.
(find_basic_blocks_1): Use alloc_EXPR_LIST.
(clear_edges): Zero n_edges.
(make_edge): Increment n_edges.
(split_edge): Don't allocate bb->local_set. Increment n_edges.
(flow_delete_insn_chain): Export.
(delete_block): Decrement n_edges.
(merge_blocks_nomove): Likewise.
(life_analysis): Give life_analysis_1 PROP flags.
(verify_wide_reg_1, verify_wide_reg): New.
(verify_local_live_at_start): New.
(update_life_info): Rewrite to call into propogate_block.
(mark_reg): New.
(mark_regs_live_at_end): After reload, if epilogue as rtl,
always mark stack pointer. Conditionally mark PIC register.
After reload, mark call-saved registers, return regsiters.
(life_analysis_1): Accept PROP flags not remove_dead_code.
Call mark_regs_live_at_end before zeroing regs_ever_live.
Use calculate_global_regs_live. Copy global_live_at_end before
calling final propagate_block. Zero reg_next_use on exit.
(calculate_global_regs_live): New.
(allocate_bb_life_data): Don't allocate bb->local_set.
(init_regset_vector, free_regset_vector): Remove.
(propagate_block): Accept FLAGS not FINAL or REMOVE_DEAD_CODE.
Test flags before every operation. Warn if prologue/epilogue insn
would have been deleted.
(mark_set_regs, mark_set_1): Accept and use FLAGS.
Use alloc_EXPR_LIST.
(mark_used_regs): Accept and use FLAGS, not FINAL.
Remove special handling for RETURN.
(try_pre_increment): Use alloc_EXPR_LIST.
(dump_flow_info): Dump n_edges.
(unlink_insn_chain, split_hard_reg_notes): Remove.
(maybe_add_dead_note, maybe_add_dead_note_use): Remove.
(find_insn_with_note, new_insn_dead_notes): Remove.
(update_n_sets, sets_reg_or_subreg_1, sets_reg_or_subreg): Remove.
(maybe_remove_dead_notes, prepend_reg_notes): Remove.
(replace_insns): Remove.
(count_or_remove_death_notes): New.
(verify_flow_info): Abort on error after all checks.
(remove_edge): Decrement n_edges.
(remove_fake_edges): Tweek format.
* haifa-sched.c (schedule_insns): Use split_all_insns.
* output.h (update_life_info): Remove declaration.
* recog.c (split_all_insns): From the corpse of split_block_insns,
do the whole function block by block. Use update_life_info.
(recog_last_allowed_insn): New.
(recog_next_insn): Mind it.
(peephole2_optimize): Set it. Walk backwards through blocks.
Use update_life_info.
* rtl.h (update_flow_info, replace_insns): Remove declarations.
(split_all_insns): Declare.
* toplev.c (rest_of_compilation): Thread prologue before flow2.
Use split_all_insns.
* i386.md (or -1 peep2s): Disable.
From-SVN: r29877
1999-10-09 21:47:18 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
sbitmap_free (blocks);
|
1999-02-02 22:22:52 +01:00
|
|
|
|
}
|
1999-08-31 22:37:09 +02:00
|
|
|
|
|
|
|
|
|
#ifdef HAVE_peephole2
|
2000-05-27 22:23:15 +02:00
|
|
|
|
struct peep2_insn_data
|
|
|
|
|
{
|
|
|
|
|
rtx insn;
|
|
|
|
|
regset live_before;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
static struct peep2_insn_data peep2_insn_data[MAX_INSNS_PER_PEEP2 + 1];
|
|
|
|
|
static int peep2_current;
|
|
|
|
|
|
|
|
|
|
/* A non-insn marker indicating the last insn of the block.
|
|
|
|
|
The live_before regset for this element is correct, indicating
|
|
|
|
|
global_live_at_end for the block. */
|
|
|
|
|
#define PEEP2_EOB pc_rtx
|
|
|
|
|
|
|
|
|
|
/* Return the Nth non-note insn after `current', or return NULL_RTX if it
|
|
|
|
|
does not exist. Used by the recognizer to find the next insn to match
|
|
|
|
|
in a multi-insn pattern. */
|
Makefile.in (flow.o): Depend on TREE_H.
* Makefile.in (flow.o): Depend on TREE_H.
* basic-block.h (REG_SET_EQUAL_P): New.
(XOR_REG_SET): New.
(n_edges): Declare.
(free_regset_vector): Remove declaration.
(flow_delete_insn_chain): Declare.
(enum update_life_extent): New.
(update_life_info, count_or_remove_death_notes): Declare.
* combine.c (distribute_notes) [REG_DEAD]: Stop search at bb->head.
Verify register live at bb->global_live_at_start before adding USE.
* flow.c (HAVE_epilogue, HAVE_prologue): Provide default.
(CLEAN_ALLOCA): New.
(n_edges): New.
(PROP_*): New flags.
(find_basic_blocks_1): Use alloc_EXPR_LIST.
(clear_edges): Zero n_edges.
(make_edge): Increment n_edges.
(split_edge): Don't allocate bb->local_set. Increment n_edges.
(flow_delete_insn_chain): Export.
(delete_block): Decrement n_edges.
(merge_blocks_nomove): Likewise.
(life_analysis): Give life_analysis_1 PROP flags.
(verify_wide_reg_1, verify_wide_reg): New.
(verify_local_live_at_start): New.
(update_life_info): Rewrite to call into propogate_block.
(mark_reg): New.
(mark_regs_live_at_end): After reload, if epilogue as rtl,
always mark stack pointer. Conditionally mark PIC register.
After reload, mark call-saved registers, return regsiters.
(life_analysis_1): Accept PROP flags not remove_dead_code.
Call mark_regs_live_at_end before zeroing regs_ever_live.
Use calculate_global_regs_live. Copy global_live_at_end before
calling final propagate_block. Zero reg_next_use on exit.
(calculate_global_regs_live): New.
(allocate_bb_life_data): Don't allocate bb->local_set.
(init_regset_vector, free_regset_vector): Remove.
(propagate_block): Accept FLAGS not FINAL or REMOVE_DEAD_CODE.
Test flags before every operation. Warn if prologue/epilogue insn
would have been deleted.
(mark_set_regs, mark_set_1): Accept and use FLAGS.
Use alloc_EXPR_LIST.
(mark_used_regs): Accept and use FLAGS, not FINAL.
Remove special handling for RETURN.
(try_pre_increment): Use alloc_EXPR_LIST.
(dump_flow_info): Dump n_edges.
(unlink_insn_chain, split_hard_reg_notes): Remove.
(maybe_add_dead_note, maybe_add_dead_note_use): Remove.
(find_insn_with_note, new_insn_dead_notes): Remove.
(update_n_sets, sets_reg_or_subreg_1, sets_reg_or_subreg): Remove.
(maybe_remove_dead_notes, prepend_reg_notes): Remove.
(replace_insns): Remove.
(count_or_remove_death_notes): New.
(verify_flow_info): Abort on error after all checks.
(remove_edge): Decrement n_edges.
(remove_fake_edges): Tweek format.
* haifa-sched.c (schedule_insns): Use split_all_insns.
* output.h (update_life_info): Remove declaration.
* recog.c (split_all_insns): From the corpse of split_block_insns,
do the whole function block by block. Use update_life_info.
(recog_last_allowed_insn): New.
(recog_next_insn): Mind it.
(peephole2_optimize): Set it. Walk backwards through blocks.
Use update_life_info.
* rtl.h (update_flow_info, replace_insns): Remove declarations.
(split_all_insns): Declare.
* toplev.c (rest_of_compilation): Thread prologue before flow2.
Use split_all_insns.
* i386.md (or -1 peep2s): Disable.
From-SVN: r29877
1999-10-09 21:47:18 +02:00
|
|
|
|
|
1999-08-31 22:37:09 +02:00
|
|
|
|
rtx
|
2000-05-27 22:23:15 +02:00
|
|
|
|
peep2_next_insn (n)
|
1999-08-31 22:37:09 +02:00
|
|
|
|
int n;
|
|
|
|
|
{
|
2000-05-27 22:23:15 +02:00
|
|
|
|
if (n >= MAX_INSNS_PER_PEEP2 + 1)
|
|
|
|
|
abort ();
|
|
|
|
|
|
|
|
|
|
n += peep2_current;
|
|
|
|
|
if (n >= MAX_INSNS_PER_PEEP2 + 1)
|
|
|
|
|
n -= MAX_INSNS_PER_PEEP2 + 1;
|
|
|
|
|
|
|
|
|
|
if (peep2_insn_data[n].insn == PEEP2_EOB)
|
|
|
|
|
return NULL_RTX;
|
|
|
|
|
return peep2_insn_data[n].insn;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Return true if REGNO is dead before the Nth non-note insn
|
|
|
|
|
after `current'. */
|
|
|
|
|
|
|
|
|
|
int
|
|
|
|
|
peep2_regno_dead_p (ofs, regno)
|
|
|
|
|
int ofs;
|
|
|
|
|
int regno;
|
|
|
|
|
{
|
|
|
|
|
if (ofs >= MAX_INSNS_PER_PEEP2 + 1)
|
|
|
|
|
abort ();
|
|
|
|
|
|
|
|
|
|
ofs += peep2_current;
|
|
|
|
|
if (ofs >= MAX_INSNS_PER_PEEP2 + 1)
|
|
|
|
|
ofs -= MAX_INSNS_PER_PEEP2 + 1;
|
|
|
|
|
|
|
|
|
|
if (peep2_insn_data[ofs].insn == NULL_RTX)
|
|
|
|
|
abort ();
|
|
|
|
|
|
|
|
|
|
return ! REGNO_REG_SET_P (peep2_insn_data[ofs].live_before, regno);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Similarly for a REG. */
|
|
|
|
|
|
|
|
|
|
int
|
|
|
|
|
peep2_reg_dead_p (ofs, reg)
|
|
|
|
|
int ofs;
|
|
|
|
|
rtx reg;
|
|
|
|
|
{
|
|
|
|
|
int regno, n;
|
|
|
|
|
|
|
|
|
|
if (ofs >= MAX_INSNS_PER_PEEP2 + 1)
|
|
|
|
|
abort ();
|
|
|
|
|
|
|
|
|
|
ofs += peep2_current;
|
|
|
|
|
if (ofs >= MAX_INSNS_PER_PEEP2 + 1)
|
|
|
|
|
ofs -= MAX_INSNS_PER_PEEP2 + 1;
|
|
|
|
|
|
|
|
|
|
if (peep2_insn_data[ofs].insn == NULL_RTX)
|
|
|
|
|
abort ();
|
|
|
|
|
|
|
|
|
|
regno = REGNO (reg);
|
|
|
|
|
n = HARD_REGNO_NREGS (regno, GET_MODE (reg));
|
|
|
|
|
while (--n >= 0)
|
|
|
|
|
if (REGNO_REG_SET_P (peep2_insn_data[ofs].live_before, regno + n))
|
|
|
|
|
return 0;
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Try to find a hard register of mode MODE, matching the register class in
|
|
|
|
|
CLASS_STR, which is available at the beginning of insn CURRENT_INSN and
|
|
|
|
|
remains available until the end of LAST_INSN. LAST_INSN may be NULL_RTX,
|
|
|
|
|
in which case the only condition is that the register must be available
|
|
|
|
|
before CURRENT_INSN.
|
|
|
|
|
Registers that already have bits set in REG_SET will not be considered.
|
|
|
|
|
|
|
|
|
|
If an appropriate register is available, it will be returned and the
|
|
|
|
|
corresponding bit(s) in REG_SET will be set; otherwise, NULL_RTX is
|
|
|
|
|
returned. */
|
|
|
|
|
|
|
|
|
|
rtx
|
|
|
|
|
peep2_find_free_register (from, to, class_str, mode, reg_set)
|
|
|
|
|
int from, to;
|
|
|
|
|
const char *class_str;
|
|
|
|
|
enum machine_mode mode;
|
|
|
|
|
HARD_REG_SET *reg_set;
|
|
|
|
|
{
|
|
|
|
|
static int search_ofs;
|
|
|
|
|
enum reg_class class;
|
|
|
|
|
HARD_REG_SET live;
|
|
|
|
|
int i;
|
|
|
|
|
|
|
|
|
|
if (from >= MAX_INSNS_PER_PEEP2 + 1 || to >= MAX_INSNS_PER_PEEP2 + 1)
|
|
|
|
|
abort ();
|
|
|
|
|
|
|
|
|
|
from += peep2_current;
|
|
|
|
|
if (from >= MAX_INSNS_PER_PEEP2 + 1)
|
|
|
|
|
from -= MAX_INSNS_PER_PEEP2 + 1;
|
|
|
|
|
to += peep2_current;
|
|
|
|
|
if (to >= MAX_INSNS_PER_PEEP2 + 1)
|
|
|
|
|
to -= MAX_INSNS_PER_PEEP2 + 1;
|
|
|
|
|
|
|
|
|
|
if (peep2_insn_data[from].insn == NULL_RTX)
|
|
|
|
|
abort ();
|
|
|
|
|
REG_SET_TO_HARD_REG_SET (live, peep2_insn_data[from].live_before);
|
|
|
|
|
|
|
|
|
|
while (from != to)
|
1999-08-31 22:37:09 +02:00
|
|
|
|
{
|
2000-05-27 22:23:15 +02:00
|
|
|
|
HARD_REG_SET this_live;
|
|
|
|
|
|
|
|
|
|
if (++from >= MAX_INSNS_PER_PEEP2 + 1)
|
|
|
|
|
from = 0;
|
|
|
|
|
if (peep2_insn_data[from].insn == NULL_RTX)
|
|
|
|
|
abort ();
|
|
|
|
|
REG_SET_TO_HARD_REG_SET (this_live, peep2_insn_data[from].live_before);
|
|
|
|
|
IOR_HARD_REG_SET (live, this_live);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
class = (class_str[0] == 'r' ? GENERAL_REGS
|
|
|
|
|
: REG_CLASS_FROM_LETTER (class_str[0]));
|
|
|
|
|
|
|
|
|
|
for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
|
|
|
|
|
{
|
|
|
|
|
int raw_regno, regno, success, j;
|
|
|
|
|
|
|
|
|
|
/* Distribute the free registers as much as possible. */
|
|
|
|
|
raw_regno = search_ofs + i;
|
|
|
|
|
if (raw_regno >= FIRST_PSEUDO_REGISTER)
|
|
|
|
|
raw_regno -= FIRST_PSEUDO_REGISTER;
|
|
|
|
|
#ifdef REG_ALLOC_ORDER
|
|
|
|
|
regno = reg_alloc_order[raw_regno];
|
|
|
|
|
#else
|
|
|
|
|
regno = raw_regno;
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
/* Don't allocate fixed registers. */
|
|
|
|
|
if (fixed_regs[regno])
|
|
|
|
|
continue;
|
|
|
|
|
/* Make sure the register is of the right class. */
|
|
|
|
|
if (! TEST_HARD_REG_BIT (reg_class_contents[class], regno))
|
|
|
|
|
continue;
|
|
|
|
|
/* And can support the mode we need. */
|
|
|
|
|
if (! HARD_REGNO_MODE_OK (regno, mode))
|
|
|
|
|
continue;
|
|
|
|
|
/* And that we don't create an extra save/restore. */
|
|
|
|
|
if (! call_used_regs[regno] && ! regs_ever_live[regno])
|
|
|
|
|
continue;
|
|
|
|
|
/* And we don't clobber traceback for noreturn functions. */
|
|
|
|
|
if ((regno == FRAME_POINTER_REGNUM || regno == HARD_FRAME_POINTER_REGNUM)
|
|
|
|
|
&& (! reload_completed || frame_pointer_needed))
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
success = 1;
|
|
|
|
|
for (j = HARD_REGNO_NREGS (regno, mode) - 1; j >= 0; j--)
|
|
|
|
|
{
|
|
|
|
|
if (TEST_HARD_REG_BIT (*reg_set, regno + j)
|
|
|
|
|
|| TEST_HARD_REG_BIT (live, regno + j))
|
|
|
|
|
{
|
|
|
|
|
success = 0;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (success)
|
Makefile.in (flow.o): Depend on TREE_H.
* Makefile.in (flow.o): Depend on TREE_H.
* basic-block.h (REG_SET_EQUAL_P): New.
(XOR_REG_SET): New.
(n_edges): Declare.
(free_regset_vector): Remove declaration.
(flow_delete_insn_chain): Declare.
(enum update_life_extent): New.
(update_life_info, count_or_remove_death_notes): Declare.
* combine.c (distribute_notes) [REG_DEAD]: Stop search at bb->head.
Verify register live at bb->global_live_at_start before adding USE.
* flow.c (HAVE_epilogue, HAVE_prologue): Provide default.
(CLEAN_ALLOCA): New.
(n_edges): New.
(PROP_*): New flags.
(find_basic_blocks_1): Use alloc_EXPR_LIST.
(clear_edges): Zero n_edges.
(make_edge): Increment n_edges.
(split_edge): Don't allocate bb->local_set. Increment n_edges.
(flow_delete_insn_chain): Export.
(delete_block): Decrement n_edges.
(merge_blocks_nomove): Likewise.
(life_analysis): Give life_analysis_1 PROP flags.
(verify_wide_reg_1, verify_wide_reg): New.
(verify_local_live_at_start): New.
(update_life_info): Rewrite to call into propogate_block.
(mark_reg): New.
(mark_regs_live_at_end): After reload, if epilogue as rtl,
always mark stack pointer. Conditionally mark PIC register.
After reload, mark call-saved registers, return regsiters.
(life_analysis_1): Accept PROP flags not remove_dead_code.
Call mark_regs_live_at_end before zeroing regs_ever_live.
Use calculate_global_regs_live. Copy global_live_at_end before
calling final propagate_block. Zero reg_next_use on exit.
(calculate_global_regs_live): New.
(allocate_bb_life_data): Don't allocate bb->local_set.
(init_regset_vector, free_regset_vector): Remove.
(propagate_block): Accept FLAGS not FINAL or REMOVE_DEAD_CODE.
Test flags before every operation. Warn if prologue/epilogue insn
would have been deleted.
(mark_set_regs, mark_set_1): Accept and use FLAGS.
Use alloc_EXPR_LIST.
(mark_used_regs): Accept and use FLAGS, not FINAL.
Remove special handling for RETURN.
(try_pre_increment): Use alloc_EXPR_LIST.
(dump_flow_info): Dump n_edges.
(unlink_insn_chain, split_hard_reg_notes): Remove.
(maybe_add_dead_note, maybe_add_dead_note_use): Remove.
(find_insn_with_note, new_insn_dead_notes): Remove.
(update_n_sets, sets_reg_or_subreg_1, sets_reg_or_subreg): Remove.
(maybe_remove_dead_notes, prepend_reg_notes): Remove.
(replace_insns): Remove.
(count_or_remove_death_notes): New.
(verify_flow_info): Abort on error after all checks.
(remove_edge): Decrement n_edges.
(remove_fake_edges): Tweek format.
* haifa-sched.c (schedule_insns): Use split_all_insns.
* output.h (update_life_info): Remove declaration.
* recog.c (split_all_insns): From the corpse of split_block_insns,
do the whole function block by block. Use update_life_info.
(recog_last_allowed_insn): New.
(recog_next_insn): Mind it.
(peephole2_optimize): Set it. Walk backwards through blocks.
Use update_life_info.
* rtl.h (update_flow_info, replace_insns): Remove declarations.
(split_all_insns): Declare.
* toplev.c (rest_of_compilation): Thread prologue before flow2.
Use split_all_insns.
* i386.md (or -1 peep2s): Disable.
From-SVN: r29877
1999-10-09 21:47:18 +02:00
|
|
|
|
{
|
2000-05-27 22:23:15 +02:00
|
|
|
|
for (j = HARD_REGNO_NREGS (regno, mode) - 1; j >= 0; j--)
|
|
|
|
|
SET_HARD_REG_BIT (*reg_set, regno + j);
|
1999-08-31 22:37:09 +02:00
|
|
|
|
|
2000-05-27 22:23:15 +02:00
|
|
|
|
/* Start the next search with the next register. */
|
|
|
|
|
if (++raw_regno >= FIRST_PSEUDO_REGISTER)
|
|
|
|
|
raw_regno = 0;
|
|
|
|
|
search_ofs = raw_regno;
|
1999-08-31 22:37:09 +02:00
|
|
|
|
|
2000-05-27 22:23:15 +02:00
|
|
|
|
return gen_rtx_REG (mode, regno);
|
Makefile.in (flow.o): Depend on TREE_H.
* Makefile.in (flow.o): Depend on TREE_H.
* basic-block.h (REG_SET_EQUAL_P): New.
(XOR_REG_SET): New.
(n_edges): Declare.
(free_regset_vector): Remove declaration.
(flow_delete_insn_chain): Declare.
(enum update_life_extent): New.
(update_life_info, count_or_remove_death_notes): Declare.
* combine.c (distribute_notes) [REG_DEAD]: Stop search at bb->head.
Verify register live at bb->global_live_at_start before adding USE.
* flow.c (HAVE_epilogue, HAVE_prologue): Provide default.
(CLEAN_ALLOCA): New.
(n_edges): New.
(PROP_*): New flags.
(find_basic_blocks_1): Use alloc_EXPR_LIST.
(clear_edges): Zero n_edges.
(make_edge): Increment n_edges.
(split_edge): Don't allocate bb->local_set. Increment n_edges.
(flow_delete_insn_chain): Export.
(delete_block): Decrement n_edges.
(merge_blocks_nomove): Likewise.
(life_analysis): Give life_analysis_1 PROP flags.
(verify_wide_reg_1, verify_wide_reg): New.
(verify_local_live_at_start): New.
(update_life_info): Rewrite to call into propogate_block.
(mark_reg): New.
(mark_regs_live_at_end): After reload, if epilogue as rtl,
always mark stack pointer. Conditionally mark PIC register.
After reload, mark call-saved registers, return regsiters.
(life_analysis_1): Accept PROP flags not remove_dead_code.
Call mark_regs_live_at_end before zeroing regs_ever_live.
Use calculate_global_regs_live. Copy global_live_at_end before
calling final propagate_block. Zero reg_next_use on exit.
(calculate_global_regs_live): New.
(allocate_bb_life_data): Don't allocate bb->local_set.
(init_regset_vector, free_regset_vector): Remove.
(propagate_block): Accept FLAGS not FINAL or REMOVE_DEAD_CODE.
Test flags before every operation. Warn if prologue/epilogue insn
would have been deleted.
(mark_set_regs, mark_set_1): Accept and use FLAGS.
Use alloc_EXPR_LIST.
(mark_used_regs): Accept and use FLAGS, not FINAL.
Remove special handling for RETURN.
(try_pre_increment): Use alloc_EXPR_LIST.
(dump_flow_info): Dump n_edges.
(unlink_insn_chain, split_hard_reg_notes): Remove.
(maybe_add_dead_note, maybe_add_dead_note_use): Remove.
(find_insn_with_note, new_insn_dead_notes): Remove.
(update_n_sets, sets_reg_or_subreg_1, sets_reg_or_subreg): Remove.
(maybe_remove_dead_notes, prepend_reg_notes): Remove.
(replace_insns): Remove.
(count_or_remove_death_notes): New.
(verify_flow_info): Abort on error after all checks.
(remove_edge): Decrement n_edges.
(remove_fake_edges): Tweek format.
* haifa-sched.c (schedule_insns): Use split_all_insns.
* output.h (update_life_info): Remove declaration.
* recog.c (split_all_insns): From the corpse of split_block_insns,
do the whole function block by block. Use update_life_info.
(recog_last_allowed_insn): New.
(recog_next_insn): Mind it.
(peephole2_optimize): Set it. Walk backwards through blocks.
Use update_life_info.
* rtl.h (update_flow_info, replace_insns): Remove declarations.
(split_all_insns): Declare.
* toplev.c (rest_of_compilation): Thread prologue before flow2.
Use split_all_insns.
* i386.md (or -1 peep2s): Disable.
From-SVN: r29877
1999-10-09 21:47:18 +02:00
|
|
|
|
}
|
1999-08-31 22:37:09 +02:00
|
|
|
|
}
|
|
|
|
|
|
2000-05-27 22:23:15 +02:00
|
|
|
|
search_ofs = 0;
|
|
|
|
|
return NULL_RTX;
|
1999-08-31 22:37:09 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Perform the peephole2 optimization pass. */
|
2000-05-27 22:23:15 +02:00
|
|
|
|
|
1999-08-31 22:37:09 +02:00
|
|
|
|
void
|
|
|
|
|
peephole2_optimize (dump_file)
|
|
|
|
|
FILE *dump_file ATTRIBUTE_UNUSED;
|
|
|
|
|
{
|
2000-05-27 22:23:15 +02:00
|
|
|
|
regset_head rs_heads[MAX_INSNS_PER_PEEP2 + 2];
|
Makefile.in (flow.o): Depend on TREE_H.
* Makefile.in (flow.o): Depend on TREE_H.
* basic-block.h (REG_SET_EQUAL_P): New.
(XOR_REG_SET): New.
(n_edges): Declare.
(free_regset_vector): Remove declaration.
(flow_delete_insn_chain): Declare.
(enum update_life_extent): New.
(update_life_info, count_or_remove_death_notes): Declare.
* combine.c (distribute_notes) [REG_DEAD]: Stop search at bb->head.
Verify register live at bb->global_live_at_start before adding USE.
* flow.c (HAVE_epilogue, HAVE_prologue): Provide default.
(CLEAN_ALLOCA): New.
(n_edges): New.
(PROP_*): New flags.
(find_basic_blocks_1): Use alloc_EXPR_LIST.
(clear_edges): Zero n_edges.
(make_edge): Increment n_edges.
(split_edge): Don't allocate bb->local_set. Increment n_edges.
(flow_delete_insn_chain): Export.
(delete_block): Decrement n_edges.
(merge_blocks_nomove): Likewise.
(life_analysis): Give life_analysis_1 PROP flags.
(verify_wide_reg_1, verify_wide_reg): New.
(verify_local_live_at_start): New.
(update_life_info): Rewrite to call into propogate_block.
(mark_reg): New.
(mark_regs_live_at_end): After reload, if epilogue as rtl,
always mark stack pointer. Conditionally mark PIC register.
After reload, mark call-saved registers, return regsiters.
(life_analysis_1): Accept PROP flags not remove_dead_code.
Call mark_regs_live_at_end before zeroing regs_ever_live.
Use calculate_global_regs_live. Copy global_live_at_end before
calling final propagate_block. Zero reg_next_use on exit.
(calculate_global_regs_live): New.
(allocate_bb_life_data): Don't allocate bb->local_set.
(init_regset_vector, free_regset_vector): Remove.
(propagate_block): Accept FLAGS not FINAL or REMOVE_DEAD_CODE.
Test flags before every operation. Warn if prologue/epilogue insn
would have been deleted.
(mark_set_regs, mark_set_1): Accept and use FLAGS.
Use alloc_EXPR_LIST.
(mark_used_regs): Accept and use FLAGS, not FINAL.
Remove special handling for RETURN.
(try_pre_increment): Use alloc_EXPR_LIST.
(dump_flow_info): Dump n_edges.
(unlink_insn_chain, split_hard_reg_notes): Remove.
(maybe_add_dead_note, maybe_add_dead_note_use): Remove.
(find_insn_with_note, new_insn_dead_notes): Remove.
(update_n_sets, sets_reg_or_subreg_1, sets_reg_or_subreg): Remove.
(maybe_remove_dead_notes, prepend_reg_notes): Remove.
(replace_insns): Remove.
(count_or_remove_death_notes): New.
(verify_flow_info): Abort on error after all checks.
(remove_edge): Decrement n_edges.
(remove_fake_edges): Tweek format.
* haifa-sched.c (schedule_insns): Use split_all_insns.
* output.h (update_life_info): Remove declaration.
* recog.c (split_all_insns): From the corpse of split_block_insns,
do the whole function block by block. Use update_life_info.
(recog_last_allowed_insn): New.
(recog_next_insn): Mind it.
(peephole2_optimize): Set it. Walk backwards through blocks.
Use update_life_info.
* rtl.h (update_flow_info, replace_insns): Remove declarations.
(split_all_insns): Declare.
* toplev.c (rest_of_compilation): Thread prologue before flow2.
Use split_all_insns.
* i386.md (or -1 peep2s): Disable.
From-SVN: r29877
1999-10-09 21:47:18 +02:00
|
|
|
|
rtx insn, prev;
|
2000-05-27 22:23:15 +02:00
|
|
|
|
regset live;
|
|
|
|
|
int i, b;
|
|
|
|
|
#ifdef HAVE_conditional_execution
|
Makefile.in (flow.o): Depend on TREE_H.
* Makefile.in (flow.o): Depend on TREE_H.
* basic-block.h (REG_SET_EQUAL_P): New.
(XOR_REG_SET): New.
(n_edges): Declare.
(free_regset_vector): Remove declaration.
(flow_delete_insn_chain): Declare.
(enum update_life_extent): New.
(update_life_info, count_or_remove_death_notes): Declare.
* combine.c (distribute_notes) [REG_DEAD]: Stop search at bb->head.
Verify register live at bb->global_live_at_start before adding USE.
* flow.c (HAVE_epilogue, HAVE_prologue): Provide default.
(CLEAN_ALLOCA): New.
(n_edges): New.
(PROP_*): New flags.
(find_basic_blocks_1): Use alloc_EXPR_LIST.
(clear_edges): Zero n_edges.
(make_edge): Increment n_edges.
(split_edge): Don't allocate bb->local_set. Increment n_edges.
(flow_delete_insn_chain): Export.
(delete_block): Decrement n_edges.
(merge_blocks_nomove): Likewise.
(life_analysis): Give life_analysis_1 PROP flags.
(verify_wide_reg_1, verify_wide_reg): New.
(verify_local_live_at_start): New.
(update_life_info): Rewrite to call into propogate_block.
(mark_reg): New.
(mark_regs_live_at_end): After reload, if epilogue as rtl,
always mark stack pointer. Conditionally mark PIC register.
After reload, mark call-saved registers, return regsiters.
(life_analysis_1): Accept PROP flags not remove_dead_code.
Call mark_regs_live_at_end before zeroing regs_ever_live.
Use calculate_global_regs_live. Copy global_live_at_end before
calling final propagate_block. Zero reg_next_use on exit.
(calculate_global_regs_live): New.
(allocate_bb_life_data): Don't allocate bb->local_set.
(init_regset_vector, free_regset_vector): Remove.
(propagate_block): Accept FLAGS not FINAL or REMOVE_DEAD_CODE.
Test flags before every operation. Warn if prologue/epilogue insn
would have been deleted.
(mark_set_regs, mark_set_1): Accept and use FLAGS.
Use alloc_EXPR_LIST.
(mark_used_regs): Accept and use FLAGS, not FINAL.
Remove special handling for RETURN.
(try_pre_increment): Use alloc_EXPR_LIST.
(dump_flow_info): Dump n_edges.
(unlink_insn_chain, split_hard_reg_notes): Remove.
(maybe_add_dead_note, maybe_add_dead_note_use): Remove.
(find_insn_with_note, new_insn_dead_notes): Remove.
(update_n_sets, sets_reg_or_subreg_1, sets_reg_or_subreg): Remove.
(maybe_remove_dead_notes, prepend_reg_notes): Remove.
(replace_insns): Remove.
(count_or_remove_death_notes): New.
(verify_flow_info): Abort on error after all checks.
(remove_edge): Decrement n_edges.
(remove_fake_edges): Tweek format.
* haifa-sched.c (schedule_insns): Use split_all_insns.
* output.h (update_life_info): Remove declaration.
* recog.c (split_all_insns): From the corpse of split_block_insns,
do the whole function block by block. Use update_life_info.
(recog_last_allowed_insn): New.
(recog_next_insn): Mind it.
(peephole2_optimize): Set it. Walk backwards through blocks.
Use update_life_info.
* rtl.h (update_flow_info, replace_insns): Remove declarations.
(split_all_insns): Declare.
* toplev.c (rest_of_compilation): Thread prologue before flow2.
Use split_all_insns.
* i386.md (or -1 peep2s): Disable.
From-SVN: r29877
1999-10-09 21:47:18 +02:00
|
|
|
|
sbitmap blocks;
|
2000-05-27 22:23:15 +02:00
|
|
|
|
int changed;
|
|
|
|
|
#endif
|
1999-08-31 22:37:09 +02:00
|
|
|
|
|
2000-05-27 22:23:15 +02:00
|
|
|
|
/* Initialize the regsets we're going to use. */
|
|
|
|
|
for (i = 0; i < MAX_INSNS_PER_PEEP2 + 1; ++i)
|
|
|
|
|
peep2_insn_data[i].live_before = INITIALIZE_REG_SET (rs_heads[i]);
|
|
|
|
|
live = INITIALIZE_REG_SET (rs_heads[i]);
|
1999-08-31 22:37:09 +02:00
|
|
|
|
|
2000-05-27 22:23:15 +02:00
|
|
|
|
#ifdef HAVE_conditional_execution
|
Makefile.in (flow.o): Depend on TREE_H.
* Makefile.in (flow.o): Depend on TREE_H.
* basic-block.h (REG_SET_EQUAL_P): New.
(XOR_REG_SET): New.
(n_edges): Declare.
(free_regset_vector): Remove declaration.
(flow_delete_insn_chain): Declare.
(enum update_life_extent): New.
(update_life_info, count_or_remove_death_notes): Declare.
* combine.c (distribute_notes) [REG_DEAD]: Stop search at bb->head.
Verify register live at bb->global_live_at_start before adding USE.
* flow.c (HAVE_epilogue, HAVE_prologue): Provide default.
(CLEAN_ALLOCA): New.
(n_edges): New.
(PROP_*): New flags.
(find_basic_blocks_1): Use alloc_EXPR_LIST.
(clear_edges): Zero n_edges.
(make_edge): Increment n_edges.
(split_edge): Don't allocate bb->local_set. Increment n_edges.
(flow_delete_insn_chain): Export.
(delete_block): Decrement n_edges.
(merge_blocks_nomove): Likewise.
(life_analysis): Give life_analysis_1 PROP flags.
(verify_wide_reg_1, verify_wide_reg): New.
(verify_local_live_at_start): New.
(update_life_info): Rewrite to call into propogate_block.
(mark_reg): New.
(mark_regs_live_at_end): After reload, if epilogue as rtl,
always mark stack pointer. Conditionally mark PIC register.
After reload, mark call-saved registers, return regsiters.
(life_analysis_1): Accept PROP flags not remove_dead_code.
Call mark_regs_live_at_end before zeroing regs_ever_live.
Use calculate_global_regs_live. Copy global_live_at_end before
calling final propagate_block. Zero reg_next_use on exit.
(calculate_global_regs_live): New.
(allocate_bb_life_data): Don't allocate bb->local_set.
(init_regset_vector, free_regset_vector): Remove.
(propagate_block): Accept FLAGS not FINAL or REMOVE_DEAD_CODE.
Test flags before every operation. Warn if prologue/epilogue insn
would have been deleted.
(mark_set_regs, mark_set_1): Accept and use FLAGS.
Use alloc_EXPR_LIST.
(mark_used_regs): Accept and use FLAGS, not FINAL.
Remove special handling for RETURN.
(try_pre_increment): Use alloc_EXPR_LIST.
(dump_flow_info): Dump n_edges.
(unlink_insn_chain, split_hard_reg_notes): Remove.
(maybe_add_dead_note, maybe_add_dead_note_use): Remove.
(find_insn_with_note, new_insn_dead_notes): Remove.
(update_n_sets, sets_reg_or_subreg_1, sets_reg_or_subreg): Remove.
(maybe_remove_dead_notes, prepend_reg_notes): Remove.
(replace_insns): Remove.
(count_or_remove_death_notes): New.
(verify_flow_info): Abort on error after all checks.
(remove_edge): Decrement n_edges.
(remove_fake_edges): Tweek format.
* haifa-sched.c (schedule_insns): Use split_all_insns.
* output.h (update_life_info): Remove declaration.
* recog.c (split_all_insns): From the corpse of split_block_insns,
do the whole function block by block. Use update_life_info.
(recog_last_allowed_insn): New.
(recog_next_insn): Mind it.
(peephole2_optimize): Set it. Walk backwards through blocks.
Use update_life_info.
* rtl.h (update_flow_info, replace_insns): Remove declarations.
(split_all_insns): Declare.
* toplev.c (rest_of_compilation): Thread prologue before flow2.
Use split_all_insns.
* i386.md (or -1 peep2s): Disable.
From-SVN: r29877
1999-10-09 21:47:18 +02:00
|
|
|
|
blocks = sbitmap_alloc (n_basic_blocks);
|
|
|
|
|
sbitmap_zero (blocks);
|
|
|
|
|
changed = 0;
|
2000-05-27 22:23:15 +02:00
|
|
|
|
#else
|
|
|
|
|
count_or_remove_death_notes (NULL, 1);
|
|
|
|
|
#endif
|
Makefile.in (flow.o): Depend on TREE_H.
* Makefile.in (flow.o): Depend on TREE_H.
* basic-block.h (REG_SET_EQUAL_P): New.
(XOR_REG_SET): New.
(n_edges): Declare.
(free_regset_vector): Remove declaration.
(flow_delete_insn_chain): Declare.
(enum update_life_extent): New.
(update_life_info, count_or_remove_death_notes): Declare.
* combine.c (distribute_notes) [REG_DEAD]: Stop search at bb->head.
Verify register live at bb->global_live_at_start before adding USE.
* flow.c (HAVE_epilogue, HAVE_prologue): Provide default.
(CLEAN_ALLOCA): New.
(n_edges): New.
(PROP_*): New flags.
(find_basic_blocks_1): Use alloc_EXPR_LIST.
(clear_edges): Zero n_edges.
(make_edge): Increment n_edges.
(split_edge): Don't allocate bb->local_set. Increment n_edges.
(flow_delete_insn_chain): Export.
(delete_block): Decrement n_edges.
(merge_blocks_nomove): Likewise.
(life_analysis): Give life_analysis_1 PROP flags.
(verify_wide_reg_1, verify_wide_reg): New.
(verify_local_live_at_start): New.
(update_life_info): Rewrite to call into propogate_block.
(mark_reg): New.
(mark_regs_live_at_end): After reload, if epilogue as rtl,
always mark stack pointer. Conditionally mark PIC register.
After reload, mark call-saved registers, return regsiters.
(life_analysis_1): Accept PROP flags not remove_dead_code.
Call mark_regs_live_at_end before zeroing regs_ever_live.
Use calculate_global_regs_live. Copy global_live_at_end before
calling final propagate_block. Zero reg_next_use on exit.
(calculate_global_regs_live): New.
(allocate_bb_life_data): Don't allocate bb->local_set.
(init_regset_vector, free_regset_vector): Remove.
(propagate_block): Accept FLAGS not FINAL or REMOVE_DEAD_CODE.
Test flags before every operation. Warn if prologue/epilogue insn
would have been deleted.
(mark_set_regs, mark_set_1): Accept and use FLAGS.
Use alloc_EXPR_LIST.
(mark_used_regs): Accept and use FLAGS, not FINAL.
Remove special handling for RETURN.
(try_pre_increment): Use alloc_EXPR_LIST.
(dump_flow_info): Dump n_edges.
(unlink_insn_chain, split_hard_reg_notes): Remove.
(maybe_add_dead_note, maybe_add_dead_note_use): Remove.
(find_insn_with_note, new_insn_dead_notes): Remove.
(update_n_sets, sets_reg_or_subreg_1, sets_reg_or_subreg): Remove.
(maybe_remove_dead_notes, prepend_reg_notes): Remove.
(replace_insns): Remove.
(count_or_remove_death_notes): New.
(verify_flow_info): Abort on error after all checks.
(remove_edge): Decrement n_edges.
(remove_fake_edges): Tweek format.
* haifa-sched.c (schedule_insns): Use split_all_insns.
* output.h (update_life_info): Remove declaration.
* recog.c (split_all_insns): From the corpse of split_block_insns,
do the whole function block by block. Use update_life_info.
(recog_last_allowed_insn): New.
(recog_next_insn): Mind it.
(peephole2_optimize): Set it. Walk backwards through blocks.
Use update_life_info.
* rtl.h (update_flow_info, replace_insns): Remove declarations.
(split_all_insns): Declare.
* toplev.c (rest_of_compilation): Thread prologue before flow2.
Use split_all_insns.
* i386.md (or -1 peep2s): Disable.
From-SVN: r29877
1999-10-09 21:47:18 +02:00
|
|
|
|
|
2000-05-27 22:23:15 +02:00
|
|
|
|
for (b = n_basic_blocks - 1; b >= 0; --b)
|
1999-08-31 22:37:09 +02:00
|
|
|
|
{
|
2000-05-27 22:23:15 +02:00
|
|
|
|
basic_block bb = BASIC_BLOCK (b);
|
|
|
|
|
struct propagate_block_info *pbi;
|
|
|
|
|
|
|
|
|
|
/* Indicate that all slots except the last holds invalid data. */
|
|
|
|
|
for (i = 0; i < MAX_INSNS_PER_PEEP2; ++i)
|
|
|
|
|
peep2_insn_data[i].insn = NULL_RTX;
|
|
|
|
|
|
|
|
|
|
/* Indicate that the last slot contains live_after data. */
|
|
|
|
|
peep2_insn_data[MAX_INSNS_PER_PEEP2].insn = PEEP2_EOB;
|
|
|
|
|
peep2_current = MAX_INSNS_PER_PEEP2;
|
Makefile.in (flow.o): Depend on TREE_H.
* Makefile.in (flow.o): Depend on TREE_H.
* basic-block.h (REG_SET_EQUAL_P): New.
(XOR_REG_SET): New.
(n_edges): Declare.
(free_regset_vector): Remove declaration.
(flow_delete_insn_chain): Declare.
(enum update_life_extent): New.
(update_life_info, count_or_remove_death_notes): Declare.
* combine.c (distribute_notes) [REG_DEAD]: Stop search at bb->head.
Verify register live at bb->global_live_at_start before adding USE.
* flow.c (HAVE_epilogue, HAVE_prologue): Provide default.
(CLEAN_ALLOCA): New.
(n_edges): New.
(PROP_*): New flags.
(find_basic_blocks_1): Use alloc_EXPR_LIST.
(clear_edges): Zero n_edges.
(make_edge): Increment n_edges.
(split_edge): Don't allocate bb->local_set. Increment n_edges.
(flow_delete_insn_chain): Export.
(delete_block): Decrement n_edges.
(merge_blocks_nomove): Likewise.
(life_analysis): Give life_analysis_1 PROP flags.
(verify_wide_reg_1, verify_wide_reg): New.
(verify_local_live_at_start): New.
(update_life_info): Rewrite to call into propogate_block.
(mark_reg): New.
(mark_regs_live_at_end): After reload, if epilogue as rtl,
always mark stack pointer. Conditionally mark PIC register.
After reload, mark call-saved registers, return regsiters.
(life_analysis_1): Accept PROP flags not remove_dead_code.
Call mark_regs_live_at_end before zeroing regs_ever_live.
Use calculate_global_regs_live. Copy global_live_at_end before
calling final propagate_block. Zero reg_next_use on exit.
(calculate_global_regs_live): New.
(allocate_bb_life_data): Don't allocate bb->local_set.
(init_regset_vector, free_regset_vector): Remove.
(propagate_block): Accept FLAGS not FINAL or REMOVE_DEAD_CODE.
Test flags before every operation. Warn if prologue/epilogue insn
would have been deleted.
(mark_set_regs, mark_set_1): Accept and use FLAGS.
Use alloc_EXPR_LIST.
(mark_used_regs): Accept and use FLAGS, not FINAL.
Remove special handling for RETURN.
(try_pre_increment): Use alloc_EXPR_LIST.
(dump_flow_info): Dump n_edges.
(unlink_insn_chain, split_hard_reg_notes): Remove.
(maybe_add_dead_note, maybe_add_dead_note_use): Remove.
(find_insn_with_note, new_insn_dead_notes): Remove.
(update_n_sets, sets_reg_or_subreg_1, sets_reg_or_subreg): Remove.
(maybe_remove_dead_notes, prepend_reg_notes): Remove.
(replace_insns): Remove.
(count_or_remove_death_notes): New.
(verify_flow_info): Abort on error after all checks.
(remove_edge): Decrement n_edges.
(remove_fake_edges): Tweek format.
* haifa-sched.c (schedule_insns): Use split_all_insns.
* output.h (update_life_info): Remove declaration.
* recog.c (split_all_insns): From the corpse of split_block_insns,
do the whole function block by block. Use update_life_info.
(recog_last_allowed_insn): New.
(recog_next_insn): Mind it.
(peephole2_optimize): Set it. Walk backwards through blocks.
Use update_life_info.
* rtl.h (update_flow_info, replace_insns): Remove declarations.
(split_all_insns): Declare.
* toplev.c (rest_of_compilation): Thread prologue before flow2.
Use split_all_insns.
* i386.md (or -1 peep2s): Disable.
From-SVN: r29877
1999-10-09 21:47:18 +02:00
|
|
|
|
|
2000-05-27 22:23:15 +02:00
|
|
|
|
/* Start up propagation. */
|
|
|
|
|
COPY_REG_SET (live, bb->global_live_at_end);
|
|
|
|
|
COPY_REG_SET (peep2_insn_data[MAX_INSNS_PER_PEEP2].live_before, live);
|
|
|
|
|
|
|
|
|
|
#ifdef HAVE_conditional_execution
|
|
|
|
|
pbi = init_propagate_block_info (bb, live, NULL, 0);
|
|
|
|
|
#else
|
|
|
|
|
pbi = init_propagate_block_info (bb, live, NULL, PROP_DEATH_NOTES);
|
|
|
|
|
#endif
|
1999-08-31 22:37:09 +02:00
|
|
|
|
|
Makefile.in (flow.o): Depend on TREE_H.
* Makefile.in (flow.o): Depend on TREE_H.
* basic-block.h (REG_SET_EQUAL_P): New.
(XOR_REG_SET): New.
(n_edges): Declare.
(free_regset_vector): Remove declaration.
(flow_delete_insn_chain): Declare.
(enum update_life_extent): New.
(update_life_info, count_or_remove_death_notes): Declare.
* combine.c (distribute_notes) [REG_DEAD]: Stop search at bb->head.
Verify register live at bb->global_live_at_start before adding USE.
* flow.c (HAVE_epilogue, HAVE_prologue): Provide default.
(CLEAN_ALLOCA): New.
(n_edges): New.
(PROP_*): New flags.
(find_basic_blocks_1): Use alloc_EXPR_LIST.
(clear_edges): Zero n_edges.
(make_edge): Increment n_edges.
(split_edge): Don't allocate bb->local_set. Increment n_edges.
(flow_delete_insn_chain): Export.
(delete_block): Decrement n_edges.
(merge_blocks_nomove): Likewise.
(life_analysis): Give life_analysis_1 PROP flags.
(verify_wide_reg_1, verify_wide_reg): New.
(verify_local_live_at_start): New.
(update_life_info): Rewrite to call into propogate_block.
(mark_reg): New.
(mark_regs_live_at_end): After reload, if epilogue as rtl,
always mark stack pointer. Conditionally mark PIC register.
After reload, mark call-saved registers, return regsiters.
(life_analysis_1): Accept PROP flags not remove_dead_code.
Call mark_regs_live_at_end before zeroing regs_ever_live.
Use calculate_global_regs_live. Copy global_live_at_end before
calling final propagate_block. Zero reg_next_use on exit.
(calculate_global_regs_live): New.
(allocate_bb_life_data): Don't allocate bb->local_set.
(init_regset_vector, free_regset_vector): Remove.
(propagate_block): Accept FLAGS not FINAL or REMOVE_DEAD_CODE.
Test flags before every operation. Warn if prologue/epilogue insn
would have been deleted.
(mark_set_regs, mark_set_1): Accept and use FLAGS.
Use alloc_EXPR_LIST.
(mark_used_regs): Accept and use FLAGS, not FINAL.
Remove special handling for RETURN.
(try_pre_increment): Use alloc_EXPR_LIST.
(dump_flow_info): Dump n_edges.
(unlink_insn_chain, split_hard_reg_notes): Remove.
(maybe_add_dead_note, maybe_add_dead_note_use): Remove.
(find_insn_with_note, new_insn_dead_notes): Remove.
(update_n_sets, sets_reg_or_subreg_1, sets_reg_or_subreg): Remove.
(maybe_remove_dead_notes, prepend_reg_notes): Remove.
(replace_insns): Remove.
(count_or_remove_death_notes): New.
(verify_flow_info): Abort on error after all checks.
(remove_edge): Decrement n_edges.
(remove_fake_edges): Tweek format.
* haifa-sched.c (schedule_insns): Use split_all_insns.
* output.h (update_life_info): Remove declaration.
* recog.c (split_all_insns): From the corpse of split_block_insns,
do the whole function block by block. Use update_life_info.
(recog_last_allowed_insn): New.
(recog_next_insn): Mind it.
(peephole2_optimize): Set it. Walk backwards through blocks.
Use update_life_info.
* rtl.h (update_flow_info, replace_insns): Remove declarations.
(split_all_insns): Declare.
* toplev.c (rest_of_compilation): Thread prologue before flow2.
Use split_all_insns.
* i386.md (or -1 peep2s): Disable.
From-SVN: r29877
1999-10-09 21:47:18 +02:00
|
|
|
|
for (insn = bb->end; ; insn = prev)
|
|
|
|
|
{
|
|
|
|
|
prev = PREV_INSN (insn);
|
2000-05-26 01:59:45 +02:00
|
|
|
|
if (INSN_P (insn))
|
1999-08-31 22:37:09 +02:00
|
|
|
|
{
|
2000-05-27 22:23:15 +02:00
|
|
|
|
rtx try;
|
|
|
|
|
int match_len;
|
|
|
|
|
|
|
|
|
|
/* Record this insn. */
|
|
|
|
|
if (--peep2_current < 0)
|
|
|
|
|
peep2_current = MAX_INSNS_PER_PEEP2;
|
|
|
|
|
peep2_insn_data[peep2_current].insn = insn;
|
|
|
|
|
propagate_one_insn (pbi, insn);
|
|
|
|
|
COPY_REG_SET (peep2_insn_data[peep2_current].live_before, live);
|
|
|
|
|
|
|
|
|
|
/* Match the peephole. */
|
|
|
|
|
try = peephole2_insns (PATTERN (insn), insn, &match_len);
|
Makefile.in (flow.o): Depend on TREE_H.
* Makefile.in (flow.o): Depend on TREE_H.
* basic-block.h (REG_SET_EQUAL_P): New.
(XOR_REG_SET): New.
(n_edges): Declare.
(free_regset_vector): Remove declaration.
(flow_delete_insn_chain): Declare.
(enum update_life_extent): New.
(update_life_info, count_or_remove_death_notes): Declare.
* combine.c (distribute_notes) [REG_DEAD]: Stop search at bb->head.
Verify register live at bb->global_live_at_start before adding USE.
* flow.c (HAVE_epilogue, HAVE_prologue): Provide default.
(CLEAN_ALLOCA): New.
(n_edges): New.
(PROP_*): New flags.
(find_basic_blocks_1): Use alloc_EXPR_LIST.
(clear_edges): Zero n_edges.
(make_edge): Increment n_edges.
(split_edge): Don't allocate bb->local_set. Increment n_edges.
(flow_delete_insn_chain): Export.
(delete_block): Decrement n_edges.
(merge_blocks_nomove): Likewise.
(life_analysis): Give life_analysis_1 PROP flags.
(verify_wide_reg_1, verify_wide_reg): New.
(verify_local_live_at_start): New.
(update_life_info): Rewrite to call into propogate_block.
(mark_reg): New.
(mark_regs_live_at_end): After reload, if epilogue as rtl,
always mark stack pointer. Conditionally mark PIC register.
After reload, mark call-saved registers, return regsiters.
(life_analysis_1): Accept PROP flags not remove_dead_code.
Call mark_regs_live_at_end before zeroing regs_ever_live.
Use calculate_global_regs_live. Copy global_live_at_end before
calling final propagate_block. Zero reg_next_use on exit.
(calculate_global_regs_live): New.
(allocate_bb_life_data): Don't allocate bb->local_set.
(init_regset_vector, free_regset_vector): Remove.
(propagate_block): Accept FLAGS not FINAL or REMOVE_DEAD_CODE.
Test flags before every operation. Warn if prologue/epilogue insn
would have been deleted.
(mark_set_regs, mark_set_1): Accept and use FLAGS.
Use alloc_EXPR_LIST.
(mark_used_regs): Accept and use FLAGS, not FINAL.
Remove special handling for RETURN.
(try_pre_increment): Use alloc_EXPR_LIST.
(dump_flow_info): Dump n_edges.
(unlink_insn_chain, split_hard_reg_notes): Remove.
(maybe_add_dead_note, maybe_add_dead_note_use): Remove.
(find_insn_with_note, new_insn_dead_notes): Remove.
(update_n_sets, sets_reg_or_subreg_1, sets_reg_or_subreg): Remove.
(maybe_remove_dead_notes, prepend_reg_notes): Remove.
(replace_insns): Remove.
(count_or_remove_death_notes): New.
(verify_flow_info): Abort on error after all checks.
(remove_edge): Decrement n_edges.
(remove_fake_edges): Tweek format.
* haifa-sched.c (schedule_insns): Use split_all_insns.
* output.h (update_life_info): Remove declaration.
* recog.c (split_all_insns): From the corpse of split_block_insns,
do the whole function block by block. Use update_life_info.
(recog_last_allowed_insn): New.
(recog_next_insn): Mind it.
(peephole2_optimize): Set it. Walk backwards through blocks.
Use update_life_info.
* rtl.h (update_flow_info, replace_insns): Remove declarations.
(split_all_insns): Declare.
* toplev.c (rest_of_compilation): Thread prologue before flow2.
Use split_all_insns.
* i386.md (or -1 peep2s): Disable.
From-SVN: r29877
1999-10-09 21:47:18 +02:00
|
|
|
|
if (try != NULL)
|
|
|
|
|
{
|
2000-05-27 22:23:15 +02:00
|
|
|
|
i = match_len + peep2_current;
|
|
|
|
|
if (i >= MAX_INSNS_PER_PEEP2 + 1)
|
|
|
|
|
i -= MAX_INSNS_PER_PEEP2 + 1;
|
|
|
|
|
|
|
|
|
|
/* Replace the old sequence with the new. */
|
|
|
|
|
flow_delete_insn_chain (insn, peep2_insn_data[i].insn);
|
Makefile.in (flow.o): Depend on TREE_H.
* Makefile.in (flow.o): Depend on TREE_H.
* basic-block.h (REG_SET_EQUAL_P): New.
(XOR_REG_SET): New.
(n_edges): Declare.
(free_regset_vector): Remove declaration.
(flow_delete_insn_chain): Declare.
(enum update_life_extent): New.
(update_life_info, count_or_remove_death_notes): Declare.
* combine.c (distribute_notes) [REG_DEAD]: Stop search at bb->head.
Verify register live at bb->global_live_at_start before adding USE.
* flow.c (HAVE_epilogue, HAVE_prologue): Provide default.
(CLEAN_ALLOCA): New.
(n_edges): New.
(PROP_*): New flags.
(find_basic_blocks_1): Use alloc_EXPR_LIST.
(clear_edges): Zero n_edges.
(make_edge): Increment n_edges.
(split_edge): Don't allocate bb->local_set. Increment n_edges.
(flow_delete_insn_chain): Export.
(delete_block): Decrement n_edges.
(merge_blocks_nomove): Likewise.
(life_analysis): Give life_analysis_1 PROP flags.
(verify_wide_reg_1, verify_wide_reg): New.
(verify_local_live_at_start): New.
(update_life_info): Rewrite to call into propogate_block.
(mark_reg): New.
(mark_regs_live_at_end): After reload, if epilogue as rtl,
always mark stack pointer. Conditionally mark PIC register.
After reload, mark call-saved registers, return regsiters.
(life_analysis_1): Accept PROP flags not remove_dead_code.
Call mark_regs_live_at_end before zeroing regs_ever_live.
Use calculate_global_regs_live. Copy global_live_at_end before
calling final propagate_block. Zero reg_next_use on exit.
(calculate_global_regs_live): New.
(allocate_bb_life_data): Don't allocate bb->local_set.
(init_regset_vector, free_regset_vector): Remove.
(propagate_block): Accept FLAGS not FINAL or REMOVE_DEAD_CODE.
Test flags before every operation. Warn if prologue/epilogue insn
would have been deleted.
(mark_set_regs, mark_set_1): Accept and use FLAGS.
Use alloc_EXPR_LIST.
(mark_used_regs): Accept and use FLAGS, not FINAL.
Remove special handling for RETURN.
(try_pre_increment): Use alloc_EXPR_LIST.
(dump_flow_info): Dump n_edges.
(unlink_insn_chain, split_hard_reg_notes): Remove.
(maybe_add_dead_note, maybe_add_dead_note_use): Remove.
(find_insn_with_note, new_insn_dead_notes): Remove.
(update_n_sets, sets_reg_or_subreg_1, sets_reg_or_subreg): Remove.
(maybe_remove_dead_notes, prepend_reg_notes): Remove.
(replace_insns): Remove.
(count_or_remove_death_notes): New.
(verify_flow_info): Abort on error after all checks.
(remove_edge): Decrement n_edges.
(remove_fake_edges): Tweek format.
* haifa-sched.c (schedule_insns): Use split_all_insns.
* output.h (update_life_info): Remove declaration.
* recog.c (split_all_insns): From the corpse of split_block_insns,
do the whole function block by block. Use update_life_info.
(recog_last_allowed_insn): New.
(recog_next_insn): Mind it.
(peephole2_optimize): Set it. Walk backwards through blocks.
Use update_life_info.
* rtl.h (update_flow_info, replace_insns): Remove declarations.
(split_all_insns): Declare.
* toplev.c (rest_of_compilation): Thread prologue before flow2.
Use split_all_insns.
* i386.md (or -1 peep2s): Disable.
From-SVN: r29877
1999-10-09 21:47:18 +02:00
|
|
|
|
try = emit_insn_after (try, prev);
|
|
|
|
|
|
2000-05-27 22:23:15 +02:00
|
|
|
|
/* Adjust the basic block boundaries. */
|
|
|
|
|
if (peep2_insn_data[i].insn == bb->end)
|
Makefile.in (flow.o): Depend on TREE_H.
* Makefile.in (flow.o): Depend on TREE_H.
* basic-block.h (REG_SET_EQUAL_P): New.
(XOR_REG_SET): New.
(n_edges): Declare.
(free_regset_vector): Remove declaration.
(flow_delete_insn_chain): Declare.
(enum update_life_extent): New.
(update_life_info, count_or_remove_death_notes): Declare.
* combine.c (distribute_notes) [REG_DEAD]: Stop search at bb->head.
Verify register live at bb->global_live_at_start before adding USE.
* flow.c (HAVE_epilogue, HAVE_prologue): Provide default.
(CLEAN_ALLOCA): New.
(n_edges): New.
(PROP_*): New flags.
(find_basic_blocks_1): Use alloc_EXPR_LIST.
(clear_edges): Zero n_edges.
(make_edge): Increment n_edges.
(split_edge): Don't allocate bb->local_set. Increment n_edges.
(flow_delete_insn_chain): Export.
(delete_block): Decrement n_edges.
(merge_blocks_nomove): Likewise.
(life_analysis): Give life_analysis_1 PROP flags.
(verify_wide_reg_1, verify_wide_reg): New.
(verify_local_live_at_start): New.
(update_life_info): Rewrite to call into propogate_block.
(mark_reg): New.
(mark_regs_live_at_end): After reload, if epilogue as rtl,
always mark stack pointer. Conditionally mark PIC register.
After reload, mark call-saved registers, return regsiters.
(life_analysis_1): Accept PROP flags not remove_dead_code.
Call mark_regs_live_at_end before zeroing regs_ever_live.
Use calculate_global_regs_live. Copy global_live_at_end before
calling final propagate_block. Zero reg_next_use on exit.
(calculate_global_regs_live): New.
(allocate_bb_life_data): Don't allocate bb->local_set.
(init_regset_vector, free_regset_vector): Remove.
(propagate_block): Accept FLAGS not FINAL or REMOVE_DEAD_CODE.
Test flags before every operation. Warn if prologue/epilogue insn
would have been deleted.
(mark_set_regs, mark_set_1): Accept and use FLAGS.
Use alloc_EXPR_LIST.
(mark_used_regs): Accept and use FLAGS, not FINAL.
Remove special handling for RETURN.
(try_pre_increment): Use alloc_EXPR_LIST.
(dump_flow_info): Dump n_edges.
(unlink_insn_chain, split_hard_reg_notes): Remove.
(maybe_add_dead_note, maybe_add_dead_note_use): Remove.
(find_insn_with_note, new_insn_dead_notes): Remove.
(update_n_sets, sets_reg_or_subreg_1, sets_reg_or_subreg): Remove.
(maybe_remove_dead_notes, prepend_reg_notes): Remove.
(replace_insns): Remove.
(count_or_remove_death_notes): New.
(verify_flow_info): Abort on error after all checks.
(remove_edge): Decrement n_edges.
(remove_fake_edges): Tweek format.
* haifa-sched.c (schedule_insns): Use split_all_insns.
* output.h (update_life_info): Remove declaration.
* recog.c (split_all_insns): From the corpse of split_block_insns,
do the whole function block by block. Use update_life_info.
(recog_last_allowed_insn): New.
(recog_next_insn): Mind it.
(peephole2_optimize): Set it. Walk backwards through blocks.
Use update_life_info.
* rtl.h (update_flow_info, replace_insns): Remove declarations.
(split_all_insns): Declare.
* toplev.c (rest_of_compilation): Thread prologue before flow2.
Use split_all_insns.
* i386.md (or -1 peep2s): Disable.
From-SVN: r29877
1999-10-09 21:47:18 +02:00
|
|
|
|
bb->end = try;
|
|
|
|
|
if (insn == bb->head)
|
|
|
|
|
bb->head = NEXT_INSN (prev);
|
|
|
|
|
|
2000-05-27 22:23:15 +02:00
|
|
|
|
#ifdef HAVE_conditional_execution
|
|
|
|
|
/* With conditional execution, we cannot back up the
|
|
|
|
|
live information so easily, since the conditional
|
|
|
|
|
death data structures are not so self-contained.
|
|
|
|
|
So record that we've made a modification to this
|
|
|
|
|
block and update life information at the end. */
|
|
|
|
|
SET_BIT (blocks, b);
|
Makefile.in (flow.o): Depend on TREE_H.
* Makefile.in (flow.o): Depend on TREE_H.
* basic-block.h (REG_SET_EQUAL_P): New.
(XOR_REG_SET): New.
(n_edges): Declare.
(free_regset_vector): Remove declaration.
(flow_delete_insn_chain): Declare.
(enum update_life_extent): New.
(update_life_info, count_or_remove_death_notes): Declare.
* combine.c (distribute_notes) [REG_DEAD]: Stop search at bb->head.
Verify register live at bb->global_live_at_start before adding USE.
* flow.c (HAVE_epilogue, HAVE_prologue): Provide default.
(CLEAN_ALLOCA): New.
(n_edges): New.
(PROP_*): New flags.
(find_basic_blocks_1): Use alloc_EXPR_LIST.
(clear_edges): Zero n_edges.
(make_edge): Increment n_edges.
(split_edge): Don't allocate bb->local_set. Increment n_edges.
(flow_delete_insn_chain): Export.
(delete_block): Decrement n_edges.
(merge_blocks_nomove): Likewise.
(life_analysis): Give life_analysis_1 PROP flags.
(verify_wide_reg_1, verify_wide_reg): New.
(verify_local_live_at_start): New.
(update_life_info): Rewrite to call into propogate_block.
(mark_reg): New.
(mark_regs_live_at_end): After reload, if epilogue as rtl,
always mark stack pointer. Conditionally mark PIC register.
After reload, mark call-saved registers, return regsiters.
(life_analysis_1): Accept PROP flags not remove_dead_code.
Call mark_regs_live_at_end before zeroing regs_ever_live.
Use calculate_global_regs_live. Copy global_live_at_end before
calling final propagate_block. Zero reg_next_use on exit.
(calculate_global_regs_live): New.
(allocate_bb_life_data): Don't allocate bb->local_set.
(init_regset_vector, free_regset_vector): Remove.
(propagate_block): Accept FLAGS not FINAL or REMOVE_DEAD_CODE.
Test flags before every operation. Warn if prologue/epilogue insn
would have been deleted.
(mark_set_regs, mark_set_1): Accept and use FLAGS.
Use alloc_EXPR_LIST.
(mark_used_regs): Accept and use FLAGS, not FINAL.
Remove special handling for RETURN.
(try_pre_increment): Use alloc_EXPR_LIST.
(dump_flow_info): Dump n_edges.
(unlink_insn_chain, split_hard_reg_notes): Remove.
(maybe_add_dead_note, maybe_add_dead_note_use): Remove.
(find_insn_with_note, new_insn_dead_notes): Remove.
(update_n_sets, sets_reg_or_subreg_1, sets_reg_or_subreg): Remove.
(maybe_remove_dead_notes, prepend_reg_notes): Remove.
(replace_insns): Remove.
(count_or_remove_death_notes): New.
(verify_flow_info): Abort on error after all checks.
(remove_edge): Decrement n_edges.
(remove_fake_edges): Tweek format.
* haifa-sched.c (schedule_insns): Use split_all_insns.
* output.h (update_life_info): Remove declaration.
* recog.c (split_all_insns): From the corpse of split_block_insns,
do the whole function block by block. Use update_life_info.
(recog_last_allowed_insn): New.
(recog_next_insn): Mind it.
(peephole2_optimize): Set it. Walk backwards through blocks.
Use update_life_info.
* rtl.h (update_flow_info, replace_insns): Remove declarations.
(split_all_insns): Declare.
* toplev.c (rest_of_compilation): Thread prologue before flow2.
Use split_all_insns.
* i386.md (or -1 peep2s): Disable.
From-SVN: r29877
1999-10-09 21:47:18 +02:00
|
|
|
|
changed = 1;
|
2000-05-27 22:23:15 +02:00
|
|
|
|
|
|
|
|
|
for (i = 0; i < MAX_INSNS_PER_PEEP2 + 1; ++i)
|
|
|
|
|
peep2_insn_data[i].insn = NULL_RTX;
|
|
|
|
|
peep2_insn_data[peep2_current].insn = PEEP2_EOB;
|
|
|
|
|
#else
|
|
|
|
|
/* Back up lifetime information past the end of the
|
|
|
|
|
newly created sequence. */
|
|
|
|
|
if (++i >= MAX_INSNS_PER_PEEP2 + 1)
|
|
|
|
|
i = 0;
|
|
|
|
|
COPY_REG_SET (live, peep2_insn_data[i].live_before);
|
|
|
|
|
|
|
|
|
|
/* Update life information for the new sequence. */
|
|
|
|
|
do
|
|
|
|
|
{
|
|
|
|
|
if (INSN_P (try))
|
|
|
|
|
{
|
|
|
|
|
if (--i < 0)
|
|
|
|
|
i = MAX_INSNS_PER_PEEP2;
|
|
|
|
|
peep2_insn_data[i].insn = try;
|
|
|
|
|
propagate_one_insn (pbi, try);
|
|
|
|
|
COPY_REG_SET (peep2_insn_data[i].live_before, live);
|
|
|
|
|
}
|
|
|
|
|
try = PREV_INSN (try);
|
|
|
|
|
}
|
|
|
|
|
while (try != prev);
|
|
|
|
|
|
|
|
|
|
/* ??? Should verify that LIVE now matches what we
|
|
|
|
|
had before the new sequence. */
|
|
|
|
|
|
|
|
|
|
peep2_current = i;
|
|
|
|
|
#endif
|
Makefile.in (flow.o): Depend on TREE_H.
* Makefile.in (flow.o): Depend on TREE_H.
* basic-block.h (REG_SET_EQUAL_P): New.
(XOR_REG_SET): New.
(n_edges): Declare.
(free_regset_vector): Remove declaration.
(flow_delete_insn_chain): Declare.
(enum update_life_extent): New.
(update_life_info, count_or_remove_death_notes): Declare.
* combine.c (distribute_notes) [REG_DEAD]: Stop search at bb->head.
Verify register live at bb->global_live_at_start before adding USE.
* flow.c (HAVE_epilogue, HAVE_prologue): Provide default.
(CLEAN_ALLOCA): New.
(n_edges): New.
(PROP_*): New flags.
(find_basic_blocks_1): Use alloc_EXPR_LIST.
(clear_edges): Zero n_edges.
(make_edge): Increment n_edges.
(split_edge): Don't allocate bb->local_set. Increment n_edges.
(flow_delete_insn_chain): Export.
(delete_block): Decrement n_edges.
(merge_blocks_nomove): Likewise.
(life_analysis): Give life_analysis_1 PROP flags.
(verify_wide_reg_1, verify_wide_reg): New.
(verify_local_live_at_start): New.
(update_life_info): Rewrite to call into propogate_block.
(mark_reg): New.
(mark_regs_live_at_end): After reload, if epilogue as rtl,
always mark stack pointer. Conditionally mark PIC register.
After reload, mark call-saved registers, return regsiters.
(life_analysis_1): Accept PROP flags not remove_dead_code.
Call mark_regs_live_at_end before zeroing regs_ever_live.
Use calculate_global_regs_live. Copy global_live_at_end before
calling final propagate_block. Zero reg_next_use on exit.
(calculate_global_regs_live): New.
(allocate_bb_life_data): Don't allocate bb->local_set.
(init_regset_vector, free_regset_vector): Remove.
(propagate_block): Accept FLAGS not FINAL or REMOVE_DEAD_CODE.
Test flags before every operation. Warn if prologue/epilogue insn
would have been deleted.
(mark_set_regs, mark_set_1): Accept and use FLAGS.
Use alloc_EXPR_LIST.
(mark_used_regs): Accept and use FLAGS, not FINAL.
Remove special handling for RETURN.
(try_pre_increment): Use alloc_EXPR_LIST.
(dump_flow_info): Dump n_edges.
(unlink_insn_chain, split_hard_reg_notes): Remove.
(maybe_add_dead_note, maybe_add_dead_note_use): Remove.
(find_insn_with_note, new_insn_dead_notes): Remove.
(update_n_sets, sets_reg_or_subreg_1, sets_reg_or_subreg): Remove.
(maybe_remove_dead_notes, prepend_reg_notes): Remove.
(replace_insns): Remove.
(count_or_remove_death_notes): New.
(verify_flow_info): Abort on error after all checks.
(remove_edge): Decrement n_edges.
(remove_fake_edges): Tweek format.
* haifa-sched.c (schedule_insns): Use split_all_insns.
* output.h (update_life_info): Remove declaration.
* recog.c (split_all_insns): From the corpse of split_block_insns,
do the whole function block by block. Use update_life_info.
(recog_last_allowed_insn): New.
(recog_next_insn): Mind it.
(peephole2_optimize): Set it. Walk backwards through blocks.
Use update_life_info.
* rtl.h (update_flow_info, replace_insns): Remove declarations.
(split_all_insns): Declare.
* toplev.c (rest_of_compilation): Thread prologue before flow2.
Use split_all_insns.
* i386.md (or -1 peep2s): Disable.
From-SVN: r29877
1999-10-09 21:47:18 +02:00
|
|
|
|
}
|
1999-08-31 22:37:09 +02:00
|
|
|
|
}
|
Makefile.in (flow.o): Depend on TREE_H.
* Makefile.in (flow.o): Depend on TREE_H.
* basic-block.h (REG_SET_EQUAL_P): New.
(XOR_REG_SET): New.
(n_edges): Declare.
(free_regset_vector): Remove declaration.
(flow_delete_insn_chain): Declare.
(enum update_life_extent): New.
(update_life_info, count_or_remove_death_notes): Declare.
* combine.c (distribute_notes) [REG_DEAD]: Stop search at bb->head.
Verify register live at bb->global_live_at_start before adding USE.
* flow.c (HAVE_epilogue, HAVE_prologue): Provide default.
(CLEAN_ALLOCA): New.
(n_edges): New.
(PROP_*): New flags.
(find_basic_blocks_1): Use alloc_EXPR_LIST.
(clear_edges): Zero n_edges.
(make_edge): Increment n_edges.
(split_edge): Don't allocate bb->local_set. Increment n_edges.
(flow_delete_insn_chain): Export.
(delete_block): Decrement n_edges.
(merge_blocks_nomove): Likewise.
(life_analysis): Give life_analysis_1 PROP flags.
(verify_wide_reg_1, verify_wide_reg): New.
(verify_local_live_at_start): New.
(update_life_info): Rewrite to call into propogate_block.
(mark_reg): New.
(mark_regs_live_at_end): After reload, if epilogue as rtl,
always mark stack pointer. Conditionally mark PIC register.
After reload, mark call-saved registers, return regsiters.
(life_analysis_1): Accept PROP flags not remove_dead_code.
Call mark_regs_live_at_end before zeroing regs_ever_live.
Use calculate_global_regs_live. Copy global_live_at_end before
calling final propagate_block. Zero reg_next_use on exit.
(calculate_global_regs_live): New.
(allocate_bb_life_data): Don't allocate bb->local_set.
(init_regset_vector, free_regset_vector): Remove.
(propagate_block): Accept FLAGS not FINAL or REMOVE_DEAD_CODE.
Test flags before every operation. Warn if prologue/epilogue insn
would have been deleted.
(mark_set_regs, mark_set_1): Accept and use FLAGS.
Use alloc_EXPR_LIST.
(mark_used_regs): Accept and use FLAGS, not FINAL.
Remove special handling for RETURN.
(try_pre_increment): Use alloc_EXPR_LIST.
(dump_flow_info): Dump n_edges.
(unlink_insn_chain, split_hard_reg_notes): Remove.
(maybe_add_dead_note, maybe_add_dead_note_use): Remove.
(find_insn_with_note, new_insn_dead_notes): Remove.
(update_n_sets, sets_reg_or_subreg_1, sets_reg_or_subreg): Remove.
(maybe_remove_dead_notes, prepend_reg_notes): Remove.
(replace_insns): Remove.
(count_or_remove_death_notes): New.
(verify_flow_info): Abort on error after all checks.
(remove_edge): Decrement n_edges.
(remove_fake_edges): Tweek format.
* haifa-sched.c (schedule_insns): Use split_all_insns.
* output.h (update_life_info): Remove declaration.
* recog.c (split_all_insns): From the corpse of split_block_insns,
do the whole function block by block. Use update_life_info.
(recog_last_allowed_insn): New.
(recog_next_insn): Mind it.
(peephole2_optimize): Set it. Walk backwards through blocks.
Use update_life_info.
* rtl.h (update_flow_info, replace_insns): Remove declarations.
(split_all_insns): Declare.
* toplev.c (rest_of_compilation): Thread prologue before flow2.
Use split_all_insns.
* i386.md (or -1 peep2s): Disable.
From-SVN: r29877
1999-10-09 21:47:18 +02:00
|
|
|
|
|
|
|
|
|
if (insn == bb->head)
|
|
|
|
|
break;
|
1999-08-31 22:37:09 +02:00
|
|
|
|
}
|
2000-05-27 22:23:15 +02:00
|
|
|
|
|
|
|
|
|
free_propagate_block_info (pbi);
|
1999-08-31 22:37:09 +02:00
|
|
|
|
}
|
|
|
|
|
|
2000-05-27 22:23:15 +02:00
|
|
|
|
for (i = 0; i < MAX_INSNS_PER_PEEP2 + 1; ++i)
|
|
|
|
|
FREE_REG_SET (peep2_insn_data[i].live_before);
|
|
|
|
|
FREE_REG_SET (live);
|
Makefile.in (flow.o): Depend on TREE_H.
* Makefile.in (flow.o): Depend on TREE_H.
* basic-block.h (REG_SET_EQUAL_P): New.
(XOR_REG_SET): New.
(n_edges): Declare.
(free_regset_vector): Remove declaration.
(flow_delete_insn_chain): Declare.
(enum update_life_extent): New.
(update_life_info, count_or_remove_death_notes): Declare.
* combine.c (distribute_notes) [REG_DEAD]: Stop search at bb->head.
Verify register live at bb->global_live_at_start before adding USE.
* flow.c (HAVE_epilogue, HAVE_prologue): Provide default.
(CLEAN_ALLOCA): New.
(n_edges): New.
(PROP_*): New flags.
(find_basic_blocks_1): Use alloc_EXPR_LIST.
(clear_edges): Zero n_edges.
(make_edge): Increment n_edges.
(split_edge): Don't allocate bb->local_set. Increment n_edges.
(flow_delete_insn_chain): Export.
(delete_block): Decrement n_edges.
(merge_blocks_nomove): Likewise.
(life_analysis): Give life_analysis_1 PROP flags.
(verify_wide_reg_1, verify_wide_reg): New.
(verify_local_live_at_start): New.
(update_life_info): Rewrite to call into propogate_block.
(mark_reg): New.
(mark_regs_live_at_end): After reload, if epilogue as rtl,
always mark stack pointer. Conditionally mark PIC register.
After reload, mark call-saved registers, return regsiters.
(life_analysis_1): Accept PROP flags not remove_dead_code.
Call mark_regs_live_at_end before zeroing regs_ever_live.
Use calculate_global_regs_live. Copy global_live_at_end before
calling final propagate_block. Zero reg_next_use on exit.
(calculate_global_regs_live): New.
(allocate_bb_life_data): Don't allocate bb->local_set.
(init_regset_vector, free_regset_vector): Remove.
(propagate_block): Accept FLAGS not FINAL or REMOVE_DEAD_CODE.
Test flags before every operation. Warn if prologue/epilogue insn
would have been deleted.
(mark_set_regs, mark_set_1): Accept and use FLAGS.
Use alloc_EXPR_LIST.
(mark_used_regs): Accept and use FLAGS, not FINAL.
Remove special handling for RETURN.
(try_pre_increment): Use alloc_EXPR_LIST.
(dump_flow_info): Dump n_edges.
(unlink_insn_chain, split_hard_reg_notes): Remove.
(maybe_add_dead_note, maybe_add_dead_note_use): Remove.
(find_insn_with_note, new_insn_dead_notes): Remove.
(update_n_sets, sets_reg_or_subreg_1, sets_reg_or_subreg): Remove.
(maybe_remove_dead_notes, prepend_reg_notes): Remove.
(replace_insns): Remove.
(count_or_remove_death_notes): New.
(verify_flow_info): Abort on error after all checks.
(remove_edge): Decrement n_edges.
(remove_fake_edges): Tweek format.
* haifa-sched.c (schedule_insns): Use split_all_insns.
* output.h (update_life_info): Remove declaration.
* recog.c (split_all_insns): From the corpse of split_block_insns,
do the whole function block by block. Use update_life_info.
(recog_last_allowed_insn): New.
(recog_next_insn): Mind it.
(peephole2_optimize): Set it. Walk backwards through blocks.
Use update_life_info.
* rtl.h (update_flow_info, replace_insns): Remove declarations.
(split_all_insns): Declare.
* toplev.c (rest_of_compilation): Thread prologue before flow2.
Use split_all_insns.
* i386.md (or -1 peep2s): Disable.
From-SVN: r29877
1999-10-09 21:47:18 +02:00
|
|
|
|
|
2000-05-27 22:23:15 +02:00
|
|
|
|
#ifdef HAVE_conditional_execution
|
Makefile.in (flow.o): Depend on TREE_H.
* Makefile.in (flow.o): Depend on TREE_H.
* basic-block.h (REG_SET_EQUAL_P): New.
(XOR_REG_SET): New.
(n_edges): Declare.
(free_regset_vector): Remove declaration.
(flow_delete_insn_chain): Declare.
(enum update_life_extent): New.
(update_life_info, count_or_remove_death_notes): Declare.
* combine.c (distribute_notes) [REG_DEAD]: Stop search at bb->head.
Verify register live at bb->global_live_at_start before adding USE.
* flow.c (HAVE_epilogue, HAVE_prologue): Provide default.
(CLEAN_ALLOCA): New.
(n_edges): New.
(PROP_*): New flags.
(find_basic_blocks_1): Use alloc_EXPR_LIST.
(clear_edges): Zero n_edges.
(make_edge): Increment n_edges.
(split_edge): Don't allocate bb->local_set. Increment n_edges.
(flow_delete_insn_chain): Export.
(delete_block): Decrement n_edges.
(merge_blocks_nomove): Likewise.
(life_analysis): Give life_analysis_1 PROP flags.
(verify_wide_reg_1, verify_wide_reg): New.
(verify_local_live_at_start): New.
(update_life_info): Rewrite to call into propogate_block.
(mark_reg): New.
(mark_regs_live_at_end): After reload, if epilogue as rtl,
always mark stack pointer. Conditionally mark PIC register.
After reload, mark call-saved registers, return regsiters.
(life_analysis_1): Accept PROP flags not remove_dead_code.
Call mark_regs_live_at_end before zeroing regs_ever_live.
Use calculate_global_regs_live. Copy global_live_at_end before
calling final propagate_block. Zero reg_next_use on exit.
(calculate_global_regs_live): New.
(allocate_bb_life_data): Don't allocate bb->local_set.
(init_regset_vector, free_regset_vector): Remove.
(propagate_block): Accept FLAGS not FINAL or REMOVE_DEAD_CODE.
Test flags before every operation. Warn if prologue/epilogue insn
would have been deleted.
(mark_set_regs, mark_set_1): Accept and use FLAGS.
Use alloc_EXPR_LIST.
(mark_used_regs): Accept and use FLAGS, not FINAL.
Remove special handling for RETURN.
(try_pre_increment): Use alloc_EXPR_LIST.
(dump_flow_info): Dump n_edges.
(unlink_insn_chain, split_hard_reg_notes): Remove.
(maybe_add_dead_note, maybe_add_dead_note_use): Remove.
(find_insn_with_note, new_insn_dead_notes): Remove.
(update_n_sets, sets_reg_or_subreg_1, sets_reg_or_subreg): Remove.
(maybe_remove_dead_notes, prepend_reg_notes): Remove.
(replace_insns): Remove.
(count_or_remove_death_notes): New.
(verify_flow_info): Abort on error after all checks.
(remove_edge): Decrement n_edges.
(remove_fake_edges): Tweek format.
* haifa-sched.c (schedule_insns): Use split_all_insns.
* output.h (update_life_info): Remove declaration.
* recog.c (split_all_insns): From the corpse of split_block_insns,
do the whole function block by block. Use update_life_info.
(recog_last_allowed_insn): New.
(recog_next_insn): Mind it.
(peephole2_optimize): Set it. Walk backwards through blocks.
Use update_life_info.
* rtl.h (update_flow_info, replace_insns): Remove declarations.
(split_all_insns): Declare.
* toplev.c (rest_of_compilation): Thread prologue before flow2.
Use split_all_insns.
* i386.md (or -1 peep2s): Disable.
From-SVN: r29877
1999-10-09 21:47:18 +02:00
|
|
|
|
count_or_remove_death_notes (blocks, 1);
|
1999-10-20 16:04:12 +02:00
|
|
|
|
update_life_info (blocks, UPDATE_LIFE_LOCAL, PROP_DEATH_NOTES);
|
2000-05-27 22:23:15 +02:00
|
|
|
|
sbitmap_free (blocks);
|
1999-08-31 22:37:09 +02:00
|
|
|
|
#endif
|
2000-05-27 22:23:15 +02:00
|
|
|
|
}
|
|
|
|
|
#endif /* HAVE_peephole2 */
|