diff options
author | Hiroaki Etoh <etoh@cvs.openbsd.org> | 2004-02-05 05:08:46 +0000 |
---|---|---|
committer | Hiroaki Etoh <etoh@cvs.openbsd.org> | 2004-02-05 05:08:46 +0000 |
commit | 75364aea6c430175c4b859d637f67f0fd40e50a9 (patch) | |
tree | 028b695017e309a56509032db3c4a401275b7abe /gnu/usr.bin/gcc | |
parent | ce080cc564ccd471f0b760f51bbb629e5af953ff (diff) |
fix the conversion of the insn that comes from gen_load_multiple. ARM processor defines HAVE_load_multiple and uses this gen_load_multiple.
ok pvalchev, drahn
Diffstat (limited to 'gnu/usr.bin/gcc')
-rw-r--r-- | gnu/usr.bin/gcc/gcc/protector.c | 85 |
1 files changed, 85 insertions, 0 deletions
diff --git a/gnu/usr.bin/gcc/gcc/protector.c b/gnu/usr.bin/gcc/gcc/protector.c index a78857bfc82..3fecb9a2d28 100644 --- a/gnu/usr.bin/gcc/gcc/protector.c +++ b/gnu/usr.bin/gcc/gcc/protector.c @@ -87,6 +87,7 @@ static int search_string_from_argsandvars PARAMS ((int caller)); static int search_string_from_local_vars PARAMS ((tree block)); static int search_pointer_def PARAMS ((tree names)); static int search_func_pointer PARAMS ((tree type)); +static int check_used_flag PARAMS ((rtx x)); static void reset_used_flags_for_insns PARAMS ((rtx insn)); static void reset_used_flags_for_decls PARAMS ((tree block)); static void reset_used_flags_of_plus PARAMS ((rtx x)); @@ -606,6 +607,64 @@ search_func_pointer (type) } +/* + * check whether the specified rtx contains PLUS rtx with used flag. + */ +static int +check_used_flag (x) + rtx x; +{ + register int i, j; + register enum rtx_code code; + register const char *format_ptr; + + if (x == 0) + return FALSE; + + code = GET_CODE (x); + + switch (code) + { + case REG: + case QUEUED: + case CONST_INT: + case CONST_DOUBLE: + case SYMBOL_REF: + case CODE_LABEL: + case PC: + case CC0: + return FALSE; + + case PLUS: + if (x->used) + return TRUE; + + default: + break; + } + + format_ptr = GET_RTX_FORMAT (code); + for (i = 0; i < GET_RTX_LENGTH (code); i++) + { + switch (*format_ptr++) + { + case 'e': + if (check_used_flag (XEXP (x, i))) + return TRUE; + break; + + case 'E': + for (j = 0; j < XVECLEN (x, i); j++) + if (check_used_flag (XVECEXP (x, i, j))) + return TRUE; + break; + } + } + + return FALSE; +} + + static void reset_used_flags_for_insns (insn) rtx insn; @@ -1537,6 +1596,14 @@ change_arg_use_of_insns_2 (insn, orig, new, size) seq = get_insns (); end_sequence (); emit_insn_before (seq, insn); + + /* load_multiple insn from virtual_incoming_args_rtx have several + load insns. If every insn change the load address of arg + to frame region, those insns are moved before the PARALLEL insn + and remove the PARALLEL insn. */ + if (GET_CODE (PATTERN (insn)) == PARALLEL + && XVECLEN (PATTERN (insn), 0) == 0) + delete_insn (insn); } } @@ -1665,6 +1732,24 @@ change_arg_use_in_operand (x, orig, new, size) } break; + case PARALLEL: + for (i = 0, j = 0; j < XVECLEN (x, 0); j++) + { + change_arg_use_in_operand (XVECEXP (x, 0, j), orig, new, size); + + /* if load_multiple insn has a insn used virtual_incoming_args_rtx, + the insn is removed from this PARARELL insn. */ + if (check_used_flag (XVECEXP (x, 0, j))) + { + emit_insn (XVECEXP (x, 0, j)); + XVECEXP (x, 0, j) = NULL; + } + else + XVECEXP (x, 0, i++) = XVECEXP (x, 0, j); + } + PUT_NUM_ELEM (XVEC (x, 0), i); + return; + default: break; } |